From ce4f69917154f01a1156550e6e66cf6bc0dc1b2a Mon Sep 17 00:00:00 2001 From: LongYinan Date: Fri, 8 Nov 2024 14:28:42 +0800 Subject: [PATCH] perf: bring back the symlink optimization --- fixtures/nested-symlink/apps/tooling | 1 + .../nested-symlink/apps/web/nm/@repo/index.js | 0 .../apps/web/nm/@repo/typescript-config | 1 + fixtures/nested-symlink/nm/index.js | 0 .../tooling/typescript-config/index.js | 1 + src/file_system.rs | 23 +++++++++++++++---- tests/resolve_test.rs | 21 +++++++++++++++++ 7 files changed, 42 insertions(+), 5 deletions(-) create mode 120000 fixtures/nested-symlink/apps/tooling create mode 100644 fixtures/nested-symlink/apps/web/nm/@repo/index.js create mode 120000 fixtures/nested-symlink/apps/web/nm/@repo/typescript-config create mode 100644 fixtures/nested-symlink/nm/index.js create mode 120000 fixtures/nested-symlink/tooling/typescript-config/index.js diff --git a/fixtures/nested-symlink/apps/tooling b/fixtures/nested-symlink/apps/tooling new file mode 120000 index 00000000..6da2dcaa --- /dev/null +++ b/fixtures/nested-symlink/apps/tooling @@ -0,0 +1 @@ +../tooling \ No newline at end of file diff --git a/fixtures/nested-symlink/apps/web/nm/@repo/index.js b/fixtures/nested-symlink/apps/web/nm/@repo/index.js new file mode 100644 index 00000000..e69de29b diff --git a/fixtures/nested-symlink/apps/web/nm/@repo/typescript-config b/fixtures/nested-symlink/apps/web/nm/@repo/typescript-config new file mode 120000 index 00000000..db36eabb --- /dev/null +++ b/fixtures/nested-symlink/apps/web/nm/@repo/typescript-config @@ -0,0 +1 @@ +../../../../tooling/typescript-config \ No newline at end of file diff --git a/fixtures/nested-symlink/nm/index.js b/fixtures/nested-symlink/nm/index.js new file mode 100644 index 00000000..e69de29b diff --git a/fixtures/nested-symlink/tooling/typescript-config/index.js b/fixtures/nested-symlink/tooling/typescript-config/index.js new file mode 120000 index 00000000..5f339dec --- /dev/null +++ b/fixtures/nested-symlink/tooling/typescript-config/index.js @@ -0,0 +1 @@ +../../nm/index.js \ No newline at end of file diff --git a/src/file_system.rs b/src/file_system.rs index 3d28bc1f..0ba7da73 100644 --- a/src/file_system.rs +++ b/src/file_system.rs @@ -172,34 +172,47 @@ impl FileSystem for FileSystemOs { } } else if #[cfg(windows)] { dunce::canonicalize(path) - } else if #[cfg(target_family = "wasm")] { + } else { use std::path::Component; let mut path_buf = path.to_path_buf(); loop { let link = fs::read_link(&path_buf)?; path_buf.pop(); + if fs::symlink_metadata(&path_buf)?.is_symlink() + { + path_buf = self.canonicalize(path_buf.as_path())?; + } for component in link.components() { match component { Component::ParentDir => { path_buf.pop(); } Component::Normal(seg) => { - // Need to trim the extra \0 introduces by https://github.com/nodejs/uvwasi/issues/262 - path_buf.push(seg.to_string_lossy().trim_end_matches('\0')); + #[cfg(target_family = "wasm")] + { + // Need to trim the extra \0 introduces by https://github.com/nodejs/uvwasi/issues/262 + path_buf.push(seg.to_string_lossy().trim_end_matches('\0')); + } + #[cfg(not(target_family = "wasm"))] + { + path_buf.push(seg); + } } Component::RootDir => { path_buf = PathBuf::from("/"); } Component::CurDir | Component::Prefix(_) => {} } + if fs::symlink_metadata(&path_buf)?.is_symlink() + { + path_buf = self.canonicalize(path_buf.as_path())?; + } } if !fs::symlink_metadata(&path_buf)?.is_symlink() { break; } } Ok(path_buf) - } else { - fs::canonicalize(path) } } } diff --git a/tests/resolve_test.rs b/tests/resolve_test.rs index 7ce9cde2..3c250569 100644 --- a/tests/resolve_test.rs +++ b/tests/resolve_test.rs @@ -184,3 +184,24 @@ fn decimal_js_from_mathjs() { assert_eq!(resolution, Ok(module_path.clone())); } } + +#[test] +// regression: https://github.com/NicholasLYang/oxc-repro +fn nested_symlinks() { + let dir = dir(); + let dir = dir.join("fixtures/nested-symlink"); + assert_eq!( + Resolver::new(ResolveOptions::default()) + // ./apps/web/nm/@repo/typescript-config is a symlink + .resolve(&dir, "./apps/web/nm/@repo/typescript-config/index.js") + .map(oxc_resolver::Resolution::into_path_buf), + Ok(dir.join("nm/index.js")) + ); + assert_eq!( + Resolver::new(ResolveOptions::default()) + // ./apps/tooling is a symlink + .resolve(&dir, "./apps/tooling/typescript-config/index.js") + .map(oxc_resolver::Resolution::into_path_buf), + Ok(dir.join("nm/index.js")) + ); +}