mirror of
https://github.com/denoland/deno.git
synced 2025-03-03 09:31:22 -05:00
libdeno: fix libdeno.print() unicode output on Windows
Note that emoji are still not supported, due limitations of the Windows console.
This commit is contained in:
parent
2e9d43391f
commit
4cb157b85b
1 changed files with 52 additions and 1 deletions
|
@ -2,9 +2,18 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
#include <io.h>
|
||||
#include <windows.h>
|
||||
#endif // _WIN32
|
||||
|
||||
#include "third_party/v8/include/v8.h"
|
||||
#include "third_party/v8/src/base/logging.h"
|
||||
|
||||
|
@ -93,10 +102,52 @@ void Print(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
|||
DenoIsolate* d = DenoIsolate::FromIsolate(isolate);
|
||||
auto context = d->context_.Get(d->isolate_);
|
||||
v8::HandleScope handle_scope(isolate);
|
||||
v8::String::Utf8Value str(isolate, args[0]);
|
||||
bool is_err =
|
||||
args.Length() >= 2 ? args[1]->BooleanValue(context).ToChecked() : false;
|
||||
FILE* file = is_err ? stderr : stdout;
|
||||
|
||||
#ifdef _WIN32
|
||||
int fd = _fileno(file);
|
||||
if (fd < 0) return;
|
||||
|
||||
HANDLE h = reinterpret_cast<HANDLE>(_get_osfhandle(fd));
|
||||
if (h == INVALID_HANDLE_VALUE) return;
|
||||
|
||||
DWORD mode;
|
||||
if (GetConsoleMode(h, &mode)) {
|
||||
// Print to Windows console. Since the Windows API generally doesn't support
|
||||
// UTF-8 encoded text, we have to use `WriteConsoleW()` which uses UTF-16.
|
||||
v8::String::Value str(isolate, args[0]);
|
||||
auto str_len = static_cast<size_t>(str.length());
|
||||
auto str_wchars = reinterpret_cast<WCHAR*>(*str);
|
||||
|
||||
// WriteConsoleW has some limit to how many characters can be written at
|
||||
// once, which is unspecified but low enough to be encountered in practice.
|
||||
// Therefore we break up the write into chunks of 8kb if necessary.
|
||||
size_t chunk_start = 0;
|
||||
while (chunk_start < str_len) {
|
||||
size_t chunk_end = std::min(chunk_start + 8192, str_len);
|
||||
|
||||
// Do not break in the middle of a surrogate pair. Note that `chunk_end`
|
||||
// points to the start of the next chunk, so we check whether it contains
|
||||
// the second half of a surrogate pair (a.k.a. "low surrogate").
|
||||
if (chunk_end < str_len && str_wchars[chunk_end] >= 0xdc00 &&
|
||||
str_wchars[chunk_end] <= 0xdfff) {
|
||||
--chunk_end;
|
||||
}
|
||||
|
||||
// Write to the console.
|
||||
DWORD chunk_len = static_cast<DWORD>(chunk_end - chunk_start);
|
||||
DWORD _;
|
||||
WriteConsoleW(h, &str_wchars[chunk_start], chunk_len, &_, nullptr);
|
||||
|
||||
chunk_start = chunk_end;
|
||||
}
|
||||
return;
|
||||
}
|
||||
#endif // _WIN32
|
||||
|
||||
v8::String::Utf8Value str(isolate, args[0]);
|
||||
fwrite(*str, sizeof(**str), str.length(), file);
|
||||
fflush(file);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue