summaryrefslogtreecommitdiff
path: root/Userland
diff options
context:
space:
mode:
authorIdan Horowitz <idan.horowitz@gmail.com>2021-06-10 22:44:17 +0300
committerLinus Groh <mail@linusgroh.de>2021-06-10 22:44:26 +0100
commit8527f00065eac52673048d4958c4463d0c3a6e97 (patch)
treef967d0ac76c53537c8f0b2a4230a4a0fe2d6cfe7 /Userland
parent7d6db3f09bb995e8e253aca08fdcf5780722fa41 (diff)
downloadserenity-8527f00065eac52673048d4958c4463d0c3a6e97.zip
LibJS: Allow and check for detached ArrayBuffers
This is required by the specification and will be used for the $262.detachArrayBuffer method in test262.
Diffstat (limited to 'Userland')
-rw-r--r--Userland/Libraries/LibJS/Runtime/ArrayBuffer.cpp2
-rw-r--r--Userland/Libraries/LibJS/Runtime/ArrayBuffer.h11
-rw-r--r--Userland/Libraries/LibJS/Runtime/ArrayBufferPrototype.cpp18
-rw-r--r--Userland/Libraries/LibJS/Runtime/ErrorTypes.h1
-rw-r--r--Userland/Libraries/LibJS/Runtime/TypedArray.cpp15
-rw-r--r--Userland/Libraries/LibJS/Runtime/TypedArrayPrototype.cpp10
6 files changed, 46 insertions, 11 deletions
diff --git a/Userland/Libraries/LibJS/Runtime/ArrayBuffer.cpp b/Userland/Libraries/LibJS/Runtime/ArrayBuffer.cpp
index a34955dd9c..52356cc8c5 100644
--- a/Userland/Libraries/LibJS/Runtime/ArrayBuffer.cpp
+++ b/Userland/Libraries/LibJS/Runtime/ArrayBuffer.cpp
@@ -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())
{
}
diff --git a/Userland/Libraries/LibJS/Runtime/ArrayBuffer.h b/Userland/Libraries/LibJS/Runtime/ArrayBuffer.h
index db2e13b605..1fd2e6798f 100644
--- a/Userland/Libraries/LibJS/Runtime/ArrayBuffer.h
+++ b/Userland/Libraries/LibJS/Runtime/ArrayBuffer.h
@@ -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;
};
}
diff --git a/Userland/Libraries/LibJS/Runtime/ArrayBufferPrototype.cpp b/Userland/Libraries/LibJS/Runtime/ArrayBufferPrototype.cpp
index 6a9dfb80b2..5a039b65d4 100644
--- a/Userland/Libraries/LibJS/Runtime/ArrayBufferPrototype.cpp
+++ b/Userland/Libraries/LibJS/Runtime/ArrayBufferPrototype.cpp
@@ -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());
}
}
diff --git a/Userland/Libraries/LibJS/Runtime/ErrorTypes.h b/Userland/Libraries/LibJS/Runtime/ErrorTypes.h
index 014436c121..e73b7d5b3b 100644
--- a/Userland/Libraries/LibJS/Runtime/ErrorTypes.h
+++ b/Userland/Libraries/LibJS/Runtime/ErrorTypes.h
@@ -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") \
diff --git a/Userland/Libraries/LibJS/Runtime/TypedArray.cpp b/Userland/Libraries/LibJS/Runtime/TypedArray.cpp
index a9bfef012d..462ac7c1f3 100644
--- a/Userland/Libraries/LibJS/Runtime/TypedArray.cpp
+++ b/Userland/Libraries/LibJS/Runtime/TypedArray.cpp
@@ -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();
diff --git a/Userland/Libraries/LibJS/Runtime/TypedArrayPrototype.cpp b/Userland/Libraries/LibJS/Runtime/TypedArrayPrototype.cpp
index 03f2dfa5b8..63c4da2158 100644
--- a/Userland/Libraries/LibJS/Runtime/TypedArrayPrototype.cpp
+++ b/Userland/Libraries/LibJS/Runtime/TypedArrayPrototype.cpp
@@ -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());
}