eslint 9.31.0 → 9.33.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.
@@ -64,6 +64,12 @@ module.exports = {
64
64
  const: {
65
65
  enum: ["always", "never", "consecutive"],
66
66
  },
67
+ using: {
68
+ enum: ["always", "never", "consecutive"],
69
+ },
70
+ awaitUsing: {
71
+ enum: ["always", "never", "consecutive"],
72
+ },
67
73
  },
68
74
  additionalProperties: false,
69
75
  },
@@ -112,6 +118,8 @@ module.exports = {
112
118
  options.var = { uninitialized: mode, initialized: mode };
113
119
  options.let = { uninitialized: mode, initialized: mode };
114
120
  options.const = { uninitialized: mode, initialized: mode };
121
+ options.using = { uninitialized: mode, initialized: mode };
122
+ options.awaitUsing = { uninitialized: mode, initialized: mode };
115
123
  } else if (typeof mode === "object") {
116
124
  // options configuration is an object
117
125
  options.separateRequires = !!mode.separateRequires;
@@ -121,15 +129,27 @@ module.exports = {
121
129
  uninitialized: mode.const,
122
130
  initialized: mode.const,
123
131
  };
132
+ options.using = {
133
+ uninitialized: mode.using,
134
+ initialized: mode.using,
135
+ };
136
+ options.awaitUsing = {
137
+ uninitialized: mode.awaitUsing,
138
+ initialized: mode.awaitUsing,
139
+ };
124
140
  if (Object.hasOwn(mode, "uninitialized")) {
125
141
  options.var.uninitialized = mode.uninitialized;
126
142
  options.let.uninitialized = mode.uninitialized;
127
143
  options.const.uninitialized = mode.uninitialized;
144
+ options.using.uninitialized = mode.uninitialized;
145
+ options.awaitUsing.uninitialized = mode.uninitialized;
128
146
  }
129
147
  if (Object.hasOwn(mode, "initialized")) {
130
148
  options.var.initialized = mode.initialized;
131
149
  options.let.initialized = mode.initialized;
132
150
  options.const.initialized = mode.initialized;
151
+ options.using.initialized = mode.initialized;
152
+ options.awaitUsing.initialized = mode.initialized;
133
153
  }
134
154
  }
135
155
 
@@ -151,6 +171,8 @@ module.exports = {
151
171
  blockStack.push({
152
172
  let: { initialized: false, uninitialized: false },
153
173
  const: { initialized: false, uninitialized: false },
174
+ using: { initialized: false, uninitialized: false },
175
+ awaitUsing: { initialized: false, uninitialized: false },
154
176
  });
155
177
  }
156
178
 
@@ -199,7 +221,7 @@ module.exports = {
199
221
 
200
222
  /**
201
223
  * Records whether initialized/uninitialized/required variables are defined in current scope.
202
- * @param {string} statementType node.kind, one of: "var", "let", or "const"
224
+ * @param {string} statementType one of: "var", "let", "const", "using", or "awaitUsing"
203
225
  * @param {ASTNode[]} declarations List of declarations
204
226
  * @param {Object} currentScope The scope being investigated
205
227
  * @returns {void}
@@ -234,7 +256,7 @@ module.exports = {
234
256
 
235
257
  /**
236
258
  * Determines the current scope (function or block)
237
- * @param {string} statementType node.kind, one of: "var", "let", or "const"
259
+ * @param {string} statementType one of: "var", "let", "const", "using", or "awaitUsing"
238
260
  * @returns {Object} The scope associated with statementType
239
261
  */
240
262
  function getCurrentScope(statementType) {
@@ -246,6 +268,10 @@ module.exports = {
246
268
  currentScope = blockStack.at(-1).let;
247
269
  } else if (statementType === "const") {
248
270
  currentScope = blockStack.at(-1).const;
271
+ } else if (statementType === "using") {
272
+ currentScope = blockStack.at(-1).using;
273
+ } else if (statementType === "awaitUsing") {
274
+ currentScope = blockStack.at(-1).awaitUsing;
249
275
  }
250
276
  return currentScope;
251
277
  }
@@ -271,7 +297,7 @@ module.exports = {
271
297
 
272
298
  /**
273
299
  * Determines if there is more than one var statement in the current scope.
274
- * @param {string} statementType node.kind, one of: "var", "let", or "const"
300
+ * @param {string} statementType one of: "var", "let", "const", "using", or "awaitUsing"
275
301
  * @param {ASTNode[]} declarations List of declarations
276
302
  * @returns {boolean} Returns true if it is the first var declaration, false if not.
277
303
  * @private
@@ -333,24 +359,27 @@ module.exports = {
333
359
  );
334
360
  const previousNode = body[currentIndex - 1];
335
361
 
336
- return fixer => {
337
- const type = sourceCode.getTokenBefore(declaration);
338
- const prevSemi = sourceCode.getTokenBefore(type);
339
- const res = [];
362
+ return function* joinDeclarationsFixer(fixer) {
363
+ const type = sourceCode.getFirstToken(declaration.parent);
364
+ const beforeType = sourceCode.getTokenBefore(type);
340
365
 
341
366
  if (
342
367
  previousNode &&
343
- previousNode.kind === sourceCode.getText(type)
368
+ previousNode.kind === declaration.parent.kind
344
369
  ) {
345
- if (prevSemi.value === ";") {
346
- res.push(fixer.replaceText(prevSemi, ","));
370
+ if (beforeType.value === ";") {
371
+ yield fixer.replaceText(beforeType, ",");
347
372
  } else {
348
- res.push(fixer.insertTextAfter(prevSemi, ","));
373
+ yield fixer.insertTextAfter(beforeType, ",");
374
+ }
375
+
376
+ if (declaration.parent.kind === "await using") {
377
+ const usingToken = sourceCode.getTokenAfter(type);
378
+ yield fixer.remove(usingToken);
349
379
  }
350
- res.push(fixer.replaceText(type, ""));
351
- }
352
380
 
353
- return res;
381
+ yield fixer.replaceText(type, "");
382
+ }
354
383
  };
355
384
  }
356
385
 
@@ -440,7 +469,10 @@ module.exports = {
440
469
  tokenAfterDeclarator.range[0],
441
470
  lastComment.range[0],
442
471
  ],
443
- `;${sourceCode.text.slice(tokenAfterDeclarator.range[1], lastComment.range[0])}${exportPlacement}${declaration.kind} `,
472
+ `;${sourceCode.text.slice(
473
+ tokenAfterDeclarator.range[1],
474
+ lastComment.range[0],
475
+ )}${exportPlacement}${declaration.kind} `,
444
476
  );
445
477
  }
446
478
 
@@ -461,8 +493,9 @@ module.exports = {
461
493
  function checkVariableDeclaration(node) {
462
494
  const parent = node.parent;
463
495
  const type = node.kind;
496
+ const key = type === "await using" ? "awaitUsing" : type;
464
497
 
465
- if (!options[type]) {
498
+ if (!options[key]) {
466
499
  return;
467
500
  }
468
501
 
@@ -471,7 +504,7 @@ module.exports = {
471
504
  const mixedRequires =
472
505
  declarations.some(isRequire) && !declarations.every(isRequire);
473
506
 
474
- if (options[type].initialized === MODE_ALWAYS) {
507
+ if (options[key].initialized === MODE_ALWAYS) {
475
508
  if (options.separateRequires && mixedRequires) {
476
509
  context.report({
477
510
  node,
@@ -508,8 +541,8 @@ module.exports = {
508
541
  );
509
542
 
510
543
  if (
511
- options[type].initialized === MODE_CONSECUTIVE &&
512
- options[type].uninitialized === MODE_CONSECUTIVE
544
+ options[key].initialized === MODE_CONSECUTIVE &&
545
+ options[key].uninitialized === MODE_CONSECUTIVE
513
546
  ) {
514
547
  context.report({
515
548
  node,
@@ -520,7 +553,7 @@ module.exports = {
520
553
  fix: joinDeclarations(declarations),
521
554
  });
522
555
  } else if (
523
- options[type].initialized === MODE_CONSECUTIVE &&
556
+ options[key].initialized === MODE_CONSECUTIVE &&
524
557
  declarationCounts.initialized > 0 &&
525
558
  previousDeclCounts.initialized > 0
526
559
  ) {
@@ -533,7 +566,7 @@ module.exports = {
533
566
  fix: joinDeclarations(declarations),
534
567
  });
535
568
  } else if (
536
- options[type].uninitialized === MODE_CONSECUTIVE &&
569
+ options[key].uninitialized === MODE_CONSECUTIVE &&
537
570
  declarationCounts.uninitialized > 0 &&
538
571
  previousDeclCounts.uninitialized > 0
539
572
  ) {
@@ -550,10 +583,10 @@ module.exports = {
550
583
  }
551
584
 
552
585
  // always
553
- if (!hasOnlyOneStatement(type, declarations)) {
586
+ if (!hasOnlyOneStatement(key, declarations)) {
554
587
  if (
555
- options[type].initialized === MODE_ALWAYS &&
556
- options[type].uninitialized === MODE_ALWAYS
588
+ options[key].initialized === MODE_ALWAYS &&
589
+ options[key].uninitialized === MODE_ALWAYS
557
590
  ) {
558
591
  context.report({
559
592
  node,
@@ -565,7 +598,7 @@ module.exports = {
565
598
  });
566
599
  } else {
567
600
  if (
568
- options[type].initialized === MODE_ALWAYS &&
601
+ options[key].initialized === MODE_ALWAYS &&
569
602
  declarationCounts.initialized > 0
570
603
  ) {
571
604
  context.report({
@@ -578,7 +611,7 @@ module.exports = {
578
611
  });
579
612
  }
580
613
  if (
581
- options[type].uninitialized === MODE_ALWAYS &&
614
+ options[key].uninitialized === MODE_ALWAYS &&
582
615
  declarationCounts.uninitialized > 0
583
616
  ) {
584
617
  if (
@@ -608,8 +641,8 @@ module.exports = {
608
641
 
609
642
  if (totalDeclarations > 1) {
610
643
  if (
611
- options[type].initialized === MODE_NEVER &&
612
- options[type].uninitialized === MODE_NEVER
644
+ options[key].initialized === MODE_NEVER &&
645
+ options[key].uninitialized === MODE_NEVER
613
646
  ) {
614
647
  // both initialized and uninitialized
615
648
  context.report({
@@ -621,7 +654,7 @@ module.exports = {
621
654
  fix: splitDeclarations(node),
622
655
  });
623
656
  } else if (
624
- options[type].initialized === MODE_NEVER &&
657
+ options[key].initialized === MODE_NEVER &&
625
658
  declarationCounts.initialized > 0
626
659
  ) {
627
660
  // initialized
@@ -634,7 +667,7 @@ module.exports = {
634
667
  fix: splitDeclarations(node),
635
668
  });
636
669
  } else if (
637
- options[type].uninitialized === MODE_NEVER &&
670
+ options[key].uninitialized === MODE_NEVER &&
638
671
  declarationCounts.uninitialized > 0
639
672
  ) {
640
673
  // uninitialized
@@ -293,6 +293,14 @@ module.exports = {
293
293
  return;
294
294
  }
295
295
 
296
+ // Variable declarations using explicit resource management cannot use destructuring (parse error)
297
+ if (
298
+ node.parent.kind === "using" ||
299
+ node.parent.kind === "await using"
300
+ ) {
301
+ return;
302
+ }
303
+
296
304
  // We only care about member expressions past this point
297
305
  if (node.init.type !== "MemberExpression") {
298
306
  return;
@@ -170,6 +170,15 @@ module.exports = {
170
170
  scopeInfo.hasAwait = true;
171
171
  }
172
172
  },
173
+ VariableDeclaration(node) {
174
+ if (!scopeInfo) {
175
+ return;
176
+ }
177
+
178
+ if (node.kind === "await using") {
179
+ scopeInfo.hasAwait = true;
180
+ }
181
+ },
173
182
  };
174
183
  },
175
184
  };
@@ -47,6 +47,12 @@ const STATEMENT_LIST_PARENTS = new Set([
47
47
  "StaticBlock",
48
48
  "SwitchCase",
49
49
  ]);
50
+ const LEXICAL_DECLARATION_KINDS = new Set([
51
+ "let",
52
+ "const",
53
+ "using",
54
+ "await using",
55
+ ]);
50
56
 
51
57
  const DECIMAL_INTEGER_PATTERN = /^(?:0|0[0-7]*[89]\d*|[1-9](?:_?\d)*)$/u;
52
58
 
@@ -298,6 +304,8 @@ function getStaticPropertyName(node) {
298
304
  case "Property":
299
305
  case "PropertyDefinition":
300
306
  case "MethodDefinition":
307
+ case "TSPropertySignature":
308
+ case "TSMethodSignature":
301
309
  prop = node.key;
302
310
  break;
303
311
 
@@ -1989,13 +1997,15 @@ module.exports = {
1989
1997
 
1990
1998
  if (
1991
1999
  parent.type === "MethodDefinition" ||
1992
- parent.type === "PropertyDefinition"
2000
+ parent.type === "PropertyDefinition" ||
2001
+ node.type === "TSPropertySignature" ||
2002
+ node.type === "TSMethodSignature"
1993
2003
  ) {
1994
2004
  // The proposal uses `static` word consistently before visibility words: https://github.com/tc39/proposal-static-class-features
1995
2005
  if (parent.static) {
1996
2006
  tokens.push("static");
1997
2007
  }
1998
- if (!parent.computed && parent.key.type === "PrivateIdentifier") {
2008
+ if (!parent.computed && parent.key?.type === "PrivateIdentifier") {
1999
2009
  tokens.push("private");
2000
2010
  }
2001
2011
  }
@@ -2017,6 +2027,14 @@ module.exports = {
2017
2027
  } else {
2018
2028
  tokens.push("method");
2019
2029
  }
2030
+ } else if (node.type === "TSMethodSignature") {
2031
+ if (node.kind === "get") {
2032
+ tokens.push("getter");
2033
+ } else if (node.kind === "set") {
2034
+ tokens.push("setter");
2035
+ } else {
2036
+ tokens.push("method");
2037
+ }
2020
2038
  } else if (parent.type === "PropertyDefinition") {
2021
2039
  tokens.push("method");
2022
2040
  } else {
@@ -2042,6 +2060,8 @@ module.exports = {
2042
2060
  tokens.push(`'${node.id.name}'`);
2043
2061
  }
2044
2062
  }
2063
+ } else if (node.type === "TSMethodSignature") {
2064
+ tokens.push(`'${getStaticPropertyName(node)}'`);
2045
2065
  } else if (node.id) {
2046
2066
  tokens.push(`'${node.id.name}'`);
2047
2067
  }
@@ -2154,7 +2174,9 @@ module.exports = {
2154
2174
  if (
2155
2175
  parent.type === "Property" ||
2156
2176
  parent.type === "MethodDefinition" ||
2157
- parent.type === "PropertyDefinition"
2177
+ parent.type === "PropertyDefinition" ||
2178
+ parent.type === "TSPropertySignature" ||
2179
+ parent.type === "TSMethodSignature"
2158
2180
  ) {
2159
2181
  start = parent.loc.start;
2160
2182
  end = getOpeningParenOfParams(node, sourceCode).loc.start;
@@ -2573,16 +2595,14 @@ module.exports = {
2573
2595
  */
2574
2596
  areBracesNecessary(node, sourceCode) {
2575
2597
  /**
2576
- * Determines if the given node is a lexical declaration (let, const, function, or class)
2598
+ * Determines if the given node is a lexical declaration (let, const, using, await using, function, or class)
2577
2599
  * @param {ASTNode} nodeToCheck The node to check
2578
2600
  * @returns {boolean} True if the node is a lexical declaration
2579
2601
  * @private
2580
2602
  */
2581
2603
  function isLexicalDeclaration(nodeToCheck) {
2582
2604
  if (nodeToCheck.type === "VariableDeclaration") {
2583
- return (
2584
- nodeToCheck.kind === "const" || nodeToCheck.kind === "let"
2585
- );
2605
+ return LEXICAL_DECLARATION_KINDS.has(nodeToCheck.kind);
2586
2606
  }
2587
2607
 
2588
2608
  return (
@@ -27,15 +27,17 @@
27
27
 
28
28
  import * as ESTree from "estree";
29
29
  import type {
30
- RuleVisitor,
31
- TextSourceCode,
30
+ CustomRuleDefinitionType,
31
+ CustomRuleTypeDefinitions,
32
+ DeprecatedInfo,
32
33
  Language,
33
- SourceRange,
34
- TraversalStep,
35
34
  LanguageOptions as GenericLanguageOptions,
36
- RuleDefinition,
37
35
  RuleContext as CoreRuleContext,
38
- DeprecatedInfo,
36
+ RuleDefinition,
37
+ RuleVisitor,
38
+ SourceRange,
39
+ TextSourceCode,
40
+ TraversalStep,
39
41
  } from "@eslint/core";
40
42
  import { JSONSchema4 } from "json-schema";
41
43
  import { LegacyESLint } from "./use-at-your-own-risk.js";
@@ -1250,27 +1252,18 @@ export namespace Rule {
1250
1252
  }
1251
1253
  }
1252
1254
 
1253
- export type JSRuleDefinitionTypeOptions = {
1254
- RuleOptions: unknown[];
1255
- MessageIds: string;
1256
- ExtRuleDocs: Record<string, unknown>;
1257
- };
1255
+ export type JSRuleDefinitionTypeOptions = CustomRuleTypeDefinitions;
1258
1256
 
1259
1257
  export type JSRuleDefinition<
1260
1258
  Options extends Partial<JSRuleDefinitionTypeOptions> = {},
1261
- > = RuleDefinition<
1262
- // Language specific type options (non-configurable)
1259
+ > = CustomRuleDefinitionType<
1263
1260
  {
1264
1261
  LangOptions: Linter.LanguageOptions;
1265
1262
  Code: SourceCode;
1266
1263
  Visitor: Rule.NodeListener;
1267
1264
  Node: JSSyntaxElement;
1268
- } & Required<
1269
- // Rule specific type options (custom)
1270
- Options &
1271
- // Rule specific type options (defaults)
1272
- Omit<JSRuleDefinitionTypeOptions, keyof Options>
1273
- >
1265
+ },
1266
+ Options
1274
1267
  >;
1275
1268
 
1276
1269
  // #region Linter
@@ -1597,7 +1590,6 @@ export namespace Linter {
1597
1590
  globalReturn?: boolean | undefined;
1598
1591
  impliedStrict?: boolean | undefined;
1599
1592
  jsx?: boolean | undefined;
1600
- experimentalObjectRestSpread?: boolean | undefined;
1601
1593
  [key: string]: any;
1602
1594
  }
1603
1595
  | undefined;
@@ -116,6 +116,10 @@ export interface ESLintRules extends Linter.RulesRecord {
116
116
  * @default true
117
117
  */
118
118
  enforceForClassMembers: boolean;
119
+ /**
120
+ * @default true
121
+ */
122
+ enforceForTSTypes: boolean;
119
123
  }>,
120
124
  ]
121
125
  >;
@@ -945,7 +949,15 @@ export interface ESLintRules extends Linter.RulesRecord {
945
949
  * @see https://eslint.org/docs/latest/rules/grouped-accessor-pairs
946
950
  */
947
951
  "grouped-accessor-pairs": Linter.RuleEntry<
948
- ["anyOrder" | "getBeforeSet" | "setBeforeGet"]
952
+ [
953
+ "anyOrder" | "getBeforeSet" | "setBeforeGet",
954
+ Partial<{
955
+ /**
956
+ * @default false
957
+ */
958
+ enforceForTSTypes: boolean;
959
+ }>,
960
+ ]
949
961
  >;
950
962
 
951
963
  /**
@@ -3391,13 +3403,26 @@ export interface ESLintRules extends Linter.RulesRecord {
3391
3403
  */
3392
3404
  "no-restricted-globals": Linter.RuleEntry<
3393
3405
  [
3394
- ...Array<
3395
- | string
3396
- | {
3397
- name: string;
3398
- message?: string | undefined;
3399
- }
3400
- >,
3406
+ ...(
3407
+ | Array<
3408
+ | string
3409
+ | {
3410
+ name: string;
3411
+ message?: string | undefined;
3412
+ }
3413
+ >
3414
+ | Array<{
3415
+ globals: Array<
3416
+ | string
3417
+ | {
3418
+ name: string;
3419
+ message?: string | undefined;
3420
+ }
3421
+ >;
3422
+ checkGlobalObject?: boolean;
3423
+ globalObjects?: string[];
3424
+ }>
3425
+ ),
3401
3426
  ]
3402
3427
  >;
3403
3428
 
@@ -4066,6 +4091,10 @@ export interface ESLintRules extends Linter.RulesRecord {
4066
4091
  * @default false
4067
4092
  */
4068
4093
  ignoreClassWithStaticInitBlock: boolean;
4094
+ /**
4095
+ * @default false
4096
+ */
4097
+ ignoreUsingDeclarations: boolean;
4069
4098
  /**
4070
4099
  * @default false
4071
4100
  */
@@ -4493,7 +4522,7 @@ export interface ESLintRules extends Linter.RulesRecord {
4493
4522
  */
4494
4523
  separateRequires: boolean;
4495
4524
  } & Record<
4496
- "var" | "let" | "const",
4525
+ "var" | "let" | "const" | "using" | "awaitUsing",
4497
4526
  "always" | "never" | "consecutive"
4498
4527
  >
4499
4528
  >
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint",
3
- "version": "9.31.0",
3
+ "version": "9.33.0",
4
4
  "author": "Nicholas C. Zakas <nicholas+npm@nczconsulting.com>",
5
5
  "description": "An AST-based pattern checker for JavaScript.",
6
6
  "type": "commonjs",
@@ -107,11 +107,11 @@
107
107
  "@eslint-community/eslint-utils": "^4.2.0",
108
108
  "@eslint-community/regexpp": "^4.12.1",
109
109
  "@eslint/config-array": "^0.21.0",
110
- "@eslint/config-helpers": "^0.3.0",
111
- "@eslint/core": "^0.15.0",
110
+ "@eslint/config-helpers": "^0.3.1",
111
+ "@eslint/core": "^0.15.2",
112
112
  "@eslint/eslintrc": "^3.3.1",
113
- "@eslint/js": "9.31.0",
114
- "@eslint/plugin-kit": "^0.3.1",
113
+ "@eslint/js": "9.33.0",
114
+ "@eslint/plugin-kit": "^0.3.5",
115
115
  "@humanfs/node": "^0.16.6",
116
116
  "@humanwhocodes/module-importer": "^1.0.1",
117
117
  "@humanwhocodes/retry": "^0.4.2",
@@ -173,12 +173,11 @@
173
173
  "globals": "^16.2.0",
174
174
  "got": "^11.8.3",
175
175
  "gray-matter": "^4.0.3",
176
- "jiti": "^2.2.0",
176
+ "jiti": "^2.5.1",
177
177
  "jiti-v2.0": "npm:jiti@2.0.x",
178
178
  "jiti-v2.1": "npm:jiti@2.1.x",
179
179
  "knip": "^5.60.2",
180
180
  "lint-staged": "^11.0.0",
181
- "load-perf": "^0.2.0",
182
181
  "markdown-it": "^12.2.0",
183
182
  "markdown-it-container": "^3.0.0",
184
183
  "marked": "^4.0.8",