diff --git a/Userland/Libraries/LibJS/Runtime/DataViewConstructor.cpp b/Userland/Libraries/LibJS/Runtime/DataViewConstructor.cpp index d606ec02a5..697f0aaed6 100644 --- a/Userland/Libraries/LibJS/Runtime/DataViewConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/DataViewConstructor.cpp @@ -34,6 +34,8 @@ void DataViewConstructor::initialize(Realm& realm) ThrowCompletionOr DataViewConstructor::call() { auto& vm = this->vm(); + + // 1. If NewTarget is undefined, throw a TypeError exception. return vm.throw_completion(ErrorType::ConstructorWithoutNew, vm.names.DataView); } @@ -43,35 +45,58 @@ ThrowCompletionOr> DataViewConstructor::construct(FunctionO auto& vm = this->vm(); auto buffer = vm.argument(0); + auto byte_offset = vm.argument(1); + auto byte_length = vm.argument(2); + + // 2. Perform ? RequireInternalSlot(buffer, [[ArrayBufferData]]). if (!buffer.is_object() || !is(buffer.as_object())) return vm.throw_completion(ErrorType::IsNotAn, buffer.to_string_without_side_effects(), vm.names.ArrayBuffer); auto& array_buffer = static_cast(buffer.as_object()); - auto offset = TRY(vm.argument(1).to_index(vm)); + // 3. Let offset be ? ToIndex(byteOffset). + auto offset = TRY(byte_offset.to_index(vm)); + // 4. If IsDetachedBuffer(buffer) is true, throw a TypeError exception. if (array_buffer.is_detached()) return vm.throw_completion(ErrorType::DetachedArrayBuffer); + // 5. Let bufferByteLength be buffer.[[ArrayBufferByteLength]]. auto buffer_byte_length = array_buffer.byte_length(); + + // 6. If offset > bufferByteLength, throw a RangeError exception. if (offset > buffer_byte_length) return vm.throw_completion(ErrorType::DataViewOutOfRangeByteOffset, offset, buffer_byte_length); size_t view_byte_length; - if (vm.argument(2).is_undefined()) { + + // 7. If byteLength is undefined, then + if (byte_length.is_undefined()) { + // a. Let viewByteLength be bufferByteLength - offset. view_byte_length = buffer_byte_length - offset; - } else { - view_byte_length = TRY(vm.argument(2).to_index(vm)); + } + // 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. 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) return vm.throw_completion(ErrorType::InvalidLength, vm.names.DataView); } + // 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. auto data_view = TRY(ordinary_create_from_constructor(vm, new_target, &Intrinsics::data_view_prototype, &array_buffer, view_byte_length, offset)); + // 10. If IsDetachedBuffer(buffer) is true, throw a TypeError exception. if (array_buffer.is_detached()) return vm.throw_completion(ErrorType::DetachedArrayBuffer); + // 14. Return O. return data_view; }