diff options
Diffstat (limited to 'cli/tsc.rs')
-rw-r--r-- | cli/tsc.rs | 178 |
1 files changed, 98 insertions, 80 deletions
diff --git a/cli/tsc.rs b/cli/tsc.rs index f76fb18fb..e87cb7c7d 100644 --- a/cli/tsc.rs +++ b/cli/tsc.rs @@ -3,6 +3,8 @@ use crate::config_file::TsConfig; use crate::diagnostics::Diagnostics; use crate::emit; +use crate::graph_util::GraphData; +use crate::graph_util::ModuleEntry; use deno_ast::MediaType; use deno_core::anyhow::anyhow; @@ -10,6 +12,7 @@ use deno_core::anyhow::Context; use deno_core::error::AnyError; use deno_core::located_script_name; use deno_core::op_sync; +use deno_core::parking_lot::RwLock; use deno_core::resolve_url_or_path; use deno_core::serde::de; use deno_core::serde::Deserialize; @@ -22,7 +25,6 @@ use deno_core::ModuleSpecifier; use deno_core::OpFn; use deno_core::RuntimeOptions; use deno_core::Snapshot; -use deno_graph::ModuleGraph; use std::collections::HashMap; use std::path::PathBuf; use std::sync::Arc; @@ -185,7 +187,7 @@ pub struct Request { pub config: TsConfig, /// Indicates to the tsc runtime if debug logging should occur. pub debug: bool, - pub graph: Arc<ModuleGraph>, + pub(crate) graph_data: Arc<RwLock<GraphData>>, pub hash_data: Vec<Vec<u8>>, pub maybe_config_specifier: Option<ModuleSpecifier>, pub maybe_tsbuildinfo: Option<String>, @@ -211,7 +213,7 @@ struct State { data_url_map: HashMap<String, ModuleSpecifier>, hash_data: Vec<Vec<u8>>, emitted_files: Vec<EmittedFile>, - graph: Arc<ModuleGraph>, + graph_data: Arc<RwLock<GraphData>>, maybe_config_specifier: Option<ModuleSpecifier>, maybe_tsbuildinfo: Option<String>, maybe_response: Option<RespondArgs>, @@ -220,7 +222,7 @@ struct State { impl State { pub fn new( - graph: Arc<ModuleGraph>, + graph_data: Arc<RwLock<GraphData>>, hash_data: Vec<Vec<u8>>, maybe_config_specifier: Option<ModuleSpecifier>, maybe_tsbuildinfo: Option<String>, @@ -231,7 +233,7 @@ impl State { data_url_map, hash_data, emitted_files: Default::default(), - graph, + graph_data, maybe_config_specifier, maybe_tsbuildinfo, maybe_response: None, @@ -335,11 +337,15 @@ struct ExistsArgs { } fn op_exists(state: &mut State, args: ExistsArgs) -> Result<bool, AnyError> { + let graph_data = state.graph_data.read(); if let Ok(specifier) = normalize_specifier(&args.specifier) { if specifier.scheme() == "asset" || specifier.scheme() == "data" { Ok(true) } else { - Ok(state.graph.contains(&specifier)) + Ok(matches!( + graph_data.get(&graph_data.follow_redirect(&specifier)), + Some(ModuleEntry::Module { .. }) + )) } } else { Ok(false) @@ -401,9 +407,16 @@ fn op_load(state: &mut State, args: Value) -> Result<Value, AnyError> { } else { specifier }; - let maybe_source = if let Some(module) = state.graph.get(&specifier) { - media_type = *module.media_type(); - module.maybe_source().map(String::from) + let graph_data = state.graph_data.read(); + let maybe_source = if let Some(ModuleEntry::Module { + code, + media_type: mt, + .. + }) = + graph_data.get(&graph_data.follow_redirect(&specifier)) + { + media_type = *mt; + Some(code.as_ref().clone()) } else { media_type = MediaType::Unknown; None @@ -427,27 +440,6 @@ pub struct ResolveArgs { pub specifiers: Vec<String>, } -fn resolve_specifier( - state: &mut State, - specifier: &ModuleSpecifier, -) -> (String, String) { - let media_type = state - .graph - .get(specifier) - .map_or(&MediaType::Unknown, |m| m.media_type()); - let specifier_str = match specifier.scheme() { - "data" | "blob" => { - let specifier_str = hash_url(specifier, media_type); - state - .data_url_map - .insert(specifier_str.clone(), specifier.clone()); - specifier_str - } - _ => specifier.to_string(), - }; - (specifier_str, media_type.as_ts_extension().into()) -} - fn op_resolve(state: &mut State, args: Value) -> Result<Value, AnyError> { let v: ResolveArgs = serde_json::from_value(args) .context("Invalid request from JavaScript for \"op_resolve\".")?; @@ -468,32 +460,62 @@ fn op_resolve(state: &mut State, args: Value) -> Result<Value, AnyError> { MediaType::from(specifier).as_ts_extension().to_string(), )); } else { - // here, we try to resolve the specifier via the referrer, but if we can't - // we will try to resolve the specifier via the configuration file, if - // present, finally defaulting to a "placeholder" specifier. This handles - // situations like the jsxImportSource, which tsc tries to resolve the - // import source from a JSX module, but the module graph only contains the - // import as a dependency of the configuration file. - let resolved_dependency = if let Some(resolved_specifier) = state - .graph - .resolve_dependency(specifier, &referrer, true) - .cloned() - { - resolve_specifier(state, &resolved_specifier) - } else if let Some(resolved_specifier) = state - .maybe_config_specifier - .as_ref() - .map(|cf| state.graph.resolve_dependency(specifier, cf, true).cloned()) - .flatten() - { - resolve_specifier(state, &resolved_specifier) - } else { - ( + let graph_data = state.graph_data.read(); + let referrer = graph_data.follow_redirect(&referrer); + let resolved_dep = match graph_data.get(&referrer) { + Some(ModuleEntry::Module { dependencies, .. }) => { + dependencies.get(specifier).and_then(|d| { + d.maybe_type.as_ref().or_else(|| d.maybe_code.as_ref()) + }) + } + Some(ModuleEntry::Configuration { dependencies }) => { + dependencies.get(specifier) + } + _ => None, + }; + let maybe_result = match resolved_dep { + Some(Ok((specifier, _))) => { + let specifier = graph_data.follow_redirect(specifier); + match graph_data.get(&specifier) { + Some(ModuleEntry::Module { + media_type, + maybe_types, + .. + }) => match maybe_types { + Some(Ok((types, _))) => { + let types = graph_data.follow_redirect(types); + match graph_data.get(&types) { + Some(ModuleEntry::Module { media_type, .. }) => { + Some((types, media_type)) + } + _ => None, + } + } + _ => Some((specifier, media_type)), + }, + _ => None, + } + } + _ => None, + }; + let result = match maybe_result { + Some((specifier, media_type)) => { + let specifier_str = match specifier.scheme() { + "data" | "blob" => { + let specifier_str = hash_url(&specifier, media_type); + state.data_url_map.insert(specifier_str.clone(), specifier); + specifier_str + } + _ => specifier.to_string(), + }; + (specifier_str, media_type.as_ts_extension().into()) + } + None => ( "deno:///missing_dependency.d.ts".to_string(), ".d.ts".to_string(), - ) + ), }; - resolved.push(resolved_dependency); + resolved.push(result); } } @@ -553,7 +575,7 @@ pub(crate) fn exec(request: Request) -> Result<Response, AnyError> { let op_state = runtime.op_state(); let mut op_state = op_state.borrow_mut(); op_state.put(State::new( - request.graph, + request.graph_data, request.hash_data.clone(), request.maybe_config_specifier.clone(), request.maybe_tsbuildinfo.clone(), @@ -656,20 +678,18 @@ mod tests { let hash_data = maybe_hash_data.unwrap_or_else(|| vec![b"".to_vec()]); let fixtures = test_util::testdata_path().join("tsc2"); let mut loader = MockLoader { fixtures }; - let graph = Arc::new( - deno_graph::create_graph( - vec![specifier], - false, - None, - &mut loader, - None, - None, - None, - ) - .await, - ); + let graph = deno_graph::create_graph( + vec![specifier], + false, + None, + &mut loader, + None, + None, + None, + ) + .await; State::new( - graph, + Arc::new(RwLock::new((&graph).into())), hash_data, None, maybe_tsbuildinfo, @@ -684,18 +704,16 @@ mod tests { let hash_data = vec![b"something".to_vec()]; let fixtures = test_util::testdata_path().join("tsc2"); let mut loader = MockLoader { fixtures }; - let graph = Arc::new( - deno_graph::create_graph( - vec![specifier.clone()], - false, - None, - &mut loader, - None, - None, - None, - ) - .await, - ); + let graph = deno_graph::create_graph( + vec![specifier.clone()], + false, + None, + &mut loader, + None, + None, + None, + ) + .await; let config = TsConfig::new(json!({ "allowJs": true, "checkJs": false, @@ -716,7 +734,7 @@ mod tests { let request = Request { config, debug: false, - graph, + graph_data: Arc::new(RwLock::new((&graph).into())), hash_data, maybe_config_specifier: None, maybe_tsbuildinfo: None, |