eslint-plugin-n 17.5.1 → 17.7.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 +5 -5
- package/lib/rules/hashbang.js +61 -6
- package/lib/rules/no-unsupported-features/node-builtins.js +1 -0
- package/lib/unsupported-features/node-builtins-modules/crypto.js +11 -3
- package/lib/unsupported-features/node-builtins-modules/events.js +6 -1
- package/lib/unsupported-features/node-builtins-modules/fs.js +20 -13
- package/lib/unsupported-features/node-builtins-modules/process.js +1 -0
- package/lib/unsupported-features/node-builtins-modules/test.js +6 -0
- package/lib/unsupported-features/node-builtins-modules/v8.js +1 -0
- package/lib/util/check-unsupported-builtins.js +66 -22
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -18,11 +18,11 @@ Additional ESLint rules for Node.js
|
|
|
18
18
|
npm install --save-dev eslint eslint-plugin-n
|
|
19
19
|
```
|
|
20
20
|
|
|
21
|
-
| Version | Supported Node.js | Supported ESLint Version |
|
|
22
|
-
|
|
23
|
-
| 17.x | `^18.18.0 \|\| ^20.9.0 \|\| >=21.1.0` | `>=8.23.0` |
|
|
24
|
-
| 16.x | `>=16.0.0` | `>=7.0.0` |
|
|
25
|
-
| 15.x | `>=12.22.0` | `>=7.0.0` |
|
|
21
|
+
| Version | Supported Node.js | Supported ESLint Version | Status |
|
|
22
|
+
|---------|-------------------|---------------------------|--------|
|
|
23
|
+
| 17.x | `^18.18.0 \|\| ^20.9.0 \|\| >=21.1.0` | `>=8.23.0` | 🏃♂️actively maintained |
|
|
24
|
+
| 16.x | `>=16.0.0` | `>=7.0.0` | ⚠️EOL |
|
|
25
|
+
| 15.x | `>=12.22.0` | `>=7.0.0` | ⚠️EOL |
|
|
26
26
|
|
|
27
27
|
**Note:** It recommends a use of [the "engines" field of package.json](https://docs.npmjs.com/files/package.json#engines). The "engines" field is used by `n/no-unsupported-features/*` rules.
|
|
28
28
|
|
package/lib/rules/hashbang.js
CHANGED
|
@@ -12,10 +12,50 @@ const { getPackageJson } = require("../util/get-package-json")
|
|
|
12
12
|
const getNpmignore = require("../util/get-npmignore")
|
|
13
13
|
const { isBinFile } = require("../util/is-bin-file")
|
|
14
14
|
|
|
15
|
-
const
|
|
15
|
+
const ENV_SHEBANG = "#!/usr/bin/env"
|
|
16
|
+
const NODE_SHEBANG = `${ENV_SHEBANG} {{executableName}}\n`
|
|
16
17
|
const SHEBANG_PATTERN = /^(#!.+?)?(\r)?\n/u
|
|
17
|
-
|
|
18
|
-
|
|
18
|
+
|
|
19
|
+
// -i -S
|
|
20
|
+
// -u name
|
|
21
|
+
// --ignore-environment
|
|
22
|
+
// --block-signal=SIGINT
|
|
23
|
+
const ENV_FLAGS = /^\s*-(-.*?\b|[ivS]+|[Pu](\s+|=)\S+)(?=\s|$)/
|
|
24
|
+
|
|
25
|
+
// NAME="some variable"
|
|
26
|
+
// FOO=bar
|
|
27
|
+
const ENV_VARS = /^\s*\w+=(?:"(?:[^"\\]|\\.)*"|\w+)/
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* @param {string} shebang
|
|
31
|
+
* @param {string} executableName
|
|
32
|
+
* @returns {boolean}
|
|
33
|
+
*/
|
|
34
|
+
function isNodeShebang(shebang, executableName) {
|
|
35
|
+
if (shebang == null || shebang.length === 0) {
|
|
36
|
+
return false
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
shebang = shebang.slice(shebang.indexOf(ENV_SHEBANG) + ENV_SHEBANG.length)
|
|
40
|
+
while (ENV_FLAGS.test(shebang) || ENV_VARS.test(shebang)) {
|
|
41
|
+
shebang = shebang.replace(ENV_FLAGS, "").replace(ENV_VARS, "")
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const [command] = shebang.trim().split(" ")
|
|
45
|
+
return command === executableName
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* @param {import('eslint').Rule.RuleContext} context The rule context.
|
|
50
|
+
* @returns {string}
|
|
51
|
+
*/
|
|
52
|
+
function getExpectedExecutableName(context) {
|
|
53
|
+
const extension = path.extname(context.filename)
|
|
54
|
+
/** @type {{ executableMap: Record<string, string> }} */
|
|
55
|
+
const { executableMap = {} } = context.options?.[0] ?? {}
|
|
56
|
+
|
|
57
|
+
return executableMap[extension] ?? "node"
|
|
58
|
+
}
|
|
19
59
|
|
|
20
60
|
/**
|
|
21
61
|
* Gets the shebang line (includes a line ending) from a given code.
|
|
@@ -56,6 +96,16 @@ module.exports = {
|
|
|
56
96
|
type: "array",
|
|
57
97
|
items: { type: "string" },
|
|
58
98
|
},
|
|
99
|
+
executableMap: {
|
|
100
|
+
type: "object",
|
|
101
|
+
patternProperties: {
|
|
102
|
+
"^\\.\\w+$": {
|
|
103
|
+
type: "string",
|
|
104
|
+
pattern: "^[\\w-]+$",
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
additionalProperties: false,
|
|
108
|
+
},
|
|
59
109
|
},
|
|
60
110
|
additionalProperties: false,
|
|
61
111
|
},
|
|
@@ -64,7 +114,7 @@ module.exports = {
|
|
|
64
114
|
unexpectedBOM: "This file must not have Unicode BOM.",
|
|
65
115
|
expectedLF: "This file must have Unix linebreaks (LF).",
|
|
66
116
|
expectedHashbangNode:
|
|
67
|
-
'This file needs shebang "#!/usr/bin/env
|
|
117
|
+
'This file needs shebang "#!/usr/bin/env {{executableName}}".',
|
|
68
118
|
expectedHashbang: "This file needs no shebang.",
|
|
69
119
|
},
|
|
70
120
|
},
|
|
@@ -116,6 +166,7 @@ module.exports = {
|
|
|
116
166
|
const needsShebang =
|
|
117
167
|
isExecutable.ignored === true ||
|
|
118
168
|
isBinFile(convertedAbsolutePath, packageJson?.bin, packageDirectory)
|
|
169
|
+
const executableName = getExpectedExecutableName(context)
|
|
119
170
|
const info = getShebangInfo(sourceCode)
|
|
120
171
|
|
|
121
172
|
return {
|
|
@@ -130,7 +181,7 @@ module.exports = {
|
|
|
130
181
|
|
|
131
182
|
if (
|
|
132
183
|
needsShebang
|
|
133
|
-
?
|
|
184
|
+
? isNodeShebang(info.shebang, executableName)
|
|
134
185
|
: !info.shebang
|
|
135
186
|
) {
|
|
136
187
|
// Good the shebang target.
|
|
@@ -159,10 +210,14 @@ module.exports = {
|
|
|
159
210
|
context.report({
|
|
160
211
|
loc,
|
|
161
212
|
messageId: "expectedHashbangNode",
|
|
213
|
+
data: { executableName },
|
|
162
214
|
fix(fixer) {
|
|
163
215
|
return fixer.replaceTextRange(
|
|
164
216
|
[-1, info.length],
|
|
165
|
-
NODE_SHEBANG
|
|
217
|
+
NODE_SHEBANG.replaceAll(
|
|
218
|
+
"{{executableName}}",
|
|
219
|
+
executableName
|
|
220
|
+
)
|
|
166
221
|
)
|
|
167
222
|
},
|
|
168
223
|
})
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict"
|
|
2
2
|
|
|
3
|
-
const { READ } = require("@eslint-community/eslint-utils")
|
|
3
|
+
const { CALL, CONSTRUCT, READ } = require("@eslint-community/eslint-utils")
|
|
4
4
|
|
|
5
5
|
/** @type {import('../types.js').SupportVersionTraceMap} */
|
|
6
6
|
const WebCrypto = {
|
|
@@ -106,8 +106,16 @@ const crypto = {
|
|
|
106
106
|
[READ]: { supported: ["0.11.14"] },
|
|
107
107
|
convertKey: { [READ]: { supported: ["10.0.0"] } },
|
|
108
108
|
},
|
|
109
|
-
Hash: {
|
|
110
|
-
|
|
109
|
+
Hash: {
|
|
110
|
+
[READ]: { supported: ["0.1.92"] },
|
|
111
|
+
[CALL]: { deprecated: ["22.0.0", "20.13.0"] },
|
|
112
|
+
[CONSTRUCT]: { deprecated: ["22.0.0", "20.13.0"] },
|
|
113
|
+
},
|
|
114
|
+
Hmac: {
|
|
115
|
+
[READ]: { supported: ["0.1.94"] },
|
|
116
|
+
[CALL]: { deprecated: ["22.0.0", "20.13.0"] },
|
|
117
|
+
[CONSTRUCT]: { deprecated: ["22.0.0", "20.13.0"] },
|
|
118
|
+
},
|
|
111
119
|
KeyObject: {
|
|
112
120
|
[READ]: { supported: ["11.6.0"] },
|
|
113
121
|
from: { [READ]: { supported: ["15.0.0"] } },
|
|
@@ -36,7 +36,12 @@ const events = {
|
|
|
36
36
|
supported: ["15.4.0"],
|
|
37
37
|
},
|
|
38
38
|
},
|
|
39
|
-
CustomEvent: {
|
|
39
|
+
CustomEvent: {
|
|
40
|
+
[READ]: {
|
|
41
|
+
experimental: ["18.7.0", "16.17.0"],
|
|
42
|
+
supported: ["22.1.0", "20.13.0"],
|
|
43
|
+
},
|
|
44
|
+
},
|
|
40
45
|
NodeEventTarget: {
|
|
41
46
|
[READ]: {
|
|
42
47
|
experimental: ["14.5.0"],
|
|
@@ -1,32 +1,34 @@
|
|
|
1
1
|
"use strict"
|
|
2
2
|
|
|
3
|
-
const { READ } = require("@eslint-community/eslint-utils")
|
|
3
|
+
const { READ, CALL, CONSTRUCT } = require("@eslint-community/eslint-utils")
|
|
4
4
|
|
|
5
5
|
/** @type {import('../types.js').SupportVersionTraceMap} */
|
|
6
6
|
const promises_api = {
|
|
7
|
-
|
|
7
|
+
FileHandle: { [READ]: { supported: ["10.0.0"] } },
|
|
8
8
|
access: { [READ]: { supported: ["10.0.0"] } },
|
|
9
9
|
appendFile: { [READ]: { supported: ["10.0.0"] } },
|
|
10
10
|
chmod: { [READ]: { supported: ["10.0.0"] } },
|
|
11
11
|
chown: { [READ]: { supported: ["10.0.0"] } },
|
|
12
|
+
constants: { [READ]: { supported: ["18.4.0", "16.17.0"] } },
|
|
12
13
|
copyFile: { [READ]: { supported: ["10.0.0"] } },
|
|
13
14
|
cp: { [READ]: { experimental: ["16.7.0"] } },
|
|
15
|
+
glob: { [READ]: { experimental: ["22.0.0"] } },
|
|
14
16
|
lchmod: { [READ]: { supported: ["10.0.0"], deprecated: ["10.0.0"] } },
|
|
15
17
|
lchown: { [READ]: { supported: ["10.0.0"] } },
|
|
16
|
-
lutimes: { [READ]: { supported: ["14.5.0", "12.19.0"] } },
|
|
17
18
|
link: { [READ]: { supported: ["10.0.0"] } },
|
|
18
19
|
lstat: { [READ]: { supported: ["10.0.0"] } },
|
|
20
|
+
lutimes: { [READ]: { supported: ["14.5.0", "12.19.0"] } },
|
|
19
21
|
mkdir: { [READ]: { supported: ["10.0.0"] } },
|
|
20
22
|
mkdtemp: { [READ]: { supported: ["10.0.0"] } },
|
|
21
23
|
open: { [READ]: { supported: ["10.0.0"] } },
|
|
22
24
|
opendir: { [READ]: { supported: ["12.12.0"] } },
|
|
23
|
-
readdir: { [READ]: { supported: ["10.0.0"] } },
|
|
24
25
|
readFile: { [READ]: { supported: ["10.0.0"] } },
|
|
26
|
+
readdir: { [READ]: { supported: ["10.0.0"] } },
|
|
25
27
|
readlink: { [READ]: { supported: ["10.0.0"] } },
|
|
26
28
|
realpath: { [READ]: { supported: ["10.0.0"] } },
|
|
27
29
|
rename: { [READ]: { supported: ["10.0.0"] } },
|
|
28
|
-
rmdir: { [READ]: { supported: ["10.0.0"] } },
|
|
29
30
|
rm: { [READ]: { supported: ["14.14.0"] } },
|
|
31
|
+
rmdir: { [READ]: { supported: ["10.0.0"] } },
|
|
30
32
|
stat: { [READ]: { supported: ["10.0.0"] } },
|
|
31
33
|
statfs: { [READ]: { supported: ["19.6.0", "18.15.0"] } },
|
|
32
34
|
symlink: { [READ]: { supported: ["10.0.0"] } },
|
|
@@ -35,7 +37,6 @@ const promises_api = {
|
|
|
35
37
|
utimes: { [READ]: { supported: ["10.0.0"] } },
|
|
36
38
|
watch: { [READ]: { supported: ["15.9.0", "14.18.0"] } },
|
|
37
39
|
writeFile: { [READ]: { supported: ["10.0.0"] } },
|
|
38
|
-
FileHandle: { [READ]: { supported: ["10.0.0"] } },
|
|
39
40
|
}
|
|
40
41
|
|
|
41
42
|
/** @type {import('../types.js').SupportVersionTraceMap} */
|
|
@@ -57,13 +58,15 @@ const callback_api = {
|
|
|
57
58
|
fsync: { [READ]: { supported: ["0.1.96"] } },
|
|
58
59
|
ftruncate: { [READ]: { supported: ["0.8.6"] } },
|
|
59
60
|
futimes: { [READ]: { supported: ["0.4.2"] } },
|
|
61
|
+
glob: { [READ]: { experimental: ["22.0.0"] } },
|
|
60
62
|
lchmod: { [READ]: { supported: ["0.1.8"], deprecated: ["0.4.7"] } },
|
|
61
63
|
lchown: { [READ]: { supported: ["0.1.8"] } },
|
|
62
|
-
lutimes: { [READ]: { supported: ["14.5.0", "12.19.0"] } },
|
|
63
64
|
link: { [READ]: { supported: ["0.1.31"] } },
|
|
64
65
|
lstat: { [READ]: { supported: ["0.1.30"] } },
|
|
66
|
+
lutimes: { [READ]: { supported: ["14.5.0", "12.19.0"] } },
|
|
65
67
|
mkdir: { [READ]: { supported: ["0.1.8"] } },
|
|
66
68
|
mkdtemp: { [READ]: { supported: ["5.10.0"] } },
|
|
69
|
+
native: { [READ]: { supported: ["9.2.0"] } },
|
|
67
70
|
open: { [READ]: { supported: ["0.0.2"] } },
|
|
68
71
|
openAsBlob: { [READ]: { experimental: ["19.8.0"] } },
|
|
69
72
|
opendir: { [READ]: { supported: ["12.12.0"] } },
|
|
@@ -76,10 +79,9 @@ const callback_api = {
|
|
|
76
79
|
[READ]: { supported: ["0.1.31"] },
|
|
77
80
|
native: { [READ]: { supported: ["9.2.0"] } },
|
|
78
81
|
},
|
|
79
|
-
native: { [READ]: { supported: ["9.2.0"] } },
|
|
80
82
|
rename: { [READ]: { supported: ["0.0.2"] } },
|
|
81
|
-
rmdir: { [READ]: { supported: ["0.0.2"] } },
|
|
82
83
|
rm: { [READ]: { supported: ["14.14.0"] } },
|
|
84
|
+
rmdir: { [READ]: { supported: ["0.0.2"] } },
|
|
83
85
|
stat: { [READ]: { supported: ["0.0.2"] } },
|
|
84
86
|
statfs: { [READ]: { supported: ["19.6.0", "18.15.0"] } },
|
|
85
87
|
symlink: { [READ]: { supported: ["0.1.31"] } },
|
|
@@ -111,13 +113,15 @@ const synchronous_api = {
|
|
|
111
113
|
fsyncSync: { [READ]: { supported: ["0.1.96"] } },
|
|
112
114
|
ftruncateSync: { [READ]: { supported: ["0.8.6"] } },
|
|
113
115
|
futimesSync: { [READ]: { supported: ["0.4.2"] } },
|
|
116
|
+
globSync: { [READ]: { experimental: ["22.0.0"] } },
|
|
114
117
|
lchmodSync: { [READ]: { supported: ["0.1.8"], deprecated: ["0.4.7"] } },
|
|
115
118
|
lchownSync: { [READ]: { supported: ["0.1.8"] } },
|
|
116
|
-
lutimesSync: { [READ]: { supported: ["14.5.0", "12.19.0"] } },
|
|
117
119
|
linkSync: { [READ]: { supported: ["0.1.31"] } },
|
|
118
120
|
lstatSync: { [READ]: { supported: ["0.1.30"] } },
|
|
121
|
+
lutimesSync: { [READ]: { supported: ["14.5.0", "12.19.0"] } },
|
|
119
122
|
mkdirSync: { [READ]: { supported: ["0.1.21"] } },
|
|
120
123
|
mkdtempSync: { [READ]: { supported: ["5.10.0"] } },
|
|
124
|
+
native: { [READ]: { supported: ["9.2.0"] } },
|
|
121
125
|
opendirSync: { [READ]: { supported: ["12.12.0"] } },
|
|
122
126
|
openSync: { [READ]: { supported: ["0.1.21"] } },
|
|
123
127
|
readdirSync: { [READ]: { supported: ["0.1.21"] } },
|
|
@@ -129,12 +133,11 @@ const synchronous_api = {
|
|
|
129
133
|
[READ]: { supported: ["0.1.31"] },
|
|
130
134
|
native: { [READ]: { supported: ["9.2.0"] } },
|
|
131
135
|
},
|
|
132
|
-
native: { [READ]: { supported: ["9.2.0"] } },
|
|
133
136
|
renameSync: { [READ]: { supported: ["0.1.21"] } },
|
|
134
137
|
rmdirSync: { [READ]: { supported: ["0.1.21"] } },
|
|
135
138
|
rmSync: { [READ]: { supported: ["14.14.0"] } },
|
|
136
|
-
statSync: { [READ]: { supported: ["0.1.21"] } },
|
|
137
139
|
statfsSync: { [READ]: { supported: ["19.6.0", "18.15.0"] } },
|
|
140
|
+
statSync: { [READ]: { supported: ["0.1.21"] } },
|
|
138
141
|
symlinkSync: { [READ]: { supported: ["0.1.31"] } },
|
|
139
142
|
truncateSync: { [READ]: { supported: ["0.8.6"] } },
|
|
140
143
|
unlinkSync: { [READ]: { supported: ["0.1.21"] } },
|
|
@@ -161,7 +164,11 @@ const fs = {
|
|
|
161
164
|
FSWatcher: { [READ]: { supported: ["0.5.8"] } },
|
|
162
165
|
StatWatcher: { [READ]: { supported: ["14.3.0", "12.20.0"] } },
|
|
163
166
|
ReadStream: { [READ]: { supported: ["0.1.93"] } },
|
|
164
|
-
Stats: {
|
|
167
|
+
Stats: {
|
|
168
|
+
[READ]: { supported: ["0.1.21"] },
|
|
169
|
+
[CALL]: { deprecated: ["22.0.0", "20.13.0"] },
|
|
170
|
+
[CONSTRUCT]: { deprecated: ["22.0.0", "20.13.0"] },
|
|
171
|
+
},
|
|
165
172
|
StatFs: { [READ]: { supported: ["19.6.0", "18.15.0"] } },
|
|
166
173
|
WriteStream: { [READ]: { supported: ["0.1.93"] } },
|
|
167
174
|
common_objects: { [READ]: { supported: ["0.1.8"] } },
|
|
@@ -5,6 +5,7 @@ const { READ } = require("@eslint-community/eslint-utils")
|
|
|
5
5
|
/** @type {import('../types.js').SupportVersionTraceMap} */
|
|
6
6
|
const process = {
|
|
7
7
|
allowedNodeEnvironmentFlags: { [READ]: { supported: ["10.10.0"] } },
|
|
8
|
+
availableMemory: { [READ]: { experimental: ["22.0.0", "20.13.0"] } },
|
|
8
9
|
arch: { [READ]: { supported: ["0.5.0"] } },
|
|
9
10
|
argv: { [READ]: { supported: ["0.1.27"] } },
|
|
10
11
|
argv0: { [READ]: { supported: ["6.4.0"] } },
|
|
@@ -20,6 +20,12 @@ const test = {
|
|
|
20
20
|
todo: { [READ]: { supported: ["20.2.0", "18.17.0"] } },
|
|
21
21
|
only: { [READ]: { supported: ["20.2.0", "18.17.0"] } },
|
|
22
22
|
},
|
|
23
|
+
suite: {
|
|
24
|
+
[READ]: { supported: ["22.0.0", "20.13.0"] },
|
|
25
|
+
skip: { [READ]: { supported: ["22.0.0", "20.13.0"] } },
|
|
26
|
+
todo: { [READ]: { supported: ["22.0.0", "20.13.0"] } },
|
|
27
|
+
only: { [READ]: { supported: ["22.0.0", "20.13.0"] } },
|
|
28
|
+
},
|
|
23
29
|
before: { [READ]: { supported: ["18.8.0", "16.18.0"] } },
|
|
24
30
|
after: { [READ]: { supported: ["18.8.0", "16.18.0"] } },
|
|
25
31
|
beforeEach: { [READ]: { supported: ["18.8.0", "16.18.0"] } },
|
|
@@ -34,6 +34,7 @@ const v8 = {
|
|
|
34
34
|
getHeapSnapshot: { [READ]: { supported: ["11.13.0"] } },
|
|
35
35
|
getHeapSpaceStatistics: { [READ]: { supported: ["6.0.0"] } },
|
|
36
36
|
getHeapStatistics: { [READ]: { supported: ["1.0.0"] } },
|
|
37
|
+
queryObjects: { [READ]: { experimental: ["22.0.0", "20.13.0"] } },
|
|
37
38
|
setFlagsFromString: { [READ]: { supported: ["1.0.0"] } },
|
|
38
39
|
stopCoverage: { [READ]: { supported: ["15.1.0", "14.18.0", "12.22.0"] } },
|
|
39
40
|
takeCoverage: { [READ]: { supported: ["15.1.0", "14.18.0", "12.22.0"] } },
|
|
@@ -15,51 +15,56 @@ const semverRangeSubset = require("semver/ranges/subset")
|
|
|
15
15
|
* Parses the options.
|
|
16
16
|
* @param {import('eslint').Rule.RuleContext} context The rule context.
|
|
17
17
|
* @returns {Readonly<{
|
|
18
|
-
* version: import('semver').Range
|
|
19
|
-
* ignores: Set<string
|
|
18
|
+
* version: import('semver').Range;
|
|
19
|
+
* ignores: Set<string>;
|
|
20
|
+
* allowExperimental: boolean;
|
|
20
21
|
* }>} Parsed value.
|
|
21
22
|
*/
|
|
22
23
|
function parseOptions(context) {
|
|
23
24
|
const raw = context.options[0] || {}
|
|
24
25
|
const version = getConfiguredNodeVersion(context)
|
|
25
26
|
const ignores = new Set(raw.ignores || [])
|
|
27
|
+
const allowExperimental = raw.allowExperimental ?? false
|
|
26
28
|
|
|
27
|
-
return Object.freeze({ version, ignores })
|
|
29
|
+
return Object.freeze({ version, ignores, allowExperimental })
|
|
28
30
|
}
|
|
29
31
|
|
|
30
32
|
/**
|
|
31
33
|
* Check if it has been supported.
|
|
32
|
-
* @param {
|
|
33
|
-
* @param {import('semver').Range}
|
|
34
|
+
* @param {string[] | undefined} featureRange The target features supported range
|
|
35
|
+
* @param {import('semver').Range} requestedRange The configured version range.
|
|
36
|
+
* @returns {boolean}
|
|
34
37
|
*/
|
|
35
|
-
function
|
|
36
|
-
if (
|
|
38
|
+
function isInRange(featureRange, requestedRange) {
|
|
39
|
+
if (featureRange == null || featureRange.length === 0) {
|
|
37
40
|
return false
|
|
38
41
|
}
|
|
39
42
|
|
|
40
|
-
const [latest] = rsort(
|
|
43
|
+
const [latest] = rsort(featureRange)
|
|
41
44
|
const range = getSemverRange(
|
|
42
|
-
[...
|
|
45
|
+
[...featureRange.map(version => `^${version}`), `>= ${latest}`].join(
|
|
46
|
+
"||"
|
|
47
|
+
)
|
|
43
48
|
)
|
|
44
49
|
|
|
45
50
|
if (range == null) {
|
|
46
51
|
return false
|
|
47
52
|
}
|
|
48
53
|
|
|
49
|
-
return semverRangeSubset(
|
|
54
|
+
return semverRangeSubset(requestedRange, range)
|
|
50
55
|
}
|
|
51
56
|
|
|
52
57
|
/**
|
|
53
58
|
* Get the formatted text of a given supported version.
|
|
54
|
-
* @param {
|
|
59
|
+
* @param {string[] | undefined} versions The support info.
|
|
55
60
|
* @returns {string | undefined}
|
|
56
61
|
*/
|
|
57
|
-
function
|
|
58
|
-
if (
|
|
62
|
+
function versionsToString(versions) {
|
|
63
|
+
if (versions == null) {
|
|
59
64
|
return
|
|
60
65
|
}
|
|
61
66
|
|
|
62
|
-
const [latest, ...backported] = rsort(
|
|
67
|
+
const [latest, ...backported] = rsort(versions)
|
|
63
68
|
|
|
64
69
|
if (backported.length === 0) {
|
|
65
70
|
return latest
|
|
@@ -92,20 +97,54 @@ module.exports.checkUnsupportedBuiltins = function checkUnsupportedBuiltins(
|
|
|
92
97
|
|
|
93
98
|
for (const { node, path, info } of references) {
|
|
94
99
|
const name = unprefixNodeColon(path.join("."))
|
|
95
|
-
const supported = isSupported(info, options.version)
|
|
96
100
|
|
|
97
|
-
if (
|
|
101
|
+
if (options.ignores.has(name)) {
|
|
98
102
|
continue
|
|
99
103
|
}
|
|
100
|
-
|
|
104
|
+
|
|
105
|
+
if (options.allowExperimental) {
|
|
106
|
+
if (isInRange(info.experimental, options.version)) {
|
|
107
|
+
continue
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const experimentalVersion = versionsToString(info.experimental)
|
|
111
|
+
if (experimentalVersion) {
|
|
112
|
+
context.report({
|
|
113
|
+
node,
|
|
114
|
+
messageId: "not-experimental-till",
|
|
115
|
+
data: {
|
|
116
|
+
name: name,
|
|
117
|
+
experimental: experimentalVersion,
|
|
118
|
+
version: options.version.raw,
|
|
119
|
+
},
|
|
120
|
+
})
|
|
121
|
+
continue
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
if (isInRange(info.supported, options.version)) {
|
|
126
|
+
continue
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const supportedVersion = versionsToString(info.supported)
|
|
130
|
+
if (supportedVersion) {
|
|
131
|
+
context.report({
|
|
132
|
+
node,
|
|
133
|
+
messageId: "not-supported-till",
|
|
134
|
+
data: {
|
|
135
|
+
name: name,
|
|
136
|
+
supported: supportedVersion,
|
|
137
|
+
version: options.version.raw,
|
|
138
|
+
},
|
|
139
|
+
})
|
|
140
|
+
continue
|
|
141
|
+
}
|
|
142
|
+
|
|
101
143
|
context.report({
|
|
102
144
|
node,
|
|
103
|
-
messageId:
|
|
104
|
-
? "not-supported-till"
|
|
105
|
-
: "not-supported-yet",
|
|
145
|
+
messageId: "not-supported-yet",
|
|
106
146
|
data: {
|
|
107
|
-
name:
|
|
108
|
-
supported: /** @type string */ (supportedVersion),
|
|
147
|
+
name: name,
|
|
109
148
|
version: options.version.raw,
|
|
110
149
|
},
|
|
111
150
|
})
|
|
@@ -113,6 +152,11 @@ module.exports.checkUnsupportedBuiltins = function checkUnsupportedBuiltins(
|
|
|
113
152
|
}
|
|
114
153
|
|
|
115
154
|
exports.messages = {
|
|
155
|
+
"not-experimental-till": [
|
|
156
|
+
"The '{{name}}' is not an experimental feature",
|
|
157
|
+
"until Node.js {{experimental}}.",
|
|
158
|
+
"The configured version range is '{{version}}'.",
|
|
159
|
+
].join(" "),
|
|
116
160
|
"not-supported-till": [
|
|
117
161
|
"The '{{name}}' is still an experimental feature",
|
|
118
162
|
"and is not supported until Node.js {{supported}}.",
|