src: add kNoBrowserGlobals flag for Environment
PR-URL: https://github.com/nodejs/node/pull/40532 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Minwoo Jung <nodecorelab@gmail.com> Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
This commit is contained in:
parent
f34c0e0bc0
commit
a706342368
@ -703,7 +703,8 @@ parser.add_argument('--no-browser-globals',
|
|||||||
dest='no_browser_globals',
|
dest='no_browser_globals',
|
||||||
default=None,
|
default=None,
|
||||||
help='do not export browser globals like setTimeout, console, etc. ' +
|
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',
|
parser.add_argument('--without-inspector',
|
||||||
action='store_true',
|
action='store_true',
|
||||||
|
118
lib/internal/bootstrap/browser.js
Normal file
118
lib/internal/bootstrap/browser.js
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const {
|
||||||
|
ObjectDefineProperty,
|
||||||
|
globalThis,
|
||||||
|
} = primordials;
|
||||||
|
|
||||||
|
const {
|
||||||
|
defineOperation,
|
||||||
|
exposeInterface,
|
||||||
|
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);
|
||||||
|
|
||||||
|
// https://www.w3.org/TR/hr-time-2/#the-performance-attribute
|
||||||
|
defineReplacableAttribute(globalThis, 'performance',
|
||||||
|
require('perf_hooks').performance);
|
||||||
|
|
||||||
|
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
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function exposeGetterAndSetter(target, name, getter, setter = undefined) {
|
||||||
|
ObjectDefineProperty(target, name, {
|
||||||
|
enumerable: false,
|
||||||
|
configurable: true,
|
||||||
|
get: getter,
|
||||||
|
set: setter,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://heycam.github.io/webidl/#Replaceable
|
||||||
|
function defineReplacableAttribute(target, name, value) {
|
||||||
|
ObjectDefineProperty(target, name, {
|
||||||
|
writable: true,
|
||||||
|
enumerable: true,
|
||||||
|
configurable: true,
|
||||||
|
value,
|
||||||
|
});
|
||||||
|
}
|
@ -56,7 +56,11 @@ const {
|
|||||||
} = primordials;
|
} = primordials;
|
||||||
const config = internalBinding('config');
|
const config = internalBinding('config');
|
||||||
const internalTimers = require('internal/timers');
|
const internalTimers = require('internal/timers');
|
||||||
const { deprecate, lazyDOMExceptionClass } = require('internal/util');
|
const {
|
||||||
|
defineOperation,
|
||||||
|
deprecate,
|
||||||
|
exposeInterface,
|
||||||
|
} = require('internal/util');
|
||||||
|
|
||||||
setupProcessObject();
|
setupProcessObject();
|
||||||
|
|
||||||
@ -205,79 +209,20 @@ const {
|
|||||||
queueMicrotask
|
queueMicrotask
|
||||||
} = require('internal/process/task_queues');
|
} = require('internal/process/task_queues');
|
||||||
|
|
||||||
if (!config.noBrowserGlobals) {
|
// Non-standard extensions:
|
||||||
// Override global console from the one provided by the VM
|
const { BroadcastChannel } = require('internal/worker/io');
|
||||||
// to the one implemented by Node.js
|
exposeInterface(globalThis, 'BroadcastChannel', BroadcastChannel);
|
||||||
// https://console.spec.whatwg.org/#console-namespace
|
|
||||||
exposeNamespace(globalThis, 'console',
|
|
||||||
createGlobalConsole(globalThis.console));
|
|
||||||
|
|
||||||
const { URL, URLSearchParams } = require('internal/url');
|
defineOperation(globalThis, 'queueMicrotask', queueMicrotask);
|
||||||
// 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 {
|
const timers = require('timers');
|
||||||
TextEncoder, TextDecoder
|
defineOperation(globalThis, 'clearImmediate', timers.clearImmediate);
|
||||||
} = require('internal/encoding');
|
defineOperation(globalThis, 'setImmediate', timers.setImmediate);
|
||||||
// https://encoding.spec.whatwg.org/#textencoder
|
|
||||||
exposeInterface(globalThis, 'TextEncoder', TextEncoder);
|
|
||||||
// https://encoding.spec.whatwg.org/#textdecoder
|
|
||||||
exposeInterface(globalThis, 'TextDecoder', TextDecoder);
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
AbortController,
|
structuredClone,
|
||||||
AbortSignal,
|
} = require('internal/structured_clone');
|
||||||
} = require('internal/abort_controller');
|
defineOperation(globalThis, 'structuredClone', structuredClone);
|
||||||
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,
|
|
||||||
BroadcastChannel,
|
|
||||||
} = require('internal/worker/io');
|
|
||||||
exposeInterface(globalThis, 'MessageChannel', MessageChannel);
|
|
||||||
exposeInterface(globalThis, 'MessagePort', MessagePort);
|
|
||||||
exposeInterface(globalThis, 'MessageEvent', MessageEvent);
|
|
||||||
exposeInterface(globalThis, 'BroadcastChannel', BroadcastChannel);
|
|
||||||
|
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the per-Environment callback that will be called
|
// Set the per-Environment callback that will be called
|
||||||
// when the TrackingTraceStateObserver updates trace state.
|
// when the TrackingTraceStateObserver updates trace state.
|
||||||
@ -483,69 +428,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,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
@ -466,6 +466,26 @@ function createDeferredPromise() {
|
|||||||
return { promise, resolve, reject };
|
return { promise, resolve, reject };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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/#es-interfaces
|
||||||
|
function exposeInterface(target, name, interfaceObject) {
|
||||||
|
ObjectDefineProperty(target, name, {
|
||||||
|
writable: true,
|
||||||
|
enumerable: false,
|
||||||
|
configurable: true,
|
||||||
|
value: interfaceObject
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
let _DOMException;
|
let _DOMException;
|
||||||
const lazyDOMExceptionClass = () => {
|
const lazyDOMExceptionClass = () => {
|
||||||
_DOMException ??= internalBinding('messaging').DOMException;
|
_DOMException ??= internalBinding('messaging').DOMException;
|
||||||
@ -484,8 +504,10 @@ module.exports = {
|
|||||||
createClassWrapper,
|
createClassWrapper,
|
||||||
createDeferredPromise,
|
createDeferredPromise,
|
||||||
decorateErrorStack,
|
decorateErrorStack,
|
||||||
|
defineOperation,
|
||||||
deprecate,
|
deprecate,
|
||||||
emitExperimentalWarning,
|
emitExperimentalWarning,
|
||||||
|
exposeInterface,
|
||||||
filterDuplicateStrings,
|
filterDuplicateStrings,
|
||||||
getConstructorOf,
|
getConstructorOf,
|
||||||
getSystemErrorMap,
|
getSystemErrorMap,
|
||||||
|
@ -882,6 +882,15 @@ inline bool Environment::no_global_search_paths() const {
|
|||||||
!options_->global_search_paths;
|
!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 {
|
bool Environment::filehandle_close_warning() const {
|
||||||
return emit_filehandle_warning_;
|
return emit_filehandle_warning_;
|
||||||
}
|
}
|
||||||
|
@ -1212,6 +1212,7 @@ class Environment : public MemoryRetainer {
|
|||||||
inline bool tracks_unmanaged_fds() const;
|
inline bool tracks_unmanaged_fds() const;
|
||||||
inline bool hide_console_windows() const;
|
inline bool hide_console_windows() const;
|
||||||
inline bool no_global_search_paths() const;
|
inline bool no_global_search_paths() const;
|
||||||
|
inline bool no_browser_globals() const;
|
||||||
inline uint64_t thread_id() const;
|
inline uint64_t thread_id() const;
|
||||||
inline worker::Worker* worker_context() const;
|
inline worker::Worker* worker_context() const;
|
||||||
Environment* worker_parent_env() const;
|
Environment* worker_parent_env() const;
|
||||||
|
15
src/node.cc
15
src/node.cc
@ -360,7 +360,16 @@ MaybeLocal<Value> Environment::BootstrapNode() {
|
|||||||
this, "internal/bootstrap/node", &node_params, &node_args);
|
this, "internal/bootstrap/node", &node_params, &node_args);
|
||||||
|
|
||||||
if (result.IsEmpty()) {
|
if (result.IsEmpty()) {
|
||||||
return scope.EscapeMaybe(result);
|
return MaybeLocal<Value>();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!no_browser_globals()) {
|
||||||
|
result = ExecuteBootstrapper(
|
||||||
|
this, "internal/bootstrap/browser", &node_params, &node_args);
|
||||||
|
|
||||||
|
if (result.IsEmpty()) {
|
||||||
|
return MaybeLocal<Value>();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(joyeecheung): skip these in the snapshot building for workers.
|
// TODO(joyeecheung): skip these in the snapshot building for workers.
|
||||||
@ -371,7 +380,7 @@ MaybeLocal<Value> Environment::BootstrapNode() {
|
|||||||
ExecuteBootstrapper(this, thread_switch_id, &node_params, &node_args);
|
ExecuteBootstrapper(this, thread_switch_id, &node_params, &node_args);
|
||||||
|
|
||||||
if (result.IsEmpty()) {
|
if (result.IsEmpty()) {
|
||||||
return scope.EscapeMaybe(result);
|
return MaybeLocal<Value>();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto process_state_switch_id =
|
auto process_state_switch_id =
|
||||||
@ -382,7 +391,7 @@ MaybeLocal<Value> Environment::BootstrapNode() {
|
|||||||
this, process_state_switch_id, &node_params, &node_args);
|
this, process_state_switch_id, &node_params, &node_args);
|
||||||
|
|
||||||
if (result.IsEmpty()) {
|
if (result.IsEmpty()) {
|
||||||
return scope.EscapeMaybe(result);
|
return MaybeLocal<Value>();
|
||||||
}
|
}
|
||||||
|
|
||||||
Local<String> env_string = FIXED_ONE_BYTE_STRING(isolate_, "env");
|
Local<String> env_string = FIXED_ONE_BYTE_STRING(isolate_, "env");
|
||||||
|
@ -439,7 +439,9 @@ enum Flags : uint64_t {
|
|||||||
// $HOME/.node_modules and $NODE_PATH. This is used by standalone apps that
|
// $HOME/.node_modules and $NODE_PATH. This is used by standalone apps that
|
||||||
// do not expect to have their behaviors changed because of globally
|
// do not expect to have their behaviors changed because of globally
|
||||||
// installed modules.
|
// installed modules.
|
||||||
kNoGlobalSearchPaths = 1 << 7
|
kNoGlobalSearchPaths = 1 << 7,
|
||||||
|
// Do not export browser globals like setTimeout, console, etc.
|
||||||
|
kNoBrowserGlobals = 1 << 8,
|
||||||
};
|
};
|
||||||
} // namespace EnvironmentFlags
|
} // namespace EnvironmentFlags
|
||||||
|
|
||||||
|
@ -574,6 +574,8 @@ void Worker::New(const FunctionCallbackInfo<Value>& args) {
|
|||||||
worker->environment_flags_ |= EnvironmentFlags::kNoNativeAddons;
|
worker->environment_flags_ |= EnvironmentFlags::kNoNativeAddons;
|
||||||
if (env->no_global_search_paths())
|
if (env->no_global_search_paths())
|
||||||
worker->environment_flags_ |= EnvironmentFlags::kNoGlobalSearchPaths;
|
worker->environment_flags_ |= EnvironmentFlags::kNoGlobalSearchPaths;
|
||||||
|
if (env->no_browser_globals())
|
||||||
|
worker->environment_flags_ |= EnvironmentFlags::kNoBrowserGlobals;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Worker::StartThread(const FunctionCallbackInfo<Value>& args) {
|
void Worker::StartThread(const FunctionCallbackInfo<Value>& args) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user