Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 1f27214

Browse filesBrowse files
Lekodanielleadams
authored andcommitted
tools: add new ESLint rule: prefer-primordials
I added a new custom ESLint rule to fix these problems. We have a lot of replaceable codes with primordials. Accessing built-in objects is restricted by existing rule (no-restricted-globals), but accessing property in the built-in objects is not restricted right now. We manually review codes that can be replaced by primordials, but there's a lot of code that actually needs to be fixed. We have often made pull requests to replace the primordials with. Restrict accessing global built-in objects such as `Promise`. Restrict calling static methods such as `Array.from` or `Symbol.for`. Don't restrict prototype methods to prevent false-positive. PR-URL: #35448 Reviewed-By: Michaël Zasso <targos@protonmail.com> Reviewed-By: Rich Trott <rtrott@gmail.com> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com> Reviewed-By: Daijiro Wachi <daijiro.wachi@gmail.com> Reviewed-By: Ben Coe <bencoe@gmail.com>
1 parent 6011bfd commit 1f27214
Copy full SHA for 1f27214

File tree

Expand file treeCollapse file tree

17 files changed

+477
-128
lines changed
Open diff view settings
Filter options
Expand file treeCollapse file tree

17 files changed

+477
-128
lines changed
Open diff view settings
Collapse file

‎lib/.eslintrc.yaml‎

Copy file name to clipboardExpand all lines: lib/.eslintrc.yaml
+39-64Lines changed: 39 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -7,105 +7,80 @@ rules:
77
no-mixed-operators:
88
- error
99
- groups: [[ "&&", "||" ]]
10-
no-restricted-globals:
10+
no-restricted-syntax:
11+
# Config copied from .eslintrc.js
12+
- error
13+
- selector: "CallExpression[callee.object.name='assert']:not([callee.property.name='ok']):not([callee.property.name='fail']):not([callee.property.name='ifError'])"
14+
message: "Please only use simple assertions in ./lib"
15+
- selector: "CallExpression[callee.name='setTimeout'][arguments.length<2]"
16+
message: "setTimeout() must be invoked with at least two arguments."
17+
- selector: "CallExpression[callee.name='setInterval'][arguments.length<2]"
18+
message: "setInterval() must be invoked with at least 2 arguments."
19+
- selector: "ThrowStatement > CallExpression[callee.name=/Error$/]"
20+
message: "Use new keyword when throwing an Error."
21+
# Config specific to lib
22+
- selector: "NewExpression[callee.name=/Error$/]:not([callee.name=/^(AssertionError|NghttpError)$/])"
23+
message: "Use an error exported by the internal/errors module."
24+
- selector: "CallExpression[callee.object.name='Error'][callee.property.name='captureStackTrace']"
25+
message: "Please use `require('internal/errors').hideStackFrames()` instead."
26+
- selector: "AssignmentExpression:matches([left.name='prepareStackTrace'], [left.property.name='prepareStackTrace'])"
27+
message: "Use 'overrideStackTrace' from 'lib/internal/errors.js' instead of 'Error.prepareStackTrace'."
28+
# Custom rules in tools/eslint-rules
29+
node-core/lowercase-name-for-primitive: error
30+
node-core/non-ascii-character: error
31+
node-core/prefer-primordials:
1132
- error
1233
- name: Array
13-
message: "Use `const { Array } = primordials;` instead of the global."
1434
- name: ArrayBuffer
15-
message: "Use `const { ArrayBuffer } = primordials;` instead of the global."
1635
- name: BigInt
17-
message: "Use `const { BigInt } = primordials;` instead of the global."
1836
- name: BigInt64Array
19-
message: "Use `const { BigInt64Array } = primordials;` instead of the global."
2037
- name: BigUint64Array
21-
message: "Use `const { BigUint64Array } = primordials;` instead of the global."
2238
- name: Boolean
23-
message: "Use `const { Boolean } = primordials;` instead of the global."
39+
- name: DataView
40+
- name: Date
2441
- name: Error
25-
message: "Use `const { Error } = primordials;` instead of the global."
42+
ignore:
43+
- stackTraceLimit
44+
- captureStackTrace
45+
- prepareStackTrace
46+
- isPrototypeOf
2647
- name: EvalError
27-
message: "Use `const { EvalError } = primordials;` instead of the global."
2848
- name: Float32Array
29-
message: "Use `const { Float32Array } = primordials;` instead of the global."
3049
- name: Float64Array
31-
message: "Use `const { Float64Array } = primordials;` instead of the global."
50+
- name: Function
3251
- name: Int16Array
33-
message: "Use `const { Int16Array } = primordials;` instead of the global."
3452
- name: Int32Array
35-
message: "Use `const { Int32Array } = primordials;` instead of the global."
3653
- name: Int8Array
37-
message: "Use `const { Int8Array } = primordials;` instead of the global."
54+
- name: isFinite
55+
into: Number
56+
- name: isNaN
57+
into: Number
3858
- name: JSON
39-
message: "Use `const { JSON } = primordials;` instead of the global."
4059
- name: Map
41-
message: "Use `const { Map } = primordials;` instead of the global."
4260
- name: Math
43-
message: "Use `const { Math } = primordials;` instead of the global."
4461
- name: Number
45-
message: "Use `const { Number } = primordials;` instead of the global."
4662
- name: Object
47-
message: "Use `const { Object } = primordials;` instead of the global."
63+
- name: parseFloat
64+
into: Number
65+
- name: parseInt
66+
into: Number
4867
- name: Promise
49-
message: "Use `const { Promise } = primordials;` instead of the global."
5068
- name: RangeError
51-
message: "Use `const { RangeError } = primordials;` instead of the global."
5269
- name: ReferenceError
53-
message: "Use `const { ReferenceError } = primordials;` instead of the global."
5470
- name: Reflect
55-
message: "Use `const { Reflect } = primordials;` instead of the global."
5671
- name: RegExp
57-
message: "Use `const { RegExp } = primordials;` instead of the global."
5872
- name: Set
59-
message: "Use `const { Set } = primordials;` instead of the global."
6073
- name: String
61-
message: "Use `const { String } = primordials;` instead of the global."
6274
- name: Symbol
63-
message: "Use `const { Symbol } = primordials;` instead of the global."
6475
- name: SyntaxError
65-
message: "Use `const { SyntaxError } = primordials;` instead of the global."
6676
- name: TypeError
67-
message: "Use `const { TypeError } = primordials;` instead of the global."
68-
- name: URIError
69-
message: "Use `const { URIError } = primordials;` instead of the global."
7077
- name: Uint16Array
71-
message: "Use `const { Uint16Array } = primordials;` instead of the global."
7278
- name: Uint32Array
73-
message: "Use `const { Uint32Array } = primordials;` instead of the global."
7479
- name: Uint8Array
75-
message: "Use `const { Uint8Array } = primordials;` instead of the global."
7680
- name: Uint8ClampedArray
77-
message: "Use `const { Uint8ClampedArray } = primordials;` instead of the global."
81+
- name: URIError
7882
- name: WeakMap
79-
message: "Use `const { WeakMap } = primordials;` instead of the global."
8083
- name: WeakSet
81-
message: "Use `const { WeakSet } = primordials;` instead of the global."
82-
- name: parseFloat
83-
message: "Use `const { NumberParseFloat } = primordials;` instead of the global."
84-
- name: parseInt
85-
message: "Use `const { NumberParseInt } = primordials;` instead of the global."
86-
no-restricted-syntax:
87-
# Config copied from .eslintrc.js
88-
- error
89-
- selector: "CallExpression[callee.object.name='assert']:not([callee.property.name='ok']):not([callee.property.name='fail']):not([callee.property.name='ifError'])"
90-
message: "Please only use simple assertions in ./lib"
91-
- selector: "CallExpression[callee.name='setTimeout'][arguments.length<2]"
92-
message: "setTimeout() must be invoked with at least two arguments."
93-
- selector: "CallExpression[callee.name='setInterval'][arguments.length<2]"
94-
message: "setInterval() must be invoked with at least 2 arguments."
95-
- selector: "ThrowStatement > CallExpression[callee.name=/Error$/]"
96-
message: "Use new keyword when throwing an Error."
97-
# Config specific to lib
98-
- selector: "NewExpression[callee.name=/Error$/]:not([callee.name=/^(AssertionError|NghttpError)$/])"
99-
message: "Use an error exported by the internal/errors module."
100-
- selector: "CallExpression[callee.object.name='Error'][callee.property.name='captureStackTrace']"
101-
message: "Please use `require('internal/errors').hideStackFrames()` instead."
102-
- selector: "AssignmentExpression:matches([left.name='prepareStackTrace'], [left.property.name='prepareStackTrace'])"
103-
message: "Use 'overrideStackTrace' from 'lib/internal/errors.js' instead of 'Error.prepareStackTrace'."
104-
- selector: "CallExpression[callee.name='isNaN']"
105-
message: "Use NumberIsNaN() primordial instead of the global isNaN() function."
106-
# Custom rules in tools/eslint-rules
107-
node-core/lowercase-name-for-primitive: error
108-
node-core/non-ascii-character: error
10984
globals:
11085
Intl: false
11186
# Parameters passed to internal modules
Collapse file

‎lib/internal/event_target.js‎

Copy file name to clipboardExpand all lines: lib/internal/event_target.js
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ const kEvents = Symbol('kEvents');
3636
const kStop = Symbol('kStop');
3737
const kTarget = Symbol('kTarget');
3838

39-
const kHybridDispatch = Symbol.for('nodejs.internal.kHybridDispatch');
39+
const kHybridDispatch = SymbolFor('nodejs.internal.kHybridDispatch');
4040
const kCreateEvent = Symbol('kCreateEvent');
4141
const kNewListener = Symbol('kNewListener');
4242
const kRemoveListener = Symbol('kRemoveListener');
Collapse file

‎lib/internal/freeze_intrinsics.js‎

Copy file name to clipboardExpand all lines: lib/internal/freeze_intrinsics.js
+87-43Lines changed: 87 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -20,21 +20,61 @@
2020
// https://github.com/tc39/proposal-ses/blob/e5271cc42a257a05dcae2fd94713ed2f46c08620/shim/src/freeze.js
2121

2222
/* global WebAssembly, SharedArrayBuffer, console */
23-
/* eslint-disable no-restricted-globals */
2423
'use strict';
2524

25+
const {
26+
Array,
27+
ArrayBuffer,
28+
ArrayPrototypeForEach,
29+
BigInt,
30+
BigInt64Array,
31+
BigUint64Array,
32+
Boolean,
33+
DataView,
34+
Date,
35+
Error,
36+
EvalError,
37+
Float32Array,
38+
Float64Array,
39+
Function,
40+
Int16Array,
41+
Int32Array,
42+
Int8Array,
43+
JSON,
44+
Map,
45+
Math,
46+
Number,
47+
Object,
48+
ObjectDefineProperty,
49+
ObjectFreeze,
50+
ObjectGetOwnPropertyDescriptor,
51+
ObjectGetOwnPropertyDescriptors,
52+
ObjectGetOwnPropertyNames,
53+
ObjectGetOwnPropertySymbols,
54+
ObjectGetPrototypeOf,
55+
ObjectPrototypeHasOwnProperty,
56+
Promise,
57+
RangeError,
58+
ReferenceError,
59+
Reflect,
60+
ReflectOwnKeys,
61+
RegExp,
62+
Set,
63+
String,
64+
Symbol,
65+
SymbolIterator,
66+
SyntaxError,
67+
TypeError,
68+
Uint16Array,
69+
Uint32Array,
70+
Uint8Array,
71+
Uint8ClampedArray,
72+
URIError,
73+
WeakMap,
74+
WeakSet,
75+
} = primordials;
76+
2677
module.exports = function() {
27-
const {
28-
defineProperty,
29-
freeze,
30-
getOwnPropertyDescriptor,
31-
getOwnPropertyDescriptors,
32-
getOwnPropertyNames,
33-
getOwnPropertySymbols,
34-
getPrototypeOf,
35-
} = Object;
36-
const objectHasOwnProperty = Object.prototype.hasOwnProperty;
37-
const { ownKeys } = Reflect;
3878
const {
3979
clearImmediate,
4080
clearInterval,
@@ -47,25 +87,25 @@ module.exports = function() {
4787
const intrinsicPrototypes = [
4888
// Anonymous Intrinsics
4989
// IteratorPrototype
50-
getPrototypeOf(
51-
getPrototypeOf(new Array()[Symbol.iterator]())
90+
ObjectGetPrototypeOf(
91+
ObjectGetPrototypeOf(new Array()[SymbolIterator]())
5292
),
5393
// ArrayIteratorPrototype
54-
getPrototypeOf(new Array()[Symbol.iterator]()),
94+
ObjectGetPrototypeOf(new Array()[SymbolIterator]()),
5595
// StringIteratorPrototype
56-
getPrototypeOf(new String()[Symbol.iterator]()),
96+
ObjectGetPrototypeOf(new String()[SymbolIterator]()),
5797
// MapIteratorPrototype
58-
getPrototypeOf(new Map()[Symbol.iterator]()),
98+
ObjectGetPrototypeOf(new Map()[SymbolIterator]()),
5999
// SetIteratorPrototype
60-
getPrototypeOf(new Set()[Symbol.iterator]()),
100+
ObjectGetPrototypeOf(new Set()[SymbolIterator]()),
61101
// GeneratorFunction
62-
getPrototypeOf(function* () {}),
102+
ObjectGetPrototypeOf(function* () {}),
63103
// AsyncFunction
64-
getPrototypeOf(async function() {}),
104+
ObjectGetPrototypeOf(async function() {}),
65105
// AsyncGeneratorFunction
66-
getPrototypeOf(async function* () {}),
106+
ObjectGetPrototypeOf(async function* () {}),
67107
// TypedArray
68-
getPrototypeOf(Uint8Array),
108+
ObjectGetPrototypeOf(Uint8Array),
69109

70110
// 19 Fundamental Objects
71111
Object.prototype, // 19.1
@@ -129,33 +169,37 @@ module.exports = function() {
129169
const intrinsics = [
130170
// Anonymous Intrinsics
131171
// ThrowTypeError
132-
getOwnPropertyDescriptor(Function.prototype, 'caller').get,
172+
ObjectGetOwnPropertyDescriptor(Function.prototype, 'caller').get,
133173
// IteratorPrototype
134-
getPrototypeOf(
135-
getPrototypeOf(new Array()[Symbol.iterator]())
174+
ObjectGetPrototypeOf(
175+
ObjectGetPrototypeOf(new Array()[SymbolIterator]())
136176
),
137177
// ArrayIteratorPrototype
138-
getPrototypeOf(new Array()[Symbol.iterator]()),
178+
ObjectGetPrototypeOf(new Array()[SymbolIterator]()),
139179
// StringIteratorPrototype
140-
getPrototypeOf(new String()[Symbol.iterator]()),
180+
ObjectGetPrototypeOf(new String()[SymbolIterator]()),
141181
// MapIteratorPrototype
142-
getPrototypeOf(new Map()[Symbol.iterator]()),
182+
ObjectGetPrototypeOf(new Map()[SymbolIterator]()),
143183
// SetIteratorPrototype
144-
getPrototypeOf(new Set()[Symbol.iterator]()),
184+
ObjectGetPrototypeOf(new Set()[SymbolIterator]()),
145185
// GeneratorFunction
146-
getPrototypeOf(function* () {}),
186+
ObjectGetPrototypeOf(function* () {}),
147187
// AsyncFunction
148-
getPrototypeOf(async function() {}),
188+
ObjectGetPrototypeOf(async function() {}),
149189
// AsyncGeneratorFunction
150-
getPrototypeOf(async function* () {}),
190+
ObjectGetPrototypeOf(async function* () {}),
151191
// TypedArray
152-
getPrototypeOf(Uint8Array),
192+
ObjectGetPrototypeOf(Uint8Array),
153193

154194
// 18 The Global Object
155195
eval,
196+
// eslint-disable-next-line node-core/prefer-primordials
156197
isFinite,
198+
// eslint-disable-next-line node-core/prefer-primordials
157199
isNaN,
200+
// eslint-disable-next-line node-core/prefer-primordials
158201
parseFloat,
202+
// eslint-disable-next-line node-core/prefer-primordials
159203
parseInt,
160204
decodeURI,
161205
decodeURIComponent,
@@ -289,16 +333,16 @@ module.exports = function() {
289333
// Object are verified before being enqueued,
290334
// therefore this is a valid candidate.
291335
// Throws if this fails (strict mode).
292-
freeze(obj);
336+
ObjectFreeze(obj);
293337

294338
// We rely upon certain commitments of Object.freeze and proxies here
295339

296340
// Get stable/immutable outbound links before a Proxy has a chance to do
297341
// something sneaky.
298-
const proto = getPrototypeOf(obj);
299-
const descs = getOwnPropertyDescriptors(obj);
342+
const proto = ObjectGetPrototypeOf(obj);
343+
const descs = ObjectGetOwnPropertyDescriptors(obj);
300344
enqueue(proto);
301-
ownKeys(descs).forEach((name) => {
345+
ArrayPrototypeForEach(ReflectOwnKeys(descs), (name) => {
302346
// TODO: Uncurried form
303347
// TODO: getOwnPropertyDescriptors is guaranteed to return well-formed
304348
// descriptors, but they still inherit from Object.prototype. If
@@ -378,10 +422,10 @@ module.exports = function() {
378422
`Cannot assign to read only property '${prop}' of object '${obj}'`
379423
);
380424
}
381-
if (objectHasOwnProperty.call(this, prop)) {
425+
if (ObjectPrototypeHasOwnProperty(this, prop)) {
382426
this[prop] = newValue;
383427
} else {
384-
defineProperty(this, prop, {
428+
ObjectDefineProperty(this, prop, {
385429
value: newValue,
386430
writable: true,
387431
enumerable: true,
@@ -390,7 +434,7 @@ module.exports = function() {
390434
}
391435
}
392436

393-
defineProperty(obj, prop, {
437+
ObjectDefineProperty(obj, prop, {
394438
get: getter,
395439
set: setter,
396440
enumerable: desc.enumerable,
@@ -403,14 +447,14 @@ module.exports = function() {
403447
if (!obj) {
404448
return;
405449
}
406-
const descs = getOwnPropertyDescriptors(obj);
450+
const descs = ObjectGetOwnPropertyDescriptors(obj);
407451
if (!descs) {
408452
return;
409453
}
410-
getOwnPropertyNames(obj).forEach((prop) => {
454+
ArrayPrototypeForEach(ObjectGetOwnPropertyNames(obj), (prop) => {
411455
return enableDerivedOverride(obj, prop, descs[prop]);
412456
});
413-
getOwnPropertySymbols(obj).forEach((prop) => {
457+
ArrayPrototypeForEach(ObjectGetOwnPropertySymbols(obj), (prop) => {
414458
return enableDerivedOverride(obj, prop, descs[prop]);
415459
});
416460
}
Collapse file

‎lib/internal/fs/utils.js‎

Copy file name to clipboardExpand all lines: lib/internal/fs/utils.js
+3-1Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,13 @@
33
const {
44
ArrayIsArray,
55
BigInt,
6+
Date,
67
DateNow,
78
ErrorCaptureStackTrace,
89
ObjectPrototypeHasOwnProperty,
910
Number,
1011
NumberIsFinite,
12+
NumberIsInteger,
1113
MathMin,
1214
ObjectSetPrototypeOf,
1315
ReflectOwnKeys,
@@ -785,7 +787,7 @@ const getValidMode = hideStackFrames((mode, type) => {
785787
if (mode == null) {
786788
return def;
787789
}
788-
if (Number.isInteger(mode) && mode >= min && mode <= max) {
790+
if (NumberIsInteger(mode) && mode >= min && mode <= max) {
789791
return mode;
790792
}
791793
if (typeof mode !== 'number') {

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.