summaryrefslogtreecommitdiff
path: root/runtime/errors.rs
diff options
context:
space:
mode:
authorBartek IwaƄczuk <biwanczuk@gmail.com>2020-12-13 19:45:53 +0100
committerGitHub <noreply@github.com>2020-12-13 19:45:53 +0100
commit2e74f164b6dcf0ecbf8dd38fba9fae550d784bd0 (patch)
tree61abe8e09d5331ace5d9de529f0e2737a8e05dbb /runtime/errors.rs
parent84ef9bd21fb48fb6b5fbc8dafc3de9f361bade3b (diff)
refactor: deno_runtime crate (#8640)
This commit moves Deno JS runtime, ops, permissions and inspector implementation to new "deno_runtime" crate located in "runtime/" directory. Details in "runtime/README.md". Co-authored-by: Ryan Dahl <ry@tinyclouds.org>
Diffstat (limited to 'runtime/errors.rs')
-rw-r--r--runtime/errors.rs209
1 files changed, 209 insertions, 0 deletions
diff --git a/runtime/errors.rs b/runtime/errors.rs
new file mode 100644
index 000000000..f8f71a859
--- /dev/null
+++ b/runtime/errors.rs
@@ -0,0 +1,209 @@
+// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
+
+//! There are many types of errors in Deno:
+//! - AnyError: a generic wrapper that can encapsulate any type of error.
+//! - JsError: a container for the error message and stack trace for exceptions
+//! thrown in JavaScript code. We use this to pretty-print stack traces.
+//! - Diagnostic: these are errors that originate in TypeScript's compiler.
+//! They're similar to JsError, in that they have line numbers. But
+//! Diagnostics are compile-time type errors, whereas JsErrors are runtime
+//! exceptions.
+
+use deno_core::error::AnyError;
+use deno_core::serde_json;
+use deno_core::url;
+use deno_core::ModuleResolutionError;
+use deno_fetch::reqwest;
+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_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: &notify::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: &regex::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 {
+ use deno_core::serde_json::error::*;
+ 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",
+ }
+}
+
+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 {
+ nix::Error::Sys(ECHILD) => "NotFound",
+ nix::Error::Sys(EINVAL) => "TypeError",
+ nix::Error::Sys(ENOENT) => "NotFound",
+ nix::Error::Sys(ENOTTY) => "BadResource",
+ nix::Error::Sys(EPERM) => "PermissionDenied",
+ nix::Error::Sys(ESRCH) => "NotFound",
+ nix::Error::Sys(UnknownErrno) => "Error",
+ nix::Error::Sys(_) => "Error",
+ nix::Error::InvalidPath => "TypeError",
+ nix::Error::InvalidUtf8 => "InvalidData",
+ nix::Error::UnsupportedOperation => unreachable!(),
+ }
+}
+
+pub fn get_error_class_name(e: &AnyError) -> Option<&'static str> {
+ deno_core::error::get_custom_error_class(e)
+ .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::<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::<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)()
+ })
+}