diff options
Diffstat (limited to 'cli/program_state.rs')
-rw-r--r-- | cli/program_state.rs | 136 |
1 files changed, 69 insertions, 67 deletions
diff --git a/cli/program_state.rs b/cli/program_state.rs index 223d043ba..008244b5f 100644 --- a/cli/program_state.rs +++ b/cli/program_state.rs @@ -8,7 +8,6 @@ use crate::http_cache; use crate::http_util; use crate::import_map::ImportMap; use crate::lockfile::Lockfile; -use crate::media_type::MediaType; use crate::module_graph::CheckOptions; use crate::module_graph::GraphBuilder; use crate::module_graph::TranspileOptions; @@ -18,11 +17,14 @@ use crate::specifier_handler::FetchHandler; use deno_runtime::inspector::InspectorServer; use deno_runtime::permissions::Permissions; -use deno_core::error::generic_error; +use deno_core::error::anyhow; +use deno_core::error::get_custom_error_class; use deno_core::error::AnyError; use deno_core::url::Url; +use deno_core::ModuleSource; use deno_core::ModuleSpecifier; use std::cell::RefCell; +use std::collections::HashMap; use std::env; use std::rc::Rc; use std::sync::Arc; @@ -36,12 +38,6 @@ pub fn exit_unstable(api_name: &str) { std::process::exit(70); } -// TODO(@kitsonk) probably can refactor this better with the graph. -pub struct CompiledModule { - pub code: String, - pub name: String, -} - /// This structure represents state of single "deno" program. /// /// It is shared by all created workers (thus V8 isolates). @@ -50,6 +46,8 @@ pub struct ProgramState { pub flags: flags::Flags, pub dir: deno_dir::DenoDir, pub file_fetcher: FileFetcher, + pub modules: + Arc<Mutex<HashMap<ModuleSpecifier, Result<ModuleSource, AnyError>>>>, pub lockfile: Option<Arc<Mutex<Lockfile>>>, pub maybe_import_map: Option<ImportMap>, pub maybe_inspector_server: Option<Arc<InspectorServer>>, @@ -111,6 +109,7 @@ impl ProgramState { dir, flags, file_fetcher, + modules: Default::default(), lockfile, maybe_import_map, maybe_inspector_server, @@ -146,17 +145,17 @@ impl ProgramState { let debug = self.flags.log_level == Some(log::Level::Debug); let maybe_config_path = self.flags.config_path.clone(); - if self.flags.no_check { - let (stats, maybe_ignored_options) = - graph.transpile(TranspileOptions { - debug, - maybe_config_path, - reload: self.flags.reload, - })?; - debug!("{}", stats); - if let Some(ignored_options) = maybe_ignored_options { - eprintln!("{}", ignored_options); + let result_modules = if self.flags.no_check { + let result_info = graph.transpile(TranspileOptions { + debug, + maybe_config_path, + reload: self.flags.reload, + })?; + 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, @@ -171,10 +170,14 @@ impl ProgramState { eprintln!("{}", ignored_options); } if !result_info.diagnostics.is_empty() { - return Err(generic_error(result_info.diagnostics.to_string())); + return Err(anyhow!(result_info.diagnostics)); } + result_info.loadable_modules }; + let mut loadable_modules = self.modules.lock().unwrap(); + loadable_modules.extend(result_modules); + if let Some(ref lockfile) = self.lockfile { let g = lockfile.lock().unwrap(); g.write()?; @@ -183,56 +186,55 @@ impl ProgramState { Ok(()) } - pub fn fetch_compiled_module( + pub fn load( &self, - module_specifier: ModuleSpecifier, + specifier: ModuleSpecifier, maybe_referrer: Option<ModuleSpecifier>, - ) -> Result<CompiledModule, AnyError> { - // TODO(@kitsonk) this really needs to be avoided and refactored out, as we - // really should just be getting this from the module graph. - let out = self - .file_fetcher - .get_source(&module_specifier) - .expect("Cached source file doesn't exist"); - - let specifier = out.specifier.clone(); - let compiled_module = if let Some((code, _)) = - self.get_emit(&specifier.as_url()) - { - CompiledModule { - code: String::from_utf8(code).unwrap(), - name: specifier.as_url().to_string(), - } - // We expect a compiled source for any non-JavaScript files, except for - // local files that have an unknown media type and no referrer (root modules - // that do not have an extension.) - } else if out.media_type != MediaType::JavaScript - && !(out.media_type == MediaType::Unknown - && maybe_referrer.is_none() - && specifier.as_url().scheme() == "file") - { - let message = if let Some(referrer) = maybe_referrer { - format!("Compiled module not found \"{}\"\n From: {}\n If the source module contains only types, use `import type` and `export type` to import it instead.", module_specifier, referrer) - } else { - format!("Compiled module not found \"{}\"\n If the source module contains only types, use `import type` and `export type` to import it instead.", module_specifier) - }; - info!("{}: {}", crate::colors::yellow("warning"), message); - CompiledModule { - code: "".to_string(), - name: specifier.as_url().to_string(), - } - } else { - CompiledModule { - code: out.source, - name: specifier.as_url().to_string(), - } - }; - - Ok(compiled_module) + ) -> Result<ModuleSource, AnyError> { + let modules = self.modules.lock().unwrap(); + 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 a straight forward API on file_fetcher or - // whatever future refactors do... + // TODO(@kitsonk) this should be refactored to get it from the module graph fn get_emit(&self, url: &Url) -> Option<(Vec<u8>, Option<Vec<u8>>)> { match url.scheme() { // we should only be looking for emits for schemes that denote external @@ -245,11 +247,11 @@ impl ProgramState { let emit_path = self .dir .gen_cache - .get_cache_filename_with_extension(&url, "js"); + .get_cache_filename_with_extension(&url, "js")?; let emit_map_path = self .dir .gen_cache - .get_cache_filename_with_extension(&url, "js.map"); + .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) |