eslint 9.12.0 → 9.14.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.
@@ -421,20 +421,19 @@ async function globMultiSearch({ searches, configLoader, errorOnUnmatchedPattern
421
421
  )
422
422
  );
423
423
 
424
- const filePaths = [];
425
-
424
+ /*
425
+ * The first loop handles errors from the glob searches. Since we can't
426
+ * use `await` inside `flatMap`, we process errors separately in this loop.
427
+ * This results in two iterations over `results`, but since the length is
428
+ * less than or equal to the number of globs and directories passed on the
429
+ * command line, the performance impact should be minimal.
430
+ */
426
431
  for (let i = 0; i < results.length; i++) {
427
432
 
428
433
  const result = results[i];
429
434
  const currentSearch = normalizedSearches[i];
430
435
 
431
436
  if (result.status === "fulfilled") {
432
-
433
- // if the search was successful just add the results
434
- if (result.value.length > 0) {
435
- filePaths.push(...result.value);
436
- }
437
-
438
437
  continue;
439
438
  }
440
439
 
@@ -457,7 +456,8 @@ async function globMultiSearch({ searches, configLoader, errorOnUnmatchedPattern
457
456
 
458
457
  }
459
458
 
460
- return filePaths;
459
+ // second loop for `fulfulled` results
460
+ return results.flatMap(result => result.value);
461
461
 
462
462
  }
463
463
 
@@ -15,6 +15,7 @@ const path = require("node:path");
15
15
  const { version } = require("../../package.json");
16
16
  const { Linter } = require("../linter");
17
17
  const { getRuleFromConfig } = require("../config/flat-config-helpers");
18
+ const { defaultConfig } = require("../config/default-config");
18
19
  const {
19
20
  Legacy: {
20
21
  ConfigOps: {
@@ -52,6 +53,7 @@ const { ConfigLoader, LegacyConfigLoader } = require("../config/config-loader");
52
53
  //------------------------------------------------------------------------------
53
54
 
54
55
  // For VSCode IntelliSense
56
+ /** @typedef {import("../cli-engine/cli-engine").ConfigArray} ConfigArray */
55
57
  /** @typedef {import("../shared/types").ConfigData} ConfigData */
56
58
  /** @typedef {import("../shared/types").DeprecatedRuleInfo} DeprecatedRuleInfo */
57
59
  /** @typedef {import("../shared/types").LintMessage} LintMessage */
@@ -522,6 +524,15 @@ class ESLint {
522
524
  return version;
523
525
  }
524
526
 
527
+ /**
528
+ * The default configuration that ESLint uses internally. This is provided for tooling that wants to calculate configurations using the same defaults as ESLint.
529
+ * Keep in mind that the default configuration may change from version to version, so you shouldn't rely on any particular keys or values to be present.
530
+ * @type {ConfigArray}
531
+ */
532
+ static get defaultConfig() {
533
+ return defaultConfig;
534
+ }
535
+
525
536
  /**
526
537
  * Outputs fixes from the given results to files.
527
538
  * @param {LintResult[]} results The lint results.
@@ -735,7 +746,7 @@ class ESLint {
735
746
  });
736
747
  const controller = new AbortController();
737
748
  const retryCodes = new Set(["ENFILE", "EMFILE"]);
738
- const retrier = new Retrier(error => retryCodes.has(error.code));
749
+ const retrier = new Retrier(error => retryCodes.has(error.code), { concurrency: 100 });
739
750
 
740
751
  debug(`${filePaths.length} files found in: ${Date.now() - startTime}ms`);
741
752
 
@@ -819,7 +830,7 @@ class ESLint {
819
830
  }
820
831
 
821
832
  return result;
822
- }))
833
+ }), { signal: controller.signal })
823
834
  .catch(error => {
824
835
  controller.abort(error);
825
836
  throw error;
@@ -12,6 +12,7 @@
12
12
  const { SourceCode } = require("./source-code");
13
13
  const createDebug = require("debug");
14
14
  const astUtils = require("../../shared/ast-utils");
15
+ const espree = require("espree");
15
16
  const eslintScope = require("eslint-scope");
16
17
  const evk = require("eslint-visitor-keys");
17
18
  const { validateLanguageOptions } = require("./validate-language-options");
@@ -69,6 +70,13 @@ module.exports = {
69
70
  nodeTypeKey: "type",
70
71
  visitorKeys: evk.KEYS,
71
72
 
73
+ defaultLanguageOptions: {
74
+ sourceType: "module",
75
+ ecmaVersion: "latest",
76
+ parser: espree,
77
+ parserOptions: {}
78
+ },
79
+
72
80
  validateLanguageOptions,
73
81
 
74
82
  /**
@@ -1643,29 +1643,26 @@ class Linter {
1643
1643
  const options = normalizeVerifyOptions(providedOptions, config);
1644
1644
  const languageOptions = config.languageOptions;
1645
1645
 
1646
- languageOptions.ecmaVersion = normalizeEcmaVersionForLanguageOptions(
1647
- languageOptions.ecmaVersion
1648
- );
1649
-
1650
- // double check that there is a parser to avoid mysterious error messages
1651
- if (!languageOptions.parser) {
1652
- throw new TypeError(`No parser specified for ${options.filename}`);
1653
- }
1646
+ if (config.language === jslang) {
1647
+ languageOptions.ecmaVersion = normalizeEcmaVersionForLanguageOptions(
1648
+ languageOptions.ecmaVersion
1649
+ );
1654
1650
 
1655
- // Espree expects this information to be passed in
1656
- if (isEspree(languageOptions.parser)) {
1657
- const parserOptions = languageOptions.parserOptions;
1651
+ // Espree expects this information to be passed in
1652
+ if (isEspree(languageOptions.parser)) {
1653
+ const parserOptions = languageOptions.parserOptions;
1658
1654
 
1659
- if (languageOptions.sourceType) {
1655
+ if (languageOptions.sourceType) {
1660
1656
 
1661
- parserOptions.sourceType = languageOptions.sourceType;
1657
+ parserOptions.sourceType = languageOptions.sourceType;
1662
1658
 
1663
- if (
1664
- parserOptions.sourceType === "module" &&
1665
- parserOptions.ecmaFeatures &&
1666
- parserOptions.ecmaFeatures.globalReturn
1667
- ) {
1668
- parserOptions.ecmaFeatures.globalReturn = false;
1659
+ if (
1660
+ parserOptions.sourceType === "module" &&
1661
+ parserOptions.ecmaFeatures &&
1662
+ parserOptions.ecmaFeatures.globalReturn
1663
+ ) {
1664
+ parserOptions.ecmaFeatures.globalReturn = false;
1665
+ }
1669
1666
  }
1670
1667
  }
1671
1668
  }
@@ -30,6 +30,7 @@ const parserSymbol = Symbol.for("eslint.RuleTester.parser");
30
30
  const { ConfigArraySymbol } = require("@eslint/config-array");
31
31
  const { isSerializable } = require("../shared/serialization");
32
32
 
33
+ const jslang = require("../languages/js");
33
34
  const { SourceCode } = require("../languages/js/source-code");
34
35
 
35
36
  //------------------------------------------------------------------------------
@@ -619,10 +620,7 @@ class RuleTester {
619
620
  }
620
621
  }
621
622
  },
622
- language: defaultConfig[0].language,
623
- languageOptions: {
624
- ...defaultConfig[0].languageOptions
625
- }
623
+ language: defaultConfig[0].language
626
624
  },
627
625
  ...defaultConfig.slice(1)
628
626
  ];
@@ -673,7 +671,10 @@ class RuleTester {
673
671
  const calculatedConfig = proto[ConfigArraySymbol.finalizeConfig].apply(this, args);
674
672
 
675
673
  // wrap the parser to catch start/end property access
676
- calculatedConfig.languageOptions.parser = wrapParser(calculatedConfig.languageOptions.parser);
674
+ if (calculatedConfig.language === jslang) {
675
+ calculatedConfig.languageOptions.parser = wrapParser(calculatedConfig.languageOptions.parser);
676
+ }
677
+
677
678
  return calculatedConfig;
678
679
  };
679
680
 
@@ -694,17 +695,6 @@ class RuleTester {
694
695
  delete itemConfig[parameter];
695
696
  }
696
697
 
697
- // wrap any parsers
698
- if (itemConfig.languageOptions && itemConfig.languageOptions.parser) {
699
-
700
- const parser = itemConfig.languageOptions.parser;
701
-
702
- if (parser && typeof parser !== "object") {
703
- throw new Error("Parser must be an object with a parse() or parseForESLint() method.");
704
- }
705
-
706
- }
707
-
708
698
  /*
709
699
  * Create the config object from the tester config and this item
710
700
  * specific configurations.
@@ -238,6 +238,13 @@ module.exports = {
238
238
  return;
239
239
  }
240
240
 
241
+ /*
242
+ * Import attribute keys are always ignored
243
+ */
244
+ if (astUtils.isImportAttributeKey(node)) {
245
+ return;
246
+ }
247
+
241
248
  report(node);
242
249
  }
243
250
 
@@ -272,7 +279,7 @@ module.exports = {
272
279
  for (const reference of scope.through) {
273
280
  const id = reference.identifier;
274
281
 
275
- if (isGoodName(id.name)) {
282
+ if (isGoodName(id.name) || astUtils.isImportAttributeKey(id)) {
276
283
  continue;
277
284
  }
278
285
 
@@ -326,7 +333,7 @@ module.exports = {
326
333
  "MethodDefinition > PrivateIdentifier.key",
327
334
  "PropertyDefinition > PrivateIdentifier.key"
328
335
  ]](node) {
329
- if (properties === "never" || isGoodName(node.name)) {
336
+ if (properties === "never" || astUtils.isImportAttributeKey(node) || isGoodName(node.name)) {
330
337
  return;
331
338
  }
332
339
  report(node);
@@ -6,6 +6,12 @@
6
6
 
7
7
  "use strict";
8
8
 
9
+ //------------------------------------------------------------------------------
10
+ // Requirements
11
+ //------------------------------------------------------------------------------
12
+
13
+ const astUtils = require("./utils/ast-utils");
14
+
9
15
  //------------------------------------------------------------------------------
10
16
  // Helpers
11
17
  //------------------------------------------------------------------------------
@@ -154,6 +160,12 @@ module.exports = {
154
160
  * @returns {boolean} `true` if the node should be checked.
155
161
  */
156
162
  function shouldCheck(node) {
163
+
164
+ // Import attributes are defined by environments, so naming conventions shouldn't apply to them
165
+ if (astUtils.isImportAttributeKey(node)) {
166
+ return false;
167
+ }
168
+
157
169
  const parent = node.parent;
158
170
 
159
171
  /*
@@ -11,7 +11,7 @@
11
11
  //------------------------------------------------------------------------------
12
12
 
13
13
  const { getGraphemeCount } = require("../shared/string-utils");
14
- const { getModuleExportName } = require("./utils/ast-utils");
14
+ const { getModuleExportName, isImportAttributeKey } = require("./utils/ast-utils");
15
15
 
16
16
  //------------------------------------------------------------------------------
17
17
  // Rule Definition
@@ -115,7 +115,7 @@ module.exports = {
115
115
  isKeyAndValueSame && parent.key === node && properties
116
116
  );
117
117
  }
118
- return properties && !parent.computed && parent.key.name === node.name;
118
+ return properties && !isImportAttributeKey(node) && !parent.computed && parent.key.name === node.name;
119
119
  },
120
120
  ImportSpecifier(parent, node) {
121
121
  return (
@@ -5,6 +5,12 @@
5
5
 
6
6
  "use strict";
7
7
 
8
+ //------------------------------------------------------------------------------
9
+ // Requirements
10
+ //------------------------------------------------------------------------------
11
+
12
+ const astUtils = require("./utils/ast-utils");
13
+
8
14
  //------------------------------------------------------------------------------
9
15
  // Rule Definition
10
16
  //------------------------------------------------------------------------------
@@ -180,7 +186,7 @@ module.exports = {
180
186
  parent = node.parent,
181
187
  effectiveParent = (parent.type === "MemberExpression") ? parent.parent : parent;
182
188
 
183
- if (isReferenceToGlobalVariable(node)) {
189
+ if (isReferenceToGlobalVariable(node) || astUtils.isImportAttributeKey(node)) {
184
190
  return;
185
191
  }
186
192
 
@@ -1054,7 +1054,7 @@ let needsPrecedingSemicolon;
1054
1054
  {
1055
1055
  const BREAK_OR_CONTINUE = new Set(["BreakStatement", "ContinueStatement"]);
1056
1056
 
1057
- // Declaration types that must contain a string Literal node at the end.
1057
+ // Declaration types that cannot be continued by a punctuator when ending with a string Literal that is a direct child.
1058
1058
  const DECLARATIONS = new Set(["ExportAllDeclaration", "ExportNamedDeclaration", "ImportDeclaration"]);
1059
1059
 
1060
1060
  const IDENTIFIER_OR_KEYWORD = new Set(["Identifier", "Keyword"]);
@@ -1132,6 +1132,48 @@ let needsPrecedingSemicolon;
1132
1132
  };
1133
1133
  }
1134
1134
 
1135
+ /**
1136
+ * Checks if a node is used as an import attribute key, either in a static or dynamic import.
1137
+ * @param {ASTNode} node The node to check.
1138
+ * @returns {boolean} Whether the node is used as an import attribute key.
1139
+ */
1140
+ function isImportAttributeKey(node) {
1141
+ const { parent } = node;
1142
+
1143
+ // static import/re-export
1144
+ if (parent.type === "ImportAttribute" && parent.key === node) {
1145
+ return true;
1146
+ }
1147
+
1148
+ // dynamic import
1149
+ if (
1150
+ parent.type === "Property" &&
1151
+ !parent.computed &&
1152
+ (parent.key === node || parent.value === node && parent.shorthand && !parent.method) &&
1153
+ parent.parent.type === "ObjectExpression"
1154
+ ) {
1155
+ const objectExpression = parent.parent;
1156
+ const objectExpressionParent = objectExpression.parent;
1157
+
1158
+ if (
1159
+ objectExpressionParent.type === "ImportExpression" &&
1160
+ objectExpressionParent.options === objectExpression
1161
+ ) {
1162
+ return true;
1163
+ }
1164
+
1165
+ // nested key
1166
+ if (
1167
+ objectExpressionParent.type === "Property" &&
1168
+ objectExpressionParent.value === objectExpression
1169
+ ) {
1170
+ return isImportAttributeKey(objectExpressionParent.key);
1171
+ }
1172
+ }
1173
+
1174
+ return false;
1175
+ }
1176
+
1135
1177
  //------------------------------------------------------------------------------
1136
1178
  // Public Interface
1137
1179
  //------------------------------------------------------------------------------
@@ -2288,5 +2330,6 @@ module.exports = {
2288
2330
  isTopLevelExpressionStatement,
2289
2331
  isDirective,
2290
2332
  isStartOfExpressionStatement,
2291
- needsPrecedingSemicolon
2333
+ needsPrecedingSemicolon,
2334
+ isImportAttributeKey
2292
2335
  };
@@ -1179,6 +1179,9 @@ export namespace Linter {
1179
1179
  ruleId: string | null;
1180
1180
  message: string;
1181
1181
  messageId?: string | undefined;
1182
+ /**
1183
+ * @deprecated `nodeType` is deprecated and will be removed in the next major version.
1184
+ */
1182
1185
  nodeType?: string | undefined;
1183
1186
  fatal?: true | undefined;
1184
1187
  severity: Exclude<Severity, 0>;
@@ -1396,6 +1399,12 @@ export class ESLint {
1396
1399
 
1397
1400
  static readonly version: string;
1398
1401
 
1402
+ /**
1403
+ * The default configuration that ESLint uses internally. This is provided for tooling that wants to calculate configurations using the same defaults as ESLint.
1404
+ * Keep in mind that the default configuration may change from version to version, so you shouldn't rely on any particular keys or values to be present.
1405
+ */
1406
+ static readonly defaultConfig: Linter.Config[];
1407
+
1399
1408
  static outputFixes(results: ESLint.LintResult[]): Promise<void>;
1400
1409
 
1401
1410
  static getErrorResults(results: ESLint.LintResult[]): ESLint.LintResult[];
@@ -1655,6 +1664,9 @@ export namespace RuleTester {
1655
1664
  interface TestCaseError {
1656
1665
  message?: string | RegExp;
1657
1666
  messageId?: string;
1667
+ /**
1668
+ * @deprecated `type` is deprecated and will be removed in the next major version.
1669
+ */
1658
1670
  type?: string | undefined;
1659
1671
  data?: any;
1660
1672
  line?: number | undefined;
@@ -118,6 +118,11 @@ export interface BestPractices extends Linter.RulesRecord {
118
118
  * @default 20
119
119
  */
120
120
  maximum: number;
121
+ /**
122
+ * @default "classic"
123
+ * @since 9.12.0
124
+ */
125
+ variant: "classic" | "modified";
121
126
  }>
122
127
  | number,
123
128
  ]
@@ -185,6 +190,7 @@ export interface BestPractices extends Linter.RulesRecord {
185
190
  * Rule to enforce consistent newlines before and after dots.
186
191
  *
187
192
  * @since 0.21.0
193
+ * @deprecated since 8.53.0, please use the [corresponding rule](https://eslint.style/rules/js/dot-location) in `@stylistic/eslint-plugin-js`.
188
194
  * @see https://eslint.org/docs/rules/dot-location
189
195
  */
190
196
  "dot-location": Linter.RuleEntry<["object" | "property"]>;
@@ -417,6 +423,10 @@ export interface BestPractices extends Linter.RulesRecord {
417
423
  * @default false
418
424
  */
419
425
  allowEmptyCase: boolean;
426
+ /**
427
+ * @default false
428
+ */
429
+ reportUnusedFallthroughComment: boolean;
420
430
  }>,
421
431
  ]
422
432
  >;
@@ -425,6 +435,7 @@ export interface BestPractices extends Linter.RulesRecord {
425
435
  * Rule to disallow leading or trailing decimal points in numeric literals.
426
436
  *
427
437
  * @since 0.0.6
438
+ * @deprecated since 8.53.0, please use the [corresponding rule](https://eslint.style/rules/js/no-floating-decimal) in `@stylistic/eslint-plugin-js`.
428
439
  * @see https://eslint.org/docs/rules/no-floating-decimal
429
440
  */
430
441
  "no-floating-decimal": Linter.RuleEntry<[]>;
@@ -601,6 +612,7 @@ export interface BestPractices extends Linter.RulesRecord {
601
612
  * Rule to disallow multiple spaces.
602
613
  *
603
614
  * @since 0.9.0
615
+ * @deprecated since 8.53.0, please use the [corresponding rule](https://eslint.style/rules/js/no-multi-spaces) in `@stylistic/eslint-plugin-js`.
604
616
  * @see https://eslint.org/docs/rules/no-multi-spaces
605
617
  */
606
618
  "no-multi-spaces": Linter.RuleEntry<
@@ -872,6 +884,15 @@ export interface BestPractices extends Linter.RulesRecord {
872
884
  */
873
885
  "no-unused-labels": Linter.RuleEntry<[]>;
874
886
 
887
+ /**
888
+ * Disallow variable assignments when the value is not used
889
+ *
890
+ *
891
+ * @since 9.0.0-alpha.1
892
+ * @see https://eslint.org/docs/latest/rules/no-useless-assignment
893
+ */
894
+ "no-useless-assignment": Linter.RuleEntry<[]>;
895
+
875
896
  /**
876
897
  * Disallow useless backreferences in regular expressions
877
898
  *
@@ -1045,12 +1066,21 @@ export interface BestPractices extends Linter.RulesRecord {
1045
1066
  "require-await": Linter.RuleEntry<[]>;
1046
1067
 
1047
1068
  /**
1048
- * Rule to enforce the use of `u` flag on RegExp.
1069
+ * Enforce the use of `u` or `v` flag on RegExp
1049
1070
  *
1050
1071
  * @since 5.3.0
1051
1072
  * @see https://eslint.org/docs/rules/require-unicode-regexp
1052
1073
  */
1053
- "require-unicode-regexp": Linter.RuleEntry<[]>;
1074
+ "require-unicode-regexp": Linter.RuleEntry<
1075
+ [
1076
+ Partial<{
1077
+ /**
1078
+ * @default false
1079
+ */
1080
+ requireFlag: "u" | "v";
1081
+ }>,
1082
+ ]
1083
+ >;
1054
1084
 
1055
1085
  /**
1056
1086
  * Rule to require `var` declarations be placed at the top of their containing scope.
@@ -1064,6 +1094,7 @@ export interface BestPractices extends Linter.RulesRecord {
1064
1094
  * Rule to require parentheses around immediate `function` invocations.
1065
1095
  *
1066
1096
  * @since 0.0.9
1097
+ * @deprecated since 8.53.0, please use the [corresponding rule](https://eslint.style/rules/js/wrap-iife) in `@stylistic/eslint-plugin-js`.
1067
1098
  * @see https://eslint.org/docs/rules/wrap-iife
1068
1099
  */
1069
1100
  "wrap-iife": Linter.RuleEntry<
@@ -191,6 +191,24 @@ export interface Deprecated extends Linter.RulesRecord {
191
191
  */
192
192
  "no-negated-in-lhs": Linter.RuleEntry<[]>;
193
193
 
194
+ /**
195
+ * Rule to disallow `Object` constructors.
196
+ *
197
+ * @since 0.0.9
198
+ * @deprecated since 8.50.0, use [`no-object-constructor`](https://eslint.org/docs/rules/no-object-constructor) instead.
199
+ * @see https://eslint.org/docs/rules/no-object-constructor
200
+ */
201
+ "no-new-object": Linter.RuleEntry<[]>;
202
+
203
+ /**
204
+ * Rule to disallow `new` operators with the `Symbol` object.
205
+ *
206
+ * @since 2.0.0-beta.1
207
+ * @deprecated since 8.27.0, use [`no-new-native-nonconstructor`](https://eslint.org/docs/rules/no-new-native-nonconstructor) instead.
208
+ * @see https://eslint.org/docs/rules/no-new-symbol
209
+ */
210
+ "no-new-symbol": Linter.RuleEntry<[]>;
211
+
194
212
  /**
195
213
  * Rule to disallow spacing between function identifiers and their applications.
196
214
  *
@@ -214,81 +232,4 @@ export interface Deprecated extends Linter.RulesRecord {
214
232
  }>,
215
233
  ]
216
234
  >;
217
-
218
- /**
219
- * Rule to require JSDoc comments.
220
- *
221
- * @since 1.4.0
222
- * @deprecated since 5.10.0
223
- * @see https://eslint.org/docs/rules/require-jsdoc
224
- */
225
- "require-jsdoc": Linter.RuleEntry<
226
- [
227
- Partial<{
228
- require: Partial<{
229
- /**
230
- * @default true
231
- */
232
- FunctionDeclaration: boolean;
233
- /**
234
- * @default false
235
- */
236
- MethodDefinition: boolean;
237
- /**
238
- * @default false
239
- */
240
- ClassDeclaration: boolean;
241
- /**
242
- * @default false
243
- */
244
- ArrowFunctionExpression: boolean;
245
- /**
246
- * @default false
247
- */
248
- FunctionExpression: boolean;
249
- }>;
250
- }>,
251
- ]
252
- >;
253
-
254
- /**
255
- * Rule to enforce valid JSDoc comments.
256
- *
257
- * @since 0.4.0
258
- * @deprecated since 5.10.0
259
- * @see https://eslint.org/docs/rules/valid-jsdoc
260
- */
261
- "valid-jsdoc": Linter.RuleEntry<
262
- [
263
- Partial<{
264
- prefer: Record<string, string>;
265
- preferType: Record<string, string>;
266
- /**
267
- * @default true
268
- */
269
- requireReturn: boolean;
270
- /**
271
- * @default true
272
- */
273
- requireReturnType: boolean;
274
- /**
275
- * @remarks
276
- * Also accept for regular expression pattern
277
- */
278
- matchDescription: string;
279
- /**
280
- * @default true
281
- */
282
- requireParamDescription: boolean;
283
- /**
284
- * @default true
285
- */
286
- requireReturnDescription: boolean;
287
- /**
288
- * @default true
289
- */
290
- requireParamType: boolean;
291
- }>,
292
- ]
293
- >;
294
235
  }