2021-06-13 22:47:08 +00:00
/*
* Copyright ( c ) 2021 , Idan Horowitz < idan . horowitz @ serenityos . org >
*
* SPDX - License - Identifier : BSD - 2 - Clause
*/
2022-06-26 21:33:22 +00:00
# include <AK/Checked.h>
2022-11-23 12:41:50 +00:00
# include <AK/TypeCasts.h>
2021-06-20 00:09:39 +00:00
# include <LibJS/Runtime/AbstractOperations.h>
2021-06-13 22:47:08 +00:00
# include <LibJS/Runtime/DataView.h>
# include <LibJS/Runtime/DataViewConstructor.h>
# include <LibJS/Runtime/Error.h>
# include <LibJS/Runtime/GlobalObject.h>
namespace JS {
2024-11-14 15:01:23 +00:00
GC_DEFINE_ALLOCATOR ( DataViewConstructor ) ;
2023-11-19 08:45:05 +00:00
2022-08-15 23:20:49 +00:00
DataViewConstructor : : DataViewConstructor ( Realm & realm )
2023-04-12 22:47:15 +00:00
: NativeFunction ( realm . vm ( ) . names . DataView . as_string ( ) , realm . intrinsics ( ) . function_prototype ( ) )
2021-06-13 22:47:08 +00:00
{
}
2023-08-07 06:41:28 +00:00
void DataViewConstructor : : initialize ( Realm & realm )
2021-06-13 22:47:08 +00:00
{
auto & vm = this - > vm ( ) ;
2023-08-07 06:41:28 +00:00
Base : : initialize ( realm ) ;
2021-06-13 22:47:08 +00:00
// 25.3.3.1 DataView.prototype, https://tc39.es/ecma262/#sec-dataview.prototype
2022-08-26 23:54:55 +00:00
define_direct_property ( vm . names . prototype , realm . intrinsics ( ) . data_view_prototype ( ) , 0 ) ;
2021-06-13 22:47:08 +00:00
2021-07-05 23:15:08 +00:00
define_direct_property ( vm . names . length , Value ( 1 ) , Attribute : : Configurable ) ;
2021-06-13 22:47:08 +00:00
}
// 25.3.2.1 DataView ( buffer [ , byteOffset [ , byteLength ] ] ), https://tc39.es/ecma262/#sec-dataview-buffer-byteoffset-bytelength
2021-10-20 20:16:30 +00:00
ThrowCompletionOr < Value > DataViewConstructor : : call ( )
2021-06-13 22:47:08 +00:00
{
auto & vm = this - > vm ( ) ;
2023-01-27 21:36:31 +00:00
// 1. If NewTarget is undefined, throw a TypeError exception.
2022-08-16 19:33:17 +00:00
return vm . throw_completion < TypeError > ( ErrorType : : ConstructorWithoutNew , vm . names . DataView ) ;
2021-06-13 22:47:08 +00:00
}
// 25.3.2.1 DataView ( buffer [ , byteOffset [ , byteLength ] ] ), https://tc39.es/ecma262/#sec-dataview-buffer-byteoffset-bytelength
2024-11-14 15:01:23 +00:00
ThrowCompletionOr < GC : : Ref < Object > > DataViewConstructor : : construct ( FunctionObject & new_target )
2021-06-13 22:47:08 +00:00
{
auto & vm = this - > vm ( ) ;
2021-06-20 00:09:39 +00:00
2021-06-13 22:47:08 +00:00
auto buffer = vm . argument ( 0 ) ;
2023-01-27 21:36:31 +00:00
auto byte_offset = vm . argument ( 1 ) ;
auto byte_length = vm . argument ( 2 ) ;
// 2. Perform ? RequireInternalSlot(buffer, [[ArrayBufferData]]).
2021-10-20 20:16:30 +00:00
if ( ! buffer . is_object ( ) | | ! is < ArrayBuffer > ( buffer . as_object ( ) ) )
2023-08-09 06:49:02 +00:00
return vm . throw_completion < TypeError > ( ErrorType : : IsNotAn , buffer . to_string_without_side_effects ( ) , vm . names . ArrayBuffer ) ;
2021-10-20 20:16:30 +00:00
2021-06-13 22:47:08 +00:00
auto & array_buffer = static_cast < ArrayBuffer & > ( buffer . as_object ( ) ) ;
2023-01-27 21:36:31 +00:00
// 3. Let offset be ? ToIndex(byteOffset).
auto offset = TRY ( byte_offset . to_index ( vm ) ) ;
2021-06-13 22:47:08 +00:00
2023-01-27 21:36:31 +00:00
// 4. If IsDetachedBuffer(buffer) is true, throw a TypeError exception.
2021-10-20 20:16:30 +00:00
if ( array_buffer . is_detached ( ) )
2022-08-16 19:33:17 +00:00
return vm . throw_completion < TypeError > ( ErrorType : : DetachedArrayBuffer ) ;
2021-06-13 22:47:08 +00:00
2023-10-15 13:46:09 +00:00
// 5. Let bufferByteLength be ArrayBufferByteLength(buffer, seq-cst).
auto buffer_byte_length = array_buffer_byte_length ( array_buffer , ArrayBuffer : : Order : : SeqCst ) ;
2023-01-27 21:36:31 +00:00
// 6. If offset > bufferByteLength, throw a RangeError exception.
2021-10-20 20:16:30 +00:00
if ( offset > buffer_byte_length )
2022-08-16 19:33:17 +00:00
return vm . throw_completion < RangeError > ( ErrorType : : DataViewOutOfRangeByteOffset , offset , buffer_byte_length ) ;
2021-06-13 22:47:08 +00:00
2023-10-15 13:46:09 +00:00
// 7. Let bufferIsFixedLength be IsFixedLengthArrayBuffer(buffer).
auto buffer_is_fixed_length = array_buffer . is_fixed_length ( ) ;
2023-01-27 21:36:31 +00:00
2023-10-15 13:46:09 +00:00
ByteLength view_byte_length { 0 } ;
// 8. If byteLength is undefined, then
2023-01-27 21:36:31 +00:00
if ( byte_length . is_undefined ( ) ) {
2023-10-15 13:46:09 +00:00
// a. If bufferIsFixedLength is true, then
if ( buffer_is_fixed_length ) {
// i. Let viewByteLength be bufferByteLength - offset.
view_byte_length = buffer_byte_length - offset ;
}
// b. Else,
else {
// i. Let viewByteLength be auto.
view_byte_length = ByteLength : : auto_ ( ) ;
}
2023-01-27 21:36:31 +00:00
}
2023-10-15 13:46:09 +00:00
// 9. Else,
2023-01-27 21:36:31 +00:00
else {
// a. Let viewByteLength be ? ToIndex(byteLength).
view_byte_length = TRY ( byte_length . to_index ( vm ) ) ;
// b. If offset + viewByteLength > bufferByteLength, throw a RangeError exception.
2023-10-15 13:46:09 +00:00
auto checked_add = AK : : make_checked ( offset ) + AK : : make_checked ( static_cast < size_t > ( view_byte_length . length ( ) ) ) ;
2022-06-26 21:33:22 +00:00
if ( checked_add . has_overflow ( ) | | checked_add . value ( ) > buffer_byte_length )
2022-08-16 19:33:17 +00:00
return vm . throw_completion < RangeError > ( ErrorType : : InvalidLength , vm . names . DataView ) ;
2021-06-13 22:47:08 +00:00
}
2023-10-15 13:46:09 +00:00
// 10. Let O be ? OrdinaryCreateFromConstructor(NewTarget, "%DataView.prototype%", « [[DataView]], [[ViewedArrayBuffer]], [[ByteLength]], [[ByteOffset]] »).
auto data_view = TRY ( ordinary_create_from_constructor < DataView > ( vm , new_target , & Intrinsics : : data_view_prototype , & array_buffer , move ( view_byte_length ) , offset ) ) ;
2021-06-20 00:09:39 +00:00
2023-10-15 13:46:09 +00:00
// 11. If IsDetachedBuffer(buffer) is true, throw a TypeError exception.
2021-10-20 20:16:30 +00:00
if ( array_buffer . is_detached ( ) )
2022-08-16 19:33:17 +00:00
return vm . throw_completion < TypeError > ( ErrorType : : DetachedArrayBuffer ) ;
2021-06-13 22:47:08 +00:00
2023-10-15 13:46:09 +00:00
// 12. Set bufferByteLength to ArrayBufferByteLength(buffer, seq-cst).
buffer_byte_length = array_buffer_byte_length ( array_buffer , ArrayBuffer : : Order : : SeqCst ) ;
// 13. If offset > bufferByteLength, throw a RangeError exception.
if ( offset > buffer_byte_length )
return vm . throw_completion < RangeError > ( ErrorType : : DataViewOutOfRangeByteOffset , offset , buffer_byte_length ) ;
// 14. If byteLength is not undefined, then
if ( ! byte_length . is_undefined ( ) ) {
// a. If offset + viewByteLength > bufferByteLength, throw a RangeError exception.
auto checked_add = AK : : make_checked ( offset ) + AK : : make_checked ( static_cast < size_t > ( view_byte_length . length ( ) ) ) ;
if ( checked_add . has_overflow ( ) | | checked_add . value ( ) > buffer_byte_length )
return vm . throw_completion < RangeError > ( ErrorType : : InvalidLength , vm . names . DataView ) ;
}
// 15. Set O.[[ViewedArrayBuffer]] to buffer.
// 16. Set O.[[ByteLength]] to viewByteLength.
// 17. Set O.[[ByteOffset]] to offset.
// 18. Return O.
2022-12-14 19:18:10 +00:00
return data_view ;
2021-06-13 22:47:08 +00:00
}
}