From 714b40262e0f9bc7e1a98e76f6e211012b161706 Mon Sep 17 00:00:00 2001 From: Benjamin Swerdlow Date: Mon, 13 Jan 2025 08:34:37 -0800 Subject: [PATCH] refactor(node_resolver): make conditions_from_resolution_mode configurable (#27596) --- cli/factory.rs | 1 + cli/lsp/resolver.rs | 1 + cli/standalone/mod.rs | 1 + resolvers/node/lib.rs | 2 + resolvers/node/resolution.rs | 75 +++++++++++++++++++++++++++++++----- 5 files changed, 70 insertions(+), 10 deletions(-) diff --git a/cli/factory.rs b/cli/factory.rs index 5cc99830bc..25a39cae8b 100644 --- a/cli/factory.rs +++ b/cli/factory.rs @@ -670,6 +670,7 @@ impl CliFactory { .into_npm_pkg_folder_resolver(), self.pkg_json_resolver().clone(), self.sys(), + node_resolver::ConditionsFromResolutionMode::default(), ))) } .boxed_local(), diff --git a/cli/lsp/resolver.rs b/cli/lsp/resolver.rs index 57ef2e6a3c..d7f7e684a9 100644 --- a/cli/lsp/resolver.rs +++ b/cli/lsp/resolver.rs @@ -783,6 +783,7 @@ impl<'a> ResolverFactory<'a> { npm_resolver.clone().into_npm_pkg_folder_resolver(), self.pkg_json_resolver.clone(), self.sys.clone(), + node_resolver::ConditionsFromResolutionMode::default(), ))) }) .as_ref() diff --git a/cli/standalone/mod.rs b/cli/standalone/mod.rs index 961e8d6b51..ff38912a89 100644 --- a/cli/standalone/mod.rs +++ b/cli/standalone/mod.rs @@ -833,6 +833,7 @@ pub async fn run( npm_resolver.clone().into_npm_pkg_folder_resolver(), pkg_json_resolver.clone(), sys.clone(), + node_resolver::ConditionsFromResolutionMode::default(), )); let cjs_tracker = Arc::new(CjsTracker::new( in_npm_pkg_checker.clone(), diff --git a/resolvers/node/lib.rs b/resolvers/node/lib.rs index 7d8c98eafc..faee4f1645 100644 --- a/resolvers/node/lib.rs +++ b/resolvers/node/lib.rs @@ -9,6 +9,7 @@ mod npm; mod package_json; mod path; mod resolution; + mod sync; pub use deno_package_json::PackageJson; @@ -22,6 +23,7 @@ pub use package_json::PackageJsonThreadLocalCache; pub use path::PathClean; pub use resolution::parse_npm_pkg_name; pub use resolution::resolve_specifier_into_node_modules; +pub use resolution::ConditionsFromResolutionMode; pub use resolution::IsBuiltInNodeModuleChecker; pub use resolution::NodeResolution; pub use resolution::NodeResolutionKind; diff --git a/resolvers/node/resolution.rs b/resolvers/node/resolution.rs index d0b52213f3..a60a6bec9e 100644 --- a/resolvers/node/resolution.rs +++ b/resolvers/node/resolution.rs @@ -1,6 +1,7 @@ // Copyright 2018-2025 the Deno authors. MIT license. use std::borrow::Cow; +use std::fmt::Debug; use std::path::Path; use std::path::PathBuf; @@ -54,12 +55,32 @@ pub static DEFAULT_CONDITIONS: &[&str] = &["deno", "node", "import"]; pub static REQUIRE_CONDITIONS: &[&str] = &["require", "node"]; static TYPES_ONLY_CONDITIONS: &[&str] = &["types"]; -fn conditions_from_resolution_mode( - resolution_mode: ResolutionMode, -) -> &'static [&'static str] { - match resolution_mode { - ResolutionMode::Import => DEFAULT_CONDITIONS, - ResolutionMode::Require => REQUIRE_CONDITIONS, +type ConditionsFromResolutionModeFn = Box< + dyn Fn(ResolutionMode) -> &'static [&'static str] + Send + Sync + 'static, +>; + +#[derive(Default)] +pub struct ConditionsFromResolutionMode(Option); + +impl Debug for ConditionsFromResolutionMode { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("ConditionsFromResolutionMode").finish() + } +} + +impl ConditionsFromResolutionMode { + pub fn new(func: ConditionsFromResolutionModeFn) -> Self { + Self(Some(func)) + } + + fn resolve( + &self, + resolution_mode: ResolutionMode, + ) -> &'static [&'static str] { + match &self.0 { + Some(func) => func(ResolutionMode::Import), + None => resolution_mode.default_conditions(), + } } } @@ -69,6 +90,15 @@ pub enum ResolutionMode { Require, } +impl ResolutionMode { + pub fn default_conditions(&self) -> &'static [&'static str] { + match self { + ResolutionMode::Import => DEFAULT_CONDITIONS, + ResolutionMode::Require => REQUIRE_CONDITIONS, + } + } +} + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum NodeResolutionKind { Execution, @@ -120,6 +150,7 @@ pub struct NodeResolver< npm_pkg_folder_resolver: NpmPackageFolderResolverRc, pkg_json_resolver: PackageJsonResolverRc, sys: TSys, + conditions_from_resolution_mode: ConditionsFromResolutionMode, } impl< @@ -133,6 +164,7 @@ impl< npm_pkg_folder_resolver: NpmPackageFolderResolverRc, pkg_json_resolver: PackageJsonResolverRc, sys: TSys, + conditions_from_resolution_mode: ConditionsFromResolutionMode, ) -> Self { Self { in_npm_pkg_checker, @@ -140,6 +172,7 @@ impl< npm_pkg_folder_resolver, pkg_json_resolver, sys, + conditions_from_resolution_mode, } } @@ -197,11 +230,14 @@ impl< } } + let conditions = self + .conditions_from_resolution_mode + .resolve(resolution_mode); let url = self.module_resolve( specifier, referrer, resolution_mode, - conditions_from_resolution_mode(resolution_mode), + conditions, resolution_kind, )?; @@ -211,6 +247,7 @@ impl< &file_path, Some(referrer), resolution_mode, + conditions, )? } else { url @@ -343,7 +380,9 @@ impl< &package_subpath, maybe_referrer, resolution_mode, - conditions_from_resolution_mode(resolution_mode), + self + .conditions_from_resolution_mode + .resolve(resolution_mode), resolution_kind, )?; // TODO(bartlomieju): skipped checking errors for commonJS resolution and @@ -411,6 +450,7 @@ impl< path: &Path, maybe_referrer: Option<&Url>, resolution_mode: ResolutionMode, + conditions: &[&str], ) -> Result { fn probe_extensions( sys: &TSys, @@ -474,7 +514,7 @@ impl< /* sub path */ ".", maybe_referrer, resolution_mode, - conditions_from_resolution_mode(resolution_mode), + conditions, NodeResolutionKind::Types, ); if let Ok(resolution) = resolution_result { @@ -855,6 +895,7 @@ impl< &path, maybe_referrer, resolution_mode, + conditions, )?)); } else { return Ok(Some(url)); @@ -1212,6 +1253,7 @@ impl< package_subpath, maybe_referrer, resolution_mode, + conditions, resolution_kind, ) .map_err(|err| { @@ -1249,6 +1291,7 @@ impl< package_json, referrer, resolution_mode, + conditions, resolution_kind, ) .map_err(|err| { @@ -1268,6 +1311,7 @@ impl< package_json, referrer, resolution_mode, + conditions, resolution_kind, ) .map_err(|err| { @@ -1281,6 +1325,7 @@ impl< package_subpath, referrer, resolution_mode, + conditions, resolution_kind, ) .map_err(|err| { @@ -1294,12 +1339,18 @@ impl< package_subpath: &str, referrer: Option<&Url>, resolution_mode: ResolutionMode, + conditions: &[&str], resolution_kind: NodeResolutionKind, ) -> Result { assert_ne!(package_subpath, "."); let file_path = directory.join(package_subpath); if resolution_kind.is_types() { - Ok(self.path_to_declaration_url(&file_path, referrer, resolution_mode)?) + Ok(self.path_to_declaration_url( + &file_path, + referrer, + resolution_mode, + conditions, + )?) } else { Ok(url_from_file_path(&file_path).unwrap()) } @@ -1311,6 +1362,7 @@ impl< package_subpath: &str, maybe_referrer: Option<&Url>, resolution_mode: ResolutionMode, + conditions: &[&str], resolution_kind: NodeResolutionKind, ) -> Result { if package_subpath == "." { @@ -1327,6 +1379,7 @@ impl< package_subpath, maybe_referrer, resolution_mode, + conditions, resolution_kind, ) .map_err(|err| err.into()) @@ -1338,6 +1391,7 @@ impl< package_json: &PackageJson, maybe_referrer: Option<&Url>, resolution_mode: ResolutionMode, + conditions: &[&str], resolution_kind: NodeResolutionKind, ) -> Result { let pkg_json_kind = match resolution_mode { @@ -1356,6 +1410,7 @@ impl< &main, maybe_referrer, resolution_mode, + conditions, ); // don't surface errors, fallback to checking the index now if let Ok(url) = decl_url_result {