mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-12-07 21:59:54 +00:00
LibJS: Use non-copying GetUint8ArrayBytes() in Uint8Array.toBase64()
If the ArrayBuffer we're looking at is non-shared, we can simply get a view onto the underlying bytes and pass that to the Base64 encoder.
This commit is contained in:
parent
124b4fc06a
commit
c1c24e8fd6
Notes:
github-actions[bot]
2025-11-29 14:40:50 +00:00
Author: https://github.com/awesomekling
Commit: c1c24e8fd6
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/6975
Reviewed-by: https://github.com/trflynn89
2 changed files with 46 additions and 14 deletions
|
|
@ -333,22 +333,33 @@ JS_DEFINE_NATIVE_FUNCTION(Uint8ArrayPrototypeHelpers::to_base64)
|
|||
}
|
||||
|
||||
// 8. Let toEncode be ? GetUint8ArrayBytes(O).
|
||||
auto to_encode = TRY(get_uint8_array_bytes(vm, typed_array));
|
||||
|
||||
String out_ascii;
|
||||
|
||||
// 9. If alphabet is "base64", then
|
||||
if (alphabet == Alphabet::Base64) {
|
||||
// a. Let outAscii be the sequence of code points which results from encoding toEncode according to the base64
|
||||
// encoding specified in section 4 of RFC 4648. Padding is included if and only if omitPadding is false.
|
||||
out_ascii = MUST(encode_base64(to_encode, omit_padding));
|
||||
}
|
||||
// 10. Else,
|
||||
else {
|
||||
// a. Assert: alphabet is "base64url".
|
||||
// b. Let outAscii be the sequence of code points which results from encoding toEncode according to the base64url
|
||||
// encoding specified in section 5 of RFC 4648. Padding is included if and only if omitPadding is false.
|
||||
out_ascii = MUST(encode_base64url(to_encode, omit_padding));
|
||||
// OPTIMIZATION: If the ArrayBuffer is not shared, we can avoid copying the bytes.
|
||||
if (!typed_array->viewed_array_buffer()->is_shared_array_buffer()
|
||||
&& !typed_array->viewed_array_buffer()->is_detached()) {
|
||||
auto to_encode = TRY(get_uint8_array_bytes_view(vm, typed_array));
|
||||
if (alphabet == Alphabet::Base64) {
|
||||
out_ascii = MUST(encode_base64(to_encode, omit_padding));
|
||||
} else {
|
||||
out_ascii = MUST(encode_base64url(to_encode, omit_padding));
|
||||
}
|
||||
} else {
|
||||
auto to_encode = TRY(get_uint8_array_bytes(vm, typed_array));
|
||||
|
||||
// 9. If alphabet is "base64", then
|
||||
if (alphabet == Alphabet::Base64) {
|
||||
// a. Let outAscii be the sequence of code points which results from encoding toEncode according to the base64
|
||||
// encoding specified in section 4 of RFC 4648. Padding is included if and only if omitPadding is false.
|
||||
out_ascii = MUST(encode_base64(to_encode, omit_padding));
|
||||
}
|
||||
// 10. Else,
|
||||
else {
|
||||
// a. Assert: alphabet is "base64url".
|
||||
// b. Let outAscii be the sequence of code points which results from encoding toEncode according to the base64url
|
||||
// encoding specified in section 5 of RFC 4648. Padding is included if and only if omitPadding is false.
|
||||
out_ascii = MUST(encode_base64url(to_encode, omit_padding));
|
||||
}
|
||||
}
|
||||
|
||||
// 11. Return CodePointsToString(outAscii).
|
||||
|
|
@ -438,6 +449,26 @@ ThrowCompletionOr<ByteBuffer> get_uint8_array_bytes(VM& vm, TypedArrayBase const
|
|||
return bytes;
|
||||
}
|
||||
|
||||
// 23.3.3.2 GetUint8ArrayBytes ( ta ), https://tc39.es/ecma262/#sec-getuint8arraybytes
|
||||
// NOTE: This is an optimized version that returns a view into the underlying buffer when possible.
|
||||
// It's only safe to use when the ArrayBuffer is known to not be shared or detached.
|
||||
ThrowCompletionOr<ReadonlyBytes> get_uint8_array_bytes_view(VM& vm, TypedArrayBase const& typed_array)
|
||||
{
|
||||
VERIFY(typed_array.kind() == TypedArrayBase::Kind::Uint8Array);
|
||||
VERIFY(!typed_array.viewed_array_buffer()->is_shared_array_buffer());
|
||||
VERIFY(!typed_array.viewed_array_buffer()->is_detached());
|
||||
auto typed_array_record = make_typed_array_with_buffer_witness_record(typed_array, ArrayBuffer::Order::SeqCst);
|
||||
if (is_typed_array_out_of_bounds(typed_array_record))
|
||||
return vm.throw_completion<TypeError>(ErrorType::BufferOutOfBounds, "TypedArray"sv);
|
||||
auto length = typed_array_length(typed_array_record);
|
||||
auto byte_offset = typed_array.byte_offset();
|
||||
|
||||
return ReadonlyBytes {
|
||||
typed_array.viewed_array_buffer()->buffer().data() + byte_offset,
|
||||
length
|
||||
};
|
||||
}
|
||||
|
||||
// 23.3.3.3 SetUint8ArrayBytes ( into, bytes ), https://tc39.es/ecma262/#sec-setuint8arraybytes
|
||||
void set_uint8_array_bytes(TypedArrayBase& into, ReadonlyBytes bytes)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ struct DecodeResult {
|
|||
|
||||
ThrowCompletionOr<GC::Ref<TypedArrayBase>> validate_uint8_array(VM&);
|
||||
ThrowCompletionOr<ByteBuffer> get_uint8_array_bytes(VM&, TypedArrayBase const&);
|
||||
ThrowCompletionOr<ReadonlyBytes> get_uint8_array_bytes_view(VM&, TypedArrayBase const&);
|
||||
void set_uint8_array_bytes(TypedArrayBase&, ReadonlyBytes);
|
||||
DecodeResult from_base64(VM&, StringView string, Alphabet alphabet, AK::LastChunkHandling last_chunk_handling, Optional<size_t> max_length = {});
|
||||
DecodeResult from_hex(VM&, StringView string, Optional<size_t> max_length = {});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue