From e3223edb890c4a4b6d06c85337f90b15b2db4262 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 Backport-PR-URL: https://github.com/nodejs/node/pull/39448 Reviewed-By: James M Snell Reviewed-By: Darshan Sen --- lib/.eslintrc.yaml | 53 ++++++++++++++++++++++++- lib/child_process.js | 1 + lib/internal/freeze_intrinsics.js | 11 ++++- 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 | 4 +- lib/internal/v8_prof_polyfill.js | 3 +- lib/internal/worker.js | 3 +- 11 files changed, 74 insertions(+), 9 deletions(-) diff --git a/lib/.eslintrc.yaml b/lib/.eslintrc.yaml index 0e6f84dc14754f..9a2e6f43ba410a 100644 --- a/lib/.eslintrc.yaml +++ b/lib/.eslintrc.yaml @@ -27,10 +27,58 @@ 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 @@ -73,6 +121,7 @@ rules: into: Number - name: parseInt into: Number + - name: Proxy - name: Promise - name: RangeError - name: ReferenceError diff --git a/lib/child_process.js b/lib/child_process.js index a9c44e12e87f11..7e3e5afe140478 100644 --- a/lib/child_process.js +++ b/lib/child_process.js @@ -43,6 +43,7 @@ let debug = require('internal/util/debuglog').debuglog( debug = fn; } ); +const { AbortController } = require('internal/abort_controller'); const { Buffer } = require('buffer'); const { Pipe, constants: PipeConstants } = internalBinding('pipe_wrap'); diff --git a/lib/internal/freeze_intrinsics.js b/lib/internal/freeze_intrinsics.js index 1e305cf6777b71..d4a72ccebabd55 100644 --- a/lib/internal/freeze_intrinsics.js +++ b/lib/internal/freeze_intrinsics.js @@ -19,7 +19,7 @@ // https://github.com/google/caja/blob/HEAD/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 { @@ -73,6 +73,7 @@ const { ObjectPrototypeHasOwnProperty, Promise, PromisePrototype, + Proxy, RangeError, RangeErrorPrototype, ReferenceError, @@ -111,8 +112,16 @@ const { decodeURIComponent, encodeURI, encodeURIComponent, + 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 18e619b4746824..407b0ee30b79b8 100644 --- a/lib/internal/http2/compat.js +++ b/lib/internal/http2/compat.js @@ -7,6 +7,7 @@ const { ObjectCreate, ObjectKeys, ObjectPrototypeHasOwnProperty, + Proxy, ReflectGetPrototypeOf, Symbol, } = primordials; diff --git a/lib/internal/http2/core.js b/lib/internal/http2/core.js index 5e930ad216a1f5..91f4e143b4c77e 100644 --- a/lib/internal/http2/core.js +++ b/lib/internal/http2/core.js @@ -12,6 +12,7 @@ const { ObjectDefineProperty, ObjectPrototypeHasOwnProperty, Promise, + Proxy, ReflectApply, ReflectGet, ReflectGetPrototypeOf, diff --git a/lib/internal/main/worker_thread.js b/lib/internal/main/worker_thread.js index 3528ebccfdba35..e6bc341c33e35d 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 237ff8dd27599f..4ff756a0ab5c3f 100644 --- a/lib/internal/modules/cjs/loader.js +++ b/lib/internal/modules/cjs/loader.js @@ -44,6 +44,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 66636d9ce092b5..0a43113a065bdf 100644 --- a/lib/internal/modules/esm/translators.js +++ b/lib/internal/modules/esm/translators.js @@ -1,7 +1,5 @@ 'use strict'; -/* global WebAssembly */ - const { ArrayPrototypeMap, Boolean, @@ -19,6 +17,7 @@ const { StringPrototypeSplit, StringPrototypeStartsWith, SyntaxErrorPrototype, + globalThis: { WebAssembly }, } = primordials; let _TYPES = null; @@ -61,6 +60,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 c80f22be331109..a4ea444ef7d832 100644 --- a/lib/internal/per_context/primordials.js +++ b/lib/internal/per_context/primordials.js @@ -173,6 +173,7 @@ primordials.SafeWeakSet = makeSafe( // Create copies of configurable value properties of the global object [ + 'Proxy', 'globalThis', ].forEach((name) => { // eslint-disable-next-line no-restricted-globals @@ -193,7 +194,8 @@ primordials.SafeWeakSet = makeSafe( [ 'JSON', 'Math', - 'Reflect' + 'Proxy', + 'Reflect', ].forEach((name) => { // eslint-disable-next-line no-restricted-globals copyPropsRenamed(global[name], primordials, name); diff --git a/lib/internal/v8_prof_polyfill.js b/lib/internal/v8_prof_polyfill.js index ae98a03ab206d8..369da5f9a34741 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 = { // eslint-disable-line no-unused-vars system: function(name, args) { if (process.platform === 'linux' && name === 'nm') { diff --git a/lib/internal/worker.js b/lib/internal/worker.js index 0965c5690fd06b..73aa910b0b77ce 100644 --- a/lib/internal/worker.js +++ b/lib/internal/worker.js @@ -1,7 +1,5 @@ 'use strict'; -/* global SharedArrayBuffer */ - const { ArrayIsArray, ArrayPrototypeMap, @@ -20,6 +18,7 @@ const { SymbolFor, TypedArrayPrototypeFill, Uint32Array, + globalThis: { Atomics, SharedArrayBuffer }, } = primordials; const EventEmitter = require('events');