From f4ea6b182404e510d05ebd1e36c4160660d1ef1a Mon Sep 17 00:00:00 2001 From: Timothy Flynn Date: Sun, 11 Jul 2021 08:57:54 -0400 Subject: LibJS: Implement TypedArray GetModifySetValueInBuffer abstract operation --- Userland/Libraries/LibJS/Runtime/ArrayBuffer.h | 21 +++++++++++++++++++++ Userland/Libraries/LibJS/Runtime/TypedArray.h | 3 +++ 2 files changed, 24 insertions(+) (limited to 'Userland/Libraries') diff --git a/Userland/Libraries/LibJS/Runtime/ArrayBuffer.h b/Userland/Libraries/LibJS/Runtime/ArrayBuffer.h index 4d712e56f4..681f363190 100644 --- a/Userland/Libraries/LibJS/Runtime/ArrayBuffer.h +++ b/Userland/Libraries/LibJS/Runtime/ArrayBuffer.h @@ -7,6 +7,7 @@ #pragma once #include +#include #include #include #include @@ -16,6 +17,9 @@ namespace JS { struct ClampedU8 { }; +// 25.1.1 Notation (read-modify-write modification function), https://tc39.es/ecma262/#sec-arraybuffer-notation +using ReadWriteModifyFunction = Function; + class ArrayBuffer : public Object { JS_OBJECT(ArrayBuffer, Object); @@ -45,6 +49,8 @@ public: Value get_value(size_t byte_index, bool is_typed_array, Order, bool is_little_endian = true); template Value set_value(size_t byte_index, Value value, bool is_typed_array, Order, bool is_little_endian = true); + template + Value get_modify_set_value(size_t byte_index, Value value, ReadWriteModifyFunction operation, bool is_little_endian = true); private: virtual void visit_edges(Visitor&) override; @@ -190,4 +196,19 @@ Value ArrayBuffer::set_value(size_t byte_index, Value value, [[maybe_unused]] bo return js_undefined(); } +// 25.1.2.13 GetModifySetValueInBuffer ( arrayBuffer, byteIndex, type, value, op [ , isLittleEndian ] ), https://tc39.es/ecma262/#sec-getmodifysetvalueinbuffer +template +Value ArrayBuffer::get_modify_set_value(size_t byte_index, Value value, ReadWriteModifyFunction operation, bool is_little_endian) +{ + auto raw_bytes = numeric_to_raw_bytes(global_object(), value, is_little_endian); + + // FIXME: Check for shared buffer + + auto raw_bytes_read = buffer_impl().slice(byte_index, sizeof(T)); + auto raw_bytes_modified = operation(raw_bytes_read, raw_bytes); + raw_bytes_modified.span().copy_to(buffer_impl().span().slice(byte_index)); + + return raw_bytes_to_numeric(global_object(), raw_bytes_read, is_little_endian); +} + } diff --git a/Userland/Libraries/LibJS/Runtime/TypedArray.h b/Userland/Libraries/LibJS/Runtime/TypedArray.h index 83d40f6cc7..fb501170e1 100644 --- a/Userland/Libraries/LibJS/Runtime/TypedArray.h +++ b/Userland/Libraries/LibJS/Runtime/TypedArray.h @@ -44,6 +44,8 @@ public: virtual Value get_value_from_buffer(size_t byte_index, ArrayBuffer::Order, bool is_little_endian = true) const = 0; // 25.1.2.12 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; + // 25.1.2.13 GetModifySetValueInBuffer ( arrayBuffer, byteIndex, type, value, op [ , isLittleEndian ] ), 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; protected: explicit TypedArrayBase(Object& prototype) @@ -438,6 +440,7 @@ public: Value get_value_from_buffer(size_t byte_index, ArrayBuffer::Order order, bool is_little_endian = true) const override { return viewed_array_buffer()->template get_value(byte_index, true, order, is_little_endian); } void set_value_in_buffer(size_t byte_index, Value value, ArrayBuffer::Order order, bool is_little_endian = true) override { viewed_array_buffer()->template set_value(byte_index, value, true, order, is_little_endian); } + Value get_modify_set_value_in_buffer(size_t byte_index, Value value, ReadWriteModifyFunction operation, bool is_little_endian = true) override { return viewed_array_buffer()->template get_modify_set_value(byte_index, value, move(operation), is_little_endian); } protected: TypedArray(u32 array_length, Object& prototype) -- cgit v1.2.3