summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock5
-rw-r--r--cli/Cargo.toml2
-rw-r--r--core/01_core.js4
-rw-r--r--core/Cargo.toml1
-rw-r--r--core/error_codes.rs212
-rw-r--r--core/lib.rs1
-rw-r--r--core/ops.rs2
-rw-r--r--runtime/Cargo.toml2
8 files changed, 225 insertions, 4 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 36b6299f5..dc58dc695 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -744,6 +744,7 @@ dependencies = [
"futures",
"indexmap",
"lazy_static",
+ "libc",
"log",
"parking_lot",
"pin-project",
@@ -2021,9 +2022,9 @@ dependencies = [
[[package]]
name = "libc"
-version = "0.2.103"
+version = "0.2.106"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dd8f7255a17a627354f321ef0055d63b898c6fb27eff628af4d1b66b7331edf6"
+checksum = "a60553f9a9e039a333b4e9b20573b9e9b9c0bb3a11e201ccc48ef4283456d673"
[[package]]
name = "libffi"
diff --git a/cli/Cargo.toml b/cli/Cargo.toml
index 2e180a494..32527180b 100644
--- a/cli/Cargo.toml
+++ b/cli/Cargo.toml
@@ -62,7 +62,7 @@ http = "0.2.4"
import_map = "0.3.3"
jsonc-parser = { version = "0.17.0", features = ["serde"] }
lazy_static = "1.4.0"
-libc = "0.2.101"
+libc = "0.2.106"
log = { version = "0.4.14", features = ["serde"] }
lspower = "1.1.0"
notify = "5.0.0-pre.12"
diff --git a/core/01_core.js b/core/01_core.js
index 24b844453..9d4bab65d 100644
--- a/core/01_core.js
+++ b/core/01_core.js
@@ -119,6 +119,10 @@
const err = errorBuilder ? errorBuilder(res.message) : new Error(
`Unregistered error class: "${className}"\n ${res.message}\n Classes of errors returned from ops should be registered via Deno.core.registerErrorClass().`,
);
+ // Set .code if error was a known OS error, see error_codes.rs
+ if (res.code) {
+ err.code = res.code;
+ }
// Strip unwrapOpResult() and errorBuilder() calls from stack trace
ErrorCaptureStackTrace(err, unwrapOpResult);
throw err;
diff --git a/core/Cargo.toml b/core/Cargo.toml
index 0d3102988..698717778 100644
--- a/core/Cargo.toml
+++ b/core/Cargo.toml
@@ -18,6 +18,7 @@ futures = "0.3.16"
# TODO(lucacasonato): unlock when https://github.com/tkaitchuck/aHash/issues/95 is resolved
indexmap = "=1.6.2"
lazy_static = "1.4.0"
+libc = "0.2.106"
log = "0.4.14"
parking_lot = "0.11.1"
pin-project = "1.0.7"
diff --git a/core/error_codes.rs b/core/error_codes.rs
new file mode 100644
index 000000000..fc613426f
--- /dev/null
+++ b/core/error_codes.rs
@@ -0,0 +1,212 @@
+use crate::error::AnyError;
+
+pub(crate) fn get_error_code(err: &AnyError) -> Option<&'static str> {
+ err
+ .downcast_ref::<std::io::Error>()
+ .map(|e| match e.raw_os_error() {
+ Some(code) => get_os_error_code(code),
+ None => get_io_error_code(e),
+ })
+ .and_then(|code| match code.is_empty() {
+ true => None,
+ false => Some(code),
+ })
+}
+
+fn get_io_error_code(err: &std::io::Error) -> &'static str {
+ // not exhaustive but simple and possibly sufficient once `io_error_more` is stabilized (https://github.com/rust-lang/rust/issues/86442)
+ // inversion of https://github.com/rust-lang/rust/blob/dca3f1b786efd27be3b325ed1e01e247aa589c3b/library/std/src/sys/unix/mod.rs#L138-L185
+ // TODO(@AaronO): revisit as `io_error_more` lands in rust stable
+ use std::io::ErrorKind;
+ match err.kind() {
+ // ErrorKind::ArgumentListTooLong => "E2BIG",
+ ErrorKind::AddrInUse => "EADDRINUSE",
+ ErrorKind::AddrNotAvailable => "EADDRNOTAVAIL",
+ // ErrorKind::ResourceBusy => "EBUSY",
+ ErrorKind::ConnectionAborted => "ECONNABORTED",
+ ErrorKind::ConnectionRefused => "ECONNREFUSED",
+ ErrorKind::ConnectionReset => "ECONNRESET",
+ // ErrorKind::Deadlock => "EDEADLK",
+ // ErrorKind::FilesystemQuotaExceeded => "EDQUOT",
+ ErrorKind::AlreadyExists => "EEXIST",
+ // ErrorKind::FileTooLarge => "EFBIG",
+ // ErrorKind::HostUnreachable => "EHOSTUNREACH",
+ ErrorKind::Interrupted => "EINTR",
+ ErrorKind::InvalidInput => "EINVAL",
+ // ErrorKind::IsADirectory => "EISDIR",
+ // ErrorKind::FilesystemLoop => "ELOOP",
+ ErrorKind::NotFound => "ENOENT",
+ ErrorKind::OutOfMemory => "ENOMEM",
+ // ErrorKind::StorageFull => "ENOSPC",
+ ErrorKind::Unsupported => "ENOSYS",
+ // ErrorKind::TooManyLinks => "EMLINK",
+ // ErrorKind::FilenameTooLong => "ENAMETOOLONG",
+ // ErrorKind::NetworkDown => "ENETDOWN",
+ // ErrorKind::NetworkUnreachable => "ENETUNREACH",
+ ErrorKind::NotConnected => "ENOTCONN",
+ // ErrorKind::NotADirectory => "ENOTDIR",
+ // ErrorKind::DirectoryNotEmpty => "ENOTEMPTY",
+ ErrorKind::BrokenPipe => "EPIPE",
+ // ErrorKind::ReadOnlyFilesystem => "EROFS",
+ // ErrorKind::NotSeekable => "ESPIPE",
+ // ErrorKind::StaleNetworkFileHandle => "ESTALE",
+ ErrorKind::TimedOut => "ETIMEDOUT",
+ // ErrorKind::ExecutableFileBusy => "ETXTBSY",
+ // ErrorKind::CrossesDevices => "EXDEV",
+ ErrorKind::PermissionDenied => "EACCES", // NOTE: Collides with EPERM ...
+ _ => "",
+ }
+}
+
+/// Maps OS errno codes to string names
+/// derived from libuv: https://github.com/libuv/libuv/blob/26b2e5dbb6301756644d6e4cf6ca9c49c00513d3/include/uv/errno.h
+/// generated with tools/codegen_error_codes.js
+#[cfg(unix)]
+fn get_os_error_code(errno: i32) -> &'static str {
+ match errno {
+ libc::E2BIG => "E2BIG",
+ libc::EACCES => "EACCES",
+ libc::EADDRINUSE => "EADDRINUSE",
+ libc::EADDRNOTAVAIL => "EADDRNOTAVAIL",
+ libc::EAFNOSUPPORT => "EAFNOSUPPORT",
+ libc::EAGAIN => "EAGAIN",
+ libc::EALREADY => "EALREADY",
+ libc::EBADF => "EBADF",
+ libc::EBUSY => "EBUSY",
+ libc::ECANCELED => "ECANCELED",
+ libc::ECONNABORTED => "ECONNABORTED",
+ libc::ECONNREFUSED => "ECONNREFUSED",
+ libc::ECONNRESET => "ECONNRESET",
+ libc::EEXIST => "EEXIST",
+ libc::EFAULT => "EFAULT",
+ libc::EHOSTUNREACH => "EHOSTUNREACH",
+ libc::EINVAL => "EINVAL",
+ libc::EIO => "EIO",
+ libc::EISCONN => "EISCONN",
+ libc::EISDIR => "EISDIR",
+ libc::ELOOP => "ELOOP",
+ libc::EMFILE => "EMFILE",
+ libc::EMSGSIZE => "EMSGSIZE",
+ libc::ENAMETOOLONG => "ENAMETOOLONG",
+ libc::ENETUNREACH => "ENETUNREACH",
+ libc::ENOBUFS => "ENOBUFS",
+ libc::ENOENT => "ENOENT",
+ libc::ENOMEM => "ENOMEM",
+ libc::ENOSPC => "ENOSPC",
+ libc::ENOTCONN => "ENOTCONN",
+ libc::ENOTEMPTY => "ENOTEMPTY",
+ libc::ENOTSOCK => "ENOTSOCK",
+ libc::ENOTSUP => "ENOTSUP",
+ libc::EPERM => "EPERM",
+ libc::EPIPE => "EPIPE",
+ libc::EPROTONOSUPPORT => "EPROTONOSUPPORT",
+ libc::EROFS => "EROFS",
+ libc::ETIMEDOUT => "ETIMEDOUT",
+ libc::EXDEV => "EXDEV",
+ libc::ESOCKTNOSUPPORT => "ESOCKTNOSUPPORT",
+ _ => "",
+ }
+}
+
+#[cfg(windows)]
+fn get_os_error_code(errno: i32) -> &'static str {
+ match errno {
+ 998 => "EACCES", // ERROR_NOACCESS
+ 10013 => "EACCES", // WSAEACCES
+ 1920 => "EACCES", // ERROR_CANT_ACCESS_FILE
+ 1227 => "EADDRINUSE", // ERROR_ADDRESS_ALREADY_ASSOCIATED
+ 10048 => "EADDRINUSE", // WSAEADDRINUSE
+ 10049 => "EADDRNOTAVAIL", // WSAEADDRNOTAVAIL
+ 10047 => "EAFNOSUPPORT", // WSAEAFNOSUPPORT
+ 10035 => "EAGAIN", // WSAEWOULDBLOCK
+ 10037 => "EALREADY", // WSAEALREADY
+ 1004 => "EBADF", // ERROR_INVALID_FLAGS
+ 6 => "EBADF", // ERROR_INVALID_HANDLE
+ 33 => "EBUSY", // ERROR_LOCK_VIOLATION
+ 231 => "EBUSY", // ERROR_PIPE_BUSY
+ 32 => "EBUSY", // ERROR_SHARING_VIOLATION
+ 995 => "ECANCELED", // ERROR_OPERATION_ABORTED
+ 10004 => "ECANCELED", // WSAEINTR
+ 1236 => "ECONNABORTED", // ERROR_CONNECTION_ABORTED
+ 10053 => "ECONNABORTED", // WSAECONNABORTED
+ 1225 => "ECONNREFUSED", // ERROR_CONNECTION_REFUSED
+ 10061 => "ECONNREFUSED", // WSAECONNREFUSED
+ 64 => "ECONNRESET", // ERROR_NETNAME_DELETED
+ 10054 => "ECONNRESET", // WSAECONNRESET
+ 183 => "EEXIST", // ERROR_ALREADY_EXISTS
+ 80 => "EEXIST", // ERROR_FILE_EXISTS
+ 111 => "EFAULT", // ERROR_BUFFER_OVERFLOW
+ 10014 => "EFAULT", // WSAEFAULT
+ 1232 => "EHOSTUNREACH", // ERROR_HOST_UNREACHABLE
+ 10065 => "EHOSTUNREACH", // WSAEHOSTUNREACH
+ 122 => "EINVAL", // ERROR_INSUFFICIENT_BUFFER
+ 13 => "EINVAL", // ERROR_INVALID_DATA
+ 87 => "EINVAL", // ERROR_INVALID_PARAMETER
+ 1464 => "EINVAL", // ERROR_SYMLINK_NOT_SUPPORTED
+ 10022 => "EINVAL", // WSAEINVAL
+ 10046 => "EINVAL", // WSAEPFNOSUPPORT
+ 1102 => "EIO", // ERROR_BEGINNING_OF_MEDIA
+ 1111 => "EIO", // ERROR_BUS_RESET
+ 23 => "EIO", // ERROR_CRC
+ 1166 => "EIO", // ERROR_DEVICE_DOOR_OPEN
+ 1165 => "EIO", // ERROR_DEVICE_REQUIRES_CLEANING
+ 1393 => "EIO", // ERROR_DISK_CORRUPT
+ 1129 => "EIO", // ERROR_EOM_OVERFLOW
+ 1101 => "EIO", // ERROR_FILEMARK_DETECTED
+ 31 => "EIO", // ERROR_GEN_FAILURE
+ 1106 => "EIO", // ERROR_INVALID_BLOCK_LENGTH
+ 1117 => "EIO", // ERROR_IO_DEVICE
+ 1104 => "EIO", // ERROR_NO_DATA_DETECTED
+ 205 => "EIO", // ERROR_NO_SIGNAL_SENT
+ 110 => "EIO", // ERROR_OPEN_FAILED
+ 1103 => "EIO", // ERROR_SETMARK_DETECTED
+ 156 => "EIO", // ERROR_SIGNAL_REFUSED
+ 10056 => "EISCONN", // WSAEISCONN
+ 1921 => "ELOOP", // ERROR_CANT_RESOLVE_FILENAME
+ 4 => "EMFILE", // ERROR_TOO_MANY_OPEN_FILES
+ 10024 => "EMFILE", // WSAEMFILE
+ 10040 => "EMSGSIZE", // WSAEMSGSIZE
+ 206 => "ENAMETOOLONG", // ERROR_FILENAME_EXCED_RANGE
+ 1231 => "ENETUNREACH", // ERROR_NETWORK_UNREACHABLE
+ 10051 => "ENETUNREACH", // WSAENETUNREACH
+ 10055 => "ENOBUFS", // WSAENOBUFS
+ 161 => "ENOENT", // ERROR_BAD_PATHNAME
+ 267 => "ENOENT", // ERROR_DIRECTORY
+ 203 => "ENOENT", // ERROR_ENVVAR_NOT_FOUND
+ 2 => "ENOENT", // ERROR_FILE_NOT_FOUND
+ 123 => "ENOENT", // ERROR_INVALID_NAME
+ 15 => "ENOENT", // ERROR_INVALID_DRIVE
+ 4392 => "ENOENT", // ERROR_INVALID_REPARSE_DATA
+ 126 => "ENOENT", // ERROR_MOD_NOT_FOUND
+ 3 => "ENOENT", // ERROR_PATH_NOT_FOUND
+ 11001 => "ENOENT", // WSAHOST_NOT_FOUND
+ 11004 => "ENOENT", // WSANO_DATA
+ 8 => "ENOMEM", // ERROR_NOT_ENOUGH_MEMORY
+ 14 => "ENOMEM", // ERROR_OUTOFMEMORY
+ 82 => "ENOSPC", // ERROR_CANNOT_MAKE
+ 112 => "ENOSPC", // ERROR_DISK_FULL
+ 277 => "ENOSPC", // ERROR_EA_TABLE_FULL
+ 1100 => "ENOSPC", // ERROR_END_OF_MEDIA
+ 39 => "ENOSPC", // ERROR_HANDLE_DISK_FULL
+ 2250 => "ENOTCONN", // ERROR_NOT_CONNECTED
+ 10057 => "ENOTCONN", // WSAENOTCONN
+ 145 => "ENOTEMPTY", // ERROR_DIR_NOT_EMPTY
+ 10038 => "ENOTSOCK", // WSAENOTSOCK
+ 50 => "ENOTSUP", // ERROR_NOT_SUPPORTED
+ 5 => "EPERM", // ERROR_ACCESS_DENIED
+ 1314 => "EPERM", // ERROR_PRIVILEGE_NOT_HELD
+ 230 => "EPIPE", // ERROR_BAD_PIPE
+ 232 => "EPIPE", // ERROR_NO_DATA
+ 233 => "EPIPE", // ERROR_PIPE_NOT_CONNECTED
+ 10058 => "EPIPE", // WSAESHUTDOWN
+ 10043 => "EPROTONOSUPPORT", // WSAEPROTONOSUPPORT
+ 19 => "EROFS", // ERROR_WRITE_PROTECT
+ 121 => "ETIMEDOUT", // ERROR_SEM_TIMEOUT
+ 10060 => "ETIMEDOUT", // WSAETIMEDOUT
+ 17 => "EXDEV", // ERROR_NOT_SAME_DEVICE
+ 1 => "EISDIR", // ERROR_INVALID_FUNCTION
+ 208 => "E2BIG", // ERROR_META_EXPANSION_TOO_LONG
+ 10044 => "ESOCKTNOSUPPORT", // WSAESOCKTNOSUPPORT
+ _ => "",
+ }
+}
diff --git a/core/lib.rs b/core/lib.rs
index eff1397cf..abf702813 100644
--- a/core/lib.rs
+++ b/core/lib.rs
@@ -3,6 +3,7 @@ mod async_cancel;
mod async_cell;
mod bindings;
pub mod error;
+mod error_codes;
mod extensions;
mod flags;
mod gotham_state;
diff --git a/core/ops.rs b/core/ops.rs
index ab233ef29..f62fe7a8e 100644
--- a/core/ops.rs
+++ b/core/ops.rs
@@ -140,6 +140,7 @@ pub struct OpError {
#[serde(rename = "$err_class_name")]
class_name: &'static str,
message: String,
+ code: Option<&'static str>,
}
pub fn serialize_op_result<R: Serialize + 'static>(
@@ -151,6 +152,7 @@ pub fn serialize_op_result<R: Serialize + 'static>(
Err(err) => OpResult::Err(OpError {
class_name: (state.borrow().get_error_class_fn)(&err),
message: err.to_string(),
+ code: crate::error_codes::get_error_code(&err),
}),
}
}
diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml
index 60f11d703..fd09a9bc3 100644
--- a/runtime/Cargo.toml
+++ b/runtime/Cargo.toml
@@ -69,7 +69,7 @@ fs3 = "0.5.0"
http = "0.2.4"
hyper = { version = "0.14.12", features = ["server", "stream", "http1", "http2", "runtime"] }
lazy_static = "1.4.0"
-libc = "0.2.101"
+libc = "0.2.106"
log = "0.4.14"
notify = "=5.0.0-pre.12"
regex = "1.5.4"