mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-08-09 17:49:40 +00:00
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:
parent
4bc3055c0f
commit
bf3e7d3ac4
Notes:
github-actions[bot]
2024-08-20 16:25:48 +00:00
Author: https://github.com/trflynn89
Commit: bf3e7d3ac4
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/1141
6 changed files with 108 additions and 109 deletions
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
};
|
};
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue