From fe1ca26218493d2e7d4121433c365a37e13285e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Donny/=EA=B0=95=EB=8F=99=EC=9C=A4?= Date: Tue, 15 Aug 2023 01:33:17 +0900 Subject: [PATCH] fix(es): Resolve `jsc.baseUrl` for `.swcrc` specified by `--config-file` (#7801) **Related issue:** - Closes #7800 --- crates/swc/src/config/mod.rs | 2 +- crates/swc/src/lib.rs | 133 ++++++++++++++++++------------ node-swc/__tests__/error_test.mjs | 2 +- package.json | 2 +- yarn.lock | 10 +-- 5 files changed, 86 insertions(+), 63 deletions(-) diff --git a/crates/swc/src/config/mod.rs b/crates/swc/src/config/mod.rs index 43a87f999d3a..b493b28772c0 100644 --- a/crates/swc/src/config/mod.rs +++ b/crates/swc/src/config/mod.rs @@ -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, diff --git a/crates/swc/src/lib.rs b/crates/swc/src/lib.rs index 8514e23853a4..00782b1b3064 100644 --- a/crates/swc/src/lib.rs +++ b/crates/swc/src/lib.rs @@ -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))?), - _ => None, + 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 + } + } }; - 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 swcrc.exists() { - let config = load_swcrc(&swcrc)?; - - 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); - } + 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 dir == root && *root_mode == RootMode::Root { - break; + 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"); + + let mut config = config + .into_config(Some(filename_path)) + .context("failed to process config file")?; + + 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() + ) + })? + }; } - 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 { + 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 { let content = read_to_string(path).context("failed to read config (.swcrc) file")?; diff --git a/node-swc/__tests__/error_test.mjs b/node-swc/__tests__/error_test.mjs index e3214f064a6c..d39b77c9d89e 100644 --- a/node-swc/__tests__/error_test.mjs +++ b/node-swc/__tests__/error_test.mjs @@ -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)", () => { diff --git a/package.json b/package.json index 45b685ded490..e1e43bb57e21 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/yarn.lock b/yarn.lock index c263a98c344a..dddceb226eee 100644 --- a/yarn.lock +++ b/yarn.lock @@ -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