summaryrefslogtreecommitdiffstats
path: root/tools/lint/eslint
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
commit26a029d407be480d791972afb5975cf62c9360a6 (patch)
treef435a8308119effd964b339f76abb83a57c29483 /tools/lint/eslint
parentInitial commit. (diff)
downloadfirefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz
firefox-26a029d407be480d791972afb5975cf62c9360a6.zip
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'tools/lint/eslint')
-rw-r--r--tools/lint/eslint/.eslintrc.js31
-rw-r--r--tools/lint/eslint/__init__.py293
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/.npmignore8
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/LICENSE363
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/README.md56
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/configs/.eslintrc.js8
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/configs/browser-test.js95
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/configs/chrome-test.js65
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/configs/mochitest-test.js66
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/configs/recommended.js351
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/configs/require-jsdoc.js41
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/configs/valid-jsdoc.js34
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/configs/xpcshell-test.js54
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/environments/browser-window.js121
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/environments/chrome-script.js28
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/environments/chrome-worker.js25
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/environments/frame-script.js39
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/environments/jsm.js25
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/environments/privileged.js819
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/environments/process-script.js38
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/environments/remote-page.js43
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/environments/simpletest.js35
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/environments/sjs.js41
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/environments/special-powers-sandbox.js46
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/environments/specific.js31
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/environments/testharness.js61
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/environments/utils.js62
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/environments/xpcshell.js59
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/globals.js668
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/helpers.js797
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/index.js102
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/rules/avoid-Date-timing.js61
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/rules/avoid-removeChild.js70
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/rules/balanced-listeners.js149
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/rules/balanced-observers.js121
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/rules/consistent-if-bracing.js54
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/rules/import-browser-window-globals.js50
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/rules/import-content-task-globals.js73
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/rules/import-globals.js21
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/rules/import-headjs-globals.js51
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/rules/lazy-getter-object-name.js48
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/rules/mark-exported-symbols-as-used.js90
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/rules/mark-test-function-used.js44
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/rules/no-aArgs.js57
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/rules/no-addtask-setup.js57
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/rules/no-arbitrary-setTimeout.js65
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/rules/no-browser-refs-in-toolkit.js48
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/rules/no-compare-against-boolean-literals.js40
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/rules/no-comparison-or-assignment-inside-ok.js80
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/rules/no-cu-reportError.js130
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/rules/no-define-cc-etc.js57
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/rules/no-redeclare-with-import-autofix.js160
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/rules/no-throw-cr-literal.js101
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/rules/no-useless-parameters.js156
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/rules/no-useless-removeEventListener.js69
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/rules/no-useless-run-test.js76
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/rules/prefer-boolean-length-check.js129
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/rules/prefer-formatValues.js97
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/rules/reject-addtask-only.js53
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/rules/reject-chromeutils-import-params.js66
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/rules/reject-chromeutils-import.js80
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/rules/reject-eager-module-in-lazy-getter.js99
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/rules/reject-global-this.js43
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/rules/reject-globalThis-modification.js74
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/rules/reject-import-system-module-from-non-system.js36
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/rules/reject-importGlobalProperties.js97
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/rules/reject-lazy-imports-into-globals.js72
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/rules/reject-mixing-eager-and-lazy.js150
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/rules/reject-multiple-getters-calls.js81
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/rules/reject-relative-requires.js42
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/rules/reject-scriptableunicodeconverter.js44
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/rules/reject-some-requires.js44
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/rules/reject-top-level-await.js45
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/rules/rejects-requires-await.js47
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/rules/use-cc-etc.js57
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/rules/use-chromeutils-definelazygetter.js58
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/rules/use-chromeutils-generateqi.js105
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/rules/use-chromeutils-import.js63
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/rules/use-console-createInstance.js44
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/rules/use-default-preference-values.js56
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/rules/use-includes-instead-of-indexOf.js53
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/rules/use-isInstance.js155
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/rules/use-ownerGlobal.js43
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/rules/use-returnValue.js48
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/rules/use-services.js120
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/rules/use-static-import.js87
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/rules/valid-ci-uses.js172
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/rules/valid-lazy.js276
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/rules/valid-services-property.js126
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/rules/valid-services.js68
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/rules/var-only-at-top-level.js42
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/lib/services.json63
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/manifest.tt10
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/package-lock.json5249
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/package.json53
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/reporters/mozilla-format.js57
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/scripts/createExports.js77
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/tests/avoid-Date-timing.js34
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/tests/avoid-removeChild.js37
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/tests/balanced-listeners.js100
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/tests/balanced-observers.js80
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/tests/consistent-if-bracing.js39
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/tests/globals.js161
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/tests/lazy-getter-object-name.js51
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/tests/mark-exported-symbols-as-used.js45
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/tests/no-addtask-setup.js69
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/tests/no-arbitrary-setTimeout.js39
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/tests/no-compare-against-boolean-literals.js59
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/tests/no-comparison-or-assignment-inside-ok.js139
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/tests/no-cu-reportError.js100
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/tests/no-define-cc-etc.js63
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/tests/no-redeclare-with-import-autofix.js77
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/tests/no-throw-cr-literal.js62
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/tests/no-useless-parameters.js175
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/tests/no-useless-removeEventListener.js96
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/tests/no-useless-run-test.js126
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/tests/prefer-boolean-length-check.js96
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/tests/prefer-formatValues.js70
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/tests/reject-addtask-only.js54
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/tests/reject-chromeutils-import-params.js67
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/tests/reject-chromeutils-import.js60
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/tests/reject-eager-module-in-lazy-getter.js67
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/tests/reject-global-this.js51
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/tests/reject-globalThis-modification.js83
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/tests/reject-import-system-module-from-non-system.js33
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/tests/reject-importGlobalProperties.js89
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/tests/reject-lazy-imports-into-globals.js46
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/tests/reject-mixing-eager-and-lazy.js104
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/tests/reject-multiple-getters-calls.js60
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/tests/reject-relative-requires.js56
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/tests/reject-scriptableunicodeconverter.js33
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/tests/reject-some-requires.js50
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/tests/reject-top-level-await.js36
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/tests/rejects-requires-await.js32
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/tests/use-cc-etc.js64
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/tests/use-chromeutils-definelazygetter.js34
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/tests/use-chromeutils-generateqi.js71
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/tests/use-chromeutils-import.js47
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/tests/use-console-createInstance.js41
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/tests/use-default-preference-values.js43
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/tests/use-includes-instead-of-indexOf.js40
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/tests/use-isInstance.js128
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/tests/use-ownerGlobal.js37
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/tests/use-returnValue.js49
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/tests/use-services.js64
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/tests/use-static-import.js80
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/tests/valid-ci-uses.js58
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/tests/valid-lazy.js160
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/tests/valid-services-property.js42
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/tests/valid-services.js32
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/tests/xpidl/docshell.xpt5940
-rw-r--r--tools/lint/eslint/eslint-plugin-mozilla/tests/xpidl/xpcom_base.xpt3165
-rwxr-xr-xtools/lint/eslint/eslint-plugin-mozilla/update.sh40
-rw-r--r--tools/lint/eslint/eslint-plugin-spidermonkey-js/LICENSE363
-rw-r--r--tools/lint/eslint/eslint-plugin-spidermonkey-js/lib/environments/self-hosted.js180
-rw-r--r--tools/lint/eslint/eslint-plugin-spidermonkey-js/lib/index.js20
-rw-r--r--tools/lint/eslint/eslint-plugin-spidermonkey-js/lib/processors/self-hosted.js129
-rw-r--r--tools/lint/eslint/eslint-plugin-spidermonkey-js/package.json28
-rw-r--r--tools/lint/eslint/manifest.tt10
-rw-r--r--tools/lint/eslint/setup_helper.py423
-rwxr-xr-xtools/lint/eslint/update.sh50
161 files changed, 28791 insertions, 0 deletions
diff --git a/tools/lint/eslint/.eslintrc.js b/tools/lint/eslint/.eslintrc.js
new file mode 100644
index 0000000000..762ddba02c
--- /dev/null
+++ b/tools/lint/eslint/.eslintrc.js
@@ -0,0 +1,31 @@
+/* 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 = {
+ plugins: ["eslint-plugin"],
+ extends: ["plugin:eslint-plugin/recommended"],
+ // eslint-plugin-mozilla runs under node, so we need a more restrictive
+ // environment / parser setup here than the rest of mozilla-central.
+ env: {
+ browser: false,
+ node: true,
+ },
+ parser: "espree",
+ parserOptions: {
+ // This should match with the minimum node version that the ESLint CI
+ // process uses (check the linux64-node toolchain).
+ ecmaVersion: 12,
+ },
+
+ rules: {
+ camelcase: ["error", { properties: "never" }],
+ "handle-callback-err": ["error", "er"],
+ "no-shadow": "error",
+ "no-undef-init": "error",
+ "one-var": ["error", "never"],
+ strict: ["error", "global"],
+ },
+};
diff --git a/tools/lint/eslint/__init__.py b/tools/lint/eslint/__init__.py
new file mode 100644
index 0000000000..fdd7504c34
--- /dev/null
+++ b/tools/lint/eslint/__init__.py
@@ -0,0 +1,293 @@
+# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+import json
+import os
+import signal
+import subprocess
+import sys
+
+sys.path.append(os.path.join(os.path.dirname(__file__), "eslint"))
+from mozbuild.nodeutil import find_node_executable
+from mozlint import result
+
+from eslint import setup_helper
+
+ESLINT_ERROR_MESSAGE = """
+An error occurred running eslint. Please check the following error messages:
+
+{}
+""".strip()
+
+ESLINT_NOT_FOUND_MESSAGE = """
+Could not find eslint! We looked at the --binary option, at the ESLINT
+environment variable, and then at your local node_modules path. Please Install
+eslint and needed plugins with:
+
+mach eslint --setup
+
+and try again.
+""".strip()
+
+PRETTIER_ERROR_MESSAGE = """
+An error occurred running prettier. Please check the following error messages:
+
+{}
+""".strip()
+
+PRETTIER_FORMATTING_MESSAGE = (
+ "This file needs formatting with Prettier (use 'mach lint --fix <path>')."
+)
+
+
+def setup(root, **lintargs):
+ setup_helper.set_project_root(root)
+
+ if not setup_helper.check_node_executables_valid():
+ return 1
+
+ return setup_helper.eslint_maybe_setup()
+
+
+def lint(paths, config, binary=None, fix=None, rules=[], setup=None, **lintargs):
+ """Run eslint."""
+ log = lintargs["log"]
+ setup_helper.set_project_root(lintargs["root"])
+ module_path = setup_helper.get_project_root()
+
+ # Valid binaries are:
+ # - Any provided by the binary argument.
+ # - Any pointed at by the ESLINT environmental variable.
+ # - Those provided by |mach lint --setup|.
+
+ if not binary:
+ binary, _ = find_node_executable()
+
+ if not binary:
+ print(ESLINT_NOT_FOUND_MESSAGE)
+ return 1
+
+ extra_args = lintargs.get("extra_args") or []
+ exclude_args = []
+ for path in config.get("exclude", []):
+ exclude_args.extend(
+ ["--ignore-pattern", os.path.relpath(path, lintargs["root"])]
+ )
+
+ for rule in rules:
+ extra_args.extend(["--rule", rule])
+
+ # First run ESLint
+ cmd_args = (
+ [
+ binary,
+ os.path.join(module_path, "node_modules", "eslint", "bin", "eslint.js"),
+ # This keeps ext as a single argument.
+ "--ext",
+ "[{}]".format(",".join(config["extensions"])),
+ "--format",
+ "json",
+ "--no-error-on-unmatched-pattern",
+ ]
+ + rules
+ + extra_args
+ + exclude_args
+ + paths
+ )
+
+ if fix:
+ # eslint requires that --fix be set before the --ext argument.
+ cmd_args.insert(2, "--fix")
+
+ log.debug("ESLint command: {}".format(" ".join(cmd_args)))
+
+ result = run(cmd_args, config)
+ if result == 1:
+ return result
+
+ # Then run Prettier
+ cmd_args = (
+ [
+ binary,
+ os.path.join(module_path, "node_modules", "prettier", "bin-prettier.js"),
+ "--list-different",
+ "--no-error-on-unmatched-pattern",
+ ]
+ + extra_args
+ # Prettier does not support exclude arguments.
+ # + exclude_args
+ + paths
+ )
+ log.debug("Prettier command: {}".format(" ".join(cmd_args)))
+
+ if fix:
+ cmd_args.append("--write")
+
+ prettier_result = run_prettier(cmd_args, config, fix)
+ if prettier_result == 1:
+ return prettier_result
+
+ result["results"].extend(prettier_result["results"])
+ result["fixed"] = result["fixed"] + prettier_result["fixed"]
+ return result
+
+
+def run(cmd_args, config):
+ shell = False
+ if (
+ os.environ.get("MSYSTEM") in ("MINGW32", "MINGW64")
+ or "MOZILLABUILD" in os.environ
+ ):
+ # The eslint binary needs to be run from a shell with msys
+ shell = True
+ encoding = "utf-8"
+
+ orig = signal.signal(signal.SIGINT, signal.SIG_IGN)
+ proc = subprocess.Popen(
+ cmd_args, shell=shell, stdout=subprocess.PIPE, stderr=subprocess.PIPE
+ )
+ signal.signal(signal.SIGINT, orig)
+
+ try:
+ output, errors = proc.communicate()
+ except KeyboardInterrupt:
+ proc.kill()
+ return {"results": [], "fixed": 0}
+
+ if errors:
+ errors = errors.decode(encoding, "replace")
+ print(ESLINT_ERROR_MESSAGE.format(errors))
+
+ if proc.returncode >= 2:
+ return 1
+
+ if not output:
+ return {"results": [], "fixed": 0} # no output means success
+ output = output.decode(encoding, "replace")
+ try:
+ jsonresult = json.loads(output)
+ except ValueError:
+ print(ESLINT_ERROR_MESSAGE.format(output))
+ return 1
+
+ results = []
+ fixed = 0
+ for obj in jsonresult:
+ errors = obj["messages"]
+ # This will return a count of files fixed, rather than issues fixed, as
+ # that is the only count we have.
+ if "output" in obj:
+ fixed = fixed + 1
+
+ for err in errors:
+ err.update(
+ {
+ "hint": err.get("fix"),
+ "level": "error" if err["severity"] == 2 else "warning",
+ "lineno": err.get("line") or 0,
+ "path": obj["filePath"],
+ "rule": err.get("ruleId"),
+ }
+ )
+ results.append(result.from_config(config, **err))
+
+ return {"results": results, "fixed": fixed}
+
+
+def run_prettier(cmd_args, config, fix):
+ shell = False
+ if is_windows():
+ # The eslint binary needs to be run from a shell with msys
+ shell = True
+ encoding = "utf-8"
+
+ orig = signal.signal(signal.SIGINT, signal.SIG_IGN)
+ proc = subprocess.Popen(
+ cmd_args, shell=shell, stdout=subprocess.PIPE, stderr=subprocess.PIPE
+ )
+ signal.signal(signal.SIGINT, orig)
+
+ try:
+ output, errors = proc.communicate()
+ except KeyboardInterrupt:
+ proc.kill()
+ return {"results": [], "fixed": 0}
+
+ results = []
+
+ if errors:
+ errors = errors.decode(encoding, "replace").strip().split("\n")
+ errors = [
+ error
+ for error in errors
+ # Unknown options are not an issue for Prettier, this avoids
+ # errors during tests.
+ if not ("Ignored unknown option" in error)
+ ]
+ if len(errors):
+ results.append(
+ result.from_config(
+ config,
+ **{
+ "name": "eslint",
+ "path": os.path.abspath("."),
+ "message": PRETTIER_ERROR_MESSAGE.format("\n".join(errors)),
+ "level": "error",
+ "rule": "prettier",
+ "lineno": 0,
+ "column": 0,
+ }
+ )
+ )
+
+ if not output:
+ # If we have errors, but no output, we assume something really bad happened.
+ if errors and len(errors):
+ return {"results": results, "fixed": 0}
+
+ return {"results": [], "fixed": 0} # no output means success
+
+ output = output.decode(encoding, "replace").splitlines()
+
+ fixed = 0
+
+ if fix:
+ # When Prettier is running in fix mode, it outputs the list of files
+ # that have been fixed, so sum them up here.
+ # If it can't fix files, it will throw an error, which will be handled
+ # above.
+ fixed = len(output)
+ else:
+ # When in "check" mode, Prettier will output the list of files that
+ # need changing, so we'll wrap them in our result structure here.
+ for file in output:
+ if not file:
+ continue
+
+ file = os.path.abspath(file)
+ results.append(
+ result.from_config(
+ config,
+ **{
+ "name": "eslint",
+ "path": file,
+ "message": PRETTIER_FORMATTING_MESSAGE,
+ "level": "error",
+ "rule": "prettier",
+ "lineno": 0,
+ "column": 0,
+ }
+ )
+ )
+
+ return {"results": results, "fixed": fixed}
+
+
+def is_windows():
+ return (
+ os.environ.get("MSYSTEM") in ("MINGW32", "MINGW64")
+ or "MOZILLABUILD" in os.environ
+ )
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/.npmignore b/tools/lint/eslint/eslint-plugin-mozilla/.npmignore
new file mode 100644
index 0000000000..3713448c7a
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/.npmignore
@@ -0,0 +1,8 @@
+.eslintrc.js
+.npmignore
+node_modules
+reporters
+scripts
+tests
+package-lock.json
+update.sh
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/LICENSE b/tools/lint/eslint/eslint-plugin-mozilla/LICENSE
new file mode 100644
index 0000000000..e87a115e46
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/LICENSE
@@ -0,0 +1,363 @@
+Mozilla Public License, version 2.0
+
+1. Definitions
+
+1.1. "Contributor"
+
+ means each individual or legal entity that creates, contributes to the
+ creation of, or owns Covered Software.
+
+1.2. "Contributor Version"
+
+ means the combination of the Contributions of others (if any) used by a
+ Contributor and that particular Contributor's Contribution.
+
+1.3. "Contribution"
+
+ means Covered Software of a particular Contributor.
+
+1.4. "Covered Software"
+
+ means Source Code Form to which the initial Contributor has attached the
+ notice in Exhibit A, the Executable Form of such Source Code Form, and
+ Modifications of such Source Code Form, in each case including portions
+ thereof.
+
+1.5. "Incompatible With Secondary Licenses"
+ means
+
+ a. that the initial Contributor has attached the notice described in
+ Exhibit B to the Covered Software; or
+
+ b. that the Covered Software was made available under the terms of
+ version 1.1 or earlier of the License, but not also under the terms of
+ a Secondary License.
+
+1.6. "Executable Form"
+
+ means any form of the work other than Source Code Form.
+
+1.7. "Larger Work"
+
+ means a work that combines Covered Software with other material, in a
+ separate file or files, that is not Covered Software.
+
+1.8. "License"
+
+ means this document.
+
+1.9. "Licensable"
+
+ means having the right to grant, to the maximum extent possible, whether
+ at the time of the initial grant or subsequently, any and all of the
+ rights conveyed by this License.
+
+1.10. "Modifications"
+
+ means any of the following:
+
+ a. any file in Source Code Form that results from an addition to,
+ deletion from, or modification of the contents of Covered Software; or
+
+ b. any new file in Source Code Form that contains any Covered Software.
+
+1.11. "Patent Claims" of a Contributor
+
+ means any patent claim(s), including without limitation, method,
+ process, and apparatus claims, in any patent Licensable by such
+ Contributor that would be infringed, but for the grant of the License,
+ by the making, using, selling, offering for sale, having made, import,
+ or transfer of either its Contributions or its Contributor Version.
+
+1.12. "Secondary License"
+
+ means either the GNU General Public License, Version 2.0, the GNU Lesser
+ General Public License, Version 2.1, the GNU Affero General Public
+ License, Version 3.0, or any later versions of those licenses.
+
+1.13. "Source Code Form"
+
+ means the form of the work preferred for making modifications.
+
+1.14. "You" (or "Your")
+
+ means an individual or a legal entity exercising rights under this
+ License. For legal entities, "You" includes any entity that controls, is
+ controlled by, or is under common control with You. For purposes of this
+ definition, "control" means (a) the power, direct or indirect, to cause
+ the direction or management of such entity, whether by contract or
+ otherwise, or (b) ownership of more than fifty percent (50%) of the
+ outstanding shares or beneficial ownership of such entity.
+
+
+2. License Grants and Conditions
+
+2.1. Grants
+
+ Each Contributor hereby grants You a world-wide, royalty-free,
+ non-exclusive license:
+
+ a. under intellectual property rights (other than patent or trademark)
+ Licensable by such Contributor to use, reproduce, make available,
+ modify, display, perform, distribute, and otherwise exploit its
+ Contributions, either on an unmodified basis, with Modifications, or
+ as part of a Larger Work; and
+
+ b. under Patent Claims of such Contributor to make, use, sell, offer for
+ sale, have made, import, and otherwise transfer either its
+ Contributions or its Contributor Version.
+
+2.2. Effective Date
+
+ The licenses granted in Section 2.1 with respect to any Contribution
+ become effective for each Contribution on the date the Contributor first
+ distributes such Contribution.
+
+2.3. Limitations on Grant Scope
+
+ The licenses granted in this Section 2 are the only rights granted under
+ this License. No additional rights or licenses will be implied from the
+ distribution or licensing of Covered Software under this License.
+ Notwithstanding Section 2.1(b) above, no patent license is granted by a
+ Contributor:
+
+ a. for any code that a Contributor has removed from Covered Software; or
+
+ b. for infringements caused by: (i) Your and any other third party's
+ modifications of Covered Software, or (ii) the combination of its
+ Contributions with other software (except as part of its Contributor
+ Version); or
+
+ c. under Patent Claims infringed by Covered Software in the absence of
+ its Contributions.
+
+ This License does not grant any rights in the trademarks, service marks,
+ or logos of any Contributor (except as may be necessary to comply with
+ the notice requirements in Section 3.4).
+
+2.4. Subsequent Licenses
+
+ No Contributor makes additional grants as a result of Your choice to
+ distribute the Covered Software under a subsequent version of this
+ License (see Section 10.2) or under the terms of a Secondary License (if
+ permitted under the terms of Section 3.3).
+
+2.5. Representation
+
+ Each Contributor represents that the Contributor believes its
+ Contributions are its original creation(s) or it has sufficient rights to
+ grant the rights to its Contributions conveyed by this License.
+
+2.6. Fair Use
+
+ This License is not intended to limit any rights You have under
+ applicable copyright doctrines of fair use, fair dealing, or other
+ equivalents.
+
+2.7. Conditions
+
+ Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in
+ Section 2.1.
+
+
+3. Responsibilities
+
+3.1. Distribution of Source Form
+
+ All distribution of Covered Software in Source Code Form, including any
+ Modifications that You create or to which You contribute, must be under
+ the terms of this License. You must inform recipients that the Source
+ Code Form of the Covered Software is governed by the terms of this
+ License, and how they can obtain a copy of this License. You may not
+ attempt to alter or restrict the recipients' rights in the Source Code
+ Form.
+
+3.2. Distribution of Executable Form
+
+ If You distribute Covered Software in Executable Form then:
+
+ a. such Covered Software must also be made available in Source Code Form,
+ as described in Section 3.1, and You must inform recipients of the
+ Executable Form how they can obtain a copy of such Source Code Form by
+ reasonable means in a timely manner, at a charge no more than the cost
+ of distribution to the recipient; and
+
+ b. You may distribute such Executable Form under the terms of this
+ License, or sublicense it under different terms, provided that the
+ license for the Executable Form does not attempt to limit or alter the
+ recipients' rights in the Source Code Form under this License.
+
+3.3. Distribution of a Larger Work
+
+ You may create and distribute a Larger Work under terms of Your choice,
+ provided that You also comply with the requirements of this License for
+ the Covered Software. If the Larger Work is a combination of Covered
+ Software with a work governed by one or more Secondary Licenses, and the
+ Covered Software is not Incompatible With Secondary Licenses, this
+ License permits You to additionally distribute such Covered Software
+ under the terms of such Secondary License(s), so that the recipient of
+ the Larger Work may, at their option, further distribute the Covered
+ Software under the terms of either this License or such Secondary
+ License(s).
+
+3.4. Notices
+
+ You may not remove or alter the substance of any license notices
+ (including copyright notices, patent notices, disclaimers of warranty, or
+ limitations of liability) contained within the Source Code Form of the
+ Covered Software, except that You may alter any license notices to the
+ extent required to remedy known factual inaccuracies.
+
+3.5. Application of Additional Terms
+
+ You may choose to offer, and to charge a fee for, warranty, support,
+ indemnity or liability obligations to one or more recipients of Covered
+ Software. However, You may do so only on Your own behalf, and not on
+ behalf of any Contributor. You must make it absolutely clear that any
+ such warranty, support, indemnity, or liability obligation is offered by
+ You alone, and You hereby agree to indemnify every Contributor for any
+ liability incurred by such Contributor as a result of warranty, support,
+ indemnity or liability terms You offer. You may include additional
+ disclaimers of warranty and limitations of liability specific to any
+ jurisdiction.
+
+4. Inability to Comply Due to Statute or Regulation
+
+ If it is impossible for You to comply with any of the terms of this License
+ with respect to some or all of the Covered Software due to statute,
+ judicial order, or regulation then You must: (a) comply with the terms of
+ this License to the maximum extent possible; and (b) describe the
+ limitations and the code they affect. Such description must be placed in a
+ text file included with all distributions of the Covered Software under
+ this License. Except to the extent prohibited by statute or regulation,
+ such description must be sufficiently detailed for a recipient of ordinary
+ skill to be able to understand it.
+
+5. Termination
+
+5.1. The rights granted under this License will terminate automatically if You
+ fail to comply with any of its terms. However, if You become compliant,
+ then the rights granted under this License from a particular Contributor
+ are reinstated (a) provisionally, unless and until such Contributor
+ explicitly and finally terminates Your grants, and (b) on an ongoing
+ basis, if such Contributor fails to notify You of the non-compliance by
+ some reasonable means prior to 60 days after You have come back into
+ compliance. Moreover, Your grants from a particular Contributor are
+ reinstated on an ongoing basis if such Contributor notifies You of the
+ non-compliance by some reasonable means, this is the first time You have
+ received notice of non-compliance with this License from such
+ Contributor, and You become compliant prior to 30 days after Your receipt
+ of the notice.
+
+5.2. If You initiate litigation against any entity by asserting a patent
+ infringement claim (excluding declaratory judgment actions,
+ counter-claims, and cross-claims) alleging that a Contributor Version
+ directly or indirectly infringes any patent, then the rights granted to
+ You by any and all Contributors for the Covered Software under Section
+ 2.1 of this License shall terminate.
+
+5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user
+ license agreements (excluding distributors and resellers) which have been
+ validly granted by You or Your distributors under this License prior to
+ termination shall survive termination.
+
+6. Disclaimer of Warranty
+
+ Covered Software is provided under this License on an "as is" basis,
+ without warranty of any kind, either expressed, implied, or statutory,
+ including, without limitation, warranties that the Covered Software is free
+ of defects, merchantable, fit for a particular purpose or non-infringing.
+ The entire risk as to the quality and performance of the Covered Software
+ is with You. Should any Covered Software prove defective in any respect,
+ You (not any Contributor) assume the cost of any necessary servicing,
+ repair, or correction. This disclaimer of warranty constitutes an essential
+ part of this License. No use of any Covered Software is authorized under
+ this License except under this disclaimer.
+
+7. Limitation of Liability
+
+ Under no circumstances and under no legal theory, whether tort (including
+ negligence), contract, or otherwise, shall any Contributor, or anyone who
+ distributes Covered Software as permitted above, be liable to You for any
+ direct, indirect, special, incidental, or consequential damages of any
+ character including, without limitation, damages for lost profits, loss of
+ goodwill, work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses, even if such party shall have been
+ informed of the possibility of such damages. This limitation of liability
+ shall not apply to liability for death or personal injury resulting from
+ such party's negligence to the extent applicable law prohibits such
+ limitation. Some jurisdictions do not allow the exclusion or limitation of
+ incidental or consequential damages, so this exclusion and limitation may
+ not apply to You.
+
+8. Litigation
+
+ Any litigation relating to this License may be brought only in the courts
+ of a jurisdiction where the defendant maintains its principal place of
+ business and such litigation shall be governed by laws of that
+ jurisdiction, without reference to its conflict-of-law provisions. Nothing
+ in this Section shall prevent a party's ability to bring cross-claims or
+ counter-claims.
+
+9. Miscellaneous
+
+ This License represents the complete agreement concerning the subject
+ matter hereof. If any provision of this License is held to be
+ unenforceable, such provision shall be reformed only to the extent
+ necessary to make it enforceable. Any law or regulation which provides that
+ the language of a contract shall be construed against the drafter shall not
+ be used to construe this License against a Contributor.
+
+
+10. Versions of the License
+
+10.1. New Versions
+
+ Mozilla Foundation is the license steward. Except as provided in Section
+ 10.3, no one other than the license steward has the right to modify or
+ publish new versions of this License. Each version will be given a
+ distinguishing version number.
+
+10.2. Effect of New Versions
+
+ You may distribute the Covered Software under the terms of the version
+ of the License under which You originally received the Covered Software,
+ or under the terms of any subsequent version published by the license
+ steward.
+
+10.3. Modified Versions
+
+ If you create software not governed by this License, and you want to
+ create a new license for such software, you may create and use a
+ modified version of this License if you rename the license and remove
+ any references to the name of the license steward (except to note that
+ such modified license differs from this License).
+
+10.4. Distributing Source Code Form that is Incompatible With Secondary
+ Licenses If You choose to distribute Source Code Form that is
+ Incompatible With Secondary Licenses under the terms of this version of
+ the License, the notice described in Exhibit B of this License must be
+ attached.
+
+Exhibit A - Source Code Form License Notice
+
+ 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/.
+
+If it is not possible or desirable to put the notice in a particular file,
+then You may include the notice in a location (such as a LICENSE file in a
+relevant directory) where a recipient would be likely to look for such a
+notice.
+
+You may add additional accurate notices of copyright ownership.
+
+Exhibit B - "Incompatible With Secondary Licenses" Notice
+
+ This Source Code Form is "Incompatible
+ With Secondary Licenses", as defined by
+ the Mozilla Public License, v. 2.0.
+
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/README.md b/tools/lint/eslint/eslint-plugin-mozilla/README.md
new file mode 100644
index 0000000000..650507754e
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/README.md
@@ -0,0 +1,56 @@
+# eslint-plugin-mozilla
+
+A collection of rules that help enforce JavaScript coding standard in the Mozilla project.
+
+These are primarily developed and used within the Firefox build system ([mozilla-central](https://hg.mozilla.org/mozilla-central/)), but are made available for other
+related projects to use as well.
+
+## Installation
+
+### Within mozilla-central:
+
+```
+$ ./mach eslint --setup
+```
+
+### Outside mozilla-central:
+
+Install ESLint [ESLint](http://eslint.org):
+
+```
+$ npm i eslint --save-dev
+```
+
+Next, install `eslint-plugin-mozilla`:
+
+```
+$ npm install eslint-plugin-mozilla --save-dev
+```
+
+## Documentation
+
+For details about the rules, please see the [firefox documentation page](http://firefox-source-docs.mozilla.org/tools/lint/linters/eslint-plugin-mozilla.html).
+
+## Source Code
+
+The sources can be found at:
+
+* Code: https://searchfox.org/mozilla-central/source/tools/lint/eslint/eslint-plugin-mozilla
+* Documentation: https://searchfox.org/mozilla-central/source/docs/code-quality/lint/linters
+
+## Bugs
+
+Please file bugs in Bugzilla in the Lint component of the Testing product.
+
+* [Existing bugs](https://bugzilla.mozilla.org/buglist.cgi?resolution=---&query_format=advanced&component=Lint&product=Testing)
+* [New bugs](https://bugzilla.mozilla.org/enter_bug.cgi?product=Testing&component=Lint)
+
+## Tests
+
+The tests can only be run from within mozilla-central. To run the tests:
+
+```
+./mach eslint --setup
+cd tools/lint/eslint/eslint-plugin-mozilla
+npm run test
+```
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/configs/.eslintrc.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/configs/.eslintrc.js
new file mode 100644
index 0000000000..76df4134f5
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/configs/.eslintrc.js
@@ -0,0 +1,8 @@
+"use strict";
+
+module.exports = {
+ rules: {
+ // Require object keys to be sorted.
+ "sort-keys": "error",
+ },
+};
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/configs/browser-test.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/configs/browser-test.js
new file mode 100644
index 0000000000..08747a3f88
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/configs/browser-test.js
@@ -0,0 +1,95 @@
+// Parent config file for all browser-chrome files.
+"use strict";
+
+module.exports = {
+ env: {
+ browser: true,
+ "mozilla/browser-window": true,
+ "mozilla/simpletest": true,
+ // "node": true
+ },
+
+ // All globals made available in the test environment.
+ globals: {
+ // `$` is defined in SimpleTest.js
+ $: false,
+ Assert: false,
+ BrowserTestUtils: false,
+ ContentTask: false,
+ ContentTaskUtils: false,
+ EventUtils: false,
+ IOUtils: false,
+ PathUtils: false,
+ PromiseDebugging: false,
+ SpecialPowers: false,
+ TestUtils: false,
+ addLoadEvent: false,
+ add_setup: false,
+ add_task: false,
+ content: false,
+ executeSoon: false,
+ expectUncaughtException: false,
+ export_assertions: false,
+ extractJarToTmp: false,
+ finish: false,
+ gTestPath: false,
+ getChromeDir: false,
+ getJar: false,
+ getResolvedURI: false,
+ getRootDirectory: false,
+ getTestFilePath: false,
+ ignoreAllUncaughtExceptions: false,
+ info: false,
+ is: false,
+ isnot: false,
+ ok: false,
+ record: false,
+ registerCleanupFunction: false,
+ requestLongerTimeout: false,
+ setExpectedFailuresForSelfTest: false,
+ stringContains: false,
+ stringMatches: false,
+ todo: false,
+ todo_is: false,
+ todo_isnot: false,
+ waitForClipboard: false,
+ waitForExplicitFinish: false,
+ waitForFocus: false,
+ },
+
+ plugins: ["mozilla", "@microsoft/sdl"],
+
+ rules: {
+ // No using of insecure url, so no http urls
+ "@microsoft/sdl/no-insecure-url": [
+ "error",
+ {
+ exceptions: [
+ "^http:\\/\\/mochi\\.test?.*",
+ "^http:\\/\\/localhost?.*",
+ "^http:\\/\\/127\\.0\\.0\\.1?.*",
+ // Exempt xmlns urls
+ "^http:\\/\\/www\\.w3\\.org?.*",
+ "^http:\\/\\/www\\.mozilla\\.org\\/keymaster\\/gatekeeper?.*",
+ // Exempt urls that start with ftp or ws.
+ "^ws:?.*",
+ "^ftp:?.*",
+ ],
+ varExceptions: ["insecure?.*"],
+ },
+ ],
+ "mozilla/import-content-task-globals": "error",
+ "mozilla/import-headjs-globals": "error",
+ "mozilla/mark-test-function-used": "error",
+ "mozilla/no-addtask-setup": "error",
+ "mozilla/no-arbitrary-setTimeout": "error",
+ "mozilla/no-redeclare-with-import-autofix": [
+ "error",
+ { errorForNonImports: false },
+ ],
+ // Turn off no-unsanitized for tests, as we do want to be able to use
+ // these for testing.
+ "no-unsanitized/method": "off",
+ "no-unsanitized/property": "off",
+ },
+};
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/configs/chrome-test.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/configs/chrome-test.js
new file mode 100644
index 0000000000..3b5bbc06e2
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/configs/chrome-test.js
@@ -0,0 +1,65 @@
+// Parent config file for all mochitest files.
+"use strict";
+
+module.exports = {
+ env: {
+ browser: true,
+ "mozilla/browser-window": true,
+ },
+
+ // All globals made available in the test environment.
+ globals: {
+ // SpecialPowers is injected into the window object via SimpleTest.js
+ SpecialPowers: false,
+ extractJarToTmp: false,
+ getChromeDir: false,
+ getJar: false,
+ getResolvedURI: false,
+ getRootDirectory: false,
+ },
+
+ overrides: [
+ {
+ 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: ["*.js"],
+ },
+ ],
+
+ plugins: ["mozilla", "@microsoft/sdl"],
+
+ rules: {
+ // No using of insecure url, so no http urls
+ "@microsoft/sdl/no-insecure-url": [
+ "error",
+ {
+ exceptions: [
+ "^http:\\/\\/mochi\\.test?.*",
+ "^http:\\/\\/localhost?.*",
+ "^http:\\/\\/127\\.0\\.0\\.1?.*",
+ // Exempt xmlns urls
+ "^http:\\/\\/www\\.w3\\.org?.*",
+ "^http:\\/\\/www\\.mozilla\\.org\\/keymaster\\/gatekeeper?.*",
+ // Exempt urls that start with ftp or ws.
+ "^ws:?.*",
+ "^ftp:?.*",
+ ],
+ varExceptions: ["insecure?.*"],
+ },
+ ],
+ "mozilla/import-content-task-globals": "error",
+ "mozilla/import-headjs-globals": "error",
+ "mozilla/mark-test-function-used": "error",
+ // We mis-predict globals for HTML test files in directories shared
+ // with browser tests.
+ "mozilla/no-redeclare-with-import-autofix": "off",
+ // Turn off no-unsanitized for tests, as we do want to be able to use
+ // these for testing.
+ "no-unsanitized/method": "off",
+ "no-unsanitized/property": "off",
+ },
+};
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/configs/mochitest-test.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/configs/mochitest-test.js
new file mode 100644
index 0000000000..ceca2beec4
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/configs/mochitest-test.js
@@ -0,0 +1,66 @@
+// Parent config file for all mochitest files.
+"use strict";
+
+module.exports = {
+ env: {
+ browser: true,
+ },
+
+ // All globals made available in the test environment.
+ globals: {
+ // SpecialPowers is injected into the window object via SimpleTest.js
+ SpecialPowers: false,
+ },
+
+ overrides: [
+ {
+ 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: ["*.js"],
+ },
+ ],
+ plugins: ["mozilla", "@microsoft/sdl"],
+
+ rules: {
+ // No using of insecure url, so no http urls
+ "@microsoft/sdl/no-insecure-url": [
+ "error",
+ {
+ exceptions: [
+ "^http:\\/\\/mochi\\.test?.*",
+ "^http:\\/\\/mochi\\.xorigin-test?.*",
+ "^http:\\/\\/localhost?.*",
+ "^http:\\/\\/127\\.0\\.0\\.1?.*",
+ // Exempt xmlns urls
+ "^http:\\/\\/www\\.w3\\.org?.*",
+ "^http:\\/\\/www\\.mozilla\\.org\\/keymaster\\/gatekeeper?.*",
+ // Exempt urls that start with ftp or ws.
+ "^ws:?.*",
+ "^ftp:?.*",
+ ],
+ varExceptions: ["insecure?.*"],
+ },
+ ],
+ "mozilla/import-content-task-globals": "error",
+ "mozilla/import-headjs-globals": "error",
+ "mozilla/mark-test-function-used": "error",
+ // Turn off no-define-cc-etc for mochitests as these don't have Cc etc defined in the
+ // global scope.
+ "mozilla/no-define-cc-etc": "off",
+ // We mis-predict globals for HTML test files in directories shared
+ // with browser tests, so don't try to "fix" imports that are needed.
+ "mozilla/no-redeclare-with-import-autofix": "off",
+ // Turn off use-chromeutils-generateqi as these tests don't have ChromeUtils
+ // available.
+ "mozilla/use-chromeutils-generateqi": "off",
+ "no-shadow": "error",
+ // Turn off no-unsanitized for tests, as we do want to be able to use
+ // these for testing.
+ "no-unsanitized/method": "off",
+ "no-unsanitized/property": "off",
+ },
+};
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/configs/recommended.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/configs/recommended.js
new file mode 100644
index 0000000000..db7a0dc731
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/configs/recommended.js
@@ -0,0 +1,351 @@
+/* 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";
+
+/**
+ * The configuration is based on eslint:recommended config. The details for all
+ * the ESLint rules, and which ones are in the recommended configuration can
+ * be found here:
+ *
+ * https://eslint.org/docs/rules/
+ *
+ * Rules that we've explicitly decided not to enable:
+ *
+ * require-await - bug 1381030.
+ * no-prototype-builtins - bug 1551829.
+ * require-atomic-updates - bug 1551829.
+ * - This generates too many false positives that are not easy to work
+ * around, and false positives seem to be inherent in the rule.
+ */
+module.exports = {
+ env: {
+ browser: true,
+ es2022: true,
+ "mozilla/privileged": true,
+ "mozilla/specific": true,
+ },
+
+ // The prettier configuration here comes from eslint-config-prettier and
+ // turns off all of ESLint's rules related to formatting.
+ extends: [
+ "eslint:recommended",
+ "prettier",
+ "plugin:json/recommended-with-comments",
+ ],
+
+ overrides: [
+ {
+ // System mjs files and jsm files are not loaded in the browser scope,
+ // so we turn that off for those. Though we do have our own special
+ // environment for them.
+ env: {
+ browser: false,
+ "mozilla/jsm": true,
+ },
+ files: ["**/*.sys.mjs", "**/*.jsm"],
+ rules: {
+ "mozilla/lazy-getter-object-name": "error",
+ "mozilla/reject-eager-module-in-lazy-getter": "error",
+ "mozilla/reject-global-this": "error",
+ "mozilla/reject-globalThis-modification": "error",
+ // For all system modules, we expect no properties to need importing,
+ // hence reject everything.
+ "mozilla/reject-importGlobalProperties": ["error", "everything"],
+ "mozilla/reject-mixing-eager-and-lazy": "error",
+ "mozilla/reject-top-level-await": "error",
+ // TODO: Bug 1575506 turn `builtinGlobals` on here.
+ // We can enable builtinGlobals for jsms due to their scopes.
+ "no-redeclare": ["error", { builtinGlobals: false }],
+ },
+ },
+ {
+ files: ["**/*.mjs", "**/*.jsx", "**/*.jsm", "**/?(*.)worker.?(m)js"],
+ rules: {
+ // Modules and workers are far easier to check for no-unused-vars on a
+ // global scope, than our content files. Hence we turn that on here.
+ "no-unused-vars": [
+ "error",
+ {
+ args: "none",
+ vars: "all",
+ },
+ ],
+ },
+ },
+ {
+ excludedFiles: ["**/*.sys.mjs"],
+ files: ["**/*.mjs"],
+ rules: {
+ "mozilla/reject-import-system-module-from-non-system": "error",
+ "mozilla/reject-lazy-imports-into-globals": "error",
+ "no-shadow": ["error", { allow: ["event"], builtinGlobals: true }],
+ },
+ },
+ {
+ files: ["**/*.mjs", "**/*.jsx"],
+ parserOptions: {
+ sourceType: "module",
+ },
+ rules: {
+ "mozilla/use-static-import": "error",
+ // This rule defaults to not allowing "use strict" in module files since
+ // they are always loaded in strict mode.
+ strict: "error",
+ },
+ },
+ {
+ files: ["**/*.jsm"],
+ rules: {
+ "mozilla/mark-exported-symbols-as-used": "error",
+ },
+ },
+ {
+ env: {
+ browser: false,
+ "mozilla/privileged": false,
+ "mozilla/sjs": true,
+ "mozilla/specific": false,
+ },
+ files: ["**/*.sjs"],
+ rules: {
+ // For sjs files, reject everything as we should update the sandbox
+ // to include the globals we need, as these are test-only files.
+ "mozilla/reject-importGlobalProperties": ["error", "everything"],
+ },
+ },
+ {
+ env: {
+ browser: false,
+ worker: true,
+ },
+ files: [
+ // Most files should use the `.worker.` format to be consistent with
+ // other items like `.sys.mjs`, but we allow simply calling the file
+ // "worker" as well.
+ "**/?(*.)worker.?(m)js",
+ ],
+ },
+ ],
+
+ parserOptions: {
+ ecmaVersion: "latest",
+ },
+
+ // When adding items to this file please check for effects on sub-directories.
+ plugins: ["fetch-options", "html", "json", "no-unsanitized"],
+
+ // When adding items to this file please check for effects on all of toolkit
+ // and browser
+ rules: {
+ // This may conflict with prettier, so we turn it off.
+ "arrow-body-style": "off",
+
+ // Warn about cyclomatic complexity in functions.
+ // XXX Get this down to 20?
+ complexity: ["error", 34],
+
+ // Functions must always return something or nothing
+ "consistent-return": "error",
+
+ // XXX This rule line should be removed to enable it. See bug 1487642.
+ // Require super() calls in constructors
+ "constructor-super": "off",
+
+ // Require braces around blocks that start a new line
+ curly: ["error", "all"],
+
+ // Encourage the use of dot notation whenever possible.
+ "dot-notation": "error",
+
+ // XXX This rule should be enabled, see Bug 1557040
+ // No credentials submitted with fetch calls
+ "fetch-options/no-fetch-credentials": "off",
+
+ // XXX This rule line should be removed to enable it. See bug 1487642.
+ // Enforce return statements in getters
+ "getter-return": "off",
+
+ // Don't enforce the maximum depth that blocks can be nested. The complexity
+ // rule is a better rule to check this.
+ "max-depth": "off",
+
+ // Maximum depth callbacks can be nested.
+ "max-nested-callbacks": ["error", 10],
+
+ "mozilla/avoid-removeChild": "error",
+ "mozilla/consistent-if-bracing": "error",
+ "mozilla/import-browser-window-globals": "error",
+ "mozilla/import-globals": "error",
+ "mozilla/no-compare-against-boolean-literals": "error",
+ "mozilla/no-cu-reportError": "error",
+ "mozilla/no-define-cc-etc": "error",
+ "mozilla/no-throw-cr-literal": "error",
+ "mozilla/no-useless-parameters": "error",
+ "mozilla/no-useless-removeEventListener": "error",
+ "mozilla/prefer-boolean-length-check": "error",
+ "mozilla/prefer-formatValues": "error",
+ "mozilla/reject-addtask-only": "error",
+ "mozilla/reject-chromeutils-import-params": "error",
+ "mozilla/reject-importGlobalProperties": ["error", "allownonwebidl"],
+ "mozilla/reject-multiple-getters-calls": "error",
+ "mozilla/reject-scriptableunicodeconverter": "warn",
+ "mozilla/rejects-requires-await": "error",
+ "mozilla/use-cc-etc": "error",
+ "mozilla/use-chromeutils-definelazygetter": "error",
+ "mozilla/use-chromeutils-generateqi": "error",
+ "mozilla/use-chromeutils-import": "error",
+ "mozilla/use-console-createInstance": "error",
+ "mozilla/use-default-preference-values": "error",
+ "mozilla/use-includes-instead-of-indexOf": "error",
+ "mozilla/use-isInstance": "error",
+ "mozilla/use-ownerGlobal": "error",
+ "mozilla/use-returnValue": "error",
+ "mozilla/use-services": "error",
+ "mozilla/valid-lazy": "error",
+ "mozilla/valid-services": "error",
+
+ // Use [] instead of Array()
+ "no-array-constructor": "error",
+
+ // Disallow use of arguments.caller or arguments.callee.
+ "no-caller": "error",
+
+ // XXX Bug 1487642 - decide if we want to enable this or not.
+ // Disallow lexical declarations in case clauses
+ "no-case-declarations": "off",
+
+ // XXX Bug 1487642 - decide if we want to enable this or not.
+ // Disallow the use of console
+ "no-console": "off",
+
+ // Disallows expressions where the operation doesn't affect the value.
+ // TODO: This is enabled by default in ESLint's v9 recommended configuration.
+ "no-constant-binary-expression": "error",
+
+ // XXX Bug 1487642 - decide if we want to enable this or not.
+ // Disallow constant expressions in conditions
+ "no-constant-condition": "off",
+
+ // If an if block ends with a return no need for an else block
+ "no-else-return": "error",
+
+ // No empty statements
+ "no-empty": ["error", { allowEmptyCatch: true }],
+
+ // Disallow eval and setInteral/setTimeout with strings
+ "no-eval": "error",
+
+ // Disallow unnecessary calls to .bind()
+ "no-extra-bind": "error",
+
+ // Disallow fallthrough of case statements
+ "no-fallthrough": [
+ "error",
+ {
+ // The eslint rule doesn't allow for case-insensitive regex option.
+ // The following pattern allows for a dash between "fall through" as
+ // well as alternate spelling of "fall thru". The pattern also allows
+ // for an optional "s" at the end of "fall" ("falls through").
+ commentPattern:
+ "[Ff][Aa][Ll][Ll][Ss]?[\\s-]?([Tt][Hh][Rr][Oo][Uu][Gg][Hh]|[Tt][Hh][Rr][Uu])",
+ },
+ ],
+
+ // Disallow eval and setInteral/setTimeout with strings
+ "no-implied-eval": "error",
+
+ // This has been superseded since we're using ES6.
+ // Disallow variable or function declarations in nested blocks
+ "no-inner-declarations": "off",
+
+ // Disallow the use of the __iterator__ property
+ "no-iterator": "error",
+
+ // No labels
+ "no-labels": "error",
+
+ // Disallow unnecessary nested blocks
+ "no-lone-blocks": "error",
+
+ // No single if block inside an else block
+ "no-lonely-if": "error",
+
+ // Nested ternary statements are confusing
+ "no-nested-ternary": "error",
+
+ // Disallow use of new wrappers
+ "no-new-wrappers": "error",
+
+ // Use {} instead of new Object(), unless arguments are passed.
+ "no-object-constructor": "error",
+
+ // We don't want this, see bug 1551829
+ "no-prototype-builtins": "off",
+
+ // Disable builtinGlobals for no-redeclare as this conflicts with our
+ // globals declarations especially for browser window.
+ "no-redeclare": ["error", { builtinGlobals: false }],
+
+ // Disallow use of event global.
+ "no-restricted-globals": ["error", "event"],
+
+ // No unnecessary comparisons
+ "no-self-compare": "error",
+
+ // No comma sequenced statements
+ "no-sequences": "error",
+
+ // No declaring variables from an outer scope
+ // "no-shadow": "error",
+
+ // Disallow throwing literals (eg. throw "error" instead of
+ // throw new Error("error")).
+ "no-throw-literal": "error",
+
+ // Disallow the use of Boolean literals in conditional expressions.
+ "no-unneeded-ternary": "error",
+
+ // No unsanitized use of innerHTML=, document.write() etc.
+ // cf. https://github.com/mozilla/eslint-plugin-no-unsanitized#rule-details
+ "no-unsanitized/method": "error",
+ "no-unsanitized/property": "error",
+
+ // No declaring variables that are never used
+ "no-unused-vars": [
+ "error",
+ {
+ args: "none",
+ vars: "local",
+ },
+ ],
+
+ // No using variables before defined
+ // "no-use-before-define": ["error", "nofunc"],
+
+ // Disallow unnecessary .call() and .apply()
+ "no-useless-call": "error",
+
+ // Don't concatenate string literals together (unless they span multiple
+ // lines)
+ "no-useless-concat": "error",
+
+ // XXX Bug 1487642 - decide if we want to enable this or not.
+ // Disallow unnecessary escape characters
+ "no-useless-escape": "off",
+
+ // Disallow redundant return statements
+ "no-useless-return": "error",
+
+ // Require object-literal shorthand with ES6 method syntax
+ "object-shorthand": ["error", "always", { avoidQuotes: true }],
+
+ // This may conflict with prettier, so turn it off.
+ "prefer-arrow-callback": "off",
+
+ // XXX Bug 1487642 - decide if we want to enable this or not.
+ // Require generator functions to contain yield
+ "require-yield": "off",
+ },
+};
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/configs/require-jsdoc.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/configs/require-jsdoc.js
new file mode 100644
index 0000000000..086fc8b1d3
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/configs/require-jsdoc.js
@@ -0,0 +1,41 @@
+/* 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 = {
+ plugins: ["jsdoc"],
+
+ rules: {
+ "jsdoc/require-jsdoc": [
+ "error",
+ {
+ require: {
+ ClassDeclaration: true,
+ FunctionDeclaration: false,
+ },
+ },
+ ],
+ "jsdoc/require-param": "error",
+ "jsdoc/require-param-description": "error",
+ "jsdoc/require-param-name": "error",
+ "jsdoc/require-property": "error",
+ "jsdoc/require-property-description": "error",
+ "jsdoc/require-property-name": "error",
+ "jsdoc/require-property-type": "error",
+ "jsdoc/require-returns": "error",
+ "jsdoc/require-returns-check": "error",
+ "jsdoc/require-yields": "error",
+ "jsdoc/require-yields-check": "error",
+ },
+ settings: {
+ jsdoc: {
+ // This changes what's allowed in JSDocs, enabling more type-inference
+ // friendly types. This is the default in eslint-plugin-jsdoc versions
+ // since May 2023, but we're still on 39.9 and need opt-in for now.
+ // https://github.com/gajus/eslint-plugin-jsdoc/issues/834
+ mode: "typescript",
+ },
+ },
+};
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/configs/valid-jsdoc.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/configs/valid-jsdoc.js
new file mode 100644
index 0000000000..65fb760fe0
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/configs/valid-jsdoc.js
@@ -0,0 +1,34 @@
+/* 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 = {
+ plugins: ["jsdoc"],
+
+ rules: {
+ "jsdoc/check-access": "error",
+ // Handled by prettier
+ // "jsdoc/check-alignment": "error",
+ "jsdoc/check-param-names": "error",
+ "jsdoc/check-property-names": "error",
+ "jsdoc/check-tag-names": "error",
+ "jsdoc/check-types": "error",
+ "jsdoc/empty-tags": "error",
+ "jsdoc/newline-after-description": "error",
+ "jsdoc/no-multi-asterisks": "error",
+ "jsdoc/require-param-type": "error",
+ "jsdoc/require-returns-type": "error",
+ "jsdoc/valid-types": "error",
+ },
+ settings: {
+ jsdoc: {
+ // This changes what's allowed in JSDocs, enabling more type-inference
+ // friendly types. This is the default in eslint-plugin-jsdoc versions
+ // since May 2023, but we're still on 39.9 and need opt-in for now.
+ // https://github.com/gajus/eslint-plugin-jsdoc/issues/834
+ mode: "typescript",
+ },
+ },
+};
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/configs/xpcshell-test.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/configs/xpcshell-test.js
new file mode 100644
index 0000000000..6a4d572911
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/configs/xpcshell-test.js
@@ -0,0 +1,54 @@
+// Parent config file for all xpcshell files.
+"use strict";
+
+module.exports = {
+ env: {
+ browser: false,
+ "mozilla/privileged": true,
+ "mozilla/xpcshell": true,
+ },
+
+ overrides: [
+ {
+ // If it is a 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: "head*.js",
+ rules: {
+ "no-unused-vars": [
+ "error",
+ {
+ args: "none",
+ vars: "local",
+ },
+ ],
+ },
+ },
+ {
+ // No declaring variables that are never used
+ files: "test*.js",
+ rules: {
+ "no-unused-vars": [
+ "error",
+ {
+ args: "none",
+ vars: "all",
+ },
+ ],
+ },
+ },
+ ],
+
+ rules: {
+ "mozilla/import-headjs-globals": "error",
+ "mozilla/mark-test-function-used": "error",
+ "mozilla/no-arbitrary-setTimeout": "error",
+ "mozilla/no-useless-run-test": "error",
+ "no-shadow": "error",
+ // Turn off no-unsanitized for tests, as we do want to be able to use
+ // these for testing.
+ "no-unsanitized/method": "off",
+ "no-unsanitized/property": "off",
+ },
+};
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/environments/browser-window.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/environments/browser-window.js
new file mode 100644
index 0000000000..241299e2d3
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/environments/browser-window.js
@@ -0,0 +1,121 @@
+/**
+ * @fileoverview Defines the environment when in the browser.xhtml window.
+ * Imports many globals from various files.
+ *
+ * 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";
+
+// -----------------------------------------------------------------------------
+// Rule Definition
+// -----------------------------------------------------------------------------
+
+var fs = require("fs");
+var helpers = require("../helpers");
+var { getScriptGlobals } = require("./utils");
+
+// When updating EXTRA_SCRIPTS or MAPPINGS, be sure to also update the
+// 'support-files' config in `tools/lint/eslint.yml`.
+
+// These are scripts not loaded from browser.xhtml or global-scripts.inc
+// but via other includes.
+const EXTRA_SCRIPTS = [
+ "browser/base/content/nsContextMenu.js",
+ "browser/components/downloads/content/downloads.js",
+ "browser/components/downloads/content/indicator.js",
+ "toolkit/content/customElements.js",
+ "toolkit/content/editMenuOverlay.js",
+];
+
+const extraDefinitions = [
+ // Via Components.utils, defineModuleGetter, defineLazyModuleGetters or
+ // defineLazyScriptGetter (and map to
+ // single) variable.
+ { name: "XPCOMUtils", writable: false },
+ { name: "Task", writable: false },
+ { name: "windowGlobalChild", writable: false },
+ // structuredClone is a new global that would be defined for the `browser`
+ // environment in ESLint, but only Firefox has implemented it currently and so
+ // it isn't in ESLint's globals yet.
+ // https://developer.mozilla.org/docs/Web/API/structuredClone
+ { name: "structuredClone", writable: false },
+];
+
+// Some files in global-scripts.inc need mapping to specific locations.
+const MAPPINGS = {
+ "printUtils.js": "toolkit/components/printing/content/printUtils.js",
+ "panelUI.js": "browser/components/customizableui/content/panelUI.js",
+ "viewSourceUtils.js":
+ "toolkit/components/viewsource/content/viewSourceUtils.js",
+ "browserPlacesViews.js":
+ "browser/components/places/content/browserPlacesViews.js",
+ "places-tree.js": "browser/components/places/content/places-tree.js",
+ "places-menupopup.js":
+ "browser/components/places/content/places-menupopup.js",
+ "shopping-sidebar.js":
+ "browser/components/shopping/content/shopping-sidebar.js",
+};
+
+const globalScriptsRegExp =
+ /^\s*Services.scriptloader.loadSubScript\(\"(.*?)\", this\);$/;
+
+function getGlobalScriptIncludes(scriptPath) {
+ let fileData;
+ try {
+ fileData = fs.readFileSync(scriptPath, { encoding: "utf8" });
+ } catch (ex) {
+ // The file isn't present, so this isn't an m-c repository.
+ return null;
+ }
+
+ fileData = fileData.split("\n");
+
+ let result = [];
+
+ for (let line of fileData) {
+ let match = line.match(globalScriptsRegExp);
+ if (match) {
+ let sourceFile = match[1]
+ .replace(
+ "chrome://browser/content/search/",
+ "browser/components/search/content/"
+ )
+ .replace(
+ "chrome://browser/content/screenshots/",
+ "browser/components/screenshots/content/"
+ )
+ .replace("chrome://browser/content/", "browser/base/content/")
+ .replace("chrome://global/content/", "toolkit/content/");
+
+ for (let mapping of Object.getOwnPropertyNames(MAPPINGS)) {
+ if (sourceFile.includes(mapping)) {
+ sourceFile = MAPPINGS[mapping];
+ }
+ }
+
+ result.push(sourceFile);
+ }
+ }
+
+ return result;
+}
+
+function getGlobalScripts() {
+ let results = [];
+ for (let scriptPath of helpers.globalScriptPaths) {
+ results = results.concat(getGlobalScriptIncludes(scriptPath));
+ }
+ return results;
+}
+
+module.exports = getScriptGlobals(
+ "browser-window",
+ getGlobalScripts().concat(EXTRA_SCRIPTS),
+ extraDefinitions,
+ {
+ browserjsScripts: getGlobalScripts().concat(EXTRA_SCRIPTS),
+ }
+);
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/environments/chrome-script.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/environments/chrome-script.js
new file mode 100644
index 0000000000..9b0ae54a2e
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/environments/chrome-script.js
@@ -0,0 +1,28 @@
+/**
+ * @fileoverview Defines the environment for SpecialPowers chrome script.
+ *
+ * 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";
+
+var { globals } = require("./special-powers-sandbox");
+var util = require("util");
+
+module.exports = {
+ globals: util._extend(
+ {
+ // testing/specialpowers/content/SpecialPowersParent.sys.mjs
+
+ // SPLoadChromeScript block
+ createWindowlessBrowser: false,
+ sendAsyncMessage: false,
+ addMessageListener: false,
+ removeMessageListener: false,
+ actorParent: false,
+ },
+ globals
+ ),
+};
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/environments/chrome-worker.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/environments/chrome-worker.js
new file mode 100644
index 0000000000..db5759b26c
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/environments/chrome-worker.js
@@ -0,0 +1,25 @@
+/**
+ * @fileoverview Defines the environment for chrome workers. This differs
+ * from normal workers by the fact that `ctypes` can be accessed
+ * as well.
+ *
+ * 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";
+
+var globals = require("globals");
+var util = require("util");
+
+var workerGlobals = util._extend(
+ {
+ ctypes: false,
+ },
+ globals.worker
+);
+
+module.exports = {
+ globals: workerGlobals,
+};
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/environments/frame-script.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/environments/frame-script.js
new file mode 100644
index 0000000000..7ac5c941cf
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/environments/frame-script.js
@@ -0,0 +1,39 @@
+/**
+ * @fileoverview Defines the environment for frame scripts.
+ *
+ * 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 = {
+ globals: {
+ // dom/chrome-webidl/MessageManager.webidl
+
+ // MessageManagerGlobal
+ dump: false,
+ atob: false,
+ btoa: false,
+
+ // MessageListenerManagerMixin
+ addMessageListener: false,
+ removeMessageListener: false,
+ addWeakMessageListener: false,
+ removeWeakMessageListener: false,
+
+ // MessageSenderMixin
+ sendAsyncMessage: false,
+ processMessageManager: false,
+ remoteType: false,
+
+ // SyncMessageSenderMixin
+ sendSyncMessage: false,
+
+ // ContentFrameMessageManager
+ content: false,
+ docShell: false,
+ tabEventTarget: false,
+ },
+};
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/environments/jsm.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/environments/jsm.js
new file mode 100644
index 0000000000..30d8e0eb9c
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/environments/jsm.js
@@ -0,0 +1,25 @@
+/**
+ * @fileoverview Defines the environment for jsm files.
+ *
+ * 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 = {
+ globals: {
+ // These globals are hard-coded and available in .jsm scopes.
+ // https://searchfox.org/mozilla-central/rev/dcb0cfb66e4ed3b9c7fbef1e80572426ff5f3c3a/js/xpconnect/loader/mozJSModuleLoader.cpp#222-223
+ // Although `debug` is allowed for jsm files, this is non-standard and something
+ // we don't want to allow in mjs files. Hence it is not included here.
+ atob: false,
+ btoa: false,
+ dump: false,
+ // The WebAssembly global is available in most (if not all) contexts where
+ // JS can run. It's definitely available in JSMs. So even if this is not
+ // the perfect place to add it, it's not wrong, and we can move it later.
+ WebAssembly: false,
+ },
+};
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/environments/privileged.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/environments/privileged.js
new file mode 100644
index 0000000000..c517de6209
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/environments/privileged.js
@@ -0,0 +1,819 @@
+/**
+ * @fileoverview Defines the environment for privileges JS files.
+ *
+ * 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 = {
+ globals: {
+ // Intl and WebAssembly are available everywhere but are not webIDL definitions.
+ Intl: false,
+ WebAssembly: false,
+ // This list of items is currently obtained manually from the list of
+ // mozilla::dom::constructor::id::ID enumerations in an object directory
+ // generated dom/bindings/RegisterBindings.cpp
+ APZHitResultFlags: false,
+ AbortController: false,
+ AbortSignal: false,
+ AccessibleNode: false,
+ Addon: false,
+ AddonEvent: false,
+ AddonInstall: false,
+ AddonManager: true,
+ AddonManagerPermissions: false,
+ AnalyserNode: false,
+ Animation: false,
+ AnimationEffect: false,
+ AnimationEvent: false,
+ AnimationPlaybackEvent: false,
+ AnimationTimeline: false,
+ AnonymousContent: false,
+ Attr: false,
+ AudioBuffer: false,
+ AudioBufferSourceNode: false,
+ AudioContext: false,
+ AudioDecoder: false,
+ AudioDestinationNode: false,
+ AudioData: false,
+ AudioEncoder: false,
+ AudioListener: false,
+ AudioNode: false,
+ AudioParam: false,
+ AudioParamMap: false,
+ AudioProcessingEvent: false,
+ AudioScheduledSourceNode: false,
+ AudioTrack: false,
+ AudioTrackList: false,
+ AudioWorklet: false,
+ AudioWorkletNode: false,
+ AuthenticatorAssertionResponse: false,
+ AuthenticatorAttestationResponse: false,
+ AuthenticatorResponse: false,
+ BarProp: false,
+ BaseAudioContext: false,
+ BatteryManager: false,
+ BeforeUnloadEvent: false,
+ BiquadFilterNode: false,
+ Blob: false,
+ BlobEvent: false,
+ BoxObject: false,
+ BroadcastChannel: false,
+ BrowsingContext: false,
+ ByteLengthQueuingStrategy: false,
+ CanonicalBrowsingContext: false,
+ CDATASection: false,
+ CSS: false,
+ CSS2Properties: false,
+ CSSAnimation: false,
+ CSSConditionRule: false,
+ CSSCounterStyleRule: false,
+ CSSFontFaceRule: false,
+ CSSFontFeatureValuesRule: false,
+ CSSGroupingRule: false,
+ CSSImportRule: false,
+ CSSKeyframeRule: false,
+ CSSKeyframesRule: false,
+ CSSMediaRule: false,
+ CSSMozDocumentRule: false,
+ CSSNamespaceRule: false,
+ CSSPageRule: false,
+ CSSPseudoElement: false,
+ CSSRule: false,
+ CSSRuleList: false,
+ CSSStyleDeclaration: false,
+ CSSStyleRule: false,
+ CSSStyleSheet: false,
+ CSSSupportsRule: false,
+ CSSTransition: false,
+ Cache: false,
+ CacheStorage: false,
+ CanvasCaptureMediaStream: false,
+ CanvasGradient: false,
+ CanvasPattern: false,
+ CanvasRenderingContext2D: false,
+ CaretPosition: false,
+ CaretStateChangedEvent: false,
+ ChannelMergerNode: false,
+ ChannelSplitterNode: false,
+ ChannelWrapper: false,
+ CharacterData: false,
+ CheckerboardReportService: false,
+ ChildProcessMessageManager: false,
+ ChildSHistory: false,
+ ChromeMessageBroadcaster: false,
+ ChromeMessageSender: false,
+ ChromeNodeList: false,
+ ChromeUtils: false,
+ ChromeWorker: false,
+ Clipboard: false,
+ ClipboardEvent: false,
+ ClonedErrorHolder: false,
+ CloseEvent: false,
+ CommandEvent: false,
+ Comment: false,
+ CompositionEvent: false,
+ ConsoleInstance: false,
+ ConstantSourceNode: false,
+ ContentFrameMessageManager: false,
+ ContentProcessMessageManager: false,
+ ConvolverNode: false,
+ CountQueuingStrategy: false,
+ CreateOfferRequest: false,
+ Credential: false,
+ CredentialsContainer: false,
+ Crypto: false,
+ CryptoKey: false,
+ CustomElementRegistry: false,
+ CustomEvent: false,
+ DOMError: false,
+ DOMException: false,
+ DOMImplementation: false,
+ DOMLocalization: false,
+ DOMMatrix: false,
+ DOMMatrixReadOnly: false,
+ DOMParser: false,
+ DOMPoint: false,
+ DOMPointReadOnly: false,
+ DOMQuad: false,
+ DOMRect: false,
+ DOMRectList: false,
+ DOMRectReadOnly: false,
+ DOMRequest: false,
+ DOMStringList: false,
+ DOMStringMap: false,
+ DOMTokenList: false,
+ DataTransfer: false,
+ DataTransferItem: false,
+ DataTransferItemList: false,
+ DebuggerNotificationObserver: false,
+ DelayNode: false,
+ DeprecationReportBody: false,
+ DeviceLightEvent: false,
+ DeviceMotionEvent: false,
+ DeviceOrientationEvent: false,
+ DeviceProximityEvent: false,
+ Directory: false,
+ Document: false,
+ DocumentFragment: false,
+ DocumentTimeline: false,
+ DocumentType: false,
+ DominatorTree: false,
+ DragEvent: false,
+ DynamicsCompressorNode: false,
+ Element: false,
+ EncodedAudioChunk: false,
+ EncodedVideoChunk: false,
+ ErrorEvent: false,
+ Event: false,
+ EventSource: false,
+ EventTarget: false,
+ FeaturePolicyViolationReportBody: false,
+ FetchObserver: false,
+ File: false,
+ FileList: false,
+ FileReader: false,
+ FileSystem: false,
+ FileSystemDirectoryEntry: false,
+ FileSystemDirectoryReader: false,
+ FileSystemEntry: false,
+ FileSystemFileEntry: false,
+ Flex: false,
+ FlexItemValues: false,
+ FlexLineValues: false,
+ FluentBundle: false,
+ FluentResource: false,
+ FocusEvent: false,
+ FontFace: false,
+ FontFaceSet: false,
+ FontFaceSetLoadEvent: false,
+ FormData: false,
+ FrameCrashedEvent: false,
+ FrameLoader: false,
+ GainNode: false,
+ Gamepad: false,
+ GamepadAxisMoveEvent: false,
+ GamepadButton: false,
+ GamepadButtonEvent: false,
+ GamepadEvent: false,
+ GamepadHapticActuator: false,
+ GamepadPose: false,
+ GamepadServiceTest: false,
+ Glean: false,
+ GleanPings: false,
+ Grid: false,
+ GridArea: false,
+ GridDimension: false,
+ GridLine: false,
+ GridLines: false,
+ GridTrack: false,
+ GridTracks: false,
+ HTMLAllCollection: false,
+ HTMLAnchorElement: false,
+ HTMLAreaElement: false,
+ HTMLAudioElement: false,
+ Audio: false,
+ HTMLBRElement: false,
+ HTMLBaseElement: false,
+ HTMLBodyElement: false,
+ HTMLButtonElement: false,
+ HTMLCanvasElement: false,
+ HTMLCollection: false,
+ HTMLDListElement: false,
+ HTMLDataElement: false,
+ HTMLDataListElement: false,
+ HTMLDetailsElement: false,
+ HTMLDialogElement: false,
+ HTMLDirectoryElement: false,
+ HTMLDivElement: false,
+ HTMLDocument: false,
+ HTMLElement: false,
+ HTMLEmbedElement: false,
+ HTMLFieldSetElement: false,
+ HTMLFontElement: false,
+ HTMLFormControlsCollection: false,
+ HTMLFormElement: false,
+ HTMLFrameElement: false,
+ HTMLFrameSetElement: false,
+ HTMLHRElement: false,
+ HTMLHeadElement: false,
+ HTMLHeadingElement: false,
+ HTMLHtmlElement: false,
+ HTMLIFrameElement: false,
+ HTMLImageElement: false,
+ Image: false,
+ HTMLInputElement: false,
+ HTMLLIElement: false,
+ HTMLLabelElement: false,
+ HTMLLegendElement: false,
+ HTMLLinkElement: false,
+ HTMLMapElement: false,
+ HTMLMarqueeElement: false,
+ HTMLMediaElement: false,
+ HTMLMenuElement: false,
+ HTMLMenuItemElement: false,
+ HTMLMetaElement: false,
+ HTMLMeterElement: false,
+ HTMLModElement: false,
+ HTMLOListElement: false,
+ HTMLObjectElement: false,
+ HTMLOptGroupElement: false,
+ HTMLOptionElement: false,
+ Option: false,
+ HTMLOptionsCollection: false,
+ HTMLOutputElement: false,
+ HTMLParagraphElement: false,
+ HTMLParamElement: false,
+ HTMLPictureElement: false,
+ HTMLPreElement: false,
+ HTMLProgressElement: false,
+ HTMLQuoteElement: false,
+ HTMLScriptElement: false,
+ HTMLSelectElement: false,
+ HTMLSlotElement: false,
+ HTMLSourceElement: false,
+ HTMLSpanElement: false,
+ HTMLStyleElement: false,
+ HTMLTableCaptionElement: false,
+ HTMLTableCellElement: false,
+ HTMLTableColElement: false,
+ HTMLTableElement: false,
+ HTMLTableRowElement: false,
+ HTMLTableSectionElement: false,
+ HTMLTemplateElement: false,
+ HTMLTextAreaElement: false,
+ HTMLTimeElement: false,
+ HTMLTitleElement: false,
+ HTMLTrackElement: false,
+ HTMLUListElement: false,
+ HTMLUnknownElement: false,
+ HTMLVideoElement: false,
+ HashChangeEvent: false,
+ Headers: false,
+ HeapSnapshot: false,
+ History: false,
+ IDBCursor: false,
+ IDBCursorWithValue: false,
+ IDBDatabase: false,
+ IDBFactory: false,
+ IDBFileHandle: false,
+ IDBFileRequest: false,
+ IDBIndex: false,
+ IDBKeyRange: false,
+ IDBMutableFile: false,
+ IDBObjectStore: false,
+ IDBOpenDBRequest: false,
+ IDBRequest: false,
+ IDBTransaction: false,
+ IDBVersionChangeEvent: false,
+ IIRFilterNode: false,
+ IdleDeadline: false,
+ ImageBitmap: false,
+ ImageBitmapRenderingContext: false,
+ ImageCapture: false,
+ ImageCaptureErrorEvent: false,
+ ImageData: false,
+ ImageDocument: false,
+ InputEvent: false,
+ InspectorFontFace: false,
+ InspectorUtils: false,
+ InstallTriggerImpl: false,
+ IntersectionObserver: false,
+ IntersectionObserverEntry: false,
+ IOUtils: false,
+ JSProcessActorChild: false,
+ JSProcessActorParent: false,
+ JSWindowActorChild: false,
+ JSWindowActorParent: false,
+ KeyEvent: false,
+ KeyboardEvent: false,
+ KeyframeEffect: false,
+ L10nFileSource: false,
+ L10nRegistry: false,
+ Localization: false,
+ Location: false,
+ MIDIAccess: false,
+ MIDIConnectionEvent: false,
+ MIDIInput: false,
+ MIDIInputMap: false,
+ MIDIMessageEvent: false,
+ MIDIOutput: false,
+ MIDIOutputMap: false,
+ MIDIPort: false,
+ MatchGlob: false,
+ MatchPattern: false,
+ MatchPatternSet: false,
+ MediaCapabilities: false,
+ MediaCapabilitiesInfo: false,
+ MediaControlService: false,
+ MediaDeviceInfo: false,
+ MediaDevices: false,
+ MediaElementAudioSourceNode: false,
+ MediaEncryptedEvent: false,
+ MediaError: false,
+ MediaKeyError: false,
+ MediaKeyMessageEvent: false,
+ MediaKeySession: false,
+ MediaKeyStatusMap: false,
+ MediaKeySystemAccess: false,
+ MediaKeys: false,
+ MediaList: false,
+ MediaQueryList: false,
+ MediaQueryListEvent: false,
+ MediaRecorder: false,
+ MediaRecorderErrorEvent: false,
+ MediaSource: false,
+ MediaStream: false,
+ MediaStreamAudioDestinationNode: false,
+ MediaStreamAudioSourceNode: false,
+ MediaStreamEvent: false,
+ MediaStreamTrack: false,
+ MediaStreamTrackAudioSourceNode: false,
+ MediaStreamTrackEvent: false,
+ MerchantValidationEvent: false,
+ MessageBroadcaster: false,
+ MessageChannel: false,
+ MessageEvent: false,
+ MessageListenerManager: false,
+ MessagePort: false,
+ MessageSender: false,
+ MimeType: false,
+ MimeTypeArray: false,
+ MouseEvent: false,
+ MouseScrollEvent: false,
+ MozCanvasPrintState: false,
+ MozDocumentMatcher: false,
+ MozDocumentObserver: false,
+ MozQueryInterface: false,
+ MozSharedMap: false,
+ MozSharedMapChangeEvent: false,
+ MozStorageAsyncStatementParams: false,
+ MozStorageStatementParams: false,
+ MozStorageStatementRow: false,
+ MozWritableSharedMap: false,
+ MutationEvent: false,
+ MutationObserver: false,
+ MutationRecord: false,
+ NamedNodeMap: false,
+ Navigator: false,
+ NetworkInformation: false,
+ Node: false,
+ NodeFilter: false,
+ NodeIterator: false,
+ NodeList: false,
+ Notification: false,
+ NotifyPaintEvent: false,
+ OfflineAudioCompletionEvent: false,
+ OfflineAudioContext: false,
+ OfflineResourceList: false,
+ OffscreenCanvas: false,
+ OscillatorNode: false,
+ PageTransitionEvent: false,
+ PaintRequest: false,
+ PaintRequestList: false,
+ PannerNode: false,
+ ParentProcessMessageManager: false,
+ Path2D: false,
+ PathUtils: false,
+ PaymentAddress: false,
+ PaymentMethodChangeEvent: false,
+ PaymentRequest: false,
+ PaymentRequestUpdateEvent: false,
+ PaymentResponse: false,
+ PeerConnectionImpl: false,
+ PeerConnectionObserver: false,
+ Performance: false,
+ PerformanceEntry: false,
+ PerformanceEntryEvent: false,
+ PerformanceMark: false,
+ PerformanceMeasure: false,
+ PerformanceNavigation: false,
+ PerformanceNavigationTiming: false,
+ PerformanceObserver: false,
+ PerformanceObserverEntryList: false,
+ PerformanceResourceTiming: false,
+ PerformanceServerTiming: false,
+ PerformanceTiming: false,
+ PeriodicWave: false,
+ PermissionStatus: false,
+ Permissions: false,
+ PlacesBookmark: false,
+ PlacesBookmarkAddition: false,
+ PlacesBookmarkGuid: false,
+ PlacesBookmarkKeyword: false,
+ PlacesBookmarkMoved: false,
+ PlacesBookmarkRemoved: false,
+ PlacesBookmarkTags: false,
+ PlacesBookmarkTime: false,
+ PlacesBookmarkTitle: false,
+ PlacesBookmarkUrl: false,
+ PlacesEvent: false,
+ PlacesHistoryCleared: false,
+ PlacesObservers: false,
+ PlacesPurgeCaches: false,
+ PlacesRanking: false,
+ PlacesVisit: false,
+ PlacesVisitRemoved: false,
+ PlacesVisitTitle: false,
+ PlacesWeakCallbackWrapper: false,
+ Plugin: false,
+ PluginArray: false,
+ PluginCrashedEvent: false,
+ PointerEvent: false,
+ PopStateEvent: false,
+ PopupBlockedEvent: false,
+ PrecompiledScript: false,
+ Presentation: false,
+ PresentationAvailability: false,
+ PresentationConnection: false,
+ PresentationConnectionAvailableEvent: false,
+ PresentationConnectionCloseEvent: false,
+ PresentationConnectionList: false,
+ PresentationReceiver: false,
+ PresentationRequest: false,
+ PrioEncoder: false,
+ ProcessMessageManager: false,
+ ProcessingInstruction: false,
+ ProgressEvent: false,
+ PromiseDebugging: false,
+ PromiseRejectionEvent: false,
+ PublicKeyCredential: false,
+ PushManager: false,
+ PushManagerImpl: false,
+ PushSubscription: false,
+ PushSubscriptionOptions: false,
+ RTCCertificate: false,
+ RTCDTMFSender: false,
+ RTCDTMFToneChangeEvent: false,
+ RTCDataChannel: false,
+ RTCDataChannelEvent: false,
+ RTCIceCandidate: false,
+ RTCPeerConnection: false,
+ RTCPeerConnectionIceEvent: false,
+ RTCPeerConnectionStatic: false,
+ RTCRtpReceiver: false,
+ RTCRtpSender: false,
+ RTCRtpTransceiver: false,
+ RTCSessionDescription: false,
+ RTCStatsReport: false,
+ RTCTrackEvent: false,
+ RadioNodeList: false,
+ Range: false,
+ ReadableStreamBYOBReader: false,
+ ReadableStreamBYOBRequest: false,
+ ReadableByteStreamController: false,
+ ReadableStream: false,
+ ReadableStreamDefaultController: false,
+ ReadableStreamDefaultReader: false,
+ Report: false,
+ ReportBody: false,
+ ReportingObserver: false,
+ Request: false,
+ Response: false,
+ SessionStoreUtils: false,
+ SVGAElement: false,
+ SVGAngle: false,
+ SVGAnimateElement: false,
+ SVGAnimateMotionElement: false,
+ SVGAnimateTransformElement: false,
+ SVGAnimatedAngle: false,
+ SVGAnimatedBoolean: false,
+ SVGAnimatedEnumeration: false,
+ SVGAnimatedInteger: false,
+ SVGAnimatedLength: false,
+ SVGAnimatedLengthList: false,
+ SVGAnimatedNumber: false,
+ SVGAnimatedNumberList: false,
+ SVGAnimatedPreserveAspectRatio: false,
+ SVGAnimatedRect: false,
+ SVGAnimatedString: false,
+ SVGAnimatedTransformList: false,
+ SVGAnimationElement: false,
+ SVGCircleElement: false,
+ SVGClipPathElement: false,
+ SVGComponentTransferFunctionElement: false,
+ SVGDefsElement: false,
+ SVGDescElement: false,
+ SVGElement: false,
+ SVGEllipseElement: false,
+ SVGFEBlendElement: false,
+ SVGFEColorMatrixElement: false,
+ SVGFEComponentTransferElement: false,
+ SVGFECompositeElement: false,
+ SVGFEConvolveMatrixElement: false,
+ SVGFEDiffuseLightingElement: false,
+ SVGFEDisplacementMapElement: false,
+ SVGFEDistantLightElement: false,
+ SVGFEDropShadowElement: false,
+ SVGFEFloodElement: false,
+ SVGFEFuncAElement: false,
+ SVGFEFuncBElement: false,
+ SVGFEFuncGElement: false,
+ SVGFEFuncRElement: false,
+ SVGFEGaussianBlurElement: false,
+ SVGFEImageElement: false,
+ SVGFEMergeElement: false,
+ SVGFEMergeNodeElement: false,
+ SVGFEMorphologyElement: false,
+ SVGFEOffsetElement: false,
+ SVGFEPointLightElement: false,
+ SVGFESpecularLightingElement: false,
+ SVGFESpotLightElement: false,
+ SVGFETileElement: false,
+ SVGFETurbulenceElement: false,
+ SVGFilterElement: false,
+ SVGForeignObjectElement: false,
+ SVGGElement: false,
+ SVGGeometryElement: false,
+ SVGGradientElement: false,
+ SVGGraphicsElement: false,
+ SVGImageElement: false,
+ SVGLength: false,
+ SVGLengthList: false,
+ SVGLineElement: false,
+ SVGLinearGradientElement: false,
+ SVGMPathElement: false,
+ SVGMarkerElement: false,
+ SVGMaskElement: false,
+ SVGMatrix: false,
+ SVGMetadataElement: false,
+ SVGNumber: false,
+ SVGNumberList: false,
+ SVGPathElement: false,
+ SVGPathSegList: false,
+ SVGPatternElement: false,
+ SVGPoint: false,
+ SVGPointList: false,
+ SVGPolygonElement: false,
+ SVGPolylineElement: false,
+ SVGPreserveAspectRatio: false,
+ SVGRadialGradientElement: false,
+ SVGRect: false,
+ SVGRectElement: false,
+ SVGSVGElement: false,
+ SVGScriptElement: false,
+ SVGSetElement: false,
+ SVGStopElement: false,
+ SVGStringList: false,
+ SVGStyleElement: false,
+ SVGSwitchElement: false,
+ SVGSymbolElement: false,
+ SVGTSpanElement: false,
+ SVGTextContentElement: false,
+ SVGTextElement: false,
+ SVGTextPathElement: false,
+ SVGTextPositioningElement: false,
+ SVGTitleElement: false,
+ SVGTransform: false,
+ SVGTransformList: false,
+ SVGUnitTypes: false,
+ SVGUseElement: false,
+ SVGViewElement: false,
+ SVGZoomAndPan: false,
+ Screen: false,
+ ScreenLuminance: false,
+ ScreenOrientation: false,
+ ScriptProcessorNode: false,
+ ScrollAreaEvent: false,
+ ScrollViewChangeEvent: false,
+ SecurityPolicyViolationEvent: false,
+ Selection: false,
+ ServiceWorker: false,
+ ServiceWorkerContainer: false,
+ ServiceWorkerRegistration: false,
+ ShadowRoot: false,
+ SharedWorker: false,
+ SimpleGestureEvent: false,
+ SourceBuffer: false,
+ SourceBufferList: false,
+ SpeechGrammar: false,
+ SpeechGrammarList: false,
+ SpeechRecognition: false,
+ SpeechRecognitionAlternative: false,
+ SpeechRecognitionError: false,
+ SpeechRecognitionEvent: false,
+ SpeechRecognitionResult: false,
+ SpeechRecognitionResultList: false,
+ SpeechSynthesis: false,
+ SpeechSynthesisErrorEvent: false,
+ SpeechSynthesisEvent: false,
+ SpeechSynthesisUtterance: false,
+ SpeechSynthesisVoice: false,
+ StereoPannerNode: false,
+ Storage: false,
+ StorageEvent: false,
+ StorageManager: false,
+ StreamFilter: false,
+ StreamFilterDataEvent: false,
+ StructuredCloneHolder: false,
+ StructuredCloneTester: false,
+ StyleSheet: false,
+ StyleSheetApplicableStateChangeEvent: false,
+ StyleSheetList: false,
+ StyleSheetRemovedEvent: false,
+ SubtleCrypto: false,
+ SyncMessageSender: false,
+ TCPServerSocket: false,
+ TCPServerSocketEvent: false,
+ TCPSocket: false,
+ TCPSocketErrorEvent: false,
+ TCPSocketEvent: false,
+ TelemetryStopwatch: false,
+ TestingDeprecatedInterface: false,
+ Text: false,
+ TextClause: false,
+ TextDecoder: false,
+ TextEncoder: false,
+ TextMetrics: false,
+ TextTrack: false,
+ TextTrackCue: false,
+ TextTrackCueList: false,
+ TextTrackList: false,
+ TimeEvent: false,
+ TimeRanges: false,
+ Touch: false,
+ TouchEvent: false,
+ TouchList: false,
+ TrackEvent: false,
+ TransceiverImpl: false,
+ TransformStream: false,
+ TransformStreamDefaultController: false,
+ TransitionEvent: false,
+ TreeColumn: false,
+ TreeColumns: false,
+ TreeContentView: false,
+ TreeWalker: false,
+ U2F: false,
+ UDPMessageEvent: false,
+ UDPSocket: false,
+ UIEvent: false,
+ URL: false,
+ URLSearchParams: false,
+ UserInteraction: false,
+ UserProximityEvent: false,
+ VRDisplay: false,
+ VRDisplayCapabilities: false,
+ VRDisplayEvent: false,
+ VREyeParameters: false,
+ VRFieldOfView: false,
+ VRFrameData: false,
+ VRMockController: false,
+ VRMockDisplay: false,
+ VRPose: false,
+ VRServiceTest: false,
+ VRStageParameters: false,
+ VRSubmitFrameResult: false,
+ VTTCue: false,
+ VTTRegion: false,
+ ValidityState: false,
+ VideoColorSpace: false,
+ VideoDecoder: false,
+ VideoEncoder: false,
+ VideoFrame: false,
+ VideoPlaybackQuality: false,
+ VideoTrack: false,
+ VideoTrackList: false,
+ VisualViewport: false,
+ WaveShaperNode: false,
+ WebExtensionContentScript: false,
+ WebExtensionPolicy: false,
+ WebGL2RenderingContext: false,
+ WebGLActiveInfo: false,
+ WebGLBuffer: false,
+ WebGLContextEvent: false,
+ WebGLFramebuffer: false,
+ WebGLProgram: false,
+ WebGLQuery: false,
+ WebGLRenderbuffer: false,
+ WebGLRenderingContext: false,
+ WebGLSampler: false,
+ WebGLShader: false,
+ WebGLShaderPrecisionFormat: false,
+ WebGLSync: false,
+ WebGLTexture: false,
+ WebGLTransformFeedback: false,
+ WebGLUniformLocation: false,
+ WebGLVertexArrayObject: false,
+ WebGPU: false,
+ WebGPUAdapter: false,
+ WebGPUAttachmentState: false,
+ WebGPUBindGroup: false,
+ WebGPUBindGroupLayout: false,
+ WebGPUBindingType: false,
+ WebGPUBlendFactor: false,
+ WebGPUBlendOperation: false,
+ WebGPUBlendState: false,
+ WebGPUBuffer: false,
+ WebGPUBufferUsage: false,
+ WebGPUColorWriteBits: false,
+ WebGPUCommandBuffer: false,
+ WebGPUCommandEncoder: false,
+ WebGPUCompareFunction: false,
+ WebGPUComputePipeline: false,
+ WebGPUDepthStencilState: false,
+ WebGPUDevice: false,
+ WebGPUFence: false,
+ WebGPUFilterMode: false,
+ WebGPUIndexFormat: false,
+ WebGPUInputState: false,
+ WebGPUInputStepMode: false,
+ WebGPULoadOp: false,
+ WebGPULogEntry: false,
+ WebGPUPipelineLayout: false,
+ WebGPUPrimitiveTopology: false,
+ WebGPUQueue: false,
+ WebGPURenderPipeline: false,
+ WebGPUSampler: false,
+ WebGPUShaderModule: false,
+ WebGPUShaderStage: false,
+ WebGPUShaderStageBit: false,
+ WebGPUStencilOperation: false,
+ WebGPUStoreOp: false,
+ WebGPUSwapChain: false,
+ WebGPUTexture: false,
+ WebGPUTextureDimension: false,
+ WebGPUTextureFormat: false,
+ WebGPUTextureUsage: false,
+ WebGPUTextureView: false,
+ WebGPUVertexFormat: false,
+ WebKitCSSMatrix: false,
+ WebSocket: false,
+ WebrtcGlobalInformation: false,
+ WheelEvent: false,
+ Window: false,
+ WindowGlobalChild: false,
+ WindowGlobalParent: false,
+ WindowRoot: false,
+ Worker: false,
+ Worklet: false,
+ WritableStream: false,
+ WritableStreamDefaultController: false,
+ WritableStreamDefaultWriter: false,
+ XMLDocument: false,
+ XMLHttpRequest: false,
+ XMLHttpRequestEventTarget: false,
+ XMLHttpRequestUpload: false,
+ XMLSerializer: false,
+ XPathEvaluator: false,
+ XPathExpression: false,
+ XPathResult: false,
+ XSLTProcessor: false,
+ XULCommandEvent: false,
+ XULElement: false,
+ XULFrameElement: false,
+ XULMenuElement: false,
+ XULPopupElement: false,
+ XULScrollElement: false,
+ XULTextElement: false,
+ console: false,
+ // These are hard-coded and available in privileged scopes.
+ // See BackstagePass::Resolve.
+ fetch: false,
+ crypto: false,
+ indexedDB: false,
+ structuredClone: false,
+ },
+};
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/environments/process-script.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/environments/process-script.js
new file mode 100644
index 0000000000..f329a6650b
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/environments/process-script.js
@@ -0,0 +1,38 @@
+/**
+ * @fileoverview Defines the environment for process scripts.
+ *
+ * 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 = {
+ globals: {
+ // dom/chrome-webidl/MessageManager.webidl
+
+ // MessageManagerGlobal
+ dump: false,
+ atob: false,
+ btoa: false,
+
+ // MessageListenerManagerMixin
+ addMessageListener: false,
+ removeMessageListener: false,
+ addWeakMessageListener: false,
+ removeWeakMessageListener: false,
+
+ // MessageSenderMixin
+ sendAsyncMessage: false,
+ processMessageManager: false,
+ remoteType: false,
+
+ // SyncMessageSenderMixin
+ sendSyncMessage: false,
+
+ // ContentProcessMessageManager
+ initialProcessData: false,
+ sharedData: false,
+ },
+};
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/environments/remote-page.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/environments/remote-page.js
new file mode 100644
index 0000000000..74055457fe
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/environments/remote-page.js
@@ -0,0 +1,43 @@
+/**
+ * @fileoverview Defines the environment for remote page.
+ *
+ * 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 = {
+ globals: {
+ atob: false,
+ btoa: false,
+ RPMAddTRRExcludedDomain: false,
+ RPMGetAppBuildID: false,
+ RPMGetInnerMostURI: false,
+ RPMGetIntPref: false,
+ RPMGetStringPref: false,
+ RPMGetBoolPref: false,
+ RPMSetPref: false,
+ RPMGetFormatURLPref: false,
+ RPMIsTRROnlyFailure: false,
+ RPMIsFirefox: false,
+ RPMIsNativeFallbackFailure: false,
+ RPMIsWindowPrivate: false,
+ RPMSendAsyncMessage: false,
+ RPMSendQuery: false,
+ RPMAddMessageListener: false,
+ RPMRecordTelemetryEvent: false,
+ RPMCheckAlternateHostAvailable: false,
+ RPMAddToHistogram: false,
+ RPMRemoveMessageListener: false,
+ RPMGetHttpResponseHeader: false,
+ RPMTryPingSecureWWWLink: false,
+ RPMOpenSecureWWWLink: false,
+ RPMOpenPreferences: false,
+ RPMGetTRRSkipReason: false,
+ RPMGetTRRDomain: false,
+ RPMIsSiteSpecificTRRError: false,
+ RPMSetTRRDisabledLoadFlags: false,
+ },
+};
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/environments/simpletest.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/environments/simpletest.js
new file mode 100644
index 0000000000..2f5dd5c33e
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/environments/simpletest.js
@@ -0,0 +1,35 @@
+/**
+ * @fileoverview Defines the environment for scripts that use the SimpleTest
+ * mochitest harness. Imports the globals from the relevant files.
+ *
+ * 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";
+
+// -----------------------------------------------------------------------------
+// Rule Definition
+// -----------------------------------------------------------------------------
+
+var path = require("path");
+var { getScriptGlobals } = require("./utils");
+
+// When updating this list, be sure to also update the 'support-files' config
+// in `tools/lint/eslint.yml`.
+const simpleTestFiles = [
+ "AccessibilityUtils.js",
+ "ExtensionTestUtils.js",
+ "EventUtils.js",
+ "MockObjects.js",
+ "SimpleTest.js",
+ "WindowSnapshot.js",
+ "paint_listener.js",
+];
+const simpleTestPath = "testing/mochitest/tests/SimpleTest";
+
+module.exports = getScriptGlobals(
+ "simpletest",
+ simpleTestFiles.map(file => path.join(simpleTestPath, file))
+);
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/environments/sjs.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/environments/sjs.js
new file mode 100644
index 0000000000..4f10641c09
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/environments/sjs.js
@@ -0,0 +1,41 @@
+/**
+ * @fileoverview Defines the environment for sjs files.
+ *
+ * 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 = {
+ globals: {
+ // All these variables are hard-coded to be available for sjs scopes only.
+ // https://searchfox.org/mozilla-central/rev/26a1b0fce12e6dd495a954c542bb1e7bd6e0d548/netwerk/test/httpserver/httpd.js#2879
+ atob: false,
+ btoa: false,
+ Cc: false,
+ ChromeUtils: false,
+ Ci: false,
+ Components: false,
+ Cr: false,
+ Cu: false,
+ dump: false,
+ IOUtils: false,
+ PathUtils: false,
+ TextDecoder: false,
+ TextEncoder: false,
+ URLSearchParams: false,
+ URL: false,
+ getState: false,
+ setState: false,
+ getSharedState: false,
+ setSharedState: false,
+ getObjectState: false,
+ setObjectState: false,
+ registerPathHandler: false,
+ Services: false,
+ // importScripts is also available.
+ importScripts: false,
+ },
+};
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/environments/special-powers-sandbox.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/environments/special-powers-sandbox.js
new file mode 100644
index 0000000000..5a28c91883
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/environments/special-powers-sandbox.js
@@ -0,0 +1,46 @@
+/**
+ * @fileoverview Defines the environment for SpecialPowers sandbox.
+ *
+ * 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 = {
+ globals: {
+ // wantComponents defaults to true,
+ Components: false,
+ Ci: false,
+ Cr: false,
+ Cc: false,
+ Cu: false,
+ Services: false,
+
+ // testing/specialpowers/content/SpecialPowersSandbox.sys.mjs
+
+ // SANDBOX_GLOBALS
+ Blob: false,
+ ChromeUtils: false,
+ FileReader: false,
+ TextDecoder: false,
+ TextEncoder: false,
+ URL: false,
+
+ // EXTRA_IMPORTS
+ EventUtils: false,
+
+ // SpecialPowersSandbox constructor
+ assert: false,
+ Assert: false,
+ BrowsingContext: false,
+ InspectorUtils: false,
+ ok: false,
+ is: false,
+ isnot: false,
+ todo: false,
+ todo_is: false,
+ info: false,
+ },
+};
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/environments/specific.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/environments/specific.js
new file mode 100644
index 0000000000..23ebcb5bb1
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/environments/specific.js
@@ -0,0 +1,31 @@
+/**
+ * @fileoverview Defines the environment for the Firefox browser. Allows global
+ * variables which are non-standard and specific to Firefox.
+ *
+ * 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 = {
+ globals: {
+ Cc: false,
+ ChromeUtils: false,
+ Ci: false,
+ Components: false,
+ Cr: false,
+ Cu: false,
+ Debugger: false,
+ InstallTrigger: false,
+ // https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/InternalError
+ InternalError: true,
+ Services: false,
+ // https://developer.mozilla.org/docs/Web/API/Window/dump
+ dump: true,
+ openDialog: false,
+ // https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/uneval
+ uneval: false,
+ },
+};
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/environments/testharness.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/environments/testharness.js
new file mode 100644
index 0000000000..cea4088a4c
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/environments/testharness.js
@@ -0,0 +1,61 @@
+/**
+ * @fileoverview Defines the environment for testharness.js files. This
+ * is automatically included in (x)html files including
+ * /resources/testharness.js.
+ *
+ * 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";
+
+// These globals are taken from dom/imptests/testharness.js, via the expose
+// function.
+
+module.exports = {
+ globals: {
+ EventWatcher: false,
+ test: false,
+ async_test: false,
+ promise_test: false,
+ promise_rejects: false,
+ generate_tests: false,
+ setup: false,
+ done: false,
+ on_event: false,
+ step_timeout: false,
+ format_value: false,
+ assert_true: false,
+ assert_false: false,
+ assert_equals: false,
+ assert_not_equals: false,
+ assert_in_array: false,
+ assert_object_equals: false,
+ assert_array_equals: false,
+ assert_approx_equals: false,
+ assert_less_than: false,
+ assert_greater_than: false,
+ assert_between_exclusive: false,
+ assert_less_than_equal: false,
+ assert_greater_than_equal: false,
+ assert_between_inclusive: false,
+ assert_regexp_match: false,
+ assert_class_string: false,
+ assert_exists: false,
+ assert_own_property: false,
+ assert_not_exists: false,
+ assert_inherits: false,
+ assert_idl_attribute: false,
+ assert_readonly: false,
+ assert_throws: false,
+ assert_unreaded: false,
+ assert_any: false,
+ fetch_tests_from_worker: false,
+ timeout: false,
+ add_start_callback: false,
+ add_test_state_callback: false,
+ add_result_callback: false,
+ add_completion_callback: false,
+ },
+};
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/environments/utils.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/environments/utils.js
new file mode 100644
index 0000000000..aeda690ba5
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/environments/utils.js
@@ -0,0 +1,62 @@
+/**
+ * @fileoverview Provides utilities for setting up environments.
+ *
+ * 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";
+
+var path = require("path");
+var helpers = require("../helpers");
+var globals = require("../globals");
+
+/**
+ * Obtains the globals for a list of files.
+ *
+ * @param {Array.<String>} files
+ * The array of files to get globals for. The paths are relative to the topsrcdir.
+ * @returns {Object}
+ * Returns an object with keys of the global names and values of if they are
+ * writable or not.
+ */
+function getGlobalsForScripts(environmentName, files, extraDefinitions) {
+ let fileGlobals = extraDefinitions;
+ const root = helpers.rootDir;
+ for (const file of files) {
+ const fileName = path.join(root, file);
+ try {
+ fileGlobals = fileGlobals.concat(globals.getGlobalsForFile(fileName));
+ } catch (e) {
+ console.error(`Could not load globals from file ${fileName}: ${e}`);
+ console.error(
+ `You may need to update the mappings for the ${environmentName} environment`
+ );
+ throw new Error(`Could not load globals from file ${fileName}: ${e}`);
+ }
+ }
+
+ var globalObjects = {};
+ for (let global of fileGlobals) {
+ globalObjects[global.name] = global.writable;
+ }
+ return globalObjects;
+}
+
+module.exports = {
+ getScriptGlobals(
+ environmentName,
+ files,
+ extraDefinitions = [],
+ extraEnv = {}
+ ) {
+ if (helpers.isMozillaCentralBased()) {
+ return {
+ globals: getGlobalsForScripts(environmentName, files, extraDefinitions),
+ ...extraEnv,
+ };
+ }
+ return helpers.getSavedEnvironmentItems(environmentName);
+ },
+};
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/environments/xpcshell.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/environments/xpcshell.js
new file mode 100644
index 0000000000..408bc2e277
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/environments/xpcshell.js
@@ -0,0 +1,59 @@
+/**
+ * @fileoverview Defines the environment for xpcshell test files.
+ *
+ * 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";
+
+var { getScriptGlobals } = require("./utils");
+
+const extraGlobals = [
+ // Defined in XPCShellImpl.cpp
+ "print",
+ "readline",
+ "load",
+ "quit",
+ "dumpXPC",
+ "dump",
+ "gc",
+ "gczeal",
+ "options",
+ "sendCommand",
+ "atob",
+ "btoa",
+ "setInterruptCallback",
+ "simulateNoScriptActivity",
+ "registerXPCTestComponents",
+
+ // Assert.sys.mjs globals.
+ "setReporter",
+ "report",
+ "ok",
+ "equal",
+ "notEqual",
+ "deepEqual",
+ "notDeepEqual",
+ "strictEqual",
+ "notStrictEqual",
+ "throws",
+ "rejects",
+ "greater",
+ "greaterOrEqual",
+ "less",
+ "lessOrEqual",
+ // TestingFunctions.cpp globals
+ "allocationMarker",
+ "byteSize",
+ "saveStack",
+];
+
+module.exports = getScriptGlobals(
+ "xpcshell",
+ ["testing/xpcshell/head.js"],
+ extraGlobals.map(g => {
+ return { name: g, writable: false };
+ })
+);
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/globals.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/globals.js
new file mode 100644
index 0000000000..25c149fa9f
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/globals.js
@@ -0,0 +1,668 @@
+/**
+ * @fileoverview functions for scanning an AST for globals including
+ * traversing referenced scripts.
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+"use strict";
+
+const path = require("path");
+const fs = require("fs");
+const helpers = require("./helpers");
+const htmlparser = require("htmlparser2");
+const testharnessEnvironment = require("./environments/testharness.js");
+
+const callExpressionDefinitions = [
+ /^loader\.lazyGetter\((?:globalThis|this), "(\w+)"/,
+ /^loader\.lazyServiceGetter\((?:globalThis|this), "(\w+)"/,
+ /^loader\.lazyRequireGetter\((?:globalThis|this), "(\w+)"/,
+ /^XPCOMUtils\.defineLazyGetter\((?:globalThis|this), "(\w+)"/,
+ /^ChromeUtils\.defineLazyGetter\((?:globalThis|this), "(\w+)"/,
+ /^ChromeUtils\.defineModuleGetter\((?:globalThis|this), "(\w+)"/,
+ /^XPCOMUtils\.defineLazyPreferenceGetter\((?:globalThis|this), "(\w+)"/,
+ /^XPCOMUtils\.defineLazyScriptGetter\((?:globalThis|this), "(\w+)"/,
+ /^XPCOMUtils\.defineLazyServiceGetter\((?:globalThis|this), "(\w+)"/,
+ /^XPCOMUtils\.defineConstant\((?:globalThis|this), "(\w+)"/,
+ /^DevToolsUtils\.defineLazyGetter\((?:globalThis|this), "(\w+)"/,
+ /^Object\.defineProperty\((?:globalThis|this), "(\w+)"/,
+ /^Reflect\.defineProperty\((?:globalThis|this), "(\w+)"/,
+ /^this\.__defineGetter__\("(\w+)"/,
+];
+
+const callExpressionMultiDefinitions = [
+ "XPCOMUtils.defineLazyGlobalGetters(this,",
+ "XPCOMUtils.defineLazyGlobalGetters(globalThis,",
+ "XPCOMUtils.defineLazyModuleGetters(this,",
+ "XPCOMUtils.defineLazyModuleGetters(globalThis,",
+ "XPCOMUtils.defineLazyServiceGetters(this,",
+ "XPCOMUtils.defineLazyServiceGetters(globalThis,",
+ "ChromeUtils.defineESModuleGetters(this,",
+ "ChromeUtils.defineESModuleGetters(globalThis,",
+ "loader.lazyRequireGetter(this,",
+ "loader.lazyRequireGetter(globalThis,",
+];
+
+const subScriptMatches = [
+ /Services\.scriptloader\.loadSubScript\("(.*?)", this\)/,
+];
+
+const workerImportFilenameMatch = /(.*\/)*((.*?)\.jsm?)/;
+
+/**
+ * Parses a list of "name:boolean_value" or/and "name" options divided by comma
+ * or whitespace.
+ *
+ * This function was copied from eslint.js
+ *
+ * @param {string} string The string to parse.
+ * @param {Comment} comment The comment node which has the string.
+ * @returns {Object} Result map object of names and boolean values
+ */
+function parseBooleanConfig(string, comment) {
+ let items = {};
+
+ // Collapse whitespace around : to make parsing easier
+ string = string.replace(/\s*:\s*/g, ":");
+ // Collapse whitespace around ,
+ string = string.replace(/\s*,\s*/g, ",");
+
+ string.split(/\s|,+/).forEach(function (name) {
+ if (!name) {
+ return;
+ }
+
+ let pos = name.indexOf(":");
+ let value;
+ if (pos !== -1) {
+ value = name.substring(pos + 1, name.length);
+ name = name.substring(0, pos);
+ }
+
+ items[name] = {
+ value: value === "true",
+ comment,
+ };
+ });
+
+ return items;
+}
+
+/**
+ * Global discovery can require parsing many files. This map of
+ * {String} => {Object} caches what globals were discovered for a file path.
+ */
+const globalCache = new Map();
+
+/**
+ * Global discovery can occasionally meet circular dependencies due to the way
+ * js files are included via html/xhtml files etc. This set is used to avoid
+ * getting into loops whilst the discovery is in progress.
+ */
+var globalDiscoveryInProgressForFiles = new Set();
+
+/**
+ * When looking for globals in HTML files, it can be common to have more than
+ * one script tag with inline javascript. These will normally be called together,
+ * so we store the globals for just the last HTML file processed.
+ */
+var lastHTMLGlobals = {};
+
+/**
+ * Attempts to convert an CallExpressions that look like module imports
+ * into global variable definitions.
+ *
+ * @param {Object} node
+ * The AST node to convert.
+ * @param {boolean} isGlobal
+ * True if the current node is in the global scope.
+ *
+ * @return {Array}
+ * An array of objects that contain details about the globals:
+ * - {String} name
+ * The name of the global.
+ * - {Boolean} writable
+ * If the global is writeable or not.
+ */
+function convertCallExpressionToGlobals(node, isGlobal) {
+ let express = node.expression;
+ if (
+ express.type === "CallExpression" &&
+ express.callee.type === "MemberExpression" &&
+ express.callee.object &&
+ express.callee.object.type === "Identifier" &&
+ express.arguments.length === 1 &&
+ express.arguments[0].type === "ArrayExpression" &&
+ express.callee.property.type === "Identifier" &&
+ express.callee.property.name === "importGlobalProperties"
+ ) {
+ return express.arguments[0].elements.map(literal => {
+ return {
+ explicit: true,
+ name: literal.value,
+ writable: false,
+ };
+ });
+ }
+
+ let source;
+ try {
+ source = helpers.getASTSource(node);
+ } catch (e) {
+ return [];
+ }
+
+ // The definition matches below must be in the global scope for us to define
+ // a global, so bail out early if we're not a global.
+ if (!isGlobal) {
+ return [];
+ }
+
+ for (let reg of subScriptMatches) {
+ let match = source.match(reg);
+ if (match) {
+ return getGlobalsForScript(match[1], "script").map(g => {
+ // We don't want any loadSubScript globals to be explicit, as this
+ // could trigger no-unused-vars when importing multiple variables
+ // from a script and not using all of them.
+ g.explicit = false;
+ return g;
+ });
+ }
+ }
+
+ for (let reg of callExpressionDefinitions) {
+ let match = source.match(reg);
+ if (match) {
+ return [{ name: match[1], writable: true, explicit: true }];
+ }
+ }
+
+ if (
+ callExpressionMultiDefinitions.some(expr => source.startsWith(expr)) &&
+ node.expression.arguments[1]
+ ) {
+ let arg = node.expression.arguments[1];
+ if (arg.type === "ObjectExpression") {
+ return arg.properties
+ .map(p => ({
+ name: p.type === "Property" && p.key.name,
+ writable: true,
+ explicit: true,
+ }))
+ .filter(g => g.name);
+ }
+ if (arg.type === "ArrayExpression") {
+ return arg.elements
+ .map(p => ({
+ name: p.type === "Literal" && p.value,
+ writable: true,
+ explicit: true,
+ }))
+ .filter(g => typeof g.name == "string");
+ }
+ }
+
+ if (
+ node.expression.callee.type == "MemberExpression" &&
+ node.expression.callee.property.type == "Identifier" &&
+ node.expression.callee.property.name == "defineLazyScriptGetter"
+ ) {
+ // The case where we have a single symbol as a string has already been
+ // handled by the regexp, so we have an array of symbols here.
+ return node.expression.arguments[1].elements.map(n => ({
+ name: n.value,
+ writable: true,
+ explicit: true,
+ }));
+ }
+
+ return [];
+}
+
+/**
+ * Attempts to convert an AssignmentExpression into a global variable
+ * definition if it applies to `this` in the global scope.
+ *
+ * @param {Object} node
+ * The AST node to convert.
+ * @param {boolean} isGlobal
+ * True if the current node is in the global scope.
+ *
+ * @return {Array}
+ * An array of objects that contain details about the globals:
+ * - {String} name
+ * The name of the global.
+ * - {Boolean} writable
+ * If the global is writeable or not.
+ */
+function convertThisAssignmentExpressionToGlobals(node, isGlobal) {
+ if (
+ isGlobal &&
+ node.expression.left &&
+ node.expression.left.object &&
+ node.expression.left.object.type === "ThisExpression" &&
+ node.expression.left.property &&
+ node.expression.left.property.type === "Identifier"
+ ) {
+ return [{ name: node.expression.left.property.name, writable: true }];
+ }
+ return [];
+}
+
+/**
+ * Attempts to convert an ExpressionStatement to likely global variable
+ * definitions.
+ *
+ * @param {Object} node
+ * The AST node to convert.
+ * @param {boolean} isGlobal
+ * True if the current node is in the global scope.
+ *
+ * @return {Array}
+ * An array of objects that contain details about the globals:
+ * - {String} name
+ * The name of the global.
+ * - {Boolean} writable
+ * If the global is writeable or not.
+ */
+function convertWorkerExpressionToGlobals(node, isGlobal, dirname) {
+ let results = [];
+ let expr = node.expression;
+
+ if (
+ node.expression.type === "CallExpression" &&
+ expr.callee &&
+ expr.callee.type === "Identifier" &&
+ expr.callee.name === "importScripts"
+ ) {
+ for (var arg of expr.arguments) {
+ var match = arg.value && arg.value.match(workerImportFilenameMatch);
+ if (match) {
+ if (!match[1]) {
+ let filePath = path.resolve(dirname, match[2]);
+ if (fs.existsSync(filePath)) {
+ let additionalGlobals = module.exports.getGlobalsForFile(filePath);
+ results = results.concat(additionalGlobals);
+ }
+ }
+ // Import with relative/absolute path should explicitly use
+ // `import-globals-from` comment.
+ }
+ }
+ }
+
+ return results;
+}
+
+/**
+ * Attempts to load the globals for a given script.
+ *
+ * @param {string} src
+ * The source path or url of the script to look for.
+ * @param {string} type
+ * The type of the current file (script/module).
+ * @param {string} [dir]
+ * The directory of the current file.
+ * @returns {object[]}
+ * An array of objects with details of the globals in them.
+ */
+function getGlobalsForScript(src, type, dir) {
+ let scriptName;
+ if (src.includes("http:")) {
+ // We don't handle this currently as the paths are complex to match.
+ } else if (src.startsWith("chrome://mochikit/content/")) {
+ // Various ways referencing test files.
+ src = src.replace("chrome://mochikit/content/", "/");
+ scriptName = path.join(helpers.rootDir, "testing", "mochitest", src);
+ } else if (src.startsWith("chrome://mochitests/content/browser")) {
+ src = src.replace("chrome://mochitests/content/browser", "");
+ scriptName = path.join(helpers.rootDir, src);
+ } else if (src.includes("SimpleTest")) {
+ // This is another way of referencing test files...
+ scriptName = path.join(helpers.rootDir, "testing", "mochitest", src);
+ } else if (src.startsWith("/tests/")) {
+ scriptName = path.join(helpers.rootDir, src.substring(7));
+ } else if (src.startsWith("/resources/testharness.js")) {
+ return Object.keys(testharnessEnvironment.globals).map(name => ({
+ name,
+ writable: true,
+ }));
+ } else if (dir) {
+ // Fallback to hoping this is a relative path.
+ scriptName = path.join(dir, src);
+ }
+ if (scriptName && fs.existsSync(scriptName)) {
+ return module.exports.getGlobalsForFile(scriptName, {
+ ecmaVersion: helpers.getECMAVersion(),
+ sourceType: type,
+ });
+ }
+ return [];
+}
+
+/**
+ * An object that returns found globals for given AST node types. Each prototype
+ * property should be named for a node type and accepts a node parameter and a
+ * parents parameter which is a list of the parent nodes of the current node.
+ * Each returns an array of globals found.
+ *
+ * @param {String} filePath
+ * The absolute path of the file being parsed.
+ */
+function GlobalsForNode(filePath, context) {
+ this.path = filePath;
+ this.context = context;
+
+ if (this.path) {
+ this.dirname = path.dirname(this.path);
+ } else {
+ this.dirname = null;
+ }
+}
+
+GlobalsForNode.prototype = {
+ Program(node) {
+ let globals = [];
+ for (let comment of node.comments) {
+ if (comment.type !== "Block") {
+ continue;
+ }
+ let value = comment.value.trim();
+ value = value.replace(/\n/g, "");
+
+ // We have to discover any globals that ESLint would have defined through
+ // comment directives.
+ let match = /^globals?\s+(.+)/.exec(value);
+ if (match) {
+ let values = parseBooleanConfig(match[1].trim(), node);
+ for (let name of Object.keys(values)) {
+ globals.push({
+ name,
+ writable: values[name].value,
+ });
+ }
+ // We matched globals, so we won't match import-globals-from.
+ continue;
+ }
+
+ match = /^import-globals-from\s+(.+)$/.exec(value);
+ if (!match) {
+ continue;
+ }
+
+ if (!this.dirname) {
+ // If this is testing context without path, ignore import.
+ return globals;
+ }
+
+ let filePath = match[1].trim();
+
+ if (filePath.endsWith(".mjs")) {
+ if (this.context) {
+ this.context.report(
+ comment,
+ "import-globals-from does not support module files - use a direct import instead"
+ );
+ } else {
+ // Fall back to throwing an error, as we do not have a context in all situations,
+ // e.g. when loading the environment.
+ throw new Error(
+ "import-globals-from does not support module files - use a direct import instead"
+ );
+ }
+ continue;
+ }
+
+ if (!path.isAbsolute(filePath)) {
+ filePath = path.resolve(this.dirname, filePath);
+ } else {
+ filePath = path.join(helpers.rootDir, filePath);
+ }
+ globals = globals.concat(module.exports.getGlobalsForFile(filePath));
+ }
+
+ return globals;
+ },
+
+ ExpressionStatement(node, parents, globalScope) {
+ let isGlobal = helpers.getIsGlobalThis(parents);
+ let globals = [];
+
+ // Note: We check the expression types here and only call the necessary
+ // functions to aid performance.
+ if (node.expression.type === "AssignmentExpression") {
+ globals = convertThisAssignmentExpressionToGlobals(node, isGlobal);
+ } else if (node.expression.type === "CallExpression") {
+ globals = convertCallExpressionToGlobals(node, isGlobal);
+ }
+
+ // Here we assume that if importScripts is set in the global scope, then
+ // this is a worker. It would be nice if eslint gave us a way of getting
+ // the environment directly.
+ //
+ // If this is testing context without path, ignore import.
+ if (globalScope && globalScope.set.get("importScripts") && this.dirname) {
+ let workerDetails = convertWorkerExpressionToGlobals(
+ node,
+ isGlobal,
+ this.dirname
+ );
+ globals = globals.concat(workerDetails);
+ }
+
+ return globals;
+ },
+};
+
+module.exports = {
+ /**
+ * Returns all globals for a given file. Recursively searches through
+ * import-globals-from directives and also includes globals defined by
+ * standard eslint directives.
+ *
+ * @param {String} filePath
+ * The absolute path of the file to be parsed.
+ * @param {Object} astOptions
+ * Extra options to pass to the parser.
+ * @return {Array}
+ * An array of objects that contain details about the globals:
+ * - {String} name
+ * The name of the global.
+ * - {Boolean} writable
+ * If the global is writeable or not.
+ */
+ getGlobalsForFile(filePath, astOptions = {}) {
+ if (globalCache.has(filePath)) {
+ return globalCache.get(filePath);
+ }
+
+ if (globalDiscoveryInProgressForFiles.has(filePath)) {
+ // We're already processing this file, so return an empty set for now -
+ // the initial processing will pick up on the globals for this file.
+ return [];
+ }
+ globalDiscoveryInProgressForFiles.add(filePath);
+
+ let content = fs.readFileSync(filePath, "utf8");
+
+ // Parse the content into an AST
+ let { ast, scopeManager, visitorKeys } = helpers.parseCode(
+ content,
+ astOptions
+ );
+
+ // Discover global declarations
+ let globalScope = scopeManager.acquire(ast);
+
+ let globals = Object.keys(globalScope.variables).map(v => ({
+ name: globalScope.variables[v].name,
+ writable: true,
+ }));
+
+ // Walk over the AST to find any of our custom globals
+ let handler = new GlobalsForNode(filePath);
+
+ helpers.walkAST(ast, visitorKeys, (type, node, parents) => {
+ if (type in handler) {
+ let newGlobals = handler[type](node, parents, globalScope);
+ globals.push.apply(globals, newGlobals);
+ }
+ });
+
+ globalCache.set(filePath, globals);
+
+ globalDiscoveryInProgressForFiles.delete(filePath);
+ return globals;
+ },
+
+ /**
+ * Returns all globals for a code.
+ * This is only for testing.
+ *
+ * @param {String} code
+ * The JS code
+ * @param {Object} astOptions
+ * Extra options to pass to the parser.
+ * @return {Array}
+ * An array of objects that contain details about the globals:
+ * - {String} name
+ * The name of the global.
+ * - {Boolean} writable
+ * If the global is writeable or not.
+ */
+ getGlobalsForCode(code, astOptions = {}) {
+ // Parse the content into an AST
+ let { ast, scopeManager, visitorKeys } = helpers.parseCode(
+ code,
+ astOptions,
+ { useBabel: false }
+ );
+
+ // Discover global declarations
+ let globalScope = scopeManager.acquire(ast);
+
+ let globals = Object.keys(globalScope.variables).map(v => ({
+ name: globalScope.variables[v].name,
+ writable: true,
+ }));
+
+ // Walk over the AST to find any of our custom globals
+ let handler = new GlobalsForNode(null);
+
+ helpers.walkAST(ast, visitorKeys, (type, node, parents) => {
+ if (type in handler) {
+ let newGlobals = handler[type](node, parents, globalScope);
+ globals.push.apply(globals, newGlobals);
+ }
+ });
+
+ return globals;
+ },
+
+ /**
+ * Returns all the globals for an html file that are defined by imported
+ * scripts (i.e. <script src="foo.js">).
+ *
+ * This function will cache results for one html file only - we expect
+ * this to be called sequentially for each chunk of a HTML file, rather
+ * than chucks of different files in random order.
+ *
+ * @param {String} filePath
+ * The absolute path of the file to be parsed.
+ * @return {Array}
+ * An array of objects that contain details about the globals:
+ * - {String} name
+ * The name of the global.
+ * - {Boolean} writable
+ * If the global is writeable or not.
+ */
+ getImportedGlobalsForHTMLFile(filePath) {
+ if (lastHTMLGlobals.filename === filePath) {
+ return lastHTMLGlobals.globals;
+ }
+
+ let dir = path.dirname(filePath);
+ let globals = [];
+
+ let content = fs.readFileSync(filePath, "utf8");
+ let scriptSrcs = [];
+
+ // We use htmlparser as this ensures we find the script tags correctly.
+ let parser = new htmlparser.Parser(
+ {
+ onopentag(name, attribs) {
+ if (name === "script" && "src" in attribs) {
+ scriptSrcs.push({
+ src: attribs.src,
+ type:
+ "type" in attribs && attribs.type == "module"
+ ? "module"
+ : "script",
+ });
+ }
+ },
+ },
+ {
+ xmlMode: filePath.endsWith("xhtml"),
+ }
+ );
+
+ parser.parseComplete(content);
+
+ for (let script of scriptSrcs) {
+ // Ensure that the script src isn't just "".
+ if (!script.src) {
+ continue;
+ }
+ globals.push(...getGlobalsForScript(script.src, script.type, dir));
+ }
+
+ lastHTMLGlobals.filePath = filePath;
+ return (lastHTMLGlobals.globals = globals);
+ },
+
+ /**
+ * Intended to be used as-is for an ESLint rule that parses for globals in
+ * the current file and recurses through import-globals-from directives.
+ *
+ * @param {Object} context
+ * The ESLint parsing context.
+ */
+ getESLintGlobalParser(context) {
+ let globalScope;
+
+ let parser = {
+ Program(node) {
+ globalScope = context.getScope();
+ },
+ };
+ let filename = context.getFilename();
+
+ let extraHTMLGlobals = [];
+ if (filename.endsWith(".html") || filename.endsWith(".xhtml")) {
+ extraHTMLGlobals = module.exports.getImportedGlobalsForHTMLFile(filename);
+ }
+
+ // Install thin wrappers around GlobalsForNode
+ let handler = new GlobalsForNode(helpers.getAbsoluteFilePath(context));
+
+ for (let type of Object.keys(GlobalsForNode.prototype)) {
+ parser[type] = function (node) {
+ if (type === "Program") {
+ globalScope = context.getScope();
+ helpers.addGlobals(extraHTMLGlobals, globalScope);
+ }
+ let globals = handler[type](node, context.getAncestors(), globalScope);
+ helpers.addGlobals(
+ globals,
+ globalScope,
+ node.type !== "Program" && node
+ );
+ };
+ }
+
+ return parser;
+ },
+};
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/helpers.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/helpers.js
new file mode 100644
index 0000000000..dc4106631a
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/helpers.js
@@ -0,0 +1,797 @@
+/**
+ * @fileoverview A collection of helper functions.
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+"use strict";
+
+const parser = require("espree");
+const { analyze } = require("eslint-scope");
+const { KEYS: defaultVisitorKeys } = require("eslint-visitor-keys");
+const estraverse = require("estraverse");
+const path = require("path");
+const fs = require("fs");
+const toml = require("toml-eslint-parser");
+const recommendedConfig = require("./configs/recommended");
+
+var gRootDir = null;
+var directoryManifests = new Map();
+
+let xpidlData;
+
+module.exports = {
+ get servicesData() {
+ return require("./services.json");
+ },
+
+ /**
+ * Obtains xpidl data from the object directory specified in the
+ * environment.
+ *
+ * @returns {Map<string, object>}
+ * A map of interface names to the interface details.
+ */
+ get xpidlData() {
+ let xpidlDir;
+
+ if (process.env.TASK_ID && !process.env.MOZ_XPT_ARTIFACTS_DIR) {
+ throw new Error(
+ "MOZ_XPT_ARTIFACTS_DIR must be set for this rule in automation"
+ );
+ }
+ xpidlDir = process.env.MOZ_XPT_ARTIFACTS_DIR;
+
+ if (!xpidlDir && process.env.MOZ_OBJDIR) {
+ xpidlDir = `${process.env.MOZ_OBJDIR}/dist/xpt_artifacts/`;
+ if (!fs.existsSync(xpidlDir)) {
+ xpidlDir = `${process.env.MOZ_OBJDIR}/config/makefiles/xpidl/`;
+ }
+ }
+ if (!xpidlDir) {
+ throw new Error(
+ "MOZ_OBJDIR must be defined in the environment for this rule, i.e. MOZ_OBJDIR=objdir-ff ./mach ..."
+ );
+ }
+ if (xpidlData) {
+ return xpidlData;
+ }
+ let files = fs.readdirSync(`${xpidlDir}`);
+ // `Makefile` is an expected file in the directory.
+ if (files.length <= 1) {
+ throw new Error("Missing xpidl data files, maybe you need to build?");
+ }
+ xpidlData = new Map();
+ for (let file of files) {
+ if (!file.endsWith(".xpt")) {
+ continue;
+ }
+ let data = JSON.parse(fs.readFileSync(path.join(`${xpidlDir}`, file)));
+ for (let details of data) {
+ xpidlData.set(details.name, details);
+ }
+ }
+ return xpidlData;
+ },
+
+ /**
+ * Gets the abstract syntax tree (AST) of the JavaScript source code contained
+ * in sourceText. This matches the results for an eslint parser, see
+ * https://eslint.org/docs/developer-guide/working-with-custom-parsers.
+ *
+ * @param {String} sourceText
+ * Text containing valid JavaScript.
+ * @param {Object} astOptions
+ * Extra configuration to pass to the espree parser, these will override
+ * the configuration from getPermissiveConfig().
+ * @param {Object} configOptions
+ * Extra options for getPermissiveConfig().
+ *
+ * @return {Object}
+ * Returns an object containing `ast`, `scopeManager` and
+ * `visitorKeys`
+ */
+ parseCode(sourceText, astOptions = {}, configOptions = {}) {
+ // Use a permissive config file to allow parsing of anything that Espree
+ // can parse.
+ let config = { ...this.getPermissiveConfig(configOptions), ...astOptions };
+
+ let parseResult = parser.parse(sourceText, config);
+
+ let visitorKeys = parseResult.visitorKeys || defaultVisitorKeys;
+
+ // eslint-scope doesn't support "latest" as a version, so we pass a really
+ // big number to ensure this always reads as the latest.
+ // xref https://github.com/eslint/eslint-scope/issues/74
+ config.ecmaVersion =
+ config.ecmaVersion == "latest" ? 1e8 : config.ecmaVersion;
+
+ return {
+ ast: parseResult,
+ scopeManager: parseResult.scopeManager || analyze(parseResult, config),
+ visitorKeys,
+ };
+ },
+
+ /**
+ * A simplistic conversion of some AST nodes to a standard string form.
+ *
+ * @param {Object} node
+ * The AST node to convert.
+ *
+ * @return {String}
+ * The JS source for the node.
+ */
+ getASTSource(node, context) {
+ switch (node.type) {
+ case "MemberExpression":
+ if (node.computed) {
+ let filename = context && context.getFilename();
+ throw new Error(
+ `getASTSource unsupported computed MemberExpression in ${filename}`
+ );
+ }
+ return (
+ this.getASTSource(node.object) +
+ "." +
+ this.getASTSource(node.property)
+ );
+ case "ThisExpression":
+ return "this";
+ case "Identifier":
+ return node.name;
+ case "Literal":
+ return JSON.stringify(node.value);
+ case "CallExpression":
+ var args = node.arguments.map(a => this.getASTSource(a)).join(", ");
+ return this.getASTSource(node.callee) + "(" + args + ")";
+ case "ObjectExpression":
+ return "{}";
+ case "ExpressionStatement":
+ return this.getASTSource(node.expression) + ";";
+ case "FunctionExpression":
+ return "function() {}";
+ case "ArrayExpression":
+ return "[" + node.elements.map(this.getASTSource, this).join(",") + "]";
+ case "ArrowFunctionExpression":
+ return "() => {}";
+ case "AssignmentExpression":
+ return (
+ this.getASTSource(node.left) + " = " + this.getASTSource(node.right)
+ );
+ case "BinaryExpression":
+ return (
+ this.getASTSource(node.left) +
+ " " +
+ node.operator +
+ " " +
+ this.getASTSource(node.right)
+ );
+ case "UnaryExpression":
+ return node.operator + " " + this.getASTSource(node.argument);
+ default:
+ throw new Error("getASTSource unsupported node type: " + node.type);
+ }
+ },
+
+ /**
+ * This walks an AST in a manner similar to ESLint passing node events to the
+ * listener. The listener is expected to be a simple function
+ * which accepts node type, node and parents arguments.
+ *
+ * @param {Object} ast
+ * The AST to walk.
+ * @param {Array} visitorKeys
+ * The visitor keys to use for the AST.
+ * @param {Function} listener
+ * A callback function to call for the nodes. Passed three arguments,
+ * event type, node and an array of parent nodes for the current node.
+ */
+ walkAST(ast, visitorKeys, listener) {
+ let parents = [];
+
+ estraverse.traverse(ast, {
+ enter(node, parent) {
+ listener(node.type, node, parents);
+
+ parents.push(node);
+ },
+
+ leave(node, parent) {
+ if (!parents.length) {
+ throw new Error("Left more nodes than entered.");
+ }
+ parents.pop();
+ },
+
+ keys: visitorKeys,
+ });
+ if (parents.length) {
+ throw new Error("Entered more nodes than left.");
+ }
+ },
+
+ /**
+ * Add a variable to the current scope.
+ * HACK: This relies on eslint internals so it could break at any time.
+ *
+ * @param {String} name
+ * The variable name to add to the scope.
+ * @param {ASTScope} scope
+ * The scope to add to.
+ * @param {boolean} writable
+ * Whether the global can be overwritten.
+ * @param {Object} [node]
+ * The AST node that defined the globals.
+ */
+ addVarToScope(name, scope, writable, node) {
+ scope.__defineGeneric(name, scope.set, scope.variables, null, null);
+
+ let variable = scope.set.get(name);
+ variable.eslintExplicitGlobal = false;
+ variable.writeable = writable;
+ if (node) {
+ variable.defs.push({
+ type: "Variable",
+ node,
+ name: { name, parent: node.parent },
+ });
+ variable.identifiers.push(node);
+ }
+
+ // Walk to the global scope which holds all undeclared variables.
+ while (scope.type != "global") {
+ scope = scope.upper;
+ }
+
+ // "through" contains all references with no found definition.
+ scope.through = scope.through.filter(function (reference) {
+ if (reference.identifier.name != name) {
+ return true;
+ }
+
+ // Links the variable and the reference.
+ // And this reference is removed from `Scope#through`.
+ reference.resolved = variable;
+ variable.references.push(reference);
+ return false;
+ });
+ },
+
+ /**
+ * Adds a set of globals to a scope.
+ *
+ * @param {Array} globalVars
+ * An array of global variable names.
+ * @param {ASTScope} scope
+ * The scope.
+ * @param {Object} [node]
+ * The AST node that defined the globals.
+ */
+ addGlobals(globalVars, scope, node) {
+ globalVars.forEach(v =>
+ this.addVarToScope(v.name, scope, v.writable, v.explicit && node)
+ );
+ },
+
+ /**
+ * To allow espree to parse almost any JavaScript we need as many features as
+ * possible turned on. This method returns that config.
+ *
+ * @param {Object} options
+ * {
+ * useBabel: {boolean} whether to set babelOptions.
+ * }
+ * @return {Object}
+ * Espree compatible permissive config.
+ */
+ getPermissiveConfig({ useBabel = true } = {}) {
+ return {
+ range: true,
+ loc: true,
+ comment: true,
+ attachComment: true,
+ ecmaVersion: this.getECMAVersion(),
+ sourceType: "script",
+ };
+ },
+
+ /**
+ * Returns the ECMA version of the recommended config.
+ *
+ * @return {Number} The ECMA version of the recommended config.
+ */
+ getECMAVersion() {
+ return recommendedConfig.parserOptions.ecmaVersion;
+ },
+
+ /**
+ * Check whether it's inside top-level script.
+ *
+ * @param {Array} ancestors
+ * The parents of the current node.
+ *
+ * @return {Boolean}
+ * True or false
+ */
+ getIsTopLevelScript(ancestors) {
+ for (let parent of ancestors) {
+ switch (parent.type) {
+ case "ArrowFunctionExpression":
+ case "FunctionDeclaration":
+ case "FunctionExpression":
+ case "PropertyDefinition":
+ case "StaticBlock":
+ return false;
+ }
+ }
+ return true;
+ },
+
+ isTopLevel(ancestors) {
+ for (let parent of ancestors) {
+ switch (parent.type) {
+ case "ArrowFunctionExpression":
+ case "FunctionDeclaration":
+ case "FunctionExpression":
+ case "PropertyDefinition":
+ case "StaticBlock":
+ case "BlockStatement":
+ return false;
+ }
+ }
+ return true;
+ },
+
+ /**
+ * Check whether `this` expression points the global this.
+ *
+ * @param {Array} ancestors
+ * The parents of the current node.
+ *
+ * @return {Boolean}
+ * True or false
+ */
+ getIsGlobalThis(ancestors) {
+ for (let parent of ancestors) {
+ switch (parent.type) {
+ case "FunctionDeclaration":
+ case "FunctionExpression":
+ case "PropertyDefinition":
+ case "StaticBlock":
+ return false;
+ }
+ }
+ return true;
+ },
+
+ /**
+ * Check whether the node is evaluated at top-level script unconditionally.
+ *
+ * @param {Array} ancestors
+ * The parents of the current node.
+ *
+ * @return {Boolean}
+ * True or false
+ */
+ getIsTopLevelAndUnconditionallyExecuted(ancestors) {
+ for (let parent of ancestors) {
+ switch (parent.type) {
+ // Control flow
+ case "IfStatement":
+ case "SwitchStatement":
+ case "TryStatement":
+ case "WhileStatement":
+ case "DoWhileStatement":
+ case "ForStatement":
+ case "ForInStatement":
+ case "ForOfStatement":
+ return false;
+
+ // Function
+ case "FunctionDeclaration":
+ case "FunctionExpression":
+ case "ArrowFunctionExpression":
+ case "ClassBody":
+ return false;
+
+ // Branch
+ case "LogicalExpression":
+ case "ConditionalExpression":
+ case "ChainExpression":
+ return false;
+
+ case "AssignmentExpression":
+ switch (parent.operator) {
+ // Branch
+ case "||=":
+ case "&&=":
+ case "??=":
+ return false;
+ }
+ break;
+
+ // Implicit branch (default value)
+ case "ObjectPattern":
+ case "ArrayPattern":
+ return false;
+ }
+ }
+ return true;
+ },
+
+ /**
+ * Check whether we might be in a test head file.
+ *
+ * @param {RuleContext} scope
+ * You should pass this from within a rule
+ * e.g. helpers.getIsHeadFile(context)
+ *
+ * @return {Boolean}
+ * True or false
+ */
+ getIsHeadFile(scope) {
+ var pathAndFilename = this.cleanUpPath(scope.getFilename());
+
+ return /.*[\\/]head(_.+)?\.js$/.test(pathAndFilename);
+ },
+
+ /**
+ * Gets the head files for a potential test file
+ *
+ * @param {RuleContext} scope
+ * You should pass this from within a rule
+ * e.g. helpers.getIsHeadFile(context)
+ *
+ * @return {String[]}
+ * Paths to head files to load for the test
+ */
+ getTestHeadFiles(scope) {
+ if (!this.getIsTest(scope)) {
+ return [];
+ }
+
+ let filepath = this.cleanUpPath(scope.getFilename());
+ let dir = path.dirname(filepath);
+
+ let names = fs
+ .readdirSync(dir)
+ .filter(
+ name =>
+ (name.startsWith("head") || name.startsWith("xpcshell-head")) &&
+ name.endsWith(".js")
+ )
+ .map(name => path.join(dir, name));
+ return names;
+ },
+
+ /**
+ * Gets all the test manifest data for a directory
+ *
+ * @param {String} dir
+ * The directory
+ *
+ * @return {Array}
+ * An array of objects with file and manifest properties
+ */
+ getManifestsForDirectory(dir) {
+ if (directoryManifests.has(dir)) {
+ return directoryManifests.get(dir);
+ }
+
+ let manifests = [];
+ let names = [];
+ try {
+ names = fs.readdirSync(dir);
+ } catch (err) {
+ // Ignore directory not found, it might be faked by a test
+ if (err.code !== "ENOENT") {
+ throw err;
+ }
+ }
+
+ for (let name of names) {
+ if (name.endsWith(".toml")) {
+ try {
+ const ast = toml.parseTOML(
+ fs.readFileSync(path.join(dir, name), "utf8")
+ );
+ var manifest = {};
+ ast.body.forEach(top => {
+ if (top.type == "TOMLTopLevelTable") {
+ top.body.forEach(obj => {
+ if (obj.type == "TOMLTable") {
+ manifest[obj.resolvedKey] = {};
+ }
+ });
+ }
+ });
+ manifests.push({
+ file: path.join(dir, name),
+ manifest,
+ });
+ } catch (e) {
+ console.log(
+ "TOML ERROR: " +
+ e.message +
+ " @line: " +
+ e.lineNumber +
+ ", column: " +
+ e.column
+ );
+ }
+ }
+ }
+
+ directoryManifests.set(dir, manifests);
+ return manifests;
+ },
+
+ /**
+ * Gets the manifest file a test is listed in
+ *
+ * @param {RuleContext} scope
+ * You should pass this from within a rule
+ * e.g. helpers.getIsHeadFile(context)
+ *
+ * @return {String}
+ * The path to the test manifest file
+ */
+ getTestManifest(scope) {
+ let filepath = this.cleanUpPath(scope.getFilename());
+
+ let dir = path.dirname(filepath);
+ let filename = path.basename(filepath);
+
+ for (let manifest of this.getManifestsForDirectory(dir)) {
+ if (filename in manifest.manifest) {
+ return manifest.file;
+ }
+ }
+
+ return null;
+ },
+
+ /**
+ * Check whether we are in a test of some kind.
+ *
+ * @param {RuleContext} scope
+ * You should pass this from within a rule
+ * e.g. helpers.getIsTest(context)
+ *
+ * @return {Boolean}
+ * True or false
+ */
+ getIsTest(scope) {
+ // Regardless of the manifest name being in a manifest means we're a test.
+ let manifest = this.getTestManifest(scope);
+ if (manifest) {
+ return true;
+ }
+
+ return !!this.getTestType(scope);
+ },
+
+ /*
+ * Check if this is an .sjs file.
+ */
+ getIsSjs(scope) {
+ let filepath = this.cleanUpPath(scope.getFilename());
+
+ return path.extname(filepath) == ".sjs";
+ },
+
+ /**
+ * Gets the type of test or null if this isn't a test.
+ *
+ * @param {RuleContext} scope
+ * You should pass this from within a rule
+ * e.g. helpers.getIsHeadFile(context)
+ *
+ * @return {String or null}
+ * Test type: xpcshell, browser, chrome, mochitest
+ */
+ getTestType(scope) {
+ let testTypes = ["browser", "xpcshell", "chrome", "mochitest", "a11y"];
+ let manifest = this.getTestManifest(scope);
+ if (manifest) {
+ let name = path.basename(manifest);
+ for (let testType of testTypes) {
+ if (name.startsWith(testType)) {
+ return testType;
+ }
+ }
+ }
+
+ let filepath = this.cleanUpPath(scope.getFilename());
+ let filename = path.basename(filepath);
+
+ if (filename.startsWith("browser_")) {
+ return "browser";
+ }
+
+ if (filename.startsWith("test_")) {
+ let parent = path.basename(path.dirname(filepath));
+ for (let testType of testTypes) {
+ if (parent.startsWith(testType)) {
+ return testType;
+ }
+ }
+
+ // It likely is a test, we're just not sure what kind.
+ return "unknown";
+ }
+
+ // Likely not a test
+ return null;
+ },
+
+ getIsWorker(filePath) {
+ let filename = path.basename(this.cleanUpPath(filePath)).toLowerCase();
+
+ return filename.includes("worker");
+ },
+
+ /**
+ * Gets the root directory of the repository by walking up directories from
+ * this file until a .eslintignore file is found. If this fails, the same
+ * procedure will be attempted from the current working dir.
+ * @return {String} The absolute path of the repository directory
+ */
+ get rootDir() {
+ if (!gRootDir) {
+ function searchUpForIgnore(dirName, filename) {
+ let parsed = path.parse(dirName);
+ while (parsed.root !== dirName) {
+ if (fs.existsSync(path.join(dirName, filename))) {
+ return dirName;
+ }
+ // Move up a level
+ dirName = parsed.dir;
+ parsed = path.parse(dirName);
+ }
+ return null;
+ }
+
+ let possibleRoot = searchUpForIgnore(
+ path.dirname(module.filename),
+ ".eslintignore"
+ );
+ if (!possibleRoot) {
+ possibleRoot = searchUpForIgnore(path.resolve(), ".eslintignore");
+ }
+ if (!possibleRoot) {
+ possibleRoot = searchUpForIgnore(path.resolve(), "package.json");
+ }
+ if (!possibleRoot) {
+ // We've couldn't find a root from the module or CWD, so lets just go
+ // for the CWD. We really don't want to throw if possible, as that
+ // tends to give confusing results when used with ESLint.
+ possibleRoot = process.cwd();
+ }
+
+ gRootDir = possibleRoot;
+ }
+
+ return gRootDir;
+ },
+
+ /**
+ * ESLint may be executed from various places: from mach, at the root of the
+ * repository, or from a directory in the repository when, for instance,
+ * executed by a text editor's plugin.
+ * The value returned by context.getFileName() varies because of this.
+ * This helper function makes sure to return an absolute file path for the
+ * current context, by looking at process.cwd().
+ * @param {Context} context
+ * @return {String} The absolute path
+ */
+ getAbsoluteFilePath(context) {
+ var fileName = this.cleanUpPath(context.getFilename());
+ var cwd = process.cwd();
+
+ if (path.isAbsolute(fileName)) {
+ // Case 2: executed from the repo's root with mach:
+ // fileName: /path/to/mozilla/repo/a/b/c/d.js
+ // cwd: /path/to/mozilla/repo
+ return fileName;
+ } else if (path.basename(fileName) == fileName) {
+ // Case 1b: executed from a nested directory, fileName is the base name
+ // without any path info (happens in Atom with linter-eslint)
+ return path.join(cwd, fileName);
+ }
+ // Case 1: executed form in a nested directory, e.g. from a text editor:
+ // fileName: a/b/c/d.js
+ // cwd: /path/to/mozilla/repo/a/b/c
+ var dirName = path.dirname(fileName);
+ return cwd.slice(0, cwd.length - dirName.length) + fileName;
+ },
+
+ /**
+ * When ESLint is run from SublimeText, paths retrieved from
+ * context.getFileName contain leading and trailing double-quote characters.
+ * These characters need to be removed.
+ */
+ cleanUpPath(pathName) {
+ return pathName.replace(/^"/, "").replace(/"$/, "");
+ },
+
+ get globalScriptPaths() {
+ return [
+ path.join(this.rootDir, "browser", "base", "content", "browser.xhtml"),
+ path.join(
+ this.rootDir,
+ "browser",
+ "base",
+ "content",
+ "global-scripts.inc"
+ ),
+ ];
+ },
+
+ isMozillaCentralBased() {
+ return fs.existsSync(this.globalScriptPaths[0]);
+ },
+
+ getSavedEnvironmentItems(environment) {
+ return require("./environments/saved-globals.json").environments[
+ environment
+ ];
+ },
+
+ getSavedRuleData(rule) {
+ return require("./rules/saved-rules-data.json").rulesData[rule];
+ },
+
+ getBuildEnvironment() {
+ var { execFileSync } = require("child_process");
+ var output = execFileSync(
+ path.join(this.rootDir, "mach"),
+ ["environment", "--format=json"],
+ { silent: true }
+ );
+ return JSON.parse(output);
+ },
+
+ /**
+ * Extract the path of require (and require-like) helpers used in DevTools.
+ */
+ getDevToolsRequirePath(node) {
+ if (
+ node.callee.type == "Identifier" &&
+ node.callee.name == "require" &&
+ node.arguments.length == 1 &&
+ node.arguments[0].type == "Literal"
+ ) {
+ return node.arguments[0].value;
+ } else if (
+ node.callee.type == "MemberExpression" &&
+ node.callee.property.type == "Identifier" &&
+ node.callee.property.name == "lazyRequireGetter" &&
+ node.arguments.length >= 3 &&
+ node.arguments[2].type == "Literal"
+ ) {
+ return node.arguments[2].value;
+ }
+ return null;
+ },
+
+ /**
+ * Returns property name from MemberExpression. Also accepts Identifier for consistency.
+ * @param {import("estree").MemberExpression | import("estree").Identifier} node
+ * @returns {string | null}
+ *
+ * @example `foo` gives "foo"
+ * @example `foo.bar` gives "bar"
+ * @example `foo.bar.baz` gives "baz"
+ */
+ maybeGetMemberPropertyName(node) {
+ if (node.type === "MemberExpression") {
+ return node.property.name;
+ }
+ if (node.type === "Identifier") {
+ return node.name;
+ }
+ return null;
+ },
+};
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/index.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/index.js
new file mode 100644
index 0000000000..0801958597
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/index.js
@@ -0,0 +1,102 @@
+/**
+ * @fileoverview A collection of rules that help enforce JavaScript coding
+ * standard and avoid common errors in the Mozilla project.
+ * 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";
+
+// ------------------------------------------------------------------------------
+// Plugin Definition
+// ------------------------------------------------------------------------------
+module.exports = {
+ configs: {
+ "browser-test": require("../lib/configs/browser-test"),
+ "chrome-test": require("../lib/configs/chrome-test"),
+ "mochitest-test": require("../lib/configs/mochitest-test"),
+ recommended: require("../lib/configs/recommended"),
+ "require-jsdoc": require("../lib/configs/require-jsdoc"),
+ "valid-jsdoc": require("../lib/configs/valid-jsdoc"),
+ "xpcshell-test": require("../lib/configs/xpcshell-test"),
+ },
+ environments: {
+ "browser-window": require("../lib/environments/browser-window.js"),
+ "chrome-script": require("../lib/environments/chrome-script.js"),
+ "chrome-worker": require("../lib/environments/chrome-worker.js"),
+ "frame-script": require("../lib/environments/frame-script.js"),
+ jsm: require("../lib/environments/jsm.js"),
+ privileged: require("../lib/environments/privileged.js"),
+ "process-script": require("../lib/environments/process-script.js"),
+ "remote-page": require("../lib/environments/remote-page.js"),
+ simpletest: require("../lib/environments/simpletest.js"),
+ sjs: require("../lib/environments/sjs.js"),
+ "special-powers-sandbox": require("../lib/environments/special-powers-sandbox.js"),
+ specific: require("../lib/environments/specific"),
+ testharness: require("../lib/environments/testharness.js"),
+ xpcshell: require("../lib/environments/xpcshell.js"),
+ },
+ rules: {
+ "avoid-Date-timing": require("../lib/rules/avoid-Date-timing"),
+ "avoid-removeChild": require("../lib/rules/avoid-removeChild"),
+ "balanced-listeners": require("../lib/rules/balanced-listeners"),
+ "balanced-observers": require("../lib/rules/balanced-observers"),
+ "consistent-if-bracing": require("../lib/rules/consistent-if-bracing"),
+ "import-browser-window-globals": require("../lib/rules/import-browser-window-globals"),
+ "import-content-task-globals": require("../lib/rules/import-content-task-globals"),
+ "import-globals": require("../lib/rules/import-globals"),
+ "import-headjs-globals": require("../lib/rules/import-headjs-globals"),
+ "lazy-getter-object-name": require("../lib/rules/lazy-getter-object-name"),
+ "mark-exported-symbols-as-used": require("../lib/rules/mark-exported-symbols-as-used"),
+ "mark-test-function-used": require("../lib/rules/mark-test-function-used"),
+ "no-aArgs": require("../lib/rules/no-aArgs"),
+ "no-addtask-setup": require("../lib/rules/no-addtask-setup"),
+ "no-arbitrary-setTimeout": require("../lib/rules/no-arbitrary-setTimeout"),
+ "no-browser-refs-in-toolkit": require("../lib/rules/no-browser-refs-in-toolkit"),
+ "no-compare-against-boolean-literals": require("../lib/rules/no-compare-against-boolean-literals"),
+ "no-comparison-or-assignment-inside-ok": require("../lib/rules/no-comparison-or-assignment-inside-ok"),
+ "no-cu-reportError": require("../lib/rules/no-cu-reportError"),
+ "no-define-cc-etc": require("../lib/rules/no-define-cc-etc"),
+ "no-redeclare-with-import-autofix": require("../lib/rules/no-redeclare-with-import-autofix"),
+ "no-throw-cr-literal": require("../lib/rules/no-throw-cr-literal"),
+ "no-useless-parameters": require("../lib/rules/no-useless-parameters"),
+ "no-useless-removeEventListener": require("../lib/rules/no-useless-removeEventListener"),
+ "no-useless-run-test": require("../lib/rules/no-useless-run-test"),
+ "prefer-boolean-length-check": require("../lib/rules/prefer-boolean-length-check"),
+ "prefer-formatValues": require("../lib/rules/prefer-formatValues"),
+ "reject-addtask-only": require("../lib/rules/reject-addtask-only"),
+ "reject-chromeutils-import": require("../lib/rules/reject-chromeutils-import"),
+ "reject-chromeutils-import-params": require("../lib/rules/reject-chromeutils-import-params"),
+ "reject-eager-module-in-lazy-getter": require("../lib/rules/reject-eager-module-in-lazy-getter"),
+ "reject-global-this": require("../lib/rules/reject-global-this"),
+ "reject-globalThis-modification": require("../lib/rules/reject-globalThis-modification"),
+ "reject-import-system-module-from-non-system": require("../lib/rules/reject-import-system-module-from-non-system"),
+ "reject-importGlobalProperties": require("../lib/rules/reject-importGlobalProperties"),
+ "reject-lazy-imports-into-globals": require("../lib/rules/reject-lazy-imports-into-globals"),
+ "reject-mixing-eager-and-lazy": require("../lib/rules/reject-mixing-eager-and-lazy"),
+ "reject-multiple-getters-calls": require("../lib/rules/reject-multiple-getters-calls"),
+ "reject-scriptableunicodeconverter": require("../lib/rules/reject-scriptableunicodeconverter"),
+ "reject-relative-requires": require("../lib/rules/reject-relative-requires"),
+ "reject-some-requires": require("../lib/rules/reject-some-requires"),
+ "reject-top-level-await": require("../lib/rules/reject-top-level-await"),
+ "rejects-requires-await": require("../lib/rules/rejects-requires-await"),
+ "use-cc-etc": require("../lib/rules/use-cc-etc"),
+ "use-chromeutils-definelazygetter": require("../lib/rules/use-chromeutils-definelazygetter"),
+ "use-chromeutils-generateqi": require("../lib/rules/use-chromeutils-generateqi"),
+ "use-chromeutils-import": require("../lib/rules/use-chromeutils-import"),
+ "use-console-createInstance": require("../lib/rules/use-console-createInstance"),
+ "use-default-preference-values": require("../lib/rules/use-default-preference-values"),
+ "use-ownerGlobal": require("../lib/rules/use-ownerGlobal"),
+ "use-includes-instead-of-indexOf": require("../lib/rules/use-includes-instead-of-indexOf"),
+ "use-isInstance": require("./rules/use-isInstance"),
+ "use-returnValue": require("../lib/rules/use-returnValue"),
+ "use-services": require("../lib/rules/use-services"),
+ "use-static-import": require("../lib/rules/use-static-import"),
+ "valid-ci-uses": require("../lib/rules/valid-ci-uses"),
+ "valid-lazy": require("../lib/rules/valid-lazy"),
+ "valid-services": require("../lib/rules/valid-services"),
+ "valid-services-property": require("../lib/rules/valid-services-property"),
+ "var-only-at-top-level": require("../lib/rules/var-only-at-top-level"),
+ },
+};
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/avoid-Date-timing.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/avoid-Date-timing.js
new file mode 100644
index 0000000000..437c53e244
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/avoid-Date-timing.js
@@ -0,0 +1,61 @@
+/**
+ * @fileoverview Disallow using Date for timing in performance sensitive code
+ *
+ * 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 = {
+ meta: {
+ docs: {
+ url: "https://firefox-source-docs.mozilla.org/code-quality/lint/linters/eslint-plugin-mozilla/rules/avoid-Date-timing.html",
+ },
+ messages: {
+ usePerfNow:
+ "use performance.now() instead of Date.now() for timing measurements",
+ },
+ schema: [],
+ type: "problem",
+ },
+
+ create(context) {
+ return {
+ CallExpression(node) {
+ let callee = node.callee;
+ if (
+ callee.type !== "MemberExpression" ||
+ callee.object.type !== "Identifier" ||
+ callee.object.name !== "Date" ||
+ callee.property.type !== "Identifier" ||
+ callee.property.name !== "now"
+ ) {
+ return;
+ }
+
+ context.report({
+ node,
+ messageId: "usePerfNow",
+ });
+ },
+
+ NewExpression(node) {
+ let callee = node.callee;
+ if (
+ callee.type !== "Identifier" ||
+ callee.name !== "Date" ||
+ node.arguments.length
+ ) {
+ return;
+ }
+
+ context.report({
+ node,
+ messageId: "usePerfNow",
+ });
+ },
+ };
+ },
+};
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/avoid-removeChild.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/avoid-removeChild.js
new file mode 100644
index 0000000000..6c74d8aa59
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/avoid-removeChild.js
@@ -0,0 +1,70 @@
+/**
+ * @fileoverview Reject using element.parentNode.removeChild(element) when
+ * element.remove() can be used instead.
+ *
+ * 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";
+
+var helpers = require("../helpers");
+
+module.exports = {
+ meta: {
+ docs: {
+ url: "https://firefox-source-docs.mozilla.org/code-quality/lint/linters/eslint-plugin-mozilla/rules/avoid-removeChild.html",
+ },
+ messages: {
+ useRemove:
+ "use element.remove() instead of element.parentNode.removeChild(element)",
+ useFirstChildRemove:
+ "use element.firstChild.remove() instead of element.removeChild(element.firstChild)",
+ },
+ schema: [],
+ type: "suggestion",
+ },
+
+ create(context) {
+ return {
+ CallExpression(node) {
+ let callee = node.callee;
+ if (
+ callee.type !== "MemberExpression" ||
+ callee.property.type !== "Identifier" ||
+ callee.property.name != "removeChild" ||
+ node.arguments.length != 1
+ ) {
+ return;
+ }
+
+ if (
+ callee.object.type == "MemberExpression" &&
+ callee.object.property.type == "Identifier" &&
+ callee.object.property.name == "parentNode" &&
+ helpers.getASTSource(callee.object.object, context) ==
+ helpers.getASTSource(node.arguments[0])
+ ) {
+ context.report({
+ node,
+ messageId: "useRemove",
+ });
+ }
+
+ if (
+ node.arguments[0].type == "MemberExpression" &&
+ node.arguments[0].property.type == "Identifier" &&
+ node.arguments[0].property.name == "firstChild" &&
+ helpers.getASTSource(callee.object, context) ==
+ helpers.getASTSource(node.arguments[0].object)
+ ) {
+ context.report({
+ node,
+ messageId: "useFirstChildRemove",
+ });
+ }
+ },
+ };
+ },
+};
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/balanced-listeners.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/balanced-listeners.js
new file mode 100644
index 0000000000..f1c98a01bc
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/balanced-listeners.js
@@ -0,0 +1,149 @@
+/**
+ * @fileoverview Check that there's a removeEventListener for each
+ * addEventListener and an off for each on.
+ * Note that for now, this rule is rather simple in that it only checks that
+ * for each event name there is both an add and remove listener. It doesn't
+ * check that these are called on the right objects or with the same callback.
+ *
+ * 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 = {
+ meta: {
+ docs: {
+ url: "https://firefox-source-docs.mozilla.org/code-quality/lint/linters/eslint-plugin-mozilla/rules/balanced-listeners.html",
+ },
+ messages: {
+ noCorresponding:
+ "No corresponding '{{functionName}}({{type}})' was found.",
+ },
+ schema: [],
+ type: "problem",
+ },
+
+ create(context) {
+ var DICTIONARY = {
+ addEventListener: "removeEventListener",
+ on: "off",
+ };
+ // Invert this dictionary to make it easy later.
+ var INVERTED_DICTIONARY = {};
+ for (var i in DICTIONARY) {
+ INVERTED_DICTIONARY[DICTIONARY[i]] = i;
+ }
+
+ // Collect the add/remove listeners in these 2 arrays.
+ var addedListeners = [];
+ var removedListeners = [];
+
+ function addAddedListener(node) {
+ var capture = false;
+ let options = node.arguments[2];
+ if (options) {
+ if (options.type == "ObjectExpression") {
+ if (
+ options.properties.some(
+ p => p.key.name == "once" && p.value.value === true
+ )
+ ) {
+ // No point in adding listeners using the 'once' option.
+ return;
+ }
+ capture = options.properties.some(
+ p => p.key.name == "capture" && p.value.value === true
+ );
+ } else {
+ capture = options.value;
+ }
+ }
+ addedListeners.push({
+ functionName: node.callee.property.name,
+ type: node.arguments[0].value,
+ node: node.callee.property,
+ useCapture: capture,
+ });
+ }
+
+ function addRemovedListener(node) {
+ var capture = false;
+ let options = node.arguments[2];
+ if (options) {
+ if (options.type == "ObjectExpression") {
+ capture = options.properties.some(
+ p => p.key.name == "capture" && p.value.value === true
+ );
+ } else {
+ capture = options.value;
+ }
+ }
+ removedListeners.push({
+ functionName: node.callee.property.name,
+ type: node.arguments[0].value,
+ useCapture: capture,
+ });
+ }
+
+ function getUnbalancedListeners() {
+ var unbalanced = [];
+
+ for (var j = 0; j < addedListeners.length; j++) {
+ if (!hasRemovedListener(addedListeners[j])) {
+ unbalanced.push(addedListeners[j]);
+ }
+ }
+ addedListeners = removedListeners = [];
+
+ return unbalanced;
+ }
+
+ function hasRemovedListener(addedListener) {
+ for (var k = 0; k < removedListeners.length; k++) {
+ var listener = removedListeners[k];
+ if (
+ DICTIONARY[addedListener.functionName] === listener.functionName &&
+ addedListener.type === listener.type &&
+ addedListener.useCapture === listener.useCapture
+ ) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ return {
+ CallExpression(node) {
+ if (node.arguments.length === 0) {
+ return;
+ }
+
+ if (node.callee.type === "MemberExpression") {
+ var listenerMethodName = node.callee.property.name;
+
+ if (DICTIONARY.hasOwnProperty(listenerMethodName)) {
+ addAddedListener(node);
+ } else if (INVERTED_DICTIONARY.hasOwnProperty(listenerMethodName)) {
+ addRemovedListener(node);
+ }
+ }
+ },
+
+ "Program:exit": function () {
+ getUnbalancedListeners().forEach(function (listener) {
+ context.report({
+ node: listener.node,
+ messageId: "noCorresponding",
+ data: {
+ functionName: DICTIONARY[listener.functionName],
+ type: listener.type,
+ },
+ });
+ });
+ },
+ };
+ },
+};
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/balanced-observers.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/balanced-observers.js
new file mode 100644
index 0000000000..854fbc9a63
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/balanced-observers.js
@@ -0,0 +1,121 @@
+/**
+ * @fileoverview Check that there's a Services.(prefs|obs).removeObserver for
+ * each addObserver.
+ *
+ * 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 = {
+ meta: {
+ docs: {
+ url: "https://firefox-source-docs.mozilla.org/code-quality/lint/linters/eslint-plugin-mozilla/rules/balanced-observers.html",
+ },
+ messages: {
+ noCorresponding:
+ "No corresponding 'removeObserver(\"{{observable}}\")' was found.",
+ },
+ schema: [],
+ type: "problem",
+ },
+
+ create(context) {
+ var addedObservers = [];
+ var removedObservers = [];
+
+ function getObserverAPI(node) {
+ const object = node.callee.object;
+ if (
+ object.type == "MemberExpression" &&
+ object.property.type == "Identifier"
+ ) {
+ return object.property.name;
+ }
+ return null;
+ }
+
+ function isServicesObserver(api) {
+ return api == "obs" || api == "prefs";
+ }
+
+ function getObservableName(node, api) {
+ if (api === "obs") {
+ return node.arguments[1].value;
+ }
+ return node.arguments[0].value;
+ }
+
+ function addAddedObserver(node) {
+ const api = getObserverAPI(node);
+ if (!isServicesObserver(api)) {
+ return;
+ }
+
+ addedObservers.push({
+ functionName: node.callee.property.name,
+ observable: getObservableName(node, api),
+ node: node.callee.property,
+ });
+ }
+
+ function addRemovedObserver(node) {
+ const api = getObserverAPI(node);
+ if (!isServicesObserver(api)) {
+ return;
+ }
+
+ removedObservers.push({
+ functionName: node.callee.property.name,
+ observable: getObservableName(node, api),
+ });
+ }
+
+ function getUnbalancedObservers() {
+ const unbalanced = addedObservers.filter(
+ observer => !hasRemovedObserver(observer)
+ );
+ addedObservers = removedObservers = [];
+
+ return unbalanced;
+ }
+
+ function hasRemovedObserver(addedObserver) {
+ return removedObservers.some(
+ observer => addedObserver.observable === observer.observable
+ );
+ }
+
+ return {
+ CallExpression(node) {
+ if (node.arguments.length === 0) {
+ return;
+ }
+
+ if (node.callee.type === "MemberExpression") {
+ var methodName = node.callee.property.name;
+
+ if (methodName === "addObserver") {
+ addAddedObserver(node);
+ } else if (methodName === "removeObserver") {
+ addRemovedObserver(node);
+ }
+ }
+ },
+
+ "Program:exit": function () {
+ getUnbalancedObservers().forEach(function (observer) {
+ context.report({
+ node: observer.node,
+ messageId: "noCorresponding",
+ data: {
+ observable: observer.observable,
+ },
+ });
+ });
+ },
+ };
+ },
+};
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/consistent-if-bracing.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/consistent-if-bracing.js
new file mode 100644
index 0000000000..0c9c9a342f
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/consistent-if-bracing.js
@@ -0,0 +1,54 @@
+/**
+ * @fileoverview checks if/else if/else bracing is consistent
+ *
+ * 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 = {
+ meta: {
+ docs: {
+ url: "https://firefox-source-docs.mozilla.org/code-quality/lint/linters/eslint-plugin-mozilla/rules/consistent-if-bracing.html",
+ },
+ messages: {
+ consistentIfBracing: "Bracing of if..else bodies should be consistent.",
+ },
+ schema: [],
+ type: "layout",
+ },
+
+ create(context) {
+ return {
+ IfStatement(node) {
+ if (node.parent.type !== "IfStatement") {
+ let types = new Set();
+ for (
+ let currentNode = node;
+ currentNode;
+ currentNode = currentNode.alternate
+ ) {
+ let type = currentNode.consequent.type;
+ types.add(type == "BlockStatement" ? "Block" : "NotBlock");
+ if (
+ currentNode.alternate &&
+ currentNode.alternate.type !== "IfStatement"
+ ) {
+ type = currentNode.alternate.type;
+ types.add(type == "BlockStatement" ? "Block" : "NotBlock");
+ break;
+ }
+ }
+ if (types.size > 1) {
+ context.report({
+ node,
+ messageId: "consistentIfBracing",
+ });
+ }
+ }
+ },
+ };
+ },
+};
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/import-browser-window-globals.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/import-browser-window-globals.js
new file mode 100644
index 0000000000..7a099ba340
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/import-browser-window-globals.js
@@ -0,0 +1,50 @@
+/**
+ * @fileoverview For scripts included in browser-window, this will automatically
+ * inject the browser-window global scopes into the file.
+ *
+ * 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";
+
+var path = require("path");
+var helpers = require("../helpers");
+var browserWindowEnv = require("../environments/browser-window");
+
+module.exports = {
+ // This rule currently has no messages.
+ // eslint-disable-next-line eslint-plugin/prefer-message-ids
+ meta: {
+ docs: {
+ url: "https://firefox-source-docs.mozilla.org/code-quality/lint/linters/eslint-plugin-mozilla/rules/import-browser-window-globals.html",
+ },
+ schema: [],
+ type: "problem",
+ },
+
+ create(context) {
+ return {
+ Program(node) {
+ let filePath = helpers.getAbsoluteFilePath(context);
+ let relativePath = path.relative(helpers.rootDir, filePath);
+ // We need to translate the path on Windows, due to the change
+ // from \ to /, and browserjsScripts assumes Posix.
+ if (path.win32) {
+ relativePath = relativePath.split(path.sep).join("/");
+ }
+
+ if (browserWindowEnv.browserjsScripts?.includes(relativePath)) {
+ for (let global in browserWindowEnv.globals) {
+ helpers.addVarToScope(
+ global,
+ context.getScope(),
+ browserWindowEnv.globals[global]
+ );
+ }
+ }
+ },
+ };
+ },
+};
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/import-content-task-globals.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/import-content-task-globals.js
new file mode 100644
index 0000000000..e2b66ce8b0
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/import-content-task-globals.js
@@ -0,0 +1,73 @@
+/**
+ * @fileoverview For ContentTask.spawn, this will automatically declare the
+ * frame script variables in the global scope.
+ * 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 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";
+
+var helpers = require("../helpers");
+var frameScriptEnv = require("../environments/frame-script");
+var sandboxEnv = require("../environments/special-powers-sandbox");
+
+module.exports = {
+ // eslint-disable-next-line eslint-plugin/prefer-message-ids
+ meta: {
+ docs: {
+ url: "https://firefox-source-docs.mozilla.org/code-quality/lint/linters/eslint-plugin-mozilla/rules/import-content-task-globals.html",
+ },
+ schema: [],
+ type: "problem",
+ },
+
+ create(context) {
+ return {
+ "CallExpression[callee.object.name='ContentTask'][callee.property.name='spawn']":
+ function (node) {
+ // testing/mochitest/BrowserTestUtils/content/content-task.js
+ // This script is loaded as a sub script into a frame script.
+ for (let [name, value] of Object.entries(frameScriptEnv.globals)) {
+ helpers.addVarToScope(name, context.getScope(), value);
+ }
+ },
+ "CallExpression[callee.object.name='SpecialPowers'][callee.property.name='spawn']":
+ function (node) {
+ for (let [name, value] of Object.entries(sandboxEnv.globals)) {
+ helpers.addVarToScope(name, context.getScope(), value);
+ }
+ let globals = [
+ // testing/specialpowers/content/SpecialPowersChild.sys.mjs
+ // SpecialPowersChild._spawnTask
+ "SpecialPowers",
+ "ContentTaskUtils",
+ "content",
+ "docShell",
+ ];
+ for (let global of globals) {
+ helpers.addVarToScope(global, context.getScope(), false);
+ }
+ },
+ "CallExpression[callee.object.name='SpecialPowers'][callee.property.name='spawnChrome']":
+ function (node) {
+ for (let [name, value] of Object.entries(sandboxEnv.globals)) {
+ helpers.addVarToScope(name, context.getScope(), value);
+ }
+ let globals = [
+ // testing/specialpowers/content/SpecialPowersParent.sys.mjs
+ // SpecialPowersParent._spawnChrome
+ "windowGlobalParent",
+ "browsingContext",
+ ];
+ for (let global of globals) {
+ helpers.addVarToScope(global, context.getScope(), false);
+ }
+ },
+ };
+ },
+};
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/import-globals.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/import-globals.js
new file mode 100644
index 0000000000..abbab511ff
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/import-globals.js
@@ -0,0 +1,21 @@
+/**
+ * @fileoverview Discovers all globals for the current file.
+ *
+ * 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 = {
+ meta: {
+ docs: {
+ url: "https://firefox-source-docs.mozilla.org/code-quality/lint/linters/eslint-plugin-mozilla/rules/import-globals.html",
+ },
+ schema: [],
+ type: "problem",
+ },
+
+ create: require("../globals").getESLintGlobalParser,
+};
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/import-headjs-globals.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/import-headjs-globals.js
new file mode 100644
index 0000000000..d4fa484b99
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/import-headjs-globals.js
@@ -0,0 +1,51 @@
+/**
+ * @fileoverview 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 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";
+
+var fs = require("fs");
+var helpers = require("../helpers");
+var globals = require("../globals");
+
+function importHead(context, path, node) {
+ try {
+ let stats = fs.statSync(path);
+ if (!stats.isFile()) {
+ return;
+ }
+ } catch (e) {
+ return;
+ }
+
+ let newGlobals = globals.getGlobalsForFile(path);
+ helpers.addGlobals(newGlobals, context.getScope());
+}
+
+module.exports = {
+ // This rule currently has no messages.
+ // eslint-disable-next-line eslint-plugin/prefer-message-ids
+ meta: {
+ docs: {
+ url: "https://firefox-source-docs.mozilla.org/code-quality/lint/linters/eslint-plugin-mozilla/rules/import-headjs-globals.html",
+ },
+ schema: [],
+ type: "problem",
+ },
+
+ create(context) {
+ return {
+ Program(node) {
+ let heads = helpers.getTestHeadFiles(context);
+ for (let head of heads) {
+ importHead(context, head, node);
+ }
+ },
+ };
+ },
+};
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/lazy-getter-object-name.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/lazy-getter-object-name.js
new file mode 100644
index 0000000000..b18cbc3725
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/lazy-getter-object-name.js
@@ -0,0 +1,48 @@
+/**
+ * @fileoverview Enforce the standard object name for
+ * ChromeUtils.defineESModuleGetters
+ *
+ * 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";
+
+function isIdentifier(node, id) {
+ return node.type === "Identifier" && node.name === id;
+}
+
+module.exports = {
+ meta: {
+ docs: {
+ url: "https://firefox-source-docs.mozilla.org/code-quality/lint/linters/eslint-plugin-mozilla/rules/lazy-getter-object-name.html",
+ },
+ messages: {
+ mustUseLazy:
+ "The variable name of the object passed to ChromeUtils.defineESModuleGetters must be `lazy`",
+ },
+ schema: [],
+ type: "problem",
+ },
+
+ create(context) {
+ return {
+ CallExpression(node) {
+ let { callee } = node;
+ if (
+ callee.type === "MemberExpression" &&
+ isIdentifier(callee.object, "ChromeUtils") &&
+ isIdentifier(callee.property, "defineESModuleGetters") &&
+ node.arguments.length >= 1 &&
+ !isIdentifier(node.arguments[0], "lazy")
+ ) {
+ context.report({
+ node,
+ messageId: "mustUseLazy",
+ });
+ }
+ },
+ };
+ },
+};
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/mark-exported-symbols-as-used.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/mark-exported-symbols-as-used.js
new file mode 100644
index 0000000000..5d0e57e4c8
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/mark-exported-symbols-as-used.js
@@ -0,0 +1,90 @@
+/**
+ * @fileoverview Simply marks exported symbols as used. Designed for use in
+ * .jsm files only.
+ *
+ * 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";
+
+function markArrayElementsAsUsed(context, node, expression) {
+ if (expression.type != "ArrayExpression") {
+ context.report({
+ node,
+ messageId: "nonArrayAssignedToImported",
+ });
+ return;
+ }
+
+ for (let element of expression.elements) {
+ context.markVariableAsUsed(element.value);
+ }
+ // Also mark EXPORTED_SYMBOLS as used.
+ context.markVariableAsUsed("EXPORTED_SYMBOLS");
+}
+
+// Ignore assignments not in the global scope, e.g. where special module
+// definitions are required due to having different ways of importing files,
+// e.g. osfile.
+function isGlobalScope(context) {
+ return !context.getScope().upper;
+}
+
+module.exports = {
+ meta: {
+ docs: {
+ url: "https://firefox-source-docs.mozilla.org/code-quality/lint/linters/eslint-plugin-mozilla/rules/mark-exported-symbols-as-used.html",
+ },
+ messages: {
+ useLetForExported:
+ "EXPORTED_SYMBOLS cannot be declared via `let`. Use `var` or `this.EXPORTED_SYMBOLS =`",
+ nonArrayAssignedToImported:
+ "Unexpected assignment of non-Array to EXPORTED_SYMBOLS",
+ },
+ schema: [],
+ type: "problem",
+ },
+
+ create(context) {
+ return {
+ AssignmentExpression(node, parents) {
+ if (
+ node.operator === "=" &&
+ node.left.type === "MemberExpression" &&
+ node.left.object.type === "ThisExpression" &&
+ node.left.property.name === "EXPORTED_SYMBOLS" &&
+ isGlobalScope(context)
+ ) {
+ markArrayElementsAsUsed(context, node, node.right);
+ }
+ },
+
+ VariableDeclaration(node, parents) {
+ if (!isGlobalScope(context)) {
+ return;
+ }
+
+ for (let item of node.declarations) {
+ if (
+ item.id &&
+ item.id.type == "Identifier" &&
+ item.id.name === "EXPORTED_SYMBOLS"
+ ) {
+ if (node.kind === "let") {
+ // The use of 'let' isn't allowed as the lexical scope may die after
+ // the script executes.
+ context.report({
+ node,
+ messageId: "useLetForExported",
+ });
+ }
+
+ markArrayElementsAsUsed(context, node, item.init);
+ }
+ }
+ },
+ };
+ },
+};
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/mark-test-function-used.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/mark-test-function-used.js
new file mode 100644
index 0000000000..4afe8a70ac
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/mark-test-function-used.js
@@ -0,0 +1,44 @@
+/**
+ * @fileoverview 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 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";
+
+var helpers = require("../helpers");
+
+module.exports = {
+ // This rule currently has no messages.
+ // eslint-disable-next-line eslint-plugin/prefer-message-ids
+ meta: {
+ docs: {
+ url: "https://firefox-source-docs.mozilla.org/code-quality/lint/linters/eslint-plugin-mozilla/rules/mark-test-function-used.html",
+ },
+ schema: [],
+ type: "problem",
+ },
+
+ create(context) {
+ return {
+ Program() {
+ let testType = helpers.getTestType(context);
+ if (testType == "browser") {
+ context.markVariableAsUsed("test");
+ }
+
+ if (testType == "xpcshell") {
+ context.markVariableAsUsed("run_test");
+ }
+
+ if (helpers.getIsSjs(context)) {
+ context.markVariableAsUsed("handleRequest");
+ }
+ },
+ };
+ },
+};
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/no-aArgs.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/no-aArgs.js
new file mode 100644
index 0000000000..7135890761
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/no-aArgs.js
@@ -0,0 +1,57 @@
+/**
+ * @fileoverview warns against using hungarian notation in function arguments
+ * (i.e. aArg).
+ *
+ * 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";
+
+function isPrefixed(name) {
+ return name.length >= 2 && /^a[A-Z]/.test(name);
+}
+
+function deHungarianize(name) {
+ return name.substring(1, 2).toLowerCase() + name.substring(2, name.length);
+}
+
+module.exports = {
+ meta: {
+ docs: {
+ url: "https://firefox-source-docs.mozilla.org/code-quality/lint/linters/eslint-plugin-mozilla/rules/no-aArgs.html",
+ },
+ messages: {
+ dontUseHungarian:
+ "Parameter '{{name}}' uses Hungarian Notation, consider using '{{suggestion}}' instead.",
+ },
+ schema: [],
+ type: "layout",
+ },
+
+ create(context) {
+ function checkFunction(node) {
+ for (var i = 0; i < node.params.length; i++) {
+ var param = node.params[i];
+ if (param.name && isPrefixed(param.name)) {
+ var errorObj = {
+ name: param.name,
+ suggestion: deHungarianize(param.name),
+ };
+ context.report({
+ node: param,
+ messageId: "dontUseHungarian",
+ data: errorObj,
+ });
+ }
+ }
+ }
+
+ return {
+ FunctionDeclaration: checkFunction,
+ ArrowFunctionExpression: checkFunction,
+ FunctionExpression: checkFunction,
+ };
+ },
+};
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/no-addtask-setup.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/no-addtask-setup.js
new file mode 100644
index 0000000000..e711252e09
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/no-addtask-setup.js
@@ -0,0 +1,57 @@
+/**
+ * @fileoverview Reject `add_task(async function setup` or similar patterns in
+ * favour of add_setup.
+ *
+ * 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";
+
+function isNamedLikeSetup(name) {
+ return /^(init|setup)$/i.test(name);
+}
+
+module.exports = {
+ meta: {
+ docs: {
+ url: "https://firefox-source-docs.mozilla.org/code-quality/lint/linters/eslint-plugin-mozilla/rules/no-addtask-setup.html",
+ },
+ fixable: "code",
+ messages: {
+ useAddSetup: "Do not use add_task() for setup, use add_setup() instead.",
+ },
+ schema: [],
+ type: "suggestion",
+ },
+ create(context) {
+ return {
+ "Program > ExpressionStatement > CallExpression": function (node) {
+ let callee = node.callee;
+ if (callee.type === "Identifier" && callee.name === "add_task") {
+ let arg = node.arguments[0];
+ if (
+ arg.type !== "FunctionExpression" ||
+ !arg.id ||
+ !isNamedLikeSetup(arg.id.name)
+ ) {
+ return;
+ }
+ context.report({
+ node,
+ messageId: "useAddSetup",
+ fix: fixer => {
+ let range = [node.callee.range[0], arg.id.range[1]];
+ let asyncOrNot = arg.async ? "async " : "";
+ return fixer.replaceTextRange(
+ range,
+ `add_setup(${asyncOrNot}function`
+ );
+ },
+ });
+ }
+ },
+ };
+ },
+};
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/no-arbitrary-setTimeout.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/no-arbitrary-setTimeout.js
new file mode 100644
index 0000000000..d0e891292d
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/no-arbitrary-setTimeout.js
@@ -0,0 +1,65 @@
+/**
+ * @fileoverview Reject use of non-zero values in setTimeout
+ *
+ * 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";
+
+var helpers = require("../helpers");
+var testTypes = new Set(["browser", "xpcshell"]);
+
+module.exports = {
+ meta: {
+ docs: {
+ url: "https://firefox-source-docs.mozilla.org/code-quality/lint/linters/eslint-plugin-mozilla/rules/no-arbitrary-setTimeout.html",
+ },
+ messages: {
+ listenForEvents:
+ "listen for events instead of setTimeout() with arbitrary delay",
+ },
+ schema: [],
+ type: "problem",
+ },
+
+ create(context) {
+ // We don't want to run this on mochitest plain as it already
+ // prevents flaky setTimeout at runtime. This check is built-in
+ // to the rule itself as sometimes other tests can live alongside
+ // plain mochitests and so it can't be configured via eslintrc.
+ if (!testTypes.has(helpers.getTestType(context))) {
+ return {};
+ }
+
+ return {
+ CallExpression(node) {
+ let callee = node.callee;
+ if (callee.type === "MemberExpression") {
+ if (
+ callee.property.name !== "setTimeout" ||
+ callee.object.name !== "window" ||
+ node.arguments.length < 2
+ ) {
+ return;
+ }
+ } else if (callee.type === "Identifier") {
+ if (callee.name !== "setTimeout" || node.arguments.length < 2) {
+ return;
+ }
+ } else {
+ return;
+ }
+
+ let timeout = node.arguments[1];
+ if (timeout.type !== "Literal" || timeout.value > 0) {
+ context.report({
+ node,
+ messageId: "listenForEvents",
+ });
+ }
+ },
+ };
+ },
+};
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/no-browser-refs-in-toolkit.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/no-browser-refs-in-toolkit.js
new file mode 100644
index 0000000000..fea94d364e
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/no-browser-refs-in-toolkit.js
@@ -0,0 +1,48 @@
+/**
+ * @fileoverview Reject use of browser/-based references from code in
+ * directories like toolkit/ that ought not to depend on
+ * running inside desktop Firefox.
+ *
+ * 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 = {
+ meta: {
+ docs: {
+ url: "https://firefox-source-docs.mozilla.org/code-quality/lint/linters/eslint-plugin-mozilla/rules/no-browser-refs-in-toolkit.html",
+ },
+ messages: {
+ noBrowserChrome:
+ "> {{url}} is part of Desktop Firefox and cannot be unconditionally " +
+ "used by this code (which has to also work elsewhere).",
+ },
+ schema: [],
+ type: "suggestion",
+ },
+
+ create(context) {
+ return {
+ Literal(node) {
+ if (typeof node.value != "string") {
+ return;
+ }
+ if (
+ node.value.startsWith("chrome://browser") ||
+ node.value.startsWith("resource:///") ||
+ node.value.startsWith("resource://app/") ||
+ (node.value.startsWith("browser/") && node.value.endsWith(".ftl"))
+ ) {
+ context.report({
+ node,
+ messageId: "noBrowserChrome",
+ data: { url: node.value },
+ });
+ }
+ },
+ };
+ },
+};
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/no-compare-against-boolean-literals.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/no-compare-against-boolean-literals.js
new file mode 100644
index 0000000000..cf52b2ad21
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/no-compare-against-boolean-literals.js
@@ -0,0 +1,40 @@
+/**
+ * @fileoverview Restrict comparing against `true` or `false`.
+ *
+ * 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 = {
+ meta: {
+ docs: {
+ url: "https://firefox-source-docs.mozilla.org/code-quality/lint/linters/eslint-plugin-mozilla/rules/no-compare-against-boolean-literals.html",
+ },
+ messages: {
+ noCompareBoolean:
+ "Don't compare for inexact equality against boolean literals",
+ },
+ schema: [],
+ type: "suggestion",
+ },
+
+ create(context) {
+ return {
+ BinaryExpression(node) {
+ if (
+ ["==", "!="].includes(node.operator) &&
+ (["true", "false"].includes(node.left.raw) ||
+ ["true", "false"].includes(node.right.raw))
+ ) {
+ context.report({
+ node,
+ messageId: "noCompareBoolean",
+ });
+ }
+ },
+ };
+ },
+};
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/no-comparison-or-assignment-inside-ok.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/no-comparison-or-assignment-inside-ok.js
new file mode 100644
index 0000000000..9bab06b000
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/no-comparison-or-assignment-inside-ok.js
@@ -0,0 +1,80 @@
+/**
+ * @fileoverview Don't allow accidental assignments inside `ok()`,
+ * and encourage people to use appropriate alternatives
+ * when using comparisons between 2 values.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+"use strict";
+
+const operatorToAssertionMap = {
+ "==": "Assert.equal",
+ "===": "Assert.strictEqual",
+ "!=": "Assert.notEqual",
+ "!==": "Assert.notStrictEqual",
+ ">": "Assert.greater",
+ "<": "Assert.less",
+ "<=": "Assert.lessOrEqual",
+ ">=": "Assert.greaterOrEqual",
+};
+
+module.exports = {
+ meta: {
+ docs: {
+ url: "https://firefox-source-docs.mozilla.org/code-quality/lint/linters/eslint-plugin-mozilla/rules/no-comparison-or-assignment-inside-ok.html",
+ },
+ fixable: "code",
+ messages: {
+ assignment:
+ "Assigning to a variable inside ok() is odd - did you mean to compare the two?",
+ comparison:
+ "Use dedicated assertion methods rather than ok(a {{operator}} b).",
+ },
+ schema: [],
+ type: "suggestion",
+ },
+
+ create(context) {
+ const exprs = new Set(["BinaryExpression", "AssignmentExpression"]);
+ return {
+ CallExpression(node) {
+ if (node.callee.type != "Identifier" || node.callee.name != "ok") {
+ return;
+ }
+ let firstArg = node.arguments[0];
+ if (!exprs.has(firstArg.type)) {
+ return;
+ }
+ if (firstArg.type == "AssignmentExpression") {
+ context.report({
+ node: firstArg,
+ messageId: "assignment",
+ });
+ } else if (
+ firstArg.type == "BinaryExpression" &&
+ operatorToAssertionMap.hasOwnProperty(firstArg.operator)
+ ) {
+ context.report({
+ node,
+ messageId: "comparison",
+ data: { operator: firstArg.operator },
+ fix: fixer => {
+ let left = context.sourceCode.getText(firstArg.left);
+ let right = context.sourceCode.getText(firstArg.right);
+ return [
+ fixer.replaceText(firstArg, left + ", " + right),
+ fixer.replaceText(
+ node.callee,
+ operatorToAssertionMap[firstArg.operator]
+ ),
+ ];
+ },
+ });
+ }
+ },
+ };
+ },
+};
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/no-cu-reportError.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/no-cu-reportError.js
new file mode 100644
index 0000000000..85daa8823e
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/no-cu-reportError.js
@@ -0,0 +1,130 @@
+/**
+ * @fileoverview Reject common XPCOM methods called with useless optional
+ * parameters, or non-existent parameters.
+ *
+ * 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";
+
+function isCuReportError(node) {
+ return (
+ node.type == "MemberExpression" &&
+ node.object.type == "Identifier" &&
+ node.object.name == "Cu" &&
+ node.property.type == "Identifier" &&
+ node.property.name == "reportError"
+ );
+}
+
+function isConcatenation(node) {
+ return node.type == "BinaryExpression" && node.operator == "+";
+}
+
+function isIdentOrMember(node) {
+ return node.type == "MemberExpression" || node.type == "Identifier";
+}
+
+function isLiteralOrConcat(node) {
+ return node.type == "Literal" || isConcatenation(node);
+}
+
+function replaceConcatWithComma(fixer, node) {
+ let fixes = [];
+ let didFixTrailingIdentifier = false;
+ let recursiveFixes;
+ let trailingIdentifier;
+ // Deal with recursion first:
+ if (isConcatenation(node.right)) {
+ // Uh oh. If the RHS is a concatenation, there are parens involved,
+ // e.g.:
+ // console.error("literal" + (b + "literal"));
+ // It's pretty much impossible to guess what to do here so bail out:
+ return { fixes: [], trailingIdentifier: false };
+ }
+ if (isConcatenation(node.left)) {
+ ({ fixes: recursiveFixes, trailingIdentifier } = replaceConcatWithComma(
+ fixer,
+ node.left
+ ));
+ fixes.push(...recursiveFixes);
+ }
+ // If the left is an identifier or memberexpression, and the right is a
+ // literal or concatenation - or vice versa - replace a + with a comma:
+ if (
+ (isIdentOrMember(node.left) && isLiteralOrConcat(node.right)) ||
+ (isIdentOrMember(node.right) && isLiteralOrConcat(node.left)) ||
+ // Or if the rhs is a literal/concatenation, while the right-most part of
+ // the lhs is also an identifier (need 2 commas either side!)
+ (trailingIdentifier && isLiteralOrConcat(node.right))
+ ) {
+ fixes.push(
+ fixer.replaceTextRange([node.left.range[1], node.right.range[0]], ", ")
+ );
+ didFixTrailingIdentifier = isIdentOrMember(node.right);
+ }
+ return { fixes, trailingIdentifier: didFixTrailingIdentifier };
+}
+
+module.exports = {
+ meta: {
+ docs: {
+ url: "https://firefox-source-docs.mozilla.org/code-quality/lint/linters/eslint-plugin-mozilla/rules/no-cu-reportError.html",
+ },
+ fixable: "code",
+ messages: {
+ useConsoleError: "Please use console.error instead of Cu.reportError",
+ },
+ schema: [],
+ type: "suggestion",
+ },
+
+ create(context) {
+ return {
+ CallExpression(node) {
+ let checkNodes = [];
+ if (isCuReportError(node.callee)) {
+ // Handles cases of `Cu.reportError()`.
+ if (node.arguments.length > 1) {
+ // TODO: Bug 1802347 For initial landing, we allow the two
+ // argument form of Cu.reportError as the second argument is a stack
+ // argument which is more complicated to deal with.
+ return;
+ }
+ checkNodes = [node.callee];
+ } else if (node.arguments.length >= 1) {
+ // Handles cases of `.foo(Cu.reportError)`.
+ checkNodes = node.arguments.filter(n => isCuReportError(n));
+ }
+
+ for (let checkNode of checkNodes) {
+ context.report({
+ node,
+ fix: fixer => {
+ let fixes = [
+ fixer.replaceText(checkNode.object, "console"),
+ fixer.replaceText(checkNode.property, "error"),
+ ];
+ // If we're adding stuff together as an argument, split
+ // into multiple arguments instead:
+ if (
+ checkNode == node.callee &&
+ isConcatenation(node.arguments[0])
+ ) {
+ let { fixes: recursiveFixes } = replaceConcatWithComma(
+ fixer,
+ node.arguments[0]
+ );
+ fixes.push(...recursiveFixes);
+ }
+ return fixes;
+ },
+ messageId: "useConsoleError",
+ });
+ }
+ },
+ };
+ },
+};
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/no-define-cc-etc.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/no-define-cc-etc.js
new file mode 100644
index 0000000000..05e7648632
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/no-define-cc-etc.js
@@ -0,0 +1,57 @@
+/**
+ * @fileoverview Reject defining Cc/Ci/Cr/Cu.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+"use strict";
+
+const componentsBlacklist = ["Cc", "Ci", "Cr", "Cu"];
+
+module.exports = {
+ meta: {
+ docs: {
+ url: "https://firefox-source-docs.mozilla.org/code-quality/lint/linters/eslint-plugin-mozilla/rules/no-define-cc-etc.html",
+ },
+ messages: {
+ noSeparateDefinition:
+ "{{name}} is now defined in global scope, a separate definition is no longer necessary.",
+ },
+ schema: [],
+ type: "suggestion",
+ },
+
+ create(context) {
+ return {
+ VariableDeclarator(node) {
+ if (
+ node.id.type == "Identifier" &&
+ componentsBlacklist.includes(node.id.name)
+ ) {
+ context.report({
+ node,
+ messageId: "noSeparateDefinition",
+ data: { name: node.id.name },
+ });
+ }
+
+ if (node.id.type == "ObjectPattern") {
+ for (let property of node.id.properties) {
+ if (
+ property.type == "Property" &&
+ componentsBlacklist.includes(property.value.name)
+ ) {
+ context.report({
+ node,
+ messageId: "noSeparateDefinition",
+ data: { name: property.value.name },
+ });
+ }
+ }
+ }
+ },
+ };
+ },
+};
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/no-redeclare-with-import-autofix.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/no-redeclare-with-import-autofix.js
new file mode 100644
index 0000000000..d914e003d3
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/no-redeclare-with-import-autofix.js
@@ -0,0 +1,160 @@
+/**
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+"use strict";
+
+const { dirname, join } = require("path");
+
+const eslintBasePath = dirname(require.resolve("eslint"));
+
+const noredeclarePath = join(eslintBasePath, "rules/no-redeclare.js");
+const baseRule = require(noredeclarePath);
+const astUtils = require(join(eslintBasePath, "rules/utils/ast-utils.js"));
+
+// Hack alert: our eslint env is pretty confused about `require` and
+// `loader` for devtools modules - so ignore it for now.
+// See bug 1812547
+const gIgnoredImports = new Set(["loader", "require"]);
+
+/**
+ * Create a trap for a call to `report` that the original rule is
+ * trying to make on `context`.
+ *
+ * Returns a function that forwards to `report` but provides a fixer
+ * for redeclared imports that just removes those imports.
+ *
+ * @return {function}
+ */
+function trapReport(context) {
+ return function (obj) {
+ let declarator = obj.node.parent;
+ while (
+ declarator &&
+ declarator.parent &&
+ declarator.type != "VariableDeclarator"
+ ) {
+ declarator = declarator.parent;
+ }
+ if (
+ declarator &&
+ declarator.type == "VariableDeclarator" &&
+ declarator.id.type == "ObjectPattern" &&
+ declarator.init.type == "CallExpression"
+ ) {
+ let initialization = declarator.init;
+ if (
+ astUtils.isSpecificMemberAccess(
+ initialization.callee,
+ "ChromeUtils",
+ /^import(ESModule|)$/
+ )
+ ) {
+ // Hack alert: our eslint env is pretty confused about `require` and
+ // `loader` for devtools modules - so ignore it for now.
+ // See bug 1812547
+ if (gIgnoredImports.has(obj.node.name)) {
+ return;
+ }
+ // OK, we've got something we can fix. But we should be careful in case
+ // there are multiple imports being destructured.
+ // Do the easy (and common) case first - just one property:
+ if (declarator.id.properties.length == 1) {
+ context.report({
+ node: declarator.parent,
+ messageId: "duplicateImport",
+ data: {
+ name: declarator.id.properties[0].key.name,
+ },
+ fix(fixer) {
+ return fixer.remove(declarator.parent);
+ },
+ });
+ return;
+ }
+
+ // OK, figure out which import is duplicated here:
+ let node = obj.node.parent;
+ // Then remove a comma after it, or a comma before
+ // if there's no comma after it.
+ let sourceCode = context.getSourceCode();
+ let rangeToRemove = node.range;
+ let tokenAfter = sourceCode.getTokenAfter(node);
+ let tokenBefore = sourceCode.getTokenBefore(node);
+ if (astUtils.isCommaToken(tokenAfter)) {
+ rangeToRemove[1] = tokenAfter.range[1];
+ } else if (astUtils.isCommaToken(tokenBefore)) {
+ rangeToRemove[0] = tokenBefore.range[0];
+ }
+ context.report({
+ node,
+ messageId: "duplicateImport",
+ data: {
+ name: node.key.name,
+ },
+ fix(fixer) {
+ return fixer.removeRange(rangeToRemove);
+ },
+ });
+ return;
+ }
+ }
+ if (context.options[0]?.errorForNonImports) {
+ // Report the result from no-redeclare - we can't autofix it.
+ // This can happen for other redeclaration issues, e.g. naming
+ // variables in a way that conflicts with builtins like "URL" or
+ // "escape".
+ context.report(obj);
+ }
+ };
+}
+
+module.exports = {
+ meta: {
+ docs: {
+ url: "https://firefox-source-docs.mozilla.org/code-quality/lint/linters/eslint-plugin-mozilla/rules/no-redeclare-with-import-autofix.html",
+ },
+ messages: {
+ ...baseRule.meta.messages,
+ duplicateImport:
+ "The import of '{{ name }}' is redundant with one set up earlier (e.g. head.js or the browser window environment). It should be removed.",
+ },
+ schema: [
+ {
+ type: "object",
+ properties: {
+ errorForNonImports: {
+ type: "boolean",
+ default: true,
+ },
+ },
+ additionalProperties: false,
+ },
+ ],
+ type: "suggestion",
+ fixable: "code",
+ },
+
+ create(context) {
+ // Test modules get the browser env applied wrongly in some cases,
+ // don't try and remove imports there. This works out of the box
+ // for sys.mjs modules because eslint won't check builtinGlobals
+ // for the no-redeclare rule.
+ if (context.getFilename().endsWith(".jsm")) {
+ return {};
+ }
+ let newOptions = [{ builtinGlobals: true }];
+ const contextForBaseRule = Object.create(context, {
+ report: {
+ value: trapReport(context),
+ writable: false,
+ },
+ options: {
+ value: newOptions,
+ },
+ });
+ return baseRule.create(contextForBaseRule);
+ },
+};
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/no-throw-cr-literal.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/no-throw-cr-literal.js
new file mode 100644
index 0000000000..5ff6bfd7c9
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/no-throw-cr-literal.js
@@ -0,0 +1,101 @@
+/**
+ * @fileoverview Rule to prevent throwing bare Cr.ERRORs.
+ *
+ * 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";
+
+function isCr(object) {
+ return object.type === "Identifier" && object.name === "Cr";
+}
+
+function isComponentsResults(object) {
+ return (
+ object.type === "MemberExpression" &&
+ object.object.type === "Identifier" &&
+ object.object.name === "Components" &&
+ object.property.type === "Identifier" &&
+ object.property.name === "results"
+ );
+}
+
+function isNewError(argument) {
+ return (
+ argument.type === "NewExpression" &&
+ argument.callee.type === "Identifier" &&
+ argument.callee.name === "Error" &&
+ argument.arguments.length === 1
+ );
+}
+
+function fixT(context, node, argument, fixer) {
+ const sourceText = context.getSourceCode().getText(argument);
+ return fixer.replaceText(node, `Components.Exception("", ${sourceText})`);
+}
+
+module.exports = {
+ meta: {
+ docs: {
+ url: "https://firefox-source-docs.mozilla.org/code-quality/lint/linters/eslint-plugin-mozilla/rules/no-throw-cr-literal.html",
+ },
+ fixable: "code",
+ messages: {
+ bareCR: "Do not throw bare Cr.ERRORs, use Components.Exception instead",
+ bareComponentsResults:
+ "Do not throw bare Components.results.ERRORs, use Components.Exception instead",
+ newErrorCR:
+ "Do not pass Cr.ERRORs to new Error(), use Components.Exception instead",
+ newErrorComponentsResults:
+ "Do not pass Components.results.ERRORs to new Error(), use Components.Exception instead",
+ },
+ schema: [],
+ type: "problem",
+ },
+
+ create(context) {
+ return {
+ ThrowStatement(node) {
+ if (node.argument.type === "MemberExpression") {
+ const fix = fixT.bind(null, context, node.argument, node.argument);
+
+ if (isCr(node.argument.object)) {
+ context.report({
+ node,
+ messageId: "bareCR",
+ fix,
+ });
+ } else if (isComponentsResults(node.argument.object)) {
+ context.report({
+ node,
+ messageId: "bareComponentsResults",
+ fix,
+ });
+ }
+ } else if (isNewError(node.argument)) {
+ const argument = node.argument.arguments[0];
+
+ if (argument.type === "MemberExpression") {
+ const fix = fixT.bind(null, context, node.argument, argument);
+
+ if (isCr(argument.object)) {
+ context.report({
+ node,
+ messageId: "newErrorCR",
+ fix,
+ });
+ } else if (isComponentsResults(argument.object)) {
+ context.report({
+ node,
+ messageId: "newErrorComponentsResults",
+ fix,
+ });
+ }
+ }
+ }
+ },
+ };
+ },
+};
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/no-useless-parameters.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/no-useless-parameters.js
new file mode 100644
index 0000000000..ac1cc334e6
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/no-useless-parameters.js
@@ -0,0 +1,156 @@
+/**
+ * @fileoverview Reject common XPCOM methods called with useless optional
+ * parameters, or non-existent parameters.
+ *
+ * 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 = {
+ meta: {
+ docs: {
+ url: "https://firefox-source-docs.mozilla.org/code-quality/lint/linters/eslint-plugin-mozilla/rules/no-useless-parameters.html",
+ },
+ fixable: "code",
+ messages: {
+ newURIParams: "newURI's last parameters are optional.",
+ obmittedWhenFalse:
+ "{{fnName}}'s {{index}} parameter can be omitted when it's false.",
+ onlyTakes: "{{fnName}} only takes {{params}}",
+ },
+ schema: [],
+ type: "suggestion",
+ },
+
+ create(context) {
+ function getRangeAfterArgToEnd(argNumber, args) {
+ let sourceCode = context.getSourceCode();
+ return [
+ sourceCode.getTokenAfter(args[argNumber]).range[0],
+ args[args.length - 1].range[1],
+ ];
+ }
+
+ return {
+ CallExpression(node) {
+ let callee = node.callee;
+ if (
+ callee.type !== "MemberExpression" ||
+ callee.property.type !== "Identifier"
+ ) {
+ return;
+ }
+
+ let isFalse = arg => arg.type === "Literal" && arg.value === false;
+ let isFalsy = arg => arg.type === "Literal" && !arg.value;
+ let isBool = arg =>
+ arg.type === "Literal" && (arg.value === false || arg.value === true);
+ let name = callee.property.name;
+ let args = node.arguments;
+
+ if (
+ ["addEventListener", "removeEventListener", "addObserver"].includes(
+ name
+ ) &&
+ args.length === 3 &&
+ isFalse(args[2])
+ ) {
+ context.report({
+ node,
+ fix: fixer => {
+ return fixer.removeRange(getRangeAfterArgToEnd(1, args));
+ },
+ messageId: "obmittedWhenFalse",
+ data: { fnName: name, index: "third" },
+ });
+ }
+
+ if (name === "clearUserPref" && args.length > 1) {
+ context.report({
+ node,
+ fix: fixer => {
+ return fixer.removeRange(getRangeAfterArgToEnd(0, args));
+ },
+ messageId: "onlyTakes",
+ data: { fnName: name, params: "1 parameter" },
+ });
+ }
+
+ if (name === "removeObserver" && args.length === 3 && isBool(args[2])) {
+ context.report({
+ node,
+ fix: fixer => {
+ return fixer.removeRange(getRangeAfterArgToEnd(1, args));
+ },
+ messageId: "onlyTakes",
+ data: { fnName: name, params: "2 parameters" },
+ });
+ }
+
+ if (name === "appendElement" && args.length === 2 && isFalse(args[1])) {
+ context.report({
+ node,
+ fix: fixer => {
+ return fixer.removeRange(getRangeAfterArgToEnd(0, args));
+ },
+ messageId: "obmittedWhenFalse",
+ data: { fnName: name, index: "second" },
+ });
+ }
+
+ if (
+ name === "notifyObservers" &&
+ args.length === 3 &&
+ isFalsy(args[2])
+ ) {
+ context.report({
+ node,
+ fix: fixer => {
+ return fixer.removeRange(getRangeAfterArgToEnd(1, args));
+ },
+ messageId: "obmittedWhenFalse",
+ data: { fnName: name, index: "third" },
+ });
+ }
+
+ if (
+ name === "getComputedStyle" &&
+ args.length === 2 &&
+ isFalsy(args[1])
+ ) {
+ context.report({
+ node,
+ fix: fixer => {
+ return fixer.removeRange(getRangeAfterArgToEnd(0, args));
+ },
+ messageId: "obmittedWhenFalse",
+ data: { fnName: "getComputedStyle", index: "second" },
+ });
+ }
+
+ if (
+ name === "newURI" &&
+ args.length > 1 &&
+ isFalsy(args[args.length - 1])
+ ) {
+ context.report({
+ node,
+ fix: fixer => {
+ if (args.length > 2 && isFalsy(args[args.length - 2])) {
+ return fixer.removeRange(getRangeAfterArgToEnd(0, args));
+ }
+
+ return fixer.removeRange(
+ getRangeAfterArgToEnd(args.length - 2, args)
+ );
+ },
+ messageId: "newURIParams",
+ });
+ }
+ },
+ };
+ },
+};
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/no-useless-removeEventListener.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/no-useless-removeEventListener.js
new file mode 100644
index 0000000000..d5f19ab717
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/no-useless-removeEventListener.js
@@ -0,0 +1,69 @@
+/**
+ * @fileoverview Reject calls to removeEventListenter where {once: true} could
+ * be used instead.
+ *
+ * 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 = {
+ meta: {
+ docs: {
+ url: "https://firefox-source-docs.mozilla.org/code-quality/lint/linters/eslint-plugin-mozilla/rules/no-useless-removeEventListener.html",
+ },
+ messages: {
+ useOnce:
+ "use {once: true} instead of removeEventListener as the first instruction of the listener",
+ },
+ schema: [],
+ type: "suggestion",
+ },
+
+ create(context) {
+ return {
+ CallExpression(node) {
+ let callee = node.callee;
+ if (
+ callee.type !== "MemberExpression" ||
+ callee.property.type !== "Identifier" ||
+ callee.property.name !== "addEventListener" ||
+ node.arguments.length == 4
+ ) {
+ return;
+ }
+
+ let listener = node.arguments[1];
+ if (
+ !listener ||
+ listener.type != "FunctionExpression" ||
+ !listener.body ||
+ listener.body.type != "BlockStatement" ||
+ !listener.body.body.length ||
+ listener.body.body[0].type != "ExpressionStatement" ||
+ listener.body.body[0].expression.type != "CallExpression"
+ ) {
+ return;
+ }
+
+ let call = listener.body.body[0].expression;
+ if (
+ call.callee.type == "MemberExpression" &&
+ call.callee.property.type == "Identifier" &&
+ call.callee.property.name == "removeEventListener" &&
+ ((call.arguments[0].type == "Literal" &&
+ call.arguments[0].value == node.arguments[0].value) ||
+ (call.arguments[0].type == "Identifier" &&
+ call.arguments[0].name == node.arguments[0].name))
+ ) {
+ context.report({
+ node: call,
+ messageId: "useOnce",
+ });
+ }
+ },
+ };
+ },
+};
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/no-useless-run-test.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/no-useless-run-test.js
new file mode 100644
index 0000000000..ddfbea05e3
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/no-useless-run-test.js
@@ -0,0 +1,76 @@
+/**
+ * @fileoverview Reject run_test() definitions where they aren't necessary.
+ *
+ * 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 = {
+ meta: {
+ docs: {
+ url: "https://firefox-source-docs.mozilla.org/code-quality/lint/linters/eslint-plugin-mozilla/rules/no-useless-run-test.html",
+ },
+ fixable: "code",
+ messages: {
+ noUselessRunTest:
+ "Useless run_test function - only contains run_next_test; whole function can be removed",
+ },
+ schema: [],
+ type: "suggestion",
+ },
+
+ create(context) {
+ return {
+ "Program > FunctionDeclaration": function (node) {
+ if (
+ node.id.name === "run_test" &&
+ node.body.type === "BlockStatement" &&
+ node.body.body.length === 1 &&
+ node.body.body[0].type === "ExpressionStatement" &&
+ node.body.body[0].expression.type === "CallExpression" &&
+ node.body.body[0].expression.callee.name === "run_next_test"
+ ) {
+ context.report({
+ node,
+ fix: fixer => {
+ let sourceCode = context.getSourceCode();
+ let startNode;
+ if (sourceCode.getCommentsBefore) {
+ // ESLint 4 has getCommentsBefore.
+ startNode = sourceCode.getCommentsBefore(node);
+ } else if (node && node.body && node.leadingComments) {
+ // This is for ESLint 3.
+ startNode = node.leadingComments;
+ }
+
+ // If we have comments, we want the start node to be the comments,
+ // rather than the token before the comments, so that we don't
+ // remove the comments - for run_test, these are likely to be useful
+ // information about the test.
+ if (startNode?.length) {
+ startNode = startNode[startNode.length - 1];
+ } else {
+ startNode = sourceCode.getTokenBefore(node);
+ }
+
+ return fixer.removeRange([
+ // If there's no startNode, we fall back to zero, i.e. start of
+ // file.
+ startNode ? startNode.range[1] + 1 : 0,
+ // We know the function is a block and it'll end with }. Normally
+ // there's a new line after that, so just advance past it. This
+ // may be slightly not dodgy in some cases, but covers the existing
+ // cases.
+ node.range[1] + 1,
+ ]);
+ },
+ messageId: "noUselessRunTest",
+ });
+ }
+ },
+ };
+ },
+};
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/prefer-boolean-length-check.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/prefer-boolean-length-check.js
new file mode 100644
index 0000000000..41c0aa1d30
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/prefer-boolean-length-check.js
@@ -0,0 +1,129 @@
+/**
+ * @fileoverview Prefer boolean length check
+ *
+ * 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";
+
+function funcForBooleanLength(context, node, conditionCheck) {
+ let newText = "";
+ const sourceCode = context.getSourceCode();
+ switch (node.operator) {
+ case ">":
+ if (node.right.value == 0) {
+ if (conditionCheck) {
+ newText = sourceCode.getText(node.left);
+ } else {
+ newText = "!!" + sourceCode.getText(node.left);
+ }
+ } else {
+ newText = "!" + sourceCode.getText(node.right);
+ }
+ break;
+ case "<":
+ if (node.right.value == 0) {
+ newText = "!" + sourceCode.getText(node.left);
+ } else if (conditionCheck) {
+ newText = sourceCode.getText(node.right);
+ } else {
+ newText = "!!" + sourceCode.getText(node.right);
+ }
+ break;
+ case "==":
+ if (node.right.value == 0) {
+ newText = "!" + sourceCode.getText(node.left);
+ } else {
+ newText = "!" + sourceCode.getText(node.right);
+ }
+ break;
+ case "!=":
+ if (node.right.value == 0) {
+ if (conditionCheck) {
+ newText = sourceCode.getText(node.left);
+ } else {
+ newText = "!!" + sourceCode.getText(node.left);
+ }
+ } else if (conditionCheck) {
+ newText = sourceCode.getText(node.right);
+ } else {
+ newText = "!!" + sourceCode.getText(node.right);
+ }
+ break;
+ }
+ return newText;
+}
+
+module.exports = {
+ meta: {
+ docs: {
+ url: "https://firefox-source-docs.mozilla.org/code-quality/lint/linters/eslint-plugin-mozilla/rules/prefer-boolean-length-check.html",
+ },
+ fixable: "code",
+ messages: {
+ preferBooleanCheck: "Prefer boolean length check",
+ },
+ schema: [],
+ type: "suggestion",
+ },
+
+ create(context) {
+ const conditionStatement = [
+ "IfStatement",
+ "WhileStatement",
+ "DoWhileStatement",
+ "ForStatement",
+ "ForInStatement",
+ "ConditionalExpression",
+ ];
+
+ return {
+ BinaryExpression(node) {
+ if (
+ ["==", "!=", ">", "<"].includes(node.operator) &&
+ ((node.right.type == "Literal" &&
+ node.right.value == 0 &&
+ node.left.property?.name == "length") ||
+ (node.left.type == "Literal" &&
+ node.left.value == 0 &&
+ node.right.property?.name == "length"))
+ ) {
+ if (
+ conditionStatement.includes(node.parent.type) ||
+ (node.parent.type == "LogicalExpression" &&
+ conditionStatement.includes(node.parent.parent.type))
+ ) {
+ context.report({
+ node,
+ fix: fixer => {
+ let generateExpression = funcForBooleanLength(
+ context,
+ node,
+ true
+ );
+
+ return fixer.replaceText(node, generateExpression);
+ },
+ messageId: "preferBooleanCheck",
+ });
+ } else {
+ context.report({
+ node,
+ fix: fixer => {
+ let generateExpression = funcForBooleanLength(
+ context,
+ node,
+ false
+ );
+ return fixer.replaceText(node, generateExpression);
+ },
+ messageId: "preferBooleanCheck",
+ });
+ }
+ }
+ },
+ };
+ },
+};
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/prefer-formatValues.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/prefer-formatValues.js
new file mode 100644
index 0000000000..4807cf1f1f
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/prefer-formatValues.js
@@ -0,0 +1,97 @@
+/**
+ * @fileoverview Reject multiple calls to document.l10n.formatValue in the same
+ * code block.
+ *
+ * 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";
+
+function isIdentifier(node, id) {
+ return node && node.type === "Identifier" && node.name === id;
+}
+
+/**
+ * As we enter blocks new sets are pushed onto this stack and then popped when
+ * we exit the block.
+ */
+const BlockStack = [];
+
+module.exports = {
+ meta: {
+ docs: {
+ description: "disallow multiple document.l10n.formatValue calls",
+ url: "https://firefox-source-docs.mozilla.org/code-quality/lint/linters/eslint-plugin-mozilla/rules/prefer-formatValues.html",
+ },
+ messages: {
+ outsideCallBlock: "call expression found outside of known block",
+ useSingleCall:
+ "prefer to use a single document.l10n.formatValues call instead " +
+ "of multiple calls to document.l10n.formatValue or document.l10n.formatValues",
+ },
+ schema: [],
+ type: "problem",
+ },
+
+ create(context) {
+ function enterBlock() {
+ BlockStack.push(new Set());
+ }
+
+ function exitBlock() {
+ let calls = BlockStack.pop();
+ if (calls.size > 1) {
+ for (let callNode of calls) {
+ context.report({
+ node: callNode,
+ messageId: "useSingleCall",
+ });
+ }
+ }
+ }
+
+ return {
+ Program: enterBlock,
+ "Program:exit": exitBlock,
+ BlockStatement: enterBlock,
+ "BlockStatement:exit": exitBlock,
+
+ CallExpression(node) {
+ if (!BlockStack.length) {
+ context.report({
+ node,
+ messageId: "outsideCallBlock",
+ });
+ }
+
+ let callee = node.callee;
+ if (callee.type !== "MemberExpression") {
+ return;
+ }
+
+ if (
+ !isIdentifier(callee.property, "formatValue") &&
+ !isIdentifier(callee.property, "formatValues")
+ ) {
+ return;
+ }
+
+ if (callee.object.type !== "MemberExpression") {
+ return;
+ }
+
+ if (
+ !isIdentifier(callee.object.object, "document") ||
+ !isIdentifier(callee.object.property, "l10n")
+ ) {
+ return;
+ }
+
+ let calls = BlockStack[BlockStack.length - 1];
+ calls.add(node);
+ },
+ };
+ },
+};
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/reject-addtask-only.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/reject-addtask-only.js
new file mode 100644
index 0000000000..b1a67cad7d
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/reject-addtask-only.js
@@ -0,0 +1,53 @@
+/**
+ * @fileoverview Don't allow only() in tests
+ *
+ * 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 = {
+ meta: {
+ docs: {
+ url: "https://firefox-source-docs.mozilla.org/code-quality/lint/linters/eslint-plugin-mozilla/rules/reject-addtask-only.html",
+ },
+ hasSuggestions: true,
+ messages: {
+ addTaskNotAllowed:
+ "add_task(...).only() not allowed - add an exception if this is intentional",
+ addTaskNotAllowedSuggestion: "Remove only() call from task",
+ },
+ schema: [],
+ type: "suggestion",
+ },
+
+ create(context) {
+ return {
+ CallExpression(node) {
+ if (
+ ["add_task", "decorate_task"].includes(
+ node.callee.object?.callee?.name
+ ) &&
+ node.callee.property?.name == "only"
+ ) {
+ context.report({
+ node,
+ messageId: "addTaskNotAllowed",
+ suggest: [
+ {
+ messageId: "addTaskNotAllowedSuggestion",
+ fix: fixer =>
+ fixer.replaceTextRange(
+ [node.callee.object.range[1], node.range[1]],
+ ""
+ ),
+ },
+ ],
+ });
+ }
+ },
+ };
+ },
+};
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/reject-chromeutils-import-params.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/reject-chromeutils-import-params.js
new file mode 100644
index 0000000000..ccfb0a1cb0
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/reject-chromeutils-import-params.js
@@ -0,0 +1,66 @@
+/**
+ * @fileoverview Reject calls to ChromeUtils.import(..., null). This allows to
+ * retrieve the global object for the JSM, instead we should rely on explicitly
+ * exported symbols.
+ *
+ * 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";
+
+function isIdentifier(node, id) {
+ return node && node.type === "Identifier" && node.name === id;
+}
+
+function getRangeAfterArgToEnd(context, argNumber, args) {
+ let sourceCode = context.getSourceCode();
+ return [
+ sourceCode.getTokenAfter(args[argNumber]).range[0],
+ args[args.length - 1].range[1],
+ ];
+}
+
+module.exports = {
+ meta: {
+ docs: {
+ url: "https://firefox-source-docs.mozilla.org/code-quality/lint/linters/eslint-plugin-mozilla/rules/reject-chromeutils-import-params.html",
+ },
+ hasSuggestions: true,
+ messages: {
+ importOnlyOneArg: "ChromeUtils.import only takes one argument.",
+ importOnlyOneArgSuggestion: "Remove the unnecessary parameters.",
+ },
+ schema: [],
+ type: "problem",
+ },
+
+ create(context) {
+ return {
+ CallExpression(node) {
+ let { callee } = node;
+ if (
+ isIdentifier(callee.object, "ChromeUtils") &&
+ isIdentifier(callee.property, "import") &&
+ node.arguments.length >= 2
+ ) {
+ context.report({
+ node,
+ messageId: "importOnlyOneArg",
+ suggest: [
+ {
+ messageId: "importOnlyOneArgSuggestion",
+ fix: fixer => {
+ return fixer.removeRange(
+ getRangeAfterArgToEnd(context, 0, node.arguments)
+ );
+ },
+ },
+ ],
+ });
+ }
+ },
+ };
+ },
+};
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/reject-chromeutils-import.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/reject-chromeutils-import.js
new file mode 100644
index 0000000000..1f746db730
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/reject-chromeutils-import.js
@@ -0,0 +1,80 @@
+/**
+ * @fileoverview Reject use of Cu.import and ChromeUtils.import
+ * in favor of ChromeUtils.importESModule.
+ *
+ * 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";
+
+function isIdentifier(node, id) {
+ return node && node.type === "Identifier" && node.name === id;
+}
+
+function isMemberExpression(node, object, member) {
+ return (
+ node.type === "MemberExpression" &&
+ isIdentifier(node.object, object) &&
+ isIdentifier(node.property, member)
+ );
+}
+
+module.exports = {
+ meta: {
+ docs: {
+ url: "https://firefox-source-docs.mozilla.org/code-quality/lint/linters/eslint-plugin-mozilla/rules/reject-chromeutils-import.html",
+ },
+ messages: {
+ useImportESModule:
+ "Please use ChromeUtils.importESModule instead of " +
+ "ChromeUtils.import unless the module is not yet ESMified",
+ useImportESModuleLazy:
+ "Please use ChromeUtils.defineESModuleGetters instead of " +
+ "ChromeUtils.defineModuleGetter " +
+ "unless the module is not yet ESMified",
+ },
+ schema: [],
+ type: "problem",
+ },
+
+ create(context) {
+ return {
+ CallExpression(node) {
+ if (node.callee.type !== "MemberExpression") {
+ return;
+ }
+
+ let { callee } = node;
+
+ if (
+ (isIdentifier(callee.object, "ChromeUtils") ||
+ isMemberExpression(
+ callee.object,
+ "SpecialPowers",
+ "ChromeUtils"
+ )) &&
+ isIdentifier(callee.property, "import")
+ ) {
+ context.report({
+ node,
+ messageId: "useImportESModule",
+ });
+ }
+
+ if (
+ (isMemberExpression(callee.object, "SpecialPowers", "ChromeUtils") &&
+ isIdentifier(callee.property, "defineModuleGetter")) ||
+ isMemberExpression(callee, "ChromeUtils", "defineModuleGetter") ||
+ isMemberExpression(callee, "XPCOMUtils", "defineLazyModuleGetters")
+ ) {
+ context.report({
+ node,
+ messageId: "useImportESModuleLazy",
+ });
+ }
+ },
+ };
+ },
+};
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/reject-eager-module-in-lazy-getter.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/reject-eager-module-in-lazy-getter.js
new file mode 100644
index 0000000000..133dd6d71f
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/reject-eager-module-in-lazy-getter.js
@@ -0,0 +1,99 @@
+/**
+ * @fileoverview Reject use of lazy getters for modules that's loaded early in
+ * the startup process and not necessarily be lazy.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+"use strict";
+const helpers = require("../helpers");
+
+function isString(node) {
+ return node.type === "Literal" && typeof node.value === "string";
+}
+
+function isEagerModule(resourceURI) {
+ return [
+ "resource://gre/modules/XPCOMUtils",
+ "resource://gre/modules/AppConstants",
+ ].includes(resourceURI.replace(/(\.jsm|\.jsm\.js|\.js|\.sys\.mjs)$/, ""));
+}
+
+function checkEagerModule(context, node, resourceURI) {
+ if (!isEagerModule(resourceURI)) {
+ return;
+ }
+ context.report({
+ node,
+ messageId: "eagerModule",
+ data: { uri: resourceURI },
+ });
+}
+
+module.exports = {
+ meta: {
+ docs: {
+ url: "https://firefox-source-docs.mozilla.org/code-quality/lint/linters/eslint-plugin-mozilla/rules/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/reject-eager-module-in-lazy-getter.html",
+ },
+ messages: {
+ eagerModule:
+ 'Module "{{uri}}" is known to be loaded early in the startup process, and should be loaded eagerly, instead of defining a lazy getter.',
+ },
+ schema: [],
+ type: "problem",
+ },
+
+ create(context) {
+ return {
+ CallExpression(node) {
+ if (node.callee.type !== "MemberExpression") {
+ return;
+ }
+
+ let callerSource;
+ try {
+ callerSource = helpers.getASTSource(node.callee);
+ } catch (e) {
+ return;
+ }
+
+ if (callerSource === "ChromeUtils.defineModuleGetter") {
+ if (node.arguments.length < 3) {
+ return;
+ }
+ const resourceURINode = node.arguments[2];
+ if (!isString(resourceURINode)) {
+ return;
+ }
+ checkEagerModule(context, node, resourceURINode.value);
+ } else if (
+ callerSource === "XPCOMUtils.defineLazyModuleGetters" ||
+ callerSource === "ChromeUtils.defineESModuleGetters"
+ ) {
+ if (node.arguments.length < 2) {
+ return;
+ }
+ const obj = node.arguments[1];
+ if (obj.type !== "ObjectExpression") {
+ return;
+ }
+ for (let prop of obj.properties) {
+ if (prop.type !== "Property") {
+ continue;
+ }
+ if (prop.kind !== "init") {
+ continue;
+ }
+ const resourceURINode = prop.value;
+ if (!isString(resourceURINode)) {
+ continue;
+ }
+ checkEagerModule(context, node, resourceURINode.value);
+ }
+ }
+ },
+ };
+ },
+};
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/reject-global-this.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/reject-global-this.js
new file mode 100644
index 0000000000..ec4b5fd43d
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/reject-global-this.js
@@ -0,0 +1,43 @@
+/**
+ * @fileoverview Reject attempts to use the global object in jsms.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+"use strict";
+
+const helpers = require("../helpers");
+
+// -----------------------------------------------------------------------------
+// Rule Definition
+// -----------------------------------------------------------------------------
+
+module.exports = {
+ meta: {
+ docs: {
+ url: "https://firefox-source-docs.mozilla.org/code-quality/lint/linters/eslint-plugin-mozilla/rules/reject-global-this.html",
+ },
+ messages: {
+ avoidGlobalThis: "JSM should not use the global this",
+ },
+ schema: [],
+ type: "problem",
+ },
+
+ create(context) {
+ return {
+ ThisExpression(node) {
+ if (!helpers.getIsGlobalThis(context.getAncestors())) {
+ return;
+ }
+
+ context.report({
+ node,
+ messageId: "avoidGlobalThis",
+ });
+ },
+ };
+ },
+};
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/reject-globalThis-modification.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/reject-globalThis-modification.js
new file mode 100644
index 0000000000..13052db80c
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/reject-globalThis-modification.js
@@ -0,0 +1,74 @@
+/**
+ * @fileoverview Enforce the standard object name for
+ * ChromeUtils.defineESMGetters
+ *
+ * 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";
+
+function isIdentifier(node, id) {
+ return node.type === "Identifier" && node.name === id;
+}
+
+function calleeToString(node) {
+ if (node.type === "Identifier") {
+ return node.name;
+ }
+
+ if (node.type === "MemberExpression" && !node.computed) {
+ return calleeToString(node.object) + "." + node.property.name;
+ }
+
+ return "???";
+}
+
+module.exports = {
+ meta: {
+ docs: {
+ url: "https://firefox-source-docs.mozilla.org/code-quality/lint/linters/eslint-plugin-mozilla/rules/reject-globalThis-modification.html",
+ },
+ messages: {
+ rejectModifyGlobalThis:
+ "`globalThis` shouldn't be modified. `globalThis` is the shared global inside the system module, and properties defined on it is visible from all modules.",
+ rejectPassingGlobalThis:
+ "`globalThis` shouldn't be passed to function that can modify it. `globalThis` is the shared global inside the system module, and properties defined on it is visible from all modules.",
+ },
+ schema: [],
+ type: "problem",
+ },
+
+ create(context) {
+ return {
+ AssignmentExpression(node, parents) {
+ let target = node.left;
+ while (target.type === "MemberExpression") {
+ target = target.object;
+ }
+ if (isIdentifier(target, "globalThis")) {
+ context.report({
+ node,
+ messageId: "rejectModifyGlobalThis",
+ });
+ }
+ },
+ CallExpression(node) {
+ const calleeStr = calleeToString(node.callee);
+ if (calleeStr.endsWith(".deserialize")) {
+ return;
+ }
+
+ for (const arg of node.arguments) {
+ if (isIdentifier(arg, "globalThis")) {
+ context.report({
+ node,
+ messageId: "rejectPassingGlobalThis",
+ });
+ }
+ }
+ },
+ };
+ },
+};
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/reject-import-system-module-from-non-system.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/reject-import-system-module-from-non-system.js
new file mode 100644
index 0000000000..2cbc4e7652
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/reject-import-system-module-from-non-system.js
@@ -0,0 +1,36 @@
+/**
+ * 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 = {
+ meta: {
+ docs: {
+ url: "https://firefox-source-docs.mozilla.org/code-quality/lint/linters/eslint-plugin-mozilla/rules/reject-import-system-module-from-non-system.html",
+ },
+ messages: {
+ rejectStaticImportSystemModuleFromNonSystem:
+ "System modules (*.sys.mjs) can be imported with static import declaration only from system modules.",
+ },
+ schema: [],
+ type: "problem",
+ },
+
+ create(context) {
+ return {
+ ImportDeclaration(node) {
+ if (!node.source.value.endsWith(".sys.mjs")) {
+ return;
+ }
+
+ context.report({
+ node,
+ messageId: "rejectStaticImportSystemModuleFromNonSystem",
+ });
+ },
+ };
+ },
+};
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/reject-importGlobalProperties.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/reject-importGlobalProperties.js
new file mode 100644
index 0000000000..b2f0aad1ae
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/reject-importGlobalProperties.js
@@ -0,0 +1,97 @@
+/**
+ * @fileoverview Reject use of Cu.importGlobalProperties
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+"use strict";
+
+const path = require("path");
+
+const privilegedGlobals = Object.keys(
+ require("../environments/privileged.js").globals
+);
+
+function getMessageId(context) {
+ return path.extname(context.getFilename()) == ".sjs"
+ ? "unexpectedCallSjs"
+ : "unexpectedCall";
+}
+
+module.exports = {
+ meta: {
+ docs: {
+ url: "https://firefox-source-docs.mozilla.org/code-quality/lint/linters/eslint-plugin-mozilla/rules/reject-importGlobalProperties.html",
+ },
+ messages: {
+ unexpectedCall: "Unexpected call to Cu.importGlobalProperties",
+ unexpectedCallCuWebIdl:
+ "Unnecessary call to Cu.importGlobalProperties for {{name}} (webidl names are automatically imported)",
+ unexpectedCallSjs:
+ "Do not call Cu.importGlobalProperties in sjs files, expand the global instead (see rule docs).",
+ unexpectedCallXPCOMWebIdl:
+ "Unnecessary call to XPCOMUtils.defineLazyGlobalGetters for {{name}} (webidl names are automatically imported)",
+ },
+ schema: [
+ {
+ enum: ["everything", "allownonwebidl"],
+ },
+ ],
+ type: "problem",
+ },
+
+ create(context) {
+ return {
+ CallExpression(node) {
+ if (node.callee.type !== "MemberExpression") {
+ return;
+ }
+ let memexp = node.callee;
+ if (
+ memexp.object.type === "Identifier" &&
+ // Only Cu, not Components.utils as `use-cc-etc` handles this for us.
+ memexp.object.name === "Cu" &&
+ memexp.property.type === "Identifier" &&
+ memexp.property.name === "importGlobalProperties"
+ ) {
+ if (context.options.includes("allownonwebidl")) {
+ for (let element of node.arguments[0].elements) {
+ if (privilegedGlobals.includes(element.value)) {
+ context.report({
+ node,
+ messageId: "unexpectedCallCuWebIdl",
+ data: { name: element.value },
+ });
+ }
+ }
+ } else {
+ context.report({ node, messageId: getMessageId(context) });
+ }
+ }
+ if (
+ memexp.object.type === "Identifier" &&
+ memexp.object.name === "XPCOMUtils" &&
+ memexp.property.type === "Identifier" &&
+ memexp.property.name === "defineLazyGlobalGetters" &&
+ node.arguments.length >= 2
+ ) {
+ if (context.options.includes("allownonwebidl")) {
+ for (let element of node.arguments[1].elements) {
+ if (privilegedGlobals.includes(element.value)) {
+ context.report({
+ node,
+ messageId: "unexpectedCallXPCOMWebIdl",
+ data: { name: element.value },
+ });
+ }
+ }
+ } else {
+ context.report({ node, messageId: getMessageId(context) });
+ }
+ }
+ },
+ };
+ },
+};
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/reject-lazy-imports-into-globals.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/reject-lazy-imports-into-globals.js
new file mode 100644
index 0000000000..492a1e3bd7
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/reject-lazy-imports-into-globals.js
@@ -0,0 +1,72 @@
+/**
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+"use strict";
+
+const helpers = require("../helpers");
+
+const callExpressionDefinitions = [
+ /^loader\.lazyGetter\((?:globalThis|window), "(\w+)"/,
+ /^loader\.lazyServiceGetter\((?:globalThis|window), "(\w+)"/,
+ /^loader\.lazyRequireGetter\((?:globalThis|window), "(\w+)"/,
+ /^ChromeUtils\.defineLazyGetter\((?:globalThis|window), "(\w+)"/,
+ /^ChromeUtils\.defineModuleGetter\((?:globalThis|window), "(\w+)"/,
+ /^XPCOMUtils\.defineLazyPreferenceGetter\((?:globalThis|window), "(\w+)"/,
+ /^XPCOMUtils\.defineLazyScriptGetter\((?:globalThis|window), "(\w+)"/,
+ /^XPCOMUtils\.defineLazyServiceGetter\((?:globalThis|window), "(\w+)"/,
+ /^XPCOMUtils\.defineConstant\((?:globalThis|window), "(\w+)"/,
+ /^DevToolsUtils\.defineLazyGetter\((?:globalThis|window), "(\w+)"/,
+ /^Object\.defineProperty\((?:globalThis|window), "(\w+)"/,
+ /^Reflect\.defineProperty\((?:globalThis|window), "(\w+)"/,
+ /^this\.__defineGetter__\("(\w+)"/,
+];
+
+const callExpressionMultiDefinitions = [
+ "XPCOMUtils.defineLazyGlobalGetters(window,",
+ "XPCOMUtils.defineLazyGlobalGetters(globalThis,",
+ "XPCOMUtils.defineLazyModuleGetters(window,",
+ "XPCOMUtils.defineLazyModuleGetters(globalThis,",
+ "XPCOMUtils.defineLazyServiceGetters(window,",
+ "XPCOMUtils.defineLazyServiceGetters(globalThis,",
+ "ChromeUtils.defineESModuleGetters(window,",
+ "ChromeUtils.defineESModuleGetters(globalThis,",
+ "loader.lazyRequireGetter(window,",
+ "loader.lazyRequireGetter(globalThis,",
+];
+
+module.exports = {
+ meta: {
+ docs: {
+ url: "https://firefox-source-docs.mozilla.org/code-quality/lint/linters/eslint-plugin-mozilla/rules/reject-lazy-imports-into-globals.html",
+ },
+ messages: {
+ rejectLazyImportsIntoGlobals:
+ "Non-system modules should not import into globalThis nor window. Prefer a lazy object holder",
+ },
+ schema: [],
+ type: "suggestion",
+ },
+
+ create(context) {
+ return {
+ CallExpression(node) {
+ let source;
+ try {
+ source = helpers.getASTSource(node);
+ } catch (e) {
+ return;
+ }
+
+ if (
+ callExpressionDefinitions.some(expr => source.match(expr)) ||
+ callExpressionMultiDefinitions.some(expr => source.startsWith(expr))
+ ) {
+ context.report({ node, messageId: "rejectLazyImportsIntoGlobals" });
+ }
+ },
+ };
+ },
+};
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/reject-mixing-eager-and-lazy.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/reject-mixing-eager-and-lazy.js
new file mode 100644
index 0000000000..5779a90afd
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/reject-mixing-eager-and-lazy.js
@@ -0,0 +1,150 @@
+/**
+ * @fileoverview Reject use of lazy getters for modules that's loaded early in
+ * the startup process and not necessarily be lazy.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+"use strict";
+const helpers = require("../helpers");
+
+function isIdentifier(node, id) {
+ return node.type === "Identifier" && node.name === id;
+}
+
+function isString(node) {
+ return node.type === "Literal" && typeof node.value === "string";
+}
+
+function checkMixed(loadedModules, context, node, type, resourceURI) {
+ if (!loadedModules.has(resourceURI)) {
+ loadedModules.set(resourceURI, type);
+ }
+
+ if (loadedModules.get(resourceURI) === type) {
+ return;
+ }
+
+ context.report({
+ node,
+ messageId: "mixedEagerAndLazy",
+ data: { uri: resourceURI },
+ });
+}
+
+module.exports = {
+ meta: {
+ docs: {
+ url: "https://firefox-source-docs.mozilla.org/code-quality/lint/linters/eslint-plugin-mozilla/rules/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/reject-mixed-eager-and-lazy.html",
+ },
+ messages: {
+ mixedEagerAndLazy:
+ 'Module "{{uri}}" is loaded eagerly, and should not be used for lazy getter.',
+ },
+ schema: [],
+ type: "problem",
+ },
+
+ create(context) {
+ const loadedModules = new Map();
+
+ return {
+ ImportDeclaration(node) {
+ const resourceURI = node.source.value;
+ checkMixed(loadedModules, context, node, "eager", resourceURI);
+ },
+ CallExpression(node) {
+ if (node.callee.type !== "MemberExpression") {
+ return;
+ }
+
+ let callerSource;
+ try {
+ callerSource = helpers.getASTSource(node.callee);
+ } catch (e) {
+ return;
+ }
+
+ if (
+ (callerSource === "ChromeUtils.import" ||
+ callerSource === "ChromeUtils.importESModule") &&
+ helpers.getIsTopLevelAndUnconditionallyExecuted(
+ context.getAncestors()
+ )
+ ) {
+ if (node.arguments.length < 1) {
+ return;
+ }
+ const resourceURINode = node.arguments[0];
+ if (!isString(resourceURINode)) {
+ return;
+ }
+ checkMixed(
+ loadedModules,
+ context,
+ node,
+ "eager",
+ resourceURINode.value
+ );
+ }
+
+ if (callerSource === "ChromeUtils.defineModuleGetter") {
+ if (node.arguments.length < 3) {
+ return;
+ }
+ if (!isIdentifier(node.arguments[0], "lazy")) {
+ return;
+ }
+
+ const resourceURINode = node.arguments[2];
+ if (!isString(resourceURINode)) {
+ return;
+ }
+ checkMixed(
+ loadedModules,
+ context,
+ node,
+ "lazy",
+ resourceURINode.value
+ );
+ } else if (
+ callerSource === "XPCOMUtils.defineLazyModuleGetters" ||
+ callerSource === "ChromeUtils.defineESModuleGetters"
+ ) {
+ if (node.arguments.length < 2) {
+ return;
+ }
+ if (!isIdentifier(node.arguments[0], "lazy")) {
+ return;
+ }
+
+ const obj = node.arguments[1];
+ if (obj.type !== "ObjectExpression") {
+ return;
+ }
+ for (let prop of obj.properties) {
+ if (prop.type !== "Property") {
+ continue;
+ }
+ if (prop.kind !== "init") {
+ continue;
+ }
+ const resourceURINode = prop.value;
+ if (!isString(resourceURINode)) {
+ continue;
+ }
+ checkMixed(
+ loadedModules,
+ context,
+ node,
+ "lazy",
+ resourceURINode.value
+ );
+ }
+ }
+ },
+ };
+ },
+};
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/reject-multiple-getters-calls.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/reject-multiple-getters-calls.js
new file mode 100644
index 0000000000..e6e37ad035
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/reject-multiple-getters-calls.js
@@ -0,0 +1,81 @@
+/**
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+"use strict";
+
+const helpers = require("../helpers");
+
+function findStatement(node) {
+ while (node && node.type !== "ExpressionStatement") {
+ node = node.parent;
+ }
+
+ return node;
+}
+
+function isIdentifier(node, id) {
+ return node && node.type === "Identifier" && node.name === id;
+}
+
+module.exports = {
+ meta: {
+ docs: {
+ url: "https://firefox-source-docs.mozilla.org/code-quality/lint/linters/eslint-plugin-mozilla/rules/reject-multiple-getters-calls.html",
+ },
+ messages: {
+ rejectMultipleCalls:
+ "ChromeUtils.defineESModuleGetters is already called for {{target}} in the same context. Please merge those calls",
+ },
+ schema: [],
+ type: "suggestion",
+ },
+
+ create(context) {
+ const parentToTargets = new Map();
+
+ return {
+ CallExpression(node) {
+ let callee = node.callee;
+ if (
+ callee.type === "MemberExpression" &&
+ isIdentifier(callee.object, "ChromeUtils") &&
+ isIdentifier(callee.property, "defineESModuleGetters")
+ ) {
+ const stmt = findStatement(node);
+ if (!stmt) {
+ return;
+ }
+
+ let target;
+ try {
+ target = helpers.getASTSource(node.arguments[0]);
+ } catch (e) {
+ return;
+ }
+
+ const parent = stmt.parent;
+ let targets;
+ if (parentToTargets.has(parent)) {
+ targets = parentToTargets.get(parent);
+ } else {
+ targets = new Set();
+ parentToTargets.set(parent, targets);
+ }
+
+ if (targets.has(target)) {
+ context.report({
+ node,
+ messageId: "rejectMultipleCalls",
+ data: { target },
+ });
+ }
+
+ targets.add(target);
+ }
+ },
+ };
+ },
+};
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/reject-relative-requires.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/reject-relative-requires.js
new file mode 100644
index 0000000000..34e4b6bd5e
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/reject-relative-requires.js
@@ -0,0 +1,42 @@
+/**
+ * @fileoverview Reject some uses of require.
+ *
+ * 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";
+
+var helpers = require("../helpers");
+
+const isRelativePath = function (path) {
+ return path.startsWith("./") || path.startsWith("../");
+};
+
+module.exports = {
+ meta: {
+ docs: {
+ url: "https://firefox-source-docs.mozilla.org/code-quality/lint/linters/eslint-plugin-mozilla/rules/reject-relative-requires.html",
+ },
+ messages: {
+ rejectRelativeRequires: "relative paths are not allowed with require()",
+ },
+ schema: [],
+ type: "problem",
+ },
+
+ create(context) {
+ return {
+ CallExpression(node) {
+ const path = helpers.getDevToolsRequirePath(node);
+ if (path && isRelativePath(path)) {
+ context.report({
+ node,
+ messageId: "rejectRelativeRequires",
+ });
+ }
+ },
+ };
+ },
+};
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/reject-scriptableunicodeconverter.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/reject-scriptableunicodeconverter.js
new file mode 100644
index 0000000000..e29a60089c
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/reject-scriptableunicodeconverter.js
@@ -0,0 +1,44 @@
+/**
+ * @fileoverview Reject calls into Ci.nsIScriptableUnicodeConverter. We're phasing this out in
+ * favour of TextEncoder or TextDecoder.
+ *
+ * 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";
+
+function isIdentifier(node, id) {
+ return node && node.type === "Identifier" && node.name === id;
+}
+
+module.exports = {
+ meta: {
+ docs: {
+ url: "https://firefox-source-docs.mozilla.org/code-quality/lint/linters/eslint-plugin-mozilla/rules/reject-scriptableunicodeconverter.html",
+ },
+ messages: {
+ rejectScriptableUnicodeConverter:
+ "Ci.nsIScriptableUnicodeConverter is deprecated. You should use TextEncoder or TextDecoder instead.",
+ },
+ schema: [],
+ type: "problem",
+ },
+
+ create(context) {
+ return {
+ MemberExpression(node) {
+ if (
+ isIdentifier(node.object, "Ci") &&
+ isIdentifier(node.property, "nsIScriptableUnicodeConverter")
+ ) {
+ context.report({
+ node,
+ messageId: "rejectScriptableUnicodeConverter",
+ });
+ }
+ },
+ };
+ },
+};
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/reject-some-requires.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/reject-some-requires.js
new file mode 100644
index 0000000000..5a4c6b4df7
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/reject-some-requires.js
@@ -0,0 +1,44 @@
+/**
+ * @fileoverview Reject some uses of require.
+ *
+ * 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";
+
+var helpers = require("../helpers");
+
+module.exports = {
+ meta: {
+ docs: {
+ url: "https://firefox-source-docs.mozilla.org/code-quality/lint/linters/eslint-plugin-mozilla/rules/reject-some-requires.html",
+ },
+ messages: {
+ rejectRequire: `require({{path}}) is not allowed`,
+ },
+ schema: [
+ {
+ type: "string",
+ },
+ ],
+ type: "problem",
+ },
+
+ create(context) {
+ if (typeof context.options[0] !== "string") {
+ throw new Error("reject-some-requires expects a regexp");
+ }
+ const RX = new RegExp(context.options[0]);
+
+ return {
+ CallExpression(node) {
+ const path = helpers.getDevToolsRequirePath(node);
+ if (path && RX.test(path)) {
+ context.report({ node, messageId: "rejectRequire", data: { path } });
+ }
+ },
+ };
+ },
+};
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/reject-top-level-await.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/reject-top-level-await.js
new file mode 100644
index 0000000000..dff7db0f9a
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/reject-top-level-await.js
@@ -0,0 +1,45 @@
+/**
+ * @fileoverview Don't allow only() in tests
+ *
+ * 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";
+
+var helpers = require("../helpers");
+
+module.exports = {
+ meta: {
+ docs: {
+ url: "https://firefox-source-docs.mozilla.org/code-quality/lint/linters/eslint-plugin-mozilla/rules/reject-top-level-await.html",
+ },
+ messages: {
+ rejectTopLevelAwait:
+ "Top-level await is not currently supported in component files.",
+ },
+ schema: [],
+ type: "problem",
+ },
+
+ create(context) {
+ return {
+ AwaitExpression(node) {
+ if (!helpers.getIsTopLevelScript(context.getAncestors())) {
+ return;
+ }
+ context.report({ node, messageId: "rejectTopLevelAwait" });
+ },
+ ForOfStatement(node) {
+ if (
+ !node.await ||
+ !helpers.getIsTopLevelScript(context.getAncestors())
+ ) {
+ return;
+ }
+ context.report({ node, messageId: "rejectTopLevelAwait" });
+ },
+ };
+ },
+};
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/rejects-requires-await.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/rejects-requires-await.js
new file mode 100644
index 0000000000..a7e7d9d7e2
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/rejects-requires-await.js
@@ -0,0 +1,47 @@
+/**
+ * @fileoverview Ensure Assert.rejects is preceded by await.
+ *
+ * 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 = {
+ meta: {
+ docs: {
+ url: "https://firefox-source-docs.mozilla.org/code-quality/lint/linters/eslint-plugin-mozilla/rules/reject-requires-await.html",
+ },
+ messages: {
+ rejectRequiresAwait: "Assert.rejects needs to be preceded by await.",
+ },
+ schema: [],
+ type: "problem",
+ },
+
+ create(context) {
+ return {
+ CallExpression(node) {
+ if (node.callee.type === "MemberExpression") {
+ let memexp = node.callee;
+ if (
+ memexp.object.type === "Identifier" &&
+ memexp.object.name === "Assert" &&
+ memexp.property.type === "Identifier" &&
+ memexp.property.name === "rejects"
+ ) {
+ // We have ourselves an Assert.rejects.
+
+ if (node.parent.type !== "AwaitExpression") {
+ context.report({
+ node,
+ messageId: "rejectRequiresAwait",
+ });
+ }
+ }
+ }
+ },
+ };
+ },
+};
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/use-cc-etc.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/use-cc-etc.js
new file mode 100644
index 0000000000..f47f03f0d2
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/use-cc-etc.js
@@ -0,0 +1,57 @@
+/**
+ * @fileoverview Reject use of Components.classes etc, prefer the shorthand instead.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+"use strict";
+
+const componentsMap = {
+ classes: "Cc",
+ interfaces: "Ci",
+ results: "Cr",
+ utils: "Cu",
+};
+
+module.exports = {
+ meta: {
+ docs: {
+ url: "https://firefox-source-docs.mozilla.org/code-quality/lint/linters/eslint-plugin-mozilla/rules/use-cc-etc.html",
+ },
+ fixable: "code",
+ messages: {
+ useCcEtc: "Use {{ shortName }} rather than Components.{{ oldName }}",
+ },
+ schema: [],
+ type: "suggestion",
+ },
+
+ create(context) {
+ return {
+ MemberExpression(node) {
+ if (
+ node.object.type === "Identifier" &&
+ node.object.name === "Components" &&
+ node.property.type === "Identifier" &&
+ Object.getOwnPropertyNames(componentsMap).includes(node.property.name)
+ ) {
+ context.report({
+ node,
+ messageId: "useCcEtc",
+ data: {
+ shortName: componentsMap[node.property.name],
+ oldName: node.property.name,
+ },
+ fix: fixer =>
+ fixer.replaceTextRange(
+ [node.range[0], node.range[1]],
+ componentsMap[node.property.name]
+ ),
+ });
+ }
+ },
+ };
+ },
+};
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/use-chromeutils-definelazygetter.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/use-chromeutils-definelazygetter.js
new file mode 100644
index 0000000000..a9f43a945a
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/use-chromeutils-definelazygetter.js
@@ -0,0 +1,58 @@
+/**
+ * @fileoverview Reject use of XPCOMUtils.defineLazyGetter in favor of ChromeUtils.defineLazyGetter.
+ *
+ * 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";
+
+function isIdentifier(node, id) {
+ return node && node.type === "Identifier" && node.name === id;
+}
+
+function isMemberExpression(node, object, member) {
+ return (
+ node.type === "MemberExpression" &&
+ isIdentifier(node.object, object) &&
+ isIdentifier(node.property, member)
+ );
+}
+
+module.exports = {
+ meta: {
+ docs: {
+ url: "https://firefox-source-docs.mozilla.org/code-quality/lint/linters/eslint-plugin-mozilla/rules/use-chromeutils-definelazygetter.html",
+ },
+ fixable: "code",
+ messages: {
+ useChromeUtilsDefineLazyGetter:
+ "Please use ChromeUtils.defineLazyGetter instead of XPCOMUtils.defineLazyGetter",
+ },
+ schema: [],
+ type: "problem",
+ },
+
+ create(context) {
+ return {
+ CallExpression(node) {
+ if (node.callee.type !== "MemberExpression") {
+ return;
+ }
+
+ let { callee } = node;
+
+ if (isMemberExpression(callee, "XPCOMUtils", "defineLazyGetter")) {
+ context.report({
+ node,
+ messageId: "useChromeUtilsDefineLazyGetter",
+ fix(fixer) {
+ return fixer.replaceText(callee, "ChromeUtils.defineLazyGetter");
+ },
+ });
+ }
+ },
+ };
+ },
+};
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/use-chromeutils-generateqi.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/use-chromeutils-generateqi.js
new file mode 100644
index 0000000000..d654b0410c
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/use-chromeutils-generateqi.js
@@ -0,0 +1,105 @@
+/**
+ * @fileoverview Reject use of XPCOMUtils.generateQI and JS-implemented
+ * QueryInterface methods in favor of ChromeUtils.
+ *
+ * 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";
+
+function isIdentifier(node, id) {
+ return node && node.type === "Identifier" && node.name === id;
+}
+
+function isMemberExpression(node, object, member) {
+ return (
+ node.type === "MemberExpression" &&
+ isIdentifier(node.object, object) &&
+ isIdentifier(node.property, member)
+ );
+}
+
+function funcToGenerateQI(context, node) {
+ const sourceCode = context.getSourceCode();
+ const text = sourceCode.getText(node);
+
+ let interfaces = [];
+ let match;
+ let re = /\bCi\.([a-zA-Z0-9]+)\b|\b(nsI[A-Z][a-zA-Z0-9]+)\b/g;
+ while ((match = re.exec(text))) {
+ interfaces.push(match[1] || match[2]);
+ }
+
+ let ifaces = interfaces
+ .filter(iface => iface != "nsISupports")
+ .map(iface => JSON.stringify(iface))
+ .join(", ");
+
+ return `ChromeUtils.generateQI([${ifaces}])`;
+}
+
+module.exports = {
+ meta: {
+ docs: {
+ url: "https://firefox-source-docs.mozilla.org/code-quality/lint/linters/eslint-plugin-mozilla/rules/use-chromeutils-generateqi.html",
+ },
+ fixable: "code",
+ messages: {
+ noJSQueryInterface:
+ "Please use ChromeUtils.generateQI rather than " +
+ "manually creating JavaScript QueryInterface functions",
+ noXpcomUtilsGenerateQI:
+ "Please use ChromeUtils.generateQI instead of XPCOMUtils.generateQI",
+ },
+ schema: [],
+ type: "suggestion",
+ },
+
+ create(context) {
+ return {
+ CallExpression(node) {
+ let { callee } = node;
+ if (isMemberExpression(callee, "XPCOMUtils", "generateQI")) {
+ context.report({
+ node,
+ messageId: "noXpcomUtilsGenerateQI",
+ fix(fixer) {
+ return fixer.replaceText(callee, "ChromeUtils.generateQI");
+ },
+ });
+ }
+ },
+
+ "AssignmentExpression > MemberExpression[property.name='QueryInterface']":
+ function (node) {
+ const { right } = node.parent;
+ if (right.type === "FunctionExpression") {
+ context.report({
+ node: node.parent,
+ messageId: "noJSQueryInterface",
+ fix(fixer) {
+ return fixer.replaceText(
+ right,
+ funcToGenerateQI(context, right)
+ );
+ },
+ });
+ }
+ },
+
+ "Property[key.name='QueryInterface'][value.type='FunctionExpression']":
+ function (node) {
+ context.report({
+ node,
+ messageId: "noJSQueryInterface",
+ fix(fixer) {
+ let generateQI = funcToGenerateQI(context, node.value);
+ return fixer.replaceText(node, `QueryInterface: ${generateQI}`);
+ },
+ });
+ },
+ };
+ },
+};
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/use-chromeutils-import.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/use-chromeutils-import.js
new file mode 100644
index 0000000000..925b4800bc
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/use-chromeutils-import.js
@@ -0,0 +1,63 @@
+/**
+ * @fileoverview Reject use of Cu.import in favor of ChromeUtils.
+ *
+ * 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";
+
+function isIdentifier(node, id) {
+ return node && node.type === "Identifier" && node.name === id;
+}
+
+function isMemberExpression(node, object, member) {
+ return (
+ node.type === "MemberExpression" &&
+ isIdentifier(node.object, object) &&
+ isIdentifier(node.property, member)
+ );
+}
+
+module.exports = {
+ meta: {
+ docs: {
+ url: "https://firefox-source-docs.mozilla.org/code-quality/lint/linters/eslint-plugin-mozilla/rules/use-chromeutils-import.html",
+ },
+ fixable: "code",
+ messages: {
+ useChromeUtilsImport:
+ "Please use ChromeUtils.import instead of Cu.import",
+ },
+ schema: [],
+ type: "suggestion",
+ },
+
+ create(context) {
+ return {
+ CallExpression(node) {
+ if (node.callee.type !== "MemberExpression") {
+ return;
+ }
+
+ let { callee } = node;
+
+ // Is the expression starting with `Cu` or `Components.utils`?
+ if (
+ (isIdentifier(callee.object, "Cu") ||
+ isMemberExpression(callee.object, "Components", "utils")) &&
+ isIdentifier(callee.property, "import")
+ ) {
+ context.report({
+ node,
+ messageId: "useChromeUtilsImport",
+ fix(fixer) {
+ return fixer.replaceText(callee, "ChromeUtils.import");
+ },
+ });
+ }
+ },
+ };
+ },
+};
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/use-console-createInstance.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/use-console-createInstance.js
new file mode 100644
index 0000000000..72add0ab24
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/use-console-createInstance.js
@@ -0,0 +1,44 @@
+/**
+ * @fileoverview Reject use of Console.sys.mjs and Log.sys.mjs.
+ *
+ * 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 = {
+ meta: {
+ docs: {
+ url: "https://firefox-source-docs.mozilla.org/code-quality/lint/linters/eslint-plugin-mozilla/rules/use-console-createInstance.html",
+ },
+ messages: {
+ useConsoleRatherThanModule:
+ "Use console.createInstance rather than {{module}}",
+ },
+ schema: [],
+ type: "suggestion",
+ },
+
+ create(context) {
+ return {
+ Literal(node) {
+ if (typeof node.value != "string") {
+ return;
+ }
+ /* eslint-disable mozilla/use-console-createInstance */
+ if (
+ node.value == "resource://gre/modules/Console.sys.mjs" ||
+ node.value == "resource://gre/modules/Log.sys.mjs"
+ ) {
+ context.report({
+ node,
+ messageId: "useConsoleRatherThanModule",
+ data: { module: node.value.split("/").at(-1) },
+ });
+ }
+ },
+ };
+ },
+};
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/use-default-preference-values.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/use-default-preference-values.js
new file mode 100644
index 0000000000..edc1e28405
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/use-default-preference-values.js
@@ -0,0 +1,56 @@
+/**
+ * @fileoverview Require providing a second parameter to get*Pref
+ * methods instead of using a try/catch block.
+ *
+ * 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 = {
+ meta: {
+ docs: {
+ url: "https://firefox-source-docs.mozilla.org/code-quality/lint/linters/eslint-plugin-mozilla/rules/use-default-preference-values.html",
+ },
+ messages: {
+ provideDefaultValue:
+ "provide a default value instead of using a try/catch block",
+ },
+ schema: [],
+ type: "suggestion",
+ },
+
+ create(context) {
+ return {
+ TryStatement(node) {
+ let types = ["Bool", "Char", "Float", "Int"];
+ let methods = types.map(type => "get" + type + "Pref");
+ if (
+ node.block.type != "BlockStatement" ||
+ node.block.body.length != 1
+ ) {
+ return;
+ }
+
+ let firstStm = node.block.body[0];
+ if (
+ firstStm.type != "ExpressionStatement" ||
+ firstStm.expression.type != "AssignmentExpression" ||
+ firstStm.expression.right.type != "CallExpression" ||
+ firstStm.expression.right.callee.type != "MemberExpression" ||
+ firstStm.expression.right.callee.property.type != "Identifier" ||
+ !methods.includes(firstStm.expression.right.callee.property.name)
+ ) {
+ return;
+ }
+
+ context.report({
+ node,
+ messageId: "provideDefaultValue",
+ });
+ },
+ };
+ },
+};
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/use-includes-instead-of-indexOf.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/use-includes-instead-of-indexOf.js
new file mode 100644
index 0000000000..245c89a095
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/use-includes-instead-of-indexOf.js
@@ -0,0 +1,53 @@
+/**
+ * @fileoverview Use .includes instead of .indexOf
+ *
+ * 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 = {
+ meta: {
+ docs: {
+ url: "https://firefox-source-docs.mozilla.org/code-quality/lint/linters/eslint-plugin-mozilla/rules/use-includes-instead-of-indexOf.html",
+ },
+ messages: {
+ useIncludes: "use .includes instead of .indexOf",
+ },
+ schema: [],
+ type: "suggestion",
+ },
+
+ create(context) {
+ return {
+ BinaryExpression(node) {
+ if (
+ node.left.type != "CallExpression" ||
+ node.left.callee.type != "MemberExpression" ||
+ node.left.callee.property.type != "Identifier" ||
+ node.left.callee.property.name != "indexOf"
+ ) {
+ return;
+ }
+
+ if (
+ (["!=", "!==", "==", "==="].includes(node.operator) &&
+ node.right.type == "UnaryExpression" &&
+ node.right.operator == "-" &&
+ node.right.argument.type == "Literal" &&
+ node.right.argument.value == 1) ||
+ ([">=", "<"].includes(node.operator) &&
+ node.right.type == "Literal" &&
+ node.right.value == 0)
+ ) {
+ context.report({
+ node,
+ messageId: "useIncludes",
+ });
+ }
+ },
+ };
+ },
+};
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/use-isInstance.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/use-isInstance.js
new file mode 100644
index 0000000000..ffd9bc9566
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/use-isInstance.js
@@ -0,0 +1,155 @@
+/**
+ * @fileoverview Reject use of instanceof against DOM interfaces
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+"use strict";
+
+const fs = require("fs");
+
+const { maybeGetMemberPropertyName } = require("../helpers");
+
+const privilegedGlobals = Object.keys(
+ require("../environments/privileged.js").globals
+);
+
+// -----------------------------------------------------------------------------
+// Rule Definition
+// -----------------------------------------------------------------------------
+
+/**
+ * Whether an identifier is defined by eslint configuration.
+ * `env: { browser: true }` or `globals: []` for example.
+ * @param {import("eslint-scope").Scope} currentScope
+ * @param {import("estree").Identifier} id
+ */
+function refersToEnvironmentGlobals(currentScope, id) {
+ const reference = currentScope.references.find(ref => ref.identifier === id);
+ const { resolved } = reference || {};
+ if (!resolved) {
+ return false;
+ }
+
+ // No definition in script files; defined via .eslintrc
+ return resolved.scope.type === "global" && resolved.defs.length === 0;
+}
+
+/**
+ * Whether a node points to a DOM interface.
+ * Includes direct references to interfaces objects and also indirect references
+ * via property access.
+ * OS.File and lazy.(Foo) are explicitly excluded.
+ *
+ * @example HTMLElement
+ * @example win.HTMLElement
+ * @example iframe.contentWindow.HTMLElement
+ * @example foo.HTMLElement
+ *
+ * @param {import("eslint-scope").Scope} currentScope
+ * @param {import("estree").Node} node
+ */
+function pointsToDOMInterface(currentScope, node) {
+ if (node.type === "MemberExpression") {
+ const objectName = maybeGetMemberPropertyName(node.object);
+ if (objectName === "lazy") {
+ // lazy.Foo is probably a non-IDL import.
+ return false;
+ }
+ if (objectName === "OS" && node.property.name === "File") {
+ // OS.File is an exception that is not a Web IDL interface
+ return false;
+ }
+ // For `win.Foo`, `iframe.contentWindow.Foo`, or such.
+ return privilegedGlobals.includes(node.property.name);
+ }
+
+ if (
+ node.type === "Identifier" &&
+ refersToEnvironmentGlobals(currentScope, node)
+ ) {
+ return privilegedGlobals.includes(node.name);
+ }
+
+ return false;
+}
+
+/**
+ * @param {import("eslint").Rule.RuleContext} context
+ */
+function isChromeContext(context) {
+ const filename = context.getFilename();
+ const isChromeFileName =
+ filename.endsWith(".sys.mjs") || filename.endsWith(".jsm");
+ if (isChromeFileName) {
+ return true;
+ }
+
+ if (filename.endsWith(".xhtml")) {
+ // Treat scripts in XUL files as chrome scripts
+ // Note: readFile is needed as getSourceCode() only gives JS blocks
+ return fs.readFileSync(filename).includes("there.is.only.xul");
+ }
+
+ // Treat scripts as chrome privileged when using:
+ // 1. ChromeUtils, but not SpecialPowers.ChromeUtils
+ // 2. BrowserTestUtils, PlacesUtils
+ // 3. document.createXULElement
+ // 4. loader.lazyRequireGetter
+ // 5. Services.foo, but not SpecialPowers.Services.foo
+ // 6. evalInSandbox
+ const source = context.getSourceCode().text;
+ return !!source.match(
+ /(^|\s)ChromeUtils|BrowserTestUtils|PlacesUtils|createXULElement|lazyRequireGetter|(^|\s)Services\.|evalInSandbox/
+ );
+}
+
+module.exports = {
+ meta: {
+ docs: {
+ url: "https://firefox-source-docs.mozilla.org/code-quality/lint/linters/eslint-plugin-mozilla/rules/use-isInstance.html",
+ },
+ fixable: "code",
+ messages: {
+ preferIsInstance:
+ "Please 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.",
+ },
+ schema: [],
+ type: "problem",
+ },
+ /**
+ * @param {import("eslint").Rule.RuleContext} context
+ */
+ create(context) {
+ if (!isChromeContext(context)) {
+ return {};
+ }
+
+ return {
+ BinaryExpression(node) {
+ const { operator, right } = node;
+ if (
+ operator === "instanceof" &&
+ pointsToDOMInterface(context.getScope(), right)
+ ) {
+ context.report({
+ node,
+ messageId: "preferIsInstance",
+ fix(fixer) {
+ const sourceCode = context.getSourceCode();
+ return fixer.replaceText(
+ node,
+ `${sourceCode.getText(right)}.isInstance(${sourceCode.getText(
+ node.left
+ )})`
+ );
+ },
+ });
+ }
+ },
+ };
+ },
+};
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/use-ownerGlobal.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/use-ownerGlobal.js
new file mode 100644
index 0000000000..1d71e82b8f
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/use-ownerGlobal.js
@@ -0,0 +1,43 @@
+/**
+ * @fileoverview Require .ownerGlobal instead of .ownerDocument.defaultView.
+ *
+ * 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 = {
+ meta: {
+ docs: {
+ url: "https://firefox-source-docs.mozilla.org/code-quality/lint/linters/eslint-plugin-mozilla/rules/use-ownerGlobal.html",
+ },
+ messages: {
+ useOwnerGlobal: "use .ownerGlobal instead of .ownerDocument.defaultView",
+ },
+ schema: [],
+ type: "suggestion",
+ },
+
+ create(context) {
+ return {
+ MemberExpression(node) {
+ if (
+ node.property.type != "Identifier" ||
+ node.property.name != "defaultView" ||
+ node.object.type != "MemberExpression" ||
+ node.object.property.type != "Identifier" ||
+ node.object.property.name != "ownerDocument"
+ ) {
+ return;
+ }
+
+ context.report({
+ node,
+ messageId: "useOwnerGlobal",
+ });
+ },
+ };
+ },
+};
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/use-returnValue.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/use-returnValue.js
new file mode 100644
index 0000000000..23bbc040b9
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/use-returnValue.js
@@ -0,0 +1,48 @@
+/**
+ * @fileoverview Warn when idempotent methods are called and their return value is unused.
+ *
+ * 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 = {
+ meta: {
+ docs: {
+ url: "https://firefox-source-docs.mozilla.org/code-quality/lint/linters/eslint-plugin-mozilla/rules/use-returnValue.html",
+ },
+ messages: {
+ useReturnValue:
+ "{Array/String}.{{ property }} doesn't modify the instance in-place",
+ },
+ schema: [],
+ type: "problem",
+ },
+
+ create(context) {
+ return {
+ ExpressionStatement(node) {
+ if (
+ node.expression?.type != "CallExpression" ||
+ node.expression.callee?.type != "MemberExpression" ||
+ node.expression.callee.property?.type != "Identifier" ||
+ !["concat", "join", "slice"].includes(
+ node.expression.callee.property?.name
+ )
+ ) {
+ return;
+ }
+
+ context.report({
+ node,
+ messageId: "useReturnValue",
+ data: {
+ property: node.expression.callee.property.name,
+ },
+ });
+ },
+ };
+ },
+};
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/use-services.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/use-services.js
new file mode 100644
index 0000000000..3a7cc34633
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/use-services.js
@@ -0,0 +1,120 @@
+/**
+ * @fileoverview Require use of Services.* rather than getService.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+"use strict";
+const helpers = require("../helpers");
+
+let servicesInterfaceMap = helpers.servicesData;
+
+module.exports = {
+ meta: {
+ docs: {
+ url: "https://firefox-source-docs.mozilla.org/code-quality/lint/linters/eslint-plugin-mozilla/rules/use-services.html",
+ },
+ // fixable: "code",
+ messages: {
+ useServices:
+ "Use Services.{{ serviceName }} rather than {{ getterName }}.",
+ },
+ schema: [],
+ type: "suggestion",
+ },
+
+ create(context) {
+ return {
+ CallExpression(node) {
+ if (!node.callee || !node.callee.property) {
+ return;
+ }
+
+ if (
+ node.callee.property.type == "Identifier" &&
+ node.callee.property.name == "defineLazyServiceGetter" &&
+ node.arguments.length == 4 &&
+ node.arguments[3].type == "Literal" &&
+ node.arguments[3].value in servicesInterfaceMap
+ ) {
+ let serviceName = servicesInterfaceMap[node.arguments[3].value];
+
+ context.report({
+ node,
+ messageId: "useServices",
+ data: {
+ serviceName,
+ getterName: "defineLazyServiceGetter",
+ },
+ });
+ return;
+ }
+
+ if (
+ node.callee.property.type == "Identifier" &&
+ node.callee.property.name == "defineLazyServiceGetters" &&
+ node.arguments.length == 2 &&
+ node.arguments[1].type == "ObjectExpression"
+ ) {
+ for (let property of node.arguments[1].properties) {
+ if (
+ property.value.type == "ArrayExpression" &&
+ property.value.elements.length == 2 &&
+ property.value.elements[1].value in servicesInterfaceMap
+ ) {
+ let serviceName =
+ servicesInterfaceMap[property.value.elements[1].value];
+
+ context.report({
+ node: property.value,
+ messageId: "useServices",
+ data: {
+ serviceName,
+ getterName: "defineLazyServiceGetters",
+ },
+ });
+ }
+ }
+ return;
+ }
+
+ if (
+ node.callee.property.type != "Identifier" ||
+ node.callee.property.name != "getService" ||
+ node.arguments.length != 1 ||
+ !node.arguments[0].property ||
+ node.arguments[0].property.type != "Identifier" ||
+ !node.arguments[0].property.name ||
+ !(node.arguments[0].property.name in servicesInterfaceMap)
+ ) {
+ return;
+ }
+
+ let serviceName = servicesInterfaceMap[node.arguments[0].property.name];
+ context.report({
+ node,
+ messageId: "useServices",
+ data: {
+ serviceName,
+ getterName: "getService()",
+ },
+ // This is not enabled by default as for mochitest plain tests we
+ // would need to replace with `SpecialPowers.Services.${serviceName}`.
+ // At the moment we do not have an easy way to detect that.
+ // fix(fixer) {
+ // let sourceCode = context.getSourceCode();
+ // return fixer.replaceTextRange(
+ // [
+ // sourceCode.getFirstToken(node.callee).range[0],
+ // sourceCode.getLastToken(node).range[1],
+ // ],
+ // `Services.${serviceName}`
+ // );
+ // },
+ });
+ },
+ };
+ },
+};
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/use-static-import.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/use-static-import.js
new file mode 100644
index 0000000000..100b5682de
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/use-static-import.js
@@ -0,0 +1,87 @@
+/**
+ * @fileoverview Require use of static imports where possible.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+"use strict";
+
+const helpers = require("../helpers");
+
+function isIdentifier(node, id) {
+ return node && node.type === "Identifier" && node.name === id;
+}
+
+module.exports = {
+ meta: {
+ docs: {
+ url: "https://firefox-source-docs.mozilla.org/code-quality/lint/linters/eslint-plugin-mozilla/rules/use-static-import.html",
+ },
+ fixable: "code",
+ messages: {
+ useStaticImport:
+ "Please use static import instead of ChromeUtils.importESModule",
+ },
+ schema: [],
+ type: "suggestion",
+ },
+
+ create(context) {
+ return {
+ VariableDeclarator(node) {
+ if (
+ node.init?.type != "CallExpression" ||
+ node.init?.callee?.type != "MemberExpression" ||
+ !context.getFilename().endsWith(".sys.mjs") ||
+ !helpers.isTopLevel(context.getAncestors())
+ ) {
+ return;
+ }
+
+ let callee = node.init.callee;
+
+ if (
+ isIdentifier(callee.object, "ChromeUtils") &&
+ isIdentifier(callee.property, "importESModule") &&
+ callee.parent.arguments.length == 1
+ ) {
+ let sourceCode = context.getSourceCode();
+ let importItemSource;
+ if (node.id.type != "ObjectPattern") {
+ importItemSource = sourceCode.getText(node.id);
+ } else {
+ importItemSource = "{ ";
+ let initial = true;
+ for (let property of node.id.properties) {
+ if (!initial) {
+ importItemSource += ", ";
+ }
+ initial = false;
+ if (property.key.name == property.value.name) {
+ importItemSource += property.key.name;
+ } else {
+ importItemSource += `${property.key.name} as ${property.value.name}`;
+ }
+ }
+ importItemSource += " }";
+ }
+
+ context.report({
+ node: node.parent,
+ messageId: "useStaticImport",
+ fix(fixer) {
+ return fixer.replaceText(
+ node.parent,
+ `import ${importItemSource} from ${sourceCode.getText(
+ callee.parent.arguments[0]
+ )}`
+ );
+ },
+ });
+ }
+ },
+ };
+ },
+};
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/valid-ci-uses.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/valid-ci-uses.js
new file mode 100644
index 0000000000..4036a72928
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/valid-ci-uses.js
@@ -0,0 +1,172 @@
+/**
+ * @fileoverview Reject uses of unknown interfaces on Ci and properties of those
+ * interfaces.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+"use strict";
+
+const os = require("os");
+const helpers = require("../helpers");
+
+// These interfaces are all platform specific, so may be not present
+// on all platforms.
+const platformSpecificInterfaces = new Map([
+ ["nsIAboutThirdParty", "windows"],
+ ["nsIAboutWindowsMessages", "windows"],
+ ["nsIDefaultAgent", "windows"],
+ ["nsIJumpListBuilder", "windows"],
+ ["nsILegacyJumpListBuilder", "windows"],
+ ["nsILegacyJumpListItem", "windows"],
+ ["nsILegacyJumpListLink", "windows"],
+ ["nsILegacyJumpListSeparator", "windows"],
+ ["nsILegacyJumpListShortcut", "windows"],
+ ["nsITaskbarWindowPreview", "windows"],
+ ["nsIWindowsAlertsService", "windows"],
+ ["nsIWindowsAlertNotification", "windows"],
+ ["nsIWindowsMutexFactory", "windows"],
+ ["nsIWinAppHelper", "windows"],
+ ["nsIWinTaskbar", "windows"],
+ ["nsIWinTaskSchedulerService", "windows"],
+ ["nsIWindowsRegKey", "windows"],
+ ["nsIWindowsPackageManager", "windows"],
+ ["nsIWindowsShellService", "windows"],
+ ["nsIAccessibleMacEvent", "darwin"],
+ ["nsIAccessibleMacInterface", "darwin"],
+ ["nsILocalFileMac", "darwin"],
+ ["nsIAccessibleMacEvent", "darwin"],
+ ["nsIMacAttributionService", "darwin"],
+ ["nsIMacShellService", "darwin"],
+ ["nsIMacDockSupport", "darwin"],
+ ["nsIMacFinderProgress", "darwin"],
+ ["nsIMacPreferencesReader", "darwin"],
+ ["nsIMacSharingService", "darwin"],
+ ["nsIMacUserActivityUpdater", "darwin"],
+ ["nsIMacWebAppUtils", "darwin"],
+ ["nsIStandaloneNativeMenu", "darwin"],
+ ["nsITouchBarHelper", "darwin"],
+ ["nsITouchBarInput", "darwin"],
+ ["nsITouchBarUpdater", "darwin"],
+ ["mozISandboxReporter", "linux"],
+ ["nsIApplicationChooser", "linux"],
+ ["nsIGNOMEShellService", "linux"],
+ ["nsIGtkTaskbarProgress", "linux"],
+
+ // These are used in the ESLint test code.
+ ["amIFoo", "any"],
+ ["nsIMeh", "any"],
+ // Can't easily detect android builds from ESLint at the moment.
+ ["nsIAndroidBridge", "any"],
+ ["nsIAndroidView", "any"],
+ // Code coverage is enabled only for certain builds (MOZ_CODE_COVERAGE).
+ ["nsICodeCoverage", "any"],
+ // Layout debugging is enabled only for certain builds (MOZ_LAYOUT_DEBUGGER).
+ ["nsILayoutDebuggingTools", "any"],
+ // Sandbox test is only enabled for certain configurations (MOZ_SANDBOX,
+ // MOZ_DEBUG, ENABLE_TESTS).
+ ["mozISandboxTest", "any"],
+]);
+
+function interfaceHasProperty(interfaceName, propertyName) {
+ // `Ci.nsIFoo.number` is valid, it returns the iid.
+ if (propertyName == "number") {
+ return true;
+ }
+
+ let interfaceInfo = helpers.xpidlData.get(interfaceName);
+
+ if (!interfaceInfo) {
+ return true;
+ }
+
+ // If the property is not in the lists of consts for this interface, check
+ // any parents as well.
+ if (!interfaceInfo.consts.find(e => e.name === propertyName)) {
+ if (interfaceInfo.parent && interfaceInfo.parent != "nsISupports") {
+ return interfaceHasProperty(interfaceName.parent, propertyName);
+ }
+ return false;
+ }
+ return true;
+}
+
+module.exports = {
+ meta: {
+ docs: {
+ url: "https://firefox-source-docs.mozilla.org/code-quality/lint/linters/eslint-plugin-mozilla/rules/valid-ci-uses.html",
+ },
+ messages: {
+ missingInterface:
+ "{{ interface }} is defined in this rule's platform specific list, but is not available",
+ unknownInterface: "Use of unknown interface Ci.{{ interface}}",
+ unknownProperty:
+ "Use of unknown property Ci.{{ interface }}.{{ property }}",
+ },
+ schema: [],
+ type: "problem",
+ },
+
+ create(context) {
+ return {
+ MemberExpression(node) {
+ if (
+ node.computed === false &&
+ node.type === "MemberExpression" &&
+ node.object.type === "Identifier" &&
+ node.object.name === "Ci" &&
+ node.property.type === "Identifier" &&
+ node.property.name.includes("I")
+ ) {
+ if (!helpers.xpidlData.get(node.property.name)) {
+ let platformSpecific = platformSpecificInterfaces.get(
+ node.property.name
+ );
+ if (!platformSpecific) {
+ context.report({
+ node,
+ messageId: "unknownInterface",
+ data: {
+ interface: node.property.name,
+ },
+ });
+ } else if (platformSpecific == os.platform) {
+ context.report({
+ node,
+ messageId: "missingInterface",
+ data: {
+ interface: node.property.name,
+ },
+ });
+ }
+ }
+ }
+
+ if (
+ node.computed === false &&
+ node.object.type === "MemberExpression" &&
+ node.object.object.type === "Identifier" &&
+ node.object.object.name === "Ci" &&
+ node.object.property.type === "Identifier" &&
+ node.object.property.name.includes("I") &&
+ node.property.type === "Identifier"
+ ) {
+ if (
+ !interfaceHasProperty(node.object.property.name, node.property.name)
+ ) {
+ context.report({
+ node,
+ messageId: "unknownProperty",
+ data: {
+ interface: node.object.property.name,
+ property: node.property.name,
+ },
+ });
+ }
+ }
+ },
+ };
+ },
+};
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/valid-lazy.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/valid-lazy.js
new file mode 100644
index 0000000000..048ed17e3e
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/valid-lazy.js
@@ -0,0 +1,276 @@
+/**
+ * @fileoverview Ensures that definitions and uses of properties on the
+ * ``lazy`` object are valid.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+"use strict";
+const helpers = require("../helpers");
+
+const items = [
+ "loader",
+ "XPCOMUtils",
+ "Integration",
+ "ChromeUtils",
+ "DevToolsUtils",
+ "Object",
+ "Reflect",
+];
+
+const callExpressionDefinitions = [
+ /^loader\.lazyGetter\(lazy, "(\w+)"/,
+ /^loader\.lazyServiceGetter\(lazy, "(\w+)"/,
+ /^loader\.lazyRequireGetter\(lazy, "(\w+)"/,
+ /^XPCOMUtils\.defineLazyGetter\(lazy, "(\w+)"/,
+ /^Integration\.downloads\.defineESModuleGetter\(lazy, "(\w+)"/,
+ /^ChromeUtils\.defineLazyGetter\(lazy, "(\w+)"/,
+ /^ChromeUtils\.defineModuleGetter\(lazy, "(\w+)"/,
+ /^XPCOMUtils\.defineLazyPreferenceGetter\(lazy, "(\w+)"/,
+ /^XPCOMUtils\.defineLazyScriptGetter\(lazy, "(\w+)"/,
+ /^XPCOMUtils\.defineLazyServiceGetter\(lazy, "(\w+)"/,
+ /^XPCOMUtils\.defineConstant\(lazy, "(\w+)"/,
+ /^DevToolsUtils\.defineLazyGetter\(lazy, "(\w+)"/,
+ /^Object\.defineProperty\(lazy, "(\w+)"/,
+ /^Reflect\.defineProperty\(lazy, "(\w+)"/,
+];
+
+const callExpressionMultiDefinitions = [
+ "ChromeUtils.defineESModuleGetters(lazy,",
+ "XPCOMUtils.defineLazyModuleGetters(lazy,",
+ "XPCOMUtils.defineLazyServiceGetters(lazy,",
+ "Object.defineProperties(lazy,",
+ "loader.lazyRequireGetter(lazy,",
+];
+
+module.exports = {
+ meta: {
+ docs: {
+ url: "https://firefox-source-docs.mozilla.org/code-quality/lint/linters/eslint-plugin-mozilla/rules/valid-lazy.html",
+ },
+ messages: {
+ duplicateSymbol: "Duplicate symbol {{name}} being added to lazy.",
+ incorrectType: "Unexpected literal for property name {{name}}",
+ unknownProperty: "Unknown lazy member property {{name}}",
+ unusedProperty: "Unused lazy property {{name}}",
+ topLevelAndUnconditional:
+ "Lazy property {{name}} is used at top-level unconditionally. It should be non-lazy.",
+ },
+ schema: [],
+ type: "problem",
+ },
+
+ create(context) {
+ let lazyProperties = new Map();
+ let unknownProperties = [];
+ let isLazyExported = false;
+
+ function getAncestorNodes(node) {
+ const ancestors = [];
+ node = node.parent;
+ while (node) {
+ ancestors.unshift(node);
+ node = node.parent;
+ }
+ return ancestors;
+ }
+
+ // Returns true if lazy getter definitions in prevNode and currNode are
+ // duplicate.
+ // This returns false if prevNode and currNode have the same IfStatement as
+ // ancestor and they're in different branches.
+ function isDuplicate(prevNode, currNode) {
+ const prevAncestors = getAncestorNodes(prevNode);
+ const currAncestors = getAncestorNodes(currNode);
+
+ for (
+ let i = 0;
+ i < prevAncestors.length && i < currAncestors.length;
+ i++
+ ) {
+ const prev = prevAncestors[i];
+ const curr = currAncestors[i];
+ if (prev === curr && prev.type === "IfStatement") {
+ if (prevAncestors[i + 1] !== currAncestors[i + 1]) {
+ return false;
+ }
+ }
+ }
+
+ return true;
+ }
+
+ function addProp(callNode, propNode, name) {
+ if (
+ lazyProperties.has(name) &&
+ isDuplicate(lazyProperties.get(name).callNode, callNode)
+ ) {
+ context.report({
+ node: propNode,
+ messageId: "duplicateSymbol",
+ data: { name },
+ });
+ return;
+ }
+ lazyProperties.set(name, { used: false, callNode, propNode });
+ }
+
+ function setPropertiesFromArgument(callNode, arg) {
+ if (arg.type === "ObjectExpression") {
+ for (let propNode of arg.properties) {
+ if (propNode.key.type == "Literal") {
+ context.report({
+ node: propNode,
+ messageId: "incorrectType",
+ data: { name: propNode.key.value },
+ });
+ continue;
+ }
+ addProp(callNode, propNode, propNode.key.name);
+ }
+ } else if (arg.type === "ArrayExpression") {
+ for (let propNode of arg.elements) {
+ if (propNode.type != "Literal") {
+ continue;
+ }
+ addProp(callNode, propNode, propNode.value);
+ }
+ }
+ }
+
+ return {
+ VariableDeclarator(node) {
+ if (
+ node.id.type === "Identifier" &&
+ node.id.name == "lazy" &&
+ node.init.type == "CallExpression" &&
+ node.init.callee.name == "createLazyLoaders"
+ ) {
+ setPropertiesFromArgument(node.init, node.init.arguments[0]);
+ }
+ },
+
+ CallExpression(node) {
+ if (
+ node.callee.type != "MemberExpression" ||
+ (node.callee.object.type == "MemberExpression" &&
+ !items.includes(node.callee.object.object.name)) ||
+ (node.callee.object.type != "MemberExpression" &&
+ !items.includes(node.callee.object.name))
+ ) {
+ return;
+ }
+
+ let source;
+ try {
+ source = helpers.getASTSource(node);
+ } catch (e) {
+ return;
+ }
+
+ for (let reg of callExpressionDefinitions) {
+ let match = source.match(reg);
+ if (match) {
+ if (
+ lazyProperties.has(match[1]) &&
+ isDuplicate(lazyProperties.get(match[1]).callNode, node)
+ ) {
+ context.report({
+ node,
+ messageId: "duplicateSymbol",
+ data: { name: match[1] },
+ });
+ return;
+ }
+ lazyProperties.set(match[1], {
+ used: false,
+ callNode: node,
+ propNode: node,
+ });
+ break;
+ }
+ }
+
+ if (
+ callExpressionMultiDefinitions.some(expr =>
+ source.startsWith(expr)
+ ) &&
+ node.arguments[1]
+ ) {
+ setPropertiesFromArgument(node, node.arguments[1]);
+ }
+ },
+
+ MemberExpression(node) {
+ if (node.computed || node.object.type !== "Identifier") {
+ return;
+ }
+
+ let name;
+ if (node.object.name == "lazy") {
+ name = node.property.name;
+ } else {
+ return;
+ }
+ let property = lazyProperties.get(name);
+ if (!property) {
+ // These will be reported on Program:exit - some definitions may
+ // be after first use, so we need to wait until we've processed
+ // the whole file before reporting.
+ unknownProperties.push({ name, node });
+ } else {
+ property.used = true;
+ }
+ if (
+ helpers.getIsTopLevelAndUnconditionallyExecuted(
+ context.getAncestors()
+ )
+ ) {
+ context.report({
+ node,
+ messageId: "topLevelAndUnconditional",
+ data: { name },
+ });
+ }
+ },
+
+ ExportNamedDeclaration(node) {
+ for (const spec of node.specifiers) {
+ if (spec.local.name === "lazy") {
+ // If the lazy object is exported, do not check unused property.
+ isLazyExported = true;
+ break;
+ }
+ }
+ },
+
+ "Program:exit": function () {
+ for (let { name, node } of unknownProperties) {
+ let property = lazyProperties.get(name);
+ if (!property) {
+ context.report({
+ node,
+ messageId: "unknownProperty",
+ data: { name },
+ });
+ } else {
+ property.used = true;
+ }
+ }
+ if (!isLazyExported) {
+ for (let [name, property] of lazyProperties.entries()) {
+ if (!property.used) {
+ context.report({
+ node: property.propNode,
+ messageId: "unusedProperty",
+ data: { name },
+ });
+ }
+ }
+ }
+ },
+ };
+ },
+};
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/valid-services-property.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/valid-services-property.js
new file mode 100644
index 0000000000..8f665d6d8a
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/valid-services-property.js
@@ -0,0 +1,126 @@
+/**
+ * @fileoverview Ensures that property accesses on Services.<alias> are valid.
+ * Although this largely duplicates the valid-services rule, the checks here
+ * require an objdir and a manual run.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+"use strict";
+
+const helpers = require("../helpers");
+
+function findInterfaceNames(name) {
+ let interfaces = [];
+ for (let [key, value] of Object.entries(helpers.servicesData)) {
+ if (value == name) {
+ interfaces.push(key);
+ }
+ }
+ return interfaces;
+}
+
+function isInInterface(interfaceName, name) {
+ let interfaceDetails = helpers.xpidlData.get(interfaceName);
+
+ // TODO: Bug 1790261 - check only methods if the expression is callable.
+ if (interfaceDetails.methods.some(m => m.name == name)) {
+ return true;
+ }
+
+ if (interfaceDetails.consts.some(c => c.name == name)) {
+ return true;
+ }
+
+ if (interfaceDetails.parent) {
+ return isInInterface(interfaceDetails.parent, name);
+ }
+ return false;
+}
+
+module.exports = {
+ meta: {
+ docs: {
+ url: "https://firefox-source-docs.mozilla.org/code-quality/lint/linters/eslint-plugin-mozilla/rules/valid-services-property.html",
+ },
+ messages: {
+ unknownProperty:
+ "Unknown property access Services.{{ alias }}.{{ propertyName }}, Interfaces: {{ checkedInterfaces }}",
+ },
+ schema: [],
+ type: "problem",
+ },
+
+ create(context) {
+ let servicesInterfaceMap = helpers.servicesData;
+ let serviceAliases = new Set([
+ ...Object.values(servicesInterfaceMap),
+ // This is defined only for Android, so most builds won't pick it up.
+ "androidBridge",
+ // These are defined without interfaces and hence are not in the services map.
+ "cpmm",
+ "crashmanager",
+ "mm",
+ "ppmm",
+ // The new xulStore also does not have an interface.
+ "xulStore",
+ ]);
+ return {
+ MemberExpression(node) {
+ if (node.computed || node.object.type !== "Identifier") {
+ return;
+ }
+
+ let mainNode;
+ if (node.object.name == "Services") {
+ mainNode = node;
+ } else if (
+ node.property.name == "Services" &&
+ node.parent.type == "MemberExpression"
+ ) {
+ mainNode = node.parent;
+ } else {
+ return;
+ }
+
+ let alias = mainNode.property.name;
+ if (!serviceAliases.has(alias)) {
+ return;
+ }
+
+ if (
+ mainNode.parent.type == "MemberExpression" &&
+ !mainNode.parent.computed
+ ) {
+ let propertyName = mainNode.parent.property.name;
+ if (propertyName == "wrappedJSObject") {
+ return;
+ }
+ let interfaces = findInterfaceNames(alias);
+ if (!interfaces.length) {
+ return;
+ }
+
+ let checkedInterfaces = [];
+ for (let item of interfaces) {
+ if (isInInterface(item, propertyName)) {
+ return;
+ }
+ checkedInterfaces.push(item);
+ }
+ context.report({
+ node,
+ messageId: "unknownProperty",
+ data: {
+ alias,
+ propertyName,
+ checkedInterfaces,
+ },
+ });
+ }
+ },
+ };
+ },
+};
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/valid-services.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/valid-services.js
new file mode 100644
index 0000000000..7380fda491
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/valid-services.js
@@ -0,0 +1,68 @@
+/**
+ * @fileoverview Ensures that Services uses have valid property names.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+"use strict";
+const helpers = require("../helpers");
+
+module.exports = {
+ meta: {
+ docs: {
+ url: "https://firefox-source-docs.mozilla.org/code-quality/lint/linters/eslint-plugin-mozilla/rules/valid-services.html",
+ },
+ messages: {
+ unknownProperty: "Unknown Services member property {{ alias }}",
+ },
+ schema: [],
+ type: "problem",
+ },
+
+ create(context) {
+ let servicesInterfaceMap = helpers.servicesData;
+ let serviceAliases = new Set([
+ ...Object.values(servicesInterfaceMap),
+ // This is defined only for Android, so most builds won't pick it up.
+ "androidBridge",
+ // These are defined without interfaces and hence are not in the services map.
+ "cpmm",
+ "crashmanager",
+ "mm",
+ "ppmm",
+ // The new xulStore also does not have an interface.
+ "xulStore",
+ ]);
+ return {
+ MemberExpression(node) {
+ if (node.computed || node.object.type !== "Identifier") {
+ return;
+ }
+
+ let alias;
+ if (node.object.name == "Services") {
+ alias = node.property.name;
+ } else if (
+ node.property.name == "Services" &&
+ node.parent.type == "MemberExpression"
+ ) {
+ alias = node.parent.property.name;
+ } else {
+ return;
+ }
+
+ if (!serviceAliases.has(alias)) {
+ context.report({
+ node,
+ messageId: "unknownProperty",
+ data: {
+ alias,
+ },
+ });
+ }
+ },
+ };
+ },
+};
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/var-only-at-top-level.js b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/var-only-at-top-level.js
new file mode 100644
index 0000000000..5da799c643
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/var-only-at-top-level.js
@@ -0,0 +1,42 @@
+/**
+ * @fileoverview Marks all var declarations that are not at the top level
+ * invalid.
+ *
+ * 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";
+
+var helpers = require("../helpers");
+
+module.exports = {
+ meta: {
+ docs: {
+ url: "https://firefox-source-docs.mozilla.org/code-quality/lint/linters/eslint-plugin-mozilla/rules/var-only-at-top-level.html",
+ },
+ messages: {
+ unexpectedVar: "Unexpected var, use let or const instead.",
+ },
+ schema: [],
+ type: "suggestion",
+ },
+
+ create(context) {
+ return {
+ VariableDeclaration(node) {
+ if (node.kind === "var") {
+ if (helpers.getIsTopLevelScript(context.getAncestors())) {
+ return;
+ }
+
+ context.report({
+ node,
+ messageId: "unexpectedVar",
+ });
+ }
+ },
+ };
+ },
+};
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/services.json b/tools/lint/eslint/eslint-plugin-mozilla/lib/services.json
new file mode 100644
index 0000000000..476c6bf784
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/services.json
@@ -0,0 +1,63 @@
+{
+ "mozIJSSubScriptLoader": "scriptloader",
+ "mozILocaleService": "locale",
+ "mozIMozIntl": "intl",
+ "mozIStorageService": "storage",
+ "nsIAppShellService": "appShell",
+ "nsIAppStartup": "startup",
+ "nsIBlocklistService": "blocklist",
+ "nsICacheStorageService": "cache2",
+ "nsICategoryManager": "catMan",
+ "nsIClearDataService": "clearData",
+ "nsIClipboard": "clipboard",
+ "nsIConsoleService": "console",
+ "nsICookieBannerService": "cookieBanners",
+ "nsICookieManager": "cookies",
+ "nsICookieService": "cookies",
+ "nsICrashReporter": "appinfo",
+ "nsIDAPTelemetry": "DAPTelemetry",
+ "nsIDOMRequestService": "DOMRequest",
+ "nsIDOMStorageManager": "domStorageManager",
+ "nsIDNSService": "dns",
+ "nsIDirectoryService": "dirsvc",
+ "nsIDroppedLinkHandler": "droppedLinkHandler",
+ "nsIEffectiveTLDService": "eTLD",
+ "nsIEnterprisePolicies": "policies",
+ "nsIEnvironment": "env",
+ "nsIEventListenerService": "els",
+ "nsIFOG": "fog",
+ "nsIFocusManager": "focus",
+ "nsIIOService": "io",
+ "nsILoadContextInfoFactory": "loadContextInfo",
+ "nsILocalStorageManager": "domStorageManager",
+ "nsILoginManager": "logins",
+ "nsINetUtil": "io",
+ "nsIObserverService": "obs",
+ "nsIPermissionManager": "perms",
+ "nsIPrefBranch": "prefs",
+ "nsIPrefService": "prefs",
+ "nsIProfiler": "profiler",
+ "nsIPromptService": "prompt",
+ "nsIProperties": "dirsvc",
+ "nsIPropertyBag2": "sysinfo",
+ "nsIQuotaManagerService": "qms",
+ "nsIRFPService": "rfp",
+ "nsIScriptSecurityManager": "scriptSecurityManager",
+ "nsISearchService": "search",
+ "nsISessionStorageService": "sessionStorage",
+ "nsISpeculativeConnect": "io",
+ "nsIStringBundleService": "strings",
+ "nsISystemInfo": "sysinfo",
+ "nsITelemetry": "telemetry",
+ "nsITextToSubURI": "textToSubURI",
+ "nsIThreadManager": "tm",
+ "nsIURIFixup": "uriFixup",
+ "nsIURLFormatter": "urlFormatter",
+ "nsIUUIDGenerator": "uuid",
+ "nsIVersionComparator": "vc",
+ "nsIWindowMediator": "wm",
+ "nsIWindowWatcher": "ww",
+ "nsIXULAppInfo": "appinfo",
+ "nsIXULRuntime": "appinfo",
+ "nsIXULStore": "xulStore"
+}
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/manifest.tt b/tools/lint/eslint/eslint-plugin-mozilla/manifest.tt
new file mode 100644
index 0000000000..47ca98109b
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/manifest.tt
@@ -0,0 +1,10 @@
+[
+ {
+ "filename": "eslint-plugin-mozilla.tar.gz",
+ "size": 5546844,
+ "algorithm": "sha512",
+ "digest": "7df05ad96a7e892f04079570e7847cef71048e3d96e7a338f7e5aa431d5bf34225196200fffc42a630678f2bb074b806dd24d76da25827fbfc16d0ae5e8e6cd5",
+ "unpack": true,
+ "visibility": "public"
+ }
+] \ No newline at end of file
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/package-lock.json b/tools/lint/eslint/eslint-plugin-mozilla/package-lock.json
new file mode 100644
index 0000000000..8265c41a94
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/package-lock.json
@@ -0,0 +1,5249 @@
+{
+ "name": "eslint-plugin-mozilla",
+ "version": "3.7.0",
+ "lockfileVersion": 2,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "eslint-plugin-mozilla",
+ "version": "3.7.0",
+ "license": "MPL-2.0",
+ "dependencies": {
+ "eslint-scope": "^7.2.2",
+ "eslint-visitor-keys": "^3.4.3",
+ "espree": "^9.6.1",
+ "estraverse": "^5.3.0",
+ "htmlparser2": "^8.0.1",
+ "toml-eslint-parser": "0.9.3"
+ },
+ "devDependencies": {
+ "eslint": "8.56.0",
+ "mocha": "10.2.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "peerDependencies": {
+ "@microsoft/eslint-plugin-sdl": "^0.2.2",
+ "eslint": "^7.23.0 || ^8.0.0",
+ "eslint-config-prettier": "^8.0.0 || ^9.0.0",
+ "eslint-plugin-fetch-options": "^0.0.5",
+ "eslint-plugin-html": "^7.0.0",
+ "eslint-plugin-json": "^3.1.0",
+ "eslint-plugin-no-unsanitized": "^4.0.0"
+ }
+ },
+ "node_modules/@aashutoshrathi/word-wrap": {
+ "version": "1.2.6",
+ "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz",
+ "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/@eslint-community/eslint-utils": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz",
+ "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==",
+ "dependencies": {
+ "eslint-visitor-keys": "^3.3.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "peerDependencies": {
+ "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
+ }
+ },
+ "node_modules/@eslint-community/regexpp": {
+ "version": "4.10.0",
+ "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz",
+ "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==",
+ "engines": {
+ "node": "^12.0.0 || ^14.0.0 || >=16.0.0"
+ }
+ },
+ "node_modules/@eslint/eslintrc": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz",
+ "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==",
+ "dependencies": {
+ "ajv": "^6.12.4",
+ "debug": "^4.3.2",
+ "espree": "^9.6.0",
+ "globals": "^13.19.0",
+ "ignore": "^5.2.0",
+ "import-fresh": "^3.2.1",
+ "js-yaml": "^4.1.0",
+ "minimatch": "^3.1.2",
+ "strip-json-comments": "^3.1.1"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/@eslint/js": {
+ "version": "8.56.0",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.56.0.tgz",
+ "integrity": "sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==",
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ }
+ },
+ "node_modules/@humanwhocodes/config-array": {
+ "version": "0.11.14",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz",
+ "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==",
+ "dependencies": {
+ "@humanwhocodes/object-schema": "^2.0.2",
+ "debug": "^4.3.1",
+ "minimatch": "^3.0.5"
+ },
+ "engines": {
+ "node": ">=10.10.0"
+ }
+ },
+ "node_modules/@humanwhocodes/module-importer": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
+ "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
+ "engines": {
+ "node": ">=12.22"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/nzakas"
+ }
+ },
+ "node_modules/@humanwhocodes/object-schema": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz",
+ "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw=="
+ },
+ "node_modules/@microsoft/eslint-plugin-sdl": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/@microsoft/eslint-plugin-sdl/-/eslint-plugin-sdl-0.2.2.tgz",
+ "integrity": "sha512-TiBepeQMSxHpvIbKA03TbO9nZqRrKR1th47wGdjY1sH2SSer+JgKlSF3S8GURGA8/zp2T/HwSiAJelclJ3hEvg==",
+ "peer": true,
+ "dependencies": {
+ "eslint-plugin-node": "11.1.0",
+ "eslint-plugin-react": "7.33.0",
+ "eslint-plugin-security": "1.4.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ },
+ "peerDependencies": {
+ "eslint": "^4.19.1 || ^5 || ^6 || ^7 || ^8"
+ }
+ },
+ "node_modules/@nodelib/fs.scandir": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
+ "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
+ "dependencies": {
+ "@nodelib/fs.stat": "2.0.5",
+ "run-parallel": "^1.1.9"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.stat": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
+ "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.walk": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
+ "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
+ "dependencies": {
+ "@nodelib/fs.scandir": "2.1.5",
+ "fastq": "^1.6.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@ungap/structured-clone": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz",
+ "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ=="
+ },
+ "node_modules/acorn": {
+ "version": "8.11.3",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz",
+ "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==",
+ "bin": {
+ "acorn": "bin/acorn"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/acorn-jsx": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
+ "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
+ "peerDependencies": {
+ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ }
+ },
+ "node_modules/ajv": {
+ "version": "6.12.6",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+ "dependencies": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/ansi-colors": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz",
+ "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/anymatch": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
+ "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
+ "dev": true,
+ "dependencies": {
+ "normalize-path": "^3.0.0",
+ "picomatch": "^2.0.4"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
+ },
+ "node_modules/array-buffer-byte-length": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz",
+ "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==",
+ "peer": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "is-array-buffer": "^3.0.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array-includes": {
+ "version": "3.1.7",
+ "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.7.tgz",
+ "integrity": "sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ==",
+ "peer": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.2.0",
+ "es-abstract": "^1.22.1",
+ "get-intrinsic": "^1.2.1",
+ "is-string": "^1.0.7"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array.prototype.flat": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz",
+ "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==",
+ "peer": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.2.0",
+ "es-abstract": "^1.22.1",
+ "es-shim-unscopables": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array.prototype.flatmap": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz",
+ "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==",
+ "peer": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.2.0",
+ "es-abstract": "^1.22.1",
+ "es-shim-unscopables": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array.prototype.tosorted": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.2.tgz",
+ "integrity": "sha512-HuQCHOlk1Weat5jzStICBCd83NxiIMwqDg/dHEsoefabn/hJRj5pVdWcPUSpRrwhwxZOsQassMpgN/xRYFBMIg==",
+ "peer": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.2.0",
+ "es-abstract": "^1.22.1",
+ "es-shim-unscopables": "^1.0.0",
+ "get-intrinsic": "^1.2.1"
+ }
+ },
+ "node_modules/arraybuffer.prototype.slice": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.2.tgz",
+ "integrity": "sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==",
+ "peer": true,
+ "dependencies": {
+ "array-buffer-byte-length": "^1.0.0",
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.2.0",
+ "es-abstract": "^1.22.1",
+ "get-intrinsic": "^1.2.1",
+ "is-array-buffer": "^3.0.2",
+ "is-shared-array-buffer": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/available-typed-arrays": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.6.tgz",
+ "integrity": "sha512-j1QzY8iPNPG4o4xmO3ptzpRxTciqD3MgEHtifP/YnJpIo58Xu+ne4BejlbkuaLfXn/nz6HFiw29bLpj2PNMdGg==",
+ "peer": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
+ },
+ "node_modules/binary-extensions": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
+ "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/braces": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
+ "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+ "dev": true,
+ "dependencies": {
+ "fill-range": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/browser-stdout": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz",
+ "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==",
+ "dev": true
+ },
+ "node_modules/call-bind": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz",
+ "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==",
+ "peer": true,
+ "dependencies": {
+ "function-bind": "^1.1.2",
+ "get-intrinsic": "^1.2.1",
+ "set-function-length": "^1.1.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/callsites": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/camelcase": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
+ "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/chokidar": {
+ "version": "3.5.3",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
+ "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://paulmillr.com/funding/"
+ }
+ ],
+ "dependencies": {
+ "anymatch": "~3.1.2",
+ "braces": "~3.0.2",
+ "glob-parent": "~5.1.2",
+ "is-binary-path": "~2.1.0",
+ "is-glob": "~4.0.1",
+ "normalize-path": "~3.0.0",
+ "readdirp": "~3.6.0"
+ },
+ "engines": {
+ "node": ">= 8.10.0"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.2"
+ }
+ },
+ "node_modules/chokidar/node_modules/glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "dev": true,
+ "dependencies": {
+ "is-glob": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/cliui": {
+ "version": "7.0.4",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz",
+ "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==",
+ "dev": true,
+ "dependencies": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.0",
+ "wrap-ansi": "^7.0.0"
+ }
+ },
+ "node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
+ },
+ "node_modules/concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
+ },
+ "node_modules/cross-spawn": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
+ "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+ "dependencies": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/debug": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+ "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+ "dependencies": {
+ "ms": "2.1.2"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/decamelize": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz",
+ "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/deep-is": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
+ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="
+ },
+ "node_modules/define-data-property": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz",
+ "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==",
+ "peer": true,
+ "dependencies": {
+ "get-intrinsic": "^1.2.1",
+ "gopd": "^1.0.1",
+ "has-property-descriptors": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/define-properties": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz",
+ "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==",
+ "peer": true,
+ "dependencies": {
+ "define-data-property": "^1.0.1",
+ "has-property-descriptors": "^1.0.0",
+ "object-keys": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/diff": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz",
+ "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.3.1"
+ }
+ },
+ "node_modules/doctrine": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
+ "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
+ "dependencies": {
+ "esutils": "^2.0.2"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/dom-serializer": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz",
+ "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==",
+ "dependencies": {
+ "domelementtype": "^2.3.0",
+ "domhandler": "^5.0.2",
+ "entities": "^4.2.0"
+ },
+ "funding": {
+ "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
+ }
+ },
+ "node_modules/domelementtype": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
+ "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/fb55"
+ }
+ ]
+ },
+ "node_modules/domhandler": {
+ "version": "5.0.3",
+ "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz",
+ "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
+ "dependencies": {
+ "domelementtype": "^2.3.0"
+ },
+ "engines": {
+ "node": ">= 4"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/domhandler?sponsor=1"
+ }
+ },
+ "node_modules/domutils": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz",
+ "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==",
+ "dependencies": {
+ "dom-serializer": "^2.0.0",
+ "domelementtype": "^2.3.0",
+ "domhandler": "^5.0.3"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/domutils?sponsor=1"
+ }
+ },
+ "node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "dev": true
+ },
+ "node_modules/entities": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
+ "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
+ "engines": {
+ "node": ">=0.12"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/entities?sponsor=1"
+ }
+ },
+ "node_modules/es-abstract": {
+ "version": "1.22.3",
+ "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.3.tgz",
+ "integrity": "sha512-eiiY8HQeYfYH2Con2berK+To6GrK2RxbPawDkGq4UiCQQfZHb6wX9qQqkbpPqaxQFcl8d9QzZqo0tGE0VcrdwA==",
+ "peer": true,
+ "dependencies": {
+ "array-buffer-byte-length": "^1.0.0",
+ "arraybuffer.prototype.slice": "^1.0.2",
+ "available-typed-arrays": "^1.0.5",
+ "call-bind": "^1.0.5",
+ "es-set-tostringtag": "^2.0.1",
+ "es-to-primitive": "^1.2.1",
+ "function.prototype.name": "^1.1.6",
+ "get-intrinsic": "^1.2.2",
+ "get-symbol-description": "^1.0.0",
+ "globalthis": "^1.0.3",
+ "gopd": "^1.0.1",
+ "has-property-descriptors": "^1.0.0",
+ "has-proto": "^1.0.1",
+ "has-symbols": "^1.0.3",
+ "hasown": "^2.0.0",
+ "internal-slot": "^1.0.5",
+ "is-array-buffer": "^3.0.2",
+ "is-callable": "^1.2.7",
+ "is-negative-zero": "^2.0.2",
+ "is-regex": "^1.1.4",
+ "is-shared-array-buffer": "^1.0.2",
+ "is-string": "^1.0.7",
+ "is-typed-array": "^1.1.12",
+ "is-weakref": "^1.0.2",
+ "object-inspect": "^1.13.1",
+ "object-keys": "^1.1.1",
+ "object.assign": "^4.1.4",
+ "regexp.prototype.flags": "^1.5.1",
+ "safe-array-concat": "^1.0.1",
+ "safe-regex-test": "^1.0.0",
+ "string.prototype.trim": "^1.2.8",
+ "string.prototype.trimend": "^1.0.7",
+ "string.prototype.trimstart": "^1.0.7",
+ "typed-array-buffer": "^1.0.0",
+ "typed-array-byte-length": "^1.0.0",
+ "typed-array-byte-offset": "^1.0.0",
+ "typed-array-length": "^1.0.4",
+ "unbox-primitive": "^1.0.2",
+ "which-typed-array": "^1.1.13"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/es-set-tostringtag": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.2.tgz",
+ "integrity": "sha512-BuDyupZt65P9D2D2vA/zqcI3G5xRsklm5N3xCwuiy+/vKy8i0ifdsQP1sLgO4tZDSCaQUSnmC48khknGMV3D2Q==",
+ "peer": true,
+ "dependencies": {
+ "get-intrinsic": "^1.2.2",
+ "has-tostringtag": "^1.0.0",
+ "hasown": "^2.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-shim-unscopables": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz",
+ "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==",
+ "peer": true,
+ "dependencies": {
+ "hasown": "^2.0.0"
+ }
+ },
+ "node_modules/es-to-primitive": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
+ "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==",
+ "peer": true,
+ "dependencies": {
+ "is-callable": "^1.1.4",
+ "is-date-object": "^1.0.1",
+ "is-symbol": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/escalade": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
+ "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/eslint": {
+ "version": "8.56.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.56.0.tgz",
+ "integrity": "sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==",
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.2.0",
+ "@eslint-community/regexpp": "^4.6.1",
+ "@eslint/eslintrc": "^2.1.4",
+ "@eslint/js": "8.56.0",
+ "@humanwhocodes/config-array": "^0.11.13",
+ "@humanwhocodes/module-importer": "^1.0.1",
+ "@nodelib/fs.walk": "^1.2.8",
+ "@ungap/structured-clone": "^1.2.0",
+ "ajv": "^6.12.4",
+ "chalk": "^4.0.0",
+ "cross-spawn": "^7.0.2",
+ "debug": "^4.3.2",
+ "doctrine": "^3.0.0",
+ "escape-string-regexp": "^4.0.0",
+ "eslint-scope": "^7.2.2",
+ "eslint-visitor-keys": "^3.4.3",
+ "espree": "^9.6.1",
+ "esquery": "^1.4.2",
+ "esutils": "^2.0.2",
+ "fast-deep-equal": "^3.1.3",
+ "file-entry-cache": "^6.0.1",
+ "find-up": "^5.0.0",
+ "glob-parent": "^6.0.2",
+ "globals": "^13.19.0",
+ "graphemer": "^1.4.0",
+ "ignore": "^5.2.0",
+ "imurmurhash": "^0.1.4",
+ "is-glob": "^4.0.0",
+ "is-path-inside": "^3.0.3",
+ "js-yaml": "^4.1.0",
+ "json-stable-stringify-without-jsonify": "^1.0.1",
+ "levn": "^0.4.1",
+ "lodash.merge": "^4.6.2",
+ "minimatch": "^3.1.2",
+ "natural-compare": "^1.4.0",
+ "optionator": "^0.9.3",
+ "strip-ansi": "^6.0.1",
+ "text-table": "^0.2.0"
+ },
+ "bin": {
+ "eslint": "bin/eslint.js"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint-config-prettier": {
+ "version": "9.1.0",
+ "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz",
+ "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==",
+ "peer": true,
+ "bin": {
+ "eslint-config-prettier": "bin/cli.js"
+ },
+ "peerDependencies": {
+ "eslint": ">=7.0.0"
+ }
+ },
+ "node_modules/eslint-plugin-es": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-3.0.1.tgz",
+ "integrity": "sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ==",
+ "peer": true,
+ "dependencies": {
+ "eslint-utils": "^2.0.0",
+ "regexpp": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8.10.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/mysticatea"
+ },
+ "peerDependencies": {
+ "eslint": ">=4.19.1"
+ }
+ },
+ "node_modules/eslint-plugin-fetch-options": {
+ "version": "0.0.5",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-fetch-options/-/eslint-plugin-fetch-options-0.0.5.tgz",
+ "integrity": "sha512-ZMxrccsOAZ7uMQ4nMvPJLqLg6oyLF96YOEwTKWAIbDHpwWUp1raXALZom8ikKucaEnhqWSRuBWI8jBXveFwkJg==",
+ "peer": true,
+ "engines": {
+ "node": ">=0.9.0"
+ }
+ },
+ "node_modules/eslint-plugin-html": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-html/-/eslint-plugin-html-7.1.0.tgz",
+ "integrity": "sha512-fNLRraV/e6j8e3XYOC9xgND4j+U7b1Rq+OygMlLcMg+wI/IpVbF+ubQa3R78EjKB9njT6TQOlcK5rFKBVVtdfg==",
+ "peer": true,
+ "dependencies": {
+ "htmlparser2": "^8.0.1"
+ }
+ },
+ "node_modules/eslint-plugin-json": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-json/-/eslint-plugin-json-3.1.0.tgz",
+ "integrity": "sha512-MrlG2ynFEHe7wDGwbUuFPsaT2b1uhuEFhJ+W1f1u+1C2EkXmTYJp4B1aAdQQ8M+CC3t//N/oRKiIVw14L2HR1g==",
+ "peer": true,
+ "dependencies": {
+ "lodash": "^4.17.21",
+ "vscode-json-languageservice": "^4.1.6"
+ },
+ "engines": {
+ "node": ">=12.0"
+ }
+ },
+ "node_modules/eslint-plugin-no-unsanitized": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-no-unsanitized/-/eslint-plugin-no-unsanitized-4.0.2.tgz",
+ "integrity": "sha512-Pry0S9YmHoz8NCEMRQh7N0Yexh2MYCNPIlrV52hTmS7qXnTghWsjXouF08bgsrrZqaW9tt1ZiK3j5NEmPE+EjQ==",
+ "peer": true,
+ "peerDependencies": {
+ "eslint": "^6 || ^7 || ^8"
+ }
+ },
+ "node_modules/eslint-plugin-node": {
+ "version": "11.1.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-11.1.0.tgz",
+ "integrity": "sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g==",
+ "peer": true,
+ "dependencies": {
+ "eslint-plugin-es": "^3.0.0",
+ "eslint-utils": "^2.0.0",
+ "ignore": "^5.1.1",
+ "minimatch": "^3.0.4",
+ "resolve": "^1.10.1",
+ "semver": "^6.1.0"
+ },
+ "engines": {
+ "node": ">=8.10.0"
+ },
+ "peerDependencies": {
+ "eslint": ">=5.16.0"
+ }
+ },
+ "node_modules/eslint-plugin-react": {
+ "version": "7.33.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.33.0.tgz",
+ "integrity": "sha512-qewL/8P34WkY8jAqdQxsiL82pDUeT7nhs8IsuXgfgnsEloKCT4miAV9N9kGtx7/KM9NH/NCGUE7Edt9iGxLXFw==",
+ "peer": true,
+ "dependencies": {
+ "array-includes": "^3.1.6",
+ "array.prototype.flatmap": "^1.3.1",
+ "array.prototype.tosorted": "^1.1.1",
+ "doctrine": "^2.1.0",
+ "estraverse": "^5.3.0",
+ "jsx-ast-utils": "^2.4.1 || ^3.0.0",
+ "minimatch": "^3.1.2",
+ "object.entries": "^1.1.6",
+ "object.fromentries": "^2.0.6",
+ "object.hasown": "^1.1.2",
+ "object.values": "^1.1.6",
+ "prop-types": "^15.8.1",
+ "resolve": "^2.0.0-next.4",
+ "semver": "^6.3.1",
+ "string.prototype.matchall": "^4.0.8"
+ },
+ "engines": {
+ "node": ">=4"
+ },
+ "peerDependencies": {
+ "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8"
+ }
+ },
+ "node_modules/eslint-plugin-react/node_modules/doctrine": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
+ "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
+ "peer": true,
+ "dependencies": {
+ "esutils": "^2.0.2"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/eslint-plugin-react/node_modules/resolve": {
+ "version": "2.0.0-next.5",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz",
+ "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==",
+ "peer": true,
+ "dependencies": {
+ "is-core-module": "^2.13.0",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ },
+ "bin": {
+ "resolve": "bin/resolve"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/eslint-plugin-security": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-security/-/eslint-plugin-security-1.4.0.tgz",
+ "integrity": "sha512-xlS7P2PLMXeqfhyf3NpqbvbnW04kN8M9NtmhpR3XGyOvt/vNKS7XPXT5EDbwKW9vCjWH4PpfQvgD/+JgN0VJKA==",
+ "peer": true,
+ "dependencies": {
+ "safe-regex": "^1.1.0"
+ }
+ },
+ "node_modules/eslint-scope": {
+ "version": "7.2.2",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz",
+ "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==",
+ "dependencies": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint-utils": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz",
+ "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==",
+ "peer": true,
+ "dependencies": {
+ "eslint-visitor-keys": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/mysticatea"
+ }
+ },
+ "node_modules/eslint-utils/node_modules/eslint-visitor-keys": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz",
+ "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==",
+ "peer": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/eslint-visitor-keys": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
+ "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/espree": {
+ "version": "9.6.1",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz",
+ "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==",
+ "dependencies": {
+ "acorn": "^8.9.0",
+ "acorn-jsx": "^5.3.2",
+ "eslint-visitor-keys": "^3.4.1"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/esquery": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz",
+ "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==",
+ "dependencies": {
+ "estraverse": "^5.1.0"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/esrecurse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
+ "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
+ "dependencies": {
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/esutils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/fast-deep-equal": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
+ },
+ "node_modules/fast-json-stable-stringify": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="
+ },
+ "node_modules/fast-levenshtein": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw=="
+ },
+ "node_modules/fastq": {
+ "version": "1.17.0",
+ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.0.tgz",
+ "integrity": "sha512-zGygtijUMT7jnk3h26kUms3BkSDp4IfIKjmnqI2tvx6nuBfiF1UqOxbnLfzdv+apBy+53oaImsKtMw/xYbW+1w==",
+ "dependencies": {
+ "reusify": "^1.0.4"
+ }
+ },
+ "node_modules/file-entry-cache": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
+ "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
+ "dependencies": {
+ "flat-cache": "^3.0.4"
+ },
+ "engines": {
+ "node": "^10.12.0 || >=12.0.0"
+ }
+ },
+ "node_modules/fill-range": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
+ "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+ "dev": true,
+ "dependencies": {
+ "to-regex-range": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/find-up": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
+ "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
+ "dependencies": {
+ "locate-path": "^6.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/flat": {
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz",
+ "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==",
+ "dev": true,
+ "bin": {
+ "flat": "cli.js"
+ }
+ },
+ "node_modules/flat-cache": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz",
+ "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==",
+ "dependencies": {
+ "flatted": "^3.2.9",
+ "keyv": "^4.5.3",
+ "rimraf": "^3.0.2"
+ },
+ "engines": {
+ "node": "^10.12.0 || >=12.0.0"
+ }
+ },
+ "node_modules/flatted": {
+ "version": "3.2.9",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz",
+ "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ=="
+ },
+ "node_modules/for-each": {
+ "version": "0.3.3",
+ "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz",
+ "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==",
+ "peer": true,
+ "dependencies": {
+ "is-callable": "^1.1.3"
+ }
+ },
+ "node_modules/fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
+ },
+ "node_modules/fsevents": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+ "dev": true,
+ "hasInstallScript": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
+ "node_modules/function-bind": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
+ "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
+ "peer": true,
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/function.prototype.name": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz",
+ "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==",
+ "peer": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.2.0",
+ "es-abstract": "^1.22.1",
+ "functions-have-names": "^1.2.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/functions-have-names": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz",
+ "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==",
+ "peer": true,
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/get-caller-file": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
+ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
+ "dev": true,
+ "engines": {
+ "node": "6.* || 8.* || >= 10.*"
+ }
+ },
+ "node_modules/get-intrinsic": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz",
+ "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==",
+ "peer": true,
+ "dependencies": {
+ "function-bind": "^1.1.2",
+ "has-proto": "^1.0.1",
+ "has-symbols": "^1.0.3",
+ "hasown": "^2.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/get-symbol-description": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz",
+ "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==",
+ "peer": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "get-intrinsic": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/glob": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz",
+ "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==",
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ },
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/glob-parent": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
+ "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
+ "dependencies": {
+ "is-glob": "^4.0.3"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/globals": {
+ "version": "13.24.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz",
+ "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==",
+ "dependencies": {
+ "type-fest": "^0.20.2"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/globalthis": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz",
+ "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==",
+ "peer": true,
+ "dependencies": {
+ "define-properties": "^1.1.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/gopd": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
+ "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
+ "peer": true,
+ "dependencies": {
+ "get-intrinsic": "^1.1.3"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/graphemer": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
+ "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag=="
+ },
+ "node_modules/has-bigints": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz",
+ "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==",
+ "peer": true,
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/has-property-descriptors": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz",
+ "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==",
+ "peer": true,
+ "dependencies": {
+ "get-intrinsic": "^1.2.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-proto": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz",
+ "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==",
+ "peer": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-symbols": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
+ "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
+ "peer": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-tostringtag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz",
+ "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==",
+ "peer": true,
+ "dependencies": {
+ "has-symbols": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/hasown": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz",
+ "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==",
+ "peer": true,
+ "dependencies": {
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/he": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
+ "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
+ "dev": true,
+ "bin": {
+ "he": "bin/he"
+ }
+ },
+ "node_modules/htmlparser2": {
+ "version": "8.0.2",
+ "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz",
+ "integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==",
+ "funding": [
+ "https://github.com/fb55/htmlparser2?sponsor=1",
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/fb55"
+ }
+ ],
+ "dependencies": {
+ "domelementtype": "^2.3.0",
+ "domhandler": "^5.0.3",
+ "domutils": "^3.0.1",
+ "entities": "^4.4.0"
+ }
+ },
+ "node_modules/ignore": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz",
+ "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==",
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/import-fresh": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
+ "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
+ "dependencies": {
+ "parent-module": "^1.0.0",
+ "resolve-from": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
+ "engines": {
+ "node": ">=0.8.19"
+ }
+ },
+ "node_modules/inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
+ "dependencies": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "node_modules/inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
+ },
+ "node_modules/internal-slot": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.6.tgz",
+ "integrity": "sha512-Xj6dv+PsbtwyPpEflsejS+oIZxmMlV44zAhG479uYu89MsjcYOhCFnNyKrkJrihbsiasQyY0afoCl/9BLR65bg==",
+ "peer": true,
+ "dependencies": {
+ "get-intrinsic": "^1.2.2",
+ "hasown": "^2.0.0",
+ "side-channel": "^1.0.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/is-array-buffer": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz",
+ "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==",
+ "peer": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "get-intrinsic": "^1.2.0",
+ "is-typed-array": "^1.1.10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-bigint": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz",
+ "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==",
+ "peer": true,
+ "dependencies": {
+ "has-bigints": "^1.0.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-binary-path": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
+ "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
+ "dev": true,
+ "dependencies": {
+ "binary-extensions": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-boolean-object": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz",
+ "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==",
+ "peer": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-callable": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
+ "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==",
+ "peer": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-core-module": {
+ "version": "2.13.1",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz",
+ "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==",
+ "peer": true,
+ "dependencies": {
+ "hasown": "^2.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-date-object": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz",
+ "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==",
+ "peer": true,
+ "dependencies": {
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-glob": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+ "dependencies": {
+ "is-extglob": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-negative-zero": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz",
+ "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==",
+ "peer": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.12.0"
+ }
+ },
+ "node_modules/is-number-object": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz",
+ "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==",
+ "peer": true,
+ "dependencies": {
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-path-inside": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
+ "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-plain-obj": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz",
+ "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-regex": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz",
+ "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==",
+ "peer": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-shared-array-buffer": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz",
+ "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==",
+ "peer": true,
+ "dependencies": {
+ "call-bind": "^1.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-string": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz",
+ "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==",
+ "peer": true,
+ "dependencies": {
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-symbol": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz",
+ "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==",
+ "peer": true,
+ "dependencies": {
+ "has-symbols": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-typed-array": {
+ "version": "1.1.12",
+ "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz",
+ "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==",
+ "peer": true,
+ "dependencies": {
+ "which-typed-array": "^1.1.11"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-unicode-supported": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz",
+ "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/is-weakref": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz",
+ "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==",
+ "peer": true,
+ "dependencies": {
+ "call-bind": "^1.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/isarray": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
+ "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==",
+ "peer": true
+ },
+ "node_modules/isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="
+ },
+ "node_modules/js-tokens": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+ "peer": true
+ },
+ "node_modules/js-yaml": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
+ "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+ "dependencies": {
+ "argparse": "^2.0.1"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/json-buffer": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
+ "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ=="
+ },
+ "node_modules/json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="
+ },
+ "node_modules/json-stable-stringify-without-jsonify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
+ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw=="
+ },
+ "node_modules/jsonc-parser": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.1.tgz",
+ "integrity": "sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==",
+ "peer": true
+ },
+ "node_modules/jsx-ast-utils": {
+ "version": "3.3.5",
+ "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz",
+ "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==",
+ "peer": true,
+ "dependencies": {
+ "array-includes": "^3.1.6",
+ "array.prototype.flat": "^1.3.1",
+ "object.assign": "^4.1.4",
+ "object.values": "^1.1.6"
+ },
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/keyv": {
+ "version": "4.5.4",
+ "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
+ "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
+ "dependencies": {
+ "json-buffer": "3.0.1"
+ }
+ },
+ "node_modules/levn": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
+ "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
+ "dependencies": {
+ "prelude-ls": "^1.2.1",
+ "type-check": "~0.4.0"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/locate-path": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
+ "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
+ "dependencies": {
+ "p-locate": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/lodash": {
+ "version": "4.17.21",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
+ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
+ "peer": true
+ },
+ "node_modules/lodash.merge": {
+ "version": "4.6.2",
+ "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
+ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="
+ },
+ "node_modules/log-symbols": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz",
+ "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==",
+ "dev": true,
+ "dependencies": {
+ "chalk": "^4.1.0",
+ "is-unicode-supported": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/loose-envify": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
+ "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
+ "peer": true,
+ "dependencies": {
+ "js-tokens": "^3.0.0 || ^4.0.0"
+ },
+ "bin": {
+ "loose-envify": "cli.js"
+ }
+ },
+ "node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/mocha": {
+ "version": "10.2.0",
+ "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.2.0.tgz",
+ "integrity": "sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg==",
+ "dev": true,
+ "dependencies": {
+ "ansi-colors": "4.1.1",
+ "browser-stdout": "1.3.1",
+ "chokidar": "3.5.3",
+ "debug": "4.3.4",
+ "diff": "5.0.0",
+ "escape-string-regexp": "4.0.0",
+ "find-up": "5.0.0",
+ "glob": "7.2.0",
+ "he": "1.2.0",
+ "js-yaml": "4.1.0",
+ "log-symbols": "4.1.0",
+ "minimatch": "5.0.1",
+ "ms": "2.1.3",
+ "nanoid": "3.3.3",
+ "serialize-javascript": "6.0.0",
+ "strip-json-comments": "3.1.1",
+ "supports-color": "8.1.1",
+ "workerpool": "6.2.1",
+ "yargs": "16.2.0",
+ "yargs-parser": "20.2.4",
+ "yargs-unparser": "2.0.0"
+ },
+ "bin": {
+ "_mocha": "bin/_mocha",
+ "mocha": "bin/mocha.js"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/mochajs"
+ }
+ },
+ "node_modules/mocha/node_modules/brace-expansion": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "dev": true,
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/mocha/node_modules/minimatch": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz",
+ "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/mocha/node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "dev": true
+ },
+ "node_modules/mocha/node_modules/supports-color": {
+ "version": "8.1.1",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
+ "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
+ "dev": true,
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/supports-color?sponsor=1"
+ }
+ },
+ "node_modules/ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
+ },
+ "node_modules/nanoid": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz",
+ "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==",
+ "dev": true,
+ "bin": {
+ "nanoid": "bin/nanoid.cjs"
+ },
+ "engines": {
+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+ }
+ },
+ "node_modules/natural-compare": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="
+ },
+ "node_modules/normalize-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/object-assign": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+ "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
+ "peer": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/object-inspect": {
+ "version": "1.13.1",
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz",
+ "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==",
+ "peer": true,
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/object-keys": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
+ "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
+ "peer": true,
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/object.assign": {
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz",
+ "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==",
+ "peer": true,
+ "dependencies": {
+ "call-bind": "^1.0.5",
+ "define-properties": "^1.2.1",
+ "has-symbols": "^1.0.3",
+ "object-keys": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/object.entries": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.7.tgz",
+ "integrity": "sha512-jCBs/0plmPsOnrKAfFQXRG2NFjlhZgjjcBLSmTnEhU8U6vVTsVe8ANeQJCHTl3gSsI4J+0emOoCgoKlmQPMgmA==",
+ "peer": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.2.0",
+ "es-abstract": "^1.22.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/object.fromentries": {
+ "version": "2.0.7",
+ "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.7.tgz",
+ "integrity": "sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA==",
+ "peer": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.2.0",
+ "es-abstract": "^1.22.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/object.hasown": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.3.tgz",
+ "integrity": "sha512-fFI4VcYpRHvSLXxP7yiZOMAd331cPfd2p7PFDVbgUsYOfCT3tICVqXWngbjr4m49OvsBwUBQ6O2uQoJvy3RexA==",
+ "peer": true,
+ "dependencies": {
+ "define-properties": "^1.2.0",
+ "es-abstract": "^1.22.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/object.values": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.7.tgz",
+ "integrity": "sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng==",
+ "peer": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.2.0",
+ "es-abstract": "^1.22.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+ "dependencies": {
+ "wrappy": "1"
+ }
+ },
+ "node_modules/optionator": {
+ "version": "0.9.3",
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz",
+ "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==",
+ "dependencies": {
+ "@aashutoshrathi/word-wrap": "^1.2.3",
+ "deep-is": "^0.1.3",
+ "fast-levenshtein": "^2.0.6",
+ "levn": "^0.4.1",
+ "prelude-ls": "^1.2.1",
+ "type-check": "^0.4.0"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/p-limit": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
+ "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
+ "dependencies": {
+ "yocto-queue": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-locate": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
+ "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
+ "dependencies": {
+ "p-limit": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/parent-module": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
+ "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
+ "dependencies": {
+ "callsites": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/path-exists": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+ "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-parse": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
+ "peer": true
+ },
+ "node_modules/picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "dev": true,
+ "engines": {
+ "node": ">=8.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/prelude-ls": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
+ "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/prop-types": {
+ "version": "15.8.1",
+ "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
+ "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
+ "peer": true,
+ "dependencies": {
+ "loose-envify": "^1.4.0",
+ "object-assign": "^4.1.1",
+ "react-is": "^16.13.1"
+ }
+ },
+ "node_modules/punycode": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
+ "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/queue-microtask": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
+ "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/randombytes": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
+ "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
+ "dev": true,
+ "dependencies": {
+ "safe-buffer": "^5.1.0"
+ }
+ },
+ "node_modules/react-is": {
+ "version": "16.13.1",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
+ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
+ "peer": true
+ },
+ "node_modules/readdirp": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
+ "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
+ "dev": true,
+ "dependencies": {
+ "picomatch": "^2.2.1"
+ },
+ "engines": {
+ "node": ">=8.10.0"
+ }
+ },
+ "node_modules/regexp.prototype.flags": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz",
+ "integrity": "sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==",
+ "peer": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.2.0",
+ "set-function-name": "^2.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/regexpp": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz",
+ "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==",
+ "peer": true,
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/mysticatea"
+ }
+ },
+ "node_modules/require-directory": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
+ "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/resolve": {
+ "version": "1.22.8",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz",
+ "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==",
+ "peer": true,
+ "dependencies": {
+ "is-core-module": "^2.13.0",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ },
+ "bin": {
+ "resolve": "bin/resolve"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/resolve-from": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/ret": {
+ "version": "0.1.15",
+ "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz",
+ "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==",
+ "peer": true,
+ "engines": {
+ "node": ">=0.12"
+ }
+ },
+ "node_modules/reusify": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
+ "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
+ "engines": {
+ "iojs": ">=1.0.0",
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/rimraf": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
+ "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+ "dependencies": {
+ "glob": "^7.1.3"
+ },
+ "bin": {
+ "rimraf": "bin.js"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/run-parallel": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
+ "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "dependencies": {
+ "queue-microtask": "^1.2.2"
+ }
+ },
+ "node_modules/safe-array-concat": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.0.tgz",
+ "integrity": "sha512-ZdQ0Jeb9Ofti4hbt5lX3T2JcAamT9hfzYU1MNB+z/jaEbB6wfFfPIR/zEORmZqobkCCJhSjodobH6WHNmJ97dg==",
+ "peer": true,
+ "dependencies": {
+ "call-bind": "^1.0.5",
+ "get-intrinsic": "^1.2.2",
+ "has-symbols": "^1.0.3",
+ "isarray": "^2.0.5"
+ },
+ "engines": {
+ "node": ">=0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/safe-buffer": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/safe-regex": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz",
+ "integrity": "sha512-aJXcif4xnaNUzvUuC5gcb46oTS7zvg4jpMTnuqtrEPlR3vFr4pxtdTwaF1Qs3Enjn9HK+ZlwQui+a7z0SywIzg==",
+ "peer": true,
+ "dependencies": {
+ "ret": "~0.1.10"
+ }
+ },
+ "node_modules/safe-regex-test": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.2.tgz",
+ "integrity": "sha512-83S9w6eFq12BBIJYvjMux6/dkirb8+4zJRA9cxNBVb7Wq5fJBW+Xze48WqR8pxua7bDuAaaAxtVVd4Idjp1dBQ==",
+ "peer": true,
+ "dependencies": {
+ "call-bind": "^1.0.5",
+ "get-intrinsic": "^1.2.2",
+ "is-regex": "^1.1.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "peer": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/serialize-javascript": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz",
+ "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==",
+ "dev": true,
+ "dependencies": {
+ "randombytes": "^2.1.0"
+ }
+ },
+ "node_modules/set-function-length": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.0.tgz",
+ "integrity": "sha512-4DBHDoyHlM1IRPGYcoxexgh67y4ueR53FKV1yyxwFMY7aCqcN/38M1+SwZ/qJQ8iLv7+ck385ot4CcisOAPT9w==",
+ "peer": true,
+ "dependencies": {
+ "define-data-property": "^1.1.1",
+ "function-bind": "^1.1.2",
+ "get-intrinsic": "^1.2.2",
+ "gopd": "^1.0.1",
+ "has-property-descriptors": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/set-function-name": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.1.tgz",
+ "integrity": "sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==",
+ "peer": true,
+ "dependencies": {
+ "define-data-property": "^1.0.1",
+ "functions-have-names": "^1.2.3",
+ "has-property-descriptors": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "dependencies": {
+ "shebang-regex": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/side-channel": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
+ "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
+ "peer": true,
+ "dependencies": {
+ "call-bind": "^1.0.0",
+ "get-intrinsic": "^1.0.2",
+ "object-inspect": "^1.9.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/string.prototype.matchall": {
+ "version": "4.0.10",
+ "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.10.tgz",
+ "integrity": "sha512-rGXbGmOEosIQi6Qva94HUjgPs9vKW+dkG7Y8Q5O2OYkWL6wFaTRZO8zM4mhP94uX55wgyrXzfS2aGtGzUL7EJQ==",
+ "peer": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.2.0",
+ "es-abstract": "^1.22.1",
+ "get-intrinsic": "^1.2.1",
+ "has-symbols": "^1.0.3",
+ "internal-slot": "^1.0.5",
+ "regexp.prototype.flags": "^1.5.0",
+ "set-function-name": "^2.0.0",
+ "side-channel": "^1.0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/string.prototype.trim": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz",
+ "integrity": "sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==",
+ "peer": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.2.0",
+ "es-abstract": "^1.22.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/string.prototype.trimend": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz",
+ "integrity": "sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==",
+ "peer": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.2.0",
+ "es-abstract": "^1.22.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/string.prototype.trimstart": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz",
+ "integrity": "sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==",
+ "peer": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.2.0",
+ "es-abstract": "^1.22.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-json-comments": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
+ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/supports-preserve-symlinks-flag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
+ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
+ "peer": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/text-table": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
+ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw=="
+ },
+ "node_modules/to-regex-range": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "dev": true,
+ "dependencies": {
+ "is-number": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=8.0"
+ }
+ },
+ "node_modules/toml-eslint-parser": {
+ "version": "0.9.3",
+ "resolved": "https://registry.npmjs.org/toml-eslint-parser/-/toml-eslint-parser-0.9.3.tgz",
+ "integrity": "sha512-moYoCvkNUAPCxSW9jmHmRElhm4tVJpHL8ItC/+uYD0EpPSFXbck7yREz9tNdJVTSpHVod8+HoipcpbQ0oE6gsw==",
+ "dependencies": {
+ "eslint-visitor-keys": "^3.0.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ota-meshi"
+ }
+ },
+ "node_modules/type-check": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
+ "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
+ "dependencies": {
+ "prelude-ls": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/type-fest": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
+ "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/typed-array-buffer": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz",
+ "integrity": "sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==",
+ "peer": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "get-intrinsic": "^1.2.1",
+ "is-typed-array": "^1.1.10"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/typed-array-byte-length": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz",
+ "integrity": "sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==",
+ "peer": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "for-each": "^0.3.3",
+ "has-proto": "^1.0.1",
+ "is-typed-array": "^1.1.10"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/typed-array-byte-offset": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz",
+ "integrity": "sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==",
+ "peer": true,
+ "dependencies": {
+ "available-typed-arrays": "^1.0.5",
+ "call-bind": "^1.0.2",
+ "for-each": "^0.3.3",
+ "has-proto": "^1.0.1",
+ "is-typed-array": "^1.1.10"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/typed-array-length": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz",
+ "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==",
+ "peer": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "for-each": "^0.3.3",
+ "is-typed-array": "^1.1.9"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/unbox-primitive": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz",
+ "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==",
+ "peer": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "has-bigints": "^1.0.2",
+ "has-symbols": "^1.0.3",
+ "which-boxed-primitive": "^1.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/uri-js": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+ "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+ "dependencies": {
+ "punycode": "^2.1.0"
+ }
+ },
+ "node_modules/vscode-json-languageservice": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/vscode-json-languageservice/-/vscode-json-languageservice-4.2.1.tgz",
+ "integrity": "sha512-xGmv9QIWs2H8obGbWg+sIPI/3/pFgj/5OWBhNzs00BkYQ9UaB2F6JJaGB/2/YOZJ3BvLXQTC4Q7muqU25QgAhA==",
+ "peer": true,
+ "dependencies": {
+ "jsonc-parser": "^3.0.0",
+ "vscode-languageserver-textdocument": "^1.0.3",
+ "vscode-languageserver-types": "^3.16.0",
+ "vscode-nls": "^5.0.0",
+ "vscode-uri": "^3.0.3"
+ }
+ },
+ "node_modules/vscode-languageserver-textdocument": {
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.11.tgz",
+ "integrity": "sha512-X+8T3GoiwTVlJbicx/sIAF+yuJAqz8VvwJyoMVhwEMoEKE/fkDmrqUgDMyBECcM2A2frVZIUj5HI/ErRXCfOeA==",
+ "peer": true
+ },
+ "node_modules/vscode-languageserver-types": {
+ "version": "3.17.5",
+ "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz",
+ "integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==",
+ "peer": true
+ },
+ "node_modules/vscode-nls": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/vscode-nls/-/vscode-nls-5.2.0.tgz",
+ "integrity": "sha512-RAaHx7B14ZU04EU31pT+rKz2/zSl7xMsfIZuo8pd+KZO6PXtQmpevpq3vxvWNcrGbdmhM/rr5Uw5Mz+NBfhVng==",
+ "peer": true
+ },
+ "node_modules/vscode-uri": {
+ "version": "3.0.8",
+ "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.8.tgz",
+ "integrity": "sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==",
+ "peer": true
+ },
+ "node_modules/which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "node-which": "bin/node-which"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/which-boxed-primitive": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz",
+ "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==",
+ "peer": true,
+ "dependencies": {
+ "is-bigint": "^1.0.1",
+ "is-boolean-object": "^1.1.0",
+ "is-number-object": "^1.0.4",
+ "is-string": "^1.0.5",
+ "is-symbol": "^1.0.3"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/which-typed-array": {
+ "version": "1.1.13",
+ "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.13.tgz",
+ "integrity": "sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow==",
+ "peer": true,
+ "dependencies": {
+ "available-typed-arrays": "^1.0.5",
+ "call-bind": "^1.0.4",
+ "for-each": "^0.3.3",
+ "gopd": "^1.0.1",
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/workerpool": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz",
+ "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==",
+ "dev": true
+ },
+ "node_modules/wrap-ansi": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
+ },
+ "node_modules/y18n": {
+ "version": "5.0.8",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
+ "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/yargs": {
+ "version": "16.2.0",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz",
+ "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==",
+ "dev": true,
+ "dependencies": {
+ "cliui": "^7.0.2",
+ "escalade": "^3.1.1",
+ "get-caller-file": "^2.0.5",
+ "require-directory": "^2.1.1",
+ "string-width": "^4.2.0",
+ "y18n": "^5.0.5",
+ "yargs-parser": "^20.2.2"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/yargs-parser": {
+ "version": "20.2.4",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz",
+ "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/yargs-unparser": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz",
+ "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==",
+ "dev": true,
+ "dependencies": {
+ "camelcase": "^6.0.0",
+ "decamelize": "^4.0.0",
+ "flat": "^5.0.2",
+ "is-plain-obj": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/yocto-queue": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
+ "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ }
+ },
+ "dependencies": {
+ "@aashutoshrathi/word-wrap": {
+ "version": "1.2.6",
+ "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz",
+ "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA=="
+ },
+ "@eslint-community/eslint-utils": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz",
+ "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==",
+ "requires": {
+ "eslint-visitor-keys": "^3.3.0"
+ }
+ },
+ "@eslint-community/regexpp": {
+ "version": "4.10.0",
+ "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz",
+ "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA=="
+ },
+ "@eslint/eslintrc": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz",
+ "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==",
+ "requires": {
+ "ajv": "^6.12.4",
+ "debug": "^4.3.2",
+ "espree": "^9.6.0",
+ "globals": "^13.19.0",
+ "ignore": "^5.2.0",
+ "import-fresh": "^3.2.1",
+ "js-yaml": "^4.1.0",
+ "minimatch": "^3.1.2",
+ "strip-json-comments": "^3.1.1"
+ }
+ },
+ "@eslint/js": {
+ "version": "8.56.0",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.56.0.tgz",
+ "integrity": "sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A=="
+ },
+ "@humanwhocodes/config-array": {
+ "version": "0.11.14",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz",
+ "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==",
+ "requires": {
+ "@humanwhocodes/object-schema": "^2.0.2",
+ "debug": "^4.3.1",
+ "minimatch": "^3.0.5"
+ }
+ },
+ "@humanwhocodes/module-importer": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
+ "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA=="
+ },
+ "@humanwhocodes/object-schema": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz",
+ "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw=="
+ },
+ "@microsoft/eslint-plugin-sdl": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/@microsoft/eslint-plugin-sdl/-/eslint-plugin-sdl-0.2.2.tgz",
+ "integrity": "sha512-TiBepeQMSxHpvIbKA03TbO9nZqRrKR1th47wGdjY1sH2SSer+JgKlSF3S8GURGA8/zp2T/HwSiAJelclJ3hEvg==",
+ "peer": true,
+ "requires": {
+ "eslint-plugin-node": "11.1.0",
+ "eslint-plugin-react": "7.33.0",
+ "eslint-plugin-security": "1.4.0"
+ }
+ },
+ "@nodelib/fs.scandir": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
+ "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
+ "requires": {
+ "@nodelib/fs.stat": "2.0.5",
+ "run-parallel": "^1.1.9"
+ }
+ },
+ "@nodelib/fs.stat": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
+ "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A=="
+ },
+ "@nodelib/fs.walk": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
+ "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
+ "requires": {
+ "@nodelib/fs.scandir": "2.1.5",
+ "fastq": "^1.6.0"
+ }
+ },
+ "@ungap/structured-clone": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz",
+ "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ=="
+ },
+ "acorn": {
+ "version": "8.11.3",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz",
+ "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg=="
+ },
+ "acorn-jsx": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
+ "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
+ "requires": {}
+ },
+ "ajv": {
+ "version": "6.12.6",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+ "requires": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ }
+ },
+ "ansi-colors": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz",
+ "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==",
+ "dev": true
+ },
+ "ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="
+ },
+ "ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "requires": {
+ "color-convert": "^2.0.1"
+ }
+ },
+ "anymatch": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
+ "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
+ "dev": true,
+ "requires": {
+ "normalize-path": "^3.0.0",
+ "picomatch": "^2.0.4"
+ }
+ },
+ "argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
+ },
+ "array-buffer-byte-length": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz",
+ "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==",
+ "peer": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "is-array-buffer": "^3.0.1"
+ }
+ },
+ "array-includes": {
+ "version": "3.1.7",
+ "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.7.tgz",
+ "integrity": "sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ==",
+ "peer": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.2.0",
+ "es-abstract": "^1.22.1",
+ "get-intrinsic": "^1.2.1",
+ "is-string": "^1.0.7"
+ }
+ },
+ "array.prototype.flat": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz",
+ "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==",
+ "peer": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.2.0",
+ "es-abstract": "^1.22.1",
+ "es-shim-unscopables": "^1.0.0"
+ }
+ },
+ "array.prototype.flatmap": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz",
+ "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==",
+ "peer": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.2.0",
+ "es-abstract": "^1.22.1",
+ "es-shim-unscopables": "^1.0.0"
+ }
+ },
+ "array.prototype.tosorted": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.2.tgz",
+ "integrity": "sha512-HuQCHOlk1Weat5jzStICBCd83NxiIMwqDg/dHEsoefabn/hJRj5pVdWcPUSpRrwhwxZOsQassMpgN/xRYFBMIg==",
+ "peer": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.2.0",
+ "es-abstract": "^1.22.1",
+ "es-shim-unscopables": "^1.0.0",
+ "get-intrinsic": "^1.2.1"
+ }
+ },
+ "arraybuffer.prototype.slice": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.2.tgz",
+ "integrity": "sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==",
+ "peer": true,
+ "requires": {
+ "array-buffer-byte-length": "^1.0.0",
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.2.0",
+ "es-abstract": "^1.22.1",
+ "get-intrinsic": "^1.2.1",
+ "is-array-buffer": "^3.0.2",
+ "is-shared-array-buffer": "^1.0.2"
+ }
+ },
+ "available-typed-arrays": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.6.tgz",
+ "integrity": "sha512-j1QzY8iPNPG4o4xmO3ptzpRxTciqD3MgEHtifP/YnJpIo58Xu+ne4BejlbkuaLfXn/nz6HFiw29bLpj2PNMdGg==",
+ "peer": true
+ },
+ "balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
+ },
+ "binary-extensions": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
+ "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
+ "dev": true
+ },
+ "brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "requires": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "braces": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
+ "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+ "dev": true,
+ "requires": {
+ "fill-range": "^7.0.1"
+ }
+ },
+ "browser-stdout": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz",
+ "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==",
+ "dev": true
+ },
+ "call-bind": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz",
+ "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==",
+ "peer": true,
+ "requires": {
+ "function-bind": "^1.1.2",
+ "get-intrinsic": "^1.2.1",
+ "set-function-length": "^1.1.1"
+ }
+ },
+ "callsites": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="
+ },
+ "camelcase": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
+ "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
+ "dev": true
+ },
+ "chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "requires": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ }
+ },
+ "chokidar": {
+ "version": "3.5.3",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
+ "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
+ "dev": true,
+ "requires": {
+ "anymatch": "~3.1.2",
+ "braces": "~3.0.2",
+ "fsevents": "~2.3.2",
+ "glob-parent": "~5.1.2",
+ "is-binary-path": "~2.1.0",
+ "is-glob": "~4.0.1",
+ "normalize-path": "~3.0.0",
+ "readdirp": "~3.6.0"
+ },
+ "dependencies": {
+ "glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "dev": true,
+ "requires": {
+ "is-glob": "^4.0.1"
+ }
+ }
+ }
+ },
+ "cliui": {
+ "version": "7.0.4",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz",
+ "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==",
+ "dev": true,
+ "requires": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.0",
+ "wrap-ansi": "^7.0.0"
+ }
+ },
+ "color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "requires": {
+ "color-name": "~1.1.4"
+ }
+ },
+ "color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
+ },
+ "concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
+ },
+ "cross-spawn": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
+ "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+ "requires": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ }
+ },
+ "debug": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+ "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+ "requires": {
+ "ms": "2.1.2"
+ }
+ },
+ "decamelize": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz",
+ "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==",
+ "dev": true
+ },
+ "deep-is": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
+ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="
+ },
+ "define-data-property": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz",
+ "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==",
+ "peer": true,
+ "requires": {
+ "get-intrinsic": "^1.2.1",
+ "gopd": "^1.0.1",
+ "has-property-descriptors": "^1.0.0"
+ }
+ },
+ "define-properties": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz",
+ "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==",
+ "peer": true,
+ "requires": {
+ "define-data-property": "^1.0.1",
+ "has-property-descriptors": "^1.0.0",
+ "object-keys": "^1.1.1"
+ }
+ },
+ "diff": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz",
+ "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==",
+ "dev": true
+ },
+ "doctrine": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
+ "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
+ "requires": {
+ "esutils": "^2.0.2"
+ }
+ },
+ "dom-serializer": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz",
+ "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==",
+ "requires": {
+ "domelementtype": "^2.3.0",
+ "domhandler": "^5.0.2",
+ "entities": "^4.2.0"
+ }
+ },
+ "domelementtype": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
+ "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw=="
+ },
+ "domhandler": {
+ "version": "5.0.3",
+ "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz",
+ "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
+ "requires": {
+ "domelementtype": "^2.3.0"
+ }
+ },
+ "domutils": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz",
+ "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==",
+ "requires": {
+ "dom-serializer": "^2.0.0",
+ "domelementtype": "^2.3.0",
+ "domhandler": "^5.0.3"
+ }
+ },
+ "emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "dev": true
+ },
+ "entities": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
+ "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="
+ },
+ "es-abstract": {
+ "version": "1.22.3",
+ "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.3.tgz",
+ "integrity": "sha512-eiiY8HQeYfYH2Con2berK+To6GrK2RxbPawDkGq4UiCQQfZHb6wX9qQqkbpPqaxQFcl8d9QzZqo0tGE0VcrdwA==",
+ "peer": true,
+ "requires": {
+ "array-buffer-byte-length": "^1.0.0",
+ "arraybuffer.prototype.slice": "^1.0.2",
+ "available-typed-arrays": "^1.0.5",
+ "call-bind": "^1.0.5",
+ "es-set-tostringtag": "^2.0.1",
+ "es-to-primitive": "^1.2.1",
+ "function.prototype.name": "^1.1.6",
+ "get-intrinsic": "^1.2.2",
+ "get-symbol-description": "^1.0.0",
+ "globalthis": "^1.0.3",
+ "gopd": "^1.0.1",
+ "has-property-descriptors": "^1.0.0",
+ "has-proto": "^1.0.1",
+ "has-symbols": "^1.0.3",
+ "hasown": "^2.0.0",
+ "internal-slot": "^1.0.5",
+ "is-array-buffer": "^3.0.2",
+ "is-callable": "^1.2.7",
+ "is-negative-zero": "^2.0.2",
+ "is-regex": "^1.1.4",
+ "is-shared-array-buffer": "^1.0.2",
+ "is-string": "^1.0.7",
+ "is-typed-array": "^1.1.12",
+ "is-weakref": "^1.0.2",
+ "object-inspect": "^1.13.1",
+ "object-keys": "^1.1.1",
+ "object.assign": "^4.1.4",
+ "regexp.prototype.flags": "^1.5.1",
+ "safe-array-concat": "^1.0.1",
+ "safe-regex-test": "^1.0.0",
+ "string.prototype.trim": "^1.2.8",
+ "string.prototype.trimend": "^1.0.7",
+ "string.prototype.trimstart": "^1.0.7",
+ "typed-array-buffer": "^1.0.0",
+ "typed-array-byte-length": "^1.0.0",
+ "typed-array-byte-offset": "^1.0.0",
+ "typed-array-length": "^1.0.4",
+ "unbox-primitive": "^1.0.2",
+ "which-typed-array": "^1.1.13"
+ }
+ },
+ "es-set-tostringtag": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.2.tgz",
+ "integrity": "sha512-BuDyupZt65P9D2D2vA/zqcI3G5xRsklm5N3xCwuiy+/vKy8i0ifdsQP1sLgO4tZDSCaQUSnmC48khknGMV3D2Q==",
+ "peer": true,
+ "requires": {
+ "get-intrinsic": "^1.2.2",
+ "has-tostringtag": "^1.0.0",
+ "hasown": "^2.0.0"
+ }
+ },
+ "es-shim-unscopables": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz",
+ "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==",
+ "peer": true,
+ "requires": {
+ "hasown": "^2.0.0"
+ }
+ },
+ "es-to-primitive": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
+ "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==",
+ "peer": true,
+ "requires": {
+ "is-callable": "^1.1.4",
+ "is-date-object": "^1.0.1",
+ "is-symbol": "^1.0.2"
+ }
+ },
+ "escalade": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
+ "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
+ "dev": true
+ },
+ "escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="
+ },
+ "eslint": {
+ "version": "8.56.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.56.0.tgz",
+ "integrity": "sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==",
+ "requires": {
+ "@eslint-community/eslint-utils": "^4.2.0",
+ "@eslint-community/regexpp": "^4.6.1",
+ "@eslint/eslintrc": "^2.1.4",
+ "@eslint/js": "8.56.0",
+ "@humanwhocodes/config-array": "^0.11.13",
+ "@humanwhocodes/module-importer": "^1.0.1",
+ "@nodelib/fs.walk": "^1.2.8",
+ "@ungap/structured-clone": "^1.2.0",
+ "ajv": "^6.12.4",
+ "chalk": "^4.0.0",
+ "cross-spawn": "^7.0.2",
+ "debug": "^4.3.2",
+ "doctrine": "^3.0.0",
+ "escape-string-regexp": "^4.0.0",
+ "eslint-scope": "^7.2.2",
+ "eslint-visitor-keys": "^3.4.3",
+ "espree": "^9.6.1",
+ "esquery": "^1.4.2",
+ "esutils": "^2.0.2",
+ "fast-deep-equal": "^3.1.3",
+ "file-entry-cache": "^6.0.1",
+ "find-up": "^5.0.0",
+ "glob-parent": "^6.0.2",
+ "globals": "^13.19.0",
+ "graphemer": "^1.4.0",
+ "ignore": "^5.2.0",
+ "imurmurhash": "^0.1.4",
+ "is-glob": "^4.0.0",
+ "is-path-inside": "^3.0.3",
+ "js-yaml": "^4.1.0",
+ "json-stable-stringify-without-jsonify": "^1.0.1",
+ "levn": "^0.4.1",
+ "lodash.merge": "^4.6.2",
+ "minimatch": "^3.1.2",
+ "natural-compare": "^1.4.0",
+ "optionator": "^0.9.3",
+ "strip-ansi": "^6.0.1",
+ "text-table": "^0.2.0"
+ }
+ },
+ "eslint-config-prettier": {
+ "version": "9.1.0",
+ "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz",
+ "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==",
+ "peer": true,
+ "requires": {}
+ },
+ "eslint-plugin-es": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-3.0.1.tgz",
+ "integrity": "sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ==",
+ "peer": true,
+ "requires": {
+ "eslint-utils": "^2.0.0",
+ "regexpp": "^3.0.0"
+ }
+ },
+ "eslint-plugin-fetch-options": {
+ "version": "0.0.5",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-fetch-options/-/eslint-plugin-fetch-options-0.0.5.tgz",
+ "integrity": "sha512-ZMxrccsOAZ7uMQ4nMvPJLqLg6oyLF96YOEwTKWAIbDHpwWUp1raXALZom8ikKucaEnhqWSRuBWI8jBXveFwkJg==",
+ "peer": true
+ },
+ "eslint-plugin-html": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-html/-/eslint-plugin-html-7.1.0.tgz",
+ "integrity": "sha512-fNLRraV/e6j8e3XYOC9xgND4j+U7b1Rq+OygMlLcMg+wI/IpVbF+ubQa3R78EjKB9njT6TQOlcK5rFKBVVtdfg==",
+ "peer": true,
+ "requires": {
+ "htmlparser2": "^8.0.1"
+ }
+ },
+ "eslint-plugin-json": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-json/-/eslint-plugin-json-3.1.0.tgz",
+ "integrity": "sha512-MrlG2ynFEHe7wDGwbUuFPsaT2b1uhuEFhJ+W1f1u+1C2EkXmTYJp4B1aAdQQ8M+CC3t//N/oRKiIVw14L2HR1g==",
+ "peer": true,
+ "requires": {
+ "lodash": "^4.17.21",
+ "vscode-json-languageservice": "^4.1.6"
+ }
+ },
+ "eslint-plugin-no-unsanitized": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-no-unsanitized/-/eslint-plugin-no-unsanitized-4.0.2.tgz",
+ "integrity": "sha512-Pry0S9YmHoz8NCEMRQh7N0Yexh2MYCNPIlrV52hTmS7qXnTghWsjXouF08bgsrrZqaW9tt1ZiK3j5NEmPE+EjQ==",
+ "peer": true,
+ "requires": {}
+ },
+ "eslint-plugin-node": {
+ "version": "11.1.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-11.1.0.tgz",
+ "integrity": "sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g==",
+ "peer": true,
+ "requires": {
+ "eslint-plugin-es": "^3.0.0",
+ "eslint-utils": "^2.0.0",
+ "ignore": "^5.1.1",
+ "minimatch": "^3.0.4",
+ "resolve": "^1.10.1",
+ "semver": "^6.1.0"
+ }
+ },
+ "eslint-plugin-react": {
+ "version": "7.33.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.33.0.tgz",
+ "integrity": "sha512-qewL/8P34WkY8jAqdQxsiL82pDUeT7nhs8IsuXgfgnsEloKCT4miAV9N9kGtx7/KM9NH/NCGUE7Edt9iGxLXFw==",
+ "peer": true,
+ "requires": {
+ "array-includes": "^3.1.6",
+ "array.prototype.flatmap": "^1.3.1",
+ "array.prototype.tosorted": "^1.1.1",
+ "doctrine": "^2.1.0",
+ "estraverse": "^5.3.0",
+ "jsx-ast-utils": "^2.4.1 || ^3.0.0",
+ "minimatch": "^3.1.2",
+ "object.entries": "^1.1.6",
+ "object.fromentries": "^2.0.6",
+ "object.hasown": "^1.1.2",
+ "object.values": "^1.1.6",
+ "prop-types": "^15.8.1",
+ "resolve": "^2.0.0-next.4",
+ "semver": "^6.3.1",
+ "string.prototype.matchall": "^4.0.8"
+ },
+ "dependencies": {
+ "doctrine": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
+ "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
+ "peer": true,
+ "requires": {
+ "esutils": "^2.0.2"
+ }
+ },
+ "resolve": {
+ "version": "2.0.0-next.5",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz",
+ "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==",
+ "peer": true,
+ "requires": {
+ "is-core-module": "^2.13.0",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ }
+ }
+ }
+ },
+ "eslint-plugin-security": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-security/-/eslint-plugin-security-1.4.0.tgz",
+ "integrity": "sha512-xlS7P2PLMXeqfhyf3NpqbvbnW04kN8M9NtmhpR3XGyOvt/vNKS7XPXT5EDbwKW9vCjWH4PpfQvgD/+JgN0VJKA==",
+ "peer": true,
+ "requires": {
+ "safe-regex": "^1.1.0"
+ }
+ },
+ "eslint-scope": {
+ "version": "7.2.2",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz",
+ "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==",
+ "requires": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^5.2.0"
+ }
+ },
+ "eslint-utils": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz",
+ "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==",
+ "peer": true,
+ "requires": {
+ "eslint-visitor-keys": "^1.1.0"
+ },
+ "dependencies": {
+ "eslint-visitor-keys": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz",
+ "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==",
+ "peer": true
+ }
+ }
+ },
+ "eslint-visitor-keys": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
+ "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="
+ },
+ "espree": {
+ "version": "9.6.1",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz",
+ "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==",
+ "requires": {
+ "acorn": "^8.9.0",
+ "acorn-jsx": "^5.3.2",
+ "eslint-visitor-keys": "^3.4.1"
+ }
+ },
+ "esquery": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz",
+ "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==",
+ "requires": {
+ "estraverse": "^5.1.0"
+ }
+ },
+ "esrecurse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
+ "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
+ "requires": {
+ "estraverse": "^5.2.0"
+ }
+ },
+ "estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA=="
+ },
+ "esutils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="
+ },
+ "fast-deep-equal": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
+ },
+ "fast-json-stable-stringify": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="
+ },
+ "fast-levenshtein": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw=="
+ },
+ "fastq": {
+ "version": "1.17.0",
+ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.0.tgz",
+ "integrity": "sha512-zGygtijUMT7jnk3h26kUms3BkSDp4IfIKjmnqI2tvx6nuBfiF1UqOxbnLfzdv+apBy+53oaImsKtMw/xYbW+1w==",
+ "requires": {
+ "reusify": "^1.0.4"
+ }
+ },
+ "file-entry-cache": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
+ "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
+ "requires": {
+ "flat-cache": "^3.0.4"
+ }
+ },
+ "fill-range": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
+ "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+ "dev": true,
+ "requires": {
+ "to-regex-range": "^5.0.1"
+ }
+ },
+ "find-up": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
+ "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
+ "requires": {
+ "locate-path": "^6.0.0",
+ "path-exists": "^4.0.0"
+ }
+ },
+ "flat": {
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz",
+ "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==",
+ "dev": true
+ },
+ "flat-cache": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz",
+ "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==",
+ "requires": {
+ "flatted": "^3.2.9",
+ "keyv": "^4.5.3",
+ "rimraf": "^3.0.2"
+ }
+ },
+ "flatted": {
+ "version": "3.2.9",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz",
+ "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ=="
+ },
+ "for-each": {
+ "version": "0.3.3",
+ "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz",
+ "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==",
+ "peer": true,
+ "requires": {
+ "is-callable": "^1.1.3"
+ }
+ },
+ "fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
+ },
+ "fsevents": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+ "dev": true,
+ "optional": true
+ },
+ "function-bind": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
+ "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
+ "peer": true
+ },
+ "function.prototype.name": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz",
+ "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==",
+ "peer": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.2.0",
+ "es-abstract": "^1.22.1",
+ "functions-have-names": "^1.2.3"
+ }
+ },
+ "functions-have-names": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz",
+ "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==",
+ "peer": true
+ },
+ "get-caller-file": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
+ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
+ "dev": true
+ },
+ "get-intrinsic": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz",
+ "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==",
+ "peer": true,
+ "requires": {
+ "function-bind": "^1.1.2",
+ "has-proto": "^1.0.1",
+ "has-symbols": "^1.0.3",
+ "hasown": "^2.0.0"
+ }
+ },
+ "get-symbol-description": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz",
+ "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==",
+ "peer": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "get-intrinsic": "^1.1.1"
+ }
+ },
+ "glob": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz",
+ "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==",
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ },
+ "glob-parent": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
+ "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
+ "requires": {
+ "is-glob": "^4.0.3"
+ }
+ },
+ "globals": {
+ "version": "13.24.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz",
+ "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==",
+ "requires": {
+ "type-fest": "^0.20.2"
+ }
+ },
+ "globalthis": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz",
+ "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==",
+ "peer": true,
+ "requires": {
+ "define-properties": "^1.1.3"
+ }
+ },
+ "gopd": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
+ "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
+ "peer": true,
+ "requires": {
+ "get-intrinsic": "^1.1.3"
+ }
+ },
+ "graphemer": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
+ "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag=="
+ },
+ "has-bigints": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz",
+ "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==",
+ "peer": true
+ },
+ "has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="
+ },
+ "has-property-descriptors": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz",
+ "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==",
+ "peer": true,
+ "requires": {
+ "get-intrinsic": "^1.2.2"
+ }
+ },
+ "has-proto": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz",
+ "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==",
+ "peer": true
+ },
+ "has-symbols": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
+ "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
+ "peer": true
+ },
+ "has-tostringtag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz",
+ "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==",
+ "peer": true,
+ "requires": {
+ "has-symbols": "^1.0.2"
+ }
+ },
+ "hasown": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz",
+ "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==",
+ "peer": true,
+ "requires": {
+ "function-bind": "^1.1.2"
+ }
+ },
+ "he": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
+ "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
+ "dev": true
+ },
+ "htmlparser2": {
+ "version": "8.0.2",
+ "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz",
+ "integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==",
+ "requires": {
+ "domelementtype": "^2.3.0",
+ "domhandler": "^5.0.3",
+ "domutils": "^3.0.1",
+ "entities": "^4.4.0"
+ }
+ },
+ "ignore": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz",
+ "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw=="
+ },
+ "import-fresh": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
+ "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
+ "requires": {
+ "parent-module": "^1.0.0",
+ "resolve-from": "^4.0.0"
+ }
+ },
+ "imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA=="
+ },
+ "inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
+ "requires": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
+ },
+ "internal-slot": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.6.tgz",
+ "integrity": "sha512-Xj6dv+PsbtwyPpEflsejS+oIZxmMlV44zAhG479uYu89MsjcYOhCFnNyKrkJrihbsiasQyY0afoCl/9BLR65bg==",
+ "peer": true,
+ "requires": {
+ "get-intrinsic": "^1.2.2",
+ "hasown": "^2.0.0",
+ "side-channel": "^1.0.4"
+ }
+ },
+ "is-array-buffer": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz",
+ "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==",
+ "peer": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "get-intrinsic": "^1.2.0",
+ "is-typed-array": "^1.1.10"
+ }
+ },
+ "is-bigint": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz",
+ "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==",
+ "peer": true,
+ "requires": {
+ "has-bigints": "^1.0.1"
+ }
+ },
+ "is-binary-path": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
+ "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
+ "dev": true,
+ "requires": {
+ "binary-extensions": "^2.0.0"
+ }
+ },
+ "is-boolean-object": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz",
+ "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==",
+ "peer": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "has-tostringtag": "^1.0.0"
+ }
+ },
+ "is-callable": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
+ "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==",
+ "peer": true
+ },
+ "is-core-module": {
+ "version": "2.13.1",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz",
+ "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==",
+ "peer": true,
+ "requires": {
+ "hasown": "^2.0.0"
+ }
+ },
+ "is-date-object": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz",
+ "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==",
+ "peer": true,
+ "requires": {
+ "has-tostringtag": "^1.0.0"
+ }
+ },
+ "is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="
+ },
+ "is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "dev": true
+ },
+ "is-glob": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+ "requires": {
+ "is-extglob": "^2.1.1"
+ }
+ },
+ "is-negative-zero": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz",
+ "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==",
+ "peer": true
+ },
+ "is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "dev": true
+ },
+ "is-number-object": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz",
+ "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==",
+ "peer": true,
+ "requires": {
+ "has-tostringtag": "^1.0.0"
+ }
+ },
+ "is-path-inside": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
+ "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ=="
+ },
+ "is-plain-obj": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz",
+ "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==",
+ "dev": true
+ },
+ "is-regex": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz",
+ "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==",
+ "peer": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "has-tostringtag": "^1.0.0"
+ }
+ },
+ "is-shared-array-buffer": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz",
+ "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==",
+ "peer": true,
+ "requires": {
+ "call-bind": "^1.0.2"
+ }
+ },
+ "is-string": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz",
+ "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==",
+ "peer": true,
+ "requires": {
+ "has-tostringtag": "^1.0.0"
+ }
+ },
+ "is-symbol": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz",
+ "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==",
+ "peer": true,
+ "requires": {
+ "has-symbols": "^1.0.2"
+ }
+ },
+ "is-typed-array": {
+ "version": "1.1.12",
+ "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz",
+ "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==",
+ "peer": true,
+ "requires": {
+ "which-typed-array": "^1.1.11"
+ }
+ },
+ "is-unicode-supported": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz",
+ "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==",
+ "dev": true
+ },
+ "is-weakref": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz",
+ "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==",
+ "peer": true,
+ "requires": {
+ "call-bind": "^1.0.2"
+ }
+ },
+ "isarray": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
+ "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==",
+ "peer": true
+ },
+ "isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="
+ },
+ "js-tokens": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+ "peer": true
+ },
+ "js-yaml": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
+ "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+ "requires": {
+ "argparse": "^2.0.1"
+ }
+ },
+ "json-buffer": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
+ "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ=="
+ },
+ "json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="
+ },
+ "json-stable-stringify-without-jsonify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
+ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw=="
+ },
+ "jsonc-parser": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.1.tgz",
+ "integrity": "sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==",
+ "peer": true
+ },
+ "jsx-ast-utils": {
+ "version": "3.3.5",
+ "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz",
+ "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==",
+ "peer": true,
+ "requires": {
+ "array-includes": "^3.1.6",
+ "array.prototype.flat": "^1.3.1",
+ "object.assign": "^4.1.4",
+ "object.values": "^1.1.6"
+ }
+ },
+ "keyv": {
+ "version": "4.5.4",
+ "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
+ "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
+ "requires": {
+ "json-buffer": "3.0.1"
+ }
+ },
+ "levn": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
+ "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
+ "requires": {
+ "prelude-ls": "^1.2.1",
+ "type-check": "~0.4.0"
+ }
+ },
+ "locate-path": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
+ "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
+ "requires": {
+ "p-locate": "^5.0.0"
+ }
+ },
+ "lodash": {
+ "version": "4.17.21",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
+ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
+ "peer": true
+ },
+ "lodash.merge": {
+ "version": "4.6.2",
+ "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
+ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="
+ },
+ "log-symbols": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz",
+ "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==",
+ "dev": true,
+ "requires": {
+ "chalk": "^4.1.0",
+ "is-unicode-supported": "^0.1.0"
+ }
+ },
+ "loose-envify": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
+ "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
+ "peer": true,
+ "requires": {
+ "js-tokens": "^3.0.0 || ^4.0.0"
+ }
+ },
+ "minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "requires": {
+ "brace-expansion": "^1.1.7"
+ }
+ },
+ "mocha": {
+ "version": "10.2.0",
+ "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.2.0.tgz",
+ "integrity": "sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg==",
+ "dev": true,
+ "requires": {
+ "ansi-colors": "4.1.1",
+ "browser-stdout": "1.3.1",
+ "chokidar": "3.5.3",
+ "debug": "4.3.4",
+ "diff": "5.0.0",
+ "escape-string-regexp": "4.0.0",
+ "find-up": "5.0.0",
+ "glob": "7.2.0",
+ "he": "1.2.0",
+ "js-yaml": "4.1.0",
+ "log-symbols": "4.1.0",
+ "minimatch": "5.0.1",
+ "ms": "2.1.3",
+ "nanoid": "3.3.3",
+ "serialize-javascript": "6.0.0",
+ "strip-json-comments": "3.1.1",
+ "supports-color": "8.1.1",
+ "workerpool": "6.2.1",
+ "yargs": "16.2.0",
+ "yargs-parser": "20.2.4",
+ "yargs-unparser": "2.0.0"
+ },
+ "dependencies": {
+ "brace-expansion": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "dev": true,
+ "requires": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "minimatch": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz",
+ "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==",
+ "dev": true,
+ "requires": {
+ "brace-expansion": "^2.0.1"
+ }
+ },
+ "ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "8.1.1",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
+ "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^4.0.0"
+ }
+ }
+ }
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
+ },
+ "nanoid": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz",
+ "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==",
+ "dev": true
+ },
+ "natural-compare": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="
+ },
+ "normalize-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+ "dev": true
+ },
+ "object-assign": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+ "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
+ "peer": true
+ },
+ "object-inspect": {
+ "version": "1.13.1",
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz",
+ "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==",
+ "peer": true
+ },
+ "object-keys": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
+ "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
+ "peer": true
+ },
+ "object.assign": {
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz",
+ "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==",
+ "peer": true,
+ "requires": {
+ "call-bind": "^1.0.5",
+ "define-properties": "^1.2.1",
+ "has-symbols": "^1.0.3",
+ "object-keys": "^1.1.1"
+ }
+ },
+ "object.entries": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.7.tgz",
+ "integrity": "sha512-jCBs/0plmPsOnrKAfFQXRG2NFjlhZgjjcBLSmTnEhU8U6vVTsVe8ANeQJCHTl3gSsI4J+0emOoCgoKlmQPMgmA==",
+ "peer": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.2.0",
+ "es-abstract": "^1.22.1"
+ }
+ },
+ "object.fromentries": {
+ "version": "2.0.7",
+ "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.7.tgz",
+ "integrity": "sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA==",
+ "peer": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.2.0",
+ "es-abstract": "^1.22.1"
+ }
+ },
+ "object.hasown": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.3.tgz",
+ "integrity": "sha512-fFI4VcYpRHvSLXxP7yiZOMAd331cPfd2p7PFDVbgUsYOfCT3tICVqXWngbjr4m49OvsBwUBQ6O2uQoJvy3RexA==",
+ "peer": true,
+ "requires": {
+ "define-properties": "^1.2.0",
+ "es-abstract": "^1.22.1"
+ }
+ },
+ "object.values": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.7.tgz",
+ "integrity": "sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng==",
+ "peer": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.2.0",
+ "es-abstract": "^1.22.1"
+ }
+ },
+ "once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+ "requires": {
+ "wrappy": "1"
+ }
+ },
+ "optionator": {
+ "version": "0.9.3",
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz",
+ "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==",
+ "requires": {
+ "@aashutoshrathi/word-wrap": "^1.2.3",
+ "deep-is": "^0.1.3",
+ "fast-levenshtein": "^2.0.6",
+ "levn": "^0.4.1",
+ "prelude-ls": "^1.2.1",
+ "type-check": "^0.4.0"
+ }
+ },
+ "p-limit": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
+ "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
+ "requires": {
+ "yocto-queue": "^0.1.0"
+ }
+ },
+ "p-locate": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
+ "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
+ "requires": {
+ "p-limit": "^3.0.2"
+ }
+ },
+ "parent-module": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
+ "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
+ "requires": {
+ "callsites": "^3.0.0"
+ }
+ },
+ "path-exists": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+ "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="
+ },
+ "path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg=="
+ },
+ "path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="
+ },
+ "path-parse": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
+ "peer": true
+ },
+ "picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "dev": true
+ },
+ "prelude-ls": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
+ "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="
+ },
+ "prop-types": {
+ "version": "15.8.1",
+ "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
+ "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
+ "peer": true,
+ "requires": {
+ "loose-envify": "^1.4.0",
+ "object-assign": "^4.1.1",
+ "react-is": "^16.13.1"
+ }
+ },
+ "punycode": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
+ "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="
+ },
+ "queue-microtask": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
+ "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="
+ },
+ "randombytes": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
+ "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
+ "dev": true,
+ "requires": {
+ "safe-buffer": "^5.1.0"
+ }
+ },
+ "react-is": {
+ "version": "16.13.1",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
+ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
+ "peer": true
+ },
+ "readdirp": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
+ "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
+ "dev": true,
+ "requires": {
+ "picomatch": "^2.2.1"
+ }
+ },
+ "regexp.prototype.flags": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz",
+ "integrity": "sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==",
+ "peer": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.2.0",
+ "set-function-name": "^2.0.0"
+ }
+ },
+ "regexpp": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz",
+ "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==",
+ "peer": true
+ },
+ "require-directory": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
+ "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
+ "dev": true
+ },
+ "resolve": {
+ "version": "1.22.8",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz",
+ "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==",
+ "peer": true,
+ "requires": {
+ "is-core-module": "^2.13.0",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ }
+ },
+ "resolve-from": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="
+ },
+ "ret": {
+ "version": "0.1.15",
+ "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz",
+ "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==",
+ "peer": true
+ },
+ "reusify": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
+ "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw=="
+ },
+ "rimraf": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
+ "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+ "requires": {
+ "glob": "^7.1.3"
+ }
+ },
+ "run-parallel": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
+ "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
+ "requires": {
+ "queue-microtask": "^1.2.2"
+ }
+ },
+ "safe-array-concat": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.0.tgz",
+ "integrity": "sha512-ZdQ0Jeb9Ofti4hbt5lX3T2JcAamT9hfzYU1MNB+z/jaEbB6wfFfPIR/zEORmZqobkCCJhSjodobH6WHNmJ97dg==",
+ "peer": true,
+ "requires": {
+ "call-bind": "^1.0.5",
+ "get-intrinsic": "^1.2.2",
+ "has-symbols": "^1.0.3",
+ "isarray": "^2.0.5"
+ }
+ },
+ "safe-buffer": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+ "dev": true
+ },
+ "safe-regex": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz",
+ "integrity": "sha512-aJXcif4xnaNUzvUuC5gcb46oTS7zvg4jpMTnuqtrEPlR3vFr4pxtdTwaF1Qs3Enjn9HK+ZlwQui+a7z0SywIzg==",
+ "peer": true,
+ "requires": {
+ "ret": "~0.1.10"
+ }
+ },
+ "safe-regex-test": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.2.tgz",
+ "integrity": "sha512-83S9w6eFq12BBIJYvjMux6/dkirb8+4zJRA9cxNBVb7Wq5fJBW+Xze48WqR8pxua7bDuAaaAxtVVd4Idjp1dBQ==",
+ "peer": true,
+ "requires": {
+ "call-bind": "^1.0.5",
+ "get-intrinsic": "^1.2.2",
+ "is-regex": "^1.1.4"
+ }
+ },
+ "semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "peer": true
+ },
+ "serialize-javascript": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz",
+ "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==",
+ "dev": true,
+ "requires": {
+ "randombytes": "^2.1.0"
+ }
+ },
+ "set-function-length": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.0.tgz",
+ "integrity": "sha512-4DBHDoyHlM1IRPGYcoxexgh67y4ueR53FKV1yyxwFMY7aCqcN/38M1+SwZ/qJQ8iLv7+ck385ot4CcisOAPT9w==",
+ "peer": true,
+ "requires": {
+ "define-data-property": "^1.1.1",
+ "function-bind": "^1.1.2",
+ "get-intrinsic": "^1.2.2",
+ "gopd": "^1.0.1",
+ "has-property-descriptors": "^1.0.1"
+ }
+ },
+ "set-function-name": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.1.tgz",
+ "integrity": "sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==",
+ "peer": true,
+ "requires": {
+ "define-data-property": "^1.0.1",
+ "functions-have-names": "^1.2.3",
+ "has-property-descriptors": "^1.0.0"
+ }
+ },
+ "shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "requires": {
+ "shebang-regex": "^3.0.0"
+ }
+ },
+ "shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="
+ },
+ "side-channel": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
+ "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
+ "peer": true,
+ "requires": {
+ "call-bind": "^1.0.0",
+ "get-intrinsic": "^1.0.2",
+ "object-inspect": "^1.9.0"
+ }
+ },
+ "string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
+ "requires": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ }
+ },
+ "string.prototype.matchall": {
+ "version": "4.0.10",
+ "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.10.tgz",
+ "integrity": "sha512-rGXbGmOEosIQi6Qva94HUjgPs9vKW+dkG7Y8Q5O2OYkWL6wFaTRZO8zM4mhP94uX55wgyrXzfS2aGtGzUL7EJQ==",
+ "peer": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.2.0",
+ "es-abstract": "^1.22.1",
+ "get-intrinsic": "^1.2.1",
+ "has-symbols": "^1.0.3",
+ "internal-slot": "^1.0.5",
+ "regexp.prototype.flags": "^1.5.0",
+ "set-function-name": "^2.0.0",
+ "side-channel": "^1.0.4"
+ }
+ },
+ "string.prototype.trim": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz",
+ "integrity": "sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==",
+ "peer": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.2.0",
+ "es-abstract": "^1.22.1"
+ }
+ },
+ "string.prototype.trimend": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz",
+ "integrity": "sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==",
+ "peer": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.2.0",
+ "es-abstract": "^1.22.1"
+ }
+ },
+ "string.prototype.trimstart": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz",
+ "integrity": "sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==",
+ "peer": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.2.0",
+ "es-abstract": "^1.22.1"
+ }
+ },
+ "strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "requires": {
+ "ansi-regex": "^5.0.1"
+ }
+ },
+ "strip-json-comments": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
+ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig=="
+ },
+ "supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "requires": {
+ "has-flag": "^4.0.0"
+ }
+ },
+ "supports-preserve-symlinks-flag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
+ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
+ "peer": true
+ },
+ "text-table": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
+ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw=="
+ },
+ "to-regex-range": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "dev": true,
+ "requires": {
+ "is-number": "^7.0.0"
+ }
+ },
+ "toml-eslint-parser": {
+ "version": "0.9.3",
+ "resolved": "https://registry.npmjs.org/toml-eslint-parser/-/toml-eslint-parser-0.9.3.tgz",
+ "integrity": "sha512-moYoCvkNUAPCxSW9jmHmRElhm4tVJpHL8ItC/+uYD0EpPSFXbck7yREz9tNdJVTSpHVod8+HoipcpbQ0oE6gsw==",
+ "requires": {
+ "eslint-visitor-keys": "^3.0.0"
+ }
+ },
+ "type-check": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
+ "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
+ "requires": {
+ "prelude-ls": "^1.2.1"
+ }
+ },
+ "type-fest": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
+ "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ=="
+ },
+ "typed-array-buffer": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz",
+ "integrity": "sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==",
+ "peer": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "get-intrinsic": "^1.2.1",
+ "is-typed-array": "^1.1.10"
+ }
+ },
+ "typed-array-byte-length": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz",
+ "integrity": "sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==",
+ "peer": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "for-each": "^0.3.3",
+ "has-proto": "^1.0.1",
+ "is-typed-array": "^1.1.10"
+ }
+ },
+ "typed-array-byte-offset": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz",
+ "integrity": "sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==",
+ "peer": true,
+ "requires": {
+ "available-typed-arrays": "^1.0.5",
+ "call-bind": "^1.0.2",
+ "for-each": "^0.3.3",
+ "has-proto": "^1.0.1",
+ "is-typed-array": "^1.1.10"
+ }
+ },
+ "typed-array-length": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz",
+ "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==",
+ "peer": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "for-each": "^0.3.3",
+ "is-typed-array": "^1.1.9"
+ }
+ },
+ "unbox-primitive": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz",
+ "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==",
+ "peer": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "has-bigints": "^1.0.2",
+ "has-symbols": "^1.0.3",
+ "which-boxed-primitive": "^1.0.2"
+ }
+ },
+ "uri-js": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+ "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+ "requires": {
+ "punycode": "^2.1.0"
+ }
+ },
+ "vscode-json-languageservice": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/vscode-json-languageservice/-/vscode-json-languageservice-4.2.1.tgz",
+ "integrity": "sha512-xGmv9QIWs2H8obGbWg+sIPI/3/pFgj/5OWBhNzs00BkYQ9UaB2F6JJaGB/2/YOZJ3BvLXQTC4Q7muqU25QgAhA==",
+ "peer": true,
+ "requires": {
+ "jsonc-parser": "^3.0.0",
+ "vscode-languageserver-textdocument": "^1.0.3",
+ "vscode-languageserver-types": "^3.16.0",
+ "vscode-nls": "^5.0.0",
+ "vscode-uri": "^3.0.3"
+ }
+ },
+ "vscode-languageserver-textdocument": {
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.11.tgz",
+ "integrity": "sha512-X+8T3GoiwTVlJbicx/sIAF+yuJAqz8VvwJyoMVhwEMoEKE/fkDmrqUgDMyBECcM2A2frVZIUj5HI/ErRXCfOeA==",
+ "peer": true
+ },
+ "vscode-languageserver-types": {
+ "version": "3.17.5",
+ "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz",
+ "integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==",
+ "peer": true
+ },
+ "vscode-nls": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/vscode-nls/-/vscode-nls-5.2.0.tgz",
+ "integrity": "sha512-RAaHx7B14ZU04EU31pT+rKz2/zSl7xMsfIZuo8pd+KZO6PXtQmpevpq3vxvWNcrGbdmhM/rr5Uw5Mz+NBfhVng==",
+ "peer": true
+ },
+ "vscode-uri": {
+ "version": "3.0.8",
+ "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.8.tgz",
+ "integrity": "sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==",
+ "peer": true
+ },
+ "which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "requires": {
+ "isexe": "^2.0.0"
+ }
+ },
+ "which-boxed-primitive": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz",
+ "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==",
+ "peer": true,
+ "requires": {
+ "is-bigint": "^1.0.1",
+ "is-boolean-object": "^1.1.0",
+ "is-number-object": "^1.0.4",
+ "is-string": "^1.0.5",
+ "is-symbol": "^1.0.3"
+ }
+ },
+ "which-typed-array": {
+ "version": "1.1.13",
+ "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.13.tgz",
+ "integrity": "sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow==",
+ "peer": true,
+ "requires": {
+ "available-typed-arrays": "^1.0.5",
+ "call-bind": "^1.0.4",
+ "for-each": "^0.3.3",
+ "gopd": "^1.0.1",
+ "has-tostringtag": "^1.0.0"
+ }
+ },
+ "workerpool": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz",
+ "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==",
+ "dev": true
+ },
+ "wrap-ansi": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ }
+ },
+ "wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
+ },
+ "y18n": {
+ "version": "5.0.8",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
+ "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
+ "dev": true
+ },
+ "yargs": {
+ "version": "16.2.0",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz",
+ "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==",
+ "dev": true,
+ "requires": {
+ "cliui": "^7.0.2",
+ "escalade": "^3.1.1",
+ "get-caller-file": "^2.0.5",
+ "require-directory": "^2.1.1",
+ "string-width": "^4.2.0",
+ "y18n": "^5.0.5",
+ "yargs-parser": "^20.2.2"
+ }
+ },
+ "yargs-parser": {
+ "version": "20.2.4",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz",
+ "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==",
+ "dev": true
+ },
+ "yargs-unparser": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz",
+ "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==",
+ "dev": true,
+ "requires": {
+ "camelcase": "^6.0.0",
+ "decamelize": "^4.0.0",
+ "flat": "^5.0.2",
+ "is-plain-obj": "^2.1.0"
+ }
+ },
+ "yocto-queue": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
+ "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="
+ }
+ }
+}
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/package.json b/tools/lint/eslint/eslint-plugin-mozilla/package.json
new file mode 100644
index 0000000000..9d4a111dd2
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/package.json
@@ -0,0 +1,53 @@
+{
+ "name": "eslint-plugin-mozilla",
+ "version": "3.7.0",
+ "description": "A collection of rules that help enforce JavaScript coding standard in the Mozilla project.",
+ "keywords": [
+ "eslint",
+ "eslintplugin",
+ "eslint-plugin",
+ "mozilla",
+ "firefox"
+ ],
+ "bugs": {
+ "url": "https://bugzilla.mozilla.org/enter_bug.cgi?product=Testing&component=Lint"
+ },
+ "homepage": "http://firefox-source-docs.mozilla.org/tools/lint/linters/eslint-plugin-mozilla.html",
+ "repository": {
+ "type": "hg",
+ "url": "https://hg.mozilla.org/mozilla-central/"
+ },
+ "author": "Mike Ratcliffe",
+ "main": "lib/index.js",
+ "dependencies": {
+ "eslint-scope": "^7.2.2",
+ "eslint-visitor-keys": "^3.4.3",
+ "espree": "^9.6.1",
+ "estraverse": "^5.3.0",
+ "htmlparser2": "^8.0.1",
+ "toml-eslint-parser": "0.9.3"
+ },
+ "devDependencies": {
+ "eslint": "8.56.0",
+ "mocha": "10.2.0"
+ },
+ "peerDependencies": {
+ "@microsoft/eslint-plugin-sdl": "^0.2.2",
+ "eslint": "^7.23.0 || ^8.0.0",
+ "eslint-config-prettier": "^8.0.0 || ^9.0.0",
+ "eslint-plugin-fetch-options": "^0.0.5",
+ "eslint-plugin-html": "^7.0.0",
+ "eslint-plugin-json": "^3.1.0",
+ "eslint-plugin-no-unsanitized": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "scripts": {
+ "prepack": "node scripts/createExports.js",
+ "test": "mocha --reporter 'reporters/mozilla-format.js' tests",
+ "postpublish": "rm -f lib/environments/saved-globals.json lib/rules/saved-rules-data.json",
+ "update-tooltool": "./update.sh"
+ },
+ "license": "MPL-2.0"
+}
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/reporters/mozilla-format.js b/tools/lint/eslint/eslint-plugin-mozilla/reporters/mozilla-format.js
new file mode 100644
index 0000000000..a3f96e7bef
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/reporters/mozilla-format.js
@@ -0,0 +1,57 @@
+/* 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/. */
+
+/**
+ * This file outputs the format that treeherder requires. If we integrate
+ * these tests with ./mach, then we may replace this with a json handler within
+ * mach itself.
+ */
+
+"use strict";
+
+var mocha = require("mocha");
+var path = require("path");
+module.exports = MozillaFormatter;
+
+function MozillaFormatter(runner) {
+ mocha.reporters.Base.call(this, runner);
+ var passes = 0;
+ var failures = [];
+
+ runner.on("start", () => {
+ console.log("SUITE-START | eslint-plugin-mozilla");
+ });
+
+ runner.on("pass", function (test) {
+ passes++;
+ let title = test.title.replace(/\n/g, "|");
+ console.log(`TEST-PASS | ${path.basename(test.file)} | ${title}`);
+ });
+
+ runner.on("fail", function (test, err) {
+ failures.push(test);
+ // Replace any newlines in the title.
+ let title = test.title.replace(/\n/g, "|");
+ console.log(
+ `TEST-UNEXPECTED-FAIL | ${path.basename(test.file)} | ${title} | ${
+ err.message
+ }`
+ );
+ mocha.reporters.Base.list([test]);
+ });
+
+ runner.on("end", function () {
+ // Space the results out visually with an additional blank line.
+ console.log("");
+ console.log("INFO | Result summary:");
+ console.log(`INFO | Passed: ${passes}`);
+ console.log(`INFO | Failed: ${failures.length}`);
+ console.log("SUITE-END");
+ // Space the failures out visually with an additional blank line.
+ console.log("");
+ console.log("Failure summary:");
+ mocha.reporters.Base.list(failures);
+ process.exit(failures.length);
+ });
+}
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/scripts/createExports.js b/tools/lint/eslint/eslint-plugin-mozilla/scripts/createExports.js
new file mode 100644
index 0000000000..7f839edfba
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/scripts/createExports.js
@@ -0,0 +1,77 @@
+/**
+ * @fileoverview A script to export the known globals to a file.
+ * 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";
+
+var fs = require("fs");
+var path = require("path");
+var helpers = require("../lib/helpers");
+
+const eslintDir = path.join(helpers.rootDir, "tools", "lint", "eslint");
+
+const globalsFile = path.join(
+ eslintDir,
+ "eslint-plugin-mozilla",
+ "lib",
+ "environments",
+ "saved-globals.json"
+);
+const rulesFile = path.join(
+ eslintDir,
+ "eslint-plugin-mozilla",
+ "lib",
+ "rules",
+ "saved-rules-data.json"
+);
+
+console.log("Copying services.json");
+
+const env = helpers.getBuildEnvironment();
+
+const servicesFile = path.join(
+ env.topobjdir,
+ "xpcom",
+ "components",
+ "services.json"
+);
+const shipServicesFile = path.join(
+ eslintDir,
+ "eslint-plugin-mozilla",
+ "lib",
+ "services.json"
+);
+
+fs.writeFileSync(shipServicesFile, fs.readFileSync(servicesFile));
+
+console.log("Generating globals file");
+
+// Export the environments.
+let environmentGlobals = require("../lib/index.js").environments;
+
+return fs.writeFile(
+ globalsFile,
+ JSON.stringify({ environments: environmentGlobals }),
+ err => {
+ if (err) {
+ console.error(err);
+ process.exit(1);
+ }
+
+ console.log("Globals file generation complete");
+
+ console.log("Creating rules data file");
+ let rulesData = {};
+
+ return fs.writeFile(rulesFile, JSON.stringify({ rulesData }), err1 => {
+ if (err1) {
+ console.error(err1);
+ process.exit(1);
+ }
+
+ console.log("Globals file generation complete");
+ });
+ }
+);
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/tests/avoid-Date-timing.js b/tools/lint/eslint/eslint-plugin-mozilla/tests/avoid-Date-timing.js
new file mode 100644
index 0000000000..37fc424617
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/tests/avoid-Date-timing.js
@@ -0,0 +1,34 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// ------------------------------------------------------------------------------
+// Requirements
+// ------------------------------------------------------------------------------
+
+var rule = require("../lib/rules/avoid-Date-timing");
+var RuleTester = require("eslint").RuleTester;
+
+const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: "latest" } });
+
+// ------------------------------------------------------------------------------
+// Tests
+// ------------------------------------------------------------------------------
+
+function invalidCode(code, type, message) {
+ return { code, errors: [{ messageId: "usePerfNow", type }] };
+}
+
+ruleTester.run("avoid-Date-timing", rule, {
+ valid: [
+ "new Date('2017-07-11');",
+ "new Date(1499790192440);",
+ "new Date(2017, 7, 11);",
+ "Date.UTC(2017, 7);",
+ ],
+ invalid: [
+ invalidCode("Date.now();", "CallExpression"),
+ invalidCode("new Date();", "NewExpression"),
+ ],
+});
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/tests/avoid-removeChild.js b/tools/lint/eslint/eslint-plugin-mozilla/tests/avoid-removeChild.js
new file mode 100644
index 0000000000..3736f25853
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/tests/avoid-removeChild.js
@@ -0,0 +1,37 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// ------------------------------------------------------------------------------
+// Requirements
+// ------------------------------------------------------------------------------
+
+var rule = require("../lib/rules/avoid-removeChild");
+var RuleTester = require("eslint").RuleTester;
+
+const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: "latest" } });
+
+// ------------------------------------------------------------------------------
+// Tests
+// ------------------------------------------------------------------------------
+
+function invalidCode(code, messageId = "useRemove") {
+ return { code, errors: [{ messageId, type: "CallExpression" }] };
+}
+
+ruleTester.run("avoid-removeChild", rule, {
+ valid: [
+ "elt.remove();",
+ "elt.parentNode.parentNode.removeChild(elt2.parentNode);",
+ "elt.parentNode.removeChild(elt2);",
+ "elt.removeChild(elt2);",
+ ],
+ invalid: [
+ invalidCode("elt.parentNode.removeChild(elt);"),
+ invalidCode("elt.parentNode.parentNode.removeChild(elt.parentNode);"),
+ invalidCode("$(e).parentNode.removeChild($(e));"),
+ invalidCode("$('e').parentNode.removeChild($('e'));"),
+ invalidCode("elt.removeChild(elt.firstChild);", "useFirstChildRemove"),
+ ],
+});
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/tests/balanced-listeners.js b/tools/lint/eslint/eslint-plugin-mozilla/tests/balanced-listeners.js
new file mode 100644
index 0000000000..b7cd4e2c2f
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/tests/balanced-listeners.js
@@ -0,0 +1,100 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// ------------------------------------------------------------------------------
+// Requirements
+// ------------------------------------------------------------------------------
+
+var rule = require("../lib/rules/balanced-listeners");
+var RuleTester = require("eslint").RuleTester;
+
+const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: "latest" } });
+
+// ------------------------------------------------------------------------------
+// Tests
+// ------------------------------------------------------------------------------
+
+function error(code, functionName, type) {
+ return {
+ code,
+ errors: [
+ {
+ messageId: "noCorresponding",
+ type: "Identifier",
+ data: { functionName, type },
+ },
+ ],
+ };
+}
+
+ruleTester.run("balanced-listeners", rule, {
+ valid: [
+ "elt.addEventListener('event', handler);" +
+ "elt.removeEventListener('event', handler);",
+
+ "elt.addEventListener('event', handler, true);" +
+ "elt.removeEventListener('event', handler, true);",
+
+ "elt.addEventListener('event', handler, false);" +
+ "elt.removeEventListener('event', handler, false);",
+
+ "elt.addEventListener('event', handler);" +
+ "elt.removeEventListener('event', handler, false);",
+
+ "elt.addEventListener('event', handler, false);" +
+ "elt.removeEventListener('event', handler);",
+
+ "elt.addEventListener('event', handler, {capture: false});" +
+ "elt.removeEventListener('event', handler);",
+
+ "elt.addEventListener('event', handler);" +
+ "elt.removeEventListener('event', handler, {capture: false});",
+
+ "elt.addEventListener('event', handler, {capture: true});" +
+ "elt.removeEventListener('event', handler, true);",
+
+ "elt.addEventListener('event', handler, true);" +
+ "elt.removeEventListener('event', handler, {capture: true});",
+
+ "elt.addEventListener('event', handler, {once: true});",
+
+ "elt.addEventListener('event', handler, {once: true, capture: true});",
+ ],
+ invalid: [
+ error(
+ "elt.addEventListener('click', handler, false);",
+ "removeEventListener",
+ "click"
+ ),
+
+ error(
+ "elt.addEventListener('click', handler, false);" +
+ "elt.removeEventListener('click', handler, true);",
+ "removeEventListener",
+ "click"
+ ),
+
+ error(
+ "elt.addEventListener('click', handler, {capture: false});" +
+ "elt.removeEventListener('click', handler, true);",
+ "removeEventListener",
+ "click"
+ ),
+
+ error(
+ "elt.addEventListener('click', handler, {capture: true});" +
+ "elt.removeEventListener('click', handler);",
+ "removeEventListener",
+ "click"
+ ),
+
+ error(
+ "elt.addEventListener('click', handler, true);" +
+ "elt.removeEventListener('click', handler);",
+ "removeEventListener",
+ "click"
+ ),
+ ],
+});
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/tests/balanced-observers.js b/tools/lint/eslint/eslint-plugin-mozilla/tests/balanced-observers.js
new file mode 100644
index 0000000000..97e578a1f4
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/tests/balanced-observers.js
@@ -0,0 +1,80 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// ------------------------------------------------------------------------------
+// Requirements
+// ------------------------------------------------------------------------------
+
+var rule = require("../lib/rules/balanced-observers");
+var RuleTester = require("eslint").RuleTester;
+
+const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: "latest" } });
+
+// ------------------------------------------------------------------------------
+// Tests
+// ------------------------------------------------------------------------------
+
+function error(code, observable) {
+ return {
+ code,
+ errors: [
+ {
+ messageId: "noCorresponding",
+ type: "Identifier",
+ data: { observable },
+ },
+ ],
+ };
+}
+
+ruleTester.run("balanced-observers", rule, {
+ valid: [
+ "Services.obs.addObserver(observer, 'observable');" +
+ "Services.obs.removeObserver(observer, 'observable');",
+ "Services.prefs.addObserver('preference.name', otherObserver);" +
+ "Services.prefs.removeObserver('preference.name', otherObserver);",
+ ],
+ invalid: [
+ error(
+ // missing Services.obs.removeObserver
+ "Services.obs.addObserver(observer, 'observable');",
+ "observable"
+ ),
+
+ error(
+ // wrong observable name for Services.obs.removeObserver
+ "Services.obs.addObserver(observer, 'observable');" +
+ "Services.obs.removeObserver(observer, 'different-observable');",
+ "observable"
+ ),
+
+ error(
+ // missing Services.prefs.removeObserver
+ "Services.prefs.addObserver('preference.name', otherObserver);",
+ "preference.name"
+ ),
+
+ error(
+ // wrong observable name for Services.prefs.removeObserver
+ "Services.prefs.addObserver('preference.name', otherObserver);" +
+ "Services.prefs.removeObserver('other.preference', otherObserver);",
+ "preference.name"
+ ),
+
+ error(
+ // mismatch Services.prefs vs Services.obs
+ "Services.obs.addObserver(observer, 'observable');" +
+ "Services.prefs.removeObserver(observer, 'observable');",
+ "observable"
+ ),
+
+ error(
+ "Services.prefs.addObserver('preference.name', otherObserver);" +
+ // mismatch Services.prefs vs Services.obs
+ "Services.obs.removeObserver('preference.name', otherObserver);",
+ "preference.name"
+ ),
+ ],
+});
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/tests/consistent-if-bracing.js b/tools/lint/eslint/eslint-plugin-mozilla/tests/consistent-if-bracing.js
new file mode 100644
index 0000000000..9712fd9a78
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/tests/consistent-if-bracing.js
@@ -0,0 +1,39 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// ------------------------------------------------------------------------------
+// Requirements
+// ------------------------------------------------------------------------------
+
+var rule = require("../lib/rules/consistent-if-bracing");
+var RuleTester = require("eslint").RuleTester;
+
+const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: "latest" } });
+
+// ------------------------------------------------------------------------------
+// Tests
+// ------------------------------------------------------------------------------
+
+function invalidCode(code) {
+ return { code, errors: [{ messageId: "consistentIfBracing" }] };
+}
+
+ruleTester.run("consistent-if-bracing", rule, {
+ valid: [
+ "if (true) {1} else {0}",
+ "if (false) 1; else 0",
+ "if (true) {1} else if (true) {2} else {0}",
+ "if (true) {1} else if (true) {2} else if (true) {3} else {0}",
+ ],
+ invalid: [
+ invalidCode(`if (true) {1} else 0`),
+ invalidCode("if (true) 1; else {0}"),
+ invalidCode("if (true) {1} else if (true) 2; else {0}"),
+ invalidCode("if (true) 1; else if (true) {2} else {0}"),
+ invalidCode("if (true) {1} else if (true) {2} else 0"),
+ invalidCode("if (true) {1} else if (true) {2} else if (true) 3; else {0}"),
+ invalidCode("if (true) {if (true) 1; else {0}} else {0}"),
+ ],
+});
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/tests/globals.js b/tools/lint/eslint/eslint-plugin-mozilla/tests/globals.js
new file mode 100644
index 0000000000..1098cb8a34
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/tests/globals.js
@@ -0,0 +1,161 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+var { getGlobalsForCode } = require("../lib/globals");
+var assert = require("assert");
+
+/* global describe, it */
+
+describe("globals", function () {
+ it("should reflect top-level this property assignment", function () {
+ const globals = getGlobalsForCode(`
+this.foo = 10;
+`);
+ assert.deepEqual(globals, [{ name: "foo", writable: true }]);
+ });
+
+ it("should reflect this property assignment inside block", function () {
+ const globals = getGlobalsForCode(`
+{
+ this.foo = 10;
+}
+`);
+ assert.deepEqual(globals, [{ name: "foo", writable: true }]);
+ });
+
+ it("should ignore this property assignment inside function declaration", function () {
+ const globals = getGlobalsForCode(`
+function f() {
+ this.foo = 10;
+}
+`);
+ assert.deepEqual(globals, [{ name: "f", writable: true }]);
+ });
+
+ it("should ignore this property assignment inside function expression", function () {
+ const globals = getGlobalsForCode(`
+(function f() {
+ this.foo = 10;
+});
+`);
+ assert.deepEqual(globals, []);
+ });
+
+ it("should ignore this property assignment inside method", function () {
+ const globals = getGlobalsForCode(`
+({
+ method() {
+ this.foo = 10;
+ }
+});
+`);
+ assert.deepEqual(globals, []);
+ });
+
+ it("should ignore this property assignment inside accessor", function () {
+ const globals = getGlobalsForCode(`
+({
+ get x() {
+ this.foo = 10;
+ },
+ set x(v) {
+ this.bar = 10;
+ }
+});
+`);
+ assert.deepEqual(globals, []);
+ });
+
+ it("should reflect this property assignment inside arrow function", function () {
+ const globals = getGlobalsForCode(`
+() => {
+ this.foo = 10;
+};
+`);
+ assert.deepEqual(globals, [{ name: "foo", writable: true }]);
+ });
+
+ it("should ignore this property assignment inside arrow function inside function expression", function () {
+ const globals = getGlobalsForCode(`
+(function f() {
+ () => {
+ this.foo = 10;
+ };
+});
+`);
+ assert.deepEqual(globals, []);
+ });
+
+ it("should ignore this property assignment inside class static", function () {
+ const globals = getGlobalsForCode(`
+class A {
+ static {
+ this.foo = 10;
+ (() => {
+ this.bar = 10;
+ })();
+ }
+}
+`);
+ assert.deepEqual(globals, [{ name: "A", writable: true }]);
+ });
+
+ it("should ignore this property assignment inside class property", function () {
+ const globals = getGlobalsForCode(`
+class A {
+ a = this.foo = 10;
+ b = (() => {
+ this.bar = 10;
+ })();
+}
+`);
+ assert.deepEqual(globals, [{ name: "A", writable: true }]);
+ });
+
+ it("should ignore this property assignment inside class static property", function () {
+ const globals = getGlobalsForCode(`
+class A {
+ static a = this.foo = 10;
+ static b = (() => {
+ this.bar = 10;
+ })();
+}
+`);
+ assert.deepEqual(globals, [{ name: "A", writable: true }]);
+ });
+
+ it("should ignore this property assignment inside class private property", function () {
+ const globals = getGlobalsForCode(`
+class A {
+ #a = this.foo = 10;
+ #b = (() => {
+ this.bar = 10;
+ })();
+}
+`);
+ assert.deepEqual(globals, [{ name: "A", writable: true }]);
+ });
+
+ it("should ignore this property assignment inside class static private property", function () {
+ const globals = getGlobalsForCode(`
+class A {
+ static #a = this.foo = 10;
+ static #b = (() => {
+ this.bar = 10;
+ })();
+}
+`);
+ assert.deepEqual(globals, [{ name: "A", writable: true }]);
+ });
+
+ it("should reflect lazy getters", function () {
+ const globals = getGlobalsForCode(`
+ChromeUtils.defineESModuleGetters(this, {
+ A: "B",
+});
+`);
+ assert.deepEqual(globals, [{ name: "A", writable: true, explicit: true }]);
+ });
+});
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/tests/lazy-getter-object-name.js b/tools/lint/eslint/eslint-plugin-mozilla/tests/lazy-getter-object-name.js
new file mode 100644
index 0000000000..33a2a6c130
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/tests/lazy-getter-object-name.js
@@ -0,0 +1,51 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// ------------------------------------------------------------------------------
+// Requirements
+// ------------------------------------------------------------------------------
+
+var rule = require("../lib/rules/lazy-getter-object-name");
+var RuleTester = require("eslint").RuleTester;
+
+const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: "latest" } });
+
+// ------------------------------------------------------------------------------
+// Tests
+// ------------------------------------------------------------------------------
+
+function invalidCode(code) {
+ return {
+ code,
+ errors: [{ messageId: "mustUseLazy", type: "CallExpression" }],
+ };
+}
+
+ruleTester.run("lazy-getter-object-name", rule, {
+ valid: [
+ `
+ ChromeUtils.defineESModuleGetters(lazy, {
+ AppConstants: "resource://gre/modules/AppConstants.sys.mjs",
+ });
+`,
+ ],
+ invalid: [
+ invalidCode(`
+ ChromeUtils.defineESModuleGetters(obj, {
+ AppConstants: "resource://gre/modules/AppConstants.sys.mjs",
+ });
+`),
+ invalidCode(`
+ ChromeUtils.defineESModuleGetters(this, {
+ AppConstants: "resource://gre/modules/AppConstants.sys.mjs",
+ });
+`),
+ invalidCode(`
+ ChromeUtils.defineESModuleGetters(window, {
+ AppConstants: "resource://gre/modules/AppConstants.sys.mjs",
+ });
+`),
+ ],
+});
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/tests/mark-exported-symbols-as-used.js b/tools/lint/eslint/eslint-plugin-mozilla/tests/mark-exported-symbols-as-used.js
new file mode 100644
index 0000000000..e738825fab
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/tests/mark-exported-symbols-as-used.js
@@ -0,0 +1,45 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// ------------------------------------------------------------------------------
+// Requirements
+// ------------------------------------------------------------------------------
+
+var rule = require("../lib/rules/mark-exported-symbols-as-used");
+var RuleTester = require("eslint").RuleTester;
+
+const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: "latest" } });
+
+// ------------------------------------------------------------------------------
+// Tests
+// ------------------------------------------------------------------------------
+
+function invalidCode(code, type, messageId) {
+ return { code, errors: [{ messageId, type }] };
+}
+
+ruleTester.run("mark-exported-symbols-as-used", rule, {
+ valid: [
+ "var EXPORTED_SYMBOLS = ['foo'];",
+ "this.EXPORTED_SYMBOLS = ['foo'];",
+ ],
+ invalid: [
+ invalidCode(
+ "let EXPORTED_SYMBOLS = ['foo'];",
+ "VariableDeclaration",
+ "useLetForExported"
+ ),
+ invalidCode(
+ "var EXPORTED_SYMBOLS = 'foo';",
+ "VariableDeclaration",
+ "nonArrayAssignedToImported"
+ ),
+ invalidCode(
+ "this.EXPORTED_SYMBOLS = 'foo';",
+ "AssignmentExpression",
+ "nonArrayAssignedToImported"
+ ),
+ ],
+});
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/tests/no-addtask-setup.js b/tools/lint/eslint/eslint-plugin-mozilla/tests/no-addtask-setup.js
new file mode 100644
index 0000000000..cd036d7d91
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/tests/no-addtask-setup.js
@@ -0,0 +1,69 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// ------------------------------------------------------------------------------
+// Requirements
+// ------------------------------------------------------------------------------
+
+var rule = require("../lib/rules/no-addtask-setup");
+var RuleTester = require("eslint").RuleTester;
+
+const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: "latest" } });
+
+// ------------------------------------------------------------------------------
+// Tests
+// ------------------------------------------------------------------------------
+
+function callError() {
+ return [{ messageId: "useAddSetup", type: "CallExpression" }];
+}
+
+ruleTester.run("no-addtask-setup", rule, {
+ valid: [
+ "add_task(function() {});",
+ "add_task(function () {});",
+ "add_task(function foo() {});",
+ "add_task(async function() {});",
+ "add_task(async function () {});",
+ "add_task(async function foo() {});",
+ "something(function setup() {});",
+ "something(async function setup() {});",
+ "add_task(setup);",
+ "add_task(setup => {});",
+ "add_task(async setup => {});",
+ ],
+ invalid: [
+ {
+ code: "add_task(function setup() {});",
+ output: "add_setup(function() {});",
+ errors: callError(),
+ },
+ {
+ code: "add_task(function setup () {});",
+ output: "add_setup(function () {});",
+ errors: callError(),
+ },
+ {
+ code: "add_task(async function setup() {});",
+ output: "add_setup(async function() {});",
+ errors: callError(),
+ },
+ {
+ code: "add_task(async function setup () {});",
+ output: "add_setup(async function () {});",
+ errors: callError(),
+ },
+ {
+ code: "add_task(async function setUp() {});",
+ output: "add_setup(async function() {});",
+ errors: callError(),
+ },
+ {
+ code: "add_task(async function init() {});",
+ output: "add_setup(async function() {});",
+ errors: callError(),
+ },
+ ],
+});
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/tests/no-arbitrary-setTimeout.js b/tools/lint/eslint/eslint-plugin-mozilla/tests/no-arbitrary-setTimeout.js
new file mode 100644
index 0000000000..ea194af6e3
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/tests/no-arbitrary-setTimeout.js
@@ -0,0 +1,39 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// ------------------------------------------------------------------------------
+// Requirements
+// ------------------------------------------------------------------------------
+
+var rule = require("../lib/rules/no-arbitrary-setTimeout");
+var RuleTester = require("eslint").RuleTester;
+
+const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: "latest" } });
+
+// ------------------------------------------------------------------------------
+// Tests
+// ------------------------------------------------------------------------------
+
+function wrapCode(code, filename = "xpcshell/test_foo.js") {
+ return { code, filename };
+}
+
+function invalidCode(code) {
+ let obj = wrapCode(code);
+ obj.errors = [{ messageId: "listenForEvents", type: "CallExpression" }];
+ return obj;
+}
+
+ruleTester.run("no-arbitrary-setTimeout", rule, {
+ valid: [
+ wrapCode("setTimeout(function() {}, 0);"),
+ wrapCode("setTimeout(function() {});"),
+ wrapCode("setTimeout(function() {}, 10);", "test_foo.js"),
+ ],
+ invalid: [
+ invalidCode("setTimeout(function() {}, 10);"),
+ invalidCode("setTimeout(function() {}, timeout);"),
+ ],
+});
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/tests/no-compare-against-boolean-literals.js b/tools/lint/eslint/eslint-plugin-mozilla/tests/no-compare-against-boolean-literals.js
new file mode 100644
index 0000000000..983ff0583e
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/tests/no-compare-against-boolean-literals.js
@@ -0,0 +1,59 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// ------------------------------------------------------------------------------
+// Requirements
+// ------------------------------------------------------------------------------
+
+var rule = require("../lib/rules/no-compare-against-boolean-literals");
+var RuleTester = require("eslint").RuleTester;
+
+const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: "latest" } });
+
+// ------------------------------------------------------------------------------
+// Tests
+// ------------------------------------------------------------------------------
+
+function callError() {
+ return [{ messageId: "noCompareBoolean", type: "BinaryExpression" }];
+}
+
+ruleTester.run("no-compare-against-boolean-literals", rule, {
+ valid: [`if (!foo) {}`, `if (!!foo) {}`],
+ invalid: [
+ {
+ code: `if (foo == true) {}`,
+ errors: callError(),
+ },
+ {
+ code: `if (foo != true) {}`,
+ errors: callError(),
+ },
+ {
+ code: `if (foo == false) {}`,
+ errors: callError(),
+ },
+ {
+ code: `if (foo != false) {}`,
+ errors: callError(),
+ },
+ {
+ code: `if (true == foo) {}`,
+ errors: callError(),
+ },
+ {
+ code: `if (true != foo) {}`,
+ errors: callError(),
+ },
+ {
+ code: `if (false == foo) {}`,
+ errors: callError(),
+ },
+ {
+ code: `if (false != foo) {}`,
+ errors: callError(),
+ },
+ ],
+});
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/tests/no-comparison-or-assignment-inside-ok.js b/tools/lint/eslint/eslint-plugin-mozilla/tests/no-comparison-or-assignment-inside-ok.js
new file mode 100644
index 0000000000..3c43e5879f
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/tests/no-comparison-or-assignment-inside-ok.js
@@ -0,0 +1,139 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// ------------------------------------------------------------------------------
+// Requirements
+// ------------------------------------------------------------------------------
+
+var rule = require("../lib/rules/no-comparison-or-assignment-inside-ok");
+var RuleTester = require("eslint").RuleTester;
+
+const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: "latest" } });
+
+// ------------------------------------------------------------------------------
+// Tests
+// ------------------------------------------------------------------------------
+
+function invalidCode(code, output, messageId, options = []) {
+ let rv = {
+ code,
+ errors: [{ messageId }],
+ };
+ if (output) {
+ rv.output = output;
+ }
+ return rv;
+}
+
+ruleTester.run("no-comparison-or-assignment-inside-ok", rule, {
+ valid: [
+ "ok(foo)",
+ "ok(!bar)",
+ "ok(!foo, 'Message')",
+ "ok(bar, 'Message')",
+ "ok(!!foo, 'Message')",
+ ],
+ invalid: [
+ // Assignment
+ invalidCode("ok(foo = bar)", null, "assignment"),
+ invalidCode("ok(foo = bar, 'msg')", null, "assignment"),
+
+ // Comparisons:
+ invalidCode("ok(foo == bar)", "Assert.equal(foo, bar)", "comparison", {
+ operator: "==",
+ }),
+ invalidCode("ok(foo != bar)", "Assert.notEqual(foo, bar)", "comparison", {
+ operator: "!=",
+ }),
+ invalidCode("ok(foo < bar)", "Assert.less(foo, bar)", "comparison", {
+ operator: "<",
+ }),
+ invalidCode("ok(foo > bar)", "Assert.greater(foo, bar)", "comparison", {
+ operator: ">",
+ }),
+ invalidCode(
+ "ok(foo <= bar)",
+ "Assert.lessOrEqual(foo, bar)",
+ "comparison",
+ { operator: "<=" }
+ ),
+ invalidCode(
+ "ok(foo >= bar)",
+ "Assert.greaterOrEqual(foo, bar)",
+ "comparison",
+ { operator: ">=" }
+ ),
+ invalidCode(
+ "ok(foo === bar)",
+ "Assert.strictEqual(foo, bar)",
+ "comparison",
+ { operator: "===" }
+ ),
+ invalidCode(
+ "ok(foo !== bar)",
+ "Assert.notStrictEqual(foo, bar)",
+ "comparison",
+ { operator: "!==" }
+ ),
+
+ // Comparisons with messages:
+ invalidCode(
+ "ok(foo == bar, 'hi')",
+ "Assert.equal(foo, bar, 'hi')",
+ "comparison",
+ { operator: "==" }
+ ),
+ invalidCode(
+ "ok(foo != bar, 'hi')",
+ "Assert.notEqual(foo, bar, 'hi')",
+ "comparison",
+ { operator: "!=" }
+ ),
+ invalidCode(
+ "ok(foo < bar, 'hi')",
+ "Assert.less(foo, bar, 'hi')",
+ "comparison",
+ { operator: "<" }
+ ),
+ invalidCode(
+ "ok(foo > bar, 'hi')",
+ "Assert.greater(foo, bar, 'hi')",
+ "comparison",
+ { operator: ">" }
+ ),
+ invalidCode(
+ "ok(foo <= bar, 'hi')",
+ "Assert.lessOrEqual(foo, bar, 'hi')",
+ "comparison",
+ { operator: "<=" }
+ ),
+ invalidCode(
+ "ok(foo >= bar, 'hi')",
+ "Assert.greaterOrEqual(foo, bar, 'hi')",
+ "comparison",
+ { operator: ">=" }
+ ),
+ invalidCode(
+ "ok(foo === bar, 'hi')",
+ "Assert.strictEqual(foo, bar, 'hi')",
+ "comparison",
+ { operator: "===" }
+ ),
+ invalidCode(
+ "ok(foo !== bar, 'hi')",
+ "Assert.notStrictEqual(foo, bar, 'hi')",
+ "comparison",
+ { operator: "!==" }
+ ),
+
+ // Confusing bits that break fixup:
+ invalidCode(
+ "async () => ok((await foo) === bar, 'Oh no')",
+ "async () => Assert.strictEqual(await foo, bar, 'Oh no')",
+ "comparison",
+ { operator: "===" }
+ ),
+ ],
+});
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/tests/no-cu-reportError.js b/tools/lint/eslint/eslint-plugin-mozilla/tests/no-cu-reportError.js
new file mode 100644
index 0000000000..6650c8bf4e
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/tests/no-cu-reportError.js
@@ -0,0 +1,100 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// ------------------------------------------------------------------------------
+// Requirements
+// ------------------------------------------------------------------------------
+
+var rule = require("../lib/rules/no-cu-reportError");
+var RuleTester = require("eslint").RuleTester;
+
+const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: "latest" } });
+
+// ------------------------------------------------------------------------------
+// Tests
+// ------------------------------------------------------------------------------
+
+function callError() {
+ return [{ messageId: "useConsoleError", type: "CallExpression" }];
+}
+
+ruleTester.run("no-cu-reportError", rule, {
+ valid: [
+ "console.error('foo')",
+ "Cu.cloneInto({}, {})",
+ "foo().catch(console.error)",
+ // TODO: Bug 1802347 - this should be treated as an error as well.
+ "Cu.reportError('foo', stack)",
+ ],
+ invalid: [
+ {
+ code: "Cu.reportError('foo')",
+ output: "console.error('foo')",
+ errors: callError(),
+ },
+ {
+ code: "Cu.reportError(bar)",
+ output: "console.error(bar)",
+ errors: callError(),
+ },
+ {
+ code: "Cu.reportError(bar.stack)",
+ output: "console.error(bar.stack)",
+ errors: callError(),
+ },
+ {
+ code: "foo().catch(Cu.reportError)",
+ output: "foo().catch(console.error)",
+ errors: callError(),
+ },
+ {
+ code: "foo().then(bar, Cu.reportError)",
+ output: "foo().then(bar, console.error)",
+ errors: callError(),
+ },
+ // When referencing identifiers/members, try to reference them rather
+ // than stringifying:
+ {
+ code: "Cu.reportError('foo' + e)",
+ output: "console.error('foo', e)",
+ errors: callError(),
+ },
+ {
+ code: "Cu.reportError('foo' + msg.data)",
+ output: "console.error('foo', msg.data)",
+ errors: callError(),
+ },
+ // Don't touch existing concatenation of literals (usually done for
+ // wrapping reasons)
+ {
+ code: "Cu.reportError('foo' + 'bar' + 'baz')",
+ output: "console.error('foo' + 'bar' + 'baz')",
+ errors: callError(),
+ },
+ // Ensure things work when nested:
+ {
+ code: "Cu.reportError('foo' + e + 'baz')",
+ output: "console.error('foo', e, 'baz')",
+ errors: callError(),
+ },
+ // Ensure things work when nested in different places:
+ {
+ code: "Cu.reportError('foo' + e + 'quux' + 'baz')",
+ output: "console.error('foo', e, 'quux' + 'baz')",
+ errors: callError(),
+ },
+ {
+ code: "Cu.reportError('foo' + 'quux' + e + 'baz')",
+ output: "console.error('foo' + 'quux', e, 'baz')",
+ errors: callError(),
+ },
+ // Ensure things work with parens changing order of operations:
+ {
+ code: "Cu.reportError('foo' + 'quux' + (e + 'baz'))",
+ output: "console.error('foo' + 'quux' + (e + 'baz'))",
+ errors: callError(),
+ },
+ ],
+});
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/tests/no-define-cc-etc.js b/tools/lint/eslint/eslint-plugin-mozilla/tests/no-define-cc-etc.js
new file mode 100644
index 0000000000..ed71f6087e
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/tests/no-define-cc-etc.js
@@ -0,0 +1,63 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// ------------------------------------------------------------------------------
+// Requirements
+// ------------------------------------------------------------------------------
+
+var rule = require("../lib/rules/no-define-cc-etc");
+var RuleTester = require("eslint").RuleTester;
+
+const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: "latest" } });
+
+// ------------------------------------------------------------------------------
+// Tests
+// ------------------------------------------------------------------------------
+
+function invalidCode(code, varNames) {
+ if (!Array.isArray(varNames)) {
+ varNames = [varNames];
+ }
+ return {
+ code,
+ errors: varNames.map(name => {
+ return {
+ messageId: "noSeparateDefinition",
+ data: { name },
+ type: "VariableDeclarator",
+ };
+ }),
+ };
+}
+
+ruleTester.run("no-define-cc-etc", rule, {
+ valid: [
+ "var Cm = Components.manager;",
+ "const CC = Components.Constructor;",
+ "var {Constructor: CC, manager: Cm} = Components;",
+ "const {Constructor: CC, manager: Cm} = Components;",
+ "foo.Cc.test();",
+ "const {bar, ...foo} = obj;",
+ ],
+ invalid: [
+ invalidCode("var Cc;", "Cc"),
+ invalidCode("let Cc;", "Cc"),
+ invalidCode("let Ci;", "Ci"),
+ invalidCode("let Cr;", "Cr"),
+ invalidCode("let Cu;", "Cu"),
+ invalidCode("var Cc = Components.classes;", "Cc"),
+ invalidCode("const {classes: Cc} = Components;", "Cc"),
+ invalidCode("let {classes: Cc, manager: Cm} = Components", "Cc"),
+ invalidCode("const Cu = Components.utils;", "Cu"),
+ invalidCode("var Ci = Components.interfaces, Cc = Components.classes;", [
+ "Ci",
+ "Cc",
+ ]),
+ invalidCode("var {'interfaces': Ci, 'classes': Cc} = Components;", [
+ "Ci",
+ "Cc",
+ ]),
+ ],
+});
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/tests/no-redeclare-with-import-autofix.js b/tools/lint/eslint/eslint-plugin-mozilla/tests/no-redeclare-with-import-autofix.js
new file mode 100644
index 0000000000..36842000d5
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/tests/no-redeclare-with-import-autofix.js
@@ -0,0 +1,77 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// ------------------------------------------------------------------------------
+// Requirements
+// ------------------------------------------------------------------------------
+
+var rule = require("../lib/rules/no-redeclare-with-import-autofix");
+var RuleTester = require("eslint").RuleTester;
+
+const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: "latest" } });
+
+// ------------------------------------------------------------------------------
+// Tests
+// ------------------------------------------------------------------------------
+
+function invalidCode(code, output, messageId, options = []) {
+ let rv = {
+ code,
+ errors: [{ messageId }],
+ options,
+ };
+ if (output) {
+ rv.output = output;
+ }
+ return rv;
+}
+
+ruleTester.run("no-redeclare-with-import-autofix", rule, {
+ valid: [
+ 'const foo = "whatever";',
+ 'let foo = "whatever";',
+ 'const {foo} = {foo: "whatever"};',
+ 'const {foo} = ChromeUtils.import("foo.jsm")',
+ 'let {foo} = ChromeUtils.import("foo.jsm")',
+ 'const {foo} = ChromeUtils.importESModule("foo.sys.mjs")',
+ 'let {foo} = ChromeUtils.importESModule("foo.sys.mjs")',
+ ],
+ invalid: [
+ invalidCode(
+ `var {foo} = ChromeUtils.importESModule("foo.sys.mjs");
+var {foo} = ChromeUtils.importESModule("foo.sys.mjs");`,
+ 'var {foo} = ChromeUtils.importESModule("foo.sys.mjs");\n',
+ "duplicateImport"
+ ),
+ invalidCode(
+ `var {foo} = ChromeUtils.import("foo.jsm");
+var {foo} = ChromeUtils.import("foo.jsm");`,
+ 'var {foo} = ChromeUtils.import("foo.jsm");\n',
+ "duplicateImport"
+ ),
+
+ invalidCode(
+ `var {foo} = ChromeUtils.import("foo.jsm");
+var {foo, bar} = ChromeUtils.import("foo.jsm");`,
+ `var {foo} = ChromeUtils.import("foo.jsm");
+var { bar} = ChromeUtils.import("foo.jsm");`,
+ "duplicateImport"
+ ),
+
+ invalidCode(
+ `var {foo} = ChromeUtils.import("foo.jsm");
+var {bar, foo} = ChromeUtils.import("foo.jsm");`,
+ `var {foo} = ChromeUtils.import("foo.jsm");
+var {bar} = ChromeUtils.import("foo.jsm");`,
+ "duplicateImport"
+ ),
+
+ invalidCode(`var foo = 5; var foo = 10;`, "", "redeclared", [
+ {
+ errorForNonImports: true,
+ },
+ ]),
+ ],
+});
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/tests/no-throw-cr-literal.js b/tools/lint/eslint/eslint-plugin-mozilla/tests/no-throw-cr-literal.js
new file mode 100644
index 0000000000..aecc5cd971
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/tests/no-throw-cr-literal.js
@@ -0,0 +1,62 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// ------------------------------------------------------------------------------
+// Requirements
+// ------------------------------------------------------------------------------
+
+var rule = require("../lib/rules/no-throw-cr-literal");
+var RuleTester = require("eslint").RuleTester;
+
+const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: "latest" } });
+
+// ------------------------------------------------------------------------------
+// Tests
+// ------------------------------------------------------------------------------
+
+function invalidCode(code, output, messageId) {
+ return {
+ code,
+ output,
+ errors: [{ messageId, type: "ThrowStatement" }],
+ };
+}
+
+ruleTester.run("no-throw-cr-literal", rule, {
+ valid: [
+ 'throw Components.Exception("", Cr.NS_ERROR_NOT_IMPLEMENTED);',
+ 'throw Components.Exception("", Components.results.NS_ERROR_UNEXPECTED);',
+ 'function t() { throw Components.Exception("", Cr.NS_ERROR_NO_CONTENT); }',
+ // We don't handle combined values, regular no-throw-literal catches them
+ 'throw Components.results.NS_ERROR_UNEXPECTED + "whoops";',
+ ],
+ invalid: [
+ invalidCode(
+ "throw Cr.NS_ERROR_NO_INTERFACE;",
+ 'throw Components.Exception("", Cr.NS_ERROR_NO_INTERFACE);',
+ "bareCR"
+ ),
+ invalidCode(
+ "throw Components.results.NS_ERROR_ABORT;",
+ 'throw Components.Exception("", Components.results.NS_ERROR_ABORT);',
+ "bareComponentsResults"
+ ),
+ invalidCode(
+ "function t() { throw Cr.NS_ERROR_NULL_POINTER; }",
+ 'function t() { throw Components.Exception("", Cr.NS_ERROR_NULL_POINTER); }',
+ "bareCR"
+ ),
+ invalidCode(
+ "throw new Error(Cr.NS_ERROR_ABORT);",
+ 'throw Components.Exception("", Cr.NS_ERROR_ABORT);',
+ "newErrorCR"
+ ),
+ invalidCode(
+ "throw new Error(Components.results.NS_ERROR_ABORT);",
+ 'throw Components.Exception("", Components.results.NS_ERROR_ABORT);',
+ "newErrorComponentsResults"
+ ),
+ ],
+});
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/tests/no-useless-parameters.js b/tools/lint/eslint/eslint-plugin-mozilla/tests/no-useless-parameters.js
new file mode 100644
index 0000000000..28d4d0d151
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/tests/no-useless-parameters.js
@@ -0,0 +1,175 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// ------------------------------------------------------------------------------
+// Requirements
+// ------------------------------------------------------------------------------
+
+var rule = require("../lib/rules/no-useless-parameters");
+var RuleTester = require("eslint").RuleTester;
+
+const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: "latest" } });
+
+// ------------------------------------------------------------------------------
+// Tests
+// ------------------------------------------------------------------------------
+
+function callError(messageId, data = {}) {
+ return [{ messageId, data, type: "CallExpression" }];
+}
+
+ruleTester.run("no-useless-parameters", rule, {
+ valid: [
+ "Services.prefs.clearUserPref('browser.search.custom');",
+ "Services.removeObserver('notification name', {});",
+ "Services.io.newURI('http://example.com');",
+ "Services.io.newURI('http://example.com', 'utf8');",
+ "elt.addEventListener('click', handler);",
+ "elt.addEventListener('click', handler, true);",
+ "elt.addEventListener('click', handler, {once: true});",
+ "elt.removeEventListener('click', handler);",
+ "elt.removeEventListener('click', handler, true);",
+ "Services.obs.addObserver(this, 'topic', true);",
+ "Services.obs.addObserver(this, 'topic');",
+ "Services.prefs.addObserver('branch', this, true);",
+ "Services.prefs.addObserver('branch', this);",
+ "array.appendElement(elt);",
+ "Services.obs.notifyObservers(obj, 'topic', 'data');",
+ "Services.obs.notifyObservers(obj, 'topic');",
+ "window.getComputedStyle(elt);",
+ "window.getComputedStyle(elt, ':before');",
+ ],
+ invalid: [
+ {
+ code: "Services.prefs.clearUserPref('browser.search.custom', false);",
+ output: "Services.prefs.clearUserPref('browser.search.custom');",
+ errors: callError("onlyTakes", {
+ fnName: "clearUserPref",
+ params: "1 parameter",
+ }),
+ },
+ {
+ code: "Services.prefs.clearUserPref('browser.search.custom',\n false);",
+ output: "Services.prefs.clearUserPref('browser.search.custom');",
+ errors: callError("onlyTakes", {
+ fnName: "clearUserPref",
+ params: "1 parameter",
+ }),
+ },
+ {
+ code: "Services.removeObserver('notification name', {}, false);",
+ output: "Services.removeObserver('notification name', {});",
+ errors: callError("onlyTakes", {
+ fnName: "removeObserver",
+ params: "2 parameters",
+ }),
+ },
+ {
+ code: "Services.removeObserver('notification name', {}, true);",
+ output: "Services.removeObserver('notification name', {});",
+ errors: callError("onlyTakes", {
+ fnName: "removeObserver",
+ params: "2 parameters",
+ }),
+ },
+ {
+ code: "Services.io.newURI('http://example.com', null, null);",
+ output: "Services.io.newURI('http://example.com');",
+ errors: callError("newURIParams"),
+ },
+ {
+ code: "Services.io.newURI('http://example.com', 'utf8', null);",
+ output: "Services.io.newURI('http://example.com', 'utf8');",
+ errors: callError("newURIParams"),
+ },
+ {
+ code: "Services.io.newURI('http://example.com', null);",
+ output: "Services.io.newURI('http://example.com');",
+ errors: callError("newURIParams"),
+ },
+ {
+ code: "Services.io.newURI('http://example.com', '', '');",
+ output: "Services.io.newURI('http://example.com');",
+ errors: callError("newURIParams"),
+ },
+ {
+ code: "Services.io.newURI('http://example.com', '');",
+ output: "Services.io.newURI('http://example.com');",
+ errors: callError("newURIParams"),
+ },
+ {
+ code: "elt.addEventListener('click', handler, false);",
+ output: "elt.addEventListener('click', handler);",
+ errors: callError("obmittedWhenFalse", {
+ fnName: "addEventListener",
+ index: "third",
+ }),
+ },
+ {
+ code: "elt.removeEventListener('click', handler, false);",
+ output: "elt.removeEventListener('click', handler);",
+ errors: callError("obmittedWhenFalse", {
+ fnName: "removeEventListener",
+ index: "third",
+ }),
+ },
+ {
+ code: "Services.obs.addObserver(this, 'topic', false);",
+ output: "Services.obs.addObserver(this, 'topic');",
+ errors: callError("obmittedWhenFalse", {
+ fnName: "addObserver",
+ index: "third",
+ }),
+ },
+ {
+ code: "Services.prefs.addObserver('branch', this, false);",
+ output: "Services.prefs.addObserver('branch', this);",
+ errors: callError("obmittedWhenFalse", {
+ fnName: "addObserver",
+ index: "third",
+ }),
+ },
+ {
+ code: "array.appendElement(elt, false);",
+ output: "array.appendElement(elt);",
+ errors: callError("obmittedWhenFalse", {
+ fnName: "appendElement",
+ index: "second",
+ }),
+ },
+ {
+ code: "Services.obs.notifyObservers(obj, 'topic', null);",
+ output: "Services.obs.notifyObservers(obj, 'topic');",
+ errors: callError("obmittedWhenFalse", {
+ fnName: "notifyObservers",
+ index: "third",
+ }),
+ },
+ {
+ code: "Services.obs.notifyObservers(obj, 'topic', '');",
+ output: "Services.obs.notifyObservers(obj, 'topic');",
+ errors: callError("obmittedWhenFalse", {
+ fnName: "notifyObservers",
+ index: "third",
+ }),
+ },
+ {
+ code: "window.getComputedStyle(elt, null);",
+ output: "window.getComputedStyle(elt);",
+ errors: callError("obmittedWhenFalse", {
+ fnName: "getComputedStyle",
+ index: "second",
+ }),
+ },
+ {
+ code: "window.getComputedStyle(elt, '');",
+ output: "window.getComputedStyle(elt);",
+ errors: callError("obmittedWhenFalse", {
+ fnName: "getComputedStyle",
+ index: "second",
+ }),
+ },
+ ],
+});
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/tests/no-useless-removeEventListener.js b/tools/lint/eslint/eslint-plugin-mozilla/tests/no-useless-removeEventListener.js
new file mode 100644
index 0000000000..f5fc60158d
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/tests/no-useless-removeEventListener.js
@@ -0,0 +1,96 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// ------------------------------------------------------------------------------
+// Requirements
+// ------------------------------------------------------------------------------
+
+var rule = require("../lib/rules/no-useless-removeEventListener");
+var RuleTester = require("eslint").RuleTester;
+
+const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: "latest" } });
+
+// ------------------------------------------------------------------------------
+// Tests
+// ------------------------------------------------------------------------------
+
+function invalidCode(code) {
+ return { code, errors: [{ messageId: "useOnce", type: "CallExpression" }] };
+}
+
+ruleTester.run("no-useless-removeEventListener", rule, {
+ valid: [
+ // Listeners that aren't a function are always valid.
+ "elt.addEventListener('click', handler);",
+ "elt.addEventListener('click', handler, true);",
+ "elt.addEventListener('click', handler, {once: true});",
+
+ // Should not fail on empty functions.
+ "elt.addEventListener('click', function() {});",
+
+ // Should not reject when removing a listener for another event.
+ "elt.addEventListener('click', function listener() {" +
+ " elt.removeEventListener('keypress', listener);" +
+ "});",
+
+ // Should not reject when there's another instruction before
+ // removeEventListener.
+ "elt.addEventListener('click', function listener() {" +
+ " elt.focus();" +
+ " elt.removeEventListener('click', listener);" +
+ "});",
+
+ // Should not reject when wantsUntrusted is true.
+ "elt.addEventListener('click', function listener() {" +
+ " elt.removeEventListener('click', listener);" +
+ "}, false, true);",
+
+ // Should not reject when there's a literal and a variable
+ "elt.addEventListener('click', function listener() {" +
+ " elt.removeEventListener(eventName, listener);" +
+ "});",
+
+ // Should not reject when there's 2 different variables
+ "elt.addEventListener(event1, function listener() {" +
+ " elt.removeEventListener(event2, listener);" +
+ "});",
+
+ // Should not fail if this is a different type of event listener function.
+ "myfunc.addEventListener(listener);",
+ ],
+ invalid: [
+ invalidCode(
+ "elt.addEventListener('click', function listener() {" +
+ " elt.removeEventListener('click', listener);" +
+ "});"
+ ),
+ invalidCode(
+ "elt.addEventListener('click', function listener() {" +
+ " elt.removeEventListener('click', listener, true);" +
+ "}, true);"
+ ),
+ invalidCode(
+ "elt.addEventListener('click', function listener() {" +
+ " elt.removeEventListener('click', listener);" +
+ "}, {once: true});"
+ ),
+ invalidCode(
+ "elt.addEventListener('click', function listener() {" +
+ " /* Comment */" +
+ " elt.removeEventListener('click', listener);" +
+ "});"
+ ),
+ invalidCode(
+ "elt.addEventListener('click', function() {" +
+ " elt.removeEventListener('click', arguments.callee);" +
+ "});"
+ ),
+ invalidCode(
+ "elt.addEventListener(eventName, function listener() {" +
+ " elt.removeEventListener(eventName, listener);" +
+ "});"
+ ),
+ ],
+});
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/tests/no-useless-run-test.js b/tools/lint/eslint/eslint-plugin-mozilla/tests/no-useless-run-test.js
new file mode 100644
index 0000000000..5ee6e0e575
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/tests/no-useless-run-test.js
@@ -0,0 +1,126 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// ------------------------------------------------------------------------------
+// Requirements
+// ------------------------------------------------------------------------------
+
+var rule = require("../lib/rules/no-useless-run-test");
+var RuleTester = require("eslint").RuleTester;
+
+const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: "latest" } });
+
+// ------------------------------------------------------------------------------
+// Tests
+// ------------------------------------------------------------------------------
+
+function invalidCode(code, output) {
+ return {
+ code,
+ output,
+ errors: [{ messageId: "noUselessRunTest", type: "FunctionDeclaration" }],
+ };
+}
+
+ruleTester.run("no-useless-run-test", rule, {
+ valid: [
+ "function run_test() {}",
+ "function run_test() {let args = 1; run_next_test();}",
+ "function run_test() {fakeCall(); run_next_test();}",
+ ],
+ invalid: [
+ // Single-line case.
+ invalidCode("function run_test() { run_next_test(); }", ""),
+ // Multiple-line cases
+ invalidCode(
+ `
+function run_test() {
+ run_next_test();
+}`,
+ ``
+ ),
+ invalidCode(
+ `
+foo();
+function run_test() {
+ run_next_test();
+}
+`,
+ `
+foo();
+`
+ ),
+ invalidCode(
+ `
+foo();
+function run_test() {
+ run_next_test();
+}
+bar();
+`,
+ `
+foo();
+bar();
+`
+ ),
+ invalidCode(
+ `
+foo();
+
+function run_test() {
+ run_next_test();
+}
+
+bar();`,
+ `
+foo();
+
+bar();`
+ ),
+ invalidCode(
+ `
+foo();
+
+function run_test() {
+ run_next_test();
+}
+
+// A comment
+bar();
+`,
+ `
+foo();
+
+// A comment
+bar();
+`
+ ),
+ invalidCode(
+ `
+foo();
+
+/**
+ * A useful comment.
+ */
+function run_test() {
+ run_next_test();
+}
+
+// A comment
+bar();
+`,
+ `
+foo();
+
+/**
+ * A useful comment.
+ */
+
+// A comment
+bar();
+`
+ ),
+ ],
+});
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/tests/prefer-boolean-length-check.js b/tools/lint/eslint/eslint-plugin-mozilla/tests/prefer-boolean-length-check.js
new file mode 100644
index 0000000000..102112a3f5
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/tests/prefer-boolean-length-check.js
@@ -0,0 +1,96 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// ------------------------------------------------------------------------------
+// Requirements
+// ------------------------------------------------------------------------------
+
+var rule = require("../lib/rules/prefer-boolean-length-check");
+var RuleTester = require("eslint").RuleTester;
+
+const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: "latest" } });
+
+// ------------------------------------------------------------------------------
+// Tests
+// ------------------------------------------------------------------------------
+
+function invalidError() {
+ return [{ messageId: "preferBooleanCheck", type: "BinaryExpression" }];
+}
+
+ruleTester.run("check-length", rule, {
+ valid: [
+ "if (foo.length && foo.length) {}",
+ "if (!foo.length) {}",
+ "if (foo.value == 0) {}",
+ "if (foo.value > 0) {}",
+ "if (0 == foo.value) {}",
+ "if (0 < foo.value) {}",
+ "var a = !!foo.length",
+ "function bar() { return !!foo.length }",
+ ],
+ invalid: [
+ {
+ code: "if (foo.length == 0) {}",
+ output: "if (!foo.length) {}",
+ errors: invalidError(),
+ },
+ {
+ code: "if (foo.length > 0) {}",
+ output: "if (foo.length) {}",
+ errors: invalidError(),
+ },
+ {
+ code: "if (0 < foo.length) {}",
+ output: "if (foo.length) {}",
+ errors: invalidError(),
+ },
+ {
+ code: "if (0 == foo.length) {}",
+ output: "if (!foo.length) {}",
+ errors: invalidError(),
+ },
+ {
+ code: "if (foo && foo.length == 0) {}",
+ output: "if (foo && !foo.length) {}",
+ errors: invalidError(),
+ },
+ {
+ code: "if (foo.bar.length == 0) {}",
+ output: "if (!foo.bar.length) {}",
+ errors: invalidError(),
+ },
+ {
+ code: "var a = foo.length>0",
+ output: "var a = !!foo.length",
+ errors: invalidError(),
+ },
+ {
+ code: "function bar() { return foo.length>0 }",
+ output: "function bar() { return !!foo.length }",
+ errors: invalidError(),
+ },
+ {
+ code: "if (foo && bar.length>0) {}",
+ output: "if (foo && bar.length) {}",
+ errors: invalidError(),
+ },
+ {
+ code: "while (foo && bar.length>0) {}",
+ output: "while (foo && bar.length) {}",
+ errors: invalidError(),
+ },
+ {
+ code: "x = y && bar.length > 0",
+ output: "x = y && !!bar.length",
+ errors: invalidError(),
+ },
+ {
+ code: "function bar() { return x && foo.length > 0}",
+ output: "function bar() { return x && !!foo.length}",
+ errors: invalidError(),
+ },
+ ],
+});
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/tests/prefer-formatValues.js b/tools/lint/eslint/eslint-plugin-mozilla/tests/prefer-formatValues.js
new file mode 100644
index 0000000000..4aa5cd1d3c
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/tests/prefer-formatValues.js
@@ -0,0 +1,70 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// ------------------------------------------------------------------------------
+// Requirements
+// ------------------------------------------------------------------------------
+
+var rule = require("../lib/rules/prefer-formatValues");
+var RuleTester = require("eslint").RuleTester;
+
+const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: "latest" } });
+
+// ------------------------------------------------------------------------------
+// Tests
+// ------------------------------------------------------------------------------
+
+function error(line, column = undefined) {
+ return {
+ messageId: "useSingleCall",
+ type: "CallExpression",
+ line,
+ column,
+ };
+}
+
+ruleTester.run("check-length", rule, {
+ valid: [
+ "document.l10n.formatValue('foobar');",
+ "document.l10n.formatValues(['foobar', 'foobaz']);",
+ `if (foo) {
+ document.l10n.formatValue('foobar');
+ } else {
+ document.l10n.formatValue('foobaz');
+ }`,
+ `document.l10n.formatValue('foobaz');
+ if (foo) {
+ document.l10n.formatValue('foobar');
+ }`,
+ `if (foo) {
+ document.l10n.formatValue('foobar');
+ }
+ document.l10n.formatValue('foobaz');`,
+ `if (foo) {
+ document.l10n.formatValue('foobar');
+ }
+ document.l10n.formatValues(['foobaz']);`,
+ ],
+ invalid: [
+ {
+ code: `document.l10n.formatValue('foobar');
+ document.l10n.formatValue('foobaz');`,
+ errors: [error(1, 1), error(2, 14)],
+ },
+ {
+ code: `document.l10n.formatValue('foobar');
+ if (foo) {
+ document.l10n.formatValue('foobiz');
+ }
+ document.l10n.formatValue('foobaz');`,
+ errors: [error(1, 1), error(5, 14)],
+ },
+ {
+ code: `document.l10n.formatValues('foobar');
+ document.l10n.formatValue('foobaz');`,
+ errors: [error(1, 1), error(2, 14)],
+ },
+ ],
+});
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/tests/reject-addtask-only.js b/tools/lint/eslint/eslint-plugin-mozilla/tests/reject-addtask-only.js
new file mode 100644
index 0000000000..f29726d9fc
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/tests/reject-addtask-only.js
@@ -0,0 +1,54 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// ------------------------------------------------------------------------------
+// Requirements
+// ------------------------------------------------------------------------------
+
+var rule = require("../lib/rules/reject-addtask-only");
+var RuleTester = require("eslint").RuleTester;
+
+const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: "latest" } });
+
+// ------------------------------------------------------------------------------
+// Tests
+// ------------------------------------------------------------------------------
+
+function invalidError(output) {
+ return [
+ {
+ messageId: "addTaskNotAllowed",
+ type: "CallExpression",
+ suggestions: [{ messageId: "addTaskNotAllowedSuggestion", output }],
+ },
+ ];
+}
+
+ruleTester.run("reject-addtask-only", rule, {
+ valid: [
+ "add_task(foo())",
+ "add_task(foo()).skip()",
+ "add_task(function() {})",
+ "add_task(function() {}).skip()",
+ ],
+ invalid: [
+ {
+ code: "add_task(foo()).only()",
+ errors: invalidError("add_task(foo())"),
+ },
+ {
+ code: "add_task(foo()).only(bar())",
+ errors: invalidError("add_task(foo())"),
+ },
+ {
+ code: "add_task(function() {}).only()",
+ errors: invalidError("add_task(function() {})"),
+ },
+ {
+ code: "add_task(function() {}).only(bar())",
+ errors: invalidError("add_task(function() {})"),
+ },
+ ],
+});
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/tests/reject-chromeutils-import-params.js b/tools/lint/eslint/eslint-plugin-mozilla/tests/reject-chromeutils-import-params.js
new file mode 100644
index 0000000000..c2b5fd9349
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/tests/reject-chromeutils-import-params.js
@@ -0,0 +1,67 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// ------------------------------------------------------------------------------
+// Requirements
+// ------------------------------------------------------------------------------
+
+var rule = require("../lib/rules/reject-chromeutils-import-params");
+var RuleTester = require("eslint").RuleTester;
+
+const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: "latest" } });
+
+// ------------------------------------------------------------------------------
+// Tests
+// ------------------------------------------------------------------------------
+
+function invalidError(suggested) {
+ return [
+ {
+ messageId: "importOnlyOneArg",
+ type: "CallExpression",
+ suggestions: [
+ {
+ messageId: "importOnlyOneArgSuggestion",
+ output: suggested,
+ },
+ ],
+ },
+ ];
+}
+
+ruleTester.run("reject-chromeutils-import-params", rule, {
+ valid: ['ChromeUtils.import("resource://some/path/to/My.jsm")'],
+ invalid: [
+ {
+ code: 'ChromeUtils.import("resource://some/path/to/My.jsm", null)',
+ errors: invalidError(
+ `ChromeUtils.import("resource://some/path/to/My.jsm")`
+ ),
+ },
+ {
+ code: `
+ChromeUtils.import(
+ "resource://some/path/to/My.jsm",
+ null
+);`,
+ errors: invalidError(`
+ChromeUtils.import(
+ "resource://some/path/to/My.jsm"
+);`),
+ },
+ {
+ code: 'ChromeUtils.import("resource://some/path/to/My.jsm", this)',
+ errors: invalidError(
+ `ChromeUtils.import("resource://some/path/to/My.jsm")`
+ ),
+ },
+ {
+ code: 'ChromeUtils.import("resource://some/path/to/My.jsm", foo, bar)',
+ errors: invalidError(
+ `ChromeUtils.import("resource://some/path/to/My.jsm")`
+ ),
+ },
+ ],
+});
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/tests/reject-chromeutils-import.js b/tools/lint/eslint/eslint-plugin-mozilla/tests/reject-chromeutils-import.js
new file mode 100644
index 0000000000..ced46f4a0f
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/tests/reject-chromeutils-import.js
@@ -0,0 +1,60 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// ------------------------------------------------------------------------------
+// Requirements
+// ------------------------------------------------------------------------------
+
+var rule = require("../lib/rules/reject-chromeutils-import");
+var RuleTester = require("eslint").RuleTester;
+
+const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: "latest" } });
+
+// ------------------------------------------------------------------------------
+// Tests
+// ------------------------------------------------------------------------------
+
+const invalidError = [
+ {
+ messageId: "useImportESModule",
+ type: "CallExpression",
+ },
+];
+
+const invalidErrorLazy = [
+ {
+ messageId: "useImportESModuleLazy",
+ type: "CallExpression",
+ },
+];
+
+ruleTester.run("reject-chromeutils-import", rule, {
+ valid: [
+ 'ChromeUtils.importESModule("resource://some/path/to/My.sys.mjs")',
+ 'ChromeUtils.defineESModuleGetters(obj, { My: "resource://some/path/to/My.sys.mjs" })',
+ ],
+ invalid: [
+ {
+ code: 'ChromeUtils.import("resource://some/path/to/My.jsm")',
+ errors: invalidError,
+ },
+ {
+ code: 'SpecialPowers.ChromeUtils.import("resource://some/path/to/My.jsm")',
+ errors: invalidError,
+ },
+ {
+ code: 'ChromeUtils.defineModuleGetter(obj, "My", "resource://some/path/to/My.jsm")',
+ errors: invalidErrorLazy,
+ },
+ {
+ code: 'SpecialPowers.ChromeUtils.defineModuleGetter(obj, "My", "resource://some/path/to/My.jsm")',
+ errors: invalidErrorLazy,
+ },
+ {
+ code: 'XPCOMUtils.defineLazyModuleGetters(obj, { My: "resource://some/path/to/My.jsm" })',
+ errors: invalidErrorLazy,
+ },
+ ],
+});
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/tests/reject-eager-module-in-lazy-getter.js b/tools/lint/eslint/eslint-plugin-mozilla/tests/reject-eager-module-in-lazy-getter.js
new file mode 100644
index 0000000000..490346b94a
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/tests/reject-eager-module-in-lazy-getter.js
@@ -0,0 +1,67 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// ------------------------------------------------------------------------------
+// Requirements
+// ------------------------------------------------------------------------------
+
+var rule = require("../lib/rules/reject-eager-module-in-lazy-getter");
+var RuleTester = require("eslint").RuleTester;
+
+const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: "latest" } });
+
+// ------------------------------------------------------------------------------
+// Tests
+// ------------------------------------------------------------------------------
+
+function invalidCode(code, uri) {
+ return { code, errors: [{ messageId: "eagerModule", data: { uri } }] };
+}
+
+ruleTester.run("reject-eager-module-in-lazy-getter", rule, {
+ valid: [
+ `
+ ChromeUtils.defineModuleGetter(
+ lazy, "Integration", "resource://gre/modules/Integration.jsm"
+ );
+`,
+ `
+ XPCOMUtils.defineLazyModuleGetters(lazy, {
+ Integration: "resource://gre/modules/Integration.jsm",
+ });
+`,
+ `
+ ChromeUtils.defineESModuleGetters(lazy, {
+ Integration: "resource://gre/modules/Integration.sys.mjs",
+ });
+`,
+ ],
+ invalid: [
+ invalidCode(
+ `
+ ChromeUtils.defineModuleGetter(
+ lazy, "XPCOMUtils", "resource://gre/modules/XPCOMUtils.jsm"
+ );
+`,
+ "resource://gre/modules/XPCOMUtils.jsm"
+ ),
+ invalidCode(
+ `
+ XPCOMUtils.defineLazyModuleGetters(lazy, {
+ AppConstants: "resource://gre/modules/AppConstants.jsm",
+ });
+`,
+ "resource://gre/modules/AppConstants.jsm"
+ ),
+ invalidCode(
+ `
+ ChromeUtils.defineESModuleGetters(lazy, {
+ AppConstants: "resource://gre/modules/AppConstants.sys.mjs",
+ });
+`,
+ "resource://gre/modules/AppConstants.sys.mjs"
+ ),
+ ],
+});
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/tests/reject-global-this.js b/tools/lint/eslint/eslint-plugin-mozilla/tests/reject-global-this.js
new file mode 100644
index 0000000000..ec9ba711dc
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/tests/reject-global-this.js
@@ -0,0 +1,51 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// ------------------------------------------------------------------------------
+// Requirements
+// ------------------------------------------------------------------------------
+
+var rule = require("../lib/rules/reject-global-this");
+var RuleTester = require("eslint").RuleTester;
+
+// class static block is available from ES2022 = 13.
+const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: "latest" } });
+
+// ------------------------------------------------------------------------------
+// Tests
+// ------------------------------------------------------------------------------
+
+function invalidCode(code) {
+ return {
+ code,
+ errors: [{ messageId: "avoidGlobalThis", type: "ThisExpression" }],
+ };
+}
+
+ruleTester.run("reject-top-level-await", rule, {
+ valid: [
+ "function f() { this; }",
+ "(function f() { this; });",
+ "({ foo() { this; } });",
+ "({ get foo() { this; } })",
+ "({ set foo(x) { this; } })",
+ "class X { foo() { this; } }",
+ "class X { get foo() { this; } }",
+ "class X { set foo(x) { this; } }",
+ "class X { static foo() { this; } }",
+ "class X { static get foo() { this; } }",
+ "class X { static set foo(x) { this; } }",
+ "class X { P = this; }",
+ "class X { #P = this; }",
+ "class X { static { this; } }",
+ ],
+ invalid: [
+ invalidCode("this;"),
+ invalidCode("() => this;"),
+
+ invalidCode("this.foo = 10;"),
+ invalidCode("ChromeUtils.defineModuleGetter(this, {});"),
+ ],
+});
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/tests/reject-globalThis-modification.js b/tools/lint/eslint/eslint-plugin-mozilla/tests/reject-globalThis-modification.js
new file mode 100644
index 0000000000..c0244eaeab
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/tests/reject-globalThis-modification.js
@@ -0,0 +1,83 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// ------------------------------------------------------------------------------
+// Requirements
+// ------------------------------------------------------------------------------
+
+var rule = require("../lib/rules/reject-globalThis-modification");
+var RuleTester = require("eslint").RuleTester;
+
+const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: "latest" } });
+
+// ------------------------------------------------------------------------------
+// Tests
+// ------------------------------------------------------------------------------
+
+function invalidCall(code) {
+ return {
+ code,
+ errors: [
+ {
+ messageId: "rejectPassingGlobalThis",
+ type: "CallExpression",
+ },
+ ],
+ };
+}
+
+function invalidAssignment(code) {
+ return {
+ code,
+ errors: [
+ {
+ messageId: "rejectModifyGlobalThis",
+ type: "AssignmentExpression",
+ },
+ ],
+ };
+}
+
+ruleTester.run("reject-globalThis-modification", rule, {
+ valid: [
+ `var x = globalThis.Array;`,
+ `Array in globalThis;`,
+ `result.deserialize(globalThis)`,
+ ],
+ invalid: [
+ invalidAssignment(`
+ globalThis.foo = 10;
+`),
+ invalidCall(`
+ Object.defineProperty(globalThis, "foo", { value: 10 });
+`),
+ invalidCall(`
+ Object.defineProperties(globalThis, {
+ foo: { value: 10 },
+ });
+`),
+ invalidCall(`
+ Object.assign(globalThis, { foo: 10 });
+`),
+ invalidCall(`
+ ChromeUtils.defineModuleGetter(
+ globalThis, "AppConstants", "resource://gre/modules/AppConstants.jsm"
+ );
+`),
+ invalidCall(`
+ ChromeUtils.defineESMGetters(globalThis, {
+ AppConstants: "resource://gre/modules/AppConstants.sys.mjs",
+ });
+`),
+ invalidCall(`
+ XPCOMUtils.defineLazyModuleGetters(globalThis, {
+ AppConstants: "resource://gre/modules/AppConstants.jsm",
+ });
+`),
+ invalidCall(`
+ someFunction(1, globalThis);
+`),
+ ],
+});
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/tests/reject-import-system-module-from-non-system.js b/tools/lint/eslint/eslint-plugin-mozilla/tests/reject-import-system-module-from-non-system.js
new file mode 100644
index 0000000000..5b09007626
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/tests/reject-import-system-module-from-non-system.js
@@ -0,0 +1,33 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// ------------------------------------------------------------------------------
+// Requirements
+// ------------------------------------------------------------------------------
+
+var rule = require("../lib/rules/reject-import-system-module-from-non-system");
+var RuleTester = require("eslint").RuleTester;
+
+const ruleTester = new RuleTester({
+ parserOptions: { ecmaVersion: "latest", sourceType: "module" },
+});
+
+// ------------------------------------------------------------------------------
+// Tests
+// ------------------------------------------------------------------------------
+
+ruleTester.run("reject-import-system-module-from-non-system", rule, {
+ valid: [
+ {
+ code: `const { AppConstants } = ChromeUtils.importESM("resource://gre/modules/AppConstants.sys.mjs");`,
+ },
+ ],
+ invalid: [
+ {
+ code: `import { AppConstants } from "resource://gre/modules/AppConstants.sys.mjs";`,
+ errors: [{ messageId: "rejectStaticImportSystemModuleFromNonSystem" }],
+ },
+ ],
+});
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/tests/reject-importGlobalProperties.js b/tools/lint/eslint/eslint-plugin-mozilla/tests/reject-importGlobalProperties.js
new file mode 100644
index 0000000000..7f796abae7
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/tests/reject-importGlobalProperties.js
@@ -0,0 +1,89 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// ------------------------------------------------------------------------------
+// Requirements
+// ------------------------------------------------------------------------------
+
+var rule = require("../lib/rules/reject-importGlobalProperties");
+var RuleTester = require("eslint").RuleTester;
+
+const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: "latest" } });
+
+// ------------------------------------------------------------------------------
+// Tests
+// ------------------------------------------------------------------------------
+
+ruleTester.run("reject-importGlobalProperties", rule, {
+ valid: [
+ {
+ code: "Cu.something();",
+ },
+ {
+ options: ["allownonwebidl"],
+ code: "Cu.importGlobalProperties(['caches'])",
+ },
+ {
+ options: ["allownonwebidl"],
+ code: "XPCOMUtils.defineLazyGlobalGetters(this, ['caches'])",
+ },
+ ],
+ invalid: [
+ {
+ code: "Cu.importGlobalProperties(['fetch'])",
+ options: ["everything"],
+ errors: [{ messageId: "unexpectedCall" }],
+ },
+ {
+ code: "XPCOMUtils.defineLazyGlobalGetters(this, ['fetch'])",
+ options: ["everything"],
+ errors: [{ messageId: "unexpectedCall" }],
+ },
+ {
+ code: "Cu.importGlobalProperties(['TextEncoder'])",
+ options: ["everything"],
+ errors: [{ messageId: "unexpectedCall" }],
+ },
+ {
+ options: ["everything"],
+ code: "XPCOMUtils.defineLazyGlobalGetters(this, ['TextEncoder'])",
+ errors: [{ messageId: "unexpectedCallSjs" }],
+ filename: "foo.sjs",
+ },
+ {
+ code: "XPCOMUtils.defineLazyGlobalGetters(this, ['TextEncoder'])",
+ options: ["everything"],
+ errors: [{ messageId: "unexpectedCall" }],
+ },
+ {
+ code: "Cu.importGlobalProperties(['TextEncoder'])",
+ options: ["allownonwebidl"],
+ errors: [{ messageId: "unexpectedCallCuWebIdl" }],
+ },
+ {
+ code: "XPCOMUtils.defineLazyGlobalGetters(this, ['TextEncoder'])",
+ options: ["allownonwebidl"],
+ errors: [{ messageId: "unexpectedCallXPCOMWebIdl" }],
+ },
+ {
+ options: ["allownonwebidl"],
+ code: "Cu.importGlobalProperties(['TextEncoder'])",
+ errors: [{ messageId: "unexpectedCallCuWebIdl" }],
+ filename: "foo.js",
+ },
+ {
+ options: ["allownonwebidl"],
+ code: "XPCOMUtils.defineLazyGlobalGetters(this, ['TextEncoder'])",
+ errors: [{ messageId: "unexpectedCallXPCOMWebIdl" }],
+ filename: "foo.js",
+ },
+ {
+ options: ["allownonwebidl"],
+ code: "Cu.importGlobalProperties(['TextEncoder'])",
+ errors: [{ messageId: "unexpectedCallCuWebIdl" }],
+ filename: "foo.sjs",
+ },
+ ],
+});
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/tests/reject-lazy-imports-into-globals.js b/tools/lint/eslint/eslint-plugin-mozilla/tests/reject-lazy-imports-into-globals.js
new file mode 100644
index 0000000000..2c50c5524d
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/tests/reject-lazy-imports-into-globals.js
@@ -0,0 +1,46 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// ------------------------------------------------------------------------------
+// Requirements
+// ------------------------------------------------------------------------------
+
+var rule = require("../lib/rules/reject-lazy-imports-into-globals");
+var RuleTester = require("eslint").RuleTester;
+
+const ruleTester = new RuleTester({
+ parserOptions: { ecmaVersion: "latest", sourceType: "module" },
+});
+
+// ------------------------------------------------------------------------------
+// Tests
+// ------------------------------------------------------------------------------
+
+function invalidCode(code) {
+ return { code, errors: [{ messageId: "rejectLazyImportsIntoGlobals" }] };
+}
+
+ruleTester.run("reject-lazy-imports-into-globals", rule, {
+ valid: [
+ `
+ const lazy = {};
+ ChromeUtils.defineLazyGetter(lazy, "foo", () => {});
+ `,
+ ],
+ invalid: [
+ invalidCode(`ChromeUtils.defineLazyGetter(globalThis, "foo", () => {});`),
+ invalidCode(`ChromeUtils.defineLazyGetter(window, "foo", () => {});`),
+ invalidCode(
+ `XPCOMUtils.defineLazyPreferenceGetter(globalThis, "foo", "foo.bar");`
+ ),
+ invalidCode(
+ `XPCOMUtils.defineLazyServiceGetter(globalThis, "foo", "@foo", "nsIFoo");`
+ ),
+ invalidCode(`XPCOMUtils.defineLazyGlobalGetters(globalThis, {});`),
+ invalidCode(`XPCOMUtils.defineLazyGlobalGetters(window, {});`),
+ invalidCode(`XPCOMUtils.defineLazyModuleGetters(globalThis, {});`),
+ invalidCode(`ChromeUtils.defineESModuleGetters(window, {});`),
+ ],
+});
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/tests/reject-mixing-eager-and-lazy.js b/tools/lint/eslint/eslint-plugin-mozilla/tests/reject-mixing-eager-and-lazy.js
new file mode 100644
index 0000000000..af0dd99c22
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/tests/reject-mixing-eager-and-lazy.js
@@ -0,0 +1,104 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// ------------------------------------------------------------------------------
+// Requirements
+// ------------------------------------------------------------------------------
+
+var rule = require("../lib/rules/reject-mixing-eager-and-lazy");
+var RuleTester = require("eslint").RuleTester;
+
+const ruleTester = new RuleTester({
+ parserOptions: { ecmaVersion: "latest", sourceType: "module" },
+});
+
+// ------------------------------------------------------------------------------
+// Tests
+// ------------------------------------------------------------------------------
+
+function invalidCode(code, uri) {
+ return { code, errors: [{ messageId: "mixedEagerAndLazy", data: { uri } }] };
+}
+
+ruleTester.run("reject-mixing-eager-and-lazy", rule, {
+ valid: [
+ `
+ ChromeUtils.import("resource://gre/modules/AppConstants.jsm");
+`,
+ `
+ ChromeUtils.importESModule("resource://gre/modules/AppConstants.sys.mjs");
+`,
+ `
+ import{ AppConstants } from "resource://gre/modules/AppConstants.sys.mjs";
+`,
+ `
+ ChromeUtils.defineModuleGetter(
+ lazy, "AppConstants", "resource://gre/modules/AppConstants.jsm"
+ );
+`,
+ `
+ XPCOMUtils.defineLazyModuleGetters(lazy, {
+ AppConstants: "resource://gre/modules/AppConstants.jsm",
+ });
+`,
+ `
+ ChromeUtils.defineESModuleGetters(lazy, {
+ AppConstants: "resource://gre/modules/AppConstants.sys.mjs",
+ });
+`,
+ `
+ if (some_condition) {
+ ChromeUtils.import("resource://gre/modules/AppConstants.jsm");
+ }
+ XPCOMUtils.defineLazyModuleGetters(lazy, {
+ AppConstants: "resource://gre/modules/AppConstants.jsm"
+ });
+`,
+ `
+ ChromeUtils.import("resource://gre/modules/AppConstants.jsm");
+ XPCOMUtils.defineLazyModuleGetters(sandbox, {
+ AppConstants: "resource://gre/modules/AppConstants.jsm",
+ });
+`,
+ ],
+ invalid: [
+ invalidCode(
+ `
+ ChromeUtils.import("resource://gre/modules/AppConstants.jsm");
+ ChromeUtils.defineModuleGetter(
+ lazy, "AppConstants", "resource://gre/modules/AppConstants.jsm"
+ );
+`,
+ "resource://gre/modules/AppConstants.jsm"
+ ),
+ invalidCode(
+ `
+ ChromeUtils.import("resource://gre/modules/AppConstants.jsm");
+ XPCOMUtils.defineLazyModuleGetters(lazy, {
+ AppConstants: "resource://gre/modules/AppConstants.jsm",
+ });
+`,
+ "resource://gre/modules/AppConstants.jsm"
+ ),
+ invalidCode(
+ `
+ ChromeUtils.importESModule("resource://gre/modules/AppConstants.sys.mjs");
+ ChromeUtils.defineESModuleGetters(lazy, {
+ AppConstants: "resource://gre/modules/AppConstants.sys.mjs",
+ });
+`,
+ "resource://gre/modules/AppConstants.sys.mjs"
+ ),
+ invalidCode(
+ `
+ import { AppConstants } from "resource://gre/modules/AppConstants.sys.mjs";
+ ChromeUtils.defineESModuleGetters(lazy, {
+ AppConstants: "resource://gre/modules/AppConstants.sys.mjs",
+ });
+`,
+ "resource://gre/modules/AppConstants.sys.mjs"
+ ),
+ ],
+});
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/tests/reject-multiple-getters-calls.js b/tools/lint/eslint/eslint-plugin-mozilla/tests/reject-multiple-getters-calls.js
new file mode 100644
index 0000000000..a2b88a8652
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/tests/reject-multiple-getters-calls.js
@@ -0,0 +1,60 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// ------------------------------------------------------------------------------
+// Requirements
+// ------------------------------------------------------------------------------
+
+var rule = require("../lib/rules/reject-multiple-getters-calls");
+var RuleTester = require("eslint").RuleTester;
+
+const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: "latest" } });
+
+// ------------------------------------------------------------------------------
+// Tests
+// ------------------------------------------------------------------------------
+
+function invalidCode(code) {
+ return { code, errors: [{ messageId: "rejectMultipleCalls" }] };
+}
+
+ruleTester.run("reject-multiple-getters-calls", rule, {
+ valid: [
+ `
+ ChromeUtils.defineESModuleGetters(lazy, {
+ AppConstants: "resource://gre/modules/AppConstants.sys.mjs",
+ PlacesUtils: "resource://gre/modules/PlacesUtils.sys.mjs",
+ });
+ `,
+ `
+ ChromeUtils.defineESModuleGetters(lazy, {
+ AppConstants: "resource://gre/modules/AppConstants.sys.mjs",
+ });
+ ChromeUtils.defineESModuleGetters(window, {
+ PlacesUtils: "resource://gre/modules/PlacesUtils.sys.mjs",
+ });
+ `,
+ `
+ ChromeUtils.defineESModuleGetters(lazy, {
+ AppConstants: "resource://gre/modules/AppConstants.sys.mjs",
+ });
+ if (cond) {
+ ChromeUtils.defineESModuleGetters(lazy, {
+ PlacesUtils: "resource://gre/modules/PlacesUtils.sys.mjs",
+ });
+ }
+ `,
+ ],
+ invalid: [
+ invalidCode(`
+ ChromeUtils.defineESModuleGetters(lazy, {
+ AppConstants: "resource://gre/modules/AppConstants.sys.mjs",
+ });
+ ChromeUtils.defineESModuleGetters(lazy, {
+ PlacesUtils: "resource://gre/modules/PlacesUtils.sys.mjs",
+ });
+ `),
+ ],
+});
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/tests/reject-relative-requires.js b/tools/lint/eslint/eslint-plugin-mozilla/tests/reject-relative-requires.js
new file mode 100644
index 0000000000..a7bad6f992
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/tests/reject-relative-requires.js
@@ -0,0 +1,56 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// ------------------------------------------------------------------------------
+// Requirements
+// ------------------------------------------------------------------------------
+
+var rule = require("../lib/rules/reject-relative-requires");
+var RuleTester = require("eslint").RuleTester;
+
+const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: "latest" } });
+
+// ------------------------------------------------------------------------------
+// Tests
+// ------------------------------------------------------------------------------
+
+function invalidError() {
+ return [{ messageId: "rejectRelativeRequires", type: "CallExpression" }];
+}
+
+ruleTester.run("reject-relative-requires", rule, {
+ valid: [
+ 'require("devtools/absolute/path")',
+ 'require("resource://gre/modules/SomeModule.jsm")',
+ 'loader.lazyRequireGetter(this, "path", "devtools/absolute/path", true)',
+ 'loader.lazyRequireGetter(this, "Path", "devtools/absolute/path")',
+ ],
+ invalid: [
+ {
+ code: 'require("./relative/path")',
+ errors: invalidError(),
+ },
+ {
+ code: 'require("../parent/folder/path")',
+ errors: invalidError(),
+ },
+ {
+ code: 'loader.lazyRequireGetter(this, "path", "./relative/path", true)',
+ errors: invalidError(),
+ },
+ {
+ code: 'loader.lazyRequireGetter(this, "path", "../parent/folder/path", true)',
+ errors: invalidError(),
+ },
+ {
+ code: 'loader.lazyRequireGetter(this, "path", "./relative/path")',
+ errors: invalidError(),
+ },
+ {
+ code: 'loader.lazyRequireGetter(this, "path", "../parent/folder/path")',
+ errors: invalidError(),
+ },
+ ],
+});
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/tests/reject-scriptableunicodeconverter.js b/tools/lint/eslint/eslint-plugin-mozilla/tests/reject-scriptableunicodeconverter.js
new file mode 100644
index 0000000000..22123bb99c
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/tests/reject-scriptableunicodeconverter.js
@@ -0,0 +1,33 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// ------------------------------------------------------------------------------
+// Requirements
+// ------------------------------------------------------------------------------
+
+var rule = require("../lib/rules/reject-scriptableunicodeconverter");
+var RuleTester = require("eslint").RuleTester;
+
+const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: "latest" } });
+
+// ------------------------------------------------------------------------------
+// Tests
+// ------------------------------------------------------------------------------
+
+function invalidError() {
+ return [
+ { messageId: "rejectScriptableUnicodeConverter", type: "MemberExpression" },
+ ];
+}
+
+ruleTester.run("reject-scriptableunicodeconverter", rule, {
+ valid: ["TextEncoder", "TextDecoder"],
+ invalid: [
+ {
+ code: "Ci.nsIScriptableUnicodeConverter",
+ errors: invalidError(),
+ },
+ ],
+});
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/tests/reject-some-requires.js b/tools/lint/eslint/eslint-plugin-mozilla/tests/reject-some-requires.js
new file mode 100644
index 0000000000..3415946b07
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/tests/reject-some-requires.js
@@ -0,0 +1,50 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// ------------------------------------------------------------------------------
+// Requirements
+// ------------------------------------------------------------------------------
+
+var rule = require("../lib/rules/reject-some-requires");
+var RuleTester = require("eslint").RuleTester;
+
+const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: "latest" } });
+
+// ------------------------------------------------------------------------------
+// Tests
+// ------------------------------------------------------------------------------
+
+function requirePathError(path) {
+ return [
+ { messageId: "rejectRequire", data: { path }, type: "CallExpression" },
+ ];
+}
+
+const DEVTOOLS_FORBIDDEN_PATH = "^(resource://)?devtools/forbidden";
+
+ruleTester.run("reject-some-requires", rule, {
+ valid: [
+ {
+ code: 'require("devtools/not-forbidden/path")',
+ options: [DEVTOOLS_FORBIDDEN_PATH],
+ },
+ {
+ code: 'require("resource://devtools/not-forbidden/path")',
+ options: [DEVTOOLS_FORBIDDEN_PATH],
+ },
+ ],
+ invalid: [
+ {
+ code: 'require("devtools/forbidden/path")',
+ errors: requirePathError("devtools/forbidden/path"),
+ options: [DEVTOOLS_FORBIDDEN_PATH],
+ },
+ {
+ code: 'require("resource://devtools/forbidden/path")',
+ errors: requirePathError("resource://devtools/forbidden/path"),
+ options: [DEVTOOLS_FORBIDDEN_PATH],
+ },
+ ],
+});
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/tests/reject-top-level-await.js b/tools/lint/eslint/eslint-plugin-mozilla/tests/reject-top-level-await.js
new file mode 100644
index 0000000000..4416b42abb
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/tests/reject-top-level-await.js
@@ -0,0 +1,36 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// ------------------------------------------------------------------------------
+// Requirements
+// ------------------------------------------------------------------------------
+
+var rule = require("../lib/rules/reject-top-level-await");
+var RuleTester = require("eslint").RuleTester;
+
+const ruleTester = new RuleTester({
+ parserOptions: { ecmaVersion: "latest", sourceType: "module" },
+});
+
+// ------------------------------------------------------------------------------
+// Tests
+// ------------------------------------------------------------------------------
+
+function invalidCode(code, messageId) {
+ return { code, errors: [{ messageId: "rejectTopLevelAwait" }] };
+}
+
+ruleTester.run("reject-top-level-await", rule, {
+ valid: [
+ "async() => { await bar() }",
+ "async() => { for await (let x of []) {} }",
+ ],
+ invalid: [
+ invalidCode("await foo"),
+ invalidCode("{ await foo }"),
+ invalidCode("(await foo)"),
+ invalidCode("for await (let x of []) {}"),
+ ],
+});
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/tests/rejects-requires-await.js b/tools/lint/eslint/eslint-plugin-mozilla/tests/rejects-requires-await.js
new file mode 100644
index 0000000000..a7e95769c1
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/tests/rejects-requires-await.js
@@ -0,0 +1,32 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// ------------------------------------------------------------------------------
+// Requirements
+// ------------------------------------------------------------------------------
+
+var rule = require("../lib/rules/rejects-requires-await");
+var RuleTester = require("eslint").RuleTester;
+
+const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: "latest" } });
+
+// ------------------------------------------------------------------------------
+// Tests
+// ------------------------------------------------------------------------------
+
+function invalidCode(code, messageId) {
+ return { code, errors: [{ messageId: "rejectRequiresAwait" }] };
+}
+
+ruleTester.run("reject-requires-await", rule, {
+ valid: [
+ "async() => { await Assert.rejects(foo, /assertion/) }",
+ "async() => { await Assert.rejects(foo, /assertion/, 'msg') }",
+ ],
+ invalid: [
+ invalidCode("Assert.rejects(foo)"),
+ invalidCode("Assert.rejects(foo, 'msg')"),
+ ],
+});
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/tests/use-cc-etc.js b/tools/lint/eslint/eslint-plugin-mozilla/tests/use-cc-etc.js
new file mode 100644
index 0000000000..d588fabc84
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/tests/use-cc-etc.js
@@ -0,0 +1,64 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// ------------------------------------------------------------------------------
+// Requirements
+// ------------------------------------------------------------------------------
+
+var rule = require("../lib/rules/use-cc-etc");
+var RuleTester = require("eslint").RuleTester;
+
+const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: "latest" } });
+
+// ------------------------------------------------------------------------------
+// Tests
+// ------------------------------------------------------------------------------
+
+function invalidCode(code, originalName, newName, output) {
+ return {
+ code,
+ output,
+ errors: [
+ {
+ messageId: "useCcEtc",
+ data: {
+ shortName: newName,
+ oldName: originalName,
+ },
+ type: "MemberExpression",
+ },
+ ],
+ };
+}
+
+ruleTester.run("use-cc-etc", rule, {
+ valid: ["Components.Constructor();", "let x = Components.foo;"],
+ invalid: [
+ invalidCode(
+ "let foo = Components.classes['bar'];",
+ "classes",
+ "Cc",
+ "let foo = Cc['bar'];"
+ ),
+ invalidCode(
+ "let bar = Components.interfaces.bar;",
+ "interfaces",
+ "Ci",
+ "let bar = Ci.bar;"
+ ),
+ invalidCode(
+ "Components.results.NS_ERROR_ILLEGAL_INPUT;",
+ "results",
+ "Cr",
+ "Cr.NS_ERROR_ILLEGAL_INPUT;"
+ ),
+ invalidCode(
+ "Components.utils.reportError('fake');",
+ "utils",
+ "Cu",
+ "Cu.reportError('fake');"
+ ),
+ ],
+});
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/tests/use-chromeutils-definelazygetter.js b/tools/lint/eslint/eslint-plugin-mozilla/tests/use-chromeutils-definelazygetter.js
new file mode 100644
index 0000000000..89948f12b7
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/tests/use-chromeutils-definelazygetter.js
@@ -0,0 +1,34 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// ------------------------------------------------------------------------------
+// Requirements
+// ------------------------------------------------------------------------------
+
+var rule = require("../lib/rules/use-chromeutils-definelazygetter");
+var RuleTester = require("eslint").RuleTester;
+
+const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: "latest" } });
+
+// ------------------------------------------------------------------------------
+// Tests
+// ------------------------------------------------------------------------------
+
+function callError(messageId) {
+ return [{ messageId, type: "CallExpression" }];
+}
+
+ruleTester.run("use-chromeutils-definelazygetter", rule, {
+ valid: [
+ `ChromeUtils.defineLazyGetter(lazy, "textEncoder", function () { return new TextEncoder(); });`,
+ ],
+ invalid: [
+ {
+ code: `XPCOMUtils.defineLazyGetter(lazy, "textEncoder", function () { return new TextEncoder(); });`,
+ output: `ChromeUtils.defineLazyGetter(lazy, "textEncoder", function () { return new TextEncoder(); });`,
+ errors: callError("useChromeUtilsDefineLazyGetter"),
+ },
+ ],
+});
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/tests/use-chromeutils-generateqi.js b/tools/lint/eslint/eslint-plugin-mozilla/tests/use-chromeutils-generateqi.js
new file mode 100644
index 0000000000..ca32d2ac26
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/tests/use-chromeutils-generateqi.js
@@ -0,0 +1,71 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// ------------------------------------------------------------------------------
+// Requirements
+// ------------------------------------------------------------------------------
+
+var rule = require("../lib/rules/use-chromeutils-generateqi");
+var RuleTester = require("eslint").RuleTester;
+
+const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: "latest" } });
+
+// ------------------------------------------------------------------------------
+// Tests
+// ------------------------------------------------------------------------------
+
+function error(messageId, type) {
+ return [{ messageId, type }];
+}
+
+/* globals nsIFlug */
+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);
+}
+
+ruleTester.run("use-chromeutils-generateqi", rule, {
+ valid: [
+ `X.prototype.QueryInterface = ChromeUtils.generateQI(["nsIMeh"]);`,
+ `X.prototype = { QueryInterface: ChromeUtils.generateQI(["nsIMeh"]) }`,
+ ],
+ invalid: [
+ {
+ code: `X.prototype.QueryInterface = XPCOMUtils.generateQI(["nsIMeh"]);`,
+ output: `X.prototype.QueryInterface = ChromeUtils.generateQI(["nsIMeh"]);`,
+ errors: error("noXpcomUtilsGenerateQI", "CallExpression"),
+ },
+ {
+ code: `X.prototype = { QueryInterface: XPCOMUtils.generateQI(["nsIMeh"]) };`,
+ output: `X.prototype = { QueryInterface: ChromeUtils.generateQI(["nsIMeh"]) };`,
+ errors: error("noXpcomUtilsGenerateQI", "CallExpression"),
+ },
+ {
+ code: `X.prototype = { QueryInterface: ${QueryInterface} };`,
+ output: `X.prototype = { QueryInterface: ChromeUtils.generateQI(["nsIMeh", "nsIFlug", "amIFoo"]) };`,
+ errors: error("noJSQueryInterface", "Property"),
+ },
+ {
+ code: `X.prototype = { ${String(QueryInterface).replace(
+ /^function /,
+ ""
+ )} };`,
+ output: `X.prototype = { QueryInterface: ChromeUtils.generateQI(["nsIMeh", "nsIFlug", "amIFoo"]) };`,
+ errors: error("noJSQueryInterface", "Property"),
+ },
+ {
+ code: `X.prototype.QueryInterface = ${QueryInterface};`,
+ output: `X.prototype.QueryInterface = ChromeUtils.generateQI(["nsIMeh", "nsIFlug", "amIFoo"]);`,
+ errors: error("noJSQueryInterface", "AssignmentExpression"),
+ },
+ ],
+});
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/tests/use-chromeutils-import.js b/tools/lint/eslint/eslint-plugin-mozilla/tests/use-chromeutils-import.js
new file mode 100644
index 0000000000..37976d252e
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/tests/use-chromeutils-import.js
@@ -0,0 +1,47 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// ------------------------------------------------------------------------------
+// Requirements
+// ------------------------------------------------------------------------------
+
+var rule = require("../lib/rules/use-chromeutils-import");
+var RuleTester = require("eslint").RuleTester;
+
+const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: "latest" } });
+
+// ------------------------------------------------------------------------------
+// Tests
+// ------------------------------------------------------------------------------
+
+function callError(messageId) {
+ return [{ messageId, type: "CallExpression" }];
+}
+
+ruleTester.run("use-chromeutils-import", rule, {
+ valid: [
+ `ChromeUtils.import("resource://gre/modules/AppConstants.jsm");`,
+ `ChromeUtils.import("resource://gre/modules/AppConstants.jsm", this);`,
+ `ChromeUtils.defineModuleGetter(this, "AppConstants",
+ "resource://gre/modules/AppConstants.jsm");`,
+ ],
+ invalid: [
+ {
+ code: `Cu.import("resource://gre/modules/AppConstants.jsm");`,
+ output: `ChromeUtils.import("resource://gre/modules/AppConstants.jsm");`,
+ errors: callError("useChromeUtilsImport"),
+ },
+ {
+ code: `Cu.import("resource://gre/modules/AppConstants.jsm", this);`,
+ output: `ChromeUtils.import("resource://gre/modules/AppConstants.jsm", this);`,
+ errors: callError("useChromeUtilsImport"),
+ },
+ {
+ code: `Components.utils.import("resource://gre/modules/AppConstants.jsm");`,
+ output: `ChromeUtils.import("resource://gre/modules/AppConstants.jsm");`,
+ errors: callError("useChromeUtilsImport"),
+ },
+ ],
+});
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/tests/use-console-createInstance.js b/tools/lint/eslint/eslint-plugin-mozilla/tests/use-console-createInstance.js
new file mode 100644
index 0000000000..bd7fe3a507
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/tests/use-console-createInstance.js
@@ -0,0 +1,41 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// ------------------------------------------------------------------------------
+// Requirements
+// ------------------------------------------------------------------------------
+
+var rule = require("../lib/rules/use-console-createInstance");
+var RuleTester = require("eslint").RuleTester;
+
+const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: "latest" } });
+
+// ------------------------------------------------------------------------------
+// Tests
+// ------------------------------------------------------------------------------
+
+ruleTester.run("use-console-createInstance", rule, {
+ valid: ['"resource://gre/modules/Foo.sys.mjs"'],
+ invalid: [
+ {
+ code: '"resource://gre/modules/Console.sys.mjs"',
+ errors: [
+ {
+ messageId: "useConsoleRatherThanModule",
+ data: { module: "Console.sys.mjs" },
+ },
+ ],
+ },
+ {
+ code: '"resource://gre/modules/Log.sys.mjs"',
+ errors: [
+ {
+ messageId: "useConsoleRatherThanModule",
+ data: { module: "Log.sys.mjs" },
+ },
+ ],
+ },
+ ],
+});
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/tests/use-default-preference-values.js b/tools/lint/eslint/eslint-plugin-mozilla/tests/use-default-preference-values.js
new file mode 100644
index 0000000000..a8353ec200
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/tests/use-default-preference-values.js
@@ -0,0 +1,43 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// ------------------------------------------------------------------------------
+// Requirements
+// ------------------------------------------------------------------------------
+
+var rule = require("../lib/rules/use-default-preference-values");
+var RuleTester = require("eslint").RuleTester;
+
+const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: "latest" } });
+
+// ------------------------------------------------------------------------------
+// Tests
+// ------------------------------------------------------------------------------
+
+function invalidCode(code) {
+ return {
+ code,
+ errors: [{ messageId: "provideDefaultValue", type: "TryStatement" }],
+ };
+}
+
+let types = ["Bool", "Char", "Float", "Int"];
+let methods = types.map(type => "get" + type + "Pref");
+
+ruleTester.run("use-default-preference-values", rule, {
+ valid: [].concat(
+ methods.map(m => "blah = branch." + m + "('blah', true);"),
+ methods.map(m => "blah = branch." + m + "('blah');"),
+ methods.map(
+ m => "try { canThrow(); blah = branch." + m + "('blah'); } catch(e) {}"
+ )
+ ),
+
+ invalid: [].concat(
+ methods.map(m =>
+ invalidCode("try { blah = branch." + m + "('blah'); } catch(e) {}")
+ )
+ ),
+});
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/tests/use-includes-instead-of-indexOf.js b/tools/lint/eslint/eslint-plugin-mozilla/tests/use-includes-instead-of-indexOf.js
new file mode 100644
index 0000000000..fff826874f
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/tests/use-includes-instead-of-indexOf.js
@@ -0,0 +1,40 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// ------------------------------------------------------------------------------
+// Requirements
+// ------------------------------------------------------------------------------
+
+var rule = require("../lib/rules/use-includes-instead-of-indexOf");
+var RuleTester = require("eslint").RuleTester;
+
+const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: "latest" } });
+
+// ------------------------------------------------------------------------------
+// Tests
+// ------------------------------------------------------------------------------
+
+function invalidCode(code) {
+ return {
+ code,
+ errors: [{ messageId: "useIncludes", type: "BinaryExpression" }],
+ };
+}
+
+ruleTester.run("use-includes-instead-of-indexOf", rule, {
+ valid: [
+ "let a = foo.includes(bar);",
+ "let a = foo.indexOf(bar) > 0;",
+ "let a = foo.indexOf(bar) != 0;",
+ ],
+ invalid: [
+ invalidCode("let a = foo.indexOf(bar) >= 0;"),
+ invalidCode("let a = foo.indexOf(bar) != -1;"),
+ invalidCode("let a = foo.indexOf(bar) !== -1;"),
+ invalidCode("let a = foo.indexOf(bar) == -1;"),
+ invalidCode("let a = foo.indexOf(bar) === -1;"),
+ invalidCode("let a = foo.indexOf(bar) < 0;"),
+ ],
+});
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/tests/use-isInstance.js b/tools/lint/eslint/eslint-plugin-mozilla/tests/use-isInstance.js
new file mode 100644
index 0000000000..0de5e4577c
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/tests/use-isInstance.js
@@ -0,0 +1,128 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// ------------------------------------------------------------------------------
+// Requirements
+// ------------------------------------------------------------------------------
+
+var rule = require("../lib/rules/use-isInstance");
+var RuleTester = require("eslint").RuleTester;
+
+const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: "latest" } });
+
+// ------------------------------------------------------------------------------
+// Tests
+// ------------------------------------------------------------------------------
+
+const errors = [
+ {
+ messageId: "preferIsInstance",
+ type: "BinaryExpression",
+ },
+];
+
+const env = { browser: true };
+
+/**
+ * A test case boilerplate simulating chrome privileged script.
+ * @param {string} code
+ */
+function mockChromeScript(code) {
+ return {
+ code,
+ filename: "foo.sys.mjs",
+ env,
+ };
+}
+
+/**
+ * A test case boilerplate simulating content script.
+ * @param {string} code
+ */
+function mockContentScript(code) {
+ return {
+ code,
+ filename: "foo.js",
+ env,
+ };
+}
+
+ruleTester.run("use-isInstance", rule, {
+ valid: [
+ mockChromeScript("(() => {}) instanceof Function;"),
+ mockChromeScript("({}) instanceof Object;"),
+ mockChromeScript("Node instanceof Object;"),
+ mockChromeScript("node instanceof lazy.Node;"),
+ mockChromeScript("var Node;node instanceof Node;"),
+ mockChromeScript("file instanceof lazy.File;"),
+ mockChromeScript("file instanceof OS.File;"),
+ mockChromeScript("file instanceof OS.File.Error;"),
+ mockChromeScript("file instanceof lazy.OS.File;"),
+ mockChromeScript("file instanceof lazy.OS.File.Error;"),
+ mockChromeScript("file instanceof lazy.lazy.OS.File;"),
+ mockChromeScript("var File;file instanceof File;"),
+ mockChromeScript("foo instanceof RandomGlobalThing;"),
+ mockChromeScript("foo instanceof lazy.RandomGlobalThing;"),
+ mockContentScript("node instanceof Node;"),
+ mockContentScript("file instanceof File;"),
+ mockContentScript(
+ "SpecialPowers.ChromeUtils.import(''); file instanceof File;"
+ ),
+ ],
+ invalid: [
+ {
+ code: "node instanceof Node",
+ output: "Node.isInstance(node)",
+ env,
+ errors,
+ filename: "foo.sys.mjs",
+ },
+ {
+ code: "text instanceof win.Text",
+ output: "win.Text.isInstance(text)",
+ errors,
+ filename: "foo.sys.mjs",
+ },
+ {
+ code: "target instanceof this.contentWindow.HTMLAudioElement",
+ output: "this.contentWindow.HTMLAudioElement.isInstance(target)",
+ errors,
+ filename: "foo.sys.mjs",
+ },
+ {
+ code: "target instanceof File",
+ output: "File.isInstance(target)",
+ env,
+ errors,
+ filename: "foo.sys.mjs",
+ },
+ {
+ code: "target instanceof win.File",
+ output: "win.File.isInstance(target)",
+ errors,
+ filename: "foo.sys.mjs",
+ },
+ {
+ code: "window.arguments[0] instanceof window.XULElement",
+ output: "window.XULElement.isInstance(window.arguments[0])",
+ errors,
+ filename: "foo.sys.mjs",
+ },
+ {
+ code: "ChromeUtils.import(''); node instanceof Node",
+ output: "ChromeUtils.import(''); Node.isInstance(node)",
+ env,
+ errors,
+ filename: "foo.js",
+ },
+ {
+ code: "ChromeUtils.import(''); file instanceof File",
+ output: "ChromeUtils.import(''); File.isInstance(file)",
+ env,
+ errors,
+ filename: "foo.js",
+ },
+ ],
+});
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/tests/use-ownerGlobal.js b/tools/lint/eslint/eslint-plugin-mozilla/tests/use-ownerGlobal.js
new file mode 100644
index 0000000000..150f0fac63
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/tests/use-ownerGlobal.js
@@ -0,0 +1,37 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// ------------------------------------------------------------------------------
+// Requirements
+// ------------------------------------------------------------------------------
+
+var rule = require("../lib/rules/use-ownerGlobal");
+var RuleTester = require("eslint").RuleTester;
+
+const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: "latest" } });
+
+// ------------------------------------------------------------------------------
+// Tests
+// ------------------------------------------------------------------------------
+
+function invalidCode(code) {
+ return {
+ code,
+ errors: [{ messageId: "useOwnerGlobal", type: "MemberExpression" }],
+ };
+}
+
+ruleTester.run("use-ownerGlobal", rule, {
+ valid: [
+ "aEvent.target.ownerGlobal;",
+ "this.DOMPointNode.ownerGlobal.getSelection();",
+ "windowToMessageManager(node.ownerGlobal);",
+ ],
+ invalid: [
+ invalidCode("aEvent.target.ownerDocument.defaultView;"),
+ invalidCode("this.DOMPointNode.ownerDocument.defaultView.getSelection();"),
+ invalidCode("windowToMessageManager(node.ownerDocument.defaultView);"),
+ ],
+});
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/tests/use-returnValue.js b/tools/lint/eslint/eslint-plugin-mozilla/tests/use-returnValue.js
new file mode 100644
index 0000000000..2c15349139
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/tests/use-returnValue.js
@@ -0,0 +1,49 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// ------------------------------------------------------------------------------
+// Requirements
+// ------------------------------------------------------------------------------
+
+var rule = require("../lib/rules/use-returnValue");
+var RuleTester = require("eslint").RuleTester;
+
+const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: "latest" } });
+
+// ------------------------------------------------------------------------------
+// Tests
+// ------------------------------------------------------------------------------
+
+function invalidCode(code, methodName) {
+ return {
+ code,
+ errors: [
+ {
+ messageId: "useReturnValue",
+ data: {
+ property: methodName,
+ },
+ type: "ExpressionStatement",
+ },
+ ],
+ };
+}
+
+ruleTester.run("use-returnValue", rule, {
+ valid: [
+ "a = foo.concat(bar)",
+ "b = bar.concat([1,3,4])",
+ "c = baz.concat()",
+ "d = qux.join(' ')",
+ "e = quux.slice(1)",
+ ],
+ invalid: [
+ invalidCode("foo.concat(bar)", "concat"),
+ invalidCode("bar.concat([1,3,4])", "concat"),
+ invalidCode("baz.concat()", "concat"),
+ invalidCode("qux.join(' ')", "join"),
+ invalidCode("quux.slice(1)", "slice"),
+ ],
+});
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/tests/use-services.js b/tools/lint/eslint/eslint-plugin-mozilla/tests/use-services.js
new file mode 100644
index 0000000000..fc4af03ac1
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/tests/use-services.js
@@ -0,0 +1,64 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// ------------------------------------------------------------------------------
+// Requirements
+// ------------------------------------------------------------------------------
+
+var rule = require("../lib/rules/use-services");
+var RuleTester = require("eslint").RuleTester;
+
+const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: "latest" } });
+
+// ------------------------------------------------------------------------------
+// Tests
+// ------------------------------------------------------------------------------
+
+function invalidCode(code, serviceName, getterName, type = "CallExpression") {
+ return {
+ code,
+ errors: [
+ { messageId: "useServices", data: { serviceName, getterName }, type },
+ ],
+ };
+}
+
+ruleTester.run("use-services", rule, {
+ valid: [
+ 'Cc["@mozilla.org/fakeservice;1"].getService(Ci.nsIFake)',
+ 'Components.classes["@mozilla.org/fakeservice;1"].getService(Components.interfaces.nsIFake)',
+ "Services.wm.addListener()",
+ ],
+ invalid: [
+ invalidCode(
+ 'Cc["@mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator);',
+ "wm",
+ "getService()"
+ ),
+ invalidCode(
+ 'Components.classes["@mozilla.org/toolkit/app-startup;1"].getService(Components.interfaces.nsIAppStartup);',
+ "startup",
+ "getService()"
+ ),
+ invalidCode(
+ `XPCOMUtils.defineLazyServiceGetters(this, {
+ uuidGen: ["@mozilla.org/uuid-generator;1", "nsIUUIDGenerator"],
+ });`,
+ "uuid",
+ "defineLazyServiceGetters",
+ "ArrayExpression"
+ ),
+ invalidCode(
+ `XPCOMUtils.defineLazyServiceGetter(
+ this,
+ "gELS",
+ "@mozilla.org/eventlistenerservice;1",
+ "nsIEventListenerService"
+ );`,
+ "els",
+ "defineLazyServiceGetter"
+ ),
+ ],
+});
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/tests/use-static-import.js b/tools/lint/eslint/eslint-plugin-mozilla/tests/use-static-import.js
new file mode 100644
index 0000000000..656e83e0e9
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/tests/use-static-import.js
@@ -0,0 +1,80 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// ------------------------------------------------------------------------------
+// Requirements
+// ------------------------------------------------------------------------------
+
+var rule = require("../lib/rules/use-static-import");
+var RuleTester = require("eslint").RuleTester;
+
+const ruleTester = new RuleTester({
+ parserOptions: { ecmaVersion: "latest", sourceType: "module" },
+});
+
+// ------------------------------------------------------------------------------
+// Tests
+// ------------------------------------------------------------------------------
+
+function callError() {
+ return [{ messageId: "useStaticImport", type: "VariableDeclaration" }];
+}
+
+ruleTester.run("use-static-import", rule, {
+ valid: [
+ {
+ // Already converted, no issues.
+ code: 'import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs";',
+ filename: "test.sys.mjs",
+ },
+ {
+ // Inside an if statement.
+ code: 'if (foo) { const { XPCOMUtils } = ChromeUtils.importESModule("resource://gre/modules/XPCOMUtils.sys.mjs") }',
+ filename: "test.sys.mjs",
+ },
+ {
+ // Inside a function.
+ code: 'function foo() { const { XPCOMUtils } = ChromeUtils.importESModule("resource://gre/modules/XPCOMUtils.sys.mjs") }',
+ filename: "test.sys.mjs",
+ },
+ {
+ // importESModule with two args cannot be converted.
+ code: 'const { f } = ChromeUtils.importESModule("some/module.sys.mjs", { loadInDevToolsLoader : true });',
+ filename: "test.sys.mjs",
+ },
+ {
+ // A non-system file attempting to import a system file should not be
+ // converted.
+ code: 'const { XPCOMUtils } = ChromeUtils.importESModule("resource://gre/modules/XPCOMUtils.sys.mjs")',
+ filename: "test.mjs",
+ },
+ ],
+ invalid: [
+ {
+ // Simple import in system module should be converted.
+ code: 'const { XPCOMUtils } = ChromeUtils.importESModule("resource://gre/modules/XPCOMUtils.sys.mjs")',
+ errors: callError(),
+ filename: "test.sys.mjs",
+ output:
+ 'import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs"',
+ },
+ {
+ // Should handle rewritten variables as well.
+ code: 'const { XPCOMUtils: foo } = ChromeUtils.importESModule("resource://gre/modules/XPCOMUtils.sys.mjs")',
+ errors: callError(),
+ filename: "test.sys.mjs",
+ output:
+ 'import { XPCOMUtils as foo } from "resource://gre/modules/XPCOMUtils.sys.mjs"',
+ },
+ {
+ // Should handle multiple variables.
+ code: 'const { foo, XPCOMUtils } = ChromeUtils.importESModule("resource://gre/modules/XPCOMUtils.sys.mjs")',
+ errors: callError(),
+ filename: "test.sys.mjs",
+ output:
+ 'import { foo, XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs"',
+ },
+ ],
+});
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/tests/valid-ci-uses.js b/tools/lint/eslint/eslint-plugin-mozilla/tests/valid-ci-uses.js
new file mode 100644
index 0000000000..0f5fe2eadf
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/tests/valid-ci-uses.js
@@ -0,0 +1,58 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// ------------------------------------------------------------------------------
+// Requirements
+// ------------------------------------------------------------------------------
+
+var os = require("os");
+var rule = require("../lib/rules/valid-ci-uses");
+var RuleTester = require("eslint").RuleTester;
+
+const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: "latest" } });
+
+// ------------------------------------------------------------------------------
+// Tests
+// ------------------------------------------------------------------------------
+
+function invalidCode(code, messageId, data) {
+ return { code, errors: [{ messageId, data }] };
+}
+
+process.env.MOZ_XPT_ARTIFACTS_DIR = `${__dirname}/xpidl`;
+
+const tests = {
+ valid: ["Ci.nsIURIFixup", "Ci.nsIURIFixup.FIXUP_FLAG_NONE"],
+ invalid: [
+ invalidCode("Ci.nsIURIFixup.UNKNOWN_CONSTANT", "unknownProperty", {
+ interface: "nsIURIFixup",
+ property: "UNKNOWN_CONSTANT",
+ }),
+ invalidCode("Ci.nsIFoo", "unknownInterface", {
+ interface: "nsIFoo",
+ }),
+ ],
+};
+
+// For ESLint tests, we only have a couple of xpt examples in the xpidl directory.
+// Therefore we can pretend that these interfaces no longer exist.
+switch (os.platform) {
+ case "windows":
+ tests.invalid.push(
+ invalidCode("Ci.nsIJumpListShortcut", "missingInterface")
+ );
+ break;
+ case "darwin":
+ tests.invalid.push(
+ invalidCode("Ci.nsIMacShellService", "missingInterface")
+ );
+ break;
+ case "linux":
+ tests.invalid.push(
+ invalidCode("Ci.mozISandboxReporter", "missingInterface")
+ );
+}
+
+ruleTester.run("valid-ci-uses", rule, tests);
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/tests/valid-lazy.js b/tools/lint/eslint/eslint-plugin-mozilla/tests/valid-lazy.js
new file mode 100644
index 0000000000..ba0a8dafab
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/tests/valid-lazy.js
@@ -0,0 +1,160 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// ------------------------------------------------------------------------------
+// Requirements
+// ------------------------------------------------------------------------------
+
+var rule = require("../lib/rules/valid-lazy");
+var RuleTester = require("eslint").RuleTester;
+
+const ruleTester = new RuleTester({
+ parserOptions: { ecmaVersion: "latest", sourceType: "module" },
+});
+
+// ------------------------------------------------------------------------------
+// Tests
+// ------------------------------------------------------------------------------
+
+function invalidCode(code, name, messageId) {
+ return { code, errors: [{ messageId, data: { name } }] };
+}
+
+ruleTester.run("valid-lazy", rule, {
+ // Note: these tests build on top of one another, although lazy gets
+ // re-declared, it
+ valid: [
+ `
+ const lazy = {};
+ ChromeUtils.defineLazyGetter(lazy, "foo", () => {});
+ if (x) { lazy.foo.bar(); }
+ `,
+ `
+ const lazy = {};
+ ChromeUtils.defineESModuleGetters(lazy, {
+ foo: "foo.mjs",
+ });
+ if (x) { lazy.foo.bar(); }
+ `,
+ `
+ const lazy = {};
+ Integration.downloads.defineESModuleGetter(lazy, "foo", "foo.sys.mjs");
+ if (x) { lazy.foo.bar(); }
+ `,
+ `
+ const lazy = createLazyLoaders({ foo: () => {}});
+ if (x) { lazy.foo.bar(); }
+ `,
+ `
+ const lazy = {};
+ loader.lazyRequireGetter(
+ lazy,
+ ["foo1", "foo2"],
+ "bar",
+ true
+ );
+ if (x) {
+ lazy.foo1.bar();
+ lazy.foo2.bar();
+ }
+ `,
+ // Test for top-level unconditional.
+ `
+ const lazy = {};
+ ChromeUtils.defineLazyGetter(lazy, "foo", () => {});
+ if (x) { lazy.foo.bar(); }
+ for (;;) { lazy.foo.bar(); }
+ for (var x in y) { lazy.foo.bar(); }
+ for (var x of y) { lazy.foo.bar(); }
+ while (true) { lazy.foo.bar(); }
+ do { lazy.foo.bar(); } while (true);
+ switch (x) { case 1: lazy.foo.bar(); }
+ try { lazy.foo.bar(); } catch (e) {}
+ function f() { lazy.foo.bar(); }
+ (function f() { lazy.foo.bar(); });
+ () => { lazy.foo.bar(); };
+ class C {
+ constructor() { lazy.foo.bar(); }
+ foo() { lazy.foo.bar(); }
+ get x() { lazy.foo.bar(); }
+ set x(v) { lazy.foo.bar(); }
+ a = lazy.foo.bar();
+ #b = lazy.foo.bar();
+ static {
+ lazy.foo.bar();
+ }
+ }
+ a && lazy.foo.bar();
+ a || lazy.foo.bar();
+ a ?? lazy.foo.bar();
+ a ? lazy.foo.bar() : b;
+ a?.b[lazy.foo.bar()];
+ a ||= lazy.foo.bar();
+ a &&= lazy.foo.bar();
+ a ??= lazy.foo.bar();
+ var { x = lazy.foo.bar() } = {};
+ var [ y = lazy.foo.bar() ] = [];
+ `,
+ `
+ const lazy = {};
+ ChromeUtils.defineLazyGetter(lazy, "foo", () => {});
+ export { lazy as Foo };
+ `,
+ `
+ const lazy = {};
+ if (cond) {
+ ChromeUtils.defineLazyGetter(lazy, "foo", () => { return 1; });
+ } else {
+ ChromeUtils.defineLazyGetter(lazy, "foo", () => { return 2; });
+ }
+ if (x) { lazy.foo; }
+ `,
+ ],
+ invalid: [
+ invalidCode("if (x) { lazy.bar; }", "bar", "unknownProperty"),
+ invalidCode(
+ `
+ const lazy = {};
+ ChromeUtils.defineLazyGetter(lazy, "foo", "foo.jsm");
+ ChromeUtils.defineLazyGetter(lazy, "foo", "foo1.jsm");
+ if (x) { lazy.foo.bar(); }
+ `,
+ "foo",
+ "duplicateSymbol"
+ ),
+ invalidCode(
+ `
+ const lazy = {};
+ XPCOMUtils.defineLazyModuleGetters(lazy, {
+ "foo-bar": "foo.jsm",
+ });
+ if (x) { lazy["foo-bar"].bar(); }
+ `,
+ "foo-bar",
+ "incorrectType"
+ ),
+ invalidCode(
+ `const lazy = {};
+ ChromeUtils.defineLazyGetter(lazy, "foo", "foo.jsm");
+ `,
+ "foo",
+ "unusedProperty"
+ ),
+ invalidCode(
+ `const lazy = {};
+ ChromeUtils.defineLazyGetter(lazy, "foo1", () => {});
+ lazy.foo1.bar();`,
+ "foo1",
+ "topLevelAndUnconditional"
+ ),
+ invalidCode(
+ `const lazy = {};
+ ChromeUtils.defineLazyGetter(lazy, "foo1", () => {});
+ { x = -f(1 + lazy.foo1.bar()); }`,
+ "foo1",
+ "topLevelAndUnconditional"
+ ),
+ ],
+});
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/tests/valid-services-property.js b/tools/lint/eslint/eslint-plugin-mozilla/tests/valid-services-property.js
new file mode 100644
index 0000000000..a9806ccc72
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/tests/valid-services-property.js
@@ -0,0 +1,42 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// ------------------------------------------------------------------------------
+// Requirements
+// ------------------------------------------------------------------------------
+
+var rule = require("../lib/rules/valid-services-property");
+var RuleTester = require("eslint").RuleTester;
+
+const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: "latest" } });
+
+// ------------------------------------------------------------------------------
+// Tests
+// ------------------------------------------------------------------------------
+
+function invalidCode(code, messageId, data) {
+ return { code, errors: [{ messageId, data }] };
+}
+
+process.env.MOZ_XPT_ARTIFACTS_DIR = `${__dirname}/xpidl`;
+
+ruleTester.run("valid-services-property", rule, {
+ valid: [
+ "Services.uriFixup.keywordToURI()",
+ "Services.uriFixup.FIXUP_FLAG_NONE",
+ ],
+ invalid: [
+ invalidCode("Services.uriFixup.UNKNOWN_CONSTANT", "unknownProperty", {
+ alias: "uriFixup",
+ propertyName: "UNKNOWN_CONSTANT",
+ checkedInterfaces: ["nsIURIFixup"],
+ }),
+ invalidCode("Services.uriFixup.foo()", "unknownProperty", {
+ alias: "uriFixup",
+ propertyName: "foo",
+ checkedInterfaces: ["nsIURIFixup"],
+ }),
+ ],
+});
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/tests/valid-services.js b/tools/lint/eslint/eslint-plugin-mozilla/tests/valid-services.js
new file mode 100644
index 0000000000..1453e95b7b
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/tests/valid-services.js
@@ -0,0 +1,32 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// ------------------------------------------------------------------------------
+// Requirements
+// ------------------------------------------------------------------------------
+
+var rule = require("../lib/rules/valid-services");
+var RuleTester = require("eslint").RuleTester;
+
+const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: "latest" } });
+
+// ------------------------------------------------------------------------------
+// Tests
+// ------------------------------------------------------------------------------
+
+function invalidCode(code, alias) {
+ return { code, errors: [{ messageId: "unknownProperty", data: { alias } }] };
+}
+
+ruleTester.run("valid-services", rule, {
+ valid: ["Services.crashmanager", "lazy.Services.crashmanager"],
+ invalid: [
+ invalidCode("Services.foo", "foo"),
+ invalidCode("Services.foo()", "foo"),
+ invalidCode("lazy.Services.foo", "foo"),
+ invalidCode("Services.foo.bar()", "foo"),
+ invalidCode("lazy.Services.foo.bar()", "foo"),
+ ],
+});
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/tests/xpidl/docshell.xpt b/tools/lint/eslint/eslint-plugin-mozilla/tests/xpidl/docshell.xpt
new file mode 100644
index 0000000000..fc8a45216b
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/tests/xpidl/docshell.xpt
@@ -0,0 +1,5940 @@
+[
+ {
+ "consts": [
+ {
+ "name": "ePrompt",
+ "type": {
+ "tag": "TD_UINT8"
+ },
+ "value": 0
+ },
+ {
+ "name": "eDontPromptAndDontUnload",
+ "type": {
+ "tag": "TD_UINT8"
+ },
+ "value": 1
+ },
+ {
+ "name": "eDontPromptAndUnload",
+ "type": {
+ "tag": "TD_UINT8"
+ },
+ "value": 2
+ },
+ {
+ "name": "eAllowNavigation",
+ "type": {
+ "tag": "TD_UINT8"
+ },
+ "value": 0
+ },
+ {
+ "name": "eRequestBlockNavigation",
+ "type": {
+ "tag": "TD_UINT8"
+ },
+ "value": 1
+ },
+ {
+ "name": "eDelayResize",
+ "type": {
+ "tag": "TD_UINT32"
+ },
+ "value": 1
+ }
+ ],
+ "flags": [
+ "builtinclass"
+ ],
+ "methods": [
+ {
+ "flags": [
+ "hidden"
+ ],
+ "name": "init",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_VOID"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_VOID"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_VOID"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "container",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "name": "nsIDocShell",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "setter"
+ ],
+ "name": "container",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsIDocShell",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "hidden"
+ ],
+ "name": "loadStart",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "headerFile": "mozilla/dom/Document.h",
+ "name": "Document",
+ "native": "mozilla::dom::Document",
+ "tag": "TD_DOMOBJECT"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [],
+ "name": "loadComplete",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_UINT32"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hidden",
+ "hasretval"
+ ],
+ "name": "loadCompleted",
+ "params": []
+ },
+ {
+ "flags": [
+ "getter",
+ "hidden",
+ "hasretval"
+ ],
+ "name": "isStopped",
+ "params": []
+ },
+ {
+ "flags": [
+ "hasretval"
+ ],
+ "name": "permitUnload",
+ "params": [
+ {
+ "flags": [
+ "in",
+ "optional"
+ ],
+ "type": {
+ "tag": "TD_UINT8"
+ }
+ },
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "inPermitUnload",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "hidden"
+ ],
+ "name": "dispatchBeforeUnload",
+ "params": []
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "beforeUnloadFiring",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [],
+ "name": "pageHide",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [],
+ "name": "close",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsISHEntry",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [],
+ "name": "destroy",
+ "params": []
+ },
+ {
+ "flags": [],
+ "name": "stop",
+ "params": []
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "DOMDocument",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "headerFile": "mozilla/dom/Document.h",
+ "name": "Document",
+ "native": "mozilla::dom::Document",
+ "tag": "TD_DOMOBJECT"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "hidden"
+ ],
+ "name": "getDocument",
+ "params": []
+ },
+ {
+ "flags": [
+ "hidden"
+ ],
+ "name": "setDocument",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "headerFile": "mozilla/dom/Document.h",
+ "name": "Document",
+ "native": "mozilla::dom::Document",
+ "tag": "TD_DOMOBJECT"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "hidden"
+ ],
+ "name": "getBounds",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_VOID"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "hidden"
+ ],
+ "name": "setBounds",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_VOID"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "hidden"
+ ],
+ "name": "setBoundsWithFlags",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_VOID"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_UINT32"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hidden",
+ "hasretval"
+ ],
+ "name": "previousViewer",
+ "params": []
+ },
+ {
+ "flags": [
+ "setter",
+ "hidden"
+ ],
+ "name": "previousViewer",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsIDocumentViewer",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [],
+ "name": "move",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_INT32"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_INT32"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [],
+ "name": "show",
+ "params": []
+ },
+ {
+ "flags": [],
+ "name": "hide",
+ "params": []
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "sticky",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "setter"
+ ],
+ "name": "sticky",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [],
+ "name": "open",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsISupports",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsISHEntry",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [],
+ "name": "clearHistoryEntry",
+ "params": []
+ },
+ {
+ "flags": [],
+ "name": "setPageModeForTesting",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsIPrintSettings",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [],
+ "name": "setPrintSettingsForSubdocument",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsIPrintSettings",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_VOID"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "historyEntry",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "name": "nsISHEntry",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "isTabModalPromptAllowed",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "isHidden",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "setter"
+ ],
+ "name": "isHidden",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hidden",
+ "hasretval"
+ ],
+ "name": "presShell",
+ "params": []
+ },
+ {
+ "flags": [
+ "getter",
+ "hidden",
+ "hasretval"
+ ],
+ "name": "presContext",
+ "params": []
+ },
+ {
+ "flags": [
+ "hidden"
+ ],
+ "name": "setDocumentInternal",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "headerFile": "mozilla/dom/Document.h",
+ "name": "Document",
+ "native": "mozilla::dom::Document",
+ "tag": "TD_DOMOBJECT"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "hidden"
+ ],
+ "name": "findContainerView",
+ "params": []
+ },
+ {
+ "flags": [
+ "hidden"
+ ],
+ "name": "setNavigationTiming",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_VOID"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "deviceFullZoomForTest",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_FLOAT"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "authorStyleDisabled",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "setter"
+ ],
+ "name": "authorStyleDisabled",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [],
+ "name": "getContentSize",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_INT32"
+ }
+ },
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_INT32"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [],
+ "name": "getContentSizeConstrained",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_INT32"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_INT32"
+ }
+ },
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_INT32"
+ }
+ },
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_INT32"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "hidden"
+ ],
+ "name": "getReloadEncodingAndSource",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_INT32"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "hidden"
+ ],
+ "name": "setReloadEncodingAndSource",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_VOID"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_INT32"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "hidden"
+ ],
+ "name": "forgetReloadEncoding",
+ "params": []
+ }
+ ],
+ "name": "nsIDocumentViewer",
+ "parent": "nsISupports",
+ "uuid": "48118355-e9a5-4452-ab18-59cc426fb817"
+ },
+ {
+ "consts": [
+ {
+ "name": "COPY_IMAGE_TEXT",
+ "type": {
+ "tag": "TD_INT32"
+ },
+ "value": 1
+ },
+ {
+ "name": "COPY_IMAGE_HTML",
+ "type": {
+ "tag": "TD_INT32"
+ },
+ "value": 2
+ },
+ {
+ "name": "COPY_IMAGE_DATA",
+ "type": {
+ "tag": "TD_INT32"
+ },
+ "value": 4
+ },
+ {
+ "name": "COPY_IMAGE_ALL",
+ "type": {
+ "tag": "TD_INT32"
+ },
+ "value": -1
+ }
+ ],
+ "flags": [],
+ "methods": [
+ {
+ "flags": [],
+ "name": "clearSelection",
+ "params": []
+ },
+ {
+ "flags": [],
+ "name": "selectAll",
+ "params": []
+ },
+ {
+ "flags": [],
+ "name": "copySelection",
+ "params": []
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "copyable",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [],
+ "name": "copyLinkLocation",
+ "params": []
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "inLink",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [],
+ "name": "copyImage",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_INT32"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "inImage",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "hasretval"
+ ],
+ "name": "getContents",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_PSTRING"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ },
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_ASTRING"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "canGetContents",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [],
+ "name": "setCommandNode",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "headerFile": "nsIContent.h",
+ "name": "Node",
+ "native": "nsINode",
+ "tag": "TD_DOMOBJECT"
+ }
+ }
+ ]
+ }
+ ],
+ "name": "nsIDocumentViewerEdit",
+ "parent": "nsISupports",
+ "uuid": "35be2d7e-f29b-48ec-bf7e-80a30a724de3"
+ },
+ {
+ "consts": [
+ {
+ "name": "ENUMERATE_FORWARDS",
+ "type": {
+ "tag": "TD_UINT8"
+ },
+ "value": 0
+ },
+ {
+ "name": "ENUMERATE_BACKWARDS",
+ "type": {
+ "tag": "TD_UINT8"
+ },
+ "value": 1
+ },
+ {
+ "name": "APP_TYPE_UNKNOWN",
+ "type": {
+ "tag": "TD_UINT8"
+ },
+ "value": 0
+ },
+ {
+ "name": "APP_TYPE_MAIL",
+ "type": {
+ "tag": "TD_UINT8"
+ },
+ "value": 1
+ },
+ {
+ "name": "APP_TYPE_EDITOR",
+ "type": {
+ "tag": "TD_UINT8"
+ },
+ "value": 2
+ },
+ {
+ "name": "BUSY_FLAGS_NONE",
+ "type": {
+ "tag": "TD_UINT8"
+ },
+ "value": 0
+ },
+ {
+ "name": "BUSY_FLAGS_BUSY",
+ "type": {
+ "tag": "TD_UINT8"
+ },
+ "value": 1
+ },
+ {
+ "name": "BUSY_FLAGS_BEFORE_PAGE_LOAD",
+ "type": {
+ "tag": "TD_UINT8"
+ },
+ "value": 2
+ },
+ {
+ "name": "BUSY_FLAGS_PAGE_LOADING",
+ "type": {
+ "tag": "TD_UINT8"
+ },
+ "value": 4
+ },
+ {
+ "name": "LOAD_CMD_NORMAL",
+ "type": {
+ "tag": "TD_UINT8"
+ },
+ "value": 1
+ },
+ {
+ "name": "LOAD_CMD_RELOAD",
+ "type": {
+ "tag": "TD_UINT8"
+ },
+ "value": 2
+ },
+ {
+ "name": "LOAD_CMD_HISTORY",
+ "type": {
+ "tag": "TD_UINT8"
+ },
+ "value": 4
+ },
+ {
+ "name": "LOAD_CMD_PUSHSTATE",
+ "type": {
+ "tag": "TD_UINT8"
+ },
+ "value": 8
+ },
+ {
+ "name": "META_VIEWPORT_OVERRIDE_DISABLED",
+ "type": {
+ "tag": "TD_UINT8"
+ },
+ "value": 0
+ },
+ {
+ "name": "META_VIEWPORT_OVERRIDE_ENABLED",
+ "type": {
+ "tag": "TD_UINT8"
+ },
+ "value": 1
+ },
+ {
+ "name": "META_VIEWPORT_OVERRIDE_NONE",
+ "type": {
+ "tag": "TD_UINT8"
+ },
+ "value": 2
+ }
+ ],
+ "flags": [
+ "builtinclass"
+ ],
+ "methods": [
+ {
+ "flags": [],
+ "name": "setCancelContentJSEpoch",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_INT32"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "hidden"
+ ],
+ "name": "loadURI",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_VOID"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "jscontext"
+ ],
+ "name": "addState",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_JSVAL"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_ASTRING"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_ASTRING"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [],
+ "name": "prepareForNewContentModel",
+ "params": []
+ },
+ {
+ "flags": [],
+ "name": "setCurrentURIForSessionStore",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsIURI",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "hidden"
+ ],
+ "name": "firePageHideNotification",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hidden",
+ "hasretval"
+ ],
+ "name": "presContext",
+ "params": []
+ },
+ {
+ "flags": [
+ "getter",
+ "hidden",
+ "hasretval"
+ ],
+ "name": "presShell",
+ "params": []
+ },
+ {
+ "flags": [
+ "getter",
+ "hidden",
+ "hasretval"
+ ],
+ "name": "eldestPresShell",
+ "params": []
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "docViewer",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "name": "nsIDocumentViewer",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "outerWindowID",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_UINT64"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "chromeEventHandler",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "headerFile": "mozilla/dom/EventTarget.h",
+ "name": "EventTarget",
+ "native": "mozilla::dom::EventTarget",
+ "tag": "TD_DOMOBJECT"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "setter"
+ ],
+ "name": "chromeEventHandler",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "headerFile": "mozilla/dom/EventTarget.h",
+ "name": "EventTarget",
+ "native": "mozilla::dom::EventTarget",
+ "tag": "TD_DOMOBJECT"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "customUserAgent",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_ASTRING"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "setter"
+ ],
+ "name": "customUserAgent",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_ASTRING"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "cssErrorReportingEnabled",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "setter"
+ ],
+ "name": "cssErrorReportingEnabled",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "allowPlugins",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "setter"
+ ],
+ "name": "allowPlugins",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "allowMetaRedirects",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "setter"
+ ],
+ "name": "allowMetaRedirects",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "allowSubframes",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "setter"
+ ],
+ "name": "allowSubframes",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "allowImages",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "setter"
+ ],
+ "name": "allowImages",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "allowMedia",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "setter"
+ ],
+ "name": "allowMedia",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "allowDNSPrefetch",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "setter"
+ ],
+ "name": "allowDNSPrefetch",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "allowWindowControl",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "setter"
+ ],
+ "name": "allowWindowControl",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "allowContentRetargeting",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "setter"
+ ],
+ "name": "allowContentRetargeting",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "allowContentRetargetingOnChildren",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "setter"
+ ],
+ "name": "allowContentRetargetingOnChildren",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "hasretval"
+ ],
+ "name": "getAllDocShellsInSubtree",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_INT32"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_UINT8"
+ }
+ },
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "element": {
+ "name": "nsIDocShell",
+ "tag": "TD_INTERFACE_TYPE"
+ },
+ "tag": "TD_ARRAY"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "appType",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_UINT8"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "setter"
+ ],
+ "name": "appType",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_UINT8"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "allowAuth",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "setter"
+ ],
+ "name": "allowAuth",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "zoom",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_FLOAT"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "setter"
+ ],
+ "name": "zoom",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_FLOAT"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "hasretval"
+ ],
+ "name": "tabToTreeOwner",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ },
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "busyFlags",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_UINT8"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "loadType",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_UINT32"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "setter"
+ ],
+ "name": "loadType",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_UINT32"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "defaultLoadFlags",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_UINT32"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "setter"
+ ],
+ "name": "defaultLoadFlags",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_UINT32"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "hasretval"
+ ],
+ "name": "isBeingDestroyed",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "isExecutingOnLoadHandler",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "layoutHistoryState",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "name": "nsILayoutHistoryState",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "setter"
+ ],
+ "name": "layoutHistoryState",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsILayoutHistoryState",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "loadURIDelegate",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "name": "nsILoadURIDelegate",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [],
+ "name": "suspendRefreshURIs",
+ "params": []
+ },
+ {
+ "flags": [],
+ "name": "resumeRefreshURIs",
+ "params": []
+ },
+ {
+ "flags": [],
+ "name": "beginRestore",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsIDocumentViewer",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [],
+ "name": "finishRestore",
+ "params": []
+ },
+ {
+ "flags": [],
+ "name": "clearCachedUserAgent",
+ "params": []
+ },
+ {
+ "flags": [],
+ "name": "clearCachedPlatform",
+ "params": []
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "restoringDocument",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "useErrorPages",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "setter"
+ ],
+ "name": "useErrorPages",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "hasretval"
+ ],
+ "name": "displayLoadError",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_UINT32"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsIURI",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_PWSTRING"
+ }
+ },
+ {
+ "flags": [
+ "in",
+ "optional"
+ ],
+ "type": {
+ "name": "nsIChannel",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ },
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "failedChannel",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "name": "nsIChannel",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "previousEntryIndex",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_INT32"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "loadedEntryIndex",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_INT32"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [],
+ "name": "historyPurged",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_INT32"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "currentDocumentChannel",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "name": "nsIChannel",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "isInUnload",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "hidden"
+ ],
+ "name": "DetachEditorFromWindow",
+ "params": []
+ },
+ {
+ "flags": [],
+ "name": "exitPrintPreview",
+ "params": []
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "historyID",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_NSID"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "hidden"
+ ],
+ "name": "HistoryID",
+ "params": []
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "isAppTab",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "setter"
+ ],
+ "name": "isAppTab",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [],
+ "name": "createAboutBlankDocumentViewer",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsIPrincipal",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsIPrincipal",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ },
+ {
+ "flags": [
+ "in",
+ "optional"
+ ],
+ "type": {
+ "name": "nsIContentSecurityPolicy",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "charset",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_CSTRING"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [],
+ "name": "forceEncodingDetection",
+ "params": []
+ },
+ {
+ "flags": [
+ "hidden"
+ ],
+ "name": "setParentCharset",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_VOID"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_INT32"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsIPrincipal",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "hidden"
+ ],
+ "name": "getParentCharset",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_VOID"
+ }
+ },
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_INT32"
+ }
+ },
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "name": "nsIPrincipal",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "hasretval"
+ ],
+ "name": "now",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_DOUBLE"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [],
+ "name": "addWeakPrivacyTransitionObserver",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsIPrivacyTransitionObserver",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [],
+ "name": "addWeakReflowObserver",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsIReflowObserver",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [],
+ "name": "removeWeakReflowObserver",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsIReflowObserver",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "hidden"
+ ],
+ "name": "notifyReflowObservers",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_DOUBLE"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_DOUBLE"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "hidden"
+ ],
+ "name": "addWeakScrollObserver",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsIScrollObserver",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "hidden"
+ ],
+ "name": "removeWeakScrollObserver",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsIScrollObserver",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "hidden"
+ ],
+ "name": "notifyScrollObservers",
+ "params": []
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "isTopLevelContentDocShell",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "asyncPanZoomEnabled",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "hidden"
+ ],
+ "name": "pluginsAllowedInCurrentDoc",
+ "params": []
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "mayEnableCharacterEncodingMenu",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "editor",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "name": "nsIEditor",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "setter"
+ ],
+ "name": "editor",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsIEditor",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "editable",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "hasEditingSession",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [],
+ "name": "makeEditable",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "hasretval"
+ ],
+ "name": "getCurrentSHEntry",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "name": "nsISHEntry",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ },
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "hasretval"
+ ],
+ "name": "isCommandEnabled",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_PSTRING"
+ }
+ },
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [],
+ "name": "doCommand",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_PSTRING"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [],
+ "name": "doCommandWithParams",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_PSTRING"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsICommandParams",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "hidden"
+ ],
+ "name": "IsInvisible",
+ "params": []
+ },
+ {
+ "flags": [
+ "hidden"
+ ],
+ "name": "SetInvisible",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "hidden"
+ ],
+ "name": "GetScriptGlobalObject",
+ "params": []
+ },
+ {
+ "flags": [
+ "hidden"
+ ],
+ "name": "getExtantDocument",
+ "params": []
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "deviceSizeIsPageSize",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "setter"
+ ],
+ "name": "deviceSizeIsPageSize",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "hasLoadedNonBlankURI",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "windowDraggingAllowed",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "setter"
+ ],
+ "name": "windowDraggingAllowed",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "currentScrollRestorationIsManual",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "setter"
+ ],
+ "name": "currentScrollRestorationIsManual",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "jscontext",
+ "hasretval"
+ ],
+ "name": "getOriginAttributes",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_JSVAL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "jscontext"
+ ],
+ "name": "setOriginAttributes",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_JSVAL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "editingSession",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "name": "nsIEditingSession",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "browserChild",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "name": "nsIBrowserChild",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "hidden"
+ ],
+ "name": "GetBrowserChild",
+ "params": []
+ },
+ {
+ "flags": [
+ "hidden"
+ ],
+ "name": "GetCommandManager",
+ "params": []
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "metaViewportOverride",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_UINT8"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "setter"
+ ],
+ "name": "metaViewportOverride",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_UINT8"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "useTrackingProtection",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "setter"
+ ],
+ "name": "useTrackingProtection",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "hidden"
+ ],
+ "name": "dispatchLocationChangeEvent",
+ "params": []
+ },
+ {
+ "flags": [
+ "hidden"
+ ],
+ "name": "startDelayedAutoplayMediaComponents",
+ "params": []
+ },
+ {
+ "flags": [
+ "hidden"
+ ],
+ "name": "TakeInitialClientSource",
+ "params": []
+ },
+ {
+ "flags": [],
+ "name": "setColorMatrix",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "element": {
+ "tag": "TD_FLOAT"
+ },
+ "tag": "TD_ARRAY"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "isForceReloading",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "hasretval"
+ ],
+ "name": "getColorMatrix",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "element": {
+ "tag": "TD_FLOAT"
+ },
+ "tag": "TD_ARRAY"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "messageManager",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "headerFile": "mozilla/dom/ContentFrameMessageManager.h",
+ "name": "ContentFrameMessageManager",
+ "native": "mozilla::dom::ContentFrameMessageManager",
+ "tag": "TD_DOMOBJECT"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "hasretval"
+ ],
+ "name": "getHasTrackingContentBlocked",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_PROMISE"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hidden",
+ "hasretval"
+ ],
+ "name": "isAttemptingToNavigate",
+ "params": []
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "isNavigating",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [],
+ "name": "synchronizeLayoutHistoryState",
+ "params": []
+ },
+ {
+ "flags": [],
+ "name": "persistLayoutHistoryState",
+ "params": []
+ }
+ ],
+ "name": "nsIDocShell",
+ "parent": "nsIDocShellTreeItem",
+ "uuid": "049234fe-da10-478b-bc5d-bc6f9a1ba63d"
+ },
+ {
+ "consts": [
+ {
+ "name": "typeChrome",
+ "type": {
+ "tag": "TD_INT32"
+ },
+ "value": 0
+ },
+ {
+ "name": "typeContent",
+ "type": {
+ "tag": "TD_INT32"
+ },
+ "value": 1
+ },
+ {
+ "name": "typeContentWrapper",
+ "type": {
+ "tag": "TD_INT32"
+ },
+ "value": 2
+ },
+ {
+ "name": "typeChromeWrapper",
+ "type": {
+ "tag": "TD_INT32"
+ },
+ "value": 3
+ },
+ {
+ "name": "typeAll",
+ "type": {
+ "tag": "TD_INT32"
+ },
+ "value": 2147483647
+ }
+ ],
+ "flags": [
+ "builtinclass"
+ ],
+ "methods": [
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "name",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_ASTRING"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "setter"
+ ],
+ "name": "name",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_ASTRING"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "hasretval"
+ ],
+ "name": "nameEquals",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_ASTRING"
+ }
+ },
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "itemType",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_INT32"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "hidden"
+ ],
+ "name": "ItemType",
+ "params": []
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "parent",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "name": "nsIDocShellTreeItem",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "sameTypeParent",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "name": "nsIDocShellTreeItem",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "rootTreeItem",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "name": "nsIDocShellTreeItem",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "sameTypeRootTreeItem",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "name": "nsIDocShellTreeItem",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "treeOwner",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "name": "nsIDocShellTreeOwner",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "hidden"
+ ],
+ "name": "setTreeOwner",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsIDocShellTreeOwner",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "childCount",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_INT32"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "hidden"
+ ],
+ "name": "addChild",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsIDocShellTreeItem",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "hidden"
+ ],
+ "name": "removeChild",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsIDocShellTreeItem",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "hasretval"
+ ],
+ "name": "getChildAt",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_INT32"
+ }
+ },
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "name": "nsIDocShellTreeItem",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "browsingContext",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "headerFile": "mozilla/dom/BrowsingContext.h",
+ "name": "BrowsingContext",
+ "native": "mozilla::dom::BrowsingContext",
+ "tag": "TD_DOMOBJECT"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "hidden"
+ ],
+ "name": "getBrowsingContext",
+ "params": []
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "domWindow",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "name": "mozIDOMWindowProxy",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "hidden"
+ ],
+ "name": "getDocument",
+ "params": []
+ },
+ {
+ "flags": [
+ "hidden"
+ ],
+ "name": "getWindow",
+ "params": []
+ }
+ ],
+ "name": "nsIDocShellTreeItem",
+ "parent": "nsISupports",
+ "uuid": "9b7c586f-9214-480c-a2c4-49b526fff1a6"
+ },
+ {
+ "consts": [],
+ "flags": [],
+ "methods": [
+ {
+ "flags": [],
+ "name": "contentShellAdded",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsIDocShellTreeItem",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [],
+ "name": "contentShellRemoved",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsIDocShellTreeItem",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "primaryContentShell",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "name": "nsIDocShellTreeItem",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [],
+ "name": "remoteTabAdded",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsIRemoteTab",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [],
+ "name": "remoteTabRemoved",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsIRemoteTab",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "primaryRemoteTab",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "name": "nsIRemoteTab",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "primaryContentBrowsingContext",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "headerFile": "mozilla/dom/BrowsingContext.h",
+ "name": "BrowsingContext",
+ "native": "mozilla::dom::BrowsingContext",
+ "tag": "TD_DOMOBJECT"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [],
+ "name": "sizeShellTo",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsIDocShellTreeItem",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_INT32"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_INT32"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [],
+ "name": "getPrimaryContentSize",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_INT32"
+ }
+ },
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_INT32"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [],
+ "name": "setPrimaryContentSize",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_INT32"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_INT32"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [],
+ "name": "getRootShellSize",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_INT32"
+ }
+ },
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_INT32"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [],
+ "name": "setRootShellSize",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_INT32"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_INT32"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [],
+ "name": "setPersistence",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [],
+ "name": "getPersistence",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ },
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ },
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "tabCount",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_UINT32"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "hasPrimaryContent",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ }
+ ],
+ "name": "nsIDocShellTreeOwner",
+ "parent": "nsISupports",
+ "uuid": "0e3dc4b1-4cea-4a37-af71-79f0afd07574"
+ },
+ {
+ "consts": [],
+ "flags": [],
+ "methods": [
+ {
+ "flags": [
+ "hasretval"
+ ],
+ "name": "createInstance",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_PSTRING"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsIChannel",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsILoadGroup",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_CSTRING"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsIDocShell",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsISupports",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ },
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "name": "nsIStreamListener",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ },
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "name": "nsIDocumentViewer",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "hasretval"
+ ],
+ "name": "createInstanceForDocument",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsISupports",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "headerFile": "mozilla/dom/Document.h",
+ "name": "Document",
+ "native": "mozilla::dom::Document",
+ "tag": "TD_DOMOBJECT"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_PSTRING"
+ }
+ },
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "name": "nsIDocumentViewer",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ }
+ ]
+ }
+ ],
+ "name": "nsIDocumentLoaderFactory",
+ "parent": "nsISupports",
+ "uuid": "e795239e-9d3c-47c4-b063-9e600fb3b287"
+ },
+ {
+ "consts": [],
+ "flags": [
+ "builtinclass"
+ ],
+ "methods": [
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "associatedWindow",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "name": "mozIDOMWindowProxy",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "topWindow",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "name": "mozIDOMWindowProxy",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "topFrameElement",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "headerFile": "mozilla/dom/Element.h",
+ "name": "Element",
+ "native": "mozilla::dom::Element",
+ "tag": "TD_DOMOBJECT"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "isContent",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "usePrivateBrowsing",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "setter"
+ ],
+ "name": "usePrivateBrowsing",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "useRemoteTabs",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "useRemoteSubframes",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "useTrackingProtection",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "setter"
+ ],
+ "name": "useTrackingProtection",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "hidden"
+ ],
+ "name": "SetPrivateBrowsing",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "hidden"
+ ],
+ "name": "SetRemoteTabs",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "hidden"
+ ],
+ "name": "SetRemoteSubframes",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "jscontext",
+ "hasretval"
+ ],
+ "name": "originAttributes",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_JSVAL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "hidden"
+ ],
+ "name": "GetOriginAttributes",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_VOID"
+ }
+ }
+ ]
+ }
+ ],
+ "name": "nsILoadContext",
+ "parent": "nsISupports",
+ "uuid": "2813a7a3-d084-4d00-acd0-f76620315c02"
+ },
+ {
+ "consts": [],
+ "flags": [],
+ "methods": [
+ {
+ "flags": [
+ "hasretval"
+ ],
+ "name": "loadURI",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsIURI",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_INT16"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_INT32"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsIPrincipal",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ },
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "hasretval"
+ ],
+ "name": "handleLoadError",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsIURI",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_UINT32"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_INT16"
+ }
+ },
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "name": "nsIURI",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ }
+ ]
+ }
+ ],
+ "name": "nsILoadURIDelegate",
+ "parent": "nsISupports",
+ "uuid": "78e42d37-a34c-4d96-b901-25385669aba4"
+ },
+ {
+ "consts": [],
+ "flags": [
+ "function"
+ ],
+ "methods": [
+ {
+ "flags": [],
+ "name": "privateModeChanged",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ }
+ ],
+ "name": "nsIPrivacyTransitionObserver",
+ "parent": "nsISupports",
+ "uuid": "b4b1449d-0ef0-47f5-b62e-adc57fd49702"
+ },
+ {
+ "consts": [],
+ "flags": [],
+ "methods": [
+ {
+ "flags": [],
+ "name": "reflow",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_DOUBLE"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_DOUBLE"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [],
+ "name": "reflowInterruptible",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_DOUBLE"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_DOUBLE"
+ }
+ }
+ ]
+ }
+ ],
+ "name": "nsIReflowObserver",
+ "parent": "nsISupports",
+ "uuid": "832e692c-c4a6-11e2-8fd1-dce678957a39"
+ },
+ {
+ "consts": [],
+ "flags": [],
+ "methods": [
+ {
+ "flags": [],
+ "name": "refreshURI",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsIURI",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsIPrincipal",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_UINT32"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [],
+ "name": "forceRefreshURI",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsIURI",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsIPrincipal",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_UINT32"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [],
+ "name": "cancelRefreshURITimers",
+ "params": []
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "refreshPending",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ }
+ ],
+ "name": "nsIRefreshURI",
+ "parent": "nsISupports",
+ "uuid": "a5e61a3c-51bd-45be-ac0c-e87b71860656"
+ },
+ {
+ "consts": [],
+ "flags": [],
+ "methods": [
+ {
+ "flags": [],
+ "name": "onShowTooltip",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_INT32"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_INT32"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_ASTRING"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_ASTRING"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [],
+ "name": "onHideTooltip",
+ "params": []
+ }
+ ],
+ "name": "nsITooltipListener",
+ "parent": "nsISupports",
+ "uuid": "44b78386-1dd2-11b2-9ad2-e4eee2ca1916"
+ },
+ {
+ "consts": [],
+ "flags": [],
+ "methods": [
+ {
+ "flags": [
+ "hasretval"
+ ],
+ "name": "getNodeText",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "headerFile": "nsIContent.h",
+ "name": "Node",
+ "native": "nsINode",
+ "tag": "TD_DOMOBJECT"
+ }
+ },
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_PWSTRING"
+ }
+ },
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_PWSTRING"
+ }
+ },
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ }
+ ],
+ "name": "nsITooltipTextProvider",
+ "parent": "nsISupports",
+ "uuid": "b128a1e6-44f3-4331-8fbe-5af360ff21ee"
+ },
+ {
+ "consts": [],
+ "flags": [],
+ "methods": [
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "consumer",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "headerFile": "mozilla/dom/BrowsingContext.h",
+ "name": "BrowsingContext",
+ "native": "mozilla::dom::BrowsingContext",
+ "tag": "TD_DOMOBJECT"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "setter"
+ ],
+ "name": "consumer",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "headerFile": "mozilla/dom/BrowsingContext.h",
+ "name": "BrowsingContext",
+ "native": "mozilla::dom::BrowsingContext",
+ "tag": "TD_DOMOBJECT"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "preferredURI",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "name": "nsIURI",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "setter"
+ ],
+ "name": "preferredURI",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsIURI",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "fixedURI",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "name": "nsIURI",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "setter"
+ ],
+ "name": "fixedURI",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsIURI",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "keywordProviderName",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_ASTRING"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "setter"
+ ],
+ "name": "keywordProviderName",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_ASTRING"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "keywordAsSent",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_ASTRING"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "setter"
+ ],
+ "name": "keywordAsSent",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_ASTRING"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "fixupChangedProtocol",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "setter"
+ ],
+ "name": "fixupChangedProtocol",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "fixupCreatedAlternateURI",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "setter"
+ ],
+ "name": "fixupCreatedAlternateURI",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "originalInput",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_UTF8STRING"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "setter"
+ ],
+ "name": "originalInput",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_UTF8STRING"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "postData",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "name": "nsIInputStream",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "setter"
+ ],
+ "name": "postData",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsIInputStream",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ }
+ ]
+ }
+ ],
+ "name": "nsIURIFixupInfo",
+ "parent": "nsISupports",
+ "uuid": "4819f183-b532-4932-ac09-b309cd853be7"
+ },
+ {
+ "consts": [
+ {
+ "name": "FIXUP_FLAG_NONE",
+ "type": {
+ "tag": "TD_UINT32"
+ },
+ "value": 0
+ },
+ {
+ "name": "FIXUP_FLAG_ALLOW_KEYWORD_LOOKUP",
+ "type": {
+ "tag": "TD_UINT32"
+ },
+ "value": 1
+ },
+ {
+ "name": "FIXUP_FLAGS_MAKE_ALTERNATE_URI",
+ "type": {
+ "tag": "TD_UINT32"
+ },
+ "value": 2
+ },
+ {
+ "name": "FIXUP_FLAG_PRIVATE_CONTEXT",
+ "type": {
+ "tag": "TD_UINT32"
+ },
+ "value": 4
+ },
+ {
+ "name": "FIXUP_FLAG_FIX_SCHEME_TYPOS",
+ "type": {
+ "tag": "TD_UINT32"
+ },
+ "value": 8
+ }
+ ],
+ "flags": [],
+ "methods": [
+ {
+ "flags": [
+ "hasretval"
+ ],
+ "name": "getFixupURIInfo",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_UTF8STRING"
+ }
+ },
+ {
+ "flags": [
+ "in",
+ "optional"
+ ],
+ "type": {
+ "tag": "TD_UINT32"
+ }
+ },
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "name": "nsIURIFixupInfo",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "hasretval"
+ ],
+ "name": "webNavigationFlagsToFixupFlags",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_UTF8STRING"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_UINT32"
+ }
+ },
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_UINT32"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "hasretval"
+ ],
+ "name": "keywordToURI",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_UTF8STRING"
+ }
+ },
+ {
+ "flags": [
+ "in",
+ "optional"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ },
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "name": "nsIURIFixupInfo",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "hasretval"
+ ],
+ "name": "forceHttpFixup",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_UTF8STRING"
+ }
+ },
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "name": "nsIURIFixupInfo",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [],
+ "name": "checkHost",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsIURI",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsIDNSListener",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ },
+ {
+ "flags": [
+ "in",
+ "optional"
+ ],
+ "type": {
+ "tag": "TD_JSVAL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "hasretval"
+ ],
+ "name": "isDomainKnown",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_UTF8STRING"
+ }
+ },
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ }
+ ],
+ "name": "nsIURIFixup",
+ "parent": "nsISupports",
+ "uuid": "1da7e9d4-620b-4949-849a-1cd6077b1b2d"
+ },
+ {
+ "consts": [
+ {
+ "name": "LOAD_FLAGS_MASK",
+ "type": {
+ "tag": "TD_UINT32"
+ },
+ "value": 65535
+ },
+ {
+ "name": "LOAD_FLAGS_NONE",
+ "type": {
+ "tag": "TD_UINT32"
+ },
+ "value": 0
+ },
+ {
+ "name": "LOAD_FLAGS_IS_REFRESH",
+ "type": {
+ "tag": "TD_UINT32"
+ },
+ "value": 16
+ },
+ {
+ "name": "LOAD_FLAGS_IS_LINK",
+ "type": {
+ "tag": "TD_UINT32"
+ },
+ "value": 32
+ },
+ {
+ "name": "LOAD_FLAGS_BYPASS_HISTORY",
+ "type": {
+ "tag": "TD_UINT32"
+ },
+ "value": 64
+ },
+ {
+ "name": "LOAD_FLAGS_REPLACE_HISTORY",
+ "type": {
+ "tag": "TD_UINT32"
+ },
+ "value": 128
+ },
+ {
+ "name": "LOAD_FLAGS_BYPASS_CACHE",
+ "type": {
+ "tag": "TD_UINT32"
+ },
+ "value": 256
+ },
+ {
+ "name": "LOAD_FLAGS_BYPASS_PROXY",
+ "type": {
+ "tag": "TD_UINT32"
+ },
+ "value": 512
+ },
+ {
+ "name": "LOAD_FLAGS_CHARSET_CHANGE",
+ "type": {
+ "tag": "TD_UINT32"
+ },
+ "value": 1024
+ },
+ {
+ "name": "LOAD_FLAGS_STOP_CONTENT",
+ "type": {
+ "tag": "TD_UINT32"
+ },
+ "value": 2048
+ },
+ {
+ "name": "LOAD_FLAGS_FROM_EXTERNAL",
+ "type": {
+ "tag": "TD_UINT32"
+ },
+ "value": 4096
+ },
+ {
+ "name": "LOAD_FLAGS_FIRST_LOAD",
+ "type": {
+ "tag": "TD_UINT32"
+ },
+ "value": 16384
+ },
+ {
+ "name": "LOAD_FLAGS_ALLOW_POPUPS",
+ "type": {
+ "tag": "TD_UINT32"
+ },
+ "value": 32768
+ },
+ {
+ "name": "LOAD_FLAGS_BYPASS_CLASSIFIER",
+ "type": {
+ "tag": "TD_UINT32"
+ },
+ "value": 65536
+ },
+ {
+ "name": "LOAD_FLAGS_FORCE_ALLOW_COOKIES",
+ "type": {
+ "tag": "TD_UINT32"
+ },
+ "value": 131072
+ },
+ {
+ "name": "LOAD_FLAGS_DISALLOW_INHERIT_PRINCIPAL",
+ "type": {
+ "tag": "TD_UINT32"
+ },
+ "value": 262144
+ },
+ {
+ "name": "LOAD_FLAGS_ERROR_LOAD_CHANGES_RV",
+ "type": {
+ "tag": "TD_UINT32"
+ },
+ "value": 524288
+ },
+ {
+ "name": "LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP",
+ "type": {
+ "tag": "TD_UINT32"
+ },
+ "value": 1048576
+ },
+ {
+ "name": "LOAD_FLAGS_FIXUP_SCHEME_TYPOS",
+ "type": {
+ "tag": "TD_UINT32"
+ },
+ "value": 2097152
+ },
+ {
+ "name": "LOAD_FLAGS_FORCE_ALLOW_DATA_URI",
+ "type": {
+ "tag": "TD_UINT32"
+ },
+ "value": 4194304
+ },
+ {
+ "name": "LOAD_FLAGS_IS_REDIRECT",
+ "type": {
+ "tag": "TD_UINT32"
+ },
+ "value": 8388608
+ },
+ {
+ "name": "LOAD_FLAGS_DISABLE_TRR",
+ "type": {
+ "tag": "TD_UINT32"
+ },
+ "value": 16777216
+ },
+ {
+ "name": "LOAD_FLAGS_FORCE_TRR",
+ "type": {
+ "tag": "TD_UINT32"
+ },
+ "value": 33554432
+ },
+ {
+ "name": "LOAD_FLAGS_BYPASS_LOAD_URI_DELEGATE",
+ "type": {
+ "tag": "TD_UINT32"
+ },
+ "value": 67108864
+ },
+ {
+ "name": "LOAD_FLAGS_USER_ACTIVATION",
+ "type": {
+ "tag": "TD_UINT32"
+ },
+ "value": 134217728
+ },
+ {
+ "name": "STOP_NETWORK",
+ "type": {
+ "tag": "TD_UINT32"
+ },
+ "value": 1
+ },
+ {
+ "name": "STOP_CONTENT",
+ "type": {
+ "tag": "TD_UINT32"
+ },
+ "value": 2
+ },
+ {
+ "name": "STOP_ALL",
+ "type": {
+ "tag": "TD_UINT32"
+ },
+ "value": 3
+ }
+ ],
+ "flags": [
+ "builtinclass"
+ ],
+ "methods": [
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "canGoBack",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "canGoForward",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [],
+ "name": "goBack",
+ "params": [
+ {
+ "flags": [
+ "in",
+ "optional"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ },
+ {
+ "flags": [
+ "in",
+ "optional"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [],
+ "name": "goForward",
+ "params": [
+ {
+ "flags": [
+ "in",
+ "optional"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ },
+ {
+ "flags": [
+ "in",
+ "optional"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [],
+ "name": "gotoIndex",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_INT32"
+ }
+ },
+ {
+ "flags": [
+ "in",
+ "optional"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "jscontext"
+ ],
+ "name": "loadURI",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_ASTRING"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_JSVAL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [],
+ "name": "binaryLoadURI",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_ASTRING"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_VOID"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [],
+ "name": "reload",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_UINT32"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [],
+ "name": "stop",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_UINT32"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "document",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "headerFile": "mozilla/dom/Document.h",
+ "name": "Document",
+ "native": "mozilla::dom::Document",
+ "tag": "TD_DOMOBJECT"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "currentURI",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "name": "nsIURI",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "sessionHistory",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "name": "nsISupports",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [],
+ "name": "resumeRedirectedLoad",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_UINT64"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_INT32"
+ }
+ }
+ ]
+ }
+ ],
+ "name": "nsIWebNavigation",
+ "parent": "nsISupports",
+ "uuid": "3ade79d4-8cb9-4952-b18d-4f9b63ca0d31"
+ },
+ {
+ "consts": [
+ {
+ "name": "UNSUPPORTED",
+ "type": {
+ "tag": "TD_UINT32"
+ },
+ "value": 0
+ },
+ {
+ "name": "IMAGE",
+ "type": {
+ "tag": "TD_UINT32"
+ },
+ "value": 1
+ },
+ {
+ "name": "FALLBACK",
+ "type": {
+ "tag": "TD_UINT32"
+ },
+ "value": 2
+ },
+ {
+ "name": "OTHER",
+ "type": {
+ "tag": "TD_UINT32"
+ },
+ "value": 32768
+ }
+ ],
+ "flags": [],
+ "methods": [
+ {
+ "flags": [
+ "hasretval"
+ ],
+ "name": "isTypeSupported",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_CSTRING"
+ }
+ },
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_UINT32"
+ }
+ }
+ ]
+ }
+ ],
+ "name": "nsIWebNavigationInfo",
+ "parent": "nsISupports",
+ "uuid": "62a93afb-93a1-465c-84c8-0432264229de"
+ },
+ {
+ "consts": [],
+ "flags": [],
+ "methods": [
+ {
+ "flags": [],
+ "name": "loadPageAsViewSource",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsIDocShell",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_ASTRING"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "currentDescriptor",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "name": "nsISupports",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ }
+ ]
+ }
+ ],
+ "name": "nsIWebPageDescriptor",
+ "parent": "nsISupports",
+ "uuid": "6f30b676-3710-4c2c-80b1-0395fb26516e"
+ }
+] \ No newline at end of file
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/tests/xpidl/xpcom_base.xpt b/tools/lint/eslint/eslint-plugin-mozilla/tests/xpidl/xpcom_base.xpt
new file mode 100644
index 0000000000..8b3db4bdeb
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/tests/xpidl/xpcom_base.xpt
@@ -0,0 +1,3165 @@
+[
+ {
+ "consts": [],
+ "flags": [],
+ "methods": [
+ {
+ "flags": [],
+ "name": "unloadTabAsync",
+ "params": []
+ }
+ ],
+ "name": "nsITabUnloader",
+ "parent": "nsISupports",
+ "uuid": "2e530956-6054-464f-9f4c-0ae6f8de5523"
+ },
+ {
+ "consts": [],
+ "flags": [],
+ "methods": [
+ {
+ "flags": [],
+ "name": "registerTabUnloader",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsITabUnloader",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [],
+ "name": "onUnloadAttemptCompleted",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_UINT32"
+ }
+ }
+ ]
+ }
+ ],
+ "name": "nsIAvailableMemoryWatcherBase",
+ "parent": "nsISupports",
+ "uuid": "b0b5701e-239d-49db-9009-37e89f86441c"
+ },
+ {
+ "consts": [],
+ "flags": [
+ "function"
+ ],
+ "methods": [
+ {
+ "flags": [],
+ "name": "observe",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsIConsoleMessage",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ }
+ ]
+ }
+ ],
+ "name": "nsIConsoleListener",
+ "parent": "nsISupports",
+ "uuid": "35c400a4-5792-438c-b915-65e30d58d557"
+ },
+ {
+ "consts": [
+ {
+ "name": "debug",
+ "type": {
+ "tag": "TD_UINT32"
+ },
+ "value": 0
+ },
+ {
+ "name": "info",
+ "type": {
+ "tag": "TD_UINT32"
+ },
+ "value": 1
+ },
+ {
+ "name": "warn",
+ "type": {
+ "tag": "TD_UINT32"
+ },
+ "value": 2
+ },
+ {
+ "name": "error",
+ "type": {
+ "tag": "TD_UINT32"
+ },
+ "value": 3
+ }
+ ],
+ "flags": [],
+ "methods": [
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "logLevel",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_UINT32"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "timeStamp",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_INT64"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "microSecondTimeStamp",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_INT64"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "message",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_ASTRING"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "isForwardedFromContentProcess",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "setter"
+ ],
+ "name": "isForwardedFromContentProcess",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "hasretval"
+ ],
+ "name": "toString",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_UTF8STRING"
+ }
+ }
+ ]
+ }
+ ],
+ "name": "nsIConsoleMessage",
+ "parent": "nsISupports",
+ "uuid": "3aba9617-10e2-4839-83ae-2e6fc4df428b"
+ },
+ {
+ "consts": [
+ {
+ "name": "SuppressLog",
+ "type": {
+ "tag": "TD_UINT8"
+ },
+ "value": 0
+ },
+ {
+ "name": "OutputToLog",
+ "type": {
+ "tag": "TD_UINT8"
+ },
+ "value": 1
+ }
+ ],
+ "flags": [
+ "builtinclass"
+ ],
+ "methods": [
+ {
+ "flags": [],
+ "name": "logMessage",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsIConsoleMessage",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [],
+ "name": "logMessageWithMode",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsIConsoleMessage",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_UINT8"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [],
+ "name": "logStringMessage",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_PWSTRING"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "hasretval"
+ ],
+ "name": "getMessageArray",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "element": {
+ "name": "nsIConsoleMessage",
+ "tag": "TD_INTERFACE_TYPE"
+ },
+ "tag": "TD_ARRAY"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [],
+ "name": "registerListener",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsIConsoleListener",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [],
+ "name": "unregisterListener",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsIConsoleListener",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [],
+ "name": "reset",
+ "params": []
+ },
+ {
+ "flags": [],
+ "name": "resetWindow",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_UINT64"
+ }
+ }
+ ]
+ }
+ ],
+ "name": "nsIConsoleService",
+ "parent": "nsISupports",
+ "uuid": "0eb81d20-c37e-42d4-82a8-ca9ae96bdf52"
+ },
+ {
+ "consts": [],
+ "flags": [],
+ "methods": [
+ {
+ "flags": [],
+ "name": "noteRefCountedObject",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_CSTRING"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_UINT32"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_CSTRING"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [],
+ "name": "noteGCedObject",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_CSTRING"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_CSTRING"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_CSTRING"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [],
+ "name": "noteEdge",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_CSTRING"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_CSTRING"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_CSTRING"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [],
+ "name": "describeRoot",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_CSTRING"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_UINT32"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [],
+ "name": "describeGarbage",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_CSTRING"
+ }
+ }
+ ]
+ }
+ ],
+ "name": "nsICycleCollectorHandler",
+ "parent": "nsISupports",
+ "uuid": "7f093367-1492-4b89-87af-c01dbc831246"
+ },
+ {
+ "consts": [],
+ "flags": [
+ "builtinclass"
+ ],
+ "methods": [
+ {
+ "flags": [
+ "hidden"
+ ],
+ "name": "open",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_VOID"
+ }
+ },
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_VOID"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [],
+ "name": "closeGCLog",
+ "params": []
+ },
+ {
+ "flags": [],
+ "name": "closeCCLog",
+ "params": []
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "filenameIdentifier",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_ASTRING"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "setter"
+ ],
+ "name": "filenameIdentifier",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_ASTRING"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "processIdentifier",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_INT32"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "setter"
+ ],
+ "name": "processIdentifier",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_INT32"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "gcLog",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "name": "nsIFile",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "ccLog",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "name": "nsIFile",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ }
+ ]
+ }
+ ],
+ "name": "nsICycleCollectorLogSink",
+ "parent": "nsISupports",
+ "uuid": "3ad9875f-d0e4-4ac2-87e3-f127f6c02ce1"
+ },
+ {
+ "consts": [],
+ "flags": [
+ "builtinclass"
+ ],
+ "methods": [
+ {
+ "flags": [
+ "hasretval"
+ ],
+ "name": "allTraces",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "name": "nsICycleCollectorListener",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "wantAllTraces",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "disableLog",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "setter"
+ ],
+ "name": "disableLog",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "logSink",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "name": "nsICycleCollectorLogSink",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "setter"
+ ],
+ "name": "logSink",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsICycleCollectorLogSink",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "wantAfterProcessing",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "setter"
+ ],
+ "name": "wantAfterProcessing",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "hasretval"
+ ],
+ "name": "processNext",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsICycleCollectorHandler",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ },
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "hidden",
+ "hasretval"
+ ],
+ "name": "asLogger",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_VOID"
+ }
+ }
+ ]
+ }
+ ],
+ "name": "nsICycleCollectorListener",
+ "parent": "nsISupports",
+ "uuid": "703b53b6-24f6-40c6-9ea9-aeb2dc53d170"
+ },
+ {
+ "consts": [],
+ "flags": [],
+ "methods": [
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "isDebugBuild",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "assertionCount",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_INT32"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "isDebuggerAttached",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [],
+ "name": "assertion",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_PSTRING"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_PSTRING"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_PSTRING"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_INT32"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [],
+ "name": "warning",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_PSTRING"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_PSTRING"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_INT32"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [],
+ "name": "break",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_PSTRING"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_INT32"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [],
+ "name": "abort",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_PSTRING"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_INT32"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [],
+ "name": "rustPanic",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_PSTRING"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [],
+ "name": "rustLog",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_PSTRING"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_PSTRING"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [],
+ "name": "crashWithOOM",
+ "params": []
+ }
+ ],
+ "name": "nsIDebug2",
+ "parent": "nsISupports",
+ "uuid": "9641dc15-10fb-42e3-a285-18be90a5c10b"
+ },
+ {
+ "consts": [],
+ "flags": [
+ "builtinclass"
+ ],
+ "methods": [
+ {
+ "flags": [
+ "getter",
+ "jscontext",
+ "hasretval"
+ ],
+ "name": "filename",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_ASTRING"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "jscontext",
+ "hasretval"
+ ],
+ "name": "name",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_ASTRING"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "jscontext",
+ "hasretval"
+ ],
+ "name": "sourceId",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_INT32"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "jscontext",
+ "hasretval"
+ ],
+ "name": "lineNumber",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_INT32"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "jscontext",
+ "hasretval"
+ ],
+ "name": "columnNumber",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_INT32"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "sourceLine",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_UTF8STRING"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "jscontext",
+ "hasretval"
+ ],
+ "name": "asyncCause",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_ASTRING"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "jscontext",
+ "hasretval"
+ ],
+ "name": "asyncCaller",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "name": "nsIStackFrame",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "jscontext",
+ "hasretval"
+ ],
+ "name": "caller",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "name": "nsIStackFrame",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "jscontext",
+ "hasretval"
+ ],
+ "name": "formattedStack",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_ASTRING"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "nativeSavedFrame",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_JSVAL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "jscontext",
+ "hasretval"
+ ],
+ "name": "toString",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_UTF8STRING"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "hidden"
+ ],
+ "name": "getFilename",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_VOID"
+ }
+ },
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_ASTRING"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "hidden"
+ ],
+ "name": "getName",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_VOID"
+ }
+ },
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_ASTRING"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "hidden"
+ ],
+ "name": "getSourceId",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_VOID"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "hidden"
+ ],
+ "name": "getLineNumber",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_VOID"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "hidden"
+ ],
+ "name": "getColumnNumber",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_VOID"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "hidden"
+ ],
+ "name": "getAsyncCause",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_VOID"
+ }
+ },
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_ASTRING"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "hidden"
+ ],
+ "name": "getAsyncCaller",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_VOID"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "hidden"
+ ],
+ "name": "getCaller",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_VOID"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "hidden"
+ ],
+ "name": "getFormattedStack",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_VOID"
+ }
+ },
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_ASTRING"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "hidden"
+ ],
+ "name": "toStringInfallible",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_VOID"
+ }
+ },
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_UTF8STRING"
+ }
+ }
+ ]
+ }
+ ],
+ "name": "nsIStackFrame",
+ "parent": "nsISupports",
+ "uuid": "28bfb2a2-5ea6-4738-918b-049dc4d51f0b"
+ },
+ {
+ "consts": [],
+ "flags": [
+ "builtinclass"
+ ],
+ "methods": [],
+ "name": "nsIException",
+ "parent": "nsISupports",
+ "uuid": "4371b5bf-6845-487f-8d9d-3f1e4a9badd2"
+ },
+ {
+ "consts": [],
+ "flags": [],
+ "methods": [
+ {
+ "flags": [],
+ "name": "init",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsIFile",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "hidden"
+ ],
+ "name": "initANSIFileDesc",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_VOID"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [],
+ "name": "write",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_UTF8STRING"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [],
+ "name": "finish",
+ "params": []
+ }
+ ],
+ "name": "nsIGZFileWriter",
+ "parent": "nsISupports",
+ "uuid": "6bd5642c-1b90-4499-ba4b-199f27efaba5"
+ },
+ {
+ "consts": [],
+ "flags": [],
+ "methods": [
+ {
+ "flags": [
+ "hasretval"
+ ],
+ "name": "getInterface",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_NSID"
+ }
+ },
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "iid_is": 0,
+ "tag": "TD_INTERFACE_IS_TYPE"
+ }
+ }
+ ]
+ }
+ ],
+ "name": "nsIInterfaceRequestor",
+ "parent": "nsISupports",
+ "uuid": "033a1470-8b2a-11d3-af88-00a024ffc08c"
+ },
+ {
+ "consts": [],
+ "flags": [],
+ "methods": [
+ {
+ "flags": [
+ "hasretval"
+ ],
+ "name": "policiesEnabled",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "jscontext",
+ "hasretval"
+ ],
+ "name": "readPreferences",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_JSVAL"
+ }
+ }
+ ]
+ }
+ ],
+ "name": "nsIMacPreferencesReader",
+ "parent": "nsISupports",
+ "uuid": "b0f20595-88ce-4738-a1a4-24de78eb8051"
+ },
+ {
+ "consts": [],
+ "flags": [],
+ "methods": [
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "architecturesInBinary",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_ASTRING"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "isTranslated",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ }
+ ],
+ "name": "nsIMacUtils",
+ "parent": "nsISupports",
+ "uuid": "5e9072d7-ff95-455e-9466-8af9841a72ec"
+ },
+ {
+ "consts": [],
+ "flags": [],
+ "methods": [
+ {
+ "flags": [],
+ "name": "heapMinimize",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "hasretval"
+ ],
+ "name": "isLowMemoryPlatform",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ }
+ ],
+ "name": "nsIMemory",
+ "parent": "nsISupports",
+ "uuid": "1e004834-6d8f-425a-bc9c-a2812ed43bb7"
+ },
+ {
+ "consts": [],
+ "flags": [
+ "function"
+ ],
+ "methods": [
+ {
+ "flags": [],
+ "name": "callback",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsISupports",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ }
+ ]
+ }
+ ],
+ "name": "nsIFinishDumpingCallback",
+ "parent": "nsISupports",
+ "uuid": "2dea18fc-fbfa-4bf7-ad45-0efaf5495f5e"
+ },
+ {
+ "consts": [],
+ "flags": [],
+ "methods": [
+ {
+ "flags": [],
+ "name": "onDump",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsIFile",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsIFile",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [],
+ "name": "onFinish",
+ "params": []
+ }
+ ],
+ "name": "nsIDumpGCAndCCLogsCallback",
+ "parent": "nsISupports",
+ "uuid": "dc1b2b24-65bd-441b-b6bd-cb5825a7ed14"
+ },
+ {
+ "consts": [],
+ "flags": [
+ "builtinclass"
+ ],
+ "methods": [
+ {
+ "flags": [],
+ "name": "dumpMemoryReportsToNamedFile",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_ASTRING"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsIFinishDumpingCallback",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsISupports",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [],
+ "name": "dumpMemoryInfoToTempDir",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_ASTRING"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [],
+ "name": "dumpGCAndCCLogsToFile",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_ASTRING"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsIDumpGCAndCCLogsCallback",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [],
+ "name": "dumpGCAndCCLogsToSink",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsICycleCollectorLogSink",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ }
+ ]
+ }
+ ],
+ "name": "nsIMemoryInfoDumper",
+ "parent": "nsISupports",
+ "uuid": "48541b74-47ee-4a62-9557-7f4b809bda5c"
+ },
+ {
+ "consts": [],
+ "flags": [
+ "function"
+ ],
+ "methods": [
+ {
+ "flags": [],
+ "name": "callback",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_CSTRING"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_UTF8STRING"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_INT32"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_INT32"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_INT64"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_UTF8STRING"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsISupports",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ }
+ ]
+ }
+ ],
+ "name": "nsIHandleReportCallback",
+ "parent": "nsISupports",
+ "uuid": "62ef0e1c-dbd6-11e3-aa75-3c970e9f4238"
+ },
+ {
+ "consts": [
+ {
+ "name": "KIND_NONHEAP",
+ "type": {
+ "tag": "TD_INT32"
+ },
+ "value": 0
+ },
+ {
+ "name": "KIND_HEAP",
+ "type": {
+ "tag": "TD_INT32"
+ },
+ "value": 1
+ },
+ {
+ "name": "KIND_OTHER",
+ "type": {
+ "tag": "TD_INT32"
+ },
+ "value": 2
+ },
+ {
+ "name": "UNITS_BYTES",
+ "type": {
+ "tag": "TD_INT32"
+ },
+ "value": 0
+ },
+ {
+ "name": "UNITS_COUNT",
+ "type": {
+ "tag": "TD_INT32"
+ },
+ "value": 1
+ },
+ {
+ "name": "UNITS_COUNT_CUMULATIVE",
+ "type": {
+ "tag": "TD_INT32"
+ },
+ "value": 2
+ },
+ {
+ "name": "UNITS_PERCENTAGE",
+ "type": {
+ "tag": "TD_INT32"
+ },
+ "value": 3
+ }
+ ],
+ "flags": [],
+ "methods": [
+ {
+ "flags": [],
+ "name": "collectReports",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsIHandleReportCallback",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsISupports",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ }
+ ],
+ "name": "nsIMemoryReporter",
+ "parent": "nsISupports",
+ "uuid": "92a36db1-46bd-4fe6-988e-47db47236d8b"
+ },
+ {
+ "consts": [],
+ "flags": [
+ "function"
+ ],
+ "methods": [
+ {
+ "flags": [],
+ "name": "callback",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsISupports",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ }
+ ]
+ }
+ ],
+ "name": "nsIFinishReportingCallback",
+ "parent": "nsISupports",
+ "uuid": "548b3909-c04d-4ca6-8466-b8bee3837457"
+ },
+ {
+ "consts": [],
+ "flags": [
+ "function"
+ ],
+ "methods": [
+ {
+ "flags": [],
+ "name": "callback",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_INT64"
+ }
+ }
+ ]
+ }
+ ],
+ "name": "nsIHeapAllocatedCallback",
+ "parent": "nsISupports",
+ "uuid": "1a80cd0f-0d9e-4397-be69-68ad28fe5175"
+ },
+ {
+ "consts": [],
+ "flags": [
+ "builtinclass"
+ ],
+ "methods": [
+ {
+ "flags": [],
+ "name": "init",
+ "params": []
+ },
+ {
+ "flags": [],
+ "name": "registerStrongReporter",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsIMemoryReporter",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [],
+ "name": "registerStrongAsyncReporter",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsIMemoryReporter",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [],
+ "name": "registerWeakReporter",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsIMemoryReporter",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [],
+ "name": "registerWeakAsyncReporter",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsIMemoryReporter",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [],
+ "name": "unregisterStrongReporter",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsIMemoryReporter",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [],
+ "name": "unregisterWeakReporter",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsIMemoryReporter",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [],
+ "name": "blockRegistrationAndHideExistingReporters",
+ "params": []
+ },
+ {
+ "flags": [],
+ "name": "unblockRegistrationAndRestoreOriginalReporters",
+ "params": []
+ },
+ {
+ "flags": [],
+ "name": "registerStrongReporterEvenIfBlocked",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsIMemoryReporter",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [],
+ "name": "getReports",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsIHandleReportCallback",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsISupports",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsIFinishReportingCallback",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsISupports",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "hidden"
+ ],
+ "name": "getReportsExtended",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsIHandleReportCallback",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsISupports",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsIFinishReportingCallback",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsISupports",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_ASTRING"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "hidden"
+ ],
+ "name": "getReportsForThisProcessExtended",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsIHandleReportCallback",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsISupports",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_VOID"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsIFinishReportingCallback",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsISupports",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "hidden"
+ ],
+ "name": "endReport",
+ "params": []
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "vsize",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_INT64"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "vsizeMaxContiguous",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_INT64"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "resident",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_INT64"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "residentFast",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_INT64"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "residentPeak",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_INT64"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "residentUnique",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_INT64"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "heapAllocated",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_INT64"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "heapOverheadFraction",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_INT64"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "JSMainRuntimeGCHeap",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_INT64"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "JSMainRuntimeTemporaryPeak",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_INT64"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "JSMainRuntimeCompartmentsSystem",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_INT64"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "JSMainRuntimeCompartmentsUser",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_INT64"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "JSMainRuntimeRealmsSystem",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_INT64"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "JSMainRuntimeRealmsUser",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_INT64"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "imagesContentUsedUncompressed",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_INT64"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "storageSQLite",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_INT64"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "lowMemoryEventsPhysical",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_INT64"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "ghostWindows",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_INT64"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "pageFaultsHard",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_INT64"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "hasMozMallocUsableSize",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "isDMDEnabled",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "getter",
+ "hasretval"
+ ],
+ "name": "isDMDRunning",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_BOOL"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [],
+ "name": "minimizeMemoryUsage",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "nsIRunnable",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [],
+ "name": "sizeOfTab",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "name": "mozIDOMWindowProxy",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ },
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_INT64"
+ }
+ },
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_INT64"
+ }
+ },
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_INT64"
+ }
+ },
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_INT64"
+ }
+ },
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_INT64"
+ }
+ },
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_INT64"
+ }
+ },
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_INT64"
+ }
+ },
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_DOUBLE"
+ }
+ },
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_DOUBLE"
+ }
+ }
+ ]
+ }
+ ],
+ "name": "nsIMemoryReporterManager",
+ "parent": "nsISupports",
+ "uuid": "2998574d-8993-407a-b1a5-8ad7417653e1"
+ },
+ {
+ "consts": [],
+ "flags": [],
+ "methods": [
+ {
+ "flags": [
+ "hasretval"
+ ],
+ "name": "QueryInterface",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_NSID"
+ }
+ },
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "iid_is": 0,
+ "tag": "TD_INTERFACE_IS_TYPE"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "hidden"
+ ],
+ "name": "AddRef",
+ "params": []
+ },
+ {
+ "flags": [
+ "hidden"
+ ],
+ "name": "Release",
+ "params": []
+ }
+ ],
+ "name": "nsISupports",
+ "parent": null,
+ "uuid": "00000000-0000-0000-c000-000000000046"
+ },
+ {
+ "consts": [],
+ "flags": [],
+ "methods": [
+ {
+ "flags": [
+ "hasretval"
+ ],
+ "name": "generateUUID",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_NSIDPTR"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "hidden"
+ ],
+ "name": "generateUUIDInPlace",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_VOID"
+ }
+ }
+ ]
+ }
+ ],
+ "name": "nsIUUIDGenerator",
+ "parent": "nsISupports",
+ "uuid": "138ad1b2-c694-41cc-b201-333ce936d8b8"
+ },
+ {
+ "consts": [],
+ "flags": [],
+ "methods": [
+ {
+ "flags": [
+ "hasretval"
+ ],
+ "name": "compare",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_CSTRING"
+ }
+ },
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_CSTRING"
+ }
+ },
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "tag": "TD_INT32"
+ }
+ }
+ ]
+ }
+ ],
+ "name": "nsIVersionComparator",
+ "parent": "nsISupports",
+ "uuid": "e6cd620a-edbb-41d2-9e42-9a2ffc8107f3"
+ },
+ {
+ "consts": [],
+ "flags": [
+ "builtinclass"
+ ],
+ "methods": [
+ {
+ "flags": [
+ "hasretval"
+ ],
+ "name": "QueryReferent",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_NSID"
+ }
+ },
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "iid_is": 0,
+ "tag": "TD_INTERFACE_IS_TYPE"
+ }
+ }
+ ]
+ },
+ {
+ "flags": [
+ "hidden"
+ ],
+ "name": "sizeOfOnlyThis",
+ "params": [
+ {
+ "flags": [
+ "in"
+ ],
+ "type": {
+ "tag": "TD_VOID"
+ }
+ }
+ ]
+ }
+ ],
+ "name": "nsIWeakReference",
+ "parent": "nsISupports",
+ "uuid": "9188bc85-f92e-11d2-81ef-0060083a0bcf"
+ },
+ {
+ "consts": [],
+ "flags": [],
+ "methods": [
+ {
+ "flags": [
+ "hasretval"
+ ],
+ "name": "GetWeakReference",
+ "params": [
+ {
+ "flags": [
+ "out"
+ ],
+ "type": {
+ "name": "nsIWeakReference",
+ "tag": "TD_INTERFACE_TYPE"
+ }
+ }
+ ]
+ }
+ ],
+ "name": "nsISupportsWeakReference",
+ "parent": "nsISupports",
+ "uuid": "9188bc86-f92e-11d2-81ef-0060083a0bcf"
+ }
+]
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/update.sh b/tools/lint/eslint/eslint-plugin-mozilla/update.sh
new file mode 100755
index 0000000000..240cfdb9c2
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/update.sh
@@ -0,0 +1,40 @@
+#!/bin/sh
+# Script to regenerate the npm packages used for eslint-plugin-mozilla by the builders.
+# Requires
+
+# Force the scripts working directory to be projdir/tools/lint/eslint/eslint-plugin-mozilla.
+DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+cd $DIR
+
+if [ -z "$TASKCLUSTER_ACCESS_TOKEN" -o -z "$TASKCLUSTER_CLIENT_ID" -o -z "$TASKCLUSTER_ROOT_URL" ]; then
+ echo "Please ensure you have run the taskcluster shell correctly to set"
+ echo "the TASKCLUSTER_ACCESS_TOKEN, TASKCLUSTER_CLIENT_ID and"
+ echo "TASKCLUSTER_ROOT_URL environment variables."
+ echo "See https://firefox-source-docs.mozilla.org/code-quality/lint/linters/eslint/enabling-rules.html"
+ exit 1;
+fi
+
+echo ""
+echo "Removing node_modules and package-lock.json..."
+# Move to the top-level directory.
+rm -rf node_modules
+rm package-lock.json
+
+echo "Installing modules for eslint-plugin-mozilla..."
+../../../../mach npm install
+
+echo "Creating eslint-plugin-mozilla.tar.gz..."
+tar cvz -f eslint-plugin-mozilla.tar.gz node_modules
+
+echo "Adding eslint-plugin-mozilla.tar.gz to tooltool..."
+rm -f manifest.tt
+../../../../python/mozbuild/mozbuild/action/tooltool.py add --visibility public --unpack eslint-plugin-mozilla.tar.gz --url="https://tooltool.mozilla-releng.net/"
+
+echo "Uploading eslint-plugin-mozilla.tar.gz to tooltool..."
+../../../../python/mozbuild/mozbuild/action/tooltool.py upload --message "node_modules folder update for tools/lint/eslint/eslint-plugin-mozilla" --url="https://tooltool.mozilla-releng.net/"
+
+echo "Cleaning up..."
+rm eslint-plugin-mozilla.tar.gz
+
+echo ""
+echo "Update complete, please commit and check in your changes."
diff --git a/tools/lint/eslint/eslint-plugin-spidermonkey-js/LICENSE b/tools/lint/eslint/eslint-plugin-spidermonkey-js/LICENSE
new file mode 100644
index 0000000000..e87a115e46
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-spidermonkey-js/LICENSE
@@ -0,0 +1,363 @@
+Mozilla Public License, version 2.0
+
+1. Definitions
+
+1.1. "Contributor"
+
+ means each individual or legal entity that creates, contributes to the
+ creation of, or owns Covered Software.
+
+1.2. "Contributor Version"
+
+ means the combination of the Contributions of others (if any) used by a
+ Contributor and that particular Contributor's Contribution.
+
+1.3. "Contribution"
+
+ means Covered Software of a particular Contributor.
+
+1.4. "Covered Software"
+
+ means Source Code Form to which the initial Contributor has attached the
+ notice in Exhibit A, the Executable Form of such Source Code Form, and
+ Modifications of such Source Code Form, in each case including portions
+ thereof.
+
+1.5. "Incompatible With Secondary Licenses"
+ means
+
+ a. that the initial Contributor has attached the notice described in
+ Exhibit B to the Covered Software; or
+
+ b. that the Covered Software was made available under the terms of
+ version 1.1 or earlier of the License, but not also under the terms of
+ a Secondary License.
+
+1.6. "Executable Form"
+
+ means any form of the work other than Source Code Form.
+
+1.7. "Larger Work"
+
+ means a work that combines Covered Software with other material, in a
+ separate file or files, that is not Covered Software.
+
+1.8. "License"
+
+ means this document.
+
+1.9. "Licensable"
+
+ means having the right to grant, to the maximum extent possible, whether
+ at the time of the initial grant or subsequently, any and all of the
+ rights conveyed by this License.
+
+1.10. "Modifications"
+
+ means any of the following:
+
+ a. any file in Source Code Form that results from an addition to,
+ deletion from, or modification of the contents of Covered Software; or
+
+ b. any new file in Source Code Form that contains any Covered Software.
+
+1.11. "Patent Claims" of a Contributor
+
+ means any patent claim(s), including without limitation, method,
+ process, and apparatus claims, in any patent Licensable by such
+ Contributor that would be infringed, but for the grant of the License,
+ by the making, using, selling, offering for sale, having made, import,
+ or transfer of either its Contributions or its Contributor Version.
+
+1.12. "Secondary License"
+
+ means either the GNU General Public License, Version 2.0, the GNU Lesser
+ General Public License, Version 2.1, the GNU Affero General Public
+ License, Version 3.0, or any later versions of those licenses.
+
+1.13. "Source Code Form"
+
+ means the form of the work preferred for making modifications.
+
+1.14. "You" (or "Your")
+
+ means an individual or a legal entity exercising rights under this
+ License. For legal entities, "You" includes any entity that controls, is
+ controlled by, or is under common control with You. For purposes of this
+ definition, "control" means (a) the power, direct or indirect, to cause
+ the direction or management of such entity, whether by contract or
+ otherwise, or (b) ownership of more than fifty percent (50%) of the
+ outstanding shares or beneficial ownership of such entity.
+
+
+2. License Grants and Conditions
+
+2.1. Grants
+
+ Each Contributor hereby grants You a world-wide, royalty-free,
+ non-exclusive license:
+
+ a. under intellectual property rights (other than patent or trademark)
+ Licensable by such Contributor to use, reproduce, make available,
+ modify, display, perform, distribute, and otherwise exploit its
+ Contributions, either on an unmodified basis, with Modifications, or
+ as part of a Larger Work; and
+
+ b. under Patent Claims of such Contributor to make, use, sell, offer for
+ sale, have made, import, and otherwise transfer either its
+ Contributions or its Contributor Version.
+
+2.2. Effective Date
+
+ The licenses granted in Section 2.1 with respect to any Contribution
+ become effective for each Contribution on the date the Contributor first
+ distributes such Contribution.
+
+2.3. Limitations on Grant Scope
+
+ The licenses granted in this Section 2 are the only rights granted under
+ this License. No additional rights or licenses will be implied from the
+ distribution or licensing of Covered Software under this License.
+ Notwithstanding Section 2.1(b) above, no patent license is granted by a
+ Contributor:
+
+ a. for any code that a Contributor has removed from Covered Software; or
+
+ b. for infringements caused by: (i) Your and any other third party's
+ modifications of Covered Software, or (ii) the combination of its
+ Contributions with other software (except as part of its Contributor
+ Version); or
+
+ c. under Patent Claims infringed by Covered Software in the absence of
+ its Contributions.
+
+ This License does not grant any rights in the trademarks, service marks,
+ or logos of any Contributor (except as may be necessary to comply with
+ the notice requirements in Section 3.4).
+
+2.4. Subsequent Licenses
+
+ No Contributor makes additional grants as a result of Your choice to
+ distribute the Covered Software under a subsequent version of this
+ License (see Section 10.2) or under the terms of a Secondary License (if
+ permitted under the terms of Section 3.3).
+
+2.5. Representation
+
+ Each Contributor represents that the Contributor believes its
+ Contributions are its original creation(s) or it has sufficient rights to
+ grant the rights to its Contributions conveyed by this License.
+
+2.6. Fair Use
+
+ This License is not intended to limit any rights You have under
+ applicable copyright doctrines of fair use, fair dealing, or other
+ equivalents.
+
+2.7. Conditions
+
+ Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in
+ Section 2.1.
+
+
+3. Responsibilities
+
+3.1. Distribution of Source Form
+
+ All distribution of Covered Software in Source Code Form, including any
+ Modifications that You create or to which You contribute, must be under
+ the terms of this License. You must inform recipients that the Source
+ Code Form of the Covered Software is governed by the terms of this
+ License, and how they can obtain a copy of this License. You may not
+ attempt to alter or restrict the recipients' rights in the Source Code
+ Form.
+
+3.2. Distribution of Executable Form
+
+ If You distribute Covered Software in Executable Form then:
+
+ a. such Covered Software must also be made available in Source Code Form,
+ as described in Section 3.1, and You must inform recipients of the
+ Executable Form how they can obtain a copy of such Source Code Form by
+ reasonable means in a timely manner, at a charge no more than the cost
+ of distribution to the recipient; and
+
+ b. You may distribute such Executable Form under the terms of this
+ License, or sublicense it under different terms, provided that the
+ license for the Executable Form does not attempt to limit or alter the
+ recipients' rights in the Source Code Form under this License.
+
+3.3. Distribution of a Larger Work
+
+ You may create and distribute a Larger Work under terms of Your choice,
+ provided that You also comply with the requirements of this License for
+ the Covered Software. If the Larger Work is a combination of Covered
+ Software with a work governed by one or more Secondary Licenses, and the
+ Covered Software is not Incompatible With Secondary Licenses, this
+ License permits You to additionally distribute such Covered Software
+ under the terms of such Secondary License(s), so that the recipient of
+ the Larger Work may, at their option, further distribute the Covered
+ Software under the terms of either this License or such Secondary
+ License(s).
+
+3.4. Notices
+
+ You may not remove or alter the substance of any license notices
+ (including copyright notices, patent notices, disclaimers of warranty, or
+ limitations of liability) contained within the Source Code Form of the
+ Covered Software, except that You may alter any license notices to the
+ extent required to remedy known factual inaccuracies.
+
+3.5. Application of Additional Terms
+
+ You may choose to offer, and to charge a fee for, warranty, support,
+ indemnity or liability obligations to one or more recipients of Covered
+ Software. However, You may do so only on Your own behalf, and not on
+ behalf of any Contributor. You must make it absolutely clear that any
+ such warranty, support, indemnity, or liability obligation is offered by
+ You alone, and You hereby agree to indemnify every Contributor for any
+ liability incurred by such Contributor as a result of warranty, support,
+ indemnity or liability terms You offer. You may include additional
+ disclaimers of warranty and limitations of liability specific to any
+ jurisdiction.
+
+4. Inability to Comply Due to Statute or Regulation
+
+ If it is impossible for You to comply with any of the terms of this License
+ with respect to some or all of the Covered Software due to statute,
+ judicial order, or regulation then You must: (a) comply with the terms of
+ this License to the maximum extent possible; and (b) describe the
+ limitations and the code they affect. Such description must be placed in a
+ text file included with all distributions of the Covered Software under
+ this License. Except to the extent prohibited by statute or regulation,
+ such description must be sufficiently detailed for a recipient of ordinary
+ skill to be able to understand it.
+
+5. Termination
+
+5.1. The rights granted under this License will terminate automatically if You
+ fail to comply with any of its terms. However, if You become compliant,
+ then the rights granted under this License from a particular Contributor
+ are reinstated (a) provisionally, unless and until such Contributor
+ explicitly and finally terminates Your grants, and (b) on an ongoing
+ basis, if such Contributor fails to notify You of the non-compliance by
+ some reasonable means prior to 60 days after You have come back into
+ compliance. Moreover, Your grants from a particular Contributor are
+ reinstated on an ongoing basis if such Contributor notifies You of the
+ non-compliance by some reasonable means, this is the first time You have
+ received notice of non-compliance with this License from such
+ Contributor, and You become compliant prior to 30 days after Your receipt
+ of the notice.
+
+5.2. If You initiate litigation against any entity by asserting a patent
+ infringement claim (excluding declaratory judgment actions,
+ counter-claims, and cross-claims) alleging that a Contributor Version
+ directly or indirectly infringes any patent, then the rights granted to
+ You by any and all Contributors for the Covered Software under Section
+ 2.1 of this License shall terminate.
+
+5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user
+ license agreements (excluding distributors and resellers) which have been
+ validly granted by You or Your distributors under this License prior to
+ termination shall survive termination.
+
+6. Disclaimer of Warranty
+
+ Covered Software is provided under this License on an "as is" basis,
+ without warranty of any kind, either expressed, implied, or statutory,
+ including, without limitation, warranties that the Covered Software is free
+ of defects, merchantable, fit for a particular purpose or non-infringing.
+ The entire risk as to the quality and performance of the Covered Software
+ is with You. Should any Covered Software prove defective in any respect,
+ You (not any Contributor) assume the cost of any necessary servicing,
+ repair, or correction. This disclaimer of warranty constitutes an essential
+ part of this License. No use of any Covered Software is authorized under
+ this License except under this disclaimer.
+
+7. Limitation of Liability
+
+ Under no circumstances and under no legal theory, whether tort (including
+ negligence), contract, or otherwise, shall any Contributor, or anyone who
+ distributes Covered Software as permitted above, be liable to You for any
+ direct, indirect, special, incidental, or consequential damages of any
+ character including, without limitation, damages for lost profits, loss of
+ goodwill, work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses, even if such party shall have been
+ informed of the possibility of such damages. This limitation of liability
+ shall not apply to liability for death or personal injury resulting from
+ such party's negligence to the extent applicable law prohibits such
+ limitation. Some jurisdictions do not allow the exclusion or limitation of
+ incidental or consequential damages, so this exclusion and limitation may
+ not apply to You.
+
+8. Litigation
+
+ Any litigation relating to this License may be brought only in the courts
+ of a jurisdiction where the defendant maintains its principal place of
+ business and such litigation shall be governed by laws of that
+ jurisdiction, without reference to its conflict-of-law provisions. Nothing
+ in this Section shall prevent a party's ability to bring cross-claims or
+ counter-claims.
+
+9. Miscellaneous
+
+ This License represents the complete agreement concerning the subject
+ matter hereof. If any provision of this License is held to be
+ unenforceable, such provision shall be reformed only to the extent
+ necessary to make it enforceable. Any law or regulation which provides that
+ the language of a contract shall be construed against the drafter shall not
+ be used to construe this License against a Contributor.
+
+
+10. Versions of the License
+
+10.1. New Versions
+
+ Mozilla Foundation is the license steward. Except as provided in Section
+ 10.3, no one other than the license steward has the right to modify or
+ publish new versions of this License. Each version will be given a
+ distinguishing version number.
+
+10.2. Effect of New Versions
+
+ You may distribute the Covered Software under the terms of the version
+ of the License under which You originally received the Covered Software,
+ or under the terms of any subsequent version published by the license
+ steward.
+
+10.3. Modified Versions
+
+ If you create software not governed by this License, and you want to
+ create a new license for such software, you may create and use a
+ modified version of this License if you rename the license and remove
+ any references to the name of the license steward (except to note that
+ such modified license differs from this License).
+
+10.4. Distributing Source Code Form that is Incompatible With Secondary
+ Licenses If You choose to distribute Source Code Form that is
+ Incompatible With Secondary Licenses under the terms of this version of
+ the License, the notice described in Exhibit B of this License must be
+ attached.
+
+Exhibit A - Source Code Form License Notice
+
+ 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/.
+
+If it is not possible or desirable to put the notice in a particular file,
+then You may include the notice in a location (such as a LICENSE file in a
+relevant directory) where a recipient would be likely to look for such a
+notice.
+
+You may add additional accurate notices of copyright ownership.
+
+Exhibit B - "Incompatible With Secondary Licenses" Notice
+
+ This Source Code Form is "Incompatible
+ With Secondary Licenses", as defined by
+ the Mozilla Public License, v. 2.0.
+
diff --git a/tools/lint/eslint/eslint-plugin-spidermonkey-js/lib/environments/self-hosted.js b/tools/lint/eslint/eslint-plugin-spidermonkey-js/lib/environments/self-hosted.js
new file mode 100644
index 0000000000..37ae42bfa3
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-spidermonkey-js/lib/environments/self-hosted.js
@@ -0,0 +1,180 @@
+/**
+ * @fileoverview Add environment defaults to SpiderMonkey's self-hosted JS.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+"use strict";
+
+const path = require("path");
+const fs = require("fs");
+
+let gRootDir = null;
+
+// Copied from `tools/lint/eslint/eslint-plugin-mozilla/lib/helpers.js`.
+function getRootDir() {
+ if (!gRootDir) {
+ function searchUpForIgnore(dirName, filename) {
+ let parsed = path.parse(dirName);
+ while (parsed.root !== dirName) {
+ if (fs.existsSync(path.join(dirName, filename))) {
+ return dirName;
+ }
+ // Move up a level
+ dirName = parsed.dir;
+ parsed = path.parse(dirName);
+ }
+ return null;
+ }
+
+ let possibleRoot = searchUpForIgnore(
+ path.dirname(module.filename),
+ ".eslintignore"
+ );
+ if (!possibleRoot) {
+ possibleRoot = searchUpForIgnore(path.resolve(), ".eslintignore");
+ }
+ if (!possibleRoot) {
+ possibleRoot = searchUpForIgnore(path.resolve(), "package.json");
+ }
+ if (!possibleRoot) {
+ // We've couldn't find a root from the module or CWD, so lets just go
+ // for the CWD. We really don't want to throw if possible, as that
+ // tends to give confusing results when used with ESLint.
+ possibleRoot = process.cwd();
+ }
+
+ gRootDir = possibleRoot;
+ }
+
+ return gRootDir;
+}
+
+function tryReadFile(filePath) {
+ let absPath = path.join(getRootDir(), filePath);
+ if (!fs.existsSync(absPath)) {
+ // Safely handle the case when the file wasn't found, because throwing
+ // errors can lead to confusing result when used with ESLint.
+ return "";
+ }
+ return fs.readFileSync(absPath, "utf-8");
+}
+
+// Search for top-level declarations, #defines, and #includes.
+function addGlobalsFrom(dirName, fileName, globals) {
+ let filePath = path.join(dirName, fileName);
+
+ // Definitions are separated by line.
+ let lines = tryReadFile(filePath).split("\n");
+
+ // We don't have to fully parse the source code, because it's formatted
+ // through "prettier", which means we know the exact code structure.
+ //
+ // |class| is disallowed in self-hosted code, so we don't have to handle it.
+ for (let line of lines) {
+ if (
+ line.startsWith("function") ||
+ line.startsWith("function*") ||
+ line.startsWith("async function") ||
+ line.startsWith("async function*")
+ ) {
+ let m = line.match(/^(?:async )?function(?:\*)?\s+([\w\$]+)\s*\(/);
+ if (m) {
+ globals[m[1]] = "readonly";
+ }
+ } else if (
+ line.startsWith("var") ||
+ line.startsWith("let") ||
+ line.startsWith("const")
+ ) {
+ let m = line.match(/^(?:var|let|const)\s+([\w\$]+)\s*[;=]/);
+ if (m) {
+ globals[m[1]] = "readonly";
+ }
+ } else if (line.startsWith("#define")) {
+ let m = line.match(/^#define (\w+)/);
+ if (m) {
+ globals[m[1]] = "readonly";
+ }
+ } else if (line.startsWith("#include")) {
+ let m = line.match(/^#include \"([\w\.]+)\"$/);
+ if (m) {
+ // Also process definitions from includes.
+ addGlobalsFrom(dirName, m[1], globals);
+ }
+ }
+ }
+}
+
+function selfHostingDefines(dirName = "js/src/builtin/") {
+ let absDir = path.join(getRootDir(), dirName);
+ if (!fs.existsSync(absDir)) {
+ // See |tryReadFile| for why we avoid to throw any errors.
+ return {};
+ }
+
+ // Search sub-directories and js-files within |dirName|.
+ let dirs = [];
+ let jsFiles = [];
+ for (let name of fs.readdirSync(absDir)) {
+ let stat = fs.statSync(path.join(absDir, name));
+ if (stat.isDirectory()) {
+ dirs.push(name);
+ } else if (stat.isFile() && name.endsWith(".js")) {
+ jsFiles.push(name);
+ }
+ }
+
+ let globals = Object.create(null);
+
+ // Process each js-file.
+ for (let jsFile of jsFiles) {
+ addGlobalsFrom(dirName, jsFile, globals);
+ }
+
+ // Recursively traverse all sub-directories.
+ for (let dir of dirs) {
+ globals = { ...globals, ...selfHostingDefines(path.join(dirName, dir)) };
+ }
+
+ return globals;
+}
+
+function selfHostingFunctions() {
+ // Definitions can be spread across multiple lines and may have extra
+ // whitespace, so we simply remove all whitespace and match over the complete
+ // file.
+ let content = tryReadFile("js/src/vm/SelfHosting.cpp").replace(/\s+/g, "");
+
+ let globals = Object.create(null);
+ for (let m of content.matchAll(/(?:JS_FN|JS_INLINABLE_FN)\("(\w+)"/g)) {
+ globals[m[1]] = "readonly";
+ }
+ return globals;
+}
+
+function errorNumbers() {
+ // Definitions are separated by line.
+ let lines = tryReadFile("js/public/friend/ErrorNumbers.msg").split("\n");
+
+ let globals = Object.create(null);
+ for (let line of lines) {
+ let m = line.match(/^MSG_DEF\((\w+),/);
+ if (m) {
+ globals[m[1]] = "readonly";
+ }
+ }
+ return globals;
+}
+
+const globals = {
+ ...selfHostingDefines(),
+ ...selfHostingFunctions(),
+ ...errorNumbers(),
+};
+
+module.exports = {
+ globals,
+};
diff --git a/tools/lint/eslint/eslint-plugin-spidermonkey-js/lib/index.js b/tools/lint/eslint/eslint-plugin-spidermonkey-js/lib/index.js
new file mode 100644
index 0000000000..d9d40af8c6
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-spidermonkey-js/lib/index.js
@@ -0,0 +1,20 @@
+/**
+ * @fileoverview A processor to help parse the spidermonkey js code.
+ * 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";
+
+// ------------------------------------------------------------------------------
+// Plugin Definition
+// ------------------------------------------------------------------------------
+module.exports = {
+ processors: {
+ processor: require("../lib/processors/self-hosted"),
+ },
+ environments: {
+ environment: require("../lib/environments/self-hosted"),
+ },
+};
diff --git a/tools/lint/eslint/eslint-plugin-spidermonkey-js/lib/processors/self-hosted.js b/tools/lint/eslint/eslint-plugin-spidermonkey-js/lib/processors/self-hosted.js
new file mode 100644
index 0000000000..02201a329b
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-spidermonkey-js/lib/processors/self-hosted.js
@@ -0,0 +1,129 @@
+/**
+ * @fileoverview Remove macros from SpiderMonkey's self-hosted JS.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+"use strict";
+
+const path = require("path");
+const fs = require("fs");
+
+const selfHostedRegex = /js\/src\/builtin\/.*?\.js$/;
+const macroRegex =
+ /\s*\#(if|ifdef|else|elif|endif|include|define|undef|error).*/;
+
+function isSelfHostedFile(filename) {
+ if (path.win32) {
+ filename = filename.split(path.sep).join("/");
+ }
+ return selfHostedRegex.test(filename);
+}
+
+function tryReadFile(filePath) {
+ if (!path.isAbsolute(filePath)) {
+ return "";
+ }
+ if (!fs.existsSync(filePath)) {
+ // Safely handle the case when the file wasn't found, because throwing
+ // errors can lead to confusing result when used with ESLint.
+ return "";
+ }
+ return fs.readFileSync(filePath, "utf-8");
+}
+
+// Adjust the range of fixes to match the original source code.
+function createFix(lines, message) {
+ let { line, column, fix } = message;
+
+ // Line and column are 1-based. Make sure we got a valid input.
+ if (line <= 0 || column <= 0) {
+ return null;
+ }
+
+ // Reject to create a fix when the line is out of range for some reason.
+ if (line > lines.length) {
+ return null;
+ }
+
+ // Find the absolute start position of the line in the original file.
+ let startOfLine = 0;
+ for (let i = 0; i < line - 1; ++i) {
+ // Add the length of the line, including its line separator.
+ startOfLine += lines[i].length + "\n".length;
+ }
+
+ // Add the 1-based column to the start of line to get the start position.
+ let start = startOfLine + (column - 1);
+
+ // Add the fix range to get the end position.
+ let end = start + (fix.range[1] - fix.range[0]);
+
+ // And finally return the new fix object.
+ return { text: fix.text, range: [start, end] };
+}
+
+module.exports = {
+ preprocess(text, filename) {
+ if (!isSelfHostedFile(filename)) {
+ return [text];
+ }
+
+ let lines = text.split(/\n/);
+ for (let i = 0; i < lines.length; i++) {
+ if (!macroRegex.test(lines[i])) {
+ // No macro here, nothing to do.
+ continue;
+ }
+
+ for (; i < lines.length; i++) {
+ // The macro isn't correctly indented, so we need to instruct
+ // prettier to ignore them.
+ lines[i] = "// prettier-ignore -- " + lines[i];
+
+ // If the line ends with a backslash (\), the next line
+ // is also part of part of the macro.
+ if (!lines[i].endsWith("\\")) {
+ break;
+ }
+ }
+ }
+
+ return [lines.join("\n")];
+ },
+
+ postprocess(messages, filename) {
+ // Don't attempt to create fixes for any non-selfhosted files.
+ if (!isSelfHostedFile(filename)) {
+ return [].concat(...messages);
+ }
+
+ let lines = null;
+
+ let result = [];
+ for (let message of messages.flat()) {
+ if (message.fix) {
+ if (lines === null) {
+ lines = tryReadFile(filename).split(/\n/);
+ }
+
+ let fix = createFix(lines, message);
+ if (fix) {
+ message.fix = fix;
+ } else {
+ // We couldn't create a fix, so we better remove the passed in fix,
+ // because its range points to the preprocessor output, but the post-
+ // processor must translate it into a range of the original source.
+ delete message.fix;
+ }
+ }
+
+ result.push(message);
+ }
+ return result;
+ },
+
+ supportsAutofix: true,
+};
diff --git a/tools/lint/eslint/eslint-plugin-spidermonkey-js/package.json b/tools/lint/eslint/eslint-plugin-spidermonkey-js/package.json
new file mode 100644
index 0000000000..7d96b5b1c4
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-spidermonkey-js/package.json
@@ -0,0 +1,28 @@
+{
+ "name": "eslint-plugin-spidermonkey-js",
+ "version": "0.1.1",
+ "description": "A collection of rules that help enforce JavaScript coding standard in the Mozilla SpiderMonkey project.",
+ "keywords": [
+ "eslint",
+ "eslintplugin",
+ "eslint-plugin",
+ "mozilla",
+ "spidermonkey"
+ ],
+ "bugs": {
+ "url": "https://bugzilla.mozilla.org/enter_bug.cgi?product=Testing&component=Lint"
+ },
+ "homepage": "http://firefox-source-docs.mozilla.org/tools/lint/linters/eslint-plugin-spidermonkey-js.html",
+ "repository": {
+ "type": "hg",
+ "url": "https://hg.mozilla.org/mozilla-central/"
+ },
+ "author": "Mozilla",
+ "main": "lib/index.js",
+ "dependencies": {},
+ "devDependencies": {},
+ "engines": {
+ "node": ">=6.9.1"
+ },
+ "license": "MPL-2.0"
+}
diff --git a/tools/lint/eslint/manifest.tt b/tools/lint/eslint/manifest.tt
new file mode 100644
index 0000000000..c1ec658b0e
--- /dev/null
+++ b/tools/lint/eslint/manifest.tt
@@ -0,0 +1,10 @@
+[
+ {
+ "filename": "eslint.tar.gz",
+ "size": 22086762,
+ "algorithm": "sha512",
+ "digest": "abf5caa29669e1f8f889459b7af074f2744c7ba7e51901a1b3ad3e504c3f331d360616a0d9c1f0114034dce33874ca7ed3971a8ae7f38f21ae2a6b4514a0e5eb",
+ "unpack": true,
+ "visibility": "public"
+ }
+] \ No newline at end of file
diff --git a/tools/lint/eslint/setup_helper.py b/tools/lint/eslint/setup_helper.py
new file mode 100644
index 0000000000..2f2074d2cf
--- /dev/null
+++ b/tools/lint/eslint/setup_helper.py
@@ -0,0 +1,423 @@
+# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+import json
+import os
+import platform
+import re
+import subprocess
+import sys
+from filecmp import dircmp
+
+from mozbuild.nodeutil import (
+ NODE_MIN_VERSION,
+ NPM_MIN_VERSION,
+ find_node_executable,
+ find_npm_executable,
+)
+from mozfile.mozfile import remove as mozfileremove
+from packaging.version import Version
+
+NODE_MACHING_VERSION_NOT_FOUND_MESSAGE = """
+Could not find Node.js executable later than %s.
+
+Executing `mach bootstrap --no-system-changes` should
+install a compatible version in ~/.mozbuild on most platforms.
+""".strip()
+
+NPM_MACHING_VERSION_NOT_FOUND_MESSAGE = """
+Could not find npm executable later than %s.
+
+Executing `mach bootstrap --no-system-changes` should
+install a compatible version in ~/.mozbuild on most platforms.
+""".strip()
+
+NODE_NOT_FOUND_MESSAGE = """
+nodejs is either not installed or is installed to a non-standard path.
+
+Executing `mach bootstrap --no-system-changes` should
+install a compatible version in ~/.mozbuild on most platforms.
+""".strip()
+
+NPM_NOT_FOUND_MESSAGE = """
+Node Package Manager (npm) is either not installed or installed to a
+non-standard path.
+
+Executing `mach bootstrap --no-system-changes` should
+install a compatible version in ~/.mozbuild on most platforms.
+""".strip()
+
+
+VERSION_RE = re.compile(r"^\d+\.\d+\.\d+$")
+CARET_VERSION_RANGE_RE = re.compile(r"^\^((\d+)\.\d+\.\d+)$")
+
+project_root = None
+
+
+def eslint_maybe_setup():
+ """Setup ESLint only if it is needed."""
+ has_issues, needs_clobber = eslint_module_needs_setup()
+
+ if has_issues:
+ eslint_setup(needs_clobber)
+
+
+def eslint_setup(should_clobber=False):
+ """Ensure eslint is optimally configured.
+
+ This command will inspect your eslint configuration and
+ guide you through an interactive wizard helping you configure
+ eslint for optimal use on Mozilla projects.
+ """
+ package_setup(get_project_root(), "eslint", should_clobber=should_clobber)
+
+
+def remove_directory(path):
+ print("Clobbering %s..." % path)
+ if sys.platform.startswith("win") and have_winrm():
+ process = subprocess.Popen(["winrm", "-rf", path])
+ process.wait()
+ else:
+ mozfileremove(path)
+
+
+def package_setup(
+ package_root,
+ package_name,
+ should_update=False,
+ should_clobber=False,
+ no_optional=False,
+):
+ """Ensure `package_name` at `package_root` is installed.
+
+ When `should_update` is true, clobber, install, and produce a new
+ "package-lock.json" file.
+
+ This populates `package_root/node_modules`.
+
+ """
+ orig_project_root = get_project_root()
+ orig_cwd = os.getcwd()
+
+ if should_update:
+ should_clobber = True
+
+ try:
+ set_project_root(package_root)
+ sys.path.append(os.path.dirname(__file__))
+
+ # npm sometimes fails to respect cwd when it is run using check_call so
+ # we manually switch folders here instead.
+ project_root = get_project_root()
+ os.chdir(project_root)
+
+ if should_clobber:
+ remove_directory(os.path.join(project_root, "node_modules"))
+
+ # Always remove the eslint-plugin-mozilla sub-directory as that can
+ # sometimes conflict with the top level node_modules, see bug 1809036.
+ remove_directory(
+ os.path.join(
+ get_eslint_module_path(), "eslint-plugin-mozilla", "node_modules"
+ )
+ )
+
+ npm_path, _ = find_npm_executable()
+ if not npm_path:
+ return 1
+
+ node_path, _ = find_node_executable()
+ if not node_path:
+ return 1
+
+ extra_parameters = ["--loglevel=error"]
+
+ if no_optional:
+ extra_parameters.append("--no-optional")
+
+ package_lock_json_path = os.path.join(get_project_root(), "package-lock.json")
+
+ if should_update:
+ cmd = [npm_path, "install"]
+ mozfileremove(package_lock_json_path)
+ else:
+ cmd = [npm_path, "ci"]
+
+ # On non-Windows, ensure npm is called via node, as node may not be in the
+ # path.
+ if platform.system() != "Windows":
+ cmd.insert(0, node_path)
+
+ cmd.extend(extra_parameters)
+
+ # Ensure that bare `node` and `npm` in scripts, including post-install scripts, finds the
+ # binary we're invoking with. Without this, it's easy for compiled extensions to get
+ # mismatched versions of the Node.js extension API.
+ path = os.environ.get("PATH", "").split(os.pathsep)
+ node_dir = os.path.dirname(node_path)
+ if node_dir not in path:
+ path = [node_dir] + path
+
+ print('Installing %s for mach using "%s"...' % (package_name, " ".join(cmd)))
+ result = call_process(
+ package_name, cmd, append_env={"PATH": os.pathsep.join(path)}
+ )
+
+ if not result:
+ return 1
+
+ bin_path = os.path.join(
+ get_project_root(), "node_modules", ".bin", package_name
+ )
+
+ print("\n%s installed successfully!" % package_name)
+ print("\nNOTE: Your local %s binary is at %s\n" % (package_name, bin_path))
+
+ finally:
+ set_project_root(orig_project_root)
+ os.chdir(orig_cwd)
+
+
+def call_process(name, cmd, cwd=None, append_env={}):
+ env = dict(os.environ)
+ env.update(append_env)
+
+ try:
+ with open(os.devnull, "w") as fnull:
+ subprocess.check_call(cmd, cwd=cwd, stdout=fnull, env=env)
+ except subprocess.CalledProcessError:
+ if cwd:
+ print("\nError installing %s in the %s folder, aborting." % (name, cwd))
+ else:
+ print("\nError installing %s, aborting." % name)
+
+ return False
+
+ return True
+
+
+def expected_eslint_modules():
+ # Read the expected version of ESLint and external modules
+ expected_modules_path = os.path.join(get_project_root(), "package.json")
+ with open(expected_modules_path, encoding="utf-8") as f:
+ sections = json.load(f)
+ expected_modules = sections.get("dependencies", {})
+ expected_modules.update(sections.get("devDependencies", {}))
+
+ # Also read the in-tree ESLint plugin mozilla information, to ensure the
+ # dependencies are up to date.
+ mozilla_json_path = os.path.join(
+ get_eslint_module_path(), "eslint-plugin-mozilla", "package.json"
+ )
+ with open(mozilla_json_path, encoding="utf-8") as f:
+ dependencies = json.load(f).get("dependencies", {})
+ expected_modules.update(dependencies)
+
+ # Also read the in-tree ESLint plugin spidermonkey information, to ensure the
+ # dependencies are up to date.
+ mozilla_json_path = os.path.join(
+ get_eslint_module_path(), "eslint-plugin-spidermonkey-js", "package.json"
+ )
+ with open(mozilla_json_path, encoding="utf-8") as f:
+ expected_modules.update(json.load(f).get("dependencies", {}))
+
+ return expected_modules
+
+
+def check_eslint_files(node_modules_path, name):
+ def check_file_diffs(dcmp):
+ # Diff files only looks at files that are different. Not for files
+ # that are only present on one side. This should be generally OK as
+ # new files will need to be added in the index.js for the package.
+ if dcmp.diff_files and dcmp.diff_files != ["package.json"]:
+ return True
+
+ result = False
+
+ # Again, we only look at common sub directories for the same reason
+ # as above.
+ for sub_dcmp in dcmp.subdirs.values():
+ result = result or check_file_diffs(sub_dcmp)
+
+ return result
+
+ dcmp = dircmp(
+ os.path.join(node_modules_path, name),
+ os.path.join(get_eslint_module_path(), name),
+ )
+
+ return check_file_diffs(dcmp)
+
+
+def eslint_module_needs_setup():
+ has_issues = False
+ needs_clobber = False
+ node_modules_path = os.path.join(get_project_root(), "node_modules")
+
+ for name, expected_data in expected_eslint_modules().items():
+ # expected_eslint_modules returns a string for the version number of
+ # dependencies for installation of eslint generally, and an object
+ # for our in-tree plugins (which contains the entire module info).
+ if "version" in expected_data:
+ version_range = expected_data["version"]
+ else:
+ version_range = expected_data
+
+ path = os.path.join(node_modules_path, name, "package.json")
+
+ if not os.path.exists(path):
+ print("%s v%s needs to be installed locally." % (name, version_range))
+ has_issues = True
+ continue
+ data = json.load(open(path, encoding="utf-8"))
+
+ if version_range.startswith("file:"):
+ # We don't need to check local file installations for versions, as
+ # these are symlinked, so we'll always pick up the latest.
+ continue
+
+ if name == "eslint" and Version("4.0.0") > Version(data["version"]):
+ print("ESLint is an old version, clobbering node_modules directory")
+ needs_clobber = True
+ has_issues = True
+ continue
+
+ if not version_in_range(data["version"], version_range):
+ print("%s v%s should be v%s." % (name, data["version"], version_range))
+ has_issues = True
+ continue
+
+ return has_issues, needs_clobber
+
+
+def version_in_range(version, version_range):
+ """
+ Check if a module version is inside a version range. Only supports explicit versions and
+ caret ranges for the moment, since that's all we've used so far.
+ """
+ if version == version_range:
+ return True
+
+ version_match = VERSION_RE.match(version)
+ if not version_match:
+ raise RuntimeError("mach eslint doesn't understand module version %s" % version)
+ version = Version(version)
+
+ # Caret ranges as specified by npm allow changes that do not modify the left-most non-zero
+ # digit in the [major, minor, patch] tuple. The code below assumes the major digit is
+ # non-zero.
+ range_match = CARET_VERSION_RANGE_RE.match(version_range)
+ if range_match:
+ range_version = range_match.group(1)
+ range_major = int(range_match.group(2))
+
+ range_min = Version(range_version)
+ range_max = Version("%d.0.0" % (range_major + 1))
+
+ return range_min <= version < range_max
+
+ return False
+
+
+def get_possible_node_paths_win():
+ """
+ Return possible nodejs paths on Windows.
+ """
+ if platform.system() != "Windows":
+ return []
+
+ return list(
+ {
+ "%s\\nodejs" % os.environ.get("SystemDrive"),
+ os.path.join(os.environ.get("ProgramFiles"), "nodejs"),
+ os.path.join(os.environ.get("PROGRAMW6432"), "nodejs"),
+ os.path.join(os.environ.get("PROGRAMFILES"), "nodejs"),
+ }
+ )
+
+
+def get_version(path):
+ try:
+ version_str = subprocess.check_output(
+ [path, "--version"], stderr=subprocess.STDOUT, universal_newlines=True
+ )
+ return version_str
+ except (subprocess.CalledProcessError, OSError):
+ return None
+
+
+def set_project_root(root=None):
+ """Sets the project root to the supplied path, or works out what the root
+ is based on looking for 'mach'.
+
+ Keyword arguments:
+ root - (optional) The path to set the root to.
+ """
+ global project_root
+
+ if root:
+ project_root = root
+ return
+
+ file_found = False
+ folder = os.getcwd()
+
+ while folder:
+ if os.path.exists(os.path.join(folder, "mach")):
+ file_found = True
+ break
+ else:
+ folder = os.path.dirname(folder)
+
+ if file_found:
+ project_root = os.path.abspath(folder)
+
+
+def get_project_root():
+ """Returns the absolute path to the root of the project, see set_project_root()
+ for how this is determined.
+ """
+ global project_root
+
+ if not project_root:
+ set_project_root()
+
+ return project_root
+
+
+def get_eslint_module_path():
+ return os.path.join(get_project_root(), "tools", "lint", "eslint")
+
+
+def check_node_executables_valid():
+ node_path, version = find_node_executable()
+ if not node_path:
+ print(NODE_NOT_FOUND_MESSAGE)
+ return False
+ if not version:
+ print(NODE_MACHING_VERSION_NOT_FOUND_MESSAGE % NODE_MIN_VERSION)
+ return False
+
+ npm_path, version = find_npm_executable()
+ if not npm_path:
+ print(NPM_NOT_FOUND_MESSAGE)
+ return False
+ if not version:
+ print(NPM_MACHING_VERSION_NOT_FOUND_MESSAGE % NPM_MIN_VERSION)
+ return False
+
+ return True
+
+
+def have_winrm():
+ # `winrm -h` should print 'winrm version ...' and exit 1
+ try:
+ p = subprocess.Popen(
+ ["winrm.exe", "-h"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT
+ )
+ return p.wait() == 1 and p.stdout.read().startswith("winrm")
+ except Exception:
+ return False
diff --git a/tools/lint/eslint/update.sh b/tools/lint/eslint/update.sh
new file mode 100755
index 0000000000..025f747135
--- /dev/null
+++ b/tools/lint/eslint/update.sh
@@ -0,0 +1,50 @@
+#!/bin/sh
+# Script to regenerate the npm packages used for ESLint by the builders.
+# Requires
+
+# Force the scripts working directory to be projdir/tools/lint/eslint.
+DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+cd $DIR
+
+if [ -z "$TASKCLUSTER_ACCESS_TOKEN" -o -z "$TASKCLUSTER_CLIENT_ID" -o -z "$TASKCLUSTER_ROOT_URL" ]; then
+ echo "Please ensure you have run the taskcluster shell correctly to set"
+ echo "the TASKCLUSTER_ACCESS_TOKEN, TASKCLUSTER_CLIENT_ID and"
+ echo "TASKCLUSTER_ROOT_URL environment variables."
+ echo "See https://firefox-source-docs.mozilla.org/code-quality/lint/linters/eslint/enabling-rules.html"
+ exit 1;
+fi
+
+echo ""
+echo "Removing node_modules and package-lock.json..."
+# Move to the top-level directory.
+cd ../../../
+rm -rf node_modules/
+rm -rf tools/lint/eslint/eslint-plugin-mozilla/node_modules
+rm package-lock.json
+
+echo "Installing eslint and external plugins..."
+# ESLint and all _external_ plugins are listed in this directory's package.json,
+# so a regular `npm install` will install them at the specified versions.
+# The in-tree eslint-plugin-mozilla is kept out of this tooltool archive on
+# purpose so that it can be changed by any developer without requiring tooltool
+# access to make changes.
+./mach npm install
+
+echo "Creating eslint.tar.gz..."
+tar cvz --exclude=eslint-plugin-mozilla --exclude=eslint-plugin-spidermonkey-js -f eslint.tar.gz node_modules
+
+echo "Adding eslint.tar.gz to tooltool..."
+rm tools/lint/eslint/manifest.tt
+./python/mozbuild/mozbuild/action/tooltool.py add --visibility public --unpack eslint.tar.gz
+
+echo "Uploading eslint.tar.gz to tooltool..."
+./python/mozbuild/mozbuild/action/tooltool.py upload --message "node_modules folder update for tools/lint/eslint"
+
+echo "Cleaning up..."
+mv manifest.tt tools/lint/eslint/manifest.tt
+rm eslint.tar.gz
+
+cd $DIR
+
+echo ""
+echo "Update complete, please commit and check in your changes."