Просмотр исходного кода

LibJS: Move DetachArrayBuffer implementation to the ArrayBuffer object

The spec notes that this AO is unused by ECMA-262, but is provided for
ECMAScript hosts. Move the definition to a common location to allow
test-js to also use it.
Timothy Flynn 3 лет назад
Родитель
Сommit
13d05403ff

+ 2 - 5
Userland/Libraries/LibJS/Contrib/Test262/$262Object.cpp

@@ -62,17 +62,14 @@ JS_DEFINE_NATIVE_FUNCTION($262Object::create_realm)
     return Value(realm->$262());
 }
 
-// 25.1.2.3 DetachArrayBuffer, https://tc39.es/ecma262/#sec-detacharraybuffer
 JS_DEFINE_NATIVE_FUNCTION($262Object::detach_array_buffer)
 {
     auto array_buffer = vm.argument(0);
     if (!array_buffer.is_object() || !is<ArrayBuffer>(array_buffer.as_object()))
         return vm.throw_completion<TypeError>(global_object);
+
     auto& array_buffer_object = static_cast<ArrayBuffer&>(array_buffer.as_object());
-    if (!same_value(array_buffer_object.detach_key(), vm.argument(1)))
-        return vm.throw_completion<TypeError>(global_object);
-    array_buffer_object.detach_buffer();
-    return js_null();
+    return JS::detach_array_buffer(global_object, array_buffer_object, vm.argument(1));
 }
 
 JS_DEFINE_NATIVE_FUNCTION($262Object::eval_script)

+ 24 - 0
Userland/Libraries/LibJS/Runtime/ArrayBuffer.cpp

@@ -96,6 +96,30 @@ ThrowCompletionOr<ArrayBuffer*> allocate_array_buffer(GlobalObject& global_objec
     return obj;
 }
 
+// 25.1.2.3 DetachArrayBuffer ( arrayBuffer [ , key ] ), https://tc39.es/ecma262/#sec-detacharraybuffer
+ThrowCompletionOr<Value> detach_array_buffer(GlobalObject& global_object, ArrayBuffer& array_buffer, Optional<Value> key)
+{
+    auto& vm = global_object.vm();
+
+    // 1. Assert: IsSharedArrayBuffer(arrayBuffer) is false.
+    // FIXME: Check for shared buffer
+
+    // 2. If key is not present, set key to undefined.
+    if (!key.has_value())
+        key = js_undefined();
+
+    // 3. If SameValue(arrayBuffer.[[ArrayBufferDetachKey]], key) is false, throw a TypeError exception.
+    if (!same_value(array_buffer.detach_key(), *key))
+        return vm.throw_completion<TypeError>(global_object, ErrorType::DetachKeyMismatch, *key, array_buffer.detach_key());
+
+    // 4. Set arrayBuffer.[[ArrayBufferData]] to null.
+    // 5. Set arrayBuffer.[[ArrayBufferByteLength]] to 0.
+    array_buffer.detach_buffer();
+
+    // 6. Return unused.
+    return js_null();
+}
+
 // 25.1.2.4 CloneArrayBuffer ( srcBuffer, srcByteOffset, srcLength, cloneConstructor ), https://tc39.es/ecma262/#sec-clonearraybuffer
 ThrowCompletionOr<ArrayBuffer*> clone_array_buffer(GlobalObject& global_object, ArrayBuffer& source_buffer, size_t source_byte_offset, size_t source_length, FunctionObject& clone_constructor)
 {

+ 1 - 0
Userland/Libraries/LibJS/Runtime/ArrayBuffer.h

@@ -81,6 +81,7 @@ private:
 };
 
 ThrowCompletionOr<ArrayBuffer*> allocate_array_buffer(GlobalObject&, FunctionObject& constructor, size_t byte_length, Optional<size_t> max_byte_length = {});
+ThrowCompletionOr<Value> detach_array_buffer(GlobalObject&, ArrayBuffer& array_buffer, Optional<Value> key = {});
 ThrowCompletionOr<ArrayBuffer*> clone_array_buffer(GlobalObject&, ArrayBuffer& source_buffer, size_t source_byte_offset, size_t source_length, FunctionObject& clone_constructor);
 
 // 25.1.2.9 RawBytesToNumeric ( type, rawBytes, isLittleEndian ), https://tc39.es/ecma262/#sec-rawbytestonumeric

+ 1 - 0
Userland/Libraries/LibJS/Runtime/ErrorTypes.h

@@ -29,6 +29,7 @@
     M(DerivedConstructorReturningInvalidValue, "Derived constructor return invalid value")                                              \
     M(DescWriteNonWritable, "Cannot write to non-writable property '{}'")                                                               \
     M(DetachedArrayBuffer, "ArrayBuffer is detached")                                                                                   \
+    M(DetachKeyMismatch, "Provided detach key {} does not match the ArrayBuffer's detach key {}")                                       \
     M(DivisionByZero, "Division by zero")                                                                                               \
     M(DynamicImportNotAllowed, "Dynamic Imports are not allowed")                                                                       \
     M(FinalizationRegistrySameTargetAndValue, "Target and held value must not be the same")                                             \