From f3b262e340cdd5aaa5ce4008936e3ba696f3dc06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Donny/=EA=B0=95=EB=8F=99=EC=9C=A4?= Date: Thu, 5 May 2022 00:07:28 +0900 Subject: [PATCH] fix(es/modules): Preserve extensions (#4524) --- .../fixture/issues-3xxx/3576/input/.swcrc | 17 +++++++++++ .../issues-3xxx/3576/input/src/input.ts | 5 ++++ .../issues-3xxx/3576/output/src/input.ts | 4 +++ crates/swc_ecma_loader/src/resolvers/node.rs | 4 +-- crates/swc_ecma_transforms_module/src/path.rs | 28 +++++++++++++++---- 5 files changed, 49 insertions(+), 9 deletions(-) create mode 100644 crates/swc/tests/fixture/issues-3xxx/3576/input/.swcrc create mode 100644 crates/swc/tests/fixture/issues-3xxx/3576/input/src/input.ts create mode 100644 crates/swc/tests/fixture/issues-3xxx/3576/output/src/input.ts diff --git a/crates/swc/tests/fixture/issues-3xxx/3576/input/.swcrc b/crates/swc/tests/fixture/issues-3xxx/3576/input/.swcrc new file mode 100644 index 00000000000..6667bf9adf9 --- /dev/null +++ b/crates/swc/tests/fixture/issues-3xxx/3576/input/.swcrc @@ -0,0 +1,17 @@ +{ + "jsc": { + "baseUrl": "./src", + "paths": { + "@modules/*": [ + "./modules/*" + ] + }, + "target": "es2020", + "parser": { + "syntax": "typescript" + } + }, + "module": { + "type": "es6" + } +} \ No newline at end of file diff --git a/crates/swc/tests/fixture/issues-3xxx/3576/input/src/input.ts b/crates/swc/tests/fixture/issues-3xxx/3576/input/src/input.ts new file mode 100644 index 00000000000..7b4d1346832 --- /dev/null +++ b/crates/swc/tests/fixture/issues-3xxx/3576/input/src/input.ts @@ -0,0 +1,5 @@ +// We keep the .js extension for ESModules, but SWC will strip it: +import { modulo } from "@modules/modulo.js"; +import { sum } from "./sum.js"; + +console.log(modulo(sum(1, 2), 2)); diff --git a/crates/swc/tests/fixture/issues-3xxx/3576/output/src/input.ts b/crates/swc/tests/fixture/issues-3xxx/3576/output/src/input.ts new file mode 100644 index 00000000000..06c5a577060 --- /dev/null +++ b/crates/swc/tests/fixture/issues-3xxx/3576/output/src/input.ts @@ -0,0 +1,4 @@ +// We keep the .js extension for ESModules, but SWC will strip it: +import { modulo } from "./modules/modulo.js"; +import { sum } from "./sum.js"; +console.log(modulo(sum(1, 2), 2)); diff --git a/crates/swc_ecma_loader/src/resolvers/node.rs b/crates/swc_ecma_loader/src/resolvers/node.rs index abde6006802..88da4022283 100644 --- a/crates/swc_ecma_loader/src/resolvers/node.rs +++ b/crates/swc_ecma_loader/src/resolvers/node.rs @@ -55,9 +55,7 @@ fn find_package_root(path: &Path) -> Option { None } -pub fn to_absolute_path(path: impl AsRef) -> Result { - let path = path.as_ref(); - +pub fn to_absolute_path(path: &Path) -> Result { let absolute_path = if path.is_absolute() { path.to_path_buf() } else { diff --git a/crates/swc_ecma_transforms_module/src/path.rs b/crates/swc_ecma_transforms_module/src/path.rs index 077b57b1333..ad26cf753a7 100644 --- a/crates/swc_ecma_transforms_module/src/path.rs +++ b/crates/swc_ecma_transforms_module/src/path.rs @@ -100,9 +100,9 @@ where R: Resolve, { fn resolve_import(&self, base: &FileName, module_specifier: &str) -> Result { - fn to_specifier(target_path: &str, is_file: Option) -> JsWord { + fn to_specifier(target_path: &str, is_file: Option, had_speicifer: bool) -> JsWord { let mut p = PathBuf::from(target_path); - if is_file.unwrap_or_else(|| p.is_file()) { + if !had_speicifer && is_file.unwrap_or_else(|| p.is_file()) { if let Some(v) = p.extension() { if v == "ts" || v == "tsx" || v == "js" || v == "jsx" { p.set_extension(""); @@ -130,6 +130,12 @@ where debug!("invoking resolver"); } + let had_speicifer = module_specifier + .split('/') + .last() + .map(|s| s.contains('.')) + .unwrap_or(false); + let target = self.resolver.resolve(base, module_specifier); let target = match target { Ok(v) => v, @@ -141,7 +147,7 @@ where let target = match target { FileName::Real(v) => v, - FileName::Custom(s) => return Ok(to_specifier(&s, None)), + FileName::Custom(s) => return Ok(to_specifier(&s, None, had_speicifer)), _ => { unreachable!( "Node path provider does not support using `{:?}` as a target file name", @@ -178,7 +184,13 @@ where let rel_path = match rel_path { Some(v) => v, - None => return Ok(to_specifier(&target.display().to_string(), Some(is_file))), + None => { + return Ok(to_specifier( + &target.display().to_string(), + Some(is_file), + had_speicifer, + )) + } }; { @@ -215,9 +227,13 @@ where Cow::Owned(format!("./{}", s)) }; if cfg!(target_os = "windows") { - Ok(to_specifier(&s.replace('\\', "/"), Some(is_file))) + Ok(to_specifier( + &s.replace('\\', "/"), + Some(is_file), + had_speicifer, + )) } else { - Ok(to_specifier(&s, Some(is_file))) + Ok(to_specifier(&s, Some(is_file), had_speicifer)) } } }