LibJS: Update spec steps/links for the ArrayBuffer transfer proposal

The proposal reached stage 4 and was merged into the ECMA-262 spec. See:
44bb0e0
This commit is contained in:
Timothy Flynn 2024-08-20 10:29:45 -04:00 committed by Tim Flynn
commit bf3e7d3ac4
Notes: github-actions[bot] 2024-08-20 16:25:48 +00:00
6 changed files with 108 additions and 109 deletions

View file

@ -181,71 +181,7 @@ ThrowCompletionOr<ArrayBuffer*> allocate_array_buffer(VM& vm, FunctionObject& co
return obj.ptr(); return obj.ptr();
} }
// 25.1.3.4 DetachArrayBuffer ( arrayBuffer [ , key ] ), https://tc39.es/ecma262/#sec-detacharraybuffer // 25.1.3.3 ArrayBufferCopyAndDetach ( arrayBuffer, newLength, preserveResizability ), https://tc39.es/ecma262/#sec-arraybuffercopyanddetach
ThrowCompletionOr<void> detach_array_buffer(VM& vm, ArrayBuffer& array_buffer, Optional<Value> key)
{
// 1. Assert: IsSharedArrayBuffer(arrayBuffer) is false.
VERIFY(!array_buffer.is_shared_array_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>(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 {};
}
// 25.1.3.5 CloneArrayBuffer ( srcBuffer, srcByteOffset, srcLength, cloneConstructor ), https://tc39.es/ecma262/#sec-clonearraybuffer
ThrowCompletionOr<ArrayBuffer*> clone_array_buffer(VM& vm, ArrayBuffer& source_buffer, size_t source_byte_offset, size_t source_length)
{
auto& realm = *vm.current_realm();
// 1. Assert: IsDetachedBuffer(srcBuffer) is false.
VERIFY(!source_buffer.is_detached());
// 2. Let targetBuffer be ? AllocateArrayBuffer(%ArrayBuffer%, srcLength).
auto* target_buffer = TRY(allocate_array_buffer(vm, realm.intrinsics().array_buffer_constructor(), source_length));
// 3. Let srcBlock be srcBuffer.[[ArrayBufferData]].
auto& source_block = source_buffer.buffer();
// 4. Let targetBlock be targetBuffer.[[ArrayBufferData]].
auto& target_block = target_buffer->buffer();
// 5. Perform CopyDataBlockBytes(targetBlock, 0, srcBlock, srcByteOffset, srcLength).
copy_data_block_bytes(target_block, 0, source_block, source_byte_offset, source_length);
// 6. Return targetBuffer.
return target_buffer;
}
// 25.1.3.6 GetArrayBufferMaxByteLengthOption ( options ), https://tc39.es/ecma262/#sec-getarraybuffermaxbytelengthoption
ThrowCompletionOr<Optional<size_t>> get_array_buffer_max_byte_length_option(VM& vm, Value options)
{
// 1. If options is not an Object, return empty.
if (!options.is_object())
return OptionalNone {};
// 2. Let maxByteLength be ? Get(options, "maxByteLength").
auto max_byte_length = TRY(options.as_object().get(vm.names.maxByteLength));
// 3. If maxByteLength is undefined, return empty.
if (max_byte_length.is_undefined())
return OptionalNone {};
// 4. Return ? ToIndex(maxByteLength).
return TRY(max_byte_length.to_index(vm));
}
// 25.1.2.14 ArrayBufferCopyAndDetach ( arrayBuffer, newLength, preserveResizability ), https://tc39.es/proposal-arraybuffer-transfer/#sec-arraybuffer.prototype.transfertofixedlength
ThrowCompletionOr<ArrayBuffer*> array_buffer_copy_and_detach(VM& vm, ArrayBuffer& array_buffer, Value new_length, PreserveResizability preserve_resizability) ThrowCompletionOr<ArrayBuffer*> array_buffer_copy_and_detach(VM& vm, ArrayBuffer& array_buffer, Value new_length, PreserveResizability preserve_resizability)
{ {
auto& realm = *vm.current_realm(); auto& realm = *vm.current_realm();
@ -257,9 +193,9 @@ ThrowCompletionOr<ArrayBuffer*> array_buffer_copy_and_detach(VM& vm, ArrayBuffer
return vm.throw_completion<TypeError>(ErrorType::SharedArrayBuffer); return vm.throw_completion<TypeError>(ErrorType::SharedArrayBuffer);
// 3. If newLength is undefined, then // 3. If newLength is undefined, then
// a. Let newByteLength be arrayBuffer.[[ArrayBufferByteLength]]. // a. Let newByteLength be arrayBuffer.[[ArrayBufferByteLength]].
// 4. Else, // 4. Else,
// a. Let newByteLength be ? ToIndex(newLength). // a. Let newByteLength be ? ToIndex(newLength).
auto new_byte_length = new_length.is_undefined() ? array_buffer.byte_length() : TRY(new_length.to_index(vm)); auto new_byte_length = new_length.is_undefined() ? array_buffer.byte_length() : TRY(new_length.to_index(vm));
// 5. If IsDetachedBuffer(arrayBuffer) is true, throw a TypeError exception. // 5. If IsDetachedBuffer(arrayBuffer) is true, throw a TypeError exception.
@ -268,15 +204,14 @@ ThrowCompletionOr<ArrayBuffer*> array_buffer_copy_and_detach(VM& vm, ArrayBuffer
Optional<size_t> new_max_byte_length; Optional<size_t> new_max_byte_length;
// 6. If preserveResizability is preserve-resizability and IsResizableArrayBuffer(arrayBuffer) is true, then // 6. If preserveResizability is PRESERVE-RESIZABILITY and IsFixedLengthArrayBuffer(arrayBuffer) is false, then
// FIXME: The ArrayBuffer transfer spec is a bit out-of-date. IsResizableArrayBuffer no longer exists, we now have IsFixedLengthArrayBuffer.
if (preserve_resizability == PreserveResizability::PreserveResizability && !array_buffer.is_fixed_length()) { if (preserve_resizability == PreserveResizability::PreserveResizability && !array_buffer.is_fixed_length()) {
// a. Let newMaxByteLength be arrayBuffer.[[ArrayBufferMaxByteLength]]. // a. Let newMaxByteLength be arrayBuffer.[[ArrayBufferMaxByteLength]].
new_max_byte_length = array_buffer.max_byte_length(); new_max_byte_length = array_buffer.max_byte_length();
} }
// 7. Else, // 7. Else,
else { else {
// a. Let newMaxByteLength be empty. // a. Let newMaxByteLength be EMPTY.
} }
// 8. If arrayBuffer.[[ArrayBufferDetachKey]] is not undefined, throw a TypeError exception. // 8. If arrayBuffer.[[ArrayBufferDetachKey]] is not undefined, throw a TypeError exception.
@ -302,6 +237,70 @@ ThrowCompletionOr<ArrayBuffer*> array_buffer_copy_and_detach(VM& vm, ArrayBuffer
return new_buffer; return new_buffer;
} }
// 25.1.3.5 DetachArrayBuffer ( arrayBuffer [ , key ] ), https://tc39.es/ecma262/#sec-detacharraybuffer
ThrowCompletionOr<void> detach_array_buffer(VM& vm, ArrayBuffer& array_buffer, Optional<Value> key)
{
// 1. Assert: IsSharedArrayBuffer(arrayBuffer) is false.
VERIFY(!array_buffer.is_shared_array_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>(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 {};
}
// 25.1.3.6 CloneArrayBuffer ( srcBuffer, srcByteOffset, srcLength, cloneConstructor ), https://tc39.es/ecma262/#sec-clonearraybuffer
ThrowCompletionOr<ArrayBuffer*> clone_array_buffer(VM& vm, ArrayBuffer& source_buffer, size_t source_byte_offset, size_t source_length)
{
auto& realm = *vm.current_realm();
// 1. Assert: IsDetachedBuffer(srcBuffer) is false.
VERIFY(!source_buffer.is_detached());
// 2. Let targetBuffer be ? AllocateArrayBuffer(%ArrayBuffer%, srcLength).
auto* target_buffer = TRY(allocate_array_buffer(vm, realm.intrinsics().array_buffer_constructor(), source_length));
// 3. Let srcBlock be srcBuffer.[[ArrayBufferData]].
auto& source_block = source_buffer.buffer();
// 4. Let targetBlock be targetBuffer.[[ArrayBufferData]].
auto& target_block = target_buffer->buffer();
// 5. Perform CopyDataBlockBytes(targetBlock, 0, srcBlock, srcByteOffset, srcLength).
copy_data_block_bytes(target_block, 0, source_block, source_byte_offset, source_length);
// 6. Return targetBuffer.
return target_buffer;
}
// 25.1.3.7 GetArrayBufferMaxByteLengthOption ( options ), https://tc39.es/ecma262/#sec-getarraybuffermaxbytelengthoption
ThrowCompletionOr<Optional<size_t>> get_array_buffer_max_byte_length_option(VM& vm, Value options)
{
// 1. If options is not an Object, return empty.
if (!options.is_object())
return OptionalNone {};
// 2. Let maxByteLength be ? Get(options, "maxByteLength").
auto max_byte_length = TRY(options.as_object().get(vm.names.maxByteLength));
// 3. If maxByteLength is undefined, return empty.
if (max_byte_length.is_undefined())
return OptionalNone {};
// 4. Return ? ToIndex(maxByteLength).
return TRY(max_byte_length.to_index(vm));
}
// 25.2.2.1 AllocateSharedArrayBuffer ( constructor, byteLength [ , maxByteLength ] ), https://tc39.es/ecma262/#sec-allocatesharedarraybuffer // 25.2.2.1 AllocateSharedArrayBuffer ( constructor, byteLength [ , maxByteLength ] ), https://tc39.es/ecma262/#sec-allocatesharedarraybuffer
ThrowCompletionOr<NonnullGCPtr<ArrayBuffer>> allocate_shared_array_buffer(VM& vm, FunctionObject& constructor, size_t byte_length) ThrowCompletionOr<NonnullGCPtr<ArrayBuffer>> allocate_shared_array_buffer(VM& vm, FunctionObject& constructor, size_t byte_length)
{ {

View file

@ -83,7 +83,7 @@ public:
void detach_buffer() { m_data_block.byte_buffer = Empty {}; } void detach_buffer() { m_data_block.byte_buffer = Empty {}; }
// 25.1.3.3 IsDetachedBuffer ( arrayBuffer ), https://tc39.es/ecma262/#sec-isdetachedbuffer // 25.1.3.4 IsDetachedBuffer ( arrayBuffer ), https://tc39.es/ecma262/#sec-isdetachedbuffer
bool is_detached() const bool is_detached() const
{ {
// 1. If arrayBuffer.[[ArrayBufferData]] is null, return true. // 1. If arrayBuffer.[[ArrayBufferData]] is null, return true.
@ -93,7 +93,7 @@ public:
return false; return false;
} }
// 25.1.3.8 IsFixedLengthArrayBuffer ( arrayBuffer ), https://tc39.es/ecma262/#sec-isfixedlengtharraybuffer // 25.1.3.9 IsFixedLengthArrayBuffer ( arrayBuffer ), https://tc39.es/ecma262/#sec-isfixedlengtharraybuffer
bool is_fixed_length() const bool is_fixed_length() const
{ {
// 1. If arrayBuffer has an [[ArrayBufferMaxByteLength]] internal slot, return false. // 1. If arrayBuffer has an [[ArrayBufferMaxByteLength]] internal slot, return false.
@ -148,10 +148,10 @@ private:
ThrowCompletionOr<DataBlock> create_byte_data_block(VM& vm, size_t size); ThrowCompletionOr<DataBlock> create_byte_data_block(VM& vm, size_t size);
void copy_data_block_bytes(ByteBuffer& to_block, u64 to_index, ByteBuffer const& from_block, u64 from_index, u64 count); void copy_data_block_bytes(ByteBuffer& to_block, u64 to_index, ByteBuffer const& from_block, u64 from_index, u64 count);
ThrowCompletionOr<ArrayBuffer*> allocate_array_buffer(VM&, FunctionObject& constructor, size_t byte_length, Optional<size_t> const& max_byte_length = {}); ThrowCompletionOr<ArrayBuffer*> allocate_array_buffer(VM&, FunctionObject& constructor, size_t byte_length, Optional<size_t> const& max_byte_length = {});
ThrowCompletionOr<ArrayBuffer*> array_buffer_copy_and_detach(VM&, ArrayBuffer& array_buffer, Value new_length, PreserveResizability preserve_resizability);
ThrowCompletionOr<void> detach_array_buffer(VM&, ArrayBuffer& array_buffer, Optional<Value> key = {}); ThrowCompletionOr<void> detach_array_buffer(VM&, ArrayBuffer& array_buffer, Optional<Value> key = {});
ThrowCompletionOr<Optional<size_t>> get_array_buffer_max_byte_length_option(VM&, Value options); ThrowCompletionOr<Optional<size_t>> get_array_buffer_max_byte_length_option(VM&, Value options);
ThrowCompletionOr<ArrayBuffer*> clone_array_buffer(VM&, ArrayBuffer& source_buffer, size_t source_byte_offset, size_t source_length); ThrowCompletionOr<ArrayBuffer*> clone_array_buffer(VM&, ArrayBuffer& source_buffer, size_t source_byte_offset, size_t source_length);
ThrowCompletionOr<ArrayBuffer*> array_buffer_copy_and_detach(VM&, ArrayBuffer& array_buffer, Value new_length, PreserveResizability preserve_resizability);
ThrowCompletionOr<NonnullGCPtr<ArrayBuffer>> allocate_shared_array_buffer(VM&, FunctionObject& constructor, size_t byte_length); ThrowCompletionOr<NonnullGCPtr<ArrayBuffer>> allocate_shared_array_buffer(VM&, FunctionObject& constructor, size_t byte_length);
// 25.1.3.2 ArrayBufferByteLength ( arrayBuffer, order ), https://tc39.es/ecma262/#sec-arraybufferbytelength // 25.1.3.2 ArrayBufferByteLength ( arrayBuffer, order ), https://tc39.es/ecma262/#sec-arraybufferbytelength
@ -170,7 +170,7 @@ inline size_t array_buffer_byte_length(ArrayBuffer const& array_buffer, ArrayBuf
return array_buffer.byte_length(); return array_buffer.byte_length();
} }
// 25.1.3.13 RawBytesToNumeric ( type, rawBytes, isLittleEndian ), https://tc39.es/ecma262/#sec-rawbytestonumeric // 25.1.3.14 RawBytesToNumeric ( type, rawBytes, isLittleEndian ), https://tc39.es/ecma262/#sec-rawbytestonumeric
template<typename T> template<typename T>
static Value raw_bytes_to_numeric(VM& vm, Bytes raw_value, bool is_little_endian) static Value raw_bytes_to_numeric(VM& vm, Bytes raw_value, bool is_little_endian)
{ {
@ -242,7 +242,7 @@ static Value raw_bytes_to_numeric(VM& vm, Bytes raw_value, bool is_little_endian
} }
} }
// 25.1.3.15 GetValueFromBuffer ( arrayBuffer, byteIndex, type, isTypedArray, order [ , isLittleEndian ] ), https://tc39.es/ecma262/#sec-getvaluefrombuffer // 25.1.3.16 GetValueFromBuffer ( arrayBuffer, byteIndex, type, isTypedArray, order [ , isLittleEndian ] ), https://tc39.es/ecma262/#sec-getvaluefrombuffer
template<typename T> template<typename T>
Value ArrayBuffer::get_value(size_t byte_index, [[maybe_unused]] bool is_typed_array, Order, bool is_little_endian) Value ArrayBuffer::get_value(size_t byte_index, [[maybe_unused]] bool is_typed_array, Order, bool is_little_endian)
{ {
@ -288,7 +288,7 @@ Value ArrayBuffer::get_value(size_t byte_index, [[maybe_unused]] bool is_typed_a
return raw_bytes_to_numeric<T>(vm, raw_value, is_little_endian); return raw_bytes_to_numeric<T>(vm, raw_value, is_little_endian);
} }
// 25.1.3.16 NumericToRawBytes ( type, value, isLittleEndian ), https://tc39.es/ecma262/#sec-numerictorawbytes // 25.1.3.17 NumericToRawBytes ( type, value, isLittleEndian ), https://tc39.es/ecma262/#sec-numerictorawbytes
template<typename T> template<typename T>
static void numeric_to_raw_bytes(VM& vm, Value value, bool is_little_endian, Bytes raw_bytes) static void numeric_to_raw_bytes(VM& vm, Value value, bool is_little_endian, Bytes raw_bytes)
{ {
@ -353,7 +353,7 @@ static void numeric_to_raw_bytes(VM& vm, Value value, bool is_little_endian, Byt
} }
} }
// 25.1.3.17 SetValueInBuffer ( arrayBuffer, byteIndex, type, value, isTypedArray, order [ , isLittleEndian ] ), https://tc39.es/ecma262/#sec-setvalueinbuffer // 25.1.3.18 SetValueInBuffer ( arrayBuffer, byteIndex, type, value, isTypedArray, order [ , isLittleEndian ] ), https://tc39.es/ecma262/#sec-setvalueinbuffer
template<typename T> template<typename T>
void ArrayBuffer::set_value(size_t byte_index, Value value, [[maybe_unused]] bool is_typed_array, Order, bool is_little_endian) void ArrayBuffer::set_value(size_t byte_index, Value value, [[maybe_unused]] bool is_typed_array, Order, bool is_little_endian)
{ {
@ -399,7 +399,7 @@ void ArrayBuffer::set_value(size_t byte_index, Value value, [[maybe_unused]] boo
// 10. Return unused. // 10. Return unused.
} }
// 25.1.3.18 GetModifySetValueInBuffer ( arrayBuffer, byteIndex, type, value, op [ , isLittleEndian ] ), https://tc39.es/ecma262/#sec-getmodifysetvalueinbuffer // 25.1.3.19 GetModifySetValueInBuffer ( arrayBuffer, byteIndex, type, value, op [ , isLittleEndian ] ), https://tc39.es/ecma262/#sec-getmodifysetvalueinbuffer
template<typename T> template<typename T>
Value ArrayBuffer::get_modify_set_value(size_t byte_index, Value value, ReadWriteModifyFunction operation, bool is_little_endian) Value ArrayBuffer::get_modify_set_value(size_t byte_index, Value value, ReadWriteModifyFunction operation, bool is_little_endian)
{ {

View file

@ -27,11 +27,11 @@ void ArrayBufferPrototype::initialize(Realm& realm)
Base::initialize(realm); Base::initialize(realm);
u8 attr = Attribute::Writable | Attribute::Configurable; u8 attr = Attribute::Writable | Attribute::Configurable;
define_native_accessor(realm, vm.names.byteLength, byte_length_getter, {}, Attribute::Configurable); define_native_accessor(realm, vm.names.byteLength, byte_length_getter, {}, Attribute::Configurable);
define_native_accessor(realm, vm.names.detached, detached_getter, {}, Attribute::Configurable);
define_native_accessor(realm, vm.names.maxByteLength, max_byte_length, {}, Attribute::Configurable); define_native_accessor(realm, vm.names.maxByteLength, max_byte_length, {}, Attribute::Configurable);
define_native_accessor(realm, vm.names.resizable, resizable, {}, Attribute::Configurable); define_native_accessor(realm, vm.names.resizable, resizable, {}, Attribute::Configurable);
define_native_function(realm, vm.names.resize, resize, 1, attr); define_native_function(realm, vm.names.resize, resize, 1, attr);
define_native_function(realm, vm.names.slice, slice, 2, attr); define_native_function(realm, vm.names.slice, slice, 2, attr);
define_native_accessor(realm, vm.names.detached, detached_getter, {}, Attribute::Configurable);
define_native_function(realm, vm.names.transfer, transfer, 0, attr); define_native_function(realm, vm.names.transfer, transfer, 0, attr);
define_native_function(realm, vm.names.transferToFixedLength, transfer_to_fixed_length, 0, attr); define_native_function(realm, vm.names.transferToFixedLength, transfer_to_fixed_length, 0, attr);
@ -57,7 +57,22 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayBufferPrototype::byte_length_getter)
return Value(array_buffer_object->byte_length()); return Value(array_buffer_object->byte_length());
} }
// 25.1.6.3 get ArrayBuffer.prototype.maxByteLength, https://tc39.es/ecma262/#sec-get-arraybuffer.prototype.maxbytelength // 25.1.6.3 get ArrayBuffer.prototype.detached, https://tc39.es/ecma262/#sec-get-arraybuffer.prototype.detached
JS_DEFINE_NATIVE_FUNCTION(ArrayBufferPrototype::detached_getter)
{
// 1. Let O be the this value.
// 2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]).
auto array_buffer_object = TRY(typed_this_value(vm));
// 3. If IsSharedArrayBuffer(O) is true, throw a TypeError exception.
if (array_buffer_object->is_shared_array_buffer())
return vm.throw_completion<TypeError>(ErrorType::SharedArrayBuffer);
// 4. Return IsDetachedBuffer(O).
return Value(array_buffer_object->is_detached());
}
// 25.1.6.4 get ArrayBuffer.prototype.maxByteLength, https://tc39.es/ecma262/#sec-get-arraybuffer.prototype.maxbytelength
JS_DEFINE_NATIVE_FUNCTION(ArrayBufferPrototype::max_byte_length) JS_DEFINE_NATIVE_FUNCTION(ArrayBufferPrototype::max_byte_length)
{ {
// 1. Let O be the this value. // 1. Let O be the this value.
@ -89,7 +104,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayBufferPrototype::max_byte_length)
return Value { length }; return Value { length };
} }
// 25.1.6.4 get ArrayBuffer.prototype.resizable, https://tc39.es/ecma262/#sec-get-arraybuffer.prototype.resizable // 25.1.6.5 get ArrayBuffer.prototype.resizable, https://tc39.es/ecma262/#sec-get-arraybuffer.prototype.resizable
JS_DEFINE_NATIVE_FUNCTION(ArrayBufferPrototype::resizable) JS_DEFINE_NATIVE_FUNCTION(ArrayBufferPrototype::resizable)
{ {
// 1. Let O be the this value. // 1. Let O be the this value.
@ -104,7 +119,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayBufferPrototype::resizable)
return Value { !array_buffer_object->is_fixed_length() }; return Value { !array_buffer_object->is_fixed_length() };
} }
// 25.1.6.5 ArrayBuffer.prototype.resize ( newLength ), https://tc39.es/ecma262/#sec-arraybuffer.prototype.resize // 25.1.6.6 ArrayBuffer.prototype.resize ( newLength ), https://tc39.es/ecma262/#sec-arraybuffer.prototype.resize
JS_DEFINE_NATIVE_FUNCTION(ArrayBufferPrototype::resize) JS_DEFINE_NATIVE_FUNCTION(ArrayBufferPrototype::resize)
{ {
auto new_length = vm.argument(0); auto new_length = vm.argument(0);
@ -161,7 +176,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayBufferPrototype::resize)
return js_undefined(); return js_undefined();
} }
// 25.1.6.6 ArrayBuffer.prototype.slice ( start, end ), https://tc39.es/ecma262/#sec-arraybuffer.prototype.slice // 25.1.6.7 ArrayBuffer.prototype.slice ( start, end ), https://tc39.es/ecma262/#sec-arraybuffer.prototype.slice
JS_DEFINE_NATIVE_FUNCTION(ArrayBufferPrototype::slice) JS_DEFINE_NATIVE_FUNCTION(ArrayBufferPrototype::slice)
{ {
auto& realm = *vm.current_realm(); auto& realm = *vm.current_realm();
@ -270,39 +285,24 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayBufferPrototype::slice)
return new_array_buffer_object; return new_array_buffer_object;
} }
// 25.1.5.4 get ArrayBuffer.prototype.detached, https://tc39.es/proposal-arraybuffer-transfer/#sec-get-arraybuffer.prototype.detached // 25.1.6.8 ArrayBuffer.prototype.transfer ( [ newLength ] ), https://tc39.es/ecma262/#sec-arraybuffer.prototype.transfer
JS_DEFINE_NATIVE_FUNCTION(ArrayBufferPrototype::detached_getter)
{
// 1. Let O be the this value.
// 2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]).
auto array_buffer_object = TRY(typed_this_value(vm));
// 3. If IsSharedArrayBuffer(O) is true, throw a TypeError exception.
if (array_buffer_object->is_shared_array_buffer())
return vm.throw_completion<TypeError>(ErrorType::SharedArrayBuffer);
// 4. Return IsDetachedBuffer(O).
return Value(array_buffer_object->is_detached());
}
// 25.1.5.5 ArrayBuffer.prototype.transfer ( [ newLength ] ), https://tc39.es/proposal-arraybuffer-transfer/#sec-arraybuffer.prototype.transfer
JS_DEFINE_NATIVE_FUNCTION(ArrayBufferPrototype::transfer) JS_DEFINE_NATIVE_FUNCTION(ArrayBufferPrototype::transfer)
{ {
// 1. Let O be the this value. // 1. Let O be the this value.
auto array_buffer_object = TRY(typed_this_value(vm)); auto array_buffer_object = TRY(typed_this_value(vm));
// 2. Return ? ArrayBufferCopyAndDetach(O, newLength, preserve-resizability). // 2. Return ? ArrayBufferCopyAndDetach(O, newLength, PRESERVE-RESIZABILITY).
auto new_length = vm.argument(0); auto new_length = vm.argument(0);
return TRY(array_buffer_copy_and_detach(vm, array_buffer_object, new_length, PreserveResizability::PreserveResizability)); return TRY(array_buffer_copy_and_detach(vm, array_buffer_object, new_length, PreserveResizability::PreserveResizability));
} }
// 25.1.5.6 ArrayBuffer.prototype.transferToFixedLength ( [ newLength ] ), https://tc39.es/proposal-arraybuffer-transfer/#sec-arraybuffer.prototype.transfertofixedlength // 25.1.6.9 ArrayBuffer.prototype.transferToFixedLength ( [ newLength ] ), https://tc39.es/ecma262/#sec-arraybuffer.prototype.transfertofixedlength
JS_DEFINE_NATIVE_FUNCTION(ArrayBufferPrototype::transfer_to_fixed_length) JS_DEFINE_NATIVE_FUNCTION(ArrayBufferPrototype::transfer_to_fixed_length)
{ {
// 1. Let O be the this value. // 1. Let O be the this value.
auto array_buffer_object = TRY(typed_this_value(vm)); auto array_buffer_object = TRY(typed_this_value(vm));
// 2. Return ? ArrayBufferCopyAndDetach(O, newLength, fixed-length). // 2. Return ? ArrayBufferCopyAndDetach(O, newLength, FIXED-LENGTH).
auto new_length = vm.argument(0); auto new_length = vm.argument(0);
return TRY(array_buffer_copy_and_detach(vm, array_buffer_object, new_length, PreserveResizability::FixedLength)); return TRY(array_buffer_copy_and_detach(vm, array_buffer_object, new_length, PreserveResizability::FixedLength));
} }

View file

@ -23,11 +23,11 @@ private:
explicit ArrayBufferPrototype(Realm&); explicit ArrayBufferPrototype(Realm&);
JS_DECLARE_NATIVE_FUNCTION(byte_length_getter); JS_DECLARE_NATIVE_FUNCTION(byte_length_getter);
JS_DECLARE_NATIVE_FUNCTION(detached_getter);
JS_DECLARE_NATIVE_FUNCTION(max_byte_length); JS_DECLARE_NATIVE_FUNCTION(max_byte_length);
JS_DECLARE_NATIVE_FUNCTION(resizable); JS_DECLARE_NATIVE_FUNCTION(resizable);
JS_DECLARE_NATIVE_FUNCTION(resize); JS_DECLARE_NATIVE_FUNCTION(resize);
JS_DECLARE_NATIVE_FUNCTION(slice); JS_DECLARE_NATIVE_FUNCTION(slice);
JS_DECLARE_NATIVE_FUNCTION(detached_getter);
JS_DECLARE_NATIVE_FUNCTION(transfer); JS_DECLARE_NATIVE_FUNCTION(transfer);
JS_DECLARE_NATIVE_FUNCTION(transfer_to_fixed_length); JS_DECLARE_NATIVE_FUNCTION(transfer_to_fixed_length);
}; };

View file

@ -54,15 +54,15 @@ public:
u32 element_size() const { return m_element_size; } u32 element_size() const { return m_element_size; }
virtual DeprecatedFlyString const& element_name() const = 0; virtual DeprecatedFlyString const& element_name() const = 0;
// 25.1.3.10 IsUnclampedIntegerElementType ( type ), https://tc39.es/ecma262/#sec-isunclampedintegerelementtype // 25.1.3.11 IsUnclampedIntegerElementType ( type ), https://tc39.es/ecma262/#sec-isunclampedintegerelementtype
virtual bool is_unclamped_integer_element_type() const = 0; virtual bool is_unclamped_integer_element_type() const = 0;
// 25.1.3.11 IsBigIntElementType ( type ), https://tc39.es/ecma262/#sec-isbigintelementtype // 25.1.3.12 IsBigIntElementType ( type ), https://tc39.es/ecma262/#sec-isbigintelementtype
virtual bool is_bigint_element_type() const = 0; virtual bool is_bigint_element_type() const = 0;
// 25.1.3.15 GetValueFromBuffer ( arrayBuffer, byteIndex, type, isTypedArray, order [ , isLittleEndian ] ), https://tc39.es/ecma262/#sec-getvaluefrombuffer // 25.1.3.16 GetValueFromBuffer ( arrayBuffer, byteIndex, type, isTypedArray, order [ , isLittleEndian ] ), https://tc39.es/ecma262/#sec-getvaluefrombuffer
virtual Value get_value_from_buffer(size_t byte_index, ArrayBuffer::Order, bool is_little_endian = true) const = 0; virtual Value get_value_from_buffer(size_t byte_index, ArrayBuffer::Order, bool is_little_endian = true) const = 0;
// 25.1.3.17 SetValueInBuffer ( arrayBuffer, byteIndex, type, value, isTypedArray, order [ , isLittleEndian ] ), https://tc39.es/ecma262/#sec-setvalueinbuffer // 25.1.3.18 SetValueInBuffer ( arrayBuffer, byteIndex, type, value, isTypedArray, order [ , isLittleEndian ] ), https://tc39.es/ecma262/#sec-setvalueinbuffer
virtual void set_value_in_buffer(size_t byte_index, Value, ArrayBuffer::Order, bool is_little_endian = true) = 0; virtual void set_value_in_buffer(size_t byte_index, Value, ArrayBuffer::Order, bool is_little_endian = true) = 0;
// 25.1.3.18 GetModifySetValueInBuffer ( arrayBuffer, byteIndex, type, value, op ), https://tc39.es/ecma262/#sec-getmodifysetvalueinbuffer // 25.1.3.19 GetModifySetValueInBuffer ( arrayBuffer, byteIndex, type, value, op ), https://tc39.es/ecma262/#sec-getmodifysetvalueinbuffer
virtual Value get_modify_set_value_in_buffer(size_t byte_index, Value value, ReadWriteModifyFunction operation, bool is_little_endian = true) = 0; virtual Value get_modify_set_value_in_buffer(size_t byte_index, Value value, ReadWriteModifyFunction operation, bool is_little_endian = true) = 0;
protected: protected:

View file

@ -146,7 +146,7 @@ VM::VM(OwnPtr<CustomData> custom_data, ErrorMessages error_messages)
// call HostEnsureCanAddPrivateElement when needed. // call HostEnsureCanAddPrivateElement when needed.
}; };
// 25.1.3.7 HostResizeArrayBuffer ( buffer, newByteLength ), https://tc39.es/ecma262/#sec-hostresizearraybuffer // 25.1.3.8 HostResizeArrayBuffer ( buffer, newByteLength ), https://tc39.es/ecma262/#sec-hostresizearraybuffer
host_resize_array_buffer = [this](ArrayBuffer& buffer, size_t new_byte_length) -> ThrowCompletionOr<HandledByHost> { host_resize_array_buffer = [this](ArrayBuffer& buffer, size_t new_byte_length) -> ThrowCompletionOr<HandledByHost> {
// The host-defined abstract operation HostResizeArrayBuffer takes arguments buffer (an ArrayBuffer) and // The host-defined abstract operation HostResizeArrayBuffer takes arguments buffer (an ArrayBuffer) and
// newByteLength (a non-negative integer) and returns either a normal completion containing either handled or // newByteLength (a non-negative integer) and returns either a normal completion containing either handled or