From 4132b294ca03685ebe6df7503d05d79b5777b635 Mon Sep 17 00:00:00 2001 From: Boshen Date: Fri, 14 Jul 2023 14:33:00 +0800 Subject: [PATCH] refactor(resolver): add our own path util for normalization --- Cargo.lock | 7 --- crates/oxc_resolver/Cargo.toml | 1 - crates/oxc_resolver/src/lib.rs | 10 ++-- crates/oxc_resolver/src/path.rs | 85 +++++++++++++++++++++++++----- crates/oxc_resolver/src/request.rs | 6 --- 5 files changed, 76 insertions(+), 33 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ab9cb4cbc..b098609cf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1042,12 +1042,6 @@ dependencies = [ "libloading", ] -[[package]] -name = "normalize-path" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5438dd2b2ff4c6df6e1ce22d825ed2fa93ee2922235cc45186991717f0a892d" - [[package]] name = "num-bigint" version = "0.4.3" @@ -1399,7 +1393,6 @@ name = "oxc_resolver" version = "0.0.0" dependencies = [ "criterion", - "normalize-path", "serde", "serde_json", "static_assertions", diff --git a/crates/oxc_resolver/Cargo.toml b/crates/oxc_resolver/Cargo.toml index 104fa0a08..a4cfa2239 100644 --- a/crates/oxc_resolver/Cargo.toml +++ b/crates/oxc_resolver/Cargo.toml @@ -11,7 +11,6 @@ license.workspace = true repository.workspace = true [dependencies] -normalize-path = "0.2.1" serde = { workspace = true, features = ["derive"] } serde_json = { workspace = true } diff --git a/crates/oxc_resolver/src/lib.rs b/crates/oxc_resolver/src/lib.rs index 06c7bd213..4fed807c5 100644 --- a/crates/oxc_resolver/src/lib.rs +++ b/crates/oxc_resolver/src/lib.rs @@ -17,7 +17,7 @@ use std::{ use package_json::PackageJson; pub use crate::error::{JSONError, ResolveError}; -use crate::{path::ResolvePath, request::Request}; +use crate::{path::PathUtil, request::Request}; pub type ResolveResult = Result; type ResolveState = Result, ResolveError>; @@ -40,11 +40,9 @@ impl Resolver { fn resolve_impl(&self, path: &Path, request: &str) -> ResolveResult { let request = Request::try_from(request).map_err(ResolveError::RequestError)?; - let path = ResolvePath::from(path); - match request { - Request::Relative(_) => { - let path = path.join(&request); + Request::Relative(relative_path) => { + let path = path.normalize_with(relative_path); if let Some(path) = self.load_as_file(&path)? { return Ok(path); } @@ -97,7 +95,7 @@ impl Resolver { // b. If "main" is a falsy value, GOTO 2. if let Some(main_field) = &package_json.main { // c. let M = X + (json main field) - let main_field_path = path.join(main_field); + let main_field_path = path.normalize_with(main_field); // d. LOAD_AS_FILE(M) if let Some(path) = self.load_as_file(&main_field_path)? { return Ok(Some(path)); diff --git a/crates/oxc_resolver/src/path.rs b/crates/oxc_resolver/src/path.rs index 5dcedddd7..29f9be047 100644 --- a/crates/oxc_resolver/src/path.rs +++ b/crates/oxc_resolver/src/path.rs @@ -1,19 +1,78 @@ -use std::path::{Path, PathBuf}; +//! Path Utilities +//! +//! Code adapted from the following libraries +//! * [path-absolutize](https://docs.rs/path-absolutize) +//! * [normalize_path]( PathBuf; -use crate::request::Request; - -pub struct ResolvePath<'a>(&'a Path); - -impl<'a> From<&'a Path> for ResolvePath<'a> { - fn from(path: &'a Path) -> Self { - Self(path) - } + /// Normalize with subpath assuming this path is normalized without performing I/O. + /// + /// All redundant separator and up-level references are collapsed. + /// + /// However, this does not resolve links. + fn normalize_with>(&self, subpath: P) -> PathBuf; } -impl<'a> ResolvePath<'a> { - pub fn join(&self, request: &Request) -> PathBuf { - self.0.join(request.as_str()).normalize() +impl PathUtil for Path { + fn normalize(&self) -> PathBuf { + let mut components = self.components().peekable(); + let mut ret = if let Some(c @ Component::Prefix(..)) = components.peek() { + let buf = PathBuf::from(c.as_os_str()); + components.next(); + buf + } else { + PathBuf::new() + }; + + for component in components { + match component { + Component::Prefix(..) => unreachable!(), + Component::RootDir => { + ret.push(component.as_os_str()); + } + Component::CurDir => {} + Component::ParentDir => { + ret.pop(); + } + Component::Normal(c) => { + ret.push(c); + } + } + } + + ret + } + + fn normalize_with>(&self, subpath: B) -> PathBuf { + let subpath = subpath.as_ref(); + let mut components = subpath.components().peekable(); + if subpath.is_absolute() || matches!(components.peek(), Some(Component::Prefix(..))) { + return subpath.to_path_buf(); + } + + let mut ret = self.to_path_buf(); + for component in subpath.components() { + match component { + Component::Prefix(..) | Component::RootDir => unreachable!(), + Component::CurDir => {} + Component::ParentDir => { + ret.pop(); + } + Component::Normal(c) => { + ret.push(c); + } + } + } + + ret } } diff --git a/crates/oxc_resolver/src/request.rs b/crates/oxc_resolver/src/request.rs index 1d1422dfc..8e790462d 100644 --- a/crates/oxc_resolver/src/request.rs +++ b/crates/oxc_resolver/src/request.rs @@ -27,12 +27,6 @@ impl<'a> Request<'a> { _ => Err(RequestError::Empty), } } - - pub fn as_str(&self) -> &str { - match self { - Self::Absolute(s) | Self::Relative(s) => s, - } - } } #[cfg(test)]