From e01ee4e30b71e490743d7d67477c294c7e7fab02 Mon Sep 17 00:00:00 2001 From: ForLoveOfCats Date: Sat, 19 Feb 2022 23:31:59 -0500 Subject: LibJS: Construct ArrayBuffer with max byte length when provided --- Userland/Libraries/LibJS/Runtime/ArrayBuffer.cpp | 26 ++++++++++++++++++------ Userland/Libraries/LibJS/Runtime/ArrayBuffer.h | 2 ++ 2 files changed, 22 insertions(+), 6 deletions(-) (limited to 'Userland/Libraries') diff --git a/Userland/Libraries/LibJS/Runtime/ArrayBuffer.cpp b/Userland/Libraries/LibJS/Runtime/ArrayBuffer.cpp index 57cb232bcf..ddf0a53da9 100644 --- a/Userland/Libraries/LibJS/Runtime/ArrayBuffer.cpp +++ b/Userland/Libraries/LibJS/Runtime/ArrayBuffer.cpp @@ -58,21 +58,35 @@ void ArrayBuffer::visit_edges(Cell::Visitor& visitor) // 1.1.2 AllocateArrayBuffer ( constructor, byteLength [, maxByteLength ] ), https://tc39.es/proposal-resizablearraybuffer/#sec-allocatearraybuffer ThrowCompletionOr allocate_array_buffer(GlobalObject& global_object, FunctionObject& constructor, size_t byte_length, Optional max_byte_length) { - (void)max_byte_length; - // 1. Let obj be ? OrdinaryCreateFromConstructor(constructor, "%ArrayBuffer.prototype%", « [[ArrayBufferData]], [[ArrayBufferByteLength]], [[ArrayBufferDetachKey]] »). + // 1. Let slots be « [[ArrayBufferData]], [[ArrayBufferByteLength]], [[ArrayBufferDetachKey]] ». + // 2. If maxByteLength is present, append [[ArrayBufferMaxByteLength]] to slots. + + // 3. Let obj be ? OrdinaryCreateFromConstructor(constructor, "%ArrayBuffer.prototype%", slots). auto* obj = TRY(ordinary_create_from_constructor(global_object, constructor, &GlobalObject::array_buffer_prototype, nullptr)); - // 2. Let block be ? CreateByteDataBlock(byteLength). + // 4. Let block be ? CreateByteDataBlock(byteLength). auto block = ByteBuffer::create_zeroed(byte_length); if (block.is_error()) return global_object.vm().throw_completion(global_object, ErrorType::NotEnoughMemoryToAllocate, byte_length); - // 3. Set obj.[[ArrayBufferData]] to block. + // 5. Set obj.[[ArrayBufferData]] to block. obj->set_buffer(block.release_value()); - // 4. Set obj.[[ArrayBufferByteLength]] to byteLength. + // 6. Set obj.[[ArrayBufferByteLength]] to byteLength. + + // 7. If maxByteLength is present, then + if (max_byte_length.has_value()) { + // a. Assert: byteLength ≤ maxByteLength. + VERIFY(byte_length <= *max_byte_length); + + // b. If it is not possible to create a Data Block block consisting of maxByteLength bytes, throw a RangeError exception. + // c. NOTE: Resizable ArrayBuffers are designed to be implementable with in-place growth. Implementations reserve the right to throw if, for example, virtual memory cannot be reserved up front. + + // d. Set obj.[[ArrayBufferMaxByteLength]] to maxByteLength. + obj->set_max_byte_length(*max_byte_length); + } - // 5. Return obj. + // 8. Return obj. return obj; } diff --git a/Userland/Libraries/LibJS/Runtime/ArrayBuffer.h b/Userland/Libraries/LibJS/Runtime/ArrayBuffer.h index 642eb900d3..3ef6c8df53 100644 --- a/Userland/Libraries/LibJS/Runtime/ArrayBuffer.h +++ b/Userland/Libraries/LibJS/Runtime/ArrayBuffer.h @@ -39,6 +39,7 @@ public: // Used by allocate_array_buffer() to attach the data block after construction void set_buffer(ByteBuffer buffer) { m_buffer = move(buffer); } + void set_max_byte_length(size_t max_byte_length) { m_max_byte_length = max_byte_length; } Value detach_key() const { return m_detach_key; } void set_detach_key(Value detach_key) { m_detach_key = detach_key; } @@ -73,6 +74,7 @@ private: // The various detach related members of ArrayBuffer are not used by any ECMA262 functionality, // but are required to be available for the use of various harnesses like the Test262 test runner. Value m_detach_key; + Optional m_max_byte_length; }; ThrowCompletionOr allocate_array_buffer(GlobalObject&, FunctionObject& constructor, size_t byte_length, Optional max_byte_length = {}); -- cgit v1.2.3