src: add CollectExceptionInfo & errors.SystemError
Preparing for the migration of existing UVException and ErrnoExceptions from the native layer, add new `errors.SystemError` to internal/errors and new `env->CollectExceptionInfo()` / `env->CollectUVExceptionInfo()` methods. PR-URL: https://github.com/nodejs/node/pull/16567 Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com> Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com>
This commit is contained in:
parent
f1f0eb2595
commit
c3dc0e0d75
@ -458,7 +458,7 @@ checks or `abort()` calls in the C++ layer.
|
||||
|
||||
## System Errors
|
||||
|
||||
System errors are generated when exceptions occur within the program's
|
||||
System errors are generated when exceptions occur within the Node.js
|
||||
runtime environment. Typically, these are operational errors that occur
|
||||
when an application violates an operating system constraint such as attempting
|
||||
to read a file that does not exist or when the user does not have sufficient
|
||||
@ -471,7 +471,24 @@ of error codes and their meanings is available by running `man 2 intro` or
|
||||
In Node.js, system errors are represented as augmented `Error` objects with
|
||||
added properties.
|
||||
|
||||
### Class: System Error
|
||||
### Class: SystemError
|
||||
|
||||
### error.info
|
||||
|
||||
`SystemError` instances may have an additional `info` property whose
|
||||
value is an object with additional details about the error conditions.
|
||||
|
||||
The following properties are provided:
|
||||
|
||||
* `code` {string} The string error code
|
||||
* `errno` {number} The system-provided error number
|
||||
* `message` {string} A system-provided human readable description of the error
|
||||
* `syscall` {string} The name of the system call that triggered the error
|
||||
* `path` {Buffer} When reporting a file system error, the `path` will identify
|
||||
the file path.
|
||||
* `dest` {Buffer} When reporting a file system error, the `dest` will identify
|
||||
the file path destination (if any).
|
||||
|
||||
|
||||
#### error.code
|
||||
|
||||
@ -1379,6 +1396,13 @@ instance.setEncoding('utf8');
|
||||
Used when an attempt is made to call [`stream.write()`][] after
|
||||
`stream.end()` has been called.
|
||||
|
||||
<a id="ERR_SYSTEM_ERROR"></a>
|
||||
### ERR_SYSTEM_ERROR
|
||||
|
||||
The `ERR_SYSTEM_ERROR` code is used when an unspecified or non-specific system
|
||||
error has occurred within the Node.js process. The error object will have an
|
||||
`err.info` object property with additional details.
|
||||
|
||||
<a id="ERR_TLS_CERT_ALTNAME_INVALID"></a>
|
||||
### ERR_TLS_CERT_ALTNAME_INVALID
|
||||
|
||||
|
@ -10,6 +10,7 @@
|
||||
// message may change, the code should not.
|
||||
|
||||
const kCode = Symbol('code');
|
||||
const kInfo = Symbol('info');
|
||||
const messages = new Map();
|
||||
|
||||
const { kMaxLength } = process.binding('buffer');
|
||||
@ -58,6 +59,68 @@ function makeNodeError(Base) {
|
||||
};
|
||||
}
|
||||
|
||||
// A specialized Error that includes an additional info property with
|
||||
// additional information about the error condition. The code key will
|
||||
// be extracted from the context object or the ERR_SYSTEM_ERROR default
|
||||
// will be used.
|
||||
class SystemError extends makeNodeError(Error) {
|
||||
constructor(context) {
|
||||
context = context || {};
|
||||
let code = 'ERR_SYSTEM_ERROR';
|
||||
if (messages.has(context.code))
|
||||
code = context.code;
|
||||
super(code,
|
||||
context.code,
|
||||
context.syscall,
|
||||
context.path,
|
||||
context.dest,
|
||||
context.message);
|
||||
Object.defineProperty(this, kInfo, {
|
||||
configurable: false,
|
||||
enumerable: false,
|
||||
value: context
|
||||
});
|
||||
}
|
||||
|
||||
get info() {
|
||||
return this[kInfo];
|
||||
}
|
||||
|
||||
get errno() {
|
||||
return this[kInfo].errno;
|
||||
}
|
||||
|
||||
set errno(val) {
|
||||
this[kInfo].errno = val;
|
||||
}
|
||||
|
||||
get syscall() {
|
||||
return this[kInfo].syscall;
|
||||
}
|
||||
|
||||
set syscall(val) {
|
||||
this[kInfo].syscall = val;
|
||||
}
|
||||
|
||||
get path() {
|
||||
return this[kInfo].path !== undefined ?
|
||||
this[kInfo].path.toString() : undefined;
|
||||
}
|
||||
|
||||
set path(val) {
|
||||
this[kInfo].path = val ? Buffer.from(val.toString()) : undefined;
|
||||
}
|
||||
|
||||
get dest() {
|
||||
return this[kInfo].path !== undefined ?
|
||||
this[kInfo].dest.toString() : undefined;
|
||||
}
|
||||
|
||||
set dest(val) {
|
||||
this[kInfo].dest = val ? Buffer.from(val.toString()) : undefined;
|
||||
}
|
||||
}
|
||||
|
||||
class AssertionError extends Error {
|
||||
constructor(options) {
|
||||
if (typeof options !== 'object' || options === null) {
|
||||
@ -128,6 +191,7 @@ module.exports = exports = {
|
||||
RangeError: makeNodeError(RangeError),
|
||||
URIError: makeNodeError(URIError),
|
||||
AssertionError,
|
||||
SystemError,
|
||||
E // This is exported only to facilitate testing.
|
||||
};
|
||||
|
||||
@ -144,6 +208,9 @@ module.exports = exports = {
|
||||
// Any error code added here should also be added to the documentation
|
||||
//
|
||||
// Note: Please try to keep these in alphabetical order
|
||||
//
|
||||
// Note: Node.js specific errors must begin with the prefix ERR_
|
||||
|
||||
E('ERR_ARG_NOT_ITERABLE', '%s must be iterable');
|
||||
E('ERR_ASSERTION', '%s');
|
||||
E('ERR_ASYNC_CALLBACK', (name) => `${name} must be a function`);
|
||||
@ -334,6 +401,7 @@ E('ERR_STREAM_READ_NOT_IMPLEMENTED', '_read() is not implemented');
|
||||
E('ERR_STREAM_UNSHIFT_AFTER_END_EVENT', 'stream.unshift() after end event');
|
||||
E('ERR_STREAM_WRAP', 'Stream has StringDecoder set or is in objectMode');
|
||||
E('ERR_STREAM_WRITE_AFTER_END', 'write after end');
|
||||
E('ERR_SYSTEM_ERROR', sysError('A system error occurred'));
|
||||
E('ERR_TLS_CERT_ALTNAME_INVALID',
|
||||
'Hostname/IP does not match certificate\'s altnames: %s');
|
||||
E('ERR_TLS_DH_PARAM_SIZE', (size) =>
|
||||
@ -371,6 +439,28 @@ E('ERR_VALUE_OUT_OF_RANGE', (start, end, value) => {
|
||||
E('ERR_ZLIB_BINDING_CLOSED', 'zlib binding closed');
|
||||
E('ERR_ZLIB_INITIALIZATION_FAILED', 'Initialization failed');
|
||||
|
||||
function sysError(defaultMessage) {
|
||||
return function(code,
|
||||
syscall,
|
||||
path,
|
||||
dest,
|
||||
message = defaultMessage) {
|
||||
if (code !== undefined)
|
||||
message += `: ${code}`;
|
||||
if (syscall !== undefined) {
|
||||
if (code === undefined)
|
||||
message += ':';
|
||||
message += ` [${syscall}]`;
|
||||
}
|
||||
if (path !== undefined) {
|
||||
message += `: ${path}`;
|
||||
if (dest !== undefined)
|
||||
message += ` => ${dest}`;
|
||||
}
|
||||
return message;
|
||||
};
|
||||
}
|
||||
|
||||
function invalidArgType(name, expected, actual) {
|
||||
internalAssert(name, 'name is required');
|
||||
|
||||
|
78
src/env.cc
78
src/env.cc
@ -1,6 +1,7 @@
|
||||
#include "node_internals.h"
|
||||
#include "async-wrap.h"
|
||||
#include "v8-profiler.h"
|
||||
#include "node_buffer.h"
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#define getpid GetCurrentProcessId
|
||||
@ -228,4 +229,81 @@ void Environment::EnvPromiseHook(v8::PromiseHookType type,
|
||||
}
|
||||
}
|
||||
|
||||
void CollectExceptionInfo(Environment* env,
|
||||
v8::Local<v8::Object> obj,
|
||||
int errorno,
|
||||
const char* err_string,
|
||||
const char* syscall,
|
||||
const char* message,
|
||||
const char* path,
|
||||
const char* dest) {
|
||||
obj->Set(env->errno_string(), v8::Integer::New(env->isolate(), errorno));
|
||||
|
||||
obj->Set(env->context(), env->code_string(),
|
||||
OneByteString(env->isolate(), err_string)).FromJust();
|
||||
|
||||
if (message != nullptr) {
|
||||
obj->Set(env->context(), env->message_string(),
|
||||
OneByteString(env->isolate(), message)).FromJust();
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> path_buffer;
|
||||
if (path != nullptr) {
|
||||
path_buffer =
|
||||
Buffer::Copy(env->isolate(), path, strlen(path)).ToLocalChecked();
|
||||
obj->Set(env->context(), env->path_string(), path_buffer).FromJust();
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> dest_buffer;
|
||||
if (dest != nullptr) {
|
||||
dest_buffer =
|
||||
Buffer::Copy(env->isolate(), dest, strlen(dest)).ToLocalChecked();
|
||||
obj->Set(env->context(), env->dest_string(), dest_buffer).FromJust();
|
||||
}
|
||||
|
||||
if (syscall != nullptr) {
|
||||
obj->Set(env->context(), env->syscall_string(),
|
||||
OneByteString(env->isolate(), syscall));
|
||||
}
|
||||
}
|
||||
|
||||
void Environment::CollectExceptionInfo(v8::Local<v8::Value> object,
|
||||
int errorno,
|
||||
const char* syscall,
|
||||
const char* message,
|
||||
const char* path) {
|
||||
if (!object->IsObject() || errorno == 0)
|
||||
return;
|
||||
|
||||
v8::Local<v8::Object> obj = object.As<v8::Object>();
|
||||
const char* err_string = node::errno_string(errorno);
|
||||
|
||||
if (message == nullptr || message[0] == '\0') {
|
||||
message = strerror(errorno);
|
||||
}
|
||||
|
||||
node::CollectExceptionInfo(this, obj, errorno, err_string,
|
||||
syscall, message, path, nullptr);
|
||||
}
|
||||
|
||||
void Environment::CollectUVExceptionInfo(v8::Local<v8::Value> object,
|
||||
int errorno,
|
||||
const char* syscall,
|
||||
const char* message,
|
||||
const char* path,
|
||||
const char* dest) {
|
||||
if (!object->IsObject() || errorno == 0)
|
||||
return;
|
||||
|
||||
v8::Local<v8::Object> obj = object.As<v8::Object>();
|
||||
const char* err_string = uv_err_name(errorno);
|
||||
|
||||
if (message == nullptr || message[0] == '\0') {
|
||||
message = uv_strerror(errorno);
|
||||
}
|
||||
|
||||
node::CollectExceptionInfo(this, obj, errorno, err_string,
|
||||
syscall, message, path, dest);
|
||||
}
|
||||
|
||||
} // namespace node
|
||||
|
13
src/env.h
13
src/env.h
@ -617,6 +617,19 @@ class Environment {
|
||||
inline performance::performance_state* performance_state();
|
||||
inline std::map<std::string, uint64_t>* performance_marks();
|
||||
|
||||
void CollectExceptionInfo(v8::Local<v8::Value> context,
|
||||
int errorno,
|
||||
const char* syscall = nullptr,
|
||||
const char* message = nullptr,
|
||||
const char* path = nullptr);
|
||||
|
||||
void CollectUVExceptionInfo(v8::Local<v8::Value> context,
|
||||
int errorno,
|
||||
const char* syscall = nullptr,
|
||||
const char* message = nullptr,
|
||||
const char* path = nullptr,
|
||||
const char* dest = nullptr);
|
||||
|
||||
inline void ThrowError(const char* errmsg);
|
||||
inline void ThrowTypeError(const char* errmsg);
|
||||
inline void ThrowRangeError(const char* errmsg);
|
||||
|
327
src/node.cc
327
src/node.cc
@ -390,333 +390,6 @@ static void IdleImmediateDummy(uv_idle_t* handle) {
|
||||
// TODO(bnoordhuis) Maybe make libuv accept nullptr idle callbacks.
|
||||
}
|
||||
|
||||
|
||||
static inline const char *errno_string(int errorno) {
|
||||
#define ERRNO_CASE(e) case e: return #e;
|
||||
switch (errorno) {
|
||||
#ifdef EACCES
|
||||
ERRNO_CASE(EACCES);
|
||||
#endif
|
||||
|
||||
#ifdef EADDRINUSE
|
||||
ERRNO_CASE(EADDRINUSE);
|
||||
#endif
|
||||
|
||||
#ifdef EADDRNOTAVAIL
|
||||
ERRNO_CASE(EADDRNOTAVAIL);
|
||||
#endif
|
||||
|
||||
#ifdef EAFNOSUPPORT
|
||||
ERRNO_CASE(EAFNOSUPPORT);
|
||||
#endif
|
||||
|
||||
#ifdef EAGAIN
|
||||
ERRNO_CASE(EAGAIN);
|
||||
#endif
|
||||
|
||||
#ifdef EWOULDBLOCK
|
||||
# if EAGAIN != EWOULDBLOCK
|
||||
ERRNO_CASE(EWOULDBLOCK);
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef EALREADY
|
||||
ERRNO_CASE(EALREADY);
|
||||
#endif
|
||||
|
||||
#ifdef EBADF
|
||||
ERRNO_CASE(EBADF);
|
||||
#endif
|
||||
|
||||
#ifdef EBADMSG
|
||||
ERRNO_CASE(EBADMSG);
|
||||
#endif
|
||||
|
||||
#ifdef EBUSY
|
||||
ERRNO_CASE(EBUSY);
|
||||
#endif
|
||||
|
||||
#ifdef ECANCELED
|
||||
ERRNO_CASE(ECANCELED);
|
||||
#endif
|
||||
|
||||
#ifdef ECHILD
|
||||
ERRNO_CASE(ECHILD);
|
||||
#endif
|
||||
|
||||
#ifdef ECONNABORTED
|
||||
ERRNO_CASE(ECONNABORTED);
|
||||
#endif
|
||||
|
||||
#ifdef ECONNREFUSED
|
||||
ERRNO_CASE(ECONNREFUSED);
|
||||
#endif
|
||||
|
||||
#ifdef ECONNRESET
|
||||
ERRNO_CASE(ECONNRESET);
|
||||
#endif
|
||||
|
||||
#ifdef EDEADLK
|
||||
ERRNO_CASE(EDEADLK);
|
||||
#endif
|
||||
|
||||
#ifdef EDESTADDRREQ
|
||||
ERRNO_CASE(EDESTADDRREQ);
|
||||
#endif
|
||||
|
||||
#ifdef EDOM
|
||||
ERRNO_CASE(EDOM);
|
||||
#endif
|
||||
|
||||
#ifdef EDQUOT
|
||||
ERRNO_CASE(EDQUOT);
|
||||
#endif
|
||||
|
||||
#ifdef EEXIST
|
||||
ERRNO_CASE(EEXIST);
|
||||
#endif
|
||||
|
||||
#ifdef EFAULT
|
||||
ERRNO_CASE(EFAULT);
|
||||
#endif
|
||||
|
||||
#ifdef EFBIG
|
||||
ERRNO_CASE(EFBIG);
|
||||
#endif
|
||||
|
||||
#ifdef EHOSTUNREACH
|
||||
ERRNO_CASE(EHOSTUNREACH);
|
||||
#endif
|
||||
|
||||
#ifdef EIDRM
|
||||
ERRNO_CASE(EIDRM);
|
||||
#endif
|
||||
|
||||
#ifdef EILSEQ
|
||||
ERRNO_CASE(EILSEQ);
|
||||
#endif
|
||||
|
||||
#ifdef EINPROGRESS
|
||||
ERRNO_CASE(EINPROGRESS);
|
||||
#endif
|
||||
|
||||
#ifdef EINTR
|
||||
ERRNO_CASE(EINTR);
|
||||
#endif
|
||||
|
||||
#ifdef EINVAL
|
||||
ERRNO_CASE(EINVAL);
|
||||
#endif
|
||||
|
||||
#ifdef EIO
|
||||
ERRNO_CASE(EIO);
|
||||
#endif
|
||||
|
||||
#ifdef EISCONN
|
||||
ERRNO_CASE(EISCONN);
|
||||
#endif
|
||||
|
||||
#ifdef EISDIR
|
||||
ERRNO_CASE(EISDIR);
|
||||
#endif
|
||||
|
||||
#ifdef ELOOP
|
||||
ERRNO_CASE(ELOOP);
|
||||
#endif
|
||||
|
||||
#ifdef EMFILE
|
||||
ERRNO_CASE(EMFILE);
|
||||
#endif
|
||||
|
||||
#ifdef EMLINK
|
||||
ERRNO_CASE(EMLINK);
|
||||
#endif
|
||||
|
||||
#ifdef EMSGSIZE
|
||||
ERRNO_CASE(EMSGSIZE);
|
||||
#endif
|
||||
|
||||
#ifdef EMULTIHOP
|
||||
ERRNO_CASE(EMULTIHOP);
|
||||
#endif
|
||||
|
||||
#ifdef ENAMETOOLONG
|
||||
ERRNO_CASE(ENAMETOOLONG);
|
||||
#endif
|
||||
|
||||
#ifdef ENETDOWN
|
||||
ERRNO_CASE(ENETDOWN);
|
||||
#endif
|
||||
|
||||
#ifdef ENETRESET
|
||||
ERRNO_CASE(ENETRESET);
|
||||
#endif
|
||||
|
||||
#ifdef ENETUNREACH
|
||||
ERRNO_CASE(ENETUNREACH);
|
||||
#endif
|
||||
|
||||
#ifdef ENFILE
|
||||
ERRNO_CASE(ENFILE);
|
||||
#endif
|
||||
|
||||
#ifdef ENOBUFS
|
||||
ERRNO_CASE(ENOBUFS);
|
||||
#endif
|
||||
|
||||
#ifdef ENODATA
|
||||
ERRNO_CASE(ENODATA);
|
||||
#endif
|
||||
|
||||
#ifdef ENODEV
|
||||
ERRNO_CASE(ENODEV);
|
||||
#endif
|
||||
|
||||
#ifdef ENOENT
|
||||
ERRNO_CASE(ENOENT);
|
||||
#endif
|
||||
|
||||
#ifdef ENOEXEC
|
||||
ERRNO_CASE(ENOEXEC);
|
||||
#endif
|
||||
|
||||
#ifdef ENOLINK
|
||||
ERRNO_CASE(ENOLINK);
|
||||
#endif
|
||||
|
||||
#ifdef ENOLCK
|
||||
# if ENOLINK != ENOLCK
|
||||
ERRNO_CASE(ENOLCK);
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef ENOMEM
|
||||
ERRNO_CASE(ENOMEM);
|
||||
#endif
|
||||
|
||||
#ifdef ENOMSG
|
||||
ERRNO_CASE(ENOMSG);
|
||||
#endif
|
||||
|
||||
#ifdef ENOPROTOOPT
|
||||
ERRNO_CASE(ENOPROTOOPT);
|
||||
#endif
|
||||
|
||||
#ifdef ENOSPC
|
||||
ERRNO_CASE(ENOSPC);
|
||||
#endif
|
||||
|
||||
#ifdef ENOSR
|
||||
ERRNO_CASE(ENOSR);
|
||||
#endif
|
||||
|
||||
#ifdef ENOSTR
|
||||
ERRNO_CASE(ENOSTR);
|
||||
#endif
|
||||
|
||||
#ifdef ENOSYS
|
||||
ERRNO_CASE(ENOSYS);
|
||||
#endif
|
||||
|
||||
#ifdef ENOTCONN
|
||||
ERRNO_CASE(ENOTCONN);
|
||||
#endif
|
||||
|
||||
#ifdef ENOTDIR
|
||||
ERRNO_CASE(ENOTDIR);
|
||||
#endif
|
||||
|
||||
#ifdef ENOTEMPTY
|
||||
# if ENOTEMPTY != EEXIST
|
||||
ERRNO_CASE(ENOTEMPTY);
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef ENOTSOCK
|
||||
ERRNO_CASE(ENOTSOCK);
|
||||
#endif
|
||||
|
||||
#ifdef ENOTSUP
|
||||
ERRNO_CASE(ENOTSUP);
|
||||
#else
|
||||
# ifdef EOPNOTSUPP
|
||||
ERRNO_CASE(EOPNOTSUPP);
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef ENOTTY
|
||||
ERRNO_CASE(ENOTTY);
|
||||
#endif
|
||||
|
||||
#ifdef ENXIO
|
||||
ERRNO_CASE(ENXIO);
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef EOVERFLOW
|
||||
ERRNO_CASE(EOVERFLOW);
|
||||
#endif
|
||||
|
||||
#ifdef EPERM
|
||||
ERRNO_CASE(EPERM);
|
||||
#endif
|
||||
|
||||
#ifdef EPIPE
|
||||
ERRNO_CASE(EPIPE);
|
||||
#endif
|
||||
|
||||
#ifdef EPROTO
|
||||
ERRNO_CASE(EPROTO);
|
||||
#endif
|
||||
|
||||
#ifdef EPROTONOSUPPORT
|
||||
ERRNO_CASE(EPROTONOSUPPORT);
|
||||
#endif
|
||||
|
||||
#ifdef EPROTOTYPE
|
||||
ERRNO_CASE(EPROTOTYPE);
|
||||
#endif
|
||||
|
||||
#ifdef ERANGE
|
||||
ERRNO_CASE(ERANGE);
|
||||
#endif
|
||||
|
||||
#ifdef EROFS
|
||||
ERRNO_CASE(EROFS);
|
||||
#endif
|
||||
|
||||
#ifdef ESPIPE
|
||||
ERRNO_CASE(ESPIPE);
|
||||
#endif
|
||||
|
||||
#ifdef ESRCH
|
||||
ERRNO_CASE(ESRCH);
|
||||
#endif
|
||||
|
||||
#ifdef ESTALE
|
||||
ERRNO_CASE(ESTALE);
|
||||
#endif
|
||||
|
||||
#ifdef ETIME
|
||||
ERRNO_CASE(ETIME);
|
||||
#endif
|
||||
|
||||
#ifdef ETIMEDOUT
|
||||
ERRNO_CASE(ETIMEDOUT);
|
||||
#endif
|
||||
|
||||
#ifdef ETXTBSY
|
||||
ERRNO_CASE(ETXTBSY);
|
||||
#endif
|
||||
|
||||
#ifdef EXDEV
|
||||
ERRNO_CASE(EXDEV);
|
||||
#endif
|
||||
|
||||
default: return "";
|
||||
}
|
||||
}
|
||||
|
||||
const char *signo_string(int signo) {
|
||||
#define SIGNO_CASE(e) case e: return #e;
|
||||
switch (signo) {
|
||||
|
@ -324,6 +324,332 @@ class InternalCallbackScope {
|
||||
bool closed_ = false;
|
||||
};
|
||||
|
||||
static inline const char *errno_string(int errorno) {
|
||||
#define ERRNO_CASE(e) case e: return #e;
|
||||
switch (errorno) {
|
||||
#ifdef EACCES
|
||||
ERRNO_CASE(EACCES);
|
||||
#endif
|
||||
|
||||
#ifdef EADDRINUSE
|
||||
ERRNO_CASE(EADDRINUSE);
|
||||
#endif
|
||||
|
||||
#ifdef EADDRNOTAVAIL
|
||||
ERRNO_CASE(EADDRNOTAVAIL);
|
||||
#endif
|
||||
|
||||
#ifdef EAFNOSUPPORT
|
||||
ERRNO_CASE(EAFNOSUPPORT);
|
||||
#endif
|
||||
|
||||
#ifdef EAGAIN
|
||||
ERRNO_CASE(EAGAIN);
|
||||
#endif
|
||||
|
||||
#ifdef EWOULDBLOCK
|
||||
# if EAGAIN != EWOULDBLOCK
|
||||
ERRNO_CASE(EWOULDBLOCK);
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef EALREADY
|
||||
ERRNO_CASE(EALREADY);
|
||||
#endif
|
||||
|
||||
#ifdef EBADF
|
||||
ERRNO_CASE(EBADF);
|
||||
#endif
|
||||
|
||||
#ifdef EBADMSG
|
||||
ERRNO_CASE(EBADMSG);
|
||||
#endif
|
||||
|
||||
#ifdef EBUSY
|
||||
ERRNO_CASE(EBUSY);
|
||||
#endif
|
||||
|
||||
#ifdef ECANCELED
|
||||
ERRNO_CASE(ECANCELED);
|
||||
#endif
|
||||
|
||||
#ifdef ECHILD
|
||||
ERRNO_CASE(ECHILD);
|
||||
#endif
|
||||
|
||||
#ifdef ECONNABORTED
|
||||
ERRNO_CASE(ECONNABORTED);
|
||||
#endif
|
||||
|
||||
#ifdef ECONNREFUSED
|
||||
ERRNO_CASE(ECONNREFUSED);
|
||||
#endif
|
||||
|
||||
#ifdef ECONNRESET
|
||||
ERRNO_CASE(ECONNRESET);
|
||||
#endif
|
||||
|
||||
#ifdef EDEADLK
|
||||
ERRNO_CASE(EDEADLK);
|
||||
#endif
|
||||
|
||||
#ifdef EDESTADDRREQ
|
||||
ERRNO_CASE(EDESTADDRREQ);
|
||||
#endif
|
||||
|
||||
#ifdef EDOM
|
||||
ERRNO_CASE(EDOM);
|
||||
#endif
|
||||
|
||||
#ifdef EDQUOT
|
||||
ERRNO_CASE(EDQUOT);
|
||||
#endif
|
||||
|
||||
#ifdef EEXIST
|
||||
ERRNO_CASE(EEXIST);
|
||||
#endif
|
||||
|
||||
#ifdef EFAULT
|
||||
ERRNO_CASE(EFAULT);
|
||||
#endif
|
||||
|
||||
#ifdef EFBIG
|
||||
ERRNO_CASE(EFBIG);
|
||||
#endif
|
||||
|
||||
#ifdef EHOSTUNREACH
|
||||
ERRNO_CASE(EHOSTUNREACH);
|
||||
#endif
|
||||
|
||||
#ifdef EIDRM
|
||||
ERRNO_CASE(EIDRM);
|
||||
#endif
|
||||
|
||||
#ifdef EILSEQ
|
||||
ERRNO_CASE(EILSEQ);
|
||||
#endif
|
||||
|
||||
#ifdef EINPROGRESS
|
||||
ERRNO_CASE(EINPROGRESS);
|
||||
#endif
|
||||
|
||||
#ifdef EINTR
|
||||
ERRNO_CASE(EINTR);
|
||||
#endif
|
||||
|
||||
#ifdef EINVAL
|
||||
ERRNO_CASE(EINVAL);
|
||||
#endif
|
||||
|
||||
#ifdef EIO
|
||||
ERRNO_CASE(EIO);
|
||||
#endif
|
||||
|
||||
#ifdef EISCONN
|
||||
ERRNO_CASE(EISCONN);
|
||||
#endif
|
||||
|
||||
#ifdef EISDIR
|
||||
ERRNO_CASE(EISDIR);
|
||||
#endif
|
||||
|
||||
#ifdef ELOOP
|
||||
ERRNO_CASE(ELOOP);
|
||||
#endif
|
||||
|
||||
#ifdef EMFILE
|
||||
ERRNO_CASE(EMFILE);
|
||||
#endif
|
||||
|
||||
#ifdef EMLINK
|
||||
ERRNO_CASE(EMLINK);
|
||||
#endif
|
||||
|
||||
#ifdef EMSGSIZE
|
||||
ERRNO_CASE(EMSGSIZE);
|
||||
#endif
|
||||
|
||||
#ifdef EMULTIHOP
|
||||
ERRNO_CASE(EMULTIHOP);
|
||||
#endif
|
||||
|
||||
#ifdef ENAMETOOLONG
|
||||
ERRNO_CASE(ENAMETOOLONG);
|
||||
#endif
|
||||
|
||||
#ifdef ENETDOWN
|
||||
ERRNO_CASE(ENETDOWN);
|
||||
#endif
|
||||
|
||||
#ifdef ENETRESET
|
||||
ERRNO_CASE(ENETRESET);
|
||||
#endif
|
||||
|
||||
#ifdef ENETUNREACH
|
||||
ERRNO_CASE(ENETUNREACH);
|
||||
#endif
|
||||
|
||||
#ifdef ENFILE
|
||||
ERRNO_CASE(ENFILE);
|
||||
#endif
|
||||
|
||||
#ifdef ENOBUFS
|
||||
ERRNO_CASE(ENOBUFS);
|
||||
#endif
|
||||
|
||||
#ifdef ENODATA
|
||||
ERRNO_CASE(ENODATA);
|
||||
#endif
|
||||
|
||||
#ifdef ENODEV
|
||||
ERRNO_CASE(ENODEV);
|
||||
#endif
|
||||
|
||||
#ifdef ENOENT
|
||||
ERRNO_CASE(ENOENT);
|
||||
#endif
|
||||
|
||||
#ifdef ENOEXEC
|
||||
ERRNO_CASE(ENOEXEC);
|
||||
#endif
|
||||
|
||||
#ifdef ENOLINK
|
||||
ERRNO_CASE(ENOLINK);
|
||||
#endif
|
||||
|
||||
#ifdef ENOLCK
|
||||
# if ENOLINK != ENOLCK
|
||||
ERRNO_CASE(ENOLCK);
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef ENOMEM
|
||||
ERRNO_CASE(ENOMEM);
|
||||
#endif
|
||||
|
||||
#ifdef ENOMSG
|
||||
ERRNO_CASE(ENOMSG);
|
||||
#endif
|
||||
|
||||
#ifdef ENOPROTOOPT
|
||||
ERRNO_CASE(ENOPROTOOPT);
|
||||
#endif
|
||||
|
||||
#ifdef ENOSPC
|
||||
ERRNO_CASE(ENOSPC);
|
||||
#endif
|
||||
|
||||
#ifdef ENOSR
|
||||
ERRNO_CASE(ENOSR);
|
||||
#endif
|
||||
|
||||
#ifdef ENOSTR
|
||||
ERRNO_CASE(ENOSTR);
|
||||
#endif
|
||||
|
||||
#ifdef ENOSYS
|
||||
ERRNO_CASE(ENOSYS);
|
||||
#endif
|
||||
|
||||
#ifdef ENOTCONN
|
||||
ERRNO_CASE(ENOTCONN);
|
||||
#endif
|
||||
|
||||
#ifdef ENOTDIR
|
||||
ERRNO_CASE(ENOTDIR);
|
||||
#endif
|
||||
|
||||
#ifdef ENOTEMPTY
|
||||
# if ENOTEMPTY != EEXIST
|
||||
ERRNO_CASE(ENOTEMPTY);
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef ENOTSOCK
|
||||
ERRNO_CASE(ENOTSOCK);
|
||||
#endif
|
||||
|
||||
#ifdef ENOTSUP
|
||||
ERRNO_CASE(ENOTSUP);
|
||||
#else
|
||||
# ifdef EOPNOTSUPP
|
||||
ERRNO_CASE(EOPNOTSUPP);
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef ENOTTY
|
||||
ERRNO_CASE(ENOTTY);
|
||||
#endif
|
||||
|
||||
#ifdef ENXIO
|
||||
ERRNO_CASE(ENXIO);
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef EOVERFLOW
|
||||
ERRNO_CASE(EOVERFLOW);
|
||||
#endif
|
||||
|
||||
#ifdef EPERM
|
||||
ERRNO_CASE(EPERM);
|
||||
#endif
|
||||
|
||||
#ifdef EPIPE
|
||||
ERRNO_CASE(EPIPE);
|
||||
#endif
|
||||
|
||||
#ifdef EPROTO
|
||||
ERRNO_CASE(EPROTO);
|
||||
#endif
|
||||
|
||||
#ifdef EPROTONOSUPPORT
|
||||
ERRNO_CASE(EPROTONOSUPPORT);
|
||||
#endif
|
||||
|
||||
#ifdef EPROTOTYPE
|
||||
ERRNO_CASE(EPROTOTYPE);
|
||||
#endif
|
||||
|
||||
#ifdef ERANGE
|
||||
ERRNO_CASE(ERANGE);
|
||||
#endif
|
||||
|
||||
#ifdef EROFS
|
||||
ERRNO_CASE(EROFS);
|
||||
#endif
|
||||
|
||||
#ifdef ESPIPE
|
||||
ERRNO_CASE(ESPIPE);
|
||||
#endif
|
||||
|
||||
#ifdef ESRCH
|
||||
ERRNO_CASE(ESRCH);
|
||||
#endif
|
||||
|
||||
#ifdef ESTALE
|
||||
ERRNO_CASE(ESTALE);
|
||||
#endif
|
||||
|
||||
#ifdef ETIME
|
||||
ERRNO_CASE(ETIME);
|
||||
#endif
|
||||
|
||||
#ifdef ETIMEDOUT
|
||||
ERRNO_CASE(ETIMEDOUT);
|
||||
#endif
|
||||
|
||||
#ifdef ETXTBSY
|
||||
ERRNO_CASE(ETXTBSY);
|
||||
#endif
|
||||
|
||||
#ifdef EXDEV
|
||||
ERRNO_CASE(EXDEV);
|
||||
#endif
|
||||
|
||||
default: return "";
|
||||
}
|
||||
}
|
||||
|
||||
#define NODE_MODULE_CONTEXT_AWARE_INTERNAL(modname, regfunc) \
|
||||
NODE_MODULE_CONTEXT_AWARE_X(modname, regfunc, NULL, NM_F_INTERNAL) \
|
||||
|
||||
|
187
test/parallel/test-errors-systemerror.js
Normal file
187
test/parallel/test-errors-systemerror.js
Normal file
@ -0,0 +1,187 @@
|
||||
// Flags: --expose-internals
|
||||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
const assert = require('assert');
|
||||
const errors = require('internal/errors');
|
||||
|
||||
common.expectsError(
|
||||
() => { throw new errors.SystemError(); },
|
||||
{
|
||||
code: 'ERR_SYSTEM_ERROR',
|
||||
type: errors.SystemError,
|
||||
message: 'A system error occurred'
|
||||
}
|
||||
);
|
||||
|
||||
common.expectsError(
|
||||
() => { throw new errors.SystemError({}); },
|
||||
{
|
||||
code: 'ERR_SYSTEM_ERROR',
|
||||
type: errors.SystemError,
|
||||
message: 'A system error occurred'
|
||||
}
|
||||
);
|
||||
|
||||
common.expectsError(
|
||||
() => { throw new errors.SystemError(null); },
|
||||
{
|
||||
code: 'ERR_SYSTEM_ERROR',
|
||||
type: errors.SystemError,
|
||||
message: 'A system error occurred'
|
||||
}
|
||||
);
|
||||
|
||||
common.expectsError(
|
||||
() => { throw new errors.SystemError({ code: 'ERR' }); },
|
||||
{
|
||||
code: 'ERR_SYSTEM_ERROR',
|
||||
type: errors.SystemError,
|
||||
message: 'A system error occurred: ERR'
|
||||
}
|
||||
);
|
||||
|
||||
{
|
||||
const ctx = {
|
||||
code: 'ERR',
|
||||
syscall: 'foo'
|
||||
};
|
||||
common.expectsError(
|
||||
() => { throw new errors.SystemError(ctx); },
|
||||
{
|
||||
code: 'ERR_SYSTEM_ERROR',
|
||||
type: errors.SystemError,
|
||||
message: 'A system error occurred: ERR [foo]'
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
{
|
||||
const ctx = {
|
||||
code: 'ERR',
|
||||
syscall: 'foo',
|
||||
path: Buffer.from('a')
|
||||
};
|
||||
common.expectsError(
|
||||
() => { throw new errors.SystemError(ctx); },
|
||||
{
|
||||
code: 'ERR_SYSTEM_ERROR',
|
||||
type: errors.SystemError,
|
||||
message: 'A system error occurred: ERR [foo]: a'
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
{
|
||||
const ctx = {
|
||||
code: 'ERR',
|
||||
syscall: 'foo',
|
||||
path: Buffer.from('a'),
|
||||
dest: Buffer.from('b')
|
||||
};
|
||||
common.expectsError(
|
||||
() => { throw new errors.SystemError(ctx); },
|
||||
{
|
||||
code: 'ERR_SYSTEM_ERROR',
|
||||
type: errors.SystemError,
|
||||
message: 'A system error occurred: ERR [foo]: a => b'
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
{
|
||||
const ctx = {
|
||||
syscall: 'foo',
|
||||
path: Buffer.from('a'),
|
||||
dest: Buffer.from('b')
|
||||
};
|
||||
common.expectsError(
|
||||
() => { throw new errors.SystemError(ctx); },
|
||||
{
|
||||
code: 'ERR_SYSTEM_ERROR',
|
||||
type: errors.SystemError,
|
||||
message: 'A system error occurred: [foo]: a => b'
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
{
|
||||
const ctx = {
|
||||
path: Buffer.from('a'),
|
||||
dest: Buffer.from('b')
|
||||
};
|
||||
common.expectsError(
|
||||
() => { throw new errors.SystemError(ctx); },
|
||||
{
|
||||
code: 'ERR_SYSTEM_ERROR',
|
||||
type: errors.SystemError,
|
||||
message: 'A system error occurred: a => b'
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
{
|
||||
const ctx = {
|
||||
code: 'ERR',
|
||||
message: 'something happened',
|
||||
syscall: 'foo',
|
||||
path: Buffer.from('a'),
|
||||
dest: Buffer.from('b')
|
||||
};
|
||||
common.expectsError(
|
||||
() => { throw new errors.SystemError(ctx); },
|
||||
{
|
||||
code: 'ERR_SYSTEM_ERROR',
|
||||
type: errors.SystemError,
|
||||
message: 'something happened: ERR [foo]: a => b'
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
{
|
||||
const ctx = {
|
||||
code: 'ERR_ASSERTION'
|
||||
};
|
||||
common.expectsError(
|
||||
() => { throw new errors.SystemError(ctx); },
|
||||
{
|
||||
code: 'ERR_ASSERTION',
|
||||
type: errors.SystemError
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
{
|
||||
const ctx = {
|
||||
code: 'ERR',
|
||||
errno: 123,
|
||||
message: 'something happened',
|
||||
syscall: 'foo',
|
||||
path: Buffer.from('a'),
|
||||
dest: Buffer.from('b')
|
||||
};
|
||||
const err = new errors.SystemError(ctx);
|
||||
assert.strictEqual(err.info, ctx);
|
||||
assert.strictEqual(err.code, 'ERR_SYSTEM_ERROR');
|
||||
err.code = 'test';
|
||||
assert.strictEqual(err.code, 'test');
|
||||
|
||||
// Test legacy properties. These shouldn't be used anymore
|
||||
// but let us make sure they still work
|
||||
assert.strictEqual(err.errno, 123);
|
||||
assert.strictEqual(err.syscall, 'foo');
|
||||
assert.strictEqual(err.path, 'a');
|
||||
assert.strictEqual(err.dest, 'b');
|
||||
|
||||
// Make sure it's mutable
|
||||
err.code = 'test';
|
||||
err.errno = 321;
|
||||
err.syscall = 'test';
|
||||
err.path = 'path';
|
||||
err.dest = 'path';
|
||||
|
||||
assert.strictEqual(err.errno, 321);
|
||||
assert.strictEqual(err.syscall, 'test');
|
||||
assert.strictEqual(err.path, 'path');
|
||||
assert.strictEqual(err.dest, 'path');
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user