File
Blob: src/workerd/api/node/exceptions.h
| 1 | #pragma once |
| 2 | |
| 3 | #include <workerd/jsg/jsg.h> |
| 4 | |
| 5 | namespace workerd::api::node { |
| 6 | |
| 7 | // Utilities for creating Node.js-style exceptions. |
| 8 | |
| 9 | // Most Node.js exceptions are represented as either Error, |
| 10 | // TypeError, or RangeError. |
| 11 | enum class JsErrorType { |
| 12 | Error, |
| 13 | TypeError, |
| 14 | RangeError, |
| 15 | }; |
| 16 | |
| 17 | // Node.js Exception Codes |
| 18 | #define NODE_EXCEPTION_CODE_LIST(V) \ |
| 19 | V(ERR_FS_CP_EEXIST) \ |
| 20 | V(ERR_FS_CP_DIR_TO_NON_DIR) \ |
| 21 | V(ERR_FS_CP_EINVAL) \ |
| 22 | V(ERR_FS_CP_NON_DIR_TO_DIR) \ |
| 23 | V(ERR_FS_EISDIR) |
| 24 | |
| 25 | enum class NodeExceptionCode { |
| 26 | #define V(name) name, |
| 27 | NODE_EXCEPTION_CODE_LIST(V) |
| 28 | #undef V |
| 29 | }; |
| 30 | |
| 31 | // A Node.js style exception is just a JS error with a string "code" property. |
| 32 | jsg::JsValue createNodeException( |
| 33 | jsg::Lock& js, NodeExceptionCode code, JsErrorType type, kj::StringPtr message = nullptr); |
| 34 | |
| 35 | [[noreturn]] inline void throwNodeException(jsg::Lock& js, |
| 36 | NodeExceptionCode code, |
| 37 | JsErrorType type = JsErrorType::Error, |
| 38 | kj::StringPtr message = nullptr) { |
| 39 | js.throwException(createNodeException(js, code, type, message)); |
| 40 | } |
| 41 | |
| 42 | #define V(name) \ |
| 43 | [[noreturn]] inline void THROW_##name(jsg::Lock& js, kj::StringPtr message = nullptr) { \ |
| 44 | throwNodeException(js, NodeExceptionCode::name, JsErrorType::Error, message); \ |
| 45 | } |
| 46 | |
| 47 | NODE_EXCEPTION_CODE_LIST(V) |
| 48 | #undef V |
| 49 | |
| 50 | // Create a Node.js-style "UVException". The UVException is an |
| 51 | // ordinary Error object with additional properties like code, |
| 52 | // syscall, path, and destination properties. It is primarily |
| 53 | // used to represent file system API errors. |
| 54 | jsg::JsValue createUVException(jsg::Lock& js, |
| 55 | int errorno, |
| 56 | kj::StringPtr syscall, |
| 57 | kj::StringPtr message = nullptr, |
| 58 | kj::StringPtr path = nullptr, |
| 59 | kj::StringPtr dest = nullptr); |
| 60 | |
| 61 | // Throw a Node.js-style "UVException". The UVException is an |
| 62 | // ordinary Error object with additional properties like code, |
| 63 | // syscall, path, and destination properties. It is primarily |
| 64 | // used to represent file system API errors. |
| 65 | [[noreturn]] inline void throwUVException(jsg::Lock& js, |
| 66 | int errorno, |
| 67 | kj::StringPtr syscall, |
| 68 | kj::StringPtr message, |
| 69 | kj::StringPtr path, |
| 70 | kj::StringPtr dest) { |
| 71 | js.throwException(createUVException(js, errorno, syscall, message, path, dest)); |
| 72 | } |
| 73 | |
| 74 | // This is an intentionally truncated list of the error codes that Node.js/libuv |
| 75 | // uses. We won't need all of the error codes that libuv uses. |
| 76 | #define UV_ERRNO_MAP(V) \ |
| 77 | V(EACCES, "permission denied") \ |
| 78 | V(EBADF, "bad file descriptor") \ |
| 79 | V(EEXIST, "file already exists") \ |
| 80 | V(EFBIG, "file too large") \ |
| 81 | V(EINVAL, "invalid argument") \ |
| 82 | V(EISDIR, "illegal operation on a directory") \ |
| 83 | V(ELOOP, "too many symbolic links encountered") \ |
| 84 | V(EMFILE, "too many open files") \ |
| 85 | V(ENAMETOOLONG, "name too long") \ |
| 86 | V(ENFILE, "file table overflow") \ |
| 87 | V(ENOBUFS, "no buffer space available") \ |
| 88 | V(ENODEV, "no such device") \ |
| 89 | V(ENOENT, "no such file or directory") \ |
| 90 | V(ENOMEM, "not enough memory") \ |
| 91 | V(ENOSPC, "no space left on device") \ |
| 92 | V(ENOSYS, "function not implemented") \ |
| 93 | V(ENOTDIR, "not a directory") \ |
| 94 | V(ENOTEMPTY, "directory not empty") \ |
| 95 | V(EPERM, "operation not permitted") \ |
| 96 | V(EMLINK, "too many links") \ |
| 97 | V(EIO, "input/output error") |
| 98 | |
| 99 | #define V(code, _) constexpr int UV_##code = -code; |
| 100 | UV_ERRNO_MAP(V) |
| 101 | #undef V |
| 102 | |
| 103 | #define V(code, _) \ |
| 104 | [[noreturn]] inline void THROW_ERR_UV_##code(jsg::Lock& js, kj::StringPtr syscall, \ |
| 105 | kj::StringPtr message = nullptr, kj::StringPtr path = nullptr, \ |
| 106 | kj::StringPtr dest = nullptr) { \ |
| 107 | throwUVException(js, UV_##code, syscall, message, path, dest); \ |
| 108 | } |
| 109 | UV_ERRNO_MAP(V) |
| 110 | #undef V |
| 111 | |
| 112 | } // namespace workerd::api::node |