From e9edc05bed299a3e97cf9a8136e6d790f5fc3f14 Mon Sep 17 00:00:00 2001 From: Kitson Kelly Date: Sun, 8 Nov 2020 07:00:42 +1100 Subject: [PATCH] fix(cli): ensure that transitory dependencies are emitted (#8275) Fixes #8111 --- cli/module_graph.rs | 42 +++++++++++++++++++++----- cli/tests/fix_emittable_skipped.js | 7 +++++ cli/tests/fix_emittable_skipped.ts.out | 2 ++ cli/tests/integration_tests.rs | 5 +++ cli/tests/subdir/emittable.d.ts | 1 + cli/tests/subdir/polyfill.ts | 10 ++++++ 6 files changed, 60 insertions(+), 7 deletions(-) create mode 100644 cli/tests/fix_emittable_skipped.js create mode 100644 cli/tests/fix_emittable_skipped.ts.out create mode 100644 cli/tests/subdir/emittable.d.ts create mode 100644 cli/tests/subdir/polyfill.ts diff --git a/cli/module_graph.rs b/cli/module_graph.rs index 4d0a4419ff..08f6c5f32a 100644 --- a/cli/module_graph.rs +++ b/cli/module_graph.rs @@ -774,7 +774,7 @@ impl Graph { info!("{} {}", colors::green("Check"), specifier); } - let root_names = self.get_root_names(); + let root_names = self.get_root_names(!config.get_check_js()); let maybe_tsbuildinfo = self.maybe_tsbuildinfo.clone(); let hash_data = vec![config.as_bytes(), version::DENO.as_bytes().to_owned()]; @@ -896,7 +896,7 @@ impl Graph { None }; - let root_names = self.get_root_names(); + let root_names = self.get_root_names(!config.get_check_js()); let hash_data = vec![config.as_bytes(), version::DENO.as_bytes().to_owned()]; let graph = Rc::new(RefCell::new(self)); @@ -1152,10 +1152,37 @@ impl Graph { /// Transform `self.roots` into something that works for `tsc`, because `tsc` /// doesn't like root names without extensions that match its expectations, /// nor does it have any concept of redirection, so we have to resolve all - /// that upfront before feeding it to `tsc`. - fn get_root_names(&self) -> Vec<(ModuleSpecifier, MediaType)> { - self - .roots + /// that upfront before feeding it to `tsc`. In addition, if checkJs is not + /// true, we should pass all emittable files in as the roots, so that `tsc` + /// type checks them and potentially emits them. + fn get_root_names( + &self, + include_emittable: bool, + ) -> Vec<(ModuleSpecifier, MediaType)> { + let root_names: Vec = if include_emittable { + // in situations where there is `allowJs` with tsc, but not `checkJs`, + // then tsc will not parse the whole module graph, meaning that any + // JavaScript importing TypeScript will get ignored, meaning that those + // files will not get emitted. To counter act that behavior, we will + // include all modules that are emittable. + let mut specifiers = HashSet::<&ModuleSpecifier>::new(); + for (_, module) in self.modules.iter() { + if module.media_type == MediaType::JSX + || module.media_type == MediaType::TypeScript + || module.media_type == MediaType::TSX + { + specifiers.insert(&module.specifier); + } + } + // We should include all the original roots as well. + for specifier in self.roots.iter() { + specifiers.insert(specifier); + } + specifiers.into_iter().cloned().collect() + } else { + self.roots.clone() + }; + root_names .iter() .map(|ms| { // if the root module has a types specifier, we should be sending that @@ -1417,9 +1444,10 @@ impl Graph { if module.media_type == MediaType::Dts { continue; } - // if we don't have check_js enabled, we won't touch non TypeScript + // if we don't have check_js enabled, we won't touch non TypeScript or JSX // modules if !(emit_options.check_js + || module.media_type == MediaType::JSX || module.media_type == MediaType::TSX || module.media_type == MediaType::TypeScript) { diff --git a/cli/tests/fix_emittable_skipped.js b/cli/tests/fix_emittable_skipped.js new file mode 100644 index 0000000000..f61907b064 --- /dev/null +++ b/cli/tests/fix_emittable_skipped.js @@ -0,0 +1,7 @@ +/// + +import "./subdir/polyfill.ts"; + +export const a = "a"; + +console.log(globalThis.polyfill); diff --git a/cli/tests/fix_emittable_skipped.ts.out b/cli/tests/fix_emittable_skipped.ts.out new file mode 100644 index 0000000000..108c2d67fe --- /dev/null +++ b/cli/tests/fix_emittable_skipped.ts.out @@ -0,0 +1,2 @@ +[WILDCARD] +[Function] diff --git a/cli/tests/integration_tests.rs b/cli/tests/integration_tests.rs index 6aa2c8a9de..16be109007 100644 --- a/cli/tests/integration_tests.rs +++ b/cli/tests/integration_tests.rs @@ -2865,6 +2865,11 @@ itest!(tsx_imports { output: "tsx_imports.ts.out", }); +itest!(fix_emittable_skipped { + args: "run --reload fix_emittable_skipped.js", + output: "fix_emittable_skipped.ts.out", +}); + itest!(fix_exotic_specifiers { args: "run --quiet --reload fix_exotic_specifiers.ts", output: "fix_exotic_specifiers.ts.out", diff --git a/cli/tests/subdir/emittable.d.ts b/cli/tests/subdir/emittable.d.ts new file mode 100644 index 0000000000..425b80f244 --- /dev/null +++ b/cli/tests/subdir/emittable.d.ts @@ -0,0 +1 @@ +export const a: string; diff --git a/cli/tests/subdir/polyfill.ts b/cli/tests/subdir/polyfill.ts new file mode 100644 index 0000000000..e1cd923cbc --- /dev/null +++ b/cli/tests/subdir/polyfill.ts @@ -0,0 +1,10 @@ +declare global { + const polyfill: () => void; +} + +export {}; + +// deno-lint-ignore no-explicit-any +(globalThis as any).polyfill = () => { + console.log("polyfill"); +};