eslint 7.0.0-alpha.3 → 7.2.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 (89) hide show
  1. package/CHANGELOG.md +303 -0
  2. package/README.md +10 -11
  3. package/bin/eslint.js +115 -77
  4. package/conf/category-list.json +0 -1
  5. package/lib/api.js +2 -0
  6. package/lib/cli-engine/cascading-config-array-factory.js +12 -0
  7. package/lib/cli-engine/cli-engine.js +53 -48
  8. package/lib/cli-engine/config-array/config-array.js +1 -1
  9. package/lib/cli-engine/config-array/ignore-pattern.js +7 -1
  10. package/lib/cli-engine/config-array-factory.js +3 -3
  11. package/lib/cli.js +181 -95
  12. package/lib/eslint/eslint.js +656 -0
  13. package/lib/eslint/index.js +7 -0
  14. package/lib/init/autoconfig.js +4 -4
  15. package/lib/init/config-initializer.js +5 -10
  16. package/lib/init/source-code-utils.js +2 -2
  17. package/lib/linter/code-path-analysis/code-path-analyzer.js +2 -2
  18. package/lib/linter/code-path-analysis/code-path-state.js +34 -12
  19. package/lib/linter/config-comment-parser.js +1 -1
  20. package/lib/linter/linter.js +2 -1
  21. package/lib/options.js +0 -1
  22. package/lib/rule-tester/rule-tester.js +6 -1
  23. package/lib/rules/accessor-pairs.js +1 -1
  24. package/lib/rules/array-callback-return.js +3 -18
  25. package/lib/rules/arrow-parens.js +19 -3
  26. package/lib/rules/block-spacing.js +19 -2
  27. package/lib/rules/callback-return.js +4 -0
  28. package/lib/rules/comma-style.js +3 -8
  29. package/lib/rules/func-call-spacing.js +22 -6
  30. package/lib/rules/getter-return.js +2 -12
  31. package/lib/rules/global-require.js +4 -0
  32. package/lib/rules/handle-callback-err.js +4 -0
  33. package/lib/rules/index.js +1 -0
  34. package/lib/rules/key-spacing.js +1 -1
  35. package/lib/rules/keyword-spacing.js +9 -2
  36. package/lib/rules/linebreak-style.js +8 -2
  37. package/lib/rules/max-lines-per-function.js +1 -1
  38. package/lib/rules/multiline-ternary.js +44 -25
  39. package/lib/rules/new-cap.js +1 -1
  40. package/lib/rules/newline-per-chained-call.js +6 -3
  41. package/lib/rules/no-buffer-constructor.js +4 -0
  42. package/lib/rules/no-control-regex.js +1 -1
  43. package/lib/rules/no-empty-function.js +1 -1
  44. package/lib/rules/no-extra-boolean-cast.js +3 -0
  45. package/lib/rules/no-extra-parens.js +35 -3
  46. package/lib/rules/no-inner-declarations.js +31 -39
  47. package/lib/rules/no-invalid-regexp.js +1 -1
  48. package/lib/rules/no-lone-blocks.js +1 -1
  49. package/lib/rules/no-loss-of-precision.js +198 -0
  50. package/lib/rules/no-misleading-character-class.js +1 -1
  51. package/lib/rules/no-mixed-operators.js +3 -2
  52. package/lib/rules/no-mixed-requires.js +4 -0
  53. package/lib/rules/no-mixed-spaces-and-tabs.js +14 -6
  54. package/lib/rules/no-new-func.js +22 -19
  55. package/lib/rules/no-new-object.js +15 -3
  56. package/lib/rules/no-new-require.js +4 -0
  57. package/lib/rules/no-new-symbol.js +2 -1
  58. package/lib/rules/no-path-concat.js +4 -0
  59. package/lib/rules/no-process-env.js +4 -0
  60. package/lib/rules/no-process-exit.js +4 -0
  61. package/lib/rules/no-regex-spaces.js +1 -1
  62. package/lib/rules/no-restricted-exports.js +6 -0
  63. package/lib/rules/no-restricted-modules.js +4 -0
  64. package/lib/rules/no-sync.js +4 -0
  65. package/lib/rules/no-unexpected-multiline.js +22 -12
  66. package/lib/rules/no-unneeded-ternary.js +6 -4
  67. package/lib/rules/no-unused-expressions.js +1 -1
  68. package/lib/rules/no-unused-vars.js +3 -1
  69. package/lib/rules/no-useless-backreference.js +1 -1
  70. package/lib/rules/no-useless-concat.js +1 -1
  71. package/lib/rules/one-var-declaration-per-line.js +1 -1
  72. package/lib/rules/padded-blocks.js +17 -4
  73. package/lib/rules/prefer-named-capture-group.js +1 -1
  74. package/lib/rules/quote-props.js +2 -2
  75. package/lib/rules/rest-spread-spacing.js +3 -6
  76. package/lib/rules/semi-spacing.js +32 -8
  77. package/lib/rules/space-before-function-paren.js +5 -2
  78. package/lib/rules/template-tag-spacing.js +8 -2
  79. package/lib/rules/utils/ast-utils.js +106 -9
  80. package/lib/rules/yoda.js +101 -51
  81. package/lib/shared/relative-module-resolver.js +1 -0
  82. package/lib/shared/types.js +7 -0
  83. package/lib/source-code/source-code.js +1 -0
  84. package/messages/extend-config-missing.txt +1 -1
  85. package/messages/no-config-found.txt +1 -1
  86. package/messages/plugin-conflict.txt +1 -1
  87. package/messages/plugin-missing.txt +1 -1
  88. package/messages/whitespace-found.txt +1 -1
  89. package/package.json +27 -26
package/bin/eslint.js CHANGED
@@ -12,97 +12,135 @@
12
12
  // to use V8's code cache to speed up instantiation time
13
13
  require("v8-compile-cache");
14
14
 
15
- //------------------------------------------------------------------------------
16
- // Helpers
17
- //------------------------------------------------------------------------------
18
-
19
- const useStdIn = process.argv.includes("--stdin"),
20
- init = process.argv.includes("--init"),
21
- debug = process.argv.includes("--debug");
22
-
23
15
  // must do this initialization *before* other requires in order to work
24
- if (debug) {
16
+ if (process.argv.includes("--debug")) {
25
17
  require("debug").enable("eslint:*,-eslint:code-path");
26
18
  }
27
19
 
28
20
  //------------------------------------------------------------------------------
29
- // Requirements
21
+ // Helpers
30
22
  //------------------------------------------------------------------------------
31
23
 
32
- // now we can safely include the other modules that use debug
33
- const path = require("path"),
34
- fs = require("fs"),
35
- cli = require("../lib/cli");
36
-
37
- //------------------------------------------------------------------------------
38
- // Execution
39
- //------------------------------------------------------------------------------
24
+ /**
25
+ * Read data from stdin til the end.
26
+ *
27
+ * Note: See
28
+ * - https://github.com/nodejs/node/blob/master/doc/api/process.md#processstdin
29
+ * - https://github.com/nodejs/node/blob/master/doc/api/process.md#a-note-on-process-io
30
+ * - https://lists.gnu.org/archive/html/bug-gnu-emacs/2016-01/msg00419.html
31
+ * - https://github.com/nodejs/node/issues/7439 (historical)
32
+ *
33
+ * On Windows using `fs.readFileSync(STDIN_FILE_DESCRIPTOR, "utf8")` seems
34
+ * to read 4096 bytes before blocking and never drains to read further data.
35
+ *
36
+ * The investigation on the Emacs thread indicates:
37
+ *
38
+ * > Emacs on MS-Windows uses pipes to communicate with subprocesses; a
39
+ * > pipe on Windows has a 4K buffer. So as soon as Emacs writes more than
40
+ * > 4096 bytes to the pipe, the pipe becomes full, and Emacs then waits for
41
+ * > the subprocess to read its end of the pipe, at which time Emacs will
42
+ * > write the rest of the stuff.
43
+ * @returns {Promise<string>} The read text.
44
+ */
45
+ function readStdin() {
46
+ return new Promise((resolve, reject) => {
47
+ let content = "";
48
+ let chunk = "";
49
+
50
+ process.stdin
51
+ .setEncoding("utf8")
52
+ .on("readable", () => {
53
+ while ((chunk = process.stdin.read()) !== null) {
54
+ content += chunk;
55
+ }
56
+ })
57
+ .on("end", () => resolve(content))
58
+ .on("error", reject);
59
+ });
60
+ }
40
61
 
41
- process.once("uncaughtException", err => {
62
+ /**
63
+ * Get the error message of a given value.
64
+ * @param {any} error The value to get.
65
+ * @returns {string} The error message.
66
+ */
67
+ function getErrorMessage(error) {
42
68
 
43
- // lazy load
69
+ // Lazy loading because those are used only if error happened.
70
+ const fs = require("fs");
71
+ const path = require("path");
72
+ const util = require("util");
44
73
  const lodash = require("lodash");
45
74
 
46
- if (typeof err.messageTemplate === "string" && err.messageTemplate.length > 0) {
47
- const template = lodash.template(fs.readFileSync(path.resolve(__dirname, `../messages/${err.messageTemplate}.txt`), "utf-8"));
48
- const pkg = require("../package.json");
75
+ // Foolproof -- thirdparty module might throw non-object.
76
+ if (typeof error !== "object" || error === null) {
77
+ return String(error);
78
+ }
79
+
80
+ // Use templates if `error.messageTemplate` is present.
81
+ if (typeof error.messageTemplate === "string") {
82
+ try {
83
+ const templateFilePath = path.resolve(
84
+ __dirname,
85
+ `../messages/${error.messageTemplate}.txt`
86
+ );
87
+
88
+ // Use sync API because Node.js should exit at this tick.
89
+ const templateText = fs.readFileSync(templateFilePath, "utf-8");
90
+ const template = lodash.template(templateText);
91
+
92
+ return template(error.messageData || {});
93
+ } catch {
94
+
95
+ // Ignore template error then fallback to use `error.stack`.
96
+ }
97
+ }
49
98
 
50
- console.error("\nOops! Something went wrong! :(");
51
- console.error(`\nESLint: ${pkg.version}.\n\n${template(err.messageData || {})}`);
52
- } else {
53
- console.error(err.stack);
99
+ // Use the stacktrace if it's an error object.
100
+ if (typeof error.stack === "string") {
101
+ return error.stack;
54
102
  }
55
103
 
104
+ // Otherwise, dump the object.
105
+ return util.format("%o", error);
106
+ }
107
+
108
+ /**
109
+ * Catch and report unexpected error.
110
+ * @param {any} error The thrown error object.
111
+ * @returns {void}
112
+ */
113
+ function onFatalError(error) {
56
114
  process.exitCode = 2;
57
- });
58
-
59
- if (useStdIn) {
60
-
61
- /*
62
- * Note: See
63
- * - https://github.com/nodejs/node/blob/master/doc/api/process.md#processstdin
64
- * - https://github.com/nodejs/node/blob/master/doc/api/process.md#a-note-on-process-io
65
- * - https://lists.gnu.org/archive/html/bug-gnu-emacs/2016-01/msg00419.html
66
- * - https://github.com/nodejs/node/issues/7439 (historical)
67
- *
68
- * On Windows using `fs.readFileSync(STDIN_FILE_DESCRIPTOR, "utf8")` seems
69
- * to read 4096 bytes before blocking and never drains to read further data.
70
- *
71
- * The investigation on the Emacs thread indicates:
72
- *
73
- * > Emacs on MS-Windows uses pipes to communicate with subprocesses; a
74
- * > pipe on Windows has a 4K buffer. So as soon as Emacs writes more than
75
- * > 4096 bytes to the pipe, the pipe becomes full, and Emacs then waits for
76
- * > the subprocess to read its end of the pipe, at which time Emacs will
77
- * > write the rest of the stuff.
78
- *
79
- * Using the nodejs code example for reading from stdin.
80
- */
81
- let contents = "",
82
- chunk = "";
83
-
84
- process.stdin.setEncoding("utf8");
85
- process.stdin.on("readable", () => {
86
-
87
- // Use a loop to make sure we read all available data.
88
- while ((chunk = process.stdin.read()) !== null) {
89
- contents += chunk;
90
- }
91
- });
92
115
 
93
- process.stdin.on("end", () => {
94
- process.exitCode = cli.execute(process.argv, contents, "utf8");
95
- });
96
- } else if (init) {
97
- const configInit = require("../lib/init/config-initializer");
98
-
99
- configInit.initializeConfig().then(() => {
100
- process.exitCode = 0;
101
- }).catch(err => {
102
- process.exitCode = 1;
103
- console.error(err.message);
104
- console.error(err.stack);
105
- });
106
- } else {
107
- process.exitCode = cli.execute(process.argv);
116
+ const { version } = require("../package.json");
117
+ const message = getErrorMessage(error);
118
+
119
+ console.error(`
120
+ Oops! Something went wrong! :(
121
+
122
+ ESLint: ${version}
123
+
124
+ ${message}`);
108
125
  }
126
+
127
+ //------------------------------------------------------------------------------
128
+ // Execution
129
+ //------------------------------------------------------------------------------
130
+
131
+ (async function main() {
132
+ process.on("uncaughtException", onFatalError);
133
+ process.on("unhandledRejection", onFatalError);
134
+
135
+ // Call the config initializer if `--init` is present.
136
+ if (process.argv.includes("--init")) {
137
+ await require("../lib/init/config-initializer").initializeConfig();
138
+ return;
139
+ }
140
+
141
+ // Otherwise, call the CLI.
142
+ process.exitCode = await require("../lib/cli").execute(
143
+ process.argv,
144
+ process.argv.includes("--stdin") ? await readStdin() : null
145
+ );
146
+ }()).catch(onFatalError);
@@ -4,7 +4,6 @@
4
4
  { "name": "Best Practices", "description": "These rules relate to better ways of doing things to help you avoid problems:" },
5
5
  { "name": "Strict Mode", "description": "These rules relate to strict mode directives:" },
6
6
  { "name": "Variables", "description": "These rules relate to variable declarations:" },
7
- { "name": "Node.js and CommonJS", "description": "These rules relate to code running in Node.js, or in browsers with CommonJS:" },
8
7
  { "name": "Stylistic Issues", "description": "These rules relate to style guidelines, and are therefore quite subjective:" },
9
8
  { "name": "ECMAScript 6", "description": "These rules relate to ES6, also known as ES2015:" }
10
9
  ],
package/lib/api.js CHANGED
@@ -6,6 +6,7 @@
6
6
  "use strict";
7
7
 
8
8
  const { CLIEngine } = require("./cli-engine");
9
+ const { ESLint } = require("./eslint");
9
10
  const { Linter } = require("./linter");
10
11
  const { RuleTester } = require("./rule-tester");
11
12
  const { SourceCode } = require("./source-code");
@@ -13,6 +14,7 @@ const { SourceCode } = require("./source-code");
13
14
  module.exports = {
14
15
  Linter,
15
16
  CLIEngine,
17
+ ESLint,
16
18
  RuleTester,
17
19
  SourceCode
18
20
  };
@@ -279,6 +279,18 @@ class CascadingConfigArrayFactory {
279
279
  );
280
280
  }
281
281
 
282
+ /**
283
+ * Set the config data to override all configs.
284
+ * Require to call `clearCache()` method after this method is called.
285
+ * @param {ConfigData} configData The config data to override all configs.
286
+ * @returns {void}
287
+ */
288
+ setOverrideConfig(configData) {
289
+ const slots = internalSlotsMap.get(this);
290
+
291
+ slots.cliConfigData = configData;
292
+ }
293
+
282
294
  /**
283
295
  * Clear config cache.
284
296
  * @returns {void}
@@ -39,6 +39,7 @@ const validFixTypes = new Set(["problem", "suggestion", "layout"]);
39
39
 
40
40
  // For VSCode IntelliSense
41
41
  /** @typedef {import("../shared/types").ConfigData} ConfigData */
42
+ /** @typedef {import("../shared/types").DeprecatedRuleInfo} DeprecatedRuleInfo */
42
43
  /** @typedef {import("../shared/types").LintMessage} LintMessage */
43
44
  /** @typedef {import("../shared/types").ParserOptions} ParserOptions */
44
45
  /** @typedef {import("../shared/types").Plugin} Plugin */
@@ -50,29 +51,29 @@ const validFixTypes = new Set(["problem", "suggestion", "layout"]);
50
51
  /**
51
52
  * The options to configure a CLI engine with.
52
53
  * @typedef {Object} CLIEngineOptions
53
- * @property {boolean} allowInlineConfig Enable or disable inline configuration comments.
54
- * @property {ConfigData} baseConfig Base config object, extended by all configs used with this CLIEngine instance
55
- * @property {boolean} cache Enable result caching.
56
- * @property {string} cacheLocation The cache file to use instead of .eslintcache.
57
- * @property {string} configFile The configuration file to use.
58
- * @property {string} cwd The value to use for the current working directory.
59
- * @property {string[]} envs An array of environments to load.
60
- * @property {string[]|null} extensions An array of file extensions to check.
61
- * @property {boolean|Function} fix Execute in autofix mode. If a function, should return a boolean.
62
- * @property {string[]} fixTypes Array of rule types to apply fixes for.
63
- * @property {string[]} globals An array of global variables to declare.
64
- * @property {boolean} ignore False disables use of .eslintignore.
65
- * @property {string} ignorePath The ignore file to use instead of .eslintignore.
66
- * @property {string|string[]} ignorePattern One or more glob patterns to ignore.
67
- * @property {boolean} useEslintrc False disables looking for .eslintrc
68
- * @property {string} parser The name of the parser to use.
69
- * @property {ParserOptions} parserOptions An object of parserOption settings to use.
70
- * @property {string[]} plugins An array of plugins to load.
71
- * @property {Record<string,RuleConf>} rules An object of rules to use.
72
- * @property {string[]} rulePaths An array of directories to load custom rules from.
73
- * @property {boolean} reportUnusedDisableDirectives `true` adds reports for unused eslint-disable directives
74
- * @property {boolean} globInputPaths Set to false to skip glob resolution of input file paths to lint (default: true). If false, each input file paths is assumed to be a non-glob path to an existing file.
75
- * @property {string} resolvePluginsRelativeTo The folder where plugins should be resolved from, defaulting to the CWD
54
+ * @property {boolean} [allowInlineConfig] Enable or disable inline configuration comments.
55
+ * @property {ConfigData} [baseConfig] Base config object, extended by all configs used with this CLIEngine instance
56
+ * @property {boolean} [cache] Enable result caching.
57
+ * @property {string} [cacheLocation] The cache file to use instead of .eslintcache.
58
+ * @property {string} [configFile] The configuration file to use.
59
+ * @property {string} [cwd] The value to use for the current working directory.
60
+ * @property {string[]} [envs] An array of environments to load.
61
+ * @property {string[]|null} [extensions] An array of file extensions to check.
62
+ * @property {boolean|Function} [fix] Execute in autofix mode. If a function, should return a boolean.
63
+ * @property {string[]} [fixTypes] Array of rule types to apply fixes for.
64
+ * @property {string[]} [globals] An array of global variables to declare.
65
+ * @property {boolean} [ignore] False disables use of .eslintignore.
66
+ * @property {string} [ignorePath] The ignore file to use instead of .eslintignore.
67
+ * @property {string|string[]} [ignorePattern] One or more glob patterns to ignore.
68
+ * @property {boolean} [useEslintrc] False disables looking for .eslintrc
69
+ * @property {string} [parser] The name of the parser to use.
70
+ * @property {ParserOptions} [parserOptions] An object of parserOption settings to use.
71
+ * @property {string[]} [plugins] An array of plugins to load.
72
+ * @property {Record<string,RuleConf>} [rules] An object of rules to use.
73
+ * @property {string[]} [rulePaths] An array of directories to load custom rules from.
74
+ * @property {boolean} [reportUnusedDisableDirectives] `true` adds reports for unused eslint-disable directives
75
+ * @property {boolean} [globInputPaths] Set to false to skip glob resolution of input file paths to lint (default: true). If false, each input file paths is assumed to be a non-glob path to an existing file.
76
+ * @property {string} [resolvePluginsRelativeTo] The folder where plugins should be resolved from, defaulting to the CWD
76
77
  */
77
78
 
78
79
  /**
@@ -88,13 +89,6 @@ const validFixTypes = new Set(["problem", "suggestion", "layout"]);
88
89
  * @property {string} [output] The source code of the file that was linted, with as many fixes applied as possible.
89
90
  */
90
91
 
91
- /**
92
- * Information of deprecated rules.
93
- * @typedef {Object} DeprecatedRuleInfo
94
- * @property {string} ruleId The rule ID.
95
- * @property {string[]} replacedBy The rule IDs that replace this deprecated rule.
96
- */
97
-
98
92
  /**
99
93
  * Linting results.
100
94
  * @typedef {Object} LintReport
@@ -409,7 +403,7 @@ function getCacheFile(cacheFile, cwd) {
409
403
 
410
404
  try {
411
405
  fileStats = fs.lstatSync(resolvedCacheFile);
412
- } catch (ex) {
406
+ } catch {
413
407
  fileStats = null;
414
408
  }
415
409
 
@@ -821,16 +815,22 @@ class CLIEngine {
821
815
  lintResultCache.reconcile();
822
816
  }
823
817
 
824
- // Collect used deprecated rules.
825
- const usedDeprecatedRules = Array.from(
826
- iterateRuleDeprecationWarnings(lastConfigArrays)
827
- );
828
-
829
818
  debug(`Linting complete in: ${Date.now() - startTime}ms`);
819
+ let usedDeprecatedRules;
820
+
830
821
  return {
831
822
  results,
832
823
  ...calculateStatsPerRun(results),
833
- usedDeprecatedRules
824
+
825
+ // Initialize it lazily because CLI and `ESLint` API don't use it.
826
+ get usedDeprecatedRules() {
827
+ if (!usedDeprecatedRules) {
828
+ usedDeprecatedRules = Array.from(
829
+ iterateRuleDeprecationWarnings(lastConfigArrays)
830
+ );
831
+ }
832
+ return usedDeprecatedRules;
833
+ }
834
834
  };
835
835
  }
836
836
 
@@ -858,9 +858,9 @@ class CLIEngine {
858
858
  const startTime = Date.now();
859
859
  const resolvedFilename = filename && path.resolve(cwd, filename);
860
860
 
861
+
861
862
  // Clear the last used config arrays.
862
863
  lastConfigArrays.length = 0;
863
-
864
864
  if (resolvedFilename && this.isPathIgnored(resolvedFilename)) {
865
865
  if (warnIgnored) {
866
866
  results.push(createIgnoreResult(resolvedFilename, cwd));
@@ -892,16 +892,22 @@ class CLIEngine {
892
892
  }));
893
893
  }
894
894
 
895
- // Collect used deprecated rules.
896
- const usedDeprecatedRules = Array.from(
897
- iterateRuleDeprecationWarnings(lastConfigArrays)
898
- );
899
-
900
895
  debug(`Linting complete in: ${Date.now() - startTime}ms`);
896
+ let usedDeprecatedRules;
897
+
901
898
  return {
902
899
  results,
903
900
  ...calculateStatsPerRun(results),
904
- usedDeprecatedRules
901
+
902
+ // Initialize it lazily because CLI and `ESLint` API don't use it.
903
+ get usedDeprecatedRules() {
904
+ if (!usedDeprecatedRules) {
905
+ usedDeprecatedRules = Array.from(
906
+ iterateRuleDeprecationWarnings(lastConfigArrays)
907
+ );
908
+ }
909
+ return usedDeprecatedRules;
910
+ }
905
911
  };
906
912
  }
907
913
 
@@ -955,11 +961,10 @@ class CLIEngine {
955
961
  }
956
962
 
957
963
  /**
958
- * Returns the formatter representing the given format or null if no formatter
959
- * with the given name can be found.
964
+ * Returns the formatter representing the given format or null if the `format` is not a string.
960
965
  * @param {string} [format] The name of the format to load or the path to a
961
966
  * custom formatter.
962
- * @returns {Function} The formatter function or null if not found.
967
+ * @returns {(Function|null)} The formatter function or null if the `format` is not a string.
963
968
  */
964
969
  getFormatter(format) {
965
970
 
@@ -986,7 +991,7 @@ class CLIEngine {
986
991
  const npmFormat = naming.normalizePackageName(normalizedFormatName, "eslint-formatter");
987
992
 
988
993
  formatterPath = ModuleResolver.resolve(npmFormat, path.join(cwd, "__placeholder__.js"));
989
- } catch (e) {
994
+ } catch {
990
995
  formatterPath = path.resolve(__dirname, "formatters", normalizedFormatName);
991
996
  }
992
997
  }
@@ -107,7 +107,7 @@ function getMatchedIndices(elements, filePath) {
107
107
  for (let i = elements.length - 1; i >= 0; --i) {
108
108
  const element = elements[i];
109
109
 
110
- if (!element.criteria || element.criteria.test(filePath)) {
110
+ if (!element.criteria || (filePath && element.criteria.test(filePath))) {
111
111
  indices.push(i);
112
112
  }
113
113
  }
@@ -71,7 +71,13 @@ function getCommonAncestorPath(sourcePaths) {
71
71
  }
72
72
  }
73
73
 
74
- return result || path.sep;
74
+ let resolvedResult = result || path.sep;
75
+
76
+ // if Windows common ancestor is root of drive must have trailing slash to be absolute.
77
+ if (resolvedResult && resolvedResult.endsWith(":") && process.platform === "win32") {
78
+ resolvedResult += path.sep;
79
+ }
80
+ return resolvedResult;
75
81
  }
76
82
 
77
83
  /**
@@ -517,7 +517,7 @@ class ConfigArrayFactory {
517
517
  try {
518
518
  loadPackageJSONConfigFile(filePath);
519
519
  return filePath;
520
- } catch (error) { /* ignore */ }
520
+ } catch { /* ignore */ }
521
521
  } else {
522
522
  return filePath;
523
523
  }
@@ -817,7 +817,7 @@ class ConfigArrayFactory {
817
817
  if (configData) {
818
818
  return this._normalizeConfigData(configData, {
819
819
  ...ctx,
820
- filePath: plugin.filePath,
820
+ filePath: plugin.filePath || ctx.filePath,
821
821
  name: `${ctx.name} » plugin:${plugin.id}/${configName}`
822
822
  });
823
823
  }
@@ -978,7 +978,7 @@ class ConfigArrayFactory {
978
978
  if (plugin) {
979
979
  return new ConfigDependency({
980
980
  definition: normalizePlugin(plugin),
981
- filePath: ctx.filePath,
981
+ filePath: "", // It's unknown where the plugin came from.
982
982
  id,
983
983
  importerName: ctx.name,
984
984
  importerPath: ctx.filePath