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 {
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
2022-12-14 19:18:10 +00:00
ThrowCompletionOr < NonnullGCPtr < 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-02-13 02:26:14 +00:00
return vm . throw_completion < TypeError > ( ErrorType : : IsNotAn , TRY_OR_THROW_OOM ( vm , 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-01-27 21:36:31 +00:00
// 5. Let bufferByteLength be buffer.[[ArrayBufferByteLength]].
2021-06-13 22:47:08 +00:00
auto buffer_byte_length = array_buffer . byte_length ( ) ;
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
size_t view_byte_length ;
2023-01-27 21:36:31 +00:00
// 7. If byteLength is undefined, then
if ( byte_length . is_undefined ( ) ) {
// a. Let viewByteLength be bufferByteLength - offset.
2021-06-13 22:47:08 +00:00
view_byte_length = buffer_byte_length - offset ;
2023-01-27 21:36:31 +00:00
}
// 8. Else,
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.
2022-06-26 21:33:22 +00:00
auto const checked_add = AK : : make_checked ( view_byte_length ) + AK : : make_checked ( offset ) ;
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-01-27 21:36:31 +00:00
// 9. Let O be ? OrdinaryCreateFromConstructor(NewTarget, "%DataView.prototype%", « [[DataView]], [[ViewedArrayBuffer]], [[ByteLength]], [[ByteOffset]] »).
// 11. Set O.[[ViewedArrayBuffer]] to buffer.
// 12. Set O.[[ByteLength]] to viewByteLength.
// 13. Set O.[[ByteOffset]] to offset.
2022-12-14 18:34:32 +00:00
auto data_view = TRY ( ordinary_create_from_constructor < DataView > ( vm , new_target , & Intrinsics : : data_view_prototype , & array_buffer , view_byte_length , offset ) ) ;
2021-06-20 00:09:39 +00:00
2023-01-27 21:36:31 +00:00
// 10. 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-01-27 21:36:31 +00:00
// 14. Return O.
2022-12-14 19:18:10 +00:00
return data_view ;
2021-06-13 22:47:08 +00:00
}
}