2018-04-02 10:36:17 +08:00
|
|
|
#ifndef SRC_NODE_ERRORS_H_
|
|
|
|
|
#define SRC_NODE_ERRORS_H_
|
|
|
|
|
|
|
|
|
|
#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
|
|
|
|
|
|
|
|
|
|
#include "node.h"
|
2019-05-09 12:52:38 -07:00
|
|
|
#include "util.h"
|
|
|
|
|
#include "env.h"
|
2018-04-02 10:36:17 +08:00
|
|
|
#include "v8.h"
|
|
|
|
|
|
2018-04-19 18:41:33 +08:00
|
|
|
// Use ostringstream to print exact-width integer types
|
|
|
|
|
// because the format specifiers are not available on AIX.
|
|
|
|
|
#include <sstream>
|
|
|
|
|
|
2018-04-02 10:36:17 +08:00
|
|
|
namespace node {
|
|
|
|
|
|
2019-03-12 11:07:35 +01:00
|
|
|
using v8::Local;
|
|
|
|
|
using v8::Message;
|
|
|
|
|
using v8::Value;
|
|
|
|
|
|
2018-11-03 22:45:40 +08:00
|
|
|
enum ErrorHandlingMode { CONTEXTIFY_ERROR, FATAL_ERROR, MODULE_ERROR };
|
|
|
|
|
void AppendExceptionLine(Environment* env,
|
2019-03-12 11:07:35 +01:00
|
|
|
Local<Value> er,
|
|
|
|
|
Local<Message> message,
|
2018-11-03 22:45:40 +08:00
|
|
|
enum ErrorHandlingMode mode);
|
|
|
|
|
|
|
|
|
|
[[noreturn]] void FatalError(const char* location, const char* message);
|
|
|
|
|
void OnFatalError(const char* location, const char* message);
|
|
|
|
|
|
|
|
|
|
void PrintErrorString(const char* format, ...);
|
|
|
|
|
|
|
|
|
|
void ReportException(Environment* env, const v8::TryCatch& try_catch);
|
|
|
|
|
|
2019-03-12 11:07:35 +01:00
|
|
|
void ReportException(Environment* env,
|
|
|
|
|
Local<Value> er,
|
|
|
|
|
Local<Message> message);
|
|
|
|
|
|
2018-11-03 22:45:40 +08:00
|
|
|
void FatalException(v8::Isolate* isolate,
|
2019-03-12 11:07:35 +01:00
|
|
|
Local<Value> error,
|
|
|
|
|
Local<Message> message);
|
2018-11-03 22:45:40 +08:00
|
|
|
|
2019-03-11 20:46:43 +01:00
|
|
|
void FatalException(v8::Isolate* isolate,
|
|
|
|
|
Local<Value> error,
|
|
|
|
|
Local<Message> message,
|
|
|
|
|
bool from_promise);
|
|
|
|
|
|
2018-04-02 10:36:17 +08:00
|
|
|
// Helpers to construct errors similar to the ones provided by
|
|
|
|
|
// lib/internal/errors.js.
|
|
|
|
|
// Example: with `V(ERR_INVALID_ARG_TYPE, TypeError)`, there will be
|
|
|
|
|
// `node::ERR_INVALID_ARG_TYPE(isolate, "message")` returning
|
|
|
|
|
// a `Local<Value>` containing the TypeError with proper code and message
|
|
|
|
|
|
|
|
|
|
#define ERRORS_WITH_CODE(V) \
|
2018-10-28 15:59:20 +01:00
|
|
|
V(ERR_BUFFER_CONTEXT_NOT_AVAILABLE, Error) \
|
2018-04-16 23:52:54 +08:00
|
|
|
V(ERR_BUFFER_OUT_OF_BOUNDS, RangeError) \
|
2018-05-13 20:11:05 +02:00
|
|
|
V(ERR_BUFFER_TOO_LARGE, Error) \
|
2017-09-05 22:38:32 +02:00
|
|
|
V(ERR_CONSTRUCT_CALL_REQUIRED, Error) \
|
2018-04-18 15:21:03 +08:00
|
|
|
V(ERR_INVALID_ARG_VALUE, TypeError) \
|
2018-04-16 22:58:19 +08:00
|
|
|
V(ERR_INVALID_ARG_TYPE, TypeError) \
|
2018-08-28 17:28:46 +02:00
|
|
|
V(ERR_INVALID_MODULE_SPECIFIER, TypeError) \
|
|
|
|
|
V(ERR_INVALID_PACKAGE_CONFIG, SyntaxError) \
|
2017-09-05 22:38:32 +02:00
|
|
|
V(ERR_INVALID_TRANSFER_OBJECT, TypeError) \
|
2018-04-02 10:36:17 +08:00
|
|
|
V(ERR_MEMORY_ALLOCATION_FAILED, Error) \
|
2018-04-18 15:39:12 +08:00
|
|
|
V(ERR_MISSING_ARGS, TypeError) \
|
2017-10-07 14:39:02 -07:00
|
|
|
V(ERR_MISSING_MESSAGE_PORT_IN_TRANSFER_LIST, TypeError) \
|
2018-12-23 15:13:32 +01:00
|
|
|
V(ERR_MISSING_PASSPHRASE, TypeError) \
|
2017-09-01 17:03:41 +02:00
|
|
|
V(ERR_MISSING_PLATFORM_FOR_WORKER, Error) \
|
2018-08-28 17:28:46 +02:00
|
|
|
V(ERR_MODULE_NOT_FOUND, Error) \
|
2018-09-19 20:04:47 -07:00
|
|
|
V(ERR_OUT_OF_RANGE, RangeError) \
|
2018-04-19 18:41:33 +08:00
|
|
|
V(ERR_SCRIPT_EXECUTION_INTERRUPTED, Error) \
|
|
|
|
|
V(ERR_SCRIPT_EXECUTION_TIMEOUT, Error) \
|
2018-04-16 22:25:11 +08:00
|
|
|
V(ERR_STRING_TOO_LONG, Error) \
|
2018-11-20 15:30:34 -08:00
|
|
|
V(ERR_TLS_INVALID_PROTOCOL_METHOD, TypeError) \
|
2018-05-13 19:39:32 +02:00
|
|
|
V(ERR_TRANSFERRING_EXTERNALIZED_SHAREDARRAYBUFFER, TypeError) \
|
2018-04-02 10:36:17 +08:00
|
|
|
|
|
|
|
|
#define V(code, type) \
|
|
|
|
|
inline v8::Local<v8::Value> code(v8::Isolate* isolate, \
|
|
|
|
|
const char* message) { \
|
|
|
|
|
v8::Local<v8::String> js_code = OneByteString(isolate, #code); \
|
|
|
|
|
v8::Local<v8::String> js_msg = OneByteString(isolate, message); \
|
|
|
|
|
v8::Local<v8::Object> e = \
|
|
|
|
|
v8::Exception::type(js_msg)->ToObject( \
|
|
|
|
|
isolate->GetCurrentContext()).ToLocalChecked(); \
|
|
|
|
|
e->Set(isolate->GetCurrentContext(), OneByteString(isolate, "code"), \
|
2019-04-09 15:21:36 -07:00
|
|
|
js_code).Check(); \
|
2018-04-02 10:36:17 +08:00
|
|
|
return e; \
|
2018-04-16 22:17:50 +08:00
|
|
|
} \
|
2018-10-25 19:35:17 +02:00
|
|
|
inline void THROW_ ## code(v8::Isolate* isolate, const char* message) { \
|
|
|
|
|
isolate->ThrowException(code(isolate, message)); \
|
|
|
|
|
} \
|
2018-04-16 22:17:50 +08:00
|
|
|
inline void THROW_ ## code(Environment* env, const char* message) { \
|
2018-10-25 19:35:17 +02:00
|
|
|
THROW_ ## code(env->isolate(), message); \
|
2018-04-02 10:36:17 +08:00
|
|
|
}
|
|
|
|
|
ERRORS_WITH_CODE(V)
|
|
|
|
|
#undef V
|
|
|
|
|
|
|
|
|
|
// Errors with predefined static messages
|
|
|
|
|
|
|
|
|
|
#define PREDEFINED_ERROR_MESSAGES(V) \
|
2018-10-28 15:59:20 +01:00
|
|
|
V(ERR_BUFFER_CONTEXT_NOT_AVAILABLE, \
|
|
|
|
|
"Buffer is not available for the current Context") \
|
2017-09-05 22:38:32 +02:00
|
|
|
V(ERR_CONSTRUCT_CALL_REQUIRED, "Cannot call constructor without `new`") \
|
|
|
|
|
V(ERR_INVALID_TRANSFER_OBJECT, "Found invalid object in transferList") \
|
2018-04-19 18:41:33 +08:00
|
|
|
V(ERR_MEMORY_ALLOCATION_FAILED, "Failed to allocate memory") \
|
2017-10-07 14:39:02 -07:00
|
|
|
V(ERR_MISSING_MESSAGE_PORT_IN_TRANSFER_LIST, \
|
|
|
|
|
"MessagePort was found in message but not listed in transferList") \
|
2017-09-01 17:03:41 +02:00
|
|
|
V(ERR_MISSING_PLATFORM_FOR_WORKER, \
|
|
|
|
|
"The V8 platform used by this instance of Node does not support " \
|
|
|
|
|
"creating Workers") \
|
2018-04-19 18:41:33 +08:00
|
|
|
V(ERR_SCRIPT_EXECUTION_INTERRUPTED, \
|
2018-05-13 19:39:32 +02:00
|
|
|
"Script execution was interrupted by `SIGINT`") \
|
|
|
|
|
V(ERR_TRANSFERRING_EXTERNALIZED_SHAREDARRAYBUFFER, \
|
|
|
|
|
"Cannot serialize externalized SharedArrayBuffer") \
|
2018-04-02 10:36:17 +08:00
|
|
|
|
|
|
|
|
#define V(code, message) \
|
|
|
|
|
inline v8::Local<v8::Value> code(v8::Isolate* isolate) { \
|
|
|
|
|
return code(isolate, message); \
|
2018-04-16 22:17:50 +08:00
|
|
|
} \
|
2018-10-25 19:35:17 +02:00
|
|
|
inline void THROW_ ## code(v8::Isolate* isolate) { \
|
|
|
|
|
isolate->ThrowException(code(isolate, message)); \
|
|
|
|
|
} \
|
2018-04-16 22:17:50 +08:00
|
|
|
inline void THROW_ ## code(Environment* env) { \
|
2018-10-25 19:35:17 +02:00
|
|
|
THROW_ ## code(env->isolate()); \
|
2018-04-02 10:36:17 +08:00
|
|
|
}
|
|
|
|
|
PREDEFINED_ERROR_MESSAGES(V)
|
|
|
|
|
#undef V
|
|
|
|
|
|
|
|
|
|
// Errors with predefined non-static messages
|
2018-04-19 18:41:33 +08:00
|
|
|
inline void THROW_ERR_SCRIPT_EXECUTION_TIMEOUT(Environment* env,
|
|
|
|
|
int64_t timeout) {
|
|
|
|
|
std::ostringstream message;
|
|
|
|
|
message << "Script execution timed out after ";
|
|
|
|
|
message << timeout << "ms";
|
|
|
|
|
THROW_ERR_SCRIPT_EXECUTION_TIMEOUT(env, message.str().c_str());
|
|
|
|
|
}
|
2018-04-02 10:36:17 +08:00
|
|
|
|
2018-05-16 11:50:48 +02:00
|
|
|
inline v8::Local<v8::Value> ERR_BUFFER_TOO_LARGE(v8::Isolate* isolate) {
|
2018-04-02 10:36:17 +08:00
|
|
|
char message[128];
|
|
|
|
|
snprintf(message, sizeof(message),
|
2018-06-10 02:49:38 +02:00
|
|
|
"Cannot create a Buffer larger than 0x%zx bytes",
|
2018-04-02 10:36:17 +08:00
|
|
|
v8::TypedArray::kMaxLength);
|
|
|
|
|
return ERR_BUFFER_TOO_LARGE(isolate, message);
|
|
|
|
|
}
|
|
|
|
|
|
2018-05-16 11:50:48 +02:00
|
|
|
inline v8::Local<v8::Value> ERR_STRING_TOO_LONG(v8::Isolate* isolate) {
|
2018-04-02 10:36:17 +08:00
|
|
|
char message[128];
|
|
|
|
|
snprintf(message, sizeof(message),
|
2018-04-07 20:36:33 +08:00
|
|
|
"Cannot create a string longer than 0x%x characters",
|
2018-04-02 10:36:17 +08:00
|
|
|
v8::String::kMaxLength);
|
2018-04-07 20:36:33 +08:00
|
|
|
return ERR_STRING_TOO_LONG(isolate, message);
|
2018-04-02 10:36:17 +08:00
|
|
|
}
|
|
|
|
|
|
2018-04-16 22:58:19 +08:00
|
|
|
#define THROW_AND_RETURN_IF_NOT_BUFFER(env, val, prefix) \
|
|
|
|
|
do { \
|
|
|
|
|
if (!Buffer::HasInstance(val)) \
|
|
|
|
|
return node::THROW_ERR_INVALID_ARG_TYPE(env, \
|
|
|
|
|
prefix " must be a buffer"); \
|
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
|
|
#define THROW_AND_RETURN_IF_NOT_STRING(env, val, prefix) \
|
|
|
|
|
do { \
|
|
|
|
|
if (!val->IsString()) \
|
|
|
|
|
return node::THROW_ERR_INVALID_ARG_TYPE(env, \
|
|
|
|
|
prefix " must be a string"); \
|
|
|
|
|
} while (0)
|
|
|
|
|
|
2018-11-30 08:13:45 -06:00
|
|
|
namespace errors {
|
|
|
|
|
|
|
|
|
|
class TryCatchScope : public v8::TryCatch {
|
|
|
|
|
public:
|
|
|
|
|
enum class CatchMode { kNormal, kFatal };
|
|
|
|
|
|
|
|
|
|
explicit TryCatchScope(Environment* env, CatchMode mode = CatchMode::kNormal)
|
|
|
|
|
: v8::TryCatch(env->isolate()), env_(env), mode_(mode) {}
|
|
|
|
|
~TryCatchScope();
|
|
|
|
|
|
|
|
|
|
// Since the dtor is not virtual we need to make sure no one creates
|
|
|
|
|
// object of it in the free store that might be held by polymorphic pointers.
|
|
|
|
|
void* operator new(std::size_t count) = delete;
|
|
|
|
|
void* operator new[](std::size_t count) = delete;
|
|
|
|
|
TryCatchScope(TryCatchScope&) = delete;
|
|
|
|
|
TryCatchScope(TryCatchScope&&) = delete;
|
|
|
|
|
TryCatchScope operator=(TryCatchScope&) = delete;
|
|
|
|
|
TryCatchScope operator=(TryCatchScope&&) = delete;
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
Environment* env_;
|
|
|
|
|
CatchMode mode_;
|
|
|
|
|
};
|
|
|
|
|
|
2019-01-08 23:08:42 +08:00
|
|
|
const char* errno_string(int errorno);
|
2019-04-19 12:40:27 +08:00
|
|
|
void PerIsolateMessageListener(v8::Local<v8::Message> message,
|
|
|
|
|
v8::Local<v8::Value> error);
|
2019-01-08 23:08:42 +08:00
|
|
|
|
2018-11-30 08:13:45 -06:00
|
|
|
} // namespace errors
|
|
|
|
|
|
|
|
|
|
void DecorateErrorStack(Environment* env,
|
|
|
|
|
const errors::TryCatchScope& try_catch);
|
2018-04-02 10:36:17 +08:00
|
|
|
} // namespace node
|
|
|
|
|
|
|
|
|
|
#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
|
|
|
|
|
|
|
|
|
|
#endif // SRC_NODE_ERRORS_H_
|