Skip to content

Commit

Permalink
src: add kNoBrowserGlobals flag for Environment
Browse files Browse the repository at this point in the history
  • Loading branch information
zcbenz committed Oct 20, 2021
1 parent c0a7020 commit 51d469f
Show file tree
Hide file tree
Showing 8 changed files with 175 additions and 145 deletions.
3 changes: 2 additions & 1 deletion configure.py
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
147 changes: 147 additions & 0 deletions lib/internal/bootstrap/browser.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
'use strict';

const {
ObjectDefineProperty,
globalThis,
} = primordials;

const { reconnectZeroFillToggle } = require('internal/buffer');
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,
});
}
145 changes: 2 additions & 143 deletions lib/internal/bootstrap/node.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ const {
globalThis,
} = primordials;
const config = internalBinding('config');
const { deprecate, lazyDOMExceptionClass } = require('internal/util');
const { deprecate } = require('internal/util');

setupProcessObject();

Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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,
});
}
9 changes: 9 additions & 0 deletions src/env-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -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_;
}
Expand Down
1 change: 1 addition & 0 deletions src/env.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
9 changes: 9 additions & 0 deletions src/node.cc
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,15 @@ MaybeLocal<Value> Environment::BootstrapNode() {
return scope.EscapeMaybe(result);
}

if (!no_browser_globals()) {
result = ExecuteBootstrapper(
this, "internal/bootstrap/browser", &node_params, &node_args);

if (result.IsEmpty()) {
return scope.EscapeMaybe(result);
}
}

// TODO(joyeecheung): skip these in the snapshot building for workers.
auto thread_switch_id =
is_main_thread() ? "internal/bootstrap/switches/is_main_thread"
Expand Down
4 changes: 3 additions & 1 deletion src/node.h
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
2 changes: 2 additions & 0 deletions src/node_worker.cc
Original file line number Diff line number Diff line change
Expand Up @@ -574,6 +574,8 @@ void Worker::New(const FunctionCallbackInfo<Value>& 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<Value>& args) {
Expand Down

0 comments on commit 51d469f

Please sign in to comment.