1 #ifndef SRC_NODE_ERRORS_H_
2 #define SRC_NODE_ERRORS_H_
3 
4 #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
5 
6 #include "node.h"
7 #include "util-inl.h"
8 #include "env-inl.h"
9 #include "v8.h"
10 
11 namespace node {
12 
13 // Helpers to construct errors similar to the ones provided by
14 // lib/internal/errors.js.
15 // Example: with `V(ERR_INVALID_ARG_TYPE, TypeError)`, there will be
16 // `node::ERR_INVALID_ARG_TYPE(isolate, "message")` returning
17 // a `Local<Value>` containing the TypeError with proper code and message
18 
19 #define ERRORS_WITH_CODE(V)                                                  \
20   V(ERR_BUFFER_OUT_OF_BOUNDS, RangeError)                                    \
21   V(ERR_BUFFER_TOO_LARGE, Error)                                             \
22   V(ERR_CANNOT_TRANSFER_OBJECT, TypeError)                                   \
23   V(ERR_CLOSED_MESSAGE_PORT, Error)                                          \
24   V(ERR_CONSTRUCT_CALL_REQUIRED, Error)                                      \
25   V(ERR_INDEX_OUT_OF_RANGE, RangeError)                                      \
26   V(ERR_INVALID_ARG_VALUE, TypeError)                                        \
27   V(ERR_INVALID_ARG_TYPE, TypeError)                                         \
28   V(ERR_INVALID_TRANSFER_OBJECT, TypeError)                                  \
29   V(ERR_MEMORY_ALLOCATION_FAILED, Error)                                     \
30   V(ERR_MISSING_ARGS, TypeError)                                             \
31   V(ERR_MISSING_MESSAGE_PORT_IN_TRANSFER_LIST, TypeError)                    \
32   V(ERR_MISSING_MODULE, Error)                                               \
33   V(ERR_MISSING_PLATFORM_FOR_WORKER, Error)                                  \
34   V(ERR_STRING_TOO_LONG, Error)                                              \
35   V(ERR_TRANSFERRING_EXTERNALIZED_SHAREDARRAYBUFFER, TypeError)              \
36 
37 #define V(code, type)                                                         \
38   inline v8::Local<v8::Value> code(v8::Isolate* isolate,                      \
39                                    const char* message)       {               \
40     v8::Local<v8::String> js_code = OneByteString(isolate, #code);            \
41     v8::Local<v8::String> js_msg = OneByteString(isolate, message);           \
42     v8::Local<v8::Object> e =                                                 \
43         v8::Exception::type(js_msg)->ToObject(                                \
44             isolate->GetCurrentContext()).ToLocalChecked();                   \
45     e->Set(isolate->GetCurrentContext(), OneByteString(isolate, "code"),      \
46            js_code).FromJust();                                               \
47     return e;                                                                 \
48   }                                                                           \
49   inline void THROW_ ## code(Environment* env, const char* message) {         \
50     env->isolate()->ThrowException(code(env->isolate(), message));            \
51   }
52   ERRORS_WITH_CODE(V)
53 #undef V
54 
55 // Errors with predefined static messages
56 
57 #define PREDEFINED_ERROR_MESSAGES(V)                                         \
58   V(ERR_CANNOT_TRANSFER_OBJECT, "Cannot transfer object of unsupported type")\
59   V(ERR_CLOSED_MESSAGE_PORT, "Cannot send data on closed MessagePort")       \
60   V(ERR_CONSTRUCT_CALL_REQUIRED, "Cannot call constructor without `new`")    \
61   V(ERR_INDEX_OUT_OF_RANGE, "Index out of range")                            \
62   V(ERR_INVALID_TRANSFER_OBJECT, "Found invalid object in transferList")     \
63   V(ERR_MEMORY_ALLOCATION_FAILED, "Failed to allocate memory")               \
64   V(ERR_MISSING_MESSAGE_PORT_IN_TRANSFER_LIST,                               \
65     "MessagePort was found in message but not listed in transferList")       \
66   V(ERR_MISSING_PLATFORM_FOR_WORKER,                                         \
67     "The V8 platform used by this instance of Node does not support "        \
68     "creating Workers")                                                      \
69   V(ERR_TRANSFERRING_EXTERNALIZED_SHAREDARRAYBUFFER,                         \
70     "Cannot serialize externalized SharedArrayBuffer")                       \
71 
72 #define V(code, message)                                                     \
73   inline v8::Local<v8::Value> code(v8::Isolate* isolate) {                   \
74     return code(isolate, message);                                           \
75   }                                                                          \
76   inline void THROW_ ## code(Environment* env) {                             \
77     env->isolate()->ThrowException(code(env->isolate(), message));           \
78   }
PREDEFINED_ERROR_MESSAGES(V)79   PREDEFINED_ERROR_MESSAGES(V)
80 #undef V
81 
82 // Errors with predefined non-static messages
83 
84 inline v8::Local<v8::Value> ERR_BUFFER_TOO_LARGE(v8::Isolate* isolate) {
85   char message[128];
86   snprintf(message, sizeof(message),
87       "Cannot create a Buffer larger than 0x%zx bytes",
88       v8::TypedArray::kMaxLength);
89   return ERR_BUFFER_TOO_LARGE(isolate, message);
90 }
91 
ERR_STRING_TOO_LONG(v8::Isolate * isolate)92 inline v8::Local<v8::Value> ERR_STRING_TOO_LONG(v8::Isolate* isolate) {
93   char message[128];
94   snprintf(message, sizeof(message),
95       "Cannot create a string longer than 0x%x characters",
96       v8::String::kMaxLength);
97   return ERR_STRING_TOO_LONG(isolate, message);
98 }
99 
100 #define THROW_AND_RETURN_IF_NOT_BUFFER(env, val, prefix)                     \
101   do {                                                                       \
102     if (!Buffer::HasInstance(val))                                           \
103       return node::THROW_ERR_INVALID_ARG_TYPE(env,                           \
104                                               prefix " must be a buffer");   \
105   } while (0)
106 
107 #define THROW_AND_RETURN_IF_NOT_STRING(env, val, prefix)                     \
108   do {                                                                       \
109     if (!val->IsString())                                                    \
110       return node::THROW_ERR_INVALID_ARG_TYPE(env,                           \
111                                               prefix " must be a string");   \
112   } while (0)
113 
114 }  // namespace node
115 
116 #endif  // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
117 
118 #endif  // SRC_NODE_ERRORS_H_
119