eslint 9.39.1 → 10.0.0-alpha.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 (42) hide show
  1. package/README.md +3 -3
  2. package/bin/eslint.js +1 -2
  3. package/lib/api.js +4 -15
  4. package/lib/cli.js +14 -56
  5. package/lib/config/config-loader.js +6 -154
  6. package/lib/eslint/eslint-helpers.js +5 -8
  7. package/lib/eslint/eslint.js +1 -1
  8. package/lib/eslint/index.js +0 -2
  9. package/lib/languages/js/source-code/source-code.js +39 -87
  10. package/lib/languages/js/source-code/token-store/utils.js +29 -8
  11. package/lib/linter/apply-disable-directives.js +0 -1
  12. package/lib/linter/file-context.js +0 -56
  13. package/lib/linter/file-report.js +0 -4
  14. package/lib/linter/linter.js +45 -1086
  15. package/lib/linter/rule-fixer.js +30 -0
  16. package/lib/options.js +62 -182
  17. package/lib/rule-tester/rule-tester.js +255 -194
  18. package/lib/rules/dot-notation.js +2 -2
  19. package/lib/rules/func-names.js +2 -0
  20. package/lib/rules/no-eval.js +1 -1
  21. package/lib/rules/no-invalid-regexp.js +1 -0
  22. package/lib/rules/no-shadow-restricted-names.js +1 -1
  23. package/lib/rules/no-unassigned-vars.js +1 -1
  24. package/lib/rules/no-useless-assignment.js +1 -1
  25. package/lib/rules/preserve-caught-error.js +1 -1
  26. package/lib/rules/radix.js +25 -48
  27. package/lib/services/parser-service.js +0 -1
  28. package/lib/services/processor-service.js +0 -1
  29. package/lib/services/warning-service.js +0 -11
  30. package/lib/shared/flags.js +0 -19
  31. package/lib/shared/translate-cli-options.js +106 -164
  32. package/lib/types/index.d.ts +7 -60
  33. package/lib/types/rules.d.ts +11 -2
  34. package/lib/types/use-at-your-own-risk.d.ts +1 -54
  35. package/lib/unsupported-api.js +3 -6
  36. package/package.json +14 -19
  37. package/conf/default-cli-options.js +0 -32
  38. package/lib/cli-engine/cli-engine.js +0 -1109
  39. package/lib/cli-engine/file-enumerator.js +0 -541
  40. package/lib/cli-engine/index.js +0 -7
  41. package/lib/cli-engine/load-rules.js +0 -46
  42. package/lib/eslint/legacy-eslint.js +0 -786
package/README.md CHANGED
@@ -42,7 +42,7 @@ ESLint is a tool for identifying and reporting on patterns found in ECMAScript/J
42
42
 
43
43
  ## Installation and Usage
44
44
 
45
- Prerequisites: [Node.js](https://nodejs.org/) (`^18.18.0`, `^20.9.0`, or `>=21.1.0`) built with SSL support. (If you are using an official Node.js distribution, SSL is always built in.)
45
+ Prerequisites: [Node.js](https://nodejs.org/) (`^20.19.0`, `^22.13.0`, or `>=24`) built with SSL support. (If you are using an official Node.js distribution, SSL is always built in.)
46
46
 
47
47
  You can install and configure ESLint using this command:
48
48
 
@@ -341,9 +341,9 @@ to get your logo on our READMEs and [website](https://eslint.org/sponsors).
341
341
 
342
342
  <h3>Platinum Sponsors</h3>
343
343
  <p><a href="https://automattic.com"><img src="https://images.opencollective.com/automattic/d0ef3e1/logo.png" alt="Automattic" height="128"></a> <a href="https://www.airbnb.com/"><img src="https://images.opencollective.com/airbnb/d327d66/logo.png" alt="Airbnb" height="128"></a></p><h3>Gold Sponsors</h3>
344
- <p><a href="https://qlty.sh/"><img src="https://images.opencollective.com/qltysh/33d157d/logo.png" alt="Qlty Software" height="96"></a> <a href="https://trunk.io/"><img src="https://images.opencollective.com/trunkio/fb92d60/avatar.png" alt="trunk.io" height="96"></a> <a href="https://shopify.engineering/"><img src="https://avatars.githubusercontent.com/u/8085" alt="Shopify" height="96"></a></p><h3>Silver Sponsors</h3>
344
+ <p><a href="https://qlty.sh/"><img src="https://images.opencollective.com/qltysh/33d157d/logo.png" alt="Qlty Software" height="96"></a> <a href="https://shopify.engineering/"><img src="https://avatars.githubusercontent.com/u/8085" alt="Shopify" height="96"></a></p><h3>Silver Sponsors</h3>
345
345
  <p><a href="https://vite.dev/"><img src="https://images.opencollective.com/vite/e6d15e1/logo.png" alt="Vite" height="64"></a> <a href="https://liftoff.io/"><img src="https://images.opencollective.com/liftoff/2d6c3b6/logo.png" alt="Liftoff" height="64"></a> <a href="https://americanexpress.io"><img src="https://avatars.githubusercontent.com/u/3853301" alt="American Express" height="64"></a> <a href="https://stackblitz.com"><img src="https://avatars.githubusercontent.com/u/28635252" alt="StackBlitz" height="64"></a></p><h3>Bronze Sponsors</h3>
346
- <p><a href="https://cybozu.co.jp/"><img src="https://images.opencollective.com/cybozu/933e46d/logo.png" alt="Cybozu" height="32"></a> <a href="https://icons8.com/"><img src="https://images.opencollective.com/icons8/7fa1641/logo.png" alt="Icons8" 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://www.gitbook.com"><img src="https://avatars.githubusercontent.com/u/7111340" alt="GitBook" height="32"></a> <a href="https://nx.dev"><img src="https://avatars.githubusercontent.com/u/23692104" alt="Nx" height="32"></a> <a href="https://opensource.mercedes-benz.com/"><img src="https://avatars.githubusercontent.com/u/34240465" alt="Mercedes-Benz Group" height="32"></a> <a href="https://herocoders.com"><img src="https://avatars.githubusercontent.com/u/37549774" alt="HeroCoders" height="32"></a> <a href="https://www.lambdatest.com"><img src="https://avatars.githubusercontent.com/u/171592363" alt="LambdaTest" height="32"></a></p>
346
+ <p><a href="https://cybozu.co.jp/"><img src="https://images.opencollective.com/cybozu/933e46d/logo.png" alt="Cybozu" height="32"></a> <a href="https://syntax.fm"><img src="https://github.com/syntaxfm.png" alt="Syntax" height="32"></a> <a href="https://icons8.com/"><img src="https://images.opencollective.com/icons8/7fa1641/logo.png" alt="Icons8" 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://www.gitbook.com"><img src="https://avatars.githubusercontent.com/u/7111340" alt="GitBook" height="32"></a> <a href="https://nx.dev"><img src="https://avatars.githubusercontent.com/u/23692104" alt="Nx" height="32"></a> <a href="https://opensource.mercedes-benz.com/"><img src="https://avatars.githubusercontent.com/u/34240465" alt="Mercedes-Benz Group" height="32"></a> <a href="https://herocoders.com"><img src="https://avatars.githubusercontent.com/u/37549774" alt="HeroCoders" height="32"></a> <a href="https://www.lambdatest.com"><img src="https://avatars.githubusercontent.com/u/171592363" alt="LambdaTest" height="32"></a></p>
347
347
  <h3>Technology Sponsors</h3>
348
348
  Technology sponsors allow us to use their products and services for free as part of a contribution to the open source ecosystem and our work.
349
349
  <p><a href="https://netlify.com"><img src="https://raw.githubusercontent.com/eslint/eslint.org/main/src/assets/images/techsponsors/netlify-icon.svg" alt="Netlify" height="32"></a> <a href="https://algolia.com"><img src="https://raw.githubusercontent.com/eslint/eslint.org/main/src/assets/images/techsponsors/algolia-icon.svg" alt="Algolia" height="32"></a> <a href="https://1password.com"><img src="https://raw.githubusercontent.com/eslint/eslint.org/main/src/assets/images/techsponsors/1password-icon.svg" alt="1Password" height="32"></a></p>
package/bin/eslint.js CHANGED
@@ -174,8 +174,7 @@ ${getErrorMessage(error)}`;
174
174
  const cli = require("../lib/cli");
175
175
  const exitCode = await cli.execute(
176
176
  process.argv,
177
- process.argv.includes("--stdin") ? await readStdin() : null,
178
- true,
177
+ process.argv.includes("--stdin") ? await readStdin() : void 0,
179
178
  );
180
179
 
181
180
  /*
package/lib/api.js CHANGED
@@ -9,8 +9,7 @@
9
9
  // Requirements
10
10
  //-----------------------------------------------------------------------------
11
11
 
12
- const { ESLint, shouldUseFlatConfig } = require("./eslint/eslint");
13
- const { LegacyESLint } = require("./eslint/legacy-eslint");
12
+ const { ESLint } = require("./eslint/eslint");
14
13
  const { Linter } = require("./linter");
15
14
  const { RuleTester } = require("./rule-tester");
16
15
  const { SourceCode } = require("./languages/js/source-code");
@@ -21,20 +20,10 @@ const { SourceCode } = require("./languages/js/source-code");
21
20
 
22
21
  /**
23
22
  * Loads the correct ESLint constructor given the options.
24
- * @param {Object} [options] The options object
25
- * @param {boolean} [options.useFlatConfig] Whether or not to use a flat config
26
- * @returns {Promise<ESLint|LegacyESLint>} The ESLint constructor
23
+ * @returns {Promise<ESLint>} The ESLint constructor
27
24
  */
28
- async function loadESLint({ useFlatConfig } = {}) {
29
- /*
30
- * Note: The v8.x version of this function also accepted a `cwd` option, but
31
- * it is not used in this implementation so we silently ignore it.
32
- */
33
-
34
- const shouldESLintUseFlatConfig =
35
- useFlatConfig ?? (await shouldUseFlatConfig());
36
-
37
- return shouldESLintUseFlatConfig ? ESLint : LegacyESLint;
25
+ async function loadESLint() {
26
+ return ESLint;
38
27
  }
39
28
 
40
29
  //-----------------------------------------------------------------------------
package/lib/cli.js CHANGED
@@ -19,12 +19,7 @@ const fs = require("node:fs"),
19
19
  { mkdir, stat, writeFile } = require("node:fs/promises"),
20
20
  path = require("node:path"),
21
21
  { pathToFileURL } = require("node:url"),
22
- { LegacyESLint } = require("./eslint"),
23
- {
24
- ESLint,
25
- shouldUseFlatConfig,
26
- locateConfigFileToUse,
27
- } = require("./eslint/eslint"),
22
+ { ESLint, locateConfigFileToUse } = require("./eslint/eslint"),
28
23
  createCLIOptions = require("./options"),
29
24
  log = require("./shared/logging"),
30
25
  RuntimeInfo = require("./shared/runtime-info"),
@@ -76,7 +71,7 @@ function createOptionsModule(options) {
76
71
  ).href;
77
72
  const optionsSrc =
78
73
  `import translateOptions from ${JSON.stringify(translateOptionsFileURL)};\n` +
79
- `export default await translateOptions(${JSON.stringify(options)}, "flat");\n`;
74
+ `export default await translateOptions(${JSON.stringify(options)});\n`;
80
75
 
81
76
  // Base64 encoding is typically shorter than URL encoding
82
77
  return new URL(
@@ -199,32 +194,14 @@ const cli = {
199
194
  * Executes the CLI based on an array of arguments that is passed in.
200
195
  * @param {string|Array|Object} args The arguments to process.
201
196
  * @param {string} [text] The text to lint (used for TTY).
202
- * @param {boolean} [allowFlatConfig=true] Whether or not to allow flat config.
203
197
  * @returns {Promise<number>} The exit code for the operation.
204
198
  */
205
- async execute(args, text, allowFlatConfig = true) {
199
+ async execute(args, text) {
206
200
  if (Array.isArray(args)) {
207
201
  debug("CLI args: %o", args.slice(2));
208
202
  }
209
203
 
210
- /*
211
- * Before doing anything, we need to see if we are using a
212
- * flat config file. If so, then we need to change the way command
213
- * line args are parsed. This is temporary, and when we fully
214
- * switch to flat config we can remove this logic.
215
- */
216
-
217
- const usingFlatConfig =
218
- allowFlatConfig && (await shouldUseFlatConfig());
219
-
220
- debug("Using flat config?", usingFlatConfig);
221
-
222
- if (allowFlatConfig && !usingFlatConfig) {
223
- const { WarningService } = require("./services/warning-service");
224
- new WarningService().emitESLintRCWarning();
225
- }
226
-
227
- const CLIOptions = createCLIOptions(usingFlatConfig);
204
+ const CLIOptions = createCLIOptions();
228
205
 
229
206
  /** @type {ParsedCLIOptions} */
230
207
  let options;
@@ -233,16 +210,7 @@ const cli = {
233
210
  options = CLIOptions.parse(args);
234
211
  validateConcurrency(options.concurrency);
235
212
  } catch (error) {
236
- debug("Error parsing CLI options:", error.message);
237
-
238
- let errorMessage = error.message;
239
-
240
- if (usingFlatConfig) {
241
- errorMessage +=
242
- "\nYou're using eslint.config.js, some command line flags are no longer available. Please see https://eslint.org/docs/latest/use/command-line-interface for details.";
243
- }
244
-
245
- log.error(errorMessage);
213
+ log.error(error.message);
246
214
  return 2;
247
215
  }
248
216
 
@@ -282,9 +250,7 @@ const cli = {
282
250
  return 2;
283
251
  }
284
252
 
285
- const engine = usingFlatConfig
286
- ? new ESLint(await translateOptions(options, "flat"))
287
- : new LegacyESLint(await translateOptions(options));
253
+ const engine = new ESLint(await translateOptions(options));
288
254
  const fileConfig = await engine.calculateConfigForFile(
289
255
  options.printConfig,
290
256
  );
@@ -299,7 +265,7 @@ const cli = {
299
265
  );
300
266
 
301
267
  try {
302
- const flatOptions = await translateOptions(options, "flat");
268
+ const flatOptions = await translateOptions(options);
303
269
  const spawn = require("cross-spawn");
304
270
  const flags = await cli.calculateInspectConfigFlags(
305
271
  flatOptions.overrideConfigFile,
@@ -349,7 +315,7 @@ const cli = {
349
315
  return 2;
350
316
  }
351
317
 
352
- if (usingFlatConfig && options.ext) {
318
+ if (options.ext) {
353
319
  // Passing `--ext ""` results in `options.ext` being an empty array.
354
320
  if (options.ext.length === 0) {
355
321
  log.error("The --ext option value cannot be empty.");
@@ -400,29 +366,21 @@ const cli = {
400
366
  return 2;
401
367
  }
402
368
 
403
- const ActiveESLint = usingFlatConfig ? ESLint : LegacyESLint;
404
-
405
- /** @type {ESLint|LegacyESLint} */
369
+ /** @type {ESLint} */
406
370
  let engine;
407
371
 
408
- if (options.concurrency && options.concurrency !== "off") {
372
+ if (options.concurrency !== "off") {
409
373
  const optionsURL = createOptionsModule(options);
410
374
  engine = await ESLint.fromOptionsModule(optionsURL);
411
375
  } else {
412
- const eslintOptions = await translateOptions(
413
- options,
414
- usingFlatConfig ? "flat" : "eslintrc",
415
- );
416
- engine = new ActiveESLint(eslintOptions);
376
+ const eslintOptions = await translateOptions(options);
377
+ engine = new ESLint(eslintOptions);
417
378
  }
418
379
  let results;
419
380
 
420
381
  if (useStdin) {
421
382
  results = await engine.lintText(text, {
422
383
  filePath: options.stdinFilename,
423
-
424
- // flatConfig respects CLI flag and constructor warnIgnored, eslintrc forces true for backwards compatibility
425
- warnIgnored: usingFlatConfig ? void 0 : true,
426
384
  });
427
385
  } else {
428
386
  results = await engine.lintFiles(files);
@@ -430,7 +388,7 @@ const cli = {
430
388
 
431
389
  if (options.fix) {
432
390
  debug("Fix mode enabled - applying fixes");
433
- await ActiveESLint.outputFixes(results);
391
+ await ESLint.outputFixes(results);
434
392
  }
435
393
 
436
394
  let unusedSuppressions = {};
@@ -489,7 +447,7 @@ const cli = {
489
447
 
490
448
  if (options.quiet) {
491
449
  debug("Quiet mode enabled - filtering out warnings");
492
- resultsToPrint = ActiveESLint.getErrorResults(resultsToPrint);
450
+ resultsToPrint = ESLint.getErrorResults(resultsToPrint);
493
451
  }
494
452
 
495
453
  const resultCounts = countErrors(results);
@@ -147,8 +147,11 @@ async function loadTypeScriptConfigFileWithJiti(filePath, fileURL, mtime) {
147
147
  );
148
148
  });
149
149
 
150
- // `createJiti` was added in jiti v2.
151
- if (typeof createJiti !== "function") {
150
+ // Ensure the version is at least 2.2.0.
151
+ const [jitiMajor, jitiMinor] = jitiVersion
152
+ .split(".")
153
+ .map(versionPart => Number(versionPart));
154
+ if (jitiMajor < 2 || (jitiMajor === 2 && jitiMinor < 2)) {
152
155
  throw new Error(
153
156
  "You are using an outdated version of the 'jiti' library. Please update to the latest version of 'jiti' to ensure compatibility and access to the latest features.",
154
157
  );
@@ -162,10 +165,6 @@ async function loadTypeScriptConfigFileWithJiti(filePath, fileURL, mtime) {
162
165
  moduleCache: false,
163
166
  };
164
167
 
165
- if (jitiVersion.startsWith("2.1.")) {
166
- jitiOptions.interopDefault = false;
167
- }
168
-
169
168
  const jiti = createJiti(__filename, jitiOptions);
170
169
  const config = await jiti.import(fileURL.href);
171
170
 
@@ -666,151 +665,4 @@ class ConfigLoader {
666
665
  }
667
666
  }
668
667
 
669
- /**
670
- * Encapsulates the loading and caching of configuration files when looking up
671
- * from the current working directory.
672
- */
673
- class LegacyConfigLoader extends ConfigLoader {
674
- /**
675
- * The options to use when loading configuration files.
676
- * @type {ConfigLoaderOptions}
677
- */
678
- #options;
679
-
680
- /**
681
- * The cached config file path for this instance.
682
- * @type {Promise<{configFilePath:string,basePath:string}|undefined>}
683
- */
684
- #configFilePath;
685
-
686
- /**
687
- * The cached config array for this instance.
688
- * @type {FlatConfigArray|Promise<FlatConfigArray>}
689
- */
690
- #configArray;
691
-
692
- /**
693
- * Creates a new instance.
694
- * @param {ConfigLoaderOptions} options The options to use when loading configuration files.
695
- */
696
- constructor(options) {
697
- const normalizedOptions = options.warningService
698
- ? options
699
- : { ...options, warningService: new WarningService() };
700
- super(normalizedOptions);
701
- this.#options = normalizedOptions;
702
- }
703
-
704
- /**
705
- * Determines which config file to use. This is determined by seeing if an
706
- * override config file was specified, and if so, using it; otherwise, as long
707
- * as override config file is not explicitly set to `false`, it will search
708
- * upwards from the cwd for a file named `eslint.config.js`.
709
- * @returns {Promise<{configFilePath:string|undefined,basePath:string}>} Location information for
710
- * the config file.
711
- */
712
- #locateConfigFileToUse() {
713
- if (!this.#configFilePath) {
714
- this.#configFilePath = ConfigLoader.locateConfigFileToUse({
715
- useConfigFile: this.#options.configFile,
716
- cwd: this.#options.cwd,
717
- });
718
- }
719
-
720
- return this.#configFilePath;
721
- }
722
-
723
- /**
724
- * Calculates the config array for this run based on inputs.
725
- * @param {string} configFilePath The absolute path to the config file to use if not overridden.
726
- * @param {string} basePath The base path to use for relative paths in the config file.
727
- * @returns {Promise<FlatConfigArray>} The config array for `eslint`.
728
- */
729
- async #calculateConfigArray(configFilePath, basePath) {
730
- // check for cached version first
731
- if (this.#configArray) {
732
- return this.#configArray;
733
- }
734
-
735
- // ensure `ConfigLoader.calculateConfigArray` is called only once
736
- this.#configArray = ConfigLoader.calculateConfigArray(
737
- configFilePath,
738
- basePath,
739
- this.#options,
740
- );
741
-
742
- // Unwrap the promise. This is primarily for the sync `getCachedConfigArrayForPath` method.
743
- this.#configArray = await this.#configArray;
744
-
745
- return this.#configArray;
746
- }
747
-
748
- /**
749
- * Returns the config file path for the given directory. This will either use
750
- * the override config file that was specified in the constructor options or
751
- * search for a config file from the directory of the file being linted.
752
- * @param {string} dirPath The directory path to get the config file path for.
753
- * @returns {Promise<string|undefined>} The config file path or `undefined` if not found.
754
- * @throws {Error} If `fileOrDirPath` is not a non-empty string.
755
- * @throws {Error} If `fileOrDirPath` is not an absolute path.
756
- */
757
- async findConfigFileForPath(dirPath) {
758
- assertValidFilePath(dirPath);
759
-
760
- const { configFilePath } = await this.#locateConfigFileToUse();
761
-
762
- return configFilePath;
763
- }
764
-
765
- /**
766
- * Returns a configuration object for the given file based on the CLI options.
767
- * This is the same logic used by the ESLint CLI executable to determine
768
- * configuration for each file it processes.
769
- * @param {string} dirPath The path of the directory to retrieve config for.
770
- * @returns {Promise<FlatConfigArray>} A configuration object for the file.
771
- */
772
- async loadConfigArrayForDirectory(dirPath) {
773
- assertValidFilePath(dirPath);
774
-
775
- debug(`[Legacy]: Calculating config for ${dirPath}`);
776
-
777
- const { configFilePath, basePath } =
778
- await this.#locateConfigFileToUse();
779
-
780
- debug(
781
- `[Legacy]: Using config file ${configFilePath} and base path ${basePath}`,
782
- );
783
- return this.#calculateConfigArray(configFilePath, basePath);
784
- }
785
-
786
- /**
787
- * Returns a configuration array for the given directory based on the CLI options.
788
- * This is a synchronous operation and does not read any files from disk. It's
789
- * intended to be used in locations where we know the config file has already
790
- * been loaded and we just need to get the configuration for a file.
791
- * @param {string} dirPath The path of the directory to retrieve a config object for.
792
- * @returns {FlatConfigArray} A configuration object for the file.
793
- * @throws {Error} If `dirPath` is not a non-empty string.
794
- * @throws {Error} If `dirPath` is not an absolute path.
795
- * @throws {Error} If the config file was not already loaded.
796
- */
797
- getCachedConfigArrayForPath(dirPath) {
798
- assertValidFilePath(dirPath);
799
-
800
- debug(`[Legacy]: Looking up cached config for ${dirPath}`);
801
-
802
- if (!this.#configArray) {
803
- throw new Error(`Could not find config file for ${dirPath}`);
804
- }
805
-
806
- if (typeof this.#configArray.then === "function") {
807
- throw new Error(
808
- `Config array for ${dirPath} has not yet been calculated or an error occurred during the calculation`,
809
- );
810
- }
811
-
812
- return this.#configArray;
813
- }
814
- }
815
-
816
- module.exports = { ConfigLoader, LegacyConfigLoader };
668
+ module.exports = { ConfigLoader };
@@ -20,7 +20,7 @@ const globParent = require("glob-parent");
20
20
  const { Linter } = require("../linter");
21
21
  const { getShorthandName } = require("../shared/naming");
22
22
  const LintResultCache = require("../cli-engine/lint-result-cache");
23
- const { ConfigLoader, LegacyConfigLoader } = require("../config/config-loader");
23
+ const { ConfigLoader } = require("../config/config-loader");
24
24
  const createDebug = require("debug");
25
25
 
26
26
  //-----------------------------------------------------------------------------
@@ -247,7 +247,7 @@ async function globMatch({ basePath, pattern }) {
247
247
  * to match.
248
248
  * @param {Array<string>} options.rawPatterns An array of glob patterns
249
249
  * as the user inputted them. Used for errors.
250
- * @param {ConfigLoader|LegacyConfigLoader} options.configLoader The config array to use for
250
+ * @param {ConfigLoader} options.configLoader The config array to use for
251
251
  * determining what to ignore.
252
252
  * @param {boolean} options.errorOnUnmatchedPattern Determines if an error
253
253
  * should be thrown when a pattern is unmatched.
@@ -425,7 +425,7 @@ async function throwErrorForUnmatchedPatterns({
425
425
  * @param {Object} options The options for this function.
426
426
  * @param {Map<string,GlobSearch>} options.searches
427
427
  * A map of absolute path glob patterns to match.
428
- * @param {ConfigLoader|LegacyConfigLoader} options.configLoader The config loader to use for
428
+ * @param {ConfigLoader} options.configLoader The config loader to use for
429
429
  * determining what to ignore.
430
430
  * @param {boolean} options.errorOnUnmatchedPattern Determines if an
431
431
  * unmatched glob pattern should throw an error.
@@ -506,7 +506,7 @@ async function globMultiSearch({
506
506
  * @param {boolean} args.globInputPaths true to interpret glob patterns,
507
507
  * false to not interpret glob patterns.
508
508
  * @param {string} args.cwd The current working directory to find from.
509
- * @param {ConfigLoader|LegacyConfigLoader} args.configLoader The config loader for the current run.
509
+ * @param {ConfigLoader} args.configLoader The config loader for the current run.
510
510
  * @param {boolean} args.errorOnUnmatchedPattern Determines if an unmatched pattern
511
511
  * should throw an error.
512
512
  * @returns {Promise<Array<string>>} The fully resolved file paths.
@@ -708,7 +708,6 @@ function createIgnoreResult(filePath, baseDir, configStatus) {
708
708
  fatal: false,
709
709
  severity: 1,
710
710
  message,
711
- nodeType: null,
712
711
  },
713
712
  ],
714
713
  suppressedMessages: [],
@@ -1428,9 +1427,7 @@ function createConfigLoader(
1428
1427
  warningService,
1429
1428
  };
1430
1429
 
1431
- return linter.hasFlag("v10_config_lookup_from_file")
1432
- ? new ConfigLoader(configLoaderOptions)
1433
- : new LegacyConfigLoader(configLoaderOptions);
1430
+ return new ConfigLoader(configLoaderOptions);
1434
1431
  }
1435
1432
 
1436
1433
  //-----------------------------------------------------------------------------
@@ -1347,7 +1347,7 @@ class ESLint {
1347
1347
  * @returns {Promise<boolean>} Whether flat config should be used.
1348
1348
  */
1349
1349
  async function shouldUseFlatConfig() {
1350
- return process.env.ESLINT_USE_FLAT_CONFIG !== "false";
1350
+ return true;
1351
1351
  }
1352
1352
 
1353
1353
  //------------------------------------------------------------------------------
@@ -1,9 +1,7 @@
1
1
  "use strict";
2
2
 
3
3
  const { ESLint } = require("./eslint");
4
- const { LegacyESLint } = require("./legacy-eslint");
5
4
 
6
5
  module.exports = {
7
6
  ESLint,
8
- LegacyESLint,
9
7
  };
@@ -20,8 +20,7 @@ const { isCommentToken } = require("@eslint-community/eslint-utils"),
20
20
  VisitNodeStep,
21
21
  CallMethodStep,
22
22
  Directive,
23
- } = require("@eslint/plugin-kit"),
24
- eslintScope = require("eslint-scope");
23
+ } = require("@eslint/plugin-kit");
25
24
 
26
25
  //------------------------------------------------------------------------------
27
26
  // Type Definitions
@@ -29,6 +28,7 @@ const { isCommentToken } = require("@eslint-community/eslint-utils"),
29
28
 
30
29
  /** @typedef {import("eslint-scope").Variable} Variable */
31
30
  /** @typedef {import("eslint-scope").Scope} Scope */
31
+ /** @typedef {import("eslint-scope").ScopeManager} ScopeManager */
32
32
  /** @typedef {import("@eslint/core").SourceCode} ISourceCode */
33
33
  /** @typedef {import("@eslint/core").Directive} IDirective */
34
34
  /** @typedef {import("@eslint/core").TraversalStep} ITraversalStep */
@@ -264,103 +264,37 @@ function findLineNumberBinarySearch(lineStartIndices, target) {
264
264
  * Ensures that variables representing built-in properties of the Global Object,
265
265
  * and any globals declared by special block comments, are present in the global
266
266
  * scope.
267
- * @param {Scope} globalScope The global scope.
267
+ * @param {ScopeManager} scopeManager Scope manager.
268
268
  * @param {Object|undefined} configGlobals The globals declared in configuration
269
269
  * @param {Object|undefined} inlineGlobals The globals declared in the source code
270
270
  * @returns {void}
271
271
  */
272
272
  function addDeclaredGlobals(
273
- globalScope,
274
- configGlobals = {},
275
- inlineGlobals = {},
273
+ scopeManager,
274
+ configGlobals = Object.create(null),
275
+ inlineGlobals = Object.create(null),
276
276
  ) {
277
- // Define configured global variables.
278
- for (const id of new Set([
279
- ...Object.keys(configGlobals),
280
- ...Object.keys(inlineGlobals),
281
- ])) {
282
- /*
283
- * `normalizeConfigGlobal` will throw an error if a configured global value is invalid. However, these errors would
284
- * typically be caught when validating a config anyway (validity for inline global comments is checked separately).
285
- */
286
- const configValue =
287
- configGlobals[id] === void 0
288
- ? void 0
289
- : normalizeConfigGlobal(configGlobals[id]);
290
- const commentValue = inlineGlobals[id] && inlineGlobals[id].value;
291
- const value = commentValue || configValue;
292
- const sourceComments = inlineGlobals[id] && inlineGlobals[id].comments;
293
-
294
- if (value === "off") {
295
- continue;
296
- }
297
-
298
- let variable = globalScope.set.get(id);
299
-
300
- if (!variable) {
301
- variable = new eslintScope.Variable(id, globalScope);
302
-
303
- globalScope.variables.push(variable);
304
- globalScope.set.set(id, variable);
305
- }
277
+ const finalGlobals = { __proto__: null, ...configGlobals };
306
278
 
307
- variable.eslintImplicitGlobalSetting = configValue;
308
- variable.eslintExplicitGlobal = sourceComments !== void 0;
309
- variable.eslintExplicitGlobalComments = sourceComments;
310
- variable.writeable = value === "writable";
279
+ for (const [name, data] of Object.entries(inlineGlobals)) {
280
+ finalGlobals[name] = data.value;
311
281
  }
312
282
 
313
- /*
314
- * "through" contains all references which definitions cannot be found.
315
- * Since we augment the global scope using configuration, we need to update
316
- * references and remove the ones that were added by configuration.
317
- */
318
- globalScope.through = globalScope.through.filter(reference => {
319
- const name = reference.identifier.name;
320
- const variable = globalScope.set.get(name);
321
-
322
- if (variable) {
323
- /*
324
- * Links the variable and the reference.
325
- * And this reference is removed from `Scope#through`.
326
- */
327
- reference.resolved = variable;
328
- variable.references.push(reference);
283
+ const names = Object.keys(finalGlobals).filter(
284
+ name => finalGlobals[name] !== "off",
285
+ );
329
286
 
330
- return false;
331
- }
287
+ scopeManager.addGlobals(names);
332
288
 
333
- return true;
334
- });
289
+ const globalScope = scopeManager.scopes[0];
335
290
 
336
- /*
337
- * "implicit" contains information about implicit global variables (those created
338
- * implicitly by assigning values to undeclared variables in non-strict code).
339
- * Since we augment the global scope using configuration, we need to remove
340
- * the ones that were added by configuration, as they are either built-in
341
- * or declared elsewhere, therefore not implicit.
342
- * Since the "implicit" property was not documented, first we'll check if it exists
343
- * because it's possible that not all custom scope managers create this property.
344
- * If it exists, we assume it has properties `variables` and `set`. Property
345
- * `left` is considered optional (for example, typescript-eslint's scope manage
346
- * has this property named `leftToBeResolved`).
347
- */
348
- const { implicit } = globalScope;
349
- if (typeof implicit === "object" && implicit !== null) {
350
- implicit.variables = implicit.variables.filter(variable => {
351
- const name = variable.name;
352
- if (globalScope.set.has(name)) {
353
- implicit.set.delete(name);
354
- return false;
355
- }
356
- return true;
357
- });
291
+ for (const name of names) {
292
+ const variable = globalScope.set.get(name);
358
293
 
359
- if (implicit.left) {
360
- implicit.left = implicit.left.filter(
361
- reference => !globalScope.set.has(reference.identifier.name),
362
- );
363
- }
294
+ variable.eslintImplicitGlobalSetting = configGlobals[name];
295
+ variable.eslintExplicitGlobal = !!inlineGlobals[name];
296
+ variable.eslintExplicitGlobalComments = inlineGlobals[name]?.comments;
297
+ variable.writeable = finalGlobals[name] === "writable";
364
298
  }
365
299
  }
366
300
 
@@ -1162,6 +1096,15 @@ class SourceCode extends TokenStore {
1162
1096
  : void 0,
1163
1097
  languageOptions.globals,
1164
1098
  );
1099
+
1100
+ /*
1101
+ * `normalizeConfigGlobal` will throw an error if a configured global value is invalid. However, these errors would
1102
+ * typically be caught when validating a config anyway (validity for inline global comments is checked separately).
1103
+ */
1104
+ for (const [name, value] of Object.entries(configGlobals)) {
1105
+ configGlobals[name] = normalizeConfigGlobal(value);
1106
+ }
1107
+
1165
1108
  const varsCache = this[caches].get("vars");
1166
1109
 
1167
1110
  varsCache.set("configGlobals", configGlobals);
@@ -1243,6 +1186,15 @@ class SourceCode extends TokenStore {
1243
1186
 
1244
1187
  break;
1245
1188
  }
1189
+ case "eslint-env": {
1190
+ problems.push({
1191
+ ruleId: null,
1192
+ loc: comment.loc,
1193
+ message:
1194
+ "/* eslint-env */ comments are no longer supported.",
1195
+ });
1196
+ break;
1197
+ }
1246
1198
 
1247
1199
  // no default
1248
1200
  }
@@ -1273,7 +1225,7 @@ class SourceCode extends TokenStore {
1273
1225
  const exportedVariables = varsCache.get("exportedVariables");
1274
1226
  const globalScope = this.scopeManager.scopes[0];
1275
1227
 
1276
- addDeclaredGlobals(globalScope, configGlobals, inlineGlobals);
1228
+ addDeclaredGlobals(this.scopeManager, configGlobals, inlineGlobals);
1277
1229
 
1278
1230
  if (exportedVariables) {
1279
1231
  markExportedVariables(globalScope, exportedVariables);