Skip to content

Commit

Permalink
src: add kNoBrowserGlobals flag for Environment
Browse files Browse the repository at this point in the history
PR-URL: #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>
  • Loading branch information
zcbenz committed Jan 5, 2022
1 parent f34c0e0 commit a706342
Show file tree
Hide file tree
Showing 9 changed files with 185 additions and 142 deletions.
3 changes: 2 additions & 1 deletion configure.py
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
118 changes: 118 additions & 0 deletions lib/internal/bootstrap/browser.js
@@ -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,
});
}
153 changes: 16 additions & 137 deletions lib/internal/bootstrap/node.js
Expand Up @@ -56,7 +56,11 @@ const {
} = primordials;
const config = internalBinding('config');
const internalTimers = require('internal/timers');
const { deprecate, lazyDOMExceptionClass } = require('internal/util');
const {
defineOperation,
deprecate,
exposeInterface,
} = require('internal/util');

setupProcessObject();

Expand Down Expand Up @@ -205,79 +209,20 @@ const {
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);
});
// Non-standard extensions:
const { BroadcastChannel } = require('internal/worker/io');
exposeInterface(globalThis, 'BroadcastChannel', BroadcastChannel);

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);
defineOperation(globalThis, 'queueMicrotask', queueMicrotask);

const {
AbortController,
AbortSignal,
} = require('internal/abort_controller');
exposeInterface(globalThis, 'AbortController', AbortController);
exposeInterface(globalThis, 'AbortSignal', AbortSignal);
const timers = require('timers');
defineOperation(globalThis, 'clearImmediate', timers.clearImmediate);
defineOperation(globalThis, 'setImmediate', timers.setImmediate);

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);
}
const {
structuredClone,
} = require('internal/structured_clone');
defineOperation(globalThis, 'structuredClone', structuredClone);

// Set the per-Environment callback that will be called
// when the TrackingTraceStateObserver updates trace state.
Expand Down Expand Up @@ -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,
});
}
22 changes: 22 additions & 0 deletions lib/internal/util.js
Expand Up @@ -466,6 +466,26 @@ function createDeferredPromise() {
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;
const lazyDOMExceptionClass = () => {
_DOMException ??= internalBinding('messaging').DOMException;
Expand All @@ -484,8 +504,10 @@ module.exports = {
createClassWrapper,
createDeferredPromise,
decorateErrorStack,
defineOperation,
deprecate,
emitExperimentalWarning,
exposeInterface,
filterDuplicateStrings,
getConstructorOf,
getSystemErrorMap,
Expand Down
9 changes: 9 additions & 0 deletions src/env-inl.h
Expand Up @@ -882,6 +882,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
Expand Up @@ -1212,6 +1212,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

0 comments on commit a706342

Please sign in to comment.