@@ -466,52 +466,64 @@ jsg::Ref<TextEncoder> TextEncoder::constructor(jsg::Lock& js) {
466466}
467467
468468jsg::BufferSource TextEncoder::encode (jsg::Lock& js, jsg::Optional<jsg::JsString> input) {
469- auto str = input.orDefault (js.str ());
469+ jsg::JsString str = input.orDefault (js.str ());
470470
471- // Do the conversion while ValueView is alive, but to a C++ heap buffer (not V8 heap)
472- kj::Array<kj::byte> output_data;
471+ if (str.length (js) == 0 ) {
472+ return jsg::BufferSource (js, jsg::BackingStore::alloc<v8::Uint8Array>(js, 0 ));
473+ }
473474
474- {
475+ // Allocate buffer and write conversion results directly, using BackingStore::wrap to avoid
476+ // heap allocation restrictions while ValueView is alive and avoid copy overhead
477+ jsg::BackingStore backing = [&]() {
475478 v8::String::ValueView value_view (js.v8Isolate , str);
476479 size_t length = static_cast <size_t >(value_view.length ());
477480
478481 if (value_view.is_one_byte ()) {
479482 auto data = reinterpret_cast <const char *>(value_view.data8 ());
480483 size_t utf8_length = simdutf::utf8_length_from_latin1 (data, length);
481- output_data = kj::heapArray<kj::byte>(utf8_length);
484+ auto * output = new kj::Array<kj::byte>(kj:: heapArray<kj::byte>(utf8_length) );
482485 [[maybe_unused]] auto written =
483- simdutf::convert_latin1_to_utf8 (data, length, output_data.asChars ().begin ());
484- KJ_DASSERT (written == output_data.size ());
486+ simdutf::convert_latin1_to_utf8 (data, length, output->asChars ().begin ());
487+ KJ_DASSERT (written == output->size ());
488+ return jsg::BackingStore::wrap<v8::Uint8Array>(output->begin (), output->size (),
489+ [](void *, size_t , void * ptr) { delete reinterpret_cast <kj::Array<kj::byte>*>(ptr); },
490+ output);
485491 } else {
486492 auto data = reinterpret_cast <const char16_t *>(value_view.data16 ());
487493
488494 // Check if UTF-16LE is valid
489- auto validation_result = simdutf::validate_utf16le (data, length);
495+ auto valid_utf16 = simdutf::validate_utf16le (data, length);
490496
491- if (validation_result ) {
497+ if (valid_utf16 ) {
492498 // Valid UTF-16LE, convert directly
493499 size_t utf8_length = simdutf::utf8_length_from_utf16le (data, length);
494- output_data = kj::heapArray<kj::byte>(utf8_length);
500+ auto * output = new kj::Array<kj::byte>(kj:: heapArray<kj::byte>(utf8_length) );
495501 [[maybe_unused]] auto written =
496- simdutf::convert_utf16le_to_utf8 (data, length, output_data.asChars ().begin ());
497- KJ_DASSERT (written == output_data.size ());
502+ simdutf::convert_utf16le_to_utf8 (data, length, output->asChars ().begin ());
503+ KJ_DASSERT (written == output->size ());
504+ return jsg::BackingStore::wrap<v8::Uint8Array>(output->begin (), output->size (),
505+ [](void *, size_t , void * ptr) { delete reinterpret_cast <kj::Array<kj::byte>*>(ptr); },
506+ output);
498507 } else {
499508 // Invalid UTF-16LE (unpaired surrogates), fix it first
500509 auto well_formed = kj::heapArray<char16_t >(length);
501510 simdutf::to_well_formed_utf16le (data, length, well_formed.begin ());
502511
503512 // Now convert the well-formed UTF-16LE to UTF-8
504513 size_t utf8_length = simdutf::utf8_length_from_utf16le (well_formed.begin (), length);
505- output_data = kj::heapArray<kj::byte>(utf8_length);
514+ auto * output = new kj::Array<kj::byte>(kj:: heapArray<kj::byte>(utf8_length) );
506515 [[maybe_unused]] auto written = simdutf::convert_utf16le_to_utf8 (
507- well_formed.begin (), length, output_data.asChars ().begin ());
508- KJ_DASSERT (written == output_data.size ());
516+ well_formed.begin (), length, output->asChars ().begin ());
517+ KJ_DASSERT (written == output->size ());
518+ return jsg::BackingStore::wrap<v8::Uint8Array>(output->begin (), output->size (),
519+ [](void *, size_t , void * ptr) { delete reinterpret_cast <kj::Array<kj::byte>*>(ptr); },
520+ output);
509521 }
510522 }
511- } // ValueView destroyed here, releasing the heap lock
523+ }(); // ValueView destroyed here, releasing the heap lock
512524
513- // Now create BufferSource from the output data (this allocates V8 objects, which is now safe)
514- return jsg::BufferSource (js, jsg::BackingStore::from (js, kj::mv (output_data) ));
525+ // Now create BufferSource from the BackingStore (this allocates V8 objects, which is now safe)
526+ return jsg::BufferSource (js, kj::mv (backing ));
515527}
516528
517529TextEncoder::EncodeIntoResult TextEncoder::encodeInto (
0 commit comments