Skip to content

Commit 972f828

Browse files
committedNov 24, 2019
✨ no-unsupported-features/node-builtins recognize backporting
Fixes #192 Closes #194
1 parent 276a9ad commit 972f828

File tree

3 files changed

+170
-65
lines changed

3 files changed

+170
-65
lines changed
 

‎lib/rules/no-unsupported-features/node-builtins.js

+66-20
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ const trackMap = {
2323
modules: {
2424
assert: {
2525
strict: {
26-
[READ]: { supported: "9.9.0" },
26+
[READ]: { supported: "9.9.0", backported: ["8.13.0"] },
2727
doesNotReject: { [READ]: { supported: "10.0.0" } },
2828
rejects: { [READ]: { supported: "10.0.0" } },
2929
},
@@ -51,9 +51,11 @@ const trackMap = {
5151
ChildProcess: { [READ]: { supported: "2.2.0" } },
5252
},
5353
console: {
54-
clear: { [READ]: { supported: "8.3.0" } },
55-
count: { [READ]: { supported: "8.3.0" } },
56-
countReset: { [READ]: { supported: "8.3.0" } },
54+
clear: { [READ]: { supported: "8.3.0", backported: ["6.13.0"] } },
55+
count: { [READ]: { supported: "8.3.0", backported: ["6.13.0"] } },
56+
countReset: {
57+
[READ]: { supported: "8.3.0", backported: ["6.13.0"] },
58+
},
5759
debug: { [READ]: { supported: "8.0.0" } },
5860
dirxml: { [READ]: { supported: "8.0.0" } },
5961
group: { [READ]: { supported: "8.5.0" } },
@@ -74,6 +76,7 @@ const trackMap = {
7476
exportPublicKey: { [READ]: { supported: "9.0.0" } },
7577
verifySpkac: { [READ]: { supported: "9.0.0" } },
7678
},
79+
ECDH: { [READ]: { supported: "8.8.0", backported: ["6.13.0"] } },
7780
KeyObject: { [READ]: { supported: "11.6.0" } },
7881
createPrivateKey: { [READ]: { supported: "11.6.0" } },
7982
createPublicKey: { [READ]: { supported: "11.6.0" } },
@@ -86,8 +89,12 @@ const trackMap = {
8689
getFips: { [READ]: { supported: "10.0.0" } },
8790
privateEncrypt: { [READ]: { supported: "1.1.0" } },
8891
publicDecrypt: { [READ]: { supported: "1.1.0" } },
89-
randomFillSync: { [READ]: { supported: "7.10.0" } },
90-
randomFill: { [READ]: { supported: "7.10.0" } },
92+
randomFillSync: {
93+
[READ]: { supported: "7.10.0", backported: ["6.13.0"] },
94+
},
95+
randomFill: {
96+
[READ]: { supported: "7.10.0", backported: ["6.13.0"] },
97+
},
9198
scrypt: { [READ]: { supported: "10.5.0" } },
9299
scryptSync: { [READ]: { supported: "10.5.0" } },
93100
setFips: { [READ]: { supported: "10.0.0" } },
@@ -99,14 +106,20 @@ const trackMap = {
99106
Resolver: { [READ]: { supported: "8.3.0" } },
100107
resolvePtr: { [READ]: { supported: "6.0.0" } },
101108
promises: {
102-
[READ]: { supported: "11.14.0", experimental: "10.6.0" },
109+
[READ]: {
110+
supported: "11.14.0",
111+
backported: ["10.17.0"],
112+
experimental: "10.6.0",
113+
},
103114
},
104115
},
105116
events: {
106117
EventEmitter: {
107-
once: { [READ]: { supported: "11.13.0" } },
118+
once: {
119+
[READ]: { supported: "11.13.0", backported: ["10.16.0"] },
120+
},
108121
},
109-
once: { [READ]: { supported: "11.13.0" } },
122+
once: { [READ]: { supported: "11.13.0", backported: ["10.16.0"] } },
110123
},
111124
fs: {
112125
Dirent: { [READ]: { supported: "10.10.0" } },
@@ -121,25 +134,43 @@ const trackMap = {
121134
native: { [READ]: { supported: "9.2.0" } },
122135
},
123136
promises: {
124-
[READ]: { supported: "11.14.0", experimental: "10.1.0" },
137+
[READ]: {
138+
supported: "11.14.0",
139+
backported: ["10.17.0"],
140+
experimental: "10.1.0",
141+
},
125142
},
126143
writev: { [READ]: { supported: "12.9.0" } },
127144
writevSync: { [READ]: { supported: "12.9.0" } },
128145
},
129146
http2: {
130-
[READ]: { supported: "10.10.0", experimental: "8.4.0" },
147+
[READ]: {
148+
supported: "10.10.0",
149+
backported: ["8.13.0"],
150+
experimental: "8.4.0",
151+
},
131152
},
132153
inspector: {
133154
[READ]: { supported: null, experimental: "8.0.0" },
134155
},
135156
module: {
136157
Module: {
137-
builtinModules: { [READ]: { supported: "9.3.0" } },
158+
builtinModules: {
159+
[READ]: {
160+
supported: "9.3.0",
161+
backported: ["6.13.0", "8.10.0"],
162+
},
163+
},
138164
createRequireFromPath: { [READ]: { supported: "10.12.0" } },
139165
createRequire: { [READ]: { supported: "12.2.0" } },
140166
syncBuiltinESMExports: { [READ]: { supported: "12.12.0" } },
141167
},
142-
builtinModules: { [READ]: { supported: "9.3.0" } },
168+
builtinModules: {
169+
[READ]: {
170+
supported: "9.3.0",
171+
backported: ["6.13.0", "8.10.0"],
172+
},
173+
},
143174
createRequireFromPath: { [READ]: { supported: "10.12.0" } },
144175
createRequire: { [READ]: { supported: "12.2.0" } },
145176
syncBuiltinESMExports: { [READ]: { supported: "12.12.0" } },
@@ -175,7 +206,12 @@ const trackMap = {
175206
hrtime: {
176207
bigint: { [READ]: { supported: "10.7.0" } },
177208
},
178-
ppid: { [READ]: { supported: "9.2.0" } },
209+
ppid: {
210+
[READ]: {
211+
supported: "9.2.0",
212+
backported: ["6.13.0", "8.10.0"],
213+
},
214+
},
179215
release: { [READ]: { supported: "3.0.0" } },
180216
report: { [READ]: { supported: null, experimental: "11.8.0" } },
181217
resourceUsage: { [READ]: { supported: "12.6.0" } },
@@ -195,7 +231,9 @@ const trackMap = {
195231
},
196232
stream: {
197233
Readable: {
198-
from: { [READ]: { supported: "12.3.0" } },
234+
from: {
235+
[READ]: { supported: "12.3.0", backported: ["10.17.0"] },
236+
},
199237
},
200238
finished: { [READ]: { supported: "10.0.0" } },
201239
pipeline: { [READ]: { supported: "10.0.0" } },
@@ -204,24 +242,32 @@ const trackMap = {
204242
[READ]: { supported: "10.0.0" },
205243
},
206244
url: {
207-
URL: { [READ]: { supported: "7.0.0" } },
208-
URLSearchParams: { [READ]: { supported: "7.5.0" } },
245+
URL: { [READ]: { supported: "7.0.0", backported: ["6.13.0"] } },
246+
URLSearchParams: {
247+
[READ]: { supported: "7.5.0", backported: ["6.13.0"] },
248+
},
209249
domainToASCII: { [READ]: { supported: "7.4.0" } },
210250
domainToUnicode: { [READ]: { supported: "7.4.0" } },
211251
},
212252
util: {
213253
callbackify: { [READ]: { supported: "8.2.0" } },
214254
formatWithOptions: { [READ]: { supported: "10.0.0" } },
215-
getSystemErrorName: { [READ]: { supported: "9.7.0" } },
255+
getSystemErrorName: {
256+
[READ]: { supported: "9.7.0", backported: ["8.12.0"] },
257+
},
216258
inspect: {
217259
custom: { [READ]: { supported: "6.6.0" } },
218260
defaultOptions: { [READ]: { supported: "6.4.0" } },
219261
replDefaults: { [READ]: { supported: "11.12.0" } },
220262
},
221263
isDeepStrictEqual: { [READ]: { supported: "9.0.0" } },
222264
promisify: { [READ]: { supported: "8.0.0" } },
223-
TextDecoder: { [READ]: { supported: "8.3.0" } },
224-
TextEncoder: { [READ]: { supported: "8.3.0" } },
265+
TextDecoder: {
266+
[READ]: { supported: "8.9.0", experimental: "8.3.0" },
267+
},
268+
TextEncoder: {
269+
[READ]: { supported: "8.9.0", experimental: "8.3.0" },
270+
},
225271
types: {
226272
[READ]: { supported: "10.0.0" },
227273
isBoxedPrimitive: { [READ]: { supported: "10.11.0" } },

‎lib/util/check-unsupported-builtins.js

+54-5
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,18 @@
44
*/
55
"use strict"
66

7-
const { Range } = require("semver") //eslint-disable-line no-unused-vars
7+
const { Range, lt, major } = require("semver") //eslint-disable-line no-unused-vars
88
const { ReferenceTracker } = require("eslint-utils")
99
const getConfiguredNodeVersion = require("./get-configured-node-version")
1010
const getSemverRange = require("./get-semver-range")
1111

12+
/**
13+
* @typedef {Object} SupportInfo
14+
* @property {string | null} supported The stably supported version. If `null` is present, it hasn't been supported yet.
15+
* @property {string[]} [backported] The backported versions.
16+
* @property {string} [experimental] The added version as experimental.
17+
*/
18+
1219
/**
1320
* Parses the options.
1421
* @param {RuleContext} context The rule context.
@@ -23,6 +30,50 @@ function parseOptions(context) {
2330
return Object.freeze({ version, ignores })
2431
}
2532

33+
/**
34+
* Check if it has been supported.
35+
* @param {SupportInfo} info The support info.
36+
* @param {Range} configured The configured version range.
37+
*/
38+
function isSupported({ backported, supported }, configured) {
39+
if (
40+
backported &&
41+
backported.length >= 2 &&
42+
!backported.every((v, i) => i === 0 || lt(backported[i - 1], v))
43+
) {
44+
throw new Error("Invalid BackportConfiguration")
45+
}
46+
47+
if (supported == null) {
48+
return false
49+
}
50+
if (backported == null || backported.length === 0) {
51+
return !configured.intersects(getSemverRange(`<${supported}`))
52+
}
53+
54+
return !configured.intersects(
55+
getSemverRange(
56+
[...backported, supported]
57+
.map((v, i) => (i === 0 ? `<${v}` : `>=${major(v)}.0.0 <${v}`))
58+
.join(" || ")
59+
)
60+
)
61+
}
62+
63+
/**
64+
* Get the formatted text of a given supported version.
65+
* @param {SupportInfo} info The support info.
66+
*/
67+
function supportedVersionToString({ backported, supported }) {
68+
if (supported == null) {
69+
return "(none yet)"
70+
}
71+
if (backported == null || backported.length === 0) {
72+
return supported
73+
}
74+
return `${supported} (backported: ^${backported.join(", ^")})`
75+
}
76+
2677
/**
2778
* Verify the code to report unsupported APIs.
2879
* @param {RuleContext} context The rule context.
@@ -40,17 +91,15 @@ module.exports = function checkUnsupportedBuiltins(context, trackMap) {
4091

4192
for (const { node, path, info } of references) {
4293
const name = path.join(".")
43-
const supported =
44-
Boolean(info.supported) &&
45-
!options.version.intersects(getSemverRange(`<${info.supported}`))
94+
const supported = isSupported(info, options.version)
4695

4796
if (!supported && !options.ignores.has(name)) {
4897
context.report({
4998
node,
5099
messageId: "unsupported",
51100
data: {
52101
name,
53-
supported: info.supported || "???",
102+
supported: supportedVersionToString(info),
54103
version: options.version.raw,
55104
},
56105
})

‎tests/lib/rules/no-unsupported-features/node-builtins.js

+50-40
Original file line numberDiff line numberDiff line change
@@ -366,7 +366,7 @@ new RuleTester({
366366
messageId: "unsupported",
367367
data: {
368368
name: "assert.strict",
369-
supported: "9.9.0",
369+
supported: "9.9.0 (backported: ^8.13.0)",
370370
version: "9.8.9",
371371
},
372372
},
@@ -381,7 +381,7 @@ new RuleTester({
381381
messageId: "unsupported",
382382
data: {
383383
name: "assert.strict",
384-
supported: "9.9.0",
384+
supported: "9.9.0 (backported: ^8.13.0)",
385385
version: "9.8.9",
386386
},
387387
},
@@ -1353,7 +1353,7 @@ new RuleTester({
13531353
messageId: "unsupported",
13541354
data: {
13551355
name: "console.clear",
1356-
supported: "8.3.0",
1356+
supported: "8.3.0 (backported: ^6.13.0)",
13571357
version: "8.2.9",
13581358
},
13591359
},
@@ -1367,7 +1367,7 @@ new RuleTester({
13671367
messageId: "unsupported",
13681368
data: {
13691369
name: "console.clear",
1370-
supported: "8.3.0",
1370+
supported: "8.3.0 (backported: ^6.13.0)",
13711371
version: "8.2.9",
13721372
},
13731373
},
@@ -1381,7 +1381,7 @@ new RuleTester({
13811381
messageId: "unsupported",
13821382
data: {
13831383
name: "console.clear",
1384-
supported: "8.3.0",
1384+
supported: "8.3.0 (backported: ^6.13.0)",
13851385
version: "8.2.9",
13861386
},
13871387
},
@@ -1395,7 +1395,7 @@ new RuleTester({
13951395
messageId: "unsupported",
13961396
data: {
13971397
name: "console.clear",
1398-
supported: "8.3.0",
1398+
supported: "8.3.0 (backported: ^6.13.0)",
13991399
version: "8.2.9",
14001400
},
14011401
},
@@ -1409,7 +1409,7 @@ new RuleTester({
14091409
messageId: "unsupported",
14101410
data: {
14111411
name: "console.clear",
1412-
supported: "8.3.0",
1412+
supported: "8.3.0 (backported: ^6.13.0)",
14131413
version: "8.2.9",
14141414
},
14151415
},
@@ -1423,7 +1423,7 @@ new RuleTester({
14231423
messageId: "unsupported",
14241424
data: {
14251425
name: "console.count",
1426-
supported: "8.3.0",
1426+
supported: "8.3.0 (backported: ^6.13.0)",
14271427
version: "8.2.9",
14281428
},
14291429
},
@@ -1437,7 +1437,7 @@ new RuleTester({
14371437
messageId: "unsupported",
14381438
data: {
14391439
name: "console.countReset",
1440-
supported: "8.3.0",
1440+
supported: "8.3.0 (backported: ^6.13.0)",
14411441
version: "8.2.9",
14421442
},
14431443
},
@@ -2055,7 +2055,7 @@ new RuleTester({
20552055
messageId: "unsupported",
20562056
data: {
20572057
name: "crypto.randomFillSync",
2058-
supported: "7.10.0",
2058+
supported: "7.10.0 (backported: ^6.13.0)",
20592059
version: "7.9.9",
20602060
},
20612061
},
@@ -2069,7 +2069,7 @@ new RuleTester({
20692069
messageId: "unsupported",
20702070
data: {
20712071
name: "crypto.randomFill",
2072-
supported: "7.10.0",
2072+
supported: "7.10.0 (backported: ^6.13.0)",
20732073
version: "7.9.9",
20742074
},
20752075
},
@@ -2295,7 +2295,7 @@ new RuleTester({
22952295
messageId: "unsupported",
22962296
data: {
22972297
name: "dns.promises",
2298-
supported: "11.14.0",
2298+
supported: "11.14.0 (backported: ^10.17.0)",
22992299
version: "11.13.9",
23002300
},
23012301
},
@@ -2420,7 +2420,7 @@ new RuleTester({
24202420
messageId: "unsupported",
24212421
data: {
24222422
name: "fs.promises",
2423-
supported: "11.14.0",
2423+
supported: "11.14.0 (backported: ^10.17.0)",
24242424
version: "11.13.9",
24252425
},
24262426
},
@@ -2434,7 +2434,7 @@ new RuleTester({
24342434
messageId: "unsupported",
24352435
data: {
24362436
name: "fs.promises",
2437-
supported: "11.14.0",
2437+
supported: "11.14.0 (backported: ^10.17.0)",
24382438
version: "11.13.9",
24392439
},
24402440
},
@@ -2448,7 +2448,7 @@ new RuleTester({
24482448
messageId: "unsupported",
24492449
data: {
24502450
name: "fs.promises",
2451-
supported: "11.14.0",
2451+
supported: "11.14.0 (backported: ^10.17.0)",
24522452
version: "11.13.9",
24532453
},
24542454
},
@@ -2462,7 +2462,7 @@ new RuleTester({
24622462
messageId: "unsupported",
24632463
data: {
24642464
name: "fs.promises",
2465-
supported: "11.14.0",
2465+
supported: "11.14.0 (backported: ^10.17.0)",
24662466
version: "11.13.9",
24672467
},
24682468
},
@@ -2476,7 +2476,7 @@ new RuleTester({
24762476
messageId: "unsupported",
24772477
data: {
24782478
name: "fs.promises",
2479-
supported: "11.14.0",
2479+
supported: "11.14.0 (backported: ^10.17.0)",
24802480
version: "11.13.9",
24812481
},
24822482
},
@@ -2600,7 +2600,7 @@ new RuleTester({
26002600
messageId: "unsupported",
26012601
data: {
26022602
name: "http2",
2603-
supported: "10.10.0",
2603+
supported: "10.10.0 (backported: ^8.13.0)",
26042604
version: "8.3.9",
26052605
},
26062606
},
@@ -2614,7 +2614,7 @@ new RuleTester({
26142614
messageId: "unsupported",
26152615
data: {
26162616
name: "http2",
2617-
supported: "10.10.0",
2617+
supported: "10.10.0 (backported: ^8.13.0)",
26182618
version: "8.3.9",
26192619
},
26202620
},
@@ -2628,7 +2628,7 @@ new RuleTester({
26282628
messageId: "unsupported",
26292629
data: {
26302630
name: "http2",
2631-
supported: "10.10.0",
2631+
supported: "10.10.0 (backported: ^8.13.0)",
26322632
version: "8.3.9",
26332633
},
26342634
},
@@ -2660,7 +2660,7 @@ new RuleTester({
26602660
messageId: "unsupported",
26612661
data: {
26622662
name: "inspector",
2663-
supported: "???",
2663+
supported: "(none yet)",
26642664
version: "7.9.9",
26652665
},
26662666
},
@@ -2674,7 +2674,7 @@ new RuleTester({
26742674
messageId: "unsupported",
26752675
data: {
26762676
name: "inspector",
2677-
supported: "???",
2677+
supported: "(none yet)",
26782678
version: "7.9.9",
26792679
},
26802680
},
@@ -2688,7 +2688,7 @@ new RuleTester({
26882688
messageId: "unsupported",
26892689
data: {
26902690
name: "inspector",
2691-
supported: "???",
2691+
supported: "(none yet)",
26922692
version: "7.9.9",
26932693
},
26942694
},
@@ -2752,7 +2752,8 @@ new RuleTester({
27522752
messageId: "unsupported",
27532753
data: {
27542754
name: "module.builtinModules",
2755-
supported: "9.3.0",
2755+
supported:
2756+
"9.3.0 (backported: ^6.13.0, ^8.10.0)",
27562757
version: "9.2.9",
27572758
},
27582759
},
@@ -3478,7 +3479,8 @@ new RuleTester({
34783479
messageId: "unsupported",
34793480
data: {
34803481
name: "process.ppid",
3481-
supported: "9.2.0",
3482+
supported:
3483+
"9.2.0 (backported: ^6.13.0, ^8.10.0)",
34823484
version: "9.1.9",
34833485
},
34843486
},
@@ -3785,6 +3787,10 @@ new RuleTester({
37853787
code: "require('url').URL",
37863788
options: [{ version: "7.0.0" }],
37873789
},
3790+
{
3791+
code: "require('url').URL",
3792+
options: [{ version: "6.13.0" }],
3793+
},
37883794
{
37893795
code: "var cp = require('url'); cp.URL",
37903796
options: [{ version: "7.0.0" }],
@@ -3805,6 +3811,10 @@ new RuleTester({
38053811
code: "require('url').URLSearchParams",
38063812
options: [{ version: "7.5.0" }],
38073813
},
3814+
{
3815+
code: "require('url').URLSearchParams",
3816+
options: [{ version: "6.13.0" }],
3817+
},
38083818
{
38093819
code: "require('url').domainToASCII",
38103820
options: [{ version: "7.4.0" }],
@@ -3901,7 +3911,7 @@ new RuleTester({
39013911
messageId: "unsupported",
39023912
data: {
39033913
name: "url.URL",
3904-
supported: "7.0.0",
3914+
supported: "7.0.0 (backported: ^6.13.0)",
39053915
version: "6.9.9",
39063916
},
39073917
},
@@ -3915,7 +3925,7 @@ new RuleTester({
39153925
messageId: "unsupported",
39163926
data: {
39173927
name: "url.URL",
3918-
supported: "7.0.0",
3928+
supported: "7.0.0 (backported: ^6.13.0)",
39193929
version: "6.9.9",
39203930
},
39213931
},
@@ -3929,7 +3939,7 @@ new RuleTester({
39293939
messageId: "unsupported",
39303940
data: {
39313941
name: "url.URL",
3932-
supported: "7.0.0",
3942+
supported: "7.0.0 (backported: ^6.13.0)",
39333943
version: "6.9.9",
39343944
},
39353945
},
@@ -3943,7 +3953,7 @@ new RuleTester({
39433953
messageId: "unsupported",
39443954
data: {
39453955
name: "url.URL",
3946-
supported: "7.0.0",
3956+
supported: "7.0.0 (backported: ^6.13.0)",
39473957
version: "6.9.9",
39483958
},
39493959
},
@@ -3957,7 +3967,7 @@ new RuleTester({
39573967
messageId: "unsupported",
39583968
data: {
39593969
name: "url.URL",
3960-
supported: "7.0.0",
3970+
supported: "7.0.0 (backported: ^6.13.0)",
39613971
version: "6.9.9",
39623972
},
39633973
},
@@ -3971,7 +3981,7 @@ new RuleTester({
39713981
messageId: "unsupported",
39723982
data: {
39733983
name: "url.URLSearchParams",
3974-
supported: "7.5.0",
3984+
supported: "7.5.0 (backported: ^6.13.0)",
39753985
version: "7.4.9",
39763986
},
39773987
},
@@ -4059,11 +4069,11 @@ new RuleTester({
40594069
},
40604070
{
40614071
code: "require('util').TextDecoder",
4062-
options: [{ version: "8.3.0" }],
4072+
options: [{ version: "8.9.0" }],
40634073
},
40644074
{
40654075
code: "require('util').TextEncoder",
4066-
options: [{ version: "8.3.0" }],
4076+
options: [{ version: "8.9.0" }],
40674077
},
40684078
{
40694079
code: "require('util').types",
@@ -4259,7 +4269,7 @@ new RuleTester({
42594269
messageId: "unsupported",
42604270
data: {
42614271
name: "util.getSystemErrorName",
4262-
supported: "9.7.0",
4272+
supported: "9.7.0 (backported: ^8.12.0)",
42634273
version: "9.6.9",
42644274
},
42654275
},
@@ -4323,28 +4333,28 @@ new RuleTester({
43234333
},
43244334
{
43254335
code: "require('util').TextDecoder",
4326-
options: [{ version: "8.2.9" }],
4336+
options: [{ version: "8.8.9" }],
43274337
errors: [
43284338
{
43294339
messageId: "unsupported",
43304340
data: {
43314341
name: "util.TextDecoder",
4332-
supported: "8.3.0",
4333-
version: "8.2.9",
4342+
supported: "8.9.0",
4343+
version: "8.8.9",
43344344
},
43354345
},
43364346
],
43374347
},
43384348
{
43394349
code: "require('util').TextEncoder",
4340-
options: [{ version: "8.2.9" }],
4350+
options: [{ version: "8.8.9" }],
43414351
errors: [
43424352
{
43434353
messageId: "unsupported",
43444354
data: {
43454355
name: "util.TextEncoder",
4346-
supported: "8.3.0",
4347-
version: "8.2.9",
4356+
supported: "8.9.0",
4357+
version: "8.8.9",
43484358
},
43494359
},
43504360
],

0 commit comments

Comments
 (0)
Please sign in to comment.