From 5c2b66e954b189718297c6519a2059e2ba8a5648 Mon Sep 17 00:00:00 2001 From: Boshen Date: Thu, 11 Jul 2024 22:43:31 +0800 Subject: [PATCH] add feature toggle --- Cargo.lock | 1 + Cargo.toml | 6 ++- justfile | 7 ++- src/file_system.rs | 128 +++++++++++++++++++++++++++------------------ src/lib.rs | 8 ++- src/options.rs | 3 ++ src/tests/mod.rs | 1 + 7 files changed, 99 insertions(+), 55 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8ca6ecbc..7f4d764b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -670,6 +670,7 @@ dependencies = [ name = "oxc_resolver" version = "1.9.4" dependencies = [ + "cfg-if", "criterion2", "dashmap", "document-features", diff --git a/Cargo.toml b/Cargo.toml index 0f6b9995..535147ec 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -85,7 +85,9 @@ once_cell = "1.19.0" # Use `std::sync::OnceLock::get_or_try_init` when it is sta thiserror = "1.0.61" json-strip-comments = "1.0.2" indexmap = { version = "2.2.6", features = ["serde"] } -pnp = "0.8.0" +cfg-if = "1.0" + +pnp = { version = "0.8.0", optional = true } document-features = { version = "0.2.8", optional = true } @@ -100,6 +102,8 @@ default = [] ## Enables the [PackageJson::raw_json] API, ## which returns the `package.json` with `serde_json::Value`. package_json_raw_json_api = [] +## [Yarn Plug'n'Play](https://yarnpkg.com/features/pnp) +yarn_pnp = ["pnp"] # For codspeed benchmark codspeed = ["criterion2/codspeed"] diff --git a/justfile b/justfile index ac87868b..1609c10d 100644 --- a/justfile +++ b/justfile @@ -10,9 +10,12 @@ alias r := ready # or install via `cargo install cargo-binstall` # Initialize the project by installing all the necessary tools. init: - pnpm install cargo binstall cargo-watch typos-cli taplo-cli cargo-llvm-cov -y +install: + pnpm install + cd fixtures/pnp && yarn + # When ready, run the same CI commands ready: git diff --exit-code --quiet @@ -44,7 +47,7 @@ check: # Run all the tests test: - cargo test + cargo test --all-features # Lint the whole project lint: diff --git a/src/file_system.rs b/src/file_system.rs index 912403fa..38a9ae5a 100644 --- a/src/file_system.rs +++ b/src/file_system.rs @@ -1,8 +1,10 @@ +use cfg_if::cfg_if; use std::{ fs, io, path::{Component, Path, PathBuf}, }; +#[cfg(feature = "yarn_pnp")] use pnp::fs::{LruZipCache, VPath, VPathInfo, ZipCache}; /// File System abstraction used for `ResolverGeneric` @@ -69,6 +71,7 @@ impl FileMetadata { } } +#[cfg(feature = "yarn_pnp")] impl From for FileMetadata { fn from(value: pnp::fs::FileType) -> Self { Self::new(value == pnp::fs::FileType::File, value == pnp::fs::FileType::Directory, false) @@ -82,35 +85,59 @@ impl From for FileMetadata { } /// Operating System +#[cfg(feature = "yarn_pnp")] pub struct FileSystemOs { - pub pnp_lru: LruZipCache>, + pnp_lru: LruZipCache>, } +#[cfg(not(feature = "yarn_pnp"))] +pub struct FileSystemOs; + impl Default for FileSystemOs { fn default() -> Self { - Self { pnp_lru: LruZipCache::new(50, pnp::fs::open_zip_via_read_p) } + cfg_if! { + if #[cfg(feature = "yarn_pnp")] { + Self { pnp_lru: LruZipCache::new(50, pnp::fs::open_zip_via_read_p) } + } else { + Self + } + } } } impl FileSystem for FileSystemOs { fn read_to_string(&self, path: &Path) -> io::Result { - match VPath::from(path)? { - VPath::Zip(info) => { - self.pnp_lru.read_to_string(info.physical_base_path(), info.zip_path) + cfg_if! { + if #[cfg(feature = "yarn_pnp")] { + match VPath::from(path)? { + VPath::Zip(info) => { + self.pnp_lru.read_to_string(info.physical_base_path(), info.zip_path) + } + VPath::Virtual(info) => fs::read_to_string(info.physical_base_path()), + VPath::Native(path) => fs::read_to_string(path), + } + } else { + fs::read_to_string(path) } - VPath::Virtual(info) => fs::read_to_string(info.physical_base_path()), - VPath::Native(path) => fs::read_to_string(path), } } fn metadata(&self, path: &Path) -> io::Result { - match VPath::from(path)? { - VPath::Zip(info) => self - .pnp_lru - .file_type(info.physical_base_path(), info.zip_path) - .map(FileMetadata::from), - VPath::Virtual(info) => fs::metadata(info.physical_base_path()).map(FileMetadata::from), - VPath::Native(path) => fs::metadata(path).map(FileMetadata::from), + cfg_if! { + if #[cfg(feature = "yarn_pnp")] { + match VPath::from(path)? { + VPath::Zip(info) => self + .pnp_lru + .file_type(info.physical_base_path(), info.zip_path) + .map(FileMetadata::from), + VPath::Virtual(info) => { + fs::metadata(info.physical_base_path()).map(FileMetadata::from) + } + VPath::Native(path) => fs::metadata(path).map(FileMetadata::from), + } + } else { + fs::metadata(path).map(FileMetadata::from) + } } } @@ -119,49 +146,50 @@ impl FileSystem for FileSystemOs { } fn canonicalize(&self, path: &Path) -> io::Result { - #[cfg(target_os = "windows")] - { - match VPath::from(path)? { - VPath::Zip(info) => { - dunce::canonicalize(info.physical_base_path().join(info.zip_path)) + cfg_if! { + if #[cfg(feature = "yarn_pnp")] { + match VPath::from(path)? { + VPath::Zip(info) => { + dunce::canonicalize(info.physical_base_path().join(info.zip_path)) + } + VPath::Virtual(info) => dunce::canonicalize(info.physical_base_path()), + VPath::Native(path) => dunce::canonicalize(path), } - VPath::Virtual(info) => dunce::canonicalize(info.physical_base_path()), - VPath::Native(path) => dunce::canonicalize(path), - } - } - #[cfg(not(target_os = "windows"))] - { - let mut path_buf = path.to_path_buf(); - loop { - let link = fs::read_link(&path_buf)?; - path_buf.pop(); - for component in link.components() { - match component { - Component::ParentDir => { - path_buf.pop(); - } - Component::Normal(seg) => { - #[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')); + } else if #[cfg(windows)] { + dunce::canonicalize(path) + } else { + let mut path_buf = path.to_path_buf(); + loop { + let link = fs::read_link(&path_buf)?; + path_buf.pop(); + for component in link.components() { + match component { + Component::ParentDir => { + path_buf.pop(); } - #[cfg(not(target_family = "wasm"))] - { - path_buf.push(seg); + Component::Normal(seg) => { + #[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(_) => {} } - Component::RootDir => { - path_buf = PathBuf::from("/"); - } - Component::CurDir | Component::Prefix(_) => {} + } + if !fs::symlink_metadata(&path_buf)?.is_symlink() { + break; } } - if !fs::symlink_metadata(&path_buf)?.is_symlink() { - break; - } + Ok(path_buf) } - Ok(path_buf) } } } diff --git a/src/lib.rs b/src/lib.rs index 4453144b..0318f3b3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -677,8 +677,11 @@ impl ResolverGeneric { specifier: &str, ctx: &mut Ctx, ) -> ResolveResult { - if let Some(resolved_path) = self.load_pnp(cached_path, specifier, ctx)? { - return Ok(Some(resolved_path)); + #[cfg(feature = "yarn_pnp")] + { + if let Some(resolved_path) = self.load_pnp(cached_path, specifier, ctx)? { + return Ok(Some(resolved_path)); + } } let (package_name, subpath) = Self::parse_package_specifier(specifier); @@ -740,6 +743,7 @@ impl ResolverGeneric { Ok(None) } + #[cfg(feature = "yarn_pnp")] fn load_pnp( &self, cached_path: &CachedPath, diff --git a/src/options.rs b/src/options.rs index 2a7e2c17..7893890e 100644 --- a/src/options.rs +++ b/src/options.rs @@ -118,6 +118,7 @@ pub struct ResolveOptions { /// A manifest loaded from pnp::load_pnp_manifest. /// /// Default `None` + #[cfg(feature = "yarn_pnp")] pub pnp_manifest: Option, /// Resolve to a context instead of a file. @@ -466,6 +467,7 @@ impl Default for ResolveOptions { main_fields: vec!["main".into()], main_files: vec!["index".into()], modules: vec!["node_modules".into()], + #[cfg(feature = "yarn_pnp")] pnp_manifest: None, resolve_to_context: false, prefer_relative: false, @@ -615,6 +617,7 @@ mod test { main_fields: vec![], main_files: vec![], modules: vec![], + #[cfg(feature = "yarn_pnp")] pnp_manifest: None, prefer_absolute: false, prefer_relative: false, diff --git a/src/tests/mod.rs b/src/tests/mod.rs index 27370d8c..e347dd1f 100644 --- a/src/tests/mod.rs +++ b/src/tests/mod.rs @@ -12,6 +12,7 @@ mod incorrect_description_file; mod main_field; mod memory_fs; mod missing; +#[cfg(feature = "yarn_pnp")] mod pnp; mod resolve; mod restrictions;