mirror of
https://github.com/denoland/deno.git
synced 2024-11-25 15:29:32 -05:00
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.
This commit is contained in:
parent
9c2f9f14e7
commit
08ec6e5831
4 changed files with 401 additions and 360 deletions
|
@ -16,38 +16,32 @@ function initialize(
|
||||||
runningOnMainThread,
|
runningOnMainThread,
|
||||||
workerId,
|
workerId,
|
||||||
maybeWorkerMetadata,
|
maybeWorkerMetadata,
|
||||||
|
warmup = false,
|
||||||
) {
|
) {
|
||||||
if (initialized) {
|
if (!warmup) {
|
||||||
throw Error("Node runtime already initialized");
|
if (initialized) {
|
||||||
}
|
throw Error("Node runtime already initialized");
|
||||||
initialized = true;
|
}
|
||||||
if (usesLocalNodeModulesDir) {
|
initialized = true;
|
||||||
requireImpl.setUsesLocalNodeModulesDir();
|
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;
|
|
||||||
|
|
||||||
// FIXME(bartlomieju): not nice to depend on `Deno` namespace here
|
// FIXME(bartlomieju): not nice to depend on `Deno` namespace here
|
||||||
// but it's the only way to get `args` and `version` and this point.
|
// but it's the only way to get `args` and `version` and this point.
|
||||||
internals.__bootstrapNodeProcess(argv0, Deno.args, Deno.version);
|
internals.__bootstrapNodeProcess(argv0, Deno.args, Deno.version);
|
||||||
internals.__initWorkerThreads(
|
internals.__initWorkerThreads(
|
||||||
runningOnMainThread,
|
runningOnMainThread,
|
||||||
workerId,
|
workerId,
|
||||||
maybeWorkerMetadata,
|
maybeWorkerMetadata,
|
||||||
);
|
);
|
||||||
internals.__setupChildProcessIpcChannel();
|
internals.__setupChildProcessIpcChannel();
|
||||||
// `Deno[Deno.internal].requireImpl` will be unreachable after this line.
|
// `Deno[Deno.internal].requireImpl` will be unreachable after this line.
|
||||||
delete internals.requireImpl;
|
delete internals.requireImpl;
|
||||||
|
} else {
|
||||||
|
// Warm up the process module
|
||||||
|
internals.__bootstrapNodeProcess(undefined, undefined, undefined, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadCjsModule(moduleName, isMain, inspectBrk) {
|
function loadCjsModule(moduleName, isMain, inspectBrk) {
|
||||||
|
@ -63,3 +57,16 @@ internals.node = {
|
||||||
initialize,
|
initialize,
|
||||||
loadCjsModule,
|
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;
|
||||||
|
|
|
@ -16,7 +16,7 @@ import * as io from "ext:deno_io/12_io.js";
|
||||||
import { guessHandleType } from "ext:deno_node/internal_binding/util.ts";
|
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
|
// 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({
|
const stream = new Writable({
|
||||||
emitClose: false,
|
emitClose: false,
|
||||||
write(buf, enc, cb) {
|
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
|
// These belong on tty.WriteStream(), but the TTY streams currently have
|
||||||
// following problems:
|
// following problems:
|
||||||
// 1. Using them here introduces a circular dependency.
|
// 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://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
|
// https://github.com/nodejs/node/blob/v18.12.1/lib/internal/bootstrap/switches/is_main_thread.js#L189
|
||||||
/** Create process.stdin */
|
/** Create process.stdin */
|
||||||
export const initStdin = () => {
|
export const initStdin = (warmup = false) => {
|
||||||
const fd = io.stdin ? io.STDIN_RID : undefined;
|
const fd = io.stdin ? io.STDIN_RID : undefined;
|
||||||
let stdin;
|
let stdin;
|
||||||
const stdinType = _guessStdinType(fd);
|
// Warmup assumes a TTY for all stdio
|
||||||
|
const stdinType = warmup ? "TTY" : _guessStdinType(fd);
|
||||||
|
|
||||||
switch (stdinType) {
|
switch (stdinType) {
|
||||||
case "FILE": {
|
case "FILE": {
|
||||||
|
@ -142,6 +145,11 @@ export const initStdin = () => {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "TTY": {
|
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);
|
stdin = new readStream(fd);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,7 +68,7 @@ const notImplementedEvents = [
|
||||||
"worker",
|
"worker",
|
||||||
];
|
];
|
||||||
|
|
||||||
export const argv: string[] = [];
|
export const argv: string[] = ["", ""];
|
||||||
let globalProcessExitCode: number | undefined = undefined;
|
let globalProcessExitCode: number | undefined = undefined;
|
||||||
|
|
||||||
/** https://nodejs.org/api/process.html#process_process_exit_code */
|
/** 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
|
// Should be called only once, in `runtime/js/99_main.js` when the runtime is
|
||||||
// bootstrapped.
|
// bootstrapped.
|
||||||
internals.__bootstrapNodeProcess = function (
|
internals.__bootstrapNodeProcess = function (
|
||||||
argv0Val: string | undefined,
|
argv0Val: string | undefined,
|
||||||
args: string[],
|
args: string[],
|
||||||
denoVersions: Record<string, string>,
|
denoVersions: Record<string, string>,
|
||||||
|
warmup = false,
|
||||||
) {
|
) {
|
||||||
// Overwrites the 1st item with getter.
|
if (!warmup) {
|
||||||
if (typeof argv0Val === "string") {
|
argv0 = argv0Val || "";
|
||||||
argv0 = argv0Val;
|
// Manually concatenate these arrays to avoid triggering the getter
|
||||||
Object.defineProperty(argv, "0", {
|
for (let i = 0; i < args.length; i++) {
|
||||||
get: () => {
|
argv[i + 2] = args[i];
|
||||||
return argv0Val;
|
}
|
||||||
},
|
|
||||||
});
|
for (const [key, value] of Object.entries(denoVersions)) {
|
||||||
|
versions[key] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
core.setNextTickCallback(processTicksAndRejections);
|
||||||
|
core.setMacrotaskCallback(runNextTicks);
|
||||||
|
enableNextTick();
|
||||||
|
|
||||||
|
// Replace stdin if it is not a terminal
|
||||||
|
const newStdin = initStdin();
|
||||||
|
if (newStdin) {
|
||||||
|
stdin = process.stdin = newStdin;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!io.stderr.isTerminal()) {
|
||||||
|
/** https://nodejs.org/api/process.html#process_process_stderr */
|
||||||
|
stderr = process.stderr = createWritableStdioStream(
|
||||||
|
io.stderr,
|
||||||
|
"stderr",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
process.setStartTime(Date.now());
|
||||||
|
|
||||||
|
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;
|
||||||
} else {
|
} else {
|
||||||
Object.defineProperty(argv, "0", { get: () => argv0 });
|
// 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,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
core.setNextTickCallback(processTicksAndRejections);
|
|
||||||
core.setMacrotaskCallback(runNextTicks);
|
|
||||||
enableNextTick();
|
|
||||||
|
|
||||||
stdin = process.stdin = initStdin();
|
|
||||||
/** 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",
|
|
||||||
);
|
|
||||||
|
|
||||||
process.setStartTime(Date.now());
|
|
||||||
|
|
||||||
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;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default process;
|
export default process;
|
||||||
|
|
|
@ -628,6 +628,28 @@ const finalDenoNs = {
|
||||||
bench: () => {},
|
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 {
|
const {
|
||||||
denoVersion,
|
denoVersion,
|
||||||
tsVersion,
|
tsVersion,
|
||||||
|
@ -635,155 +657,130 @@ const {
|
||||||
target,
|
target,
|
||||||
} = op_snapshot_options();
|
} = op_snapshot_options();
|
||||||
|
|
||||||
function bootstrapMainRuntime(runtimeOptions) {
|
function bootstrapMainRuntime(runtimeOptions, warmup = false) {
|
||||||
if (hasBootstrapped) {
|
if (!warmup) {
|
||||||
throw new Error("Worker runtime already bootstrapped");
|
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_);
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
if (inspectFlag) {
|
|
||||||
const consoleFromDeno = globalThis.console;
|
|
||||||
core.wrapConsole(consoleFromDeno, core.v8Console);
|
|
||||||
}
|
|
||||||
|
|
||||||
event.setEventTargetData(globalThis);
|
|
||||||
event.saveGlobalThisReference(globalThis);
|
|
||||||
|
|
||||||
event.defineEventHandler(globalThis, "error");
|
|
||||||
event.defineEventHandler(globalThis, "load");
|
|
||||||
event.defineEventHandler(globalThis, "beforeunload");
|
|
||||||
event.defineEventHandler(globalThis, "unload");
|
|
||||||
event.defineEventHandler(globalThis, "unhandledrejection");
|
|
||||||
|
|
||||||
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;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
// 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)) {
|
const {
|
||||||
// Removes the `__proto__` for security reasons.
|
0: location_,
|
||||||
// https://tc39.es/ecma262/#sec-get-object.prototype.__proto__
|
1: unstableFlag,
|
||||||
delete Object.prototype.__proto__;
|
2: unstableFeatures,
|
||||||
}
|
3: inspectFlag,
|
||||||
|
5: hasNodeModulesDir,
|
||||||
|
6: argv0,
|
||||||
|
7: shouldDisableDeprecatedApiWarning,
|
||||||
|
8: shouldUseVerboseDeprecatedApiWarning,
|
||||||
|
9: future,
|
||||||
|
} = runtimeOptions;
|
||||||
|
|
||||||
if (!ArrayPrototypeIncludes(unstableFeatures, unstableIds.temporal)) {
|
removeImportedOps();
|
||||||
// Removes the `Temporal` API.
|
|
||||||
delete globalThis.Temporal;
|
|
||||||
delete globalThis.Date.prototype.toTemporalInstant;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Setup `Deno` global - we're actually overriding already existing global
|
deprecatedApiWarningDisabled = shouldDisableDeprecatedApiWarning;
|
||||||
// `Deno` with `Deno` namespace from "./deno.ts".
|
verboseDeprecatedApiWarning = shouldUseVerboseDeprecatedApiWarning;
|
||||||
ObjectDefineProperty(globalThis, "Deno", core.propReadOnly(finalDenoNs));
|
performance.setTimeOrigin(DateNow());
|
||||||
|
globalThis_ = globalThis;
|
||||||
|
|
||||||
if (nodeBootstrap) {
|
// Remove bootstrapping data from the global scope
|
||||||
nodeBootstrap(hasNodeModulesDir, argv0, /* runningOnMainThread */ true);
|
delete globalThis.__bootstrap;
|
||||||
}
|
delete globalThis.bootstrap;
|
||||||
|
hasBootstrapped = true;
|
||||||
|
|
||||||
if (future) {
|
// If the `--location` flag isn't set, make `globalThis.location` `undefined` and
|
||||||
delete globalThis.window;
|
// 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_);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
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");
|
||||||
|
|
||||||
|
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]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Warmup
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -793,146 +790,153 @@ function bootstrapWorkerRuntime(
|
||||||
internalName,
|
internalName,
|
||||||
workerId,
|
workerId,
|
||||||
maybeWorkerMetadata,
|
maybeWorkerMetadata,
|
||||||
|
warmup = false,
|
||||||
) {
|
) {
|
||||||
if (hasBootstrapped) {
|
if (!warmup) {
|
||||||
throw new Error("Worker runtime already bootstrapped");
|
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);
|
|
||||||
|
|
||||||
const consoleFromDeno = globalThis.console;
|
|
||||||
core.wrapConsole(consoleFromDeno, core.v8Console);
|
|
||||||
|
|
||||||
event.setEventTargetData(globalThis);
|
|
||||||
event.saveGlobalThisReference(globalThis);
|
|
||||||
|
|
||||||
event.defineEventHandler(self, "message");
|
|
||||||
event.defineEventHandler(self, "error", undefined, true);
|
|
||||||
event.defineEventHandler(self, "unhandledrejection");
|
|
||||||
|
|
||||||
// `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,
|
|
||||||
);
|
|
||||||
|
|
||||||
location.setLocationHref(location_);
|
|
||||||
|
|
||||||
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]);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (!ArrayPrototypeIncludes(unstableFeatures, unstableIds.unsafeProto)) {
|
const {
|
||||||
// Removes the `__proto__` for security reasons.
|
0: location_,
|
||||||
// https://tc39.es/ecma262/#sec-get-object.prototype.__proto__
|
1: unstableFlag,
|
||||||
delete Object.prototype.__proto__;
|
2: unstableFeatures,
|
||||||
}
|
4: enableTestingFeaturesFlag,
|
||||||
|
5: hasNodeModulesDir,
|
||||||
|
6: argv0,
|
||||||
|
7: shouldDisableDeprecatedApiWarning,
|
||||||
|
8: shouldUseVerboseDeprecatedApiWarning,
|
||||||
|
9: _future,
|
||||||
|
} = runtimeOptions;
|
||||||
|
|
||||||
if (!ArrayPrototypeIncludes(unstableFeatures, unstableIds.temporal)) {
|
deprecatedApiWarningDisabled = shouldDisableDeprecatedApiWarning;
|
||||||
// Removes the `Temporal` API.
|
verboseDeprecatedApiWarning = shouldUseVerboseDeprecatedApiWarning;
|
||||||
delete globalThis.Temporal;
|
performance.setTimeOrigin(DateNow());
|
||||||
delete globalThis.Date.prototype.toTemporalInstant;
|
globalThis_ = globalThis;
|
||||||
}
|
|
||||||
|
|
||||||
ObjectDefineProperties(finalDenoNs, {
|
// Remove bootstrapping data from the global scope
|
||||||
pid: core.propGetterOnly(opPid),
|
delete globalThis.__bootstrap;
|
||||||
noColor: core.propGetterOnly(() => op_bootstrap_no_color()),
|
delete globalThis.bootstrap;
|
||||||
args: core.propGetterOnly(opArgs),
|
hasBootstrapped = true;
|
||||||
// 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
|
exposeUnstableFeaturesForWindowOrWorkerGlobalScope({
|
||||||
? messagePort.deserializeJsMessageData(maybeWorkerMetadata)
|
unstableFlag,
|
||||||
: undefined;
|
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 (nodeBootstrap) {
|
const consoleFromDeno = globalThis.console;
|
||||||
nodeBootstrap(
|
core.wrapConsole(consoleFromDeno, core.v8Console);
|
||||||
hasNodeModulesDir,
|
|
||||||
argv0,
|
event.defineEventHandler(self, "message");
|
||||||
/* runningOnMainThread */ false,
|
event.defineEventHandler(self, "error", undefined, true);
|
||||||
workerId,
|
|
||||||
workerMetadata,
|
// `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,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
location.setLocationHref(location_);
|
||||||
|
|
||||||
|
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]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not available in workers
|
||||||
|
delete finalDenoNs.mainModule;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 = {
|
globalThis.bootstrap = {
|
||||||
mainRuntime: bootstrapMainRuntime,
|
mainRuntime: bootstrapMainRuntime,
|
||||||
workerRuntime: bootstrapWorkerRuntime,
|
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);
|
||||||
|
|
Loading…
Reference in a new issue