fix(es): Resolve jsc.baseUrl for .swcrc specified by --config-file (#7801)

**Related issue:**

 - Closes #7800
This commit is contained in:
Donny/강동윤 2023-08-15 01:33:17 +09:00 committed by GitHub
parent 0f66ee315a
commit fe1ca26218
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 84 additions and 61 deletions

View File

@ -863,7 +863,7 @@ impl Options {
}
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
pub enum RootMode {
#[serde(rename = "root")]
Root,

View File

@ -140,7 +140,6 @@ use swc_common::{
BytePos, FileName, Mark, SourceFile, SourceMap, Spanned, GLOBALS,
};
pub use swc_config::config_types::{BoolConfig, BoolOr, BoolOrDataConfig};
use swc_config::merge::Merge;
use swc_ecma_ast::{EsVersion, Ident, Program};
use swc_ecma_codegen::{self, text_writer::WriteJs, Emitter, Node};
use swc_ecma_loader::resolvers::{
@ -755,67 +754,73 @@ impl Compiler {
let root = root.as_ref().unwrap_or(&CUR_DIR);
let config_file = match config_file {
Some(ConfigFile::Str(ref s)) => Some(load_swcrc(Path::new(&s))?),
let swcrc_path = match config_file {
Some(ConfigFile::Str(s)) => Some(PathBuf::from(s.clone())),
_ => {
if *swcrc {
if let FileName::Real(ref path) = name {
find_swcrc(path, root, *root_mode)
} else {
None
}
} else {
None
}
}
};
let config_file = match swcrc_path.as_deref() {
Some(s) => Some(load_swcrc(s)?),
_ => None,
};
let filename_path = match name {
FileName::Real(p) => Some(&**p),
_ => None,
};
if let FileName::Real(ref path) = name {
if *swcrc {
let mut parent = path.parent();
while let Some(dir) = parent {
let swcrc = dir.join(".swcrc");
if let Some(filename_path) = filename_path {
if let Some(config) = config_file {
let dir = swcrc_path
.as_deref()
.and_then(|p| p.parent())
.expect(".swcrc path should have parent dir");
if swcrc.exists() {
let config = load_swcrc(&swcrc)?;
let mut config = config
.into_config(Some(filename_path))
.context("failed to process config file")?;
let mut config = config
.into_config(Some(path))
.context("failed to process config file")?;
if let Some(config_file) = config_file {
config.merge(config_file.into_config(Some(path))?)
}
if let Some(c) = &mut config {
if c.jsc.base_url != PathBuf::new() {
let joined = dir.join(&c.jsc.base_url);
c.jsc.base_url = if cfg!(target_os = "windows")
&& c.jsc.base_url.as_os_str() == "."
{
dir.canonicalize().with_context(|| {
format!(
"failed to canonicalize base url using the path \
of .swcrc\nDir: {}\n(Used logic for windows)",
dir.display(),
)
})?
} else {
joined.canonicalize().with_context(|| {
format!(
"failed to canonicalize base url using the path \
of .swcrc\nPath: {}\nDir: {}\nbaseUrl: {}",
joined.display(),
dir.display(),
c.jsc.base_url.display()
)
})?
};
}
}
return Ok(config);
if let Some(c) = &mut config {
if c.jsc.base_url != PathBuf::new() {
let joined = dir.join(&c.jsc.base_url);
c.jsc.base_url = if cfg!(target_os = "windows")
&& c.jsc.base_url.as_os_str() == "."
{
dir.canonicalize().with_context(|| {
format!(
"failed to canonicalize base url using the path of \
.swcrc\nDir: {}\n(Used logic for windows)",
dir.display(),
)
})?
} else {
joined.canonicalize().with_context(|| {
format!(
"failed to canonicalize base url using the path of \
.swcrc\nPath: {}\nDir: {}\nbaseUrl: {}",
joined.display(),
dir.display(),
c.jsc.base_url.display()
)
})?
};
}
if dir == root && *root_mode == RootMode::Root {
break;
}
parent = dir.parent();
}
return Ok(config);
}
let config_file = config_file.unwrap_or_default();
let config = config_file.into_config(Some(path))?;
let config = config_file.into_config(Some(filename_path))?;
return Ok(config);
}
@ -832,7 +837,7 @@ impl Compiler {
}
}
})
.with_context(|| format!("failed to read swcrc file ({})", name))
.with_context(|| format!("failed to read .swcrc file for input file at `{}`", name))
}
/// This method returns [None] if a file should be skipped.
@ -1258,6 +1263,24 @@ impl Compiler {
}
}
fn find_swcrc(path: &Path, root: &Path, root_mode: RootMode) -> Option<PathBuf> {
let mut parent = path.parent();
while let Some(dir) = parent {
let swcrc = dir.join(".swcrc");
if swcrc.exists() {
return Some(swcrc);
}
if dir == root && root_mode == RootMode::Root {
break;
}
parent = dir.parent();
}
None
}
#[tracing::instrument(level = "info", skip_all)]
fn load_swcrc(path: &Path) -> Result<Rc, Error> {
let content = read_to_string(path).context("failed to read config (.swcrc) file")?;

View File

@ -13,7 +13,7 @@ it("should work", () => {
it("should report good error", () => {
expect(() => {
swc.transformFileSync(__dirname + "/../tests/error/simple.js");
}).toThrow("failed to read swcrc file");
}).toThrow("failed to deserialize .swcrc (json) file");
});
it("should report good error (handler)", () => {

View File

@ -96,7 +96,7 @@
"@swc/plugin-jest": "latest",
"@taplo/cli": "^0.3.2",
"@types/jest": "^28.1.4",
"@types/node": "^14.14.41",
"@types/node": "^20.5.0",
"@types/terser": "^3.12.0",
"acorn": "^8.6.0",
"acorn-jsx": "^5.3.2",

View File

@ -2566,7 +2566,7 @@ __metadata:
"@swc/plugin-jest": latest
"@taplo/cli": ^0.3.2
"@types/jest": ^28.1.4
"@types/node": ^14.14.41
"@types/node": ^20.5.0
"@types/terser": ^3.12.0
acorn: ^8.6.0
acorn-jsx: ^5.3.2
@ -2785,10 +2785,10 @@ __metadata:
languageName: node
linkType: hard
"@types/node@npm:^14.14.41":
version: 14.18.48
resolution: "@types/node@npm:14.18.48"
checksum: bc410153cd12b5f5218c2c2a5ab4a65e8dc99ebffe98261a30e9d4beb8f9a0e4ee48c41b850f8cb80da6ed1024e42bba8dee1592869aa5b1826ddb7c29ad6899
"@types/node@npm:^20.5.0":
version: 20.5.0
resolution: "@types/node@npm:20.5.0"
checksum: 659bc5fc93b5c02bd88ca4bfae4f6b9dc307d45884d1dd9d69df85819a9943cdc00cd3c87eec3048866df6a67f52297f74d170e47a44f61edb3e8f770d94e85e
languageName: node
linkType: hard