2021-09-26 14:53:28 +01:00
/*
* Copyright ( c ) 2021 , Luke Wilde < lukew @ serenityos . org >
2021-12-13 22:07:04 +00:00
* Copyright ( c ) 2021 , Linus Groh < linusg @ serenityos . org >
2021-09-26 14:53:28 +01:00
*
* SPDX - License - Identifier : BSD - 2 - Clause
*/
2021-12-13 22:07:04 +00:00
# include <AK/ByteBuffer.h>
2021-09-26 14:53:28 +01:00
# include <AK/NumericLimits.h>
# include <LibJS/Runtime/AbstractOperations.h>
2021-12-13 22:07:04 +00:00
# include <LibJS/Runtime/ArrayBuffer.h>
# include <LibJS/Runtime/DataView.h>
2021-10-24 16:01:24 +02:00
# include <LibJS/Runtime/PropertyKey.h>
2021-12-13 22:07:04 +00:00
# include <LibJS/Runtime/TypedArray.h>
2021-09-26 14:53:28 +01:00
# include <LibWeb/Bindings/IDLAbstractOperations.h>
namespace Web : : Bindings : : IDL {
2021-10-11 13:15:16 +01:00
// https://webidl.spec.whatwg.org/#is-an-array-index
2021-10-24 16:01:24 +02:00
bool is_an_array_index ( JS : : GlobalObject & global_object , JS : : PropertyKey const & property_name )
2021-09-26 14:53:28 +01:00
{
// 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 ;
}
2021-12-13 22:07:04 +00:00
// 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 ( ) )
2021-12-14 19:49:15 +00:00
return ByteBuffer { } ;
2021-12-13 22:07:04 +00:00
// 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 ;
}
2021-09-26 14:53:28 +01:00
}