fix(es/loader): Support fully-specified ESM import specifiers (#3050)

This commit is contained in:
magic-akari 2021-12-16 19:37:22 +08:00 committed by GitHub
parent 189b1e286d
commit d5c7fb898f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 83 additions and 4 deletions

View File

@ -167,10 +167,39 @@ impl NodeResolver {
return Ok(path.to_path_buf());
}
for ext in EXTENSIONS {
let ext_path = path.with_extension(ext);
if ext_path.is_file() {
return Ok(ext_path);
if let Some(name) = path.file_name() {
let mut ext_path = path.to_path_buf();
let name = name.to_string_lossy();
for ext in EXTENSIONS {
ext_path.set_file_name(format!("{}.{}", name, ext));
if ext_path.is_file() {
return Ok(ext_path);
}
}
// TypeScript-specific behavior: if the extension is ".js" or ".jsx",
// try replacing it with ".ts" or ".tsx".
ext_path.set_file_name(name.into_owned());
let old_ext = path.extension().and_then(|ext| ext.to_str());
if let Some(old_ext) = old_ext {
let extensions = match old_ext {
// Note that the official compiler code always tries ".ts" before
// ".tsx" even if the original extension was ".jsx".
"js" => ["ts", "tsx"].as_slice(),
"jsx" => ["ts", "tsx"].as_slice(),
"mjs" => ["mts"].as_slice(),
"cjs" => ["cts"].as_slice(),
_ => [].as_slice(),
};
for ext in extensions {
ext_path.set_extension(ext);
if ext_path.is_file() {
return Ok(ext_path);
}
}
}
}

View File

@ -0,0 +1,2 @@
import { two } from "./two.js";
two();

View File

@ -0,0 +1 @@
export function two() {}

View File

@ -0,0 +1,3 @@
function two() {
}
two();

View File

@ -0,0 +1,3 @@
function two() {
}
two();

View File

@ -0,0 +1,2 @@
import { result } from "./foo.js";
console.log(result);

View File

@ -0,0 +1 @@
export const result = "foo.js.ts";

View File

@ -0,0 +1 @@
export const result = "foo.ts";

View File

@ -0,0 +1,2 @@
const result = "foo.js.ts";
console.log(result);

View File

@ -0,0 +1,2 @@
const result = "foo.js.ts";
console.log(result);

View File

@ -0,0 +1,2 @@
import { result } from "./foo.mjs";
console.log(result);

View File

@ -0,0 +1 @@
export const result = "foo.mts";

View File

@ -0,0 +1 @@
export const result = "foo.ts";

View File

@ -0,0 +1,2 @@
const result = "foo.mts";
console.log(result);

View File

@ -0,0 +1,2 @@
const result = "foo.mts";
console.log(result);

View File

@ -115,6 +115,31 @@ impl NodeModulesResolver {
return Ok(Some(ext_path));
}
}
// TypeScript-specific behavior: if the extension is ".js" or ".jsx",
// try replacing it with ".ts" or ".tsx".
ext_path.set_file_name(name.into_owned());
let old_ext = path.extension().and_then(|ext| ext.to_str());
if let Some(old_ext) = old_ext {
let extensions = match old_ext {
// Note that the official compiler code always tries ".ts" before
// ".tsx" even if the original extension was ".jsx".
"js" => ["ts", "tsx"].as_slice(),
"jsx" => ["ts", "tsx"].as_slice(),
"mjs" => ["mts"].as_slice(),
"cjs" => ["cts"].as_slice(),
_ => [].as_slice(),
};
for ext in extensions {
ext_path.set_extension(ext);
if ext_path.is_file() {
return Ok(Some(ext_path));
}
}
}
}
bail!("file not found: {}", path.display())