eslint 8.56.0 → 8.57.1

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.
package/lib/api.js CHANGED
@@ -9,17 +9,45 @@
9
9
  // Requirements
10
10
  //-----------------------------------------------------------------------------
11
11
 
12
- const { ESLint } = require("./eslint");
12
+ const { ESLint, FlatESLint } = require("./eslint");
13
+ const { shouldUseFlatConfig } = require("./eslint/flat-eslint");
13
14
  const { Linter } = require("./linter");
14
15
  const { RuleTester } = require("./rule-tester");
15
16
  const { SourceCode } = require("./source-code");
16
17
 
18
+ //-----------------------------------------------------------------------------
19
+ // Functions
20
+ //-----------------------------------------------------------------------------
21
+
22
+ /**
23
+ * 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
+ * @param {string} [options.cwd] The current working directory
27
+ * @returns {Promise<ESLint|LegacyESLint>} The ESLint constructor
28
+ */
29
+ async function loadESLint({ useFlatConfig, cwd = process.cwd() } = {}) {
30
+
31
+ /*
32
+ * Note: The v9.x version of this function doesn't have a cwd option
33
+ * because it's not used. It's only used in the v8.x version of this
34
+ * function.
35
+ */
36
+
37
+ const shouldESLintUseFlatConfig = typeof useFlatConfig === "boolean"
38
+ ? useFlatConfig
39
+ : await shouldUseFlatConfig({ cwd });
40
+
41
+ return shouldESLintUseFlatConfig ? FlatESLint : ESLint;
42
+ }
43
+
17
44
  //-----------------------------------------------------------------------------
18
45
  // Exports
19
46
  //-----------------------------------------------------------------------------
20
47
 
21
48
  module.exports = {
22
49
  Linter,
50
+ loadESLint,
23
51
  ESLint,
24
52
  RuleTester,
25
53
  SourceCode
@@ -19,6 +19,11 @@ const jsPlugin = require("@eslint/js");
19
19
  // Helpers
20
20
  //-----------------------------------------------------------------------------
21
21
 
22
+ /**
23
+ * Fields that are considered metadata and not part of the config object.
24
+ */
25
+ const META_FIELDS = new Set(["name"]);
26
+
22
27
  const ruleValidator = new RuleValidator();
23
28
 
24
29
  /**
@@ -75,7 +80,53 @@ function getObjectId(object) {
75
80
  return name;
76
81
  }
77
82
 
83
+ /**
84
+ * Wraps a config error with details about where the error occurred.
85
+ * @param {Error} error The original error.
86
+ * @param {number} originalLength The original length of the config array.
87
+ * @param {number} baseLength The length of the base config.
88
+ * @returns {TypeError} The new error with details.
89
+ */
90
+ function wrapConfigErrorWithDetails(error, originalLength, baseLength) {
91
+
92
+ let location = "user-defined";
93
+ let configIndex = error.index;
94
+
95
+ /*
96
+ * A config array is set up in this order:
97
+ * 1. Base config
98
+ * 2. Original configs
99
+ * 3. User-defined configs
100
+ * 4. CLI-defined configs
101
+ *
102
+ * So we need to adjust the index to account for the base config.
103
+ *
104
+ * - If the index is less than the base length, it's in the base config
105
+ * (as specified by `baseConfig` argument to `FlatConfigArray` constructor).
106
+ * - If the index is greater than the base length but less than the original
107
+ * length + base length, it's in the original config. The original config
108
+ * is passed to the `FlatConfigArray` constructor as the first argument.
109
+ * - Otherwise, it's in the user-defined config, which is loaded from the
110
+ * config file and merged with any command-line options.
111
+ */
112
+ if (error.index < baseLength) {
113
+ location = "base";
114
+ } else if (error.index < originalLength + baseLength) {
115
+ location = "original";
116
+ configIndex = error.index - baseLength;
117
+ } else {
118
+ configIndex = error.index - originalLength - baseLength;
119
+ }
120
+
121
+ return new TypeError(
122
+ `${error.message.slice(0, -1)} at ${location} index ${configIndex}.`,
123
+ { cause: error }
124
+ );
125
+ }
126
+
78
127
  const originalBaseConfig = Symbol("originalBaseConfig");
128
+ const originalLength = Symbol("originalLength");
129
+ const baseLength = Symbol("baseLength");
79
130
 
80
131
  //-----------------------------------------------------------------------------
81
132
  // Exports
@@ -102,12 +153,24 @@ class FlatConfigArray extends ConfigArray {
102
153
  schema: flatConfigSchema
103
154
  });
104
155
 
156
+ /**
157
+ * The original length of the array before any modifications.
158
+ * @type {number}
159
+ */
160
+ this[originalLength] = this.length;
161
+
105
162
  if (baseConfig[Symbol.iterator]) {
106
163
  this.unshift(...baseConfig);
107
164
  } else {
108
165
  this.unshift(baseConfig);
109
166
  }
110
167
 
168
+ /**
169
+ * The length of the array after applying the base config.
170
+ * @type {number}
171
+ */
172
+ this[baseLength] = this.length - this[originalLength];
173
+
111
174
  /**
112
175
  * The base config used to build the config array.
113
176
  * @type {Array<FlatConfig>}
@@ -125,6 +188,49 @@ class FlatConfigArray extends ConfigArray {
125
188
  Object.defineProperty(this, "shouldIgnore", { writable: false });
126
189
  }
127
190
 
191
+ /**
192
+ * Normalizes the array by calling the superclass method and catching/rethrowing
193
+ * any ConfigError exceptions with additional details.
194
+ * @param {any} [context] The context to use to normalize the array.
195
+ * @returns {Promise<FlatConfigArray>} A promise that resolves when the array is normalized.
196
+ */
197
+ normalize(context) {
198
+ return super.normalize(context)
199
+ .catch(error => {
200
+ if (error.name === "ConfigError") {
201
+ throw wrapConfigErrorWithDetails(error, this[originalLength], this[baseLength]);
202
+ }
203
+
204
+ throw error;
205
+
206
+ });
207
+ }
208
+
209
+ /**
210
+ * Normalizes the array by calling the superclass method and catching/rethrowing
211
+ * any ConfigError exceptions with additional details.
212
+ * @param {any} [context] The context to use to normalize the array.
213
+ * @returns {FlatConfigArray} The current instance.
214
+ * @throws {TypeError} If the config is invalid.
215
+ */
216
+ normalizeSync(context) {
217
+
218
+ try {
219
+
220
+ return super.normalizeSync(context);
221
+
222
+ } catch (error) {
223
+
224
+ if (error.name === "ConfigError") {
225
+ throw wrapConfigErrorWithDetails(error, this[originalLength], this[baseLength]);
226
+ }
227
+
228
+ throw error;
229
+
230
+ }
231
+
232
+ }
233
+
128
234
  /* eslint-disable class-methods-use-this -- Desired as instance method */
129
235
  /**
130
236
  * Replaces a config with another config to allow us to put strings
@@ -155,15 +261,15 @@ class FlatConfigArray extends ConfigArray {
155
261
  }
156
262
 
157
263
  /*
158
- * If `shouldIgnore` is false, we remove any ignore patterns specified
159
- * in the config so long as it's not a default config and it doesn't
160
- * have a `files` entry.
264
+ * If a config object has `ignores` and no other non-meta fields, then it's an object
265
+ * for global ignores. If `shouldIgnore` is false, that object shouldn't apply,
266
+ * so we'll remove its `ignores`.
161
267
  */
162
268
  if (
163
269
  !this.shouldIgnore &&
164
270
  !this[originalBaseConfig].includes(config) &&
165
271
  config.ignores &&
166
- !config.files
272
+ Object.keys(config).filter(key => !META_FIELDS.has(key)).length === 1
167
273
  ) {
168
274
  /* eslint-disable-next-line no-unused-vars -- need to strip off other keys */
169
275
  const { ignores, ...otherKeys } = config;
@@ -53,6 +53,15 @@ function isNonNullObject(value) {
53
53
  return typeof value === "object" && value !== null;
54
54
  }
55
55
 
56
+ /**
57
+ * Check if a value is a non-null non-array object.
58
+ * @param {any} value The value to check.
59
+ * @returns {boolean} `true` if the value is a non-null non-array object.
60
+ */
61
+ function isNonArrayObject(value) {
62
+ return isNonNullObject(value) && !Array.isArray(value);
63
+ }
64
+
56
65
  /**
57
66
  * Check if a value is undefined.
58
67
  * @param {any} value The value to check.
@@ -63,19 +72,27 @@ function isUndefined(value) {
63
72
  }
64
73
 
65
74
  /**
66
- * Deeply merges two objects.
75
+ * Deeply merges two non-array objects.
67
76
  * @param {Object} first The base object.
68
77
  * @param {Object} second The overrides object.
78
+ * @param {Map<string, Map<string, Object>>} [mergeMap] Maps the combination of first and second arguments to a merged result.
69
79
  * @returns {Object} An object with properties from both first and second.
70
80
  */
71
- function deepMerge(first = {}, second = {}) {
81
+ function deepMerge(first, second, mergeMap = new Map()) {
72
82
 
73
- /*
74
- * If the second value is an array, just return it. We don't merge
75
- * arrays because order matters and we can't know the correct order.
76
- */
77
- if (Array.isArray(second)) {
78
- return second;
83
+ let secondMergeMap = mergeMap.get(first);
84
+
85
+ if (secondMergeMap) {
86
+ const result = secondMergeMap.get(second);
87
+
88
+ if (result) {
89
+
90
+ // If this combination of first and second arguments has been already visited, return the previously created result.
91
+ return result;
92
+ }
93
+ } else {
94
+ secondMergeMap = new Map();
95
+ mergeMap.set(first, secondMergeMap);
79
96
  }
80
97
 
81
98
  /*
@@ -89,27 +106,25 @@ function deepMerge(first = {}, second = {}) {
89
106
  ...second
90
107
  };
91
108
 
109
+ delete result.__proto__; // eslint-disable-line no-proto -- don't merge own property "__proto__"
110
+
111
+ // Store the pending result for this combination of first and second arguments.
112
+ secondMergeMap.set(second, result);
113
+
92
114
  for (const key of Object.keys(second)) {
93
115
 
94
116
  // avoid hairy edge case
95
- if (key === "__proto__") {
117
+ if (key === "__proto__" || !Object.prototype.propertyIsEnumerable.call(first, key)) {
96
118
  continue;
97
119
  }
98
120
 
99
121
  const firstValue = first[key];
100
122
  const secondValue = second[key];
101
123
 
102
- if (isNonNullObject(firstValue)) {
103
- result[key] = deepMerge(firstValue, secondValue);
104
- } else if (isUndefined(firstValue)) {
105
- if (isNonNullObject(secondValue)) {
106
- result[key] = deepMerge(
107
- Array.isArray(secondValue) ? [] : {},
108
- secondValue
109
- );
110
- } else if (!isUndefined(secondValue)) {
111
- result[key] = secondValue;
112
- }
124
+ if (isNonArrayObject(firstValue) && isNonArrayObject(secondValue)) {
125
+ result[key] = deepMerge(firstValue, secondValue, mergeMap);
126
+ } else if (isUndefined(secondValue)) {
127
+ result[key] = firstValue;
113
128
  }
114
129
  }
115
130
 
@@ -15,7 +15,6 @@ const fsp = fs.promises;
15
15
  const isGlob = require("is-glob");
16
16
  const hash = require("../cli-engine/hash");
17
17
  const minimatch = require("minimatch");
18
- const util = require("util");
19
18
  const fswalk = require("@nodelib/fs.walk");
20
19
  const globParent = require("glob-parent");
21
20
  const isPathInside = require("is-path-inside");
@@ -24,7 +23,6 @@ const isPathInside = require("is-path-inside");
24
23
  // Fixup references
25
24
  //-----------------------------------------------------------------------------
26
25
 
27
- const doFsWalk = util.promisify(fswalk.walk);
28
26
  const Minimatch = minimatch.Minimatch;
29
27
  const MINIMATCH_OPTIONS = { dot: true };
30
28
 
@@ -270,56 +268,92 @@ async function globSearch({
270
268
  */
271
269
  const unmatchedPatterns = new Set([...relativeToPatterns.keys()]);
272
270
 
273
- const filePaths = (await doFsWalk(basePath, {
271
+ const filePaths = (await new Promise((resolve, reject) => {
274
272
 
275
- deepFilter(entry) {
276
- const relativePath = normalizeToPosix(path.relative(basePath, entry.path));
277
- const matchesPattern = matchers.some(matcher => matcher.match(relativePath, true));
278
-
279
- return matchesPattern && !configs.isDirectoryIgnored(entry.path);
280
- },
281
- entryFilter(entry) {
282
- const relativePath = normalizeToPosix(path.relative(basePath, entry.path));
273
+ let promiseRejected = false;
283
274
 
284
- // entries may be directories or files so filter out directories
285
- if (entry.dirent.isDirectory()) {
275
+ /**
276
+ * Wraps a boolean-returning filter function. The wrapped function will reject the promise if an error occurs.
277
+ * @param {Function} filter A filter function to wrap.
278
+ * @returns {Function} A function similar to the wrapped filter that rejects the promise if an error occurs.
279
+ */
280
+ function wrapFilter(filter) {
281
+ return (...args) => {
282
+
283
+ // No need to run the filter if an error has been thrown.
284
+ if (!promiseRejected) {
285
+ try {
286
+ return filter(...args);
287
+ } catch (error) {
288
+ promiseRejected = true;
289
+ reject(error);
290
+ }
291
+ }
286
292
  return false;
287
- }
293
+ };
294
+ }
288
295
 
289
- /*
290
- * Optimization: We need to track when patterns are left unmatched
291
- * and so we use `unmatchedPatterns` to do that. There is a bit of
292
- * complexity here because the same file can be matched by more than
293
- * one pattern. So, when we start, we actually need to test every
294
- * pattern against every file. Once we know there are no remaining
295
- * unmatched patterns, then we can switch to just looking for the
296
- * first matching pattern for improved speed.
297
- */
298
- const matchesPattern = unmatchedPatterns.size > 0
299
- ? matchers.reduce((previousValue, matcher) => {
300
- const pathMatches = matcher.match(relativePath);
296
+ fswalk.walk(
297
+ basePath,
298
+ {
299
+ deepFilter: wrapFilter(entry => {
300
+ const relativePath = normalizeToPosix(path.relative(basePath, entry.path));
301
+ const matchesPattern = matchers.some(matcher => matcher.match(relativePath, true));
302
+
303
+ return matchesPattern && !configs.isDirectoryIgnored(entry.path);
304
+ }),
305
+ entryFilter: wrapFilter(entry => {
306
+ const relativePath = normalizeToPosix(path.relative(basePath, entry.path));
307
+
308
+ // entries may be directories or files so filter out directories
309
+ if (entry.dirent.isDirectory()) {
310
+ return false;
311
+ }
301
312
 
302
313
  /*
303
- * We updated the unmatched patterns set only if the path
304
- * matches and the file isn't ignored. If the file is
305
- * ignored, that means there wasn't a match for the
306
- * pattern so it should not be removed.
307
- *
308
- * Performance note: isFileIgnored() aggressively caches
309
- * results so there is no performance penalty for calling
310
- * it twice with the same argument.
314
+ * Optimization: We need to track when patterns are left unmatched
315
+ * and so we use `unmatchedPatterns` to do that. There is a bit of
316
+ * complexity here because the same file can be matched by more than
317
+ * one pattern. So, when we start, we actually need to test every
318
+ * pattern against every file. Once we know there are no remaining
319
+ * unmatched patterns, then we can switch to just looking for the
320
+ * first matching pattern for improved speed.
311
321
  */
312
- if (pathMatches && !configs.isFileIgnored(entry.path)) {
313
- unmatchedPatterns.delete(matcher.pattern);
314
- }
315
-
316
- return pathMatches || previousValue;
317
- }, false)
318
- : matchers.some(matcher => matcher.match(relativePath));
319
-
320
- return matchesPattern && !configs.isFileIgnored(entry.path);
321
- }
322
-
322
+ const matchesPattern = unmatchedPatterns.size > 0
323
+ ? matchers.reduce((previousValue, matcher) => {
324
+ const pathMatches = matcher.match(relativePath);
325
+
326
+ /*
327
+ * We updated the unmatched patterns set only if the path
328
+ * matches and the file isn't ignored. If the file is
329
+ * ignored, that means there wasn't a match for the
330
+ * pattern so it should not be removed.
331
+ *
332
+ * Performance note: isFileIgnored() aggressively caches
333
+ * results so there is no performance penalty for calling
334
+ * it twice with the same argument.
335
+ */
336
+ if (pathMatches && !configs.isFileIgnored(entry.path)) {
337
+ unmatchedPatterns.delete(matcher.pattern);
338
+ }
339
+
340
+ return pathMatches || previousValue;
341
+ }, false)
342
+ : matchers.some(matcher => matcher.match(relativePath));
343
+
344
+ return matchesPattern && !configs.isFileIgnored(entry.path);
345
+ })
346
+ },
347
+ (error, entries) => {
348
+
349
+ // If the promise is already rejected, calling `resolve` or `reject` will do nothing.
350
+ if (error) {
351
+ reject(error);
352
+ } else {
353
+ resolve(entries);
354
+ }
355
+ }
356
+ );
323
357
  })).map(entry => entry.path);
324
358
 
325
359
  // now check to see if we have any unmatched patterns
@@ -450,7 +484,7 @@ async function globMultiSearch({ searches, configs, errorOnUnmatchedPattern }) {
450
484
 
451
485
  }
452
486
 
453
- return [...new Set(filePaths)];
487
+ return filePaths;
454
488
 
455
489
  }
456
490
 
@@ -499,10 +533,7 @@ async function findFiles({
499
533
 
500
534
  // files are added directly to the list
501
535
  if (stat.isFile()) {
502
- results.push({
503
- filePath,
504
- ignored: configs.isFileIgnored(filePath)
505
- });
536
+ results.push(filePath);
506
537
  }
507
538
 
508
539
  // directories need extensions attached
@@ -560,11 +591,10 @@ async function findFiles({
560
591
  });
561
592
 
562
593
  return [
563
- ...results,
564
- ...globbyResults.map(filePath => ({
565
- filePath: path.resolve(filePath),
566
- ignored: false
567
- }))
594
+ ...new Set([
595
+ ...results,
596
+ ...globbyResults.map(filePath => path.resolve(filePath))
597
+ ])
568
598
  ];
569
599
  }
570
600
 
@@ -682,6 +682,13 @@ class ESLint {
682
682
  }
683
683
  }
684
684
 
685
+ /**
686
+ * The type of configuration used by this class.
687
+ * @type {string}
688
+ * @static
689
+ */
690
+ ESLint.configType = "eslintrc";
691
+
685
692
  //------------------------------------------------------------------------------
686
693
  // Public Interface
687
694
  //------------------------------------------------------------------------------
@@ -91,7 +91,11 @@ const LintResultCache = require("../cli-engine/lint-result-cache");
91
91
  // Helpers
92
92
  //------------------------------------------------------------------------------
93
93
 
94
- const FLAT_CONFIG_FILENAME = "eslint.config.js";
94
+ const FLAT_CONFIG_FILENAMES = [
95
+ "eslint.config.js",
96
+ "eslint.config.mjs",
97
+ "eslint.config.cjs"
98
+ ];
95
99
  const debug = require("debug")("eslint:flat-eslint");
96
100
  const removedFormatters = new Set(["table", "codeframe"]);
97
101
  const privateMembers = new WeakMap();
@@ -248,7 +252,7 @@ function compareResultsByFilePath(a, b) {
248
252
  */
249
253
  function findFlatConfigFile(cwd) {
250
254
  return findUp(
251
- FLAT_CONFIG_FILENAME,
255
+ FLAT_CONFIG_FILENAMES,
252
256
  { cwd }
253
257
  );
254
258
  }
@@ -485,7 +489,7 @@ function verifyText({
485
489
  * @returns {boolean} `true` if the linter should adopt the code block.
486
490
  */
487
491
  filterCodeBlock(blockFilename) {
488
- return configs.isExplicitMatch(blockFilename);
492
+ return configs.getConfig(blockFilename) !== void 0;
489
493
  }
490
494
  }
491
495
  );
@@ -537,6 +541,23 @@ function createExtraneousResultsError() {
537
541
  return new TypeError("Results object was not created from this ESLint instance.");
538
542
  }
539
543
 
544
+ /**
545
+ * Creates a fixer function based on the provided fix, fixTypesSet, and config.
546
+ * @param {Function|boolean} fix The original fix option.
547
+ * @param {Set<string>} fixTypesSet A set of fix types to filter messages for fixing.
548
+ * @param {FlatConfig} config The config for the file that generated the message.
549
+ * @returns {Function|boolean} The fixer function or the original fix value.
550
+ */
551
+ function getFixerForFixTypes(fix, fixTypesSet, config) {
552
+ if (!fix || !fixTypesSet) {
553
+ return fix;
554
+ }
555
+
556
+ const originalFix = (typeof fix === "function") ? fix : () => true;
557
+
558
+ return message => shouldMessageBeFixed(message, config, fixTypesSet) && originalFix(message);
559
+ }
560
+
540
561
  //-----------------------------------------------------------------------------
541
562
  // Main API
542
563
  //-----------------------------------------------------------------------------
@@ -786,13 +807,15 @@ class FlatESLint {
786
807
  */
787
808
  const results = await Promise.all(
788
809
 
789
- filePaths.map(({ filePath, ignored }) => {
810
+ filePaths.map(filePath => {
811
+
812
+ const config = configs.getConfig(filePath);
790
813
 
791
814
  /*
792
- * If a filename was entered that matches an ignore
793
- * pattern, then notify the user.
815
+ * If a filename was entered that cannot be matched
816
+ * to a config, then notify the user.
794
817
  */
795
- if (ignored) {
818
+ if (!config) {
796
819
  if (warnIgnored) {
797
820
  return createIgnoreResult(filePath, cwd);
798
821
  }
@@ -800,17 +823,6 @@ class FlatESLint {
800
823
  return void 0;
801
824
  }
802
825
 
803
- const config = configs.getConfig(filePath);
804
-
805
- /*
806
- * Sometimes a file found through a glob pattern will
807
- * be ignored. In this case, `config` will be undefined
808
- * and we just silently ignore the file.
809
- */
810
- if (!config) {
811
- return void 0;
812
- }
813
-
814
826
  // Skip if there is cached result.
815
827
  if (lintResultCache) {
816
828
  const cachedResult =
@@ -832,16 +844,7 @@ class FlatESLint {
832
844
 
833
845
 
834
846
  // set up fixer for fixTypes if necessary
835
- let fixer = fix;
836
-
837
- if (fix && fixTypesSet) {
838
-
839
- // save original value of options.fix in case it's a function
840
- const originalFix = (typeof fix === "function")
841
- ? fix : () => true;
842
-
843
- fixer = message => shouldMessageBeFixed(message, config, fixTypesSet) && originalFix(message);
844
- }
847
+ const fixer = getFixerForFixTypes(fix, fixTypesSet, config);
845
848
 
846
849
  return fs.readFile(filePath, "utf8")
847
850
  .then(text => {
@@ -938,11 +941,16 @@ class FlatESLint {
938
941
  allowInlineConfig,
939
942
  cwd,
940
943
  fix,
944
+ fixTypes,
941
945
  warnIgnored: constructorWarnIgnored
942
946
  } = eslintOptions;
943
947
  const results = [];
944
948
  const startTime = Date.now();
949
+ const fixTypesSet = fixTypes ? new Set(fixTypes) : null;
945
950
  const resolvedFilename = path.resolve(cwd, filePath || "__placeholder__.js");
951
+ const config = configs.getConfig(resolvedFilename);
952
+
953
+ const fixer = getFixerForFixTypes(fix, fixTypesSet, config);
946
954
 
947
955
  // Clear the last used config arrays.
948
956
  if (resolvedFilename && await this.isPathIgnored(resolvedFilename)) {
@@ -959,7 +967,7 @@ class FlatESLint {
959
967
  filePath: resolvedFilename.endsWith("__placeholder__.js") ? "<text>" : resolvedFilename,
960
968
  configs,
961
969
  cwd,
962
- fix,
970
+ fix: fixer,
963
971
  allowInlineConfig,
964
972
  linter
965
973
  }));
@@ -1112,11 +1120,20 @@ class FlatESLint {
1112
1120
  }
1113
1121
  }
1114
1122
 
1123
+ /**
1124
+ * The type of configuration used by this class.
1125
+ * @type {string}
1126
+ * @static
1127
+ */
1128
+ FlatESLint.configType = "flat";
1129
+
1115
1130
  /**
1116
1131
  * Returns whether flat config should be used.
1132
+ * @param {Object} [options] The options for this function.
1133
+ * @param {string} [options.cwd] The current working directory.
1117
1134
  * @returns {Promise<boolean>} Whether flat config should be used.
1118
1135
  */
1119
- async function shouldUseFlatConfig() {
1136
+ async function shouldUseFlatConfig({ cwd = process.cwd() } = {}) {
1120
1137
  switch (process.env.ESLINT_USE_FLAT_CONFIG) {
1121
1138
  case "true":
1122
1139
  return true;
@@ -1128,7 +1145,7 @@ async function shouldUseFlatConfig() {
1128
1145
  * If neither explicitly enabled nor disabled, then use the presence
1129
1146
  * of a flat config file to determine enablement.
1130
1147
  */
1131
- return !!(await findFlatConfigFile(process.cwd()));
1148
+ return !!(await findFlatConfigFile(cwd));
1132
1149
  }
1133
1150
  }
1134
1151
 
@@ -733,7 +733,7 @@ function createLanguageOptions({ globals: configuredGlobals, parser, parserOptio
733
733
  */
734
734
  function resolveGlobals(providedGlobals, enabledEnvironments) {
735
735
  return Object.assign(
736
- {},
736
+ Object.create(null),
737
737
  ...enabledEnvironments.filter(env => env.globals).map(env => env.globals),
738
738
  providedGlobals
739
739
  );
package/lib/options.js CHANGED
@@ -168,7 +168,7 @@ module.exports = function(usingFlatConfig) {
168
168
  alias: "c",
169
169
  type: "path::String",
170
170
  description: usingFlatConfig
171
- ? "Use this configuration instead of eslint.config.js"
171
+ ? "Use this configuration instead of eslint.config.js, eslint.config.mjs, or eslint.config.cjs"
172
172
  : "Use this configuration, overriding .eslintrc.* config options if present"
173
173
  },
174
174
  envFlag,
@@ -13,6 +13,7 @@
13
13
  const
14
14
  assert = require("assert"),
15
15
  util = require("util"),
16
+ path = require("path"),
16
17
  equal = require("fast-deep-equal"),
17
18
  Traverser = require("../shared/traverser"),
18
19
  { getRuleOptionsSchema } = require("../config/flat-config-helpers"),
@@ -592,7 +593,15 @@ class FlatRuleTester {
592
593
  * @private
593
594
  */
594
595
  function runRuleForItem(item) {
595
- const configs = new FlatConfigArray(testerConfig, { baseConfig });
596
+ const flatConfigArrayOptions = {
597
+ baseConfig
598
+ };
599
+
600
+ if (item.filename) {
601
+ flatConfigArrayOptions.basePath = path.parse(item.filename).root;
602
+ }
603
+
604
+ const configs = new FlatConfigArray(testerConfig, flatConfigArrayOptions);
596
605
 
597
606
  /*
598
607
  * Modify the returned config so that the parser is wrapped to catch
@@ -934,7 +934,7 @@ class SourceCode extends TokenStore {
934
934
  * https://github.com/eslint/eslint/issues/16302
935
935
  */
936
936
  const configGlobals = Object.assign(
937
- {},
937
+ Object.create(null), // https://github.com/eslint/eslint/issues/18363
938
938
  getGlobalsForEcmaVersion(languageOptions.ecmaVersion),
939
939
  languageOptions.sourceType === "commonjs" ? globals.commonjs : void 0,
940
940
  languageOptions.globals
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint",
3
- "version": "8.56.0",
3
+ "version": "8.57.1",
4
4
  "author": "Nicholas C. Zakas <nicholas+npm@nczconsulting.com>",
5
5
  "description": "An AST-based pattern checker for JavaScript.",
6
6
  "bin": {
@@ -24,7 +24,8 @@
24
24
  "lint:fix:docs:js": "node Makefile.js lintDocsJS -- fix",
25
25
  "release:generate:alpha": "node Makefile.js generatePrerelease -- alpha",
26
26
  "release:generate:beta": "node Makefile.js generatePrerelease -- beta",
27
- "release:generate:latest": "node Makefile.js generateRelease",
27
+ "release:generate:latest": "node Makefile.js generateRelease -- latest",
28
+ "release:generate:maintenance": "node Makefile.js generateRelease -- maintenance",
28
29
  "release:generate:rc": "node Makefile.js generatePrerelease -- rc",
29
30
  "release:publish": "node Makefile.js publishRelease",
30
31
  "test": "node Makefile.js test",
@@ -65,8 +66,8 @@
65
66
  "@eslint-community/eslint-utils": "^4.2.0",
66
67
  "@eslint-community/regexpp": "^4.6.1",
67
68
  "@eslint/eslintrc": "^2.1.4",
68
- "@eslint/js": "8.56.0",
69
- "@humanwhocodes/config-array": "^0.11.13",
69
+ "@eslint/js": "8.57.1",
70
+ "@humanwhocodes/config-array": "^0.13.0",
70
71
  "@humanwhocodes/module-importer": "^1.0.1",
71
72
  "@nodelib/fs.walk": "^1.2.8",
72
73
  "@ungap/structured-clone": "^1.2.0",
@@ -104,6 +105,7 @@
104
105
  "devDependencies": {
105
106
  "@babel/core": "^7.4.3",
106
107
  "@babel/preset-env": "^7.4.3",
108
+ "@sinonjs/fake-timers": "11.2.2",
107
109
  "@wdio/browser-runner": "^8.14.6",
108
110
  "@wdio/cli": "^8.14.6",
109
111
  "@wdio/concise-reporter": "^8.14.0",
@@ -122,9 +124,9 @@
122
124
  "eslint-plugin-eslint-plugin": "^5.2.1",
123
125
  "eslint-plugin-internal-rules": "file:tools/internal-rules",
124
126
  "eslint-plugin-jsdoc": "^46.2.5",
125
- "eslint-plugin-n": "^16.4.0",
127
+ "eslint-plugin-n": "^16.6.0",
126
128
  "eslint-plugin-unicorn": "^49.0.0",
127
- "eslint-release": "^3.2.0",
129
+ "eslint-release": "^3.3.0",
128
130
  "eslump": "^3.0.0",
129
131
  "esprima": "^4.0.1",
130
132
  "fast-glob": "^3.2.11",
@@ -159,7 +161,7 @@
159
161
  "semver": "^7.5.3",
160
162
  "shelljs": "^0.8.2",
161
163
  "sinon": "^11.0.0",
162
- "vite-plugin-commonjs": "^0.10.0",
164
+ "vite-plugin-commonjs": "0.10.1",
163
165
  "webdriverio": "^8.14.6",
164
166
  "webpack": "^5.23.0",
165
167
  "webpack-cli": "^4.5.0",