From 5e06d5e9e587139bfa4a583a51bbd5d567cb954b Mon Sep 17 00:00:00 2001 From: Linus Groh Date: Mon, 13 Dec 2021 22:07:04 +0000 Subject: [PATCH] LibWeb: Implement "get a copy of the bytes held by the buffer source" --- .../LibWeb/Bindings/IDLAbstractOperations.cpp | 73 +++++++++++++++++++ .../LibWeb/Bindings/IDLAbstractOperations.h | 3 + 2 files changed, 76 insertions(+) diff --git a/Userland/Libraries/LibWeb/Bindings/IDLAbstractOperations.cpp b/Userland/Libraries/LibWeb/Bindings/IDLAbstractOperations.cpp index f87ea04f61..34c7dc3da9 100644 --- a/Userland/Libraries/LibWeb/Bindings/IDLAbstractOperations.cpp +++ b/Userland/Libraries/LibWeb/Bindings/IDLAbstractOperations.cpp @@ -1,12 +1,17 @@ /* * Copyright (c) 2021, Luke Wilde + * Copyright (c) 2021, Linus Groh * * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include +#include +#include #include +#include #include namespace Web::Bindings::IDL { @@ -50,4 +55,72 @@ bool is_an_array_index(JS::GlobalObject& global_object, JS::PropertyKey const& p return true; } +// https://webidl.spec.whatwg.org/#dfn-get-buffer-source-copy +Optional get_buffer_source_copy(JS::Object const& buffer_source) +{ + // 1. Let esBufferSource be the result of converting bufferSource to an ECMAScript value. + + // 2. Let esArrayBuffer be esBufferSource. + JS::ArrayBuffer* es_array_buffer; + + // 3. Let offset be 0. + u32 offset = 0; + + // 4. Let length be 0. + u32 length = 0; + + // 5. If esBufferSource has a [[ViewedArrayBuffer]] internal slot, then: + if (is(buffer_source)) { + auto const& es_buffer_source = static_cast(buffer_source); + + // 1. Set esArrayBuffer to esBufferSource.[[ViewedArrayBuffer]]. + es_array_buffer = es_buffer_source.viewed_array_buffer(); + + // 2. Set offset to esBufferSource.[[ByteOffset]]. + offset = es_buffer_source.byte_offset(); + + // 3. Set length to esBufferSource.[[ByteLength]]. + length = es_buffer_source.byte_length(); + } else if (is(buffer_source)) { + auto const& es_buffer_source = static_cast(buffer_source); + + // 1. Set esArrayBuffer to esBufferSource.[[ViewedArrayBuffer]]. + es_array_buffer = es_buffer_source.viewed_array_buffer(); + + // 2. Set offset to esBufferSource.[[ByteOffset]]. + offset = es_buffer_source.byte_offset(); + + // 3. Set length to esBufferSource.[[ByteLength]]. + length = es_buffer_source.byte_length(); + } + // 6. Otherwise: + else { + // 1. Assert: esBufferSource is an ArrayBuffer or SharedArrayBuffer object. + auto const& es_buffer_source = static_cast(buffer_source); + es_array_buffer = &const_cast(es_buffer_source); + + // 2. Set length to esBufferSource.[[ArrayBufferByteLength]]. + length = es_buffer_source.byte_length(); + } + + // 7. If ! IsDetachedBuffer(esArrayBuffer) is true, then return the empty byte sequence. + if (es_array_buffer->is_detached()) + return {}; + + // 8. Let bytes be a new byte sequence of length equal to length. + auto bytes = ByteBuffer::create_zeroed(length); + if (!bytes.has_value()) + return {}; + + // 9. For i in the range offset to offset + length − 1, inclusive, set bytes[i − offset] to ! GetValueFromBuffer(esArrayBuffer, i, Uint8, true, Unordered). + for (u64 i = offset; i <= offset + length - 1; ++i) { + auto value = es_array_buffer->get_value(i, true, JS::ArrayBuffer::Unordered); + dbgln("value at i = {} is {}", i, value); + (*bytes)[i - offset] = (u8)value.as_u32(); + } + + // 10. Return bytes. + return bytes; +} + } diff --git a/Userland/Libraries/LibWeb/Bindings/IDLAbstractOperations.h b/Userland/Libraries/LibWeb/Bindings/IDLAbstractOperations.h index b3157b5eba..c6940d6989 100644 --- a/Userland/Libraries/LibWeb/Bindings/IDLAbstractOperations.h +++ b/Userland/Libraries/LibWeb/Bindings/IDLAbstractOperations.h @@ -1,15 +1,18 @@ /* * Copyright (c) 2021, Luke Wilde + * Copyright (c) 2021, Linus Groh * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once +#include #include namespace Web::Bindings::IDL { bool is_an_array_index(JS::GlobalObject&, JS::PropertyKey const&); +Optional get_buffer_source_copy(JS::Object const& buffer_source); }