Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(unstable): ability to resolve specifiers with no extension, specifiers for a directory, and TS files from JS extensions #21464

Merged
merged 18 commits into from
Dec 7, 2023
Merged
Prev Previous commit
Next Next commit
Add basic test
  • Loading branch information
dsherret committed Dec 4, 2023
commit 36506ba81650b18a029b4d393c52526e77439ca0
4 changes: 3 additions & 1 deletion cli/args/flags.rs
Original file line number Diff line number Diff line change
Expand Up @@ -976,7 +976,9 @@ fn clap_root() -> Command {
.arg(
Arg::new("unstable-loose-imports")
.long("unstable-loose-imports")
.help("Enable unstable resolving of .js file specifiers to .ts files")
.help(
"Enable unstable resolving of file specifiers by extension probing and .js to .ts.",
)
.env("DENO_UNSTABLE_LOOSE_IMPORTS")
.value_parser(FalseyValueParser::new())
.action(ArgAction::SetTrue)
Expand Down
1 change: 1 addition & 0 deletions cli/cache/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ pub struct FetchCacher {
}

impl FetchCacher {
#[allow(clippy::too_many_arguments)]
pub fn new(
emit_cache: EmitCache,
file_fetcher: Arc<FileFetcher>,
Expand Down
67 changes: 65 additions & 2 deletions cli/resolver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -488,9 +488,9 @@ impl UnstableLooseImportsResolver {
return Cow::Borrowed(specifier);
}

let media_type = MediaType::from_specifier(&specifier);
let media_type = MediaType::from_specifier(specifier);
let probe_media_type_types = match media_type {
MediaType::JavaScript => vec![MediaType::TypeScript],
MediaType::JavaScript => vec![MediaType::TypeScript, MediaType::Tsx],
MediaType::Jsx => vec![MediaType::Tsx],
MediaType::Mjs => vec![MediaType::Mts],
MediaType::Cjs => vec![MediaType::Cts],
Expand Down Expand Up @@ -555,6 +555,9 @@ impl UnstableLooseImportsResolver {
mod test {
use std::collections::BTreeMap;

use deno_runtime::deno_fs::RealFs;
use test_util::TestContext;

use super::*;

#[test]
Expand Down Expand Up @@ -616,4 +619,64 @@ mod test {
// non-existent bare specifier
assert_eq!(resolve("non-existent", &deps).unwrap(), None);
}

#[test]
fn test_unstable_loose_imports() {
// It would be more ideal to use an in memory file system, but
// we haven't written one.
let context = TestContext::default();
let temp_dir = context.temp_dir().path();
let fs = Arc::new(RealFs);
let resolver = UnstableLooseImportsResolver::new(fs);

// scenarios like resolving ./example.js to ./example.ts
for (ext_from, ext_to) in [("js", "ts"), ("js", "tsx"), ("mjs", "mts")] {
let ts_file = temp_dir.join(format!("file.{}", ext_to));
ts_file.write("");
assert_eq!(
resolver.resolve(&ts_file.uri_file()).to_string(),
ts_file.uri_file().to_string(),
);
assert_eq!(
resolver
.resolve(
&temp_dir
.uri_dir()
.join(&format!("file.{}", ext_from))
.unwrap()
)
.to_string(),
ts_file.uri_file().to_string(),
);
ts_file.remove_file();
}

// no extension scenarios
for ext in ["js", "ts", "js", "tsx", "jsx", "mjs", "mts"] {
let file = temp_dir.join(format!("file.{}", ext));
file.write("");
assert_eq!(
resolver
.resolve(
&temp_dir
.uri_dir()
.join("file") // no ext
.unwrap()
)
.to_string(),
file.uri_file().to_string(),
);
file.remove_file();
}

// .ts and .js exists, .js specified (goes to specified)
let ts_file = temp_dir.join("file.ts");
ts_file.write("");
let js_file = temp_dir.join("file.js");
js_file.write("");
assert_eq!(
resolver.resolve(&js_file.uri_file()).to_string(),
js_file.uri_file().to_string(),
);
}
}