Optimize napi_get_value_string_utf8 napi_get_value_string_latin1 napi_get_value_string_utf16 (#20612)

This commit is contained in:
Jarred Sumner
2025-06-24 17:39:33 -07:00
committed by GitHub
parent c019f86f14
commit 5131e66fa5

View File

@@ -2059,23 +2059,26 @@ struct BufferElement<NapiStringEncoding::utf16le> {
template<NapiStringEncoding EncodeTo>
napi_status napi_get_value_string_any_encoding(napi_env env, napi_value napiValue, typename BufferElement<EncodeTo>::Type* buf, size_t bufsize, size_t* writtenPtr)
{
NAPI_PREAMBLE(env);
NAPI_CHECK_ARG(env, napiValue);
JSValue jsValue = toJS(napiValue);
NAPI_RETURN_EARLY_IF_FALSE(env, jsValue.isString(), napi_string_expected);
Zig::GlobalObject* globalObject = toJS(env);
String view = jsValue.asCell()->getString(globalObject);
size_t length = view.length();
JSString* jsString = jsValue.toString(globalObject);
NAPI_RETURN_IF_EXCEPTION(env);
const auto view = jsString->view(globalObject);
NAPI_RETURN_IF_EXCEPTION(env);
if (buf == nullptr) {
// they just want to know the length
NAPI_CHECK_ARG(env, writtenPtr);
switch (EncodeTo) {
case NapiStringEncoding::utf8:
if (view.is8Bit()) {
*writtenPtr = Bun__encoding__byteLengthLatin1AsUTF8(view.span8().data(), length);
if (view->is8Bit()) {
*writtenPtr = Bun__encoding__byteLengthLatin1AsUTF8(view->span8().data(), view->length());
} else {
*writtenPtr = Bun__encoding__byteLengthUTF16AsUTF8(view.span16().data(), length);
*writtenPtr = Bun__encoding__byteLengthUTF16AsUTF8(view->span16().data(), view->length());
}
break;
case NapiStringEncoding::utf16le:
@@ -2084,7 +2087,7 @@ napi_status napi_get_value_string_any_encoding(napi_env env, napi_value napiValu
// if the string's encoding is the same as the destination encoding, this is trivially correct
// if we are converting UTF-16 to Latin-1, then we do so by truncating each code unit, so the length is the same
// if we are converting Latin-1 to UTF-16, then we do so by extending each code unit, so the length is also the same
*writtenPtr = length;
*writtenPtr = view->length();
break;
}
return napi_set_last_error(env, napi_ok);
@@ -2108,19 +2111,22 @@ napi_status napi_get_value_string_any_encoding(napi_env env, napi_value napiValu
// since we need to put a null terminator there
? 2 * (bufsize - 1)
: bufsize - 1);
if (view.is8Bit()) {
if (view->is8Bit()) {
const auto span = view->span8();
if constexpr (EncodeTo == NapiStringEncoding::utf16le) {
// pass subslice to work around Bun__encoding__writeLatin1 asserting that the output has room
written = Bun__encoding__writeLatin1(view.span8().data(),
std::min(static_cast<size_t>(view.span8().size()), bufsize),
written = Bun__encoding__writeLatin1(span.data(),
std::min(static_cast<size_t>(span.size()), bufsize),
writable_byte_slice.data(),
writable_byte_slice.size(),
static_cast<uint8_t>(EncodeTo));
} else {
written = Bun__encoding__writeLatin1(view.span8().data(), view.length(), writable_byte_slice.data(), writable_byte_slice.size(), static_cast<uint8_t>(EncodeTo));
written = Bun__encoding__writeLatin1(span.data(), span.size(), writable_byte_slice.data(), writable_byte_slice.size(), static_cast<uint8_t>(EncodeTo));
}
} else {
written = Bun__encoding__writeUTF16(view.span16().data(), view.length(), writable_byte_slice.data(), writable_byte_slice.size(), static_cast<uint8_t>(EncodeTo));
const auto span = view->span16();
written = Bun__encoding__writeUTF16(span.data(), span.size(), writable_byte_slice.data(), writable_byte_slice.size(), static_cast<uint8_t>(EncodeTo));
}
// convert bytes to code units