fix(es/module): Read link if an import is resolved as symlink (#8297)

**Related issue:**

 - Closes #8265
This commit is contained in:
Donny/강동윤 2023-11-21 07:17:05 +09:00 committed by GitHub
parent 38c489c26c
commit 7dfdc12218
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 353 additions and 7 deletions

162
Cargo.lock generated
View File

@ -173,6 +173,36 @@ version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711"
[[package]]
name = "assert_cmd"
version = "2.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "88903cb14723e4d4003335bb7f8a14f27691649105346a0f0957466c096adfe6"
dependencies = [
"anstyle",
"bstr",
"doc-comment",
"predicates",
"predicates-core",
"predicates-tree",
"wait-timeout",
]
[[package]]
name = "assert_fs"
version = "1.0.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f070617a68e5c2ed5d06ee8dd620ee18fb72b99f6c094bed34cf8ab07c875b48"
dependencies = [
"anstyle",
"doc-comment",
"globwalk",
"predicates",
"predicates-core",
"predicates-tree",
"tempfile",
]
[[package]]
name = "ast_node"
version = "0.9.5"
@ -358,7 +388,7 @@ dependencies = [
"anyhow",
"chrono",
"either",
"itertools",
"itertools 0.10.5",
"nom",
"once_cell",
"quote",
@ -369,6 +399,17 @@ dependencies = [
"thiserror",
]
[[package]]
name = "bstr"
version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "542f33a8835a0884b006a0c3df3dadd99c0c3f296ed26c2fdc8028e01ad6230c"
dependencies = [
"memchr",
"regex-automata 0.4.3",
"serde",
]
[[package]]
name = "bumpalo"
version = "3.13.0"
@ -849,7 +890,7 @@ dependencies = [
"clap 4.4.6",
"criterion-plot",
"is-terminal",
"itertools",
"itertools 0.10.5",
"num-traits",
"once_cell",
"oorandom",
@ -870,7 +911,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1"
dependencies = [
"cast",
"itertools",
"itertools 0.10.5",
]
[[package]]
@ -1124,6 +1165,12 @@ version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198"
[[package]]
name = "difflib"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8"
[[package]]
name = "digest"
version = "0.10.7"
@ -1161,6 +1208,12 @@ version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0"
[[package]]
name = "doc-comment"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10"
[[package]]
name = "either"
version = "1.8.1"
@ -1515,6 +1568,30 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
[[package]]
name = "globset"
version = "0.4.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "759c97c1e17c55525b57192c06a267cda0ac5210b222d6b82189a2338fa1c13d"
dependencies = [
"aho-corasick",
"bstr",
"fnv",
"log",
"regex",
]
[[package]]
name = "globwalk"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93e3af942408868f6934a7b85134a3230832b9977cf66125df2f9edcfce4ddcc"
dependencies = [
"bitflags 1.3.2",
"ignore",
"walkdir",
]
[[package]]
name = "h2"
version = "0.3.18"
@ -1767,6 +1844,23 @@ version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb56e1aa765b4b4f3aadfab769793b7087bb03a4ea4920644a6d238e2df5b9ed"
[[package]]
name = "ignore"
version = "0.4.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dbe7873dab538a9a44ad79ede1faf5f30d49f9a5c883ddbab48bce81b64b7492"
dependencies = [
"globset",
"lazy_static",
"log",
"memchr",
"regex",
"same-file",
"thread_local",
"walkdir",
"winapi-util",
]
[[package]]
name = "indexmap"
version = "1.9.3"
@ -1855,6 +1949,15 @@ dependencies = [
"either",
]
[[package]]
name = "itertools"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57"
dependencies = [
"either",
]
[[package]]
name = "itoa"
version = "1.0.6"
@ -2080,7 +2183,7 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558"
dependencies = [
"regex-automata",
"regex-automata 0.1.10",
]
[[package]]
@ -2752,6 +2855,34 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
[[package]]
name = "predicates"
version = "3.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6dfc28575c2e3f19cb3c73b93af36460ae898d426eba6fc15b9bd2a5220758a0"
dependencies = [
"anstyle",
"difflib",
"itertools 0.11.0",
"predicates-core",
]
[[package]]
name = "predicates-core"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b794032607612e7abeb4db69adb4e33590fa6cf1149e95fd7cb00e634b92f174"
[[package]]
name = "predicates-tree"
version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "368ba315fb8c5052ab692e68a0eefec6ec57b23a36959c14496f0b0df2c0cecf"
dependencies = [
"predicates-core",
"termtree",
]
[[package]]
name = "preset_env_base"
version = "0.4.8"
@ -3012,6 +3143,12 @@ dependencies = [
"regex-syntax 0.6.29",
]
[[package]]
name = "regex-automata"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f"
[[package]]
name = "regex-syntax"
version = "0.6.29"
@ -3823,6 +3960,8 @@ name = "swc_cli_impl"
version = "0.4.71"
dependencies = [
"anyhow",
"assert_cmd",
"assert_fs",
"atty",
"clap 3.2.25",
"glob",
@ -5454,6 +5593,12 @@ dependencies = [
"libc",
]
[[package]]
name = "termtree"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3369f5ac52d5eb6ab48c6b4ffdc8efbcad6b89c765749064ba298f2c68a16a76"
[[package]]
name = "testing"
version = "0.35.11"
@ -6124,6 +6269,15 @@ dependencies = [
"unicode-xid",
]
[[package]]
name = "wait-timeout"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6"
dependencies = [
"libc",
]
[[package]]
name = "waker-fn"
version = "1.1.0"

View File

@ -0,0 +1,17 @@
{
"jsc": {
"parser": {
"syntax": "typescript"
},
"target": "es2021",
"baseUrl": "./src",
"paths": {
"@modules/*": [
"./modules/*"
]
}
},
"module": {
"type": "commonjs"
},
}

View File

@ -0,0 +1,3 @@
import { moduleA } from "@modules/moduleA";
moduleA();

View File

@ -0,0 +1,6 @@
import { moduleB } from "@modules/moduleB";
export const moduleA = () => {
console.log("This is module A");
moduleB();
};

View File

@ -0,0 +1 @@
export const moduleB = () => console.log("This is module B!");

View File

@ -0,0 +1,6 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
const _moduleA = require("./modules/moduleA");
(0, _moduleA.moduleA)();

View File

@ -0,0 +1,15 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "moduleA", {
enumerable: true,
get: function() {
return moduleA;
}
});
const _moduleB = require("../moduleB");
const moduleA = ()=>{
console.log("This is module A");
(0, _moduleB.moduleB)();
};

View File

@ -0,0 +1,11 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "moduleB", {
enumerable: true,
get: function() {
return moduleB;
}
});
const moduleB = ()=>console.log("This is module B!");

View File

@ -8,11 +8,19 @@ name = "swc_cli_impl"
repository = "https://github.com/swc-project/swc.git"
version = "0.4.71"
[[bin]]
name = "swc"
path = "src/main.rs"
[lib]
crate-type = ["rlib"]
path = "src/lib.rs"
[features]
default = []
plugin = [
"swc_core/plugin_transform_host_native",
"swc_core/plugin_transform_host_native_filesystem_cache",
"swc_core/plugin_transform_host_native",
"swc_core/plugin_transform_host_native_filesystem_cache",
]
[dependencies]
@ -37,3 +45,7 @@ swc_core = { version = "0.86.71", features = [
"common_concurrent",
"base_concurrent",
], path = "../swc_core" }
[dev-dependencies]
assert_cmd = "2.0.12"
assert_fs = "1.0.13"

View File

@ -0,0 +1,5 @@
//! Used for testing
fn main() -> anyhow::Result<()> {
swc_cli_impl::run()
}

View File

@ -0,0 +1,18 @@
{
"jsc": {
"parser": {
"syntax": "typescript"
},
"target": "es2021",
"baseUrl": "./src",
"paths": {
"@modules/*": [
"./modules/*"
]
}
},
"module": {
"type": "commonjs"
},
"sourceMaps": true
}

View File

@ -0,0 +1,3 @@
import { moduleA } from "@modules/moduleA";
moduleA();

View File

@ -0,0 +1,6 @@
import { moduleB } from "@modules/moduleB";
export const moduleA = () => {
console.log("This is module A");
moduleB();
};

View File

@ -0,0 +1 @@
export const moduleB = () => console.log("This is module B!");

View File

@ -0,0 +1,78 @@
use std::{
fs::{self, create_dir_all},
path::Path,
process::{Command, Stdio},
};
use anyhow::{Context, Result};
use assert_cmd::prelude::*;
use assert_fs::TempDir;
fn cli() -> Result<Command> {
let mut cmd = Command::cargo_bin("swc").context("Failed to get swc binary")?;
cmd.stderr(Stdio::inherit());
Ok(cmd)
}
#[test]
fn issue_8265_1() -> Result<()> {
let pwd = Path::new("tests/fixture-manual/8265").canonicalize()?;
let tmp = TempDir::new()?;
create_dir_all(tmp.path().join("src/modules/moduleA"))?;
create_dir_all(tmp.path().join("src/modules/moduleB"))?;
symlink(&pwd.join(".swcrc"), &tmp.path().join(".swcrc"));
symlink(&pwd.join("src/index.ts"), &tmp.path().join("src/index.ts"));
symlink(
&pwd.join("src/modules/moduleA/index.ts"),
&tmp.path().join("src/modules/moduleA/index.ts"),
);
symlink(
&pwd.join("src/modules/moduleB/index.ts"),
&tmp.path().join("src/modules/moduleB/index.ts"),
);
print_ls_alr(&tmp);
let mut cmd = cli()?;
cmd.current_dir(&tmp)
.arg("compile")
.arg("--source-maps")
.arg("false")
.arg("--config-file")
.arg(".swcrc")
.arg("--out-file")
.arg("src/index.js")
.arg("src/index.ts");
cmd.assert().success();
let content = fs::read_to_string(tmp.join("src/index.js"))?;
assert!(
content.contains("require(\"./modules/moduleA\")"),
"{}",
content
);
Ok(())
}
/// ln -s $a $b
fn symlink(a: &Path, b: &Path) {
#[cfg(unix)]
{
std::os::unix::fs::symlink(a, b).unwrap();
}
#[cfg(windows)]
{
std::os::windows::fs::symlink_file(a, b).unwrap();
}
}
fn print_ls_alr(path: &Path) {
let mut cmd = Command::new("ls");
cmd.arg("-alR").arg(path);
cmd.status().unwrap();
}

View File

@ -1,6 +1,7 @@
use std::{
borrow::Cow,
env::current_dir,
fs::read_link,
io,
path::{Component, Path, PathBuf},
sync::Arc,
@ -212,7 +213,7 @@ where
let orig_filename = module_specifier.split('/').last();
let target = self.resolver.resolve(base, module_specifier);
let target = match target {
let mut target = match target {
Ok(v) => v,
Err(err) => {
warn!("import rewriter: failed to resolve: {}", err);
@ -220,6 +221,15 @@ where
}
};
// Bazel uses symlink
//
// https://github.com/swc-project/swc/issues/8265
if let FileName::Real(resolved) = &target {
if let Ok(orig) = read_link(resolved) {
target = FileName::Real(orig);
}
}
info!("Resolved to {}", target);
let mut target = match target {