From 568dd132fb0a47f9afb11bffec341c7481dda75c Mon Sep 17 00:00:00 2001 From: David Sherret Date: Tue, 16 Jul 2024 18:32:41 -0400 Subject: [PATCH] refactor(node): internally add `.code()` to node resolution errors (#24610) This makes it easier to tell what kind of error something is (even for deeply nested errors) and will help in the future once we add error codes to the JS errors this returns. --- cli/resolver.rs | 61 ++++---- ext/node/errors.rs | 302 +++++++++++++++++++++++++++++++++------ ext/node/package_json.rs | 13 +- ext/node/resolution.rs | 35 +++-- 4 files changed, 313 insertions(+), 98 deletions(-) diff --git a/cli/resolver.rs b/cli/resolver.rs index 7b8766ee99..6049ec2732 100644 --- a/cli/resolver.rs +++ b/cli/resolver.rs @@ -24,6 +24,8 @@ use deno_npm::resolution::NpmResolutionError; use deno_runtime::deno_fs; use deno_runtime::deno_fs::FileSystem; use deno_runtime::deno_node::errors::ClosestPkgJsonError; +use deno_runtime::deno_node::errors::NodeResolveError; +use deno_runtime::deno_node::errors::ResolvePkgSubpathFromDenoModuleError; use deno_runtime::deno_node::errors::UrlToNodeResolutionError; use deno_runtime::deno_node::is_builtin_node_module; use deno_runtime::deno_node::parse_npm_pkg_name; @@ -105,7 +107,7 @@ impl CliNodeResolver { specifier: &str, referrer: &ModuleSpecifier, mode: NodeResolutionMode, - ) -> Option, AnyError>> { + ) -> Option, NodeResolveError>> { if self.in_npm_package(referrer) { // we're in an npm package, so use node resolution Some(self.resolve(specifier, referrer, mode)) @@ -119,19 +121,18 @@ impl CliNodeResolver { specifier: &str, referrer: &ModuleSpecifier, mode: NodeResolutionMode, - ) -> Result, AnyError> { + ) -> Result, NodeResolveError> { let referrer_kind = if self.cjs_resolutions.contains(referrer) { NodeModuleKind::Cjs } else { NodeModuleKind::Esm }; - self.handle_node_resolve_result( + let maybe_res = self .node_resolver - .resolve(specifier, referrer, referrer_kind, mode) - .map_err(AnyError::from), - ) + .resolve(specifier, referrer, referrer_kind, mode)?; + Ok(self.handle_node_resolution(maybe_res)) } pub fn resolve_req_reference( @@ -218,18 +219,16 @@ impl CliNodeResolver { sub_path: Option<&str>, maybe_referrer: Option<&ModuleSpecifier>, mode: NodeResolutionMode, - ) -> Result, AnyError> { - self.handle_node_resolve_result( - self - .node_resolver - .resolve_package_subpath_from_deno_module( - package_folder, - sub_path, - maybe_referrer, - mode, - ) - .map_err(AnyError::from), - ) + ) -> Result, ResolvePkgSubpathFromDenoModuleError> { + let maybe_res = self + .node_resolver + .resolve_package_subpath_from_deno_module( + package_folder, + sub_path, + maybe_referrer, + mode, + )?; + Ok(self.handle_node_resolution(maybe_res)) } pub fn handle_if_in_node_modules( @@ -266,20 +265,15 @@ impl CliNodeResolver { self.node_resolver.url_to_node_resolution(specifier) } - fn handle_node_resolve_result( + fn handle_node_resolution( &self, - result: Result, AnyError>, - ) -> Result, AnyError> { - match result? { - Some(response) => { - if let NodeResolution::CommonJs(specifier) = &response { - // remember that this was a common js resolution - self.cjs_resolutions.insert(specifier.clone()); - } - Ok(Some(response)) - } - None => Ok(None), + maybe_resolution: Option, + ) -> Option { + if let Some(NodeResolution::CommonJs(specifier)) = &maybe_resolution { + // remember that this was a common js resolution + self.cjs_resolutions.insert(specifier.clone()); } + maybe_resolution } } @@ -465,7 +459,7 @@ impl CliGraphResolver { } } - // todo(dsherret): if we returned structured errors from the NodeResolver we wouldn't need this + // todo(dsherret): update this and the surrounding code to handle the structured errors from NodeResolver fn check_surface_byonm_node_error( &self, specifier: &str, @@ -681,7 +675,10 @@ impl Resolver for CliGraphResolver { Err(err) => { self .check_surface_byonm_node_error( - specifier, referrer, err, resolver, + specifier, + referrer, + err.into(), + resolver, ) .map_err(ResolveError::Other)?; } diff --git a/ext/node/errors.rs b/ext/node/errors.rs index 560336d68c..98b207e86a 100644 --- a/ext/node/errors.rs +++ b/ext/node/errors.rs @@ -1,10 +1,9 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. use std::borrow::Cow; +use std::fmt::Write; use std::path::PathBuf; -use deno_core::error::generic_error; -use deno_core::error::AnyError; use deno_core::ModuleSpecifier; use thiserror::Error; @@ -38,11 +37,62 @@ macro_rules! kinded_err { }; } +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +#[allow(non_camel_case_types)] +pub enum NodeJsErrorCode { + ERR_INVALID_MODULE_SPECIFIER, + ERR_INVALID_PACKAGE_CONFIG, + ERR_INVALID_PACKAGE_TARGET, + ERR_MODULE_NOT_FOUND, + ERR_PACKAGE_IMPORT_NOT_DEFINED, + ERR_PACKAGE_PATH_NOT_EXPORTED, + ERR_UNKNOWN_FILE_EXTENSION, + ERR_UNSUPPORTED_DIR_IMPORT, + ERR_UNSUPPORTED_ESM_URL_SCHEME, +} + +impl std::fmt::Display for NodeJsErrorCode { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.as_str()) + } +} + +impl NodeJsErrorCode { + pub fn as_str(&self) -> &'static str { + use NodeJsErrorCode::*; + match self { + ERR_INVALID_MODULE_SPECIFIER => "ERR_INVALID_MODULE_SPECIFIER", + ERR_INVALID_PACKAGE_CONFIG => "ERR_INVALID_PACKAGE_CONFIG", + ERR_INVALID_PACKAGE_TARGET => "ERR_INVALID_PACKAGE_TARGET", + ERR_MODULE_NOT_FOUND => "ERR_MODULE_NOT_FOUND", + ERR_PACKAGE_IMPORT_NOT_DEFINED => "ERR_PACKAGE_IMPORT_NOT_DEFINED", + ERR_PACKAGE_PATH_NOT_EXPORTED => "ERR_PACKAGE_PATH_NOT_EXPORTED", + ERR_UNKNOWN_FILE_EXTENSION => "ERR_UNKNOWN_FILE_EXTENSION", + ERR_UNSUPPORTED_DIR_IMPORT => "ERR_UNSUPPORTED_DIR_IMPORT", + ERR_UNSUPPORTED_ESM_URL_SCHEME => "ERR_UNSUPPORTED_ESM_URL_SCHEME", + } + } +} + +pub trait NodeJsErrorCoded { + fn code(&self) -> NodeJsErrorCode; +} + kinded_err!( ResolvePkgSubpathFromDenoModuleError, ResolvePkgSubpathFromDenoModuleErrorKind ); +impl NodeJsErrorCoded for ResolvePkgSubpathFromDenoModuleError { + fn code(&self) -> NodeJsErrorCode { + use ResolvePkgSubpathFromDenoModuleErrorKind::*; + match self.as_kind() { + PackageSubpathResolve(e) => e.code(), + UrlToNodeResolution(e) => e.code(), + } + } +} + #[derive(Debug, Error)] pub enum ResolvePkgSubpathFromDenoModuleErrorKind { #[error(transparent)] @@ -54,7 +104,8 @@ pub enum ResolvePkgSubpathFromDenoModuleErrorKind { // todo(https://github.com/denoland/deno_core/issues/810): make this a TypeError #[derive(Debug, Clone, Error)] #[error( - "[ERR_INVALID_MODULE_SPECIFIER] Invalid module '{}' {}{}", + "[{}] Invalid module '{}' {}{}", + self.code(), request, reason, maybe_referrer.as_ref().map(|referrer| format!(" imported from '{}'", referrer)).unwrap_or_default() @@ -65,14 +116,40 @@ pub struct InvalidModuleSpecifierError { pub maybe_referrer: Option, } +impl NodeJsErrorCoded for InvalidModuleSpecifierError { + fn code(&self) -> NodeJsErrorCode { + NodeJsErrorCode::ERR_INVALID_MODULE_SPECIFIER + } +} + #[derive(Debug, Error)] pub enum LegacyMainResolveError { #[error(transparent)] PathToDeclarationUrl(PathToDeclarationUrlError), } +impl NodeJsErrorCoded for LegacyMainResolveError { + fn code(&self) -> NodeJsErrorCode { + match self { + Self::PathToDeclarationUrl(e) => e.code(), + } + } +} + kinded_err!(PackageFolderResolveError, PackageFolderResolveErrorKind); +impl NodeJsErrorCoded for PackageFolderResolveError { + fn code(&self) -> NodeJsErrorCode { + match self.as_kind() { + PackageFolderResolveErrorKind::NotFoundPackage { .. } + | PackageFolderResolveErrorKind::NotFoundReferrer { .. } + | PackageFolderResolveErrorKind::Io { .. } => { + NodeJsErrorCode::ERR_MODULE_NOT_FOUND + } + } + } +} + #[derive(Debug, Error)] pub enum PackageFolderResolveErrorKind { #[error( @@ -108,15 +185,25 @@ pub enum PackageFolderResolveErrorKind { kinded_err!(PackageSubpathResolveError, PackageSubpathResolveErrorKind); +impl NodeJsErrorCoded for PackageSubpathResolveError { + fn code(&self) -> NodeJsErrorCode { + match self.as_kind() { + PackageSubpathResolveErrorKind::PkgJsonLoad(e) => e.code(), + PackageSubpathResolveErrorKind::PackageFolderResolve(e) => e.code(), + PackageSubpathResolveErrorKind::Exports(e) => e.code(), + PackageSubpathResolveErrorKind::LegacyMain(e) => e.code(), + PackageSubpathResolveErrorKind::LegacyExact(e) => e.code(), + } + } +} + #[derive(Debug, Error)] pub enum PackageSubpathResolveErrorKind { #[error(transparent)] - PkgJsonLoad(#[from] deno_config::package_json::PackageJsonLoadError), + PkgJsonLoad(#[from] PackageJsonLoadError), #[error(transparent)] PackageFolderResolve(#[from] PackageFolderResolveError), #[error(transparent)] - DirNotFound(AnyError), - #[error(transparent)] Exports(PackageExportsResolveError), #[error(transparent)] LegacyMain(LegacyMainResolveError), @@ -152,8 +239,26 @@ pub struct PackageTargetNotFoundError { pub mode: NodeResolutionMode, } +impl NodeJsErrorCoded for PackageTargetNotFoundError { + fn code(&self) -> NodeJsErrorCode { + NodeJsErrorCode::ERR_MODULE_NOT_FOUND + } +} + kinded_err!(PackageTargetResolveError, PackageTargetResolveErrorKind); +impl NodeJsErrorCoded for PackageTargetResolveError { + fn code(&self) -> NodeJsErrorCode { + match self.as_kind() { + PackageTargetResolveErrorKind::NotFound(e) => e.code(), + PackageTargetResolveErrorKind::InvalidPackageTarget(e) => e.code(), + PackageTargetResolveErrorKind::InvalidModuleSpecifier(e) => e.code(), + PackageTargetResolveErrorKind::PackageResolve(e) => e.code(), + PackageTargetResolveErrorKind::PathToDeclarationUrl(e) => e.code(), + } + } +} + #[derive(Debug, Error)] pub enum PackageTargetResolveErrorKind { #[error(transparent)] @@ -170,6 +275,15 @@ pub enum PackageTargetResolveErrorKind { kinded_err!(PackageExportsResolveError, PackageExportsResolveErrorKind); +impl NodeJsErrorCoded for PackageExportsResolveError { + fn code(&self) -> NodeJsErrorCode { + match self.as_kind() { + PackageExportsResolveErrorKind::PackagePathNotExported(e) => e.code(), + PackageExportsResolveErrorKind::PackageTargetResolve(e) => e.code(), + } + } +} + #[derive(Debug, Error)] pub enum PackageExportsResolveErrorKind { #[error(transparent)] @@ -184,18 +298,63 @@ pub enum PathToDeclarationUrlError { SubPath(#[from] PackageSubpathResolveError), } +impl NodeJsErrorCoded for PathToDeclarationUrlError { + fn code(&self) -> NodeJsErrorCode { + match self { + PathToDeclarationUrlError::SubPath(e) => e.code(), + } + } +} + +#[derive(Debug, Error)] +#[error( + "[{}] Invalid package config. {}", + self.code(), + self.0 +)] +pub struct PackageJsonLoadError( + #[source] + #[from] + pub deno_config::package_json::PackageJsonLoadError, +); + +impl NodeJsErrorCoded for PackageJsonLoadError { + fn code(&self) -> NodeJsErrorCode { + NodeJsErrorCode::ERR_INVALID_PACKAGE_CONFIG + } +} + kinded_err!(ClosestPkgJsonError, ClosestPkgJsonErrorKind); +impl NodeJsErrorCoded for ClosestPkgJsonError { + fn code(&self) -> NodeJsErrorCode { + match self.as_kind() { + ClosestPkgJsonErrorKind::CanonicalizingDir(e) => e.code(), + ClosestPkgJsonErrorKind::Load(e) => e.code(), + } + } +} + #[derive(Debug, Error)] pub enum ClosestPkgJsonErrorKind { - #[error("Failed canonicalizing package.json directory '{dir_path}'.")] - CanonicalizingDir { - dir_path: PathBuf, - #[source] - source: std::io::Error, - }, #[error(transparent)] - Load(#[from] deno_config::package_json::PackageJsonLoadError), + CanonicalizingDir(#[from] CanonicalizingPkgJsonDirError), + #[error(transparent)] + Load(#[from] PackageJsonLoadError), +} + +#[derive(Debug, Error)] +#[error("[{}] Failed canonicalizing package.json directory '{}'.", self.code(), dir_path.display())] +pub struct CanonicalizingPkgJsonDirError { + pub dir_path: PathBuf, + #[source] + pub source: std::io::Error, +} + +impl NodeJsErrorCoded for CanonicalizingPkgJsonDirError { + fn code(&self) -> NodeJsErrorCode { + NodeJsErrorCode::ERR_MODULE_NOT_FOUND + } } #[derive(Debug, Error)] @@ -204,8 +363,23 @@ pub struct TypeScriptNotSupportedInNpmError { pub specifier: ModuleSpecifier, } +impl NodeJsErrorCoded for TypeScriptNotSupportedInNpmError { + fn code(&self) -> NodeJsErrorCode { + NodeJsErrorCode::ERR_UNKNOWN_FILE_EXTENSION + } +} + kinded_err!(UrlToNodeResolutionError, UrlToNodeResolutionErrorKind); +impl NodeJsErrorCoded for UrlToNodeResolutionError { + fn code(&self) -> NodeJsErrorCode { + match self.as_kind() { + UrlToNodeResolutionErrorKind::TypeScriptNotSupported(e) => e.code(), + UrlToNodeResolutionErrorKind::ClosestPkgJson(e) => e.code(), + } + } +} + #[derive(Debug, Error)] pub enum UrlToNodeResolutionErrorKind { #[error(transparent)] @@ -217,7 +391,8 @@ pub enum UrlToNodeResolutionErrorKind { // todo(https://github.com/denoland/deno_core/issues/810): make this a TypeError #[derive(Debug, Error)] #[error( - "[ERR_PACKAGE_IMPORT_NOT_DEFINED] Package import specifier \"{}\" is not defined{}{}", + "[{}] Package import specifier \"{}\" is not defined{}{}", + self.code(), name, package_json_path.as_ref().map(|p| format!(" in package {}", p.display())).unwrap_or_default(), maybe_referrer.as_ref().map(|r| format!(" imported from '{}'", r)).unwrap_or_default(), @@ -228,6 +403,12 @@ pub struct PackageImportNotDefinedError { pub maybe_referrer: Option, } +impl NodeJsErrorCoded for PackageImportNotDefinedError { + fn code(&self) -> NodeJsErrorCode { + NodeJsErrorCode::ERR_PACKAGE_IMPORT_NOT_DEFINED + } +} + kinded_err!(PackageImportsResolveError, PackageImportsResolveErrorKind); #[derive(Debug, Error)] @@ -242,8 +423,30 @@ pub enum PackageImportsResolveErrorKind { Target(#[from] PackageTargetResolveError), } +impl NodeJsErrorCoded for PackageImportsResolveErrorKind { + fn code(&self) -> NodeJsErrorCode { + match self { + Self::ClosestPkgJson(e) => e.code(), + Self::InvalidModuleSpecifier(e) => e.code(), + Self::NotDefined(e) => e.code(), + Self::Target(e) => e.code(), + } + } +} + kinded_err!(PackageResolveError, PackageResolveErrorKind); +impl NodeJsErrorCoded for PackageResolveError { + fn code(&self) -> NodeJsErrorCode { + match self.as_kind() { + PackageResolveErrorKind::ClosestPkgJson(e) => e.code(), + PackageResolveErrorKind::InvalidModuleSpecifier(e) => e.code(), + PackageResolveErrorKind::ExportsResolve(e) => e.code(), + PackageResolveErrorKind::SubpathResolve(e) => e.code(), + } + } +} + #[derive(Debug, Error)] pub enum PackageResolveErrorKind { #[error(transparent)] @@ -298,7 +501,8 @@ pub enum FinalizeResolutionErrorKind { #[derive(Debug, Error)] #[error( - "[ERR_MODULE_NOT_FOUND] Cannot find {} '{}'{}", + "[{}] Cannot find {} '{}'{}", + self.code(), typ, specifier, maybe_referrer.as_ref().map(|referrer| format!(" imported from '{}'", referrer)).unwrap_or_default() @@ -309,9 +513,16 @@ pub struct ModuleNotFoundError { pub typ: &'static str, } +impl ModuleNotFoundError { + pub fn code(&self) -> &'static str { + "ERR_MODULE_NOT_FOUND" + } +} + #[derive(Debug, Error)] #[error( - "[ERR_UNSUPPORTED_DIR_IMPORT] Directory import '{}' is not supported resolving ES modules{}", + "[{}] Directory import '{}' is not supported resolving ES modules{}", + self.code(), dir_url, maybe_referrer.as_ref().map(|referrer| format!(" imported from '{}'", referrer)).unwrap_or_default(), )] @@ -320,6 +531,12 @@ pub struct UnsupportedDirImportError { pub maybe_referrer: Option, } +impl NodeJsErrorCoded for UnsupportedDirImportError { + fn code(&self) -> NodeJsErrorCode { + NodeJsErrorCode::ERR_UNSUPPORTED_DIR_IMPORT + } +} + #[derive(Debug)] pub struct InvalidPackageTargetError { pub pkg_json_path: PathBuf, @@ -336,7 +553,9 @@ impl std::fmt::Display for InvalidPackageTargetError { let rel_error = !self.is_import && !self.target.is_empty() && !self.target.starts_with("./"); - f.write_str("[ERR_INVALID_PACKAGE_TARGET]")?; + f.write_char('[')?; + f.write_str(self.code().as_str())?; + f.write_char(']')?; if self.sub_path == "." { assert!(!self.is_import); @@ -368,6 +587,12 @@ impl std::fmt::Display for InvalidPackageTargetError { } } +impl NodeJsErrorCoded for InvalidPackageTargetError { + fn code(&self) -> NodeJsErrorCode { + NodeJsErrorCode::ERR_INVALID_PACKAGE_TARGET + } +} + #[derive(Debug)] pub struct PackagePathNotExportedError { pub pkg_json_path: PathBuf, @@ -376,11 +601,19 @@ pub struct PackagePathNotExportedError { pub mode: NodeResolutionMode, } +impl NodeJsErrorCoded for PackagePathNotExportedError { + fn code(&self) -> NodeJsErrorCode { + NodeJsErrorCode::ERR_PACKAGE_PATH_NOT_EXPORTED + } +} + impl std::error::Error for PackagePathNotExportedError {} impl std::fmt::Display for PackagePathNotExportedError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.write_str("[ERR_PACKAGE_PATH_NOT_EXPORTED]")?; + f.write_char('[')?; + f.write_str(self.code().as_str())?; + f.write_char(']')?; let types_msg = match self.mode { NodeResolutionMode::Execution => String::new(), @@ -412,7 +645,8 @@ impl std::fmt::Display for PackagePathNotExportedError { #[derive(Debug, Clone, Error)] #[error( - "[ERR_UNSUPPORTED_ESM_URL_SCHEME] Only file and data URLS are supported by the default ESM loader.{} Received protocol '{}'", + "[{}] Only file and data URLs are supported by the default ESM loader.{} Received protocol '{}'", + self.code(), if cfg!(windows) && url_scheme.len() == 2 { " On Windows, absolute path must be valid file:// URLS."} else { "" }, url_scheme )] @@ -420,10 +654,16 @@ pub struct UnsupportedEsmUrlSchemeError { pub url_scheme: String, } +impl NodeJsErrorCoded for UnsupportedEsmUrlSchemeError { + fn code(&self) -> NodeJsErrorCode { + NodeJsErrorCode::ERR_UNSUPPORTED_ESM_URL_SCHEME + } +} + #[derive(Debug, Error)] pub enum ResolvePkgJsonBinExportError { #[error(transparent)] - PkgJsonLoad(#[from] deno_config::package_json::PackageJsonLoadError), + PkgJsonLoad(#[from] PackageJsonLoadError), #[error("Failed resolving binary export. '{}' did not exist", pkg_json_path.display())] MissingPkgJson { pkg_json_path: PathBuf }, #[error("Failed resolving binary export. {message}")] @@ -435,31 +675,11 @@ pub enum ResolvePkgJsonBinExportError { #[derive(Debug, Error)] pub enum ResolveBinaryCommandsError { #[error(transparent)] - PkgJsonLoad(#[from] deno_config::package_json::PackageJsonLoadError), + PkgJsonLoad(#[from] PackageJsonLoadError), #[error("'{}' did not have a name", pkg_json_path.display())] MissingPkgJsonName { pkg_json_path: PathBuf }, } -#[allow(unused)] -pub fn err_invalid_package_config( - path: &str, - maybe_base: Option, - maybe_message: Option, -) -> AnyError { - let mut msg = - format!("[ERR_INVALID_PACKAGE_CONFIG] Invalid package config {path}"); - - if let Some(base) = maybe_base { - msg = format!("{msg} while importing {base}"); - } - - if let Some(message) = maybe_message { - msg = format!("{msg}. {message}"); - } - - generic_error(msg) -} - #[cfg(test)] mod test { use super::*; diff --git a/ext/node/package_json.rs b/ext/node/package_json.rs index 8a88fe8f10..b28207db8b 100644 --- a/ext/node/package_json.rs +++ b/ext/node/package_json.rs @@ -1,7 +1,6 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. use deno_config::package_json::PackageJson; -use deno_config::package_json::PackageJsonLoadError; use deno_config::package_json::PackageJsonRc; use deno_fs::DenoConfigFsAdapter; use std::cell::RefCell; @@ -10,6 +9,8 @@ use std::io::ErrorKind; use std::path::Path; use std::path::PathBuf; +use crate::errors::PackageJsonLoadError; + // use a thread local cache so that workers have their own distinct cache thread_local! { static CACHE: RefCell> = RefCell::new(HashMap::new()); @@ -48,11 +49,9 @@ pub fn load_pkg_json( ); match result { Ok(pkg_json) => Ok(Some(pkg_json)), - Err(PackageJsonLoadError::Io { source, .. }) - if source.kind() == ErrorKind::NotFound => - { - Ok(None) - } - Err(err) => Err(err), + Err(deno_config::package_json::PackageJsonLoadError::Io { + source, .. + }) if source.kind() == ErrorKind::NotFound => Ok(None), + Err(err) => Err(PackageJsonLoadError(err)), } } diff --git a/ext/node/resolution.rs b/ext/node/resolution.rs index 84d8ba39dd..cf30305a9f 100644 --- a/ext/node/resolution.rs +++ b/ext/node/resolution.rs @@ -16,18 +16,21 @@ use deno_fs::FileSystemRc; use deno_media_type::MediaType; use crate::errors; +use crate::errors::CanonicalizingPkgJsonDirError; use crate::errors::ClosestPkgJsonError; -use crate::errors::ClosestPkgJsonErrorKind; use crate::errors::FinalizeResolutionError; use crate::errors::InvalidModuleSpecifierError; use crate::errors::InvalidPackageTargetError; use crate::errors::LegacyMainResolveError; use crate::errors::ModuleNotFoundError; +use crate::errors::NodeJsErrorCode; +use crate::errors::NodeJsErrorCoded; use crate::errors::NodeResolveError; use crate::errors::PackageExportsResolveError; use crate::errors::PackageImportNotDefinedError; use crate::errors::PackageImportsResolveError; use crate::errors::PackageImportsResolveErrorKind; +use crate::errors::PackageJsonLoadError; use crate::errors::PackagePathNotExportedError; use crate::errors::PackageResolveError; use crate::errors::PackageSubpathResolveError; @@ -283,7 +286,7 @@ impl NodeResolver { let maybe_url = if mode.is_types() { let file_path = to_file_path(&url); - self.path_to_declaration_url(file_path, Some(referrer), referrer_kind)? + self.path_to_declaration_url(&file_path, Some(referrer), referrer_kind)? } else { Some(url) }; @@ -469,7 +472,7 @@ impl NodeResolver { /// Checks if the resolved file has a corresponding declaration file. fn path_to_declaration_url( &self, - path: PathBuf, + path: &Path, maybe_referrer: Option<&ModuleSpecifier>, referrer_kind: NodeModuleKind, ) -> Result, PathToDeclarationUrlError> { @@ -522,16 +525,16 @@ impl NodeResolver { || lowercase_path.ends_with(".d.cts") || lowercase_path.ends_with(".d.mts") { - return Ok(Some(to_file_specifier(&path))); + return Ok(Some(to_file_specifier(path))); } if let Some(path) = - probe_extensions(&*self.fs, &path, &lowercase_path, referrer_kind) + probe_extensions(&*self.fs, path, &lowercase_path, referrer_kind) { return Ok(Some(to_file_specifier(&path))); } - if self.fs.is_dir_sync(&path) { + if self.fs.is_dir_sync(path) { let maybe_resolution = self.resolve_package_dir_subpath( - &path, + path, /* sub path */ ".", maybe_referrer, referrer_kind, @@ -556,7 +559,7 @@ impl NodeResolver { } // allow resolving .css files for types resolution if lowercase_path.ends_with(".css") { - return Ok(Some(to_file_specifier(&path))); + return Ok(Some(to_file_specifier(path))); } Ok(None) } @@ -845,7 +848,7 @@ impl NodeResolver { if mode.is_types() && url.scheme() == "file" { let path = url.to_file_path().unwrap(); return Ok(self.path_to_declaration_url( - path, + &path, maybe_referrer, referrer_kind, )?); @@ -879,8 +882,7 @@ impl NodeResolver { continue; } Err(e) => { - // todo(dsherret): add codes to each error and match on that instead - if e.to_string().starts_with("[ERR_INVALID_PACKAGE_TARGET]") { + if e.code() == NodeJsErrorCode::ERR_INVALID_PACKAGE_TARGET { last_error = Some(e); continue; } else { @@ -1274,7 +1276,7 @@ impl NodeResolver { assert_ne!(package_subpath, "."); let file_path = directory.join(package_subpath); if mode.is_types() { - Ok(self.path_to_declaration_url(file_path, referrer, referrer_kind)?) + Ok(self.path_to_declaration_url(&file_path, referrer, referrer_kind)?) } else { Ok(Some(to_file_specifier(&file_path))) } @@ -1318,7 +1320,7 @@ impl NodeResolver { let parent_dir = file_path.parent().unwrap(); let current_dir = deno_core::strip_unc_prefix(self.fs.realpath_sync(parent_dir).map_err( - |source| ClosestPkgJsonErrorKind::CanonicalizingDir { + |source| CanonicalizingPkgJsonDirError { dir_path: parent_dir.to_path_buf(), source: source.into_io_error(), }, @@ -1336,10 +1338,7 @@ impl NodeResolver { pub(super) fn load_package_json( &self, package_json_path: &Path, - ) -> Result< - Option, - deno_config::package_json::PackageJsonLoadError, - > { + ) -> Result, PackageJsonLoadError> { crate::package_json::load_pkg_json(&*self.fs, package_json_path) } @@ -1359,7 +1358,7 @@ impl NodeResolver { if let Some(main) = package_json.main(referrer_kind) { let main = package_json.path.parent().unwrap().join(main).clean(); let maybe_decl_url = self - .path_to_declaration_url(main, maybe_referrer, referrer_kind) + .path_to_declaration_url(&main, maybe_referrer, referrer_kind) .map_err(LegacyMainResolveError::PathToDeclarationUrl)?; if let Some(path) = maybe_decl_url { return Ok(Some(path));