Skip to content

Commit d6a4615

Browse files
authoredJan 27, 2024
fix(es/loader): Make tsc resolver work for bare specifier (#8550)
**Description:** From the typescript [baseUrl](https://www.typescriptlang.org/docs/handbook/modules/reference.html#baseurl) doc: When using bare specifiers (module specifiers that don’t begin with ./, ../, or /), baseUrl has a higher precedence than node_modules package lookups. In the current tsc resolver implementation, when resolving bare module specifiers, baseUrl was not used except for `paths`, this cause the belowing resolution failed, but it worked when used in typescript project. `tsconfig.json` / `.swcrc`: ```json { baseUrl: "." paths: { "@common/*": ["src/common/*"] } } ``` File structure: - ./src/common/helper.ts - ./src/index.ts ./src/index.ts content: ```ts // tsc can resolve this, but tsc resolver cannot import sth from "src/common/helper" ```
1 parent 039c168 commit d6a4615

File tree

2 files changed

+100
-1
lines changed

2 files changed

+100
-1
lines changed
 

‎crates/swc_ecma_loader/src/resolvers/tsc.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,14 @@ where
310310
}
311311
}
312312

313-
if let Ok(v) = self.invoke_inner_resolver(&self.base_url_filename, module_specifier) {
313+
let path = self.base_url.join(module_specifier);
314+
#[cfg(windows)]
315+
let path_string: String = path.to_string_lossy().replace("\\", "/");
316+
#[cfg(not(windows))]
317+
let path_string: String = path.to_string_lossy().to_string();
318+
319+
// https://www.typescriptlang.org/docs/handbook/modules/reference.html#baseurl
320+
if let Ok(v) = self.invoke_inner_resolver(base, path_string.as_str()) {
314321
return Ok(v);
315322
}
316323

‎crates/swc_ecma_loader/tests/tsc_resolver.rs

+92
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,98 @@ fn pattern_1() {
9797
}
9898
}
9999

100+
#[test]
101+
fn base_url_works_for_bare_specifier() {
102+
let mut map = HashMap::default();
103+
map.insert("./src/common/helper".to_string(), "helper".to_string());
104+
105+
let r = TsConfigResolver::new(
106+
TestResolver(map),
107+
".".into(),
108+
vec![("@common/*".into(), vec!["src/common/*".into()])],
109+
);
110+
111+
{
112+
let resolved = r
113+
.resolve(&FileName::Anon, "@common/helper")
114+
.expect("should resolve");
115+
116+
assert_eq!(
117+
resolved,
118+
Resolution {
119+
filename: FileName::Custom("helper".into()),
120+
slug: None
121+
}
122+
);
123+
}
124+
125+
{
126+
let resolved = r
127+
.resolve(&FileName::Anon, "src/common/helper")
128+
.expect("should resolve");
129+
130+
assert_eq!(
131+
resolved,
132+
Resolution {
133+
filename: FileName::Custom("helper".into()),
134+
slug: None
135+
}
136+
);
137+
}
138+
139+
{
140+
let resolved = r
141+
.resolve(&FileName::Anon, "./src/common/helper")
142+
.expect("should resolve");
143+
144+
assert_eq!(
145+
resolved,
146+
Resolution {
147+
filename: FileName::Custom("helper".into()),
148+
slug: None
149+
}
150+
);
151+
}
152+
}
153+
154+
#[test]
155+
fn base_url_precedence() {
156+
let mut map = HashMap::default();
157+
map.insert("./jquery".to_string(), "jq in base url".to_string());
158+
map.insert("jquery".to_string(), "jq in node module".to_string());
159+
map.insert("react".to_string(), "react in node module".to_string());
160+
161+
let r = TsConfigResolver::new(TestResolver(map), ".".into(), vec![]);
162+
163+
{
164+
let resolved = r
165+
.resolve(&FileName::Anon, "jquery")
166+
.expect("should resolve from base url");
167+
168+
assert_eq!(
169+
resolved,
170+
Resolution {
171+
filename: FileName::Custom("jq in base url".into()),
172+
slug: None
173+
}
174+
);
175+
}
176+
177+
{
178+
let resolved = r
179+
.resolve(&FileName::Anon, "react")
180+
.expect("should resolve from node modules");
181+
182+
assert_eq!(
183+
resolved,
184+
Resolution {
185+
filename: FileName::Custom("react in node module".into()),
186+
slug: None
187+
}
188+
);
189+
}
190+
}
191+
100192
struct TestResolver(AHashMap<String, String>);
101193

102194
impl Resolve for TestResolver {

0 commit comments

Comments
 (0)
Please sign in to comment.