es-check 9.6.0-1 → 9.6.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.
- package/README.md +47 -23
- package/lib/check-runner/utils.js +5 -1
- package/lib/constants/es-features/13.js +1 -0
- package/lib/constants/es-features/polyfills.js +11 -11
- package/lib/detectFeatures.js +7 -2
- package/lib/helpers/ast.js +24 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -80,7 +80,7 @@ Modern JavaScript builds assume proper transpilation via tools like Babel. ES Ch
|
|
|
80
80
|
|
|
81
81
|
## What features does ES Check check for?
|
|
82
82
|
|
|
83
|
-
ES Check validates syntax by default. Add `--checkFeatures` for ES version-specific feature checking. View supported [features](./lib/
|
|
83
|
+
ES Check validates syntax by default. Add `--checkFeatures` for ES version-specific feature checking. View supported [features](./lib/constants/es-features/).
|
|
84
84
|
|
|
85
85
|
---
|
|
86
86
|
|
|
@@ -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
|
|
121
|
+
es13/es2022, es14/es2023, es15/es2024, es16/es2025
|
|
122
122
|
files a glob of files to to test the EcmaScript version against
|
|
123
123
|
|
|
124
124
|
```
|
|
@@ -142,6 +142,7 @@ Here's a comprehensive list of all available options:
|
|
|
142
142
|
| `--silent` | Silent mode: does not output anything, giving no indication of success or failure other than the exit code (default: false) |
|
|
143
143
|
| `--checkFeatures` | Check for actual ES version specific features (default: false) |
|
|
144
144
|
| `--checkForPolyfills` | Consider polyfills when checking features (only works with --checkFeatures) (default: false) |
|
|
145
|
+
| `--ignorePolyfillable [lib]` | Ignore polyfillable features; optionally specify library (e.g., `core-js`) to limit scope |
|
|
145
146
|
| `--ignore <features>` | Comma-separated list of features to ignore, e.g., "ErrorCause,TopLevelAwait" |
|
|
146
147
|
| `--ignoreFile <path>` | Path to JSON file containing features to ignore |
|
|
147
148
|
| `--allowList <features>` | Comma-separated list of features to allow even in lower ES versions, e.g., "const,let" |
|
|
@@ -309,6 +310,7 @@ Here's an example of what an `.escheckrc` file will look like:
|
|
|
309
310
|
"looseGlobMatching": false,
|
|
310
311
|
"checkFeatures": true,
|
|
311
312
|
"checkForPolyfills": true,
|
|
313
|
+
"ignorePolyfillable": "core-js",
|
|
312
314
|
"ignore": ["ErrorCause", "TopLevelAwait"],
|
|
313
315
|
"allowList": ["ArrayToSorted", "ObjectHasOwn"],
|
|
314
316
|
"checkBrowser": false,
|
|
@@ -320,22 +322,23 @@ Here's an example of what an `.escheckrc` file will look like:
|
|
|
320
322
|
|
|
321
323
|
### Configuration Options
|
|
322
324
|
|
|
323
|
-
| Option
|
|
324
|
-
|
|
|
325
|
-
| `ecmaVersion`
|
|
326
|
-
| `files`
|
|
327
|
-
| `module`
|
|
328
|
-
| `not`
|
|
329
|
-
| `allowHashBang`
|
|
330
|
-
| `looseGlobMatching`
|
|
331
|
-
| `checkFeatures`
|
|
332
|
-
| `checkForPolyfills`
|
|
333
|
-
| `
|
|
334
|
-
| `
|
|
335
|
-
| `
|
|
336
|
-
| `
|
|
337
|
-
| `
|
|
338
|
-
| `
|
|
325
|
+
| Option | Type | Description |
|
|
326
|
+
| -------------------- | --------------- | ------------------------------------------------------------------------------------ |
|
|
327
|
+
| `ecmaVersion` | String | ECMAScript version to check against (e.g., "es5", "es6", "es2020") |
|
|
328
|
+
| `files` | String or Array | Files or glob patterns to check |
|
|
329
|
+
| `module` | Boolean | Whether to parse files as ES modules |
|
|
330
|
+
| `not` | Array | Files or glob patterns to exclude |
|
|
331
|
+
| `allowHashBang` | Boolean | Whether to allow hash bang in files |
|
|
332
|
+
| `looseGlobMatching` | Boolean | Whether to ignore missing files in globs |
|
|
333
|
+
| `checkFeatures` | Boolean | Whether to check for ES version specific features |
|
|
334
|
+
| `checkForPolyfills` | Boolean | Whether to consider polyfills when checking features |
|
|
335
|
+
| `ignorePolyfillable` | Boolean/String | Ignore polyfillable features; set to library name (e.g., `"core-js"`) to limit scope |
|
|
336
|
+
| `ignore` | Array | Features to ignore when checking |
|
|
337
|
+
| `allowList` | Array | Features to allow even in lower ES versions |
|
|
338
|
+
| `checkBrowser` | Boolean | Whether to use browserslist configuration to determine ES version |
|
|
339
|
+
| `browserslistQuery` | String | Custom browserslist query to use |
|
|
340
|
+
| `browserslistPath` | String | Path to custom browserslist configuration |
|
|
341
|
+
| `browserslistEnv` | String | Browserslist environment to use |
|
|
339
342
|
|
|
340
343
|
### Multiple Configurations
|
|
341
344
|
|
|
@@ -443,7 +446,23 @@ ES Check provides three ways to handle polyfilled features:
|
|
|
443
446
|
es-check es2022 './dist/**/*.js' --checkFeatures --allowList="ArrayToSorted,ObjectHasOwn"
|
|
444
447
|
```
|
|
445
448
|
|
|
446
|
-
3. **--
|
|
449
|
+
3. **--ignorePolyfillable**: Ignore all features that can be polyfilled (or limit to a specific library)
|
|
450
|
+
|
|
451
|
+
```sh
|
|
452
|
+
# Ignore all polyfillable features
|
|
453
|
+
es-check es2017 './dist/**/*.js' --checkFeatures --ignorePolyfillable
|
|
454
|
+
|
|
455
|
+
# Ignore only features polyfillable by core-js
|
|
456
|
+
es-check es2017 './dist/**/*.js' --checkFeatures --ignorePolyfillable=core-js
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
4. **--allowList**: Explicitly specify features to allow regardless of ES version
|
|
460
|
+
|
|
461
|
+
```sh
|
|
462
|
+
es-check es2022 './dist/**/*.js' --checkFeatures --allowList="ArrayToSorted,ObjectHasOwn"
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
5. **--ignore**: Completely ignore specific features during checking
|
|
447
466
|
```sh
|
|
448
467
|
es-check es2022 './dist/**/*.js' --checkFeatures --ignore="ArrayToSorted,ObjectHasOwn"
|
|
449
468
|
```
|
|
@@ -451,6 +470,7 @@ ES Check provides three ways to handle polyfilled features:
|
|
|
451
470
|
#### When to use each option:
|
|
452
471
|
|
|
453
472
|
- Use `--checkForPolyfills` when you have a standard polyfill setup (like core-js) and want automatic detection
|
|
473
|
+
- Use `--ignorePolyfillable` when you know polyfills are provided externally and don't want to flag polyfillable features
|
|
454
474
|
- Use `--allowList` when you have custom polyfills or want to be explicit about which features are allowed
|
|
455
475
|
- Use `--ignore` as a temporary solution when you're working on fixes
|
|
456
476
|
|
|
@@ -584,7 +604,11 @@ flowchart LR
|
|
|
584
604
|
E -->|No| F[Success]
|
|
585
605
|
G --> G1{Features<br/>Valid?}
|
|
586
606
|
G1 -->|Pass| H{--checkForPolyfills?}
|
|
587
|
-
G1 -->|Fail|
|
|
607
|
+
G1 -->|Fail| L{--ignorePolyfillable?}
|
|
608
|
+
L -->|Yes| M{Feature<br/>Polyfillable?}
|
|
609
|
+
L -->|No| D
|
|
610
|
+
M -->|Yes| F
|
|
611
|
+
M -->|No| D
|
|
588
612
|
H -->|Yes| I{Polyfills<br/>Detected?}
|
|
589
613
|
H -->|No| F
|
|
590
614
|
I -->|Yes| F
|
|
@@ -693,9 +717,9 @@ To update ES version support:
|
|
|
693
717
|
|
|
694
718
|
To update ES feature detection:
|
|
695
719
|
|
|
696
|
-
- Add features to [version-specific files](./lib/
|
|
697
|
-
- Update [polyfill patterns](./lib/
|
|
698
|
-
- Feature detection uses [
|
|
720
|
+
- Add features to [version-specific files](./lib/constants/es-features/) (e.g., `6.js` for ES6 features)
|
|
721
|
+
- Update [polyfill patterns](./lib/constants/es-features/polyfills.js) if needed
|
|
722
|
+
- Feature detection uses AST traversal via [Acorn](https://github.com/acornjs/acorn/)
|
|
699
723
|
|
|
700
724
|
Tests are located in `tests/unit/` and mirror the `lib/` structure. Please add tests for new features!
|
|
701
725
|
|
|
@@ -329,7 +329,11 @@ function processFullAST(
|
|
|
329
329
|
esVersion,
|
|
330
330
|
parseSourceType,
|
|
331
331
|
ignoreList,
|
|
332
|
-
{
|
|
332
|
+
{
|
|
333
|
+
ast,
|
|
334
|
+
checkForPolyfills: config.checkForPolyfills,
|
|
335
|
+
ignorePolyfillable: config.ignorePolyfillable,
|
|
336
|
+
},
|
|
333
337
|
);
|
|
334
338
|
foundFeatures = result.foundFeatures;
|
|
335
339
|
unsupportedFeatures = result.unsupportedFeatures;
|
|
@@ -15,57 +15,57 @@ const POLYFILL_PATTERNS = [
|
|
|
15
15
|
const IMPORT_PATTERNS = [
|
|
16
16
|
{
|
|
17
17
|
pattern:
|
|
18
|
-
/(?:from\s+|require\s*\(\s
|
|
18
|
+
/(?:from\s+|require\s*\(\s*|import\s+)['"]core-js\/modules\/es\.array\.to-sorted['"]/,
|
|
19
19
|
feature: "ArrayToSorted",
|
|
20
20
|
},
|
|
21
21
|
{
|
|
22
22
|
pattern:
|
|
23
|
-
/(?:from\s+|require\s*\(\s
|
|
23
|
+
/(?:from\s+|require\s*\(\s*|import\s+)['"]core-js\/modules\/es\.array\.find-last['"]/,
|
|
24
24
|
feature: "ArrayFindLast",
|
|
25
25
|
},
|
|
26
26
|
{
|
|
27
27
|
pattern:
|
|
28
|
-
/(?:from\s+|require\s*\(\s
|
|
28
|
+
/(?:from\s+|require\s*\(\s*|import\s+)['"]core-js\/modules\/es\.array\.find-last-index['"]/,
|
|
29
29
|
feature: "ArrayFindLastIndex",
|
|
30
30
|
},
|
|
31
31
|
{
|
|
32
32
|
pattern:
|
|
33
|
-
/(?:from\s+|require\s*\(\s
|
|
33
|
+
/(?:from\s+|require\s*\(\s*|import\s+)['"]core-js\/modules\/es\.array\.at['"]/,
|
|
34
34
|
feature: "ArrayAt",
|
|
35
35
|
},
|
|
36
36
|
{
|
|
37
37
|
pattern:
|
|
38
|
-
/(?:from\s+|require\s*\(\s
|
|
38
|
+
/(?:from\s+|require\s*\(\s*|import\s+)['"]core-js\/modules\/es\.string\.replace-all['"]/,
|
|
39
39
|
feature: "StringReplaceAll",
|
|
40
40
|
},
|
|
41
41
|
{
|
|
42
42
|
pattern:
|
|
43
|
-
/(?:from\s+|require\s*\(\s
|
|
43
|
+
/(?:from\s+|require\s*\(\s*|import\s+)['"]core-js\/modules\/es\.string\.match-all['"]/,
|
|
44
44
|
feature: "StringMatchAll",
|
|
45
45
|
},
|
|
46
46
|
{
|
|
47
47
|
pattern:
|
|
48
|
-
/(?:from\s+|require\s*\(\s
|
|
48
|
+
/(?:from\s+|require\s*\(\s*|import\s+)['"]core-js\/modules\/es\.string\.at['"]/,
|
|
49
49
|
feature: "StringAt",
|
|
50
50
|
},
|
|
51
51
|
{
|
|
52
52
|
pattern:
|
|
53
|
-
/(?:from\s+|require\s*\(\s
|
|
53
|
+
/(?:from\s+|require\s*\(\s*|import\s+)['"]core-js\/modules\/es\.object\.has-own['"]/,
|
|
54
54
|
feature: "ObjectHasOwn",
|
|
55
55
|
},
|
|
56
56
|
{
|
|
57
57
|
pattern:
|
|
58
|
-
/(?:from\s+|require\s*\(\s
|
|
58
|
+
/(?:from\s+|require\s*\(\s*|import\s+)['"]core-js\/modules\/es\.promise\.any['"]/,
|
|
59
59
|
feature: "PromiseAny",
|
|
60
60
|
},
|
|
61
61
|
{
|
|
62
62
|
pattern:
|
|
63
|
-
/(?:from\s+|require\s*\(\s
|
|
63
|
+
/(?:from\s+|require\s*\(\s*|import\s+)['"]core-js\/modules\/es\.regexp\.exec['"]/,
|
|
64
64
|
feature: "RegExpExec",
|
|
65
65
|
},
|
|
66
66
|
{
|
|
67
67
|
pattern:
|
|
68
|
-
/(?:from\s+|require\s*\(\s
|
|
68
|
+
/(?:from\s+|require\s*\(\s*|import\s+)['"]core-js\/modules\/es\.global-this['"]/,
|
|
69
69
|
feature: "GlobalThis",
|
|
70
70
|
},
|
|
71
71
|
];
|
package/lib/detectFeatures.js
CHANGED
|
@@ -63,7 +63,7 @@ const detectFeatures = (
|
|
|
63
63
|
ignoreList = new Set(),
|
|
64
64
|
options = {},
|
|
65
65
|
) => {
|
|
66
|
-
const { checkForPolyfills, ast } = options;
|
|
66
|
+
const { checkForPolyfills, ast, ignorePolyfillable } = options;
|
|
67
67
|
|
|
68
68
|
if (!ast) {
|
|
69
69
|
const error = new Error("AST is required for feature detection");
|
|
@@ -76,13 +76,18 @@ const detectFeatures = (
|
|
|
76
76
|
|
|
77
77
|
const foundFeatures = detectFeaturesFromAST(ast);
|
|
78
78
|
|
|
79
|
+
const polyfillableSet = ignorePolyfillable
|
|
80
|
+
? getPolyfillableFeatures(ignorePolyfillable)
|
|
81
|
+
: null;
|
|
82
|
+
|
|
79
83
|
const unsupportedFeatures = Object.entries(ES_FEATURES)
|
|
80
84
|
.filter(
|
|
81
85
|
([name, { minVersion }]) =>
|
|
82
86
|
foundFeatures[name] &&
|
|
83
87
|
minVersion > ecmaVersion &&
|
|
84
88
|
!ignoreList.has(name) &&
|
|
85
|
-
!(checkForPolyfills && polyfills.has(name))
|
|
89
|
+
!(checkForPolyfills && polyfills.has(name)) &&
|
|
90
|
+
!(polyfillableSet && polyfillableSet.has(name)),
|
|
86
91
|
)
|
|
87
92
|
.map(([name]) => name);
|
|
88
93
|
|
package/lib/helpers/ast.js
CHANGED
|
@@ -13,6 +13,25 @@ function hasOptionsCause(node) {
|
|
|
13
13
|
);
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
+
function hasNumericArgument(node) {
|
|
17
|
+
const args = node.arguments;
|
|
18
|
+
const hasArgs = args && args.length === 1;
|
|
19
|
+
if (!hasArgs) return false;
|
|
20
|
+
|
|
21
|
+
const arg = args[0];
|
|
22
|
+
const isNumericLiteral =
|
|
23
|
+
arg.type === "Literal" && typeof arg.value === "number";
|
|
24
|
+
|
|
25
|
+
const isUnaryExpression = arg.type === "UnaryExpression";
|
|
26
|
+
const isNegationOperator = arg.operator === "-";
|
|
27
|
+
const hasNumericLiteralArgument =
|
|
28
|
+
arg.argument?.type === "Literal" && typeof arg.argument.value === "number";
|
|
29
|
+
const isNegativeNumeric =
|
|
30
|
+
isUnaryExpression && isNegationOperator && hasNumericLiteralArgument;
|
|
31
|
+
|
|
32
|
+
return isNumericLiteral || isNegativeNumeric;
|
|
33
|
+
}
|
|
34
|
+
|
|
16
35
|
function checkMap(node, astInfo) {
|
|
17
36
|
const callee = node.callee;
|
|
18
37
|
const calleeObject = callee?.object;
|
|
@@ -60,6 +79,9 @@ function checkMap(node, astInfo) {
|
|
|
60
79
|
const hasExcludedCallerType =
|
|
61
80
|
astInfo.excludeCallerTypes?.includes(callerType);
|
|
62
81
|
|
|
82
|
+
const hasNumericArgMismatch =
|
|
83
|
+
astInfo.requireNumericArg && !hasNumericArgument(node);
|
|
84
|
+
|
|
63
85
|
const hasMismatch =
|
|
64
86
|
hasKindMismatch ||
|
|
65
87
|
hasOperatorMismatch ||
|
|
@@ -70,7 +92,8 @@ function checkMap(node, astInfo) {
|
|
|
70
92
|
hasPropertyWithExclusion ||
|
|
71
93
|
hasObjectAndPropertyMismatch ||
|
|
72
94
|
hasOptionsCauseMismatch ||
|
|
73
|
-
hasExcludedCallerType
|
|
95
|
+
hasExcludedCallerType ||
|
|
96
|
+
hasNumericArgMismatch;
|
|
74
97
|
|
|
75
98
|
if (hasMismatch) return false;
|
|
76
99
|
|
package/package.json
CHANGED