Skip to content

Commit

Permalink
Detect if stdout is a console in quickjs-libc
Browse files Browse the repository at this point in the history
Use regular libc stdio (fwrite) when stdout is redirected, don't
call WriteConsoleA because that circumvents the redirection.

Fixes: #635
  • Loading branch information
bnoordhuis committed Oct 31, 2024
1 parent df81c99 commit d4f540e
Showing 1 changed file with 41 additions and 39 deletions.
80 changes: 41 additions & 39 deletions quickjs-libc.c
Original file line number Diff line number Diff line change
Expand Up @@ -3910,54 +3910,56 @@ JSModuleDef *js_init_module_os(JSContext *ctx, const char *module_name)

/**********************************************************/

#ifdef _WIN32
static JSValue js_print(JSContext *ctx, JSValue this_val,
int argc, JSValue *argv)
{
int i;
const char *str;
size_t len;
DWORD written;
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
if (hConsole == INVALID_HANDLE_VALUE)
return JS_EXCEPTION;
for(i = 0; i < argc; i++) {
if (i != 0)
WriteConsoleW(hConsole, L" ", 1, &written, NULL);
str = JS_ToCStringLen(ctx, &len, argv[i]);
if (!str)
return JS_EXCEPTION;
DWORD prev = GetConsoleOutputCP();
SetConsoleOutputCP(CP_UTF8);
WriteConsoleA(hConsole, str, len, &written, NULL);
SetConsoleOutputCP(prev);
JS_FreeCString(ctx, str);
}
WriteConsoleW(hConsole, L"\n", 1, &written, NULL);
FlushFileBuffers(hConsole);
return JS_UNDEFINED;
}
#else
static JSValue js_print(JSContext *ctx, JSValue this_val,
int argc, JSValue *argv)
{
#ifdef _WIN32
HANDLE handle;
DWORD mode;
#endif
const char *s;
DynBuf b;
int i;
const char *str;
size_t len;

dbuf_init(&b);
for(i = 0; i < argc; i++) {
if (i != 0)
putchar(' ');
str = JS_ToCStringLen(ctx, &len, argv[i]);
if (!str)
return JS_EXCEPTION;
fwrite(str, 1, len, stdout);
JS_FreeCString(ctx, str);
s = JS_ToCString(ctx, argv[i]);
if (s) {
dbuf_printf(&b, "%s%s", &" "[!i], s);
JS_FreeCString(ctx, s);
} else {
dbuf_printf(&b, "%s<exception>", &" "[!i]);
JS_FreeValue(ctx, JS_GetException(ctx));
}
}
putchar('\n');
dbuf_putc(&b, '\n');
#ifdef _WIN32
// use WriteConsoleA with CP_UTF8 for better Unicode handling vis-a-vis
// the mangling that happens when going through msvcrt's stdio layer,
// *except* when stdout is redirected to something that is not a console
handle = (HANDLE)_get_osfhandle(/*STDOUT_FILENO*/1); // don't CloseHandle
if (GetFileType(handle) != FILE_TYPE_CHAR)
goto fallback;
if (!GetConsoleMode(handle, &mode))
goto fallback;
handle = GetStdHandle(STD_OUTPUT_HANDLE);
if (handle == INVALID_HANDLE_VALUE)
goto fallback;
mode = GetConsoleOutputCP();
SetConsoleOutputCP(CP_UTF8);
WriteConsoleA(handle, b.buf, b.size, NULL, NULL);
SetConsoleOutputCP(mode);
FlushFileBuffers(handle);
goto done;
fallback:
#endif
fwrite(b.buf, 1, b.size, stdout);
fflush(stdout);
goto done; // avoid unused label warning
done:
dbuf_free(&b);
return JS_UNDEFINED;
}
#endif

void js_std_add_helpers(JSContext *ctx, int argc, char **argv)
{
Expand Down

0 comments on commit d4f540e

Please sign in to comment.