diff options
Diffstat (limited to 'runtime')
-rw-r--r-- | runtime/js/99_main.js | 19 | ||||
-rw-r--r-- | runtime/ops/worker_host.rs | 25 | ||||
-rw-r--r-- | runtime/web_worker.rs | 36 | ||||
-rw-r--r-- | runtime/worker.rs | 14 | ||||
-rw-r--r-- | runtime/worker_bootstrap.rs | 204 |
5 files changed, 103 insertions, 195 deletions
diff --git a/runtime/js/99_main.js b/runtime/js/99_main.js index c8fdabc25..fdd82862c 100644 --- a/runtime/js/99_main.js +++ b/runtime/js/99_main.js @@ -438,6 +438,7 @@ function bootstrapMainRuntime(runtimeOptions) { if (hasBootstrapped) { throw new Error("Worker runtime already bootstrapped"); } + const nodeBootstrap = globalThis.nodeBootstrap; const { 0: args, @@ -456,6 +457,8 @@ function bootstrapMainRuntime(runtimeOptions) { 13: userAgent, 14: inspectFlag, // 15: enableTestingFeaturesFlag + 16: hasNodeModulesDir, + 17: maybeBinaryNpmCommandName, } = runtimeOptions; performance.setTimeOrigin(DateNow()); @@ -464,12 +467,13 @@ function bootstrapMainRuntime(runtimeOptions) { // 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_ === undefined) { + if (location_ == null) { mainRuntimeGlobalProperties.location = { writable: true, }; @@ -542,6 +546,10 @@ function bootstrapMainRuntime(runtimeOptions) { ObjectDefineProperty(globalThis, "Deno", util.readOnly(finalDenoNs)); util.log("args", args); + + if (nodeBootstrap) { + nodeBootstrap(hasNodeModulesDir, maybeBinaryNpmCommandName); + } } function bootstrapWorkerRuntime( @@ -553,6 +561,8 @@ function bootstrapWorkerRuntime( throw new Error("Worker runtime already bootstrapped"); } + const nodeBootstrap = globalThis.nodeBootstrap; + const { 0: args, 1: cpuCount, @@ -570,6 +580,8 @@ function bootstrapWorkerRuntime( 13: userAgent, // 14: inspectFlag, 15: enableTestingFeaturesFlag, + 16: hasNodeModulesDir, + 17: maybeBinaryNpmCommandName, } = runtimeOptions; performance.setTimeOrigin(DateNow()); @@ -580,6 +592,7 @@ function bootstrapWorkerRuntime( // Remove bootstrapping data from the global scope delete globalThis.__bootstrap; delete globalThis.bootstrap; + delete globalThis.nodeBootstrap; hasBootstrapped = true; if (unstableFlag) { @@ -649,6 +662,10 @@ function bootstrapWorkerRuntime( // Setup `Deno` global - we're actually overriding already // existing global `Deno` with `Deno` namespace from "./deno.ts". ObjectDefineProperty(globalThis, "Deno", util.readOnly(finalDenoNs)); + + if (nodeBootstrap) { + nodeBootstrap(hasNodeModulesDir, maybeBinaryNpmCommandName); + } } globalThis.bootstrap = { diff --git a/runtime/ops/worker_host.rs b/runtime/ops/worker_host.rs index f96ae38e8..9bfbd9d10 100644 --- a/runtime/ops/worker_host.rs +++ b/runtime/ops/worker_host.rs @@ -13,7 +13,6 @@ use crate::web_worker::WorkerControlEvent; use crate::web_worker::WorkerId; use crate::worker::FormatJsErrorFn; use deno_core::error::AnyError; -use deno_core::futures::future::LocalFutureObj; use deno_core::op; use deno_core::serde::Deserialize; use deno_core::CancelFuture; @@ -40,10 +39,6 @@ pub type CreateWebWorkerCb = dyn Fn(CreateWebWorkerArgs) -> (WebWorker, Sendable + Sync + Send; -pub type WorkerEventCb = dyn Fn(WebWorker) -> LocalFutureObj<'static, Result<WebWorker, AnyError>> - + Sync - + Send; - /// A holder for callback that is used to create a new /// WebWorker. It's a struct instead of a type alias /// because `GothamState` used in `OpState` overrides @@ -54,12 +49,6 @@ struct CreateWebWorkerCbHolder(Arc<CreateWebWorkerCb>); #[derive(Clone)] struct FormatJsErrorFnHolder(Option<Arc<FormatJsErrorFn>>); -#[derive(Clone)] -struct PreloadModuleCbHolder(Arc<WorkerEventCb>); - -#[derive(Clone)] -struct PreExecuteModuleCbHolder(Arc<WorkerEventCb>); - pub struct WorkerThread { worker_handle: WebWorkerHandle, cancel_handle: Rc<CancelHandle>, @@ -98,8 +87,6 @@ deno_core::extension!( ], options = { create_web_worker_cb: Arc<CreateWebWorkerCb>, - preload_module_cb: Arc<WorkerEventCb>, - pre_execute_module_cb: Arc<WorkerEventCb>, format_js_error_fn: Option<Arc<FormatJsErrorFn>>, }, state = |state, options| { @@ -109,12 +96,6 @@ deno_core::extension!( let create_web_worker_cb_holder = CreateWebWorkerCbHolder(options.create_web_worker_cb); state.put::<CreateWebWorkerCbHolder>(create_web_worker_cb_holder); - let preload_module_cb_holder = - PreloadModuleCbHolder(options.preload_module_cb); - state.put::<PreloadModuleCbHolder>(preload_module_cb_holder); - let pre_execute_module_cb_holder = - PreExecuteModuleCbHolder(options.pre_execute_module_cb); - state.put::<PreExecuteModuleCbHolder>(pre_execute_module_cb_holder); let format_js_error_fn_holder = FormatJsErrorFnHolder(options.format_js_error_fn); state.put::<FormatJsErrorFnHolder>(format_js_error_fn_holder); @@ -174,10 +155,6 @@ fn op_create_worker( let worker_id = state.take::<WorkerId>(); let create_web_worker_cb = state.take::<CreateWebWorkerCbHolder>(); state.put::<CreateWebWorkerCbHolder>(create_web_worker_cb.clone()); - let preload_module_cb = state.take::<PreloadModuleCbHolder>(); - state.put::<PreloadModuleCbHolder>(preload_module_cb.clone()); - let pre_execute_module_cb = state.take::<PreExecuteModuleCbHolder>(); - state.put::<PreExecuteModuleCbHolder>(pre_execute_module_cb.clone()); let format_js_error_fn = state.take::<FormatJsErrorFnHolder>(); state.put::<FormatJsErrorFnHolder>(format_js_error_fn.clone()); state.put::<WorkerId>(worker_id.next().unwrap()); @@ -221,8 +198,6 @@ fn op_create_worker( worker, module_specifier, maybe_source_code, - preload_module_cb.0, - pre_execute_module_cb.0, format_js_error_fn.0, ) })?; diff --git a/runtime/web_worker.rs b/runtime/web_worker.rs index a3b93836c..0c4e95140 100644 --- a/runtime/web_worker.rs +++ b/runtime/web_worker.rs @@ -338,8 +338,6 @@ pub struct WebWorkerOptions { pub module_loader: Rc<dyn ModuleLoader>, pub npm_resolver: Option<Arc<dyn deno_node::NpmResolver>>, pub create_web_worker_cb: Arc<ops::worker_host::CreateWebWorkerCb>, - pub preload_module_cb: Arc<ops::worker_host::WorkerEventCb>, - pub pre_execute_module_cb: Arc<ops::worker_host::WorkerEventCb>, pub format_js_error_fn: Option<Arc<FormatJsErrorFn>>, pub source_map_getter: Option<Box<dyn SourceMapGetter>>, pub worker_type: WebWorkerType, @@ -460,8 +458,6 @@ impl WebWorker { ops::runtime::deno_runtime::init_ops_and_esm(main_module.clone()), ops::worker_host::deno_worker_host::init_ops_and_esm( options.create_web_worker_cb.clone(), - options.preload_module_cb.clone(), - options.pre_execute_module_cb.clone(), options.format_js_error_fn.clone(), ), ops::fs_events::deno_fs_events::init_ops_and_esm(), @@ -600,7 +596,7 @@ impl WebWorker { .unwrap() .into(); bootstrap_fn - .call(scope, undefined.into(), &[args.into(), name_str, id_str]) + .call(scope, undefined.into(), &[args, name_str, id_str]) .unwrap(); } // TODO(bartlomieju): this could be done using V8 API, without calling `execute_script`. @@ -782,11 +778,9 @@ fn print_worker_error( /// This function should be called from a thread dedicated to this worker. // TODO(bartlomieju): check if order of actions is aligned to Worker spec pub fn run_web_worker( - worker: WebWorker, + mut worker: WebWorker, specifier: ModuleSpecifier, mut maybe_source_code: Option<String>, - preload_module_cb: Arc<ops::worker_host::WorkerEventCb>, - pre_execute_module_cb: Arc<ops::worker_host::WorkerEventCb>, format_js_error_fn: Option<Arc<FormatJsErrorFn>>, ) -> Result<(), AnyError> { let name = worker.name.to_string(); @@ -796,20 +790,6 @@ pub fn run_web_worker( let fut = async move { let internal_handle = worker.internal_handle.clone(); - let result = (preload_module_cb)(worker).await; - - let mut worker = match result { - Ok(worker) => worker, - Err(e) => { - print_worker_error(&e, &name, format_js_error_fn.as_deref()); - internal_handle - .post_event(WorkerControlEvent::TerminalError(e)) - .expect("Failed to post message to host"); - - // Failure to execute script is a terminal error, bye, bye. - return Ok(()); - } - }; // Execute provided source code immediately let result = if let Some(source_code) = maybe_source_code.take() { @@ -821,18 +801,6 @@ pub fn run_web_worker( // script instead of module match worker.preload_main_module(&specifier).await { Ok(id) => { - worker = match (pre_execute_module_cb)(worker).await { - Ok(worker) => worker, - Err(e) => { - print_worker_error(&e, &name, format_js_error_fn.as_deref()); - internal_handle - .post_event(WorkerControlEvent::TerminalError(e)) - .expect("Failed to post message to host"); - - // Failure to execute script is a terminal error, bye, bye. - return Ok(()); - } - }; worker.start_polling_for_messages(); worker.execute_main_module(id).await } diff --git a/runtime/worker.rs b/runtime/worker.rs index 060f5537b..5eefd5fa8 100644 --- a/runtime/worker.rs +++ b/runtime/worker.rs @@ -178,8 +178,6 @@ pub struct WorkerOptions { pub npm_resolver: Option<Arc<dyn deno_node::NpmResolver>>, // Callbacks invoked when creating new instance of WebWorker pub create_web_worker_cb: Arc<ops::worker_host::CreateWebWorkerCb>, - pub web_worker_preload_module_cb: Arc<ops::worker_host::WorkerEventCb>, - pub web_worker_pre_execute_module_cb: Arc<ops::worker_host::WorkerEventCb>, pub format_js_error_fn: Option<Arc<FormatJsErrorFn>>, /// Source map reference for errors. @@ -221,12 +219,6 @@ pub struct WorkerOptions { impl Default for WorkerOptions { fn default() -> Self { Self { - web_worker_preload_module_cb: Arc::new(|_| { - unimplemented!("web workers are not supported") - }), - web_worker_pre_execute_module_cb: Arc::new(|_| { - unimplemented!("web workers are not supported") - }), create_web_worker_cb: Arc::new(|_| { unimplemented!("web workers are not supported") }), @@ -362,8 +354,6 @@ impl MainWorker { ops::runtime::deno_runtime::init_ops_and_esm(main_module.clone()), ops::worker_host::deno_worker_host::init_ops_and_esm( options.create_web_worker_cb.clone(), - options.web_worker_preload_module_cb.clone(), - options.web_worker_pre_execute_module_cb.clone(), options.format_js_error_fn.clone(), ), ops::fs_events::deno_fs_events::init_ops_and_esm(), @@ -478,9 +468,7 @@ impl MainWorker { 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(), &[args.into()]) - .unwrap(); + bootstrap_fn.call(scope, undefined.into(), &[args]).unwrap(); } /// See [JsRuntime::execute_script](deno_core::JsRuntime::execute_script) diff --git a/runtime/worker_bootstrap.rs b/runtime/worker_bootstrap.rs index 9627281a6..0f533344f 100644 --- a/runtime/worker_bootstrap.rs +++ b/runtime/worker_bootstrap.rs @@ -2,6 +2,8 @@ use deno_core::v8; use deno_core::ModuleSpecifier; +use serde::Serialize; +use std::cell::RefCell; use std::thread; use crate::colors; @@ -55,6 +57,8 @@ pub struct BootstrapOptions { pub unstable: bool, pub user_agent: String, pub inspect: bool, + pub has_node_modules_dir: bool, + pub maybe_binary_npm_command_name: Option<String>, } impl Default for BootstrapOptions { @@ -80,135 +84,91 @@ impl Default for BootstrapOptions { unstable: Default::default(), inspect: Default::default(), args: Default::default(), + has_node_modules_dir: Default::default(), + maybe_binary_npm_command_name: None, } } } +/// This is a struct that we use to serialize the contents of the `BootstrapOptions` +/// struct above to a V8 form. While `serde_v8` is not as fast as hand-coding this, +/// it's "fast enough" while serializing a large tuple like this that it doesn't appear +/// on flamegraphs. +/// +/// Note that a few fields in here are derived from the process and environment and +/// are not sourced from the underlying `BootstrapOptions`. +/// +/// Keep this in sync with `99_main.js`. +#[derive(Serialize)] +struct BootstrapV8<'a>( + // args + &'a Vec<String>, + // cpu_count + i32, + // log_level + i32, + // runtime_version + &'a str, + // locale + &'a str, + // location + Option<&'a str>, + // no_color + bool, + // is_tty + bool, + // ts_version + &'a str, + // unstable + bool, + // process_id + i32, + // env!("TARGET") + &'a str, + // v8_version + &'a str, + // user_agent + &'a str, + // inspect + bool, + // enable_testing_features + bool, + // has_node_modules_dir + bool, + // maybe_binary_npm_command_name + Option<&'a str>, +); + impl BootstrapOptions { + /// Return the v8 equivalent of this structure. pub fn as_v8<'s>( &self, scope: &mut v8::HandleScope<'s>, - ) -> v8::Local<'s, v8::Array> { - let array = v8::Array::new(scope, 16); - - { - let args = v8::Array::new(scope, self.args.len() as i32); - for (idx, arg) in self.args.iter().enumerate() { - let arg_str = v8::String::new(scope, arg).unwrap(); - args.set_index(scope, idx as u32, arg_str.into()); - } - array.set_index(scope, 0, args.into()); - } - - { - let val = v8::Integer::new(scope, self.cpu_count as i32); - array.set_index(scope, 1, val.into()); - } - - { - let val = v8::Integer::new(scope, self.log_level as i32); - 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::String::new_external_onebyte_static( - scope, - env!("TARGET").as_bytes(), - ) - .unwrap(); - array.set_index(scope, 11, 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, 12, val.into()); - } - - { - let val = v8::String::new_from_one_byte( - scope, - self.user_agent.as_bytes(), - v8::NewStringType::Normal, - ) - .unwrap(); - array.set_index(scope, 13, val.into()); - } - - { - let val = v8::Boolean::new(scope, self.inspect); - array.set_index(scope, 14, val.into()); - } - - { - let val = v8::Boolean::new(scope, self.enable_testing_features); - array.set_index(scope, 15, val.into()); - } - - array + ) -> v8::Local<'s, v8::Value> { + let scope = RefCell::new(scope); + let ser = deno_core::serde_v8::Serializer::new(&scope); + + let bootstrap = BootstrapV8( + &self.args, + self.cpu_count as _, + self.log_level as _, + &self.runtime_version, + &self.locale, + self.location.as_ref().map(|l| l.as_str()), + self.no_color, + self.is_tty, + &self.ts_version, + self.unstable, + std::process::id() as _, + env!("TARGET"), + deno_core::v8_version(), + &self.user_agent, + self.inspect, + self.enable_testing_features, + self.has_node_modules_dir, + self.maybe_binary_npm_command_name.as_deref(), + ); + + bootstrap.serialize(ser).unwrap() } } |