diff options
Diffstat (limited to 'cli/main.rs')
-rw-r--r-- | cli/main.rs | 380 |
1 files changed, 25 insertions, 355 deletions
diff --git a/cli/main.rs b/cli/main.rs index 8489a5f2f..de89c7e12 100644 --- a/cli/main.rs +++ b/cli/main.rs @@ -35,6 +35,7 @@ mod tsc; mod unix_util; mod version; mod windows_util; +mod worker; use crate::args::flags_from_vec; use crate::args::BenchFlags; @@ -67,7 +68,6 @@ use crate::file_watcher::ResolutionResult; use crate::fmt_errors::format_js_error; use crate::graph_util::graph_lock_or_exit; use crate::graph_util::graph_valid; -use crate::module_loader::CliModuleLoader; use crate::proc_state::ProcState; use crate::resolver::ImportMapResolver; use crate::resolver::JsxResolver; @@ -78,26 +78,16 @@ use deno_core::error::generic_error; use deno_core::error::AnyError; use deno_core::error::JsError; use deno_core::futures::future::FutureExt; -use deno_core::futures::future::LocalFutureObj; use deno_core::futures::Future; -use deno_core::located_script_name; use deno_core::parking_lot::RwLock; use deno_core::resolve_url_or_path; use deno_core::serde_json; use deno_core::serde_json::json; use deno_core::v8_set_flags; -use deno_core::Extension; use deno_core::ModuleSpecifier; use deno_runtime::colors; -use deno_runtime::ops::worker_host::CreateWebWorkerCb; -use deno_runtime::ops::worker_host::PreloadModuleCb; use deno_runtime::permissions::Permissions; use deno_runtime::tokio_util::run_local; -use deno_runtime::web_worker::WebWorker; -use deno_runtime::web_worker::WebWorkerOptions; -use deno_runtime::worker::MainWorker; -use deno_runtime::worker::WorkerOptions; -use deno_runtime::BootstrapOptions; use log::debug; use log::info; use std::env; @@ -107,167 +97,7 @@ use std::iter::once; use std::path::PathBuf; use std::pin::Pin; use std::sync::Arc; - -fn create_web_worker_preload_module_callback( - ps: ProcState, -) -> Arc<PreloadModuleCb> { - let compat = ps.options.compat(); - - Arc::new(move |mut worker| { - let fut = async move { - if compat { - worker.execute_side_module(&compat::GLOBAL_URL).await?; - worker.execute_side_module(&compat::MODULE_URL).await?; - } - - Ok(worker) - }; - LocalFutureObj::new(Box::new(fut)) - }) -} - -fn create_web_worker_callback( - ps: ProcState, - stdio: deno_runtime::ops::io::Stdio, -) -> Arc<CreateWebWorkerCb> { - Arc::new(move |args| { - let maybe_inspector_server = ps.maybe_inspector_server.clone(); - - let module_loader = CliModuleLoader::new_for_worker( - ps.clone(), - args.parent_permissions.clone(), - ); - let create_web_worker_cb = - create_web_worker_callback(ps.clone(), stdio.clone()); - let preload_module_cb = - create_web_worker_preload_module_callback(ps.clone()); - - let extensions = ops::cli_exts(ps.clone()); - - let options = WebWorkerOptions { - bootstrap: BootstrapOptions { - args: ps.options.argv().clone(), - cpu_count: std::thread::available_parallelism() - .map(|p| p.get()) - .unwrap_or(1), - debug_flag: ps - .options - .log_level() - .map_or(false, |l| l == log::Level::Debug), - enable_testing_features: ps.options.enable_testing_features(), - location: Some(args.main_module.clone()), - no_color: !colors::use_color(), - is_tty: colors::is_tty(), - runtime_version: version::deno(), - ts_version: version::TYPESCRIPT.to_string(), - unstable: ps.options.unstable(), - user_agent: version::get_user_agent(), - }, - extensions, - unsafely_ignore_certificate_errors: ps - .options - .unsafely_ignore_certificate_errors() - .map(ToOwned::to_owned), - root_cert_store: Some(ps.root_cert_store.clone()), - seed: ps.options.seed(), - create_web_worker_cb, - preload_module_cb, - format_js_error_fn: Some(Arc::new(format_js_error)), - source_map_getter: Some(Box::new(module_loader.clone())), - module_loader, - worker_type: args.worker_type, - maybe_inspector_server, - get_error_class_fn: Some(&errors::get_error_class_name), - blob_store: ps.blob_store.clone(), - broadcast_channel: ps.broadcast_channel.clone(), - shared_array_buffer_store: Some(ps.shared_array_buffer_store.clone()), - compiled_wasm_module_store: Some(ps.compiled_wasm_module_store.clone()), - stdio: stdio.clone(), - }; - - WebWorker::bootstrap_from_options( - args.name, - args.permissions, - args.main_module, - args.worker_id, - options, - ) - }) -} - -pub fn create_main_worker( - ps: &ProcState, - main_module: ModuleSpecifier, - permissions: Permissions, - mut custom_extensions: Vec<Extension>, - stdio: deno_runtime::ops::io::Stdio, -) -> MainWorker { - let module_loader = CliModuleLoader::new(ps.clone()); - - let maybe_inspector_server = ps.maybe_inspector_server.clone(); - let should_break_on_first_statement = ps.options.inspect_brk().is_some(); - - let create_web_worker_cb = - create_web_worker_callback(ps.clone(), stdio.clone()); - let web_worker_preload_module_cb = - create_web_worker_preload_module_callback(ps.clone()); - - let maybe_storage_key = ps.options.resolve_storage_key(&main_module); - let origin_storage_dir = maybe_storage_key.map(|key| { - ps.dir - .root - // TODO(@crowlKats): change to origin_data for 2.0 - .join("location_data") - .join(checksum::gen(&[key.as_bytes()])) - }); - - let mut extensions = ops::cli_exts(ps.clone()); - extensions.append(&mut custom_extensions); - - let options = WorkerOptions { - bootstrap: BootstrapOptions { - args: ps.options.argv().clone(), - cpu_count: std::thread::available_parallelism() - .map(|p| p.get()) - .unwrap_or(1), - debug_flag: ps - .options - .log_level() - .map_or(false, |l| l == log::Level::Debug), - enable_testing_features: ps.options.enable_testing_features(), - location: ps.options.location_flag().map(ToOwned::to_owned), - no_color: !colors::use_color(), - is_tty: colors::is_tty(), - runtime_version: version::deno(), - ts_version: version::TYPESCRIPT.to_string(), - unstable: ps.options.unstable(), - user_agent: version::get_user_agent(), - }, - extensions, - unsafely_ignore_certificate_errors: ps - .options - .unsafely_ignore_certificate_errors() - .map(ToOwned::to_owned), - root_cert_store: Some(ps.root_cert_store.clone()), - seed: ps.options.seed(), - source_map_getter: Some(Box::new(module_loader.clone())), - format_js_error_fn: Some(Arc::new(format_js_error)), - create_web_worker_cb, - web_worker_preload_module_cb, - maybe_inspector_server, - should_break_on_first_statement, - module_loader, - get_error_class_fn: Some(&errors::get_error_class_name), - origin_storage_dir, - blob_store: ps.blob_store.clone(), - broadcast_channel: ps.broadcast_channel.clone(), - shared_array_buffer_store: Some(ps.shared_array_buffer_store.clone()), - compiled_wasm_module_store: Some(ps.compiled_wasm_module_store.clone()), - stdio, - }; - - MainWorker::bootstrap_from_options(main_module, permissions, options) -} +use worker::create_main_worker; pub fn write_to_stdout_ignore_sigpipe( bytes: &[u8], @@ -479,13 +309,13 @@ async fn install_command( let main_module = resolve_url_or_path(&install_flags.module_url)?; let mut worker = create_main_worker( &ps, - main_module.clone(), + main_module, permissions, vec![], Default::default(), ); // First, fetch and compile the module; this step ensures that the module exists. - worker.preload_main_module(&main_module).await?; + worker.preload_main_module().await?; tools::installer::install(flags, install_flags)?; Ok(0) } @@ -593,21 +423,8 @@ async fn eval_command( // Save our fake file into file fetcher cache // to allow module access by TS compiler. ps.file_fetcher.insert_cached(file); - debug!("main_module {}", &main_module); - if ps.options.compat() { - worker.execute_side_module(&compat::GLOBAL_URL).await?; - } - worker.execute_main_module(&main_module).await?; - worker.dispatch_load_event(&located_script_name!())?; - loop { - worker.run_event_loop(false).await?; - - if !worker.dispatch_beforeunload_event(&located_script_name!())? { - break; - } - } - worker.dispatch_unload_event(&located_script_name!())?; - Ok(0) + let exit_code = worker.run().await?; + Ok(exit_code) } async fn create_graph_and_maybe_check( @@ -868,15 +685,14 @@ async fn repl_command( vec![], Default::default(), ); - if ps.options.compat() { - worker.execute_side_module(&compat::GLOBAL_URL).await?; - compat::add_global_require(&mut worker.js_runtime, main_module.as_str())?; - worker.run_event_loop(false).await?; - compat::setup_builtin_modules(&mut worker.js_runtime)?; - } - worker.run_event_loop(false).await?; - - tools::repl::run(&ps, worker, repl_flags.eval_files, repl_flags.eval).await + worker.setup_repl().await?; + tools::repl::run( + &ps, + worker.into_main_worker(), + repl_flags.eval_files, + repl_flags.eval, + ) + .await } async fn run_from_stdin(flags: Flags) -> Result<i32, AnyError> { @@ -905,88 +721,13 @@ async fn run_from_stdin(flags: Flags) -> Result<i32, AnyError> { // to allow module access by TS compiler ps.file_fetcher.insert_cached(source_file); - debug!("main_module {}", main_module); - if ps.options.compat() { - worker.execute_side_module(&compat::GLOBAL_URL).await?; - } - worker.execute_main_module(&main_module).await?; - worker.dispatch_load_event(&located_script_name!())?; - loop { - worker.run_event_loop(false).await?; - if !worker.dispatch_beforeunload_event(&located_script_name!())? { - break; - } - } - worker.dispatch_unload_event(&located_script_name!())?; - Ok(worker.get_exit_code()) + let exit_code = worker.run().await?; + Ok(exit_code) } // TODO(bartlomieju): this function is not handling `exit_code` set by the runtime // code properly. async fn run_with_watch(flags: Flags, script: String) -> Result<i32, AnyError> { - /// The FileWatcherModuleExecutor provides module execution with safe dispatching of life-cycle events by tracking the - /// state of any pending events and emitting accordingly on drop in the case of a future - /// cancellation. - struct FileWatcherModuleExecutor { - worker: MainWorker, - pending_unload: bool, - compat: bool, - } - - impl FileWatcherModuleExecutor { - pub fn new(worker: MainWorker, compat: bool) -> FileWatcherModuleExecutor { - FileWatcherModuleExecutor { - worker, - pending_unload: false, - compat, - } - } - - /// Execute the given main module emitting load and unload events before and after execution - /// respectively. - pub async fn execute( - &mut self, - main_module: &ModuleSpecifier, - ) -> Result<(), AnyError> { - if self.compat { - self.worker.execute_side_module(&compat::GLOBAL_URL).await?; - } - self.worker.execute_main_module(main_module).await?; - self.worker.dispatch_load_event(&located_script_name!())?; - self.pending_unload = true; - - let result = loop { - let result = self.worker.run_event_loop(false).await; - if !self - .worker - .dispatch_beforeunload_event(&located_script_name!())? - { - break result; - } - }; - self.pending_unload = false; - - if let Err(err) = result { - return Err(err); - } - - self.worker.dispatch_unload_event(&located_script_name!())?; - - Ok(()) - } - } - - impl Drop for FileWatcherModuleExecutor { - fn drop(&mut self) { - if self.pending_unload { - self - .worker - .dispatch_unload_event(&located_script_name!()) - .unwrap(); - } - } - } - let flags = Arc::new(flags); let main_module = resolve_url_or_path(&script)?; let (sender, receiver) = tokio::sync::mpsc::unbounded_channel(); @@ -1001,20 +742,14 @@ async fn run_with_watch(flags: Flags, script: String) -> Result<i32, AnyError> { let ps = ProcState::build_for_file_watcher((*flags).clone(), sender.clone()) .await?; - // We make use an module executor guard to ensure that unload is always fired when an - // operation is called. - let mut executor = FileWatcherModuleExecutor::new( - create_main_worker( - &ps, - main_module.clone(), - permissions, - vec![], - Default::default(), - ), - flags.compat, + let worker = create_main_worker( + &ps, + main_module.clone(), + permissions, + vec![], + Default::default(), ); - - executor.execute(&main_module).await?; + worker.run_for_watcher().await?; Ok(()) }) @@ -1064,73 +799,8 @@ async fn run_command( Default::default(), ); - let mut maybe_coverage_collector = - if let Some(ref coverage_dir) = ps.coverage_dir { - let session = worker.create_inspector_session().await; - - let coverage_dir = PathBuf::from(coverage_dir); - let mut coverage_collector = - tools::coverage::CoverageCollector::new(coverage_dir, session); - worker - .with_event_loop(coverage_collector.start_collecting().boxed_local()) - .await?; - Some(coverage_collector) - } else { - None - }; - - debug!("main_module {}", main_module); - - if ps.options.compat() { - // TODO(bartlomieju): fix me - assert_eq!(main_module.scheme(), "file"); - - // Set up Node globals - worker.execute_side_module(&compat::GLOBAL_URL).await?; - // And `module` module that we'll use for checking which - // loader to use and potentially load CJS module with. - // This allows to skip permission check for `--allow-net` - // which would otherwise be requested by dynamically importing - // this file. - worker.execute_side_module(&compat::MODULE_URL).await?; - - let use_esm_loader = compat::check_if_should_use_esm_loader(&main_module)?; - - if use_esm_loader { - // ES module execution in Node compatiblity mode - worker.execute_main_module(&main_module).await?; - } else { - // CJS module execution in Node compatiblity mode - compat::load_cjs_module( - &mut worker.js_runtime, - &main_module.to_file_path().unwrap().display().to_string(), - true, - )?; - } - } else { - // Regular ES module execution - worker.execute_main_module(&main_module).await?; - } - - worker.dispatch_load_event(&located_script_name!())?; - - loop { - worker - .run_event_loop(maybe_coverage_collector.is_none()) - .await?; - if !worker.dispatch_beforeunload_event(&located_script_name!())? { - break; - } - } - - worker.dispatch_unload_event(&located_script_name!())?; - - if let Some(coverage_collector) = maybe_coverage_collector.as_mut() { - worker - .with_event_loop(coverage_collector.stop_collecting().boxed_local()) - .await?; - } - Ok(worker.get_exit_code()) + let exit_code = worker.run().await?; + Ok(exit_code) } async fn task_command( |