2020-08-25 22:22:15 +00:00
|
|
|
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
|
|
|
|
|
|
|
//! There are many types of errors in Deno:
|
2020-09-14 16:48:57 +00:00
|
|
|
//! - AnyError: a generic wrapper that can encapsulate any type of error.
|
2020-09-06 19:44:29 +00:00
|
|
|
//! - JsError: a container for the error message and stack trace for exceptions
|
2020-08-25 22:22:15 +00:00
|
|
|
//! thrown in JavaScript code. We use this to pretty-print stack traces.
|
|
|
|
//! - Diagnostic: these are errors that originate in TypeScript's compiler.
|
2020-09-14 16:48:57 +00:00
|
|
|
//! They're similar to JsError, in that they have line numbers. But
|
|
|
|
//! Diagnostics are compile-time type errors, whereas JsErrors are runtime
|
2020-08-25 22:22:15 +00:00
|
|
|
//! exceptions.
|
|
|
|
|
2020-09-14 12:27:44 +00:00
|
|
|
use crate::ast::DiagnosticBuffer;
|
2020-08-25 22:22:15 +00:00
|
|
|
use crate::import_map::ImportMapError;
|
2020-09-14 16:48:57 +00:00
|
|
|
use deno_core::error::AnyError;
|
2020-09-21 16:36:37 +00:00
|
|
|
use deno_core::serde_json;
|
2020-09-16 18:28:07 +00:00
|
|
|
use deno_core::url;
|
2020-08-25 22:22:15 +00:00
|
|
|
use deno_core::ModuleResolutionError;
|
2020-09-18 17:07:09 +00:00
|
|
|
use deno_fetch::reqwest;
|
2020-08-25 22:22:15 +00:00
|
|
|
use rustyline::error::ReadlineError;
|
|
|
|
use std::env;
|
|
|
|
use std::error::Error;
|
|
|
|
use std::io;
|
|
|
|
|
|
|
|
fn get_dlopen_error_class(error: &dlopen::Error) -> &'static str {
|
|
|
|
use dlopen::Error::*;
|
|
|
|
match error {
|
|
|
|
NullCharacter(_) => "InvalidData",
|
|
|
|
OpeningLibraryError(ref e) => get_io_error_class(e),
|
|
|
|
SymbolGettingError(ref e) => get_io_error_class(e),
|
|
|
|
AddrNotMatchingDll(ref e) => get_io_error_class(e),
|
|
|
|
NullSymbol => "NotFound",
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn get_env_var_error_class(error: &env::VarError) -> &'static str {
|
|
|
|
use env::VarError::*;
|
|
|
|
match error {
|
|
|
|
NotPresent => "NotFound",
|
|
|
|
NotUnicode(..) => "InvalidData",
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn get_import_map_error_class(_: &ImportMapError) -> &'static str {
|
|
|
|
"URIError"
|
|
|
|
}
|
|
|
|
|
|
|
|
fn get_io_error_class(error: &io::Error) -> &'static str {
|
|
|
|
use io::ErrorKind::*;
|
|
|
|
match error.kind() {
|
|
|
|
NotFound => "NotFound",
|
|
|
|
PermissionDenied => "PermissionDenied",
|
|
|
|
ConnectionRefused => "ConnectionRefused",
|
|
|
|
ConnectionReset => "ConnectionReset",
|
|
|
|
ConnectionAborted => "ConnectionAborted",
|
|
|
|
NotConnected => "NotConnected",
|
|
|
|
AddrInUse => "AddrInUse",
|
|
|
|
AddrNotAvailable => "AddrNotAvailable",
|
|
|
|
BrokenPipe => "BrokenPipe",
|
|
|
|
AlreadyExists => "AlreadyExists",
|
|
|
|
InvalidInput => "TypeError",
|
|
|
|
InvalidData => "InvalidData",
|
|
|
|
TimedOut => "TimedOut",
|
|
|
|
Interrupted => "Interrupted",
|
|
|
|
WriteZero => "WriteZero",
|
|
|
|
UnexpectedEof => "UnexpectedEof",
|
|
|
|
Other => "Error",
|
|
|
|
WouldBlock => unreachable!(),
|
|
|
|
// Non-exhaustive enum - might add new variants
|
|
|
|
// in the future
|
|
|
|
_ => unreachable!(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn get_module_resolution_error_class(
|
|
|
|
_: &ModuleResolutionError,
|
|
|
|
) -> &'static str {
|
|
|
|
"URIError"
|
|
|
|
}
|
|
|
|
|
|
|
|
fn get_notify_error_class(error: ¬ify::Error) -> &'static str {
|
|
|
|
use notify::ErrorKind::*;
|
|
|
|
match error.kind {
|
|
|
|
Generic(_) => "Error",
|
|
|
|
Io(ref e) => get_io_error_class(e),
|
|
|
|
PathNotFound => "NotFound",
|
|
|
|
WatchNotFound => "NotFound",
|
|
|
|
InvalidConfig(_) => "InvalidData",
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn get_readline_error_class(error: &ReadlineError) -> &'static str {
|
|
|
|
use ReadlineError::*;
|
|
|
|
match error {
|
|
|
|
Io(err) => get_io_error_class(err),
|
|
|
|
Eof => "UnexpectedEof",
|
|
|
|
Interrupted => "Interrupted",
|
|
|
|
#[cfg(unix)]
|
|
|
|
Errno(err) => get_nix_error_class(err),
|
|
|
|
_ => unimplemented!(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn get_regex_error_class(error: ®ex::Error) -> &'static str {
|
|
|
|
use regex::Error::*;
|
|
|
|
match error {
|
|
|
|
Syntax(_) => "SyntaxError",
|
|
|
|
CompiledTooBig(_) => "RangeError",
|
|
|
|
_ => "Error",
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn get_request_error_class(error: &reqwest::Error) -> &'static str {
|
|
|
|
error
|
|
|
|
.source()
|
|
|
|
.and_then(|inner_err| {
|
|
|
|
(inner_err
|
|
|
|
.downcast_ref::<io::Error>()
|
|
|
|
.map(get_io_error_class))
|
|
|
|
.or_else(|| {
|
|
|
|
inner_err
|
|
|
|
.downcast_ref::<serde_json::error::Error>()
|
|
|
|
.map(get_serde_json_error_class)
|
|
|
|
})
|
|
|
|
.or_else(|| {
|
|
|
|
inner_err
|
|
|
|
.downcast_ref::<url::ParseError>()
|
|
|
|
.map(get_url_parse_error_class)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
.unwrap_or("Http")
|
|
|
|
}
|
|
|
|
|
|
|
|
fn get_serde_json_error_class(
|
|
|
|
error: &serde_json::error::Error,
|
|
|
|
) -> &'static str {
|
2020-09-21 16:36:37 +00:00
|
|
|
use deno_core::serde_json::error::*;
|
2020-08-25 22:22:15 +00:00
|
|
|
match error.classify() {
|
|
|
|
Category::Io => error
|
|
|
|
.source()
|
|
|
|
.and_then(|e| e.downcast_ref::<io::Error>())
|
|
|
|
.map(get_io_error_class)
|
|
|
|
.unwrap(),
|
|
|
|
Category::Syntax => "SyntaxError",
|
|
|
|
Category::Data => "InvalidData",
|
|
|
|
Category::Eof => "UnexpectedEof",
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-14 12:27:44 +00:00
|
|
|
fn get_diagnostic_class(_: &DiagnosticBuffer) -> &'static str {
|
2020-08-25 22:22:15 +00:00
|
|
|
"SyntaxError"
|
|
|
|
}
|
|
|
|
|
|
|
|
fn get_url_parse_error_class(_error: &url::ParseError) -> &'static str {
|
|
|
|
"URIError"
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(unix)]
|
|
|
|
fn get_nix_error_class(error: &nix::Error) -> &'static str {
|
|
|
|
use nix::errno::Errno::*;
|
|
|
|
match error {
|
2020-09-09 20:40:16 +00:00
|
|
|
nix::Error::Sys(ECHILD) => "NotFound",
|
2020-08-25 22:22:15 +00:00
|
|
|
nix::Error::Sys(EINVAL) => "TypeError",
|
|
|
|
nix::Error::Sys(ENOENT) => "NotFound",
|
|
|
|
nix::Error::Sys(ENOTTY) => "BadResource",
|
2020-09-09 20:40:16 +00:00
|
|
|
nix::Error::Sys(EPERM) => "PermissionDenied",
|
|
|
|
nix::Error::Sys(ESRCH) => "NotFound",
|
|
|
|
nix::Error::Sys(UnknownErrno) => "Error",
|
|
|
|
nix::Error::Sys(_) => "Error",
|
2020-08-25 22:22:15 +00:00
|
|
|
nix::Error::InvalidPath => "TypeError",
|
|
|
|
nix::Error::InvalidUtf8 => "InvalidData",
|
|
|
|
nix::Error::UnsupportedOperation => unreachable!(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-14 16:48:57 +00:00
|
|
|
pub(crate) fn get_error_class_name(e: &AnyError) -> &'static str {
|
2020-09-15 14:24:13 +00:00
|
|
|
deno_core::error::get_custom_error_class(e)
|
2020-09-14 16:48:57 +00:00
|
|
|
.or_else(|| {
|
|
|
|
e.downcast_ref::<dlopen::Error>()
|
|
|
|
.map(get_dlopen_error_class)
|
|
|
|
})
|
|
|
|
.or_else(|| {
|
|
|
|
e.downcast_ref::<env::VarError>()
|
|
|
|
.map(get_env_var_error_class)
|
|
|
|
})
|
|
|
|
.or_else(|| {
|
|
|
|
e.downcast_ref::<ImportMapError>()
|
|
|
|
.map(get_import_map_error_class)
|
|
|
|
})
|
|
|
|
.or_else(|| e.downcast_ref::<io::Error>().map(get_io_error_class))
|
|
|
|
.or_else(|| {
|
|
|
|
e.downcast_ref::<ModuleResolutionError>()
|
|
|
|
.map(get_module_resolution_error_class)
|
|
|
|
})
|
|
|
|
.or_else(|| {
|
|
|
|
e.downcast_ref::<notify::Error>()
|
|
|
|
.map(get_notify_error_class)
|
|
|
|
})
|
|
|
|
.or_else(|| {
|
|
|
|
e.downcast_ref::<ReadlineError>()
|
|
|
|
.map(get_readline_error_class)
|
|
|
|
})
|
|
|
|
.or_else(|| {
|
|
|
|
e.downcast_ref::<reqwest::Error>()
|
|
|
|
.map(get_request_error_class)
|
|
|
|
})
|
|
|
|
.or_else(|| e.downcast_ref::<regex::Error>().map(get_regex_error_class))
|
|
|
|
.or_else(|| {
|
|
|
|
e.downcast_ref::<serde_json::error::Error>()
|
|
|
|
.map(get_serde_json_error_class)
|
|
|
|
})
|
|
|
|
.or_else(|| {
|
|
|
|
e.downcast_ref::<DiagnosticBuffer>()
|
|
|
|
.map(get_diagnostic_class)
|
|
|
|
})
|
|
|
|
.or_else(|| {
|
|
|
|
e.downcast_ref::<url::ParseError>()
|
|
|
|
.map(get_url_parse_error_class)
|
|
|
|
})
|
|
|
|
.or_else(|| {
|
|
|
|
#[cfg(unix)]
|
|
|
|
let maybe_get_nix_error_class =
|
|
|
|
|| e.downcast_ref::<nix::Error>().map(get_nix_error_class);
|
|
|
|
#[cfg(not(unix))]
|
|
|
|
let maybe_get_nix_error_class = || Option::<&'static str>::None;
|
|
|
|
(maybe_get_nix_error_class)()
|
|
|
|
})
|
|
|
|
.unwrap_or_else(|| {
|
|
|
|
panic!("Error '{}' contains boxed error of unknown type", e);
|
|
|
|
})
|
2020-08-25 22:22:15 +00:00
|
|
|
}
|