ladybird/Userland/Libraries/LibWeb/Bindings/IDLAbstractOperations.cpp
Linus Groh 5f993eecdb LibWeb: Replace incorrect empty Optional return with ByteBuffer
This function initially returned a ByteBuffer, so `return {}` was fine.
It was then changed to return Optional<ByteBuffer>, so we accidentally
started returning an empty Optional instead. Explicitly specify the
constructor name to fix this.

Thanks to DexesTTP for catching this!
2021-12-14 19:49:15 +00:00

125 lines
4.3 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* Copyright (c) 2021, Luke Wilde <lukew@serenityos.org>
* Copyright (c) 2021, Linus Groh <linusg@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <AK/ByteBuffer.h>
#include <AK/NumericLimits.h>
#include <LibJS/Runtime/AbstractOperations.h>
#include <LibJS/Runtime/ArrayBuffer.h>
#include <LibJS/Runtime/DataView.h>
#include <LibJS/Runtime/PropertyKey.h>
#include <LibJS/Runtime/TypedArray.h>
#include <LibWeb/Bindings/IDLAbstractOperations.h>
namespace Web::Bindings::IDL {
// https://webidl.spec.whatwg.org/#is-an-array-index
bool is_an_array_index(JS::GlobalObject& global_object, JS::PropertyKey const& property_name)
{
// 1. If Type(P) is not String, then return false.
if (!property_name.is_number())
return false;
// 2. Let index be ! CanonicalNumericIndexString(P).
auto index = JS::canonical_numeric_index_string(global_object, property_name);
// 3. If index is undefined, then return false.
if (index.is_undefined())
return false;
// 4. If IsInteger(index) is false, then return false.
// NOTE: IsInteger is the old name of IsIntegralNumber.
if (!index.is_integral_number())
return false;
// 5. If index is 0, then return false.
if (index.is_negative_zero())
return false;
// FIXME: I'm not sure if this is correct.
auto index_as_double = index.as_double();
// 6. If index < 0, then return false.
if (index_as_double < 0)
return false;
// 7. If index ≥ 2 ** 32 1, then return false.
// Note: 2 ** 32 1 is the maximum array length allowed by ECMAScript.
if (index_as_double >= NumericLimits<u32>::max())
return false;
// 8. Return true.
return true;
}
// https://webidl.spec.whatwg.org/#dfn-get-buffer-source-copy
Optional<ByteBuffer> 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<JS::TypedArrayBase>(buffer_source)) {
auto const& es_buffer_source = static_cast<JS::TypedArrayBase const&>(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<JS::DataView>(buffer_source)) {
auto const& es_buffer_source = static_cast<JS::DataView const&>(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<JS::ArrayBuffer const&>(buffer_source);
es_array_buffer = &const_cast<JS ::ArrayBuffer&>(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 ByteBuffer {};
// 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<u8>(i, true, JS::ArrayBuffer::Unordered);
(*bytes)[i - offset] = (u8)value.as_u32();
}
// 10. Return bytes.
return bytes;
}
}