diff options
author | Idan Horowitz <idan.horowitz@gmail.com> | 2021-06-14 02:02:53 +0300 |
---|---|---|
committer | Linus Groh <mail@linusgroh.de> | 2021-06-14 01:45:04 +0100 |
commit | d7a70eb77ce7bc3baf8a03800e3cda3771f3e71e (patch) | |
tree | 30fffdfff4b2eecbf537c3bb83e4f7ac74cb4995 /Userland/Libraries/LibJS/Runtime/ArrayBuffer.h | |
parent | c54b9a692011d8094f20f6852ddac0f77edddc24 (diff) | |
download | serenity-d7a70eb77ce7bc3baf8a03800e3cda3771f3e71e.zip |
LibJS: Add all of the DataView.prototype.set* methods
Diffstat (limited to 'Userland/Libraries/LibJS/Runtime/ArrayBuffer.h')
-rw-r--r-- | Userland/Libraries/LibJS/Runtime/ArrayBuffer.h | 57 |
1 files changed, 57 insertions, 0 deletions
diff --git a/Userland/Libraries/LibJS/Runtime/ArrayBuffer.h b/Userland/Libraries/LibJS/Runtime/ArrayBuffer.h index cc9b5f1a49..c2ee642ca3 100644 --- a/Userland/Libraries/LibJS/Runtime/ArrayBuffer.h +++ b/Userland/Libraries/LibJS/Runtime/ArrayBuffer.h @@ -40,6 +40,8 @@ public: }; template<typename type> Value get_value(size_t byte_index, bool is_typed_array, Order, bool is_little_endian = true); + template<typename type> + Value set_value(size_t byte_index, Value value, bool is_typed_array, Order, bool is_little_endian = true); private: virtual void visit_edges(Visitor&) override; @@ -108,4 +110,59 @@ Value ArrayBuffer::get_value(size_t byte_index, [[maybe_unused]] bool is_typed_a return raw_bytes_to_numeric<T>(global_object(), move(raw_value), is_little_endian); } +// 25.1.2.11 NumericToRawBytes ( type, value, isLittleEndian ), https://tc39.es/ecma262/#sec-numerictorawbytes +template<typename T> +static ByteBuffer numeric_to_raw_bytes(GlobalObject& global_object, Value value, bool is_little_endian) +{ + ByteBuffer raw_bytes = ByteBuffer::create_uninitialized(sizeof(T)); + auto flip_if_needed = [&]() { + if (is_little_endian) + return; + VERIFY(sizeof(T) % 2 == 0); + for (size_t i = 0; i < sizeof(T) / 2; ++i) + swap(raw_bytes[i], raw_bytes[sizeof(T) - 1 - i]); + }; + if constexpr (IsSame<T, float>) { + float raw_value = value.to_double(global_object); + ReadonlyBytes { &raw_value, sizeof(float) }.copy_to(raw_bytes); + flip_if_needed(); + return raw_bytes; + } + if constexpr (IsSame<T, double>) { + double raw_value = value.to_double(global_object); + ReadonlyBytes { &raw_value, sizeof(double) }.copy_to(raw_bytes); + flip_if_needed(); + return raw_bytes; + } + if constexpr (!IsIntegral<T>) + VERIFY_NOT_REACHED(); + if constexpr (sizeof(T) == 8) { + u64 int_value = value.as_bigint().big_integer().to_u64(); + ReadonlyBytes { &int_value, sizeof(u64) }.copy_to(raw_bytes); + flip_if_needed(); + return raw_bytes; + } else { + T int_value; + if constexpr (IsSigned<T>) + int_value = value.to_i32(global_object); + else + int_value = value.to_u32(global_object); + ReadonlyBytes { &int_value, sizeof(T) }.copy_to(raw_bytes); + flip_if_needed(); + return raw_bytes; + } +} + +// 25.1.2.12 SetValueInBuffer ( arrayBuffer, byteIndex, type, value, isTypedArray, order [ , isLittleEndian ] ), https://tc39.es/ecma262/#sec-setvalueinbuffer +template<typename T> +Value ArrayBuffer::set_value(size_t byte_index, Value value, [[maybe_unused]] bool is_typed_array, Order, bool is_little_endian) +{ + auto raw_bytes = numeric_to_raw_bytes<T>(global_object(), value, is_little_endian); + + // FIXME: Check for shared buffer + + raw_bytes.span().copy_to(buffer_impl().span().slice(byte_index)); + return js_undefined(); +} + } |