From 7919ced0c97e9a5b17e6042e0b57bc911d23583d Mon Sep 17 00:00:00 2001 From: Antoine du Hamel Date: Mon, 26 Apr 2021 18:03:54 +0200 Subject: [PATCH] lib: harden lint checks for globals PR-URL: https://github.com/nodejs/node/pull/38419 Reviewed-By: James M Snell Reviewed-By: Darshan Sen --- lib/.eslintrc.yaml | 54 ++++++++++++++++++++++++- lib/internal/blob.js | 2 + lib/internal/bootstrap/node.js | 1 + lib/internal/crypto/webcrypto.js | 2 +- lib/internal/freeze_intrinsics.js | 10 ++++- lib/internal/http2/compat.js | 1 + lib/internal/http2/core.js | 1 + lib/internal/main/worker_thread.js | 1 + lib/internal/modules/cjs/loader.js | 1 + lib/internal/modules/esm/translators.js | 4 +- lib/internal/per_context/primordials.js | 2 + lib/internal/v8_prof_polyfill.js | 3 +- lib/internal/worker.js | 3 +- lib/internal/worker/io.js | 1 + 14 files changed, 77 insertions(+), 9 deletions(-) diff --git a/lib/.eslintrc.yaml b/lib/.eslintrc.yaml index 9a0450449fbad2..38ca7683247b8c 100644 --- a/lib/.eslintrc.yaml +++ b/lib/.eslintrc.yaml @@ -27,16 +27,65 @@ rules: message: "Use 'overrideStackTrace' from 'lib/internal/errors.js' instead of 'Error.prepareStackTrace'." no-restricted-globals: - error - - name: globalThis - message: "Use `const { globalThis } = primordials;` instead of the global." + - name: AbortController + message: "Use `const { AbortController } = require('internal/abort_controller');` instead of the global." + - name: AbortSignal + message: "Use `const { AbortSignal } = require('internal/abort_controller');` instead of the global." + # Atomics is not available in primordials because it can be + # disabled with --no-harmony-atomics CLI flag. + - name: Atomics + message: "Use `const { Atomics } = globalThis;` instead of the global." + - name: Buffer + message: "Use `const { Buffer } = require('buffer');` instead of the global." + - name: Event + message: "Use `const { Event } = require('internal/event_target');` instead of the global." + - name: EventTarget + message: "Use `const { EventTarget } = require('internal/event_target');` instead of the global." + # Intl is not available in primordials because it can be + # disabled with --without-intl build flag. + - name: Intl + message: "Use `const { Intl } = globalThis;` instead of the global." + - name: MessageChannel + message: "Use `const { MessageChannel } = require('internal/worker/io');` instead of the global." + - name: MessageEvent + message: "Use `const { MessageEvent } = require('internal/worker/io');` instead of the global." + - name: MessagePort + message: "Use `const { MessagePort } = require('internal/worker/io');` instead of the global." + # SharedArrayBuffer is not available in primordials because it can be + # disabled with --no-harmony-sharedarraybuffer CLI flag. + - name: SharedArrayBuffer + message: "Use `const { SharedArrayBuffer } = globalThis;` instead of the global." + - name: TextDecoder + message: "Use `const { TextDecoder } = require('internal/encoding');` instead of the global." + - name: TextEncoder + message: "Use `const { TextEncoder } = require('internal/encoding');` instead of the global." + - name: URL + message: "Use `const { URL } = require('internal/url');` instead of the global." + - name: URLSearchParams + message: "Use `const { URLSearchParams } = require('internal/url');` instead of the global." + # WebAssembly is not available in primordials because it can be + # disabled with --jitless CLI flag. + - name: WebAssembly + message: "Use `const { WebAssembly } = globalThis;` instead of the global." + - name: atob + message: "Use `const { atob } = require('buffer');` instead of the global." + - name: btoa + message: "Use `const { btoa } = require('buffer');` instead of the global." - name: global message: "Use `const { globalThis } = primordials;` instead of `global`." + - name: globalThis + message: "Use `const { globalThis } = primordials;` instead of the global." + - name: performance + message: "Use `const { performance } = require('perf_hooks');` instead of the global." + - name: queueMicrotask + message: "Use `const { queueMicrotask } = require('internal/process/task_queues');` instead of the global." # Custom rules in tools/eslint-rules node-core/lowercase-name-for-primitive: error node-core/non-ascii-character: error node-core/no-array-destructuring: error node-core/prefer-primordials: - error + - name: AggregateError - name: Array - name: ArrayBuffer - name: BigInt @@ -76,6 +125,7 @@ rules: into: Number - name: parseInt into: Number + - name: Proxy - name: Promise - name: RangeError - name: ReferenceError diff --git a/lib/internal/blob.js b/lib/internal/blob.js index b767426dcb2b7d..927b9f54046bf2 100644 --- a/lib/internal/blob.js +++ b/lib/internal/blob.js @@ -20,6 +20,8 @@ const { FixedSizeBlobCopyJob, } = internalBinding('buffer'); +const { TextDecoder } = require('internal/encoding'); + const { JSTransferable, kClone, diff --git a/lib/internal/bootstrap/node.js b/lib/internal/bootstrap/node.js index 46e0e967f79991..0b6e4a6fa6bfe6 100644 --- a/lib/internal/bootstrap/node.js +++ b/lib/internal/bootstrap/node.js @@ -46,6 +46,7 @@ const { ObjectGetPrototypeOf, ObjectPreventExtensions, ObjectSetPrototypeOf, + Proxy, ReflectGet, ReflectSet, SymbolToStringTag, diff --git a/lib/internal/crypto/webcrypto.js b/lib/internal/crypto/webcrypto.js index 47c34b9ca0d665..b28ee9b8167be5 100644 --- a/lib/internal/crypto/webcrypto.js +++ b/lib/internal/crypto/webcrypto.js @@ -26,7 +26,7 @@ const { validateString, } = require('internal/validators'); -const { TextDecoder } = require('internal/encoding'); +const { TextDecoder, TextEncoder } = require('internal/encoding'); const { codes: { diff --git a/lib/internal/freeze_intrinsics.js b/lib/internal/freeze_intrinsics.js index ca73559c3eb0cf..9dd21af4025094 100644 --- a/lib/internal/freeze_intrinsics.js +++ b/lib/internal/freeze_intrinsics.js @@ -19,7 +19,7 @@ // https://github.com/google/caja/blob/master/src/com/google/caja/ses/repairES5.js // https://github.com/tc39/proposal-ses/blob/e5271cc42a257a05dcae2fd94713ed2f46c08620/shim/src/freeze.js -/* global WebAssembly, SharedArrayBuffer, console */ +/* global console */ 'use strict'; const { @@ -78,6 +78,7 @@ const { ObjectPrototypeHasOwnProperty, Promise, PromisePrototype, + Proxy, RangeError, RangeErrorPrototype, ReferenceError, @@ -124,6 +125,13 @@ const { globalThis, } = primordials; +const { + Atomics, + Intl, + SharedArrayBuffer, + WebAssembly +} = globalThis; + module.exports = function() { const { clearImmediate, diff --git a/lib/internal/http2/compat.js b/lib/internal/http2/compat.js index 4795e59581d993..a1ee6cdbbc7777 100644 --- a/lib/internal/http2/compat.js +++ b/lib/internal/http2/compat.js @@ -9,6 +9,7 @@ const { ObjectCreate, ObjectKeys, ObjectPrototypeHasOwnProperty, + Proxy, ReflectApply, ReflectGetPrototypeOf, StringPrototypeIncludes, diff --git a/lib/internal/http2/core.js b/lib/internal/http2/core.js index 5427f74a5f2b59..1654f2460cdd5a 100644 --- a/lib/internal/http2/core.js +++ b/lib/internal/http2/core.js @@ -18,6 +18,7 @@ const { ObjectPrototypeHasOwnProperty, Promise, PromisePrototypeCatch, + Proxy, ReflectApply, ReflectGet, ReflectGetPrototypeOf, diff --git a/lib/internal/main/worker_thread.js b/lib/internal/main/worker_thread.js index cd092381eaef73..e22fd17fa2d214 100644 --- a/lib/internal/main/worker_thread.js +++ b/lib/internal/main/worker_thread.js @@ -9,6 +9,7 @@ const { ArrayPrototypeSplice, ObjectDefineProperty, PromisePrototypeCatch, + globalThis: { Atomics }, } = primordials; const { diff --git a/lib/internal/modules/cjs/loader.js b/lib/internal/modules/cjs/loader.js index 61f6e9cb786e94..fbfc17ba6d1885 100644 --- a/lib/internal/modules/cjs/loader.js +++ b/lib/internal/modules/cjs/loader.js @@ -45,6 +45,7 @@ const { ObjectPrototype, ObjectPrototypeHasOwnProperty, ObjectSetPrototypeOf, + Proxy, ReflectApply, ReflectSet, RegExpPrototypeTest, diff --git a/lib/internal/modules/esm/translators.js b/lib/internal/modules/esm/translators.js index 43cc31c633c169..6d295089e42c70 100644 --- a/lib/internal/modules/esm/translators.js +++ b/lib/internal/modules/esm/translators.js @@ -1,7 +1,5 @@ 'use strict'; -/* global WebAssembly */ - const { ArrayPrototypeForEach, ArrayPrototypeMap, @@ -21,6 +19,7 @@ const { StringPrototypeSplit, StringPrototypeStartsWith, SyntaxErrorPrototype, + globalThis: { WebAssembly }, } = primordials; let _TYPES = null; @@ -63,6 +62,7 @@ const experimentalImportMetaResolve = getOptionValue('--experimental-import-meta-resolve'); const asyncESM = require('internal/process/esm_loader'); const { emitWarningSync } = require('internal/process/warning'); +const { TextDecoder } = require('internal/encoding'); let cjsParse; async function initCJSParse() { diff --git a/lib/internal/per_context/primordials.js b/lib/internal/per_context/primordials.js index f6832030381b6b..78f778b65703c5 100644 --- a/lib/internal/per_context/primordials.js +++ b/lib/internal/per_context/primordials.js @@ -137,6 +137,7 @@ function copyPrototype(src, dest, prefix) { // Create copies of configurable value properties of the global object [ + 'Proxy', 'globalThis', ].forEach((name) => { // eslint-disable-next-line no-restricted-globals @@ -157,6 +158,7 @@ function copyPrototype(src, dest, prefix) { [ 'JSON', 'Math', + 'Proxy', 'Reflect', ].forEach((name) => { // eslint-disable-next-line no-restricted-globals diff --git a/lib/internal/v8_prof_polyfill.js b/lib/internal/v8_prof_polyfill.js index 2b6b90c58d1147..21d9b932c10f4b 100644 --- a/lib/internal/v8_prof_polyfill.js +++ b/lib/internal/v8_prof_polyfill.js @@ -28,7 +28,7 @@ 'use strict'; /* eslint-disable node-core/prefer-primordials */ -/* global Buffer, console */ +/* global console */ module.exports = { versionCheck }; @@ -40,6 +40,7 @@ if (module.id === 'internal/v8_prof_polyfill') return; // Node polyfill const fs = require('fs'); const cp = require('child_process'); +const { Buffer } = require('buffer'); const os = { system: function(name, args) { if (process.platform === 'linux' && name === 'nm') { diff --git a/lib/internal/worker.js b/lib/internal/worker.js index 0d60235395d9c0..f1da0d4ded4cea 100644 --- a/lib/internal/worker.js +++ b/lib/internal/worker.js @@ -1,7 +1,5 @@ 'use strict'; -/* global SharedArrayBuffer */ - const { ArrayIsArray, ArrayPrototypeForEach, @@ -24,6 +22,7 @@ const { SymbolFor, TypedArrayPrototypeFill, Uint32Array, + globalThis: { Atomics, SharedArrayBuffer }, } = primordials; const EventEmitter = require('events'); diff --git a/lib/internal/worker/io.js b/lib/internal/worker/io.js index fdfbe10b5fefcf..adacdd913c6693 100644 --- a/lib/internal/worker/io.js +++ b/lib/internal/worker/io.js @@ -41,6 +41,7 @@ const { const { Readable, Writable } = require('stream'); const { Event, + EventTarget, NodeEventTarget, defineEventHandler, initNodeEventTarget,