From b3e22e16120af8341f0605d0e0104e10ca775577 Mon Sep 17 00:00:00 2001 From: Antoine du Hamel Date: Sat, 7 Nov 2020 17:23:14 +0100 Subject: [PATCH] lib,tools: enforce access to prototype from primordials PR-URL: https://github.com/nodejs/node/pull/36025 Reviewed-By: Shingo Inoue Reviewed-By: Rich Trott --- lib/internal/freeze_intrinsics.js | 138 +++++++++++------- lib/internal/process/warning.js | 7 +- .../test-eslint-prefer-primordials.js | 8 + tools/eslint-rules/prefer-primordials.js | 1 - 4 files changed, 100 insertions(+), 54 deletions(-) diff --git a/lib/internal/freeze_intrinsics.js b/lib/internal/freeze_intrinsics.js index 5e99af2d9ad0bb..50ae655206479a 100644 --- a/lib/internal/freeze_intrinsics.js +++ b/lib/internal/freeze_intrinsics.js @@ -25,25 +25,42 @@ const { Array, ArrayBuffer, + ArrayBufferPrototype, + ArrayPrototype, ArrayPrototypeForEach, + ArrayPrototypePush, BigInt, BigInt64Array, + BigInt64ArrayPrototype, + BigIntPrototype, BigUint64Array, + BigUint64ArrayPrototype, Boolean, + BooleanPrototype, DataView, + DataViewPrototype, Date, + DatePrototype, Error, + ErrorPrototype, EvalError, + EvalErrorPrototype, Float32Array, + Float32ArrayPrototype, Float64Array, + Float64ArrayPrototype, Function, + FunctionPrototype, Int16Array, + Int16ArrayPrototype, Int32Array, + Int32ArrayPrototype, Int8Array, - JSON, + Int8ArrayPrototype, Map, - Math, + MapPrototype, Number, + NumberPrototype, Object, ObjectDefineProperty, ObjectFreeze, @@ -52,28 +69,44 @@ const { ObjectGetOwnPropertyNames, ObjectGetOwnPropertySymbols, ObjectGetPrototypeOf, + ObjectPrototype, ObjectPrototypeHasOwnProperty, Promise, + PromisePrototype, RangeError, + RangeErrorPrototype, ReferenceError, - Reflect, + ReferenceErrorPrototype, ReflectOwnKeys, RegExp, + RegExpPrototype, + SafeSet, Set, + SetPrototype, String, + StringPrototype, Symbol, SymbolIterator, SyntaxError, + SyntaxErrorPrototype, TypeError, + TypeErrorPrototype, TypedArray, TypedArrayPrototype, Uint16Array, + Uint16ArrayPrototype, Uint32Array, + Uint32ArrayPrototype, Uint8Array, + Uint8ArrayPrototype, Uint8ClampedArray, + Uint8ClampedArrayPrototype, URIError, + URIErrorPrototype, WeakMap, + WeakMapPrototype, WeakSet, + WeakSetPrototype, } = primordials; module.exports = function() { @@ -110,55 +143,55 @@ module.exports = function() { TypedArrayPrototype, // 19 Fundamental Objects - Object.prototype, // 19.1 - Function.prototype, // 19.2 - Boolean.prototype, // 19.3 - - Error.prototype, // 19.5 - EvalError.prototype, - RangeError.prototype, - ReferenceError.prototype, - SyntaxError.prototype, - TypeError.prototype, - URIError.prototype, + ObjectPrototype, // 19.1 + FunctionPrototype, // 19.2 + BooleanPrototype, // 19.3 + + ErrorPrototype, // 19.5 + EvalErrorPrototype, + RangeErrorPrototype, + ReferenceErrorPrototype, + SyntaxErrorPrototype, + TypeErrorPrototype, + URIErrorPrototype, // 20 Numbers and Dates - Number.prototype, // 20.1 - Date.prototype, // 20.3 + NumberPrototype, // 20.1 + DatePrototype, // 20.3 // 21 Text Processing - String.prototype, // 21.1 - RegExp.prototype, // 21.2 + StringPrototype, // 21.1 + RegExpPrototype, // 21.2 // 22 Indexed Collections - Array.prototype, // 22.1 - - Int8Array.prototype, - Uint8Array.prototype, - Uint8ClampedArray.prototype, - Int16Array.prototype, - Uint16Array.prototype, - Int32Array.prototype, - Uint32Array.prototype, - Float32Array.prototype, - Float64Array.prototype, - BigInt64Array.prototype, - BigUint64Array.prototype, + ArrayPrototype, // 22.1 + + Int8ArrayPrototype, + Uint8ArrayPrototype, + Uint8ClampedArrayPrototype, + Int16ArrayPrototype, + Uint16ArrayPrototype, + Int32ArrayPrototype, + Uint32ArrayPrototype, + Float32ArrayPrototype, + Float64ArrayPrototype, + BigInt64ArrayPrototype, + BigUint64ArrayPrototype, // 23 Keyed Collections - Map.prototype, // 23.1 - Set.prototype, // 23.2 - WeakMap.prototype, // 23.3 - WeakSet.prototype, // 23.4 + MapPrototype, // 23.1 + SetPrototype, // 23.2 + WeakMapPrototype, // 23.3 + WeakSetPrototype, // 23.4 // 24 Structured Data - ArrayBuffer.prototype, // 24.1 - DataView.prototype, // 24.3 - Promise.prototype, // 25.4 + ArrayBufferPrototype, // 24.1 + DataViewPrototype, // 24.3 + PromisePrototype, // 25.4 // Other APIs / Web Compatibility console.Console.prototype, - BigInt.prototype, + BigIntPrototype, WebAssembly.Module.prototype, WebAssembly.Instance.prototype, WebAssembly.Table.prototype, @@ -171,7 +204,7 @@ module.exports = function() { const intrinsics = [ // Anonymous Intrinsics // ThrowTypeError - ObjectGetOwnPropertyDescriptor(Function.prototype, 'caller').get, + ObjectGetOwnPropertyDescriptor(FunctionPrototype, 'caller').get, // IteratorPrototype ObjectGetPrototypeOf( ObjectGetPrototypeOf(new Array()[SymbolIterator]()) @@ -224,6 +257,7 @@ module.exports = function() { // 20 Numbers and Dates Number, // 20.1 + // eslint-disable-next-line node-core/prefer-primordials Math, // 20.2 Date, // 20.3 @@ -255,10 +289,12 @@ module.exports = function() { // 24 Structured Data ArrayBuffer, // 24.1 DataView, // 24.3 + // eslint-disable-next-line node-core/prefer-primordials JSON, // 24.5 Promise, // 25.4 // 26 Reflection + // eslint-disable-next-line node-core/prefer-primordials Reflect, // 26.1 Proxy, // 26.2 @@ -281,19 +317,21 @@ module.exports = function() { ]; if (typeof Intl !== 'undefined') { - intrinsicPrototypes.push(Intl.Collator.prototype); - intrinsicPrototypes.push(Intl.DateTimeFormat.prototype); - intrinsicPrototypes.push(Intl.ListFormat.prototype); - intrinsicPrototypes.push(Intl.NumberFormat.prototype); - intrinsicPrototypes.push(Intl.PluralRules.prototype); - intrinsicPrototypes.push(Intl.RelativeTimeFormat.prototype); - intrinsics.push(Intl); + ArrayPrototypePush(intrinsicPrototypes, + Intl.Collator.prototype, + Intl.DateTimeFormat.prototype, + Intl.ListFormat.prototype, + Intl.NumberFormat.prototype, + Intl.PluralRules.prototype, + Intl.RelativeTimeFormat.prototype, + ); + ArrayPrototypePush(intrinsics, Intl); } - intrinsicPrototypes.forEach(enableDerivedOverrides); + ArrayPrototypeForEach(intrinsicPrototypes, enableDerivedOverrides); const frozenSet = new WeakSet(); - intrinsics.forEach(deepFreeze); + ArrayPrototypeForEach(intrinsics, deepFreeze); // Objects that are deeply frozen. function deepFreeze(root) { @@ -306,7 +344,7 @@ module.exports = function() { */ function innerDeepFreeze(node) { // Objects that we have frozen in this round. - const freezingSet = new Set(); + const freezingSet = new SafeSet(); // If val is something we should be freezing but aren't yet, // add it to freezingSet. diff --git a/lib/internal/process/warning.js b/lib/internal/process/warning.js index ffea12cd81d04c..f0eec72ae4bd20 100644 --- a/lib/internal/process/warning.js +++ b/lib/internal/process/warning.js @@ -3,6 +3,7 @@ const { ArrayIsArray, Error, + ErrorPrototypeToString, ErrorCaptureStackTrace, String, } = primordials; @@ -81,10 +82,10 @@ function onWarning(warning) { if (trace && warning.stack) { msg += `${warning.stack}`; } else { - const toString = + msg += typeof warning.toString === 'function' ? - warning.toString : Error.prototype.toString; - msg += `${toString.apply(warning)}`; + `${warning.toString()}` : + ErrorPrototypeToString(warning); } if (typeof warning.detail === 'string') { msg += `\n${warning.detail}`; diff --git a/test/parallel/test-eslint-prefer-primordials.js b/test/parallel/test-eslint-prefer-primordials.js index 6a28f541e4de84..2d04f9a1081c56 100644 --- a/test/parallel/test-eslint-prefer-primordials.js +++ b/test/parallel/test-eslint-prefer-primordials.js @@ -163,5 +163,13 @@ new RuleTester({ options: [{ name: 'Map', into: 'Safe' }], errors: [{ message: /const { SafeMap } = primordials/ }] }, + { + code: ` + const { Function } = primordials; + const noop = Function.prototype; + `, + options: [{ name: 'Function' }], + errors: [{ message: /const { FunctionPrototype } = primordials/ }] + }, ] }); diff --git a/tools/eslint-rules/prefer-primordials.js b/tools/eslint-rules/prefer-primordials.js index ffbb1e6e308c95..51fb6ab8c2ad44 100644 --- a/tools/eslint-rules/prefer-primordials.js +++ b/tools/eslint-rules/prefer-primordials.js @@ -75,7 +75,6 @@ module.exports = { acc.set( option.name, (option.ignore || []) - .concat(['prototype']) .reduce((acc, name) => acc.set(name, { ignored: true }), new Map())