summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatt Mastracci <matthew@mastracci.com>2024-03-22 13:49:07 -0700
committerGitHub <noreply@github.com>2024-03-22 20:49:07 +0000
commit08ec6e5831478f6d15188e91d9a8e3c00d80c1ed (patch)
tree13a830c1ab1ee2ce5ebcffe5c0fcecd77146c8bc
parent9c2f9f14e749e4dd63ad02e3ca8af5fc8bd112ee (diff)
perf: warm expensive init code at snapshot time (#22714)
Slightly different approach to similar changes in #22386 Note that this doesn't use a warmup script -- we are actually just doing more work at snapshot time.
-rw-r--r--ext/node/polyfills/02_init.js67
-rw-r--r--ext/node/polyfills/_process/streams.mjs16
-rw-r--r--ext/node/polyfills/process.ts120
-rw-r--r--runtime/js/99_main.js526
4 files changed, 385 insertions, 344 deletions
diff --git a/ext/node/polyfills/02_init.js b/ext/node/polyfills/02_init.js
index 85f924493..752f518bf 100644
--- a/ext/node/polyfills/02_init.js
+++ b/ext/node/polyfills/02_init.js
@@ -16,38 +16,32 @@ function initialize(
runningOnMainThread,
workerId,
maybeWorkerMetadata,
+ warmup = false,
) {
- if (initialized) {
- throw Error("Node runtime already initialized");
- }
- initialized = true;
- if (usesLocalNodeModulesDir) {
- requireImpl.setUsesLocalNodeModulesDir();
- }
- const nativeModuleExports = requireImpl.nativeModuleExports;
- nodeGlobals.Buffer = nativeModuleExports["buffer"].Buffer;
- nodeGlobals.clearImmediate = nativeModuleExports["timers"].clearImmediate;
- nodeGlobals.clearInterval = nativeModuleExports["timers"].clearInterval;
- nodeGlobals.clearTimeout = nativeModuleExports["timers"].clearTimeout;
- nodeGlobals.console = nativeModuleExports["console"];
- nodeGlobals.global = globalThis;
- nodeGlobals.process = nativeModuleExports["process"];
- nodeGlobals.setImmediate = nativeModuleExports["timers"].setImmediate;
- nodeGlobals.setInterval = nativeModuleExports["timers"].setInterval;
- nodeGlobals.setTimeout = nativeModuleExports["timers"].setTimeout;
- nodeGlobals.performance = nativeModuleExports["perf_hooks"].performance;
+ if (!warmup) {
+ if (initialized) {
+ throw Error("Node runtime already initialized");
+ }
+ initialized = true;
+ if (usesLocalNodeModulesDir) {
+ requireImpl.setUsesLocalNodeModulesDir();
+ }
- // FIXME(bartlomieju): not nice to depend on `Deno` namespace here
- // but it's the only way to get `args` and `version` and this point.
- internals.__bootstrapNodeProcess(argv0, Deno.args, Deno.version);
- internals.__initWorkerThreads(
- runningOnMainThread,
- workerId,
- maybeWorkerMetadata,
- );
- internals.__setupChildProcessIpcChannel();
- // `Deno[Deno.internal].requireImpl` will be unreachable after this line.
- delete internals.requireImpl;
+ // FIXME(bartlomieju): not nice to depend on `Deno` namespace here
+ // but it's the only way to get `args` and `version` and this point.
+ internals.__bootstrapNodeProcess(argv0, Deno.args, Deno.version);
+ internals.__initWorkerThreads(
+ runningOnMainThread,
+ workerId,
+ maybeWorkerMetadata,
+ );
+ internals.__setupChildProcessIpcChannel();
+ // `Deno[Deno.internal].requireImpl` will be unreachable after this line.
+ delete internals.requireImpl;
+ } else {
+ // Warm up the process module
+ internals.__bootstrapNodeProcess(undefined, undefined, undefined, true);
+ }
}
function loadCjsModule(moduleName, isMain, inspectBrk) {
@@ -63,3 +57,16 @@ internals.node = {
initialize,
loadCjsModule,
};
+
+const nativeModuleExports = requireImpl.nativeModuleExports;
+nodeGlobals.Buffer = nativeModuleExports["buffer"].Buffer;
+nodeGlobals.clearImmediate = nativeModuleExports["timers"].clearImmediate;
+nodeGlobals.clearInterval = nativeModuleExports["timers"].clearInterval;
+nodeGlobals.clearTimeout = nativeModuleExports["timers"].clearTimeout;
+nodeGlobals.console = nativeModuleExports["console"];
+nodeGlobals.global = globalThis;
+nodeGlobals.process = nativeModuleExports["process"];
+nodeGlobals.setImmediate = nativeModuleExports["timers"].setImmediate;
+nodeGlobals.setInterval = nativeModuleExports["timers"].setInterval;
+nodeGlobals.setTimeout = nativeModuleExports["timers"].setTimeout;
+nodeGlobals.performance = nativeModuleExports["perf_hooks"].performance;
diff --git a/ext/node/polyfills/_process/streams.mjs b/ext/node/polyfills/_process/streams.mjs
index 09c53eb9a..f50e20588 100644
--- a/ext/node/polyfills/_process/streams.mjs
+++ b/ext/node/polyfills/_process/streams.mjs
@@ -16,7 +16,7 @@ import * as io from "ext:deno_io/12_io.js";
import { guessHandleType } from "ext:deno_node/internal_binding/util.ts";
// https://github.com/nodejs/node/blob/00738314828074243c9a52a228ab4c68b04259ef/lib/internal/bootstrap/switches/is_main_thread.js#L41
-export function createWritableStdioStream(writer, name) {
+export function createWritableStdioStream(writer, name, warmup = false) {
const stream = new Writable({
emitClose: false,
write(buf, enc, cb) {
@@ -73,7 +73,9 @@ export function createWritableStdioStream(writer, name) {
},
});
- if (writer?.isTerminal()) {
+ // If we're warming up, create a stdout/stderr stream that assumes a terminal (the most likely case).
+ // If we're wrong at boot time, we'll recreate it.
+ if (warmup || writer?.isTerminal()) {
// These belong on tty.WriteStream(), but the TTY streams currently have
// following problems:
// 1. Using them here introduces a circular dependency.
@@ -123,10 +125,11 @@ export function setReadStream(s) {
/** https://nodejs.org/api/process.html#process_process_stdin */
// https://github.com/nodejs/node/blob/v18.12.1/lib/internal/bootstrap/switches/is_main_thread.js#L189
/** Create process.stdin */
-export const initStdin = () => {
+export const initStdin = (warmup = false) => {
const fd = io.stdin ? io.STDIN_RID : undefined;
let stdin;
- const stdinType = _guessStdinType(fd);
+ // Warmup assumes a TTY for all stdio
+ const stdinType = warmup ? "TTY" : _guessStdinType(fd);
switch (stdinType) {
case "FILE": {
@@ -142,6 +145,11 @@ export const initStdin = () => {
break;
}
case "TTY": {
+ // If it's a TTY, we know that the stdin we created during warmup is the correct one and
+ // just return null to re-use it.
+ if (!warmup) {
+ return null;
+ }
stdin = new readStream(fd);
break;
}
diff --git a/ext/node/polyfills/process.ts b/ext/node/polyfills/process.ts
index 44207e2f4..70c516c96 100644
--- a/ext/node/polyfills/process.ts
+++ b/ext/node/polyfills/process.ts
@@ -68,7 +68,7 @@ const notImplementedEvents = [
"worker",
];
-export const argv: string[] = [];
+export const argv: string[] = ["", ""];
let globalProcessExitCode: number | undefined = undefined;
/** https://nodejs.org/api/process.html#process_process_exit_code */
@@ -868,69 +868,91 @@ function synchronizeListeners() {
}
}
+// Overwrites the 1st and 2nd items with getters.
+Object.defineProperty(argv, "0", { get: () => argv0 });
+Object.defineProperty(argv, "1", {
+ get: () => {
+ if (Deno.mainModule?.startsWith("file:")) {
+ return pathFromURL(new URL(Deno.mainModule));
+ } else {
+ return join(Deno.cwd(), "$deno$node.js");
+ }
+ },
+});
+
// Should be called only once, in `runtime/js/99_main.js` when the runtime is
// bootstrapped.
internals.__bootstrapNodeProcess = function (
argv0Val: string | undefined,
args: string[],
denoVersions: Record<string, string>,
+ warmup = false,
) {
- // Overwrites the 1st item with getter.
- if (typeof argv0Val === "string") {
- argv0 = argv0Val;
- Object.defineProperty(argv, "0", {
- get: () => {
- return argv0Val;
- },
- });
- } else {
- Object.defineProperty(argv, "0", { get: () => argv0 });
- }
+ if (!warmup) {
+ argv0 = argv0Val || "";
+ // Manually concatenate these arrays to avoid triggering the getter
+ for (let i = 0; i < args.length; i++) {
+ argv[i + 2] = args[i];
+ }
- // Overwrites the 2st item with getter.
- Object.defineProperty(argv, "1", {
- get: () => {
- if (Deno.mainModule?.startsWith("file:")) {
- return pathFromURL(new URL(Deno.mainModule));
- } else {
- return join(Deno.cwd(), "$deno$node.js");
- }
- },
- });
- for (let i = 0; i < args.length; i++) {
- argv[i + 2] = args[i];
- }
+ for (const [key, value] of Object.entries(denoVersions)) {
+ versions[key] = value;
+ }
- for (const [key, value] of Object.entries(denoVersions)) {
- versions[key] = value;
- }
+ core.setNextTickCallback(processTicksAndRejections);
+ core.setMacrotaskCallback(runNextTicks);
+ enableNextTick();
- core.setNextTickCallback(processTicksAndRejections);
- core.setMacrotaskCallback(runNextTicks);
- enableNextTick();
+ // Replace stdin if it is not a terminal
+ const newStdin = initStdin();
+ if (newStdin) {
+ stdin = process.stdin = newStdin;
+ }
- stdin = process.stdin = initStdin();
- /** https://nodejs.org/api/process.html#process_process_stdout */
- stdout = process.stdout = createWritableStdioStream(
- io.stdout,
- "stdout",
- );
+ // Replace stdout/stderr if they are not terminals
+ if (!io.stdout.isTerminal()) {
+ /** https://nodejs.org/api/process.html#process_process_stdout */
+ stdout = process.stdout = createWritableStdioStream(
+ io.stdout,
+ "stdout",
+ );
+ }
- /** https://nodejs.org/api/process.html#process_process_stderr */
- stderr = process.stderr = createWritableStdioStream(
- io.stderr,
- "stderr",
- );
+ if (!io.stderr.isTerminal()) {
+ /** https://nodejs.org/api/process.html#process_process_stderr */
+ stderr = process.stderr = createWritableStdioStream(
+ io.stderr,
+ "stderr",
+ );
+ }
- process.setStartTime(Date.now());
+ process.setStartTime(Date.now());
- arch = arch_();
- platform = isWindows ? "win32" : Deno.build.os;
- pid = Deno.pid;
+ arch = arch_();
+ platform = isWindows ? "win32" : Deno.build.os;
+ pid = Deno.pid;
- // @ts-ignore Remove setStartTime and #startTime is not modifiable
- delete process.setStartTime;
- delete internals.__bootstrapNodeProcess;
+ // @ts-ignore Remove setStartTime and #startTime is not modifiable
+ delete process.setStartTime;
+ delete internals.__bootstrapNodeProcess;
+ } else {
+ // Warmup, assuming stdin/stdout/stderr are all terminals
+ stdin = process.stdin = initStdin(true);
+
+ /** https://nodejs.org/api/process.html#process_process_stdout */
+ stdout = process.stdout = createWritableStdioStream(
+ io.stdout,
+ "stdout",
+ true,
+ );
+
+ /** https://nodejs.org/api/process.html#process_process_stderr */
+ stderr = process.stderr = createWritableStdioStream(
+ io.stderr,
+ "stderr",
+ true,
+ );
+ }
};
export default process;
diff --git a/runtime/js/99_main.js b/runtime/js/99_main.js
index 1a1f78119..a47a7163e 100644
--- a/runtime/js/99_main.js
+++ b/runtime/js/99_main.js
@@ -628,6 +628,28 @@ const finalDenoNs = {
bench: () => {},
};
+ObjectDefineProperties(finalDenoNs, {
+ pid: core.propGetterOnly(opPid),
+ // `ppid` should not be memoized.
+ // https://github.com/denoland/deno/issues/23004
+ ppid: core.propGetterOnly(() => op_ppid()),
+ noColor: core.propGetterOnly(() => op_bootstrap_no_color()),
+ args: core.propGetterOnly(opArgs),
+ mainModule: core.propGetterOnly(() => op_main_module()),
+ // TODO(kt3k): Remove this export at v2
+ // See https://github.com/denoland/deno/issues/9294
+ customInspect: {
+ get() {
+ warnOnDeprecatedApi(
+ "Deno.customInspect",
+ new Error().stack,
+ 'Use `Symbol.for("Deno.customInspect")` instead.',
+ );
+ return customInspect;
+ },
+ },
+});
+
const {
denoVersion,
tsVersion,
@@ -635,155 +657,130 @@ const {
target,
} = op_snapshot_options();
-function bootstrapMainRuntime(runtimeOptions) {
- if (hasBootstrapped) {
- throw new Error("Worker runtime already bootstrapped");
- }
- const nodeBootstrap = globalThis.nodeBootstrap;
-
- const {
- 0: location_,
- 1: unstableFlag,
- 2: unstableFeatures,
- 3: inspectFlag,
- 5: hasNodeModulesDir,
- 6: argv0,
- 7: shouldDisableDeprecatedApiWarning,
- 8: shouldUseVerboseDeprecatedApiWarning,
- 9: future,
- } = runtimeOptions;
-
- removeImportedOps();
-
- deprecatedApiWarningDisabled = shouldDisableDeprecatedApiWarning;
- verboseDeprecatedApiWarning = shouldUseVerboseDeprecatedApiWarning;
- performance.setTimeOrigin(DateNow());
- globalThis_ = globalThis;
-
- // Remove bootstrapping data from the global scope
- delete globalThis.__bootstrap;
- delete globalThis.bootstrap;
- delete globalThis.nodeBootstrap;
- hasBootstrapped = true;
-
- // If the `--location` flag isn't set, make `globalThis.location` `undefined` and
- // writable, so that they can mock it themselves if they like. If the flag was
- // set, define `globalThis.location`, using the provided value.
- if (location_ == null) {
- mainRuntimeGlobalProperties.location = {
- writable: true,
- };
- } else {
- location.setLocationHref(location_);
- }
+function bootstrapMainRuntime(runtimeOptions, warmup = false) {
+ if (!warmup) {
+ if (hasBootstrapped) {
+ throw new Error("Worker runtime already bootstrapped");
+ }
- exposeUnstableFeaturesForWindowOrWorkerGlobalScope({
- unstableFlag,
- unstableFeatures,
- });
- ObjectDefineProperties(globalThis, mainRuntimeGlobalProperties);
- ObjectDefineProperties(globalThis, {
- // TODO(bartlomieju): in the future we might want to change the
- // behavior of setting `name` to actually update the process name.
- // Empty string matches what browsers do.
- name: core.propWritable(""),
- close: core.propWritable(windowClose),
- closed: core.propGetterOnly(() => windowIsClosing),
- });
- ObjectSetPrototypeOf(globalThis, Window.prototype);
+ const {
+ 0: location_,
+ 1: unstableFlag,
+ 2: unstableFeatures,
+ 3: inspectFlag,
+ 5: hasNodeModulesDir,
+ 6: argv0,
+ 7: shouldDisableDeprecatedApiWarning,
+ 8: shouldUseVerboseDeprecatedApiWarning,
+ 9: future,
+ } = runtimeOptions;
+
+ removeImportedOps();
+
+ deprecatedApiWarningDisabled = shouldDisableDeprecatedApiWarning;
+ verboseDeprecatedApiWarning = shouldUseVerboseDeprecatedApiWarning;
+ performance.setTimeOrigin(DateNow());
+ globalThis_ = globalThis;
+
+ // Remove bootstrapping data from the global scope
+ delete globalThis.__bootstrap;
+ delete globalThis.bootstrap;
+ hasBootstrapped = true;
+
+ // If the `--location` flag isn't set, make `globalThis.location` `undefined` and
+ // writable, so that they can mock it themselves if they like. If the flag was
+ // set, define `globalThis.location`, using the provided value.
+ if (location_ == null) {
+ mainRuntimeGlobalProperties.location = {
+ writable: true,
+ };
+ } else {
+ location.setLocationHref(location_);
+ }
- if (inspectFlag) {
- const consoleFromDeno = globalThis.console;
- core.wrapConsole(consoleFromDeno, core.v8Console);
- }
+ exposeUnstableFeaturesForWindowOrWorkerGlobalScope({
+ unstableFlag,
+ unstableFeatures,
+ });
+ ObjectDefineProperties(globalThis, mainRuntimeGlobalProperties);
+ ObjectDefineProperties(globalThis, {
+ // TODO(bartlomieju): in the future we might want to change the
+ // behavior of setting `name` to actually update the process name.
+ // Empty string matches what browsers do.
+ name: core.propWritable(""),
+ close: core.propWritable(windowClose),
+ closed: core.propGetterOnly(() => windowIsClosing),
+ });
+ ObjectSetPrototypeOf(globalThis, Window.prototype);
- event.setEventTargetData(globalThis);
- event.saveGlobalThisReference(globalThis);
+ if (inspectFlag) {
+ const consoleFromDeno = globalThis.console;
+ core.wrapConsole(consoleFromDeno, core.v8Console);
+ }
- event.defineEventHandler(globalThis, "error");
- event.defineEventHandler(globalThis, "load");
- event.defineEventHandler(globalThis, "beforeunload");
- event.defineEventHandler(globalThis, "unload");
- event.defineEventHandler(globalThis, "unhandledrejection");
+ event.defineEventHandler(globalThis, "error");
+ event.defineEventHandler(globalThis, "load");
+ event.defineEventHandler(globalThis, "beforeunload");
+ event.defineEventHandler(globalThis, "unload");
- runtimeStart(
- denoVersion,
- v8Version,
- tsVersion,
- target,
- );
-
- ObjectDefineProperties(finalDenoNs, {
- pid: core.propGetterOnly(opPid),
- // `ppid` should not be memoized.
- // https://github.com/denoland/deno/issues/23004
- ppid: core.propGetterOnly(() => op_ppid()),
- noColor: core.propGetterOnly(() => op_bootstrap_no_color()),
- args: core.propGetterOnly(opArgs),
- mainModule: core.propGetterOnly(() => op_main_module()),
- // TODO(kt3k): Remove this export at v2
- // See https://github.com/denoland/deno/issues/9294
- customInspect: {
- get() {
- warnOnDeprecatedApi(
- "Deno.customInspect",
- new Error().stack,
- 'Use `Symbol.for("Deno.customInspect")` instead.',
- );
- return customInspect;
- },
- },
- });
+ runtimeStart(
+ denoVersion,
+ v8Version,
+ tsVersion,
+ target,
+ );
- // TODO(bartlomieju): deprecate --unstable
- if (unstableFlag) {
- ObjectAssign(finalDenoNs, denoNsUnstable);
- // TODO(bartlomieju): this is not ideal, but because we use `ObjectAssign`
- // above any properties that are defined elsewhere using `Object.defineProperty`
- // are lost.
- let jupyterNs = undefined;
- ObjectDefineProperty(finalDenoNs, "jupyter", {
- get() {
- if (jupyterNs) {
- return jupyterNs;
- }
- throw new Error(
- "Deno.jupyter is only available in `deno jupyter` subcommand.",
- );
- },
- set(val) {
- jupyterNs = val;
- },
- });
- } else {
- for (let i = 0; i <= unstableFeatures.length; i++) {
- const id = unstableFeatures[i];
- ObjectAssign(finalDenoNs, denoNsUnstableById[id]);
+ // TODO(bartlomieju): deprecate --unstable
+ if (unstableFlag) {
+ ObjectAssign(finalDenoNs, denoNsUnstable);
+ // TODO(bartlomieju): this is not ideal, but because we use `ObjectAssign`
+ // above any properties that are defined elsewhere using `Object.defineProperty`
+ // are lost.
+ let jupyterNs = undefined;
+ ObjectDefineProperty(finalDenoNs, "jupyter", {
+ get() {
+ if (jupyterNs) {
+ return jupyterNs;
+ }
+ throw new Error(
+ "Deno.jupyter is only available in `deno jupyter` subcommand.",
+ );
+ },
+ set(val) {
+ jupyterNs = val;
+ },
+ });
+ } else {
+ for (let i = 0; i <= unstableFeatures.length; i++) {
+ const id = unstableFeatures[i];
+ ObjectAssign(finalDenoNs, denoNsUnstableById[id]);
+ }
}
- }
- if (!ArrayPrototypeIncludes(unstableFeatures, unstableIds.unsafeProto)) {
- // Removes the `__proto__` for security reasons.
- // https://tc39.es/ecma262/#sec-get-object.prototype.__proto__
- delete Object.prototype.__proto__;
- }
+ if (!ArrayPrototypeIncludes(unstableFeatures, unstableIds.unsafeProto)) {
+ // Removes the `__proto__` for security reasons.
+ // https://tc39.es/ecma262/#sec-get-object.prototype.__proto__
+ delete Object.prototype.__proto__;
+ }
- if (!ArrayPrototypeIncludes(unstableFeatures, unstableIds.temporal)) {
- // Removes the `Temporal` API.
- delete globalThis.Temporal;
- delete globalThis.Date.prototype.toTemporalInstant;
- }
+ if (!ArrayPrototypeIncludes(unstableFeatures, unstableIds.temporal)) {
+ // Removes the `Temporal` API.
+ delete globalThis.Temporal;
+ delete globalThis.Date.prototype.toTemporalInstant;
+ }
- // Setup `Deno` global - we're actually overriding already existing global
- // `Deno` with `Deno` namespace from "./deno.ts".
- ObjectDefineProperty(globalThis, "Deno", core.propReadOnly(finalDenoNs));
+ // Setup `Deno` global - we're actually overriding already existing global
+ // `Deno` with `Deno` namespace from "./deno.ts".
+ ObjectDefineProperty(globalThis, "Deno", core.propReadOnly(finalDenoNs));
- if (nodeBootstrap) {
- nodeBootstrap(hasNodeModulesDir, argv0, /* runningOnMainThread */ true);
- }
-
- if (future) {
- delete globalThis.window;
+ if (nodeBootstrap) {
+ nodeBootstrap(hasNodeModulesDir, argv0, /* runningOnMainThread */ true);
+ }
+ if (future) {
+ delete globalThis.window;
+ }
+ } else {
+ // Warmup
}
}
@@ -793,146 +790,153 @@ function bootstrapWorkerRuntime(
internalName,
workerId,
maybeWorkerMetadata,
+ warmup = false,
) {
- if (hasBootstrapped) {
- throw new Error("Worker runtime already bootstrapped");
- }
-
- const nodeBootstrap = globalThis.nodeBootstrap;
-
- const {
- 0: location_,
- 1: unstableFlag,
- 2: unstableFeatures,
- 4: enableTestingFeaturesFlag,
- 5: hasNodeModulesDir,
- 6: argv0,
- 7: shouldDisableDeprecatedApiWarning,
- 8: shouldUseVerboseDeprecatedApiWarning,
- 9: _future,
- } = runtimeOptions;
-
- deprecatedApiWarningDisabled = shouldDisableDeprecatedApiWarning;
- verboseDeprecatedApiWarning = shouldUseVerboseDeprecatedApiWarning;
- performance.setTimeOrigin(DateNow());
- globalThis_ = globalThis;
-
- removeImportedOps();
-
- // Remove bootstrapping data from the global scope
- delete globalThis.__bootstrap;
- delete globalThis.bootstrap;
- delete globalThis.nodeBootstrap;
- hasBootstrapped = true;
-
- exposeUnstableFeaturesForWindowOrWorkerGlobalScope({
- unstableFlag,
- unstableFeatures,
- });
- ObjectDefineProperties(globalThis, workerRuntimeGlobalProperties);
- ObjectDefineProperties(globalThis, {
- name: core.propWritable(name),
- // TODO(bartlomieju): should be readonly?
- close: core.propNonEnumerable(workerClose),
- postMessage: core.propWritable(postMessage),
- });
- if (enableTestingFeaturesFlag) {
- ObjectDefineProperty(
- globalThis,
- "importScripts",
- core.propWritable(importScripts),
- );
- }
- ObjectSetPrototypeOf(globalThis, DedicatedWorkerGlobalScope.prototype);
+ if (!warmup) {
+ if (hasBootstrapped) {
+ throw new Error("Worker runtime already bootstrapped");
+ }
- const consoleFromDeno = globalThis.console;
- core.wrapConsole(consoleFromDeno, core.v8Console);
+ const {
+ 0: location_,
+ 1: unstableFlag,
+ 2: unstableFeatures,
+ 4: enableTestingFeaturesFlag,
+ 5: hasNodeModulesDir,
+ 6: argv0,
+ 7: shouldDisableDeprecatedApiWarning,
+ 8: shouldUseVerboseDeprecatedApiWarning,
+ 9: _future,
+ } = runtimeOptions;
+
+ deprecatedApiWarningDisabled = shouldDisableDeprecatedApiWarning;
+ verboseDeprecatedApiWarning = shouldUseVerboseDeprecatedApiWarning;
+ performance.setTimeOrigin(DateNow());
+ globalThis_ = globalThis;
+
+ // Remove bootstrapping data from the global scope
+ delete globalThis.__bootstrap;
+ delete globalThis.bootstrap;
+ hasBootstrapped = true;
+
+ exposeUnstableFeaturesForWindowOrWorkerGlobalScope({
+ unstableFlag,
+ unstableFeatures,
+ });
+ ObjectDefineProperties(globalThis, workerRuntimeGlobalProperties);
+ ObjectDefineProperties(globalThis, {
+ name: core.propWritable(name),
+ // TODO(bartlomieju): should be readonly?
+ close: core.propNonEnumerable(workerClose),
+ postMessage: core.propWritable(postMessage),
+ });
+ if (enableTestingFeaturesFlag) {
+ ObjectDefineProperty(
+ globalThis,
+ "importScripts",
+ core.propWritable(importScripts),
+ );
+ }
+ ObjectSetPrototypeOf(globalThis, DedicatedWorkerGlobalScope.prototype);
- event.setEventTargetData(globalThis);
- event.saveGlobalThisReference(globalThis);
+ const consoleFromDeno = globalThis.console;
+ core.wrapConsole(consoleFromDeno, core.v8Console);
- event.defineEventHandler(self, "message");
- event.defineEventHandler(self, "error", undefined, true);
- event.defineEventHandler(self, "unhandledrejection");
+ event.defineEventHandler(self, "message");
+ event.defineEventHandler(self, "error", undefined, true);
- // `Deno.exit()` is an alias to `self.close()`. Setting and exit
- // code using an op in worker context is a no-op.
- os.setExitHandler((_exitCode) => {
- workerClose();
- });
+ // `Deno.exit()` is an alias to `self.close()`. Setting and exit
+ // code using an op in worker context is a no-op.
+ os.setExitHandler((_exitCode) => {
+ workerClose();
+ });
- runtimeStart(
- denoVersion,
- v8Version,
- tsVersion,
- target,
- internalName ?? name,
- );
+ runtimeStart(
+ denoVersion,
+ v8Version,
+ tsVersion,
+ target,
+ internalName ?? name,
+ );
- location.setLocationHref(location_);
+ location.setLocationHref(location_);
- globalThis.pollForMessages = pollForMessages;
- globalThis.hasMessageEventListener = hasMessageEventListener;
+ globalThis.pollForMessages = pollForMessages;
+ globalThis.hasMessageEventListener = hasMessageEventListener;
- // TODO(bartlomieju): deprecate --unstable
- if (unstableFlag) {
- ObjectAssign(finalDenoNs, denoNsUnstable);
- } else {
- for (let i = 0; i <= unstableFeatures.length; i++) {
- const id = unstableFeatures[i];
- ObjectAssign(finalDenoNs, denoNsUnstableById[id]);
+ // TODO(bartlomieju): deprecate --unstable
+ if (unstableFlag) {
+ ObjectAssign(finalDenoNs, denoNsUnstable);
+ } else {
+ for (let i = 0; i <= unstableFeatures.length; i++) {
+ const id = unstableFeatures[i];
+ ObjectAssign(finalDenoNs, denoNsUnstableById[id]);
+ }
}
- }
- if (!ArrayPrototypeIncludes(unstableFeatures, unstableIds.unsafeProto)) {
- // Removes the `__proto__` for security reasons.
- // https://tc39.es/ecma262/#sec-get-object.prototype.__proto__
- delete Object.prototype.__proto__;
- }
+ // Not available in workers
+ delete finalDenoNs.mainModule;
- if (!ArrayPrototypeIncludes(unstableFeatures, unstableIds.temporal)) {
- // Removes the `Temporal` API.
- delete globalThis.Temporal;
- delete globalThis.Date.prototype.toTemporalInstant;
- }
+ if (!ArrayPrototypeIncludes(unstableFeatures, unstableIds.unsafeProto)) {
+ // Removes the `__proto__` for security reasons.
+ // https://tc39.es/ecma262/#sec-get-object.prototype.__proto__
+ delete Object.prototype.__proto__;
+ }
- ObjectDefineProperties(finalDenoNs, {
- pid: core.propGetterOnly(opPid),
- noColor: core.propGetterOnly(() => op_bootstrap_no_color()),
- args: core.propGetterOnly(opArgs),
- // TODO(kt3k): Remove this export at v2
- // See https://github.com/denoland/deno/issues/9294
- customInspect: {
- get() {
- warnOnDeprecatedApi(
- "Deno.customInspect",
- new Error().stack,
- 'Use `Symbol.for("Deno.customInspect")` instead.',
- );
- return customInspect;
- },
- },
- });
- // Setup `Deno` global - we're actually overriding already
- // existing global `Deno` with `Deno` namespace from "./deno.ts".
- ObjectDefineProperty(globalThis, "Deno", core.propReadOnly(finalDenoNs));
-
- const workerMetadata = maybeWorkerMetadata
- ? messagePort.deserializeJsMessageData(maybeWorkerMetadata)
- : undefined;
-
- if (nodeBootstrap) {
- nodeBootstrap(
- hasNodeModulesDir,
- argv0,
- /* runningOnMainThread */ false,
- workerId,
- workerMetadata,
- );
+ if (!ArrayPrototypeIncludes(unstableFeatures, unstableIds.temporal)) {
+ // Removes the `Temporal` API.
+ delete globalThis.Temporal;
+ delete globalThis.Date.prototype.toTemporalInstant;
+ }
+
+ // Setup `Deno` global - we're actually overriding already existing global
+ // `Deno` with `Deno` namespace from "./deno.ts".
+ ObjectDefineProperty(globalThis, "Deno", core.propReadOnly(finalDenoNs));
+
+ const workerMetadata = maybeWorkerMetadata
+ ? messagePort.deserializeJsMessageData(maybeWorkerMetadata)
+ : undefined;
+
+ if (nodeBootstrap) {
+ nodeBootstrap(
+ hasNodeModulesDir,
+ argv0,
+ /* runningOnMainThread */ false,
+ workerId,
+ workerMetadata,
+ );
+ }
+ } else {
+ // Warmup
+ return;
}
}
+const nodeBootstrap = globalThis.nodeBootstrap;
+delete globalThis.nodeBootstrap;
+
globalThis.bootstrap = {
mainRuntime: bootstrapMainRuntime,
workerRuntime: bootstrapWorkerRuntime,
};
+
+event.setEventTargetData(globalThis);
+event.saveGlobalThisReference(globalThis);
+event.defineEventHandler(globalThis, "unhandledrejection");
+
+// Nothing listens to this, but it warms up the code paths for event dispatch
+(new event.EventTarget()).dispatchEvent(new Event("warmup"));
+
+removeImportedOps();
+
+// Run the warmup path through node and runtime/worker bootstrap functions
+bootstrapMainRuntime(undefined, true);
+bootstrapWorkerRuntime(
+ undefined,
+ undefined,
+ undefined,
+ undefined,
+ undefined,
+ true,
+);
+nodeBootstrap(undefined, undefined, undefined, undefined, undefined, true);