mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-29 02:50:26 +00:00
LibJS: Allow and check for detached ArrayBuffers
This is required by the specification and will be used for the $262.detachArrayBuffer method in test262.
This commit is contained in:
parent
7d6db3f09b
commit
8527f00065
Notes:
sideshowbarker
2024-07-18 12:28:14 +09:00
Author: https://github.com/IdanHo Commit: https://github.com/SerenityOS/serenity/commit/8527f00065e Pull-request: https://github.com/SerenityOS/serenity/pull/7974 Reviewed-by: https://github.com/linusg
6 changed files with 46 additions and 11 deletions
|
@ -22,12 +22,14 @@ ArrayBuffer* ArrayBuffer::create(GlobalObject& global_object, ByteBuffer* buffer
|
|||
ArrayBuffer::ArrayBuffer(size_t byte_size, Object& prototype)
|
||||
: Object(prototype)
|
||||
, m_buffer(ByteBuffer::create_zeroed(byte_size))
|
||||
, m_detach_key(js_undefined())
|
||||
{
|
||||
}
|
||||
|
||||
ArrayBuffer::ArrayBuffer(ByteBuffer* buffer, Object& prototype)
|
||||
: Object(prototype)
|
||||
, m_buffer(buffer)
|
||||
, m_detach_key(js_undefined())
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -27,17 +27,24 @@ public:
|
|||
ByteBuffer& buffer() { return buffer_impl(); }
|
||||
const ByteBuffer& buffer() const { return buffer_impl(); }
|
||||
|
||||
Value detach_key() const { return m_detach_key; }
|
||||
void detach_buffer() { m_buffer = Empty {}; }
|
||||
bool is_detached() const { return m_buffer.has<Empty>(); }
|
||||
|
||||
private:
|
||||
ByteBuffer& buffer_impl()
|
||||
{
|
||||
ByteBuffer* ptr { nullptr };
|
||||
m_buffer.visit([&](auto* pointer) { ptr = pointer; }, [&](auto& value) { ptr = &value; });
|
||||
m_buffer.visit([&](Empty) { VERIFY_NOT_REACHED(); }, [&](auto* pointer) { ptr = pointer; }, [&](auto& value) { ptr = &value; });
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
const ByteBuffer& buffer_impl() const { return const_cast<ArrayBuffer*>(this)->buffer_impl(); }
|
||||
|
||||
Variant<ByteBuffer, ByteBuffer*> m_buffer;
|
||||
Variant<Empty, ByteBuffer, ByteBuffer*> m_buffer;
|
||||
// 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;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2020, Linus Groh <linusg@serenityos.org>
|
||||
* Copyright (c) 2021, Idan Horowitz <idan.horowitz@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
@ -52,7 +53,10 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayBufferPrototype::slice)
|
|||
return {};
|
||||
|
||||
// FIXME: Check for shared buffer
|
||||
// FIXME: Check for detached buffer
|
||||
if (array_buffer_object->is_detached()) {
|
||||
vm.throw_exception<TypeError>(global_object, ErrorType::DetachedArrayBuffer);
|
||||
return {};
|
||||
}
|
||||
|
||||
auto length = array_buffer_object->byte_length();
|
||||
|
||||
|
@ -95,7 +99,10 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayBufferPrototype::slice)
|
|||
auto* new_array_buffer_object = static_cast<ArrayBuffer*>(&new_array_buffer.as_object());
|
||||
|
||||
// FIXME: Check for shared buffer
|
||||
// FIXME: Check for detached buffer
|
||||
if (new_array_buffer_object->is_detached()) {
|
||||
vm.throw_exception<TypeError>(global_object, ErrorType::SpeciesConstructorReturned, "a detached ArrayBuffer");
|
||||
return {};
|
||||
}
|
||||
if (same_value(new_array_buffer_object, array_buffer_object)) {
|
||||
vm.throw_exception<TypeError>(global_object, ErrorType::SpeciesConstructorReturned, "same ArrayBuffer instance");
|
||||
return {};
|
||||
|
@ -120,9 +127,12 @@ JS_DEFINE_NATIVE_GETTER(ArrayBufferPrototype::byte_length_getter)
|
|||
auto array_buffer_object = array_buffer_object_from(vm, global_object);
|
||||
if (!array_buffer_object)
|
||||
return {};
|
||||
|
||||
// FIXME: Check for shared buffer
|
||||
// FIXME: Check for detached buffer
|
||||
return Value((double)array_buffer_object->byte_length());
|
||||
if (array_buffer_object->is_detached())
|
||||
return Value(0);
|
||||
|
||||
return Value(array_buffer_object->byte_length());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
M(ConvertUndefinedToObject, "Cannot convert undefined to object") \
|
||||
M(DescChangeNonConfigurable, "Cannot change attributes of non-configurable property '{}'") \
|
||||
M(DescWriteNonWritable, "Cannot write to non-writable property '{}'") \
|
||||
M(DetachedArrayBuffer, "ArrayBuffer is detached") \
|
||||
M(DivisionByZero, "Division by zero") \
|
||||
M(GetCapabilitiesExecutorCalledMultipleTimes, "GetCapabilitiesExecutor was called multiple times") \
|
||||
M(InOperatorWithObject, "'in' operator must be used on an object") \
|
||||
|
|
|
@ -33,7 +33,12 @@ static void initialize_typed_array_from_array_buffer(GlobalObject& global_object
|
|||
if (vm.exception())
|
||||
return;
|
||||
}
|
||||
// FIXME: 8. If IsDetachedBuffer(buffer) is true, throw a TypeError exception.
|
||||
|
||||
if (array_buffer.is_detached()) {
|
||||
vm.throw_exception<TypeError>(global_object, ErrorType::DetachedArrayBuffer);
|
||||
return;
|
||||
}
|
||||
|
||||
auto buffer_byte_length = array_buffer.byte_length();
|
||||
Checked<size_t> new_byte_length;
|
||||
if (length.is_undefined()) {
|
||||
|
@ -81,8 +86,12 @@ static void initialize_typed_array_from_typed_array(GlobalObject& global_object,
|
|||
if (vm.exception())
|
||||
return;
|
||||
|
||||
// FIXME: 4. If IsDetachedBuffer(src_data) is true, throw a TypeError exception.
|
||||
VERIFY(src_array.viewed_array_buffer());
|
||||
auto* source_array_buffer = src_array.viewed_array_buffer();
|
||||
VERIFY(source_array_buffer);
|
||||
if (source_array_buffer->is_detached()) {
|
||||
vm.throw_exception<TypeError>(global_object, ErrorType::DetachedArrayBuffer);
|
||||
return;
|
||||
}
|
||||
|
||||
auto src_array_length = src_array.array_length();
|
||||
auto dest_element_size = dest_array.element_size();
|
||||
|
|
|
@ -50,6 +50,10 @@ JS_DEFINE_NATIVE_GETTER(TypedArrayPrototype::length_getter)
|
|||
auto typed_array = typed_array_from(vm, global_object);
|
||||
if (!typed_array)
|
||||
return {};
|
||||
auto* array_buffer = typed_array->viewed_array_buffer();
|
||||
VERIFY(array_buffer);
|
||||
if (array_buffer->is_detached())
|
||||
return Value(0);
|
||||
return Value(typed_array->array_length());
|
||||
}
|
||||
|
||||
|
@ -95,7 +99,8 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::byte_length_getter)
|
|||
return {};
|
||||
auto* array_buffer = typed_array->viewed_array_buffer();
|
||||
VERIFY(array_buffer);
|
||||
// FIXME: If array_buffer is detached, return 0.
|
||||
if (array_buffer->is_detached())
|
||||
return Value(0);
|
||||
return Value(typed_array->byte_length());
|
||||
}
|
||||
|
||||
|
@ -107,7 +112,8 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::byte_offset_getter)
|
|||
return {};
|
||||
auto* array_buffer = typed_array->viewed_array_buffer();
|
||||
VERIFY(array_buffer);
|
||||
// FIXME: If array_buffer is detached, return 0.
|
||||
if (array_buffer->is_detached())
|
||||
return Value(0);
|
||||
return Value(typed_array->byte_offset());
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue