From c935b6a3c745f1cfe795f2f16499c1202ac7282a Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 18 Oct 2021 10:45:10 +0900 Subject: [PATCH] src: add kNoBrowserGlobals flag for Environment --- configure.py | 3 +- lib/internal/bootstrap/browser.js | 146 ++++++++++++++++++++++++++++++ lib/internal/bootstrap/node.js | 145 +---------------------------- src/env-inl.h | 9 ++ src/env.h | 1 + src/node.cc | 15 ++- src/node.h | 4 +- src/node_worker.cc | 2 + 8 files changed, 177 insertions(+), 148 deletions(-) create mode 100644 lib/internal/bootstrap/browser.js diff --git a/configure.py b/configure.py index a879a9661d65f7..2f200966851f6d 100755 --- a/configure.py +++ b/configure.py @@ -703,7 +703,8 @@ dest='no_browser_globals', default=None, help='do not export browser globals like setTimeout, console, etc. ' + - '(This mode is not officially supported for regular applications)') + '(This mode is deprecated and not officially supported for regular ' + + 'applications)') parser.add_argument('--without-inspector', action='store_true', diff --git a/lib/internal/bootstrap/browser.js b/lib/internal/bootstrap/browser.js new file mode 100644 index 00000000000000..15942de3f4c1e8 --- /dev/null +++ b/lib/internal/bootstrap/browser.js @@ -0,0 +1,146 @@ +'use strict'; + +const { + ObjectDefineProperty, + globalThis, +} = primordials; + +const { lazyDOMExceptionClass } = require('internal/util'); +const config = internalBinding('config'); + +// Override global console from the one provided by the VM +// to the one implemented by Node.js +// https://console.spec.whatwg.org/#console-namespace +exposeNamespace(globalThis, 'console', + createGlobalConsole(globalThis.console)); + +const { URL, URLSearchParams } = require('internal/url'); +// https://url.spec.whatwg.org/#url +exposeInterface(globalThis, 'URL', URL); +// https://url.spec.whatwg.org/#urlsearchparams +exposeInterface(globalThis, 'URLSearchParams', URLSearchParams); +exposeGetterAndSetter(globalThis, + 'DOMException', + lazyDOMExceptionClass, + (value) => { + exposeInterface(globalThis, 'DOMException', value); + }); + +const { + TextEncoder, TextDecoder +} = require('internal/encoding'); +// https://encoding.spec.whatwg.org/#textencoder +exposeInterface(globalThis, 'TextEncoder', TextEncoder); +// https://encoding.spec.whatwg.org/#textdecoder +exposeInterface(globalThis, 'TextDecoder', TextDecoder); + +const { + AbortController, + AbortSignal, +} = require('internal/abort_controller'); +exposeInterface(globalThis, 'AbortController', AbortController); +exposeInterface(globalThis, 'AbortSignal', AbortSignal); + +const { + EventTarget, + Event, +} = require('internal/event_target'); +exposeInterface(globalThis, 'EventTarget', EventTarget); +exposeInterface(globalThis, 'Event', Event); +const { + MessageChannel, + MessagePort, + MessageEvent, +} = require('internal/worker/io'); +exposeInterface(globalThis, 'MessageChannel', MessageChannel); +exposeInterface(globalThis, 'MessagePort', MessagePort); +exposeInterface(globalThis, 'MessageEvent', MessageEvent); + +// https://html.spec.whatwg.org/multipage/webappapis.html#windoworworkerglobalscope +const timers = require('timers'); +defineOperation(globalThis, 'clearInterval', timers.clearInterval); +defineOperation(globalThis, 'clearTimeout', timers.clearTimeout); +defineOperation(globalThis, 'setInterval', timers.setInterval); +defineOperation(globalThis, 'setTimeout', timers.setTimeout); + +const { queueMicrotask } = require('internal/process/task_queues'); +defineOperation(globalThis, 'queueMicrotask', queueMicrotask); + +// https://www.w3.org/TR/hr-time-2/#the-performance-attribute +defineReplacableAttribute(globalThis, 'performance', + require('perf_hooks').performance); + +// Non-standard extensions: +defineOperation(globalThis, 'clearImmediate', timers.clearImmediate); +defineOperation(globalThis, 'setImmediate', timers.setImmediate); + +const { + structuredClone, +} = require('internal/structured_clone'); +defineOperation(globalThis, 'structuredClone', structuredClone); + +function createGlobalConsole(consoleFromVM) { + const consoleFromNode = + require('internal/console/global'); + if (config.hasInspector) { + const inspector = require('internal/util/inspector'); + // This will be exposed by `require('inspector').console` later. + inspector.consoleFromVM = consoleFromVM; + // TODO(joyeecheung): postpone this until the first time inspector + // is activated. + inspector.wrapConsole(consoleFromNode, consoleFromVM); + const { setConsoleExtensionInstaller } = internalBinding('inspector'); + // Setup inspector command line API. + setConsoleExtensionInstaller(inspector.installConsoleExtensions); + } + return consoleFromNode; +} + +// https://heycam.github.io/webidl/#es-namespaces +function exposeNamespace(target, name, namespaceObject) { + ObjectDefineProperty(target, name, { + writable: true, + enumerable: false, + configurable: true, + value: namespaceObject + }); +} + +// https://heycam.github.io/webidl/#es-interfaces +function exposeInterface(target, name, interfaceObject) { + ObjectDefineProperty(target, name, { + writable: true, + enumerable: false, + configurable: true, + value: interfaceObject + }); +} + +function exposeGetterAndSetter(target, name, getter, setter = undefined) { + ObjectDefineProperty(target, name, { + enumerable: false, + configurable: true, + get: getter, + set: setter, + }); +} + +// https://heycam.github.io/webidl/#define-the-operations +function defineOperation(target, name, method) { + ObjectDefineProperty(target, name, { + writable: true, + enumerable: true, + configurable: true, + value: method + }); +} + +// https://heycam.github.io/webidl/#Replaceable +function defineReplacableAttribute(target, name, value) { + ObjectDefineProperty(target, name, { + writable: true, + enumerable: true, + configurable: true, + value, + }); +} diff --git a/lib/internal/bootstrap/node.js b/lib/internal/bootstrap/node.js index ae4eac502803e7..2e46630bdfb3cb 100644 --- a/lib/internal/bootstrap/node.js +++ b/lib/internal/bootstrap/node.js @@ -52,7 +52,7 @@ const { globalThis, } = primordials; const config = internalBinding('config'); -const { deprecate, lazyDOMExceptionClass } = require('internal/util'); +const { deprecate } = require('internal/util'); setupProcessObject(); @@ -184,82 +184,7 @@ if (credentials.implementsPosixCredentials) { const { nativeHooks } = require('internal/async_hooks'); internalBinding('async_wrap').setupHooks(nativeHooks); -const { - setupTaskQueue, - queueMicrotask -} = require('internal/process/task_queues'); - -if (!config.noBrowserGlobals) { - // Override global console from the one provided by the VM - // to the one implemented by Node.js - // https://console.spec.whatwg.org/#console-namespace - exposeNamespace(globalThis, 'console', - createGlobalConsole(globalThis.console)); - - const { URL, URLSearchParams } = require('internal/url'); - // https://url.spec.whatwg.org/#url - exposeInterface(globalThis, 'URL', URL); - // https://url.spec.whatwg.org/#urlsearchparams - exposeInterface(globalThis, 'URLSearchParams', URLSearchParams); - exposeGetterAndSetter(globalThis, - 'DOMException', - lazyDOMExceptionClass, - (value) => { - exposeInterface(globalThis, 'DOMException', value); - }); - - const { - TextEncoder, TextDecoder - } = require('internal/encoding'); - // https://encoding.spec.whatwg.org/#textencoder - exposeInterface(globalThis, 'TextEncoder', TextEncoder); - // https://encoding.spec.whatwg.org/#textdecoder - exposeInterface(globalThis, 'TextDecoder', TextDecoder); - - const { - AbortController, - AbortSignal, - } = require('internal/abort_controller'); - exposeInterface(globalThis, 'AbortController', AbortController); - exposeInterface(globalThis, 'AbortSignal', AbortSignal); - - const { - EventTarget, - Event, - } = require('internal/event_target'); - exposeInterface(globalThis, 'EventTarget', EventTarget); - exposeInterface(globalThis, 'Event', Event); - const { - MessageChannel, - MessagePort, - MessageEvent, - } = require('internal/worker/io'); - exposeInterface(globalThis, 'MessageChannel', MessageChannel); - exposeInterface(globalThis, 'MessagePort', MessagePort); - exposeInterface(globalThis, 'MessageEvent', MessageEvent); - - // https://html.spec.whatwg.org/multipage/webappapis.html#windoworworkerglobalscope - const timers = require('timers'); - defineOperation(globalThis, 'clearInterval', timers.clearInterval); - defineOperation(globalThis, 'clearTimeout', timers.clearTimeout); - defineOperation(globalThis, 'setInterval', timers.setInterval); - defineOperation(globalThis, 'setTimeout', timers.setTimeout); - - defineOperation(globalThis, 'queueMicrotask', queueMicrotask); - - // https://www.w3.org/TR/hr-time-2/#the-performance-attribute - defineReplacableAttribute(globalThis, 'performance', - require('perf_hooks').performance); - - // Non-standard extensions: - defineOperation(globalThis, 'clearImmediate', timers.clearImmediate); - defineOperation(globalThis, 'setImmediate', timers.setImmediate); - - const { - structuredClone, - } = require('internal/structured_clone'); - defineOperation(globalThis, 'structuredClone', structuredClone); -} +const { setupTaskQueue } = require('internal/process/task_queues'); // Set the per-Environment callback that will be called // when the TrackingTraceStateObserver updates trace state. @@ -456,69 +381,3 @@ function setupBuffer() { }, }); } - -function createGlobalConsole(consoleFromVM) { - const consoleFromNode = - require('internal/console/global'); - if (config.hasInspector) { - const inspector = require('internal/util/inspector'); - // This will be exposed by `require('inspector').console` later. - inspector.consoleFromVM = consoleFromVM; - // TODO(joyeecheung): postpone this until the first time inspector - // is activated. - inspector.wrapConsole(consoleFromNode, consoleFromVM); - const { setConsoleExtensionInstaller } = internalBinding('inspector'); - // Setup inspector command line API. - setConsoleExtensionInstaller(inspector.installConsoleExtensions); - } - return consoleFromNode; -} - -// https://heycam.github.io/webidl/#es-namespaces -function exposeNamespace(target, name, namespaceObject) { - ObjectDefineProperty(target, name, { - writable: true, - enumerable: false, - configurable: true, - value: namespaceObject - }); -} - -// https://heycam.github.io/webidl/#es-interfaces -function exposeInterface(target, name, interfaceObject) { - ObjectDefineProperty(target, name, { - writable: true, - enumerable: false, - configurable: true, - value: interfaceObject - }); -} - -function exposeGetterAndSetter(target, name, getter, setter = undefined) { - ObjectDefineProperty(target, name, { - enumerable: false, - configurable: true, - get: getter, - set: setter, - }); -} - -// https://heycam.github.io/webidl/#define-the-operations -function defineOperation(target, name, method) { - ObjectDefineProperty(target, name, { - writable: true, - enumerable: true, - configurable: true, - value: method - }); -} - -// https://heycam.github.io/webidl/#Replaceable -function defineReplacableAttribute(target, name, value) { - ObjectDefineProperty(target, name, { - writable: true, - enumerable: true, - configurable: true, - value, - }); -} diff --git a/src/env-inl.h b/src/env-inl.h index 1e85bc07a4cc29..14757419db00b2 100644 --- a/src/env-inl.h +++ b/src/env-inl.h @@ -892,6 +892,15 @@ inline bool Environment::no_global_search_paths() const { !options_->global_search_paths; } +inline bool Environment::no_browser_globals() const { + // configure --no-browser-globals +#ifdef NODE_NO_BROWSER_GLOBALS + return true; +#else + return flags_ & EnvironmentFlags::kNoBrowserGlobals; +#endif +} + bool Environment::filehandle_close_warning() const { return emit_filehandle_warning_; } diff --git a/src/env.h b/src/env.h index 0c3715151488f4..a9773c016ab3fd 100644 --- a/src/env.h +++ b/src/env.h @@ -1204,6 +1204,7 @@ class Environment : public MemoryRetainer { inline bool tracks_unmanaged_fds() const; inline bool hide_console_windows() const; inline bool no_global_search_paths() const; + inline bool no_browser_globals() const; inline uint64_t thread_id() const; inline worker::Worker* worker_context() const; Environment* worker_parent_env() const; diff --git a/src/node.cc b/src/node.cc index 0fa51b269764f4..cfd154ed15d277 100644 --- a/src/node.cc +++ b/src/node.cc @@ -360,7 +360,16 @@ MaybeLocal Environment::BootstrapNode() { this, "internal/bootstrap/node", &node_params, &node_args); if (result.IsEmpty()) { - return scope.EscapeMaybe(result); + return MaybeLocal(); + } + + if (!no_browser_globals()) { + result = ExecuteBootstrapper( + this, "internal/bootstrap/browser", &node_params, &node_args); + + if (result.IsEmpty()) { + return MaybeLocal(); + } } // TODO(joyeecheung): skip these in the snapshot building for workers. @@ -371,7 +380,7 @@ MaybeLocal Environment::BootstrapNode() { ExecuteBootstrapper(this, thread_switch_id, &node_params, &node_args); if (result.IsEmpty()) { - return scope.EscapeMaybe(result); + return MaybeLocal(); } auto process_state_switch_id = @@ -382,7 +391,7 @@ MaybeLocal Environment::BootstrapNode() { this, process_state_switch_id, &node_params, &node_args); if (result.IsEmpty()) { - return scope.EscapeMaybe(result); + return MaybeLocal(); } Local env_string = FIXED_ONE_BYTE_STRING(isolate_, "env"); diff --git a/src/node.h b/src/node.h index 8d9e9935258c35..1631fff20cf30c 100644 --- a/src/node.h +++ b/src/node.h @@ -439,7 +439,9 @@ enum Flags : uint64_t { // $HOME/.node_modules and $NODE_PATH. This is used by standalone apps that // do not expect to have their behaviors changed because of globally // installed modules. - kNoGlobalSearchPaths = 1 << 7 + kNoGlobalSearchPaths = 1 << 7, + // Do not export browser globals like setTimeout, console, etc. + kNoBrowserGlobals = 1 << 8, }; } // namespace EnvironmentFlags diff --git a/src/node_worker.cc b/src/node_worker.cc index 16b7be36f28431..afecfb7622e750 100644 --- a/src/node_worker.cc +++ b/src/node_worker.cc @@ -574,6 +574,8 @@ void Worker::New(const FunctionCallbackInfo& args) { worker->environment_flags_ |= EnvironmentFlags::kNoNativeAddons; if (env->no_global_search_paths()) worker->environment_flags_ |= EnvironmentFlags::kNoGlobalSearchPaths; + if (env->no_browser_globals()) + worker->environment_flags_ |= EnvironmentFlags::kNoBrowserGlobals; } void Worker::StartThread(const FunctionCallbackInfo& args) {