From 9e3c08db40b8916968b9f30096c7be3f00ce9647 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 21 Apr 2024 13:44:51 +0200 Subject: Adding upstream version 1:115.7.0. Signed-off-by: Daniel Baumann --- tools/lint/eslint/.eslintrc.js | 30 + tools/lint/eslint/__init__.py | 280 + tools/lint/eslint/eslint-plugin-mozilla/.npmignore | 8 + tools/lint/eslint/eslint-plugin-mozilla/LICENSE | 363 + tools/lint/eslint/eslint-plugin-mozilla/README.md | 56 + .../eslint-plugin-mozilla/lib/configs/.eslintrc.js | 8 + .../lib/configs/browser-test.js | 91 + .../lib/configs/chrome-test.js | 61 + .../lib/configs/mochitest-test.js | 59 + .../lib/configs/recommended.js | 356 + .../lib/configs/require-jsdoc.js | 32 + .../lib/configs/valid-jsdoc.js | 25 + .../lib/configs/xpcshell-test.js | 50 + .../lib/environments/browser-window.js | 119 + .../lib/environments/chrome-script.js | 28 + .../lib/environments/chrome-worker.js | 25 + .../lib/environments/frame-script.js | 39 + .../eslint-plugin-mozilla/lib/environments/jsm.js | 31 + .../lib/environments/privileged.js | 803 +++ .../lib/environments/process-script.js | 38 + .../lib/environments/remote-page.js | 43 + .../lib/environments/simpletest.js | 35 + .../eslint-plugin-mozilla/lib/environments/sjs.js | 30 + .../lib/environments/special-powers-sandbox.js | 46 + .../lib/environments/specific.js | 31 + .../lib/environments/utils.js | 62 + .../lib/environments/xpcshell.js | 59 + .../eslint/eslint-plugin-mozilla/lib/globals.js | 665 ++ .../eslint/eslint-plugin-mozilla/lib/helpers.js | 805 +++ .../lint/eslint/eslint-plugin-mozilla/lib/index.js | 96 + .../lib/rules/avoid-Date-timing.js | 61 + .../lib/rules/avoid-removeChild.js | 70 + .../lib/rules/balanced-listeners.js | 149 + .../lib/rules/balanced-observers.js | 121 + .../lib/rules/consistent-if-bracing.js | 54 + .../lib/rules/import-browser-window-globals.js | 50 + .../lib/rules/import-content-task-globals.js | 73 + .../lib/rules/import-globals.js | 21 + .../lib/rules/import-headjs-globals.js | 51 + .../lib/rules/lazy-getter-object-name.js | 48 + .../lib/rules/mark-exported-symbols-as-used.js | 90 + .../lib/rules/mark-test-function-used.js | 44 + .../eslint-plugin-mozilla/lib/rules/no-aArgs.js | 57 + .../lib/rules/no-addtask-setup.js | 57 + .../lib/rules/no-arbitrary-setTimeout.js | 65 + .../rules/no-compare-against-boolean-literals.js | 40 + .../lib/rules/no-cu-reportError.js | 130 + .../lib/rules/no-define-cc-etc.js | 57 + .../lib/rules/no-redeclare-with-import-autofix.js | 160 + .../lib/rules/no-throw-cr-literal.js | 101 + .../lib/rules/no-useless-parameters.js | 156 + .../lib/rules/no-useless-removeEventListener.js | 69 + .../lib/rules/no-useless-run-test.js | 76 + .../lib/rules/prefer-boolean-length-check.js | 129 + .../lib/rules/prefer-formatValues.js | 97 + .../lib/rules/reject-addtask-only.js | 48 + .../lib/rules/reject-chromeutils-import-params.js | 62 + .../rules/reject-eager-module-in-lazy-getter.js | 103 + .../lib/rules/reject-global-this.js | 40 + .../lib/rules/reject-globalThis-modification.js | 70 + .../reject-import-system-module-from-non-system.js | 36 + .../lib/rules/reject-importGlobalProperties.js | 94 + .../lib/rules/reject-lazy-imports-into-globals.js | 76 + .../lib/rules/reject-mixing-eager-and-lazy.js | 153 + .../lib/rules/reject-multiple-getters-calls.js | 81 + .../lib/rules/reject-relative-requires.js | 39 + .../lib/rules/reject-scriptableunicodeconverter.js | 41 + .../lib/rules/reject-some-requires.js | 41 + .../lib/rules/reject-top-level-await.js | 45 + .../lib/rules/rejects-requires-await.js | 47 + .../eslint-plugin-mozilla/lib/rules/use-cc-etc.js | 52 + .../lib/rules/use-chromeutils-generateqi.js | 105 + .../lib/rules/use-chromeutils-import.js | 78 + .../lib/rules/use-default-preference-values.js | 52 + .../lib/rules/use-includes-instead-of-indexOf.js | 50 + .../lib/rules/use-isInstance.js | 154 + .../lib/rules/use-ownerGlobal.js | 40 + .../lib/rules/use-returnValue.js | 41 + .../lib/rules/use-services.js | 104 + .../lib/rules/use-static-import.js | 87 + .../lib/rules/valid-ci-uses.js | 167 + .../eslint-plugin-mozilla/lib/rules/valid-lazy.js | 221 + .../lib/rules/valid-services-property.js | 126 + .../lib/rules/valid-services.js | 62 + .../lib/rules/var-only-at-top-level.js | 39 + .../eslint/eslint-plugin-mozilla/lib/services.json | 62 + .../lint/eslint/eslint-plugin-mozilla/manifest.tt | 10 + .../eslint/eslint-plugin-mozilla/package-lock.json | 6924 ++++++++++++++++++++ .../lint/eslint/eslint-plugin-mozilla/package.json | 53 + .../reporters/mozilla-format.js | 57 + .../eslint-plugin-mozilla/scripts/createExports.js | 77 + .../tests/avoid-Date-timing.js | 34 + .../tests/avoid-removeChild.js | 37 + .../tests/balanced-listeners.js | 100 + .../tests/balanced-observers.js | 80 + .../tests/consistent-if-bracing.js | 39 + .../eslint/eslint-plugin-mozilla/tests/globals.js | 161 + .../tests/lazy-getter-object-name.js | 51 + .../tests/mark-exported-symbols-as-used.js | 45 + .../tests/no-addtask-setup.js | 69 + .../tests/no-arbitrary-setTimeout.js | 39 + .../tests/no-compare-against-boolean-literals.js | 59 + .../tests/no-cu-reportError.js | 100 + .../tests/no-define-cc-etc.js | 63 + .../tests/no-redeclare-with-import-autofix.js | 77 + .../tests/no-throw-cr-literal.js | 62 + .../tests/no-useless-parameters.js | 175 + .../tests/no-useless-removeEventListener.js | 96 + .../tests/no-useless-run-test.js | 126 + .../tests/prefer-boolean-length-check.js | 96 + .../tests/prefer-formatValues.js | 70 + .../tests/reject-addtask-only.js | 56 + .../tests/reject-chromeutils-import-params.js | 67 + .../tests/reject-eager-module-in-lazy-getter.js | 80 + .../tests/reject-global-this.js | 49 + .../tests/reject-globalThis-modification.js | 90 + .../reject-import-system-module-from-non-system.js | 33 + .../tests/reject-importGlobalProperties.js | 87 + .../tests/reject-lazy-imports-into-globals.js | 56 + .../tests/reject-mixing-eager-and-lazy.js | 124 + .../tests/reject-multiple-getters-calls.js | 60 + .../tests/reject-relative-requires.js | 57 + .../tests/reject-scriptableunicodeconverter.js | 33 + .../tests/reject-some-requires.js | 49 + .../tests/reject-top-level-await.js | 36 + .../tests/rejects-requires-await.js | 32 + .../eslint-plugin-mozilla/tests/use-cc-etc.js | 60 + .../tests/use-chromeutils-generateqi.js | 81 + .../tests/use-chromeutils-import.js | 65 + .../tests/use-default-preference-values.js | 41 + .../tests/use-includes-instead-of-indexOf.js | 38 + .../eslint-plugin-mozilla/tests/use-isInstance.js | 130 + .../eslint-plugin-mozilla/tests/use-ownerGlobal.js | 35 + .../eslint-plugin-mozilla/tests/use-returnValue.js | 39 + .../eslint-plugin-mozilla/tests/use-services.js | 60 + .../tests/use-static-import.js | 80 + .../eslint-plugin-mozilla/tests/valid-ci-uses.js | 58 + .../eslint-plugin-mozilla/tests/valid-lazy.js | 176 + .../tests/valid-services-property.js | 42 + .../eslint-plugin-mozilla/tests/valid-services.js | 33 + .../eslint-plugin-mozilla/tests/xpidl/docshell.xpt | 6077 +++++++++++++++++ .../tests/xpidl/xpcom_base.xpt | 3197 +++++++++ tools/lint/eslint/eslint-plugin-mozilla/update.sh | 61 + .../eslint/eslint-plugin-spidermonkey-js/LICENSE | 363 + .../lib/environments/self-hosted.js | 180 + .../eslint-plugin-spidermonkey-js/lib/index.js | 20 + .../lib/processors/self-hosted.js | 128 + .../eslint-plugin-spidermonkey-js/package.json | 28 + tools/lint/eslint/manifest.tt | 10 + tools/lint/eslint/setup_helper.py | 432 ++ tools/lint/eslint/update.sh | 71 + 151 files changed, 29930 insertions(+) create mode 100644 tools/lint/eslint/.eslintrc.js create mode 100644 tools/lint/eslint/__init__.py create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/.npmignore create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/LICENSE create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/README.md create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/lib/configs/.eslintrc.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/lib/configs/browser-test.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/lib/configs/chrome-test.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/lib/configs/mochitest-test.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/lib/configs/recommended.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/lib/configs/require-jsdoc.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/lib/configs/valid-jsdoc.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/lib/configs/xpcshell-test.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/lib/environments/browser-window.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/lib/environments/chrome-script.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/lib/environments/chrome-worker.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/lib/environments/frame-script.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/lib/environments/jsm.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/lib/environments/privileged.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/lib/environments/process-script.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/lib/environments/remote-page.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/lib/environments/simpletest.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/lib/environments/sjs.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/lib/environments/special-powers-sandbox.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/lib/environments/specific.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/lib/environments/utils.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/lib/environments/xpcshell.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/lib/globals.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/lib/helpers.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/lib/index.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/lib/rules/avoid-Date-timing.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/lib/rules/avoid-removeChild.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/lib/rules/balanced-listeners.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/lib/rules/balanced-observers.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/lib/rules/consistent-if-bracing.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/lib/rules/import-browser-window-globals.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/lib/rules/import-content-task-globals.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/lib/rules/import-globals.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/lib/rules/import-headjs-globals.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/lib/rules/lazy-getter-object-name.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/lib/rules/mark-exported-symbols-as-used.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/lib/rules/mark-test-function-used.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/lib/rules/no-aArgs.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/lib/rules/no-addtask-setup.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/lib/rules/no-arbitrary-setTimeout.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/lib/rules/no-compare-against-boolean-literals.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/lib/rules/no-cu-reportError.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/lib/rules/no-define-cc-etc.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/lib/rules/no-redeclare-with-import-autofix.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/lib/rules/no-throw-cr-literal.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/lib/rules/no-useless-parameters.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/lib/rules/no-useless-removeEventListener.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/lib/rules/no-useless-run-test.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/lib/rules/prefer-boolean-length-check.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/lib/rules/prefer-formatValues.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/lib/rules/reject-addtask-only.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/lib/rules/reject-chromeutils-import-params.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/lib/rules/reject-eager-module-in-lazy-getter.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/lib/rules/reject-global-this.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/lib/rules/reject-globalThis-modification.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/lib/rules/reject-import-system-module-from-non-system.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/lib/rules/reject-importGlobalProperties.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/lib/rules/reject-lazy-imports-into-globals.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/lib/rules/reject-mixing-eager-and-lazy.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/lib/rules/reject-multiple-getters-calls.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/lib/rules/reject-relative-requires.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/lib/rules/reject-scriptableunicodeconverter.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/lib/rules/reject-some-requires.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/lib/rules/reject-top-level-await.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/lib/rules/rejects-requires-await.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/lib/rules/use-cc-etc.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/lib/rules/use-chromeutils-generateqi.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/lib/rules/use-chromeutils-import.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/lib/rules/use-default-preference-values.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/lib/rules/use-includes-instead-of-indexOf.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/lib/rules/use-isInstance.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/lib/rules/use-ownerGlobal.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/lib/rules/use-returnValue.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/lib/rules/use-services.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/lib/rules/use-static-import.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/lib/rules/valid-ci-uses.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/lib/rules/valid-lazy.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/lib/rules/valid-services-property.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/lib/rules/valid-services.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/lib/rules/var-only-at-top-level.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/lib/services.json create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/manifest.tt create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/package-lock.json create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/package.json create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/reporters/mozilla-format.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/scripts/createExports.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/tests/avoid-Date-timing.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/tests/avoid-removeChild.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/tests/balanced-listeners.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/tests/balanced-observers.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/tests/consistent-if-bracing.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/tests/globals.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/tests/lazy-getter-object-name.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/tests/mark-exported-symbols-as-used.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/tests/no-addtask-setup.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/tests/no-arbitrary-setTimeout.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/tests/no-compare-against-boolean-literals.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/tests/no-cu-reportError.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/tests/no-define-cc-etc.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/tests/no-redeclare-with-import-autofix.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/tests/no-throw-cr-literal.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/tests/no-useless-parameters.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/tests/no-useless-removeEventListener.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/tests/no-useless-run-test.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/tests/prefer-boolean-length-check.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/tests/prefer-formatValues.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/tests/reject-addtask-only.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/tests/reject-chromeutils-import-params.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/tests/reject-eager-module-in-lazy-getter.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/tests/reject-global-this.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/tests/reject-globalThis-modification.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/tests/reject-import-system-module-from-non-system.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/tests/reject-importGlobalProperties.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/tests/reject-lazy-imports-into-globals.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/tests/reject-mixing-eager-and-lazy.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/tests/reject-multiple-getters-calls.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/tests/reject-relative-requires.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/tests/reject-scriptableunicodeconverter.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/tests/reject-some-requires.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/tests/reject-top-level-await.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/tests/rejects-requires-await.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/tests/use-cc-etc.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/tests/use-chromeutils-generateqi.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/tests/use-chromeutils-import.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/tests/use-default-preference-values.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/tests/use-includes-instead-of-indexOf.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/tests/use-isInstance.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/tests/use-ownerGlobal.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/tests/use-returnValue.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/tests/use-services.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/tests/use-static-import.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/tests/valid-ci-uses.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/tests/valid-lazy.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/tests/valid-services-property.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/tests/valid-services.js create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/tests/xpidl/docshell.xpt create mode 100644 tools/lint/eslint/eslint-plugin-mozilla/tests/xpidl/xpcom_base.xpt create mode 100755 tools/lint/eslint/eslint-plugin-mozilla/update.sh create mode 100644 tools/lint/eslint/eslint-plugin-spidermonkey-js/LICENSE create mode 100644 tools/lint/eslint/eslint-plugin-spidermonkey-js/lib/environments/self-hosted.js create mode 100644 tools/lint/eslint/eslint-plugin-spidermonkey-js/lib/index.js create mode 100644 tools/lint/eslint/eslint-plugin-spidermonkey-js/lib/processors/self-hosted.js create mode 100644 tools/lint/eslint/eslint-plugin-spidermonkey-js/package.json create mode 100644 tools/lint/eslint/manifest.tt create mode 100644 tools/lint/eslint/setup_helper.py create mode 100755 tools/lint/eslint/update.sh (limited to 'tools/lint/eslint') diff --git a/tools/lint/eslint/.eslintrc.js b/tools/lint/eslint/.eslintrc.js new file mode 100644 index 0000000000..4a245d9de2 --- /dev/null +++ b/tools/lint/eslint/.eslintrc.js @@ -0,0 +1,30 @@ +/* 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: { + 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"], + "eslint-plugin/prefer-message-ids": "off", + }, +}; diff --git a/tools/lint/eslint/__init__.py b/tools/lint/eslint/__init__.py new file mode 100644 index 0000000000..0bd320d691 --- /dev/null +++ b/tools/lint/eslint/__init__.py @@ -0,0 +1,280 @@ +# -*- 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 ')." +) + + +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} + + 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): + print(PRETTIER_ERROR_MESSAGE.format("\n".join(errors))) + + if not output: + # If we have errors, but no output, we assume something really bad happened. + if errors and len(errors): + return 1 + + return {"results": [], "fixed": 0} # no output means success + + output = output.decode(encoding, "replace").splitlines() + + results = [] + 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..28b51f9ed3 --- /dev/null +++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/configs/browser-test.js @@ -0,0 +1,91 @@ +// 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 }, + ], + }, +}; 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..fa1e8d6190 --- /dev/null +++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/configs/chrome-test.js @@ -0,0 +1,61 @@ +// 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", + }, +}; 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..3f72193d4d --- /dev/null +++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/configs/mochitest-test.js @@ -0,0 +1,59 @@ +// 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", + "no-shadow": "error", + }, +}; 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..a7d8c067f0 --- /dev/null +++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/configs/recommended.js @@ -0,0 +1,356 @@ +/* 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/ + */ +module.exports = { + env: { + browser: true, + es2021: 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"], + + 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", "**/*.jsm.js"], + 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", "**/*.jsm"], + rules: { + // Modules 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", + }, + ], + }, + }, + { + files: ["**/*.sys.mjs"], + rules: { + "mozilla/use-static-import": "error", + }, + }, + { + 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"], + 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", "**/*.jsm.js"], + rules: { + "mozilla/mark-exported-symbols-as-used": "error", + }, + }, + { + env: { + browser: false, + "mozilla/privileged": false, + "mozilla/sjs": true, + }, + files: ["**/*.sjs"], + rules: { + // TODO Bug 1501127: sjs files have their own sandbox, and do not inherit + // the Window backstage pass directly. Turn this rule off for sjs files for + // now until we develop a solution. + "mozilla/reject-importGlobalProperties": "off", + }, + }, + ], + + parserOptions: { + ecmaVersion: 12, + }, + + // When adding items to this file please check for effects on sub-directories. + plugins: ["html", "fetch-options", "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-generateqi": "error", + "mozilla/use-chromeutils-import": "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. + "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", + + // No duplicate keys in object declarations + "no-dupe-keys": "error", + + // 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 assignments to native objects or read-only global variables + "no-global-assign": "error", + + // 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", + + // Disallow the use of number literals that immediately lose precision at runtime when converted to JS Number + "no-loss-of-precision": "error", + + // Nested ternary statements are confusing + "no-nested-ternary": "error", + + // Use {} instead of new Object() + "no-new-object": "error", + + // Disallow use of new wrappers + "no-new-wrappers": "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"], + + // Disallows unnecessary `return await ...`. + "no-return-await": "error", + + // No unnecessary comparisons + "no-self-compare": "error", + + // No comma sequenced statements + "no-sequences": "error", + + // No declaring variables from an outer scope + // "no-shadow": "error", + + // No declaring variables that hide things like arguments + "no-shadow-restricted-names": "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", + + // No using with + "no-with": "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", + + // This generates too many false positives that are not easy to work around, + // and false positives seem to be inherent in the rule. + "require-atomic-updates": "off", + + // XXX Bug 1487642 - decide if we want to enable this or not. + // Require generator functions to contain yield + "require-yield": "off", + }, + + // To avoid bad interactions of the html plugin with the xml preprocessor in + // eslint-plugin-mozilla, we turn off processing of the html plugin for .xml + // files. + settings: { + "html/xml-extensions": [".xhtml"], + }, +}; 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..0a037ab159 --- /dev/null +++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/configs/require-jsdoc.js @@ -0,0 +1,32 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +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", + }, +}; 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..485dddfbd4 --- /dev/null +++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/configs/valid-jsdoc.js @@ -0,0 +1,25 @@ +/* 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", + }, +}; 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..492ecc1ae9 --- /dev/null +++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/configs/xpcshell-test.js @@ -0,0 +1,50 @@ +// 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", + }, +}; 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..01f7d512b6 --- /dev/null +++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/environments/browser-window.js @@ -0,0 +1,119 @@ +/** + * @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", +}; + +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..1ff73c04d9 --- /dev/null +++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/environments/jsm.js @@ -0,0 +1,31 @@ +/** + * @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, + // These are hard-coded and available in .jsm scopes. + // See BackstagePass::Resolve. + fetch: false, + crypto: false, + indexedDB: false, + structuredClone: 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..13e81f7cef --- /dev/null +++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/environments/privileged.js @@ -0,0 +1,803 @@ +/** + * @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, + AudioDestinationNode: 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, + 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, + IDBLocaleAwareKeyRange: 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, + 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, + 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, + 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, + }, +}; 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..5b362ea2e0 --- /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, + RPMSetBoolPref: 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..995c3173d2 --- /dev/null +++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/environments/sjs.js @@ -0,0 +1,30 @@ +/** + * @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, + ChromeUtils: false, + dump: 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/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.} 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..aa3d4258ae --- /dev/null +++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/globals.js @@ -0,0 +1,665 @@ +/** + * @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 callExpressionDefinitions = [ + /^loader\.lazyGetter\((?:globalThis|this), "(\w+)"/, + /^loader\.lazyServiceGetter\((?:globalThis|this), "(\w+)"/, + /^loader\.lazyRequireGetter\((?:globalThis|this), "(\w+)"/, + /^XPCOMUtils\.defineLazyGetter\((?:globalThis|this), "(\w+)"/, + /^XPCOMUtils\.defineLazyModuleGetter\((?:globalThis|this), "(\w+)"/, + /^ChromeUtils\.defineLazyGetter\((?:globalThis|this), "(\w+)"/, + /^ChromeUtils\.defineModuleGetter\((?:globalThis|this), "(\w+)"/, + /^XPCOMUtils\.defineLazyPreferenceGetter\((?:globalThis|this), "(\w+)"/, + /^XPCOMUtils\.defineLazyProxy\((?:globalThis|this), "(\w+)"/, + /^XPCOMUtils\.defineLazyScriptGetter\((?:globalThis|this), "(\w+)"/, + /^XPCOMUtils\.defineLazyServiceGetter\((?:globalThis|this), "(\w+)"/, + /^XPCOMUtils\.defineConstant\((?:globalThis|this), "(\w+)"/, + /^DevToolsUtils\.defineLazyModuleGetter\((?: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 (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.