summaryrefslogtreecommitdiff
path: root/ext/node/errors.rs
diff options
context:
space:
mode:
Diffstat (limited to 'ext/node/errors.rs')
-rw-r--r--ext/node/errors.rs302
1 files changed, 261 insertions, 41 deletions
diff --git a/ext/node/errors.rs b/ext/node/errors.rs
index 560336d68..98b207e86 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<String>,
}
+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<ModuleSpecifier>,
}
+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<ModuleSpecifier>,
}
+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<String>,
- maybe_message: Option<String>,
-) -> 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::*;