Skip to content
File

Blob: src/workerd/api/node/exceptions.h

cpp113 lines
1#pragma once
2 
3#include <workerd/jsg/jsg.h>
4 
5namespace 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.
11enum 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 
25enum 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.
32jsg::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 
47NODE_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.
54jsg::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;
100UV_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 }
109UV_ERRNO_MAP(V)
110#undef V
111 
112} // namespace workerd::api::node