mirror of
https://github.com/nodejs/node.git
synced 2025-05-01 08:42:45 +00:00

This patch refactors the DNS default resolver code to make it easier to be included in a snapshot: - The code specific for the callback-based DNS resolver are not in a separate module to make the dependency clearer (it's not actually needed if the user only ever loads `dns/promises`) - The common part of the callback-based resolver and the promise- based resolver is now ResolverBase. The other two user-facing resolvers are now subclasses of ResolverBase. The default Resolver is constructed with just ResolverBase. This would be fine as the default resolver is never actually exposed to the user-land and it has been working using duck-typing anyway. - Move the construction of Resolver subclasses into a common method `createResolverClass()` to reduce code duplication. The two subclasses now also share the same base constructor. This would make it possible for them to also share code for snapshot support later. - `--dns-result-order` is now queried and refreshed during pre-execution. To avoid loading the cares_wrap binding unnecessarily the loading of the binding is also made lazy. PR-URL: https://github.com/nodejs/node/pull/44541 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Zeyu "Alex" Yang <himself65@outlook.com> Reviewed-By: Minwoo Jung <nodecorelab@gmail.com>
628 lines
19 KiB
JavaScript
628 lines
19 KiB
JavaScript
'use strict';
|
|
|
|
const {
|
|
NumberParseInt,
|
|
ObjectDefineProperties,
|
|
ObjectDefineProperty,
|
|
ObjectGetOwnPropertyDescriptor,
|
|
SafeMap,
|
|
SafeWeakMap,
|
|
StringPrototypeStartsWith,
|
|
globalThis,
|
|
} = primordials;
|
|
|
|
const {
|
|
getOptionValue,
|
|
getEmbedderOptions,
|
|
refreshOptions,
|
|
} = require('internal/options');
|
|
const { reconnectZeroFillToggle } = require('internal/buffer');
|
|
const {
|
|
defineOperation,
|
|
emitExperimentalWarning,
|
|
exposeInterface,
|
|
} = require('internal/util');
|
|
|
|
const {
|
|
ERR_MANIFEST_ASSERT_INTEGRITY,
|
|
} = require('internal/errors').codes;
|
|
const assert = require('internal/assert');
|
|
|
|
const {
|
|
addSerializeCallback,
|
|
isBuildingSnapshot,
|
|
} = require('v8').startupSnapshot;
|
|
|
|
function prepareMainThreadExecution(expandArgv1 = false,
|
|
initialzeModules = true) {
|
|
refreshRuntimeOptions();
|
|
|
|
// TODO(joyeecheung): this is also necessary for workers when they deserialize
|
|
// this toggle from the snapshot.
|
|
reconnectZeroFillToggle();
|
|
|
|
// Patch the process object with legacy properties and normalizations
|
|
patchProcessObject(expandArgv1);
|
|
setupTraceCategoryState();
|
|
setupPerfHooks();
|
|
setupInspectorHooks();
|
|
setupWarningHandler();
|
|
setupFetch();
|
|
setupWebCrypto();
|
|
setupCustomEvent();
|
|
|
|
// Resolve the coverage directory to an absolute path, and
|
|
// overwrite process.env so that the original path gets passed
|
|
// to child processes even when they switch cwd.
|
|
if (process.env.NODE_V8_COVERAGE) {
|
|
process.env.NODE_V8_COVERAGE =
|
|
setupCoverageHooks(process.env.NODE_V8_COVERAGE);
|
|
}
|
|
|
|
setupDebugEnv();
|
|
|
|
// Print stack trace on `SIGINT` if option `--trace-sigint` presents.
|
|
setupStacktracePrinterOnSigint();
|
|
|
|
// Process initial diagnostic reporting configuration, if present.
|
|
initializeReport();
|
|
initializeReportSignalHandlers(); // Main-thread-only.
|
|
|
|
initializeHeapSnapshotSignalHandlers();
|
|
|
|
// If the process is spawned with env NODE_CHANNEL_FD, it's probably
|
|
// spawned by our child_process module, then initialize IPC.
|
|
// This attaches some internal event listeners and creates:
|
|
// process.send(), process.channel, process.connected,
|
|
// process.disconnect().
|
|
setupChildProcessIpcChannel();
|
|
|
|
// Load policy from disk and parse it.
|
|
initializePolicy();
|
|
|
|
// If this is a worker in cluster mode, start up the communication
|
|
// channel. This needs to be done before any user code gets executed
|
|
// (including preload modules).
|
|
initializeClusterIPC();
|
|
|
|
initializeSourceMapsHandlers();
|
|
initializeDeprecations();
|
|
initializeWASI();
|
|
|
|
require('internal/dns/utils').initializeDns();
|
|
|
|
require('internal/v8/startup_snapshot').runDeserializeCallbacks();
|
|
|
|
if (!initialzeModules) {
|
|
return;
|
|
}
|
|
|
|
initializeCJSLoader();
|
|
initializeESMLoader();
|
|
const CJSLoader = require('internal/modules/cjs/loader');
|
|
assert(!CJSLoader.hasLoadedAnyUserCJSModule);
|
|
loadPreloadModules();
|
|
initializeFrozenIntrinsics();
|
|
}
|
|
|
|
function refreshRuntimeOptions() {
|
|
refreshOptions();
|
|
}
|
|
|
|
function patchProcessObject(expandArgv1) {
|
|
const binding = internalBinding('process_methods');
|
|
binding.patchProcessObject(process);
|
|
|
|
require('internal/process/per_thread').refreshHrtimeBuffer();
|
|
|
|
ObjectDefineProperty(process, 'argv0', {
|
|
__proto__: null,
|
|
enumerable: true,
|
|
// Only set it to true during snapshot building.
|
|
configurable: getOptionValue('--build-snapshot'),
|
|
value: process.argv[0]
|
|
});
|
|
|
|
process.exitCode = undefined;
|
|
process._exiting = false;
|
|
process.argv[0] = process.execPath;
|
|
|
|
if (expandArgv1 && process.argv[1] &&
|
|
!StringPrototypeStartsWith(process.argv[1], '-')) {
|
|
// Expand process.argv[1] into a full path.
|
|
const path = require('path');
|
|
try {
|
|
process.argv[1] = path.resolve(process.argv[1]);
|
|
} catch {
|
|
// Continue regardless of error.
|
|
}
|
|
}
|
|
|
|
// We need to initialize the global console here again with process.stdout
|
|
// and friends for snapshot deserialization.
|
|
const globalConsole = require('internal/console/global');
|
|
const { initializeGlobalConsole } = require('internal/console/constructor');
|
|
initializeGlobalConsole(globalConsole);
|
|
|
|
// TODO(joyeecheung): most of these should be deprecated and removed,
|
|
// except some that we need to be able to mutate during run time.
|
|
addReadOnlyProcessAlias('_eval', '--eval');
|
|
addReadOnlyProcessAlias('_print_eval', '--print');
|
|
addReadOnlyProcessAlias('_syntax_check_only', '--check');
|
|
addReadOnlyProcessAlias('_forceRepl', '--interactive');
|
|
addReadOnlyProcessAlias('_preload_modules', '--require');
|
|
addReadOnlyProcessAlias('noDeprecation', '--no-deprecation');
|
|
addReadOnlyProcessAlias('noProcessWarnings', '--no-warnings');
|
|
addReadOnlyProcessAlias('traceProcessWarnings', '--trace-warnings');
|
|
addReadOnlyProcessAlias('throwDeprecation', '--throw-deprecation');
|
|
addReadOnlyProcessAlias('profProcess', '--prof-process');
|
|
addReadOnlyProcessAlias('traceDeprecation', '--trace-deprecation');
|
|
addReadOnlyProcessAlias('_breakFirstLine', '--inspect-brk', false);
|
|
addReadOnlyProcessAlias('_breakNodeFirstLine', '--inspect-brk-node', false);
|
|
}
|
|
|
|
function addReadOnlyProcessAlias(name, option, enumerable = true) {
|
|
const value = getOptionValue(option);
|
|
if (value) {
|
|
ObjectDefineProperty(process, name, {
|
|
__proto__: null,
|
|
writable: false,
|
|
configurable: true,
|
|
enumerable,
|
|
value
|
|
});
|
|
}
|
|
}
|
|
|
|
function setupWarningHandler() {
|
|
const {
|
|
onWarning,
|
|
resetForSerialization
|
|
} = require('internal/process/warning');
|
|
if (getOptionValue('--warnings') &&
|
|
process.env.NODE_NO_WARNINGS !== '1') {
|
|
process.on('warning', onWarning);
|
|
|
|
// The code above would add the listener back during deserialization,
|
|
// if applicable.
|
|
if (isBuildingSnapshot()) {
|
|
addSerializeCallback(() => {
|
|
process.removeListener('warning', onWarning);
|
|
resetForSerialization();
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
// https://fetch.spec.whatwg.org/
|
|
function setupFetch() {
|
|
if (process.config.variables.node_no_browser_globals ||
|
|
getOptionValue('--no-experimental-fetch')) {
|
|
return;
|
|
}
|
|
|
|
let undici;
|
|
function lazyUndici() {
|
|
if (undici) {
|
|
return undici;
|
|
}
|
|
|
|
undici = require('internal/deps/undici/undici');
|
|
return undici;
|
|
}
|
|
|
|
async function fetch(input, init = undefined) {
|
|
emitExperimentalWarning('The Fetch API');
|
|
return lazyUndici().fetch(input, init);
|
|
}
|
|
|
|
defineOperation(globalThis, 'fetch', fetch);
|
|
|
|
function lazyInterface(name) {
|
|
return {
|
|
configurable: true,
|
|
enumerable: false,
|
|
get() {
|
|
return lazyUndici()[name];
|
|
},
|
|
set(value) {
|
|
exposeInterface(globalThis, name, value);
|
|
}
|
|
};
|
|
}
|
|
|
|
ObjectDefineProperties(globalThis, {
|
|
FormData: lazyInterface('FormData'),
|
|
Headers: lazyInterface('Headers'),
|
|
Request: lazyInterface('Request'),
|
|
Response: lazyInterface('Response'),
|
|
});
|
|
|
|
// The WebAssembly Web API: https://webassembly.github.io/spec/web-api
|
|
const { wasmStreamingCallback } = require('internal/wasm_web_api');
|
|
internalBinding('wasm_web_api').setImplementation(wasmStreamingCallback);
|
|
}
|
|
|
|
// TODO(aduh95): move this to internal/bootstrap/browser when the CLI flag is
|
|
// removed.
|
|
function setupWebCrypto() {
|
|
if (process.config.variables.node_no_browser_globals ||
|
|
!getOptionValue('--experimental-global-webcrypto')) {
|
|
return;
|
|
}
|
|
|
|
let webcrypto;
|
|
ObjectDefineProperty(globalThis, 'crypto',
|
|
{ __proto__: null, ...ObjectGetOwnPropertyDescriptor({
|
|
get crypto() {
|
|
webcrypto ??= require('internal/crypto/webcrypto');
|
|
return webcrypto.crypto;
|
|
}
|
|
}, 'crypto') });
|
|
if (internalBinding('config').hasOpenSSL) {
|
|
webcrypto ??= require('internal/crypto/webcrypto');
|
|
exposeInterface(globalThis, 'Crypto', webcrypto.Crypto);
|
|
exposeInterface(globalThis, 'CryptoKey', webcrypto.CryptoKey);
|
|
exposeInterface(globalThis, 'SubtleCrypto', webcrypto.SubtleCrypto);
|
|
}
|
|
}
|
|
|
|
// TODO(daeyeon): move this to internal/bootstrap/browser when the CLI flag is
|
|
// removed.
|
|
function setupCustomEvent() {
|
|
if (process.config.variables.node_no_browser_globals ||
|
|
!getOptionValue('--experimental-global-customevent')) {
|
|
return;
|
|
}
|
|
const { CustomEvent } = require('internal/event_target');
|
|
exposeInterface(globalThis, 'CustomEvent', CustomEvent);
|
|
}
|
|
|
|
// Setup User-facing NODE_V8_COVERAGE environment variable that writes
|
|
// ScriptCoverage to a specified file.
|
|
function setupCoverageHooks(dir) {
|
|
const cwd = require('internal/process/execution').tryGetCwd();
|
|
const { resolve } = require('path');
|
|
const coverageDirectory = resolve(cwd, dir);
|
|
const { sourceMapCacheToObject } =
|
|
require('internal/source_map/source_map_cache');
|
|
|
|
if (process.features.inspector) {
|
|
internalBinding('profiler').setCoverageDirectory(coverageDirectory);
|
|
internalBinding('profiler').setSourceMapCacheGetter(sourceMapCacheToObject);
|
|
} else {
|
|
process.emitWarning('The inspector is disabled, ' +
|
|
'coverage could not be collected',
|
|
'Warning');
|
|
return '';
|
|
}
|
|
return coverageDirectory;
|
|
}
|
|
|
|
function setupStacktracePrinterOnSigint() {
|
|
if (!getOptionValue('--trace-sigint')) {
|
|
return;
|
|
}
|
|
const { SigintWatchdog } = require('internal/watchdog');
|
|
|
|
const watchdog = new SigintWatchdog();
|
|
watchdog.start();
|
|
}
|
|
|
|
function initializeReport() {
|
|
const { report } = require('internal/process/report');
|
|
ObjectDefineProperty(process, 'report', {
|
|
__proto__: null,
|
|
enumerable: true,
|
|
configurable: true,
|
|
get() {
|
|
return report;
|
|
}
|
|
});
|
|
}
|
|
|
|
function setupDebugEnv() {
|
|
require('internal/util/debuglog').initializeDebugEnv(process.env.NODE_DEBUG);
|
|
if (getOptionValue('--expose-internals')) {
|
|
require('internal/bootstrap/loaders').BuiltinModule.exposeInternals();
|
|
}
|
|
}
|
|
|
|
// This has to be called after initializeReport() is called
|
|
function initializeReportSignalHandlers() {
|
|
const { addSignalHandler } = require('internal/process/report');
|
|
|
|
addSignalHandler();
|
|
}
|
|
|
|
function initializeHeapSnapshotSignalHandlers() {
|
|
const signal = getOptionValue('--heapsnapshot-signal');
|
|
|
|
if (!signal)
|
|
return;
|
|
|
|
require('internal/validators').validateSignalName(signal);
|
|
const { writeHeapSnapshot } = require('v8');
|
|
|
|
function doWriteHeapSnapshot() {
|
|
writeHeapSnapshot();
|
|
}
|
|
process.on(signal, doWriteHeapSnapshot);
|
|
|
|
// The code above would add the listener back during deserialization,
|
|
// if applicable.
|
|
if (isBuildingSnapshot()) {
|
|
addSerializeCallback(() => {
|
|
process.removeListener(signal, doWriteHeapSnapshot);
|
|
});
|
|
}
|
|
}
|
|
|
|
function setupTraceCategoryState() {
|
|
const { isTraceCategoryEnabled } = internalBinding('trace_events');
|
|
const { toggleTraceCategoryState } = require('internal/process/per_thread');
|
|
toggleTraceCategoryState(isTraceCategoryEnabled('node.async_hooks'));
|
|
}
|
|
|
|
function setupPerfHooks() {
|
|
require('internal/perf/performance').refreshTimeOrigin();
|
|
require('internal/perf/utils').refreshTimeOrigin();
|
|
}
|
|
|
|
function setupInspectorHooks() {
|
|
// If Debugger.setAsyncCallStackDepth is sent during bootstrap,
|
|
// we cannot immediately call into JS to enable the hooks, which could
|
|
// interrupt the JS execution of bootstrap. So instead we save the
|
|
// notification in the inspector agent if it's sent in the middle of
|
|
// bootstrap, and process the notification later here.
|
|
if (internalBinding('config').hasInspector) {
|
|
const {
|
|
enable,
|
|
disable
|
|
} = require('internal/inspector_async_hook');
|
|
internalBinding('inspector').registerAsyncHook(enable, disable);
|
|
}
|
|
}
|
|
|
|
// In general deprecations are initialized wherever the APIs are implemented,
|
|
// this is used to deprecate APIs implemented in C++ where the deprecation
|
|
// utilities are not easily accessible.
|
|
function initializeDeprecations() {
|
|
const { deprecate } = require('internal/util');
|
|
const pendingDeprecation = getOptionValue('--pending-deprecation');
|
|
|
|
// DEP0103: access to `process.binding('util').isX` type checkers
|
|
// TODO(addaleax): Turn into a full runtime deprecation.
|
|
const utilBinding = internalBinding('util');
|
|
const types = require('internal/util/types');
|
|
for (const name of [
|
|
'isArrayBuffer',
|
|
'isArrayBufferView',
|
|
'isAsyncFunction',
|
|
'isDataView',
|
|
'isDate',
|
|
'isExternal',
|
|
'isMap',
|
|
'isMapIterator',
|
|
'isNativeError',
|
|
'isPromise',
|
|
'isRegExp',
|
|
'isSet',
|
|
'isSetIterator',
|
|
'isTypedArray',
|
|
'isUint8Array',
|
|
'isAnyArrayBuffer',
|
|
]) {
|
|
utilBinding[name] = pendingDeprecation ?
|
|
deprecate(types[name],
|
|
'Accessing native typechecking bindings of Node ' +
|
|
'directly is deprecated. ' +
|
|
`Please use \`util.types.${name}\` instead.`,
|
|
'DEP0103') :
|
|
types[name];
|
|
}
|
|
|
|
// TODO(joyeecheung): this is a legacy property exposed to process.
|
|
// Now that we use the config binding to carry this information, remove
|
|
// it from the process. We may consider exposing it properly in
|
|
// process.features.
|
|
const { noBrowserGlobals } = internalBinding('config');
|
|
if (noBrowserGlobals) {
|
|
ObjectDefineProperty(process, '_noBrowserGlobals', {
|
|
__proto__: null,
|
|
writable: false,
|
|
enumerable: true,
|
|
configurable: true,
|
|
value: noBrowserGlobals
|
|
});
|
|
}
|
|
|
|
if (pendingDeprecation) {
|
|
process.binding = deprecate(process.binding,
|
|
'process.binding() is deprecated. ' +
|
|
'Please use public APIs instead.', 'DEP0111');
|
|
|
|
process._tickCallback = deprecate(process._tickCallback,
|
|
'process._tickCallback() is deprecated',
|
|
'DEP0134');
|
|
}
|
|
}
|
|
|
|
function setupChildProcessIpcChannel() {
|
|
if (process.env.NODE_CHANNEL_FD) {
|
|
const assert = require('internal/assert');
|
|
|
|
const fd = NumberParseInt(process.env.NODE_CHANNEL_FD, 10);
|
|
assert(fd >= 0);
|
|
|
|
// Make sure it's not accidentally inherited by child processes.
|
|
delete process.env.NODE_CHANNEL_FD;
|
|
|
|
const serializationMode =
|
|
process.env.NODE_CHANNEL_SERIALIZATION_MODE || 'json';
|
|
delete process.env.NODE_CHANNEL_SERIALIZATION_MODE;
|
|
|
|
require('child_process')._forkChild(fd, serializationMode);
|
|
assert(process.send);
|
|
}
|
|
}
|
|
|
|
function initializeClusterIPC() {
|
|
if (process.argv[1] && process.env.NODE_UNIQUE_ID) {
|
|
const cluster = require('cluster');
|
|
cluster._setupWorker();
|
|
// Make sure it's not accidentally inherited by child processes.
|
|
delete process.env.NODE_UNIQUE_ID;
|
|
}
|
|
}
|
|
|
|
function initializePolicy() {
|
|
const experimentalPolicy = getOptionValue('--experimental-policy');
|
|
if (experimentalPolicy) {
|
|
process.emitWarning('Policies are experimental.',
|
|
'ExperimentalWarning');
|
|
const { pathToFileURL, URL } = require('internal/url');
|
|
// URL here as it is slightly different parsing
|
|
// no bare specifiers for now
|
|
let manifestURL;
|
|
if (require('path').isAbsolute(experimentalPolicy)) {
|
|
manifestURL = new URL(`file://${experimentalPolicy}`);
|
|
} else {
|
|
const cwdURL = pathToFileURL(process.cwd());
|
|
cwdURL.pathname += '/';
|
|
manifestURL = new URL(experimentalPolicy, cwdURL);
|
|
}
|
|
const fs = require('fs');
|
|
const src = fs.readFileSync(manifestURL, 'utf8');
|
|
const experimentalPolicyIntegrity = getOptionValue('--policy-integrity');
|
|
if (experimentalPolicyIntegrity) {
|
|
const SRI = require('internal/policy/sri');
|
|
const { createHash, timingSafeEqual } = require('crypto');
|
|
const realIntegrities = new SafeMap();
|
|
const integrityEntries = SRI.parse(experimentalPolicyIntegrity);
|
|
let foundMatch = false;
|
|
for (let i = 0; i < integrityEntries.length; i++) {
|
|
const {
|
|
algorithm,
|
|
value: expected
|
|
} = integrityEntries[i];
|
|
const hash = createHash(algorithm);
|
|
hash.update(src);
|
|
const digest = hash.digest();
|
|
if (digest.length === expected.length &&
|
|
timingSafeEqual(digest, expected)) {
|
|
foundMatch = true;
|
|
break;
|
|
}
|
|
realIntegrities.set(algorithm, digest.toString('base64'));
|
|
}
|
|
if (!foundMatch) {
|
|
throw new ERR_MANIFEST_ASSERT_INTEGRITY(manifestURL, realIntegrities);
|
|
}
|
|
}
|
|
require('internal/process/policy')
|
|
.setup(src, manifestURL.href);
|
|
}
|
|
}
|
|
|
|
function initializeWASI() {
|
|
const { BuiltinModule } = require('internal/bootstrap/loaders');
|
|
const mod = BuiltinModule.map.get('wasi');
|
|
mod.canBeRequiredByUsers =
|
|
getOptionValue('--experimental-wasi-unstable-preview1');
|
|
}
|
|
|
|
function initializeCJSLoader() {
|
|
const CJSLoader = require('internal/modules/cjs/loader');
|
|
if (!getEmbedderOptions().noGlobalSearchPaths) {
|
|
CJSLoader.Module._initPaths();
|
|
}
|
|
// TODO(joyeecheung): deprecate this in favor of a proper hook?
|
|
CJSLoader.Module.runMain =
|
|
require('internal/modules/run_main').executeUserEntryPoint;
|
|
}
|
|
|
|
function initializeESMLoader() {
|
|
// Create this WeakMap in js-land because V8 has no C++ API for WeakMap.
|
|
internalBinding('module_wrap').callbackMap = new SafeWeakMap();
|
|
|
|
if (getEmbedderOptions().shouldNotRegisterESMLoader) return;
|
|
|
|
const {
|
|
setImportModuleDynamicallyCallback,
|
|
setInitializeImportMetaObjectCallback
|
|
} = internalBinding('module_wrap');
|
|
const esm = require('internal/process/esm_loader');
|
|
// Setup per-isolate callbacks that locate data or callbacks that we keep
|
|
// track of for different ESM modules.
|
|
setInitializeImportMetaObjectCallback(esm.initializeImportMetaObject);
|
|
setImportModuleDynamicallyCallback(esm.importModuleDynamicallyCallback);
|
|
|
|
// Patch the vm module when --experimental-vm-modules is on.
|
|
// Please update the comments in vm.js when this block changes.
|
|
if (getOptionValue('--experimental-vm-modules')) {
|
|
const {
|
|
Module, SourceTextModule, SyntheticModule,
|
|
} = require('internal/vm/module');
|
|
const vm = require('vm');
|
|
vm.Module = Module;
|
|
vm.SourceTextModule = SourceTextModule;
|
|
vm.SyntheticModule = SyntheticModule;
|
|
}
|
|
}
|
|
|
|
function initializeSourceMapsHandlers() {
|
|
const { setSourceMapsEnabled } =
|
|
require('internal/source_map/source_map_cache');
|
|
process.setSourceMapsEnabled = setSourceMapsEnabled;
|
|
}
|
|
|
|
function initializeFrozenIntrinsics() {
|
|
if (getOptionValue('--frozen-intrinsics')) {
|
|
process.emitWarning('The --frozen-intrinsics flag is experimental',
|
|
'ExperimentalWarning');
|
|
require('internal/freeze_intrinsics')();
|
|
}
|
|
}
|
|
|
|
function loadPreloadModules() {
|
|
// For user code, we preload modules if `-r` is passed
|
|
const preloadModules = getOptionValue('--require');
|
|
if (preloadModules && preloadModules.length > 0) {
|
|
const {
|
|
Module: {
|
|
_preloadModules
|
|
},
|
|
} = require('internal/modules/cjs/loader');
|
|
_preloadModules(preloadModules);
|
|
}
|
|
}
|
|
|
|
function markBootstrapComplete() {
|
|
internalBinding('performance').markBootstrapComplete();
|
|
}
|
|
|
|
module.exports = {
|
|
refreshRuntimeOptions,
|
|
patchProcessObject,
|
|
setupCoverageHooks,
|
|
setupWarningHandler,
|
|
setupFetch,
|
|
setupWebCrypto,
|
|
setupCustomEvent,
|
|
setupDebugEnv,
|
|
setupPerfHooks,
|
|
prepareMainThreadExecution,
|
|
initializeDeprecations,
|
|
initializeESMLoader,
|
|
initializeFrozenIntrinsics,
|
|
initializeSourceMapsHandlers,
|
|
loadPreloadModules,
|
|
setupTraceCategoryState,
|
|
setupInspectorHooks,
|
|
initializeReport,
|
|
initializeCJSLoader,
|
|
initializeWASI,
|
|
markBootstrapComplete
|
|
};
|