From 01da1d0adc0d09d60eb765ac583be8108eb31e36 Mon Sep 17 00:00:00 2001 From: Ryan Dahl Date: Fri, 24 Sep 2021 11:10:42 -0400 Subject: refactor: Rename ProgramState to ProcState (#12204) Move Arc into struct --- cli/lsp/sources.rs | 16 +- cli/main.rs | 310 ++++++++++++--------------- cli/module_loader.rs | 50 ++--- cli/ops/errors.rs | 7 +- cli/ops/runtime_compiler.rs | 10 +- cli/proc_state.rs | 512 ++++++++++++++++++++++++++++++++++++++++++++ cli/program_state.rs | 504 ------------------------------------------- cli/source_maps.rs | 16 +- cli/specifier_handler.rs | 10 +- cli/standalone.rs | 8 +- cli/tools/coverage.rs | 31 ++- cli/tools/doc.rs | 18 +- cli/tools/repl.rs | 6 +- cli/tools/test.rs | 100 ++++----- 14 files changed, 774 insertions(+), 824 deletions(-) create mode 100644 cli/proc_state.rs delete mode 100644 cli/program_state.rs (limited to 'cli') diff --git a/cli/lsp/sources.rs b/cli/lsp/sources.rs index d453c6972..bd5835cf2 100644 --- a/cli/lsp/sources.rs +++ b/cli/lsp/sources.rs @@ -14,7 +14,7 @@ use crate::flags::Flags; use crate::http_cache; use crate::http_cache::HttpCache; use crate::module_graph::GraphBuilder; -use crate::program_state::ProgramState; +use crate::proc_state::ProcState; use crate::specifier_handler::FetchHandler; use crate::text_encoding; use import_map::ImportMap; @@ -40,15 +40,13 @@ pub async fn cache( maybe_config_file: &Option, maybe_cache_path: &Option, ) -> Result<(), AnyError> { - let program_state = Arc::new( - ProgramState::build(Flags { - cache_path: maybe_cache_path.clone(), - ..Default::default() - }) - .await?, - ); + let ps = ProcState::build(Flags { + cache_path: maybe_cache_path.clone(), + ..Default::default() + }) + .await?; let handler = Arc::new(Mutex::new(FetchHandler::new( - &program_state, + &ps, Permissions::allow_all(), Permissions::allow_all(), )?)); diff --git a/cli/main.rs b/cli/main.rs index 8c27e34b7..a217d2cf4 100644 --- a/cli/main.rs +++ b/cli/main.rs @@ -24,7 +24,7 @@ mod lsp; mod module_graph; mod module_loader; mod ops; -mod program_state; +mod proc_state; mod source_maps; mod specifier_handler; mod standalone; @@ -56,7 +56,7 @@ use crate::flags::TestFlags; use crate::flags::UpgradeFlags; use crate::fmt_errors::PrettyJsError; use crate::module_loader::CliModuleLoader; -use crate::program_state::ProgramState; +use crate::proc_state::ProcState; use crate::source_maps::apply_source_map; use crate::specifier_handler::FetchHandler; use crate::tools::installer::infer_name_from_url; @@ -91,42 +91,36 @@ use std::pin::Pin; use std::rc::Rc; use std::sync::Arc; -fn create_web_worker_callback( - program_state: Arc, -) -> Arc { +fn create_web_worker_callback(ps: ProcState) -> Arc { Arc::new(move |args| { - let global_state_ = program_state.clone(); + let global_state_ = ps.clone(); let js_error_create_fn = Rc::new(move |core_js_error| { let source_mapped_error = apply_source_map(&core_js_error, global_state_.clone()); PrettyJsError::create(source_mapped_error) }); - let maybe_inspector_server = program_state.maybe_inspector_server.clone(); + let maybe_inspector_server = ps.maybe_inspector_server.clone(); let module_loader = CliModuleLoader::new_for_worker( - program_state.clone(), + ps.clone(), args.parent_permissions.clone(), ); - let create_web_worker_cb = - create_web_worker_callback(program_state.clone()); + let create_web_worker_cb = create_web_worker_callback(ps.clone()); let options = WebWorkerOptions { - args: program_state.flags.argv.clone(), + args: ps.flags.argv.clone(), apply_source_maps: true, - debug_flag: program_state - .flags - .log_level - .map_or(false, |l| l == log::Level::Debug), - unstable: program_state.flags.unstable, - enable_testing_features: program_state.flags.enable_testing_features, - unsafely_ignore_certificate_errors: program_state + debug_flag: ps.flags.log_level.map_or(false, |l| l == log::Level::Debug), + unstable: ps.flags.unstable, + enable_testing_features: ps.flags.enable_testing_features, + unsafely_ignore_certificate_errors: ps .flags .unsafely_ignore_certificate_errors .clone(), - root_cert_store: program_state.root_cert_store.clone(), + root_cert_store: ps.root_cert_store.clone(), user_agent: version::get_user_agent(), - seed: program_state.flags.seed, + seed: ps.flags.seed, module_loader, create_web_worker_cb, js_error_create_fn: Some(js_error_create_fn), @@ -137,11 +131,9 @@ fn create_web_worker_callback( ts_version: version::TYPESCRIPT.to_string(), no_color: !colors::use_color(), get_error_class_fn: Some(&crate::errors::get_error_class_name), - blob_store: program_state.blob_store.clone(), - broadcast_channel: program_state.broadcast_channel.clone(), - shared_array_buffer_store: Some( - program_state.shared_array_buffer_store.clone(), - ), + blob_store: ps.blob_store.clone(), + broadcast_channel: ps.broadcast_channel.clone(), + shared_array_buffer_store: Some(ps.shared_array_buffer_store.clone()), cpu_count: num_cpus::get(), }; @@ -160,7 +152,7 @@ fn create_web_worker_callback( js_runtime .op_state() .borrow_mut() - .put::>(program_state.clone()); + .put::(ps.clone()); // Applies source maps - works in conjuction with `js_error_create_fn` // above ops::errors::init(js_runtime); @@ -176,14 +168,14 @@ fn create_web_worker_callback( } pub fn create_main_worker( - program_state: &Arc, + ps: &ProcState, main_module: ModuleSpecifier, permissions: Permissions, maybe_op_init: Option<&dyn Fn(&mut JsRuntime)>, ) -> MainWorker { - let module_loader = CliModuleLoader::new(program_state.clone()); + let module_loader = CliModuleLoader::new(ps.clone()); - let global_state_ = program_state.clone(); + let global_state_ = ps.clone(); let js_error_create_fn = Rc::new(move |core_js_error| { let source_mapped_error = @@ -191,28 +183,24 @@ pub fn create_main_worker( PrettyJsError::create(source_mapped_error) }); - let maybe_inspector_server = program_state.maybe_inspector_server.clone(); - let should_break_on_first_statement = - program_state.flags.inspect_brk.is_some(); + let maybe_inspector_server = ps.maybe_inspector_server.clone(); + let should_break_on_first_statement = ps.flags.inspect_brk.is_some(); - let create_web_worker_cb = create_web_worker_callback(program_state.clone()); + let create_web_worker_cb = create_web_worker_callback(ps.clone()); let options = WorkerOptions { apply_source_maps: true, - args: program_state.flags.argv.clone(), - debug_flag: program_state - .flags - .log_level - .map_or(false, |l| l == log::Level::Debug), - unstable: program_state.flags.unstable, - enable_testing_features: program_state.flags.enable_testing_features, - unsafely_ignore_certificate_errors: program_state + args: ps.flags.argv.clone(), + debug_flag: ps.flags.log_level.map_or(false, |l| l == log::Level::Debug), + unstable: ps.flags.unstable, + enable_testing_features: ps.flags.enable_testing_features, + unsafely_ignore_certificate_errors: ps .flags .unsafely_ignore_certificate_errors .clone(), - root_cert_store: program_state.root_cert_store.clone(), + root_cert_store: ps.root_cert_store.clone(), user_agent: version::get_user_agent(), - seed: program_state.flags.seed, + seed: ps.flags.seed, js_error_create_fn: Some(js_error_create_fn), create_web_worker_cb, maybe_inspector_server, @@ -222,21 +210,18 @@ pub fn create_main_worker( ts_version: version::TYPESCRIPT.to_string(), no_color: !colors::use_color(), get_error_class_fn: Some(&crate::errors::get_error_class_name), - location: program_state.flags.location.clone(), - origin_storage_dir: program_state.flags.location.clone().map(|loc| { - program_state - .dir + location: ps.flags.location.clone(), + origin_storage_dir: ps.flags.location.clone().map(|loc| { + ps.dir .root .clone() // TODO(@crowlKats): change to origin_data for 2.0 .join("location_data") .join(checksum::gen(&[loc.to_string().as_bytes()])) }), - blob_store: program_state.blob_store.clone(), - broadcast_channel: program_state.broadcast_channel.clone(), - shared_array_buffer_store: Some( - program_state.shared_array_buffer_store.clone(), - ), + blob_store: ps.blob_store.clone(), + broadcast_channel: ps.broadcast_channel.clone(), + shared_array_buffer_store: Some(ps.shared_array_buffer_store.clone()), cpu_count: num_cpus::get(), }; @@ -249,7 +234,7 @@ pub fn create_main_worker( js_runtime .op_state() .borrow_mut() - .put::>(program_state.clone()); + .put::(ps.clone()); // Applies source maps - works in conjuction with `js_error_create_fn` // above ops::errors::init(js_runtime); @@ -291,7 +276,7 @@ where } fn print_cache_info( - state: &Arc, + state: &ProcState, json: bool, location: Option, ) -> Result<(), AnyError> { @@ -387,8 +372,8 @@ async fn compile_command( )?; let module_specifier = resolve_url_or_path(&compile_flags.source_file)?; - let program_state = ProgramState::build(flags.clone()).await?; - let deno_dir = &program_state.dir; + let ps = ProcState::build(flags.clone()).await?; + let deno_dir = &ps.dir; let output = compile_flags.output.or_else(|| { infer_name_from_url(&module_specifier).map(PathBuf::from) @@ -398,7 +383,7 @@ async fn compile_command( let module_graph = create_module_graph_and_maybe_check( module_specifier.clone(), - program_state.clone(), + ps.clone(), debug, ) .await?; @@ -408,8 +393,7 @@ async fn compile_command( colors::green("Bundle"), module_specifier.to_string() ); - let bundle_str = - bundle_module_graph(module_graph, program_state.clone(), flags, debug)?; + let bundle_str = bundle_module_graph(module_graph, ps.clone(), flags, debug)?; info!( "{} {}", @@ -445,11 +429,11 @@ async fn info_command( info_flags: InfoFlags, ) -> Result<(), AnyError> { let location = flags.location.clone(); - let program_state = ProgramState::build(flags).await?; + let ps = ProcState::build(flags).await?; if let Some(specifier) = info_flags.file { let specifier = resolve_url_or_path(&specifier)?; let handler = Arc::new(Mutex::new(specifier_handler::FetchHandler::new( - &program_state, + &ps, // info accesses dynamically imported modules just for their information // so we allow access to all of them. Permissions::allow_all(), @@ -457,13 +441,11 @@ async fn info_command( )?)); let mut builder = module_graph::GraphBuilder::new( handler, - program_state.maybe_import_map.clone(), - program_state.lockfile.clone(), + ps.maybe_import_map.clone(), + ps.lockfile.clone(), ); builder.add(&specifier, false).await?; - builder - .analyze_config_file(&program_state.maybe_config_file) - .await?; + builder.analyze_config_file(&ps.maybe_config_file).await?; let graph = builder.get_graph(); let info = graph.info()?; @@ -475,7 +457,7 @@ async fn info_command( } } else { // If it was just "deno info" print location of caches and exit - print_cache_info(&program_state, info_flags.json, location) + print_cache_info(&ps, info_flags.json, location) } } @@ -487,10 +469,10 @@ async fn install_command( preload_flags.inspect = None; preload_flags.inspect_brk = None; let permissions = Permissions::from_options(&preload_flags.clone().into()); - let program_state = ProgramState::build(preload_flags).await?; + let ps = ProcState::build(preload_flags).await?; let main_module = resolve_url_or_path(&install_flags.module_url)?; let mut worker = - create_main_worker(&program_state, main_module.clone(), permissions, None); + create_main_worker(&ps, main_module.clone(), permissions, None); // First, fetch and compile the module; this step ensures that the module exists. worker.preload_module(&main_module, true).await?; tools::installer::install( @@ -517,13 +499,12 @@ async fn lint_command( return Ok(()); } - let program_state = ProgramState::build(flags.clone()).await?; - let maybe_lint_config = - if let Some(config_file) = &program_state.maybe_config_file { - config_file.to_lint_config()? - } else { - None - }; + let ps = ProcState::build(flags.clone()).await?; + let maybe_lint_config = if let Some(config_file) = &ps.maybe_config_file { + config_file.to_lint_config()? + } else { + None + }; tools::lint::lint_files( maybe_lint_config, @@ -546,20 +527,19 @@ async fn cache_command( } else { module_graph::TypeLib::DenoWindow }; - let program_state = ProgramState::build(flags).await?; + let ps = ProcState::build(flags).await?; for file in cache_flags.files { let specifier = resolve_url_or_path(&file)?; - program_state - .prepare_module_load( - specifier, - lib.clone(), - Permissions::allow_all(), - Permissions::allow_all(), - false, - program_state.maybe_import_map.clone(), - ) - .await?; + ps.prepare_module_load( + specifier, + lib.clone(), + Permissions::allow_all(), + Permissions::allow_all(), + false, + ps.maybe_import_map.clone(), + ) + .await?; } Ok(()) @@ -572,9 +552,9 @@ async fn eval_command( // Force TypeScript compile. let main_module = resolve_url_or_path("./$deno$eval.ts").unwrap(); let permissions = Permissions::from_options(&flags.clone().into()); - let program_state = ProgramState::build(flags).await?; + let ps = ProcState::build(flags).await?; let mut worker = - create_main_worker(&program_state, main_module.clone(), permissions, None); + create_main_worker(&ps, main_module.clone(), permissions, None); // Create a dummy source file. let source_code = if eval_flags.print { format!("console.log({})", eval_flags.code) @@ -602,7 +582,7 @@ async fn eval_command( // Save our fake file into file fetcher cache // to allow module access by TS compiler. - program_state.file_fetcher.insert_cached(file); + ps.file_fetcher.insert_cached(file); debug!("main_module {}", &main_module); worker.execute_main_module(&main_module).await?; worker.execute_script( @@ -619,11 +599,11 @@ async fn eval_command( async fn create_module_graph_and_maybe_check( module_specifier: ModuleSpecifier, - program_state: Arc, + ps: ProcState, debug: bool, ) -> Result { let handler = Arc::new(Mutex::new(FetchHandler::new( - &program_state, + &ps, // when bundling, dynamic imports are only access for their type safety, // therefore we will allow the graph to access any module. Permissions::allow_all(), @@ -631,18 +611,16 @@ async fn create_module_graph_and_maybe_check( )?)); let mut builder = module_graph::GraphBuilder::new( handler, - program_state.maybe_import_map.clone(), - program_state.lockfile.clone(), + ps.maybe_import_map.clone(), + ps.lockfile.clone(), ); builder.add(&module_specifier, false).await?; - builder - .analyze_config_file(&program_state.maybe_config_file) - .await?; + builder.analyze_config_file(&ps.maybe_config_file).await?; let module_graph = builder.get_graph(); - if !program_state.flags.no_check { + if !ps.flags.no_check { // TODO(@kitsonk) support bundling for workers - let lib = if program_state.flags.unstable { + let lib = if ps.flags.unstable { module_graph::TypeLib::UnstableDenoWindow } else { module_graph::TypeLib::DenoWindow @@ -652,8 +630,8 @@ async fn create_module_graph_and_maybe_check( debug, emit: false, lib, - maybe_config_file: program_state.maybe_config_file.clone(), - reload: program_state.flags.reload, + maybe_config_file: ps.maybe_config_file.clone(), + reload: ps.flags.reload, ..Default::default() })?; @@ -671,14 +649,14 @@ async fn create_module_graph_and_maybe_check( fn bundle_module_graph( module_graph: module_graph::Graph, - program_state: Arc, + ps: ProcState, flags: Flags, debug: bool, ) -> Result { let (bundle, stats, maybe_ignored_options) = module_graph.bundle(module_graph::BundleOptions { debug, - maybe_config_file: program_state.maybe_config_file.clone(), + maybe_config_file: ps.maybe_config_file.clone(), })?; match maybe_ignored_options { Some(ignored_options) if flags.no_check => { @@ -704,11 +682,11 @@ async fn bundle_command( let module_specifier = resolve_url_or_path(&source_file1)?; debug!(">>>>> bundle START"); - let program_state = ProgramState::build(flags.clone()).await?; + let ps = ProcState::build(flags.clone()).await?; let module_graph = create_module_graph_and_maybe_check( module_specifier, - program_state.clone(), + ps.clone(), debug, ) .await?; @@ -719,20 +697,18 @@ async fn bundle_command( .filter_map(|specifier| specifier.to_file_path().ok()) .collect(); - if let Some(import_map) = program_state.flags.import_map_path.as_ref() { + if let Some(import_map) = ps.flags.import_map_path.as_ref() { paths_to_watch .push(fs_util::resolve_from_cwd(std::path::Path::new(import_map))?); } - Ok((paths_to_watch, module_graph, program_state)) + Ok((paths_to_watch, module_graph, ps)) } .map(move |result| match result { - Ok((paths_to_watch, module_graph, program_state)) => { - ResolutionResult::Restart { - paths_to_watch, - result: Ok((program_state, module_graph)), - } - } + Ok((paths_to_watch, module_graph, ps)) => ResolutionResult::Restart { + paths_to_watch, + result: Ok((ps, module_graph)), + }, Err(e) => ResolutionResult::Restart { paths_to_watch: vec![PathBuf::from(source_file2)], result: Err(e), @@ -740,17 +716,13 @@ async fn bundle_command( }) }; - let operation = |(program_state, module_graph): ( - Arc, - module_graph::Graph, - )| { + let operation = |(ps, module_graph): (ProcState, module_graph::Graph)| { let flags = flags.clone(); let out_file = bundle_flags.out_file.clone(); async move { info!("{} {}", colors::green("Bundle"), module_graph.info()?.root); - let output = - bundle_module_graph(module_graph, program_state, flags, debug)?; + let output = bundle_module_graph(module_graph, ps, flags, debug)?; debug!(">>>>> bundle END"); @@ -805,13 +777,12 @@ async fn format_command( flags: Flags, fmt_flags: FmtFlags, ) -> Result<(), AnyError> { - let program_state = ProgramState::build(flags.clone()).await?; - let maybe_fmt_config = - if let Some(config_file) = &program_state.maybe_config_file { - config_file.to_fmt_config()? - } else { - None - }; + let ps = ProcState::build(flags.clone()).await?; + let maybe_fmt_config = if let Some(config_file) = &ps.maybe_config_file { + config_file.to_fmt_config()? + } else { + None + }; if fmt_flags.files.len() == 1 && fmt_flags.files[0].to_string_lossy() == "-" { return tools::fmt::format_stdin( @@ -827,24 +798,20 @@ async fn format_command( async fn run_repl(flags: Flags, repl_flags: ReplFlags) -> Result<(), AnyError> { let main_module = resolve_url_or_path("./$deno$repl.ts").unwrap(); let permissions = Permissions::from_options(&flags.clone().into()); - let program_state = ProgramState::build(flags).await?; + let ps = ProcState::build(flags).await?; let mut worker = - create_main_worker(&program_state, main_module.clone(), permissions, None); + create_main_worker(&ps, main_module.clone(), permissions, None); worker.run_event_loop(false).await?; - tools::repl::run(&program_state, worker, repl_flags.eval).await + tools::repl::run(&ps, worker, repl_flags.eval).await } async fn run_from_stdin(flags: Flags) -> Result<(), AnyError> { - let program_state = ProgramState::build(flags.clone()).await?; + let ps = ProcState::build(flags.clone()).await?; let permissions = Permissions::from_options(&flags.clone().into()); let main_module = resolve_url_or_path("./$deno$stdin.ts").unwrap(); - let mut worker = create_main_worker( - &program_state.clone(), - main_module.clone(), - permissions, - None, - ); + let mut worker = + create_main_worker(&ps.clone(), main_module.clone(), permissions, None); let mut source = Vec::new(); std::io::stdin().read_to_end(&mut source)?; @@ -859,7 +826,7 @@ async fn run_from_stdin(flags: Flags) -> Result<(), AnyError> { }; // Save our fake file into file fetcher cache // to allow module access by TS compiler - program_state.file_fetcher.insert_cached(source_file); + ps.file_fetcher.insert_cached(source_file); debug!("main_module {}", main_module); worker.execute_main_module(&main_module).await?; @@ -882,21 +849,19 @@ async fn run_with_watch(flags: Flags, script: String) -> Result<(), AnyError> { let flags = flags.clone(); async move { let main_module = resolve_url_or_path(&script1)?; - let program_state = ProgramState::build(flags).await?; + let ps = ProcState::build(flags).await?; let handler = Arc::new(Mutex::new(FetchHandler::new( - &program_state, + &ps, Permissions::allow_all(), Permissions::allow_all(), )?)); let mut builder = module_graph::GraphBuilder::new( handler, - program_state.maybe_import_map.clone(), - program_state.lockfile.clone(), + ps.maybe_import_map.clone(), + ps.lockfile.clone(), ); builder.add(&main_module, false).await?; - builder - .analyze_config_file(&program_state.maybe_config_file) - .await?; + builder.analyze_config_file(&ps.maybe_config_file).await?; let module_graph = builder.get_graph(); // Find all local files in graph @@ -906,20 +871,18 @@ async fn run_with_watch(flags: Flags, script: String) -> Result<(), AnyError> { .filter_map(|specifier| specifier.to_file_path().ok()) .collect(); - if let Some(import_map) = program_state.flags.import_map_path.as_ref() { + if let Some(import_map) = ps.flags.import_map_path.as_ref() { paths_to_watch .push(fs_util::resolve_from_cwd(std::path::Path::new(import_map))?); } - Ok((paths_to_watch, main_module, program_state)) + Ok((paths_to_watch, main_module, ps)) } .map(move |result| match result { - Ok((paths_to_watch, module_info, program_state)) => { - ResolutionResult::Restart { - paths_to_watch, - result: Ok((program_state, module_info)), - } - } + Ok((paths_to_watch, module_info, ps)) => ResolutionResult::Restart { + paths_to_watch, + result: Ok((ps, module_info)), + }, Err(e) => ResolutionResult::Restart { paths_to_watch: vec![PathBuf::from(script2)], result: Err(e), @@ -986,25 +949,24 @@ async fn run_with_watch(flags: Flags, script: String) -> Result<(), AnyError> { } } - let operation = - |(program_state, main_module): (Arc, ModuleSpecifier)| { - let flags = flags.clone(); - let permissions = Permissions::from_options(&flags.into()); - async move { - // 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( - &program_state, - main_module.clone(), - permissions, - None, - )); - - executor.execute(&main_module).await?; - - Ok(()) - } - }; + let operation = |(ps, main_module): (ProcState, ModuleSpecifier)| { + let flags = flags.clone(); + let permissions = Permissions::from_options(&flags.into()); + async move { + // 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, + None, + )); + + executor.execute(&main_module).await?; + + Ok(()) + } + }; file_watcher::watch_func(resolver, operation, "Process").await } @@ -1023,13 +985,13 @@ async fn run_command( } let main_module = resolve_url_or_path(&run_flags.script)?; - let program_state = ProgramState::build(flags.clone()).await?; + let ps = ProcState::build(flags.clone()).await?; let permissions = Permissions::from_options(&flags.clone().into()); let mut worker = - create_main_worker(&program_state, main_module.clone(), permissions, None); + create_main_worker(&ps, main_module.clone(), permissions, None); let mut maybe_coverage_collector = - if let Some(ref coverage_dir) = program_state.coverage_dir { + if let Some(ref coverage_dir) = ps.coverage_dir { let session = worker.create_inspector_session().await; let coverage_dir = PathBuf::from(coverage_dir); diff --git a/cli/module_loader.rs b/cli/module_loader.rs index 575919495..faf1492bb 100644 --- a/cli/module_loader.rs +++ b/cli/module_loader.rs @@ -1,7 +1,7 @@ // Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. use crate::module_graph::TypeLib; -use crate::program_state::ProgramState; +use crate::proc_state::ProcState; use deno_core::error::AnyError; use deno_core::futures::future::FutureExt; use deno_core::futures::Future; @@ -15,7 +15,6 @@ use std::cell::RefCell; use std::pin::Pin; use std::rc::Rc; use std::str; -use std::sync::Arc; pub struct CliModuleLoader { /// When flags contains a `.import_map_path` option, the content of the @@ -26,32 +25,29 @@ pub struct CliModuleLoader { /// worker. They are decoupled from the worker (dynamic) permissions since /// read access errors must be raised based on the parent thread permissions. pub root_permissions: Permissions, - pub program_state: Arc, + pub ps: ProcState, } impl CliModuleLoader { - pub fn new(program_state: Arc) -> Rc { - let lib = if program_state.flags.unstable { + pub fn new(ps: ProcState) -> Rc { + let lib = if ps.flags.unstable { TypeLib::UnstableDenoWindow } else { TypeLib::DenoWindow }; - let import_map = program_state.maybe_import_map.clone(); + let import_map = ps.maybe_import_map.clone(); Rc::new(CliModuleLoader { import_map, lib, root_permissions: Permissions::allow_all(), - program_state, + ps, }) } - pub fn new_for_worker( - program_state: Arc, - permissions: Permissions, - ) -> Rc { - let lib = if program_state.flags.unstable { + pub fn new_for_worker(ps: ProcState, permissions: Permissions) -> Rc { + let lib = if ps.flags.unstable { TypeLib::UnstableDenoWorker } else { TypeLib::DenoWorker @@ -61,7 +57,7 @@ impl CliModuleLoader { import_map: None, lib, root_permissions: permissions, - program_state, + ps, }) } } @@ -75,7 +71,7 @@ impl ModuleLoader for CliModuleLoader { is_main: bool, ) -> Result { // FIXME(bartlomieju): hacky way to provide compatibility with repl - let referrer = if referrer.is_empty() && self.program_state.flags.repl { + let referrer = if referrer.is_empty() && self.ps.flags.repl { deno_core::DUMMY_SPECIFIER } else { referrer @@ -102,13 +98,12 @@ impl ModuleLoader for CliModuleLoader { _is_dynamic: bool, ) -> Pin> { let module_specifier = module_specifier.clone(); - let program_state = self.program_state.clone(); + let ps = self.ps.clone(); // NOTE: this block is async only because of `deno_core` // interface requirements; module was already loaded // when constructing module graph during call to `prepare_load`. - async move { program_state.load(module_specifier, maybe_referrer) } - .boxed_local() + async move { ps.load(module_specifier, maybe_referrer) }.boxed_local() } fn prepare_load( @@ -120,7 +115,7 @@ impl ModuleLoader for CliModuleLoader { is_dynamic: bool, ) -> Pin>>> { let specifier = specifier.clone(); - let program_state = self.program_state.clone(); + let ps = self.ps.clone(); let maybe_import_map = self.import_map.clone(); let state = op_state.borrow(); @@ -132,16 +127,15 @@ impl ModuleLoader for CliModuleLoader { // TODO(bartlomieju): `prepare_module_load` should take `load_id` param async move { - program_state - .prepare_module_load( - specifier, - lib, - root_permissions, - dynamic_permissions, - is_dynamic, - maybe_import_map, - ) - .await + ps.prepare_module_load( + specifier, + lib, + root_permissions, + dynamic_permissions, + is_dynamic, + maybe_import_map, + ) + .await } .boxed_local() } diff --git a/cli/ops/errors.rs b/cli/ops/errors.rs index a889b1b0d..ea6a5ae5a 100644 --- a/cli/ops/errors.rs +++ b/cli/ops/errors.rs @@ -2,7 +2,7 @@ use crate::diagnostics::Diagnostics; use crate::fmt_errors::format_file_name; -use crate::program_state::ProgramState; +use crate::proc_state::ProcState; use crate::source_maps::get_orig_position; use crate::source_maps::CachedMaps; use deno_core::error::AnyError; @@ -12,7 +12,6 @@ use deno_core::serde_json::Value; use deno_core::OpState; use serde::Deserialize; use std::collections::HashMap; -use std::sync::Arc; pub fn init(rt: &mut deno_core::JsRuntime) { super::reg_sync(rt, "op_apply_source_map", op_apply_source_map); @@ -36,7 +35,7 @@ fn op_apply_source_map( let args: ApplySourceMap = serde_json::from_value(args)?; let mut mappings_map: CachedMaps = HashMap::new(); - let program_state = state.borrow::>().clone(); + let ps = state.borrow::().clone(); let (orig_file_name, orig_line_number, orig_column_number, _) = get_orig_position( @@ -44,7 +43,7 @@ fn op_apply_source_map( args.line_number.into(), args.column_number.into(), &mut mappings_map, - program_state, + ps, ); Ok(json!({ diff --git a/cli/ops/runtime_compiler.rs b/cli/ops/runtime_compiler.rs index 01bfa3ad5..e77f4d1e7 100644 --- a/cli/ops/runtime_compiler.rs +++ b/cli/ops/runtime_compiler.rs @@ -3,7 +3,7 @@ use crate::module_graph::BundleType; use crate::module_graph::EmitOptions; use crate::module_graph::GraphBuilder; -use crate::program_state::ProgramState; +use crate::proc_state::ProcState; use crate::specifier_handler::FetchHandler; use crate::specifier_handler::MemoryHandler; use crate::specifier_handler::SpecifierHandler; @@ -58,7 +58,7 @@ async fn op_emit( deno_runtime::ops::check_unstable2(&state, "Deno.emit"); let args: EmitArgs = serde_json::from_value(args)?; let root_specifier = args.root_specifier; - let program_state = state.borrow().borrow::>().clone(); + let ps = state.borrow().borrow::().clone(); let mut runtime_permissions = { let state = state.borrow(); state.borrow::().clone() @@ -71,7 +71,7 @@ async fn op_emit( Arc::new(Mutex::new(MemoryHandler::new(sources))) } else { Arc::new(Mutex::new(FetchHandler::new( - &program_state, + &ps, runtime_permissions.clone(), runtime_permissions.clone(), )?)) @@ -82,7 +82,7 @@ async fn op_emit( let import_map = if let Some(value) = args.import_map { ImportMap::from_json(import_map_specifier.as_str(), &value.to_string())? } else { - let file = program_state + let file = ps .file_fetcher .fetch(&import_map_specifier, &mut runtime_permissions) .await @@ -117,7 +117,7 @@ async fn op_emit( None => BundleType::None, }; let graph = builder.get_graph(); - let debug = program_state.flags.log_level == Some(log::Level::Debug); + let debug = ps.flags.log_level == Some(log::Level::Debug); let graph_errors = graph.get_errors(); let (files, mut result_info) = graph.emit(EmitOptions { bundle_type, diff --git a/cli/proc_state.rs b/cli/proc_state.rs new file mode 100644 index 000000000..e6bc5f997 --- /dev/null +++ b/cli/proc_state.rs @@ -0,0 +1,512 @@ +// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. + +use crate::colors; +use crate::config_file::ConfigFile; +use crate::deno_dir; +use crate::file_fetcher::CacheSetting; +use crate::file_fetcher::FileFetcher; +use crate::flags; +use crate::http_cache; +use crate::lockfile::Lockfile; +use crate::module_graph::CheckOptions; +use crate::module_graph::GraphBuilder; +use crate::module_graph::TranspileOptions; +use crate::module_graph::TypeLib; +use crate::source_maps::SourceMapGetter; +use crate::specifier_handler::FetchHandler; +use crate::version; + +use deno_core::error::anyhow; +use deno_core::error::get_custom_error_class; +use deno_core::error::AnyError; +use deno_core::error::Context; +use deno_core::parking_lot::Mutex; +use deno_core::resolve_url; +use deno_core::url::Url; +use deno_core::ModuleSource; +use deno_core::ModuleSpecifier; +use deno_core::SharedArrayBufferStore; +use deno_runtime::deno_broadcast_channel::InMemoryBroadcastChannel; +use deno_runtime::deno_web::BlobStore; +use deno_runtime::inspector_server::InspectorServer; +use deno_runtime::permissions::Permissions; +use deno_tls::rustls::RootCertStore; +use deno_tls::rustls_native_certs::load_native_certs; +use deno_tls::webpki_roots::TLS_SERVER_ROOTS; +use import_map::ImportMap; +use log::debug; +use log::warn; +use std::collections::HashMap; +use std::collections::HashSet; +use std::env; +use std::fs::File; +use std::io::BufReader; +use std::ops::Deref; +use std::sync::Arc; + +/// This structure represents state of single "deno" program. +/// +/// It is shared by all created workers (thus V8 isolates). +#[derive(Clone)] +pub struct ProcState(Arc); + +pub struct Inner { + /// Flags parsed from `argv` contents. + pub flags: flags::Flags, + pub dir: deno_dir::DenoDir, + pub coverage_dir: Option, + pub file_fetcher: FileFetcher, + pub modules: + Arc>>>, + pub lockfile: Option>>, + pub maybe_config_file: Option, + pub maybe_import_map: Option, + pub maybe_inspector_server: Option>, + pub root_cert_store: Option, + pub blob_store: BlobStore, + pub broadcast_channel: InMemoryBroadcastChannel, + pub shared_array_buffer_store: SharedArrayBufferStore, +} + +impl Deref for ProcState { + type Target = Arc; + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl ProcState { + pub async fn build(flags: flags::Flags) -> Result { + let maybe_custom_root = flags + .cache_path + .clone() + .or_else(|| env::var("DENO_DIR").map(String::into).ok()); + let dir = deno_dir::DenoDir::new(maybe_custom_root)?; + let deps_cache_location = dir.root.join("deps"); + let http_cache = http_cache::HttpCache::new(&deps_cache_location); + + let mut root_cert_store = RootCertStore::empty(); + let ca_stores: Vec = flags + .ca_stores + .clone() + .or_else(|| { + let env_ca_store = env::var("DENO_TLS_CA_STORE").ok()?; + Some( + env_ca_store + .split(',') + .map(|s| s.trim().to_string()) + .filter(|s| !s.is_empty()) + .collect(), + ) + }) + .unwrap_or_else(|| vec!["mozilla".to_string()]); + + for store in ca_stores.iter() { + match store.as_str() { + "mozilla" => { + root_cert_store.add_server_trust_anchors(&TLS_SERVER_ROOTS); + } + "system" => { + let roots = load_native_certs() + .expect("could not load platform certs") + .roots; + root_cert_store.roots.extend(roots); + } + _ => { + return Err(anyhow!("Unknown certificate store \"{}\" specified (allowed: \"system,mozilla\")", store)); + } + } + } + + let ca_file = flags.ca_file.clone().or_else(|| env::var("DENO_CERT").ok()); + if let Some(ca_file) = ca_file { + let certfile = File::open(&ca_file)?; + let mut reader = BufReader::new(certfile); + + // This function does not return specific errors, if it fails give a generic message. + if let Err(_err) = root_cert_store.add_pem_file(&mut reader) { + return Err(anyhow!("Unable to add pem file to certificate store")); + } + } + + if let Some(insecure_allowlist) = + flags.unsafely_ignore_certificate_errors.as_ref() + { + let domains = if insecure_allowlist.is_empty() { + "for all hostnames".to_string() + } else { + format!("for: {}", insecure_allowlist.join(", ")) + }; + let msg = + format!("DANGER: TLS certificate validation is disabled {}", domains); + eprintln!("{}", colors::yellow(msg)); + } + + let cache_usage = if flags.cached_only { + CacheSetting::Only + } else if !flags.cache_blocklist.is_empty() { + CacheSetting::ReloadSome(flags.cache_blocklist.clone()) + } else if flags.reload { + CacheSetting::ReloadAll + } else { + CacheSetting::Use + }; + + let blob_store = BlobStore::default(); + let broadcast_channel = InMemoryBroadcastChannel::default(); + let shared_array_buffer_store = SharedArrayBufferStore::default(); + + let file_fetcher = FileFetcher::new( + http_cache, + cache_usage, + !flags.no_remote, + Some(root_cert_store.clone()), + blob_store.clone(), + flags.unsafely_ignore_certificate_errors.clone(), + )?; + + let lockfile = if let Some(filename) = &flags.lock { + let lockfile = Lockfile::new(filename.clone(), flags.lock_write)?; + Some(Arc::new(Mutex::new(lockfile))) + } else { + None + }; + + let maybe_config_file = + if let Some(config_path) = flags.config_path.as_ref() { + Some(ConfigFile::read(config_path)?) + } else { + None + }; + + let maybe_import_map: Option = + match flags.import_map_path.as_ref() { + None => None, + Some(import_map_url) => { + let import_map_specifier = + deno_core::resolve_url_or_path(import_map_url).context(format!( + "Bad URL (\"{}\") for import map.", + import_map_url + ))?; + let file = file_fetcher + .fetch(&import_map_specifier, &mut Permissions::allow_all()) + .await + .context(format!( + "Unable to load '{}' import map", + import_map_specifier + ))?; + let import_map = + ImportMap::from_json(import_map_specifier.as_str(), &file.source)?; + Some(import_map) + } + }; + + let maybe_inspect_host = flags.inspect.or(flags.inspect_brk); + let maybe_inspector_server = maybe_inspect_host.map(|host| { + Arc::new(InspectorServer::new(host, version::get_user_agent())) + }); + + let coverage_dir = flags + .coverage_dir + .clone() + .or_else(|| env::var("DENO_UNSTABLE_COVERAGE_DIR").ok()); + + Ok(ProcState(Arc::new(Inner { + dir, + coverage_dir, + flags, + file_fetcher, + modules: Default::default(), + lockfile, + maybe_config_file, + maybe_import_map, + maybe_inspector_server, + root_cert_store: Some(root_cert_store.clone()), + blob_store, + broadcast_channel, + shared_array_buffer_store, + }))) + } + + /// Prepares a set of module specifiers for loading in one shot. + pub async fn prepare_module_graph( + &self, + specifiers: Vec, + lib: TypeLib, + root_permissions: Permissions, + dynamic_permissions: Permissions, + maybe_import_map: Option, + ) -> Result<(), AnyError> { + let handler = Arc::new(Mutex::new(FetchHandler::new( + self, + root_permissions, + dynamic_permissions, + )?)); + + let mut builder = + GraphBuilder::new(handler, maybe_import_map, self.lockfile.clone()); + + for specifier in specifiers { + builder.add(&specifier, false).await?; + } + builder.analyze_config_file(&self.maybe_config_file).await?; + + let mut graph = builder.get_graph(); + let debug = self.flags.log_level == Some(log::Level::Debug); + let maybe_config_file = self.maybe_config_file.clone(); + let reload_exclusions = { + let modules = self.modules.lock(); + modules.keys().cloned().collect::>() + }; + + let result_modules = if self.flags.no_check { + let result_info = graph.transpile(TranspileOptions { + debug, + maybe_config_file, + reload: self.flags.reload, + reload_exclusions, + })?; + debug!("{}", result_info.stats); + if let Some(ignored_options) = result_info.maybe_ignored_options { + warn!("{}", ignored_options); + } + result_info.loadable_modules + } else { + let result_info = graph.check(CheckOptions { + debug, + emit: true, + lib, + maybe_config_file, + reload: self.flags.reload, + reload_exclusions, + })?; + + debug!("{}", result_info.stats); + if let Some(ignored_options) = result_info.maybe_ignored_options { + eprintln!("{}", ignored_options); + } + if !result_info.diagnostics.is_empty() { + return Err(anyhow!(result_info.diagnostics)); + } + result_info.loadable_modules + }; + + let mut loadable_modules = self.modules.lock(); + loadable_modules.extend(result_modules); + + if let Some(ref lockfile) = self.lockfile { + let g = lockfile.lock(); + g.write()?; + } + + Ok(()) + } + + /// This function is called when new module load is initialized by the JsRuntime. Its + /// resposibility is to collect all dependencies and if it is required then also perform TS + /// typecheck and traspilation. + pub async fn prepare_module_load( + &self, + specifier: ModuleSpecifier, + lib: TypeLib, + root_permissions: Permissions, + dynamic_permissions: Permissions, + is_dynamic: bool, + maybe_import_map: Option, + ) -> Result<(), AnyError> { + let specifier = specifier.clone(); + let handler = Arc::new(Mutex::new(FetchHandler::new( + self, + root_permissions, + dynamic_permissions, + )?)); + let mut builder = + GraphBuilder::new(handler, maybe_import_map, self.lockfile.clone()); + builder.add(&specifier, is_dynamic).await?; + builder.analyze_config_file(&self.maybe_config_file).await?; + let mut graph = builder.get_graph(); + let debug = self.flags.log_level == Some(log::Level::Debug); + let maybe_config_file = self.maybe_config_file.clone(); + let reload_exclusions = { + let modules = self.modules.lock(); + modules.keys().cloned().collect::>() + }; + + let result_modules = if self.flags.no_check { + let result_info = graph.transpile(TranspileOptions { + debug, + maybe_config_file, + reload: self.flags.reload, + reload_exclusions, + })?; + debug!("{}", result_info.stats); + if let Some(ignored_options) = result_info.maybe_ignored_options { + warn!("{}", ignored_options); + } + result_info.loadable_modules + } else { + let result_info = graph.check(CheckOptions { + debug, + emit: true, + lib, + maybe_config_file, + reload: self.flags.reload, + reload_exclusions, + })?; + + debug!("{}", result_info.stats); + if let Some(ignored_options) = result_info.maybe_ignored_options { + eprintln!("{}", ignored_options); + } + if !result_info.diagnostics.is_empty() { + return Err(anyhow!(result_info.diagnostics)); + } + result_info.loadable_modules + }; + + let mut loadable_modules = self.modules.lock(); + loadable_modules.extend(result_modules); + + if let Some(ref lockfile) = self.lockfile { + let g = lockfile.lock(); + g.write()?; + } + + Ok(()) + } + + pub fn load( + &self, + specifier: ModuleSpecifier, + maybe_referrer: Option, + ) -> Result { + let modules = self.modules.lock(); + modules + .get(&specifier) + .map(|r| match r { + Ok(module_source) => Ok(module_source.clone()), + Err(err) => { + // TODO(@kitsonk) this feels a bit hacky but it works, without + // introducing another enum to have to try to deal with. + if get_custom_error_class(err) == Some("NotFound") { + let message = if let Some(referrer) = &maybe_referrer { + format!("{}\n From: {}\n If the source module contains only types, use `import type` and `export type` to import it instead.", err, referrer) + } else { + format!("{}\n If the source module contains only types, use `import type` and `export type` to import it instead.", err) + }; + warn!("{}: {}", crate::colors::yellow("warning"), message); + Ok(ModuleSource { + code: "".to_string(), + module_url_found: specifier.to_string(), + module_url_specified: specifier.to_string(), + }) + } else { + // anyhow errors don't support cloning, so we have to manage this + // ourselves + Err(anyhow!(err.to_string())) + } + }, + }) + .unwrap_or_else(|| { + if let Some(referrer) = maybe_referrer { + Err(anyhow!( + "Module \"{}\" is missing from the graph.\n From: {}", + specifier, + referrer + )) + } else { + Err(anyhow!( + "Module \"{}\" is missing from the graph.", + specifier + )) + } + }) + } + + // TODO(@kitsonk) this should be refactored to get it from the module graph + fn get_emit(&self, url: &Url) -> Option<(Vec, Option>)> { + match url.scheme() { + // we should only be looking for emits for schemes that denote external + // modules, which the disk_cache supports + "wasm" | "file" | "http" | "https" | "data" | "blob" => (), + _ => { + return None; + } + } + let emit_path = self + .dir + .gen_cache + .get_cache_filename_with_extension(url, "js")?; + let emit_map_path = self + .dir + .gen_cache + .get_cache_filename_with_extension(url, "js.map")?; + if let Ok(code) = self.dir.gen_cache.get(&emit_path) { + let maybe_map = if let Ok(map) = self.dir.gen_cache.get(&emit_map_path) { + Some(map) + } else { + None + }; + Some((code, maybe_map)) + } else { + None + } + } +} + +// TODO(@kitsonk) this is only temporary, but should be refactored to somewhere +// else, like a refactored file_fetcher. +impl SourceMapGetter for ProcState { + fn get_source_map(&self, file_name: &str) -> Option> { + if let Ok(specifier) = resolve_url(file_name) { + if let Some((code, maybe_map)) = self.get_emit(&specifier) { + let code = String::from_utf8(code).unwrap(); + source_map_from_code(code).or(maybe_map) + } else if let Ok(source) = self.load(specifier, None) { + source_map_from_code(source.code) + } else { + None + } + } else { + None + } + } + + fn get_source_line( + &self, + file_name: &str, + line_number: usize, + ) -> Option { + if let Ok(specifier) = resolve_url(file_name) { + self.file_fetcher.get_source(&specifier).map(|out| { + // Do NOT use .lines(): it skips the terminating empty line. + // (due to internally using .split_terminator() instead of .split()) + let lines: Vec<&str> = out.source.split('\n').collect(); + assert!(lines.len() > line_number); + lines[line_number].to_string() + }) + } else { + None + } + } +} + +fn source_map_from_code(code: String) -> Option> { + let lines: Vec<&str> = code.split('\n').collect(); + if let Some(last_line) = lines.last() { + if last_line + .starts_with("//# sourceMappingURL=data:application/json;base64,") + { + let input = last_line.trim_start_matches( + "//# sourceMappingURL=data:application/json;base64,", + ); + let decoded_map = base64::decode(input) + .expect("Unable to decode source map from emitted file."); + Some(decoded_map) + } else { + None + } + } else { + None + } +} diff --git a/cli/program_state.rs b/cli/program_state.rs deleted file mode 100644 index 6b723ca3d..000000000 --- a/cli/program_state.rs +++ /dev/null @@ -1,504 +0,0 @@ -// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. - -use crate::colors; -use crate::config_file::ConfigFile; -use crate::deno_dir; -use crate::file_fetcher::CacheSetting; -use crate::file_fetcher::FileFetcher; -use crate::flags; -use crate::http_cache; -use crate::lockfile::Lockfile; -use crate::module_graph::CheckOptions; -use crate::module_graph::GraphBuilder; -use crate::module_graph::TranspileOptions; -use crate::module_graph::TypeLib; -use crate::source_maps::SourceMapGetter; -use crate::specifier_handler::FetchHandler; -use crate::version; - -use deno_core::error::anyhow; -use deno_core::error::get_custom_error_class; -use deno_core::error::AnyError; -use deno_core::error::Context; -use deno_core::parking_lot::Mutex; -use deno_core::resolve_url; -use deno_core::url::Url; -use deno_core::ModuleSource; -use deno_core::ModuleSpecifier; -use deno_core::SharedArrayBufferStore; -use deno_runtime::deno_broadcast_channel::InMemoryBroadcastChannel; -use deno_runtime::deno_web::BlobStore; -use deno_runtime::inspector_server::InspectorServer; -use deno_runtime::permissions::Permissions; -use deno_tls::rustls::RootCertStore; -use deno_tls::rustls_native_certs::load_native_certs; -use deno_tls::webpki_roots::TLS_SERVER_ROOTS; -use import_map::ImportMap; -use log::debug; -use log::warn; -use std::collections::HashMap; -use std::collections::HashSet; -use std::env; -use std::fs::File; -use std::io::BufReader; -use std::sync::Arc; - -/// This structure represents state of single "deno" program. -/// -/// It is shared by all created workers (thus V8 isolates). -pub struct ProgramState { - /// Flags parsed from `argv` contents. - pub flags: flags::Flags, - pub dir: deno_dir::DenoDir, - pub coverage_dir: Option, - pub file_fetcher: FileFetcher, - pub modules: - Arc>>>, - pub lockfile: Option>>, - pub maybe_config_file: Option, - pub maybe_import_map: Option, - pub maybe_inspector_server: Option>, - pub root_cert_store: Option, - pub blob_store: BlobStore, - pub broadcast_channel: InMemoryBroadcastChannel, - pub shared_array_buffer_store: SharedArrayBufferStore, -} - -impl ProgramState { - pub async fn build(flags: flags::Flags) -> Result, AnyError> { - let maybe_custom_root = flags - .cache_path - .clone() - .or_else(|| env::var("DENO_DIR").map(String::into).ok()); - let dir = deno_dir::DenoDir::new(maybe_custom_root)?; - let deps_cache_location = dir.root.join("deps"); - let http_cache = http_cache::HttpCache::new(&deps_cache_location); - - let mut root_cert_store = RootCertStore::empty(); - let ca_stores: Vec = flags - .ca_stores - .clone() - .or_else(|| { - let env_ca_store = env::var("DENO_TLS_CA_STORE").ok()?; - Some( - env_ca_store - .split(',') - .map(|s| s.trim().to_string()) - .filter(|s| !s.is_empty()) - .collect(), - ) - }) - .unwrap_or_else(|| vec!["mozilla".to_string()]); - - for store in ca_stores.iter() { - match store.as_str() { - "mozilla" => { - root_cert_store.add_server_trust_anchors(&TLS_SERVER_ROOTS); - } - "system" => { - let roots = load_native_certs() - .expect("could not load platform certs") - .roots; - root_cert_store.roots.extend(roots); - } - _ => { - return Err(anyhow!("Unknown certificate store \"{}\" specified (allowed: \"system,mozilla\")", store)); - } - } - } - - let ca_file = flags.ca_file.clone().or_else(|| env::var("DENO_CERT").ok()); - if let Some(ca_file) = ca_file { - let certfile = File::open(&ca_file)?; - let mut reader = BufReader::new(certfile); - - // This function does not return specific errors, if it fails give a generic message. - if let Err(_err) = root_cert_store.add_pem_file(&mut reader) { - return Err(anyhow!("Unable to add pem file to certificate store")); - } - } - - if let Some(insecure_allowlist) = - flags.unsafely_ignore_certificate_errors.as_ref() - { - let domains = if insecure_allowlist.is_empty() { - "for all hostnames".to_string() - } else { - format!("for: {}", insecure_allowlist.join(", ")) - }; - let msg = - format!("DANGER: TLS certificate validation is disabled {}", domains); - eprintln!("{}", colors::yellow(msg)); - } - - let cache_usage = if flags.cached_only { - CacheSetting::Only - } else if !flags.cache_blocklist.is_empty() { - CacheSetting::ReloadSome(flags.cache_blocklist.clone()) - } else if flags.reload { - CacheSetting::ReloadAll - } else { - CacheSetting::Use - }; - - let blob_store = BlobStore::default(); - let broadcast_channel = InMemoryBroadcastChannel::default(); - let shared_array_buffer_store = SharedArrayBufferStore::default(); - - let file_fetcher = FileFetcher::new( - http_cache, - cache_usage, - !flags.no_remote, - Some(root_cert_store.clone()), - blob_store.clone(), - flags.unsafely_ignore_certificate_errors.clone(), - )?; - - let lockfile = if let Some(filename) = &flags.lock { - let lockfile = Lockfile::new(filename.clone(), flags.lock_write)?; - Some(Arc::new(Mutex::new(lockfile))) - } else { - None - }; - - let maybe_config_file = - if let Some(config_path) = flags.config_path.as_ref() { - Some(ConfigFile::read(config_path)?) - } else { - None - }; - - let maybe_import_map: Option = - match flags.import_map_path.as_ref() { - None => None, - Some(import_map_url) => { - let import_map_specifier = - deno_core::resolve_url_or_path(import_map_url).context(format!( - "Bad URL (\"{}\") for import map.", - import_map_url - ))?; - let file = file_fetcher - .fetch(&import_map_specifier, &mut Permissions::allow_all()) - .await - .context(format!( - "Unable to load '{}' import map", - import_map_specifier - ))?; - let import_map = - ImportMap::from_json(import_map_specifier.as_str(), &file.source)?; - Some(import_map) - } - }; - - let maybe_inspect_host = flags.inspect.or(flags.inspect_brk); - let maybe_inspector_server = maybe_inspect_host.map(|host| { - Arc::new(InspectorServer::new(host, version::get_user_agent())) - }); - - let coverage_dir = flags - .coverage_dir - .clone() - .or_else(|| env::var("DENO_UNSTABLE_COVERAGE_DIR").ok()); - - let program_state = ProgramState { - dir, - coverage_dir, - flags, - file_fetcher, - modules: Default::default(), - lockfile, - maybe_config_file, - maybe_import_map, - maybe_inspector_server, - root_cert_store: Some(root_cert_store.clone()), - blob_store, - broadcast_channel, - shared_array_buffer_store, - }; - Ok(Arc::new(program_state)) - } - - /// Prepares a set of module specifiers for loading in one shot. - /// - pub async fn prepare_module_graph( - self: &Arc, - specifiers: Vec, - lib: TypeLib, - root_permissions: Permissions, - dynamic_permissions: Permissions, - maybe_import_map: Option, - ) -> Result<(), AnyError> { - let handler = Arc::new(Mutex::new(FetchHandler::new( - self, - root_permissions, - dynamic_permissions, - )?)); - - let mut builder = - GraphBuilder::new(handler, maybe_import_map, self.lockfile.clone()); - - for specifier in specifiers { - builder.add(&specifier, false).await?; - } - builder.analyze_config_file(&self.maybe_config_file).await?; - - let mut graph = builder.get_graph(); - let debug = self.flags.log_level == Some(log::Level::Debug); - let maybe_config_file = self.maybe_config_file.clone(); - let reload_exclusions = { - let modules = self.modules.lock(); - modules.keys().cloned().collect::>() - }; - - let result_modules = if self.flags.no_check { - let result_info = graph.transpile(TranspileOptions { - debug, - maybe_config_file, - reload: self.flags.reload, - reload_exclusions, - })?; - debug!("{}", result_info.stats); - if let Some(ignored_options) = result_info.maybe_ignored_options { - warn!("{}", ignored_options); - } - result_info.loadable_modules - } else { - let result_info = graph.check(CheckOptions { - debug, - emit: true, - lib, - maybe_config_file, - reload: self.flags.reload, - reload_exclusions, - })?; - - debug!("{}", result_info.stats); - if let Some(ignored_options) = result_info.maybe_ignored_options { - eprintln!("{}", ignored_options); - } - if !result_info.diagnostics.is_empty() { - return Err(anyhow!(result_info.diagnostics)); - } - result_info.loadable_modules - }; - - let mut loadable_modules = self.modules.lock(); - loadable_modules.extend(result_modules); - - if let Some(ref lockfile) = self.lockfile { - let g = lockfile.lock(); - g.write()?; - } - - Ok(()) - } - - /// This function is called when new module load is - /// initialized by the JsRuntime. Its resposibility is to collect - /// all dependencies and if it is required then also perform TS typecheck - /// and traspilation. - pub async fn prepare_module_load( - self: &Arc, - specifier: ModuleSpecifier, - lib: TypeLib, - root_permissions: Permissions, - dynamic_permissions: Permissions, - is_dynamic: bool, - maybe_import_map: Option, - ) -> Result<(), AnyError> { - let specifier = specifier.clone(); - let handler = Arc::new(Mutex::new(FetchHandler::new( - self, - root_permissions, - dynamic_permissions, - )?)); - let mut builder = - GraphBuilder::new(handler, maybe_import_map, self.lockfile.clone()); - builder.add(&specifier, is_dynamic).await?; - builder.analyze_config_file(&self.maybe_config_file).await?; - let mut graph = builder.get_graph(); - let debug = self.flags.log_level == Some(log::Level::Debug); - let maybe_config_file = self.maybe_config_file.clone(); - let reload_exclusions = { - let modules = self.modules.lock(); - modules.keys().cloned().collect::>() - }; - - let result_modules = if self.flags.no_check { - let result_info = graph.transpile(TranspileOptions { - debug, - maybe_config_file, - reload: self.flags.reload, - reload_exclusions, - })?; - debug!("{}", result_info.stats); - if let Some(ignored_options) = result_info.maybe_ignored_options { - warn!("{}", ignored_options); - } - result_info.loadable_modules - } else { - let result_info = graph.check(CheckOptions { - debug, - emit: true, - lib, - maybe_config_file, - reload: self.flags.reload, - reload_exclusions, - })?; - - debug!("{}", result_info.stats); - if let Some(ignored_options) = result_info.maybe_ignored_options { - eprintln!("{}", ignored_options); - } - if !result_info.diagnostics.is_empty() { - return Err(anyhow!(result_info.diagnostics)); - } - result_info.loadable_modules - }; - - let mut loadable_modules = self.modules.lock(); - loadable_modules.extend(result_modules); - - if let Some(ref lockfile) = self.lockfile { - let g = lockfile.lock(); - g.write()?; - } - - Ok(()) - } - - pub fn load( - &self, - specifier: ModuleSpecifier, - maybe_referrer: Option, - ) -> Result { - let modules = self.modules.lock(); - modules - .get(&specifier) - .map(|r| match r { - Ok(module_source) => Ok(module_source.clone()), - Err(err) => { - // TODO(@kitsonk) this feels a bit hacky but it works, without - // introducing another enum to have to try to deal with. - if get_custom_error_class(err) == Some("NotFound") { - let message = if let Some(referrer) = &maybe_referrer { - format!("{}\n From: {}\n If the source module contains only types, use `import type` and `export type` to import it instead.", err, referrer) - } else { - format!("{}\n If the source module contains only types, use `import type` and `export type` to import it instead.", err) - }; - warn!("{}: {}", crate::colors::yellow("warning"), message); - Ok(ModuleSource { - code: "".to_string(), - module_url_found: specifier.to_string(), - module_url_specified: specifier.to_string(), - }) - } else { - // anyhow errors don't support cloning, so we have to manage this - // ourselves - Err(anyhow!(err.to_string())) - } - }, - }) - .unwrap_or_else(|| { - if let Some(referrer) = maybe_referrer { - Err(anyhow!( - "Module \"{}\" is missing from the graph.\n From: {}", - specifier, - referrer - )) - } else { - Err(anyhow!( - "Module \"{}\" is missing from the graph.", - specifier - )) - } - }) - } - - // TODO(@kitsonk) this should be refactored to get it from the module graph - fn get_emit(&self, url: &Url) -> Option<(Vec, Option>)> { - match url.scheme() { - // we should only be looking for emits for schemes that denote external - // modules, which the disk_cache supports - "wasm" | "file" | "http" | "https" | "data" | "blob" => (), - _ => { - return None; - } - } - let emit_path = self - .dir - .gen_cache - .get_cache_filename_with_extension(url, "js")?; - let emit_map_path = self - .dir - .gen_cache - .get_cache_filename_with_extension(url, "js.map")?; - if let Ok(code) = self.dir.gen_cache.get(&emit_path) { - let maybe_map = if let Ok(map) = self.dir.gen_cache.get(&emit_map_path) { - Some(map) - } else { - None - }; - Some((code, maybe_map)) - } else { - None - } - } -} - -// TODO(@kitsonk) this is only temporary, but should be refactored to somewhere -// else, like a refactored file_fetcher. -impl SourceMapGetter for ProgramState { - fn get_source_map(&self, file_name: &str) -> Option> { - if let Ok(specifier) = resolve_url(file_name) { - if let Some((code, maybe_map)) = self.get_emit(&specifier) { - let code = String::from_utf8(code).unwrap(); - source_map_from_code(code).or(maybe_map) - } else if let Ok(source) = self.load(specifier, None) { - source_map_from_code(source.code) - } else { - None - } - } else { - None - } - } - - fn get_source_line( - &self, - file_name: &str, - line_number: usize, - ) -> Option { - if let Ok(specifier) = resolve_url(file_name) { - self.file_fetcher.get_source(&specifier).map(|out| { - // Do NOT use .lines(): it skips the terminating empty line. - // (due to internally using .split_terminator() instead of .split()) - let lines: Vec<&str> = out.source.split('\n').collect(); - assert!(lines.len() > line_number); - lines[line_number].to_string() - }) - } else { - None - } - } -} - -fn source_map_from_code(code: String) -> Option> { - let lines: Vec<&str> = code.split('\n').collect(); - if let Some(last_line) = lines.last() { - if last_line - .starts_with("//# sourceMappingURL=data:application/json;base64,") - { - let input = last_line.trim_start_matches( - "//# sourceMappingURL=data:application/json;base64,", - ); - let decoded_map = base64::decode(input) - .expect("Unable to decode source map from emitted file."); - Some(decoded_map) - } else { - None - } - } else { - None - } -} diff --git a/cli/source_maps.rs b/cli/source_maps.rs index d62c0f3e0..74c390893 100644 --- a/cli/source_maps.rs +++ b/cli/source_maps.rs @@ -6,9 +6,8 @@ use deno_core::error::JsError; use sourcemap::SourceMap; use std::collections::HashMap; use std::str; -use std::sync::Arc; -pub trait SourceMapGetter: Sync + Send { +pub trait SourceMapGetter: Sync + Send + Clone { /// Returns the raw source map file. fn get_source_map(&self, file_name: &str) -> Option>; fn get_source_line( @@ -27,7 +26,7 @@ pub type CachedMaps = HashMap>; /// source, rather than the transpiled source code. pub fn apply_source_map( js_error: &JsError, - getter: Arc, + getter: G, ) -> JsError { // Note that js_error.frames has already been source mapped in // prepareStackTrace(). @@ -97,7 +96,7 @@ fn get_maybe_orig_position( line_number: Option, column_number: Option, mappings_map: &mut CachedMaps, - getter: Arc, + getter: G, ) -> (Option, Option, Option, Option) { match (file_name, line_number, column_number) { (Some(file_name_v), Some(line_v), Some(column_v)) => { @@ -119,7 +118,7 @@ pub fn get_orig_position( line_number: i64, column_number: i64, mappings_map: &mut CachedMaps, - getter: Arc, + getter: G, ) -> (String, i64, i64, Option) { // Lookup expects 0-based line and column numbers, but ours are 1-based. let line_number = line_number - 1; @@ -173,7 +172,7 @@ pub fn get_orig_position( fn get_mappings<'a, G: SourceMapGetter>( file_name: &str, mappings_map: &'a mut CachedMaps, - getter: Arc, + getter: G, ) -> &'a Option { mappings_map .entry(file_name.to_string()) @@ -184,7 +183,7 @@ fn get_mappings<'a, G: SourceMapGetter>( // the module meta data. fn parse_map_string( file_name: &str, - getter: Arc, + getter: G, ) -> Option { getter .get_source_map(file_name) @@ -195,6 +194,7 @@ fn parse_map_string( mod tests { use super::*; + #[derive(Clone)] struct MockSourceMapGetter {} impl SourceMapGetter for MockSourceMapGetter { @@ -246,7 +246,7 @@ mod tests { frames: vec![], stack: None, }; - let getter = Arc::new(MockSourceMapGetter {}); + let getter = MockSourceMapGetter {}; let actual = apply_source_map(&e, getter); assert_eq!(actual.source_line, Some("console.log('foo');".to_string())); } diff --git a/cli/specifier_handler.rs b/cli/specifier_handler.rs index 112fac900..aec35a738 100644 --- a/cli/specifier_handler.rs +++ b/cli/specifier_handler.rs @@ -3,7 +3,7 @@ use crate::ast::Location; use crate::disk_cache::DiskCache; use crate::file_fetcher::FileFetcher; -use crate::program_state::ProgramState; +use crate::proc_state::ProcState; use deno_ast::MediaType; use deno_core::error::custom_error; @@ -219,18 +219,18 @@ pub struct FetchHandler { root_permissions: Permissions, /// The set of permissions which are used for dynamic imports. dynamic_permissions: Permissions, - /// A clone of the `program_state` file fetcher. + /// A clone of the `ps` file fetcher. file_fetcher: FileFetcher, } impl FetchHandler { pub fn new( - program_state: &Arc, + ps: &ProcState, root_permissions: Permissions, dynamic_permissions: Permissions, ) -> Result { - let disk_cache = program_state.dir.gen_cache.clone(); - let file_fetcher = program_state.file_fetcher.clone(); + let disk_cache = ps.dir.gen_cache.clone(); + let file_fetcher = ps.file_fetcher.clone(); Ok(FetchHandler { disk_cache, diff --git a/cli/standalone.rs b/cli/standalone.rs index 19132723c..b957f2505 100644 --- a/cli/standalone.rs +++ b/cli/standalone.rs @@ -4,7 +4,7 @@ use crate::colors; use crate::file_fetcher::get_source_from_data_url; use crate::flags::Flags; use crate::ops; -use crate::program_state::ProgramState; +use crate::proc_state::ProcState; use crate::version; use deno_core::error::anyhow; use deno_core::error::type_error; @@ -202,7 +202,7 @@ pub async fn run( ) -> Result<(), AnyError> { let flags = metadata_to_flags(&metadata); let main_module = resolve_url(SPECIFIER)?; - let program_state = ProgramState::build(flags).await?; + let ps = ProcState::build(flags).await?; let permissions = Permissions::from_options(&metadata.permissions); let blob_store = BlobStore::default(); let broadcast_channel = InMemoryBroadcastChannel::default(); @@ -218,7 +218,7 @@ pub async fn run( .collect::>(), ); - let mut root_cert_store = program_state + let mut root_cert_store = ps .root_cert_store .clone() .unwrap_or_else(create_default_root_cert_store); @@ -265,7 +265,7 @@ pub async fn run( js_runtime .op_state() .borrow_mut() - .put::>(program_state.clone()); + .put::(ps.clone()); ops::errors::init(js_runtime); ops::runtime_compiler::init(js_runtime); js_runtime.sync_ops_cache(); diff --git a/cli/tools/coverage.rs b/cli/tools/coverage.rs index 92ade77fd..60efe789c 100644 --- a/cli/tools/coverage.rs +++ b/cli/tools/coverage.rs @@ -4,7 +4,7 @@ use crate::colors; use crate::flags::Flags; use crate::fs_util::collect_files; use crate::module_graph::TypeLib; -use crate::program_state::ProgramState; +use crate::proc_state::ProcState; use crate::source_maps::SourceMapGetter; use deno_ast::swc::common::Span; use deno_ast::MediaType; @@ -670,7 +670,7 @@ pub async fn cover_files( exclude: Vec, lcov: bool, ) -> Result<(), AnyError> { - let program_state = ProgramState::build(flags).await?; + let ps = ProcState::build(flags).await?; let script_coverages = collect_coverages(files, ignore)?; let script_coverages = filter_coverages(script_coverages, include, exclude); @@ -686,22 +686,21 @@ pub async fn cover_files( for script_coverage in script_coverages { let module_specifier = deno_core::resolve_url_or_path(&script_coverage.url)?; - program_state - .prepare_module_load( - module_specifier.clone(), - TypeLib::UnstableDenoWindow, - Permissions::allow_all(), - Permissions::allow_all(), - false, - program_state.maybe_import_map.clone(), - ) - .await?; - - let module_source = program_state.load(module_specifier.clone(), None)?; + ps.prepare_module_load( + module_specifier.clone(), + TypeLib::UnstableDenoWindow, + Permissions::allow_all(), + Permissions::allow_all(), + false, + ps.maybe_import_map.clone(), + ) + .await?; + + let module_source = ps.load(module_specifier.clone(), None)?; let script_source = &module_source.code; - let maybe_source_map = program_state.get_source_map(&script_coverage.url); - let maybe_cached_source = program_state + let maybe_source_map = ps.get_source_map(&script_coverage.url); + let maybe_cached_source = ps .file_fetcher .get_source(&module_specifier) .map(|f| f.source); diff --git a/cli/tools/doc.rs b/cli/tools/doc.rs index a02c858f0..1711c5ccd 100644 --- a/cli/tools/doc.rs +++ b/cli/tools/doc.rs @@ -4,7 +4,7 @@ use crate::colors; use crate::file_fetcher::File; use crate::flags::Flags; use crate::get_types; -use crate::program_state::ProgramState; +use crate::proc_state::ProcState; use crate::write_json_to_stdout; use crate::write_to_stdout_ignore_sigpipe; use deno_ast::MediaType; @@ -61,7 +61,7 @@ impl Resolver for DocResolver { } struct DocLoader { - program_state: Arc, + ps: ProcState, } impl Loader for DocLoader { @@ -71,9 +71,9 @@ impl Loader for DocLoader { _is_dynamic: bool, ) -> LoadFuture { let specifier = specifier.clone(); - let program_state = self.program_state.clone(); + let ps = self.ps.clone(); async move { - let result = program_state + let result = ps .file_fetcher .fetch(&specifier, &mut Permissions::allow_all()) .await @@ -97,7 +97,7 @@ pub async fn print_docs( maybe_filter: Option, private: bool, ) -> Result<(), AnyError> { - let program_state = ProgramState::build(flags.clone()).await?; + let ps = ProcState::build(flags.clone()).await?; let source_file = source_file.unwrap_or_else(|| "--builtin".to_string()); let source_parser = deno_graph::DefaultSourceParser::new(); @@ -135,13 +135,11 @@ pub async fn print_docs( }; // Save our fake file into file fetcher cache. - program_state.file_fetcher.insert_cached(root); + ps.file_fetcher.insert_cached(root); - let mut loader = DocLoader { - program_state: program_state.clone(), - }; + let mut loader = DocLoader { ps: ps.clone() }; let resolver = DocResolver { - import_map: program_state.maybe_import_map.clone(), + import_map: ps.maybe_import_map.clone(), }; let graph = create_graph( root_specifier.clone(), diff --git a/cli/tools/repl.rs b/cli/tools/repl.rs index 774cece24..219ee3502 100644 --- a/cli/tools/repl.rs +++ b/cli/tools/repl.rs @@ -3,7 +3,7 @@ use crate::ast::transpile; use crate::ast::ImportsNotUsedAsValues; use crate::colors; -use crate::program_state::ProgramState; +use crate::proc_state::ProcState; use deno_ast::swc::parser::error::SyntaxError; use deno_ast::swc::parser::token::{Token, Word}; use deno_core::error::AnyError; @@ -731,7 +731,7 @@ async fn read_line_and_poll( } pub async fn run( - program_state: &ProgramState, + ps: &ProcState, worker: MainWorker, maybe_eval: Option, ) -> Result<(), AnyError> { @@ -745,7 +745,7 @@ pub async fn run( response_rx: RefCell::new(response_rx), }; - let history_file_path = program_state.dir.root.join("deno_history.txt"); + let history_file_path = ps.dir.root.join("deno_history.txt"); let editor = ReplEditor::new(helper, history_file_path); if let Some(eval) = maybe_eval { diff --git a/cli/tools/test.rs b/cli/tools/test.rs index 976855893..8d005b101 100644 --- a/cli/tools/test.rs +++ b/cli/tools/test.rs @@ -16,7 +16,7 @@ use crate::module_graph::GraphBuilder; use crate::module_graph::Module; use crate::module_graph::TypeLib; use crate::ops; -use crate::program_state::ProgramState; +use crate::proc_state::ProcState; use crate::tokio_util; use crate::tools::coverage::CoverageCollector; use crate::FetchHandler; @@ -247,7 +247,7 @@ fn create_reporter( /// Test a single specifier as documentation containing test programs, an executable test module or /// both. async fn test_specifier( - program_state: Arc, + ps: ProcState, permissions: Permissions, specifier: ModuleSpecifier, mode: TestMode, @@ -264,15 +264,11 @@ async fn test_specifier( .put::>(channel.clone()); }; - let mut worker = create_main_worker( - &program_state, - specifier.clone(), - permissions, - Some(&init_ops), - ); + let mut worker = + create_main_worker(&ps, specifier.clone(), permissions, Some(&init_ops)); let mut maybe_coverage_collector = if let Some(ref coverage_dir) = - program_state.coverage_dir + ps.coverage_dir { let session = worker.create_inspector_session().await; let coverage_dir = PathBuf::from(coverage_dir); @@ -468,13 +464,13 @@ fn extract_files_from_fenced_blocks( } async fn fetch_inline_files( - program_state: Arc, + ps: ProcState, specifiers: Vec, ) -> Result, AnyError> { let mut files = Vec::new(); for specifier in specifiers { let mut fetch_permissions = Permissions::allow_all(); - let file = program_state + let file = ps .file_fetcher .fetch(&specifier, &mut fetch_permissions) .await?; @@ -501,13 +497,13 @@ async fn fetch_inline_files( /// Type check a collection of module and document specifiers. async fn check_specifiers( - program_state: Arc, + ps: ProcState, permissions: Permissions, specifiers: Vec<(ModuleSpecifier, TestMode)>, lib: TypeLib, ) -> Result<(), AnyError> { let inline_files = fetch_inline_files( - program_state.clone(), + ps.clone(), specifiers .iter() .filter_map(|(specifier, mode)| { @@ -528,18 +524,17 @@ async fn check_specifiers( .collect(); for file in inline_files { - program_state.file_fetcher.insert_cached(file); + ps.file_fetcher.insert_cached(file); } - program_state - .prepare_module_graph( - specifiers, - lib.clone(), - Permissions::allow_all(), - permissions.clone(), - program_state.maybe_import_map.clone(), - ) - .await?; + ps.prepare_module_graph( + specifiers, + lib.clone(), + Permissions::allow_all(), + permissions.clone(), + ps.maybe_import_map.clone(), + ) + .await?; } let module_specifiers = specifiers @@ -553,22 +548,21 @@ async fn check_specifiers( }) .collect(); - program_state - .prepare_module_graph( - module_specifiers, - lib, - Permissions::allow_all(), - permissions, - program_state.maybe_import_map.clone(), - ) - .await?; + ps.prepare_module_graph( + module_specifiers, + lib, + Permissions::allow_all(), + permissions, + ps.maybe_import_map.clone(), + ) + .await?; Ok(()) } /// Test a collection of specifiers with test modes concurrently. async fn test_specifiers( - program_state: Arc, + ps: ProcState, permissions: Permissions, specifiers_with_mode: Vec<(ModuleSpecifier, TestMode)>, fail_fast: Option, @@ -576,7 +570,7 @@ async fn test_specifiers( shuffle: Option, concurrent_jobs: NonZeroUsize, ) -> Result<(), AnyError> { - let log_level = program_state.flags.log_level; + let log_level = ps.flags.log_level; let specifiers_with_mode = if let Some(seed) = shuffle { let mut rng = SmallRng::seed_from_u64(seed); let mut specifiers_with_mode = specifiers_with_mode.clone(); @@ -591,7 +585,7 @@ async fn test_specifiers( let join_handles = specifiers_with_mode.iter().map(move |(specifier, mode)| { - let program_state = program_state.clone(); + let ps = ps.clone(); let permissions = permissions.clone(); let specifier = specifier.clone(); let mode = mode.clone(); @@ -601,7 +595,7 @@ async fn test_specifiers( tokio::task::spawn_blocking(move || { let join_handle = std::thread::spawn(move || { let future = test_specifier( - program_state, + ps, permissions, specifier, mode, @@ -755,7 +749,7 @@ fn collect_specifiers_with_test_mode( /// Specifiers that do not have a known media type that can be executed as a module are marked as /// `TestMode::Documentation`. async fn fetch_specifiers_with_test_mode( - program_state: Arc, + ps: ProcState, include: Vec, ignore: Vec, include_inline: bool, @@ -763,7 +757,7 @@ async fn fetch_specifiers_with_test_mode( let mut specifiers_with_mode = collect_specifiers_with_test_mode(include, ignore, include_inline)?; for (specifier, mode) in &mut specifiers_with_mode { - let file = program_state + let file = ps .file_fetcher .fetch(specifier, &mut Permissions::allow_all()) .await?; @@ -789,10 +783,10 @@ pub async fn run_tests( shuffle: Option, concurrent_jobs: NonZeroUsize, ) -> Result<(), AnyError> { - let program_state = ProgramState::build(flags.clone()).await?; + let ps = ProcState::build(flags.clone()).await?; let permissions = Permissions::from_options(&flags.clone().into()); let specifiers_with_mode = fetch_specifiers_with_test_mode( - program_state.clone(), + ps.clone(), include.unwrap_or_else(|| vec![".".to_string()]), ignore.clone(), doc, @@ -810,7 +804,7 @@ pub async fn run_tests( }; check_specifiers( - program_state.clone(), + ps.clone(), permissions.clone(), specifiers_with_mode.clone(), lib, @@ -822,7 +816,7 @@ pub async fn run_tests( } test_specifiers( - program_state, + ps, permissions, specifiers_with_mode, fail_fast, @@ -847,7 +841,7 @@ pub async fn run_tests_with_watch( shuffle: Option, concurrent_jobs: NonZeroUsize, ) -> Result<(), AnyError> { - let program_state = ProgramState::build(flags.clone()).await?; + let ps = ProcState::build(flags.clone()).await?; let permissions = Permissions::from_options(&flags.clone().into()); let lib = if flags.unstable { @@ -857,7 +851,7 @@ pub async fn run_tests_with_watch( }; let handler = Arc::new(Mutex::new(FetchHandler::new( - &program_state, + &ps, Permissions::allow_all(), Permissions::allow_all(), )?)); @@ -870,7 +864,7 @@ pub async fn run_tests_with_watch( let paths_to_watch_clone = paths_to_watch.clone(); let handler = handler.clone(); - let program_state = program_state.clone(); + let ps = ps.clone(); let files_changed = changed.is_some(); let include = include.clone(); let ignore = ignore.clone(); @@ -894,15 +888,13 @@ pub async fn run_tests_with_watch( let mut builder = GraphBuilder::new( handler, - program_state.maybe_import_map.clone(), - program_state.lockfile.clone(), + ps.maybe_import_map.clone(), + ps.lockfile.clone(), ); for specifier in test_modules.iter() { builder.add(specifier, false).await?; } - builder - .analyze_config_file(&program_state.maybe_config_file) - .await?; + builder.analyze_config_file(&ps.maybe_config_file).await?; let graph = builder.get_graph(); for specifier in test_modules { @@ -998,11 +990,11 @@ pub async fn run_tests_with_watch( let ignore = ignore.clone(); let lib = lib.clone(); let permissions = permissions.clone(); - let program_state = program_state.clone(); + let ps = ps.clone(); async move { let specifiers_with_mode = fetch_specifiers_with_test_mode( - program_state.clone(), + ps.clone(), include.clone(), ignore.clone(), doc, @@ -1014,7 +1006,7 @@ pub async fn run_tests_with_watch( .collect::>(); check_specifiers( - program_state.clone(), + ps.clone(), permissions.clone(), specifiers_with_mode.clone(), lib, @@ -1026,7 +1018,7 @@ pub async fn run_tests_with_watch( } test_specifiers( - program_state.clone(), + ps.clone(), permissions.clone(), specifiers_with_mode, fail_fast, -- cgit v1.2.3