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