diff --git a/cli/args/mod.rs b/cli/args/mod.rs index f83b339368..440403f62c 100644 --- a/cli/args/mod.rs +++ b/cli/args/mod.rs @@ -817,30 +817,6 @@ impl CliOptions { ) } - /// Resolves the storage key to use based on the current flags, config, or main module. - pub fn resolve_storage_key( - &self, - main_module: &ModuleSpecifier, - ) -> Option { - if let Some(location) = &self.flags.location { - // if a location is set, then the ascii serialization of the location is - // used, unless the origin is opaque, and then no storage origin is set, as - // we can't expect the origin to be reproducible - let storage_origin = location.origin(); - if storage_origin.is_tuple() { - Some(storage_origin.ascii_serialization()) - } else { - None - } - } else if let Some(config_file) = &self.maybe_config_file { - // otherwise we will use the path to the config file - Some(config_file.specifier.to_string()) - } else { - // otherwise we will use the path to the main module - Some(main_module.to_string()) - } - } - pub fn resolve_inspector_server(&self) -> Option { let maybe_inspect_host = self .flags @@ -1089,20 +1065,6 @@ impl CliOptions { &self.flags.subcommand } - pub fn trace_ops(&self) -> bool { - match self.sub_command() { - DenoSubcommand::Test(flags) => flags.trace_ops, - _ => false, - } - } - - pub fn shuffle_tests(&self) -> Option { - match self.sub_command() { - DenoSubcommand::Test(flags) => flags.shuffle, - _ => None, - } - } - pub fn type_check_mode(&self) -> TypeCheckMode { self.flags.type_check_mode } @@ -1216,6 +1178,44 @@ fn resolve_import_map_specifier( Ok(None) } +pub struct StorageKeyResolver(Option>); + +impl StorageKeyResolver { + pub fn from_options(options: &CliOptions) -> Self { + Self(if let Some(location) = &options.flags.location { + // if a location is set, then the ascii serialization of the location is + // used, unless the origin is opaque, and then no storage origin is set, as + // we can't expect the origin to be reproducible + let storage_origin = location.origin(); + if storage_origin.is_tuple() { + Some(Some(storage_origin.ascii_serialization())) + } else { + Some(None) + } + } else { + // otherwise we will use the path to the config file or None to + // fall back to using the main module's path + options + .maybe_config_file + .as_ref() + .map(|config_file| Some(config_file.specifier.to_string())) + }) + } + + /// Resolves the storage key to use based on the current flags, config, or main module. + pub fn resolve_storage_key( + &self, + main_module: &ModuleSpecifier, + ) -> Option { + // use the stored value or fall back to using the path of the main module. + if let Some(maybe_value) = &self.0 { + maybe_value.clone() + } else { + Some(main_module.to_string()) + } + } +} + /// Collect included and ignored files. CLI flags take precedence /// over config file, i.e. if there's `files.ignore` in config file /// and `--ignore` CLI flag, only the flag value is taken into account. @@ -1381,4 +1381,21 @@ mod test { let actual = actual.unwrap(); assert_eq!(actual, None); } + + #[test] + fn storage_key_resolver_test() { + let resolver = StorageKeyResolver(None); + let specifier = ModuleSpecifier::parse("file:///a.ts").unwrap(); + assert_eq!( + resolver.resolve_storage_key(&specifier), + Some(specifier.to_string()) + ); + let resolver = StorageKeyResolver(Some(None)); + assert_eq!(resolver.resolve_storage_key(&specifier), None); + let resolver = StorageKeyResolver(Some(Some("value".to_string()))); + assert_eq!( + resolver.resolve_storage_key(&specifier), + Some("value".to_string()) + ); + } } diff --git a/cli/lsp/testing/execution.rs b/cli/lsp/testing/execution.rs index 5e5a3788af..b7859ebda4 100644 --- a/cli/lsp/testing/execution.rs +++ b/cli/lsp/testing/execution.rs @@ -257,10 +257,11 @@ impl TestRun { let tests: Arc>> = Arc::new(RwLock::new(IndexMap::new())); let mut test_steps = IndexMap::new(); + let worker_factory = Arc::new(ps.into_cli_main_worker_factory()); let join_handles = queue.into_iter().map(move |specifier| { let specifier = specifier.clone(); - let ps = ps.clone(); + let worker_factory = worker_factory.clone(); let permissions = permissions.clone(); let mut sender = sender.clone(); let fail_fast_tracker = fail_fast_tracker.clone(); @@ -288,12 +289,16 @@ impl TestRun { Ok(()) } else { run_local(test::test_specifier( - &ps, + &worker_factory, permissions, specifier, sender.clone(), fail_fast_tracker, - filter, + &test::TestSpecifierOptions { + filter, + shuffle: None, + trace_ops: false, + }, )) }; if let Err(error) = file_result { diff --git a/cli/module_loader.rs b/cli/module_loader.rs index e4b8b616d7..7de45af28a 100644 --- a/cli/module_loader.rs +++ b/cli/module_loader.rs @@ -14,7 +14,6 @@ use crate::node; use crate::node::CliNodeCodeTranslator; use crate::proc_state::CjsResolutionStore; use crate::proc_state::FileWatcherReporter; -use crate::proc_state::ProcState; use crate::resolver::CliGraphResolver; use crate::tools::check; use crate::tools::check::TypeChecker; @@ -224,6 +223,88 @@ pub struct ModuleCodeSource { pub media_type: MediaType, } +struct SharedCliModuleLoaderState { + lib_window: TsTypeLib, + lib_worker: TsTypeLib, + is_inspecting: bool, + is_repl: bool, + emitter: Arc, + graph_container: Arc, + module_load_preparer: Arc, + parsed_source_cache: Arc, + resolver: Arc, + npm_module_loader: NpmModuleLoader, +} + +pub struct CliModuleLoaderFactory { + state: Arc, +} + +impl CliModuleLoaderFactory { + pub fn new( + options: &CliOptions, + emitter: Arc, + graph_container: Arc, + module_load_preparer: Arc, + parsed_source_cache: Arc, + resolver: Arc, + npm_module_loader: NpmModuleLoader, + ) -> Self { + Self { + state: Arc::new(SharedCliModuleLoaderState { + lib_window: options.ts_type_lib_window(), + lib_worker: options.ts_type_lib_worker(), + is_inspecting: options.is_inspecting(), + is_repl: matches!(options.sub_command(), DenoSubcommand::Repl(_)), + emitter, + graph_container, + module_load_preparer, + parsed_source_cache, + resolver, + npm_module_loader, + }), + } + } + + pub fn create_for_main( + &self, + root_permissions: PermissionsContainer, + dynamic_permissions: PermissionsContainer, + ) -> CliModuleLoader { + self.create_with_lib( + self.state.lib_window, + root_permissions, + dynamic_permissions, + ) + } + + pub fn create_for_worker( + &self, + root_permissions: PermissionsContainer, + dynamic_permissions: PermissionsContainer, + ) -> CliModuleLoader { + self.create_with_lib( + self.state.lib_worker, + root_permissions, + dynamic_permissions, + ) + } + + fn create_with_lib( + &self, + lib: TsTypeLib, + root_permissions: PermissionsContainer, + dynamic_permissions: PermissionsContainer, + ) -> CliModuleLoader { + CliModuleLoader { + lib, + root_permissions, + dynamic_permissions, + shared: self.state.clone(), + } + } +} + pub struct CliModuleLoader { lib: TsTypeLib, /// The initial set of permissions used to resolve the static imports in the @@ -233,62 +314,10 @@ pub struct CliModuleLoader { /// Permissions used to resolve dynamic imports, these get passed as /// "root permissions" for Web Worker. dynamic_permissions: PermissionsContainer, - cli_options: Arc, - emitter: Arc, - graph_container: Arc, - module_load_preparer: Arc, - parsed_source_cache: Arc, - resolver: Arc, - npm_module_loader: NpmModuleLoader, + shared: Arc, } impl CliModuleLoader { - pub fn new( - ps: ProcState, - root_permissions: PermissionsContainer, - dynamic_permissions: PermissionsContainer, - ) -> Rc { - Rc::new(CliModuleLoader { - lib: ps.options.ts_type_lib_window(), - root_permissions, - dynamic_permissions, - cli_options: ps.options.clone(), - emitter: ps.emitter.clone(), - graph_container: ps.graph_container.clone(), - module_load_preparer: ps.module_load_preparer.clone(), - parsed_source_cache: ps.parsed_source_cache.clone(), - resolver: ps.resolver.clone(), - npm_module_loader: NpmModuleLoader::new( - ps.cjs_resolutions.clone(), - ps.node_code_translator.clone(), - ps.node_resolver.clone(), - ), - }) - } - - pub fn new_for_worker( - ps: ProcState, - root_permissions: PermissionsContainer, - dynamic_permissions: PermissionsContainer, - ) -> Rc { - Rc::new(CliModuleLoader { - lib: ps.options.ts_type_lib_worker(), - root_permissions, - dynamic_permissions, - cli_options: ps.options.clone(), - emitter: ps.emitter.clone(), - graph_container: ps.graph_container.clone(), - module_load_preparer: ps.module_load_preparer.clone(), - parsed_source_cache: ps.parsed_source_cache.clone(), - resolver: ps.resolver.clone(), - npm_module_loader: NpmModuleLoader::new( - ps.cjs_resolutions.clone(), - ps.node_code_translator.clone(), - ps.node_resolver.clone(), - ), - }) - } - fn load_prepared_module( &self, specifier: &ModuleSpecifier, @@ -298,7 +327,7 @@ impl CliModuleLoader { unreachable!(); // Node built-in modules should be handled internally. } - let graph = self.graph_container.graph(); + let graph = self.shared.graph_container.graph(); match graph.get(specifier) { Some(deno_graph::Module::Json(JsonModule { source, @@ -331,9 +360,11 @@ impl CliModuleLoader { | MediaType::Jsx | MediaType::Tsx => { // get emit text - self - .emitter - .emit_parsed_source(specifier, *media_type, source)? + self.shared.emitter.emit_parsed_source( + specifier, + *media_type, + source, + )? } MediaType::TsBuildInfo | MediaType::Wasm | MediaType::SourceMap => { panic!("Unexpected media type {media_type} for {specifier}") @@ -341,7 +372,7 @@ impl CliModuleLoader { }; // at this point, we no longer need the parsed source in memory, so free it - self.parsed_source_cache.free(specifier); + self.shared.parsed_source_cache.free(specifier); Ok(ModuleCodeSource { code, @@ -370,15 +401,17 @@ impl CliModuleLoader { } else { &self.root_permissions }; - let code_source = if let Some(code_source) = self - .npm_module_loader - .load_sync(specifier, maybe_referrer, permissions)? - { + let code_source = if let Some(code_source) = + self.shared.npm_module_loader.load_sync( + specifier, + maybe_referrer, + permissions, + )? { code_source } else { self.load_prepared_module(specifier, maybe_referrer)? }; - let code = if self.cli_options.is_inspecting() { + let code = if self.shared.is_inspecting { // we need the code with the source map in order for // it to work with --inspect or --inspect-brk code_source.code @@ -418,15 +451,15 @@ impl ModuleLoader for CliModuleLoader { let referrer_result = deno_core::resolve_url_or_path(referrer, &cwd); if let Ok(referrer) = referrer_result.as_ref() { - if let Some(result) = self.npm_module_loader.resolve_if_in_npm_package( - specifier, - referrer, - permissions, - ) { + if let Some(result) = self + .shared + .npm_module_loader + .resolve_if_in_npm_package(specifier, referrer, permissions) + { return result; } - let graph = self.graph_container.graph(); + let graph = self.shared.graph_container.graph(); let maybe_resolved = match graph.get(referrer) { Some(Module::Esm(module)) => { module.dependencies.get(specifier).map(|d| &d.maybe_code) @@ -440,6 +473,7 @@ impl ModuleLoader for CliModuleLoader { return match graph.get(specifier) { Some(Module::Npm(module)) => self + .shared .npm_module_loader .resolve_npm_module(module, permissions), Some(Module::Node(module)) => { @@ -471,9 +505,7 @@ impl ModuleLoader for CliModuleLoader { // FIXME(bartlomieju): this is a hacky way to provide compatibility with REPL // and `Deno.core.evalContext` API. Ideally we should always have a referrer filled // but sadly that's not the case due to missing APIs in V8. - let is_repl = - matches!(self.cli_options.sub_command(), DenoSubcommand::Repl(_)); - let referrer = if referrer.is_empty() && is_repl { + let referrer = if referrer.is_empty() && self.shared.is_repl { deno_core::resolve_path("./$deno$repl.ts", &cwd)? } else { referrer_result? @@ -481,9 +513,9 @@ impl ModuleLoader for CliModuleLoader { // FIXME(bartlomieju): this is another hack way to provide NPM specifier // support in REPL. This should be fixed. - let resolution = self.resolver.resolve(specifier, &referrer); + let resolution = self.shared.resolver.resolve(specifier, &referrer); - if is_repl { + if self.shared.is_repl { let specifier = resolution .as_ref() .ok() @@ -494,6 +526,7 @@ impl ModuleLoader for CliModuleLoader { NpmPackageReqReference::from_specifier(&specifier) { return self + .shared .npm_module_loader .resolve_for_repl(&reference, permissions); } @@ -526,12 +559,14 @@ impl ModuleLoader for CliModuleLoader { _maybe_referrer: Option, is_dynamic: bool, ) -> Pin>>> { - if let Some(result) = self.npm_module_loader.maybe_prepare_load(specifier) { + if let Some(result) = + self.shared.npm_module_loader.maybe_prepare_load(specifier) + { return Box::pin(deno_core::futures::future::ready(result)); } let specifier = specifier.clone(); - let module_load_preparer = self.module_load_preparer.clone(); + let module_load_preparer = self.shared.module_load_preparer.clone(); let root_permissions = if is_dynamic { self.dynamic_permissions.clone() @@ -567,7 +602,7 @@ impl SourceMapGetter for CliModuleLoader { file_name: &str, line_number: usize, ) -> Option { - let graph = self.graph_container.graph(); + let graph = self.shared.graph_container.graph(); let code = match graph.get(&resolve_url(file_name).ok()?) { Some(deno_graph::Module::Esm(module)) => &module.source, Some(deno_graph::Module::Json(module)) => &module.source, diff --git a/cli/proc_state.rs b/cli/proc_state.rs index 950e198242..bb8fd9c3e7 100644 --- a/cli/proc_state.rs +++ b/cli/proc_state.rs @@ -4,6 +4,7 @@ use crate::args::CliOptions; use crate::args::DenoSubcommand; use crate::args::Flags; use crate::args::Lockfile; +use crate::args::StorageKeyResolver; use crate::args::TsConfigType; use crate::cache::Caches; use crate::cache::DenoDir; @@ -16,7 +17,9 @@ use crate::file_fetcher::FileFetcher; use crate::graph_util::ModuleGraphBuilder; use crate::graph_util::ModuleGraphContainer; use crate::http_util::HttpClient; +use crate::module_loader::CliModuleLoaderFactory; use crate::module_loader::ModuleLoadPreparer; +use crate::module_loader::NpmModuleLoader; use crate::node::CliCjsEsmCodeAnalyzer; use crate::node::CliNodeCodeTranslator; use crate::npm::create_npm_fs_resolver; @@ -29,20 +32,20 @@ use crate::resolver::CliGraphResolver; use crate::tools::check::TypeChecker; use crate::util::progress_bar::ProgressBar; use crate::util::progress_bar::ProgressBarStyle; +use crate::worker::CliMainWorkerFactory; +use crate::worker::CliMainWorkerOptions; use deno_core::error::AnyError; use deno_core::parking_lot::Mutex; -use deno_core::CompiledWasmModuleStore; use deno_core::ModuleSpecifier; -use deno_core::SharedArrayBufferStore; -use deno_runtime::deno_broadcast_channel::InMemoryBroadcastChannel; use deno_runtime::deno_node; use deno_runtime::deno_node::analyze::NodeCodeTranslator; use deno_runtime::deno_node::NodeResolver; use deno_runtime::deno_tls::rustls::RootCertStore; use deno_runtime::deno_web::BlobStore; use deno_runtime::inspector_server::InspectorServer; +use deno_semver::npm::NpmPackageReqReference; use import_map::ImportMap; use log::warn; use std::collections::HashSet; @@ -70,9 +73,6 @@ pub struct Inner { pub maybe_inspector_server: Option>, pub root_cert_store: RootCertStore, pub blob_store: BlobStore, - pub broadcast_channel: InMemoryBroadcastChannel, - pub shared_array_buffer_store: SharedArrayBufferStore, - pub compiled_wasm_module_store: CompiledWasmModuleStore, pub parsed_source_cache: Arc, pub resolver: Arc, maybe_file_watcher_reporter: Option, @@ -142,9 +142,6 @@ impl ProcState { maybe_inspector_server: self.maybe_inspector_server.clone(), root_cert_store: self.root_cert_store.clone(), blob_store: self.blob_store.clone(), - broadcast_channel: Default::default(), - shared_array_buffer_store: Default::default(), - compiled_wasm_module_store: Default::default(), parsed_source_cache: self.parsed_source_cache.clone(), resolver: self.resolver.clone(), maybe_file_watcher_reporter: self.maybe_file_watcher_reporter.clone(), @@ -203,9 +200,6 @@ impl ProcState { _ => {} } let blob_store = BlobStore::default(); - let broadcast_channel = InMemoryBroadcastChannel::default(); - let shared_array_buffer_store = SharedArrayBufferStore::default(); - let compiled_wasm_module_store = CompiledWasmModuleStore::default(); let deps_cache_location = dir.deps_folder_path(); let http_cache = HttpCache::new(&deps_cache_location); let root_cert_store = cli_options.resolve_root_cert_store()?; @@ -358,9 +352,6 @@ impl ProcState { maybe_inspector_server, root_cert_store, blob_store, - broadcast_channel, - shared_array_buffer_store, - compiled_wasm_module_store, parsed_source_cache, resolver, maybe_file_watcher_reporter, @@ -378,6 +369,73 @@ impl ProcState { progress_bar, }))) } + + // todo(dsherret): this is a transitory method as we separate out + // ProcState from more code + pub fn into_cli_main_worker_factory(self) -> CliMainWorkerFactory { + CliMainWorkerFactory::new( + StorageKeyResolver::from_options(&self.options), + self.npm_resolver.clone(), + self.node_resolver.clone(), + self.graph_container.clone(), + self.blob_store.clone(), + CliModuleLoaderFactory::new( + &self.options, + self.emitter.clone(), + self.graph_container.clone(), + self.module_load_preparer.clone(), + self.parsed_source_cache.clone(), + self.resolver.clone(), + NpmModuleLoader::new( + self.cjs_resolutions.clone(), + self.node_code_translator.clone(), + self.node_resolver.clone(), + ), + ), + self.root_cert_store.clone(), + self.node_fs.clone(), + self.maybe_inspector_server.clone(), + CliMainWorkerOptions { + argv: self.options.argv().clone(), + debug: self + .options + .log_level() + .map(|l| l == log::Level::Debug) + .unwrap_or(false), + coverage_dir: self.options.coverage_dir(), + enable_testing_features: self.options.enable_testing_features(), + has_node_modules_dir: self.options.has_node_modules_dir(), + inspect_brk: self.options.inspect_brk().is_some(), + inspect_wait: self.options.inspect_wait().is_some(), + is_inspecting: self.options.is_inspecting(), + is_npm_main: self.options.is_npm_main(), + location: self.options.location_flag().clone(), + maybe_binary_npm_command_name: { + let mut maybe_binary_command_name = None; + if let DenoSubcommand::Run(flags) = self.options.sub_command() { + if let Ok(pkg_ref) = NpmPackageReqReference::from_str(&flags.script) + { + // if the user ran a binary command, we'll need to set process.argv[0] + // to be the name of the binary command instead of deno + let binary_name = pkg_ref + .sub_path + .as_deref() + .unwrap_or(pkg_ref.req.name.as_str()); + maybe_binary_command_name = Some(binary_name.to_string()); + } + } + maybe_binary_command_name + }, + origin_data_folder_path: self.dir.origin_data_folder_path(), + seed: self.options.seed(), + unsafely_ignore_certificate_errors: self + .options + .unsafely_ignore_certificate_errors() + .clone(), + unstable: self.options.unstable(), + }, + ) + } } /// Keeps track of what module specifiers were resolved as CJS. diff --git a/cli/tools/bench.rs b/cli/tools/bench.rs index 5f467bc6e2..88e19dd701 100644 --- a/cli/tools/bench.rs +++ b/cli/tools/bench.rs @@ -15,7 +15,7 @@ use crate::util::file_watcher::ResolutionResult; use crate::util::fs::collect_specifiers; use crate::util::path::is_supported_ext; use crate::version::get_user_agent; -use crate::worker::create_custom_worker; +use crate::worker::CliMainWorkerFactory; use deno_core::error::generic_error; use deno_core::error::AnyError; @@ -48,6 +48,7 @@ use tokio::sync::mpsc::UnboundedSender; struct BenchSpecifierOptions { filter: TestFilter, json: bool, + log_level: Option, } #[derive(Debug, Clone, Eq, PartialEq, Deserialize)] @@ -434,20 +435,20 @@ async fn check_specifiers( /// Run a single specifier as an executable bench module. async fn bench_specifier( - ps: ProcState, + worker_factory: &CliMainWorkerFactory, permissions: Permissions, specifier: ModuleSpecifier, sender: UnboundedSender, filter: TestFilter, ) -> Result<(), AnyError> { - let mut worker = create_custom_worker( - &ps, - specifier.clone(), - PermissionsContainer::new(permissions), - vec![ops::bench::deno_bench::init_ops(sender.clone())], - Default::default(), - ) - .await?; + let mut worker = worker_factory + .create_custom_worker( + specifier.clone(), + PermissionsContainer::new(permissions), + vec![ops::bench::deno_bench::init_ops(sender.clone())], + Default::default(), + ) + .await?; // We execute the main module as a side module so that import.meta.main is not set. worker.execute_side_module_possibly_with_npm().await?; @@ -508,26 +509,29 @@ async fn bench_specifier( /// Test a collection of specifiers with test modes concurrently. async fn bench_specifiers( - ps: &ProcState, + worker_factory: Arc, permissions: &Permissions, specifiers: Vec, options: BenchSpecifierOptions, ) -> Result<(), AnyError> { - let log_level = ps.options.log_level(); - let (sender, mut receiver) = unbounded_channel::(); - + let log_level = options.log_level; let option_for_handles = options.clone(); let join_handles = specifiers.into_iter().map(move |specifier| { - let ps = ps.clone(); + let worker_factory = worker_factory.clone(); let permissions = permissions.clone(); let specifier = specifier; let sender = sender.clone(); let options = option_for_handles.clone(); tokio::task::spawn_blocking(move || { - let future = - bench_specifier(ps, permissions, specifier, sender, options.filter); + let future = bench_specifier( + &worker_factory, + permissions, + specifier, + sender, + options.filter, + ); run_local(future) }) }); @@ -650,13 +654,16 @@ pub async fn run_benchmarks( return Ok(()); } + let log_level = ps.options.log_level(); + let worker_factory = Arc::new(ps.into_cli_main_worker_factory()); bench_specifiers( - &ps, + worker_factory, &permissions, specifiers, BenchSpecifierOptions { filter: TestFilter::from_flag(&bench_options.filter), json: bench_options.json, + log_level, }, ) .await?; @@ -809,13 +816,16 @@ pub async fn run_benchmarks_with_watch( return Ok(()); } + let log_level = ps.options.log_level(); + let worker_factory = Arc::new(ps.into_cli_main_worker_factory()); bench_specifiers( - &ps, + worker_factory, permissions, specifiers, BenchSpecifierOptions { filter: TestFilter::from_flag(&bench_options.filter), json: bench_options.json, + log_level, }, ) .await?; diff --git a/cli/tools/repl/mod.rs b/cli/tools/repl/mod.rs index a6cc716373..bfba627525 100644 --- a/cli/tools/repl/mod.rs +++ b/cli/tools/repl/mod.rs @@ -1,10 +1,11 @@ // Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. +use crate::args::CliOptions; use crate::args::Flags; use crate::args::ReplFlags; use crate::colors; +use crate::file_fetcher::FileFetcher; use crate::proc_state::ProcState; -use crate::worker::create_main_worker; use deno_core::error::AnyError; use deno_runtime::permissions::Permissions; use deno_runtime::permissions::PermissionsContainer; @@ -65,14 +66,14 @@ async fn read_line_and_poll( } async fn read_eval_file( - ps: &ProcState, + cli_options: &CliOptions, + file_fetcher: &FileFetcher, eval_file: &str, ) -> Result { let specifier = - deno_core::resolve_url_or_path(eval_file, ps.options.initial_cwd())?; + deno_core::resolve_url_or_path(eval_file, cli_options.initial_cwd())?; - let file = ps - .file_fetcher + let file = file_fetcher .fetch(&specifier, PermissionsContainer::allow_all()) .await?; @@ -82,17 +83,24 @@ async fn read_eval_file( pub async fn run(flags: Flags, repl_flags: ReplFlags) -> Result { let ps = ProcState::from_flags(flags).await?; let main_module = ps.options.resolve_main_module()?; - let mut worker = create_main_worker( - &ps, - main_module, - PermissionsContainer::new(Permissions::from_options( - &ps.options.permissions_options(), - )?), - ) - .await?; + let permissions = PermissionsContainer::new(Permissions::from_options( + &ps.options.permissions_options(), + )?); + let cli_options = ps.options.clone(); + let npm_resolver = ps.npm_resolver.clone(); + let resolver = ps.resolver.clone(); + let dir = ps.dir.clone(); + let file_fetcher = ps.file_fetcher.clone(); + let worker_factory = ps.into_cli_main_worker_factory(); + + let mut worker = worker_factory + .create_main_worker(main_module, permissions) + .await?; worker.setup_repl().await?; let worker = worker.into_main_worker(); - let mut repl_session = ReplSession::initialize(ps.clone(), worker).await?; + let mut repl_session = + ReplSession::initialize(&cli_options, npm_resolver, resolver, worker) + .await?; let mut rustyline_channel = rustyline_channel(); let helper = EditorHelper { @@ -100,12 +108,12 @@ pub async fn run(flags: Flags, repl_flags: ReplFlags) -> Result { sync_sender: rustyline_channel.0, }; - let history_file_path = ps.dir.repl_history_file_path(); + let history_file_path = dir.repl_history_file_path(); let editor = ReplEditor::new(helper, history_file_path)?; if let Some(eval_files) = repl_flags.eval_files { for eval_file in eval_files { - match read_eval_file(&ps, &eval_file).await { + match read_eval_file(&cli_options, &file_fetcher, &eval_file).await { Ok(eval_source) => { let output = repl_session .evaluate_line_and_get_output(&eval_source) @@ -132,7 +140,7 @@ pub async fn run(flags: Flags, repl_flags: ReplFlags) -> Result { // Doing this manually, instead of using `log::info!` because these messages // are supposed to go to stdout, not stderr. - if !ps.options.is_quiet() { + if !cli_options.is_quiet() { println!("Deno {}", crate::version::deno()); println!("exit using ctrl+d, ctrl+c, or close()"); if repl_flags.is_default_command { diff --git a/cli/tools/repl/session.rs b/cli/tools/repl/session.rs index 7fc251362e..b2645097c4 100644 --- a/cli/tools/repl/session.rs +++ b/cli/tools/repl/session.rs @@ -1,8 +1,12 @@ // Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. +use std::sync::Arc; + +use crate::args::CliOptions; use crate::colors; use crate::lsp::ReplLanguageServer; -use crate::ProcState; +use crate::npm::CliNpmResolver; +use crate::resolver::CliGraphResolver; use deno_ast::swc::ast as swc_ast; use deno_ast::swc::visit::noop_visit_type; @@ -117,7 +121,9 @@ struct TsEvaluateResponse { } pub struct ReplSession { - proc_state: ProcState, + has_node_modules_dir: bool, + npm_resolver: Arc, + resolver: Arc, pub worker: MainWorker, session: LocalInspectorSession, pub context_id: u64, @@ -132,7 +138,9 @@ pub struct ReplSession { impl ReplSession { pub async fn initialize( - proc_state: ProcState, + cli_options: &CliOptions, + npm_resolver: Arc, + resolver: Arc, mut worker: MainWorker, ) -> Result { let language_server = ReplLanguageServer::new_initialized().await?; @@ -171,14 +179,14 @@ impl ReplSession { } assert_ne!(context_id, 0); - let referrer = deno_core::resolve_path( - "./$deno$repl.ts", - proc_state.options.initial_cwd(), - ) - .unwrap(); + let referrer = + deno_core::resolve_path("./$deno$repl.ts", cli_options.initial_cwd()) + .unwrap(); let mut repl_session = ReplSession { - proc_state, + has_node_modules_dir: cli_options.has_node_modules_dir(), + npm_resolver, + resolver, worker, session, context_id, @@ -487,7 +495,6 @@ impl ReplSession { .iter() .flat_map(|i| { self - .proc_state .resolver .resolve(i, &self.referrer) .ok() @@ -506,22 +513,17 @@ impl ReplSession { if !self.has_initialized_node_runtime { deno_node::initialize_runtime( &mut self.worker.js_runtime, - self.proc_state.options.has_node_modules_dir(), + self.has_node_modules_dir, None, )?; self.has_initialized_node_runtime = true; } - self - .proc_state - .npm_resolver - .add_package_reqs(npm_imports) - .await?; + self.npm_resolver.add_package_reqs(npm_imports).await?; // prevent messages in the repl about @types/node not being cached if has_node_specifier { self - .proc_state .npm_resolver .inject_synthetic_types_node_package() .await?; diff --git a/cli/tools/run.rs b/cli/tools/run.rs index 7f4b5c8f74..6515ebde69 100644 --- a/cli/tools/run.rs +++ b/cli/tools/run.rs @@ -13,7 +13,6 @@ use crate::args::Flags; use crate::file_fetcher::File; use crate::proc_state::ProcState; use crate::util; -use crate::worker::create_main_worker; pub async fn run_script(flags: Flags) -> Result { if !flags.has_permission() && flags.has_permission_in_argv() { @@ -48,7 +47,10 @@ To grant permissions, set them before the script argument. For example: let permissions = PermissionsContainer::new(Permissions::from_options( &ps.options.permissions_options(), )?); - let mut worker = create_main_worker(&ps, main_module, permissions).await?; + let worker_factory = ps.into_cli_main_worker_factory(); + let mut worker = worker_factory + .create_main_worker(main_module, permissions) + .await?; let exit_code = worker.run().await?; Ok(exit_code) @@ -58,15 +60,9 @@ pub async fn run_from_stdin(flags: Flags) -> Result { let ps = ProcState::from_flags(flags).await?; let main_module = ps.options.resolve_main_module()?; - let mut worker = create_main_worker( - &ps, - main_module.clone(), - PermissionsContainer::new(Permissions::from_options( - &ps.options.permissions_options(), - )?), - ) - .await?; - + let permissions = PermissionsContainer::new(Permissions::from_options( + &ps.options.permissions_options(), + )?); let mut source = Vec::new(); std::io::stdin().read_to_end(&mut source)?; // Create a dummy source file. @@ -75,13 +71,17 @@ pub async fn run_from_stdin(flags: Flags) -> Result { maybe_types: None, media_type: MediaType::TypeScript, source: String::from_utf8(source)?.into(), - specifier: main_module, + specifier: main_module.clone(), maybe_headers: None, }; // Save our fake file into file fetcher cache // to allow module access by TS compiler ps.file_fetcher.insert_cached(source_file); + let worker_factory = ps.into_cli_main_worker_factory(); + let mut worker = worker_factory + .create_main_worker(main_module, permissions) + .await?; let exit_code = worker.run().await?; Ok(exit_code) } @@ -102,7 +102,10 @@ async fn run_with_watch(flags: Flags) -> Result { let permissions = PermissionsContainer::new(Permissions::from_options( &ps.options.permissions_options(), )?); - let worker = create_main_worker(&ps, main_module, permissions).await?; + let worker_factory = ps.into_cli_main_worker_factory(); + let worker = worker_factory + .create_main_worker(main_module, permissions) + .await?; worker.run_for_watcher().await?; Ok(()) @@ -132,8 +135,6 @@ pub async fn eval_command( let permissions = PermissionsContainer::new(Permissions::from_options( &ps.options.permissions_options(), )?); - let mut worker = - create_main_worker(&ps, main_module.clone(), permissions).await?; // Create a dummy source file. let source_code = if eval_flags.print { format!("console.log({})", eval_flags.code) @@ -147,13 +148,18 @@ pub async fn eval_command( maybe_types: None, media_type: MediaType::Unknown, source: String::from_utf8(source_code)?.into(), - specifier: main_module, + specifier: main_module.clone(), maybe_headers: None, }; // Save our fake file into file fetcher cache // to allow module access by TS compiler. ps.file_fetcher.insert_cached(file); + + let mut worker = ps + .into_cli_main_worker_factory() + .create_main_worker(main_module, permissions) + .await?; let exit_code = worker.run().await?; Ok(exit_code) } diff --git a/cli/tools/test.rs b/cli/tools/test.rs index 62a104733d..3bc0e79aab 100644 --- a/cli/tools/test.rs +++ b/cli/tools/test.rs @@ -17,7 +17,7 @@ use crate::util::fs::collect_specifiers; use crate::util::path::get_extension; use crate::util::path::is_supported_ext; use crate::util::path::mapped_specifier_for_tsc; -use crate::worker::create_custom_worker; +use crate::worker::CliMainWorkerFactory; use deno_ast::swc::common::comments::CommentKind; use deno_ast::MediaType; @@ -336,10 +336,18 @@ pub struct TestSummary { } #[derive(Debug, Clone)] -struct TestSpecifierOptions { +struct TestSpecifiersOptions { concurrent_jobs: NonZeroUsize, fail_fast: Option, - filter: TestFilter, + log_level: Option, + specifier: TestSpecifierOptions, +} + +#[derive(Debug, Clone)] +pub struct TestSpecifierOptions { + pub shuffle: Option, + pub filter: TestFilter, + pub trace_ops: bool, } impl TestSummary { @@ -907,30 +915,30 @@ pub fn format_test_error(js_error: &JsError) -> String { /// Test a single specifier as documentation containing test programs, an executable test module or /// both. pub async fn test_specifier( - ps: &ProcState, + worker_factory: &CliMainWorkerFactory, permissions: Permissions, specifier: ModuleSpecifier, mut sender: TestEventSender, fail_fast_tracker: FailFastTracker, - filter: TestFilter, + options: &TestSpecifierOptions, ) -> Result<(), AnyError> { if fail_fast_tracker.should_stop() { return Ok(()); } let stdout = StdioPipe::File(sender.stdout()); let stderr = StdioPipe::File(sender.stderr()); - let mut worker = create_custom_worker( - ps, - specifier.clone(), - PermissionsContainer::new(permissions), - vec![ops::testing::deno_test::init_ops(sender.clone())], - Stdio { - stdin: StdioPipe::Inherit, - stdout, - stderr, - }, - ) - .await?; + let mut worker = worker_factory + .create_custom_worker( + specifier.clone(), + PermissionsContainer::new(permissions), + vec![ops::testing::deno_test::init_ops(sender.clone())], + Stdio { + stdin: StdioPipe::Inherit, + stdout, + stderr, + }, + ) + .await?; let mut coverage_collector = worker.maybe_setup_coverage_collector().await?; @@ -951,7 +959,7 @@ pub async fn test_specifier( } let mut worker = worker.into_main_worker(); - if ps.options.trace_ops() { + if options.trace_ops { worker.js_runtime.execute_script_static( located_script_name!(), "Deno[Deno.internal].enableOpCallTracing();", @@ -971,9 +979,9 @@ pub async fn test_specifier( let tests = if used_only { only } else { no_only }; let mut tests = tests .into_iter() - .filter(|(d, _)| filter.includes(&d.name)) + .filter(|(d, _)| options.filter.includes(&d.name)) .collect::>(); - if let Some(seed) = ps.options.shuffle_tests() { + if let Some(seed) = options.shuffle { tests.shuffle(&mut SmallRng::seed_from_u64(seed)); } sender.send(TestEvent::Plan(TestPlan { @@ -1288,13 +1296,12 @@ static HAS_TEST_RUN_SIGINT_HANDLER: AtomicBool = AtomicBool::new(false); /// Test a collection of specifiers with test modes concurrently. async fn test_specifiers( - ps: &ProcState, + worker_factory: Arc, permissions: &Permissions, specifiers: Vec, - options: TestSpecifierOptions, + options: TestSpecifiersOptions, ) -> Result<(), AnyError> { - let log_level = ps.options.log_level(); - let specifiers = if let Some(seed) = ps.options.shuffle_tests() { + let specifiers = if let Some(seed) = options.specifier.shuffle { let mut rng = SmallRng::seed_from_u64(seed); let mut specifiers = specifiers; specifiers.sort(); @@ -1316,19 +1323,19 @@ async fn test_specifiers( HAS_TEST_RUN_SIGINT_HANDLER.store(true, Ordering::Relaxed); let join_handles = specifiers.into_iter().map(move |specifier| { - let ps = ps.clone(); + let worker_factory = worker_factory.clone(); let permissions = permissions.clone(); let sender = sender.clone(); - let options = options.clone(); let fail_fast_tracker = FailFastTracker::new(options.fail_fast); + let specifier_options = options.specifier.clone(); tokio::task::spawn_blocking(move || { run_local(test_specifier( - &ps, + &worker_factory, permissions, specifier, sender.clone(), fail_fast_tracker, - options.filter, + &specifier_options, )) }) }); @@ -1339,7 +1346,7 @@ async fn test_specifiers( let mut reporter = Box::new(PrettyTestReporter::new( concurrent_jobs.get() > 1, - log_level != Some(Level::Error), + options.log_level != Some(Level::Error), )); let handler = { @@ -1626,6 +1633,7 @@ pub async fn run_tests( // file would have impact on other files, which is undesirable. let permissions = Permissions::from_options(&ps.options.permissions_options())?; + let log_level = ps.options.log_level(); let specifiers_with_mode = fetch_specifiers_with_test_mode( &ps, @@ -1644,8 +1652,10 @@ pub async fn run_tests( return Ok(()); } + let worker_factory = Arc::new(ps.into_cli_main_worker_factory()); + test_specifiers( - &ps, + worker_factory, &permissions, specifiers_with_mode .into_iter() @@ -1654,10 +1664,15 @@ pub async fn run_tests( _ => Some(s), }) .collect(), - TestSpecifierOptions { + TestSpecifiersOptions { concurrent_jobs: test_options.concurrent_jobs, fail_fast: test_options.fail_fast, - filter: TestFilter::from_flag(&test_options.filter), + log_level, + specifier: TestSpecifierOptions { + filter: TestFilter::from_flag(&test_options.filter), + shuffle: test_options.shuffle, + trace_ops: test_options.trace_ops, + }, }, ) .await?; @@ -1676,6 +1691,7 @@ pub async fn run_tests_with_watch( let permissions = Permissions::from_options(&ps.options.permissions_options())?; let no_check = ps.options.type_check_mode() == TypeCheckMode::None; + let log_level = ps.options.log_level(); let ps = RefCell::new(ps); @@ -1816,8 +1832,10 @@ pub async fn run_tests_with_watch( return Ok(()); } + let worker_factory = Arc::new(ps.into_cli_main_worker_factory()); + test_specifiers( - &ps, + worker_factory, permissions, specifiers_with_mode .into_iter() @@ -1826,10 +1844,15 @@ pub async fn run_tests_with_watch( _ => Some(s), }) .collect(), - TestSpecifierOptions { + TestSpecifiersOptions { concurrent_jobs: test_options.concurrent_jobs, fail_fast: test_options.fail_fast, - filter: TestFilter::from_flag(&test_options.filter), + log_level, + specifier: TestSpecifierOptions { + filter: TestFilter::from_flag(&test_options.filter), + shuffle: test_options.shuffle, + trace_ops: test_options.trace_ops, + }, }, ) .await?; diff --git a/cli/worker.rs b/cli/worker.rs index e565789ede..3dad2fbe14 100644 --- a/cli/worker.rs +++ b/cli/worker.rs @@ -1,6 +1,7 @@ // Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. use std::path::PathBuf; +use std::rc::Rc; use std::sync::Arc; use deno_ast::ModuleSpecifier; @@ -8,12 +9,20 @@ use deno_core::error::AnyError; use deno_core::futures::task::LocalFutureObj; use deno_core::futures::FutureExt; use deno_core::located_script_name; +use deno_core::url::Url; +use deno_core::CompiledWasmModuleStore; use deno_core::Extension; use deno_core::ModuleId; +use deno_core::SharedArrayBufferStore; use deno_runtime::colors; +use deno_runtime::deno_broadcast_channel::InMemoryBroadcastChannel; use deno_runtime::deno_node; use deno_runtime::deno_node::NodeResolution; +use deno_runtime::deno_node::NodeResolver; +use deno_runtime::deno_tls::rustls::RootCertStore; +use deno_runtime::deno_web::BlobStore; use deno_runtime::fmt_errors::format_js_error; +use deno_runtime::inspector_server::InspectorServer; use deno_runtime::ops::worker_host::CreateWebWorkerCb; use deno_runtime::ops::worker_host::WorkerEventCb; use deno_runtime::permissions::PermissionsContainer; @@ -24,21 +33,56 @@ use deno_runtime::worker::WorkerOptions; use deno_runtime::BootstrapOptions; use deno_semver::npm::NpmPackageReqReference; -use crate::args::DenoSubcommand; +use crate::args::StorageKeyResolver; use crate::errors; -use crate::module_loader::CliModuleLoader; +use crate::graph_util::ModuleGraphContainer; +use crate::module_loader::CliModuleLoaderFactory; +use crate::npm::CliNpmResolver; use crate::ops; -use crate::proc_state::ProcState; use crate::tools; use crate::tools::coverage::CoverageCollector; use crate::util::checksum; use crate::version; +pub struct CliMainWorkerOptions { + pub argv: Vec, + pub debug: bool, + pub coverage_dir: Option, + pub enable_testing_features: bool, + pub has_node_modules_dir: bool, + pub inspect_brk: bool, + pub inspect_wait: bool, + pub is_inspecting: bool, + pub is_npm_main: bool, + pub location: Option, + pub maybe_binary_npm_command_name: Option, + pub origin_data_folder_path: PathBuf, + pub seed: Option, + pub unsafely_ignore_certificate_errors: Option>, + pub unstable: bool, +} + +struct SharedWorkerState { + pub options: CliMainWorkerOptions, + pub storage_key_resolver: StorageKeyResolver, + pub npm_resolver: Arc, + pub node_resolver: Arc, + pub graph_container: Arc, + pub blob_store: BlobStore, + pub broadcast_channel: InMemoryBroadcastChannel, + pub shared_array_buffer_store: SharedArrayBufferStore, + pub compiled_wasm_module_store: CompiledWasmModuleStore, + pub module_loader_factory: CliModuleLoaderFactory, + pub root_cert_store: RootCertStore, + pub node_fs: Arc, + pub maybe_inspector_server: Option>, +} + pub struct CliMainWorker { main_module: ModuleSpecifier, is_main_cjs: bool, worker: MainWorker, - ps: ProcState, + shared: Arc, } impl CliMainWorker { @@ -62,7 +106,7 @@ impl CliMainWorker { &mut self.worker.js_runtime, &self.main_module.to_file_path().unwrap().to_string_lossy(), true, - self.ps.options.inspect_brk().is_some(), + self.shared.options.inspect_brk, )?; } else { self.execute_main_module_possibly_with_npm().await?; @@ -183,8 +227,8 @@ impl CliMainWorker { &mut self, id: ModuleId, ) -> Result<(), AnyError> { - if self.ps.npm_resolver.has_packages() - || self.ps.graph_container.graph().has_node_specifier + if self.shared.npm_resolver.has_packages() + || self.shared.graph_container.graph().has_node_specifier { self.initialize_main_module_for_node()?; } @@ -192,24 +236,10 @@ impl CliMainWorker { } fn initialize_main_module_for_node(&mut self) -> Result<(), AnyError> { - let mut maybe_binary_command_name = None; - - if let DenoSubcommand::Run(flags) = self.ps.options.sub_command() { - if let Ok(pkg_ref) = NpmPackageReqReference::from_str(&flags.script) { - // if the user ran a binary command, we'll need to set process.argv[0] - // to be the name of the binary command instead of deno - let binary_name = pkg_ref - .sub_path - .as_deref() - .unwrap_or(pkg_ref.req.name.as_str()); - maybe_binary_command_name = Some(binary_name.to_string()); - } - } - deno_node::initialize_runtime( &mut self.worker.js_runtime, - self.ps.options.has_node_modules_dir(), - maybe_binary_command_name, + self.shared.options.has_node_modules_dir, + self.shared.options.maybe_binary_npm_command_name.as_deref(), )?; Ok(()) @@ -218,7 +248,7 @@ impl CliMainWorker { pub async fn maybe_setup_coverage_collector( &mut self, ) -> Result, AnyError> { - if let Some(ref coverage_dir) = self.ps.options.coverage_dir() { + if let Some(coverage_dir) = &self.shared.options.coverage_dir { let session = self.worker.create_inspector_session().await; let coverage_dir = PathBuf::from(coverage_dir); @@ -235,142 +265,188 @@ impl CliMainWorker { } } -pub async fn create_main_worker( - ps: &ProcState, - main_module: ModuleSpecifier, - permissions: PermissionsContainer, -) -> Result { - create_custom_worker(ps, main_module, permissions, vec![], Default::default()) - .await +pub struct CliMainWorkerFactory { + shared: Arc, } -pub async fn create_custom_worker( - ps: &ProcState, - main_module: ModuleSpecifier, - permissions: PermissionsContainer, - mut custom_extensions: Vec, - stdio: deno_runtime::deno_io::Stdio, -) -> Result { - let (main_module, is_main_cjs) = if let Ok(package_ref) = - NpmPackageReqReference::from_specifier(&main_module) - { - ps.npm_resolver - .add_package_reqs(vec![package_ref.req.clone()]) - .await?; - let node_resolution = - ps.node_resolver.resolve_binary_export(&package_ref)?; - let is_main_cjs = matches!(node_resolution, NodeResolution::CommonJs(_)); - (node_resolution.into_url(), is_main_cjs) - } else if ps.options.is_npm_main() { - let node_resolution = - ps.node_resolver.url_to_node_resolution(main_module)?; - let is_main_cjs = matches!(node_resolution, NodeResolution::CommonJs(_)); - (node_resolution.into_url(), is_main_cjs) - } else { - (main_module, false) - }; +impl CliMainWorkerFactory { + #[allow(clippy::too_many_arguments)] + pub fn new( + storage_key_resolver: StorageKeyResolver, + npm_resolver: Arc, + node_resolver: Arc, + graph_container: Arc, + blob_store: BlobStore, + module_loader_factory: CliModuleLoaderFactory, + root_cert_store: RootCertStore, + node_fs: Arc, + maybe_inspector_server: Option>, + options: CliMainWorkerOptions, + ) -> Self { + Self { + shared: Arc::new(SharedWorkerState { + options, + storage_key_resolver, + npm_resolver, + node_resolver, + graph_container, + blob_store, + broadcast_channel: Default::default(), + shared_array_buffer_store: Default::default(), + compiled_wasm_module_store: Default::default(), + module_loader_factory, + root_cert_store, + node_fs, + maybe_inspector_server, + }), + } + } - let module_loader = CliModuleLoader::new( - ps.clone(), - PermissionsContainer::allow_all(), - permissions.clone(), - ); + pub async fn create_main_worker( + &self, + main_module: ModuleSpecifier, + permissions: PermissionsContainer, + ) -> Result { + self + .create_custom_worker( + main_module, + permissions, + vec![], + Default::default(), + ) + .await + } - let maybe_inspector_server = ps.maybe_inspector_server.clone(); + pub async fn create_custom_worker( + &self, + main_module: ModuleSpecifier, + permissions: PermissionsContainer, + mut custom_extensions: Vec, + stdio: deno_runtime::deno_io::Stdio, + ) -> Result { + let shared = &self.shared; + let (main_module, is_main_cjs) = if let Ok(package_ref) = + NpmPackageReqReference::from_specifier(&main_module) + { + shared + .npm_resolver + .add_package_reqs(vec![package_ref.req.clone()]) + .await?; + let node_resolution = + shared.node_resolver.resolve_binary_export(&package_ref)?; + let is_main_cjs = matches!(node_resolution, NodeResolution::CommonJs(_)); + (node_resolution.into_url(), is_main_cjs) + } else if shared.options.is_npm_main { + let node_resolution = + shared.node_resolver.url_to_node_resolution(main_module)?; + let is_main_cjs = matches!(node_resolution, NodeResolution::CommonJs(_)); + (node_resolution.into_url(), is_main_cjs) + } else { + (main_module, false) + }; - 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 web_worker_pre_execute_module_cb = - create_web_worker_pre_execute_module_callback(ps.clone()); + let module_loader = + Rc::new(shared.module_loader_factory.create_for_main( + PermissionsContainer::allow_all(), + permissions.clone(), + )); + let maybe_inspector_server = shared.maybe_inspector_server.clone(); - let maybe_storage_key = ps.options.resolve_storage_key(&main_module); - let origin_storage_dir = maybe_storage_key.as_ref().map(|key| { - ps.dir - .origin_data_folder_path() - .join(checksum::gen(&[key.as_bytes()])) - }); - let cache_storage_dir = maybe_storage_key.map(|key| { - // TODO(@satyarohith): storage quota management - // Note: we currently use temp_dir() to avoid managing storage size. - std::env::temp_dir() - .join("deno_cache") - .join(checksum::gen(&[key.as_bytes()])) - }); + let create_web_worker_cb = + create_web_worker_callback(shared.clone(), stdio.clone()); + let web_worker_preload_module_cb = + create_web_worker_preload_module_callback(shared); + let web_worker_pre_execute_module_cb = + create_web_worker_pre_execute_module_callback(shared.clone()); - let mut extensions = ops::cli_exts(ps.npm_resolver.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 + let maybe_storage_key = shared + .storage_key_resolver + .resolve_storage_key(&main_module); + let origin_storage_dir = maybe_storage_key.as_ref().map(|key| { + shared .options - .log_level() - .map(|l| l == log::Level::Debug) - .unwrap_or(false), - enable_testing_features: ps.options.enable_testing_features(), - locale: deno_core::v8::icu::get_language_tag(), - location: ps.options.location_flag().clone(), - no_color: !colors::use_color(), - is_tty: colors::is_tty(), - runtime_version: version::deno().to_string(), - ts_version: version::TYPESCRIPT.to_string(), - unstable: ps.options.unstable(), - user_agent: version::get_user_agent().to_string(), - inspect: ps.options.is_inspecting(), - }, - extensions, - startup_snapshot: Some(crate::js::deno_isolate_init()), - unsafely_ignore_certificate_errors: ps - .options - .unsafely_ignore_certificate_errors() - .clone(), - 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, - web_worker_pre_execute_module_cb, - maybe_inspector_server, - should_break_on_first_statement: ps.options.inspect_brk().is_some(), - should_wait_for_inspector_session: ps.options.inspect_wait().is_some(), - module_loader, - node_fs: Some(ps.node_fs.clone()), - npm_resolver: Some(ps.npm_resolver.clone()), - get_error_class_fn: Some(&errors::get_error_class_name), - cache_storage_dir, - 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, - }; + .origin_data_folder_path + .join(checksum::gen(&[key.as_bytes()])) + }); + let cache_storage_dir = maybe_storage_key.map(|key| { + // TODO(@satyarohith): storage quota management + // Note: we currently use temp_dir() to avoid managing storage size. + std::env::temp_dir() + .join("deno_cache") + .join(checksum::gen(&[key.as_bytes()])) + }); - let worker = MainWorker::bootstrap_from_options( - main_module.clone(), - permissions, - options, - ); + let mut extensions = ops::cli_exts(shared.npm_resolver.clone()); + extensions.append(&mut custom_extensions); - Ok(CliMainWorker { - main_module, - is_main_cjs, - worker, - ps: ps.clone(), - }) + let options = WorkerOptions { + bootstrap: BootstrapOptions { + args: shared.options.argv.clone(), + cpu_count: std::thread::available_parallelism() + .map(|p| p.get()) + .unwrap_or(1), + debug_flag: shared.options.debug, + enable_testing_features: shared.options.enable_testing_features, + locale: deno_core::v8::icu::get_language_tag(), + location: shared.options.location.clone(), + no_color: !colors::use_color(), + is_tty: colors::is_tty(), + runtime_version: version::deno().to_string(), + ts_version: version::TYPESCRIPT.to_string(), + unstable: shared.options.unstable, + user_agent: version::get_user_agent().to_string(), + inspect: shared.options.is_inspecting, + }, + extensions, + startup_snapshot: Some(crate::js::deno_isolate_init()), + unsafely_ignore_certificate_errors: shared + .options + .unsafely_ignore_certificate_errors + .clone(), + root_cert_store: Some(shared.root_cert_store.clone()), + seed: shared.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, + web_worker_pre_execute_module_cb, + maybe_inspector_server, + should_break_on_first_statement: shared.options.inspect_brk, + should_wait_for_inspector_session: shared.options.inspect_wait, + module_loader, + node_fs: Some(shared.node_fs.clone()), + npm_resolver: Some(shared.npm_resolver.clone()), + get_error_class_fn: Some(&errors::get_error_class_name), + cache_storage_dir, + origin_storage_dir, + blob_store: shared.blob_store.clone(), + broadcast_channel: shared.broadcast_channel.clone(), + shared_array_buffer_store: Some(shared.shared_array_buffer_store.clone()), + compiled_wasm_module_store: Some( + shared.compiled_wasm_module_store.clone(), + ), + stdio, + }; + + let worker = MainWorker::bootstrap_from_options( + main_module.clone(), + permissions, + options, + ); + + Ok(CliMainWorker { + main_module, + is_main_cjs, + worker, + shared: shared.clone(), + }) + } } // TODO(bartlomieju): this callback could have default value // and not be required fn create_web_worker_preload_module_callback( - _ps: ProcState, + _shared: &Arc, ) -> Arc { Arc::new(move |worker| { let fut = async move { Ok(worker) }; @@ -379,16 +455,16 @@ fn create_web_worker_preload_module_callback( } fn create_web_worker_pre_execute_module_callback( - ps: ProcState, + shared: Arc, ) -> Arc { Arc::new(move |mut worker| { - let ps = ps.clone(); + let shared = shared.clone(); let fut = async move { // this will be up to date after pre-load - if ps.npm_resolver.has_packages() { + if shared.npm_resolver.has_packages() { deno_node::initialize_runtime( &mut worker.js_runtime, - ps.options.has_node_modules_dir(), + shared.options.has_node_modules_dir, None, )?; } @@ -400,27 +476,28 @@ fn create_web_worker_pre_execute_module_callback( } fn create_web_worker_callback( - ps: ProcState, + shared: Arc, stdio: deno_runtime::deno_io::Stdio, ) -> Arc { Arc::new(move |args| { - let maybe_inspector_server = ps.maybe_inspector_server.clone(); + let maybe_inspector_server = shared.maybe_inspector_server.clone(); - let module_loader = CliModuleLoader::new_for_worker( - ps.clone(), - args.parent_permissions.clone(), - args.permissions.clone(), - ); + let module_loader = + Rc::new(shared.module_loader_factory.create_for_worker( + args.parent_permissions.clone(), + args.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()); + create_web_worker_callback(shared.clone(), stdio.clone()); + let preload_module_cb = create_web_worker_preload_module_callback(&shared); let pre_execute_module_cb = - create_web_worker_pre_execute_module_callback(ps.clone()); + create_web_worker_pre_execute_module_callback(shared.clone()); - let extensions = ops::cli_exts(ps.npm_resolver.clone()); + let extensions = ops::cli_exts(shared.npm_resolver.clone()); - let maybe_storage_key = ps.options.resolve_storage_key(&args.main_module); + let maybe_storage_key = shared + .storage_key_resolver + .resolve_storage_key(&args.main_module); let cache_storage_dir = maybe_storage_key.map(|key| { // TODO(@satyarohith): storage quota management // Note: we currently use temp_dir() to avoid managing storage size. @@ -431,49 +508,47 @@ fn create_web_worker_callback( let options = WebWorkerOptions { bootstrap: BootstrapOptions { - args: ps.options.argv().clone(), + args: shared.options.argv.clone(), cpu_count: std::thread::available_parallelism() .map(|p| p.get()) .unwrap_or(1), - debug_flag: ps - .options - .log_level() - .map(|l| l == log::Level::Debug) - .unwrap_or(false), - enable_testing_features: ps.options.enable_testing_features(), + debug_flag: shared.options.debug, + enable_testing_features: shared.options.enable_testing_features, locale: deno_core::v8::icu::get_language_tag(), location: Some(args.main_module.clone()), no_color: !colors::use_color(), is_tty: colors::is_tty(), runtime_version: version::deno().to_string(), ts_version: version::TYPESCRIPT.to_string(), - unstable: ps.options.unstable(), + unstable: shared.options.unstable, user_agent: version::get_user_agent().to_string(), - inspect: ps.options.is_inspecting(), + inspect: shared.options.is_inspecting, }, extensions, startup_snapshot: Some(crate::js::deno_isolate_init()), - unsafely_ignore_certificate_errors: ps + unsafely_ignore_certificate_errors: shared .options - .unsafely_ignore_certificate_errors() + .unsafely_ignore_certificate_errors .clone(), - root_cert_store: Some(ps.root_cert_store.clone()), - seed: ps.options.seed(), + root_cert_store: Some(shared.root_cert_store.clone()), + seed: shared.options.seed, create_web_worker_cb, preload_module_cb, pre_execute_module_cb, format_js_error_fn: Some(Arc::new(format_js_error)), source_map_getter: Some(Box::new(module_loader.clone())), module_loader, - node_fs: Some(ps.node_fs.clone()), - npm_resolver: Some(ps.npm_resolver.clone()), + node_fs: Some(shared.node_fs.clone()), + npm_resolver: Some(shared.npm_resolver.clone()), 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()), + blob_store: shared.blob_store.clone(), + broadcast_channel: shared.broadcast_channel.clone(), + shared_array_buffer_store: Some(shared.shared_array_buffer_store.clone()), + compiled_wasm_module_store: Some( + shared.compiled_wasm_module_store.clone(), + ), stdio: stdio.clone(), cache_storage_dir, }; diff --git a/ext/node/lib.rs b/ext/node/lib.rs index cc4afb2b80..53b4f5c08d 100644 --- a/ext/node/lib.rs +++ b/ext/node/lib.rs @@ -534,10 +534,10 @@ deno_core::extension!(deno_node, pub fn initialize_runtime( js_runtime: &mut JsRuntime, uses_local_node_modules_dir: bool, - maybe_binary_command_name: Option, + maybe_binary_command_name: Option<&str>, ) -> Result<(), AnyError> { let argv0 = if let Some(binary_command_name) = maybe_binary_command_name { - serde_json::to_string(binary_command_name.as_str())? + serde_json::to_string(binary_command_name)? } else { "undefined".to_string() };