es-check 9.6.4 → 9.7.2
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/README.md +4 -1
- package/lib/browserslist.js +23 -13
- package/lib/cache.js +2 -1
- package/lib/check-runner/index.js +13 -31
- package/lib/check-runner/utils.js +80 -121
- package/lib/cli/constants.js +4 -7
- package/lib/cli/handler.js +66 -76
- package/lib/cli/parser.js +16 -12
- package/lib/cli/utils.js +21 -25
- package/lib/constants/es-features/15.js +17 -1
- package/lib/constants/es-features/16.js +34 -0
- package/lib/constants/es-features/17.js +90 -11
- package/lib/constants/es-features/9.js +2 -1
- package/lib/constants/es-features/globals.js +71 -0
- package/lib/constants/es-features/index.js +19 -19
- package/lib/constants/es-features/polyfills.js +15 -43
- package/lib/constants/featureParserMapping.js +2 -7
- package/lib/constants/index.js +59 -1
- package/lib/constants/polyfillableFeatures.js +12 -0
- package/lib/constants/versions.js +1 -1
- package/lib/detectFeatures.js +54 -50
- package/lib/helpers/ast.js +66 -154
- package/lib/helpers/astDetector.js +1647 -68
- package/lib/helpers/files.js +9 -5
- package/lib/helpers/index.js +7 -18
- package/lib/helpers/logger.js +3 -7
- package/lib/helpers/parsers.js +25 -20
- package/lib/helpers/sourcemap.js +40 -39
- package/package.json +116 -198
package/README.md
CHANGED
|
@@ -118,7 +118,7 @@ Usage: index [options] [ecmaVersion] [files...]
|
|
|
118
118
|
|
|
119
119
|
Arguments:
|
|
120
120
|
ecmaVersion ecmaVersion to check files against. Can be: es3, es4, es5, es6/es2015, es7/es2016, es8/es2017, es9/es2018, es10/es2019, es11/es2020, es12/es2021,
|
|
121
|
-
es13/es2022, es14/es2023, es15/es2024, es16/es2025
|
|
121
|
+
es13/es2022, es14/es2023, es15/es2024, es16/es2025, es17/es2026
|
|
122
122
|
files a glob of files to to test the EcmaScript version against
|
|
123
123
|
|
|
124
124
|
```
|
|
@@ -177,6 +177,8 @@ es-check es5 './src/**/*.{js,ts}' --typescript
|
|
|
177
177
|
|
|
178
178
|
This is experimental functionality that strips TypeScript type annotations and tests the resulting JavaScript against the specified ES version.
|
|
179
179
|
|
|
180
|
+
Runtime support for TypeScript checks is limited to Node.js v22.13.0+ through `module.stripTypeScriptTypes` and Bun v1.0.0+ through `Bun.Transpiler`. JavaScript checks still work on older supported Node.js versions.
|
|
181
|
+
|
|
180
182
|
**Skipping specific files or directories:**
|
|
181
183
|
|
|
182
184
|
```sh
|
|
@@ -718,6 +720,7 @@ To update ES version support:
|
|
|
718
720
|
To update ES feature detection:
|
|
719
721
|
|
|
720
722
|
- Add features to [version-specific files](./lib/constants/es-features/) (e.g., `6.js` for ES6 features)
|
|
723
|
+
- Update [ES globals](./lib/constants/es-features/globals.js) from [sindresorhus/globals](https://github.com/sindresorhus/globals/blob/main/globals.json) when global availability changes
|
|
721
724
|
- Update [polyfill patterns](./lib/constants/es-features/polyfills.js) if needed
|
|
722
725
|
- Feature detection uses AST traversal via [Acorn](https://github.com/acornjs/acorn/)
|
|
723
726
|
|
package/lib/browserslist.js
CHANGED
|
@@ -15,22 +15,26 @@ function getESVersionForBrowser(browser, version) {
|
|
|
15
15
|
const targetVersion = parseFloat(version);
|
|
16
16
|
let matchedVersion = null;
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
let versionIndex = 0;
|
|
19
|
+
while (versionIndex < browserVersions.length) {
|
|
20
|
+
const v = browserVersions[versionIndex];
|
|
19
21
|
if (v <= targetVersion) {
|
|
20
22
|
matchedVersion = v.toString();
|
|
21
23
|
} else {
|
|
22
24
|
break;
|
|
23
25
|
}
|
|
26
|
+
versionIndex += 1;
|
|
24
27
|
}
|
|
25
28
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
29
|
+
const hasNoMatchedVersion = matchedVersion === null;
|
|
30
|
+
const isModernDefaultBrowser = browser === "chrome" || browser === "firefox";
|
|
31
|
+
const shouldUseModernDefault = hasNoMatchedVersion && isModernDefaultBrowser;
|
|
32
|
+
|
|
33
|
+
if (shouldUseModernDefault) {
|
|
30
34
|
return 6;
|
|
31
35
|
}
|
|
32
36
|
|
|
33
|
-
if (
|
|
37
|
+
if (hasNoMatchedVersion) {
|
|
34
38
|
return defaultVersion;
|
|
35
39
|
}
|
|
36
40
|
|
|
@@ -46,24 +50,30 @@ function getESVersionFromBrowserslist(options = {}) {
|
|
|
46
50
|
env: browserslistEnv,
|
|
47
51
|
});
|
|
48
52
|
|
|
49
|
-
|
|
53
|
+
const hasNoBrowsers = !browsers || browsers.length === 0;
|
|
54
|
+
if (hasNoBrowsers) {
|
|
50
55
|
return 5;
|
|
51
56
|
}
|
|
52
57
|
|
|
53
58
|
const hasIE = browsers.some((browser) => browser.includes("ie "));
|
|
54
59
|
const hasOldEdge = browsers.some((browser) => {
|
|
55
60
|
const [name, version] = browser.split(" ");
|
|
56
|
-
|
|
61
|
+
const isEdge = name === "edge";
|
|
62
|
+
const edgeVersion = parseInt(version, 10);
|
|
63
|
+
const isOldEdge = edgeVersion < 79;
|
|
64
|
+
return isEdge && isOldEdge;
|
|
57
65
|
});
|
|
58
66
|
|
|
59
|
-
|
|
67
|
+
const hasLegacyBrowser = hasIE || hasOldEdge;
|
|
68
|
+
if (hasLegacyBrowser) {
|
|
60
69
|
return 5;
|
|
61
70
|
}
|
|
62
71
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
72
|
+
const hasLegacyPath = browserslistPath && browserslistPath.includes("legacy");
|
|
73
|
+
const hasLegacyEnv = browserslistEnv && browserslistEnv.includes("legacy");
|
|
74
|
+
const hasLegacyConfig = hasLegacyPath || hasLegacyEnv;
|
|
75
|
+
|
|
76
|
+
if (hasLegacyConfig) {
|
|
67
77
|
return 5;
|
|
68
78
|
}
|
|
69
79
|
|
package/lib/cache.js
CHANGED
|
@@ -36,8 +36,9 @@ class SimpleCache {
|
|
|
36
36
|
set(key, value) {
|
|
37
37
|
const isFull = this.cache.size >= this.maxSize;
|
|
38
38
|
const hasKey = this.cache.has(key);
|
|
39
|
+
const shouldEvict = isFull && !hasKey;
|
|
39
40
|
|
|
40
|
-
if (
|
|
41
|
+
if (shouldEvict) {
|
|
41
42
|
const firstKey = this.cache.keys().next().value;
|
|
42
43
|
this.cache.delete(firstKey);
|
|
43
44
|
}
|
|
@@ -2,9 +2,7 @@ const fs = require("fs");
|
|
|
2
2
|
const { parseIgnoreList, processBatchedFiles } = require("../helpers");
|
|
3
3
|
const { determineInvocationType } = require("../cli/utils");
|
|
4
4
|
const { LATEST_PARSER_VERSION } = require("../constants/versions");
|
|
5
|
-
const {
|
|
6
|
-
getMinimumParserVersion,
|
|
7
|
-
} = require("../constants/featureParserMapping");
|
|
5
|
+
const { getMinimumParserVersion } = require("../constants/featureParserMapping");
|
|
8
6
|
const {
|
|
9
7
|
parseFilePatterns,
|
|
10
8
|
validateConfig,
|
|
@@ -33,13 +31,10 @@ function processConfig(config, context) {
|
|
|
33
31
|
|
|
34
32
|
const ignoreFilePath = config.ignoreFile || config["ignore-file"];
|
|
35
33
|
const ignoreFileExists = ignoreFilePath && fs.existsSync(ignoreFilePath);
|
|
36
|
-
const shouldWarnAboutIgnoreFile =
|
|
37
|
-
ignoreFilePath && !ignoreFileExists && isWarn;
|
|
34
|
+
const shouldWarnAboutIgnoreFile = ignoreFilePath && !ignoreFileExists && isWarn;
|
|
38
35
|
|
|
39
36
|
if (shouldWarnAboutIgnoreFile) {
|
|
40
|
-
logger.warn(
|
|
41
|
-
`Warning: Ignore file '${ignoreFilePath}' does not exist or is not accessible`,
|
|
42
|
-
);
|
|
37
|
+
logger.warn(`Warning: Ignore file '${ignoreFilePath}' does not exist or is not accessible`);
|
|
43
38
|
}
|
|
44
39
|
|
|
45
40
|
const validationResult = validateConfig(config, {
|
|
@@ -88,14 +83,9 @@ function processConfig(config, context) {
|
|
|
88
83
|
const targetEsVersion = parseInt(ecmaVersion, 10);
|
|
89
84
|
|
|
90
85
|
const enableFeatureDetection = config.checkBrowser || config.checkFeatures;
|
|
91
|
-
const minRequiredParser = getMinimumParserVersion(
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
);
|
|
95
|
-
|
|
96
|
-
const parserEcmaVersion = useLatestForParsing
|
|
97
|
-
? LATEST_PARSER_VERSION
|
|
98
|
-
: minRequiredParser;
|
|
86
|
+
const minRequiredParser = getMinimumParserVersion(targetEsVersion, enableFeatureDetection);
|
|
87
|
+
|
|
88
|
+
const parserEcmaVersion = useLatestForParsing ? LATEST_PARSER_VERSION : minRequiredParser;
|
|
99
89
|
const acornOpts = { ecmaVersion: parserEcmaVersion, silent: true };
|
|
100
90
|
|
|
101
91
|
if (isDebug) {
|
|
@@ -115,30 +105,22 @@ function processConfig(config, context) {
|
|
|
115
105
|
}
|
|
116
106
|
|
|
117
107
|
const pathsToIgnore = [].concat(config.not || []);
|
|
118
|
-
const filteredFiles = filterIgnoredFiles(
|
|
119
|
-
findFilesResult.files,
|
|
120
|
-
pathsToIgnore,
|
|
121
|
-
globOpts,
|
|
122
|
-
);
|
|
108
|
+
const filteredFiles = filterIgnoredFiles(findFilesResult.files, pathsToIgnore, globOpts);
|
|
123
109
|
|
|
124
110
|
const ignoreList = parseIgnoreList(config);
|
|
125
111
|
const hasIgnores = ignoreList.size > 0;
|
|
126
112
|
const shouldDebugIgnores = hasIgnores && isDebug;
|
|
127
113
|
|
|
128
114
|
if (shouldDebugIgnores) {
|
|
129
|
-
logger.debug(
|
|
130
|
-
"ES-Check: ignoring features:",
|
|
131
|
-
Array.from(ignoreList).join(", "),
|
|
132
|
-
);
|
|
115
|
+
logger.debug("ES-Check: ignoring features:", Array.from(ignoreList).join(", "));
|
|
133
116
|
}
|
|
134
117
|
|
|
135
118
|
const fileCount = filteredFiles.length;
|
|
136
119
|
const hasLogger = logger !== null && logger !== undefined;
|
|
120
|
+
const shouldLogFileCount = hasLogger && fileCount > 0;
|
|
137
121
|
|
|
138
|
-
if (
|
|
139
|
-
logger.info(
|
|
140
|
-
`ES-Check: checking ${fileCount} file${fileCount === 1 ? "" : "s"}...`,
|
|
141
|
-
);
|
|
122
|
+
if (shouldLogFileCount) {
|
|
123
|
+
logger.info(`ES-Check: checking ${fileCount} file${fileCount === 1 ? "" : "s"}...`);
|
|
142
124
|
}
|
|
143
125
|
|
|
144
126
|
const batchSize = parseInt(config.batchSize || "0", 10);
|
|
@@ -166,10 +148,10 @@ function runChecks(configs, loggerOrOptions) {
|
|
|
166
148
|
const allErrors = [];
|
|
167
149
|
const context = { logger, isDebug, isWarn, isNodeAPI, allErrors };
|
|
168
150
|
|
|
169
|
-
|
|
151
|
+
let results = [];
|
|
170
152
|
for (const config of configs) {
|
|
171
153
|
const result = processConfig(config, context);
|
|
172
|
-
results.
|
|
154
|
+
results = results.concat(result);
|
|
173
155
|
|
|
174
156
|
const shouldBreak = result.hasErrors && !result.shouldContinue;
|
|
175
157
|
if (shouldBreak) break;
|
|
@@ -9,13 +9,22 @@ const {
|
|
|
9
9
|
readFile,
|
|
10
10
|
parseCode,
|
|
11
11
|
} = require("../helpers");
|
|
12
|
-
const {
|
|
13
|
-
ECMA_VERSION_MAP,
|
|
14
|
-
ECMA_VERSION_TO_NUMBER,
|
|
15
|
-
} = require("../constants/versions");
|
|
12
|
+
const { ECMA_VERSION_MAP, ECMA_VERSION_TO_NUMBER } = require("../constants/versions");
|
|
16
13
|
|
|
17
14
|
let polyfillDetector = null;
|
|
18
15
|
|
|
16
|
+
function appendError(allErrors, error) {
|
|
17
|
+
allErrors[allErrors.length] = error;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function appendErrors(allErrors, errors) {
|
|
21
|
+
let index = 0;
|
|
22
|
+
while (index < errors.length) {
|
|
23
|
+
appendError(allErrors, errors[index]);
|
|
24
|
+
index += 1;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
19
28
|
function parseFilePatterns(configFilesValue) {
|
|
20
29
|
const hasNoValue = !configFilesValue;
|
|
21
30
|
if (hasNoValue) return [];
|
|
@@ -50,17 +59,13 @@ function validateConfig(config, options) {
|
|
|
50
59
|
const isExiting = !isNodeAPI;
|
|
51
60
|
|
|
52
61
|
if (hasLogger) {
|
|
53
|
-
logger.error(
|
|
54
|
-
"No ecmaScript version or checkBrowser option specified in configuration",
|
|
55
|
-
);
|
|
62
|
+
logger.error("No ecmaScript version or checkBrowser option specified in configuration");
|
|
56
63
|
}
|
|
57
64
|
|
|
58
65
|
if (isExiting) process.exit(1);
|
|
59
66
|
|
|
60
|
-
allErrors
|
|
61
|
-
err: new Error(
|
|
62
|
-
"No ecmaScript version or checkBrowser option specified in configuration",
|
|
63
|
-
),
|
|
67
|
+
appendError(allErrors, {
|
|
68
|
+
err: new Error("No ecmaScript version or checkBrowser option specified in configuration"),
|
|
64
69
|
file: "config",
|
|
65
70
|
});
|
|
66
71
|
|
|
@@ -73,14 +78,12 @@ function handleMissingFiles(pattern, options) {
|
|
|
73
78
|
const isExiting = !isNodeAPI;
|
|
74
79
|
|
|
75
80
|
if (hasLogger) {
|
|
76
|
-
logger.error(
|
|
77
|
-
`ES-Check: Did not find any files to check for pattern: ${pattern}.`,
|
|
78
|
-
);
|
|
81
|
+
logger.error(`ES-Check: Did not find any files to check for pattern: ${pattern}.`);
|
|
79
82
|
}
|
|
80
83
|
|
|
81
84
|
if (isExiting) process.exit(1);
|
|
82
85
|
|
|
83
|
-
allErrors
|
|
86
|
+
appendError(allErrors, {
|
|
84
87
|
err: new Error(`Did not find any files to check for pattern: ${pattern}`),
|
|
85
88
|
file: "glob",
|
|
86
89
|
});
|
|
@@ -93,15 +96,17 @@ function findFiles(patterns, options) {
|
|
|
93
96
|
const shouldEnforceFilePatterns = !hasFilePatterns && !looseGlobMatching;
|
|
94
97
|
const hasLogger = logger !== null && logger !== undefined;
|
|
95
98
|
const isExiting = !isNodeAPI;
|
|
99
|
+
const shouldLogMissingPatterns = shouldEnforceFilePatterns && hasLogger;
|
|
100
|
+
const shouldExitMissingPatterns = shouldEnforceFilePatterns && isExiting;
|
|
96
101
|
|
|
97
|
-
if (
|
|
102
|
+
if (shouldLogMissingPatterns) {
|
|
98
103
|
logger.error("ES-Check: No file patterns specified to check.");
|
|
99
104
|
}
|
|
100
105
|
|
|
101
|
-
if (
|
|
106
|
+
if (shouldExitMissingPatterns) process.exit(1);
|
|
102
107
|
|
|
103
108
|
if (shouldEnforceFilePatterns) {
|
|
104
|
-
allErrors
|
|
109
|
+
appendError(allErrors, {
|
|
105
110
|
err: new Error("No file patterns specified to check"),
|
|
106
111
|
file: "config",
|
|
107
112
|
});
|
|
@@ -109,7 +114,7 @@ function findFiles(patterns, options) {
|
|
|
109
114
|
}
|
|
110
115
|
|
|
111
116
|
let hasPatternWithNoFiles = false;
|
|
112
|
-
const
|
|
117
|
+
const matchPattern = (pattern) => {
|
|
113
118
|
const globbedFiles = glob.sync(pattern, globOpts);
|
|
114
119
|
const noFilesFound = globbedFiles.length === 0;
|
|
115
120
|
const shouldErrorOnNoFiles = noFilesFound && !looseGlobMatching;
|
|
@@ -120,35 +125,34 @@ function findFiles(patterns, options) {
|
|
|
120
125
|
}
|
|
121
126
|
|
|
122
127
|
return globbedFiles;
|
|
123
|
-
}
|
|
128
|
+
};
|
|
129
|
+
const allMatchedFiles = patterns.map(matchPattern).flat();
|
|
124
130
|
|
|
125
131
|
const noMatchedFiles = allMatchedFiles.length === 0;
|
|
126
|
-
const shouldErrorOnNoMatchedFiles =
|
|
127
|
-
noMatchedFiles && hasFilePatterns && !looseGlobMatching;
|
|
132
|
+
const shouldErrorOnNoMatchedFiles = noMatchedFiles && hasFilePatterns && !looseGlobMatching;
|
|
128
133
|
const shouldWarnOnNoMatchedFiles = noMatchedFiles && looseGlobMatching;
|
|
134
|
+
const shouldLogNoMatchedFiles = shouldErrorOnNoMatchedFiles && hasLogger;
|
|
135
|
+
const shouldExitNoMatchedFiles = shouldErrorOnNoMatchedFiles && isExiting;
|
|
136
|
+
const shouldLogNoMatchedFilesWarning = shouldWarnOnNoMatchedFiles && hasLogger;
|
|
129
137
|
|
|
130
|
-
if (
|
|
138
|
+
if (shouldLogNoMatchedFiles) {
|
|
131
139
|
logger.error(
|
|
132
140
|
`ES-Check: Did not find any files to check across all patterns: ${patterns.join(", ")}.`,
|
|
133
141
|
);
|
|
134
142
|
}
|
|
135
143
|
|
|
136
|
-
if (
|
|
144
|
+
if (shouldExitNoMatchedFiles) process.exit(1);
|
|
137
145
|
|
|
138
146
|
if (shouldErrorOnNoMatchedFiles) {
|
|
139
|
-
allErrors
|
|
140
|
-
err: new Error(
|
|
141
|
-
`Did not find any files to check across all patterns: ${patterns.join(", ")}`,
|
|
142
|
-
),
|
|
147
|
+
appendError(allErrors, {
|
|
148
|
+
err: new Error(`Did not find any files to check across all patterns: ${patterns.join(", ")}`),
|
|
143
149
|
file: "glob",
|
|
144
150
|
});
|
|
145
151
|
return { files: [], hasError: true };
|
|
146
152
|
}
|
|
147
153
|
|
|
148
|
-
if (
|
|
149
|
-
logger.warn(
|
|
150
|
-
"ES-Check: No file patterns specified or no files found (running in loose mode).",
|
|
151
|
-
);
|
|
154
|
+
if (shouldLogNoMatchedFilesWarning) {
|
|
155
|
+
logger.warn("ES-Check: No file patterns specified or no files found (running in loose mode).");
|
|
152
156
|
}
|
|
153
157
|
|
|
154
158
|
return { files: allMatchedFiles, hasError: hasPatternWithNoFiles };
|
|
@@ -160,17 +164,13 @@ function handleBrowserslistError(browserslistError, options) {
|
|
|
160
164
|
const isExiting = !isNodeAPI;
|
|
161
165
|
|
|
162
166
|
if (hasLogger) {
|
|
163
|
-
logger.error(
|
|
164
|
-
`Error determining ES version from browserslist: ${browserslistError.message}`,
|
|
165
|
-
);
|
|
167
|
+
logger.error(`Error determining ES version from browserslist: ${browserslistError.message}`);
|
|
166
168
|
}
|
|
167
169
|
|
|
168
170
|
if (isExiting) process.exit(1);
|
|
169
171
|
|
|
170
|
-
allErrors
|
|
171
|
-
err: new Error(
|
|
172
|
-
`Error determining ES version from browserslist: ${browserslistError.message}`,
|
|
173
|
-
),
|
|
172
|
+
appendError(allErrors, {
|
|
173
|
+
err: new Error(`Error determining ES version from browserslist: ${browserslistError.message}`),
|
|
174
174
|
file: "browserslist",
|
|
175
175
|
});
|
|
176
176
|
}
|
|
@@ -181,14 +181,12 @@ function handleInvalidVersion(options) {
|
|
|
181
181
|
const isExiting = !isNodeAPI;
|
|
182
182
|
|
|
183
183
|
if (hasLogger) {
|
|
184
|
-
logger.error(
|
|
185
|
-
"Invalid ecmaScript version, please pass a valid version, use --help for help",
|
|
186
|
-
);
|
|
184
|
+
logger.error("Invalid ecmaScript version, please pass a valid version, use --help for help");
|
|
187
185
|
}
|
|
188
186
|
|
|
189
187
|
if (isExiting) process.exit(1);
|
|
190
188
|
|
|
191
|
-
allErrors
|
|
189
|
+
appendError(allErrors, {
|
|
192
190
|
err: new Error("Invalid ecmaScript version"),
|
|
193
191
|
file: "config",
|
|
194
192
|
});
|
|
@@ -198,9 +196,7 @@ function determineEcmaVersion(config, options) {
|
|
|
198
196
|
const { logger, isDebug, isWarn, isNodeAPI, allErrors } = options;
|
|
199
197
|
const { ecmaVersion: expectedEcmaVersion, checkBrowser } = config;
|
|
200
198
|
|
|
201
|
-
const isBrowserslistCheck = Boolean(
|
|
202
|
-
expectedEcmaVersion === "checkBrowser" || checkBrowser,
|
|
203
|
-
);
|
|
199
|
+
const isBrowserslistCheck = Boolean(expectedEcmaVersion === "checkBrowser" || checkBrowser);
|
|
204
200
|
|
|
205
201
|
if (isBrowserslistCheck) {
|
|
206
202
|
const browserslistQuery = config.browserslistQuery;
|
|
@@ -224,9 +220,7 @@ function determineEcmaVersion(config, options) {
|
|
|
224
220
|
const shouldDebug = hasNoError && isDebug;
|
|
225
221
|
|
|
226
222
|
if (shouldDebug) {
|
|
227
|
-
logger.debug(
|
|
228
|
-
`ES-Check: Using ES${ecmaVersion} based on browserslist configuration`,
|
|
229
|
-
);
|
|
223
|
+
logger.debug(`ES-Check: Using ES${ecmaVersion} based on browserslist configuration`);
|
|
230
224
|
}
|
|
231
225
|
|
|
232
226
|
if (hasError) {
|
|
@@ -243,8 +237,7 @@ function determineEcmaVersion(config, options) {
|
|
|
243
237
|
|
|
244
238
|
const mappedVersion = ECMA_VERSION_MAP[expectedEcmaVersion];
|
|
245
239
|
const isInvalidVersion = !mappedVersion;
|
|
246
|
-
const isLegacyVersion =
|
|
247
|
-
expectedEcmaVersion === "es3" || expectedEcmaVersion === "es4";
|
|
240
|
+
const isLegacyVersion = expectedEcmaVersion === "es3" || expectedEcmaVersion === "es4";
|
|
248
241
|
const hasLegacyWarning = isLegacyVersion && isWarn;
|
|
249
242
|
|
|
250
243
|
if (hasLegacyWarning) {
|
|
@@ -274,42 +267,38 @@ function filterIgnoredFiles(files, pathsToIgnore, globOpts) {
|
|
|
274
267
|
const hasNoExpandedIgnores = expandedPathsToIgnore.length === 0;
|
|
275
268
|
if (hasNoExpandedIgnores) return files;
|
|
276
269
|
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
270
|
+
const shouldKeepFile = (filePath) => {
|
|
271
|
+
let index = 0;
|
|
272
|
+
while (index < expandedPathsToIgnore.length) {
|
|
273
|
+
const ignoreValue = expandedPathsToIgnore[index];
|
|
274
|
+
const pathParts = filePath.split(ignoreValue);
|
|
275
|
+
const includesIgnoreValue = pathParts.length > 1;
|
|
276
|
+
if (includesIgnoreValue) return false;
|
|
277
|
+
index += 1;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
return true;
|
|
281
|
+
};
|
|
282
|
+
|
|
283
|
+
return files.filter(shouldKeepFile);
|
|
282
284
|
}
|
|
283
285
|
|
|
284
|
-
function processFullAST(
|
|
285
|
-
code,
|
|
286
|
-
acornOpts,
|
|
287
|
-
file,
|
|
288
|
-
config,
|
|
289
|
-
ignoreList,
|
|
290
|
-
ecmaVersion,
|
|
291
|
-
isDebug,
|
|
292
|
-
logger,
|
|
293
|
-
) {
|
|
286
|
+
function processFullAST(code, acornOpts, file, config, ignoreList, ecmaVersion, isDebug, logger) {
|
|
294
287
|
const needsFullAST = config.checkFeatures;
|
|
295
288
|
const parserOptions = needsFullAST
|
|
296
289
|
? acornOpts
|
|
297
|
-
: {
|
|
290
|
+
: Object.assign({}, acornOpts, {
|
|
291
|
+
locations: false,
|
|
292
|
+
ranges: false,
|
|
293
|
+
onComment: null,
|
|
294
|
+
});
|
|
298
295
|
|
|
299
|
-
const { ast, error: parseError } = parseCode(
|
|
300
|
-
code,
|
|
301
|
-
parserOptions,
|
|
302
|
-
acorn,
|
|
303
|
-
file,
|
|
304
|
-
config,
|
|
305
|
-
);
|
|
296
|
+
const { ast, error: parseError } = parseCode(code, parserOptions, acorn, file, config);
|
|
306
297
|
const hasParseError = parseError !== null;
|
|
307
298
|
const shouldDebugError = hasParseError && isDebug;
|
|
308
299
|
|
|
309
300
|
if (shouldDebugError) {
|
|
310
|
-
logger.debug(
|
|
311
|
-
`ES-Check: failed to parse file: ${file} \n - error: ${parseError.err}`,
|
|
312
|
-
);
|
|
301
|
+
logger.debug(`ES-Check: failed to parse file: ${file} \n - error: ${parseError.err}`);
|
|
313
302
|
}
|
|
314
303
|
|
|
315
304
|
if (hasParseError) return parseError;
|
|
@@ -324,17 +313,11 @@ function processFullAST(
|
|
|
324
313
|
let unsupportedFeatures;
|
|
325
314
|
|
|
326
315
|
try {
|
|
327
|
-
const result = detectFeatures(
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
{
|
|
333
|
-
ast,
|
|
334
|
-
checkForPolyfills: config.checkForPolyfills,
|
|
335
|
-
ignorePolyfillable: config.ignorePolyfillable,
|
|
336
|
-
},
|
|
337
|
-
);
|
|
316
|
+
const result = detectFeatures(code, esVersion, parseSourceType, ignoreList, {
|
|
317
|
+
ast,
|
|
318
|
+
checkForPolyfills: config.checkForPolyfills,
|
|
319
|
+
ignorePolyfillable: config.ignorePolyfillable,
|
|
320
|
+
});
|
|
338
321
|
foundFeatures = result.foundFeatures;
|
|
339
322
|
unsupportedFeatures = result.unsupportedFeatures;
|
|
340
323
|
} catch (err) {
|
|
@@ -350,8 +333,7 @@ function processFullAST(
|
|
|
350
333
|
logger.debug(`Features found in ${file}: ${stringifiedFeatures}`);
|
|
351
334
|
}
|
|
352
335
|
|
|
353
|
-
const shouldCheckPolyfills =
|
|
354
|
-
config.checkForPolyfills && unsupportedFeatures.length > 0;
|
|
336
|
+
const shouldCheckPolyfills = config.checkForPolyfills && unsupportedFeatures.length > 0;
|
|
355
337
|
|
|
356
338
|
if (!shouldCheckPolyfills) {
|
|
357
339
|
const isSupported = unsupportedFeatures.length === 0;
|
|
@@ -378,8 +360,7 @@ function processFullAST(
|
|
|
378
360
|
);
|
|
379
361
|
|
|
380
362
|
const hasPolyfillReduction =
|
|
381
|
-
isDebug &&
|
|
382
|
-
filteredUnsupportedFeatures.length !== unsupportedFeatures.length;
|
|
363
|
+
isDebug && filteredUnsupportedFeatures.length !== unsupportedFeatures.length;
|
|
383
364
|
|
|
384
365
|
if (hasPolyfillReduction) {
|
|
385
366
|
logger.debug(
|
|
@@ -395,8 +376,7 @@ function processFullAST(
|
|
|
395
376
|
);
|
|
396
377
|
|
|
397
378
|
const hasPolyfillableReduction =
|
|
398
|
-
isDebug &&
|
|
399
|
-
filteredUnsupportedFeatures.length !== beforeIgnorePolyfillable;
|
|
379
|
+
isDebug && filteredUnsupportedFeatures.length !== beforeIgnorePolyfillable;
|
|
400
380
|
|
|
401
381
|
if (hasPolyfillableReduction) {
|
|
402
382
|
logger.debug(
|
|
@@ -431,16 +411,7 @@ function createFileProcessor(config, options) {
|
|
|
431
411
|
logger.debug(`ES-Check: checking ${file}`);
|
|
432
412
|
}
|
|
433
413
|
|
|
434
|
-
return processFullAST(
|
|
435
|
-
code,
|
|
436
|
-
acornOpts,
|
|
437
|
-
file,
|
|
438
|
-
config,
|
|
439
|
-
ignoreList,
|
|
440
|
-
ecmaVersion,
|
|
441
|
-
isDebug,
|
|
442
|
-
logger,
|
|
443
|
-
);
|
|
414
|
+
return processFullAST(code, acornOpts, file, config, ignoreList, ecmaVersion, isDebug, logger);
|
|
444
415
|
};
|
|
445
416
|
}
|
|
446
417
|
|
|
@@ -448,9 +419,7 @@ function logErrors(errors, logger) {
|
|
|
448
419
|
const hasLogger = logger !== null && logger !== undefined;
|
|
449
420
|
if (!hasLogger) return;
|
|
450
421
|
|
|
451
|
-
logger.error(
|
|
452
|
-
`ES-Check: there were ${errors.length} ES version matching errors.`,
|
|
453
|
-
);
|
|
422
|
+
logger.error(`ES-Check: there were ${errors.length} ES version matching errors.`);
|
|
454
423
|
|
|
455
424
|
const { mapErrorPosition } = require("../helpers/sourcemap");
|
|
456
425
|
|
|
@@ -460,9 +429,7 @@ function logErrors(errors, logger) {
|
|
|
460
429
|
? mapErrorPosition(error.file, error.line, error.column)
|
|
461
430
|
: { file: error.file, line: error.line, column: error.column };
|
|
462
431
|
|
|
463
|
-
const locationInfo = hasLocation
|
|
464
|
-
? ` at ${mapped.file}:${mapped.line}:${mapped.column}`
|
|
465
|
-
: "";
|
|
432
|
+
const locationInfo = hasLocation ? ` at ${mapped.file}:${mapped.line}:${mapped.column}` : "";
|
|
466
433
|
|
|
467
434
|
logger.info(`
|
|
468
435
|
ES-Check Error:
|
|
@@ -476,18 +443,12 @@ function logErrors(errors, logger) {
|
|
|
476
443
|
}
|
|
477
444
|
}
|
|
478
445
|
|
|
479
|
-
function processConfigResult(
|
|
480
|
-
errors,
|
|
481
|
-
logger,
|
|
482
|
-
isNodeAPI,
|
|
483
|
-
allErrors,
|
|
484
|
-
ecmaVersion,
|
|
485
|
-
) {
|
|
446
|
+
function processConfigResult(errors, logger, isNodeAPI, allErrors, ecmaVersion) {
|
|
486
447
|
const hasFileErrors = errors.length > 0;
|
|
487
448
|
|
|
488
449
|
if (hasFileErrors) {
|
|
489
450
|
logErrors(errors, logger);
|
|
490
|
-
allErrors
|
|
451
|
+
appendErrors(allErrors, errors);
|
|
491
452
|
|
|
492
453
|
const isExiting = !isNodeAPI;
|
|
493
454
|
if (isExiting) {
|
|
@@ -499,9 +460,7 @@ function processConfigResult(
|
|
|
499
460
|
|
|
500
461
|
const hasLogger = logger !== null && logger !== undefined;
|
|
501
462
|
if (hasLogger) {
|
|
502
|
-
const versionLabel = ecmaVersion
|
|
503
|
-
? `ES${ecmaVersion}`
|
|
504
|
-
: "the specified ES version";
|
|
463
|
+
const versionLabel = ecmaVersion ? `ES${ecmaVersion}` : "the specified ES version";
|
|
505
464
|
logger.info(`✓ ES-Check passed! All files are ${versionLabel} compatible.`);
|
|
506
465
|
}
|
|
507
466
|
|
package/lib/cli/constants.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const CLI_DESCRIPTION = {
|
|
2
2
|
main: "es-check 🏆 - Check JavaScript files against an ECMAScript version",
|
|
3
3
|
ecmaVersion:
|
|
4
|
-
"ecmaVersion to check files against. Can be: es3, es4, es5, es6/es2015, es7/es2016, es8/es2017, es9/es2018, es10/es2019, es11/es2020, es12/es2021, es13/es2022, es14/es2023, es15/es2024, es16/es2025, checkBrowser",
|
|
4
|
+
"ecmaVersion to check files against. Can be: es3, es4, es5, es6/es2015, es7/es2016, es8/es2017, es9/es2018, es10/es2019, es11/es2020, es12/es2021, es13/es2022, es14/es2023, es15/es2024, es16/es2025, es17/es2026, checkBrowser",
|
|
5
5
|
files: "a glob of files to to test the EcmaScript version against",
|
|
6
6
|
completion: "generate shell completion script",
|
|
7
7
|
shell: "shell type: bash, zsh",
|
|
@@ -25,8 +25,7 @@ const CLI_OPTIONS = [
|
|
|
25
25
|
},
|
|
26
26
|
{
|
|
27
27
|
flags: "--files <files>",
|
|
28
|
-
description:
|
|
29
|
-
"a glob of files to to test the EcmaScript version against (alias for [files...])",
|
|
28
|
+
description: "a glob of files to to test the EcmaScript version against (alias for [files...])",
|
|
30
29
|
},
|
|
31
30
|
{
|
|
32
31
|
flags: "--not <files>",
|
|
@@ -65,8 +64,7 @@ const CLI_OPTIONS = [
|
|
|
65
64
|
},
|
|
66
65
|
{
|
|
67
66
|
flags: "--checkForPolyfills",
|
|
68
|
-
description:
|
|
69
|
-
"consider polyfills when checking features (only works with --checkFeatures)",
|
|
67
|
+
description: "consider polyfills when checking features (only works with --checkFeatures)",
|
|
70
68
|
default: false,
|
|
71
69
|
},
|
|
72
70
|
{
|
|
@@ -77,8 +75,7 @@ const CLI_OPTIONS = [
|
|
|
77
75
|
},
|
|
78
76
|
{
|
|
79
77
|
flags: "--ignore <features>",
|
|
80
|
-
description:
|
|
81
|
-
'comma-separated list of features to ignore, e.g., "ErrorCause,TopLevelAwait"',
|
|
78
|
+
description: 'comma-separated list of features to ignore, e.g., "ErrorCause,TopLevelAwait"',
|
|
82
79
|
},
|
|
83
80
|
{
|
|
84
81
|
flags: "--ignore-file <path>",
|