From 9eafd0c6c41f86c5244f7346ab22382212b7c1c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B0=95=EB=8F=99=EC=9C=A4?= Date: Fri, 10 Sep 2021 21:29:26 +0900 Subject: [PATCH] fix(es/loader): Fix support for `jsc.paths`. (#2227) swc_ecma_loader: - `TsConfigResolver`: Use `baseUrl`. (#2050) swc: - Change type of `JscConfig.base_url` to `PathBuf`. testing: - Improve `NormalizedOutput::compare_to_file`. --- Cargo.lock | 6 +-- Cargo.toml | 2 +- ecmascript/loader/Cargo.toml | 2 +- ecmascript/loader/src/resolvers/tsc.rs | 11 +++++- ecmascript/transforms/module/src/path.rs | 2 +- node-swc/__tests__/paths_test.mjs | 5 +++ src/builder.rs | 4 +- src/config/mod.rs | 9 +++-- src/lib.rs | 39 ++++++++++++++++--- testing/Cargo.toml | 2 +- testing/src/output.rs | 22 +++-------- tests/fixture/issue-2050/input/.swcrc | 17 ++++++++ tests/fixture/issue-2050/input/index.ts | 4 ++ tests/fixture/issue-2050/input/subfolder/A.ts | 5 +++ tests/fixture/issue-2050/input/subfolder/B.ts | 1 + tests/fixture/issue-2050/output/index.ts | 8 ++++ .../fixture/issue-2050/output/subfolder/A.ts | 9 +++++ .../fixture/issue-2050/output/subfolder/B.ts | 7 ++++ .../paths/cjs-001/output/{ => src}/dep.ts | 0 .../paths/cjs-001/output/{ => src2}/dep-2.ts | 0 tests/projects.rs | 19 +++++---- tests/t.js | 4 -- 22 files changed, 130 insertions(+), 48 deletions(-) create mode 100644 tests/fixture/issue-2050/input/.swcrc create mode 100644 tests/fixture/issue-2050/input/index.ts create mode 100644 tests/fixture/issue-2050/input/subfolder/A.ts create mode 100644 tests/fixture/issue-2050/input/subfolder/B.ts create mode 100644 tests/fixture/issue-2050/output/index.ts create mode 100644 tests/fixture/issue-2050/output/subfolder/A.ts create mode 100644 tests/fixture/issue-2050/output/subfolder/B.ts rename tests/fixture/paths/cjs-001/output/{ => src}/dep.ts (100%) rename tests/fixture/paths/cjs-001/output/{ => src2}/dep-2.ts (100%) delete mode 100644 tests/t.js diff --git a/Cargo.lock b/Cargo.lock index 5c9aeb1f538..70fb8f96572 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2287,7 +2287,7 @@ checksum = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c" [[package]] name = "swc" -version = "0.52.0" +version = "0.53.0" dependencies = [ "ahash", "anyhow", @@ -2608,7 +2608,7 @@ dependencies = [ [[package]] name = "swc_ecma_loader" -version = "0.18.1" +version = "0.18.2" dependencies = [ "anyhow", "dashmap", @@ -3161,7 +3161,7 @@ dependencies = [ [[package]] name = "testing" -version = "0.13.0" +version = "0.13.1" dependencies = [ "ansi_term 0.12.1", "difference", diff --git a/Cargo.toml b/Cargo.toml index 5c68d67b10d..7797a2bc744 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,7 +20,7 @@ edition = "2018" license = "Apache-2.0/MIT" name = "swc" repository = "https://github.com/swc-project/swc.git" -version = "0.52.0" +version = "0.53.0" [lib] name = "swc" diff --git a/ecmascript/loader/Cargo.toml b/ecmascript/loader/Cargo.toml index 8c80e0b34f3..5522d899e63 100644 --- a/ecmascript/loader/Cargo.toml +++ b/ecmascript/loader/Cargo.toml @@ -6,7 +6,7 @@ edition = "2018" license = "Apache-2.0/MIT" name = "swc_ecma_loader" repository = "https://github.com/swc-project/swc.git" -version = "0.18.1" +version = "0.18.2" [package.metadata.docs.rs] all-features = true diff --git a/ecmascript/loader/src/resolvers/tsc.rs b/ecmascript/loader/src/resolvers/tsc.rs index b3c1ddc94a1..c3a1281abee 100644 --- a/ecmascript/loader/src/resolvers/tsc.rs +++ b/ecmascript/loader/src/resolvers/tsc.rs @@ -135,7 +135,7 @@ where ); let mut errors = vec![]; for target in to { - let replaced = target.replace('*', capture.as_str()); + let mut replaced = target.replace('*', capture.as_str()); let rel = format!("./{}", replaced); let res = self.inner.resolve(base, &rel).with_context(|| { @@ -150,8 +150,15 @@ where Err(err) => err, }); + if cfg!(target_os = "windows") { + if replaced.starts_with("./") { + replaced = replaced[2..].to_string(); + } + replaced = replaced.replace('/', "\\"); + } + if to.len() == 1 { - return Ok(FileName::Custom(replaced)); + return Ok(FileName::Real(self.base_url.join(replaced))); } } diff --git a/ecmascript/transforms/module/src/path.rs b/ecmascript/transforms/module/src/path.rs index beea75c438c..154a31231d1 100644 --- a/ecmascript/transforms/module/src/path.rs +++ b/ecmascript/transforms/module/src/path.rs @@ -97,7 +97,7 @@ where let rel_path = match rel_path { Some(v) => v, - None => return Ok(module_specifier.into()), + None => return Ok(to_specifier(&target.display().to_string())), }; { diff --git a/node-swc/__tests__/paths_test.mjs b/node-swc/__tests__/paths_test.mjs index 5dc3a105c1f..d1a1828a594 100644 --- a/node-swc/__tests__/paths_test.mjs +++ b/node-swc/__tests__/paths_test.mjs @@ -1,4 +1,8 @@ import swc from "../.."; +import { dirname } from 'path'; +import { fileURLToPath } from 'url'; + +const __dirname = dirname(fileURLToPath(import.meta.url)); it("should respect paths", async () => { const { code } = await swc.transform(` @@ -13,6 +17,7 @@ it("should respect paths", async () => { transform: { }, + baseUrl: __dirname, paths: { '@src/*': ['bar/*'] } diff --git a/src/builder.rs b/src/builder.rs index 67b498a4275..0c143f0d137 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -4,7 +4,7 @@ use crate::{ }; use compat::es2020::export_namespace_from; use either::Either; -use std::{cell::RefCell, collections::HashMap, rc::Rc, sync::Arc}; +use std::{cell::RefCell, collections::HashMap, path::PathBuf, rc::Rc, sync::Arc}; use swc_atoms::JsWord; use swc_common::{ chain, comments::Comments, errors::Handler, sync::Lrc, util::take::Take, FileName, Mark, @@ -142,7 +142,7 @@ impl<'a, 'b, P: swc_ecma_visit::Fold> PassBuilder<'a, 'b, P> { /// - fixer if enabled pub fn finalize<'cmt>( self, - base_url: String, + base_url: PathBuf, paths: CompiledPaths, base: &FileName, syntax: Syntax, diff --git a/src/config/mod.rs b/src/config/mod.rs index cd22fc52129..3bd012bdd43 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -208,6 +208,7 @@ impl Options { minify: js_minify, .. } = config.jsc; + let target = target.unwrap_or_default(); let syntax = syntax.unwrap_or_default(); @@ -774,7 +775,7 @@ pub struct JscConfig { pub keep_class_names: bool, #[serde(default)] - pub base_url: String, + pub base_url: PathBuf, #[serde(default)] pub paths: Paths, @@ -816,7 +817,7 @@ pub enum ModuleConfig { impl ModuleConfig { pub fn build( cm: Arc, - base_url: String, + base_url: PathBuf, paths: CompiledPaths, base: &FileName, root_mark: Mark, @@ -1224,8 +1225,8 @@ impl Merge for ConstModulesConfig { } } -fn build_resolver(base_url: String, paths: CompiledPaths) -> SwcImportResolver { - static CACHE: Lazy> = +fn build_resolver(base_url: PathBuf, paths: CompiledPaths) -> SwcImportResolver { + static CACHE: Lazy> = Lazy::new(|| Default::default()); if let Some(cached) = CACHE.get(&(base_url.clone(), paths.clone())) { diff --git a/src/lib.rs b/src/lib.rs index 92e5c0373c0..8c99dad94e6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -52,6 +52,8 @@ use swc_ecma_visit::{noop_visit_type, FoldWith, Visit, VisitWith}; mod builder; pub mod config; pub mod resolver { + use std::path::PathBuf; + use crate::config::CompiledPaths; use fxhash::FxHashMap; use swc_ecma_ast::TargetEnv; @@ -64,14 +66,10 @@ pub mod resolver { pub fn paths_resolver( target_env: TargetEnv, alias: FxHashMap, - base_url: String, + base_url: PathBuf, paths: CompiledPaths, ) -> CachingResolver> { - let r = TsConfigResolver::new( - NodeModulesResolver::new(target_env, alias), - base_url.clone().into(), - paths.clone(), - ); + let r = TsConfigResolver::new(NodeModulesResolver::new(target_env, alias), base_url, paths); CachingResolver::new(40, r) } @@ -588,6 +586,35 @@ impl Compiler { 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); } diff --git a/testing/Cargo.toml b/testing/Cargo.toml index 72649bbadec..a3bfdedf143 100644 --- a/testing/Cargo.toml +++ b/testing/Cargo.toml @@ -6,7 +6,7 @@ edition = "2018" license = "Apache-2.0/MIT" name = "testing" repository = "https://github.com/swc-project/swc.git" -version = "0.13.0" +version = "0.13.1" [dependencies] ansi_term = "0.12.1" diff --git a/testing/src/output.rs b/testing/src/output.rs index a99584d7162..c03a2e8739e 100644 --- a/testing/src/output.rs +++ b/testing/src/output.rs @@ -2,7 +2,7 @@ use crate::paths; use pretty_assertions::assert_eq; use std::{ fmt, - fs::{create_dir_all, remove_file, File}, + fs::{create_dir_all, File}, io::Read, ops::Deref, path::Path, @@ -79,22 +79,12 @@ impl NormalizedOutput { String::new() }); - let path_for_actual = paths::test_results_dir().join("ui").join( - path.strip_prefix(&paths::manifest_dir()) - .unwrap_or_else(|_| { - unreachable!( - "failed to strip prefix: CARGO_MANIFEST_DIR\nPath: {}\nManifest dir: {}", - path.display(), - paths::manifest_dir().display() - ) - }), - ); - eprintln!("{}:{}", path.display(), path_for_actual.display()); - if self.0 == expected { - let _ = remove_file(path_for_actual); + if expected == self.0 { return Ok(()); } - create_dir_all(path_for_actual.parent().unwrap()).expect("failed to run `mkdir -p`"); + + eprintln!("Comparing output to {}", path.display()); + create_dir_all(path.parent().unwrap()).expect("failed to run `mkdir -p`"); let diff = Diff { expected: NormalizedOutput(expected), @@ -106,7 +96,7 @@ impl NormalizedOutput { eprintln!( "Assertion failed: \nActual file printed to {}", - path_for_actual.display() + path.display() ); } diff --git a/tests/fixture/issue-2050/input/.swcrc b/tests/fixture/issue-2050/input/.swcrc new file mode 100644 index 00000000000..cb9f940803a --- /dev/null +++ b/tests/fixture/issue-2050/input/.swcrc @@ -0,0 +1,17 @@ +{ + "jsc": { + "parser": { + "syntax": "typescript" + }, + "target": "es2020", + "baseUrl": ".", + "paths": { + "~/*": [ + "./*" + ] + } + }, + "module": { + "type": "commonjs" + } +} diff --git a/tests/fixture/issue-2050/input/index.ts b/tests/fixture/issue-2050/input/index.ts new file mode 100644 index 00000000000..a63dec0776a --- /dev/null +++ b/tests/fixture/issue-2050/input/index.ts @@ -0,0 +1,4 @@ +import A from './subfolder/A' + + +console.log(A); \ No newline at end of file diff --git a/tests/fixture/issue-2050/input/subfolder/A.ts b/tests/fixture/issue-2050/input/subfolder/A.ts new file mode 100644 index 00000000000..91ecee23778 --- /dev/null +++ b/tests/fixture/issue-2050/input/subfolder/A.ts @@ -0,0 +1,5 @@ +import { B } from '~/subfolder/B'; + +console.log(B); + +export const A = 400; \ No newline at end of file diff --git a/tests/fixture/issue-2050/input/subfolder/B.ts b/tests/fixture/issue-2050/input/subfolder/B.ts new file mode 100644 index 00000000000..0a85309e93c --- /dev/null +++ b/tests/fixture/issue-2050/input/subfolder/B.ts @@ -0,0 +1 @@ +export const B = 500; \ No newline at end of file diff --git a/tests/fixture/issue-2050/output/index.ts b/tests/fixture/issue-2050/output/index.ts new file mode 100644 index 00000000000..018b72f779e --- /dev/null +++ b/tests/fixture/issue-2050/output/index.ts @@ -0,0 +1,8 @@ +"use strict"; +var _a = _interopRequireDefault(require("./subfolder/A")); +function _interopRequireDefault(obj) { + return obj && obj.__esModule ? obj : { + default: obj + }; +} +console.log(_a.default); diff --git a/tests/fixture/issue-2050/output/subfolder/A.ts b/tests/fixture/issue-2050/output/subfolder/A.ts new file mode 100644 index 00000000000..33979bf901a --- /dev/null +++ b/tests/fixture/issue-2050/output/subfolder/A.ts @@ -0,0 +1,9 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.A = void 0; +var _b = require("./B"); +console.log(_b.B); +const A = 400; +exports.A = A; diff --git a/tests/fixture/issue-2050/output/subfolder/B.ts b/tests/fixture/issue-2050/output/subfolder/B.ts new file mode 100644 index 00000000000..658b5e3abbb --- /dev/null +++ b/tests/fixture/issue-2050/output/subfolder/B.ts @@ -0,0 +1,7 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.B = void 0; +const B = 500; +exports.B = B; diff --git a/tests/fixture/paths/cjs-001/output/dep.ts b/tests/fixture/paths/cjs-001/output/src/dep.ts similarity index 100% rename from tests/fixture/paths/cjs-001/output/dep.ts rename to tests/fixture/paths/cjs-001/output/src/dep.ts diff --git a/tests/fixture/paths/cjs-001/output/dep-2.ts b/tests/fixture/paths/cjs-001/output/src2/dep-2.ts similarity index 100% rename from tests/fixture/paths/cjs-001/output/dep-2.ts rename to tests/fixture/paths/cjs-001/output/src2/dep-2.ts diff --git a/tests/projects.rs b/tests/projects.rs index e42521fe9b6..0e5b111111d 100644 --- a/tests/projects.rs +++ b/tests/projects.rs @@ -783,15 +783,14 @@ fn should_visit() { } #[testing::fixture("tests/fixture/**/input/")] -fn tests(dir: PathBuf) { - let output = dir.parent().unwrap().join("output"); - let _ = create_dir_all(&output); +fn tests(input_dir: PathBuf) { + let output = input_dir.parent().unwrap().join("output"); Tester::new() .print_errors(|cm, handler| { let c = Compiler::new(cm.clone()); - for entry in WalkDir::new(&dir) { + for entry in WalkDir::new(&input_dir) { let entry = entry.unwrap(); if entry.metadata().unwrap().is_dir() { continue; @@ -805,6 +804,11 @@ fn tests(dir: PathBuf) { continue; } + let rel_path = entry + .path() + .strip_prefix(&input_dir) + .expect("failed to strip prefix"); + let fm = cm.load_file(entry.path()).expect("failed to load file"); match c.process_js_file( fm, @@ -819,9 +823,11 @@ fn tests(dir: PathBuf) { ) { Ok(v) => { NormalizedOutput::from(v.code) - .compare_to_file(output.join(entry.file_name())) + .compare_to_file(output.join(rel_path)) .unwrap(); + let _ = create_dir_all(output.join(rel_path).parent().unwrap()); + let map = v.map.map(|json| { let json: serde_json::Value = serde_json::from_str(&json).unwrap(); serde_json::to_string_pretty(&json).unwrap() @@ -829,8 +835,7 @@ fn tests(dir: PathBuf) { NormalizedOutput::from(map.unwrap_or_default()) .compare_to_file( - output - .join(entry.path().with_extension("map").file_name().unwrap()), + output.join(rel_path.with_extension("map").file_name().unwrap()), ) .unwrap(); } diff --git a/tests/t.js b/tests/t.js deleted file mode 100644 index d6622b68ed3..00000000000 --- a/tests/t.js +++ /dev/null @@ -1,4 +0,0 @@ -console.log('--Hello--'); -throw new Error('Error here'); - -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9Vc2Vycy9rZHkxL3Byb2plY3RzL3N3Yy1idWdzL3Rlc3RzL3N0YWNrdHJhY2UvaXNzdWUtMTY4NS9pbnB1dC9pbmRleC5qcyJdLCJzb3VyY2VzQ29udGVudCI6WyJjb25zb2xlLmxvZygnLS1IZWxsby0tJylcblxudGhyb3cgbmV3IEVycm9yKCdFcnJvciBoZXJlJyk7Il0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sQ0FBQyxHQUFHLEVBQUMsU0FBVztBQUV2QixLQUFLLENBQUMsR0FBRyxDQUFDLEtBQUssRUFBQyxVQUFZIn0= \ No newline at end of file