Skip to content

Commit 96825a3

Browse files
authored
perf: bring back the symlink optimization (#298)
1 parent edc503c commit 96825a3

File tree

7 files changed

+42
-5
lines changed

7 files changed

+42
-5
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../tooling

fixtures/nested-symlink/apps/web/nm/@repo/index.js

Whitespace-only changes.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../../../../tooling/typescript-config

fixtures/nested-symlink/nm/index.js

Whitespace-only changes.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../../nm/index.js

src/file_system.rs

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -172,34 +172,47 @@ impl FileSystem for FileSystemOs {
172172
}
173173
} else if #[cfg(windows)] {
174174
dunce::canonicalize(path)
175-
} else if #[cfg(target_family = "wasm")] {
175+
} else {
176176
use std::path::Component;
177177
let mut path_buf = path.to_path_buf();
178178
loop {
179179
let link = fs::read_link(&path_buf)?;
180180
path_buf.pop();
181+
if fs::symlink_metadata(&path_buf)?.is_symlink()
182+
{
183+
path_buf = self.canonicalize(path_buf.as_path())?;
184+
}
181185
for component in link.components() {
182186
match component {
183187
Component::ParentDir => {
184188
path_buf.pop();
185189
}
186190
Component::Normal(seg) => {
187-
// Need to trim the extra \0 introduces by https://github.com/nodejs/uvwasi/issues/262
188-
path_buf.push(seg.to_string_lossy().trim_end_matches('\0'));
191+
#[cfg(target_family = "wasm")]
192+
{
193+
// Need to trim the extra \0 introduces by https://github.com/nodejs/uvwasi/issues/262
194+
path_buf.push(seg.to_string_lossy().trim_end_matches('\0'));
195+
}
196+
#[cfg(not(target_family = "wasm"))]
197+
{
198+
path_buf.push(seg);
199+
}
189200
}
190201
Component::RootDir => {
191202
path_buf = PathBuf::from("/");
192203
}
193204
Component::CurDir | Component::Prefix(_) => {}
194205
}
206+
if fs::symlink_metadata(&path_buf)?.is_symlink()
207+
{
208+
path_buf = self.canonicalize(path_buf.as_path())?;
209+
}
195210
}
196211
if !fs::symlink_metadata(&path_buf)?.is_symlink() {
197212
break;
198213
}
199214
}
200215
Ok(path_buf)
201-
} else {
202-
fs::canonicalize(path)
203216
}
204217
}
205218
}

tests/resolve_test.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,3 +184,24 @@ fn decimal_js_from_mathjs() {
184184
assert_eq!(resolution, Ok(module_path.clone()));
185185
}
186186
}
187+
188+
#[test]
189+
// regression: https://github.com/NicholasLYang/oxc-repro
190+
fn nested_symlinks() {
191+
let dir = dir();
192+
let dir = dir.join("fixtures/nested-symlink");
193+
assert_eq!(
194+
Resolver::new(ResolveOptions::default())
195+
// ./apps/web/nm/@repo/typescript-config is a symlink
196+
.resolve(&dir, "./apps/web/nm/@repo/typescript-config/index.js")
197+
.map(oxc_resolver::Resolution::into_path_buf),
198+
Ok(dir.join("nm/index.js"))
199+
);
200+
assert_eq!(
201+
Resolver::new(ResolveOptions::default())
202+
// ./apps/tooling is a symlink
203+
.resolve(&dir, "./apps/tooling/typescript-config/index.js")
204+
.map(oxc_resolver::Resolution::into_path_buf),
205+
Ok(dir.join("nm/index.js"))
206+
);
207+
}

0 commit comments

Comments
 (0)