/src/serenity/Userland/Libraries/LibJS/Runtime/ArrayBuffer.h
Line | Count | Source |
1 | | /* |
2 | | * Copyright (c) 2020-2022, Linus Groh <linusg@serenityos.org> |
3 | | * |
4 | | * SPDX-License-Identifier: BSD-2-Clause |
5 | | */ |
6 | | |
7 | | #pragma once |
8 | | |
9 | | #include <AK/ByteBuffer.h> |
10 | | #include <AK/Function.h> |
11 | | #include <AK/Variant.h> |
12 | | #include <LibJS/Runtime/BigInt.h> |
13 | | #include <LibJS/Runtime/Completion.h> |
14 | | #include <LibJS/Runtime/GlobalObject.h> |
15 | | #include <LibJS/Runtime/Object.h> |
16 | | |
17 | | namespace JS { |
18 | | |
19 | | struct ClampedU8 { |
20 | | }; |
21 | | |
22 | | // 25.1.1 Notation (read-modify-write modification function), https://tc39.es/ecma262/#sec-arraybuffer-notation |
23 | | using ReadWriteModifyFunction = Function<ByteBuffer(ByteBuffer, ByteBuffer)>; |
24 | | |
25 | | enum class PreserveResizability { |
26 | | FixedLength, |
27 | | PreserveResizability |
28 | | }; |
29 | | |
30 | | // 6.2.9 Data Blocks, https://tc39.es/ecma262/#sec-data-blocks |
31 | | struct DataBlock { |
32 | | enum class Shared { |
33 | | No, |
34 | | Yes, |
35 | | }; |
36 | | |
37 | | ByteBuffer& buffer() |
38 | 0 | { |
39 | 0 | ByteBuffer* ptr { nullptr }; |
40 | 0 | byte_buffer.visit([&](Empty) { VERIFY_NOT_REACHED(); }, [&](auto* pointer) { ptr = pointer; }, [&](auto& value) { ptr = &value; }); |
41 | 0 | return *ptr; |
42 | 0 | } |
43 | 0 | ByteBuffer const& buffer() const { return const_cast<DataBlock*>(this)->buffer(); } |
44 | | |
45 | | size_t size() const |
46 | 0 | { |
47 | 0 | return byte_buffer.visit( |
48 | 0 | [](Empty) -> size_t { return 0u; }, |
49 | 0 | [](ByteBuffer const& buffer) { return buffer.size(); }, |
50 | 0 | [](ByteBuffer const* buffer) { return buffer->size(); }); |
51 | 0 | } |
52 | | |
53 | | Variant<Empty, ByteBuffer, ByteBuffer*> byte_buffer; |
54 | | Shared is_shared = { Shared::No }; |
55 | | }; |
56 | | |
57 | | class ArrayBuffer : public Object { |
58 | | JS_OBJECT(ArrayBuffer, Object); |
59 | | JS_DECLARE_ALLOCATOR(ArrayBuffer); |
60 | | |
61 | | public: |
62 | | static ThrowCompletionOr<NonnullGCPtr<ArrayBuffer>> create(Realm&, size_t); |
63 | | static NonnullGCPtr<ArrayBuffer> create(Realm&, ByteBuffer); |
64 | | static NonnullGCPtr<ArrayBuffer> create(Realm&, ByteBuffer*); |
65 | | |
66 | 0 | virtual ~ArrayBuffer() override = default; |
67 | | |
68 | 0 | size_t byte_length() const { return m_data_block.size(); } |
69 | | |
70 | | // [[ArrayBufferData]] |
71 | 0 | ByteBuffer& buffer() { return m_data_block.buffer(); } |
72 | 0 | ByteBuffer const& buffer() const { return m_data_block.buffer(); } |
73 | | |
74 | | // [[ArrayBufferMaxByteLength]] |
75 | 0 | size_t max_byte_length() const { return m_max_byte_length.value(); } |
76 | 0 | void set_max_byte_length(size_t max_byte_length) { m_max_byte_length = max_byte_length; } |
77 | | |
78 | | // Used by allocate_array_buffer() to attach the data block after construction |
79 | 0 | void set_data_block(DataBlock block) { m_data_block = move(block); } |
80 | | |
81 | 0 | Value detach_key() const { return m_detach_key; } |
82 | 0 | void set_detach_key(Value detach_key) { m_detach_key = detach_key; } |
83 | | |
84 | 0 | void detach_buffer() { m_data_block.byte_buffer = Empty {}; } |
85 | | |
86 | | // 25.1.3.4 IsDetachedBuffer ( arrayBuffer ), https://tc39.es/ecma262/#sec-isdetachedbuffer |
87 | | bool is_detached() const |
88 | 0 | { |
89 | | // 1. If arrayBuffer.[[ArrayBufferData]] is null, return true. |
90 | 0 | if (m_data_block.byte_buffer.has<Empty>()) |
91 | 0 | return true; |
92 | | // 2. Return false. |
93 | 0 | return false; |
94 | 0 | } |
95 | | |
96 | | // 25.1.3.9 IsFixedLengthArrayBuffer ( arrayBuffer ), https://tc39.es/ecma262/#sec-isfixedlengtharraybuffer |
97 | | bool is_fixed_length() const |
98 | 0 | { |
99 | | // 1. If arrayBuffer has an [[ArrayBufferMaxByteLength]] internal slot, return false. |
100 | 0 | if (m_max_byte_length.has_value()) |
101 | 0 | return false; |
102 | | |
103 | | // 2. Return true. |
104 | 0 | return true; |
105 | 0 | } |
106 | | |
107 | | // 25.2.2.2 IsSharedArrayBuffer ( obj ), https://tc39.es/ecma262/#sec-issharedarraybuffer |
108 | | bool is_shared_array_buffer() const |
109 | 0 | { |
110 | | // 1. Let bufferData be obj.[[ArrayBufferData]]. |
111 | | // 2. If bufferData is null, return false. |
112 | 0 | if (m_data_block.byte_buffer.has<Empty>()) |
113 | 0 | return false; |
114 | | // 3. If bufferData is a Data Block, return false. |
115 | 0 | if (m_data_block.is_shared == DataBlock::Shared::No) |
116 | 0 | return false; |
117 | | // 4. Assert: bufferData is a Shared Data Block. |
118 | 0 | VERIFY(m_data_block.is_shared == DataBlock::Shared::Yes); |
119 | | // 5. Return true. |
120 | 0 | return true; |
121 | 0 | } |
122 | | |
123 | | enum Order { |
124 | | SeqCst, |
125 | | Unordered |
126 | | }; |
127 | | template<typename type> |
128 | | Value get_value(size_t byte_index, bool is_typed_array, Order, bool is_little_endian = true); |
129 | | template<typename type> |
130 | | void set_value(size_t byte_index, Value value, bool is_typed_array, Order, bool is_little_endian = true); |
131 | | template<typename T> |
132 | | Value get_modify_set_value(size_t byte_index, Value value, ReadWriteModifyFunction operation, bool is_little_endian = true); |
133 | | |
134 | | private: |
135 | | ArrayBuffer(ByteBuffer buffer, Object& prototype); |
136 | | ArrayBuffer(ByteBuffer* buffer, Object& prototype); |
137 | | |
138 | | virtual void visit_edges(Visitor&) override; |
139 | | |
140 | | DataBlock m_data_block; |
141 | | Optional<size_t> m_max_byte_length; |
142 | | |
143 | | // The various detach related members of ArrayBuffer are not used by any ECMA262 functionality, |
144 | | // but are required to be available for the use of various harnesses like the Test262 test runner. |
145 | | Value m_detach_key; |
146 | | }; |
147 | | |
148 | | ThrowCompletionOr<DataBlock> create_byte_data_block(VM& vm, size_t size); |
149 | | void copy_data_block_bytes(ByteBuffer& to_block, u64 to_index, ByteBuffer const& from_block, u64 from_index, u64 count); |
150 | | ThrowCompletionOr<ArrayBuffer*> allocate_array_buffer(VM&, FunctionObject& constructor, size_t byte_length, Optional<size_t> const& max_byte_length = {}); |
151 | | ThrowCompletionOr<ArrayBuffer*> array_buffer_copy_and_detach(VM&, ArrayBuffer& array_buffer, Value new_length, PreserveResizability preserve_resizability); |
152 | | ThrowCompletionOr<void> detach_array_buffer(VM&, ArrayBuffer& array_buffer, Optional<Value> key = {}); |
153 | | ThrowCompletionOr<Optional<size_t>> get_array_buffer_max_byte_length_option(VM&, Value options); |
154 | | ThrowCompletionOr<ArrayBuffer*> clone_array_buffer(VM&, ArrayBuffer& source_buffer, size_t source_byte_offset, size_t source_length); |
155 | | ThrowCompletionOr<NonnullGCPtr<ArrayBuffer>> allocate_shared_array_buffer(VM&, FunctionObject& constructor, size_t byte_length); |
156 | | |
157 | | // 25.1.3.2 ArrayBufferByteLength ( arrayBuffer, order ), https://tc39.es/ecma262/#sec-arraybufferbytelength |
158 | | inline size_t array_buffer_byte_length(ArrayBuffer const& array_buffer, ArrayBuffer::Order) |
159 | 0 | { |
160 | | // FIXME: 1. If IsSharedArrayBuffer(arrayBuffer) is true and arrayBuffer has an [[ArrayBufferByteLengthData]] internal slot, then |
161 | | // FIXME: a. Let bufferByteLengthBlock be arrayBuffer.[[ArrayBufferByteLengthData]]. |
162 | | // FIXME: b. Let rawLength be GetRawBytesFromSharedBlock(bufferByteLengthBlock, 0, biguint64, true, order). |
163 | | // FIXME: c. Let isLittleEndian be the value of the [[LittleEndian]] field of the surrounding agent's Agent Record. |
164 | | // FIXME: d. Return ℝ(RawBytesToNumeric(biguint64, rawLength, isLittleEndian)). |
165 | | |
166 | | // 2. Assert: IsDetachedBuffer(arrayBuffer) is false. |
167 | 0 | VERIFY(!array_buffer.is_detached()); |
168 | | |
169 | | // 3. Return arrayBuffer.[[ArrayBufferByteLength]]. |
170 | 0 | return array_buffer.byte_length(); |
171 | 0 | } |
172 | | |
173 | | // 25.1.3.14 RawBytesToNumeric ( type, rawBytes, isLittleEndian ), https://tc39.es/ecma262/#sec-rawbytestonumeric |
174 | | template<typename T> |
175 | | static Value raw_bytes_to_numeric(VM& vm, Bytes raw_value, bool is_little_endian) |
176 | 0 | { |
177 | | // 1. Let elementSize be the Element Size value specified in Table 70 for Element Type type. |
178 | | // NOTE: Used in step 6, but not needed with our implementation of that step. |
179 | | |
180 | | // 2. If isLittleEndian is false, reverse the order of the elements of rawBytes. |
181 | 0 | if (!is_little_endian) { |
182 | 0 | VERIFY(raw_value.size() % 2 == 0); |
183 | 0 | for (size_t i = 0; i < raw_value.size() / 2; ++i) |
184 | 0 | swap(raw_value[i], raw_value[raw_value.size() - 1 - i]); |
185 | 0 | } |
186 | | |
187 | | // 3. If type is Float32, then |
188 | 0 | using UnderlyingBufferDataType = Conditional<IsSame<ClampedU8, T>, u8, T>; |
189 | 0 | if constexpr (IsSame<UnderlyingBufferDataType, float>) { |
190 | | // a. Let value be the byte elements of rawBytes concatenated and interpreted as a little-endian bit string encoding of an IEEE 754-2019 binary32 value. |
191 | 0 | float value; |
192 | 0 | raw_value.copy_to({ &value, sizeof(float) }); |
193 | | |
194 | | // b. If value is an IEEE 754-2019 binary32 NaN value, return the NaN Number value. |
195 | 0 | if (isnan(value)) |
196 | 0 | return js_nan(); |
197 | | |
198 | | // c. Return the Number value that corresponds to value. |
199 | 0 | return Value(value); |
200 | 0 | } |
201 | | |
202 | | // 4. If type is Float64, then |
203 | 0 | if constexpr (IsSame<UnderlyingBufferDataType, double>) { |
204 | | // a. Let value be the byte elements of rawBytes concatenated and interpreted as a little-endian bit string encoding of an IEEE 754-2019 binary64 value. |
205 | 0 | double value; |
206 | 0 | raw_value.copy_to({ &value, sizeof(double) }); |
207 | | |
208 | | // b. If value is an IEEE 754-2019 binary64 NaN value, return the NaN Number value. |
209 | 0 | if (isnan(value)) |
210 | 0 | return js_nan(); |
211 | | |
212 | | // c. Return the Number value that corresponds to value. |
213 | 0 | return Value(value); |
214 | 0 | } |
215 | | |
216 | | // NOTE: Not in spec, sanity check for steps below. |
217 | | if constexpr (!IsIntegral<UnderlyingBufferDataType>) |
218 | 0 | VERIFY_NOT_REACHED(); |
219 | | |
220 | | // 5. If IsUnsignedElementType(type) is true, then |
221 | | // a. Let intValue be the byte elements of rawBytes concatenated and interpreted as a bit string encoding of an unsigned little-endian binary number. |
222 | | // 6. Else, |
223 | | // a. Let intValue be the byte elements of rawBytes concatenated and interpreted as a bit string encoding of a binary little-endian two's complement number of bit length elementSize × 8. |
224 | | // |
225 | | // NOTE: The signed/unsigned logic above is implemented in step 7 by the IsSigned<> check, and in step 8 by JS::Value constructor overloads. |
226 | 0 | UnderlyingBufferDataType int_value = 0; |
227 | 0 | raw_value.copy_to({ &int_value, sizeof(UnderlyingBufferDataType) }); |
228 | | |
229 | | // 7. If IsBigIntElementType(type) is true, return the BigInt value that corresponds to intValue. |
230 | 0 | if constexpr (sizeof(UnderlyingBufferDataType) == 8) { |
231 | 0 | if constexpr (IsSigned<UnderlyingBufferDataType>) { |
232 | 0 | static_assert(IsSame<UnderlyingBufferDataType, i64>); |
233 | 0 | return BigInt::create(vm, Crypto::SignedBigInteger { int_value }); |
234 | 0 | } else { |
235 | 0 | static_assert(IsOneOf<UnderlyingBufferDataType, u64, double>); |
236 | 0 | return BigInt::create(vm, Crypto::SignedBigInteger { Crypto::UnsignedBigInteger { int_value } }); |
237 | 0 | } |
238 | | } |
239 | | // 8. Otherwise, return the Number value that corresponds to intValue. |
240 | 0 | else { |
241 | 0 | return Value(int_value); |
242 | 0 | } |
243 | 0 | } Unexecuted instantiation: Interpreter.cpp:JS::Value JS::raw_bytes_to_numeric<unsigned char>(JS::VM&, AK::Span<unsigned char>, bool) Unexecuted instantiation: Interpreter.cpp:JS::Value JS::raw_bytes_to_numeric<JS::ClampedU8>(JS::VM&, AK::Span<unsigned char>, bool) Unexecuted instantiation: Interpreter.cpp:JS::Value JS::raw_bytes_to_numeric<unsigned short>(JS::VM&, AK::Span<unsigned char>, bool) Unexecuted instantiation: Interpreter.cpp:JS::Value JS::raw_bytes_to_numeric<unsigned int>(JS::VM&, AK::Span<unsigned char>, bool) Unexecuted instantiation: Interpreter.cpp:JS::Value JS::raw_bytes_to_numeric<unsigned long>(JS::VM&, AK::Span<unsigned char>, bool) Unexecuted instantiation: Interpreter.cpp:JS::Value JS::raw_bytes_to_numeric<signed char>(JS::VM&, AK::Span<unsigned char>, bool) Unexecuted instantiation: Interpreter.cpp:JS::Value JS::raw_bytes_to_numeric<short>(JS::VM&, AK::Span<unsigned char>, bool) Unexecuted instantiation: Interpreter.cpp:JS::Value JS::raw_bytes_to_numeric<int>(JS::VM&, AK::Span<unsigned char>, bool) Unexecuted instantiation: Interpreter.cpp:JS::Value JS::raw_bytes_to_numeric<long>(JS::VM&, AK::Span<unsigned char>, bool) Unexecuted instantiation: Interpreter.cpp:JS::Value JS::raw_bytes_to_numeric<float>(JS::VM&, AK::Span<unsigned char>, bool) Unexecuted instantiation: Interpreter.cpp:JS::Value JS::raw_bytes_to_numeric<double>(JS::VM&, AK::Span<unsigned char>, bool) Unexecuted instantiation: DataViewPrototype.cpp:JS::Value JS::raw_bytes_to_numeric<long>(JS::VM&, AK::Span<unsigned char>, bool) Unexecuted instantiation: DataViewPrototype.cpp:JS::Value JS::raw_bytes_to_numeric<unsigned long>(JS::VM&, AK::Span<unsigned char>, bool) Unexecuted instantiation: DataViewPrototype.cpp:JS::Value JS::raw_bytes_to_numeric<float>(JS::VM&, AK::Span<unsigned char>, bool) Unexecuted instantiation: DataViewPrototype.cpp:JS::Value JS::raw_bytes_to_numeric<double>(JS::VM&, AK::Span<unsigned char>, bool) Unexecuted instantiation: DataViewPrototype.cpp:JS::Value JS::raw_bytes_to_numeric<signed char>(JS::VM&, AK::Span<unsigned char>, bool) Unexecuted instantiation: DataViewPrototype.cpp:JS::Value JS::raw_bytes_to_numeric<short>(JS::VM&, AK::Span<unsigned char>, bool) Unexecuted instantiation: DataViewPrototype.cpp:JS::Value JS::raw_bytes_to_numeric<int>(JS::VM&, AK::Span<unsigned char>, bool) Unexecuted instantiation: DataViewPrototype.cpp:JS::Value JS::raw_bytes_to_numeric<unsigned char>(JS::VM&, AK::Span<unsigned char>, bool) Unexecuted instantiation: DataViewPrototype.cpp:JS::Value JS::raw_bytes_to_numeric<unsigned short>(JS::VM&, AK::Span<unsigned char>, bool) Unexecuted instantiation: DataViewPrototype.cpp:JS::Value JS::raw_bytes_to_numeric<unsigned int>(JS::VM&, AK::Span<unsigned char>, bool) Unexecuted instantiation: AtomicsObject.cpp:JS::Value JS::raw_bytes_to_numeric<unsigned char>(JS::VM&, AK::Span<unsigned char>, bool) Unexecuted instantiation: AtomicsObject.cpp:JS::Value JS::raw_bytes_to_numeric<JS::ClampedU8>(JS::VM&, AK::Span<unsigned char>, bool) Unexecuted instantiation: AtomicsObject.cpp:JS::Value JS::raw_bytes_to_numeric<unsigned short>(JS::VM&, AK::Span<unsigned char>, bool) Unexecuted instantiation: AtomicsObject.cpp:JS::Value JS::raw_bytes_to_numeric<unsigned int>(JS::VM&, AK::Span<unsigned char>, bool) Unexecuted instantiation: AtomicsObject.cpp:JS::Value JS::raw_bytes_to_numeric<unsigned long>(JS::VM&, AK::Span<unsigned char>, bool) Unexecuted instantiation: AtomicsObject.cpp:JS::Value JS::raw_bytes_to_numeric<signed char>(JS::VM&, AK::Span<unsigned char>, bool) Unexecuted instantiation: AtomicsObject.cpp:JS::Value JS::raw_bytes_to_numeric<short>(JS::VM&, AK::Span<unsigned char>, bool) Unexecuted instantiation: AtomicsObject.cpp:JS::Value JS::raw_bytes_to_numeric<int>(JS::VM&, AK::Span<unsigned char>, bool) Unexecuted instantiation: AtomicsObject.cpp:JS::Value JS::raw_bytes_to_numeric<long>(JS::VM&, AK::Span<unsigned char>, bool) Unexecuted instantiation: AtomicsObject.cpp:JS::Value JS::raw_bytes_to_numeric<float>(JS::VM&, AK::Span<unsigned char>, bool) Unexecuted instantiation: AtomicsObject.cpp:JS::Value JS::raw_bytes_to_numeric<double>(JS::VM&, AK::Span<unsigned char>, bool) Unexecuted instantiation: TypedArray.cpp:JS::Value JS::raw_bytes_to_numeric<unsigned char>(JS::VM&, AK::Span<unsigned char>, bool) Unexecuted instantiation: TypedArray.cpp:JS::Value JS::raw_bytes_to_numeric<JS::ClampedU8>(JS::VM&, AK::Span<unsigned char>, bool) Unexecuted instantiation: TypedArray.cpp:JS::Value JS::raw_bytes_to_numeric<unsigned short>(JS::VM&, AK::Span<unsigned char>, bool) Unexecuted instantiation: TypedArray.cpp:JS::Value JS::raw_bytes_to_numeric<unsigned int>(JS::VM&, AK::Span<unsigned char>, bool) Unexecuted instantiation: TypedArray.cpp:JS::Value JS::raw_bytes_to_numeric<unsigned long>(JS::VM&, AK::Span<unsigned char>, bool) Unexecuted instantiation: TypedArray.cpp:JS::Value JS::raw_bytes_to_numeric<signed char>(JS::VM&, AK::Span<unsigned char>, bool) Unexecuted instantiation: TypedArray.cpp:JS::Value JS::raw_bytes_to_numeric<short>(JS::VM&, AK::Span<unsigned char>, bool) Unexecuted instantiation: TypedArray.cpp:JS::Value JS::raw_bytes_to_numeric<int>(JS::VM&, AK::Span<unsigned char>, bool) Unexecuted instantiation: TypedArray.cpp:JS::Value JS::raw_bytes_to_numeric<long>(JS::VM&, AK::Span<unsigned char>, bool) Unexecuted instantiation: TypedArray.cpp:JS::Value JS::raw_bytes_to_numeric<float>(JS::VM&, AK::Span<unsigned char>, bool) Unexecuted instantiation: TypedArray.cpp:JS::Value JS::raw_bytes_to_numeric<double>(JS::VM&, AK::Span<unsigned char>, bool) Unexecuted instantiation: TypedArrayPrototype.cpp:JS::Value JS::raw_bytes_to_numeric<unsigned char>(JS::VM&, AK::Span<unsigned char>, bool) Unexecuted instantiation: AbstractOperations.cpp:JS::Value JS::raw_bytes_to_numeric<unsigned char>(JS::VM&, AK::Span<unsigned char>, bool) |
244 | | |
245 | | // 25.1.3.16 GetValueFromBuffer ( arrayBuffer, byteIndex, type, isTypedArray, order [ , isLittleEndian ] ), https://tc39.es/ecma262/#sec-getvaluefrombuffer |
246 | | template<typename T> |
247 | | Value ArrayBuffer::get_value(size_t byte_index, [[maybe_unused]] bool is_typed_array, Order, bool is_little_endian) |
248 | 0 | { |
249 | 0 | auto& vm = this->vm(); |
250 | | // 1. Assert: IsDetachedBuffer(arrayBuffer) is false. |
251 | 0 | VERIFY(!is_detached()); |
252 | | |
253 | | // 2. Assert: There are sufficient bytes in arrayBuffer starting at byteIndex to represent a value of type. |
254 | 0 | VERIFY(m_data_block.buffer().bytes().slice(byte_index).size() >= sizeof(T)); |
255 | | |
256 | | // 3. Let block be arrayBuffer.[[ArrayBufferData]]. |
257 | 0 | auto& block = m_data_block.buffer(); |
258 | | |
259 | | // 4. Let elementSize be the Element Size value specified in Table 70 for Element Type type. |
260 | 0 | auto element_size = sizeof(T); |
261 | |
|
262 | 0 | AK::Array<u8, sizeof(T)> raw_value {}; |
263 | | |
264 | | // FIXME: 5. If IsSharedArrayBuffer(arrayBuffer) is true, then |
265 | 0 | if (false) { |
266 | | // FIXME: a. Let execution be the [[CandidateExecution]] field of the surrounding agent's Agent Record. |
267 | | // FIXME: b. Let eventsRecord be the Agent Events Record of execution.[[EventsRecords]] whose [[AgentSignifier]] is AgentSignifier(). |
268 | | // FIXME: c. If isTypedArray is true and IsNoTearConfiguration(type, order) is true, let noTear be true; otherwise let noTear be false. |
269 | | // FIXME: d. Let rawValue be a List of length elementSize whose elements are nondeterministically chosen byte values. |
270 | | // FIXME: e. NOTE: In implementations, rawValue is the result of a non-atomic or atomic read instruction on the underlying hardware. The nondeterminism is a semantic prescription of the memory model to describe observable behaviour of hardware with weak consistency. |
271 | | // FIXME: f. Let readEvent be ReadSharedMemory { [[Order]]: order, [[NoTear]]: noTear, [[Block]]: block, [[ByteIndex]]: byteIndex, [[ElementSize]]: elementSize }. |
272 | | // FIXME: g. Append readEvent to eventsRecord.[[EventList]]. |
273 | | // FIXME: h. Append Chosen Value Record { [[Event]]: readEvent, [[ChosenValue]]: rawValue } to execution.[[ChosenValues]]. |
274 | 0 | } |
275 | | // 6. Else, |
276 | 0 | else { |
277 | | // a. Let rawValue be a List whose elements are bytes from block at indices in the interval from byteIndex (inclusive) to byteIndex + elementSize (exclusive). |
278 | 0 | block.bytes().slice(byte_index, element_size).copy_to(raw_value); |
279 | 0 | } |
280 | | |
281 | | // 7. Assert: The number of elements in rawValue is elementSize. |
282 | 0 | VERIFY(raw_value.size() == element_size); |
283 | | |
284 | | // 8. If isLittleEndian is not present, set isLittleEndian to the value of the [[LittleEndian]] field of the surrounding agent's Agent Record. |
285 | | // NOTE: Done by default parameter at declaration of this function. |
286 | | |
287 | | // 9. Return RawBytesToNumeric(type, rawValue, isLittleEndian). |
288 | 0 | return raw_bytes_to_numeric<T>(vm, raw_value, is_little_endian); |
289 | 0 | } Unexecuted instantiation: JS::Value JS::ArrayBuffer::get_value<unsigned char>(unsigned long, bool, JS::ArrayBuffer::Order, bool) Unexecuted instantiation: JS::Value JS::ArrayBuffer::get_value<JS::ClampedU8>(unsigned long, bool, JS::ArrayBuffer::Order, bool) Unexecuted instantiation: JS::Value JS::ArrayBuffer::get_value<unsigned short>(unsigned long, bool, JS::ArrayBuffer::Order, bool) Unexecuted instantiation: JS::Value JS::ArrayBuffer::get_value<unsigned int>(unsigned long, bool, JS::ArrayBuffer::Order, bool) Unexecuted instantiation: JS::Value JS::ArrayBuffer::get_value<unsigned long>(unsigned long, bool, JS::ArrayBuffer::Order, bool) Unexecuted instantiation: JS::Value JS::ArrayBuffer::get_value<signed char>(unsigned long, bool, JS::ArrayBuffer::Order, bool) Unexecuted instantiation: JS::Value JS::ArrayBuffer::get_value<short>(unsigned long, bool, JS::ArrayBuffer::Order, bool) Unexecuted instantiation: JS::Value JS::ArrayBuffer::get_value<int>(unsigned long, bool, JS::ArrayBuffer::Order, bool) Unexecuted instantiation: JS::Value JS::ArrayBuffer::get_value<long>(unsigned long, bool, JS::ArrayBuffer::Order, bool) Unexecuted instantiation: JS::Value JS::ArrayBuffer::get_value<float>(unsigned long, bool, JS::ArrayBuffer::Order, bool) Unexecuted instantiation: JS::Value JS::ArrayBuffer::get_value<double>(unsigned long, bool, JS::ArrayBuffer::Order, bool) |
290 | | |
291 | | // 25.1.3.17 NumericToRawBytes ( type, value, isLittleEndian ), https://tc39.es/ecma262/#sec-numerictorawbytes |
292 | | template<typename T> |
293 | | static void numeric_to_raw_bytes(VM& vm, Value value, bool is_little_endian, Bytes raw_bytes) |
294 | 0 | { |
295 | 0 | VERIFY(value.is_number() || value.is_bigint()); |
296 | 0 | using UnderlyingBufferDataType = Conditional<IsSame<ClampedU8, T>, u8, T>; |
297 | 0 | VERIFY(raw_bytes.size() == sizeof(UnderlyingBufferDataType)); |
298 | 0 | auto flip_if_needed = [&]() { |
299 | 0 | if (is_little_endian) |
300 | 0 | return; |
301 | 0 | VERIFY(sizeof(UnderlyingBufferDataType) % 2 == 0); |
302 | 0 | for (size_t i = 0; i < sizeof(UnderlyingBufferDataType) / 2; ++i) |
303 | 0 | swap(raw_bytes[i], raw_bytes[sizeof(UnderlyingBufferDataType) - 1 - i]); |
304 | 0 | }; Unexecuted instantiation: Interpreter.cpp:JS::numeric_to_raw_bytes<unsigned short>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>)::{lambda()#1}::operator()() constUnexecuted instantiation: Interpreter.cpp:JS::numeric_to_raw_bytes<unsigned int>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>)::{lambda()#1}::operator()() constUnexecuted instantiation: Interpreter.cpp:JS::numeric_to_raw_bytes<unsigned long>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>)::{lambda()#1}::operator()() constUnexecuted instantiation: Interpreter.cpp:JS::numeric_to_raw_bytes<short>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>)::{lambda()#1}::operator()() constUnexecuted instantiation: Interpreter.cpp:JS::numeric_to_raw_bytes<int>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>)::{lambda()#1}::operator()() constUnexecuted instantiation: Interpreter.cpp:JS::numeric_to_raw_bytes<long>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>)::{lambda()#1}::operator()() constUnexecuted instantiation: Interpreter.cpp:JS::numeric_to_raw_bytes<float>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>)::{lambda()#1}::operator()() constUnexecuted instantiation: Interpreter.cpp:JS::numeric_to_raw_bytes<double>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>)::{lambda()#1}::operator()() constUnexecuted instantiation: DataViewPrototype.cpp:JS::numeric_to_raw_bytes<long>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>)::{lambda()#1}::operator()() constUnexecuted instantiation: DataViewPrototype.cpp:JS::numeric_to_raw_bytes<unsigned long>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>)::{lambda()#1}::operator()() constUnexecuted instantiation: DataViewPrototype.cpp:JS::numeric_to_raw_bytes<float>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>)::{lambda()#1}::operator()() constUnexecuted instantiation: DataViewPrototype.cpp:JS::numeric_to_raw_bytes<double>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>)::{lambda()#1}::operator()() constUnexecuted instantiation: DataViewPrototype.cpp:JS::numeric_to_raw_bytes<short>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>)::{lambda()#1}::operator()() constUnexecuted instantiation: DataViewPrototype.cpp:JS::numeric_to_raw_bytes<int>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>)::{lambda()#1}::operator()() constUnexecuted instantiation: DataViewPrototype.cpp:JS::numeric_to_raw_bytes<unsigned short>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>)::{lambda()#1}::operator()() constUnexecuted instantiation: DataViewPrototype.cpp:JS::numeric_to_raw_bytes<unsigned int>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>)::{lambda()#1}::operator()() constUnexecuted instantiation: AtomicsObject.cpp:JS::numeric_to_raw_bytes<unsigned short>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>)::{lambda()#1}::operator()() constUnexecuted instantiation: AtomicsObject.cpp:JS::numeric_to_raw_bytes<unsigned int>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>)::{lambda()#1}::operator()() constUnexecuted instantiation: AtomicsObject.cpp:JS::numeric_to_raw_bytes<unsigned long>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>)::{lambda()#1}::operator()() constUnexecuted instantiation: AtomicsObject.cpp:JS::numeric_to_raw_bytes<short>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>)::{lambda()#1}::operator()() constUnexecuted instantiation: AtomicsObject.cpp:JS::numeric_to_raw_bytes<int>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>)::{lambda()#1}::operator()() constUnexecuted instantiation: AtomicsObject.cpp:JS::numeric_to_raw_bytes<long>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>)::{lambda()#1}::operator()() constUnexecuted instantiation: AtomicsObject.cpp:JS::numeric_to_raw_bytes<float>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>)::{lambda()#1}::operator()() constUnexecuted instantiation: AtomicsObject.cpp:JS::numeric_to_raw_bytes<double>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>)::{lambda()#1}::operator()() constUnexecuted instantiation: TypedArray.cpp:JS::numeric_to_raw_bytes<unsigned short>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>)::{lambda()#1}::operator()() constUnexecuted instantiation: TypedArray.cpp:JS::numeric_to_raw_bytes<unsigned int>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>)::{lambda()#1}::operator()() constUnexecuted instantiation: TypedArray.cpp:JS::numeric_to_raw_bytes<unsigned long>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>)::{lambda()#1}::operator()() constUnexecuted instantiation: TypedArray.cpp:JS::numeric_to_raw_bytes<short>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>)::{lambda()#1}::operator()() constUnexecuted instantiation: TypedArray.cpp:JS::numeric_to_raw_bytes<int>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>)::{lambda()#1}::operator()() constUnexecuted instantiation: TypedArray.cpp:JS::numeric_to_raw_bytes<long>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>)::{lambda()#1}::operator()() constUnexecuted instantiation: TypedArray.cpp:JS::numeric_to_raw_bytes<float>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>)::{lambda()#1}::operator()() constUnexecuted instantiation: TypedArray.cpp:JS::numeric_to_raw_bytes<double>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>)::{lambda()#1}::operator()() constUnexecuted instantiation: TypedArrayPrototype.cpp:JS::numeric_to_raw_bytes<unsigned short>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>)::{lambda()#1}::operator()() constUnexecuted instantiation: TypedArrayPrototype.cpp:JS::numeric_to_raw_bytes<unsigned int>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>)::{lambda()#1}::operator()() constUnexecuted instantiation: TypedArrayPrototype.cpp:JS::numeric_to_raw_bytes<unsigned long>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>)::{lambda()#1}::operator()() constUnexecuted instantiation: TypedArrayPrototype.cpp:JS::numeric_to_raw_bytes<short>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>)::{lambda()#1}::operator()() constUnexecuted instantiation: TypedArrayPrototype.cpp:JS::numeric_to_raw_bytes<int>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>)::{lambda()#1}::operator()() constUnexecuted instantiation: TypedArrayPrototype.cpp:JS::numeric_to_raw_bytes<long>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>)::{lambda()#1}::operator()() constUnexecuted instantiation: TypedArrayPrototype.cpp:JS::numeric_to_raw_bytes<float>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>)::{lambda()#1}::operator()() constUnexecuted instantiation: TypedArrayPrototype.cpp:JS::numeric_to_raw_bytes<double>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>)::{lambda()#1}::operator()() const |
305 | 0 | if constexpr (IsSame<UnderlyingBufferDataType, float>) { |
306 | 0 | float raw_value = MUST(value.to_double(vm)); |
307 | 0 | ReadonlyBytes { &raw_value, sizeof(float) }.copy_to(raw_bytes); |
308 | 0 | flip_if_needed(); |
309 | 0 | return; |
310 | 0 | } |
311 | 0 | if constexpr (IsSame<UnderlyingBufferDataType, double>) { |
312 | 0 | double raw_value = MUST(value.to_double(vm)); |
313 | 0 | ReadonlyBytes { &raw_value, sizeof(double) }.copy_to(raw_bytes); |
314 | 0 | flip_if_needed(); |
315 | 0 | return; |
316 | 0 | } |
317 | | if constexpr (!IsIntegral<UnderlyingBufferDataType>) |
318 | 0 | VERIFY_NOT_REACHED(); |
319 | 0 | if constexpr (sizeof(UnderlyingBufferDataType) == 8) { |
320 | 0 | UnderlyingBufferDataType int_value; |
321 | |
|
322 | | if constexpr (IsSigned<UnderlyingBufferDataType>) |
323 | 0 | int_value = MUST(value.to_bigint_int64(vm)); |
324 | | else |
325 | 0 | int_value = MUST(value.to_bigint_uint64(vm)); |
326 | |
|
327 | 0 | ReadonlyBytes { &int_value, sizeof(UnderlyingBufferDataType) }.copy_to(raw_bytes); |
328 | 0 | flip_if_needed(); |
329 | 0 | return; |
330 | 0 | } else { |
331 | 0 | UnderlyingBufferDataType int_value; |
332 | 0 | if constexpr (IsSigned<UnderlyingBufferDataType>) { |
333 | | if constexpr (sizeof(UnderlyingBufferDataType) == 4) |
334 | 0 | int_value = MUST(value.to_i32(vm)); |
335 | | else if constexpr (sizeof(UnderlyingBufferDataType) == 2) |
336 | 0 | int_value = MUST(value.to_i16(vm)); |
337 | | else |
338 | 0 | int_value = MUST(value.to_i8(vm)); |
339 | 0 | } else { |
340 | | if constexpr (sizeof(UnderlyingBufferDataType) == 4) |
341 | 0 | int_value = MUST(value.to_u32(vm)); |
342 | | else if constexpr (sizeof(UnderlyingBufferDataType) == 2) |
343 | 0 | int_value = MUST(value.to_u16(vm)); |
344 | | else if constexpr (!IsSame<T, ClampedU8>) |
345 | 0 | int_value = MUST(value.to_u8(vm)); |
346 | | else |
347 | 0 | int_value = MUST(value.to_u8_clamp(vm)); |
348 | 0 | } |
349 | 0 | ReadonlyBytes { &int_value, sizeof(UnderlyingBufferDataType) }.copy_to(raw_bytes); |
350 | | if constexpr (sizeof(UnderlyingBufferDataType) % 2 == 0) |
351 | 0 | flip_if_needed(); |
352 | 0 | return; |
353 | 0 | } |
354 | 0 | } Unexecuted instantiation: Interpreter.cpp:void JS::numeric_to_raw_bytes<unsigned char>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>) Unexecuted instantiation: Interpreter.cpp:void JS::numeric_to_raw_bytes<JS::ClampedU8>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>) Unexecuted instantiation: Interpreter.cpp:void JS::numeric_to_raw_bytes<unsigned short>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>) Unexecuted instantiation: Interpreter.cpp:void JS::numeric_to_raw_bytes<unsigned int>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>) Unexecuted instantiation: Interpreter.cpp:void JS::numeric_to_raw_bytes<unsigned long>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>) Unexecuted instantiation: Interpreter.cpp:void JS::numeric_to_raw_bytes<signed char>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>) Unexecuted instantiation: Interpreter.cpp:void JS::numeric_to_raw_bytes<short>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>) Unexecuted instantiation: Interpreter.cpp:void JS::numeric_to_raw_bytes<int>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>) Unexecuted instantiation: Interpreter.cpp:void JS::numeric_to_raw_bytes<long>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>) Unexecuted instantiation: Interpreter.cpp:void JS::numeric_to_raw_bytes<float>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>) Unexecuted instantiation: Interpreter.cpp:void JS::numeric_to_raw_bytes<double>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>) Unexecuted instantiation: DataViewPrototype.cpp:void JS::numeric_to_raw_bytes<long>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>) Unexecuted instantiation: DataViewPrototype.cpp:void JS::numeric_to_raw_bytes<unsigned long>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>) Unexecuted instantiation: DataViewPrototype.cpp:void JS::numeric_to_raw_bytes<float>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>) Unexecuted instantiation: DataViewPrototype.cpp:void JS::numeric_to_raw_bytes<double>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>) Unexecuted instantiation: DataViewPrototype.cpp:void JS::numeric_to_raw_bytes<signed char>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>) Unexecuted instantiation: DataViewPrototype.cpp:void JS::numeric_to_raw_bytes<short>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>) Unexecuted instantiation: DataViewPrototype.cpp:void JS::numeric_to_raw_bytes<int>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>) Unexecuted instantiation: DataViewPrototype.cpp:void JS::numeric_to_raw_bytes<unsigned char>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>) Unexecuted instantiation: DataViewPrototype.cpp:void JS::numeric_to_raw_bytes<unsigned short>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>) Unexecuted instantiation: DataViewPrototype.cpp:void JS::numeric_to_raw_bytes<unsigned int>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>) Unexecuted instantiation: AtomicsObject.cpp:void JS::numeric_to_raw_bytes<unsigned char>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>) Unexecuted instantiation: AtomicsObject.cpp:void JS::numeric_to_raw_bytes<JS::ClampedU8>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>) Unexecuted instantiation: AtomicsObject.cpp:void JS::numeric_to_raw_bytes<unsigned short>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>) Unexecuted instantiation: AtomicsObject.cpp:void JS::numeric_to_raw_bytes<unsigned int>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>) Unexecuted instantiation: AtomicsObject.cpp:void JS::numeric_to_raw_bytes<unsigned long>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>) Unexecuted instantiation: AtomicsObject.cpp:void JS::numeric_to_raw_bytes<signed char>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>) Unexecuted instantiation: AtomicsObject.cpp:void JS::numeric_to_raw_bytes<short>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>) Unexecuted instantiation: AtomicsObject.cpp:void JS::numeric_to_raw_bytes<int>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>) Unexecuted instantiation: AtomicsObject.cpp:void JS::numeric_to_raw_bytes<long>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>) Unexecuted instantiation: AtomicsObject.cpp:void JS::numeric_to_raw_bytes<float>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>) Unexecuted instantiation: AtomicsObject.cpp:void JS::numeric_to_raw_bytes<double>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>) Unexecuted instantiation: TypedArray.cpp:void JS::numeric_to_raw_bytes<unsigned char>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>) Unexecuted instantiation: TypedArray.cpp:void JS::numeric_to_raw_bytes<JS::ClampedU8>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>) Unexecuted instantiation: TypedArray.cpp:void JS::numeric_to_raw_bytes<unsigned short>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>) Unexecuted instantiation: TypedArray.cpp:void JS::numeric_to_raw_bytes<unsigned int>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>) Unexecuted instantiation: TypedArray.cpp:void JS::numeric_to_raw_bytes<unsigned long>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>) Unexecuted instantiation: TypedArray.cpp:void JS::numeric_to_raw_bytes<signed char>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>) Unexecuted instantiation: TypedArray.cpp:void JS::numeric_to_raw_bytes<short>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>) Unexecuted instantiation: TypedArray.cpp:void JS::numeric_to_raw_bytes<int>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>) Unexecuted instantiation: TypedArray.cpp:void JS::numeric_to_raw_bytes<long>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>) Unexecuted instantiation: TypedArray.cpp:void JS::numeric_to_raw_bytes<float>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>) Unexecuted instantiation: TypedArray.cpp:void JS::numeric_to_raw_bytes<double>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>) Unexecuted instantiation: TypedArrayPrototype.cpp:void JS::numeric_to_raw_bytes<unsigned char>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>) Unexecuted instantiation: TypedArrayPrototype.cpp:void JS::numeric_to_raw_bytes<JS::ClampedU8>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>) Unexecuted instantiation: TypedArrayPrototype.cpp:void JS::numeric_to_raw_bytes<unsigned short>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>) Unexecuted instantiation: TypedArrayPrototype.cpp:void JS::numeric_to_raw_bytes<unsigned int>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>) Unexecuted instantiation: TypedArrayPrototype.cpp:void JS::numeric_to_raw_bytes<unsigned long>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>) Unexecuted instantiation: TypedArrayPrototype.cpp:void JS::numeric_to_raw_bytes<signed char>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>) Unexecuted instantiation: TypedArrayPrototype.cpp:void JS::numeric_to_raw_bytes<short>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>) Unexecuted instantiation: TypedArrayPrototype.cpp:void JS::numeric_to_raw_bytes<int>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>) Unexecuted instantiation: TypedArrayPrototype.cpp:void JS::numeric_to_raw_bytes<long>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>) Unexecuted instantiation: TypedArrayPrototype.cpp:void JS::numeric_to_raw_bytes<float>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>) Unexecuted instantiation: TypedArrayPrototype.cpp:void JS::numeric_to_raw_bytes<double>(JS::VM&, JS::Value, bool, AK::Span<unsigned char>) |
355 | | |
356 | | // 25.1.3.18 SetValueInBuffer ( arrayBuffer, byteIndex, type, value, isTypedArray, order [ , isLittleEndian ] ), https://tc39.es/ecma262/#sec-setvalueinbuffer |
357 | | template<typename T> |
358 | | void ArrayBuffer::set_value(size_t byte_index, Value value, [[maybe_unused]] bool is_typed_array, Order, bool is_little_endian) |
359 | 0 | { |
360 | 0 | auto& vm = this->vm(); |
361 | | |
362 | | // 1. Assert: IsDetachedBuffer(arrayBuffer) is false. |
363 | 0 | VERIFY(!is_detached()); |
364 | | |
365 | | // 2. Assert: There are sufficient bytes in arrayBuffer starting at byteIndex to represent a value of type. |
366 | 0 | VERIFY(m_data_block.buffer().bytes().slice(byte_index).size() >= sizeof(T)); |
367 | | |
368 | | // 3. Assert: value is a BigInt if IsBigIntElementType(type) is true; otherwise, value is a Number. |
369 | | if constexpr (IsIntegral<T> && sizeof(T) == 8) |
370 | 0 | VERIFY(value.is_bigint()); |
371 | | else |
372 | 0 | VERIFY(value.is_number()); |
373 | | |
374 | | // 4. Let block be arrayBuffer.[[ArrayBufferData]]. |
375 | 0 | auto& block = m_data_block.buffer(); |
376 | | |
377 | | // FIXME: 5. Let elementSize be the Element Size value specified in Table 70 for Element Type type. |
378 | | |
379 | | // 6. If isLittleEndian is not present, set isLittleEndian to the value of the [[LittleEndian]] field of the surrounding agent's Agent Record. |
380 | | // NOTE: Done by default parameter at declaration of this function. |
381 | | |
382 | | // 7. Let rawBytes be NumericToRawBytes(type, value, isLittleEndian). |
383 | 0 | AK::Array<u8, sizeof(T)> raw_bytes; |
384 | 0 | numeric_to_raw_bytes<T>(vm, value, is_little_endian, raw_bytes); |
385 | | |
386 | | // FIXME 8. If IsSharedArrayBuffer(arrayBuffer) is true, then |
387 | 0 | if (false) { |
388 | | // FIXME: a. Let execution be the [[CandidateExecution]] field of the surrounding agent's Agent Record. |
389 | | // FIXME: b. Let eventsRecord be the Agent Events Record of execution.[[EventsRecords]] whose [[AgentSignifier]] is AgentSignifier(). |
390 | | // FIXME: c. If isTypedArray is true and IsNoTearConfiguration(type, order) is true, let noTear be true; otherwise let noTear be false. |
391 | | // FIXME: d. Append WriteSharedMemory { [[Order]]: order, [[NoTear]]: noTear, [[Block]]: block, [[ByteIndex]]: byteIndex, [[ElementSize]]: elementSize, [[Payload]]: rawBytes } to eventsRecord.[[EventList]]. |
392 | 0 | } |
393 | | // 9. Else, |
394 | 0 | else { |
395 | | // a. Store the individual bytes of rawBytes into block, starting at block[byteIndex]. |
396 | 0 | raw_bytes.span().copy_to(block.span().slice(byte_index)); |
397 | 0 | } |
398 | | |
399 | | // 10. Return unused. |
400 | 0 | } Unexecuted instantiation: void JS::ArrayBuffer::set_value<unsigned char>(unsigned long, JS::Value, bool, JS::ArrayBuffer::Order, bool) Unexecuted instantiation: void JS::ArrayBuffer::set_value<JS::ClampedU8>(unsigned long, JS::Value, bool, JS::ArrayBuffer::Order, bool) Unexecuted instantiation: void JS::ArrayBuffer::set_value<unsigned short>(unsigned long, JS::Value, bool, JS::ArrayBuffer::Order, bool) Unexecuted instantiation: void JS::ArrayBuffer::set_value<unsigned int>(unsigned long, JS::Value, bool, JS::ArrayBuffer::Order, bool) Unexecuted instantiation: void JS::ArrayBuffer::set_value<unsigned long>(unsigned long, JS::Value, bool, JS::ArrayBuffer::Order, bool) Unexecuted instantiation: void JS::ArrayBuffer::set_value<signed char>(unsigned long, JS::Value, bool, JS::ArrayBuffer::Order, bool) Unexecuted instantiation: void JS::ArrayBuffer::set_value<short>(unsigned long, JS::Value, bool, JS::ArrayBuffer::Order, bool) Unexecuted instantiation: void JS::ArrayBuffer::set_value<int>(unsigned long, JS::Value, bool, JS::ArrayBuffer::Order, bool) Unexecuted instantiation: void JS::ArrayBuffer::set_value<long>(unsigned long, JS::Value, bool, JS::ArrayBuffer::Order, bool) Unexecuted instantiation: void JS::ArrayBuffer::set_value<float>(unsigned long, JS::Value, bool, JS::ArrayBuffer::Order, bool) Unexecuted instantiation: void JS::ArrayBuffer::set_value<double>(unsigned long, JS::Value, bool, JS::ArrayBuffer::Order, bool) |
401 | | |
402 | | // 25.1.3.19 GetModifySetValueInBuffer ( arrayBuffer, byteIndex, type, value, op [ , isLittleEndian ] ), https://tc39.es/ecma262/#sec-getmodifysetvalueinbuffer |
403 | | template<typename T> |
404 | | Value ArrayBuffer::get_modify_set_value(size_t byte_index, Value value, ReadWriteModifyFunction operation, bool is_little_endian) |
405 | 0 | { |
406 | 0 | auto& vm = this->vm(); |
407 | |
|
408 | 0 | auto raw_bytes = MUST(ByteBuffer::create_uninitialized(sizeof(T))); |
409 | 0 | numeric_to_raw_bytes<T>(vm, value, is_little_endian, raw_bytes); |
410 | | |
411 | | // FIXME: Check for shared buffer |
412 | |
|
413 | 0 | auto raw_bytes_read = MUST(ByteBuffer::create_uninitialized(sizeof(T))); |
414 | 0 | m_data_block.buffer().bytes().slice(byte_index, sizeof(T)).copy_to(raw_bytes_read); |
415 | 0 | auto raw_bytes_modified = operation(raw_bytes_read, raw_bytes); |
416 | 0 | raw_bytes_modified.span().copy_to(m_data_block.buffer().span().slice(byte_index)); |
417 | |
|
418 | 0 | return raw_bytes_to_numeric<T>(vm, raw_bytes_read, is_little_endian); |
419 | 0 | } Unexecuted instantiation: JS::Value JS::ArrayBuffer::get_modify_set_value<unsigned char>(unsigned long, JS::Value, AK::Function<AK::Detail::ByteBuffer<32ul> (AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>)>, bool) Unexecuted instantiation: JS::Value JS::ArrayBuffer::get_modify_set_value<JS::ClampedU8>(unsigned long, JS::Value, AK::Function<AK::Detail::ByteBuffer<32ul> (AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>)>, bool) Unexecuted instantiation: JS::Value JS::ArrayBuffer::get_modify_set_value<unsigned short>(unsigned long, JS::Value, AK::Function<AK::Detail::ByteBuffer<32ul> (AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>)>, bool) Unexecuted instantiation: JS::Value JS::ArrayBuffer::get_modify_set_value<unsigned int>(unsigned long, JS::Value, AK::Function<AK::Detail::ByteBuffer<32ul> (AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>)>, bool) Unexecuted instantiation: JS::Value JS::ArrayBuffer::get_modify_set_value<unsigned long>(unsigned long, JS::Value, AK::Function<AK::Detail::ByteBuffer<32ul> (AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>)>, bool) Unexecuted instantiation: JS::Value JS::ArrayBuffer::get_modify_set_value<signed char>(unsigned long, JS::Value, AK::Function<AK::Detail::ByteBuffer<32ul> (AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>)>, bool) Unexecuted instantiation: JS::Value JS::ArrayBuffer::get_modify_set_value<short>(unsigned long, JS::Value, AK::Function<AK::Detail::ByteBuffer<32ul> (AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>)>, bool) Unexecuted instantiation: JS::Value JS::ArrayBuffer::get_modify_set_value<int>(unsigned long, JS::Value, AK::Function<AK::Detail::ByteBuffer<32ul> (AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>)>, bool) Unexecuted instantiation: JS::Value JS::ArrayBuffer::get_modify_set_value<long>(unsigned long, JS::Value, AK::Function<AK::Detail::ByteBuffer<32ul> (AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>)>, bool) Unexecuted instantiation: JS::Value JS::ArrayBuffer::get_modify_set_value<float>(unsigned long, JS::Value, AK::Function<AK::Detail::ByteBuffer<32ul> (AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>)>, bool) Unexecuted instantiation: JS::Value JS::ArrayBuffer::get_modify_set_value<double>(unsigned long, JS::Value, AK::Function<AK::Detail::ByteBuffer<32ul> (AK::Detail::ByteBuffer<32ul>, AK::Detail::ByteBuffer<32ul>)>, bool) |
420 | | |
421 | | } |