mirror of
https://github.com/denoland/deno.git
synced 2025-01-03 04:48:52 -05:00
perf(core, runtime): Further improve startup time (#17860)
This commit further improves startup time by: - no relying on "JsRuntime::execute_script" for runtime bootstrapping, this is instead done using V8 APIs directly - registering error classes during the snapshot time, instead of on startup Further improvements can be made, mainly around removing "core.initializeAsyncOps()" which takes around 2ms. This commit should result in ~1ms startup time improvement.
This commit is contained in:
parent
5becfd6381
commit
4c6db7aa14
6 changed files with 184 additions and 94 deletions
|
@ -111,12 +111,29 @@ pub fn initialize_context<'s>(
|
||||||
|
|
||||||
let scope = &mut v8::ContextScope::new(scope, context);
|
let scope = &mut v8::ContextScope::new(scope, context);
|
||||||
|
|
||||||
|
let deno_str = v8::String::new(scope, "Deno").unwrap();
|
||||||
|
let core_str = v8::String::new(scope, "core").unwrap();
|
||||||
|
let ops_str = v8::String::new(scope, "ops").unwrap();
|
||||||
|
|
||||||
// Snapshot already registered `Deno.core.ops` but
|
// Snapshot already registered `Deno.core.ops` but
|
||||||
// extensions may provide ops that aren't part of the snapshot.
|
// extensions may provide ops that aren't part of the snapshot.
|
||||||
if snapshot_options.loaded() {
|
if snapshot_options.loaded() {
|
||||||
// Grab the Deno.core.ops object & init it
|
// Grab the Deno.core.ops object & init it
|
||||||
let ops_obj = JsRuntime::eval::<v8::Object>(scope, "Deno.core.ops")
|
let deno_obj: v8::Local<v8::Object> = global
|
||||||
.expect("Deno.core.ops to exist");
|
.get(scope, deno_str.into())
|
||||||
|
.unwrap()
|
||||||
|
.try_into()
|
||||||
|
.unwrap();
|
||||||
|
let core_obj: v8::Local<v8::Object> = deno_obj
|
||||||
|
.get(scope, core_str.into())
|
||||||
|
.unwrap()
|
||||||
|
.try_into()
|
||||||
|
.unwrap();
|
||||||
|
let ops_obj: v8::Local<v8::Object> = core_obj
|
||||||
|
.get(scope, ops_str.into())
|
||||||
|
.expect("Deno.core.ops to exist")
|
||||||
|
.try_into()
|
||||||
|
.unwrap();
|
||||||
initialize_ops(scope, ops_obj, op_ctxs, snapshot_options);
|
initialize_ops(scope, ops_obj, op_ctxs, snapshot_options);
|
||||||
if snapshot_options != SnapshotOptions::CreateFromExisting {
|
if snapshot_options != SnapshotOptions::CreateFromExisting {
|
||||||
initialize_async_ops_info(scope, ops_obj, op_ctxs);
|
initialize_async_ops_info(scope, ops_obj, op_ctxs);
|
||||||
|
@ -126,11 +143,9 @@ pub fn initialize_context<'s>(
|
||||||
|
|
||||||
// global.Deno = { core: { } };
|
// global.Deno = { core: { } };
|
||||||
let deno_obj = v8::Object::new(scope);
|
let deno_obj = v8::Object::new(scope);
|
||||||
let deno_str = v8::String::new(scope, "Deno").unwrap();
|
|
||||||
global.set(scope, deno_str.into(), deno_obj.into());
|
global.set(scope, deno_str.into(), deno_obj.into());
|
||||||
|
|
||||||
let core_obj = v8::Object::new(scope);
|
let core_obj = v8::Object::new(scope);
|
||||||
let core_str = v8::String::new(scope, "core").unwrap();
|
|
||||||
deno_obj.set(scope, core_str.into(), core_obj.into());
|
deno_obj.set(scope, core_str.into(), core_obj.into());
|
||||||
|
|
||||||
// Bind functions to Deno.core.*
|
// Bind functions to Deno.core.*
|
||||||
|
@ -144,7 +159,6 @@ pub fn initialize_context<'s>(
|
||||||
|
|
||||||
// Bind functions to Deno.core.ops.*
|
// Bind functions to Deno.core.ops.*
|
||||||
let ops_obj = v8::Object::new(scope);
|
let ops_obj = v8::Object::new(scope);
|
||||||
let ops_str = v8::String::new(scope, "ops").unwrap();
|
|
||||||
core_obj.set(scope, ops_str.into(), ops_obj.into());
|
core_obj.set(scope, ops_str.into(), ops_obj.into());
|
||||||
|
|
||||||
if !snapshot_options.will_snapshot() {
|
if !snapshot_options.will_snapshot() {
|
||||||
|
|
|
@ -985,11 +985,36 @@ impl JsRuntime {
|
||||||
fn init_cbs(&mut self, realm: &JsRealm) {
|
fn init_cbs(&mut self, realm: &JsRealm) {
|
||||||
let (recv_cb, build_custom_error_cb) = {
|
let (recv_cb, build_custom_error_cb) = {
|
||||||
let scope = &mut realm.handle_scope(self.v8_isolate());
|
let scope = &mut realm.handle_scope(self.v8_isolate());
|
||||||
let recv_cb =
|
let context = realm.context();
|
||||||
Self::eval::<v8::Function>(scope, "Deno.core.opresolve").unwrap();
|
let context_local = v8::Local::new(scope, context);
|
||||||
let build_custom_error_cb =
|
let global = context_local.global(scope);
|
||||||
Self::eval::<v8::Function>(scope, "Deno.core.buildCustomError")
|
let deno_str = v8::String::new(scope, "Deno").unwrap();
|
||||||
.expect("Deno.core.buildCustomError is undefined in the realm");
|
let core_str = v8::String::new(scope, "core").unwrap();
|
||||||
|
let opresolve_str = v8::String::new(scope, "opresolve").unwrap();
|
||||||
|
let build_custom_error_str =
|
||||||
|
v8::String::new(scope, "buildCustomError").unwrap();
|
||||||
|
|
||||||
|
let deno_obj: v8::Local<v8::Object> = global
|
||||||
|
.get(scope, deno_str.into())
|
||||||
|
.unwrap()
|
||||||
|
.try_into()
|
||||||
|
.unwrap();
|
||||||
|
let core_obj: v8::Local<v8::Object> = deno_obj
|
||||||
|
.get(scope, core_str.into())
|
||||||
|
.unwrap()
|
||||||
|
.try_into()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let recv_cb: v8::Local<v8::Function> = core_obj
|
||||||
|
.get(scope, opresolve_str.into())
|
||||||
|
.unwrap()
|
||||||
|
.try_into()
|
||||||
|
.unwrap();
|
||||||
|
let build_custom_error_cb: v8::Local<v8::Function> = core_obj
|
||||||
|
.get(scope, build_custom_error_str.into())
|
||||||
|
.unwrap()
|
||||||
|
.try_into()
|
||||||
|
.unwrap();
|
||||||
(
|
(
|
||||||
v8::Global::new(scope, recv_cb),
|
v8::Global::new(scope, recv_cb),
|
||||||
v8::Global::new(scope, build_custom_error_cb),
|
v8::Global::new(scope, build_custom_error_cb),
|
||||||
|
|
|
@ -231,6 +231,69 @@ function formatException(error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
core.registerErrorClass("NotFound", errors.NotFound);
|
||||||
|
core.registerErrorClass("PermissionDenied", errors.PermissionDenied);
|
||||||
|
core.registerErrorClass("ConnectionRefused", errors.ConnectionRefused);
|
||||||
|
core.registerErrorClass("ConnectionReset", errors.ConnectionReset);
|
||||||
|
core.registerErrorClass("ConnectionAborted", errors.ConnectionAborted);
|
||||||
|
core.registerErrorClass("NotConnected", errors.NotConnected);
|
||||||
|
core.registerErrorClass("AddrInUse", errors.AddrInUse);
|
||||||
|
core.registerErrorClass("AddrNotAvailable", errors.AddrNotAvailable);
|
||||||
|
core.registerErrorClass("BrokenPipe", errors.BrokenPipe);
|
||||||
|
core.registerErrorClass("AlreadyExists", errors.AlreadyExists);
|
||||||
|
core.registerErrorClass("InvalidData", errors.InvalidData);
|
||||||
|
core.registerErrorClass("TimedOut", errors.TimedOut);
|
||||||
|
core.registerErrorClass("Interrupted", errors.Interrupted);
|
||||||
|
core.registerErrorClass("WouldBlock", errors.WouldBlock);
|
||||||
|
core.registerErrorClass("WriteZero", errors.WriteZero);
|
||||||
|
core.registerErrorClass("UnexpectedEof", errors.UnexpectedEof);
|
||||||
|
core.registerErrorClass("BadResource", errors.BadResource);
|
||||||
|
core.registerErrorClass("Http", errors.Http);
|
||||||
|
core.registerErrorClass("Busy", errors.Busy);
|
||||||
|
core.registerErrorClass("NotSupported", errors.NotSupported);
|
||||||
|
core.registerErrorBuilder(
|
||||||
|
"DOMExceptionOperationError",
|
||||||
|
function DOMExceptionOperationError(msg) {
|
||||||
|
return new DOMException(msg, "OperationError");
|
||||||
|
},
|
||||||
|
);
|
||||||
|
core.registerErrorBuilder(
|
||||||
|
"DOMExceptionQuotaExceededError",
|
||||||
|
function DOMExceptionQuotaExceededError(msg) {
|
||||||
|
return new DOMException(msg, "QuotaExceededError");
|
||||||
|
},
|
||||||
|
);
|
||||||
|
core.registerErrorBuilder(
|
||||||
|
"DOMExceptionNotSupportedError",
|
||||||
|
function DOMExceptionNotSupportedError(msg) {
|
||||||
|
return new DOMException(msg, "NotSupported");
|
||||||
|
},
|
||||||
|
);
|
||||||
|
core.registerErrorBuilder(
|
||||||
|
"DOMExceptionNetworkError",
|
||||||
|
function DOMExceptionNetworkError(msg) {
|
||||||
|
return new DOMException(msg, "NetworkError");
|
||||||
|
},
|
||||||
|
);
|
||||||
|
core.registerErrorBuilder(
|
||||||
|
"DOMExceptionAbortError",
|
||||||
|
function DOMExceptionAbortError(msg) {
|
||||||
|
return new DOMException(msg, "AbortError");
|
||||||
|
},
|
||||||
|
);
|
||||||
|
core.registerErrorBuilder(
|
||||||
|
"DOMExceptionInvalidCharacterError",
|
||||||
|
function DOMExceptionInvalidCharacterError(msg) {
|
||||||
|
return new DOMException(msg, "InvalidCharacterError");
|
||||||
|
},
|
||||||
|
);
|
||||||
|
core.registerErrorBuilder(
|
||||||
|
"DOMExceptionDataError",
|
||||||
|
function DOMExceptionDataError(msg) {
|
||||||
|
return new DOMException(msg, "DataError");
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
function runtimeStart(runtimeOptions, source) {
|
function runtimeStart(runtimeOptions, source) {
|
||||||
core.setMacrotaskCallback(timers.handleTimerMacrotask);
|
core.setMacrotaskCallback(timers.handleTimerMacrotask);
|
||||||
core.setMacrotaskCallback(promiseRejectMacrotaskCallback);
|
core.setMacrotaskCallback(promiseRejectMacrotaskCallback);
|
||||||
|
@ -247,72 +310,6 @@ function runtimeStart(runtimeOptions, source) {
|
||||||
colors.setNoColor(runtimeOptions.noColor || !runtimeOptions.isTty);
|
colors.setNoColor(runtimeOptions.noColor || !runtimeOptions.isTty);
|
||||||
// deno-lint-ignore prefer-primordials
|
// deno-lint-ignore prefer-primordials
|
||||||
Error.prepareStackTrace = core.prepareStackTrace;
|
Error.prepareStackTrace = core.prepareStackTrace;
|
||||||
registerErrors();
|
|
||||||
}
|
|
||||||
|
|
||||||
function registerErrors() {
|
|
||||||
core.registerErrorClass("NotFound", errors.NotFound);
|
|
||||||
core.registerErrorClass("PermissionDenied", errors.PermissionDenied);
|
|
||||||
core.registerErrorClass("ConnectionRefused", errors.ConnectionRefused);
|
|
||||||
core.registerErrorClass("ConnectionReset", errors.ConnectionReset);
|
|
||||||
core.registerErrorClass("ConnectionAborted", errors.ConnectionAborted);
|
|
||||||
core.registerErrorClass("NotConnected", errors.NotConnected);
|
|
||||||
core.registerErrorClass("AddrInUse", errors.AddrInUse);
|
|
||||||
core.registerErrorClass("AddrNotAvailable", errors.AddrNotAvailable);
|
|
||||||
core.registerErrorClass("BrokenPipe", errors.BrokenPipe);
|
|
||||||
core.registerErrorClass("AlreadyExists", errors.AlreadyExists);
|
|
||||||
core.registerErrorClass("InvalidData", errors.InvalidData);
|
|
||||||
core.registerErrorClass("TimedOut", errors.TimedOut);
|
|
||||||
core.registerErrorClass("Interrupted", errors.Interrupted);
|
|
||||||
core.registerErrorClass("WouldBlock", errors.WouldBlock);
|
|
||||||
core.registerErrorClass("WriteZero", errors.WriteZero);
|
|
||||||
core.registerErrorClass("UnexpectedEof", errors.UnexpectedEof);
|
|
||||||
core.registerErrorClass("BadResource", errors.BadResource);
|
|
||||||
core.registerErrorClass("Http", errors.Http);
|
|
||||||
core.registerErrorClass("Busy", errors.Busy);
|
|
||||||
core.registerErrorClass("NotSupported", errors.NotSupported);
|
|
||||||
core.registerErrorBuilder(
|
|
||||||
"DOMExceptionOperationError",
|
|
||||||
function DOMExceptionOperationError(msg) {
|
|
||||||
return new DOMException(msg, "OperationError");
|
|
||||||
},
|
|
||||||
);
|
|
||||||
core.registerErrorBuilder(
|
|
||||||
"DOMExceptionQuotaExceededError",
|
|
||||||
function DOMExceptionQuotaExceededError(msg) {
|
|
||||||
return new DOMException(msg, "QuotaExceededError");
|
|
||||||
},
|
|
||||||
);
|
|
||||||
core.registerErrorBuilder(
|
|
||||||
"DOMExceptionNotSupportedError",
|
|
||||||
function DOMExceptionNotSupportedError(msg) {
|
|
||||||
return new DOMException(msg, "NotSupported");
|
|
||||||
},
|
|
||||||
);
|
|
||||||
core.registerErrorBuilder(
|
|
||||||
"DOMExceptionNetworkError",
|
|
||||||
function DOMExceptionNetworkError(msg) {
|
|
||||||
return new DOMException(msg, "NetworkError");
|
|
||||||
},
|
|
||||||
);
|
|
||||||
core.registerErrorBuilder(
|
|
||||||
"DOMExceptionAbortError",
|
|
||||||
function DOMExceptionAbortError(msg) {
|
|
||||||
return new DOMException(msg, "AbortError");
|
|
||||||
},
|
|
||||||
);
|
|
||||||
core.registerErrorBuilder(
|
|
||||||
"DOMExceptionInvalidCharacterError",
|
|
||||||
function DOMExceptionInvalidCharacterError(msg) {
|
|
||||||
return new DOMException(msg, "InvalidCharacterError");
|
|
||||||
},
|
|
||||||
);
|
|
||||||
core.registerErrorBuilder(
|
|
||||||
"DOMExceptionDataError",
|
|
||||||
function DOMExceptionDataError(msg) {
|
|
||||||
return new DOMException(msg, "DataError");
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const pendingRejections = [];
|
const pendingRejections = [];
|
||||||
|
|
|
@ -318,6 +318,7 @@ pub struct WebWorker {
|
||||||
pub worker_type: WebWorkerType,
|
pub worker_type: WebWorkerType,
|
||||||
pub main_module: ModuleSpecifier,
|
pub main_module: ModuleSpecifier,
|
||||||
poll_for_messages_fn: Option<v8::Global<v8::Value>>,
|
poll_for_messages_fn: Option<v8::Global<v8::Value>>,
|
||||||
|
bootstrap_fn_global: Option<v8::Global<v8::Function>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct WebWorkerOptions {
|
pub struct WebWorkerOptions {
|
||||||
|
@ -496,6 +497,25 @@ impl WebWorker {
|
||||||
(internal_handle, external_handle)
|
(internal_handle, external_handle)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let bootstrap_fn_global = {
|
||||||
|
let context = js_runtime.global_context();
|
||||||
|
let scope = &mut js_runtime.handle_scope();
|
||||||
|
let context_local = v8::Local::new(scope, context);
|
||||||
|
let global_obj = context_local.global(scope);
|
||||||
|
let bootstrap_str = v8::String::new(scope, "bootstrap").unwrap();
|
||||||
|
let bootstrap_ns: v8::Local<v8::Object> = global_obj
|
||||||
|
.get(scope, bootstrap_str.into())
|
||||||
|
.unwrap()
|
||||||
|
.try_into()
|
||||||
|
.unwrap();
|
||||||
|
let main_runtime_str = v8::String::new(scope, "workerRuntime").unwrap();
|
||||||
|
let bootstrap_fn =
|
||||||
|
bootstrap_ns.get(scope, main_runtime_str.into()).unwrap();
|
||||||
|
let bootstrap_fn =
|
||||||
|
v8::Local::<v8::Function>::try_from(bootstrap_fn).unwrap();
|
||||||
|
v8::Global::new(scope, bootstrap_fn)
|
||||||
|
};
|
||||||
|
|
||||||
(
|
(
|
||||||
Self {
|
Self {
|
||||||
id: worker_id,
|
id: worker_id,
|
||||||
|
@ -505,6 +525,7 @@ impl WebWorker {
|
||||||
worker_type: options.worker_type,
|
worker_type: options.worker_type,
|
||||||
main_module,
|
main_module,
|
||||||
poll_for_messages_fn: None,
|
poll_for_messages_fn: None,
|
||||||
|
bootstrap_fn_global: Some(bootstrap_fn_global),
|
||||||
},
|
},
|
||||||
external_handle,
|
external_handle,
|
||||||
)
|
)
|
||||||
|
@ -513,15 +534,24 @@ impl WebWorker {
|
||||||
pub fn bootstrap(&mut self, options: &BootstrapOptions) {
|
pub fn bootstrap(&mut self, options: &BootstrapOptions) {
|
||||||
// Instead of using name for log we use `worker-${id}` because
|
// Instead of using name for log we use `worker-${id}` because
|
||||||
// WebWorkers can have empty string as name.
|
// WebWorkers can have empty string as name.
|
||||||
let script = format!(
|
{
|
||||||
"bootstrap.workerRuntime({}, \"{}\", \"{}\")",
|
let scope = &mut self.js_runtime.handle_scope();
|
||||||
options.as_json(),
|
let options_v8 =
|
||||||
self.name,
|
deno_core::serde_v8::to_v8(scope, options.as_json()).unwrap();
|
||||||
self.id
|
let bootstrap_fn = self.bootstrap_fn_global.take().unwrap();
|
||||||
);
|
let bootstrap_fn = v8::Local::new(scope, bootstrap_fn);
|
||||||
self
|
let undefined = v8::undefined(scope);
|
||||||
.execute_script(&located_script_name!(), &script)
|
let name_str: v8::Local<v8::Value> =
|
||||||
.expect("Failed to execute worker bootstrap script");
|
v8::String::new(scope, &self.name).unwrap().into();
|
||||||
|
let id_str: v8::Local<v8::Value> =
|
||||||
|
v8::String::new(scope, &format!("{}", self.id))
|
||||||
|
.unwrap()
|
||||||
|
.into();
|
||||||
|
bootstrap_fn
|
||||||
|
.call(scope, undefined.into(), &[options_v8, name_str, id_str])
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
// TODO(bartlomieju): this could be done using V8 API, without calling `execute_script`.
|
||||||
// Save a reference to function that will start polling for messages
|
// Save a reference to function that will start polling for messages
|
||||||
// from a worker host; it will be called after the user code is loaded.
|
// from a worker host; it will be called after the user code is loaded.
|
||||||
let script = r#"
|
let script = r#"
|
||||||
|
|
|
@ -14,7 +14,6 @@ use deno_cache::SqliteBackedCache;
|
||||||
use deno_core::error::AnyError;
|
use deno_core::error::AnyError;
|
||||||
use deno_core::error::JsError;
|
use deno_core::error::JsError;
|
||||||
use deno_core::futures::Future;
|
use deno_core::futures::Future;
|
||||||
use deno_core::located_script_name;
|
|
||||||
use deno_core::v8;
|
use deno_core::v8;
|
||||||
use deno_core::CompiledWasmModuleStore;
|
use deno_core::CompiledWasmModuleStore;
|
||||||
use deno_core::Extension;
|
use deno_core::Extension;
|
||||||
|
@ -66,6 +65,7 @@ pub struct MainWorker {
|
||||||
should_break_on_first_statement: bool,
|
should_break_on_first_statement: bool,
|
||||||
should_wait_for_inspector_session: bool,
|
should_wait_for_inspector_session: bool,
|
||||||
exit_code: ExitCode,
|
exit_code: ExitCode,
|
||||||
|
bootstrap_fn_global: Option<v8::Global<v8::Function>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct WorkerOptions {
|
pub struct WorkerOptions {
|
||||||
|
@ -318,20 +318,45 @@ impl MainWorker {
|
||||||
op_state.borrow_mut().put(inspector);
|
op_state.borrow_mut().put(inspector);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let bootstrap_fn_global = {
|
||||||
|
let context = js_runtime.global_context();
|
||||||
|
let scope = &mut js_runtime.handle_scope();
|
||||||
|
let context_local = v8::Local::new(scope, context);
|
||||||
|
let global_obj = context_local.global(scope);
|
||||||
|
let bootstrap_str = v8::String::new(scope, "bootstrap").unwrap();
|
||||||
|
let bootstrap_ns: v8::Local<v8::Object> = global_obj
|
||||||
|
.get(scope, bootstrap_str.into())
|
||||||
|
.unwrap()
|
||||||
|
.try_into()
|
||||||
|
.unwrap();
|
||||||
|
let main_runtime_str = v8::String::new(scope, "mainRuntime").unwrap();
|
||||||
|
let bootstrap_fn =
|
||||||
|
bootstrap_ns.get(scope, main_runtime_str.into()).unwrap();
|
||||||
|
let bootstrap_fn =
|
||||||
|
v8::Local::<v8::Function>::try_from(bootstrap_fn).unwrap();
|
||||||
|
v8::Global::new(scope, bootstrap_fn)
|
||||||
|
};
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
js_runtime,
|
js_runtime,
|
||||||
should_break_on_first_statement: options.should_break_on_first_statement,
|
should_break_on_first_statement: options.should_break_on_first_statement,
|
||||||
should_wait_for_inspector_session: options
|
should_wait_for_inspector_session: options
|
||||||
.should_wait_for_inspector_session,
|
.should_wait_for_inspector_session,
|
||||||
exit_code,
|
exit_code,
|
||||||
|
bootstrap_fn_global: Some(bootstrap_fn_global),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn bootstrap(&mut self, options: &BootstrapOptions) {
|
pub fn bootstrap(&mut self, options: &BootstrapOptions) {
|
||||||
let script = format!("bootstrap.mainRuntime({})", options.as_json());
|
let scope = &mut self.js_runtime.handle_scope();
|
||||||
self
|
let options_v8 =
|
||||||
.execute_script(&located_script_name!(), &script)
|
deno_core::serde_v8::to_v8(scope, options.as_json()).unwrap();
|
||||||
.expect("Failed to execute bootstrap script");
|
let bootstrap_fn = self.bootstrap_fn_global.take().unwrap();
|
||||||
|
let bootstrap_fn = v8::Local::new(scope, bootstrap_fn);
|
||||||
|
let undefined = v8::undefined(scope);
|
||||||
|
bootstrap_fn
|
||||||
|
.call(scope, undefined.into(), &[options_v8])
|
||||||
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// See [JsRuntime::execute_script](deno_core::JsRuntime::execute_script)
|
/// See [JsRuntime::execute_script](deno_core::JsRuntime::execute_script)
|
||||||
|
|
|
@ -58,8 +58,8 @@ impl Default for BootstrapOptions {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BootstrapOptions {
|
impl BootstrapOptions {
|
||||||
pub fn as_json(&self) -> String {
|
pub fn as_json(&self) -> serde_json::Value {
|
||||||
let payload = json!({
|
json!({
|
||||||
// Shared bootstrap args
|
// Shared bootstrap args
|
||||||
"args": self.args,
|
"args": self.args,
|
||||||
"cpuCount": self.cpu_count,
|
"cpuCount": self.cpu_count,
|
||||||
|
@ -80,7 +80,6 @@ impl BootstrapOptions {
|
||||||
"v8Version": deno_core::v8_version(),
|
"v8Version": deno_core::v8_version(),
|
||||||
"userAgent": self.user_agent,
|
"userAgent": self.user_agent,
|
||||||
"inspectFlag": self.inspect,
|
"inspectFlag": self.inspect,
|
||||||
});
|
})
|
||||||
serde_json::to_string_pretty(&payload).unwrap()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue