refactor(resolver): add our own path util for normalization

This commit is contained in:
Boshen 2023-07-14 14:33:00 +08:00
parent d92c834956
commit 4132b294ca
No known key found for this signature in database
GPG key ID: A69211CB52CC6548
5 changed files with 76 additions and 33 deletions

7
Cargo.lock generated
View file

@ -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",

View file

@ -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 }

View file

@ -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<PathBuf, ResolveError>;
type ResolveState = Result<Option<PathBuf>, 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));

View file

@ -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](<https://docs.rs/normalize-path)
use std::path::{Component, Path, PathBuf};
use normalize_path::NormalizePath;
/// Extension trait to add path normalization to std's [`Path`].
pub trait PathUtil {
/// Normalize this path without performing I/O.
///
/// All redundant separator and up-level references are collapsed.
///
/// However, this does not resolve links.
fn normalize(&self) -> 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<P: AsRef<Path>>(&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<B: AsRef<Self>>(&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
}
}

View file

@ -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)]