eslint 8.34.0 → 8.36.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/README.md +11 -12
  2. package/conf/rule-type-list.json +2 -2
  3. package/lib/cli-engine/cli-engine.js +2 -2
  4. package/lib/cli-engine/file-enumerator.js +8 -6
  5. package/lib/config/flat-config-array.js +74 -13
  6. package/lib/eslint/eslint-helpers.js +3 -3
  7. package/lib/rules/lines-around-comment.js +11 -0
  8. package/lib/rules/logical-assignment-operators.js +1 -1
  9. package/lib/rules/multiline-comment-style.js +42 -3
  10. package/lib/rules/no-constant-binary-expression.js +32 -25
  11. package/lib/rules/no-control-regex.js +1 -1
  12. package/lib/rules/no-eval.js +1 -1
  13. package/lib/rules/no-extra-boolean-cast.js +1 -1
  14. package/lib/rules/no-extra-parens.js +1 -1
  15. package/lib/rules/no-implied-eval.js +1 -1
  16. package/lib/rules/no-import-assign.js +1 -1
  17. package/lib/rules/no-invalid-regexp.js +1 -1
  18. package/lib/rules/no-misleading-character-class.js +2 -2
  19. package/lib/rules/no-obj-calls.js +1 -1
  20. package/lib/rules/no-promise-executor-return.js +1 -1
  21. package/lib/rules/no-regex-spaces.js +1 -1
  22. package/lib/rules/no-setter-return.js +1 -1
  23. package/lib/rules/no-useless-backreference.js +2 -2
  24. package/lib/rules/no-useless-return.js +1 -1
  25. package/lib/rules/prefer-exponentiation-operator.js +1 -1
  26. package/lib/rules/prefer-named-capture-group.js +2 -2
  27. package/lib/rules/prefer-object-spread.js +1 -1
  28. package/lib/rules/prefer-regex-literals.js +2 -2
  29. package/lib/rules/require-unicode-regexp.js +1 -1
  30. package/lib/rules/wrap-iife.js +1 -1
  31. package/lib/source-code/source-code.js +1 -1
  32. package/lib/source-code/token-store/index.js +1 -1
  33. package/messages/no-config-found.js +1 -1
  34. package/package.json +11 -6
  35. package/conf/eslint-all.js +0 -31
  36. package/conf/eslint-recommended.js +0 -76
package/README.md CHANGED
@@ -16,8 +16,7 @@
16
16
  [Report Bugs](https://eslint.org/docs/latest/contribute/report-bugs) |
17
17
  [Code of Conduct](https://eslint.org/conduct) |
18
18
  [Twitter](https://twitter.com/geteslint) |
19
- [Mailing List](https://groups.google.com/group/eslint) |
20
- [Chat Room](https://eslint.org/chat)
19
+ [Discord](https://eslint.org/chat)
21
20
 
22
21
  ESLint is a tool for identifying and reporting on patterns found in ECMAScript/JavaScript code. In many ways, it is similar to JSLint and JSHint with a few exceptions:
23
22
 
@@ -129,7 +128,7 @@ Once a language feature has been adopted into the ECMAScript standard (stage 4 a
129
128
 
130
129
  ### Where to ask for help?
131
130
 
132
- Join our [Mailing List](https://groups.google.com/group/eslint) or [Chatroom](https://eslint.org/chat).
131
+ Open a [discussion](https://github.com/eslint/eslint/discussions) or stop by our [Discord server](https://eslint.org/chat).
133
132
 
134
133
  ### Why doesn't ESLint lock dependency versions?
135
134
 
@@ -213,11 +212,6 @@ The people who manage releases, review feature requests, and meet regularly to e
213
212
  Nicholas C. Zakas
214
213
  </a>
215
214
  </td><td align="center" valign="top" width="11%">
216
- <a href="https://github.com/btmills">
217
- <img src="https://github.com/btmills.png?s=75" width="75" height="75"><br />
218
- Brandon Mills
219
- </a>
220
- </td><td align="center" valign="top" width="11%">
221
215
  <a href="https://github.com/mdjermanovic">
222
216
  <img src="https://github.com/mdjermanovic.png?s=75" width="75" height="75"><br />
223
217
  Milos Djermanovic
@@ -250,9 +244,14 @@ The people who review and fix bugs and help triage issues.
250
244
  Bryan Mishkin
251
245
  </a>
252
246
  </td><td align="center" valign="top" width="11%">
253
- <a href="https://github.com/SaraSoueidan">
254
- <img src="https://github.com/SaraSoueidan.png?s=75" width="75" height="75"><br />
255
- Sara Soueidan
247
+ <a href="https://github.com/btmills">
248
+ <img src="https://github.com/btmills.png?s=75" width="75" height="75"><br />
249
+ Brandon Mills
250
+ </a>
251
+ </td><td align="center" valign="top" width="11%">
252
+ <a href="https://github.com/fasttime">
253
+ <img src="https://github.com/fasttime.png?s=75" width="75" height="75"><br />
254
+ Francesco Trotta
256
255
  </a>
257
256
  </td><td align="center" valign="top" width="11%">
258
257
  <a href="https://github.com/yeonjuan">
@@ -293,7 +292,7 @@ The following companies, organizations, and individuals support ESLint's ongoing
293
292
  <h3>Platinum Sponsors</h3>
294
293
  <p><a href="#"><img src="https://images.opencollective.com/2021-frameworks-fund/logo.png" alt="Chrome Frameworks Fund" height="undefined"></a> <a href="https://automattic.com"><img src="https://images.opencollective.com/automattic/d0ef3e1/logo.png" alt="Automattic" height="undefined"></a></p><h3>Gold Sponsors</h3>
295
294
  <p><a href="https://ridicorp.com/career/"><img src="https://images.opencollective.com/ridi-corporation/175dcf3/logo.png" alt="RIDI" height="96"></a> <a href="https://engineering.salesforce.com"><img src="https://images.opencollective.com/salesforce/ca8f997/logo.png" alt="Salesforce" height="96"></a> <a href="https://www.airbnb.com/"><img src="https://images.opencollective.com/airbnb/d327d66/logo.png" alt="Airbnb" height="96"></a></p><h3>Silver Sponsors</h3>
296
- <p><a href="https://sentry.io"><img src="https://avatars.githubusercontent.com/u/1396951?v=4" alt="Sentry" height="64"></a> <a href="https://liftoff.io/"><img src="https://images.opencollective.com/liftoff/5c4fa84/logo.png" alt="Liftoff" height="64"></a></p><h3>Bronze Sponsors</h3>
295
+ <p><a href="https://sentry.io"><img src="https://avatars.githubusercontent.com/u/1396951?v=4" alt="Sentry" height="64"></a> <a href="https://liftoff.io/"><img src="https://images.opencollective.com/liftoff/5c4fa84/logo.png" alt="Liftoff" height="64"></a> <a href="https://americanexpress.io"><img src="https://avatars.githubusercontent.com/u/3853301?v=4" alt="American Express" height="64"></a></p><h3>Bronze Sponsors</h3>
297
296
  <p><a href="https://paydaysay.com/"><img src="https://images.opencollective.com/payday-say-organization/9cd2467/logo.png" alt="PayDay Say" height="32"></a> <a href="https://themeisle.com"><img src="https://images.opencollective.com/themeisle/d5592fe/logo.png" alt="ThemeIsle" height="32"></a> <a href="https://nx.dev"><img src="https://images.opencollective.com/nx/0efbe42/logo.png" alt="Nx (by Nrwl)" height="32"></a> <a href="https://www.crosswordsolver.org/anagram-solver/"><img src="https://images.opencollective.com/anagram-solver/2666271/logo.png" alt="Anagram Solver" height="32"></a> <a href="https://icons8.com"><img src="https://images.opencollective.com/icons8/7fa1641/logo.png" alt="Icons8: free icons, photos, illustrations, and music" height="32"></a> <a href="https://discord.com"><img src="https://images.opencollective.com/discordapp/f9645d9/logo.png" alt="Discord" height="32"></a> <a href="https://transloadit.com/"><img src="https://avatars.githubusercontent.com/u/125754?v=4" alt="Transloadit" height="32"></a> <a href="https://www.ignitionapp.com"><img src="https://avatars.githubusercontent.com/u/5753491?v=4" alt="Ignition" height="32"></a> <a href="https://herocoders.com"><img src="https://avatars.githubusercontent.com/u/37549774?v=4" alt="HeroCoders" height="32"></a> <a href="https://quickbookstoolhub.com"><img src="https://avatars.githubusercontent.com/u/95090305?u=e5bc398ef775c9ed19f955c675cdc1fb6abf01df&v=4" alt="QuickBooks Tool hub" height="32"></a></p>
298
297
  <!--sponsorsend-->
299
298
 
@@ -6,12 +6,12 @@
6
6
  ],
7
7
  "deprecated": {
8
8
  "name": "Deprecated",
9
- "description": "These rules have been deprecated in accordance with the <a href=\"/docs/use/rule-deprecation\">deprecation policy</a>, and replaced by newer rules:",
9
+ "description": "These rules have been deprecated in accordance with the <a href=\"{{ '/use/rule-deprecation' | url }}\">deprecation policy</a>, and replaced by newer rules:",
10
10
  "rules": []
11
11
  },
12
12
  "removed": {
13
13
  "name": "Removed",
14
- "description": "These rules from older versions of ESLint (before the <a href=\"/docs/use/rule-deprecation\">deprecation policy</a> existed) have been replaced by newer rules:",
14
+ "description": "These rules from older versions of ESLint (before the <a href=\"{{ '/use/rule-deprecation' | url }}\">deprecation policy</a> existed) have been replaced by newer rules:",
15
15
  "rules": [
16
16
  { "removed": "generator-star", "replacedBy": ["generator-star-spacing"] },
17
17
  { "removed": "global-strict", "replacedBy": ["strict"] },
@@ -615,8 +615,8 @@ class CLIEngine {
615
615
  useEslintrc: options.useEslintrc,
616
616
  builtInRules,
617
617
  loadRules,
618
- getEslintRecommendedConfig: () => require("../../conf/eslint-recommended.js"),
619
- getEslintAllConfig: () => require("../../conf/eslint-all.js")
618
+ getEslintRecommendedConfig: () => require("@eslint/js").configs.recommended,
619
+ getEslintAllConfig: () => require("@eslint/js").configs.all
620
620
  });
621
621
  const fileEnumerator = new FileEnumerator({
622
622
  configArrayFactory,
@@ -217,8 +217,8 @@ class FileEnumerator {
217
217
  cwd = process.cwd(),
218
218
  configArrayFactory = new CascadingConfigArrayFactory({
219
219
  cwd,
220
- getEslintRecommendedConfig: () => require("../../conf/eslint-recommended.js"),
221
- getEslintAllConfig: () => require("../../conf/eslint-all.js")
220
+ getEslintRecommendedConfig: () => require("@eslint/js").configs.recommended,
221
+ getEslintAllConfig: () => require("@eslint/js").configs.all
222
222
  }),
223
223
  extensions = null,
224
224
  globInputPaths = true,
@@ -349,7 +349,7 @@ class FileEnumerator {
349
349
  return this._iterateFilesWithFile(absolutePath);
350
350
  }
351
351
  if (globInputPaths && isGlobPattern(pattern)) {
352
- return this._iterateFilesWithGlob(absolutePath, isDot);
352
+ return this._iterateFilesWithGlob(pattern, isDot);
353
353
  }
354
354
 
355
355
  return [];
@@ -398,15 +398,17 @@ class FileEnumerator {
398
398
  _iterateFilesWithGlob(pattern, dotfiles) {
399
399
  debug(`Glob: ${pattern}`);
400
400
 
401
- const directoryPath = path.resolve(getGlobParent(pattern));
402
- const globPart = pattern.slice(directoryPath.length + 1);
401
+ const { cwd } = internalSlotsMap.get(this);
402
+ const directoryPath = path.resolve(cwd, getGlobParent(pattern));
403
+ const absolutePath = path.resolve(cwd, pattern);
404
+ const globPart = absolutePath.slice(directoryPath.length + 1);
403
405
 
404
406
  /*
405
407
  * recursive if there are `**` or path separators in the glob part.
406
408
  * Otherwise, patterns such as `src/*.js`, it doesn't need recursive.
407
409
  */
408
410
  const recursive = /\*\*|\/|\\/u.test(globPart);
409
- const selector = new Minimatch(pattern, minimatchOpts);
411
+ const selector = new Minimatch(absolutePath, minimatchOpts);
410
412
 
411
413
  debug(`recursive? ${recursive}`);
412
414
 
@@ -13,7 +13,7 @@ const { ConfigArray, ConfigArraySymbol } = require("@humanwhocodes/config-array"
13
13
  const { flatConfigSchema } = require("./flat-config-schema");
14
14
  const { RuleValidator } = require("./rule-validator");
15
15
  const { defaultConfig } = require("./default-config");
16
- const recommendedConfig = require("../../conf/eslint-recommended");
16
+ const jsPlugin = require("@eslint/js");
17
17
 
18
18
  //-----------------------------------------------------------------------------
19
19
  // Helpers
@@ -36,6 +36,45 @@ function splitPluginIdentifier(identifier) {
36
36
  };
37
37
  }
38
38
 
39
+ /**
40
+ * Returns the name of an object in the config by reading its `meta` key.
41
+ * @param {Object} object The object to check.
42
+ * @returns {string?} The name of the object if found or `null` if there
43
+ * is no name.
44
+ */
45
+ function getObjectId(object) {
46
+
47
+ // first check old-style name
48
+ let name = object.name;
49
+
50
+ if (!name) {
51
+
52
+ if (!object.meta) {
53
+ return null;
54
+ }
55
+
56
+ name = object.meta.name;
57
+
58
+ if (!name) {
59
+ return null;
60
+ }
61
+ }
62
+
63
+ // now check for old-style version
64
+ let version = object.version;
65
+
66
+ if (!version) {
67
+ version = object.meta && object.meta.version;
68
+ }
69
+
70
+ // if there's a version then append that
71
+ if (version) {
72
+ return `${name}@${version}`;
73
+ }
74
+
75
+ return name;
76
+ }
77
+
39
78
  const originalBaseConfig = Symbol("originalBaseConfig");
40
79
 
41
80
  //-----------------------------------------------------------------------------
@@ -96,17 +135,23 @@ class FlatConfigArray extends ConfigArray {
96
135
  */
97
136
  [ConfigArraySymbol.preprocessConfig](config) {
98
137
  if (config === "eslint:recommended") {
99
- return recommendedConfig;
138
+
139
+ // if we are in a Node.js environment warn the user
140
+ if (typeof process !== "undefined" && process.emitWarning) {
141
+ process.emitWarning("The 'eslint:recommended' string configuration is deprecated and will be replaced by the @eslint/js package's 'recommended' config.");
142
+ }
143
+
144
+ return jsPlugin.configs.recommended;
100
145
  }
101
146
 
102
147
  if (config === "eslint:all") {
103
148
 
104
- /*
105
- * Load `eslint-all.js` here instead of at the top level to avoid loading all rule modules
106
- * when it isn't necessary. `eslint-all.js` reads `meta` of rule objects to filter out deprecated ones,
107
- * so requiring `eslint-all.js` module loads all rule modules as a consequence.
108
- */
109
- return require("../../conf/eslint-all");
149
+ // if we are in a Node.js environment warn the user
150
+ if (typeof process !== "undefined" && process.emitWarning) {
151
+ process.emitWarning("The 'eslint:all' string configuration is deprecated and will be replaced by the @eslint/js package's 'all' config.");
152
+ }
153
+
154
+ return jsPlugin.configs.all;
110
155
  }
111
156
 
112
157
  /*
@@ -145,16 +190,25 @@ class FlatConfigArray extends ConfigArray {
145
190
 
146
191
  // Check parser value
147
192
  if (languageOptions && languageOptions.parser) {
148
- if (typeof languageOptions.parser === "string") {
149
- const { pluginName, objectName: localParserName } = splitPluginIdentifier(languageOptions.parser);
193
+ const { parser } = languageOptions;
150
194
 
151
- parserName = languageOptions.parser;
195
+ if (typeof parser === "string") {
196
+ const { pluginName, objectName: localParserName } = splitPluginIdentifier(parser);
197
+
198
+ parserName = parser;
152
199
 
153
200
  if (!plugins || !plugins[pluginName] || !plugins[pluginName].parsers || !plugins[pluginName].parsers[localParserName]) {
154
201
  throw new TypeError(`Key "parser": Could not find "${localParserName}" in plugin "${pluginName}".`);
155
202
  }
156
203
 
157
204
  languageOptions.parser = plugins[pluginName].parsers[localParserName];
205
+ } else if (typeof parser === "object") {
206
+ parserName = getObjectId(parser);
207
+
208
+ if (!parserName) {
209
+ invalidParser = true;
210
+ }
211
+
158
212
  } else {
159
213
  invalidParser = true;
160
214
  }
@@ -172,6 +226,13 @@ class FlatConfigArray extends ConfigArray {
172
226
  }
173
227
 
174
228
  config.processor = plugins[pluginName].processors[localProcessorName];
229
+ } else if (typeof processor === "object") {
230
+ processorName = getObjectId(processor);
231
+
232
+ if (!processorName) {
233
+ invalidProcessor = true;
234
+ }
235
+
175
236
  } else {
176
237
  invalidProcessor = true;
177
238
  }
@@ -185,11 +246,11 @@ class FlatConfigArray extends ConfigArray {
185
246
  value: function() {
186
247
 
187
248
  if (invalidParser) {
188
- throw new Error("Caching is not supported when parser is an object.");
249
+ throw new Error("Could not serialize parser object (missing 'meta' object).");
189
250
  }
190
251
 
191
252
  if (invalidProcessor) {
192
- throw new Error("Caching is not supported when processor is an object.");
253
+ throw new Error("Could not serialize processor object (missing 'meta' object).");
193
254
  }
194
255
 
195
256
  return {
@@ -223,7 +223,7 @@ function globMatch({ basePath, pattern }) {
223
223
  * should be thrown when a pattern is unmatched.
224
224
  * @returns {Promise<Array<string>>} An array of matching file paths
225
225
  * or an empty array if there are no matches.
226
- * @throws {UnmatchedSearchPatternsErrror} If there is a pattern that doesn't
226
+ * @throws {UnmatchedSearchPatternsError} If there is a pattern that doesn't
227
227
  * match any files.
228
228
  */
229
229
  async function globSearch({
@@ -526,9 +526,9 @@ async function findFiles({
526
526
  }
527
527
 
528
528
  // save patterns for later use based on whether globs are enabled
529
- if (globInputPaths && isGlobPattern(filePath)) {
529
+ if (globInputPaths && isGlobPattern(pattern)) {
530
530
 
531
- const basePath = globParent(filePath);
531
+ const basePath = path.resolve(cwd, globParent(pattern));
532
532
 
533
533
  // group in cwd if possible and split out others
534
534
  if (isPathInside(basePath, cwd)) {
@@ -113,6 +113,10 @@ module.exports = {
113
113
  },
114
114
  applyDefaultIgnorePatterns: {
115
115
  type: "boolean"
116
+ },
117
+ afterHashbangComment: {
118
+ type: "boolean",
119
+ default: false
116
120
  }
117
121
  },
118
122
  additionalProperties: false
@@ -449,6 +453,13 @@ module.exports = {
449
453
  before: options.beforeBlockComment
450
454
  });
451
455
  }
456
+ } else if (token.type === "Shebang") {
457
+ if (options.afterHashbangComment) {
458
+ checkForEmptyLine(token, {
459
+ after: options.afterHashbangComment,
460
+ before: false
461
+ });
462
+ }
452
463
  }
453
464
  });
454
465
  }
@@ -112,7 +112,7 @@ function isBooleanCast(expression, scope) {
112
112
  /**
113
113
  * Returns true for:
114
114
  * truthiness checks: value, Boolean(value), !!value
115
- * falsyness checks: !value, !Boolean(value)
115
+ * falsiness checks: !value, !Boolean(value)
116
116
  * nullish checks: value == null, value === undefined || value === null
117
117
  * @param {ASTNode} expression Test condition
118
118
  * @param {import('eslint-scope').Scope} scope Scope of the expression
@@ -22,7 +22,37 @@ module.exports = {
22
22
  },
23
23
 
24
24
  fixable: "whitespace",
25
- schema: [{ enum: ["starred-block", "separate-lines", "bare-block"] }],
25
+ schema: {
26
+ anyOf: [
27
+ {
28
+ type: "array",
29
+ items: [
30
+ {
31
+ enum: ["starred-block", "bare-block"]
32
+ }
33
+ ],
34
+ additionalItems: false
35
+ },
36
+ {
37
+ type: "array",
38
+ items: [
39
+ {
40
+ enum: ["separate-lines"]
41
+ },
42
+ {
43
+ type: "object",
44
+ properties: {
45
+ checkJSDoc: {
46
+ type: "boolean"
47
+ }
48
+ },
49
+ additionalProperties: false
50
+ }
51
+ ],
52
+ additionalItems: false
53
+ }
54
+ ]
55
+ },
26
56
  messages: {
27
57
  expectedBlock: "Expected a block comment instead of consecutive line comments.",
28
58
  expectedBareBlock: "Expected a block comment without padding stars.",
@@ -37,6 +67,8 @@ module.exports = {
37
67
  create(context) {
38
68
  const sourceCode = context.getSourceCode();
39
69
  const option = context.options[0] || "starred-block";
70
+ const params = context.options[1] || {};
71
+ const checkJSDoc = !!params.checkJSDoc;
40
72
 
41
73
  //----------------------------------------------------------------------
42
74
  // Helpers
@@ -333,11 +365,18 @@ module.exports = {
333
365
  "separate-lines"(commentGroup) {
334
366
  const [firstComment] = commentGroup;
335
367
 
336
- if (firstComment.type !== "Block" || isJSDocComment(commentGroup)) {
368
+ const isJSDoc = isJSDocComment(commentGroup);
369
+
370
+ if (firstComment.type !== "Block" || (!checkJSDoc && isJSDoc)) {
337
371
  return;
338
372
  }
339
373
 
340
- const commentLines = getCommentLines(commentGroup);
374
+ let commentLines = getCommentLines(commentGroup);
375
+
376
+ if (isJSDoc) {
377
+ commentLines = commentLines.slice(1, commentLines.length - 1);
378
+ }
379
+
341
380
  const tokenAfter = sourceCode.getTokenAfter(firstComment, { includeComments: true });
342
381
 
343
382
  if (tokenAfter && firstComment.loc.end.line === tokenAfter.loc.start.line) {
@@ -14,6 +14,23 @@ const NUMERIC_OR_STRING_BINARY_OPERATORS = new Set(["+", "-", "*", "/", "%", "|"
14
14
  // Helpers
15
15
  //------------------------------------------------------------------------------
16
16
 
17
+ /**
18
+ * Checks whether or not a node is `null` or `undefined`. Similar to the one
19
+ * found in ast-utils.js, but this one correctly handles the edge case that
20
+ * `undefined` has been redefined.
21
+ * @param {Scope} scope Scope in which the expression was found.
22
+ * @param {ASTNode} node A node to check.
23
+ * @returns {boolean} Whether or not the node is a `null` or `undefined`.
24
+ * @public
25
+ */
26
+ function isNullOrUndefined(scope, node) {
27
+ return (
28
+ isNullLiteral(node) ||
29
+ (node.type === "Identifier" && node.name === "undefined" && isReferenceToGlobalVariable(scope, node)) ||
30
+ (node.type === "UnaryExpression" && node.operator === "void")
31
+ );
32
+ }
33
+
17
34
  /**
18
35
  * Test if an AST node has a statically knowable constant nullishness. Meaning,
19
36
  * it will always resolve to a constant value of either: `null`, `undefined`
@@ -21,9 +38,14 @@ const NUMERIC_OR_STRING_BINARY_OPERATORS = new Set(["+", "-", "*", "/", "%", "|"
21
38
  * three states at runtime would return `false`.
22
39
  * @param {Scope} scope The scope in which the node was found.
23
40
  * @param {ASTNode} node The AST node being tested.
41
+ * @param {boolean} nonNullish if `true` then nullish values are not considered constant.
24
42
  * @returns {boolean} Does `node` have constant nullishness?
25
43
  */
26
- function hasConstantNullishness(scope, node) {
44
+ function hasConstantNullishness(scope, node, nonNullish) {
45
+ if (nonNullish && isNullOrUndefined(scope, node)) {
46
+ return false;
47
+ }
48
+
27
49
  switch (node.type) {
28
50
  case "ObjectExpression": // Objects are never nullish
29
51
  case "ArrayExpression": // Arrays are never nullish
@@ -45,9 +67,12 @@ function hasConstantNullishness(scope, node) {
45
67
  return (functionName === "Boolean" || functionName === "String" || functionName === "Number") &&
46
68
  isReferenceToGlobalVariable(scope, node.callee);
47
69
  }
70
+ case "LogicalExpression": {
71
+ return node.operator === "??" && hasConstantNullishness(scope, node.right, true);
72
+ }
48
73
  case "AssignmentExpression":
49
74
  if (node.operator === "=") {
50
- return hasConstantNullishness(scope, node.right);
75
+ return hasConstantNullishness(scope, node.right, nonNullish);
51
76
  }
52
77
 
53
78
  /*
@@ -80,7 +105,7 @@ function hasConstantNullishness(scope, node) {
80
105
  case "SequenceExpression": {
81
106
  const last = node.expressions[node.expressions.length - 1];
82
107
 
83
- return hasConstantNullishness(scope, last);
108
+ return hasConstantNullishness(scope, last, nonNullish);
84
109
  }
85
110
  case "Identifier":
86
111
  return node.name === "undefined" && isReferenceToGlobalVariable(scope, node);
@@ -348,7 +373,7 @@ function isAlwaysNew(scope, node) {
348
373
  * user-defined constructors could return a sentinel
349
374
  * object.
350
375
  *
351
- * Catching these is especially useful for primitive constructures
376
+ * Catching these is especially useful for primitive constructors
352
377
  * which return boxed values, a surprising gotcha' in JavaScript.
353
378
  */
354
379
  return Object.hasOwnProperty.call(globals.builtin, node.callee.name) &&
@@ -378,24 +403,6 @@ function isAlwaysNew(scope, node) {
378
403
  }
379
404
  }
380
405
 
381
- /**
382
- * Checks whether or not a node is `null` or `undefined`. Similar to the one
383
- * found in ast-utils.js, but this one correctly handles the edge case that
384
- * `undefined` has been redefined.
385
- * @param {Scope} scope Scope in which the expression was found.
386
- * @param {ASTNode} node A node to check.
387
- * @returns {boolean} Whether or not the node is a `null` or `undefined`.
388
- * @public
389
- */
390
- function isNullOrUndefined(scope, node) {
391
- return (
392
- isNullLiteral(node) ||
393
- (node.type === "Identifier" && node.name === "undefined" && isReferenceToGlobalVariable(scope, node)) ||
394
- (node.type === "UnaryExpression" && node.operator === "void")
395
- );
396
- }
397
-
398
-
399
406
  /**
400
407
  * Checks if one operand will cause the result to be constant.
401
408
  * @param {Scope} scope Scope in which the expression was found.
@@ -407,14 +414,14 @@ function isNullOrUndefined(scope, node) {
407
414
  function findBinaryExpressionConstantOperand(scope, a, b, operator) {
408
415
  if (operator === "==" || operator === "!=") {
409
416
  if (
410
- (isNullOrUndefined(scope, a) && hasConstantNullishness(scope, b)) ||
417
+ (isNullOrUndefined(scope, a) && hasConstantNullishness(scope, b, false)) ||
411
418
  (isStaticBoolean(scope, a) && hasConstantLooseBooleanComparison(scope, b))
412
419
  ) {
413
420
  return b;
414
421
  }
415
422
  } else if (operator === "===" || operator === "!==") {
416
423
  if (
417
- (isNullOrUndefined(scope, a) && hasConstantNullishness(scope, b)) ||
424
+ (isNullOrUndefined(scope, a) && hasConstantNullishness(scope, b, false)) ||
418
425
  (isStaticBoolean(scope, a) && hasConstantStrictBooleanComparison(scope, b))
419
426
  ) {
420
427
  return b;
@@ -453,7 +460,7 @@ module.exports = {
453
460
 
454
461
  if ((operator === "&&" || operator === "||") && isConstant(scope, left, true)) {
455
462
  context.report({ node: left, messageId: "constantShortCircuit", data: { property: "truthiness", operator } });
456
- } else if (operator === "??" && hasConstantNullishness(scope, left)) {
463
+ } else if (operator === "??" && hasConstantNullishness(scope, left, false)) {
457
464
  context.report({ node: left, messageId: "constantShortCircuit", data: { property: "nullishness", operator } });
458
465
  }
459
466
  },
@@ -5,7 +5,7 @@
5
5
 
6
6
  "use strict";
7
7
 
8
- const RegExpValidator = require("regexpp").RegExpValidator;
8
+ const RegExpValidator = require("@eslint-community/regexpp").RegExpValidator;
9
9
  const collector = new (class {
10
10
  constructor() {
11
11
  this._source = "";
@@ -72,7 +72,7 @@ module.exports = {
72
72
  let funcInfo = null;
73
73
 
74
74
  /**
75
- * Pushs a `this` scope (non-arrow function, class static block, or class field initializer) information to the stack.
75
+ * Pushes a `this` scope (non-arrow function, class static block, or class field initializer) information to the stack.
76
76
  * Top-level scopes are handled separately.
77
77
  *
78
78
  * This is used in order to check whether or not `this` binding is a
@@ -10,7 +10,7 @@
10
10
  //------------------------------------------------------------------------------
11
11
 
12
12
  const astUtils = require("./utils/ast-utils");
13
- const eslintUtils = require("eslint-utils");
13
+ const eslintUtils = require("@eslint-community/eslint-utils");
14
14
 
15
15
  const precedence = astUtils.getPrecedence;
16
16
 
@@ -8,7 +8,7 @@
8
8
  // Rule Definition
9
9
  //------------------------------------------------------------------------------
10
10
 
11
- const { isParenthesized: isParenthesizedRaw } = require("eslint-utils");
11
+ const { isParenthesized: isParenthesizedRaw } = require("@eslint-community/eslint-utils");
12
12
  const astUtils = require("./utils/ast-utils.js");
13
13
 
14
14
  /** @type {import('../shared/types').Rule} */
@@ -10,7 +10,7 @@
10
10
  //------------------------------------------------------------------------------
11
11
 
12
12
  const astUtils = require("./utils/ast-utils");
13
- const { getStaticValue } = require("eslint-utils");
13
+ const { getStaticValue } = require("@eslint-community/eslint-utils");
14
14
 
15
15
  //------------------------------------------------------------------------------
16
16
  // Rule Definition
@@ -9,7 +9,7 @@
9
9
  // Helpers
10
10
  //------------------------------------------------------------------------------
11
11
 
12
- const { findVariable } = require("eslint-utils");
12
+ const { findVariable } = require("@eslint-community/eslint-utils");
13
13
  const astUtils = require("./utils/ast-utils");
14
14
 
15
15
  const WellKnownMutationFunctions = {
@@ -8,7 +8,7 @@
8
8
  // Requirements
9
9
  //------------------------------------------------------------------------------
10
10
 
11
- const RegExpValidator = require("regexpp").RegExpValidator;
11
+ const RegExpValidator = require("@eslint-community/regexpp").RegExpValidator;
12
12
  const validator = new RegExpValidator();
13
13
  const validFlags = /[dgimsuy]/gu;
14
14
  const undefined1 = void 0;
@@ -3,8 +3,8 @@
3
3
  */
4
4
  "use strict";
5
5
 
6
- const { CALL, CONSTRUCT, ReferenceTracker, getStringIfConstant } = require("eslint-utils");
7
- const { RegExpValidator, RegExpParser, visitRegExpAST } = require("regexpp");
6
+ const { CALL, CONSTRUCT, ReferenceTracker, getStringIfConstant } = require("@eslint-community/eslint-utils");
7
+ const { RegExpValidator, RegExpParser, visitRegExpAST } = require("@eslint-community/regexpp");
8
8
  const { isCombiningCharacter, isEmojiModifier, isRegionalIndicatorSymbol, isSurrogatePair } = require("./utils/unicode");
9
9
  const astUtils = require("./utils/ast-utils.js");
10
10
 
@@ -9,7 +9,7 @@
9
9
  // Requirements
10
10
  //------------------------------------------------------------------------------
11
11
 
12
- const { CALL, CONSTRUCT, ReferenceTracker } = require("eslint-utils");
12
+ const { CALL, CONSTRUCT, ReferenceTracker } = require("@eslint-community/eslint-utils");
13
13
  const getPropertyName = require("./utils/ast-utils").getStaticPropertyName;
14
14
 
15
15
  //------------------------------------------------------------------------------
@@ -9,7 +9,7 @@
9
9
  // Requirements
10
10
  //------------------------------------------------------------------------------
11
11
 
12
- const { findVariable } = require("eslint-utils");
12
+ const { findVariable } = require("@eslint-community/eslint-utils");
13
13
 
14
14
  //------------------------------------------------------------------------------
15
15
  // Helpers
@@ -10,7 +10,7 @@
10
10
  //------------------------------------------------------------------------------
11
11
 
12
12
  const astUtils = require("./utils/ast-utils");
13
- const regexpp = require("regexpp");
13
+ const regexpp = require("@eslint-community/regexpp");
14
14
 
15
15
  //------------------------------------------------------------------------------
16
16
  // Helpers
@@ -10,7 +10,7 @@
10
10
  //------------------------------------------------------------------------------
11
11
 
12
12
  const astUtils = require("./utils/ast-utils");
13
- const { findVariable } = require("eslint-utils");
13
+ const { findVariable } = require("@eslint-community/eslint-utils");
14
14
 
15
15
  //------------------------------------------------------------------------------
16
16
  // Helpers
@@ -9,8 +9,8 @@
9
9
  // Requirements
10
10
  //------------------------------------------------------------------------------
11
11
 
12
- const { CALL, CONSTRUCT, ReferenceTracker, getStringIfConstant } = require("eslint-utils");
13
- const { RegExpParser, visitRegExpAST } = require("regexpp");
12
+ const { CALL, CONSTRUCT, ReferenceTracker, getStringIfConstant } = require("@eslint-community/eslint-utils");
13
+ const { RegExpParser, visitRegExpAST } = require("@eslint-community/regexpp");
14
14
 
15
15
  //------------------------------------------------------------------------------
16
16
  // Helpers
@@ -197,7 +197,7 @@ module.exports = {
197
197
 
198
198
  return {
199
199
 
200
- // Makes and pushs a new scope information.
200
+ // Makes and pushes a new scope information.
201
201
  onCodePathStart(codePath) {
202
202
  scopeInfo = {
203
203
  upper: scopeInfo,
@@ -10,7 +10,7 @@
10
10
  //------------------------------------------------------------------------------
11
11
 
12
12
  const astUtils = require("./utils/ast-utils");
13
- const { CALL, ReferenceTracker } = require("eslint-utils");
13
+ const { CALL, ReferenceTracker } = require("@eslint-community/eslint-utils");
14
14
 
15
15
  //------------------------------------------------------------------------------
16
16
  // Helpers
@@ -14,8 +14,8 @@ const {
14
14
  CONSTRUCT,
15
15
  ReferenceTracker,
16
16
  getStringIfConstant
17
- } = require("eslint-utils");
18
- const regexpp = require("regexpp");
17
+ } = require("@eslint-community/eslint-utils");
18
+ const regexpp = require("@eslint-community/regexpp");
19
19
 
20
20
  //------------------------------------------------------------------------------
21
21
  // Helpers
@@ -6,7 +6,7 @@
6
6
 
7
7
  "use strict";
8
8
 
9
- const { CALL, ReferenceTracker } = require("eslint-utils");
9
+ const { CALL, ReferenceTracker } = require("@eslint-community/eslint-utils");
10
10
  const {
11
11
  isCommaToken,
12
12
  isOpeningParenToken,
@@ -10,8 +10,8 @@
10
10
  //------------------------------------------------------------------------------
11
11
 
12
12
  const astUtils = require("./utils/ast-utils");
13
- const { CALL, CONSTRUCT, ReferenceTracker, findVariable } = require("eslint-utils");
14
- const { RegExpValidator, visitRegExpAST, RegExpParser } = require("regexpp");
13
+ const { CALL, CONSTRUCT, ReferenceTracker, findVariable } = require("@eslint-community/eslint-utils");
14
+ const { RegExpValidator, visitRegExpAST, RegExpParser } = require("@eslint-community/regexpp");
15
15
  const { canTokensBeAdjacent } = require("./utils/ast-utils");
16
16
 
17
17
  //------------------------------------------------------------------------------
@@ -14,7 +14,7 @@ const {
14
14
  CONSTRUCT,
15
15
  ReferenceTracker,
16
16
  getStringIfConstant
17
- } = require("eslint-utils");
17
+ } = require("@eslint-community/eslint-utils");
18
18
 
19
19
  //------------------------------------------------------------------------------
20
20
  // Rule Definition
@@ -10,7 +10,7 @@
10
10
  //------------------------------------------------------------------------------
11
11
 
12
12
  const astUtils = require("./utils/ast-utils");
13
- const eslintUtils = require("eslint-utils");
13
+ const eslintUtils = require("@eslint-community/eslint-utils");
14
14
 
15
15
  //----------------------------------------------------------------------
16
16
  // Helpers
@@ -9,7 +9,7 @@
9
9
  //------------------------------------------------------------------------------
10
10
 
11
11
  const
12
- { isCommentToken } = require("eslint-utils"),
12
+ { isCommentToken } = require("@eslint-community/eslint-utils"),
13
13
  TokenStore = require("./token-store"),
14
14
  astUtils = require("../shared/ast-utils"),
15
15
  Traverser = require("../shared/traverser");
@@ -9,7 +9,7 @@
9
9
  //------------------------------------------------------------------------------
10
10
 
11
11
  const assert = require("assert");
12
- const { isCommentToken } = require("eslint-utils");
12
+ const { isCommentToken } = require("@eslint-community/eslint-utils");
13
13
  const cursors = require("./cursors");
14
14
  const ForwardTokenCursor = require("./forward-token-cursor");
15
15
  const PaddedTokenCursor = require("./padded-token-cursor");
@@ -10,6 +10,6 @@ ESLint couldn't find a configuration file. To set up a configuration file for th
10
10
 
11
11
  ESLint looked for configuration files in ${directoryPath} and its ancestors. If it found none, it then looked in your home directory.
12
12
 
13
- If you think you already have a configuration file or if you need more help, please stop by the ESLint chat room: https://eslint.org/chat/help
13
+ If you think you already have a configuration file or if you need more help, please stop by the ESLint Discord server: https://eslint.org/chat
14
14
  `.trimStart();
15
15
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint",
3
- "version": "8.34.0",
3
+ "version": "8.36.0",
4
4
  "author": "Nicholas C. Zakas <nicholas+npm@nczconsulting.com>",
5
5
  "description": "An AST-based pattern checker for JavaScript.",
6
6
  "bin": {
@@ -37,6 +37,10 @@
37
37
  "lint-staged": {
38
38
  "*.js": "eslint --fix",
39
39
  "*.md": "markdownlint --fix",
40
+ "lib/rules/*.js": [
41
+ "node tools/update-eslint-all.js",
42
+ "git add packages/js/src/configs/eslint-all.js"
43
+ ],
40
44
  "docs/src/rules/*.md": [
41
45
  "node tools/fetch-docs-links.js",
42
46
  "git add docs/src/_data/further_reading_links.json"
@@ -56,7 +60,10 @@
56
60
  "homepage": "https://eslint.org",
57
61
  "bugs": "https://github.com/eslint/eslint/issues/",
58
62
  "dependencies": {
59
- "@eslint/eslintrc": "^1.4.1",
63
+ "@eslint-community/eslint-utils": "^4.2.0",
64
+ "@eslint-community/regexpp": "^4.4.0",
65
+ "@eslint/eslintrc": "^2.0.1",
66
+ "@eslint/js": "8.36.0",
60
67
  "@humanwhocodes/config-array": "^0.11.8",
61
68
  "@humanwhocodes/module-importer": "^1.0.1",
62
69
  "@nodelib/fs.walk": "^1.2.8",
@@ -67,10 +74,9 @@
67
74
  "doctrine": "^3.0.0",
68
75
  "escape-string-regexp": "^4.0.0",
69
76
  "eslint-scope": "^7.1.1",
70
- "eslint-utils": "^3.0.0",
71
77
  "eslint-visitor-keys": "^3.3.0",
72
- "espree": "^9.4.0",
73
- "esquery": "^1.4.0",
78
+ "espree": "^9.5.0",
79
+ "esquery": "^1.4.2",
74
80
  "esutils": "^2.0.2",
75
81
  "fast-deep-equal": "^3.1.3",
76
82
  "file-entry-cache": "^6.0.1",
@@ -91,7 +97,6 @@
91
97
  "minimatch": "^3.1.2",
92
98
  "natural-compare": "^1.4.0",
93
99
  "optionator": "^0.9.1",
94
- "regexpp": "^3.2.0",
95
100
  "strip-ansi": "^6.0.1",
96
101
  "strip-json-comments": "^3.1.0",
97
102
  "text-table": "^0.2.0"
@@ -1,31 +0,0 @@
1
- /**
2
- * @fileoverview Config to enable all rules.
3
- * @author Robert Fletcher
4
- */
5
-
6
- "use strict";
7
-
8
- //------------------------------------------------------------------------------
9
- // Requirements
10
- //------------------------------------------------------------------------------
11
-
12
- const builtInRules = require("../lib/rules");
13
-
14
- //------------------------------------------------------------------------------
15
- // Helpers
16
- //------------------------------------------------------------------------------
17
-
18
- const allRules = {};
19
-
20
- for (const [ruleId, rule] of builtInRules) {
21
- if (!rule.meta.deprecated) {
22
- allRules[ruleId] = "error";
23
- }
24
- }
25
-
26
- //------------------------------------------------------------------------------
27
- // Public Interface
28
- //------------------------------------------------------------------------------
29
-
30
- /** @type {import("../lib/shared/types").ConfigData} */
31
- module.exports = { rules: allRules };
@@ -1,76 +0,0 @@
1
- /**
2
- * @fileoverview Configuration applied when a user configuration extends from
3
- * eslint:recommended.
4
- * @author Nicholas C. Zakas
5
- */
6
-
7
- "use strict";
8
-
9
- /* eslint sort-keys: ["error", "asc"] -- Long, so make more readable */
10
-
11
- /** @type {import("../lib/shared/types").ConfigData} */
12
- module.exports = {
13
- rules: {
14
- "constructor-super": "error",
15
- "for-direction": "error",
16
- "getter-return": "error",
17
- "no-async-promise-executor": "error",
18
- "no-case-declarations": "error",
19
- "no-class-assign": "error",
20
- "no-compare-neg-zero": "error",
21
- "no-cond-assign": "error",
22
- "no-const-assign": "error",
23
- "no-constant-condition": "error",
24
- "no-control-regex": "error",
25
- "no-debugger": "error",
26
- "no-delete-var": "error",
27
- "no-dupe-args": "error",
28
- "no-dupe-class-members": "error",
29
- "no-dupe-else-if": "error",
30
- "no-dupe-keys": "error",
31
- "no-duplicate-case": "error",
32
- "no-empty": "error",
33
- "no-empty-character-class": "error",
34
- "no-empty-pattern": "error",
35
- "no-ex-assign": "error",
36
- "no-extra-boolean-cast": "error",
37
- "no-extra-semi": "error",
38
- "no-fallthrough": "error",
39
- "no-func-assign": "error",
40
- "no-global-assign": "error",
41
- "no-import-assign": "error",
42
- "no-inner-declarations": "error",
43
- "no-invalid-regexp": "error",
44
- "no-irregular-whitespace": "error",
45
- "no-loss-of-precision": "error",
46
- "no-misleading-character-class": "error",
47
- "no-mixed-spaces-and-tabs": "error",
48
- "no-new-symbol": "error",
49
- "no-nonoctal-decimal-escape": "error",
50
- "no-obj-calls": "error",
51
- "no-octal": "error",
52
- "no-prototype-builtins": "error",
53
- "no-redeclare": "error",
54
- "no-regex-spaces": "error",
55
- "no-self-assign": "error",
56
- "no-setter-return": "error",
57
- "no-shadow-restricted-names": "error",
58
- "no-sparse-arrays": "error",
59
- "no-this-before-super": "error",
60
- "no-undef": "error",
61
- "no-unexpected-multiline": "error",
62
- "no-unreachable": "error",
63
- "no-unsafe-finally": "error",
64
- "no-unsafe-negation": "error",
65
- "no-unsafe-optional-chaining": "error",
66
- "no-unused-labels": "error",
67
- "no-unused-vars": "error",
68
- "no-useless-backreference": "error",
69
- "no-useless-catch": "error",
70
- "no-useless-escape": "error",
71
- "no-with": "error",
72
- "require-yield": "error",
73
- "use-isnan": "error",
74
- "valid-typeof": "error"
75
- }
76
- };