51
51
#include < stdlib.h>
52
52
#include < string.h>
53
53
#include < sys/types.h>
54
+ #include < vector>
54
55
55
56
#if defined(NODE_HAVE_I18N_SUPPORT)
56
57
#include < unicode/uvernum.h>
@@ -156,6 +157,38 @@ static Isolate* node_isolate = nullptr;
156
157
static v8::Platform* default_platform;
157
158
158
159
160
+ static void PrintErrorString (const char * format, ...) {
161
+ va_list ap;
162
+ va_start (ap, format);
163
+ #ifdef _WIN32
164
+ HANDLE stderr_handle = GetStdHandle (STD_ERROR_HANDLE);
165
+
166
+ // Check if stderr is something other than a tty/console
167
+ if (stderr_handle == INVALID_HANDLE_VALUE ||
168
+ stderr_handle == nullptr ||
169
+ uv_guess_handle (_fileno (stderr)) != UV_TTY) {
170
+ vfprintf (stderr, format, ap);
171
+ return ;
172
+ }
173
+
174
+ // Fill in any placeholders
175
+ int n = _vscprintf (format, ap);
176
+ std::vector<char > out (n + 1 );
177
+ vsprintf (out.data (), format, ap);
178
+
179
+ // Get required wide buffer size
180
+ n = MultiByteToWideChar (CP_UTF8, 0 , out.data (), -1 , nullptr , 0 );
181
+
182
+ std::vector<wchar_t > wbuf (n);
183
+ MultiByteToWideChar (CP_UTF8, 0 , out.data (), -1 , wbuf.data (), n);
184
+ WriteConsoleW (stderr_handle, wbuf.data (), n, nullptr , nullptr );
185
+ #else
186
+ vfprintf (stderr, format, ap);
187
+ #endif
188
+ va_end (ap);
189
+ }
190
+
191
+
159
192
static void CheckImmediate (uv_check_t * handle) {
160
193
Environment* env = Environment::from_immediate_check_handle (handle);
161
194
HandleScope scope (env->isolate ());
@@ -1404,7 +1437,7 @@ void AppendExceptionLine(Environment* env,
1404
1437
return ;
1405
1438
env->set_printed_error (true );
1406
1439
uv_tty_reset_mode ();
1407
- fprintf (stderr, " \n %s" , arrow);
1440
+ PrintErrorString ( " \n %s" , arrow);
1408
1441
}
1409
1442
1410
1443
@@ -1432,10 +1465,10 @@ static void ReportException(Environment* env,
1432
1465
// range errors have a trace member set to undefined
1433
1466
if (trace.length () > 0 && !trace_value->IsUndefined ()) {
1434
1467
if (arrow.IsEmpty () || !arrow->IsString ()) {
1435
- fprintf (stderr, " %s\n " , *trace);
1468
+ PrintErrorString ( " %s\n " , *trace);
1436
1469
} else {
1437
1470
node::Utf8Value arrow_string (env->isolate (), arrow);
1438
- fprintf (stderr, " %s\n %s\n " , *arrow_string, *trace);
1471
+ PrintErrorString ( " %s\n %s\n " , *arrow_string, *trace);
1439
1472
}
1440
1473
} else {
1441
1474
// this really only happens for RangeErrors, since they're the only
@@ -1456,20 +1489,19 @@ static void ReportException(Environment* env,
1456
1489
name->IsUndefined ()) {
1457
1490
// Not an error object. Just print as-is.
1458
1491
node::Utf8Value message (env->isolate (), er);
1459
- fprintf (stderr, " %s\n " , *message);
1492
+ PrintErrorString ( " %s\n " , *message);
1460
1493
} else {
1461
1494
node::Utf8Value name_string (env->isolate (), name);
1462
1495
node::Utf8Value message_string (env->isolate (), message);
1463
1496
1464
1497
if (arrow.IsEmpty () || !arrow->IsString ()) {
1465
- fprintf (stderr, " %s: %s\n " , *name_string, *message_string);
1498
+ PrintErrorString ( " %s: %s\n " , *name_string, *message_string);
1466
1499
} else {
1467
1500
node::Utf8Value arrow_string (env->isolate (), arrow);
1468
- fprintf (stderr,
1469
- " %s\n %s: %s\n " ,
1470
- *arrow_string,
1471
- *name_string,
1472
- *message_string);
1501
+ PrintErrorString (" %s\n %s: %s\n " ,
1502
+ *arrow_string,
1503
+ *name_string,
1504
+ *message_string);
1473
1505
}
1474
1506
}
1475
1507
}
@@ -2164,9 +2196,9 @@ void DLOpen(const FunctionCallbackInfo<Value>& args) {
2164
2196
2165
2197
static void OnFatalError (const char * location, const char * message) {
2166
2198
if (location) {
2167
- fprintf (stderr, " FATAL ERROR: %s %s\n " , location, message);
2199
+ PrintErrorString ( " FATAL ERROR: %s %s\n " , location, message);
2168
2200
} else {
2169
- fprintf (stderr, " FATAL ERROR: %s\n " , message);
2201
+ PrintErrorString ( " FATAL ERROR: %s\n " , message);
2170
2202
}
2171
2203
fflush (stderr);
2172
2204
ABORT ();
@@ -2985,7 +3017,7 @@ static void RawDebug(const FunctionCallbackInfo<Value>& args) {
2985
3017
CHECK (args.Length () == 1 && args[0 ]->IsString () &&
2986
3018
" must be called with a single string" );
2987
3019
node::Utf8Value message (args.GetIsolate (), args[0 ]);
2988
- fprintf (stderr, " %s\n " , *message);
3020
+ PrintErrorString ( " %s\n " , *message);
2989
3021
fflush (stderr);
2990
3022
}
2991
3023
0 commit comments