Upload Kmake

This commit is contained in:
Gorochu
2026-05-26 23:36:42 -07:00
parent ba051b2f74
commit 555ec72358
41615 changed files with 13344630 additions and 1 deletions

View File

@ -0,0 +1,475 @@
// Hello, and welcome to hacking node.js!
//
// This file is invoked by `Realm::BootstrapRealm()` in `src/node_realm.cc`,
// and is responsible for setting up Node.js core before main scripts
// under `lib/internal/main/` are executed.
//
// By default, Node.js binaries come with an embedded V8 startup snapshot
// that is generated at build-time with a `node_mksnapshot` executable.
// The snapshot generation code can be found in `SnapshotBuilder::Generate()`
// from `src/node_snapshotable.cc`.
// This snapshot captures the V8 heap initialized by scripts under
// `lib/internal/bootstrap/`, including this file. When initializing the main
// thread, Node.js deserializes the heap from the snapshot, instead of actually
// running this script and others in `lib/internal/bootstrap/`. To disable this
// behavior, pass `--no-node-snapshot` when starting the process so that
// Node.js actually runs this script to initialize the heap.
//
// This script is expected not to perform any asynchronous operations itself
// when being executed - those should be done in either
// `lib/internal/process/pre_execution.js` or in main scripts. It should not
// query any run-time states (e.g. command line arguments, environment
// variables) when being executed - functions in this script that are invoked
// at a later time can, however, query those states lazily.
// The majority of the code here focuses on setting up the global object and
// the process object in a synchronous, environment-independent manner.
//
// Scripts run before this file:
// - `lib/internal/per_context/primordials.js`: this saves copies of JavaScript
// builtins that won't be affected by user land monkey-patching for internal
// modules to use.
// - `lib/internal/per_context/domexception.js`: implementation of the
// `DOMException` class.
// - `lib/internal/per_context/messageport.js`: JS-side components of the
// `MessagePort` implementation.
// - `lib/internal/bootstrap/realm.js`: this sets up internal binding and
// module loaders, including `process.binding()`, `process._linkedBinding()`,
// `internalBinding()` and `BuiltinModule`, and per-realm internal states
// and bindings, including `prepare_stack_trace_callback`.
//
// The initialization done in this script is included in both the main thread
// and the worker threads. After this, further initialization is done based
// on the configuration of the Node.js instance by executing the scripts in
// `lib/internal/bootstrap/switches/`.
//
// Then, depending on how the Node.js instance is launched, one of the main
// scripts in `lib/internal/main` will be selected by C++ to start the actual
// execution. They may run additional setups exported by
// `lib/internal/process/pre_execution.js` depending on the run-time states.
'use strict';
// This file is compiled as if it's wrapped in a function with arguments
// passed by `BuiltinLoader::CompileAndCall()`.
/* global process, require, internalBinding, primordials */
const {
FunctionPrototypeCall,
JSONParse,
Number,
NumberIsNaN,
ObjectDefineProperty,
ObjectFreeze,
ObjectGetPrototypeOf,
ObjectSetPrototypeOf,
SymbolToStringTag,
globalThis,
} = primordials;
const config = internalBinding('config');
const internalTimers = require('internal/timers');
const { defineOperation } = require('internal/util');
const {
validateInteger,
} = require('internal/validators');
const {
constants: {
kExitCode,
kExiting,
kHasExitCode,
},
privateSymbols: {
exit_info_private_symbol,
},
} = internalBinding('util');
setupProcessObject();
setupGlobalProxy();
setupBuffer();
process.domain = null;
// process._exiting and process.exitCode
{
const fields = process[exit_info_private_symbol];
ObjectDefineProperty(process, '_exiting', {
__proto__: null,
get() {
return fields[kExiting] === 1;
},
set(value) {
fields[kExiting] = value ? 1 : 0;
},
enumerable: true,
configurable: true,
});
ObjectDefineProperty(process, 'exitCode', {
__proto__: null,
get() {
return fields[kHasExitCode] ? fields[kExitCode] : undefined;
},
set(code) {
if (code !== null && code !== undefined) {
let value = code;
if (typeof code === 'string' && code !== '' &&
NumberIsNaN((value = Number(code)))) {
value = code;
}
validateInteger(value, 'code');
fields[kExitCode] = value;
fields[kHasExitCode] = 1;
} else {
fields[kHasExitCode] = 0;
}
},
enumerable: true,
configurable: false,
});
}
process._exiting = false;
// process.config is serialized config.gypi
const binding = internalBinding('builtins');
const processConfig = JSONParse(binding.config, (_key, value) => {
// The `reviver` argument of the JSONParse method will visit all the values of
// the parsed config, including the "root" object, so there is no need to
// explicitly freeze the config outside of this method
return ObjectFreeze(value);
});
ObjectDefineProperty(process, 'config', {
__proto__: null,
enumerable: true,
configurable: true,
value: processConfig,
});
require('internal/worker/js_transferable').setup();
// Bootstrappers for all threads, including worker threads and main thread
const perThreadSetup = require('internal/process/per_thread');
const rawMethods = internalBinding('process_methods');
// Set up methods on the process object for all threads
{
process.dlopen = rawMethods.dlopen;
process.uptime = rawMethods.uptime;
// TODO(joyeecheung): either remove them or make them public
process._getActiveRequests = rawMethods._getActiveRequests;
process._getActiveHandles = rawMethods._getActiveHandles;
process.getActiveResourcesInfo = rawMethods.getActiveResourcesInfo;
// TODO(joyeecheung): remove these
process.reallyExit = rawMethods.reallyExit;
process._kill = rawMethods._kill;
const wrapped = perThreadSetup.wrapProcessMethods(rawMethods);
process.loadEnvFile = wrapped.loadEnvFile;
process._rawDebug = wrapped._rawDebug;
process.cpuUsage = wrapped.cpuUsage;
process.threadCpuUsage = wrapped.threadCpuUsage;
process.resourceUsage = wrapped.resourceUsage;
process.memoryUsage = wrapped.memoryUsage;
process.constrainedMemory = rawMethods.constrainedMemory;
process.availableMemory = rawMethods.availableMemory;
process.kill = wrapped.kill;
process.exit = wrapped.exit;
process.execve = wrapped.execve;
process.ref = perThreadSetup.ref;
process.unref = perThreadSetup.unref;
let finalizationMod;
ObjectDefineProperty(process, 'finalization', {
__proto__: null,
get() {
if (finalizationMod !== undefined) {
return finalizationMod;
}
const { createFinalization } = require('internal/process/finalization');
finalizationMod = createFinalization();
return finalizationMod;
},
set(value) {
finalizationMod = value;
},
enumerable: true,
configurable: true,
});
process.hrtime = perThreadSetup.hrtime;
process.hrtime.bigint = perThreadSetup.hrtimeBigInt;
process.openStdin = function() {
process.stdin.resume();
return process.stdin;
};
}
const credentials = internalBinding('credentials');
if (credentials.implementsPosixCredentials) {
process.getuid = credentials.getuid;
process.geteuid = credentials.geteuid;
process.getgid = credentials.getgid;
process.getegid = credentials.getegid;
process.getgroups = credentials.getgroups;
}
// Setup the callbacks that node::AsyncWrap will call when there are hooks to
// process. They use the same functions as the JS embedder API. These callbacks
// are setup immediately to prevent async_wrap.setupHooks() from being hijacked
// and the cost of doing so is negligible.
const { nativeHooks } = require('internal/async_hooks');
internalBinding('async_wrap').setupHooks(nativeHooks);
const {
setupTaskQueue,
} = require('internal/process/task_queues');
const timers = require('timers');
// Non-standard extensions:
defineOperation(globalThis, 'clearImmediate', timers.clearImmediate);
defineOperation(globalThis, 'setImmediate', timers.setImmediate);
// Set the per-Environment callback that will be called
// when the TrackingTraceStateObserver updates trace state.
// Note that when NODE_USE_V8_PLATFORM is true, the observer is
// attached to the per-process TracingController.
const { setTraceCategoryStateUpdateHandler } = internalBinding('trace_events');
setTraceCategoryStateUpdateHandler(perThreadSetup.toggleTraceCategoryState);
// process.allowedNodeEnvironmentFlags
ObjectDefineProperty(process, 'allowedNodeEnvironmentFlags', {
__proto__: null,
get() {
const flags = perThreadSetup.buildAllowedFlags();
process.allowedNodeEnvironmentFlags = flags;
return process.allowedNodeEnvironmentFlags;
},
// If the user tries to set this to another value, override
// this completely to that value.
set(value) {
ObjectDefineProperty(this, 'allowedNodeEnvironmentFlags', {
__proto__: null,
value,
configurable: true,
enumerable: true,
writable: true,
});
},
enumerable: true,
configurable: true,
});
// TODO(joyeecheung): this property has not been well-maintained, should we
// deprecate it in favor of a better API?
const { isDebugBuild, hasOpenSSL, openSSLIsBoringSSL, hasInspector } = config;
const features = {
inspector: hasInspector,
debug: isDebugBuild,
uv: true,
ipv6: true, // TODO(bnoordhuis) ping libuv
tls_alpn: hasOpenSSL,
tls_sni: hasOpenSSL,
tls_ocsp: hasOpenSSL,
tls: hasOpenSSL,
openssl_is_boringssl: openSSLIsBoringSSL,
// This needs to be dynamic because --no-node-snapshot disables the
// code cache even if the binary is built with embedded code cache.
get cached_builtins() {
return binding.hasCachedBuiltins();
},
get require_module() {
return getOptionValue('--experimental-require-module');
},
};
ObjectDefineProperty(process, 'features', {
__proto__: null,
enumerable: true,
writable: false,
configurable: false,
value: features,
});
{
const {
onGlobalUncaughtException,
setUncaughtExceptionCaptureCallback,
hasUncaughtExceptionCaptureCallback,
} = require('internal/process/execution');
// For legacy reasons this is still called `_fatalException`, even
// though it is now a global uncaught exception handler.
// The C++ land node::errors::TriggerUncaughtException grabs it
// from the process object because it has been monkey-patchable.
// TODO(joyeecheung): investigate whether process._fatalException
// can be deprecated.
process._fatalException = onGlobalUncaughtException;
process.setUncaughtExceptionCaptureCallback =
setUncaughtExceptionCaptureCallback;
process.hasUncaughtExceptionCaptureCallback =
hasUncaughtExceptionCaptureCallback;
}
const { emitWarning, emitWarningSync } = require('internal/process/warning');
const { getOptionValue } = require('internal/options');
let kTypeStrippingMode = process.config.variables.node_use_amaro ? null : false;
// This must be a getter, as getOptionValue does not work
// before bootstrapping.
ObjectDefineProperty(process.features, 'typescript', {
__proto__: null,
get() {
if (kTypeStrippingMode === null) {
if (getOptionValue('--experimental-transform-types')) {
kTypeStrippingMode = 'transform';
} else if (getOptionValue('--experimental-strip-types')) {
kTypeStrippingMode = 'strip';
} else {
kTypeStrippingMode = false;
}
}
return kTypeStrippingMode;
},
configurable: true,
enumerable: true,
});
process.emitWarning = emitWarning;
internalBinding('process_methods').setEmitWarningSync(emitWarningSync);
// We initialize the tick callbacks and the timer callbacks last during
// bootstrap to make sure that any operation done before this are synchronous.
// If any ticks or timers are scheduled before this they are unlikely to work.
{
const { nextTick, runNextTicks } = setupTaskQueue();
process.nextTick = nextTick;
// Used to emulate a tick manually in the JS land.
// A better name for this function would be `runNextTicks` but
// it has been exposed to the process object so we keep this legacy name
// TODO(joyeecheung): either remove it or make it public
process._tickCallback = runNextTicks;
const { setupTimers } = internalBinding('timers');
const {
processImmediate,
processTimers,
} = internalTimers.getTimerCallbacks(runNextTicks);
// Sets two per-Environment callbacks that will be run from libuv:
// - processImmediate will be run in the callback of the per-Environment
// check handle.
// - processTimers will be run in the callback of the per-Environment timer.
setupTimers(processImmediate, processTimers);
// Note: only after this point are the timers effective
}
{
const {
getSourceMapsSupport,
setSourceMapsSupport,
maybeCacheGeneratedSourceMap,
} = require('internal/source_map/source_map_cache');
const {
setMaybeCacheGeneratedSourceMap,
} = internalBinding('errors');
ObjectDefineProperty(process, 'sourceMapsEnabled', {
__proto__: null,
enumerable: true,
configurable: true,
get() {
return getSourceMapsSupport().enabled;
},
});
process.setSourceMapsEnabled = function setSourceMapsEnabled(val) {
setSourceMapsSupport(val, {
__proto__: null,
// TODO(legendecas): In order to smoothly improve the source map support,
// skip source maps in node_modules and generated code with
// `process.setSourceMapsEnabled(true)` in a semver major version.
nodeModules: val,
generatedCode: val,
});
};
// The C++ land calls back to maybeCacheGeneratedSourceMap()
// when code is generated by user with eval() or new Function()
// to cache the source maps from the evaluated code, if any.
setMaybeCacheGeneratedSourceMap(maybeCacheGeneratedSourceMap);
}
{
const { getBuiltinModule } = require('internal/modules/helpers');
process.getBuiltinModule = getBuiltinModule;
}
function setupProcessObject() {
const EventEmitter = require('events');
const origProcProto = ObjectGetPrototypeOf(process);
ObjectSetPrototypeOf(origProcProto, EventEmitter.prototype);
FunctionPrototypeCall(EventEmitter, process);
ObjectDefineProperty(process, SymbolToStringTag, {
__proto__: null,
enumerable: false,
writable: true,
configurable: false,
value: 'process',
});
// Create global.process as getters so that we have a
// deprecation path for these in ES Modules.
// See https://github.com/nodejs/node/pull/26334.
let _process = process;
ObjectDefineProperty(globalThis, 'process', {
__proto__: null,
get() {
return _process;
},
set(value) {
_process = value;
},
enumerable: false,
configurable: true,
});
}
function setupGlobalProxy() {
ObjectDefineProperty(globalThis, SymbolToStringTag, {
__proto__: null,
value: 'global',
writable: false,
enumerable: false,
configurable: true,
});
globalThis.global = globalThis;
}
function setupBuffer() {
const {
Buffer,
} = require('buffer');
const bufferBinding = internalBinding('buffer');
// Only after this point can C++ use Buffer::New()
bufferBinding.setBufferPrototype(Buffer.prototype);
delete bufferBinding.setBufferPrototype;
// Create global.Buffer as getters so that we have a
// deprecation path for these in ES Modules.
// See https://github.com/nodejs/node/pull/26334.
let _Buffer = Buffer;
ObjectDefineProperty(globalThis, 'Buffer', {
__proto__: null,
get() {
return _Buffer;
},
set(value) {
_Buffer = value;
},
enumerable: false,
configurable: true,
});
}

View File

@ -0,0 +1,475 @@
// This file is executed in every realm that is created by Node.js, including
// the context of main thread, worker threads, and ShadowRealms.
// Only per-realm internal states and bindings should be bootstrapped in this
// file and no globals should be exposed to the user code.
//
// This file creates the internal module & binding loaders used by built-in
// modules. In contrast, user land modules are loaded using
// lib/internal/modules/cjs/loader.js (CommonJS Modules) or
// lib/internal/modules/esm/* (ES Modules).
//
// This file is compiled and run by node.cc before bootstrap/node.js
// was called, therefore the loaders are bootstrapped before we start to
// actually bootstrap Node.js. It creates the following objects:
//
// C++ binding loaders:
// - process.binding(): the legacy C++ binding loader, accessible from user land
// because it is an object attached to the global process object.
// These C++ bindings are created using NODE_BUILTIN_MODULE_CONTEXT_AWARE()
// and have their nm_flags set to NM_F_BUILTIN. We do not make any guarantees
// about the stability of these bindings, but still have to take care of
// compatibility issues caused by them from time to time.
// - process._linkedBinding(): intended to be used by embedders to add
// additional C++ bindings in their applications. These C++ bindings
// can be created using NODE_BINDING_CONTEXT_AWARE_CPP() with the flag
// NM_F_LINKED.
// - internalBinding(): the private internal C++ binding loader, inaccessible
// from user land unless through `require('internal/test/binding')`.
// These C++ bindings are created using NODE_BINDING_CONTEXT_AWARE_INTERNAL()
// and have their nm_flags set to NM_F_INTERNAL.
//
// Internal JavaScript module loader:
// - BuiltinModule: a minimal module system used to load the JavaScript core
// modules found in lib/**/*.js and deps/**/*.js. All core modules are
// compiled into the node binary via node_javascript.cc generated by js2c.cc,
// so they can be loaded faster without the cost of I/O. This class makes the
// lib/internal/*, deps/internal/* modules and internalBinding() available by
// default to core modules, and lets the core modules require itself via
// require('internal/bootstrap/realm') even when this file is not written in
// CommonJS style.
//
// Other objects:
// - process.moduleLoadList: an array recording the bindings and the modules
// loaded in the process and the order in which they are loaded.
'use strict';
// This file is compiled as if it's wrapped in a function with arguments
// passed by node::RunBootstrapping()
/* global process, getLinkedBinding, getInternalBinding, primordials */
const {
ArrayFrom,
ArrayPrototypeFilter,
ArrayPrototypeIncludes,
ArrayPrototypeMap,
ArrayPrototypePush,
ArrayPrototypePushApply,
ArrayPrototypeSlice,
Error,
ObjectDefineProperty,
ObjectKeys,
ObjectPrototypeHasOwnProperty,
ObjectSetPrototypeOf,
ReflectGet,
SafeMap,
SafeSet,
String,
StringPrototypeSlice,
StringPrototypeStartsWith,
TypeError,
} = primordials;
// Set up process.moduleLoadList.
const moduleLoadList = [];
ObjectDefineProperty(process, 'moduleLoadList', {
__proto__: null,
value: moduleLoadList,
configurable: true,
enumerable: true,
writable: false,
});
// processBindingAllowList contains the name of bindings that are allowed
// for access via process.binding(). This is used to provide a transition
// path for modules that are being moved over to internalBinding.
// Certain bindings may not actually correspond to an internalBinding any
// more, we just implement them as legacy wrappers instead. See the
// legacyWrapperList.
const processBindingAllowList = new SafeSet([
'buffer',
'cares_wrap',
'config',
'constants',
'contextify',
'fs',
'fs_event_wrap',
'icu',
'inspector',
'js_stream',
'os',
'pipe_wrap',
'process_wrap',
'spawn_sync',
'stream_wrap',
'tcp_wrap',
'tls_wrap',
'tty_wrap',
'udp_wrap',
'uv',
'zlib',
]);
const runtimeDeprecatedList = new SafeSet([
// The list of runtime-deprecated bindings is currently empty.
]);
const legacyWrapperList = new SafeSet([
'natives',
'util',
]);
// The code bellow assumes that the two lists must not contain any modules
// beginning with "internal/".
// Modules that can only be imported via the node: scheme.
const schemelessBlockList = new SafeSet([
'sea',
'sqlite',
'quic',
'test',
'test/reporters',
]);
// Modules that will only be enabled at run time.
const experimentalModuleList = new SafeSet(['sqlite', 'quic']);
// Set up process.binding() and process._linkedBinding().
{
const bindingObj = { __proto__: null };
process.binding = function binding(module) {
module = String(module);
const mod = bindingObj[module];
if (typeof mod === 'object') {
return mod;
}
// Deprecated specific process.binding() modules, but not all, allow
// selective fallback to internalBinding for the deprecated ones.
if (runtimeDeprecatedList.has(module)) {
process.emitWarning(
`Access to process.binding('${module}') is deprecated.`,
'DeprecationWarning',
'DEP0111');
return internalBinding(module);
}
if (legacyWrapperList.has(module)) {
return requireBuiltin('internal/legacy/processbinding')[module]();
}
if (processBindingAllowList.has(module)) {
return internalBinding(module);
}
// eslint-disable-next-line no-restricted-syntax
throw new Error(`No such module: ${module}`);
};
process._linkedBinding = function _linkedBinding(module) {
module = String(module);
let mod = bindingObj[module];
if (typeof mod !== 'object')
mod = bindingObj[module] = getLinkedBinding(module);
return mod;
};
}
/**
* Set up internalBinding() in the closure.
* @type {import('typings/globals').internalBinding}
*/
let internalBinding;
{
const bindingObj = { __proto__: null };
// eslint-disable-next-line no-global-assign
internalBinding = function internalBinding(module) {
let mod = bindingObj[module];
if (typeof mod !== 'object') {
mod = bindingObj[module] = getInternalBinding(module);
ArrayPrototypePush(moduleLoadList, `Internal Binding ${module}`);
}
return mod;
};
}
const selfId = 'internal/bootstrap/realm';
const {
builtinIds,
compileFunction,
setInternalLoaders,
} = internalBinding('builtins');
const { ModuleWrap } = internalBinding('module_wrap');
ObjectSetPrototypeOf(ModuleWrap.prototype, null);
const getOwn = (target, property, receiver) => {
return ObjectPrototypeHasOwnProperty(target, property) ?
ReflectGet(target, property, receiver) :
undefined;
};
const publicBuiltinIds = builtinIds
.filter((id) =>
!StringPrototypeStartsWith(id, 'internal/') &&
!experimentalModuleList.has(id),
);
// Do not expose the loaders to user land even with --expose-internals.
const internalBuiltinIds = builtinIds
.filter((id) => StringPrototypeStartsWith(id, 'internal/') && id !== selfId);
// When --expose-internals is on we'll add the internal builtin ids to these.
let canBeRequiredByUsersList = new SafeSet(publicBuiltinIds);
let canBeRequiredByUsersWithoutSchemeList =
new SafeSet(publicBuiltinIds.filter((id) => !schemelessBlockList.has(id)));
/**
* An internal abstraction for the built-in JavaScript modules of Node.js.
* Be careful not to expose this to user land unless --expose-internals is
* used, in which case there is no compatibility guarantee about this class.
*/
class BuiltinModule {
/**
* A map from the module IDs to the module instances.
* @type {Map<string, BuiltinModule>}
*/
static map = new SafeMap(
ArrayPrototypeMap(builtinIds, (id) => [id, new BuiltinModule(id)]),
);
constructor(id) {
this.filename = `${id}.js`;
this.id = id;
// The CJS exports object of the module.
this.exports = {};
// States used to work around circular dependencies.
this.loaded = false;
this.loading = false;
// The following properties are used by the ESM implementation and only
// initialized when the built-in module is loaded by users.
/**
* The C++ ModuleWrap binding used to interface with the ESM implementation.
* @type {ModuleWrap|undefined}
*/
this.module = undefined;
/**
* Exported names for the ESM imports.
* @type {string[]|undefined}
*/
this.exportKeys = undefined;
}
static allowRequireByUsers(id) {
if (id === selfId) {
// No code because this is an assertion against bugs.
// eslint-disable-next-line no-restricted-syntax
throw new Error(`Should not allow ${id}`);
}
canBeRequiredByUsersList.add(id);
if (!schemelessBlockList.has(id)) {
canBeRequiredByUsersWithoutSchemeList.add(id);
}
}
static setRealmAllowRequireByUsers(ids) {
canBeRequiredByUsersList =
new SafeSet(ArrayPrototypeFilter(ids, (id) => ArrayPrototypeIncludes(publicBuiltinIds, id)));
canBeRequiredByUsersWithoutSchemeList =
new SafeSet(ArrayPrototypeFilter(ids, (id) => !schemelessBlockList.has(id)));
}
// To be called during pre-execution when --expose-internals is on.
// Enables the user-land module loader to access internal modules.
static exposeInternals() {
for (let i = 0; i < internalBuiltinIds.length; ++i) {
BuiltinModule.allowRequireByUsers(internalBuiltinIds[i]);
}
}
static exists(id) {
return BuiltinModule.map.has(id);
}
static canBeRequiredByUsers(id) {
return canBeRequiredByUsersList.has(id);
}
static canBeRequiredWithoutScheme(id) {
return canBeRequiredByUsersWithoutSchemeList.has(id);
}
static normalizeRequirableId(id) {
if (StringPrototypeStartsWith(id, 'node:')) {
const normalizedId = StringPrototypeSlice(id, 5);
if (BuiltinModule.canBeRequiredByUsers(normalizedId)) {
return normalizedId;
}
} else if (BuiltinModule.canBeRequiredWithoutScheme(id)) {
return id;
}
return undefined;
}
static isBuiltin(id) {
return BuiltinModule.canBeRequiredWithoutScheme(id) || (
typeof id === 'string' &&
StringPrototypeStartsWith(id, 'node:') &&
BuiltinModule.canBeRequiredByUsers(StringPrototypeSlice(id, 5))
);
}
static getSchemeOnlyModuleNames() {
return ArrayFrom(schemelessBlockList);
}
static getAllBuiltinModuleIds() {
const allBuiltins = ArrayFrom(canBeRequiredByUsersWithoutSchemeList);
ArrayPrototypePushApply(allBuiltins, ArrayFrom(schemelessBlockList, (x) => `node:${x}`));
return allBuiltins;
}
// Used by user-land module loaders to compile and load builtins.
compileForPublicLoader() {
if (!BuiltinModule.canBeRequiredByUsers(this.id)) {
// No code because this is an assertion against bugs
// eslint-disable-next-line no-restricted-syntax
throw new Error(`Should not compile ${this.id} for public use`);
}
this.compileForInternalLoader();
if (!this.exportKeys) {
// When using --expose-internals, we do not want to reflect the named
// exports from core modules as this can trigger unnecessary getters.
const internal = StringPrototypeStartsWith(this.id, 'internal/');
this.exportKeys = internal ? [] : ObjectKeys(this.exports);
}
return this.exports;
}
getESMFacade() {
if (this.module) return this.module;
const url = `node:${this.id}`;
const builtin = this;
const exportsKeys = ArrayPrototypeSlice(this.exportKeys);
if (!ArrayPrototypeIncludes(exportsKeys, 'default')) {
ArrayPrototypePush(exportsKeys, 'default');
}
this.module = new ModuleWrap(
url, undefined, exportsKeys,
function() {
builtin.syncExports();
this.setExport('default', builtin.exports);
});
// Ensure immediate sync execution to capture exports now
this.module.instantiate();
this.module.evaluate(-1, false);
return this.module;
}
// Provide named exports for all builtin libraries so that the libraries
// may be imported in a nicer way for ESM users. The default export is left
// as the entire namespace (module.exports) and updates when this function is
// called so that APMs and other behavior are supported.
syncExports() {
const names = this.exportKeys;
if (this.module) {
for (let i = 0; i < names.length; i++) {
const exportName = names[i];
if (exportName === 'default') continue;
this.module.setExport(exportName,
getOwn(this.exports, exportName, this.exports));
}
}
}
compileForInternalLoader() {
if (this.loaded || this.loading) {
return this.exports;
}
const id = this.id;
this.loading = true;
try {
const requireFn = StringPrototypeStartsWith(this.id, 'internal/deps/') ?
requireWithFallbackInDeps : requireBuiltin;
const fn = compileFunction(id);
// Arguments must match the parameters specified in
// BuiltinLoader::LookupAndCompile().
fn(this.exports, requireFn, this, process, internalBinding, primordials);
this.loaded = true;
} finally {
this.loading = false;
}
// "NativeModule" is a legacy name of "BuiltinModule". We keep it
// here to avoid breaking users who parse process.moduleLoadList.
ArrayPrototypePush(moduleLoadList, `NativeModule ${id}`);
return this.exports;
}
}
// Think of this as module.exports in this file even though it is not
// written in CommonJS style.
const loaderExports = {
internalBinding,
BuiltinModule,
require: requireBuiltin,
};
function requireBuiltin(id) {
if (id === selfId) {
return loaderExports;
}
const mod = BuiltinModule.map.get(id);
// Can't load the internal errors module from here, have to use a raw error.
// eslint-disable-next-line no-restricted-syntax
if (!mod) throw new TypeError(`Missing internal module '${id}'`);
return mod.compileForInternalLoader();
}
// Allow internal modules from dependencies to require
// other modules from dependencies by providing fallbacks.
function requireWithFallbackInDeps(request) {
if (StringPrototypeStartsWith(request, 'node:')) {
request = StringPrototypeSlice(request, 5);
} else if (!BuiltinModule.map.has(request)) {
request = `internal/deps/${request}`;
}
return requireBuiltin(request);
}
function setupPrepareStackTrace() {
const {
setEnhanceStackForFatalException,
setPrepareStackTraceCallback,
} = internalBinding('errors');
const {
prepareStackTraceCallback,
ErrorPrepareStackTrace,
fatalExceptionStackEnhancers: {
beforeInspector,
afterInspector,
},
} = requireBuiltin('internal/errors');
// Tell our PrepareStackTraceCallback passed to the V8 API
// to call prepareStackTrace().
setPrepareStackTraceCallback(prepareStackTraceCallback);
// Set the function used to enhance the error stack for printing
setEnhanceStackForFatalException(beforeInspector, afterInspector);
// Setup the default Error.prepareStackTrace.
ObjectDefineProperty(Error, 'prepareStackTrace', {
__proto__: null,
writable: true,
enumerable: false,
configurable: true,
value: ErrorPrepareStackTrace,
});
}
// Store the internal loaders in C++.
setInternalLoaders(internalBinding, requireBuiltin);
// Setup per-realm bindings.
setupPrepareStackTrace();

View File

@ -0,0 +1,21 @@
'use strict';
// This script sets up the context for shadow realms.
const {
prepareShadowRealmExecution,
} = require('internal/process/pre_execution');
const {
BuiltinModule,
} = require('internal/bootstrap/realm');
BuiltinModule.setRealmAllowRequireByUsers([
/**
* The built-in modules exposed in the ShadowRealm must each be providing
* platform capabilities with no authority to cause side effects such as
* I/O or mutation of values that are shared across different realms within
* the same Node.js environment.
*/
]);
prepareShadowRealmExecution();

View File

@ -0,0 +1,38 @@
'use strict';
const credentials = internalBinding('credentials');
const rawMethods = internalBinding('process_methods');
// TODO: this should be detached from ERR_WORKER_UNSUPPORTED_OPERATION
const { unavailable } = require('internal/process/worker_thread_only');
process.abort = unavailable('process.abort()');
process.chdir = unavailable('process.chdir()');
process.umask = wrappedUmask;
process.cwd = rawMethods.cwd;
if (credentials.implementsPosixCredentials) {
process.initgroups = unavailable('process.initgroups()');
process.setgroups = unavailable('process.setgroups()');
process.setegid = unavailable('process.setegid()');
process.seteuid = unavailable('process.seteuid()');
process.setgid = unavailable('process.setgid()');
process.setuid = unavailable('process.setuid()');
}
// ---- keep the attachment of the wrappers above so that it's easier to ----
// ---- compare the setups side-by-side -----
const {
codes: {
ERR_WORKER_UNSUPPORTED_OPERATION,
},
} = require('internal/errors');
function wrappedUmask(mask) {
// process.umask() is a read-only operation in workers.
if (mask !== undefined) {
throw new ERR_WORKER_UNSUPPORTED_OPERATION('Setting process.umask()');
}
return rawMethods.umask(mask);
}

View File

@ -0,0 +1,144 @@
'use strict';
const credentials = internalBinding('credentials');
const rawMethods = internalBinding('process_methods');
const {
namespace: {
addDeserializeCallback,
addSerializeCallback,
isBuildingSnapshot,
},
} = require('internal/v8/startup_snapshot');
process.abort = rawMethods.abort;
process.umask = wrappedUmask;
process.chdir = wrappedChdir;
process.cwd = wrappedCwd;
if (credentials.implementsPosixCredentials) {
const wrapped = wrapPosixCredentialSetters(credentials);
process.initgroups = wrapped.initgroups;
process.setgroups = wrapped.setgroups;
process.setegid = wrapped.setegid;
process.seteuid = wrapped.seteuid;
process.setgid = wrapped.setgid;
process.setuid = wrapped.setuid;
}
// ---- keep the attachment of the wrappers above so that it's easier to ----
// ---- compare the setups side-by-side -----
const {
parseFileMode,
validateArray,
validateString,
validateUint32,
} = require('internal/validators');
function wrapPosixCredentialSetters(credentials) {
const {
codes: {
ERR_INVALID_ARG_TYPE,
ERR_UNKNOWN_CREDENTIAL,
},
} = require('internal/errors');
const {
initgroups: _initgroups,
setgroups: _setgroups,
setegid: _setegid,
seteuid: _seteuid,
setgid: _setgid,
setuid: _setuid,
} = credentials;
function initgroups(user, extraGroup) {
validateId(user, 'user');
validateId(extraGroup, 'extraGroup');
// Result is 0 on success, 1 if user is unknown, 2 if group is unknown.
const result = _initgroups(user, extraGroup);
if (result === 1) {
throw new ERR_UNKNOWN_CREDENTIAL('User', user);
} else if (result === 2) {
throw new ERR_UNKNOWN_CREDENTIAL('Group', extraGroup);
}
}
function setgroups(groups) {
validateArray(groups, 'groups');
for (let i = 0; i < groups.length; i++) {
validateId(groups[i], `groups[${i}]`);
}
// Result is 0 on success. A positive integer indicates that the
// corresponding group was not found.
const result = _setgroups(groups);
if (result > 0) {
throw new ERR_UNKNOWN_CREDENTIAL('Group', groups[result - 1]);
}
}
function wrapIdSetter(type, method) {
return function(id) {
validateId(id, 'id');
if (typeof id === 'number') id >>>= 0;
// Result is 0 on success, 1 if credential is unknown.
const result = method(id);
if (result === 1) {
throw new ERR_UNKNOWN_CREDENTIAL(type, id);
}
};
}
function validateId(id, name) {
if (typeof id === 'number') {
validateUint32(id, name);
} else if (typeof id !== 'string') {
throw new ERR_INVALID_ARG_TYPE(name, ['number', 'string'], id);
}
}
return {
initgroups,
setgroups,
setegid: wrapIdSetter('Group', _setegid),
seteuid: wrapIdSetter('User', _seteuid),
setgid: wrapIdSetter('Group', _setgid),
setuid: wrapIdSetter('User', _setuid),
};
}
// Cache the working directory to prevent lots of lookups. If the working
// directory is changed by `chdir`, it'll be updated.
let cachedCwd = '';
if (isBuildingSnapshot()) {
// Reset the cwd on both serialization and deserialization so it's fine
// for process.cwd() to be accessed inside of serialization callbacks.
addSerializeCallback(() => {
cachedCwd = '';
addDeserializeCallback(() => {
cachedCwd = '';
});
});
}
function wrappedChdir(directory) {
validateString(directory, 'directory');
rawMethods.chdir(directory);
// Mark cache that it requires an update.
cachedCwd = '';
}
function wrappedUmask(mask) {
if (mask !== undefined) {
mask = parseFileMode(mask, 'mask');
}
return rawMethods.umask(mask);
}
function wrappedCwd() {
if (cachedCwd === '')
cachedCwd = rawMethods.cwd();
return cachedCwd;
}

View File

@ -0,0 +1,318 @@
'use strict';
const {
ObjectDefineProperty,
} = primordials;
const rawMethods = internalBinding('process_methods');
const {
namespace: {
addSerializeCallback,
isBuildingSnapshot,
},
} = require('internal/v8/startup_snapshot');
// TODO(joyeecheung): deprecate and remove these underscore methods
process._debugProcess = rawMethods._debugProcess;
process._debugEnd = rawMethods._debugEnd;
// See the discussion in https://github.com/nodejs/node/issues/19009 and
// https://github.com/nodejs/node/pull/34010 for why these are no-ops.
// Five word summary: they were broken beyond repair.
process._startProfilerIdleNotifier = () => {};
process._stopProfilerIdleNotifier = () => {};
function defineStream(name, getter) {
ObjectDefineProperty(process, name, {
__proto__: null,
configurable: true,
enumerable: true,
get: getter,
});
}
defineStream('stdout', getStdout);
defineStream('stdin', getStdin);
defineStream('stderr', getStderr);
// Worker threads don't receive signals.
const {
startListeningIfSignal,
stopListeningIfSignal,
} = require('internal/process/signal');
process.on('newListener', startListeningIfSignal);
process.on('removeListener', stopListeningIfSignal);
// ---- keep the attachment of the wrappers above so that it's easier to ----
// ---- compare the setups side-by-side -----
const { guessHandleType } = require('internal/util');
function createWritableStdioStream(fd) {
let stream;
// Note stream._type is used for test-module-load-list.js
switch (guessHandleType(fd)) {
case 'TTY': {
const tty = require('tty');
stream = new tty.WriteStream(fd);
stream._type = 'tty';
break;
}
case 'FILE': {
const SyncWriteStream = require('internal/fs/sync_write_stream');
stream = new SyncWriteStream(fd, { autoClose: false });
stream._type = 'fs';
break;
}
case 'PIPE':
case 'TCP': {
const net = require('net');
// If fd is already being used for the IPC channel, libuv will return
// an error when trying to use it again. In that case, create the socket
// using the existing handle instead of the fd.
if (process.channel && process.channel.fd === fd) {
const { kChannelHandle } = require('internal/child_process');
stream = new net.Socket({
handle: process[kChannelHandle],
readable: false,
writable: true,
});
} else {
stream = new net.Socket({
fd,
readable: false,
writable: true,
});
}
stream._type = 'pipe';
break;
}
default: {
// Provide a dummy black-hole output for e.g. non-console
// Windows applications.
const { Writable } = require('stream');
stream = new Writable({
write(buf, enc, cb) {
cb();
},
});
}
}
// For supporting legacy API we put the FD here.
stream.fd = fd;
stream._isStdio = true;
return stream;
}
function dummyDestroy(err, cb) {
cb(err);
this._undestroy();
// We need to emit 'close' anyway so that the closing
// of the stream is observable. We just make sure we
// are not going to do it twice.
// The 'close' event is needed so that finished and
// pipeline work correctly.
if (!this._writableState.emitClose) {
process.nextTick(() => {
this.emit('close');
});
}
}
let stdin;
let stdout;
let stderr;
let stdoutDestroy;
let stderrDestroy;
function refreshStdoutOnSigWinch() {
stdout._refreshSize();
}
function refreshStderrOnSigWinch() {
stderr._refreshSize();
}
function addCleanup(fn) {
if (isBuildingSnapshot()) {
addSerializeCallback(fn);
}
}
function getStdout() {
if (stdout) return stdout;
stdout = createWritableStdioStream(1);
stdout.destroySoon = stdout.destroy;
// Override _destroy so that the fd is never actually closed.
stdoutDestroy = stdout._destroy;
stdout._destroy = dummyDestroy;
if (stdout.isTTY) {
process.on('SIGWINCH', refreshStdoutOnSigWinch);
}
addCleanup(function cleanupStdout() {
stdout._destroy = stdoutDestroy;
stdout.destroy();
process.removeListener('SIGWINCH', refreshStdoutOnSigWinch);
stdout = undefined;
});
// No need to add deserialize callback because stdout = undefined above
// causes the stream to be lazily initialized again later.
return stdout;
}
function getStderr() {
if (stderr) return stderr;
stderr = createWritableStdioStream(2);
stderr.destroySoon = stderr.destroy;
stderrDestroy = stderr._destroy;
// Override _destroy so that the fd is never actually closed.
stderr._destroy = dummyDestroy;
if (stderr.isTTY) {
process.on('SIGWINCH', refreshStderrOnSigWinch);
}
addCleanup(function cleanupStderr() {
stderr._destroy = stderrDestroy;
stderr.destroy();
process.removeListener('SIGWINCH', refreshStderrOnSigWinch);
stderr = undefined;
});
// No need to add deserialize callback because stderr = undefined above
// causes the stream to be lazily initialized again later.
return stderr;
}
function getStdin() {
if (stdin) return stdin;
const fd = 0;
switch (guessHandleType(fd)) {
case 'TTY': {
const tty = require('tty');
stdin = new tty.ReadStream(fd);
break;
}
case 'FILE': {
const fs = require('fs');
stdin = new fs.ReadStream(null, { fd: fd, autoClose: false });
break;
}
case 'PIPE':
case 'TCP': {
const net = require('net');
// It could be that process has been started with an IPC channel
// sitting on fd=0, in such case the pipe for this fd is already
// present and creating a new one will lead to the assertion failure
// in libuv.
if (process.channel && process.channel.fd === fd) {
stdin = new net.Socket({
handle: process.channel,
readable: true,
writable: false,
manualStart: true,
});
} else {
stdin = new net.Socket({
fd: fd,
readable: true,
writable: false,
manualStart: true,
});
}
// Make sure the stdin can't be `.end()`-ed
stdin._writableState.ended = true;
break;
}
default: {
// Provide a dummy contentless input for e.g. non-console
// Windows applications.
const { Readable } = require('stream');
stdin = new Readable({ read() {} });
stdin.push(null);
}
}
// For supporting legacy API we put the FD here.
stdin.fd = fd;
// `stdin` starts out life in a paused state, but node doesn't
// know yet. Explicitly to readStop() it to put it in the
// not-reading state.
if (stdin._handle?.readStop) {
stdin._handle.reading = false;
stdin._readableState.reading = false;
stdin._handle.readStop();
}
// If the user calls stdin.pause(), then we need to stop reading
// once the stream implementation does so (one nextTick later),
// so that the process can close down.
stdin.on('pause', () => {
process.nextTick(onpause);
});
function onpause() {
if (!stdin._handle)
return;
if (stdin._handle.reading && !stdin.readableFlowing) {
stdin._readableState.reading = false;
stdin._handle.reading = false;
stdin._handle.readStop();
}
}
addCleanup(function cleanupStdin() {
stdin.destroy();
stdin = undefined;
});
// No need to add deserialize callback because stdin = undefined above
// causes the stream to be lazily initialized again later.
return stdin;
}
// Used by internal tests.
rawMethods.resetStdioForTesting = function() {
stdin = undefined;
stdout = undefined;
stderr = undefined;
};
// Needed by the module loader and generally needed everywhere.
require('fs');
require('util');
require('url'); // eslint-disable-line no-restricted-modules
internalBinding('module_wrap');
require('internal/modules/cjs/loader');
require('internal/modules/esm/utils');
// Needed to refresh the time origin.
require('internal/perf/utils');
// Needed to register the async hooks.
if (internalBinding('config').hasInspector) {
require('internal/inspector_async_hook');
}
// Needed to set the wasm web API callbacks.
internalBinding('wasm_web_api');
// Needed to detect whether it's on main thread.
internalBinding('worker');
// Needed by most execution modes.
require('internal/modules/run_main');
// Needed to refresh DNS configurations.
require('internal/dns/utils');
// Needed by almost all execution modes. It's fine to
// load them into the snapshot as long as we don't run
// any of the initialization.
require('internal/process/pre_execution');

View File

@ -0,0 +1,58 @@
'use strict';
const {
ObjectDefineProperty,
} = primordials;
delete process._debugProcess;
delete process._debugEnd;
function defineStream(name, getter) {
ObjectDefineProperty(process, name, {
__proto__: null,
configurable: true,
enumerable: true,
get: getter,
});
}
defineStream('stdout', getStdout);
defineStream('stdin', getStdin);
defineStream('stderr', getStderr);
// Worker threads don't receive signals.
const {
startListeningIfSignal,
stopListeningIfSignal,
} = require('internal/process/signal');
process.removeListener('newListener', startListeningIfSignal);
process.removeListener('removeListener', stopListeningIfSignal);
// ---- keep the attachment of the wrappers above so that it's easier to ----
// ---- compare the setups side-by-side -----
const {
createWorkerStdio,
kStdioWantsMoreDataCallback,
} = require('internal/worker/io');
let workerStdio;
function lazyWorkerStdio() {
if (workerStdio === undefined) {
workerStdio = createWorkerStdio();
process.on('exit', flushSync);
}
return workerStdio;
}
function flushSync() {
workerStdio.stdout[kStdioWantsMoreDataCallback]();
workerStdio.stderr[kStdioWantsMoreDataCallback]();
}
function getStdout() { return lazyWorkerStdio().stdout; }
function getStderr() { return lazyWorkerStdio().stderr; }
function getStdin() { return lazyWorkerStdio().stdin; }

View File

@ -0,0 +1,105 @@
'use strict';
/**
* This file exposes web interfaces that is defined with the WebIDL
* [Exposed=*] extended attribute.
* See more details at https://webidl.spec.whatwg.org/#Exposed.
*/
const {
globalThis,
} = primordials;
const {
exposeInterface,
exposeLazyInterfaces,
exposeNamespace,
} = require('internal/util');
const config = internalBinding('config');
const { exposeLazyDOMExceptionProperty } = internalBinding('messaging');
// https://console.spec.whatwg.org/#console-namespace
exposeNamespace(globalThis, 'console',
createGlobalConsole());
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);
exposeLazyDOMExceptionProperty(globalThis);
// https://dom.spec.whatwg.org/#interface-abortcontroller
// Lazy ones.
exposeLazyInterfaces(globalThis, 'internal/abort_controller', [
'AbortController', 'AbortSignal',
]);
// https://dom.spec.whatwg.org/#interface-eventtarget
const {
EventTarget, Event,
} = require('internal/event_target');
exposeInterface(globalThis, 'Event', Event);
exposeInterface(globalThis, 'EventTarget', EventTarget);
exposeLazyInterfaces(globalThis, 'internal/event_target', ['CustomEvent']);
// https://encoding.spec.whatwg.org/#textencoder
// https://encoding.spec.whatwg.org/#textdecoder
exposeLazyInterfaces(globalThis,
'internal/encoding',
['TextEncoder', 'TextDecoder']);
function createGlobalConsole() {
const consoleFromNode =
require('internal/console/global');
if (config.hasInspector) {
const inspector = require('internal/util/inspector');
// TODO(joyeecheung): postpone this until the first time inspector
// is activated.
inspector.wrapConsole(consoleFromNode);
const { setConsoleExtensionInstaller } = internalBinding('inspector');
// Setup inspector command line API.
setConsoleExtensionInstaller(inspector.installConsoleExtensions);
}
return consoleFromNode;
}
// Web Streams API
exposeLazyInterfaces(
globalThis,
'internal/webstreams/transformstream',
['TransformStream', 'TransformStreamDefaultController']);
exposeLazyInterfaces(
globalThis,
'internal/webstreams/writablestream',
['WritableStream', 'WritableStreamDefaultController', 'WritableStreamDefaultWriter']);
exposeLazyInterfaces(
globalThis,
'internal/webstreams/readablestream',
[
'ReadableStream', 'ReadableStreamDefaultReader',
'ReadableStreamBYOBReader', 'ReadableStreamBYOBRequest',
'ReadableByteStreamController', 'ReadableStreamDefaultController',
]);
exposeLazyInterfaces(
globalThis,
'internal/webstreams/queuingstrategies',
[
'ByteLengthQueuingStrategy', 'CountQueuingStrategy',
]);
exposeLazyInterfaces(
globalThis,
'internal/webstreams/encoding',
[
'TextEncoderStream', 'TextDecoderStream',
]);
exposeLazyInterfaces(
globalThis,
'internal/webstreams/compression',
[
'CompressionStream', 'DecompressionStream',
]);

View File

@ -0,0 +1,129 @@
'use strict';
/**
* This file exposes web interfaces that is defined with the WebIDL
* Exposed=Window + Exposed=(Window,Worker) extended attribute or exposed in
* WindowOrWorkerGlobalScope mixin.
* See more details at https://webidl.spec.whatwg.org/#Exposed and
* https://html.spec.whatwg.org/multipage/webappapis.html#windoworworkerglobalscope.
*/
const {
ObjectDefineProperty,
ObjectGetOwnPropertyDescriptor,
globalThis,
} = primordials;
const {
defineOperation,
defineLazyProperties,
defineReplaceableLazyAttribute,
exposeLazyInterfaces,
exposeInterface,
} = require('internal/util');
const {
ERR_INVALID_THIS,
ERR_NO_CRYPTO,
} = require('internal/errors').codes;
// 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);
defineLazyProperties(
globalThis,
'internal/worker/js_transferable',
['structuredClone'],
);
defineLazyProperties(globalThis, 'buffer', ['atob', 'btoa']);
// https://html.spec.whatwg.org/multipage/web-messaging.html#broadcasting-to-other-browsing-contexts
exposeLazyInterfaces(globalThis, 'internal/worker/io', ['BroadcastChannel']);
exposeLazyInterfaces(globalThis, 'internal/worker/io', [
'MessageChannel', 'MessagePort',
]);
// https://www.w3.org/TR/FileAPI/#dfn-Blob
exposeLazyInterfaces(globalThis, 'internal/blob', ['Blob']);
// https://www.w3.org/TR/FileAPI/#dfn-file
exposeLazyInterfaces(globalThis, 'internal/file', ['File']);
// https://www.w3.org/TR/hr-time-2/#the-performance-attribute
exposeLazyInterfaces(globalThis, 'perf_hooks', [
'Performance', 'PerformanceEntry', 'PerformanceMark', 'PerformanceMeasure',
'PerformanceObserver', 'PerformanceObserverEntryList', 'PerformanceResourceTiming',
]);
defineReplaceableLazyAttribute(globalThis, 'perf_hooks', ['performance']);
// https://w3c.github.io/FileAPI/#creating-revoking
const { installObjectURLMethods, URLPattern } = require('internal/url');
installObjectURLMethods();
exposeInterface(globalThis, 'URLPattern', URLPattern);
let fetchImpl;
// https://fetch.spec.whatwg.org/#fetch-method
ObjectDefineProperty(globalThis, 'fetch', {
__proto__: null,
configurable: true,
enumerable: true,
writable: true,
value: function fetch(input, init = undefined) { // eslint-disable-line func-name-matching
if (!fetchImpl) { // Implement lazy loading of undici module for fetch function
const undiciModule = require('internal/deps/undici/undici');
fetchImpl = undiciModule.fetch;
}
return fetchImpl(input, init);
},
});
// https://xhr.spec.whatwg.org/#interface-formdata
// https://fetch.spec.whatwg.org/#headers-class
// https://fetch.spec.whatwg.org/#request-class
// https://fetch.spec.whatwg.org/#response-class
exposeLazyInterfaces(globalThis, 'internal/deps/undici/undici', [
'FormData', 'Headers', 'Request', 'Response', 'MessageEvent', 'CloseEvent',
]);
// https://html.spec.whatwg.org/multipage/server-sent-events.html#server-sent-events.org/
// https://websockets.spec.whatwg.org/
exposeLazyInterfaces(globalThis, 'internal/deps/undici/undici', ['EventSource', 'WebSocket']);
// The WebAssembly Web API which relies on Response.
// https:// webassembly.github.io/spec/web-api/#streaming-modules
internalBinding('wasm_web_api').setImplementation((streamState, source) => {
require('internal/wasm_web_api').wasmStreamingCallback(streamState, source);
});
// WebCryptoAPI
if (internalBinding('config').hasOpenSSL) {
defineReplaceableLazyAttribute(
globalThis,
'internal/crypto/webcrypto',
['crypto'],
false,
function cryptoThisCheck() {
if (this !== globalThis && this != null)
throw new ERR_INVALID_THIS(
'nullish or must be the global object');
},
);
exposeLazyInterfaces(
globalThis, 'internal/crypto/webcrypto',
['Crypto', 'CryptoKey', 'SubtleCrypto'],
);
} else {
ObjectDefineProperty(globalThis, 'crypto',
{ __proto__: null, ...ObjectGetOwnPropertyDescriptor({
get crypto() {
throw new ERR_NO_CRYPTO();
},
}, 'crypto') });
}