summaryrefslogtreecommitdiff
path: root/cli/resolver.rs
diff options
context:
space:
mode:
authorDavid Sherret <dsherret@users.noreply.github.com>2024-11-14 15:24:25 -0500
committerGitHub <noreply@github.com>2024-11-14 15:24:25 -0500
commit617350e79c58b6e01984e3d7c7436d243d0e5cff (patch)
treedadb3c7675d1d49952a30c525bbc6ee3086a78e3 /cli/resolver.rs
parentde34c7ed29bcce8b46a65f5effe45090b8493ba5 (diff)
refactor(resolver): move more resolution code into deno_resolver (#26873)
Follow-up to cjs refactor. This moves most of the resolution code into the deno_resolver crate. Still pending is the npm resolution code.
Diffstat (limited to 'cli/resolver.rs')
-rw-r--r--cli/resolver.rs769
1 files changed, 62 insertions, 707 deletions
diff --git a/cli/resolver.rs b/cli/resolver.rs
index 786e5d0db..a2dd47430 100644
--- a/cli/resolver.rs
+++ b/cli/resolver.rs
@@ -4,10 +4,8 @@ use async_trait::async_trait;
use dashmap::DashMap;
use dashmap::DashSet;
use deno_ast::MediaType;
-use deno_config::workspace::MappedResolution;
use deno_config::workspace::MappedResolutionDiagnostic;
use deno_config::workspace::MappedResolutionError;
-use deno_config::workspace::WorkspaceResolver;
use deno_core::anyhow::anyhow;
use deno_core::anyhow::Context;
use deno_core::error::AnyError;
@@ -20,28 +18,14 @@ use deno_graph::source::UnknownBuiltInNodeModuleError;
use deno_graph::NpmLoadError;
use deno_graph::NpmResolvePkgReqsResult;
use deno_npm::resolution::NpmResolutionError;
-use deno_package_json::PackageJsonDepValue;
-use deno_resolver::sloppy_imports::SloppyImportsResolutionMode;
use deno_resolver::sloppy_imports::SloppyImportsResolver;
use deno_runtime::colors;
use deno_runtime::deno_fs;
use deno_runtime::deno_fs::FileSystem;
use deno_runtime::deno_node::is_builtin_node_module;
-use deno_runtime::deno_node::NodeResolver;
-use deno_runtime::deno_node::PackageJsonResolver;
-use deno_semver::npm::NpmPackageReqReference;
+use deno_runtime::deno_node::DenoFsNodeResolverEnv;
use deno_semver::package::PackageReq;
-use node_resolver::errors::ClosestPkgJsonError;
-use node_resolver::errors::NodeResolveError;
-use node_resolver::errors::NodeResolveErrorKind;
-use node_resolver::errors::PackageFolderResolveErrorKind;
-use node_resolver::errors::PackageFolderResolveIoError;
-use node_resolver::errors::PackageNotFoundError;
-use node_resolver::errors::PackageResolveErrorKind;
-use node_resolver::errors::PackageSubpathResolveError;
-use node_resolver::InNpmPackageChecker;
use node_resolver::NodeModuleKind;
-use node_resolver::NodeResolution;
use node_resolver::NodeResolutionMode;
use std::borrow::Cow;
use std::path::Path;
@@ -56,6 +40,20 @@ use crate::npm::InnerCliNpmResolverRef;
use crate::util::sync::AtomicFlag;
use crate::util::text_encoding::from_utf8_lossy_owned;
+pub type CjsTracker = deno_resolver::cjs::CjsTracker<DenoFsNodeResolverEnv>;
+pub type IsCjsResolver =
+ deno_resolver::cjs::IsCjsResolver<DenoFsNodeResolverEnv>;
+pub type IsCjsResolverOptions = deno_resolver::cjs::IsCjsResolverOptions;
+pub type CliSloppyImportsResolver =
+ SloppyImportsResolver<SloppyImportsCachedFs>;
+pub type CliDenoResolver = deno_resolver::DenoResolver<
+ CliDenoResolverFs,
+ DenoFsNodeResolverEnv,
+ SloppyImportsCachedFs,
+>;
+pub type CliNpmReqResolver =
+ deno_resolver::npm::NpmReqResolver<CliDenoResolverFs, DenoFsNodeResolverEnv>;
+
pub struct ModuleCodeStringSource {
pub code: ModuleSourceCode,
pub found_url: ModuleSpecifier,
@@ -77,6 +75,10 @@ impl deno_resolver::fs::DenoResolverFs for CliDenoResolverFs {
self.0.realpath_sync(path).map_err(|e| e.into_io_error())
}
+ fn exists_sync(&self, path: &Path) -> bool {
+ self.0.exists_sync(path)
+ }
+
fn is_dir_sync(&self, path: &Path) -> bool {
self.0.is_dir_sync(path)
}
@@ -102,211 +104,6 @@ impl deno_resolver::fs::DenoResolverFs for CliDenoResolverFs {
}
}
-#[derive(Debug)]
-pub struct CliNodeResolver {
- fs: Arc<dyn deno_fs::FileSystem>,
- in_npm_pkg_checker: Arc<dyn InNpmPackageChecker>,
- node_resolver: Arc<NodeResolver>,
- npm_resolver: Arc<dyn CliNpmResolver>,
-}
-
-impl CliNodeResolver {
- pub fn new(
- fs: Arc<dyn deno_fs::FileSystem>,
- in_npm_pkg_checker: Arc<dyn InNpmPackageChecker>,
- node_resolver: Arc<NodeResolver>,
- npm_resolver: Arc<dyn CliNpmResolver>,
- ) -> Self {
- Self {
- fs,
- in_npm_pkg_checker,
- node_resolver,
- npm_resolver,
- }
- }
-
- pub fn in_npm_package(&self, specifier: &ModuleSpecifier) -> bool {
- self.in_npm_pkg_checker.in_npm_package(specifier)
- }
-
- pub fn resolve_if_for_npm_pkg(
- &self,
- specifier: &str,
- referrer: &ModuleSpecifier,
- referrer_kind: NodeModuleKind,
- mode: NodeResolutionMode,
- ) -> Result<Option<NodeResolution>, AnyError> {
- let resolution_result =
- self.resolve(specifier, referrer, referrer_kind, mode);
- match resolution_result {
- Ok(res) => Ok(Some(res)),
- Err(err) => {
- let err = err.into_kind();
- match err {
- NodeResolveErrorKind::RelativeJoin(_)
- | NodeResolveErrorKind::PackageImportsResolve(_)
- | NodeResolveErrorKind::UnsupportedEsmUrlScheme(_)
- | NodeResolveErrorKind::DataUrlReferrer(_)
- | NodeResolveErrorKind::TypesNotFound(_)
- | NodeResolveErrorKind::FinalizeResolution(_) => Err(err.into()),
- NodeResolveErrorKind::PackageResolve(err) => {
- let err = err.into_kind();
- match err {
- PackageResolveErrorKind::ClosestPkgJson(_)
- | PackageResolveErrorKind::InvalidModuleSpecifier(_)
- | PackageResolveErrorKind::ExportsResolve(_)
- | PackageResolveErrorKind::SubpathResolve(_) => Err(err.into()),
- PackageResolveErrorKind::PackageFolderResolve(err) => {
- match err.as_kind() {
- PackageFolderResolveErrorKind::Io(
- PackageFolderResolveIoError { package_name, .. },
- )
- | PackageFolderResolveErrorKind::PackageNotFound(
- PackageNotFoundError { package_name, .. },
- ) => {
- if self.in_npm_package(referrer) {
- return Err(err.into());
- }
- if let Some(byonm_npm_resolver) =
- self.npm_resolver.as_byonm()
- {
- if byonm_npm_resolver
- .find_ancestor_package_json_with_dep(
- package_name,
- referrer,
- )
- .is_some()
- {
- return Err(anyhow!(
- concat!(
- "Could not resolve \"{}\", but found it in a package.json. ",
- "Deno expects the node_modules/ directory to be up to date. ",
- "Did you forget to run `deno install`?"
- ),
- specifier
- ));
- }
- }
- Ok(None)
- }
- PackageFolderResolveErrorKind::ReferrerNotFound(_) => {
- if self.in_npm_package(referrer) {
- return Err(err.into());
- }
- Ok(None)
- }
- }
- }
- }
- }
- }
- }
- }
- }
-
- pub fn resolve(
- &self,
- specifier: &str,
- referrer: &ModuleSpecifier,
- referrer_kind: NodeModuleKind,
- mode: NodeResolutionMode,
- ) -> Result<NodeResolution, NodeResolveError> {
- self
- .node_resolver
- .resolve(specifier, referrer, referrer_kind, mode)
- }
-
- pub fn resolve_req_reference(
- &self,
- req_ref: &NpmPackageReqReference,
- referrer: &ModuleSpecifier,
- referrer_kind: NodeModuleKind,
- mode: NodeResolutionMode,
- ) -> Result<ModuleSpecifier, AnyError> {
- self.resolve_req_with_sub_path(
- req_ref.req(),
- req_ref.sub_path(),
- referrer,
- referrer_kind,
- mode,
- )
- }
-
- pub fn resolve_req_with_sub_path(
- &self,
- req: &PackageReq,
- sub_path: Option<&str>,
- referrer: &ModuleSpecifier,
- referrer_kind: NodeModuleKind,
- mode: NodeResolutionMode,
- ) -> Result<ModuleSpecifier, AnyError> {
- let package_folder = self
- .npm_resolver
- .resolve_pkg_folder_from_deno_module_req(req, referrer)?;
- let resolution_result = self.resolve_package_sub_path_from_deno_module(
- &package_folder,
- sub_path,
- Some(referrer),
- referrer_kind,
- mode,
- );
- match resolution_result {
- Ok(url) => Ok(url),
- Err(err) => {
- if self.npm_resolver.as_byonm().is_some() {
- let package_json_path = package_folder.join("package.json");
- if !self.fs.exists_sync(&package_json_path) {
- return Err(anyhow!(
- "Could not find '{}'. Deno expects the node_modules/ directory to be up to date. Did you forget to run `deno install`?",
- package_json_path.display(),
- ));
- }
- }
- Err(err.into())
- }
- }
- }
-
- pub fn resolve_package_sub_path_from_deno_module(
- &self,
- package_folder: &Path,
- sub_path: Option<&str>,
- maybe_referrer: Option<&ModuleSpecifier>,
- referrer_kind: NodeModuleKind,
- mode: NodeResolutionMode,
- ) -> Result<ModuleSpecifier, PackageSubpathResolveError> {
- self.node_resolver.resolve_package_subpath_from_deno_module(
- package_folder,
- sub_path,
- maybe_referrer,
- referrer_kind,
- mode,
- )
- }
-
- pub fn handle_if_in_node_modules(
- &self,
- specifier: &ModuleSpecifier,
- ) -> Result<Option<ModuleSpecifier>, AnyError> {
- // skip canonicalizing if we definitely know it's unnecessary
- if specifier.scheme() == "file"
- && specifier.path().contains("/node_modules/")
- {
- // Specifiers in the node_modules directory are canonicalized
- // so canoncalize then check if it's in the node_modules directory.
- // If so, check if we need to store this specifier as being a CJS
- // resolution.
- let specifier = crate::node::resolve_specifier_into_node_modules(
- specifier,
- self.fs.as_ref(),
- );
- return Ok(Some(specifier));
- }
-
- Ok(None)
- }
-}
-
#[derive(Debug, Error)]
#[error("{media_type} files are not supported in npm packages: {specifier}")]
pub struct NotSupportedKindInNpmError {
@@ -409,305 +206,36 @@ impl NpmModuleLoader {
}
}
-/// Keeps track of what module specifiers were resolved as CJS.
-///
-/// Modules that are `.js` or `.ts` are only known to be CJS or
-/// ESM after they're loaded based on their contents. So these files
-/// will be "maybe CJS" until they're loaded.
-#[derive(Debug)]
-pub struct CjsTracker {
- is_cjs_resolver: IsCjsResolver,
- known: DashMap<ModuleSpecifier, NodeModuleKind>,
-}
-
-impl CjsTracker {
- pub fn new(
- in_npm_pkg_checker: Arc<dyn InNpmPackageChecker>,
- pkg_json_resolver: Arc<PackageJsonResolver>,
- options: IsCjsResolverOptions,
- ) -> Self {
- Self {
- is_cjs_resolver: IsCjsResolver::new(
- in_npm_pkg_checker,
- pkg_json_resolver,
- options,
- ),
- known: Default::default(),
- }
- }
-
- /// Checks whether the file might be treated as CJS, but it's not for sure
- /// yet because the source hasn't been loaded to see whether it contains
- /// imports or exports.
- pub fn is_maybe_cjs(
- &self,
- specifier: &ModuleSpecifier,
- media_type: MediaType,
- ) -> Result<bool, ClosestPkgJsonError> {
- self.treat_as_cjs_with_is_script(specifier, media_type, None)
- }
-
- /// Gets whether the file is CJS. If true, this is for sure
- /// cjs because `is_script` is provided.
- ///
- /// `is_script` should be `true` when the contents of the file at the
- /// provided specifier are known to be a script and not an ES module.
- pub fn is_cjs_with_known_is_script(
- &self,
- specifier: &ModuleSpecifier,
- media_type: MediaType,
- is_script: bool,
- ) -> Result<bool, ClosestPkgJsonError> {
- self.treat_as_cjs_with_is_script(specifier, media_type, Some(is_script))
- }
-
- fn treat_as_cjs_with_is_script(
- &self,
- specifier: &ModuleSpecifier,
- media_type: MediaType,
- is_script: Option<bool>,
- ) -> Result<bool, ClosestPkgJsonError> {
- let kind = match self
- .get_known_kind_with_is_script(specifier, media_type, is_script)
- {
- Some(kind) => kind,
- None => self.is_cjs_resolver.check_based_on_pkg_json(specifier)?,
- };
- Ok(kind == NodeModuleKind::Cjs)
- }
-
- pub fn get_known_kind(
- &self,
- specifier: &ModuleSpecifier,
- media_type: MediaType,
- ) -> Option<NodeModuleKind> {
- self.get_known_kind_with_is_script(specifier, media_type, None)
- }
-
- pub fn get_referrer_kind(
- &self,
- specifier: &ModuleSpecifier,
- ) -> NodeModuleKind {
- if specifier.scheme() != "file" {
- return NodeModuleKind::Esm;
- }
- self
- .get_known_kind(specifier, MediaType::from_specifier(specifier))
- .unwrap_or(NodeModuleKind::Esm)
- }
-
- fn get_known_kind_with_is_script(
- &self,
- specifier: &ModuleSpecifier,
- media_type: MediaType,
- is_script: Option<bool>,
- ) -> Option<NodeModuleKind> {
- self.is_cjs_resolver.get_known_kind_with_is_script(
- specifier,
- media_type,
- is_script,
- &self.known,
- )
- }
-}
-
-#[derive(Debug)]
-pub struct IsCjsResolverOptions {
- pub detect_cjs: bool,
- pub is_node_main: bool,
-}
-
-#[derive(Debug)]
-pub struct IsCjsResolver {
- in_npm_pkg_checker: Arc<dyn InNpmPackageChecker>,
- pkg_json_resolver: Arc<PackageJsonResolver>,
- options: IsCjsResolverOptions,
-}
-
-impl IsCjsResolver {
- pub fn new(
- in_npm_pkg_checker: Arc<dyn InNpmPackageChecker>,
- pkg_json_resolver: Arc<PackageJsonResolver>,
- options: IsCjsResolverOptions,
- ) -> Self {
- Self {
- in_npm_pkg_checker,
- pkg_json_resolver,
- options,
- }
- }
-
- pub fn get_lsp_referrer_kind(
- &self,
- specifier: &ModuleSpecifier,
- is_script: Option<bool>,
- ) -> NodeModuleKind {
- if specifier.scheme() != "file" {
- return NodeModuleKind::Esm;
- }
- match MediaType::from_specifier(specifier) {
- MediaType::Mts | MediaType::Mjs | MediaType::Dmts => NodeModuleKind::Esm,
- MediaType::Cjs | MediaType::Cts | MediaType::Dcts => NodeModuleKind::Cjs,
- MediaType::Dts => {
- // dts files are always determined based on the package.json because
- // they contain imports/exports even when considered CJS
- self.check_based_on_pkg_json(specifier).unwrap_or(NodeModuleKind::Esm)
- }
- MediaType::Wasm |
- MediaType::Json => NodeModuleKind::Esm,
- MediaType::JavaScript
- | MediaType::Jsx
- | MediaType::TypeScript
- | MediaType::Tsx
- // treat these as unknown
- | MediaType::Css
- | MediaType::SourceMap
- | MediaType::Unknown => {
- match is_script {
- Some(true) => self.check_based_on_pkg_json(specifier).unwrap_or(NodeModuleKind::Esm),
- Some(false) | None => NodeModuleKind::Esm,
- }
- }
- }
- }
-
- fn get_known_kind_with_is_script(
- &self,
- specifier: &ModuleSpecifier,
- media_type: MediaType,
- is_script: Option<bool>,
- known_cache: &DashMap<ModuleSpecifier, NodeModuleKind>,
- ) -> Option<NodeModuleKind> {
- if specifier.scheme() != "file" {
- return Some(NodeModuleKind::Esm);
- }
-
- match media_type {
- MediaType::Mts | MediaType::Mjs | MediaType::Dmts => Some(NodeModuleKind::Esm),
- MediaType::Cjs | MediaType::Cts | MediaType::Dcts => Some(NodeModuleKind::Cjs),
- MediaType::Dts => {
- // dts files are always determined based on the package.json because
- // they contain imports/exports even when considered CJS
- if let Some(value) = known_cache.get(specifier).map(|v| *v) {
- Some(value)
- } else {
- let value = self.check_based_on_pkg_json(specifier).ok();
- if let Some(value) = value {
- known_cache.insert(specifier.clone(), value);
- }
- Some(value.unwrap_or(NodeModuleKind::Esm))
- }
- }
- MediaType::Wasm |
- MediaType::Json => Some(NodeModuleKind::Esm),
- MediaType::JavaScript
- | MediaType::Jsx
- | MediaType::TypeScript
- | MediaType::Tsx
- // treat these as unknown
- | MediaType::Css
- | MediaType::SourceMap
- | MediaType::Unknown => {
- if let Some(value) = known_cache.get(specifier).map(|v| *v) {
- if value == NodeModuleKind::Cjs && is_script == Some(false) {
- // we now know this is actually esm
- known_cache.insert(specifier.clone(), NodeModuleKind::Esm);
- Some(NodeModuleKind::Esm)
- } else {
- Some(value)
- }
- } else if is_script == Some(false) {
- // we know this is esm
- known_cache.insert(specifier.clone(), NodeModuleKind::Esm);
- Some(NodeModuleKind::Esm)
- } else {
- None
- }
- }
- }
- }
-
- fn check_based_on_pkg_json(
- &self,
- specifier: &ModuleSpecifier,
- ) -> Result<NodeModuleKind, ClosestPkgJsonError> {
- if self.in_npm_pkg_checker.in_npm_package(specifier) {
- if let Some(pkg_json) =
- self.pkg_json_resolver.get_closest_package_json(specifier)?
- {
- let is_file_location_cjs = pkg_json.typ != "module";
- Ok(if is_file_location_cjs {
- NodeModuleKind::Cjs
- } else {
- NodeModuleKind::Esm
- })
- } else {
- Ok(NodeModuleKind::Cjs)
- }
- } else if self.options.detect_cjs || self.options.is_node_main {
- if let Some(pkg_json) =
- self.pkg_json_resolver.get_closest_package_json(specifier)?
- {
- let is_cjs_type = pkg_json.typ == "commonjs"
- || self.options.is_node_main && pkg_json.typ == "none";
- Ok(if is_cjs_type {
- NodeModuleKind::Cjs
- } else {
- NodeModuleKind::Esm
- })
- } else if self.options.is_node_main {
- Ok(NodeModuleKind::Cjs)
- } else {
- Ok(NodeModuleKind::Esm)
- }
- } else {
- Ok(NodeModuleKind::Esm)
- }
- }
+pub struct CliResolverOptions {
+ pub deno_resolver: Arc<CliDenoResolver>,
+ pub npm_resolver: Option<Arc<dyn CliNpmResolver>>,
+ pub bare_node_builtins_enabled: bool,
}
-pub type CliSloppyImportsResolver =
- SloppyImportsResolver<SloppyImportsCachedFs>;
-
/// A resolver that takes care of resolution, taking into account loaded
/// import map, JSX settings.
#[derive(Debug)]
pub struct CliResolver {
- node_resolver: Option<Arc<CliNodeResolver>>,
+ deno_resolver: Arc<CliDenoResolver>,
npm_resolver: Option<Arc<dyn CliNpmResolver>>,
- sloppy_imports_resolver: Option<Arc<CliSloppyImportsResolver>>,
- workspace_resolver: Arc<WorkspaceResolver>,
- maybe_vendor_specifier: Option<ModuleSpecifier>,
found_package_json_dep_flag: AtomicFlag,
bare_node_builtins_enabled: bool,
warned_pkgs: DashSet<PackageReq>,
}
-pub struct CliResolverOptions<'a> {
- pub node_resolver: Option<Arc<CliNodeResolver>>,
- pub npm_resolver: Option<Arc<dyn CliNpmResolver>>,
- pub sloppy_imports_resolver: Option<Arc<CliSloppyImportsResolver>>,
- pub workspace_resolver: Arc<WorkspaceResolver>,
- pub bare_node_builtins_enabled: bool,
- pub maybe_vendor_dir: Option<&'a PathBuf>,
-}
-
impl CliResolver {
pub fn new(options: CliResolverOptions) -> Self {
Self {
- node_resolver: options.node_resolver,
+ deno_resolver: options.deno_resolver,
npm_resolver: options.npm_resolver,
- sloppy_imports_resolver: options.sloppy_imports_resolver,
- workspace_resolver: options.workspace_resolver,
- maybe_vendor_specifier: options
- .maybe_vendor_dir
- .and_then(|v| ModuleSpecifier::from_directory_path(v).ok()),
found_package_json_dep_flag: Default::default(),
bare_node_builtins_enabled: options.bare_node_builtins_enabled,
warned_pkgs: Default::default(),
}
}
+ // todo(dsherret): move this off CliResolver as CliResolver is acting
+ // like a factory by doing this (it's beyond its responsibility)
pub fn create_graph_npm_resolver(&self) -> WorkerCliNpmGraphResolver {
WorkerCliNpmGraphResolver {
npm_resolver: self.npm_resolver.as_ref(),
@@ -730,223 +258,50 @@ impl CliResolver {
}
}
- let referrer = &referrer_range.specifier;
+ let resolution = self
+ .deno_resolver
+ .resolve(
+ raw_specifier,
+ &referrer_range.specifier,
+ referrer_kind,
+ to_node_mode(mode),
+ )
+ .map_err(|err| match err.into_kind() {
+ deno_resolver::DenoResolveErrorKind::MappedResolution(
+ mapped_resolution_error,
+ ) => match mapped_resolution_error {
+ MappedResolutionError::Specifier(e) => ResolveError::Specifier(e),
+ // deno_graph checks specifically for an ImportMapError
+ MappedResolutionError::ImportMap(e) => ResolveError::Other(e.into()),
+ err => ResolveError::Other(err.into()),
+ },
+ err => ResolveError::Other(err.into()),
+ })?;
- // Use node resolution if we're in an npm package
- if let Some(node_resolver) = self.node_resolver.as_ref() {
- if referrer.scheme() == "file" && node_resolver.in_npm_package(referrer) {
- return node_resolver
- .resolve(raw_specifier, referrer, referrer_kind, to_node_mode(mode))
- .map(|res| res.into_url())
- .map_err(|e| ResolveError::Other(e.into()));
- }
+ if resolution.found_package_json_dep {
+ // mark that we need to do an "npm install" later
+ self.found_package_json_dep_flag.raise();
}
- // Attempt to resolve with the workspace resolver
- let result: Result<_, ResolveError> = self
- .workspace_resolver
- .resolve(raw_specifier, referrer)
- .map_err(|err| match err {
- MappedResolutionError::Specifier(err) => ResolveError::Specifier(err),
- MappedResolutionError::ImportMap(err) => {
- ResolveError::Other(err.into())
- }
- MappedResolutionError::Workspace(err) => {
- ResolveError::Other(err.into())
- }
- });
- let result = match result {
- Ok(resolution) => match resolution {
- MappedResolution::Normal {
- specifier,
- maybe_diagnostic,
- }
- | MappedResolution::ImportMap {
- specifier,
- maybe_diagnostic,
- } => {
- if let Some(diagnostic) = maybe_diagnostic {
- match &*diagnostic {
- MappedResolutionDiagnostic::ConstraintNotMatchedLocalVersion { reference, .. } => {
- if self.warned_pkgs.insert(reference.req().clone()) {
- log::warn!("{} {}\n at {}", colors::yellow("Warning"), diagnostic, referrer_range);
- }
- }
- }
- }
- // do sloppy imports resolution if enabled
- if let Some(sloppy_imports_resolver) = &self.sloppy_imports_resolver {
- Ok(
- sloppy_imports_resolver
- .resolve(
- &specifier,
- match mode {
- ResolutionMode::Execution => {
- SloppyImportsResolutionMode::Execution
- }
- ResolutionMode::Types => SloppyImportsResolutionMode::Types,
- },
- )
- .map(|s| s.into_specifier())
- .unwrap_or(specifier),
- )
- } else {
- Ok(specifier)
- }
- }
- MappedResolution::WorkspaceJsrPackage { specifier, .. } => {
- Ok(specifier)
- }
- MappedResolution::WorkspaceNpmPackage {
- target_pkg_json: pkg_json,
- sub_path,
- ..
- } => self
- .node_resolver
- .as_ref()
- .unwrap()
- .resolve_package_sub_path_from_deno_module(
- pkg_json.dir_path(),
- sub_path.as_deref(),
- Some(referrer),
- referrer_kind,
- to_node_mode(mode),
- )
- .map_err(|e| ResolveError::Other(e.into())),
- MappedResolution::PackageJson {
- dep_result,
- alias,
- sub_path,
+ if let Some(diagnostic) = resolution.maybe_diagnostic {
+ match &*diagnostic {
+ MappedResolutionDiagnostic::ConstraintNotMatchedLocalVersion {
+ reference,
..
} => {
- // 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();
-
- dep_result
- .as_ref()
- .map_err(|e| ResolveError::Other(e.clone().into()))
- .and_then(|dep| match dep {
- PackageJsonDepValue::Req(req) => {
- ModuleSpecifier::parse(&format!(
- "npm:{}{}",
- req,
- sub_path.map(|s| format!("/{}", s)).unwrap_or_default()
- ))
- .map_err(|e| ResolveError::Other(e.into()))
- }
- PackageJsonDepValue::Workspace(version_req) => self
- .workspace_resolver
- .resolve_workspace_pkg_json_folder_for_pkg_json_dep(
- alias,
- version_req,
- )
- .map_err(|e| ResolveError::Other(e.into()))
- .and_then(|pkg_folder| {
- self
- .node_resolver
- .as_ref()
- .unwrap()
- .resolve_package_sub_path_from_deno_module(
- pkg_folder,
- sub_path.as_deref(),
- Some(referrer),
- referrer_kind,
- to_node_mode(mode),
- )
- .map_err(|e| ResolveError::Other(e.into()))
- }),
- })
- }
- },
- Err(err) => Err(err),
- };
-
- // When the user is vendoring, don't allow them to import directly from the vendor/ directory
- // as it might cause them confusion or duplicate dependencies. Additionally, this folder has
- // special treatment in the language server so it will definitely cause issues/confusion there
- // if they do this.
- if let Some(vendor_specifier) = &self.maybe_vendor_specifier {
- if let Ok(specifier) = &result {
- if specifier.as_str().starts_with(vendor_specifier.as_str()) {
- return Err(ResolveError::Other(anyhow!("Importing from the vendor directory is not permitted. Use a remote specifier instead or disable vendoring.")));
- }
- }
- }
-
- let Some(node_resolver) = &self.node_resolver else {
- return result;
- };
-
- let is_byonm = self
- .npm_resolver
- .as_ref()
- .is_some_and(|r| r.as_byonm().is_some());
- match result {
- Ok(specifier) => {
- if let Ok(npm_req_ref) =
- NpmPackageReqReference::from_specifier(&specifier)
- {
- // check if the npm specifier resolves to a workspace member
- if let Some(pkg_folder) = self
- .workspace_resolver
- .resolve_workspace_pkg_json_folder_for_npm_specifier(
- npm_req_ref.req(),
- )
- {
- return node_resolver
- .resolve_package_sub_path_from_deno_module(
- pkg_folder,
- npm_req_ref.sub_path(),
- Some(referrer),
- referrer_kind,
- to_node_mode(mode),
- )
- .map_err(|e| ResolveError::Other(e.into()));
- }
-
- // do npm resolution for byonm
- if is_byonm {
- return node_resolver
- .resolve_req_reference(
- &npm_req_ref,
- referrer,
- referrer_kind,
- to_node_mode(mode),
- )
- .map_err(|err| err.into());
+ if self.warned_pkgs.insert(reference.req().clone()) {
+ log::warn!(
+ "{} {}\n at {}",
+ colors::yellow("Warning"),
+ diagnostic,
+ referrer_range
+ );
}
}
-
- Ok(match node_resolver.handle_if_in_node_modules(&specifier)? {
- Some(specifier) => specifier,
- None => specifier,
- })
- }
- Err(err) => {
- // If byonm, check if the bare specifier resolves to an npm package
- if is_byonm && referrer.scheme() == "file" {
- let maybe_resolution = node_resolver
- .resolve_if_for_npm_pkg(
- raw_specifier,
- referrer,
- referrer_kind,
- to_node_mode(mode),
- )
- .map_err(ResolveError::Other)?;
- if let Some(res) = maybe_resolution {
- match res {
- NodeResolution::Module(url) => return Ok(url),
- NodeResolution::BuiltIn(_) => {
- // don't resolve bare specifiers for built-in modules via node resolution
- }
- }
- }
- }
-
- Err(err)
}
}
+
+ Ok(resolution.url)
}
}