summaryrefslogtreecommitdiff
path: root/Userland/Libraries/LibJS/Runtime/ArrayBufferConstructor.cpp
diff options
context:
space:
mode:
authorForLoveOfCats <floc@unpromptedtirade.com>2022-03-02 11:44:32 -0500
committerLinus Groh <mail@linusgroh.de>2022-03-02 20:53:18 +0100
commite8416b603fafa59caf87c5b73ceda54a33d2bb7b (patch)
treeb096b46c165bacd3274a19fd954f13295b07afa1 /Userland/Libraries/LibJS/Runtime/ArrayBufferConstructor.cpp
parent4eb2c70a03d5c1dd243ff82f74076a0d974a62f5 (diff)
downloadserenity-e8416b603fafa59caf87c5b73ceda54a33d2bb7b.zip
LibJS: Accept ArrayBuffer constructor options argument
Test262 seems to test the changes in the "Resizable ArrayBuffer and growable SharedArrayBuffer" proposal. Begin implementing this proposal by accepting the new options object argument to the ArrayBuffer constructor. https://tc39.es/proposal-resizablearraybuffer https://github.com/tc39/test262/blob/main/test/built-ins/ArrayBuffer/options-maxbytelength-diminuitive.js
Diffstat (limited to 'Userland/Libraries/LibJS/Runtime/ArrayBufferConstructor.cpp')
-rw-r--r--Userland/Libraries/LibJS/Runtime/ArrayBufferConstructor.cpp50
1 files changed, 47 insertions, 3 deletions
diff --git a/Userland/Libraries/LibJS/Runtime/ArrayBufferConstructor.cpp b/Userland/Libraries/LibJS/Runtime/ArrayBufferConstructor.cpp
index 43318a0328..db1a394e66 100644
--- a/Userland/Libraries/LibJS/Runtime/ArrayBufferConstructor.cpp
+++ b/Userland/Libraries/LibJS/Runtime/ArrayBufferConstructor.cpp
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2020, Linus Groh <linusg@serenityos.org>
+ * Copyright (c) 2022, the SerenityOS developers.
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@@ -46,20 +47,63 @@ ThrowCompletionOr<Value> ArrayBufferConstructor::call()
return vm.throw_completion<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, vm.names.ArrayBuffer);
}
+// 1.1.6 GetArrayBufferMaxByteLengthOption ( options ), https://tc39.es/proposal-resizablearraybuffer/#sec-getarraybuffermaxbytelengthoption
+static ThrowCompletionOr<Optional<size_t>> get_array_buffer_max_byte_length_option(VM& vm, GlobalObject& global_object, Value options)
+{
+ // 1. If Type(options) is not Object, return empty.
+ if (!options.is_object())
+ return Optional<size_t>();
+
+ // 2. Let maxByteLength be ? Get(options, "maxByteLength").
+ auto max_byte_length = TRY(options.get(global_object, vm.names.maxByteLength));
+
+ // 3. If maxByteLength is undefined, return empty.
+ if (max_byte_length.is_undefined())
+ return Optional<size_t>();
+
+ // 4. Return ? ToIndex(maxByteLength).
+ return TRY(max_byte_length.to_index(global_object));
+}
+
// 25.1.3.1 ArrayBuffer ( length ), https://tc39.es/ecma262/#sec-arraybuffer-length
+// 1.2.1 ArrayBuffer ( length [, options ] ), https://tc39.es/proposal-resizablearraybuffer/#sec-arraybuffer-constructor
ThrowCompletionOr<Object*> ArrayBufferConstructor::construct(FunctionObject& new_target)
{
+ auto& global_object = new_target.realm()->global_object();
auto& vm = this->vm();
- auto byte_length_or_error = vm.argument(0).to_index(global_object());
+
+ // 1. If NewTarget is undefined, throw a TypeError exception.
+ // NOTE: See `ArrayBufferConstructor::call()`
+
+ // 2. Let byteLength be ? ToIndex(length).
+ auto byte_length_or_error = vm.argument(0).to_index(global_object);
if (byte_length_or_error.is_error()) {
auto error = byte_length_or_error.release_error();
if (error.value()->is_object() && is<RangeError>(error.value()->as_object())) {
// Re-throw more specific RangeError
- return vm.throw_completion<RangeError>(global_object(), ErrorType::InvalidLength, "array buffer");
+ return vm.throw_completion<RangeError>(global_object, ErrorType::InvalidLength, "array buffer");
}
return error;
}
- return TRY(allocate_array_buffer(global_object(), new_target, byte_length_or_error.release_value()));
+ auto byte_length = byte_length_or_error.release_value();
+
+ // 3. Let requestedMaxByteLength be ? GetArrayBufferMaxByteLengthOption(options).
+ auto options = vm.argument(1);
+ auto requested_max_byte_length_value = TRY(get_array_buffer_max_byte_length_option(vm, global_object, options));
+
+ // 4. If requestedMaxByteLength is empty, then
+ if (!requested_max_byte_length_value.has_value()) {
+ // a. Return ? AllocateArrayBuffer(NewTarget, byteLength).
+ return TRY(allocate_array_buffer(global_object, new_target, byte_length));
+ }
+ auto requested_max_byte_length = requested_max_byte_length_value.release_value();
+
+ // 5. If byteLength > requestedMaxByteLength, throw a RangeError exception.
+ if (byte_length > requested_max_byte_length)
+ return vm.throw_completion<RangeError>(global_object, ErrorType::ByteLengthBeyondRequestedMax);
+
+ // 6. Return ? AllocateArrayBuffer(NewTarget, byteLength, requestedMaxByteLength).
+ return TRY(allocate_array_buffer(global_object, new_target, byte_length, requested_max_byte_length));
}
// 25.1.4.1 ArrayBuffer.isView ( arg ), https://tc39.es/ecma262/#sec-arraybuffer.isview