Where Online Learning is simpler!
The C and C++ Include Header Files
cat -n /usr/include/nodejs/src/node_errors.h
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 "debug_utils-inl.h" 7 #include "env.h" 8 #include "node_buffer.h" 9 #include "v8.h" 10 11 // Use ostringstream to print exact-width integer types 12 // because the format specifiers are not available on AIX. 13 #include <sstream> 14 15 namespace node { 16 // This forward declaration is required to have the method 17 // available in error messages. 18 namespace errors { 19 const char* errno_string(int errorno); 20 } 21 22 enum ErrorHandlingMode { CONTEXTIFY_ERROR, FATAL_ERROR, MODULE_ERROR }; 23 void AppendExceptionLine(Environment* env, 24 v8::Local<v8::Value> er, 25 v8::Local<v8::Message> message, 26 enum ErrorHandlingMode mode); 27 28 // This function calls backtrace, it should have not be marked as [[noreturn]]. 29 // But it is a public API, removing the attribute can break. 30 // Prefer UNREACHABLE() internally instead, it doesn't need manually set 31 // location. 32 [[noreturn]] void OnFatalError(const char* location, const char* message); 33 // This function calls backtrace, do not mark as [[noreturn]]. Read more in the 34 // ABORT macro. 35 void OOMErrorHandler(const char* location, const v8::OOMDetails& details); 36 37 // Helpers to construct errors similar to the ones provided by 38 // lib/internal/errors.js. 39 // Example: with `V(ERR_INVALID_ARG_TYPE, TypeError)`, there will be 40 // `node::ERR_INVALID_ARG_TYPE(isolate, "message")` returning 41 // a `Local<Value>` containing the TypeError with proper code and message 42 43 #define ERRORS_WITH_CODE(V) \ 44 V(ERR_ACCESS_DENIED, Error) \ 45 V(ERR_BUFFER_CONTEXT_NOT_AVAILABLE, Error) \ 46 V(ERR_BUFFER_OUT_OF_BOUNDS, RangeError) \ 47 V(ERR_BUFFER_TOO_LARGE, Error) \ 48 V(ERR_CLOSED_MESSAGE_PORT, Error) \ 49 V(ERR_CONSTRUCT_CALL_REQUIRED, TypeError) \ 50 V(ERR_CONSTRUCT_CALL_INVALID, TypeError) \ 51 V(ERR_CPU_PROFILE_ALREADY_STARTED, Error) \ 52 V(ERR_CPU_PROFILE_NOT_STARTED, Error) \ 53 V(ERR_CPU_PROFILE_TOO_MANY, Error) \ 54 V(ERR_CRYPTO_CUSTOM_ENGINE_NOT_SUPPORTED, Error) \ 55 V(ERR_CRYPTO_INITIALIZATION_FAILED, Error) \ 56 V(ERR_CRYPTO_INVALID_AUTH_TAG, TypeError) \ 57 V(ERR_CRYPTO_INVALID_COUNTER, TypeError) \ 58 V(ERR_CRYPTO_INVALID_CURVE, TypeError) \ 59 V(ERR_CRYPTO_INVALID_DIGEST, TypeError) \ 60 V(ERR_CRYPTO_INVALID_IV, TypeError) \ 61 V(ERR_CRYPTO_INVALID_JWK, TypeError) \ 62 V(ERR_CRYPTO_INVALID_KEYLEN, RangeError) \ 63 V(ERR_CRYPTO_INVALID_KEYPAIR, RangeError) \ 64 V(ERR_CRYPTO_INVALID_KEYTYPE, RangeError) \ 65 V(ERR_CRYPTO_INVALID_MESSAGELEN, RangeError) \ 66 V(ERR_CRYPTO_INVALID_SCRYPT_PARAMS, RangeError) \ 67 V(ERR_CRYPTO_INVALID_STATE, Error) \ 68 V(ERR_CRYPTO_INVALID_TAG_LENGTH, RangeError) \ 69 V(ERR_CRYPTO_JWK_UNSUPPORTED_CURVE, Error) \ 70 V(ERR_CRYPTO_JWK_UNSUPPORTED_KEY_TYPE, Error) \ 71 V(ERR_CRYPTO_OPERATION_FAILED, Error) \ 72 V(ERR_CRYPTO_TIMING_SAFE_EQUAL_LENGTH, RangeError) \ 73 V(ERR_CRYPTO_UNKNOWN_CIPHER, Error) \ 74 V(ERR_CRYPTO_UNKNOWN_DH_GROUP, Error) \ 75 V(ERR_CRYPTO_UNSUPPORTED_OPERATION, Error) \ 76 V(ERR_CRYPTO_JOB_INIT_FAILED, Error) \ 77 V(ERR_DLOPEN_DISABLED, Error) \ 78 V(ERR_DLOPEN_FAILED, Error) \ 79 V(ERR_ENCODING_INVALID_ENCODED_DATA, TypeError) \ 80 V(ERR_EXECUTION_ENVIRONMENT_NOT_AVAILABLE, Error) \ 81 V(ERR_FS_CP_EINVAL, Error) \ 82 V(ERR_FS_CP_DIR_TO_NON_DIR, Error) \ 83 V(ERR_FS_CP_NON_DIR_TO_DIR, Error) \ 84 V(ERR_FS_CP_SYMLINK_TO_SUBDIRECTORY, Error) \ 85 V(ERR_FS_EISDIR, Error) \ 86 V(ERR_FS_CP_EEXIST, Error) \ 87 V(ERR_FS_CP_SOCKET, Error) \ 88 V(ERR_FS_CP_FIFO_PIPE, Error) \ 89 V(ERR_FS_CP_UNKNOWN, Error) \ 90 V(ERR_ILLEGAL_CONSTRUCTOR, Error) \ 91 V(ERR_INVALID_ADDRESS, Error) \ 92 V(ERR_INVALID_ARG_VALUE, TypeError) \ 93 V(ERR_OSSL_EVP_INVALID_DIGEST, Error) \ 94 V(ERR_INVALID_ARG_TYPE, TypeError) \ 95 V(ERR_INVALID_FILE_URL_HOST, TypeError) \ 96 V(ERR_INVALID_FILE_URL_PATH, TypeError) \ 97 V(ERR_INVALID_INVOCATION, TypeError) \ 98 V(ERR_INVALID_PACKAGE_CONFIG, Error) \ 99 V(ERR_INVALID_OBJECT_DEFINE_PROPERTY, TypeError) \ 100 V(ERR_INVALID_MODULE, Error) \ 101 V(ERR_INVALID_STATE, Error) \ 102 V(ERR_INVALID_THIS, TypeError) \ 103 V(ERR_INVALID_URL, TypeError) \ 104 V(ERR_INVALID_URL_SCHEME, TypeError) \ 105 V(ERR_LOAD_SQLITE_EXTENSION, Error) \ 106 V(ERR_MEMORY_ALLOCATION_FAILED, Error) \ 107 V(ERR_MESSAGE_TARGET_CONTEXT_UNAVAILABLE, Error) \ 108 V(ERR_MISSING_ARGS, TypeError) \ 109 V(ERR_MISSING_PASSPHRASE, TypeError) \ 110 V(ERR_MISSING_PLATFORM_FOR_WORKER, Error) \ 111 V(ERR_MODULE_NOT_FOUND, Error) \ 112 V(ERR_MODULE_LINK_MISMATCH, TypeError) \ 113 V(ERR_NON_CONTEXT_AWARE_DISABLED, Error) \ 114 V(ERR_OPTIONS_BEFORE_BOOTSTRAPPING, Error) \ 115 V(ERR_OUT_OF_RANGE, RangeError) \ 116 V(ERR_REQUIRE_ASYNC_MODULE, Error) \ 117 V(ERR_SCRIPT_EXECUTION_INTERRUPTED, Error) \ 118 V(ERR_SCRIPT_EXECUTION_TIMEOUT, Error) \ 119 V(ERR_STRING_TOO_LONG, Error) \ 120 V(ERR_TLS_INVALID_PROTOCOL_METHOD, TypeError) \ 121 V(ERR_TLS_PSK_SET_IDENTIY_HINT_FAILED, Error) \ 122 V(ERR_VM_MODULE_CACHED_DATA_REJECTED, Error) \ 123 V(ERR_VM_MODULE_LINK_FAILURE, Error) \ 124 V(ERR_WASI_NOT_STARTED, Error) \ 125 V(ERR_ZLIB_INITIALIZATION_FAILED, Error) \ 126 V(ERR_WORKER_INIT_FAILED, Error) \ 127 V(ERR_PROTO_ACCESS, Error) 128 129 // If the macros are used as ERR_*(isolate, message) or 130 // THROW_ERR_*(isolate, message) with a single string argument, do run 131 // formatter on the message, and allow the caller to pass in a message 132 // directly with characters that would otherwise need escaping if used 133 // as format string unconditionally. 134 #define V(code, type) \ 135 template <typename... Args> \ 136 inline v8::Local<v8::Object> code( \ 137 v8::Isolate* isolate, std::string_view format, Args&&... args) { \ 138 std::string message; \ 139 if (sizeof...(Args) == 0) { \ 140 message = format; \ 141 } else { \ 142 message = SPrintF(format, std::forward<Args>(args)...); \ 143 } \ 144 v8::Local<v8::String> js_code = FIXED_ONE_BYTE_STRING(isolate, #code); \ 145 v8::Local<v8::String> js_msg = \ 146 v8::String::NewFromUtf8(isolate, \ 147 message.c_str(), \ 148 v8::NewStringType::kNormal, \ 149 message.length()) \ 150 .ToLocalChecked(); \ 151 v8::Local<v8::Object> e = v8::Exception::type(js_msg) \ 152 ->ToObject(isolate->GetCurrentContext()) \ 153 .ToLocalChecked(); \ 154 e->Set(isolate->GetCurrentContext(), \ 155 FIXED_ONE_BYTE_STRING(isolate, "code"), \ 156 js_code) \ 157 .Check(); \ 158 return e; \ 159 } \ 160 template <typename... Args> \ 161 inline void THROW_##code( \ 162 v8::Isolate* isolate, std::string_view format, Args&&... args) { \ 163 isolate->ThrowException( \ 164 code(isolate, format, std::forward<Args>(args)...)); \ 165 } \ 166 template <typename... Args> \ 167 inline void THROW_##code( \ 168 Environment* env, std::string_view format, Args&&... args) { \ 169 THROW_##code(env->isolate(), format, std::forward<Args>(args)...); \ 170 } \ 171 template <typename... Args> \ 172 inline void THROW_##code( \ 173 Realm* realm, std::string_view format, Args&&... args) { \ 174 THROW_##code(realm->isolate(), format, std::forward<Args>(args)...); \ 175 } 176 ERRORS_WITH_CODE(V) 177 #undef V 178 179 // Errors with predefined static messages 180 181 #define PREDEFINED_ERROR_MESSAGES(V) \ 182 V(ERR_ACCESS_DENIED, "Access to this API has been restricted") \ 183 V(ERR_BUFFER_CONTEXT_NOT_AVAILABLE, \ 184 "Buffer is not available for the current Context") \ 185 V(ERR_CLOSED_MESSAGE_PORT, "Cannot send data on closed MessagePort") \ 186 V(ERR_CONSTRUCT_CALL_INVALID, "Constructor cannot be called") \ 187 V(ERR_CONSTRUCT_CALL_REQUIRED, "Cannot call constructor without `new`") \ 188 V(ERR_CRYPTO_INITIALIZATION_FAILED, "Initialization failed") \ 189 V(ERR_CRYPTO_INVALID_AUTH_TAG, "Invalid authentication tag") \ 190 V(ERR_CRYPTO_INVALID_COUNTER, "Invalid counter") \ 191 V(ERR_CRYPTO_INVALID_CURVE, "Invalid EC curve name") \ 192 V(ERR_CRYPTO_INVALID_DIGEST, "Invalid digest") \ 193 V(ERR_CRYPTO_INVALID_IV, "Invalid initialization vector") \ 194 V(ERR_CRYPTO_INVALID_JWK, "Invalid JWK format") \ 195 V(ERR_CRYPTO_INVALID_KEYLEN, "Invalid key length") \ 196 V(ERR_CRYPTO_INVALID_KEYPAIR, "Invalid key pair") \ 197 V(ERR_CRYPTO_INVALID_KEYTYPE, "Invalid key type") \ 198 V(ERR_CRYPTO_INVALID_MESSAGELEN, "Invalid message length") \ 199 V(ERR_CRYPTO_INVALID_SCRYPT_PARAMS, "Invalid scrypt params") \ 200 V(ERR_CRYPTO_INVALID_STATE, "Invalid state") \ 201 V(ERR_CRYPTO_INVALID_TAG_LENGTH, "Invalid taglength") \ 202 V(ERR_CRYPTO_JWK_UNSUPPORTED_KEY_TYPE, "Unsupported JWK Key Type.") \ 203 V(ERR_CRYPTO_OPERATION_FAILED, "Operation failed") \ 204 V(ERR_CRYPTO_TIMING_SAFE_EQUAL_LENGTH, \ 205 "Input buffers must have the same byte length") \ 206 V(ERR_CRYPTO_UNKNOWN_CIPHER, "Unknown cipher") \ 207 V(ERR_CRYPTO_UNKNOWN_DH_GROUP, "Unknown DH group") \ 208 V(ERR_CRYPTO_UNSUPPORTED_OPERATION, "Unsupported crypto operation") \ 209 V(ERR_CRYPTO_JOB_INIT_FAILED, "Failed to initialize crypto job config") \ 210 V(ERR_DLOPEN_FAILED, "DLOpen failed") \ 211 V(ERR_EXECUTION_ENVIRONMENT_NOT_AVAILABLE, \ 212 "Context not associated with Node.js environment") \ 213 V(ERR_ILLEGAL_CONSTRUCTOR, "Illegal constructor") \ 214 V(ERR_INVALID_ADDRESS, "Invalid socket address") \ 215 V(ERR_INVALID_INVOCATION, "Invalid invocation") \ 216 V(ERR_INVALID_MODULE, "No such module") \ 217 V(ERR_INVALID_STATE, "Invalid state") \ 218 V(ERR_INVALID_THIS, "Value of \"this\" is the wrong type") \ 219 V(ERR_INVALID_URL_SCHEME, "The URL must be of scheme file:") \ 220 V(ERR_LOAD_SQLITE_EXTENSION, "Failed to load SQLite extension") \ 221 V(ERR_MEMORY_ALLOCATION_FAILED, "Failed to allocate memory") \ 222 V(ERR_OSSL_EVP_INVALID_DIGEST, "Invalid digest used") \ 223 V(ERR_MESSAGE_TARGET_CONTEXT_UNAVAILABLE, \ 224 "A message object could not be deserialized successfully in the target " \ 225 "vm.Context") \ 226 V(ERR_MISSING_PLATFORM_FOR_WORKER, \ 227 "The V8 platform used by this instance of Node does not support " \ 228 "creating Workers") \ 229 V(ERR_NON_CONTEXT_AWARE_DISABLED, \ 230 "Loading non context-aware native addons has been disabled") \ 231 V(ERR_SCRIPT_EXECUTION_INTERRUPTED, \ 232 "Script execution was interrupted by `SIGINT`") \ 233 V(ERR_TLS_PSK_SET_IDENTIY_HINT_FAILED, "Failed to set PSK identity hint") \ 234 V(ERR_WASI_NOT_STARTED, "wasi.start() has not been called") \ 235 V(ERR_WORKER_INIT_FAILED, "Worker initialization failure") \ 236 V(ERR_PROTO_ACCESS, \ 237 "Accessing Object.prototype.__proto__ has been " \ 238 "disallowed with --disable-proto=throw") 239 240 #define V(code, message) \ 241 inline v8::Local<v8::Object> code(v8::Isolate* isolate) { \ 242 return code(isolate, message); \ 243 } \ 244 inline void THROW_##code(v8::Isolate* isolate) { \ 245 isolate->ThrowException(code(isolate, message)); \ 246 } \ 247 inline void THROW_##code(Environment* env) { THROW_##code(env->isolate()); } 248 PREDEFINED_ERROR_MESSAGES(V) 249 #undef V 250 251 // Errors with predefined non-static messages 252 inline void THROW_ERR_SCRIPT_EXECUTION_TIMEOUT(Environment* env, 253 int64_t timeout) { 254 THROW_ERR_SCRIPT_EXECUTION_TIMEOUT( 255 env, "Script execution timed out after %dms", timeout); 256 } 257 258 inline void THROW_ERR_REQUIRE_ASYNC_MODULE( 259 Environment* env, 260 v8::Local<v8::Value> filename, 261 v8::Local<v8::Value> parent_filename) { 262 static constexpr const char* prefix = 263 "require() cannot be used on an ESM graph with top-level await. Use " 264 "import() instead. To see where the top-level await comes from, use " 265 "--experimental-print-required-tla."; 266 std::string message = prefix; 267 if (!parent_filename.IsEmpty() && parent_filename->IsString()) { 268 Utf8Value utf8(env->isolate(), parent_filename); 269 message += "\n From "; 270 message += utf8.ToStringView(); 271 } 272 if (!filename.IsEmpty() && filename->IsString()) { 273 Utf8Value utf8(env->isolate(), filename); 274 message += "\n Requiring "; 275 message += utf8.ToStringView(); 276 } 277 THROW_ERR_REQUIRE_ASYNC_MODULE(env, message); 278 } 279 280 inline v8::Local<v8::Object> ERR_BUFFER_TOO_LARGE(v8::Isolate* isolate) { 281 char message[128]; 282 snprintf(message, 283 sizeof(message), 284 "Cannot create a Buffer larger than 0x%zx bytes", 285 Buffer::kMaxLength); 286 return ERR_BUFFER_TOO_LARGE(isolate, message); 287 } 288 289 inline v8::Local<v8::Object> ERR_STRING_TOO_LONG(v8::Isolate* isolate) { 290 char message[128]; 291 snprintf(message, sizeof(message), 292 "Cannot create a string longer than 0x%x characters", 293 v8::String::kMaxLength); 294 return ERR_STRING_TOO_LONG(isolate, message); 295 } 296 297 #define THROW_AND_RETURN_IF_NOT_BUFFER(env, val, prefix) \ 298 do { \ 299 if (!Buffer::HasInstance(val)) \ 300 return node::THROW_ERR_INVALID_ARG_TYPE(env, \ 301 prefix " must be a buffer"); \ 302 } while (0) 303 304 #define THROW_AND_RETURN_IF_NOT_STRING(env, val, prefix) \ 305 do { \ 306 if (!val->IsString()) \ 307 return node::THROW_ERR_INVALID_ARG_TYPE(env, \ 308 prefix " must be a string"); \ 309 } while (0) 310 311 namespace errors { 312 313 class TryCatchScope : public v8::TryCatch { 314 public: 315 enum class CatchMode { kNormal, kFatal, kFatalRethrowStackOverflow }; 316 317 explicit TryCatchScope(Environment* env, CatchMode mode = CatchMode::kNormal) 318 : v8::TryCatch(env->isolate()), env_(env), mode_(mode) {} 319 ~TryCatchScope(); 320 321 // Since the dtor is not virtual we need to make sure no one creates 322 // object of it in the free store that might be held by polymorphic pointers. 323 void* operator new(std::size_t count) = delete; 324 void* operator new[](std::size_t count) = delete; 325 TryCatchScope(TryCatchScope&) = delete; 326 TryCatchScope(TryCatchScope&&) = delete; 327 TryCatchScope operator=(TryCatchScope&) = delete; 328 TryCatchScope operator=(TryCatchScope&&) = delete; 329 330 private: 331 Environment* env_; 332 CatchMode mode_; 333 }; 334 335 // Trigger the global uncaught exception handler `process._fatalException` 336 // in JS land (which emits the 'uncaughtException' event). If that returns 337 // true, continue program execution, otherwise exit the process. 338 void TriggerUncaughtException(v8::Isolate* isolate, 339 const v8::TryCatch& try_catch); 340 void TriggerUncaughtException(v8::Isolate* isolate, 341 v8::Local<v8::Value> error, 342 v8::Local<v8::Message> message, 343 bool from_promise = false); 344 345 const char* errno_string(int errorno); 346 void PerIsolateMessageListener(v8::Local<v8::Message> message, 347 v8::Local<v8::Value> error); 348 349 void DecorateErrorStack(Environment* env, 350 const errors::TryCatchScope& try_catch); 351 void DecorateErrorStack(Environment* env, 352 v8::Local<v8::Value> error, 353 v8::Local<v8::Message> message); 354 355 class PrinterTryCatch : public v8::TryCatch { 356 public: 357 enum PrintSourceLine { kPrintSourceLine, kDontPrintSourceLine }; 358 explicit PrinterTryCatch(v8::Isolate* isolate, 359 PrintSourceLine print_source_line) 360 : v8::TryCatch(isolate), 361 isolate_(isolate), 362 print_source_line_(print_source_line) {} 363 ~PrinterTryCatch(); 364 365 private: 366 v8::Isolate* isolate_; 367 PrintSourceLine print_source_line_; 368 }; 369 370 } // namespace errors 371 372 v8::ModifyCodeGenerationFromStringsResult ModifyCodeGenerationFromStrings( 373 v8::Local<v8::Context> context, 374 v8::Local<v8::Value> source, 375 bool is_code_like); 376 } // namespace node 377 378 #endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS 379 380 #endif // SRC_NODE_ERRORS_H_