mirror of
https://github.com/swc-project/swc.git
synced 2024-12-28 08:04:43 +03:00
d6a4615898
**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" ```
207 lines
4.9 KiB
Rust
207 lines
4.9 KiB
Rust
#![cfg(feature = "tsc")]
|
|
|
|
use std::collections::HashMap;
|
|
|
|
use anyhow::{anyhow, Error};
|
|
use swc_common::{collections::AHashMap, FileName};
|
|
use swc_ecma_loader::{
|
|
resolve::{Resolution, Resolve},
|
|
resolvers::tsc::TsConfigResolver,
|
|
};
|
|
|
|
#[test]
|
|
fn base_dir_exact() {}
|
|
|
|
#[test]
|
|
fn base_dir_wildcard() {}
|
|
|
|
#[test]
|
|
fn exact() {
|
|
let mut map = HashMap::default();
|
|
map.insert("jquery".to_string(), "fail".to_string());
|
|
map.insert(
|
|
"./node_modules/jquery/dist/jquery".to_string(),
|
|
"success".to_string(),
|
|
);
|
|
let r = TsConfigResolver::new(
|
|
TestResolver(map),
|
|
".".into(),
|
|
vec![(
|
|
"jquery".into(),
|
|
vec!["node_modules/jquery/dist/jquery".into()],
|
|
)],
|
|
);
|
|
|
|
{
|
|
let resolved = r
|
|
.resolve(&FileName::Anon, "jquery")
|
|
.expect("should resolve");
|
|
|
|
assert_eq!(
|
|
resolved,
|
|
Resolution {
|
|
filename: FileName::Custom("success".into()),
|
|
slug: None
|
|
}
|
|
);
|
|
}
|
|
|
|
{
|
|
r.resolve(&FileName::Anon, "unrelated")
|
|
.expect_err("should not touch error");
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn pattern_1() {
|
|
let mut map = HashMap::default();
|
|
map.insert("./folder1/file1".to_string(), "success-1".to_string());
|
|
map.insert("./folder1/file2".to_string(), "success-2".to_string());
|
|
map.insert(
|
|
"./generated/folder2/file3".to_string(),
|
|
"success-3".to_string(),
|
|
);
|
|
|
|
let r = TsConfigResolver::new(
|
|
TestResolver(map),
|
|
".".into(),
|
|
vec![("*".into(), vec!["*".into(), "generated/*".into()])],
|
|
);
|
|
|
|
{
|
|
let resolved = r
|
|
.resolve(&FileName::Anon, "folder1/file2")
|
|
.expect("should resolve");
|
|
|
|
assert_eq!(
|
|
resolved,
|
|
Resolution {
|
|
filename: FileName::Custom("success-2".into()),
|
|
slug: None
|
|
}
|
|
);
|
|
}
|
|
|
|
{
|
|
let resolved = r
|
|
.resolve(&FileName::Anon, "folder2/file3")
|
|
.expect("should resolve");
|
|
|
|
assert_eq!(
|
|
resolved,
|
|
Resolution {
|
|
filename: FileName::Custom("success-3".into()),
|
|
slug: None
|
|
}
|
|
);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn base_url_works_for_bare_specifier() {
|
|
let mut map = HashMap::default();
|
|
map.insert("./src/common/helper".to_string(), "helper".to_string());
|
|
|
|
let r = TsConfigResolver::new(
|
|
TestResolver(map),
|
|
".".into(),
|
|
vec![("@common/*".into(), vec!["src/common/*".into()])],
|
|
);
|
|
|
|
{
|
|
let resolved = r
|
|
.resolve(&FileName::Anon, "@common/helper")
|
|
.expect("should resolve");
|
|
|
|
assert_eq!(
|
|
resolved,
|
|
Resolution {
|
|
filename: FileName::Custom("helper".into()),
|
|
slug: None
|
|
}
|
|
);
|
|
}
|
|
|
|
{
|
|
let resolved = r
|
|
.resolve(&FileName::Anon, "src/common/helper")
|
|
.expect("should resolve");
|
|
|
|
assert_eq!(
|
|
resolved,
|
|
Resolution {
|
|
filename: FileName::Custom("helper".into()),
|
|
slug: None
|
|
}
|
|
);
|
|
}
|
|
|
|
{
|
|
let resolved = r
|
|
.resolve(&FileName::Anon, "./src/common/helper")
|
|
.expect("should resolve");
|
|
|
|
assert_eq!(
|
|
resolved,
|
|
Resolution {
|
|
filename: FileName::Custom("helper".into()),
|
|
slug: None
|
|
}
|
|
);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn base_url_precedence() {
|
|
let mut map = HashMap::default();
|
|
map.insert("./jquery".to_string(), "jq in base url".to_string());
|
|
map.insert("jquery".to_string(), "jq in node module".to_string());
|
|
map.insert("react".to_string(), "react in node module".to_string());
|
|
|
|
let r = TsConfigResolver::new(TestResolver(map), ".".into(), vec![]);
|
|
|
|
{
|
|
let resolved = r
|
|
.resolve(&FileName::Anon, "jquery")
|
|
.expect("should resolve from base url");
|
|
|
|
assert_eq!(
|
|
resolved,
|
|
Resolution {
|
|
filename: FileName::Custom("jq in base url".into()),
|
|
slug: None
|
|
}
|
|
);
|
|
}
|
|
|
|
{
|
|
let resolved = r
|
|
.resolve(&FileName::Anon, "react")
|
|
.expect("should resolve from node modules");
|
|
|
|
assert_eq!(
|
|
resolved,
|
|
Resolution {
|
|
filename: FileName::Custom("react in node module".into()),
|
|
slug: None
|
|
}
|
|
);
|
|
}
|
|
}
|
|
|
|
struct TestResolver(AHashMap<String, String>);
|
|
|
|
impl Resolve for TestResolver {
|
|
fn resolve(&self, _: &FileName, src: &str) -> Result<Resolution, Error> {
|
|
self.0
|
|
.get(src)
|
|
.cloned()
|
|
.map(FileName::Custom)
|
|
.map(|v| Resolution {
|
|
filename: v,
|
|
slug: None,
|
|
})
|
|
.ok_or_else(|| anyhow!("failed to resolve `{}`", src))
|
|
}
|
|
}
|