From 9b404bb4689627e3dd6ca3f431d1bfc72242054c Mon Sep 17 00:00:00 2001 From: Nayeem Rahman Date: Tue, 23 Nov 2021 21:20:30 +0000 Subject: [PATCH] fix(cli): don't cache .tsbuildinfo unless emitting (#12830) Fixes #12755 Fixes #12807 Fixes #12832 --- cli/emit.rs | 23 +++++++++++-------- cli/main.rs | 1 + cli/ops/runtime_compiler.rs | 2 ++ cli/proc_state.rs | 1 + cli/tests/integration/run_tests.rs | 36 ++++++++++++++++++++++++++++++ 5 files changed, 54 insertions(+), 9 deletions(-) diff --git a/cli/emit.rs b/cli/emit.rs index 9eac892fff..86cb8f57c5 100644 --- a/cli/emit.rs +++ b/cli/emit.rs @@ -304,6 +304,8 @@ pub(crate) struct CheckOptions { pub maybe_config_specifier: Option, /// The derived tsconfig that should be used when checking. pub ts_config: TsConfig, + /// If true, existing `.tsbuildinfo` files will be ignored. + pub reload: bool, } /// The result of a check or emit of a module graph. Note that the actual @@ -331,8 +333,11 @@ pub(crate) fn check_and_maybe_emit( // while there might be multiple roots, we can't "merge" the build info, so we // try to retrieve the build info for first root, which is the most common use // case. - let maybe_tsbuildinfo = - cache.get(CacheType::TypeScriptBuildInfo, &graph.roots[0]); + let maybe_tsbuildinfo = if options.reload { + None + } else { + cache.get(CacheType::TypeScriptBuildInfo, &graph.roots[0]) + }; // to make tsc build info work, we need to consistently hash modules, so that // tsc can better determine if an emit is still valid or not, so we provide // that data here. @@ -352,18 +357,18 @@ pub(crate) fn check_and_maybe_emit( root_names, })?; - if let Some(info) = &response.maybe_tsbuildinfo { - // while we retrieve the build info for just the first module, it can be - // used for all the roots in the graph, so we will cache it for all roots - for root in &graph.roots { - cache.set(CacheType::TypeScriptBuildInfo, root, info.clone())?; - } - } // sometimes we want to emit when there are diagnostics, and sometimes we // don't. tsc will always return an emit if there are diagnostics if (response.diagnostics.is_empty() || options.emit_with_diagnostics) && !response.emitted_files.is_empty() { + if let Some(info) = &response.maybe_tsbuildinfo { + // while we retrieve the build info for just the first module, it can be + // used for all the roots in the graph, so we will cache it for all roots + for root in &graph.roots { + cache.set(CacheType::TypeScriptBuildInfo, root, info.clone())?; + } + } for emit in response.emitted_files.into_iter() { if let Some(specifiers) = emit.maybe_specifiers { assert!(specifiers.len() == 1); diff --git a/cli/main.rs b/cli/main.rs index 5afb34f02a..6e8b50599e 100644 --- a/cli/main.rs +++ b/cli/main.rs @@ -724,6 +724,7 @@ async fn create_graph_and_maybe_check( emit_with_diagnostics: false, maybe_config_specifier, ts_config, + reload: ps.flags.reload, }, )?; debug!("{}", check_result.stats); diff --git a/cli/ops/runtime_compiler.rs b/cli/ops/runtime_compiler.rs index 145da4c1d6..0c3b48cd9d 100644 --- a/cli/ops/runtime_compiler.rs +++ b/cli/ops/runtime_compiler.rs @@ -252,6 +252,7 @@ async fn op_emit( emit_with_diagnostics: true, maybe_config_specifier: None, ts_config, + reload: true, }, )?; (emit_result.diagnostics, emit_result.stats) @@ -271,6 +272,7 @@ async fn op_emit( emit_with_diagnostics: true, maybe_config_specifier: None, ts_config: ts_config.clone(), + reload: true, }, )?; (emit_result.diagnostics, emit_result.stats) diff --git a/cli/proc_state.rs b/cli/proc_state.rs index 8a3864d398..b2f7c2aa23 100644 --- a/cli/proc_state.rs +++ b/cli/proc_state.rs @@ -481,6 +481,7 @@ impl ProcState { emit_with_diagnostics: false, maybe_config_specifier, ts_config, + reload: self.flags.reload, }; for root in &graph.roots { let root_str = root.to_string(); diff --git a/cli/tests/integration/run_tests.rs b/cli/tests/integration/run_tests.rs index 2d96fab8f5..d6a5a4c252 100644 --- a/cli/tests/integration/run_tests.rs +++ b/cli/tests/integration/run_tests.rs @@ -2305,3 +2305,39 @@ fn issue12740() { .unwrap(); assert!(!status.success()); } + +/// Regression test for https://github.com/denoland/deno/issues/12807. +#[test] +fn issue12807() { + let mod_dir = TempDir::new().expect("tempdir fail"); + let mod1_path = mod_dir.path().join("mod1.ts"); + let mod2_path = mod_dir.path().join("mod2.ts"); + let mut deno_cmd = util::deno_cmd(); + // With a fresh `DENO_DIR`, run a module with a dependency and a type error. + std::fs::write(&mod1_path, "import './mod2.ts'; Deno.exit('0');").unwrap(); + std::fs::write(&mod2_path, "console.log('Hello, world!');").unwrap(); + let status = deno_cmd + .current_dir(util::testdata_path()) + .arg("run") + .arg(&mod1_path) + .stderr(std::process::Stdio::null()) + .stdout(std::process::Stdio::null()) + .spawn() + .unwrap() + .wait() + .unwrap(); + assert!(!status.success()); + // Fix the type error and run again. + std::fs::write(&mod1_path, "import './mod2.ts'; Deno.exit(0);").unwrap(); + let status = deno_cmd + .current_dir(util::testdata_path()) + .arg("run") + .arg(&mod1_path) + .stderr(std::process::Stdio::null()) + .stdout(std::process::Stdio::null()) + .spawn() + .unwrap() + .wait() + .unwrap(); + assert!(status.success()); +}