diff options
author | David Sherret <dsherret@users.noreply.github.com> | 2023-05-10 20:06:59 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-05-10 20:06:59 -0400 |
commit | 28aa489de9cd4f995ec2fc02e2c9d224e89f4c01 (patch) | |
tree | b316937a47fe9c8f9f6768bc13b9a686c07cf42f /cli/resolver.rs | |
parent | 5fd74bfa1c5ed514c3e19fdb2e8590fe251d3ee6 (diff) |
feat(compile): unstable npm and node specifier support (#19005)
This is the initial support for npm and node specifiers in `deno
compile`. The npm packages are included in the binary and read from it via
a virtual file system. This also supports the `--node-modules-dir` flag,
dependencies specified in a package.json, and npm binary commands (ex.
`deno compile --unstable npm:cowsay`)
Closes #16632
Diffstat (limited to 'cli/resolver.rs')
-rw-r--r-- | cli/resolver.rs | 116 |
1 files changed, 91 insertions, 25 deletions
diff --git a/cli/resolver.rs b/cli/resolver.rs index 113a06fe7..7f49116f4 100644 --- a/cli/resolver.rs +++ b/cli/resolver.rs @@ -20,16 +20,86 @@ use std::sync::Arc; use crate::args::package_json::PackageJsonDeps; use crate::args::JsxImportSourceConfig; +use crate::args::PackageJsonDepsProvider; use crate::npm::CliNpmRegistryApi; use crate::npm::NpmResolution; use crate::npm::PackageJsonDepsInstaller; use crate::util::sync::AtomicFlag; +/// Result of checking if a specifier is mapped via +/// an import map or package.json. +pub enum MappedResolution { + None, + PackageJson(ModuleSpecifier), + ImportMap(ModuleSpecifier), +} + +impl MappedResolution { + pub fn into_specifier(self) -> Option<ModuleSpecifier> { + match self { + MappedResolution::None => Option::None, + MappedResolution::PackageJson(specifier) => Some(specifier), + MappedResolution::ImportMap(specifier) => Some(specifier), + } + } +} + +/// Resolver for specifiers that could be mapped via an +/// import map or package.json. +#[derive(Debug)] +pub struct MappedSpecifierResolver { + maybe_import_map: Option<Arc<ImportMap>>, + package_json_deps_provider: Arc<PackageJsonDepsProvider>, +} + +impl MappedSpecifierResolver { + pub fn new( + maybe_import_map: Option<Arc<ImportMap>>, + package_json_deps_provider: Arc<PackageJsonDepsProvider>, + ) -> Self { + Self { + maybe_import_map, + package_json_deps_provider, + } + } + + pub fn resolve( + &self, + specifier: &str, + referrer: &ModuleSpecifier, + ) -> Result<MappedResolution, AnyError> { + // attempt to resolve with the import map first + let maybe_import_map_err = match self + .maybe_import_map + .as_ref() + .map(|import_map| import_map.resolve(specifier, referrer)) + { + Some(Ok(value)) => return Ok(MappedResolution::ImportMap(value)), + Some(Err(err)) => Some(err), + None => None, + }; + + // then with package.json + if let Some(deps) = self.package_json_deps_provider.deps() { + if let Some(specifier) = resolve_package_json_dep(specifier, deps)? { + return Ok(MappedResolution::PackageJson(specifier)); + } + } + + // otherwise, surface the import map error or try resolving when has no import map + if let Some(err) = maybe_import_map_err { + Err(err.into()) + } else { + Ok(MappedResolution::None) + } + } +} + /// A resolver that takes care of resolution, taking into account loaded /// import map, JSX settings. #[derive(Debug)] pub struct CliGraphResolver { - maybe_import_map: Option<Arc<ImportMap>>, + mapped_specifier_resolver: MappedSpecifierResolver, maybe_default_jsx_import_source: Option<String>, maybe_jsx_import_source_module: Option<String>, no_npm: bool, @@ -51,7 +121,10 @@ impl Default for CliGraphResolver { None, )); Self { - maybe_import_map: Default::default(), + mapped_specifier_resolver: MappedSpecifierResolver { + maybe_import_map: Default::default(), + package_json_deps_provider: Default::default(), + }, maybe_default_jsx_import_source: Default::default(), maybe_jsx_import_source_module: Default::default(), no_npm: false, @@ -71,10 +144,14 @@ impl CliGraphResolver { no_npm: bool, npm_registry_api: Arc<CliNpmRegistryApi>, npm_resolution: Arc<NpmResolution>, + package_json_deps_provider: Arc<PackageJsonDepsProvider>, package_json_deps_installer: Arc<PackageJsonDepsInstaller>, ) -> Self { Self { - maybe_import_map, + mapped_specifier_resolver: MappedSpecifierResolver { + maybe_import_map, + package_json_deps_provider, + }, maybe_default_jsx_import_source: maybe_jsx_import_source_config .as_ref() .and_then(|c| c.default_specifier.clone()), @@ -135,31 +212,20 @@ impl Resolver for CliGraphResolver { specifier: &str, referrer: &ModuleSpecifier, ) -> Result<ModuleSpecifier, AnyError> { - // attempt to resolve with the import map first - let maybe_import_map_err = match self - .maybe_import_map - .as_ref() - .map(|import_map| import_map.resolve(specifier, referrer)) - { - Some(Ok(value)) => return Ok(value), - Some(Err(err)) => Some(err), - None => None, - }; - - // then with package.json - if let Some(deps) = self.package_json_deps_installer.package_deps().as_ref() + use MappedResolution::*; + match self + .mapped_specifier_resolver + .resolve(specifier, referrer)? { - if let Some(specifier) = resolve_package_json_dep(specifier, deps)? { + ImportMap(specifier) => Ok(specifier), + PackageJson(specifier) => { + // found a specifier in the package.json, so mark that + // we need to do an "npm install" later self.found_package_json_dep_flag.raise(); - return Ok(specifier); + Ok(specifier) } - } - - // otherwise, surface the import map error or try resolving when has no import map - if let Some(err) = maybe_import_map_err { - Err(err.into()) - } else { - deno_graph::resolve_import(specifier, referrer).map_err(|err| err.into()) + None => deno_graph::resolve_import(specifier, referrer) + .map_err(|err| err.into()), } } } |