fix(cli): don't cache .tsbuildinfo unless emitting (#12830)

Fixes #12755
Fixes #12807
Fixes #12832
This commit is contained in:
Nayeem Rahman 2021-11-23 21:20:30 +00:00 committed by GitHub
parent d2c53e7f10
commit 7413c96985
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 54 additions and 9 deletions

View file

@ -304,6 +304,8 @@ pub(crate) struct CheckOptions {
pub maybe_config_specifier: Option<ModuleSpecifier>,
/// 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);

View file

@ -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);

View file

@ -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)

View file

@ -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();

View file

@ -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());
}