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 ());
@@ -1416,7 +1449,7 @@ void AppendExceptionLine(Environment* env,
1416
1449
return ;
1417
1450
env->set_printed_error (true );
1418
1451
uv_tty_reset_mode ();
1419
- fprintf (stderr, " \n %s" , arrow);
1452
+ PrintErrorString ( " \n %s" , arrow);
1420
1453
}
1421
1454
1422
1455
@@ -1444,10 +1477,10 @@ static void ReportException(Environment* env,
1444
1477
// range errors have a trace member set to undefined
1445
1478
if (trace.length () > 0 && !trace_value->IsUndefined ()) {
1446
1479
if (arrow.IsEmpty () || !arrow->IsString ()) {
1447
- fprintf (stderr, " %s\n " , *trace);
1480
+ PrintErrorString ( " %s\n " , *trace);
1448
1481
} else {
1449
1482
node::Utf8Value arrow_string (env->isolate (), arrow);
1450
- fprintf (stderr, " %s\n %s\n " , *arrow_string, *trace);
1483
+ PrintErrorString ( " %s\n %s\n " , *arrow_string, *trace);
1451
1484
}
1452
1485
} else {
1453
1486
// this really only happens for RangeErrors, since they're the only
@@ -1468,20 +1501,19 @@ static void ReportException(Environment* env,
1468
1501
name->IsUndefined ()) {
1469
1502
// Not an error object. Just print as-is.
1470
1503
node::Utf8Value message (env->isolate (), er);
1471
- fprintf (stderr, " %s\n " , *message);
1504
+ PrintErrorString ( " %s\n " , *message);
1472
1505
} else {
1473
1506
node::Utf8Value name_string (env->isolate (), name);
1474
1507
node::Utf8Value message_string (env->isolate (), message);
1475
1508
1476
1509
if (arrow.IsEmpty () || !arrow->IsString ()) {
1477
- fprintf (stderr, " %s: %s\n " , *name_string, *message_string);
1510
+ PrintErrorString ( " %s: %s\n " , *name_string, *message_string);
1478
1511
} else {
1479
1512
node::Utf8Value arrow_string (env->isolate (), arrow);
1480
- fprintf (stderr,
1481
- " %s\n %s: %s\n " ,
1482
- *arrow_string,
1483
- *name_string,
1484
- *message_string);
1513
+ PrintErrorString (" %s\n %s: %s\n " ,
1514
+ *arrow_string,
1515
+ *name_string,
1516
+ *message_string);
1485
1517
}
1486
1518
}
1487
1519
}
@@ -2176,9 +2208,9 @@ void DLOpen(const FunctionCallbackInfo<Value>& args) {
2176
2208
2177
2209
static void OnFatalError (const char * location, const char * message) {
2178
2210
if (location) {
2179
- fprintf (stderr, " FATAL ERROR: %s %s\n " , location, message);
2211
+ PrintErrorString ( " FATAL ERROR: %s %s\n " , location, message);
2180
2212
} else {
2181
- fprintf (stderr, " FATAL ERROR: %s\n " , message);
2213
+ PrintErrorString ( " FATAL ERROR: %s\n " , message);
2182
2214
}
2183
2215
fflush (stderr);
2184
2216
ABORT ();
@@ -3002,7 +3034,7 @@ static void RawDebug(const FunctionCallbackInfo<Value>& args) {
3002
3034
CHECK (args.Length () == 1 && args[0 ]->IsString () &&
3003
3035
" must be called with a single string" );
3004
3036
node::Utf8Value message (args.GetIsolate (), args[0 ]);
3005
- fprintf (stderr, " %s\n " , *message);
3037
+ PrintErrorString ( " %s\n " , *message);
3006
3038
fflush (stderr);
3007
3039
}
3008
3040
0 commit comments