1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2025-01-18 03:44:05 -05:00

refactor: add 'sync' feature to deno_resolver crate (#27357)

This commit is contained in:
Bartek Iwańczuk 2024-12-15 08:18:04 +00:00 committed by GitHub
parent 39f7845d4e
commit 7949f53cab
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 98 additions and 45 deletions

View file

@ -80,7 +80,7 @@ deno_npm.workspace = true
deno_npm_cache.workspace = true deno_npm_cache.workspace = true
deno_package_json.workspace = true deno_package_json.workspace = true
deno_path_util.workspace = true deno_path_util.workspace = true
deno_resolver.workspace = true deno_resolver = { workspace = true, features = ["sync"] }
deno_runtime = { workspace = true, features = ["include_js_files_for_snapshotting"] } deno_runtime = { workspace = true, features = ["include_js_files_for_snapshotting"] }
deno_semver.workspace = true deno_semver.workspace = true
deno_task_shell = "=0.20.2" deno_task_shell = "=0.20.2"

View file

@ -13,11 +13,14 @@ description = "Deno resolution algorithm"
[lib] [lib]
path = "lib.rs" path = "lib.rs"
[features]
sync = ["dashmap"]
[dependencies] [dependencies]
anyhow.workspace = true anyhow.workspace = true
base32.workspace = true base32.workspace = true
boxed_error.workspace = true boxed_error.workspace = true
dashmap.workspace = true dashmap = { workspace = true, optional = true }
deno_config.workspace = true deno_config.workspace = true
deno_media_type.workspace = true deno_media_type.workspace = true
deno_package_json.workspace = true deno_package_json.workspace = true

View file

@ -1,13 +1,11 @@
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
use std::sync::Arc; use crate::sync::MaybeDashMap;
use dashmap::DashMap;
use deno_media_type::MediaType; use deno_media_type::MediaType;
use node_resolver::env::NodeResolverEnv; use node_resolver::env::NodeResolverEnv;
use node_resolver::errors::ClosestPkgJsonError; use node_resolver::errors::ClosestPkgJsonError;
use node_resolver::InNpmPackageChecker; use node_resolver::InNpmPackageCheckerRc;
use node_resolver::PackageJsonResolver; use node_resolver::PackageJsonResolverRc;
use node_resolver::ResolutionMode; use node_resolver::ResolutionMode;
use url::Url; use url::Url;
@ -19,13 +17,13 @@ use url::Url;
#[derive(Debug)] #[derive(Debug)]
pub struct CjsTracker<TEnv: NodeResolverEnv> { pub struct CjsTracker<TEnv: NodeResolverEnv> {
is_cjs_resolver: IsCjsResolver<TEnv>, is_cjs_resolver: IsCjsResolver<TEnv>,
known: DashMap<Url, ResolutionMode>, known: MaybeDashMap<Url, ResolutionMode>,
} }
impl<TEnv: NodeResolverEnv> CjsTracker<TEnv> { impl<TEnv: NodeResolverEnv> CjsTracker<TEnv> {
pub fn new( pub fn new(
in_npm_pkg_checker: Arc<dyn InNpmPackageChecker>, in_npm_pkg_checker: InNpmPackageCheckerRc,
pkg_json_resolver: Arc<PackageJsonResolver<TEnv>>, pkg_json_resolver: PackageJsonResolverRc<TEnv>,
mode: IsCjsResolutionMode, mode: IsCjsResolutionMode,
) -> Self { ) -> Self {
Self { Self {
@ -127,15 +125,15 @@ pub enum IsCjsResolutionMode {
/// Resolves whether a module is CJS or ESM. /// Resolves whether a module is CJS or ESM.
#[derive(Debug)] #[derive(Debug)]
pub struct IsCjsResolver<TEnv: NodeResolverEnv> { pub struct IsCjsResolver<TEnv: NodeResolverEnv> {
in_npm_pkg_checker: Arc<dyn InNpmPackageChecker>, in_npm_pkg_checker: InNpmPackageCheckerRc,
pkg_json_resolver: Arc<PackageJsonResolver<TEnv>>, pkg_json_resolver: PackageJsonResolverRc<TEnv>,
mode: IsCjsResolutionMode, mode: IsCjsResolutionMode,
} }
impl<TEnv: NodeResolverEnv> IsCjsResolver<TEnv> { impl<TEnv: NodeResolverEnv> IsCjsResolver<TEnv> {
pub fn new( pub fn new(
in_npm_pkg_checker: Arc<dyn InNpmPackageChecker>, in_npm_pkg_checker: InNpmPackageCheckerRc,
pkg_json_resolver: Arc<PackageJsonResolver<TEnv>>, pkg_json_resolver: PackageJsonResolverRc<TEnv>,
mode: IsCjsResolutionMode, mode: IsCjsResolutionMode,
) -> Self { ) -> Self {
Self { Self {
@ -185,7 +183,7 @@ impl<TEnv: NodeResolverEnv> IsCjsResolver<TEnv> {
specifier: &Url, specifier: &Url,
media_type: MediaType, media_type: MediaType,
is_script: Option<bool>, is_script: Option<bool>,
known_cache: &DashMap<Url, ResolutionMode>, known_cache: &MaybeDashMap<Url, ResolutionMode>,
) -> Option<ResolutionMode> { ) -> Option<ResolutionMode> {
if specifier.scheme() != "file" { if specifier.scheme() != "file" {
return Some(ResolutionMode::Import); return Some(ResolutionMode::Import);

View file

@ -47,6 +47,5 @@ disallowed-methods = [
{ path = "url::Url::from_directory_path", reason = "Use deno_path_util instead so it works in Wasm" }, { path = "url::Url::from_directory_path", reason = "Use deno_path_util instead so it works in Wasm" },
] ]
disallowed-types = [ disallowed-types = [
# todo(dsherret): consider for the future { path = "std::sync::Arc", reason = "use crate::sync::MaybeArc instead" },
# { path = "std::sync::Arc", reason = "use crate::sync::MaybeArc instead" },
] ]

View file

@ -4,7 +4,6 @@
#![deny(clippy::print_stdout)] #![deny(clippy::print_stdout)]
use std::path::PathBuf; use std::path::PathBuf;
use std::sync::Arc;
use boxed_error::Boxed; use boxed_error::Boxed;
use deno_config::workspace::MappedResolution; use deno_config::workspace::MappedResolution;
@ -19,20 +18,20 @@ use fs::DenoResolverFs;
use node_resolver::env::NodeResolverEnv; use node_resolver::env::NodeResolverEnv;
use node_resolver::errors::NodeResolveError; use node_resolver::errors::NodeResolveError;
use node_resolver::errors::PackageSubpathResolveError; use node_resolver::errors::PackageSubpathResolveError;
use node_resolver::InNpmPackageChecker; use node_resolver::InNpmPackageCheckerRc;
use node_resolver::NodeResolution; use node_resolver::NodeResolution;
use node_resolver::NodeResolutionKind; use node_resolver::NodeResolutionKind;
use node_resolver::NodeResolver; use node_resolver::NodeResolverRc;
use node_resolver::ResolutionMode; use node_resolver::ResolutionMode;
use npm::MissingPackageNodeModulesFolderError; use npm::MissingPackageNodeModulesFolderError;
use npm::NodeModulesOutOfDateError; use npm::NodeModulesOutOfDateError;
use npm::NpmReqResolver; use npm::NpmReqResolverRc;
use npm::ResolveIfForNpmPackageErrorKind; use npm::ResolveIfForNpmPackageErrorKind;
use npm::ResolvePkgFolderFromDenoReqError; use npm::ResolvePkgFolderFromDenoReqError;
use npm::ResolveReqWithSubPathErrorKind; use npm::ResolveReqWithSubPathErrorKind;
use sloppy_imports::SloppyImportResolverFs; use sloppy_imports::SloppyImportResolverFs;
use sloppy_imports::SloppyImportsResolutionKind; use sloppy_imports::SloppyImportsResolutionKind;
use sloppy_imports::SloppyImportsResolver; use sloppy_imports::SloppyImportsResolverRc;
use thiserror::Error; use thiserror::Error;
use url::Url; use url::Url;
@ -40,6 +39,10 @@ pub mod cjs;
pub mod fs; pub mod fs;
pub mod npm; pub mod npm;
pub mod sloppy_imports; pub mod sloppy_imports;
mod sync;
#[allow(clippy::disallowed_types)]
pub type WorkspaceResolverRc = crate::sync::MaybeArc<WorkspaceResolver>;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct DenoResolution { pub struct DenoResolution {
@ -80,8 +83,8 @@ pub struct NodeAndNpmReqResolver<
Fs: DenoResolverFs, Fs: DenoResolverFs,
TNodeResolverEnv: NodeResolverEnv, TNodeResolverEnv: NodeResolverEnv,
> { > {
pub node_resolver: Arc<NodeResolver<TNodeResolverEnv>>, pub node_resolver: NodeResolverRc<TNodeResolverEnv>,
pub npm_req_resolver: Arc<NpmReqResolver<Fs, TNodeResolverEnv>>, pub npm_req_resolver: NpmReqResolverRc<Fs, TNodeResolverEnv>,
} }
pub struct DenoResolverOptions< pub struct DenoResolverOptions<
@ -90,12 +93,12 @@ pub struct DenoResolverOptions<
TNodeResolverEnv: NodeResolverEnv, TNodeResolverEnv: NodeResolverEnv,
TSloppyImportResolverFs: SloppyImportResolverFs, TSloppyImportResolverFs: SloppyImportResolverFs,
> { > {
pub in_npm_pkg_checker: Arc<dyn InNpmPackageChecker>, pub in_npm_pkg_checker: InNpmPackageCheckerRc,
pub node_and_req_resolver: pub node_and_req_resolver:
Option<NodeAndNpmReqResolver<Fs, TNodeResolverEnv>>, Option<NodeAndNpmReqResolver<Fs, TNodeResolverEnv>>,
pub sloppy_imports_resolver: pub sloppy_imports_resolver:
Option<Arc<SloppyImportsResolver<TSloppyImportResolverFs>>>, Option<SloppyImportsResolverRc<TSloppyImportResolverFs>>,
pub workspace_resolver: Arc<WorkspaceResolver>, pub workspace_resolver: WorkspaceResolverRc,
/// Whether "bring your own node_modules" is enabled where Deno does not /// Whether "bring your own node_modules" is enabled where Deno does not
/// setup the node_modules directories automatically, but instead uses /// setup the node_modules directories automatically, but instead uses
/// what already exists on the file system. /// what already exists on the file system.
@ -111,11 +114,11 @@ pub struct DenoResolver<
TNodeResolverEnv: NodeResolverEnv, TNodeResolverEnv: NodeResolverEnv,
TSloppyImportResolverFs: SloppyImportResolverFs, TSloppyImportResolverFs: SloppyImportResolverFs,
> { > {
in_npm_pkg_checker: Arc<dyn InNpmPackageChecker>, in_npm_pkg_checker: InNpmPackageCheckerRc,
node_and_npm_resolver: Option<NodeAndNpmReqResolver<Fs, TNodeResolverEnv>>, node_and_npm_resolver: Option<NodeAndNpmReqResolver<Fs, TNodeResolverEnv>>,
sloppy_imports_resolver: sloppy_imports_resolver:
Option<Arc<SloppyImportsResolver<TSloppyImportResolverFs>>>, Option<SloppyImportsResolverRc<TSloppyImportResolverFs>>,
workspace_resolver: Arc<WorkspaceResolver>, workspace_resolver: WorkspaceResolverRc,
is_byonm: bool, is_byonm: bool,
maybe_vendor_specifier: Option<Url>, maybe_vendor_specifier: Option<Url>,
} }

View file

@ -3,10 +3,10 @@
use std::borrow::Cow; use std::borrow::Cow;
use std::path::Path; use std::path::Path;
use std::path::PathBuf; use std::path::PathBuf;
use std::sync::Arc;
use deno_package_json::PackageJson; use deno_package_json::PackageJson;
use deno_package_json::PackageJsonDepValue; use deno_package_json::PackageJsonDepValue;
use deno_package_json::PackageJsonRc;
use deno_path_util::url_to_file_path; use deno_path_util::url_to_file_path;
use deno_semver::package::PackageReq; use deno_semver::package::PackageReq;
use deno_semver::Version; use deno_semver::Version;
@ -49,6 +49,10 @@ pub struct ByonmNpmResolverCreateOptions<
pub pkg_json_resolver: PackageJsonResolverRc<TEnv>, pub pkg_json_resolver: PackageJsonResolverRc<TEnv>,
} }
#[allow(clippy::disallowed_types)]
pub type ByonmNpmResolverRc<Fs, TEnv> =
crate::sync::MaybeArc<ByonmNpmResolver<Fs, TEnv>>;
#[derive(Debug)] #[derive(Debug)]
pub struct ByonmNpmResolver<Fs: DenoResolverFs, TEnv: NodeResolverEnv> { pub struct ByonmNpmResolver<Fs: DenoResolverFs, TEnv: NodeResolverEnv> {
fs: Fs, fs: Fs,
@ -84,7 +88,7 @@ impl<Fs: DenoResolverFs, TEnv: NodeResolverEnv> ByonmNpmResolver<Fs, TEnv> {
fn load_pkg_json( fn load_pkg_json(
&self, &self,
path: &Path, path: &Path,
) -> Result<Option<Arc<PackageJson>>, PackageJsonLoadError> { ) -> Result<Option<PackageJsonRc>, PackageJsonLoadError> {
self.pkg_json_resolver.load_package_json(path) self.pkg_json_resolver.load_package_json(path)
} }
@ -93,7 +97,7 @@ impl<Fs: DenoResolverFs, TEnv: NodeResolverEnv> ByonmNpmResolver<Fs, TEnv> {
&self, &self,
dep_name: &str, dep_name: &str,
referrer: &Url, referrer: &Url,
) -> Option<Arc<PackageJson>> { ) -> Option<PackageJsonRc> {
let referrer_path = url_to_file_path(referrer).ok()?; let referrer_path = url_to_file_path(referrer).ok()?;
let mut current_folder = referrer_path.parent()?; let mut current_folder = referrer_path.parent()?;
loop { loop {
@ -173,7 +177,7 @@ impl<Fs: DenoResolverFs, TEnv: NodeResolverEnv> ByonmNpmResolver<Fs, TEnv> {
&self, &self,
req: &PackageReq, req: &PackageReq,
referrer: &Url, referrer: &Url,
) -> Result<Option<(Arc<PackageJson>, String)>, PackageJsonLoadError> { ) -> Result<Option<(PackageJsonRc, String)>, PackageJsonLoadError> {
fn resolve_alias_from_pkg_json( fn resolve_alias_from_pkg_json(
req: &PackageReq, req: &PackageReq,
pkg_json: &PackageJson, pkg_json: &PackageJson,

View file

@ -2,7 +2,6 @@
use std::fmt::Debug; use std::fmt::Debug;
use std::path::PathBuf; use std::path::PathBuf;
use std::sync::Arc;
use boxed_error::Boxed; use boxed_error::Boxed;
use deno_semver::npm::NpmPackageReqReference; use deno_semver::npm::NpmPackageReqReference;
@ -15,10 +14,10 @@ use node_resolver::errors::PackageFolderResolveIoError;
use node_resolver::errors::PackageNotFoundError; use node_resolver::errors::PackageNotFoundError;
use node_resolver::errors::PackageResolveErrorKind; use node_resolver::errors::PackageResolveErrorKind;
use node_resolver::errors::PackageSubpathResolveError; use node_resolver::errors::PackageSubpathResolveError;
use node_resolver::InNpmPackageChecker; use node_resolver::InNpmPackageCheckerRc;
use node_resolver::NodeResolution; use node_resolver::NodeResolution;
use node_resolver::NodeResolutionKind; use node_resolver::NodeResolutionKind;
use node_resolver::NodeResolver; use node_resolver::NodeResolverRc;
use node_resolver::ResolutionMode; use node_resolver::ResolutionMode;
use thiserror::Error; use thiserror::Error;
use url::Url; use url::Url;
@ -28,6 +27,7 @@ use crate::fs::DenoResolverFs;
pub use byonm::ByonmInNpmPackageChecker; pub use byonm::ByonmInNpmPackageChecker;
pub use byonm::ByonmNpmResolver; pub use byonm::ByonmNpmResolver;
pub use byonm::ByonmNpmResolverCreateOptions; pub use byonm::ByonmNpmResolverCreateOptions;
pub use byonm::ByonmNpmResolverRc;
pub use byonm::ByonmResolvePkgFolderFromDenoReqError; pub use byonm::ByonmResolvePkgFolderFromDenoReqError;
pub use local::normalize_pkg_name_for_node_modules_deno_folder; pub use local::normalize_pkg_name_for_node_modules_deno_folder;
@ -81,6 +81,9 @@ pub enum ResolvePkgFolderFromDenoReqError {
Byonm(#[from] ByonmResolvePkgFolderFromDenoReqError), Byonm(#[from] ByonmResolvePkgFolderFromDenoReqError),
} }
#[allow(clippy::disallowed_types)]
pub type CliNpmReqResolverRc = crate::sync::MaybeArc<dyn CliNpmReqResolver>;
// todo(dsherret): a temporary trait until we extract // todo(dsherret): a temporary trait until we extract
// out the CLI npm resolver into here // out the CLI npm resolver into here
pub trait CliNpmReqResolver: Debug + Send + Sync { pub trait CliNpmReqResolver: Debug + Send + Sync {
@ -98,21 +101,25 @@ pub struct NpmReqResolverOptions<
/// The resolver when "bring your own node_modules" is enabled where Deno /// The resolver when "bring your own node_modules" is enabled where Deno
/// does not setup the node_modules directories automatically, but instead /// does not setup the node_modules directories automatically, but instead
/// uses what already exists on the file system. /// uses what already exists on the file system.
pub byonm_resolver: Option<Arc<ByonmNpmResolver<Fs, TNodeResolverEnv>>>, pub byonm_resolver: Option<ByonmNpmResolverRc<Fs, TNodeResolverEnv>>,
pub fs: Fs, pub fs: Fs,
pub in_npm_pkg_checker: Arc<dyn InNpmPackageChecker>, pub in_npm_pkg_checker: InNpmPackageCheckerRc,
pub node_resolver: Arc<NodeResolver<TNodeResolverEnv>>, pub node_resolver: NodeResolverRc<TNodeResolverEnv>,
pub npm_req_resolver: Arc<dyn CliNpmReqResolver>, pub npm_req_resolver: CliNpmReqResolverRc,
} }
#[allow(clippy::disallowed_types)]
pub type NpmReqResolverRc<Fs, TNodeResolverEnv> =
crate::sync::MaybeArc<NpmReqResolver<Fs, TNodeResolverEnv>>;
#[derive(Debug)] #[derive(Debug)]
pub struct NpmReqResolver<Fs: DenoResolverFs, TNodeResolverEnv: NodeResolverEnv> pub struct NpmReqResolver<Fs: DenoResolverFs, TNodeResolverEnv: NodeResolverEnv>
{ {
byonm_resolver: Option<Arc<ByonmNpmResolver<Fs, TNodeResolverEnv>>>, byonm_resolver: Option<ByonmNpmResolverRc<Fs, TNodeResolverEnv>>,
fs: Fs, fs: Fs,
in_npm_pkg_checker: Arc<dyn InNpmPackageChecker>, in_npm_pkg_checker: InNpmPackageCheckerRc,
node_resolver: Arc<NodeResolver<TNodeResolverEnv>>, node_resolver: NodeResolverRc<TNodeResolverEnv>,
npm_resolver: Arc<dyn CliNpmReqResolver>, npm_resolver: CliNpmReqResolverRc,
} }
impl<Fs: DenoResolverFs, TNodeResolverEnv: NodeResolverEnv> impl<Fs: DenoResolverFs, TNodeResolverEnv: NodeResolverEnv>

View file

@ -101,6 +101,10 @@ pub trait SloppyImportResolverFs {
} }
} }
#[allow(clippy::disallowed_types)]
pub type SloppyImportsResolverRc<TSloppyImportResolverFs> =
crate::sync::MaybeArc<SloppyImportsResolver<TSloppyImportResolverFs>>;
#[derive(Debug)] #[derive(Debug)]
pub struct SloppyImportsResolver<Fs: SloppyImportResolverFs> { pub struct SloppyImportsResolver<Fs: SloppyImportResolverFs> {
fs: Fs, fs: Fs,

34
resolvers/deno/sync.rs Normal file
View file

@ -0,0 +1,34 @@
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
pub use inner::*;
#[cfg(feature = "sync")]
mod inner {
#![allow(clippy::disallowed_types)]
pub use std::sync::Arc as MaybeArc;
pub use dashmap::DashMap as MaybeDashMap;
}
#[cfg(not(feature = "sync"))]
mod inner {
use std::hash::RandomState;
pub use std::rc::Rc as MaybeArc;
// Wrapper struct that exposes a subset of `DashMap` API.
#[derive(Default)]
struct MaybeDashMap<K, V, S = RandomState>(RefCell<HashMap<K, V, S>>);
impl MaybeDashMap<K, V, S> {
pub fn get(&'a self, key: &K) -> Option<&'a V> {
let inner = self.0.borrow();
inner.get(key)
}
pub fn insert(&self, key: K, value: V) -> Option<V> {
let inner = self.0.borrow_mut();
inner.insert(key, value)
}
}
}

View file

@ -26,6 +26,7 @@ pub use resolution::resolve_specifier_into_node_modules;
pub use resolution::NodeResolution; pub use resolution::NodeResolution;
pub use resolution::NodeResolutionKind; pub use resolution::NodeResolutionKind;
pub use resolution::NodeResolver; pub use resolution::NodeResolver;
pub use resolution::NodeResolverRc;
pub use resolution::ResolutionMode; pub use resolution::ResolutionMode;
pub use resolution::DEFAULT_CONDITIONS; pub use resolution::DEFAULT_CONDITIONS;
pub use resolution::REQUIRE_CONDITIONS; pub use resolution::REQUIRE_CONDITIONS;