diff --git a/Libraries/LibWeb/IndexedDB/Internal/Algorithms.cpp b/Libraries/LibWeb/IndexedDB/Internal/Algorithms.cpp index efe4aa2dbd7..53859afff5f 100644 --- a/Libraries/LibWeb/IndexedDB/Internal/Algorithms.cpp +++ b/Libraries/LibWeb/IndexedDB/Internal/Algorithms.cpp @@ -22,6 +22,7 @@ #include #include #include +#include namespace Web::IndexedDB { @@ -213,10 +214,14 @@ ErrorOr> convert_a_value_to_a_key(JS::Realm& realm, JS::Value input // - If input is a buffer source type if (input.is_object() && (is(input.as_object()) || is(input.as_object()) || is(input.as_object()))) { - // 1. Let bytes be the result of getting a copy of the bytes held by the buffer source input. Rethrow any exceptions. + // 1. If input is [detached] then return invalid. + if (WebIDL::is_buffer_source_detached(input)) + return Error::from_string_literal("Detached buffer is not supported as key"); + + // 2. Let bytes be the result of getting a copy of the bytes held by the buffer source input. auto data_buffer = TRY(WebIDL::get_buffer_source_copy(input.as_object())); - // 2. Return a new key with type binary and value bytes. + // 3. Return a new key with type binary and value bytes. return Key::create_binary(realm, data_buffer); } diff --git a/Libraries/LibWeb/WebIDL/Buffers.cpp b/Libraries/LibWeb/WebIDL/Buffers.cpp index e53aad280a1..6f056173192 100644 --- a/Libraries/LibWeb/WebIDL/Buffers.cpp +++ b/Libraries/LibWeb/WebIDL/Buffers.cpp @@ -127,4 +127,30 @@ void ArrayBufferView::write(ReadonlyBytes bytes, u32 starting_offset) BufferSource::~BufferSource() = default; +// https://webidl.spec.whatwg.org/#buffersource-detached +bool is_buffer_source_detached(JS::Value const& buffer_source) +{ + // A buffer source type instance bufferSource is detached if the following steps return true: + + // 1. Let jsArrayBuffer be the result of converting bufferSource to a JavaScript value. + // 2. If jsArrayBuffer has a [[ViewedArrayBuffer]] internal slot, then set jsArrayBuffer to jsArrayBuffer.[[ViewedArrayBuffer]]. + if (!buffer_source.is_object()) + return false; + + JS::ArrayBuffer const* js_array_buffer = nullptr; + auto const& array_buffer_object = buffer_source.as_object(); + if (auto const* array_buffer = as_if(array_buffer_object)) { + js_array_buffer = array_buffer; + } else if (auto const* typed_array_base = as_if(array_buffer_object)) { + js_array_buffer = typed_array_base->viewed_array_buffer(); + } else if (auto const* data_view = as_if(array_buffer_object)) { + js_array_buffer = data_view->viewed_array_buffer(); + } else { + return false; + } + + // 3. Return IsDetachedBuffer(jsArrayBuffer). + return js_array_buffer->is_detached(); +} + } diff --git a/Libraries/LibWeb/WebIDL/Buffers.h b/Libraries/LibWeb/WebIDL/Buffers.h index ce9aebc72ee..46da8d20398 100644 --- a/Libraries/LibWeb/WebIDL/Buffers.h +++ b/Libraries/LibWeb/WebIDL/Buffers.h @@ -14,6 +14,8 @@ namespace Web::WebIDL { +bool is_buffer_source_detached(JS::Value const&); + using BufferableObject = Variant< GC::Ref, GC::Ref,