summaryrefslogtreecommitdiff
path: root/std/node
diff options
context:
space:
mode:
Diffstat (limited to 'std/node')
-rw-r--r--std/node/_errors.ts296
-rw-r--r--std/node/util.ts18
-rw-r--r--std/node/util_test.ts40
3 files changed, 352 insertions, 2 deletions
diff --git a/std/node/_errors.ts b/std/node/_errors.ts
index 2321bb24f..864f1252b 100644
--- a/std/node/_errors.ts
+++ b/std/node/_errors.ts
@@ -21,7 +21,10 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
+import { unreachable } from "../testing/asserts.ts";
+
// It will do so until we'll have Node errors completely ported (#5944):
+
// Ref: https://github.com/nodejs/node/blob/50d28d4b3a616b04537feff014aa70437f064e30/lib/internal/errors.js#L251
// Ref: https://github.com/nodejs/node/blob/50d28d4b3a616b04537feff014aa70437f064e30/lib/internal/errors.js#L299
// Ref: https://github.com/nodejs/node/blob/50d28d4b3a616b04537feff014aa70437f064e30/lib/internal/errors.js#L325
@@ -43,6 +46,299 @@ class ERR_INVALID_ARG_TYPE extends TypeError {
}
}
+class ERR_OUT_OF_RANGE extends RangeError {
+ code = "ERR_OUT_OF_RANGE";
+
+ constructor(str: string, range: string, received: unknown) {
+ super(
+ `The value of "${str}" is out of range. It must be ${range}. Received ${received}`,
+ );
+
+ const { name } = this;
+ // Add the error code to the name to include it in the stack trace.
+ this.name = `${name} [${this.code}]`;
+ // Access the stack to generate the error message including the error code from the name.
+ this.stack;
+ // Reset the name to the actual name.
+ this.name = name;
+ }
+}
+
export const codes = {
ERR_INVALID_ARG_TYPE,
+ ERR_OUT_OF_RANGE,
};
+
+// In Node these values are coming from libuv:
+// Ref: https://github.com/libuv/libuv/blob/v1.x/include/uv/errno.h
+// Ref: https://github.com/nodejs/node/blob/524123fbf064ff64bb6fcd83485cfc27db932f68/lib/internal/errors.js#L383
+// Since there is no easy way to port code from libuv and these maps are
+// changing very rarely, we simply extract them from Node and store here.
+
+// Note
+// Run the following to get the map:
+// $ node -e "console.log(process.binding('uv').getErrorMap())"
+// This setup automatically exports maps from both "win", "linux" & darwin:
+// https://github.com/schwarzkopfb/node_errno_map
+
+type ErrMapData = Array<[number, [string, string]]>;
+
+const windows: ErrMapData = [
+ [-4093, ["E2BIG", "argument list too long"]],
+ [-4092, ["EACCES", "permission denied"]],
+ [-4091, ["EADDRINUSE", "address already in use"]],
+ [-4090, ["EADDRNOTAVAIL", "address not available"]],
+ [-4089, ["EAFNOSUPPORT", "address family not supported"]],
+ [-4088, ["EAGAIN", "resource temporarily unavailable"]],
+ [-3000, ["EAI_ADDRFAMILY", "address family not supported"]],
+ [-3001, ["EAI_AGAIN", "temporary failure"]],
+ [-3002, ["EAI_BADFLAGS", "bad ai_flags value"]],
+ [-3013, ["EAI_BADHINTS", "invalid value for hints"]],
+ [-3003, ["EAI_CANCELED", "request canceled"]],
+ [-3004, ["EAI_FAIL", "permanent failure"]],
+ [-3005, ["EAI_FAMILY", "ai_family not supported"]],
+ [-3006, ["EAI_MEMORY", "out of memory"]],
+ [-3007, ["EAI_NODATA", "no address"]],
+ [-3008, ["EAI_NONAME", "unknown node or service"]],
+ [-3009, ["EAI_OVERFLOW", "argument buffer overflow"]],
+ [-3014, ["EAI_PROTOCOL", "resolved protocol is unknown"]],
+ [-3010, ["EAI_SERVICE", "service not available for socket type"]],
+ [-3011, ["EAI_SOCKTYPE", "socket type not supported"]],
+ [-4084, ["EALREADY", "connection already in progress"]],
+ [-4083, ["EBADF", "bad file descriptor"]],
+ [-4082, ["EBUSY", "resource busy or locked"]],
+ [-4081, ["ECANCELED", "operation canceled"]],
+ [-4080, ["ECHARSET", "invalid Unicode character"]],
+ [-4079, ["ECONNABORTED", "software caused connection abort"]],
+ [-4078, ["ECONNREFUSED", "connection refused"]],
+ [-4077, ["ECONNRESET", "connection reset by peer"]],
+ [-4076, ["EDESTADDRREQ", "destination address required"]],
+ [-4075, ["EEXIST", "file already exists"]],
+ [-4074, ["EFAULT", "bad address in system call argument"]],
+ [-4036, ["EFBIG", "file too large"]],
+ [-4073, ["EHOSTUNREACH", "host is unreachable"]],
+ [-4072, ["EINTR", "interrupted system call"]],
+ [-4071, ["EINVAL", "invalid argument"]],
+ [-4070, ["EIO", "i/o error"]],
+ [-4069, ["EISCONN", "socket is already connected"]],
+ [-4068, ["EISDIR", "illegal operation on a directory"]],
+ [-4067, ["ELOOP", "too many symbolic links encountered"]],
+ [-4066, ["EMFILE", "too many open files"]],
+ [-4065, ["EMSGSIZE", "message too long"]],
+ [-4064, ["ENAMETOOLONG", "name too long"]],
+ [-4063, ["ENETDOWN", "network is down"]],
+ [-4062, ["ENETUNREACH", "network is unreachable"]],
+ [-4061, ["ENFILE", "file table overflow"]],
+ [-4060, ["ENOBUFS", "no buffer space available"]],
+ [-4059, ["ENODEV", "no such device"]],
+ [-4058, ["ENOENT", "no such file or directory"]],
+ [-4057, ["ENOMEM", "not enough memory"]],
+ [-4056, ["ENONET", "machine is not on the network"]],
+ [-4035, ["ENOPROTOOPT", "protocol not available"]],
+ [-4055, ["ENOSPC", "no space left on device"]],
+ [-4054, ["ENOSYS", "function not implemented"]],
+ [-4053, ["ENOTCONN", "socket is not connected"]],
+ [-4052, ["ENOTDIR", "not a directory"]],
+ [-4051, ["ENOTEMPTY", "directory not empty"]],
+ [-4050, ["ENOTSOCK", "socket operation on non-socket"]],
+ [-4049, ["ENOTSUP", "operation not supported on socket"]],
+ [-4048, ["EPERM", "operation not permitted"]],
+ [-4047, ["EPIPE", "broken pipe"]],
+ [-4046, ["EPROTO", "protocol error"]],
+ [-4045, ["EPROTONOSUPPORT", "protocol not supported"]],
+ [-4044, ["EPROTOTYPE", "protocol wrong type for socket"]],
+ [-4034, ["ERANGE", "result too large"]],
+ [-4043, ["EROFS", "read-only file system"]],
+ [-4042, ["ESHUTDOWN", "cannot send after transport endpoint shutdown"]],
+ [-4041, ["ESPIPE", "invalid seek"]],
+ [-4040, ["ESRCH", "no such process"]],
+ [-4039, ["ETIMEDOUT", "connection timed out"]],
+ [-4038, ["ETXTBSY", "text file is busy"]],
+ [-4037, ["EXDEV", "cross-device link not permitted"]],
+ [-4094, ["UNKNOWN", "unknown error"]],
+ [-4095, ["EOF", "end of file"]],
+ [-4033, ["ENXIO", "no such device or address"]],
+ [-4032, ["EMLINK", "too many links"]],
+ [-4031, ["EHOSTDOWN", "host is down"]],
+ [-4030, ["EREMOTEIO", "remote I/O error"]],
+ [-4029, ["ENOTTY", "inappropriate ioctl for device"]],
+ [-4028, ["EFTYPE", "inappropriate file type or format"]],
+ [-4027, ["EILSEQ", "illegal byte sequence"]],
+];
+
+const darwin: ErrMapData = [
+ [-7, ["E2BIG", "argument list too long"]],
+ [-13, ["EACCES", "permission denied"]],
+ [-48, ["EADDRINUSE", "address already in use"]],
+ [-49, ["EADDRNOTAVAIL", "address not available"]],
+ [-47, ["EAFNOSUPPORT", "address family not supported"]],
+ [-35, ["EAGAIN", "resource temporarily unavailable"]],
+ [-3000, ["EAI_ADDRFAMILY", "address family not supported"]],
+ [-3001, ["EAI_AGAIN", "temporary failure"]],
+ [-3002, ["EAI_BADFLAGS", "bad ai_flags value"]],
+ [-3013, ["EAI_BADHINTS", "invalid value for hints"]],
+ [-3003, ["EAI_CANCELED", "request canceled"]],
+ [-3004, ["EAI_FAIL", "permanent failure"]],
+ [-3005, ["EAI_FAMILY", "ai_family not supported"]],
+ [-3006, ["EAI_MEMORY", "out of memory"]],
+ [-3007, ["EAI_NODATA", "no address"]],
+ [-3008, ["EAI_NONAME", "unknown node or service"]],
+ [-3009, ["EAI_OVERFLOW", "argument buffer overflow"]],
+ [-3014, ["EAI_PROTOCOL", "resolved protocol is unknown"]],
+ [-3010, ["EAI_SERVICE", "service not available for socket type"]],
+ [-3011, ["EAI_SOCKTYPE", "socket type not supported"]],
+ [-37, ["EALREADY", "connection already in progress"]],
+ [-9, ["EBADF", "bad file descriptor"]],
+ [-16, ["EBUSY", "resource busy or locked"]],
+ [-89, ["ECANCELED", "operation canceled"]],
+ [-4080, ["ECHARSET", "invalid Unicode character"]],
+ [-53, ["ECONNABORTED", "software caused connection abort"]],
+ [-61, ["ECONNREFUSED", "connection refused"]],
+ [-54, ["ECONNRESET", "connection reset by peer"]],
+ [-39, ["EDESTADDRREQ", "destination address required"]],
+ [-17, ["EEXIST", "file already exists"]],
+ [-14, ["EFAULT", "bad address in system call argument"]],
+ [-27, ["EFBIG", "file too large"]],
+ [-65, ["EHOSTUNREACH", "host is unreachable"]],
+ [-4, ["EINTR", "interrupted system call"]],
+ [-22, ["EINVAL", "invalid argument"]],
+ [-5, ["EIO", "i/o error"]],
+ [-56, ["EISCONN", "socket is already connected"]],
+ [-21, ["EISDIR", "illegal operation on a directory"]],
+ [-62, ["ELOOP", "too many symbolic links encountered"]],
+ [-24, ["EMFILE", "too many open files"]],
+ [-40, ["EMSGSIZE", "message too long"]],
+ [-63, ["ENAMETOOLONG", "name too long"]],
+ [-50, ["ENETDOWN", "network is down"]],
+ [-51, ["ENETUNREACH", "network is unreachable"]],
+ [-23, ["ENFILE", "file table overflow"]],
+ [-55, ["ENOBUFS", "no buffer space available"]],
+ [-19, ["ENODEV", "no such device"]],
+ [-2, ["ENOENT", "no such file or directory"]],
+ [-12, ["ENOMEM", "not enough memory"]],
+ [-4056, ["ENONET", "machine is not on the network"]],
+ [-42, ["ENOPROTOOPT", "protocol not available"]],
+ [-28, ["ENOSPC", "no space left on device"]],
+ [-78, ["ENOSYS", "function not implemented"]],
+ [-57, ["ENOTCONN", "socket is not connected"]],
+ [-20, ["ENOTDIR", "not a directory"]],
+ [-66, ["ENOTEMPTY", "directory not empty"]],
+ [-38, ["ENOTSOCK", "socket operation on non-socket"]],
+ [-45, ["ENOTSUP", "operation not supported on socket"]],
+ [-1, ["EPERM", "operation not permitted"]],
+ [-32, ["EPIPE", "broken pipe"]],
+ [-100, ["EPROTO", "protocol error"]],
+ [-43, ["EPROTONOSUPPORT", "protocol not supported"]],
+ [-41, ["EPROTOTYPE", "protocol wrong type for socket"]],
+ [-34, ["ERANGE", "result too large"]],
+ [-30, ["EROFS", "read-only file system"]],
+ [-58, ["ESHUTDOWN", "cannot send after transport endpoint shutdown"]],
+ [-29, ["ESPIPE", "invalid seek"]],
+ [-3, ["ESRCH", "no such process"]],
+ [-60, ["ETIMEDOUT", "connection timed out"]],
+ [-26, ["ETXTBSY", "text file is busy"]],
+ [-18, ["EXDEV", "cross-device link not permitted"]],
+ [-4094, ["UNKNOWN", "unknown error"]],
+ [-4095, ["EOF", "end of file"]],
+ [-6, ["ENXIO", "no such device or address"]],
+ [-31, ["EMLINK", "too many links"]],
+ [-64, ["EHOSTDOWN", "host is down"]],
+ [-4030, ["EREMOTEIO", "remote I/O error"]],
+ [-25, ["ENOTTY", "inappropriate ioctl for device"]],
+ [-79, ["EFTYPE", "inappropriate file type or format"]],
+ [-92, ["EILSEQ", "illegal byte sequence"]],
+];
+
+const linux: ErrMapData = [
+ [-7, ["E2BIG", "argument list too long"]],
+ [-13, ["EACCES", "permission denied"]],
+ [-98, ["EADDRINUSE", "address already in use"]],
+ [-99, ["EADDRNOTAVAIL", "address not available"]],
+ [-97, ["EAFNOSUPPORT", "address family not supported"]],
+ [-11, ["EAGAIN", "resource temporarily unavailable"]],
+ [-3000, ["EAI_ADDRFAMILY", "address family not supported"]],
+ [-3001, ["EAI_AGAIN", "temporary failure"]],
+ [-3002, ["EAI_BADFLAGS", "bad ai_flags value"]],
+ [-3013, ["EAI_BADHINTS", "invalid value for hints"]],
+ [-3003, ["EAI_CANCELED", "request canceled"]],
+ [-3004, ["EAI_FAIL", "permanent failure"]],
+ [-3005, ["EAI_FAMILY", "ai_family not supported"]],
+ [-3006, ["EAI_MEMORY", "out of memory"]],
+ [-3007, ["EAI_NODATA", "no address"]],
+ [-3008, ["EAI_NONAME", "unknown node or service"]],
+ [-3009, ["EAI_OVERFLOW", "argument buffer overflow"]],
+ [-3014, ["EAI_PROTOCOL", "resolved protocol is unknown"]],
+ [-3010, ["EAI_SERVICE", "service not available for socket type"]],
+ [-3011, ["EAI_SOCKTYPE", "socket type not supported"]],
+ [-114, ["EALREADY", "connection already in progress"]],
+ [-9, ["EBADF", "bad file descriptor"]],
+ [-16, ["EBUSY", "resource busy or locked"]],
+ [-125, ["ECANCELED", "operation canceled"]],
+ [-4080, ["ECHARSET", "invalid Unicode character"]],
+ [-103, ["ECONNABORTED", "software caused connection abort"]],
+ [-111, ["ECONNREFUSED", "connection refused"]],
+ [-104, ["ECONNRESET", "connection reset by peer"]],
+ [-89, ["EDESTADDRREQ", "destination address required"]],
+ [-17, ["EEXIST", "file already exists"]],
+ [-14, ["EFAULT", "bad address in system call argument"]],
+ [-27, ["EFBIG", "file too large"]],
+ [-113, ["EHOSTUNREACH", "host is unreachable"]],
+ [-4, ["EINTR", "interrupted system call"]],
+ [-22, ["EINVAL", "invalid argument"]],
+ [-5, ["EIO", "i/o error"]],
+ [-106, ["EISCONN", "socket is already connected"]],
+ [-21, ["EISDIR", "illegal operation on a directory"]],
+ [-40, ["ELOOP", "too many symbolic links encountered"]],
+ [-24, ["EMFILE", "too many open files"]],
+ [-90, ["EMSGSIZE", "message too long"]],
+ [-36, ["ENAMETOOLONG", "name too long"]],
+ [-100, ["ENETDOWN", "network is down"]],
+ [-101, ["ENETUNREACH", "network is unreachable"]],
+ [-23, ["ENFILE", "file table overflow"]],
+ [-105, ["ENOBUFS", "no buffer space available"]],
+ [-19, ["ENODEV", "no such device"]],
+ [-2, ["ENOENT", "no such file or directory"]],
+ [-12, ["ENOMEM", "not enough memory"]],
+ [-64, ["ENONET", "machine is not on the network"]],
+ [-92, ["ENOPROTOOPT", "protocol not available"]],
+ [-28, ["ENOSPC", "no space left on device"]],
+ [-38, ["ENOSYS", "function not implemented"]],
+ [-107, ["ENOTCONN", "socket is not connected"]],
+ [-20, ["ENOTDIR", "not a directory"]],
+ [-39, ["ENOTEMPTY", "directory not empty"]],
+ [-88, ["ENOTSOCK", "socket operation on non-socket"]],
+ [-95, ["ENOTSUP", "operation not supported on socket"]],
+ [-1, ["EPERM", "operation not permitted"]],
+ [-32, ["EPIPE", "broken pipe"]],
+ [-71, ["EPROTO", "protocol error"]],
+ [-93, ["EPROTONOSUPPORT", "protocol not supported"]],
+ [-91, ["EPROTOTYPE", "protocol wrong type for socket"]],
+ [-34, ["ERANGE", "result too large"]],
+ [-30, ["EROFS", "read-only file system"]],
+ [-108, ["ESHUTDOWN", "cannot send after transport endpoint shutdown"]],
+ [-29, ["ESPIPE", "invalid seek"]],
+ [-3, ["ESRCH", "no such process"]],
+ [-110, ["ETIMEDOUT", "connection timed out"]],
+ [-26, ["ETXTBSY", "text file is busy"]],
+ [-18, ["EXDEV", "cross-device link not permitted"]],
+ [-4094, ["UNKNOWN", "unknown error"]],
+ [-4095, ["EOF", "end of file"]],
+ [-6, ["ENXIO", "no such device or address"]],
+ [-31, ["EMLINK", "too many links"]],
+ [-112, ["EHOSTDOWN", "host is down"]],
+ [-121, ["EREMOTEIO", "remote I/O error"]],
+ [-25, ["ENOTTY", "inappropriate ioctl for device"]],
+ [-4028, ["EFTYPE", "inappropriate file type or format"]],
+ [-84, ["EILSEQ", "illegal byte sequence"]],
+];
+
+const { os } = Deno.build;
+export const errorMap = new Map<number, [string, string]>(
+ os === "windows"
+ ? windows
+ : os === "darwin"
+ ? darwin
+ : os === "linux"
+ ? linux
+ : unreachable(),
+);
diff --git a/std/node/util.ts b/std/node/util.ts
index 27aa5a12b..076a5b830 100644
--- a/std/node/util.ts
+++ b/std/node/util.ts
@@ -1,10 +1,16 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
export { promisify } from "./_util/_util_promisify.ts";
export { callbackify } from "./_util/_util_callbackify.ts";
+import { codes, errorMap } from "./_errors.ts";
import * as types from "./_util/_util_types.ts";
-
export { types };
+const NumberIsSafeInteger = Number.isSafeInteger;
+const {
+ ERR_OUT_OF_RANGE,
+ ERR_INVALID_ARG_TYPE,
+} = codes;
+
const DEFAULT_INSPECT_OPTIONS = {
showHidden: false,
depth: 2,
@@ -90,6 +96,16 @@ export function isPrimitive(value: unknown): boolean {
);
}
+export function getSystemErrorName(code: number): string | undefined {
+ if (typeof code !== "number") {
+ throw new ERR_INVALID_ARG_TYPE("err", "number", code);
+ }
+ if (code >= 0 || !NumberIsSafeInteger(code)) {
+ throw new ERR_OUT_OF_RANGE("err", "a negative integer", code);
+ }
+ return errorMap.get(code)?.[0];
+}
+
import { _TextDecoder, _TextEncoder } from "./_utils.ts";
/** The global TextDecoder */
diff --git a/std/node/util_test.ts b/std/node/util_test.ts
index 9b55d0178..9db463b99 100644
--- a/std/node/util_test.ts
+++ b/std/node/util_test.ts
@@ -1,5 +1,11 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
-import { assert, assertEquals } from "../testing/asserts.ts";
+
+import {
+ assert,
+ assertEquals,
+ assertStrictEquals,
+ assertThrows,
+} from "../testing/asserts.ts";
import { stripColor } from "../fmt/colors.ts";
import * as util from "./util.ts";
@@ -182,3 +188,35 @@ Deno.test({
assert(util.types.isDate(new Date()));
},
});
+
+Deno.test({
+ name: "[util] getSystemErrorName()",
+ fn() {
+ type FnTestInvalidArg = (code?: unknown) => void;
+
+ assertThrows(
+ () => (util.getSystemErrorName as FnTestInvalidArg)(),
+ TypeError,
+ );
+ assertThrows(
+ () => (util.getSystemErrorName as FnTestInvalidArg)(1),
+ RangeError,
+ );
+
+ assertStrictEquals(util.getSystemErrorName(-424242), undefined);
+
+ switch (Deno.build.os) {
+ case "windows":
+ assertStrictEquals(util.getSystemErrorName(-4091), "EADDRINUSE");
+ break;
+
+ case "darwin":
+ assertStrictEquals(util.getSystemErrorName(-48), "EADDRINUSE");
+ break;
+
+ case "linux":
+ assertStrictEquals(util.getSystemErrorName(-98), "EADDRINUSE");
+ break;
+ }
+ },
+});