diff --git a/cli/factory.rs b/cli/factory.rs index 967ede0486..94bc458a86 100644 --- a/cli/factory.rs +++ b/cli/factory.rs @@ -54,8 +54,7 @@ use deno_runtime::permissions::RuntimePermissionDescriptorParser; use deno_runtime::FeatureChecker; use node_resolver::analyze::NodeCodeTranslator; use node_resolver::cache::NodeResolutionThreadLocalCache; -use node_resolver::ConditionResolver; -use node_resolver::ConditionResolverOptions; +use node_resolver::NodeConditionOptions; use node_resolver::NodeResolverOptions; use once_cell::sync::OnceCell; use sys_traits::EnvCurrentDir; @@ -1212,16 +1211,15 @@ impl CliFactory { IsCjsResolutionMode::Disabled }, node_resolver_options: NodeResolverOptions { - condition_resolver: ConditionResolver::new( - ConditionResolverOptions { - conditions: options - .node_conditions() - .iter() - .map(|c| Cow::Owned(c.clone())) - .collect(), - ..Default::default() - }, - ), + conditions: NodeConditionOptions { + conditions: options + .node_conditions() + .iter() + .map(|c| Cow::Owned(c.clone())) + .collect(), + import_conditions_override: None, + require_conditions_override: None, + }, typescript_version: Some( deno_semver::Version::parse_standard( deno_lib::version::DENO_VERSION_INFO.typescript, diff --git a/cli/lsp/resolver.rs b/cli/lsp/resolver.rs index 90be25626f..4fff91b1e1 100644 --- a/cli/lsp/resolver.rs +++ b/cli/lsp/resolver.rs @@ -1113,7 +1113,7 @@ impl<'a> ResolverFactory<'a> { self.pkg_json_resolver.clone(), self.node_resolution_sys.clone(), NodeResolverOptions { - condition_resolver: Default::default(), + conditions: Default::default(), typescript_version: Some( deno_semver::Version::parse_standard( deno_lib::version::DENO_VERSION_INFO.typescript, diff --git a/resolvers/deno/factory.rs b/resolvers/deno/factory.rs index b0870f46ce..b56f4cfd67 100644 --- a/resolvers/deno/factory.rs +++ b/resolvers/deno/factory.rs @@ -20,7 +20,7 @@ use deno_config::workspace::WorkspaceDirectoryEmptyOptions; use deno_config::workspace::WorkspaceDiscoverError; use deno_config::workspace::WorkspaceDiscoverOptions; use deno_config::workspace::WorkspaceDiscoverStart; -use deno_npm::NpmSystemInfo; +pub use deno_npm::NpmSystemInfo; use deno_path_util::fs::canonicalize_path_maybe_not_exists; use deno_path_util::normalize_path; use futures::future::FutureExt; diff --git a/resolvers/node/lib.rs b/resolvers/node/lib.rs index ebd4577d50..b03f16ac15 100644 --- a/resolvers/node/lib.rs +++ b/resolvers/node/lib.rs @@ -32,8 +32,7 @@ pub use path::UrlOrPathRef; pub use resolution::parse_npm_pkg_name; pub use resolution::resolve_specifier_into_node_modules; pub use resolution::types_package_name; -pub use resolution::ConditionResolver; -pub use resolution::ConditionResolverOptions; +pub use resolution::NodeConditionOptions; pub use resolution::NodeResolution; pub use resolution::NodeResolutionKind; pub use resolution::NodeResolver; @@ -41,5 +40,5 @@ pub use resolution::NodeResolverOptions; pub use resolution::NodeResolverRc; pub use resolution::NodeResolverSys; pub use resolution::ResolutionMode; -pub use resolution::DEFAULT_CONDITIONS; +pub use resolution::IMPORT_CONDITIONS; pub use resolution::REQUIRE_CONDITIONS; diff --git a/resolvers/node/resolution.rs b/resolvers/node/resolution.rs index 009996e0b1..1abddfdffc 100644 --- a/resolvers/node/resolution.rs +++ b/resolvers/node/resolution.rs @@ -61,7 +61,7 @@ use crate::NpmPackageFolderResolver; use crate::PackageJsonResolverRc; use crate::PathClean; -pub static DEFAULT_CONDITIONS: &[Cow<'static, str>] = &[ +pub static IMPORT_CONDITIONS: &[Cow<'static, str>] = &[ Cow::Borrowed("deno"), Cow::Borrowed("node"), Cow::Borrowed("import"), @@ -70,57 +70,62 @@ pub static REQUIRE_CONDITIONS: &[Cow<'static, str>] = &[Cow::Borrowed("require"), Cow::Borrowed("node")]; static TYPES_ONLY_CONDITIONS: &[Cow<'static, str>] = &[Cow::Borrowed("types")]; -#[derive(Debug, Clone)] -pub struct ConditionResolverOptions { +#[derive(Debug, Default, Clone)] +pub struct NodeConditionOptions { pub conditions: Vec>, - pub default_import_conditions: Vec>, - pub default_require_conditions: Vec>, -} - -impl Default for ConditionResolverOptions { - fn default() -> Self { - Self { - conditions: Vec::new(), - default_import_conditions: DEFAULT_CONDITIONS.to_vec(), - default_require_conditions: REQUIRE_CONDITIONS.to_vec(), - } - } + /// Provide a value to override the default import conditions. + /// + /// Defaults to `["deno", "node", "import"]` + pub import_conditions_override: Option>>, + /// Provide a value to override the default require conditions. + /// + /// Defaults to `["require", "node"]` + pub require_conditions_override: Option>>, } #[derive(Debug, Clone)] -pub struct ConditionResolver { - import_conditions: Vec>, - require_conditions: Vec>, -} - -impl Default for ConditionResolver { - fn default() -> Self { - Self::new(Default::default()) - } +struct ConditionResolver { + import_conditions: Cow<'static, [Cow<'static, str>]>, + require_conditions: Cow<'static, [Cow<'static, str>]>, } impl ConditionResolver { - pub fn new(options: ConditionResolverOptions) -> Self { - if options.conditions.is_empty() { - // Fast path for no custom conditions. - return Self { - import_conditions: options.default_import_conditions, - require_conditions: options.default_require_conditions, - }; + pub fn new(options: NodeConditionOptions) -> Self { + fn combine_conditions( + user_conditions: Cow<'_, [Cow<'static, str>]>, + override_default: Option>>, + default_conditions: &'static [Cow<'static, str>], + ) -> Cow<'static, [Cow<'static, str>]> { + if user_conditions.is_empty() { + Cow::Borrowed(default_conditions) + } else { + let default_conditions = override_default + .map(Cow::Owned) + .unwrap_or(Cow::Borrowed(default_conditions)); + let mut new = + Vec::with_capacity(user_conditions.len() + default_conditions.len()); + let mut append = + |conditions: Cow<'_, [Cow<'static, str>]>| match conditions { + Cow::Borrowed(conditions) => new.extend(conditions.iter().cloned()), + Cow::Owned(conditions) => new.extend(conditions), + }; + append(user_conditions); + append(default_conditions); + Cow::Owned(new) + } } + Self { - import_conditions: options - .conditions - .iter() - .chain(&options.default_import_conditions) - .cloned() - .collect(), - require_conditions: options - .conditions - .iter() - .chain(&options.default_require_conditions) - .cloned() - .collect(), + import_conditions: combine_conditions( + Cow::Borrowed(&options.conditions), + options.import_conditions_override, + IMPORT_CONDITIONS, + ), + require_conditions: combine_conditions( + Cow::Owned(options.conditions), + options.require_conditions_override, + REQUIRE_CONDITIONS, + ), } } @@ -144,7 +149,7 @@ pub enum ResolutionMode { impl ResolutionMode { pub fn default_conditions(&self) -> &'static [Cow<'static, str>] { match self { - ResolutionMode::Import => DEFAULT_CONDITIONS, + ResolutionMode::Import => IMPORT_CONDITIONS, ResolutionMode::Require => REQUIRE_CONDITIONS, } } @@ -234,7 +239,7 @@ enum ResolvedMethod { #[derive(Debug, Default, Clone)] pub struct NodeResolverOptions { - pub condition_resolver: ConditionResolver, + pub conditions: NodeConditionOptions, /// TypeScript version to use for typesVersions resolution and /// `types@req` exports resolution. pub typescript_version: Option, @@ -302,7 +307,7 @@ impl< npm_pkg_folder_resolver, pkg_json_resolver, sys, - condition_resolver: options.condition_resolver, + condition_resolver: ConditionResolver::new(options.conditions), typescript_version: options.typescript_version, package_resolution_lookup_cache: None, }