summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBrian White <mscdex@mscdex.net>2015-10-13 17:18:15 -0400
committerBrian White <mscdex@mscdex.net>2015-10-13 18:10:27 -0400
commit2d3560767e6da62ceb0e5189c8f0b9a8f0a0924d (patch)
treeb95bef3cb06eb92e83fdc9fbb420d9557b4798b6 /src
parent0a7076b0f14bc26c6544caed199e3e169869295d (diff)
downloadnode-new-2d3560767e6da62ceb0e5189c8f0b9a8f0a0924d.tar.gz
src: fix exception message encoding on Windows
The printf family of functions do not properly display UTF8 strings well on Windows. Use the appropriate wide character API instead if stderr is a tty. PR-URL: https://github.com/nodejs/node/pull/3288 Fixes: https://github.com/nodejs/node/issues/3284 Reviewed-By: Bert Belder <bertbelder@gmail.com>
Diffstat (limited to 'src')
-rw-r--r--src/node.cc58
1 files changed, 45 insertions, 13 deletions
diff --git a/src/node.cc b/src/node.cc
index 91e8c16974..1dfa854ed5 100644
--- a/src/node.cc
+++ b/src/node.cc
@@ -51,6 +51,7 @@
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
+#include <vector>
#if defined(NODE_HAVE_I18N_SUPPORT)
#include <unicode/uvernum.h>
@@ -156,6 +157,38 @@ static Isolate* node_isolate = nullptr;
static v8::Platform* default_platform;
+static void PrintErrorString(const char* format, ...) {
+ va_list ap;
+ va_start(ap, format);
+#ifdef _WIN32
+ HANDLE stderr_handle = GetStdHandle(STD_ERROR_HANDLE);
+
+ // Check if stderr is something other than a tty/console
+ if (stderr_handle == INVALID_HANDLE_VALUE ||
+ stderr_handle == nullptr ||
+ uv_guess_handle(_fileno(stderr)) != UV_TTY) {
+ vfprintf(stderr, format, ap);
+ return;
+ }
+
+ // Fill in any placeholders
+ int n = _vscprintf(format, ap);
+ std::vector<char> out(n + 1);
+ vsprintf(out.data(), format, ap);
+
+ // Get required wide buffer size
+ n = MultiByteToWideChar(CP_UTF8, 0, out.data(), -1, nullptr, 0);
+
+ std::vector<wchar_t> wbuf(n);
+ MultiByteToWideChar(CP_UTF8, 0, out.data(), -1, wbuf.data(), n);
+ WriteConsoleW(stderr_handle, wbuf.data(), n, nullptr, nullptr);
+#else
+ vfprintf(stderr, format, ap);
+#endif
+ va_end(ap);
+}
+
+
static void CheckImmediate(uv_check_t* handle) {
Environment* env = Environment::from_immediate_check_handle(handle);
HandleScope scope(env->isolate());
@@ -1404,7 +1437,7 @@ void AppendExceptionLine(Environment* env,
return;
env->set_printed_error(true);
uv_tty_reset_mode();
- fprintf(stderr, "\n%s", arrow);
+ PrintErrorString("\n%s", arrow);
}
@@ -1432,10 +1465,10 @@ static void ReportException(Environment* env,
// range errors have a trace member set to undefined
if (trace.length() > 0 && !trace_value->IsUndefined()) {
if (arrow.IsEmpty() || !arrow->IsString()) {
- fprintf(stderr, "%s\n", *trace);
+ PrintErrorString("%s\n", *trace);
} else {
node::Utf8Value arrow_string(env->isolate(), arrow);
- fprintf(stderr, "%s\n%s\n", *arrow_string, *trace);
+ PrintErrorString("%s\n%s\n", *arrow_string, *trace);
}
} else {
// this really only happens for RangeErrors, since they're the only
@@ -1456,20 +1489,19 @@ static void ReportException(Environment* env,
name->IsUndefined()) {
// Not an error object. Just print as-is.
node::Utf8Value message(env->isolate(), er);
- fprintf(stderr, "%s\n", *message);
+ PrintErrorString("%s\n", *message);
} else {
node::Utf8Value name_string(env->isolate(), name);
node::Utf8Value message_string(env->isolate(), message);
if (arrow.IsEmpty() || !arrow->IsString()) {
- fprintf(stderr, "%s: %s\n", *name_string, *message_string);
+ PrintErrorString("%s: %s\n", *name_string, *message_string);
} else {
node::Utf8Value arrow_string(env->isolate(), arrow);
- fprintf(stderr,
- "%s\n%s: %s\n",
- *arrow_string,
- *name_string,
- *message_string);
+ PrintErrorString("%s\n%s: %s\n",
+ *arrow_string,
+ *name_string,
+ *message_string);
}
}
}
@@ -2164,9 +2196,9 @@ void DLOpen(const FunctionCallbackInfo<Value>& args) {
static void OnFatalError(const char* location, const char* message) {
if (location) {
- fprintf(stderr, "FATAL ERROR: %s %s\n", location, message);
+ PrintErrorString("FATAL ERROR: %s %s\n", location, message);
} else {
- fprintf(stderr, "FATAL ERROR: %s\n", message);
+ PrintErrorString("FATAL ERROR: %s\n", message);
}
fflush(stderr);
ABORT();
@@ -2985,7 +3017,7 @@ static void RawDebug(const FunctionCallbackInfo<Value>& args) {
CHECK(args.Length() == 1 && args[0]->IsString() &&
"must be called with a single string");
node::Utf8Value message(args.GetIsolate(), args[0]);
- fprintf(stderr, "%s\n", *message);
+ PrintErrorString("%s\n", *message);
fflush(stderr);
}