From 010ad8c26c86c968d57e10e30e68b746d760682c Mon Sep 17 00:00:00 2001 From: James M Snell Date: Wed, 16 May 2018 14:24:25 -0700 Subject: [PATCH] src: move *Exceptions out to separate cc/h PR-URL: https://github.com/nodejs/node/pull/20789 Reviewed-By: Anna Henningsen Reviewed-By: Daniel Bevenius Reviewed-By: Gus Caplan Reviewed-By: Tiancheng "Timothy" Gu --- node.gyp | 2 + src/callback_scope.h | 11 +-- src/core.h | 44 +++++++++ src/exceptions.cc | 215 +++++++++++++++++++++++++++++++++++++++++++ src/exceptions.h | 76 +++++++++++++++ src/node.cc | 195 --------------------------------------- src/node.h | 103 +-------------------- 7 files changed, 340 insertions(+), 306 deletions(-) create mode 100644 src/core.h create mode 100644 src/exceptions.cc create mode 100644 src/exceptions.h diff --git a/node.gyp b/node.gyp index 6bd95c9954b96a..a40206944f8780 100644 --- a/node.gyp +++ b/node.gyp @@ -307,6 +307,7 @@ 'src/connection_wrap.cc', 'src/connect_wrap.cc', 'src/env.cc', + 'src/exceptions.cc', 'src/fs_event_wrap.cc', 'src/handle_wrap.cc', 'src/js_stream.cc', @@ -369,6 +370,7 @@ 'src/connect_wrap.h', 'src/env.h', 'src/env-inl.h', + 'src/exceptions.h', 'src/handle_wrap.h', 'src/js_stream.h', 'src/module_wrap.h', diff --git a/src/callback_scope.h b/src/callback_scope.h index 11fee0dd57ac81..7f199aaea228d4 100644 --- a/src/callback_scope.h +++ b/src/callback_scope.h @@ -1,16 +1,7 @@ #ifndef SRC_CALLBACK_SCOPE_H_ #define SRC_CALLBACK_SCOPE_H_ -#ifdef _WIN32 -# ifndef BUILDING_NODE_EXTENSION -# define NODE_EXTERN __declspec(dllexport) -# else -# define NODE_EXTERN __declspec(dllimport) -# endif -#else -# define NODE_EXTERN /* nothing */ -#endif - +#include "core.h" #include "v8.h" namespace node { diff --git a/src/core.h b/src/core.h new file mode 100644 index 00000000000000..0dbce4f3f8f6f9 --- /dev/null +++ b/src/core.h @@ -0,0 +1,44 @@ +#ifndef SRC_CORE_H_ +#define SRC_CORE_H_ + +#ifdef _WIN32 +# ifndef BUILDING_NODE_EXTENSION +# define NODE_EXTERN __declspec(dllexport) +# else +# define NODE_EXTERN __declspec(dllimport) +# endif +#else +# define NODE_EXTERN /* nothing */ +#endif + +#define NODE_MAKE_VERSION(major, minor, patch) \ + ((major) * 0x1000 + (minor) * 0x100 + (patch)) + +#ifdef __clang__ +# define NODE_CLANG_AT_LEAST(major, minor, patch) \ + (NODE_MAKE_VERSION(major, minor, patch) <= \ + NODE_MAKE_VERSION(__clang_major__, __clang_minor__, __clang_patchlevel__)) +#else +# define NODE_CLANG_AT_LEAST(major, minor, patch) (0) +#endif + +#ifdef __GNUC__ +# define NODE_GNUC_AT_LEAST(major, minor, patch) \ + (NODE_MAKE_VERSION(major, minor, patch) <= \ + NODE_MAKE_VERSION(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)) +#else +# define NODE_GNUC_AT_LEAST(major, minor, patch) (0) +#endif + +#if NODE_CLANG_AT_LEAST(2, 9, 0) || NODE_GNUC_AT_LEAST(4, 5, 0) +# define NODE_DEPRECATED(message, declarator) \ + __attribute__((deprecated(message))) declarator +#elif defined(_MSC_VER) +# define NODE_DEPRECATED(message, declarator) \ + __declspec(deprecated) declarator +#else +# define NODE_DEPRECATED(message, declarator) \ + declarator +#endif + +#endif // SRC_CORE_H_ diff --git a/src/exceptions.cc b/src/exceptions.cc new file mode 100644 index 00000000000000..3068483bdf58ff --- /dev/null +++ b/src/exceptions.cc @@ -0,0 +1,215 @@ +#include "node.h" +#include "node_internals.h" +#include "env.h" +#include "env-inl.h" +#include "exceptions.h" +#include "util.h" +#include "util-inl.h" +#include "v8.h" +#include "uv.h" + +#include + +namespace node { + +using v8::Exception; +using v8::Integer; +using v8::Isolate; +using v8::Local; +using v8::Message; +using v8::Object; +using v8::String; +using v8::Value; + +Local ErrnoException(Isolate* isolate, + int errorno, + const char *syscall, + const char *msg, + const char *path) { + Environment* env = Environment::GetCurrent(isolate); + + Local e; + Local estring = OneByteString(env->isolate(), errno_string(errorno)); + if (msg == nullptr || msg[0] == '\0') { + msg = strerror(errorno); + } + Local message = OneByteString(env->isolate(), msg); + + Local cons = + String::Concat(estring, FIXED_ONE_BYTE_STRING(env->isolate(), ", ")); + cons = String::Concat(cons, message); + + Local path_string; + if (path != nullptr) { + // FIXME(bnoordhuis) It's questionable to interpret the file path as UTF-8. + path_string = String::NewFromUtf8(env->isolate(), path); + } + + if (path_string.IsEmpty() == false) { + cons = String::Concat(cons, FIXED_ONE_BYTE_STRING(env->isolate(), " '")); + cons = String::Concat(cons, path_string); + cons = String::Concat(cons, FIXED_ONE_BYTE_STRING(env->isolate(), "'")); + } + e = Exception::Error(cons); + + Local obj = e.As(); + obj->Set(env->errno_string(), Integer::New(env->isolate(), errorno)); + obj->Set(env->code_string(), estring); + + if (path_string.IsEmpty() == false) { + obj->Set(env->path_string(), path_string); + } + + if (syscall != nullptr) { + obj->Set(env->syscall_string(), OneByteString(env->isolate(), syscall)); + } + + return e; +} + +static Local StringFromPath(Isolate* isolate, const char* path) { +#ifdef _WIN32 + if (strncmp(path, "\\\\?\\UNC\\", 8) == 0) { + return String::Concat(FIXED_ONE_BYTE_STRING(isolate, "\\\\"), + String::NewFromUtf8(isolate, path + 8)); + } else if (strncmp(path, "\\\\?\\", 4) == 0) { + return String::NewFromUtf8(isolate, path + 4); + } +#endif + + return String::NewFromUtf8(isolate, path); +} + + +Local UVException(Isolate* isolate, + int errorno, + const char* syscall, + const char* msg, + const char* path) { + return UVException(isolate, errorno, syscall, msg, path, nullptr); +} + + +Local UVException(Isolate* isolate, + int errorno, + const char* syscall, + const char* msg, + const char* path, + const char* dest) { + Environment* env = Environment::GetCurrent(isolate); + + if (!msg || !msg[0]) + msg = uv_strerror(errorno); + + Local js_code = OneByteString(isolate, uv_err_name(errorno)); + Local js_syscall = OneByteString(isolate, syscall); + Local js_path; + Local js_dest; + + Local js_msg = js_code; + js_msg = String::Concat(js_msg, FIXED_ONE_BYTE_STRING(isolate, ": ")); + js_msg = String::Concat(js_msg, OneByteString(isolate, msg)); + js_msg = String::Concat(js_msg, FIXED_ONE_BYTE_STRING(isolate, ", ")); + js_msg = String::Concat(js_msg, js_syscall); + + if (path != nullptr) { + js_path = StringFromPath(isolate, path); + + js_msg = String::Concat(js_msg, FIXED_ONE_BYTE_STRING(isolate, " '")); + js_msg = String::Concat(js_msg, js_path); + js_msg = String::Concat(js_msg, FIXED_ONE_BYTE_STRING(isolate, "'")); + } + + if (dest != nullptr) { + js_dest = StringFromPath(isolate, dest); + + js_msg = String::Concat(js_msg, FIXED_ONE_BYTE_STRING(isolate, " -> '")); + js_msg = String::Concat(js_msg, js_dest); + js_msg = String::Concat(js_msg, FIXED_ONE_BYTE_STRING(isolate, "'")); + } + + Local e = Exception::Error(js_msg)->ToObject(isolate); + + e->Set(env->errno_string(), Integer::New(isolate, errorno)); + e->Set(env->code_string(), js_code); + e->Set(env->syscall_string(), js_syscall); + if (!js_path.IsEmpty()) + e->Set(env->path_string(), js_path); + if (!js_dest.IsEmpty()) + e->Set(env->dest_string(), js_dest); + + return e; +} + +#ifdef _WIN32 +// Does about the same as strerror(), +// but supports all windows error messages +static const char *winapi_strerror(const int errorno, bool* must_free) { + char *errmsg = nullptr; + + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, errorno, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&errmsg, 0, nullptr); + + if (errmsg) { + *must_free = true; + + // Remove trailing newlines + for (int i = strlen(errmsg) - 1; + i >= 0 && (errmsg[i] == '\n' || errmsg[i] == '\r'); i--) { + errmsg[i] = '\0'; + } + + return errmsg; + } else { + // FormatMessage failed + *must_free = false; + return "Unknown error"; + } +} + + +Local WinapiErrnoException(Isolate* isolate, + int errorno, + const char* syscall, + const char* msg, + const char* path) { + Environment* env = Environment::GetCurrent(isolate); + Local e; + bool must_free = false; + if (!msg || !msg[0]) { + msg = winapi_strerror(errorno, &must_free); + } + Local message = OneByteString(env->isolate(), msg); + + if (path) { + Local cons1 = + String::Concat(message, FIXED_ONE_BYTE_STRING(isolate, " '")); + Local cons2 = + String::Concat(cons1, String::NewFromUtf8(isolate, path)); + Local cons3 = + String::Concat(cons2, FIXED_ONE_BYTE_STRING(isolate, "'")); + e = Exception::Error(cons3); + } else { + e = Exception::Error(message); + } + + Local obj = e.As(); + obj->Set(env->errno_string(), Integer::New(isolate, errorno)); + + if (path != nullptr) { + obj->Set(env->path_string(), String::NewFromUtf8(isolate, path)); + } + + if (syscall != nullptr) { + obj->Set(env->syscall_string(), OneByteString(isolate, syscall)); + } + + if (must_free) + LocalFree((HLOCAL)msg); + + return e; +} +#endif + +} // namespace node diff --git a/src/exceptions.h b/src/exceptions.h new file mode 100644 index 00000000000000..8a4a8ce99e876d --- /dev/null +++ b/src/exceptions.h @@ -0,0 +1,76 @@ +#ifndef SRC_EXCEPTIONS_H_ +#define SRC_EXCEPTIONS_H_ + +#include "core.h" +#include "v8.h" + +namespace node { + +NODE_EXTERN v8::Local ErrnoException(v8::Isolate* isolate, + int errorno, + const char* syscall = nullptr, + const char* message = nullptr, + const char* path = nullptr); +NODE_EXTERN v8::Local UVException(v8::Isolate* isolate, + int errorno, + const char* syscall = nullptr, + const char* message = nullptr, + const char* path = nullptr); +NODE_EXTERN v8::Local UVException(v8::Isolate* isolate, + int errorno, + const char* syscall, + const char* message, + const char* path, + const char* dest); + +NODE_DEPRECATED( + "Use ErrnoException(isolate, ...)", + inline v8::Local ErrnoException( + int errorno, + const char* syscall = nullptr, + const char* message = nullptr, + const char* path = nullptr) { + return ErrnoException(v8::Isolate::GetCurrent(), + errorno, + syscall, + message, + path); +}) + +inline v8::Local UVException(int errorno, + const char* syscall = nullptr, + const char* message = nullptr, + const char* path = nullptr) { + return UVException(v8::Isolate::GetCurrent(), + errorno, + syscall, + message, + path); +} + +#ifdef _WIN32 +NODE_EXTERN v8::Local WinapiErrnoException( + v8::Isolate* isolate, + int errorno, + const char *syscall = nullptr, + const char *msg = "", + const char *path = nullptr); + +NODE_DEPRECATED( + "Use WinapiErrnoException(isolate, ...)", + inline v8::Local WinapiErrnoException( + int errorno, + const char *syscall = nullptr, + const char *msg = "", + const char *path = nullptr) { + return WinapiErrnoException(v8::Isolate::GetCurrent(), + errorno, + syscall, + msg, + path); +}) +#endif + +} // namespace node + +#endif // SRC_EXCEPTIONS_H_ diff --git a/src/node.cc b/src/node.cc index 3fac1e897a62de..1edb87bf84f0ba 100644 --- a/src/node.cc +++ b/src/node.cc @@ -575,129 +575,6 @@ const char *signo_string(int signo) { } } - -Local ErrnoException(Isolate* isolate, - int errorno, - const char *syscall, - const char *msg, - const char *path) { - Environment* env = Environment::GetCurrent(isolate); - - Local e; - Local estring = OneByteString(env->isolate(), errno_string(errorno)); - if (msg == nullptr || msg[0] == '\0') { - msg = strerror(errorno); - } - Local message = OneByteString(env->isolate(), msg); - - Local cons = - String::Concat(estring, FIXED_ONE_BYTE_STRING(env->isolate(), ", ")); - cons = String::Concat(cons, message); - - Local path_string; - if (path != nullptr) { - // FIXME(bnoordhuis) It's questionable to interpret the file path as UTF-8. - path_string = String::NewFromUtf8(env->isolate(), path); - } - - if (path_string.IsEmpty() == false) { - cons = String::Concat(cons, FIXED_ONE_BYTE_STRING(env->isolate(), " '")); - cons = String::Concat(cons, path_string); - cons = String::Concat(cons, FIXED_ONE_BYTE_STRING(env->isolate(), "'")); - } - e = Exception::Error(cons); - - Local obj = e.As(); - obj->Set(env->errno_string(), Integer::New(env->isolate(), errorno)); - obj->Set(env->code_string(), estring); - - if (path_string.IsEmpty() == false) { - obj->Set(env->path_string(), path_string); - } - - if (syscall != nullptr) { - obj->Set(env->syscall_string(), OneByteString(env->isolate(), syscall)); - } - - return e; -} - - -static Local StringFromPath(Isolate* isolate, const char* path) { -#ifdef _WIN32 - if (strncmp(path, "\\\\?\\UNC\\", 8) == 0) { - return String::Concat(FIXED_ONE_BYTE_STRING(isolate, "\\\\"), - String::NewFromUtf8(isolate, path + 8)); - } else if (strncmp(path, "\\\\?\\", 4) == 0) { - return String::NewFromUtf8(isolate, path + 4); - } -#endif - - return String::NewFromUtf8(isolate, path); -} - - -Local UVException(Isolate* isolate, - int errorno, - const char* syscall, - const char* msg, - const char* path) { - return UVException(isolate, errorno, syscall, msg, path, nullptr); -} - - -Local UVException(Isolate* isolate, - int errorno, - const char* syscall, - const char* msg, - const char* path, - const char* dest) { - Environment* env = Environment::GetCurrent(isolate); - - if (!msg || !msg[0]) - msg = uv_strerror(errorno); - - Local js_code = OneByteString(isolate, uv_err_name(errorno)); - Local js_syscall = OneByteString(isolate, syscall); - Local js_path; - Local js_dest; - - Local js_msg = js_code; - js_msg = String::Concat(js_msg, FIXED_ONE_BYTE_STRING(isolate, ": ")); - js_msg = String::Concat(js_msg, OneByteString(isolate, msg)); - js_msg = String::Concat(js_msg, FIXED_ONE_BYTE_STRING(isolate, ", ")); - js_msg = String::Concat(js_msg, js_syscall); - - if (path != nullptr) { - js_path = StringFromPath(isolate, path); - - js_msg = String::Concat(js_msg, FIXED_ONE_BYTE_STRING(isolate, " '")); - js_msg = String::Concat(js_msg, js_path); - js_msg = String::Concat(js_msg, FIXED_ONE_BYTE_STRING(isolate, "'")); - } - - if (dest != nullptr) { - js_dest = StringFromPath(isolate, dest); - - js_msg = String::Concat(js_msg, FIXED_ONE_BYTE_STRING(isolate, " -> '")); - js_msg = String::Concat(js_msg, js_dest); - js_msg = String::Concat(js_msg, FIXED_ONE_BYTE_STRING(isolate, "'")); - } - - Local e = Exception::Error(js_msg)->ToObject(isolate); - - e->Set(env->errno_string(), Integer::New(isolate, errorno)); - e->Set(env->code_string(), js_code); - e->Set(env->syscall_string(), js_syscall); - if (!js_path.IsEmpty()) - e->Set(env->path_string(), js_path); - if (!js_dest.IsEmpty()) - e->Set(env->dest_string(), js_dest); - - return e; -} - - // Look up environment variable unless running as setuid root. bool SafeGetenv(const char* key, std::string* text) { #if !defined(__CloudABI__) && !defined(_WIN32) @@ -719,78 +596,6 @@ bool SafeGetenv(const char* key, std::string* text) { } -#ifdef _WIN32 -// Does about the same as strerror(), -// but supports all windows error messages -static const char *winapi_strerror(const int errorno, bool* must_free) { - char *errmsg = nullptr; - - FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, errorno, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&errmsg, 0, nullptr); - - if (errmsg) { - *must_free = true; - - // Remove trailing newlines - for (int i = strlen(errmsg) - 1; - i >= 0 && (errmsg[i] == '\n' || errmsg[i] == '\r'); i--) { - errmsg[i] = '\0'; - } - - return errmsg; - } else { - // FormatMessage failed - *must_free = false; - return "Unknown error"; - } -} - - -Local WinapiErrnoException(Isolate* isolate, - int errorno, - const char* syscall, - const char* msg, - const char* path) { - Environment* env = Environment::GetCurrent(isolate); - Local e; - bool must_free = false; - if (!msg || !msg[0]) { - msg = winapi_strerror(errorno, &must_free); - } - Local message = OneByteString(env->isolate(), msg); - - if (path) { - Local cons1 = - String::Concat(message, FIXED_ONE_BYTE_STRING(isolate, " '")); - Local cons2 = - String::Concat(cons1, String::NewFromUtf8(isolate, path)); - Local cons3 = - String::Concat(cons2, FIXED_ONE_BYTE_STRING(isolate, "'")); - e = Exception::Error(cons3); - } else { - e = Exception::Error(message); - } - - Local obj = e.As(); - obj->Set(env->errno_string(), Integer::New(isolate, errorno)); - - if (path != nullptr) { - obj->Set(env->path_string(), String::NewFromUtf8(isolate, path)); - } - - if (syscall != nullptr) { - obj->Set(env->syscall_string(), OneByteString(isolate, syscall)); - } - - if (must_free) - LocalFree((HLOCAL)msg); - - return e; -} -#endif - - void* ArrayBufferAllocator::Allocate(size_t size) { if (zero_fill_field_ || zero_fill_all_buffers) return UncheckedCalloc(size); diff --git a/src/node.h b/src/node.h index e10e393cd64d4b..d4b934645163f1 100644 --- a/src/node.h +++ b/src/node.h @@ -22,16 +22,6 @@ #ifndef SRC_NODE_H_ #define SRC_NODE_H_ -#ifdef _WIN32 -# ifndef BUILDING_NODE_EXTENSION -# define NODE_EXTERN __declspec(dllexport) -# else -# define NODE_EXTERN __declspec(dllimport) -# endif -#else -# define NODE_EXTERN /* nothing */ -#endif - #ifdef BUILDING_NODE_EXTENSION # undef BUILDING_V8_SHARED # undef BUILDING_UV_SHARED @@ -60,40 +50,12 @@ # define SIGKILL 9 #endif +#include "core.h" // NOLINT(build/include_order) #include "v8.h" // NOLINT(build/include_order) #include "v8-platform.h" // NOLINT(build/include_order) #include "node_version.h" // NODE_MODULE_VERSION #include "callback_scope.h" - -#define NODE_MAKE_VERSION(major, minor, patch) \ - ((major) * 0x1000 + (minor) * 0x100 + (patch)) - -#ifdef __clang__ -# define NODE_CLANG_AT_LEAST(major, minor, patch) \ - (NODE_MAKE_VERSION(major, minor, patch) <= \ - NODE_MAKE_VERSION(__clang_major__, __clang_minor__, __clang_patchlevel__)) -#else -# define NODE_CLANG_AT_LEAST(major, minor, patch) (0) -#endif - -#ifdef __GNUC__ -# define NODE_GNUC_AT_LEAST(major, minor, patch) \ - (NODE_MAKE_VERSION(major, minor, patch) <= \ - NODE_MAKE_VERSION(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)) -#else -# define NODE_GNUC_AT_LEAST(major, minor, patch) (0) -#endif - -#if NODE_CLANG_AT_LEAST(2, 9, 0) || NODE_GNUC_AT_LEAST(4, 5, 0) -# define NODE_DEPRECATED(message, declarator) \ - __attribute__((deprecated(message))) declarator -#elif defined(_MSC_VER) -# define NODE_DEPRECATED(message, declarator) \ - __declspec(deprecated) declarator -#else -# define NODE_DEPRECATED(message, declarator) \ - declarator -#endif +#include "exceptions.h" // Forward-declare libuv loop struct uv_loop_s; @@ -107,47 +69,6 @@ class TracingController; // terminally confused when it's done in node_internals.h namespace node { -NODE_EXTERN v8::Local ErrnoException(v8::Isolate* isolate, - int errorno, - const char* syscall = nullptr, - const char* message = nullptr, - const char* path = nullptr); -NODE_EXTERN v8::Local UVException(v8::Isolate* isolate, - int errorno, - const char* syscall = nullptr, - const char* message = nullptr, - const char* path = nullptr); -NODE_EXTERN v8::Local UVException(v8::Isolate* isolate, - int errorno, - const char* syscall, - const char* message, - const char* path, - const char* dest); - -NODE_DEPRECATED("Use ErrnoException(isolate, ...)", - inline v8::Local ErrnoException( - int errorno, - const char* syscall = nullptr, - const char* message = nullptr, - const char* path = nullptr) { - return ErrnoException(v8::Isolate::GetCurrent(), - errorno, - syscall, - message, - path); -}) - -inline v8::Local UVException(int errorno, - const char* syscall = nullptr, - const char* message = nullptr, - const char* path = nullptr) { - return UVException(v8::Isolate::GetCurrent(), - errorno, - syscall, - message, - path); -} - /* * These methods need to be called in a HandleScope. * @@ -452,26 +373,6 @@ NODE_DEPRECATED("Use DecodeWrite(isolate, ...)", return DecodeWrite(v8::Isolate::GetCurrent(), buf, buflen, val, encoding); }) -#ifdef _WIN32 -NODE_EXTERN v8::Local WinapiErrnoException( - v8::Isolate* isolate, - int errorno, - const char *syscall = nullptr, - const char *msg = "", - const char *path = nullptr); - -NODE_DEPRECATED("Use WinapiErrnoException(isolate, ...)", - inline v8::Local WinapiErrnoException(int errorno, - const char *syscall = nullptr, const char *msg = "", - const char *path = nullptr) { - return WinapiErrnoException(v8::Isolate::GetCurrent(), - errorno, - syscall, - msg, - path); -}) -#endif - const char *signo_string(int errorno);