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: https://github.com/nodejs/node/pull/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>
This commit is contained in:
parent
1d525f55bc
commit
cef144421c
@ -7,82 +7,6 @@ rules:
|
|||||||
no-mixed-operators:
|
no-mixed-operators:
|
||||||
- error
|
- error
|
||||||
- groups: [[ "&&", "||" ]]
|
- groups: [[ "&&", "||" ]]
|
||||||
no-restricted-globals:
|
|
||||||
- error
|
|
||||||
- name: Array
|
|
||||||
message: "Use `const { Array } = primordials;` instead of the global."
|
|
||||||
- name: ArrayBuffer
|
|
||||||
message: "Use `const { ArrayBuffer } = primordials;` instead of the global."
|
|
||||||
- name: BigInt
|
|
||||||
message: "Use `const { BigInt } = primordials;` instead of the global."
|
|
||||||
- name: BigInt64Array
|
|
||||||
message: "Use `const { BigInt64Array } = primordials;` instead of the global."
|
|
||||||
- name: BigUint64Array
|
|
||||||
message: "Use `const { BigUint64Array } = primordials;` instead of the global."
|
|
||||||
- name: Boolean
|
|
||||||
message: "Use `const { Boolean } = primordials;` instead of the global."
|
|
||||||
- name: Error
|
|
||||||
message: "Use `const { Error } = primordials;` instead of the global."
|
|
||||||
- name: EvalError
|
|
||||||
message: "Use `const { EvalError } = primordials;` instead of the global."
|
|
||||||
- name: Float32Array
|
|
||||||
message: "Use `const { Float32Array } = primordials;` instead of the global."
|
|
||||||
- name: Float64Array
|
|
||||||
message: "Use `const { Float64Array } = primordials;` instead of the global."
|
|
||||||
- name: Int16Array
|
|
||||||
message: "Use `const { Int16Array } = primordials;` instead of the global."
|
|
||||||
- name: Int32Array
|
|
||||||
message: "Use `const { Int32Array } = primordials;` instead of the global."
|
|
||||||
- name: Int8Array
|
|
||||||
message: "Use `const { Int8Array } = primordials;` instead of the global."
|
|
||||||
- name: JSON
|
|
||||||
message: "Use `const { JSON } = primordials;` instead of the global."
|
|
||||||
- name: Map
|
|
||||||
message: "Use `const { Map } = primordials;` instead of the global."
|
|
||||||
- name: Math
|
|
||||||
message: "Use `const { Math } = primordials;` instead of the global."
|
|
||||||
- name: Number
|
|
||||||
message: "Use `const { Number } = primordials;` instead of the global."
|
|
||||||
- name: Object
|
|
||||||
message: "Use `const { Object } = primordials;` instead of the global."
|
|
||||||
- name: Promise
|
|
||||||
message: "Use `const { Promise } = primordials;` instead of the global."
|
|
||||||
- name: RangeError
|
|
||||||
message: "Use `const { RangeError } = primordials;` instead of the global."
|
|
||||||
- name: ReferenceError
|
|
||||||
message: "Use `const { ReferenceError } = primordials;` instead of the global."
|
|
||||||
- name: Reflect
|
|
||||||
message: "Use `const { Reflect } = primordials;` instead of the global."
|
|
||||||
- name: RegExp
|
|
||||||
message: "Use `const { RegExp } = primordials;` instead of the global."
|
|
||||||
- name: Set
|
|
||||||
message: "Use `const { Set } = primordials;` instead of the global."
|
|
||||||
- name: String
|
|
||||||
message: "Use `const { String } = primordials;` instead of the global."
|
|
||||||
- name: Symbol
|
|
||||||
message: "Use `const { Symbol } = primordials;` instead of the global."
|
|
||||||
- name: SyntaxError
|
|
||||||
message: "Use `const { SyntaxError } = primordials;` instead of the global."
|
|
||||||
- name: TypeError
|
|
||||||
message: "Use `const { TypeError } = primordials;` instead of the global."
|
|
||||||
- name: URIError
|
|
||||||
message: "Use `const { URIError } = primordials;` instead of the global."
|
|
||||||
- name: Uint16Array
|
|
||||||
message: "Use `const { Uint16Array } = primordials;` instead of the global."
|
|
||||||
- name: Uint32Array
|
|
||||||
message: "Use `const { Uint32Array } = primordials;` instead of the global."
|
|
||||||
- name: Uint8Array
|
|
||||||
message: "Use `const { Uint8Array } = primordials;` instead of the global."
|
|
||||||
- name: Uint8ClampedArray
|
|
||||||
message: "Use `const { Uint8ClampedArray } = primordials;` instead of the global."
|
|
||||||
- name: WeakMap
|
|
||||||
message: "Use `const { WeakMap } = primordials;` instead of the global."
|
|
||||||
- name: WeakSet
|
|
||||||
message: "Use `const { WeakSet } = primordials;` instead of the global."
|
|
||||||
- name: parseFloat
|
|
||||||
message: "Use `const { NumberParseFloat } = primordials;` instead of the global."
|
|
||||||
- name: parseInt
|
|
||||||
message: "Use `const { NumberParseInt } = primordials;` instead of the global."
|
|
||||||
no-restricted-syntax:
|
no-restricted-syntax:
|
||||||
# Config copied from .eslintrc.js
|
# Config copied from .eslintrc.js
|
||||||
- error
|
- error
|
||||||
@ -101,11 +25,62 @@ rules:
|
|||||||
message: "Please use `require('internal/errors').hideStackFrames()` instead."
|
message: "Please use `require('internal/errors').hideStackFrames()` instead."
|
||||||
- selector: "AssignmentExpression:matches([left.name='prepareStackTrace'], [left.property.name='prepareStackTrace'])"
|
- selector: "AssignmentExpression:matches([left.name='prepareStackTrace'], [left.property.name='prepareStackTrace'])"
|
||||||
message: "Use 'overrideStackTrace' from 'lib/internal/errors.js' instead of 'Error.prepareStackTrace'."
|
message: "Use 'overrideStackTrace' from 'lib/internal/errors.js' instead of 'Error.prepareStackTrace'."
|
||||||
- selector: "CallExpression[callee.name='isNaN']"
|
|
||||||
message: "Use NumberIsNaN() primordial instead of the global isNaN() function."
|
|
||||||
# Custom rules in tools/eslint-rules
|
# Custom rules in tools/eslint-rules
|
||||||
node-core/lowercase-name-for-primitive: error
|
node-core/lowercase-name-for-primitive: error
|
||||||
node-core/non-ascii-character: error
|
node-core/non-ascii-character: error
|
||||||
|
node-core/prefer-primordials:
|
||||||
|
- error
|
||||||
|
- name: Array
|
||||||
|
- name: ArrayBuffer
|
||||||
|
- name: BigInt
|
||||||
|
- name: BigInt64Array
|
||||||
|
- name: BigUint64Array
|
||||||
|
- name: Boolean
|
||||||
|
- name: DataView
|
||||||
|
- name: Date
|
||||||
|
- name: Error
|
||||||
|
ignore:
|
||||||
|
- stackTraceLimit
|
||||||
|
- captureStackTrace
|
||||||
|
- prepareStackTrace
|
||||||
|
- isPrototypeOf
|
||||||
|
- name: EvalError
|
||||||
|
- name: Float32Array
|
||||||
|
- name: Float64Array
|
||||||
|
- name: Function
|
||||||
|
- name: Int16Array
|
||||||
|
- name: Int32Array
|
||||||
|
- name: Int8Array
|
||||||
|
- name: isFinite
|
||||||
|
into: Number
|
||||||
|
- name: isNaN
|
||||||
|
into: Number
|
||||||
|
- name: JSON
|
||||||
|
- name: Map
|
||||||
|
- name: Math
|
||||||
|
- name: Number
|
||||||
|
- name: Object
|
||||||
|
- name: parseFloat
|
||||||
|
into: Number
|
||||||
|
- name: parseInt
|
||||||
|
into: Number
|
||||||
|
- name: Promise
|
||||||
|
- name: RangeError
|
||||||
|
- name: ReferenceError
|
||||||
|
- name: Reflect
|
||||||
|
- name: RegExp
|
||||||
|
- name: Set
|
||||||
|
- name: String
|
||||||
|
- name: Symbol
|
||||||
|
- name: SyntaxError
|
||||||
|
- name: TypeError
|
||||||
|
- name: Uint16Array
|
||||||
|
- name: Uint32Array
|
||||||
|
- name: Uint8Array
|
||||||
|
- name: Uint8ClampedArray
|
||||||
|
- name: URIError
|
||||||
|
- name: WeakMap
|
||||||
|
- name: WeakSet
|
||||||
globals:
|
globals:
|
||||||
Intl: false
|
Intl: false
|
||||||
# Parameters passed to internal modules
|
# Parameters passed to internal modules
|
||||||
|
@ -36,7 +36,7 @@ const kEvents = Symbol('kEvents');
|
|||||||
const kStop = Symbol('kStop');
|
const kStop = Symbol('kStop');
|
||||||
const kTarget = Symbol('kTarget');
|
const kTarget = Symbol('kTarget');
|
||||||
|
|
||||||
const kHybridDispatch = Symbol.for('nodejs.internal.kHybridDispatch');
|
const kHybridDispatch = SymbolFor('nodejs.internal.kHybridDispatch');
|
||||||
const kCreateEvent = Symbol('kCreateEvent');
|
const kCreateEvent = Symbol('kCreateEvent');
|
||||||
const kNewListener = Symbol('kNewListener');
|
const kNewListener = Symbol('kNewListener');
|
||||||
const kRemoveListener = Symbol('kRemoveListener');
|
const kRemoveListener = Symbol('kRemoveListener');
|
||||||
|
@ -20,21 +20,61 @@
|
|||||||
// https://github.com/tc39/proposal-ses/blob/e5271cc42a257a05dcae2fd94713ed2f46c08620/shim/src/freeze.js
|
// https://github.com/tc39/proposal-ses/blob/e5271cc42a257a05dcae2fd94713ed2f46c08620/shim/src/freeze.js
|
||||||
|
|
||||||
/* global WebAssembly, SharedArrayBuffer, console */
|
/* global WebAssembly, SharedArrayBuffer, console */
|
||||||
/* eslint-disable no-restricted-globals */
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
const {
|
||||||
|
Array,
|
||||||
|
ArrayBuffer,
|
||||||
|
ArrayPrototypeForEach,
|
||||||
|
BigInt,
|
||||||
|
BigInt64Array,
|
||||||
|
BigUint64Array,
|
||||||
|
Boolean,
|
||||||
|
DataView,
|
||||||
|
Date,
|
||||||
|
Error,
|
||||||
|
EvalError,
|
||||||
|
Float32Array,
|
||||||
|
Float64Array,
|
||||||
|
Function,
|
||||||
|
Int16Array,
|
||||||
|
Int32Array,
|
||||||
|
Int8Array,
|
||||||
|
JSON,
|
||||||
|
Map,
|
||||||
|
Math,
|
||||||
|
Number,
|
||||||
|
Object,
|
||||||
|
ObjectDefineProperty,
|
||||||
|
ObjectFreeze,
|
||||||
|
ObjectGetOwnPropertyDescriptor,
|
||||||
|
ObjectGetOwnPropertyDescriptors,
|
||||||
|
ObjectGetOwnPropertyNames,
|
||||||
|
ObjectGetOwnPropertySymbols,
|
||||||
|
ObjectGetPrototypeOf,
|
||||||
|
ObjectPrototypeHasOwnProperty,
|
||||||
|
Promise,
|
||||||
|
RangeError,
|
||||||
|
ReferenceError,
|
||||||
|
Reflect,
|
||||||
|
ReflectOwnKeys,
|
||||||
|
RegExp,
|
||||||
|
Set,
|
||||||
|
String,
|
||||||
|
Symbol,
|
||||||
|
SymbolIterator,
|
||||||
|
SyntaxError,
|
||||||
|
TypeError,
|
||||||
|
Uint16Array,
|
||||||
|
Uint32Array,
|
||||||
|
Uint8Array,
|
||||||
|
Uint8ClampedArray,
|
||||||
|
URIError,
|
||||||
|
WeakMap,
|
||||||
|
WeakSet,
|
||||||
|
} = primordials;
|
||||||
|
|
||||||
module.exports = function() {
|
module.exports = function() {
|
||||||
const {
|
|
||||||
defineProperty,
|
|
||||||
freeze,
|
|
||||||
getOwnPropertyDescriptor,
|
|
||||||
getOwnPropertyDescriptors,
|
|
||||||
getOwnPropertyNames,
|
|
||||||
getOwnPropertySymbols,
|
|
||||||
getPrototypeOf,
|
|
||||||
} = Object;
|
|
||||||
const objectHasOwnProperty = Object.prototype.hasOwnProperty;
|
|
||||||
const { ownKeys } = Reflect;
|
|
||||||
const {
|
const {
|
||||||
clearImmediate,
|
clearImmediate,
|
||||||
clearInterval,
|
clearInterval,
|
||||||
@ -47,25 +87,25 @@ module.exports = function() {
|
|||||||
const intrinsicPrototypes = [
|
const intrinsicPrototypes = [
|
||||||
// Anonymous Intrinsics
|
// Anonymous Intrinsics
|
||||||
// IteratorPrototype
|
// IteratorPrototype
|
||||||
getPrototypeOf(
|
ObjectGetPrototypeOf(
|
||||||
getPrototypeOf(new Array()[Symbol.iterator]())
|
ObjectGetPrototypeOf(new Array()[SymbolIterator]())
|
||||||
),
|
),
|
||||||
// ArrayIteratorPrototype
|
// ArrayIteratorPrototype
|
||||||
getPrototypeOf(new Array()[Symbol.iterator]()),
|
ObjectGetPrototypeOf(new Array()[SymbolIterator]()),
|
||||||
// StringIteratorPrototype
|
// StringIteratorPrototype
|
||||||
getPrototypeOf(new String()[Symbol.iterator]()),
|
ObjectGetPrototypeOf(new String()[SymbolIterator]()),
|
||||||
// MapIteratorPrototype
|
// MapIteratorPrototype
|
||||||
getPrototypeOf(new Map()[Symbol.iterator]()),
|
ObjectGetPrototypeOf(new Map()[SymbolIterator]()),
|
||||||
// SetIteratorPrototype
|
// SetIteratorPrototype
|
||||||
getPrototypeOf(new Set()[Symbol.iterator]()),
|
ObjectGetPrototypeOf(new Set()[SymbolIterator]()),
|
||||||
// GeneratorFunction
|
// GeneratorFunction
|
||||||
getPrototypeOf(function* () {}),
|
ObjectGetPrototypeOf(function* () {}),
|
||||||
// AsyncFunction
|
// AsyncFunction
|
||||||
getPrototypeOf(async function() {}),
|
ObjectGetPrototypeOf(async function() {}),
|
||||||
// AsyncGeneratorFunction
|
// AsyncGeneratorFunction
|
||||||
getPrototypeOf(async function* () {}),
|
ObjectGetPrototypeOf(async function* () {}),
|
||||||
// TypedArray
|
// TypedArray
|
||||||
getPrototypeOf(Uint8Array),
|
ObjectGetPrototypeOf(Uint8Array),
|
||||||
|
|
||||||
// 19 Fundamental Objects
|
// 19 Fundamental Objects
|
||||||
Object.prototype, // 19.1
|
Object.prototype, // 19.1
|
||||||
@ -129,33 +169,37 @@ module.exports = function() {
|
|||||||
const intrinsics = [
|
const intrinsics = [
|
||||||
// Anonymous Intrinsics
|
// Anonymous Intrinsics
|
||||||
// ThrowTypeError
|
// ThrowTypeError
|
||||||
getOwnPropertyDescriptor(Function.prototype, 'caller').get,
|
ObjectGetOwnPropertyDescriptor(Function.prototype, 'caller').get,
|
||||||
// IteratorPrototype
|
// IteratorPrototype
|
||||||
getPrototypeOf(
|
ObjectGetPrototypeOf(
|
||||||
getPrototypeOf(new Array()[Symbol.iterator]())
|
ObjectGetPrototypeOf(new Array()[SymbolIterator]())
|
||||||
),
|
),
|
||||||
// ArrayIteratorPrototype
|
// ArrayIteratorPrototype
|
||||||
getPrototypeOf(new Array()[Symbol.iterator]()),
|
ObjectGetPrototypeOf(new Array()[SymbolIterator]()),
|
||||||
// StringIteratorPrototype
|
// StringIteratorPrototype
|
||||||
getPrototypeOf(new String()[Symbol.iterator]()),
|
ObjectGetPrototypeOf(new String()[SymbolIterator]()),
|
||||||
// MapIteratorPrototype
|
// MapIteratorPrototype
|
||||||
getPrototypeOf(new Map()[Symbol.iterator]()),
|
ObjectGetPrototypeOf(new Map()[SymbolIterator]()),
|
||||||
// SetIteratorPrototype
|
// SetIteratorPrototype
|
||||||
getPrototypeOf(new Set()[Symbol.iterator]()),
|
ObjectGetPrototypeOf(new Set()[SymbolIterator]()),
|
||||||
// GeneratorFunction
|
// GeneratorFunction
|
||||||
getPrototypeOf(function* () {}),
|
ObjectGetPrototypeOf(function* () {}),
|
||||||
// AsyncFunction
|
// AsyncFunction
|
||||||
getPrototypeOf(async function() {}),
|
ObjectGetPrototypeOf(async function() {}),
|
||||||
// AsyncGeneratorFunction
|
// AsyncGeneratorFunction
|
||||||
getPrototypeOf(async function* () {}),
|
ObjectGetPrototypeOf(async function* () {}),
|
||||||
// TypedArray
|
// TypedArray
|
||||||
getPrototypeOf(Uint8Array),
|
ObjectGetPrototypeOf(Uint8Array),
|
||||||
|
|
||||||
// 18 The Global Object
|
// 18 The Global Object
|
||||||
eval,
|
eval,
|
||||||
|
// eslint-disable-next-line node-core/prefer-primordials
|
||||||
isFinite,
|
isFinite,
|
||||||
|
// eslint-disable-next-line node-core/prefer-primordials
|
||||||
isNaN,
|
isNaN,
|
||||||
|
// eslint-disable-next-line node-core/prefer-primordials
|
||||||
parseFloat,
|
parseFloat,
|
||||||
|
// eslint-disable-next-line node-core/prefer-primordials
|
||||||
parseInt,
|
parseInt,
|
||||||
decodeURI,
|
decodeURI,
|
||||||
decodeURIComponent,
|
decodeURIComponent,
|
||||||
@ -289,16 +333,16 @@ module.exports = function() {
|
|||||||
// Object are verified before being enqueued,
|
// Object are verified before being enqueued,
|
||||||
// therefore this is a valid candidate.
|
// therefore this is a valid candidate.
|
||||||
// Throws if this fails (strict mode).
|
// Throws if this fails (strict mode).
|
||||||
freeze(obj);
|
ObjectFreeze(obj);
|
||||||
|
|
||||||
// We rely upon certain commitments of Object.freeze and proxies here
|
// We rely upon certain commitments of Object.freeze and proxies here
|
||||||
|
|
||||||
// Get stable/immutable outbound links before a Proxy has a chance to do
|
// Get stable/immutable outbound links before a Proxy has a chance to do
|
||||||
// something sneaky.
|
// something sneaky.
|
||||||
const proto = getPrototypeOf(obj);
|
const proto = ObjectGetPrototypeOf(obj);
|
||||||
const descs = getOwnPropertyDescriptors(obj);
|
const descs = ObjectGetOwnPropertyDescriptors(obj);
|
||||||
enqueue(proto);
|
enqueue(proto);
|
||||||
ownKeys(descs).forEach((name) => {
|
ArrayPrototypeForEach(ReflectOwnKeys(descs), (name) => {
|
||||||
// TODO: Uncurried form
|
// TODO: Uncurried form
|
||||||
// TODO: getOwnPropertyDescriptors is guaranteed to return well-formed
|
// TODO: getOwnPropertyDescriptors is guaranteed to return well-formed
|
||||||
// descriptors, but they still inherit from Object.prototype. If
|
// descriptors, but they still inherit from Object.prototype. If
|
||||||
@ -378,10 +422,10 @@ module.exports = function() {
|
|||||||
`Cannot assign to read only property '${prop}' of object '${obj}'`
|
`Cannot assign to read only property '${prop}' of object '${obj}'`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (objectHasOwnProperty.call(this, prop)) {
|
if (ObjectPrototypeHasOwnProperty(this, prop)) {
|
||||||
this[prop] = newValue;
|
this[prop] = newValue;
|
||||||
} else {
|
} else {
|
||||||
defineProperty(this, prop, {
|
ObjectDefineProperty(this, prop, {
|
||||||
value: newValue,
|
value: newValue,
|
||||||
writable: true,
|
writable: true,
|
||||||
enumerable: true,
|
enumerable: true,
|
||||||
@ -390,7 +434,7 @@ module.exports = function() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
defineProperty(obj, prop, {
|
ObjectDefineProperty(obj, prop, {
|
||||||
get: getter,
|
get: getter,
|
||||||
set: setter,
|
set: setter,
|
||||||
enumerable: desc.enumerable,
|
enumerable: desc.enumerable,
|
||||||
@ -403,14 +447,14 @@ module.exports = function() {
|
|||||||
if (!obj) {
|
if (!obj) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const descs = getOwnPropertyDescriptors(obj);
|
const descs = ObjectGetOwnPropertyDescriptors(obj);
|
||||||
if (!descs) {
|
if (!descs) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
getOwnPropertyNames(obj).forEach((prop) => {
|
ArrayPrototypeForEach(ObjectGetOwnPropertyNames(obj), (prop) => {
|
||||||
return enableDerivedOverride(obj, prop, descs[prop]);
|
return enableDerivedOverride(obj, prop, descs[prop]);
|
||||||
});
|
});
|
||||||
getOwnPropertySymbols(obj).forEach((prop) => {
|
ArrayPrototypeForEach(ObjectGetOwnPropertySymbols(obj), (prop) => {
|
||||||
return enableDerivedOverride(obj, prop, descs[prop]);
|
return enableDerivedOverride(obj, prop, descs[prop]);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -3,11 +3,13 @@
|
|||||||
const {
|
const {
|
||||||
ArrayIsArray,
|
ArrayIsArray,
|
||||||
BigInt,
|
BigInt,
|
||||||
|
Date,
|
||||||
DateNow,
|
DateNow,
|
||||||
ErrorCaptureStackTrace,
|
ErrorCaptureStackTrace,
|
||||||
ObjectPrototypeHasOwnProperty,
|
ObjectPrototypeHasOwnProperty,
|
||||||
Number,
|
Number,
|
||||||
NumberIsFinite,
|
NumberIsFinite,
|
||||||
|
NumberIsInteger,
|
||||||
MathMin,
|
MathMin,
|
||||||
ObjectSetPrototypeOf,
|
ObjectSetPrototypeOf,
|
||||||
ReflectOwnKeys,
|
ReflectOwnKeys,
|
||||||
@ -785,7 +787,7 @@ const getValidMode = hideStackFrames((mode, type) => {
|
|||||||
if (mode == null) {
|
if (mode == null) {
|
||||||
return def;
|
return def;
|
||||||
}
|
}
|
||||||
if (Number.isInteger(mode) && mode >= min && mode <= max) {
|
if (NumberIsInteger(mode) && mode >= min && mode <= max) {
|
||||||
return mode;
|
return mode;
|
||||||
}
|
}
|
||||||
if (typeof mode !== 'number') {
|
if (typeof mode !== 'number') {
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
const {
|
const {
|
||||||
Symbol,
|
Symbol,
|
||||||
|
Date,
|
||||||
} = primordials;
|
} = primordials;
|
||||||
|
|
||||||
const { setUnrefTimeout } = require('internal/timers');
|
const { setUnrefTimeout } = require('internal/timers');
|
||||||
|
@ -1,6 +1,13 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
/* eslint-disable no-restricted-globals */
|
const {
|
||||||
|
Boolean,
|
||||||
|
Map,
|
||||||
|
MathFloor,
|
||||||
|
MathMax,
|
||||||
|
ObjectKeys,
|
||||||
|
RegExp,
|
||||||
|
} = primordials;
|
||||||
|
|
||||||
const { types } = internalBinding('options');
|
const { types } = internalBinding('options');
|
||||||
const hasCrypto = Boolean(process.versions.openssl);
|
const hasCrypto = Boolean(process.versions.openssl);
|
||||||
@ -10,7 +17,7 @@ const {
|
|||||||
} = require('internal/bootstrap/pre_execution');
|
} = require('internal/bootstrap/pre_execution');
|
||||||
|
|
||||||
const typeLookup = [];
|
const typeLookup = [];
|
||||||
for (const key of Object.keys(types))
|
for (const key of ObjectKeys(types))
|
||||||
typeLookup[types[key]] = key;
|
typeLookup[types[key]] = key;
|
||||||
|
|
||||||
// Environment variables are parsed ad-hoc throughout the code base,
|
// Environment variables are parsed ad-hoc throughout the code base,
|
||||||
@ -127,7 +134,7 @@ function format({ options, aliases = new Map(), firstColumn, secondColumn }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
text += displayName;
|
text += displayName;
|
||||||
maxFirstColumnUsed = Math.max(maxFirstColumnUsed, displayName.length);
|
maxFirstColumnUsed = MathMax(maxFirstColumnUsed, displayName.length);
|
||||||
if (displayName.length >= firstColumn)
|
if (displayName.length >= firstColumn)
|
||||||
text += '\n' + ' '.repeat(firstColumn);
|
text += '\n' + ' '.repeat(firstColumn);
|
||||||
else
|
else
|
||||||
@ -154,9 +161,9 @@ function print(stream) {
|
|||||||
const { options, aliases } = require('internal/options');
|
const { options, aliases } = require('internal/options');
|
||||||
|
|
||||||
// Use 75 % of the available width, and at least 70 characters.
|
// Use 75 % of the available width, and at least 70 characters.
|
||||||
const width = Math.max(70, (stream.columns || 0) * 0.75);
|
const width = MathMax(70, (stream.columns || 0) * 0.75);
|
||||||
const firstColumn = Math.floor(width * 0.4);
|
const firstColumn = MathFloor(width * 0.4);
|
||||||
const secondColumn = Math.floor(width * 0.57);
|
const secondColumn = MathFloor(width * 0.57);
|
||||||
|
|
||||||
options.set('-', { helpText: 'script read from stdin ' +
|
options.set('-', { helpText: 'script read from stdin ' +
|
||||||
'(default if no file name is provided, ' +
|
'(default if no file name is provided, ' +
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
/* eslint-disable no-restricted-globals */
|
/* eslint-disable node-core/prefer-primordials */
|
||||||
|
|
||||||
// This file subclasses and stores the JS builtins that come from the VM
|
// This file subclasses and stores the JS builtins that come from the VM
|
||||||
// so that Node.js's builtin modules do not need to later look these up from
|
// so that Node.js's builtin modules do not need to later look these up from
|
||||||
|
@ -10,7 +10,7 @@ const {
|
|||||||
assertCrypto();
|
assertCrypto();
|
||||||
|
|
||||||
const {
|
const {
|
||||||
Array,
|
ArrayFrom,
|
||||||
BigInt64Array,
|
BigInt64Array,
|
||||||
Boolean,
|
Boolean,
|
||||||
Error,
|
Error,
|
||||||
@ -22,6 +22,7 @@ const {
|
|||||||
PromiseResolve,
|
PromiseResolve,
|
||||||
Set,
|
Set,
|
||||||
Symbol,
|
Symbol,
|
||||||
|
SymbolFor,
|
||||||
} = primordials;
|
} = primordials;
|
||||||
|
|
||||||
const { Buffer } = require('buffer');
|
const { Buffer } = require('buffer');
|
||||||
@ -242,7 +243,7 @@ const kUsePreferredAddress = Symbol('kUsePreferredAddress');
|
|||||||
const kVersionNegotiation = Symbol('kVersionNegotiation');
|
const kVersionNegotiation = Symbol('kVersionNegotiation');
|
||||||
const kWriteGeneric = Symbol('kWriteGeneric');
|
const kWriteGeneric = Symbol('kWriteGeneric');
|
||||||
|
|
||||||
const kRejections = Symbol.for('nodejs.rejection');
|
const kRejections = SymbolFor('nodejs.rejection');
|
||||||
|
|
||||||
const kSocketUnbound = 0;
|
const kSocketUnbound = 0;
|
||||||
const kSocketPending = 1;
|
const kSocketPending = 1;
|
||||||
@ -1020,7 +1021,7 @@ class QuicSocket extends EventEmitter {
|
|||||||
const state = this[kInternalState];
|
const state = this[kInternalState];
|
||||||
return customInspect(this, {
|
return customInspect(this, {
|
||||||
endpoints: this.endpoints,
|
endpoints: this.endpoints,
|
||||||
sessions: Array.from(state.sessions),
|
sessions: ArrayFrom(state.sessions),
|
||||||
bound: this.bound,
|
bound: this.bound,
|
||||||
pending: this.pending,
|
pending: this.pending,
|
||||||
closing: this.closing,
|
closing: this.closing,
|
||||||
@ -1470,7 +1471,7 @@ class QuicSocket extends EventEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get endpoints() {
|
get endpoints() {
|
||||||
return Array.from(this[kInternalState].endpoints);
|
return ArrayFrom(this[kInternalState].endpoints);
|
||||||
}
|
}
|
||||||
|
|
||||||
get serverSecureContext() {
|
get serverSecureContext() {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const {
|
const {
|
||||||
String,
|
StringFromCharCode,
|
||||||
Symbol,
|
Symbol,
|
||||||
} = primordials;
|
} = primordials;
|
||||||
|
|
||||||
@ -325,7 +325,7 @@ function* emitKeys(stream) {
|
|||||||
key.meta = escaped;
|
key.meta = escaped;
|
||||||
} else if (!escaped && ch <= '\x1a') {
|
} else if (!escaped && ch <= '\x1a') {
|
||||||
// ctrl+letter
|
// ctrl+letter
|
||||||
key.name = String.fromCharCode(ch.charCodeAt(0) + 'a'.charCodeAt(0) - 1);
|
key.name = StringFromCharCode(ch.charCodeAt(0) + 'a'.charCodeAt(0) - 1);
|
||||||
key.ctrl = true;
|
key.ctrl = true;
|
||||||
} else if (/^[0-9A-Za-z]$/.test(ch)) {
|
} else if (/^[0-9A-Za-z]$/.test(ch)) {
|
||||||
// Letter, number, shift+letter
|
// Letter, number, shift+letter
|
||||||
|
@ -75,6 +75,7 @@
|
|||||||
const {
|
const {
|
||||||
MathMax,
|
MathMax,
|
||||||
MathTrunc,
|
MathTrunc,
|
||||||
|
NumberIsFinite,
|
||||||
NumberMIN_SAFE_INTEGER,
|
NumberMIN_SAFE_INTEGER,
|
||||||
ObjectCreate,
|
ObjectCreate,
|
||||||
Symbol,
|
Symbol,
|
||||||
@ -380,7 +381,7 @@ function setUnrefTimeout(callback, after) {
|
|||||||
// Type checking used by timers.enroll() and Socket#setTimeout()
|
// Type checking used by timers.enroll() and Socket#setTimeout()
|
||||||
function getTimerDuration(msecs, name) {
|
function getTimerDuration(msecs, name) {
|
||||||
validateNumber(msecs, name);
|
validateNumber(msecs, name);
|
||||||
if (msecs < 0 || !isFinite(msecs)) {
|
if (msecs < 0 || !NumberIsFinite(msecs)) {
|
||||||
throw new ERR_OUT_OF_RANGE(name, 'a non-negative finite number', msecs);
|
throw new ERR_OUT_OF_RANGE(name, 'a non-negative finite number', msecs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
const {
|
const {
|
||||||
makeSafe,
|
makeSafe,
|
||||||
Object,
|
ObjectFreeze,
|
||||||
SafeSet,
|
SafeSet,
|
||||||
SafeWeakMap,
|
SafeWeakMap,
|
||||||
SymbolIterator,
|
SymbolIterator,
|
||||||
@ -79,7 +79,7 @@ function cleanup({ set, ref }) {
|
|||||||
set.delete(ref);
|
set.delete(ref);
|
||||||
}
|
}
|
||||||
|
|
||||||
Object.freeze(IterableWeakMap.prototype);
|
ObjectFreeze(IterableWeakMap.prototype);
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
IterableWeakMap,
|
IterableWeakMap,
|
||||||
|
@ -9,6 +9,7 @@ const {
|
|||||||
ObjectSetPrototypeOf,
|
ObjectSetPrototypeOf,
|
||||||
SafePromise,
|
SafePromise,
|
||||||
Symbol,
|
Symbol,
|
||||||
|
SymbolToStringTag,
|
||||||
TypeError,
|
TypeError,
|
||||||
WeakMap,
|
WeakMap,
|
||||||
} = primordials;
|
} = primordials;
|
||||||
@ -239,7 +240,7 @@ class Module {
|
|||||||
o.context = this.context;
|
o.context = this.context;
|
||||||
|
|
||||||
ObjectSetPrototypeOf(o, ObjectGetPrototypeOf(this));
|
ObjectSetPrototypeOf(o, ObjectGetPrototypeOf(this));
|
||||||
ObjectDefineProperty(o, Symbol.toStringTag, {
|
ObjectDefineProperty(o, SymbolToStringTag, {
|
||||||
value: constructor.name,
|
value: constructor.name,
|
||||||
configurable: true
|
configurable: true
|
||||||
});
|
});
|
||||||
|
@ -27,6 +27,7 @@ const {
|
|||||||
Array,
|
Array,
|
||||||
ArrayIsArray,
|
ArrayIsArray,
|
||||||
MathAbs,
|
MathAbs,
|
||||||
|
NumberIsFinite,
|
||||||
ObjectCreate,
|
ObjectCreate,
|
||||||
ObjectKeys,
|
ObjectKeys,
|
||||||
String,
|
String,
|
||||||
@ -156,7 +157,7 @@ function qsEscape(str) {
|
|||||||
function stringifyPrimitive(v) {
|
function stringifyPrimitive(v) {
|
||||||
if (typeof v === 'string')
|
if (typeof v === 'string')
|
||||||
return v;
|
return v;
|
||||||
if (typeof v === 'number' && isFinite(v))
|
if (typeof v === 'number' && NumberIsFinite(v))
|
||||||
return '' + v;
|
return '' + v;
|
||||||
if (typeof v === 'boolean')
|
if (typeof v === 'boolean')
|
||||||
return v ? 'true' : 'false';
|
return v ? 'true' : 'false';
|
||||||
@ -167,7 +168,7 @@ function stringifyPrimitive(v) {
|
|||||||
function encodeStringified(v, encode) {
|
function encodeStringified(v, encode) {
|
||||||
if (typeof v === 'string')
|
if (typeof v === 'string')
|
||||||
return (v.length ? encode(v) : '');
|
return (v.length ? encode(v) : '');
|
||||||
if (typeof v === 'number' && isFinite(v)) {
|
if (typeof v === 'number' && NumberIsFinite(v)) {
|
||||||
// Values >= 1e21 automatically switch to scientific notation which requires
|
// Values >= 1e21 automatically switch to scientific notation which requires
|
||||||
// escaping due to the inclusion of a '+' in the output
|
// escaping due to the inclusion of a '+' in the output
|
||||||
return (MathAbs(v) < 1e21 ? '' + v : encode('' + v));
|
return (MathAbs(v) < 1e21 ? '' + v : encode('' + v));
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
|
|
||||||
const {
|
const {
|
||||||
ArrayIsArray,
|
ArrayIsArray,
|
||||||
|
Date,
|
||||||
Error,
|
Error,
|
||||||
NumberIsSafeInteger,
|
NumberIsSafeInteger,
|
||||||
ObjectDefineProperties,
|
ObjectDefineProperties,
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
const {
|
const {
|
||||||
Array,
|
Array,
|
||||||
ArrayBuffer,
|
ArrayBuffer,
|
||||||
|
DataView,
|
||||||
Error,
|
Error,
|
||||||
Float32Array,
|
Float32Array,
|
||||||
Float64Array,
|
Float64Array,
|
||||||
|
158
test/parallel/test-eslint-prefer-primordials.js
Normal file
158
test/parallel/test-eslint-prefer-primordials.js
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const common = require('../common');
|
||||||
|
if (!common.hasCrypto)
|
||||||
|
common.skip('missing crypto');
|
||||||
|
|
||||||
|
common.skipIfEslintMissing();
|
||||||
|
|
||||||
|
const RuleTester = require('../../tools/node_modules/eslint').RuleTester;
|
||||||
|
const rule = require('../../tools/eslint-rules/prefer-primordials');
|
||||||
|
|
||||||
|
new RuleTester({
|
||||||
|
parserOptions: { ecmaVersion: 6 },
|
||||||
|
env: { es6: true }
|
||||||
|
})
|
||||||
|
.run('prefer-primordials', rule, {
|
||||||
|
valid: [
|
||||||
|
'new Array()',
|
||||||
|
'JSON.stringify({})',
|
||||||
|
'class A { *[Symbol.iterator] () { yield "a"; } }',
|
||||||
|
'const a = { *[Symbol.iterator] () { yield "a"; } }',
|
||||||
|
'Object.defineProperty(o, Symbol.toStringTag, { value: "o" })',
|
||||||
|
'parseInt("10")',
|
||||||
|
`
|
||||||
|
const { Reflect } = primordials;
|
||||||
|
module.exports = function() {
|
||||||
|
const { ownKeys } = Reflect;
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
{
|
||||||
|
code: 'const { Array } = primordials; new Array()',
|
||||||
|
options: [{ name: 'Array' }]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: 'const { JSONStringify } = primordials; JSONStringify({})',
|
||||||
|
options: [{ name: 'JSON' }]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: 'const { SymbolFor } = primordials; SymbolFor("xxx")',
|
||||||
|
options: [{ name: 'Symbol' }]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: `
|
||||||
|
const { SymbolIterator } = primordials;
|
||||||
|
class A { *[SymbolIterator] () { yield "a"; } }
|
||||||
|
`,
|
||||||
|
options: [{ name: 'Symbol' }]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: `
|
||||||
|
const { Symbol } = primordials;
|
||||||
|
const a = { *[Symbol.iterator] () { yield "a"; } }
|
||||||
|
`,
|
||||||
|
options: [{ name: 'Symbol', ignore: ['iterator'] }]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: `
|
||||||
|
const { ObjectDefineProperty, Symbol } = primordials;
|
||||||
|
ObjectDefineProperty(o, Symbol.toStringTag, { value: "o" })
|
||||||
|
`,
|
||||||
|
options: [{ name: 'Symbol', ignore: ['toStringTag'] }]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: 'const { Symbol } = primordials; Symbol.for("xxx")',
|
||||||
|
options: [{ name: 'Symbol', ignore: ['for'] }]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: 'const { NumberParseInt } = primordials; NumberParseInt("xxx")',
|
||||||
|
options: [{ name: 'parseInt' }]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: `
|
||||||
|
const { ReflectOwnKeys } = primordials;
|
||||||
|
module.exports = function() {
|
||||||
|
ReflectOwnKeys({})
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
options: [{ name: 'Reflect' }],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
invalid: [
|
||||||
|
{
|
||||||
|
code: 'new Array()',
|
||||||
|
options: [{ name: 'Array' }],
|
||||||
|
errors: [{ message: /const { Array } = primordials/ }]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: 'JSON.parse("{}")',
|
||||||
|
options: [{ name: 'JSON' }],
|
||||||
|
errors: [
|
||||||
|
{ message: /const { JSONParse } = primordials/ },
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: 'const { JSON } = primordials; JSON.parse("{}")',
|
||||||
|
options: [{ name: 'JSON' }],
|
||||||
|
errors: [{ message: /const { JSONParse } = primordials/ }]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: 'Symbol.for("xxx")',
|
||||||
|
options: [{ name: 'Symbol' }],
|
||||||
|
errors: [
|
||||||
|
{ message: /const { SymbolFor } = primordials/ },
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: 'const { Symbol } = primordials; Symbol.for("xxx")',
|
||||||
|
options: [{ name: 'Symbol' }],
|
||||||
|
errors: [{ message: /const { SymbolFor } = primordials/ }]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: `
|
||||||
|
const { Symbol } = primordials;
|
||||||
|
class A { *[Symbol.iterator] () { yield "a"; } }
|
||||||
|
`,
|
||||||
|
options: [{ name: 'Symbol' }],
|
||||||
|
errors: [{ message: /const { SymbolIterator } = primordials/ }]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: `
|
||||||
|
const { Symbol } = primordials;
|
||||||
|
const a = { *[Symbol.iterator] () { yield "a"; } }
|
||||||
|
`,
|
||||||
|
options: [{ name: 'Symbol' }],
|
||||||
|
errors: [{ message: /const { SymbolIterator } = primordials/ }]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: `
|
||||||
|
const { ObjectDefineProperty, Symbol } = primordials;
|
||||||
|
ObjectDefineProperty(o, Symbol.toStringTag, { value: "o" })
|
||||||
|
`,
|
||||||
|
options: [{ name: 'Symbol' }],
|
||||||
|
errors: [{ message: /const { SymbolToStringTag } = primordials/ }]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: `
|
||||||
|
const { Number } = primordials;
|
||||||
|
Number.parseInt('10')
|
||||||
|
`,
|
||||||
|
options: [{ name: 'Number', into: Number }],
|
||||||
|
errors: [{ message: /const { NumberParseInt } = primordials/ }]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: 'parseInt("10")',
|
||||||
|
options: [{ name: 'parseInt', into: 'Number' }],
|
||||||
|
errors: [{ message: /const { NumberParseInt } = primordials/ }]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: `
|
||||||
|
module.exports = function() {
|
||||||
|
const { ownKeys } = Reflect;
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
options: [{ name: 'Reflect' }],
|
||||||
|
errors: [{ message: /const { ReflectOwnKeys } = primordials/ }]
|
||||||
|
},
|
||||||
|
]
|
||||||
|
});
|
156
tools/eslint-rules/prefer-primordials.js
Normal file
156
tools/eslint-rules/prefer-primordials.js
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
/**
|
||||||
|
* @fileoverview We shouldn't use global built-in object for security and
|
||||||
|
* performance reason. This linter rule reports replacable codes
|
||||||
|
* that can be replaced with primordials.
|
||||||
|
* @author Leko <leko.noor@gmail.com>
|
||||||
|
*/
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Rule Definition
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
function toPrimordialsName(obj, prop) {
|
||||||
|
return obj + toUcFirst(prop);
|
||||||
|
}
|
||||||
|
|
||||||
|
function toUcFirst(str) {
|
||||||
|
return str[0].toUpperCase() + str.slice(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
function isTarget(map, varName) {
|
||||||
|
return map.has(varName);
|
||||||
|
}
|
||||||
|
|
||||||
|
function isIgnored(map, varName, propName) {
|
||||||
|
if (!map.has(varName) || !map.get(varName).has(propName)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return map.get(varName).get(propName).ignored;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getReportName({ name, parentName, into }) {
|
||||||
|
if (into) {
|
||||||
|
return toPrimordialsName(into, name);
|
||||||
|
}
|
||||||
|
if (parentName) {
|
||||||
|
return toPrimordialsName(parentName, name);
|
||||||
|
}
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get identifier of object spread assignment
|
||||||
|
*
|
||||||
|
* code: 'const { ownKeys } = Reflect;'
|
||||||
|
* argument: 'ownKeys'
|
||||||
|
* return: 'Reflect'
|
||||||
|
*/
|
||||||
|
function getDestructuringAssignmentParent(scope, node) {
|
||||||
|
const declaration = scope.set.get(node.name);
|
||||||
|
if (
|
||||||
|
!declaration ||
|
||||||
|
!declaration.defs ||
|
||||||
|
declaration.defs.length === 0 ||
|
||||||
|
declaration.defs[0].type !== 'Variable' ||
|
||||||
|
!declaration.defs[0].node.init
|
||||||
|
) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return declaration.defs[0].node.init.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
const identifierSelector =
|
||||||
|
'[type!=VariableDeclarator][type!=MemberExpression]>Identifier';
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
meta: {
|
||||||
|
messages: {
|
||||||
|
error: 'Use `const { {{name}} } = primordials;` instead of the global.'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
create(context) {
|
||||||
|
const globalScope = context.getSourceCode().scopeManager.globalScope;
|
||||||
|
const nameMap = context.options.reduce((acc, option) =>
|
||||||
|
acc.set(
|
||||||
|
option.name,
|
||||||
|
(option.ignore || [])
|
||||||
|
.concat(['prototype'])
|
||||||
|
.reduce((acc, name) => acc.set(name, {
|
||||||
|
ignored: true
|
||||||
|
}), new Map())
|
||||||
|
)
|
||||||
|
, new Map());
|
||||||
|
const renameMap = context.options
|
||||||
|
.filter((option) => option.into)
|
||||||
|
.reduce((acc, option) =>
|
||||||
|
acc.set(option.name, option.into)
|
||||||
|
, new Map());
|
||||||
|
let reported;
|
||||||
|
|
||||||
|
return {
|
||||||
|
Program() {
|
||||||
|
reported = new Map();
|
||||||
|
},
|
||||||
|
[identifierSelector](node) {
|
||||||
|
if (reported.has(node.range[0])) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const name = node.name;
|
||||||
|
const parentName = getDestructuringAssignmentParent(
|
||||||
|
context.getScope(),
|
||||||
|
node
|
||||||
|
);
|
||||||
|
if (!isTarget(nameMap, name) && !isTarget(nameMap, parentName)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const defs = (globalScope.set.get(name) || {}).defs || null;
|
||||||
|
if (parentName && isTarget(nameMap, parentName)) {
|
||||||
|
if (!defs || defs[0].name.name !== 'primordials') {
|
||||||
|
reported.set(node.range[0], true);
|
||||||
|
const into = renameMap.get(name);
|
||||||
|
context.report({
|
||||||
|
node,
|
||||||
|
messageId: 'error',
|
||||||
|
data: {
|
||||||
|
name: getReportName({ into, parentName, name })
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (defs.length === 0 || defs[0].node.init.name !== 'primordials') {
|
||||||
|
reported.set(node.range[0], true);
|
||||||
|
const into = renameMap.get(name);
|
||||||
|
context.report({
|
||||||
|
node,
|
||||||
|
messageId: 'error',
|
||||||
|
data: {
|
||||||
|
name: getReportName({ into, parentName, name })
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
MemberExpression(node) {
|
||||||
|
const obj = node.object.name;
|
||||||
|
const prop = node.property.name;
|
||||||
|
if (!prop || !isTarget(nameMap, obj) || isIgnored(nameMap, obj, prop)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const variables =
|
||||||
|
context.getSourceCode().scopeManager.getDeclaredVariables(node);
|
||||||
|
if (variables.length === 0) {
|
||||||
|
context.report({
|
||||||
|
node,
|
||||||
|
messageId: 'error',
|
||||||
|
data: {
|
||||||
|
name: toPrimordialsName(obj, prop),
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
Loading…
x
Reference in New Issue
Block a user