mirror of
https://github.com/danbulant/oxc
synced 2026-05-24 20:32:10 +00:00
refactor(resolver): add our own path util for normalization
This commit is contained in:
parent
d92c834956
commit
4132b294ca
5 changed files with 76 additions and 33 deletions
7
Cargo.lock
generated
7
Cargo.lock
generated
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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 }
|
||||
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)]
|
||||
|
|
|
|||
Loading…
Reference in a new issue