mirror of
https://github.com/denoland/deno.git
synced 2024-12-01 16:51:13 -05:00
refactor(runtime): manual serialization of bootstrap data (#18448)
This commit changes how data required to bootstrap main and worker runtime is serialized. Instead of relying on serde_v8 and using JSON object, we're doing manual serialization to a "v8::Array". This limits number of V8 strings that need to be serialized by 16. It also made it clear that some data could be obtained during snapshotting instead of during bootstrap.
This commit is contained in:
parent
d23579fe6d
commit
6c0df5e94e
4 changed files with 230 additions and 62 deletions
|
@ -292,20 +292,29 @@ core.registerErrorBuilder(
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
function runtimeStart(runtimeOptions, source) {
|
function runtimeStart(
|
||||||
|
denoVersion,
|
||||||
|
v8Version,
|
||||||
|
tsVersion,
|
||||||
|
target,
|
||||||
|
debugFlag,
|
||||||
|
noColor,
|
||||||
|
isTty,
|
||||||
|
source,
|
||||||
|
) {
|
||||||
core.setMacrotaskCallback(timers.handleTimerMacrotask);
|
core.setMacrotaskCallback(timers.handleTimerMacrotask);
|
||||||
core.setMacrotaskCallback(promiseRejectMacrotaskCallback);
|
core.setMacrotaskCallback(promiseRejectMacrotaskCallback);
|
||||||
core.setWasmStreamingCallback(fetch.handleWasmStreaming);
|
core.setWasmStreamingCallback(fetch.handleWasmStreaming);
|
||||||
core.setReportExceptionCallback(event.reportException);
|
core.setReportExceptionCallback(event.reportException);
|
||||||
ops.op_set_format_exception_callback(formatException);
|
ops.op_set_format_exception_callback(formatException);
|
||||||
version.setVersions(
|
version.setVersions(
|
||||||
runtimeOptions.denoVersion,
|
denoVersion,
|
||||||
runtimeOptions.v8Version,
|
v8Version,
|
||||||
runtimeOptions.tsVersion,
|
tsVersion,
|
||||||
);
|
);
|
||||||
core.setBuildInfo(runtimeOptions.target);
|
core.setBuildInfo(target);
|
||||||
util.setLogDebug(runtimeOptions.debugFlag, source);
|
util.setLogDebug(debugFlag, source);
|
||||||
colors.setNoColor(runtimeOptions.noColor || !runtimeOptions.isTty);
|
colors.setNoColor(noColor || !isTty);
|
||||||
// deno-lint-ignore prefer-primordials
|
// deno-lint-ignore prefer-primordials
|
||||||
Error.prepareStackTrace = core.prepareStackTrace;
|
Error.prepareStackTrace = core.prepareStackTrace;
|
||||||
}
|
}
|
||||||
|
@ -403,6 +412,27 @@ function bootstrapMainRuntime(runtimeOptions) {
|
||||||
if (hasBootstrapped) {
|
if (hasBootstrapped) {
|
||||||
throw new Error("Worker runtime already bootstrapped");
|
throw new Error("Worker runtime already bootstrapped");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const [
|
||||||
|
args,
|
||||||
|
cpuCount,
|
||||||
|
debugFlag,
|
||||||
|
denoVersion,
|
||||||
|
locale,
|
||||||
|
location_,
|
||||||
|
noColor,
|
||||||
|
isTty,
|
||||||
|
tsVersion,
|
||||||
|
unstableFlag,
|
||||||
|
pid,
|
||||||
|
ppid,
|
||||||
|
target,
|
||||||
|
v8Version,
|
||||||
|
userAgent,
|
||||||
|
inspectFlag,
|
||||||
|
_,
|
||||||
|
] = runtimeOptions;
|
||||||
|
|
||||||
performance.setTimeOrigin(DateNow());
|
performance.setTimeOrigin(DateNow());
|
||||||
globalThis_ = globalThis;
|
globalThis_ = globalThis;
|
||||||
|
|
||||||
|
@ -414,15 +444,15 @@ function bootstrapMainRuntime(runtimeOptions) {
|
||||||
// If the `--location` flag isn't set, make `globalThis.location` `undefined` and
|
// 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
|
// writable, so that they can mock it themselves if they like. If the flag was
|
||||||
// set, define `globalThis.location`, using the provided value.
|
// set, define `globalThis.location`, using the provided value.
|
||||||
if (runtimeOptions.location == null) {
|
if (location_ === undefined) {
|
||||||
mainRuntimeGlobalProperties.location = {
|
mainRuntimeGlobalProperties.location = {
|
||||||
writable: true,
|
writable: true,
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
location.setLocationHref(runtimeOptions.location);
|
location.setLocationHref(location_);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (runtimeOptions.unstableFlag) {
|
if (unstableFlag) {
|
||||||
ObjectDefineProperties(globalThis, unstableWindowOrWorkerGlobalScope);
|
ObjectDefineProperties(globalThis, unstableWindowOrWorkerGlobalScope);
|
||||||
}
|
}
|
||||||
ObjectDefineProperties(globalThis, mainRuntimeGlobalProperties);
|
ObjectDefineProperties(globalThis, mainRuntimeGlobalProperties);
|
||||||
|
@ -432,7 +462,7 @@ function bootstrapMainRuntime(runtimeOptions) {
|
||||||
});
|
});
|
||||||
ObjectSetPrototypeOf(globalThis, Window.prototype);
|
ObjectSetPrototypeOf(globalThis, Window.prototype);
|
||||||
|
|
||||||
if (runtimeOptions.inspectFlag) {
|
if (inspectFlag) {
|
||||||
const consoleFromV8 = core.console;
|
const consoleFromV8 = core.console;
|
||||||
const consoleFromDeno = globalThis.console;
|
const consoleFromDeno = globalThis.console;
|
||||||
wrapConsole(consoleFromDeno, consoleFromV8);
|
wrapConsole(consoleFromDeno, consoleFromV8);
|
||||||
|
@ -449,11 +479,19 @@ function bootstrapMainRuntime(runtimeOptions) {
|
||||||
|
|
||||||
core.setPromiseRejectCallback(promiseRejectCallback);
|
core.setPromiseRejectCallback(promiseRejectCallback);
|
||||||
|
|
||||||
runtimeStart(runtimeOptions);
|
runtimeStart(
|
||||||
|
denoVersion,
|
||||||
|
v8Version,
|
||||||
|
tsVersion,
|
||||||
|
target,
|
||||||
|
debugFlag,
|
||||||
|
noColor,
|
||||||
|
isTty,
|
||||||
|
);
|
||||||
|
|
||||||
setNumCpus(runtimeOptions.cpuCount);
|
setNumCpus(cpuCount);
|
||||||
setUserAgent(runtimeOptions.userAgent);
|
setUserAgent(userAgent);
|
||||||
setLanguage(runtimeOptions.locale);
|
setLanguage(locale);
|
||||||
|
|
||||||
// These have to initialized here and not in `90_deno_ns.js` because
|
// These have to initialized here and not in `90_deno_ns.js` because
|
||||||
// the op function that needs to be passed will be invalidated by creating
|
// the op function that needs to be passed will be invalidated by creating
|
||||||
|
@ -477,14 +515,14 @@ function bootstrapMainRuntime(runtimeOptions) {
|
||||||
});
|
});
|
||||||
|
|
||||||
ObjectDefineProperties(finalDenoNs, {
|
ObjectDefineProperties(finalDenoNs, {
|
||||||
pid: util.readOnly(runtimeOptions.pid),
|
pid: util.readOnly(pid),
|
||||||
ppid: util.readOnly(runtimeOptions.ppid),
|
ppid: util.readOnly(ppid),
|
||||||
noColor: util.readOnly(runtimeOptions.noColor),
|
noColor: util.readOnly(noColor),
|
||||||
args: util.readOnly(ObjectFreeze(runtimeOptions.args)),
|
args: util.readOnly(ObjectFreeze(args)),
|
||||||
mainModule: util.getterOnly(opMainModule),
|
mainModule: util.getterOnly(opMainModule),
|
||||||
});
|
});
|
||||||
|
|
||||||
if (runtimeOptions.unstableFlag) {
|
if (unstableFlag) {
|
||||||
ObjectAssign(finalDenoNs, denoNsUnstable);
|
ObjectAssign(finalDenoNs, denoNsUnstable);
|
||||||
// These have to initialized here and not in `90_deno_ns.js` because
|
// These have to initialized here and not in `90_deno_ns.js` because
|
||||||
// the op function that needs to be passed will be invalidated by creating
|
// the op function that needs to be passed will be invalidated by creating
|
||||||
|
@ -502,7 +540,7 @@ function bootstrapMainRuntime(runtimeOptions) {
|
||||||
// `Deno` with `Deno` namespace from "./deno.ts".
|
// `Deno` with `Deno` namespace from "./deno.ts".
|
||||||
ObjectDefineProperty(globalThis, "Deno", util.readOnly(finalDenoNs));
|
ObjectDefineProperty(globalThis, "Deno", util.readOnly(finalDenoNs));
|
||||||
|
|
||||||
util.log("args", runtimeOptions.args);
|
util.log("args", args);
|
||||||
}
|
}
|
||||||
|
|
||||||
function bootstrapWorkerRuntime(
|
function bootstrapWorkerRuntime(
|
||||||
|
@ -514,6 +552,26 @@ function bootstrapWorkerRuntime(
|
||||||
throw new Error("Worker runtime already bootstrapped");
|
throw new Error("Worker runtime already bootstrapped");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const [
|
||||||
|
args,
|
||||||
|
cpuCount,
|
||||||
|
debugFlag,
|
||||||
|
denoVersion,
|
||||||
|
locale,
|
||||||
|
location_,
|
||||||
|
noColor,
|
||||||
|
isTty,
|
||||||
|
tsVersion,
|
||||||
|
unstableFlag,
|
||||||
|
pid,
|
||||||
|
_ppid,
|
||||||
|
target,
|
||||||
|
v8Version,
|
||||||
|
_userAgent,
|
||||||
|
_inspectFlag,
|
||||||
|
enableTestingFeaturesFlag,
|
||||||
|
] = runtimeOptions;
|
||||||
|
|
||||||
performance.setTimeOrigin(DateNow());
|
performance.setTimeOrigin(DateNow());
|
||||||
globalThis_ = globalThis;
|
globalThis_ = globalThis;
|
||||||
|
|
||||||
|
@ -524,7 +582,7 @@ function bootstrapWorkerRuntime(
|
||||||
delete globalThis.bootstrap;
|
delete globalThis.bootstrap;
|
||||||
hasBootstrapped = true;
|
hasBootstrapped = true;
|
||||||
|
|
||||||
if (runtimeOptions.unstableFlag) {
|
if (unstableFlag) {
|
||||||
ObjectDefineProperties(globalThis, unstableWindowOrWorkerGlobalScope);
|
ObjectDefineProperties(globalThis, unstableWindowOrWorkerGlobalScope);
|
||||||
}
|
}
|
||||||
ObjectDefineProperties(globalThis, workerRuntimeGlobalProperties);
|
ObjectDefineProperties(globalThis, workerRuntimeGlobalProperties);
|
||||||
|
@ -534,7 +592,7 @@ function bootstrapWorkerRuntime(
|
||||||
close: util.nonEnumerable(workerClose),
|
close: util.nonEnumerable(workerClose),
|
||||||
postMessage: util.writable(postMessage),
|
postMessage: util.writable(postMessage),
|
||||||
});
|
});
|
||||||
if (runtimeOptions.enableTestingFeaturesFlag) {
|
if (enableTestingFeaturesFlag) {
|
||||||
ObjectDefineProperty(
|
ObjectDefineProperty(
|
||||||
globalThis,
|
globalThis,
|
||||||
"importScripts",
|
"importScripts",
|
||||||
|
@ -562,14 +620,20 @@ function bootstrapWorkerRuntime(
|
||||||
});
|
});
|
||||||
|
|
||||||
runtimeStart(
|
runtimeStart(
|
||||||
runtimeOptions,
|
denoVersion,
|
||||||
|
v8Version,
|
||||||
|
tsVersion,
|
||||||
|
target,
|
||||||
|
debugFlag,
|
||||||
|
noColor,
|
||||||
|
isTty,
|
||||||
internalName ?? name,
|
internalName ?? name,
|
||||||
);
|
);
|
||||||
|
|
||||||
location.setLocationHref(runtimeOptions.location);
|
location.setLocationHref(location_);
|
||||||
|
|
||||||
setNumCpus(runtimeOptions.cpuCount);
|
setNumCpus(cpuCount);
|
||||||
setLanguage(runtimeOptions.locale);
|
setLanguage(locale);
|
||||||
|
|
||||||
globalThis.pollForMessages = pollForMessages;
|
globalThis.pollForMessages = pollForMessages;
|
||||||
|
|
||||||
|
@ -594,7 +658,7 @@ function bootstrapWorkerRuntime(
|
||||||
core,
|
core,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (runtimeOptions.unstableFlag) {
|
if (unstableFlag) {
|
||||||
ObjectAssign(finalDenoNs, denoNsUnstable);
|
ObjectAssign(finalDenoNs, denoNsUnstable);
|
||||||
// These have to initialized here and not in `90_deno_ns.js` because
|
// These have to initialized here and not in `90_deno_ns.js` because
|
||||||
// the op function that needs to be passed will be invalidated by creating
|
// the op function that needs to be passed will be invalidated by creating
|
||||||
|
@ -608,9 +672,9 @@ function bootstrapWorkerRuntime(
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
ObjectDefineProperties(finalDenoNs, {
|
ObjectDefineProperties(finalDenoNs, {
|
||||||
pid: util.readOnly(runtimeOptions.pid),
|
pid: util.readOnly(pid),
|
||||||
noColor: util.readOnly(runtimeOptions.noColor),
|
noColor: util.readOnly(noColor),
|
||||||
args: util.readOnly(ObjectFreeze(runtimeOptions.args)),
|
args: util.readOnly(ObjectFreeze(args)),
|
||||||
});
|
});
|
||||||
// Setup `Deno` global - we're actually overriding already
|
// Setup `Deno` global - we're actually overriding already
|
||||||
// existing global `Deno` with `Deno` namespace from "./deno.ts".
|
// existing global `Deno` with `Deno` namespace from "./deno.ts".
|
||||||
|
|
|
@ -556,8 +556,7 @@ impl WebWorker {
|
||||||
// WebWorkers can have empty string as name.
|
// WebWorkers can have empty string as name.
|
||||||
{
|
{
|
||||||
let scope = &mut self.js_runtime.handle_scope();
|
let scope = &mut self.js_runtime.handle_scope();
|
||||||
let options_v8 =
|
let args = options.as_v8(scope);
|
||||||
deno_core::serde_v8::to_v8(scope, options.as_json()).unwrap();
|
|
||||||
let bootstrap_fn = self.bootstrap_fn_global.take().unwrap();
|
let bootstrap_fn = self.bootstrap_fn_global.take().unwrap();
|
||||||
let bootstrap_fn = v8::Local::new(scope, bootstrap_fn);
|
let bootstrap_fn = v8::Local::new(scope, bootstrap_fn);
|
||||||
let undefined = v8::undefined(scope);
|
let undefined = v8::undefined(scope);
|
||||||
|
@ -568,7 +567,7 @@ impl WebWorker {
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.into();
|
.into();
|
||||||
bootstrap_fn
|
bootstrap_fn
|
||||||
.call(scope, undefined.into(), &[options_v8, name_str, id_str])
|
.call(scope, undefined.into(), &[args.into(), name_str, id_str])
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
// TODO(bartlomieju): this could be done using V8 API, without calling `execute_script`.
|
// TODO(bartlomieju): this could be done using V8 API, without calling `execute_script`.
|
||||||
|
|
|
@ -361,13 +361,12 @@ impl MainWorker {
|
||||||
|
|
||||||
pub fn bootstrap(&mut self, options: &BootstrapOptions) {
|
pub fn bootstrap(&mut self, options: &BootstrapOptions) {
|
||||||
let scope = &mut self.js_runtime.handle_scope();
|
let scope = &mut self.js_runtime.handle_scope();
|
||||||
let options_v8 =
|
let args = options.as_v8(scope);
|
||||||
deno_core::serde_v8::to_v8(scope, options.as_json()).unwrap();
|
|
||||||
let bootstrap_fn = self.bootstrap_fn_global.take().unwrap();
|
let bootstrap_fn = self.bootstrap_fn_global.take().unwrap();
|
||||||
let bootstrap_fn = v8::Local::new(scope, bootstrap_fn);
|
let bootstrap_fn = v8::Local::new(scope, bootstrap_fn);
|
||||||
let undefined = v8::undefined(scope);
|
let undefined = v8::undefined(scope);
|
||||||
bootstrap_fn
|
bootstrap_fn
|
||||||
.call(scope, undefined.into(), &[options_v8])
|
.call(scope, undefined.into(), &[args.into()])
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
use deno_core::serde_json;
|
use deno_core::v8;
|
||||||
use deno_core::serde_json::json;
|
|
||||||
use deno_core::ModuleSpecifier;
|
use deno_core::ModuleSpecifier;
|
||||||
use std::thread;
|
use std::thread;
|
||||||
|
|
||||||
|
@ -58,28 +57,135 @@ impl Default for BootstrapOptions {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BootstrapOptions {
|
impl BootstrapOptions {
|
||||||
pub fn as_json(&self) -> serde_json::Value {
|
pub fn as_v8<'s>(
|
||||||
json!({
|
&self,
|
||||||
// Shared bootstrap args
|
scope: &mut v8::HandleScope<'s>,
|
||||||
"args": self.args,
|
) -> v8::Local<'s, v8::Array> {
|
||||||
"cpuCount": self.cpu_count,
|
let array = v8::Array::new(scope, 17);
|
||||||
"debugFlag": self.debug_flag,
|
|
||||||
"denoVersion": self.runtime_version,
|
{
|
||||||
"locale": self.locale,
|
let args = v8::Array::new(scope, self.args.len() as i32);
|
||||||
"location": self.location,
|
for (idx, arg) in self.args.iter().enumerate() {
|
||||||
"noColor": self.no_color,
|
let arg_str = v8::String::new(scope, arg).unwrap();
|
||||||
"isTty": self.is_tty,
|
args.set_index(scope, idx as u32, arg_str.into());
|
||||||
"tsVersion": self.ts_version,
|
}
|
||||||
"unstableFlag": self.unstable,
|
array.set_index(scope, 0, args.into());
|
||||||
// Web worker only
|
}
|
||||||
"enableTestingFeaturesFlag": self.enable_testing_features,
|
|
||||||
// Env values
|
{
|
||||||
"pid": std::process::id(),
|
let val = v8::Integer::new(scope, self.cpu_count as i32);
|
||||||
"ppid": ppid(),
|
array.set_index(scope, 1, val.into());
|
||||||
"target": env!("TARGET"),
|
}
|
||||||
"v8Version": deno_core::v8_version(),
|
|
||||||
"userAgent": self.user_agent,
|
{
|
||||||
"inspectFlag": self.inspect,
|
let val = v8::Boolean::new(scope, self.debug_flag);
|
||||||
})
|
array.set_index(scope, 2, val.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
let val = v8::String::new_from_one_byte(
|
||||||
|
scope,
|
||||||
|
self.runtime_version.as_bytes(),
|
||||||
|
v8::NewStringType::Internalized,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
array.set_index(scope, 3, val.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
let val = v8::String::new_from_one_byte(
|
||||||
|
scope,
|
||||||
|
self.locale.as_bytes(),
|
||||||
|
v8::NewStringType::Normal,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
array.set_index(scope, 4, val.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
let val: v8::Local<v8::Value> = if let Some(location) = &self.location {
|
||||||
|
v8::String::new(scope, location.as_str()).unwrap().into()
|
||||||
|
} else {
|
||||||
|
v8::undefined(scope).into()
|
||||||
|
};
|
||||||
|
|
||||||
|
array.set_index(scope, 5, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
let val = v8::Boolean::new(scope, self.no_color);
|
||||||
|
array.set_index(scope, 6, val.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
let val = v8::Boolean::new(scope, self.is_tty);
|
||||||
|
array.set_index(scope, 7, val.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
let val = v8::String::new_from_one_byte(
|
||||||
|
scope,
|
||||||
|
self.ts_version.as_bytes(),
|
||||||
|
v8::NewStringType::Normal,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
array.set_index(scope, 8, val.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
let val = v8::Boolean::new(scope, self.unstable);
|
||||||
|
array.set_index(scope, 9, val.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
let val = v8::Integer::new(scope, std::process::id() as i32);
|
||||||
|
array.set_index(scope, 10, val.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
let val = v8::Integer::new(scope, ppid() as i32);
|
||||||
|
array.set_index(scope, 11, val.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
let val = v8::String::new_external_onebyte_static(
|
||||||
|
scope,
|
||||||
|
env!("TARGET").as_bytes(),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
array.set_index(scope, 12, val.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
let val = v8::String::new_from_one_byte(
|
||||||
|
scope,
|
||||||
|
deno_core::v8_version().as_bytes(),
|
||||||
|
v8::NewStringType::Normal,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
array.set_index(scope, 13, val.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
let val = v8::String::new_from_one_byte(
|
||||||
|
scope,
|
||||||
|
self.user_agent.as_bytes(),
|
||||||
|
v8::NewStringType::Normal,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
array.set_index(scope, 14, val.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
let val = v8::Boolean::new(scope, self.inspect);
|
||||||
|
array.set_index(scope, 15, val.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
let val = v8::Boolean::new(scope, self.enable_testing_features);
|
||||||
|
array.set_index(scope, 16, val.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
array
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue