Skip to content

Commit c53a0a8

Browse files
authored
Detect if stdout is a console in quickjs-libc (#642)
Use regular libc stdio (fwrite) when stdout is redirected, don't call WriteConsoleA because that circumvents the redirection. Fixes: #635
1 parent df81c99 commit c53a0a8

File tree

1 file changed

+41
-39
lines changed

1 file changed

+41
-39
lines changed

quickjs-libc.c

Lines changed: 41 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -3910,54 +3910,56 @@ JSModuleDef *js_init_module_os(JSContext *ctx, const char *module_name)
39103910

39113911
/**********************************************************/
39123912

3913-
#ifdef _WIN32
3914-
static JSValue js_print(JSContext *ctx, JSValue this_val,
3915-
int argc, JSValue *argv)
3916-
{
3917-
int i;
3918-
const char *str;
3919-
size_t len;
3920-
DWORD written;
3921-
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
3922-
if (hConsole == INVALID_HANDLE_VALUE)
3923-
return JS_EXCEPTION;
3924-
for(i = 0; i < argc; i++) {
3925-
if (i != 0)
3926-
WriteConsoleW(hConsole, L" ", 1, &written, NULL);
3927-
str = JS_ToCStringLen(ctx, &len, argv[i]);
3928-
if (!str)
3929-
return JS_EXCEPTION;
3930-
DWORD prev = GetConsoleOutputCP();
3931-
SetConsoleOutputCP(CP_UTF8);
3932-
WriteConsoleA(hConsole, str, len, &written, NULL);
3933-
SetConsoleOutputCP(prev);
3934-
JS_FreeCString(ctx, str);
3935-
}
3936-
WriteConsoleW(hConsole, L"\n", 1, &written, NULL);
3937-
FlushFileBuffers(hConsole);
3938-
return JS_UNDEFINED;
3939-
}
3940-
#else
39413913
static JSValue js_print(JSContext *ctx, JSValue this_val,
39423914
int argc, JSValue *argv)
39433915
{
3916+
#ifdef _WIN32
3917+
HANDLE handle;
3918+
DWORD mode;
3919+
#endif
3920+
const char *s;
3921+
DynBuf b;
39443922
int i;
3945-
const char *str;
3946-
size_t len;
3923+
3924+
dbuf_init(&b);
39473925
for(i = 0; i < argc; i++) {
3948-
if (i != 0)
3949-
putchar(' ');
3950-
str = JS_ToCStringLen(ctx, &len, argv[i]);
3951-
if (!str)
3952-
return JS_EXCEPTION;
3953-
fwrite(str, 1, len, stdout);
3954-
JS_FreeCString(ctx, str);
3926+
s = JS_ToCString(ctx, argv[i]);
3927+
if (s) {
3928+
dbuf_printf(&b, "%s%s", &" "[!i], s);
3929+
JS_FreeCString(ctx, s);
3930+
} else {
3931+
dbuf_printf(&b, "%s<exception>", &" "[!i]);
3932+
JS_FreeValue(ctx, JS_GetException(ctx));
3933+
}
39553934
}
3956-
putchar('\n');
3935+
dbuf_putc(&b, '\n');
3936+
#ifdef _WIN32
3937+
// use WriteConsoleA with CP_UTF8 for better Unicode handling vis-a-vis
3938+
// the mangling that happens when going through msvcrt's stdio layer,
3939+
// *except* when stdout is redirected to something that is not a console
3940+
handle = (HANDLE)_get_osfhandle(/*STDOUT_FILENO*/1); // don't CloseHandle
3941+
if (GetFileType(handle) != FILE_TYPE_CHAR)
3942+
goto fallback;
3943+
if (!GetConsoleMode(handle, &mode))
3944+
goto fallback;
3945+
handle = GetStdHandle(STD_OUTPUT_HANDLE);
3946+
if (handle == INVALID_HANDLE_VALUE)
3947+
goto fallback;
3948+
mode = GetConsoleOutputCP();
3949+
SetConsoleOutputCP(CP_UTF8);
3950+
WriteConsoleA(handle, b.buf, b.size, NULL, NULL);
3951+
SetConsoleOutputCP(mode);
3952+
FlushFileBuffers(handle);
3953+
goto done;
3954+
fallback:
3955+
#endif
3956+
fwrite(b.buf, 1, b.size, stdout);
39573957
fflush(stdout);
3958+
goto done; // avoid unused label warning
3959+
done:
3960+
dbuf_free(&b);
39583961
return JS_UNDEFINED;
39593962
}
3960-
#endif
39613963

39623964
void js_std_add_helpers(JSContext *ctx, int argc, char **argv)
39633965
{

0 commit comments

Comments
 (0)