Skip to content

Commit

Permalink
src: move *Exceptions out to separate cc/h
Browse files Browse the repository at this point in the history
PR-URL: #20789
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Daniel Bevenius <daniel.bevenius@gmail.com>
Reviewed-By: Gus Caplan <me@gus.host>
Reviewed-By: Tiancheng "Timothy" Gu <timothygu99@gmail.com>
  • Loading branch information
jasnell authored and MylesBorins committed May 22, 2018
1 parent 08b98d1 commit 010ad8c
Show file tree
Hide file tree
Showing 7 changed files with 340 additions and 306 deletions.
2 changes: 2 additions & 0 deletions node.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down Expand Up @@ -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',
Expand Down
11 changes: 1 addition & 10 deletions src/callback_scope.h
Original file line number Diff line number Diff line change
@@ -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 {
Expand Down
44 changes: 44 additions & 0 deletions src/core.h
Original file line number Diff line number Diff line change
@@ -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_
215 changes: 215 additions & 0 deletions src/exceptions.cc
Original file line number Diff line number Diff line change
@@ -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 <string.h>

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<Value> ErrnoException(Isolate* isolate,
int errorno,
const char *syscall,
const char *msg,
const char *path) {
Environment* env = Environment::GetCurrent(isolate);

Local<Value> e;
Local<String> estring = OneByteString(env->isolate(), errno_string(errorno));
if (msg == nullptr || msg[0] == '\0') {
msg = strerror(errorno);
}
Local<String> message = OneByteString(env->isolate(), msg);

Local<String> cons =
String::Concat(estring, FIXED_ONE_BYTE_STRING(env->isolate(), ", "));
cons = String::Concat(cons, message);

Local<String> 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<Object> obj = e.As<Object>();
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<String> 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<Value> UVException(Isolate* isolate,
int errorno,
const char* syscall,
const char* msg,
const char* path) {
return UVException(isolate, errorno, syscall, msg, path, nullptr);
}


Local<Value> 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<String> js_code = OneByteString(isolate, uv_err_name(errorno));
Local<String> js_syscall = OneByteString(isolate, syscall);
Local<String> js_path;
Local<String> js_dest;

Local<String> 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<Object> 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<Value> WinapiErrnoException(Isolate* isolate,
int errorno,
const char* syscall,
const char* msg,
const char* path) {
Environment* env = Environment::GetCurrent(isolate);
Local<Value> e;
bool must_free = false;
if (!msg || !msg[0]) {
msg = winapi_strerror(errorno, &must_free);
}
Local<String> message = OneByteString(env->isolate(), msg);

if (path) {
Local<String> cons1 =
String::Concat(message, FIXED_ONE_BYTE_STRING(isolate, " '"));
Local<String> cons2 =
String::Concat(cons1, String::NewFromUtf8(isolate, path));
Local<String> cons3 =
String::Concat(cons2, FIXED_ONE_BYTE_STRING(isolate, "'"));
e = Exception::Error(cons3);
} else {
e = Exception::Error(message);
}

Local<Object> obj = e.As<Object>();
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
76 changes: 76 additions & 0 deletions src/exceptions.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
#ifndef SRC_EXCEPTIONS_H_
#define SRC_EXCEPTIONS_H_

#include "core.h"
#include "v8.h"

namespace node {

NODE_EXTERN v8::Local<v8::Value> ErrnoException(v8::Isolate* isolate,
int errorno,
const char* syscall = nullptr,
const char* message = nullptr,
const char* path = nullptr);
NODE_EXTERN v8::Local<v8::Value> UVException(v8::Isolate* isolate,
int errorno,
const char* syscall = nullptr,
const char* message = nullptr,
const char* path = nullptr);
NODE_EXTERN v8::Local<v8::Value> 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<v8::Value> 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<v8::Value> 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<v8::Value> 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<v8::Value> 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_
Loading

0 comments on commit 010ad8c

Please sign in to comment.