Backed out changeset 2d88daa2e4bc (bug 1899848) for conflicting with the backout...
[gecko.git] / .eslintrc.js
blob738b2c77b541e3b0cfc899831e017dc211d96dc0
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this
3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 "use strict";
7 const xpcshellTestConfig = require("eslint-plugin-mozilla/lib/configs/xpcshell-test.js");
8 const browserTestConfig = require("eslint-plugin-mozilla/lib/configs/browser-test.js");
9 const mochitestTestConfig = require("eslint-plugin-mozilla/lib/configs/mochitest-test.js");
10 const chromeTestConfig = require("eslint-plugin-mozilla/lib/configs/chrome-test.js");
11 const { testPaths } = require("./.eslintrc-test-paths.js");
12 const { rollouts } = require("./.eslintrc-rollouts.js");
13 const fs = require("fs");
14 const path = require("path");
16 /**
17  * Some configurations have overrides, which can't be specified within overrides,
18  * so we need to remove them.
19  *
20  * @param {object} config
21  *   The configuration to remove overrides from.
22  * @returns {object}
23  *   The new configuration.
24  */
25 function removeOverrides(config) {
26   config = { ...config };
27   delete config.overrides;
28   return config;
31 function readFile(path) {
32   return fs
33     .readFileSync(path, { encoding: "utf-8" })
34     .split("\n")
35     .filter(p => p && !p.startsWith("#"));
38 const ignorePatterns = [
39   ...readFile(
40     path.join(__dirname, "tools", "rewriting", "ThirdPartyPaths.txt")
41   ),
42   ...readFile(path.join(__dirname, "tools", "rewriting", "Generated.txt")),
43   ...readFile(
44     path.join(
45       __dirname,
46       "devtools",
47       "client",
48       "debugger",
49       "src",
50       ".eslintignore"
51     )
52   ).map(p => `devtools/client/debugger/src/${p}`),
54 const httpTestingPaths = [
55   "**/*mixedcontent",
56   "**/*CrossOrigin",
57   "**/*crossorigin",
58   "**/*cors",
59   "**/*downgrade",
60   "**/*Downgrade",
63 module.exports = {
64   settings: {
65     "import/extensions": [".mjs"],
66   },
67   ignorePatterns,
68   // Ignore eslint configurations in parent directories.
69   root: true,
70   // New rules and configurations should generally be added in
71   // tools/lint/eslint/eslint-plugin-mozilla/lib/configs/recommended.js to
72   // allow external repositories that use the plugin to pick them up as well.
73   extends: ["plugin:mozilla/recommended"],
74   plugins: ["mozilla", "import", "json"],
75   overrides: [
76     {
77       files: [
78         // All .eslintrc.js files are in the node environment, so turn that
79         // on here.
80         // https://github.com/eslint/eslint/issues/13008
81         ".eslintrc*.js",
82         // *.config.js files are generally assumed to be configuration files
83         // based for node.
84         "*.config.?(m)js",
85       ],
86       env: {
87         node: true,
88         browser: false,
89       },
90     },
91     {
92       files: ["browser/base/content/browser.js"],
93       rules: {
94         "mozilla/no-more-globals": "error",
95       },
96     },
97     {
98       files: [
99         "**/*.jsx",
100         "browser/components/pocket/content/**/*.js",
101         "browser/components/storybook/.storybook/**/*.mjs",
102       ],
103       parserOptions: {
104         ecmaFeatures: {
105           jsx: true,
106         },
107       },
108     },
109     {
110       files: ["browser/components/storybook/**"],
111       env: {
112         "mozilla/privileged": false,
113       },
114     },
115     {
116       files: ["*.mjs"],
117       rules: {
118         "import/default": "error",
119         "import/export": "error",
120         "import/named": "error",
121         "import/namespace": "error",
122         "import/newline-after-import": "error",
123         "import/no-duplicates": "error",
124         "import/no-absolute-path": "error",
125         "import/no-named-default": "error",
126         "import/no-named-as-default": "error",
127         "import/no-named-as-default-member": "error",
128         "import/no-self-import": "error",
129         "import/no-unassigned-import": "error",
130         "import/no-unresolved": [
131           "error",
132           // Bug 1773473 - Ignore resolver URLs for chrome and resource as we
133           // do not yet have a resolver for them.
134           { ignore: ["chrome://", "resource://"] },
135         ],
136         "import/no-useless-path-segments": "error",
137       },
138     },
139     {
140       // Turn off no-unassigned-import for files that typically test our
141       // custom elements, which are imported for the side effects (ie
142       // the custom element being registered) rather than any particular
143       // export:
144       files: ["**/*.stories.mjs"],
145       rules: {
146         "import/no-unassigned-import": "off",
147       },
148     },
149     {
150       files: ["**/test/**", "**/tests/**"],
151       extends: ["plugin:mozilla/general-test"],
152     },
153     {
154       ...removeOverrides(xpcshellTestConfig),
155       files: testPaths.xpcshell.map(path => `${path}**`),
156       excludedFiles: ["**/*.jsm", "**/*.mjs", "**/*.sjs"],
157     },
158     {
159       // If it is an xpcshell head file, we turn off global unused variable checks, as it
160       // would require searching the other test files to know if they are used or not.
161       // This would be expensive and slow, and it isn't worth it for head files.
162       // We could get developers to declare as exported, but that doesn't seem worth it.
163       files: testPaths.xpcshell.map(path => `${path}head*.js`),
164       rules: {
165         "no-unused-vars": [
166           "error",
167           {
168             argsIgnorePattern: "^_",
169             vars: "local",
170           },
171         ],
172       },
173     },
174     {
175       // This section enables errors of no-unused-vars globally for all test*.js
176       // files in xpcshell test paths.
177       // This is not done in the xpcshell-test configuration as we cannot pull
178       // in overrides from there. We should at some stage, aim to enable this
179       // for all files in xpcshell-tests.
180       files: testPaths.xpcshell.map(path => `${path}test*.js`),
181       rules: {
182         // No declaring variables that are never used
183         "no-unused-vars": [
184           "error",
185           {
186             argsIgnorePattern: "^_",
187             vars: "all",
188           },
189         ],
190       },
191     },
192     {
193       ...removeOverrides(browserTestConfig),
194       files: testPaths.browser.map(path => `${path}**`),
195       excludedFiles: ["**/*.jsm", "**/*.mjs", "**/*.sjs"],
196     },
197     {
198       ...removeOverrides(mochitestTestConfig),
199       files: testPaths.mochitest.map(path => `${path}**`),
200       excludedFiles: [
201         "**/*.jsm",
202         "**/*.mjs",
203         "security/manager/ssl/tests/mochitest/browser/**",
204       ],
205     },
206     {
207       ...removeOverrides(chromeTestConfig),
208       files: testPaths.chrome.map(path => `${path}**`),
209       excludedFiles: ["**/*.jsm", "**/*.mjs", "**/*.sjs"],
210     },
211     {
212       env: {
213         // Ideally we wouldn't be using the simpletest env here, but our uses of
214         // js files mean we pick up everything from the global scope, which could
215         // be any one of a number of html files. So we just allow the basics...
216         "mozilla/simpletest": true,
217       },
218       files: [
219         ...testPaths.mochitest.map(path => `${path}/**/*.js`),
220         ...testPaths.chrome.map(path => `${path}/**/*.js`),
221       ],
222       excludedFiles: ["**/*.jsm", "**/*.mjs", "**/*.sjs"],
223     },
224     {
225       // Some directories have multiple kinds of tests, and some rules
226       // don't work well for HTML-based mochitests, so disable those.
227       files: testPaths.xpcshell
228         .concat(testPaths.browser)
229         .map(path => [`${path}/**/*.html`, `${path}/**/*.xhtml`])
230         .flat(),
231       rules: {
232         // plain/chrome mochitests don't automatically include Assert, so
233         // autofixing `ok()` to Assert.something is bad.
234         "mozilla/no-comparison-or-assignment-inside-ok": "off",
235       },
236     },
237     {
238       // Some directories reuse `test_foo.js` files between mochitest-plain and
239       // unit tests, or use custom postMessage-based assertion propagation into
240       // browser tests. Ignore those too:
241       files: [
242         // Reuses xpcshell unit test scripts in mochitest-plain HTML files.
243         "dom/indexedDB/test/**",
244         // Dispatches functions to the webpage in ways that are hard to detect.
245         "toolkit/components/antitracking/test/**",
246       ],
247       rules: {
248         "mozilla/no-comparison-or-assignment-inside-ok": "off",
249       },
250     },
251     {
252       // Rules of Hooks broadly checks for camelCase "use" identifiers, so
253       // enable only for paths actually using React to avoid false positives.
254       extends: ["plugin:react-hooks/recommended"],
255       files: [
256         "browser/components/aboutwelcome/**",
257         "browser/components/asrouter/**",
258         "browser/components/newtab/**",
259         "browser/components/pocket/**",
260         "devtools/**",
261       ],
262       rules: {
263         // react-hooks/recommended has exhaustive-deps as a warning, we prefer
264         // errors, so that raised issues get addressed one way or the other.
265         "react-hooks/exhaustive-deps": "error",
266       },
267     },
268     {
269       // Exempt files with these paths since they have to use http for full coverage
270       files: httpTestingPaths.map(path => `${path}**`),
271       rules: {
272         "@microsoft/sdl/no-insecure-url": "off",
273       },
274     },
275     ...rollouts,
276   ],