1 /*
2 * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "ecmascript/builtins/builtins_typedarray.h"
17 #include <cmath>
18 #include "ecmascript/base/typed_array_helper-inl.h"
19 #include "ecmascript/builtins/builtins_array.h"
20 #include "ecmascript/ecma_string-inl.h"
21 #include "ecmascript/interpreter/interpreter.h"
22 #include "ecmascript/js_stable_array.h"
23 #include "ecmascript/object_fast_operator-inl.h"
24
25 namespace panda::ecmascript::builtins {
26 using TypedArrayHelper = base::TypedArrayHelper;
27 using BuiltinsArray = builtins::BuiltinsArray;
28 using BuiltinsArrayBuffer = builtins::BuiltinsArrayBuffer;
29
30 // 22.2.1
TypedArrayBaseConstructor(EcmaRuntimeCallInfo * argv)31 JSTaggedValue BuiltinsTypedArray::TypedArrayBaseConstructor(EcmaRuntimeCallInfo *argv)
32 {
33 ASSERT(argv);
34 BUILTINS_API_TRACE(argv->GetThread(), TypedArray, BaseConstructor);
35 THROW_TYPE_ERROR_AND_RETURN(argv->GetThread(), "TypedArray Constructor cannot be called.",
36 JSTaggedValue::Exception());
37 }
38
Int8ArrayConstructor(EcmaRuntimeCallInfo * argv)39 JSTaggedValue BuiltinsTypedArray::Int8ArrayConstructor(EcmaRuntimeCallInfo *argv)
40 {
41 ASSERT(argv);
42 BUILTINS_API_TRACE(argv->GetThread(), TypedArray, Int8ArrayConstructor);
43 JSThread *thread = argv->GetThread();
44 return TypedArrayHelper::TypedArrayConstructor(argv, thread->GlobalConstants()->GetHandledInt8ArrayString(),
45 DataViewType::INT8);
46 }
47
Uint8ArrayConstructor(EcmaRuntimeCallInfo * argv)48 JSTaggedValue BuiltinsTypedArray::Uint8ArrayConstructor(EcmaRuntimeCallInfo *argv)
49 {
50 ASSERT(argv);
51 BUILTINS_API_TRACE(argv->GetThread(), TypedArray, Uint8ArrayConstructor);
52 JSThread *thread = argv->GetThread();
53 return TypedArrayHelper::TypedArrayConstructor(argv, thread->GlobalConstants()->GetHandledUint8ArrayString(),
54 DataViewType::UINT8);
55 }
56
Uint8ClampedArrayConstructor(EcmaRuntimeCallInfo * argv)57 JSTaggedValue BuiltinsTypedArray::Uint8ClampedArrayConstructor(EcmaRuntimeCallInfo *argv)
58 {
59 ASSERT(argv);
60 BUILTINS_API_TRACE(argv->GetThread(), TypedArray, Uint8ClampedArrayConstructor);
61 JSThread *thread = argv->GetThread();
62 return TypedArrayHelper::TypedArrayConstructor(argv,
63 thread->GlobalConstants()->GetHandledUint8ClampedArrayString(),
64 DataViewType::UINT8_CLAMPED);
65 }
66
Int16ArrayConstructor(EcmaRuntimeCallInfo * argv)67 JSTaggedValue BuiltinsTypedArray::Int16ArrayConstructor(EcmaRuntimeCallInfo *argv)
68 {
69 ASSERT(argv);
70 BUILTINS_API_TRACE(argv->GetThread(), TypedArray, Int16ArrayConstructor);
71 JSThread *thread = argv->GetThread();
72 return TypedArrayHelper::TypedArrayConstructor(argv, thread->GlobalConstants()->GetHandledInt16ArrayString(),
73 DataViewType::INT16);
74 }
75
Uint16ArrayConstructor(EcmaRuntimeCallInfo * argv)76 JSTaggedValue BuiltinsTypedArray::Uint16ArrayConstructor(EcmaRuntimeCallInfo *argv)
77 {
78 ASSERT(argv);
79 BUILTINS_API_TRACE(argv->GetThread(), TypedArray, Uint16ArrayConstructor);
80 JSThread *thread = argv->GetThread();
81 return TypedArrayHelper::TypedArrayConstructor(argv, thread->GlobalConstants()->GetHandledUint16ArrayString(),
82 DataViewType::UINT16);
83 }
84
Int32ArrayConstructor(EcmaRuntimeCallInfo * argv)85 JSTaggedValue BuiltinsTypedArray::Int32ArrayConstructor(EcmaRuntimeCallInfo *argv)
86 {
87 ASSERT(argv);
88 BUILTINS_API_TRACE(argv->GetThread(), TypedArray, Int32ArrayConstructor);
89 JSThread *thread = argv->GetThread();
90 return TypedArrayHelper::TypedArrayConstructor(argv, thread->GlobalConstants()->GetHandledInt32ArrayString(),
91 DataViewType::INT32);
92 }
93
Uint32ArrayConstructor(EcmaRuntimeCallInfo * argv)94 JSTaggedValue BuiltinsTypedArray::Uint32ArrayConstructor(EcmaRuntimeCallInfo *argv)
95 {
96 ASSERT(argv);
97 BUILTINS_API_TRACE(argv->GetThread(), TypedArray, Uint32ArrayConstructor);
98 JSThread *thread = argv->GetThread();
99 return TypedArrayHelper::TypedArrayConstructor(argv, thread->GlobalConstants()->GetHandledUint32ArrayString(),
100 DataViewType::UINT32);
101 }
102
Float32ArrayConstructor(EcmaRuntimeCallInfo * argv)103 JSTaggedValue BuiltinsTypedArray::Float32ArrayConstructor(EcmaRuntimeCallInfo *argv)
104 {
105 ASSERT(argv);
106 BUILTINS_API_TRACE(argv->GetThread(), TypedArray, Float32ArrayConstructor);
107 JSThread *thread = argv->GetThread();
108 return TypedArrayHelper::TypedArrayConstructor(argv, thread->GlobalConstants()->GetHandledFloat32ArrayString(),
109 DataViewType::FLOAT32);
110 }
111
Float64ArrayConstructor(EcmaRuntimeCallInfo * argv)112 JSTaggedValue BuiltinsTypedArray::Float64ArrayConstructor(EcmaRuntimeCallInfo *argv)
113 {
114 ASSERT(argv);
115 BUILTINS_API_TRACE(argv->GetThread(), TypedArray, Float64ArrayConstructor);
116 JSThread *thread = argv->GetThread();
117 return TypedArrayHelper::TypedArrayConstructor(argv, thread->GlobalConstants()->GetHandledFloat64ArrayString(),
118 DataViewType::FLOAT64);
119 }
120
BigInt64ArrayConstructor(EcmaRuntimeCallInfo * argv)121 JSTaggedValue BuiltinsTypedArray::BigInt64ArrayConstructor(EcmaRuntimeCallInfo *argv)
122 {
123 ASSERT(argv);
124 BUILTINS_API_TRACE(argv->GetThread(), TypedArray, BigInt64ArrayConstructor);
125 JSThread *thread = argv->GetThread();
126 return TypedArrayHelper::TypedArrayConstructor(argv, thread->GlobalConstants()->GetHandledBigInt64ArrayString(),
127 DataViewType::BIGINT64);
128 }
129
BigUint64ArrayConstructor(EcmaRuntimeCallInfo * argv)130 JSTaggedValue BuiltinsTypedArray::BigUint64ArrayConstructor(EcmaRuntimeCallInfo *argv)
131 {
132 ASSERT(argv);
133 BUILTINS_API_TRACE(argv->GetThread(), TypedArray, BigUint64ArrayConstructor);
134 JSThread *thread = argv->GetThread();
135 return TypedArrayHelper::TypedArrayConstructor(argv, thread->GlobalConstants()->GetHandledBigUint64ArrayString(),
136 DataViewType::BIGUINT64);
137 }
138
FromUsingIteratorUndefinedValues(JSThread * thread,const JSHandle<JSTaggedValue> & thisHandle,const JSHandle<JSTaggedValue> source,const JSHandle<JSTaggedValue> & thisArgHandle,const JSHandle<JSTaggedValue> & mapfn)139 JSTaggedValue FromUsingIteratorUndefinedValues(JSThread *thread, const JSHandle<JSTaggedValue> &thisHandle,
140 const JSHandle<JSTaggedValue> source,
141 const JSHandle<JSTaggedValue> &thisArgHandle,
142 const JSHandle<JSTaggedValue> &mapfn)
143 {
144 // 3. If mapfn is undefined, let mapping be false.
145 // 4. Else,
146 // a. If IsCallable(mapfn) is false, throw a TypeError exception.
147 // b. Let mapping be true.
148 bool mapping = false;
149 if (!mapfn->IsUndefined()) {
150 if (!mapfn->IsCallable()) {
151 THROW_TYPE_ERROR_AND_RETURN(thread, "the mapfn is not callable.", JSTaggedValue::Exception());
152 }
153 mapping = true;
154 }
155 // 7. NOTE: source is not an Iterable so assume it is already an array-like object.
156 // 8. Let arrayLike be ! ToObject(source).
157 JSHandle<JSObject> arrayLikeObj = JSTaggedValue::ToObject(thread, source);
158 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
159 JSHandle<JSTaggedValue> arrayLike(arrayLikeObj);
160 // 9. Let len be ? LengthOfArrayLike(arrayLike).
161 JSHandle<JSTaggedValue> lengthKey = thread->GlobalConstants()->GetHandledLengthString();
162 JSHandle<JSTaggedValue> lenResult = JSTaggedValue::GetProperty(thread, arrayLike, lengthKey).GetValue();
163 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
164 JSTaggedNumber tLen = JSTaggedValue::ToLength(thread, lenResult);
165 // 6. ReturnIfAbrupt(relativeTarget).
166 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
167 int64_t len = tLen.GetNumber();
168 // 10. Let targetObj be ? TypedArrayCreate(C, « len »).
169 JSTaggedType args[1] = {JSTaggedValue(len).GetRawData()};
170 JSHandle<JSObject> targetObj = TypedArrayHelper::TypedArrayCreate(thread, thisHandle, 1, args);
171 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
172 // 11. Let k be 0.
173 // 12. Repeat, while k < len
174 // a. Let Pk be ! ToString(k).
175 // b. Let kValue be ? Get(arrayLike, Pk).
176 // c. If mapping is true, then
177 // i. Let mappedValue be ? Call(mapfn, thisArg, « kValue, k »).
178 // d. Else, let mappedValue be kValue.
179 // e. Perform ? Set(targetObj, Pk, mappedValue, true).
180 // f. Set k to k + 1.
181 JSMutableHandle<JSTaggedValue> tKey(thread, JSTaggedValue::Undefined());
182 const uint32_t argsLength = 2;
183 int64_t k = 0;
184 JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
185 JSMutableHandle<JSTaggedValue> kValue(thread, JSTaggedValue::Undefined());
186 JSHandle<JSTaggedValue> mapValue;
187 while (k < len) {
188 tKey.Update(JSTaggedValue(k));
189 kValue.Update(
190 ObjectFastOperator::FastGetPropertyByValue(thread, arrayLike.GetTaggedValue(), tKey.GetTaggedValue()));
191 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
192 if (mapping) {
193 EcmaRuntimeCallInfo *info =
194 EcmaInterpreter::NewRuntimeCallInfo(thread, mapfn, thisArgHandle, undefined, argsLength);
195 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
196 info->SetCallArg(kValue.GetTaggedValue(), tKey.GetTaggedValue());
197 JSTaggedValue callResult = JSFunction::Call(info);
198 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
199 mapValue = JSHandle<JSTaggedValue>(thread, callResult);
200 } else {
201 mapValue = kValue;
202 }
203 ObjectFastOperator::FastSetPropertyByIndex(thread, targetObj.GetTaggedValue(), k, mapValue.GetTaggedValue());
204 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
205 k++;
206 }
207 // 13. Return targetObj.
208 return targetObj.GetTaggedValue();
209 }
210
ProcessFromNotUndefinedValues(JSThread * thread,const CVector<JSHandle<JSTaggedValue>> & vec,const JSHandle<JSTaggedValue> & thisHandle,JSHandle<JSTaggedValue> & thisArgHandle,JSHandle<JSTaggedValue> & mapfn)211 JSTaggedValue ProcessFromNotUndefinedValues(JSThread *thread, const CVector<JSHandle<JSTaggedValue>> &vec,
212 const JSHandle<JSTaggedValue> &thisHandle,
213 JSHandle<JSTaggedValue> &thisArgHandle, JSHandle<JSTaggedValue> &mapfn)
214 {
215 // 3. If mapfn is undefined, let mapping be false.
216 // 4. Else,
217 // a. If IsCallable(mapfn) is false, throw a TypeError exception.
218 // b. Let mapping be true.
219 bool mapping = false;
220 if (!mapfn->IsUndefined()) {
221 if (!mapfn->IsCallable()) {
222 THROW_TYPE_ERROR_AND_RETURN(thread, "the mapfn is not callable.", JSTaggedValue::Exception());
223 }
224 mapping = true;
225 }
226 uint32_t len = vec.size();
227 JSTaggedType args[1] = {JSTaggedValue(len).GetRawData()};
228 JSHandle<JSObject> targetObj = TypedArrayHelper::TypedArrayCreate(thread, thisHandle, 1, args);
229 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
230 // d. Let k be 0.
231 // e. Repeat, while k < len
232 // i. Let Pk be ! ToString(k).
233 // ii. Let kValue be the first element of values and remove that element from values.
234 // iii. If mapping is true, then
235 // 1. Let mappedValue be ? Call(mapfn, thisArg, « kValue, k »).
236 // iv. Else, let mappedValue be kValue.
237 // v. Perform ? Set(targetObj, Pk, mappedValue, true).
238 // vi. Set k to k + 1.
239 JSMutableHandle<JSTaggedValue> tKey(thread, JSTaggedValue::Undefined());
240 JSMutableHandle<JSTaggedValue> mapValue(thread, JSTaggedValue::Undefined());
241 const uint32_t argsLength = 2;
242 uint32_t k = 0;
243 JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
244 while (k < len) {
245 tKey.Update(JSTaggedValue(k));
246 JSHandle<JSTaggedValue> kValue = vec[k];
247 if (mapping) {
248 EcmaRuntimeCallInfo *info =
249 EcmaInterpreter::NewRuntimeCallInfo(thread, mapfn, thisArgHandle, undefined, argsLength);
250 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
251 info->SetCallArg(kValue.GetTaggedValue(), tKey.GetTaggedValue());
252 JSTaggedValue callResult = JSFunction::Call(info);
253 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
254 mapValue.Update(callResult);
255 } else {
256 mapValue.Update(kValue.GetTaggedValue());
257 }
258 ObjectFastOperator::FastSetPropertyByIndex(thread, targetObj.GetTaggedValue(), k, mapValue.GetTaggedValue());
259 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
260 k++;
261 }
262 // f. Assert: values is now an empty List.
263 // g. Return targetObj.
264 return targetObj.GetTaggedValue();
265 }
266
267 // 22.2.2.1 %TypedArray%.from ( source [ , mapfn [ , thisArg ] ] )
From(EcmaRuntimeCallInfo * argv)268 JSTaggedValue BuiltinsTypedArray::From(EcmaRuntimeCallInfo *argv)
269 {
270 ASSERT(argv);
271 BUILTINS_API_TRACE(argv->GetThread(), TypedArray, From);
272 JSThread *thread = argv->GetThread();
273 [[maybe_unused]] EcmaHandleScope handleScope(thread);
274 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
275 // 1. Let C be the this value.
276 // 2. If IsConstructor(C) is false, throw a TypeError exception.
277 JSHandle<JSTaggedValue> thisHandle = GetThis(argv);
278 if (!thisHandle->IsConstructor()) {
279 THROW_TYPE_ERROR_AND_RETURN(thread, "the this value is not a Constructor.", JSTaggedValue::Exception());
280 }
281 JSHandle<JSTaggedValue> thisArgHandle = GetCallArg(argv, BuiltinsBase::ArgsPosition::THIRD);
282 // 3. If mapfn is undefined, let mapping be false.
283 // 4. Else,
284 // a. If IsCallable(mapfn) is false, throw a TypeError exception.
285 // b. Let mapping be true.
286 JSHandle<JSTaggedValue> mapfn = GetCallArg(argv, 1);
287 if (!mapfn->IsUndefined()) {
288 if (!mapfn->IsCallable()) {
289 THROW_TYPE_ERROR_AND_RETURN(thread, "the mapfn is not callable.", JSTaggedValue::Exception());
290 }
291 }
292 // 5. Let usingIterator be ? GetMethod(source, @@iterator).
293 JSHandle<JSTaggedValue> source = GetCallArg(argv, 0);
294 JSHandle<JSTaggedValue> iteratorSymbol = env->GetIteratorSymbol();
295 JSHandle<JSTaggedValue> usingIterator = JSObject::GetMethod(thread, source, iteratorSymbol);
296 // 6. If usingIterator is not undefined, then
297 // a. Let values be ? IterableToList(source, usingIterator).
298 // b. Let len be the number of elements in values.
299 // c. Let targetObj be ? TypedArrayCreate(C, « len »).
300 if (!usingIterator->IsUndefined() && !TypedArrayHelper::IsNativeArrayIterator(thread, source, usingIterator)) {
301 CVector<JSHandle<JSTaggedValue>> vec;
302 JSHandle<JSTaggedValue> iterator = JSIterator::GetIterator(thread, source, usingIterator);
303 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
304 JSHandle<JSTaggedValue> next(thread, JSTaggedValue::True());
305 while (!next->IsFalse()) {
306 next = JSIterator::IteratorStep(thread, iterator);
307 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
308 if (!next->IsFalse()) {
309 JSHandle<JSTaggedValue> nextValue = JSIterator::IteratorValue(thread, next);
310 RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, nextValue.GetTaggedValue());
311 vec.push_back(nextValue);
312 }
313 }
314 return ProcessFromNotUndefinedValues(thread, vec, thisHandle, thisArgHandle, mapfn);
315 }
316 return FromUsingIteratorUndefinedValues(thread, thisHandle, source, thisArgHandle, mapfn);
317 }
318
319 // 22.2.2.2 %TypedArray%.of ( ...items )
Of(EcmaRuntimeCallInfo * argv)320 JSTaggedValue BuiltinsTypedArray::Of(EcmaRuntimeCallInfo *argv)
321 {
322 ASSERT(argv);
323 BUILTINS_API_TRACE(argv->GetThread(), TypedArray, Of);
324 JSThread *thread = argv->GetThread();
325 [[maybe_unused]] EcmaHandleScope handleScope(thread);
326 // 1. Let len be the actual number of arguments passed to this function.
327 uint32_t len = argv->GetArgsNumber();
328 // 2. Let items be the List of arguments passed to this function.
329 // 3. Let C be the this value.
330 JSHandle<JSTaggedValue> thisHandle = GetThis(argv);
331 // 4. If IsConstructor(C) is false, throw a TypeError exception.
332 if (!thisHandle->IsConstructor()) {
333 THROW_TYPE_ERROR_AND_RETURN(thread, "the this value is not a Constructor.", JSTaggedValue::Exception());
334 }
335 // 5. Let newObj be TypedArrayCreate(C, « len »).
336 JSTaggedType args[1] = {JSTaggedValue(len).GetRawData()};
337 JSHandle<JSObject> newObj = TypedArrayHelper::TypedArrayCreate(thread, thisHandle, 1, args);
338 // 6. ReturnIfAbrupt(newObj).
339 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
340 // 7. Let k be 0.
341 // 8. Repeat, while k < len
342 // a. Let kValue be items[k].
343 // b. Let Pk be ! ToString(k).
344 // c. Perform ? Set(newObj, Pk, kValue, true).
345 // d. ReturnIfAbrupt(status).
346 // e. Set k to k + 1.
347 JSMutableHandle<JSTaggedValue> tKey(thread, JSTaggedValue::Undefined());
348 uint32_t k = 0;
349 while (k < len) {
350 tKey.Update(JSTaggedValue(k));
351 JSHandle<JSTaggedValue> kKey(JSTaggedValue::ToString(thread, tKey));
352 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
353 JSHandle<JSTaggedValue> kValue = GetCallArg(argv, k);
354 JSTaggedValue::SetProperty(thread, JSHandle<JSTaggedValue>::Cast(newObj), kKey, kValue, true);
355 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
356 k++;
357 }
358 // 9. Return newObj.
359 return newObj.GetTaggedValue();
360 }
361
362 // 22.2.2.4
Species(EcmaRuntimeCallInfo * argv)363 JSTaggedValue BuiltinsTypedArray::Species(EcmaRuntimeCallInfo *argv)
364 {
365 ASSERT(argv);
366 BUILTINS_API_TRACE(argv->GetThread(), TypedArray, Species);
367 // 1. Return the this value.
368 return GetThis(argv).GetTaggedValue();
369 }
370
371 // prototype
372 // 22.2.3.1 get %TypedArray%.prototype.buffer
GetBuffer(EcmaRuntimeCallInfo * argv)373 JSTaggedValue BuiltinsTypedArray::GetBuffer(EcmaRuntimeCallInfo *argv)
374 {
375 ASSERT(argv);
376 BUILTINS_API_TRACE(argv->GetThread(), TypedArray, GetBuffer);
377 JSThread *thread = argv->GetThread();
378 [[maybe_unused]] EcmaHandleScope handleScope(thread);
379 // 1. Let O be the this value.
380 JSHandle<JSTaggedValue> thisHandle = GetThis(argv);
381 // 2. If Type(O) is not Object, throw a TypeError exception.
382 if (!thisHandle->IsECMAObject()) {
383 THROW_TYPE_ERROR_AND_RETURN(thread, "This value is not an object.", JSTaggedValue::Exception());
384 }
385 // 3. If O does not have a [[ViewedArrayBuffer]] internal slot, throw a TypeError exception.
386 if (!thisHandle->IsTypedArray()) {
387 THROW_TYPE_ERROR_AND_RETURN(thread, "This value does not have a [[ViewedArrayBuffer]] internal slot.",
388 JSTaggedValue::Exception());
389 }
390 // 4. Let buffer be the value of O’s [[ViewedArrayBuffer]] internal slot.
391 JSHandle<JSTypedArray> typedArray = JSHandle<JSTypedArray>::Cast(thisHandle);
392 JSTaggedValue buffer = JSTypedArray::GetOffHeapBuffer(thread, typedArray);
393 // 5. Return buffer.
394 return buffer;
395 }
396
397 // 22.2.3.2
GetByteLength(EcmaRuntimeCallInfo * argv)398 JSTaggedValue BuiltinsTypedArray::GetByteLength(EcmaRuntimeCallInfo *argv)
399 {
400 ASSERT(argv);
401 BUILTINS_API_TRACE(argv->GetThread(), TypedArray, GetByteLength);
402 JSThread *thread = argv->GetThread();
403 [[maybe_unused]] EcmaHandleScope handleScope(thread);
404 // 1. Let O be the this value.
405 JSHandle<JSTaggedValue> thisHandle = GetThis(argv);
406 // 2. If Type(O) is not Object, throw a TypeError exception.
407 if (!thisHandle->IsECMAObject()) {
408 THROW_TYPE_ERROR_AND_RETURN(thread, "This value is not an object.", JSTaggedValue::Exception());
409 }
410 // 3. If O does not have a [[ViewedArrayBuffer]] internal slot, throw a TypeError exception.
411 if (!thisHandle->IsTypedArray()) {
412 THROW_TYPE_ERROR_AND_RETURN(thread, "This value does not have a [[ViewedArrayBuffer]] internal slot.",
413 JSTaggedValue::Exception());
414 }
415 // 4. Let buffer be the value of O’s [[ViewedArrayBuffer]] internal slot.
416 JSHandle<JSTypedArray> typeArrayObj = JSHandle<JSTypedArray>::Cast(thisHandle);
417 JSTaggedValue buffer = typeArrayObj->GetViewedArrayBufferOrByteArray();
418 // 5. If IsDetachedBuffer(buffer) is true, return 0.
419 if (BuiltinsArrayBuffer::IsDetachedBuffer(buffer)) {
420 return JSTaggedValue(0);
421 }
422 // 6. Let size be the value of O’s [[ByteLength]] internal slot.
423 // 7. Return size.
424 return JSTaggedValue(typeArrayObj->GetByteLength());
425 }
426
427 // 22.2.3.3
GetByteOffset(EcmaRuntimeCallInfo * argv)428 JSTaggedValue BuiltinsTypedArray::GetByteOffset(EcmaRuntimeCallInfo *argv)
429 {
430 ASSERT(argv);
431 BUILTINS_API_TRACE(argv->GetThread(), TypedArray, GetByteOffset);
432 JSThread *thread = argv->GetThread();
433 [[maybe_unused]] EcmaHandleScope handleScope(thread);
434 // 1. Let O be the this value.
435 JSHandle<JSTaggedValue> thisHandle = GetThis(argv);
436 // 2. If Type(O) is not Object, throw a TypeError exception.
437 if (!thisHandle->IsECMAObject()) {
438 THROW_TYPE_ERROR_AND_RETURN(thread, "This value is not an object.", JSTaggedValue::Exception());
439 }
440 // 3. If O does not have a [[ViewedArrayBuffer]] internal slot, throw a TypeError exception.
441 if (!thisHandle->IsTypedArray()) {
442 THROW_TYPE_ERROR_AND_RETURN(thread, "This value does not have a [[ViewedArrayBuffer]] internal slot.",
443 JSTaggedValue::Exception());
444 }
445 // 4. Let buffer be the value of O’s [[ViewedArrayBuffer]] internal slot.
446 JSHandle<JSTypedArray> typeArrayObj = JSHandle<JSTypedArray>::Cast(thisHandle);
447 JSTaggedValue buffer = typeArrayObj->GetViewedArrayBufferOrByteArray();
448 // 5. If IsDetachedBuffer(buffer) is true, return 0.
449 if (BuiltinsArrayBuffer::IsDetachedBuffer(buffer)) {
450 return JSTaggedValue(0);
451 }
452 // 6. Let offset be the value of O’s [[ByteOffset]] internal slot.
453 uint32_t offset = typeArrayObj->GetByteOffset();
454 // 7. Return offset.
455 return JSTaggedValue(offset);
456 }
457
458 // 22.2.3.5
CopyWithin(EcmaRuntimeCallInfo * argv)459 JSTaggedValue BuiltinsTypedArray::CopyWithin(EcmaRuntimeCallInfo *argv)
460 {
461 ASSERT(argv);
462 BUILTINS_API_TRACE(argv->GetThread(), TypedArray, CopyWithin);
463 if (!GetThis(argv)->IsTypedArray()) {
464 THROW_TYPE_ERROR_AND_RETURN(argv->GetThread(), "This is not a TypedArray.", JSTaggedValue::Exception());
465 }
466 return BuiltinsArray::CopyWithin(argv);
467 }
468
469 // 22.2.3.6
Entries(EcmaRuntimeCallInfo * argv)470 JSTaggedValue BuiltinsTypedArray::Entries(EcmaRuntimeCallInfo *argv)
471 {
472 ASSERT(argv);
473 BUILTINS_API_TRACE(argv->GetThread(), TypedArray, Entries);
474 JSThread *thread = argv->GetThread();
475 [[maybe_unused]] EcmaHandleScope handleScope(thread);
476 // 1. Let O be the this value.
477 JSHandle<JSTaggedValue> thisHandle = GetThis(argv);
478 // 2. Let valid be ValidateTypedArray(O).
479 TypedArrayHelper::ValidateTypedArray(thread, thisHandle);
480 // 3. ReturnIfAbrupt(valid).
481 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(argv->GetThread());
482 JSHandle<JSObject> self(thisHandle);
483 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
484 // 4. Return CreateArrayIterator(O, "key+value").
485 JSHandle<JSArrayIterator> iter(factory->NewJSArrayIterator(self, IterationKind::KEY_AND_VALUE));
486 return iter.GetTaggedValue();
487 }
488
489 // 22.2.3.7
Every(EcmaRuntimeCallInfo * argv)490 JSTaggedValue BuiltinsTypedArray::Every(EcmaRuntimeCallInfo *argv)
491 {
492 ASSERT(argv);
493 BUILTINS_API_TRACE(argv->GetThread(), TypedArray, Every);
494 JSThread *thread = argv->GetThread();
495 [[maybe_unused]] EcmaHandleScope handleScope(thread);
496
497 // 1. Let valid be ValidateTypedArray(O).
498 JSHandle<JSTaggedValue> thisHandle = GetThis(argv);
499 TypedArrayHelper::ValidateTypedArray(thread, thisHandle);
500 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
501 JSHandle<JSObject> thisObjHandle = JSTaggedValue::ToObject(thread, thisHandle);
502 // 2. ReturnIfAbrupt(O).
503 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
504 JSHandle<JSTaggedValue> thisObjVal(thisObjHandle);
505
506 // 3. Let len be ToLength(Get(O, "length")).
507 uint32_t len = JSHandle<JSTypedArray>::Cast(thisObjHandle)->GetArrayLength();
508 // 4. ReturnIfAbrupt(len).
509 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
510 // 5. If IsCallable(callbackfn) is false, throw a TypeError exception.
511 JSHandle<JSTaggedValue> callbackFnHandle = GetCallArg(argv, 0);
512 if (!callbackFnHandle->IsCallable()) {
513 THROW_TYPE_ERROR_AND_RETURN(thread, "the callbackfun is not callable.", JSTaggedValue::Exception());
514 }
515
516 // 6. If thisArg was supplied, let T be thisArg; else let T be undefined.
517 JSHandle<JSTaggedValue> thisArgHandle = GetCallArg(argv, 1);
518
519 // 7. Let k be 0.
520 // 8. Repeat, while k < len
521 // a. Let Pk be ToString(k).
522 // b. Let kPresent be HasProperty(O, Pk).
523 // c. ReturnIfAbrupt(kPresent).
524 // d. If kPresent is true, then
525 // i. Let kValue be Get(O, Pk).
526 // ii. ReturnIfAbrupt(kValue).
527 // iii. Let testResult be ToBoolean(Call(callbackfn, T, «kValue, k, O»)).
528 // iv. ReturnIfAbrupt(testResult).
529 // v. If testResult is false, return false.
530 // e. Increase k by 1.
531 JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
532 const uint32_t argsLength = 3;
533 JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
534 uint32_t k = 0;
535 while (k < len) {
536 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
537 JSHandle<JSTaggedValue> kValue = JSTaggedValue::GetProperty(thread, thisObjVal, k).GetValue();
538 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
539 key.Update(JSTaggedValue(k));
540 EcmaRuntimeCallInfo *info =
541 EcmaInterpreter::NewRuntimeCallInfo(thread, callbackFnHandle, thisArgHandle, undefined, argsLength);
542 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
543 info->SetCallArg(kValue.GetTaggedValue(), key.GetTaggedValue(), thisObjVal.GetTaggedValue());
544 JSTaggedValue callResult = JSFunction::Call(info);
545 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
546 bool boolResult = callResult.ToBoolean();
547 if (!boolResult) {
548 return GetTaggedBoolean(false);
549 }
550 k++;
551 }
552
553 // 9. Return true.
554 return GetTaggedBoolean(true);
555 }
556
557 // 22.2.3.8
Fill(EcmaRuntimeCallInfo * argv)558 JSTaggedValue BuiltinsTypedArray::Fill(EcmaRuntimeCallInfo *argv)
559 {
560 ASSERT(argv);
561 JSThread *thread = argv->GetThread();
562 BUILTINS_API_TRACE(thread, TypedArray, Fill);
563 JSHandle<JSTaggedValue> thisHandle = GetThis(argv);
564 // 1. Let O be ToObject(this value).
565 JSHandle<JSObject> thisObjHandle = JSTaggedValue::ToObject(thread, thisHandle);
566 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
567 // 2. Let taRecord be ? ValidateTypedArray(O, SEQ-CST).
568 TypedArrayHelper::ValidateTypedArray(thread, thisHandle);
569 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
570 // 3. Let len be TypedArrayLength(taRecord).
571 JSHandle<JSTaggedValue> thisObjVal(thisObjHandle);
572 int64_t len = JSHandle<JSTypedArray>::Cast(thisObjVal)->GetArrayLength();
573 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
574 // 4. If O.[[ContentType]] is BIGINT, set value to ? ToBigInt(value).
575 // 5. Otherwise, set value to ? ToNumber(value).
576 JSHandle<JSTaggedValue> value = GetCallArg(argv, 0);
577 if (thisObjVal->IsTypedArray() || thisObjVal->IsSharedTypedArray()) {
578 ContentType contentType = JSHandle<JSTypedArray>::Cast(thisObjVal)->GetContentType();
579 if (contentType == ContentType::BigInt) {
580 value = JSHandle<JSTaggedValue>(thread, JSTaggedValue::ToBigInt(thread, value));
581 } else {
582 value = JSHandle<JSTaggedValue>(thread, JSTaggedValue::ToNumber(thread, value));
583 }
584 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
585 }
586 // 6. Let relativeStart be ? ToIntegerOrInfinity(start).
587 JSHandle<JSTaggedValue> startArg = GetCallArg(argv, 1);
588 JSTaggedNumber argStartTemp = JSTaggedValue::ToInteger(thread, startArg);
589 // 7. ReturnIfAbrupt(relativeStart).
590 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
591 double argStart = argStartTemp.GetNumber();
592 // 8. Else if relativeStart < 0, let startIndex be max(len + relativeStart, 0).
593 // 9. Else, let startIndex be min(relativeStart, len).
594 int64_t start = 0;
595 if (argStart < 0) {
596 double tempStart = argStart + len;
597 start = tempStart > 0 ? tempStart : 0;
598 } else {
599 start = argStart < len ? argStart : len;
600 }
601
602 // 10. If end is undefined, let relativeEnd be len; else let relativeEnd be ? ToIntegerOrInfinity(end).
603 double argEnd = len;
604 JSHandle<JSTaggedValue> endArg = GetCallArg(argv, INDEX_TWO);
605 if (!endArg->IsUndefined()) {
606 JSTaggedNumber argEndTemp = JSTaggedValue::ToInteger(thread, endArg);
607 // 11. ReturnIfAbrupt(relativeEnd).
608 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
609 argEnd = argEndTemp.GetNumber();
610 }
611
612 // 12. Else if relativeEnd < 0, let endIndex be max(len + relativeEnd, 0).
613 // 13. Else, let endIndex be min(relativeEnd, len).
614 int64_t end = len;
615 if (argEnd < 0) {
616 double tempEnd = argEnd + len;
617 end = tempEnd > 0 ? tempEnd : 0;
618 } else {
619 end = argEnd < len ? argEnd : len;
620 }
621
622 // 14. Set taRecord to MakeTypedArrayWithBufferWitnessRecord(O, SEQ-CST).
623 // 15. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
624 TypedArrayHelper::ValidateTypedArray(thread, thisHandle);
625 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
626
627 // 19. Repeat, while k < final
628 // a. Let Pk be ! ToString((k)).
629 // b. Perform ! Set(O, Pk, value, true).
630 // c. Set k to k + 1.
631
632 if (thisObjVal->IsTypedArray() || thisObjVal->IsSharedTypedArray()) {
633 bool result = JSTypedArray::FastTypedArrayFill(thread, thisObjVal, value, start, end);
634 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
635 if (result) {
636 return thisObjHandle.GetTaggedValue();
637 }
638 }
639
640 int64_t k = start;
641 JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
642 while (k < end) {
643 key.Update(JSTaggedValue(k));
644 JSArray::FastSetPropertyByValue(thread, thisObjVal, key, value);
645 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
646 k++;
647 }
648
649 // 20. Return O.
650 return thisObjHandle.GetTaggedValue();
651 }
652
653 // 22.2.3.9 %TypedArray%.prototype.filter ( callbackfn [ , thisArg ] )
Filter(EcmaRuntimeCallInfo * argv)654 JSTaggedValue BuiltinsTypedArray::Filter(EcmaRuntimeCallInfo *argv)
655 {
656 ASSERT(argv);
657 BUILTINS_API_TRACE(argv->GetThread(), TypedArray, Filter);
658 JSThread *thread = argv->GetThread();
659 [[maybe_unused]] EcmaHandleScope handleScope(thread);
660 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
661 // 1. Let O be the this value.
662 JSHandle<JSTaggedValue> thisHandle = GetThis(argv);
663 // 2. Let valid be ValidateTypedArray(O).
664 TypedArrayHelper::ValidateTypedArray(thread, thisHandle);
665 // 3. ReturnIfAbrupt(valid).
666 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
667
668 JSHandle<JSTypedArray> thisObj(thisHandle);
669 // 4. Let len be the value of O’s [[ArrayLength]] internal slot.
670 uint32_t len = thisObj->GetArrayLength();
671 // 5. If IsCallable(callbackfn) is false, throw a TypeError exception.
672 JSHandle<JSTaggedValue> callbackFnHandle = GetCallArg(argv, 0);
673 if (!callbackFnHandle->IsCallable()) {
674 THROW_TYPE_ERROR_AND_RETURN(thread, "the callbackfun is not callable.", JSTaggedValue::Exception());
675 }
676 // 6. If thisArg was supplied, let T be thisArg; else let T be undefined.
677 JSHandle<JSTaggedValue> thisArgHandle = GetCallArg(argv, 1);
678
679 // 10. Let kept be a new empty List.
680 JSHandle<TaggedArray> kept(factory->NewTaggedArray(len));
681
682 // 11. Let k be 0.
683 // 12. Let captured be 0.
684 // 13. Repeat, while k < len
685 // a. Let Pk be ToString(k).
686 // b. Let kValue be Get(O, Pk).
687 // c. ReturnIfAbrupt(kValue).
688 // d. Let selected be ToBoolean(Call(callbackfn, T, «kValue, k, O»)).
689 // e. ReturnIfAbrupt(selected).
690 // f. If selected is true, then
691 // i. Append kValue to the end of kept.
692 // ii. Increase captured by 1.
693 // g. Increase k by 1.
694 int32_t captured = 0;
695 JSMutableHandle<JSTaggedValue> tKey(thread, JSTaggedValue::Undefined());
696 JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
697 JSMutableHandle<JSTaggedValue> kValue(thread, JSTaggedValue::Undefined());
698 for (uint32_t k = 0; k < len; k++) {
699 tKey.Update(JSTaggedValue(k));
700 kValue.Update(ObjectFastOperator::FastGetPropertyByValue(thread, thisHandle.GetTaggedValue(),
701 tKey.GetTaggedValue()));
702 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
703 EcmaRuntimeCallInfo *info =
704 EcmaInterpreter::NewRuntimeCallInfo(thread, callbackFnHandle, thisArgHandle,
705 undefined, 3); // 3: «kValue, k, O»
706 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
707 info->SetCallArg(kValue.GetTaggedValue(), tKey.GetTaggedValue(), thisHandle.GetTaggedValue());
708 JSTaggedValue callResult = JSFunction::Call(info);
709 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
710 if (callResult.ToBoolean()) {
711 kept->Set(thread, captured, kValue);
712 captured++;
713 }
714 }
715 // es11 9. Let A be ? TypedArraySpeciesCreate(O, « captured »).
716 JSTaggedType args[1] = {JSTaggedValue(captured).GetRawData()};
717 JSHandle<JSObject> newArrObj = TypedArrayHelper::TypedArraySpeciesCreate(thread, thisObj, 1, args);
718 // 15. ReturnIfAbrupt(A).
719 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
720 // 16. Let n be 0.
721 // 17. For each element e of kept
722 // a. Let status be Set(A, ToString(n), e, true ).
723 // b. ReturnIfAbrupt(status).
724 // c. Increase n by 1.
725 JSMutableHandle<JSTaggedValue> valueHandle(thread, JSTaggedValue::Undefined());
726 JSMutableHandle<JSTaggedValue> ntKey(thread, JSTaggedValue::Undefined());
727 for (int32_t n = 0; n < captured; n++) {
728 valueHandle.Update(kept->Get(n));
729 ntKey.Update(JSTaggedValue(n));
730 ObjectFastOperator::FastSetPropertyByValue(thread, newArrObj.GetTaggedValue(),
731 ntKey.GetTaggedValue(), valueHandle.GetTaggedValue());
732 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
733 }
734 // 18. Return A.
735 return newArrObj.GetTaggedValue();
736 }
737
738 // 22.2.3.10
Find(EcmaRuntimeCallInfo * argv)739 JSTaggedValue BuiltinsTypedArray::Find(EcmaRuntimeCallInfo *argv)
740 {
741 ASSERT(argv);
742 BUILTINS_API_TRACE(argv->GetThread(), TypedArray, Find);
743 if (!GetThis(argv)->IsTypedArray()) {
744 THROW_TYPE_ERROR_AND_RETURN(argv->GetThread(), "This is not a TypedArray.", JSTaggedValue::Exception());
745 }
746 return BuiltinsArray::Find(argv);
747 }
748
749 // 22.2.3.11
FindIndex(EcmaRuntimeCallInfo * argv)750 JSTaggedValue BuiltinsTypedArray::FindIndex(EcmaRuntimeCallInfo *argv)
751 {
752 ASSERT(argv);
753 BUILTINS_API_TRACE(argv->GetThread(), TypedArray, FindIndex);
754 if (!GetThis(argv)->IsTypedArray()) {
755 THROW_TYPE_ERROR_AND_RETURN(argv->GetThread(), "This is not a TypedArray.", JSTaggedValue::Exception());
756 }
757 return BuiltinsArray::FindIndex(argv);
758 }
759
760 // 22.2.3.12
ForEach(EcmaRuntimeCallInfo * argv)761 JSTaggedValue BuiltinsTypedArray::ForEach(EcmaRuntimeCallInfo *argv)
762 {
763 ASSERT(argv);
764 BUILTINS_API_TRACE(argv->GetThread(), TypedArray, ForEach);
765 JSThread *thread = argv->GetThread();
766 [[maybe_unused]] EcmaHandleScope handleScope(thread);
767
768 // 1. Let valid be ValidateTypedArray(O).
769 JSHandle<JSTaggedValue> thisHandle = GetThis(argv);
770 TypedArrayHelper::ValidateTypedArray(thread, thisHandle);
771 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
772 JSHandle<JSObject> thisObjHandle = JSTaggedValue::ToObject(thread, thisHandle);
773 // 2. ReturnIfAbrupt(O).
774 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
775 JSHandle<JSTaggedValue> thisObjVal(thisObjHandle);
776
777 // 3. Let len be ToLength(Get(O, "length")).
778 uint32_t len = JSHandle<JSTypedArray>::Cast(thisObjHandle)->GetArrayLength();
779 // 4. ReturnIfAbrupt(len).
780 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
781
782 // 5. If IsCallable(callbackfn) is false, throw a TypeError exception.
783 JSHandle<JSTaggedValue> callbackFnHandle = GetCallArg(argv, 0);
784 if (!callbackFnHandle->IsCallable()) {
785 THROW_TYPE_ERROR_AND_RETURN(thread, "the callbackfun is not callable.", JSTaggedValue::Exception());
786 }
787
788 // 6. If thisArg was supplied, let T be thisArg; else let T be undefined.
789 JSHandle<JSTaggedValue> thisArgHandle = GetCallArg(argv, 1);
790
791 // 7. Let k be 0.
792 // 8. Repeat, while k < len
793 // a. Let Pk be ToString(k).
794 // b. Let kPresent be HasProperty(O, Pk).
795 // c. ReturnIfAbrupt(kPresent).
796 // d. If kPresent is true, then
797 // i. Let kValue be Get(O, Pk).
798 // ii. ReturnIfAbrupt(kValue).
799 // iii. Let funcResult be Call(callbackfn, T, «kValue, k, O»).
800 // iv. ReturnIfAbrupt(funcResult).
801 // e. Increase k by 1.
802 JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
803 const uint32_t argsLength = 3;
804 JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
805 uint32_t k = 0;
806 while (k < len) {
807 JSHandle<JSTaggedValue> kValue = JSTaggedValue::GetProperty(thread, thisObjVal, k).GetValue();
808 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
809 key.Update(JSTaggedValue(k));
810 EcmaRuntimeCallInfo *info =
811 EcmaInterpreter::NewRuntimeCallInfo(thread, callbackFnHandle, thisArgHandle, undefined, argsLength);
812 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
813 info->SetCallArg(kValue.GetTaggedValue(), key.GetTaggedValue(), thisObjVal.GetTaggedValue());
814 JSTaggedValue funcResult = JSFunction::Call(info);
815 RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, funcResult);
816 k++;
817 }
818
819 // 9. Return undefined.
820 return JSTaggedValue::Undefined();
821 }
822
823 // 22.2.3.13
IndexOf(EcmaRuntimeCallInfo * argv)824 JSTaggedValue BuiltinsTypedArray::IndexOf(EcmaRuntimeCallInfo *argv)
825 {
826 ASSERT(argv);
827 JSThread *thread = argv->GetThread();
828 BUILTINS_API_TRACE(argv->GetThread(), TypedArray, IndexOf);
829 TypedArrayHelper::ValidateTypedArray(thread, GetThis(argv));
830 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
831 return BuiltinsArray::IndexOf(argv);
832 }
833
834 // 22.2.3.14
Join(EcmaRuntimeCallInfo * argv)835 JSTaggedValue BuiltinsTypedArray::Join(EcmaRuntimeCallInfo *argv)
836 {
837 ASSERT(argv);
838 BUILTINS_API_TRACE(argv->GetThread(), TypedArray, Join);
839 JSThread *thread = argv->GetThread();
840 [[maybe_unused]] EcmaHandleScope handleScope(thread);
841
842 JSHandle<JSTaggedValue> thisHandle = GetThis(argv);
843
844 if (!thisHandle->IsTypedArray()) {
845 THROW_TYPE_ERROR_AND_RETURN(argv->GetThread(), "This is not a TypedArray.", JSTaggedValue::Exception());
846 }
847
848 uint32_t length = JSHandle<JSTypedArray>::Cast(thisHandle)->GetArrayLength();
849
850 JSHandle<JSTaggedValue> sepHandle = GetCallArg(argv, 0);
851 int sep = ',';
852 uint32_t sepLength = 1;
853 JSHandle<EcmaString> sepStringHandle;
854 if (!sepHandle->IsUndefined()) {
855 if (sepHandle->IsString()) {
856 sepStringHandle = JSHandle<EcmaString>::Cast(sepHandle);
857 } else {
858 sepStringHandle = JSTaggedValue::ToString(thread, sepHandle);
859 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
860 }
861 if (EcmaStringAccessor(sepStringHandle).IsUtf8() && EcmaStringAccessor(sepStringHandle).GetLength() == 1) {
862 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
863 sep = EcmaStringAccessor(sepStringHandle).Get(0);
864 } else if (EcmaStringAccessor(sepStringHandle).GetLength() == 0) {
865 sep = BuiltinsTypedArray::SeparatorFlag::MINUS_TWO;
866 sepLength = 0;
867 } else {
868 sep = BuiltinsTypedArray::SeparatorFlag::MINUS_ONE;
869 sepLength = EcmaStringAccessor(sepStringHandle).GetLength();
870 }
871 }
872 if (length == 0) {
873 const GlobalEnvConstants *globalConst = thread->GlobalConstants();
874 return globalConst->GetEmptyString();
875 }
876 uint64_t allocateLength = 0;
877 bool isOneByte = (sep != BuiltinsTypedArray::SeparatorFlag::MINUS_ONE) ||
878 EcmaStringAccessor(sepStringHandle).IsUtf8();
879 CVector<JSHandle<EcmaString>> vec;
880 JSMutableHandle<JSTaggedValue> elementHandle(thread, JSTaggedValue::Undefined());
881 const GlobalEnvConstants *globalConst = thread->GlobalConstants();
882 if (length <= 1) {
883 // sep unused, set isOneByte to default(true)
884 isOneByte = true;
885 }
886 for (uint32_t k = 0; k < length; k++) {
887 JSTaggedValue element = JSTypedArray::GetProperty(thread, thisHandle, k).GetValue().GetTaggedValue();
888 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
889 if (!element.IsUndefinedOrNull() && !element.IsHole()) {
890 if (!element.IsString()) {
891 elementHandle.Update(element);
892 JSHandle<EcmaString> strElement = JSTaggedValue::ToString(thread, elementHandle);
893 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
894 element = strElement.GetTaggedValue();
895 }
896 auto nextStr = EcmaString::Cast(element.GetTaggedObject());
897 JSHandle<EcmaString> nextStrHandle(thread, nextStr);
898 vec.push_back(nextStrHandle);
899 isOneByte = EcmaStringAccessor(nextStr).IsUtf8() ? isOneByte : false;
900 allocateLength += EcmaStringAccessor(nextStr).GetLength();
901 } else {
902 vec.push_back(JSHandle<EcmaString>(globalConst->GetHandledEmptyString()));
903 }
904 }
905 allocateLength += static_cast<uint64_t>(sepLength) * (length - 1);
906 if (allocateLength > EcmaString::MAX_STRING_LENGTH) {
907 THROW_RANGE_ERROR_AND_RETURN(thread, "Invalid string length", JSTaggedValue::Exception());
908 }
909 auto newString =
910 EcmaStringAccessor::CreateLineString(thread->GetEcmaVM(), static_cast<size_t>(allocateLength), isOneByte);
911 int current = 0;
912 DISALLOW_GARBAGE_COLLECTION;
913 for (uint32_t k = 0; k < length; k++) {
914 if (k > 0) {
915 if (sep >= 0) {
916 EcmaStringAccessor(newString).Set(current, static_cast<uint16_t>(sep));
917 } else if (sep != BuiltinsTypedArray::SeparatorFlag::MINUS_TWO) {
918 EcmaStringAccessor::ReadData(
919 newString, *sepStringHandle, current, allocateLength - static_cast<size_t>(current), sepLength);
920 }
921 current += static_cast<int>(sepLength);
922 }
923 JSHandle<EcmaString> nextStr = vec[k];
924 int nextLength = static_cast<int>(EcmaStringAccessor(nextStr).GetLength());
925 EcmaStringAccessor::ReadData(newString, *nextStr, current,
926 allocateLength - static_cast<size_t>(current), nextLength);
927 current += nextLength;
928 }
929 ASSERT_PRINT(
930 isOneByte == EcmaStringAccessor::CanBeCompressed(newString), "isOneByte does not match the real value!");
931 return JSTaggedValue(newString);
932 }
933
934 // 22.2.3.15
Keys(EcmaRuntimeCallInfo * argv)935 JSTaggedValue BuiltinsTypedArray::Keys(EcmaRuntimeCallInfo *argv)
936 {
937 ASSERT(argv);
938 BUILTINS_API_TRACE(argv->GetThread(), TypedArray, Keys);
939 JSThread *thread = argv->GetThread();
940 [[maybe_unused]] EcmaHandleScope handleScope(thread);
941 // 1. Let O be the this value.
942 JSHandle<JSTaggedValue> thisHandle = GetThis(argv);
943 // 2. Let valid be ValidateTypedArray(O).
944 TypedArrayHelper::ValidateTypedArray(thread, thisHandle);
945 // 3. ReturnIfAbrupt(valid).
946 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(argv->GetThread());
947 JSHandle<JSObject> self(thisHandle);
948 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
949 // 4. Return CreateArrayIterator(O, "key").
950 JSHandle<JSArrayIterator> iter(factory->NewJSArrayIterator(self, IterationKind::KEY));
951 return iter.GetTaggedValue();
952 }
953
954 // 22.2.3.16
LastIndexOf(EcmaRuntimeCallInfo * argv)955 JSTaggedValue BuiltinsTypedArray::LastIndexOf(EcmaRuntimeCallInfo *argv)
956 {
957 ASSERT(argv);
958 JSThread *thread = argv->GetThread();
959 BUILTINS_API_TRACE(argv->GetThread(), TypedArray, LastIndexOf);
960 TypedArrayHelper::ValidateTypedArray(thread, GetThis(argv));
961 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
962 return BuiltinsArray::LastIndexOf(argv);
963 }
964
965 // 22.2.3.17
GetLength(EcmaRuntimeCallInfo * argv)966 JSTaggedValue BuiltinsTypedArray::GetLength(EcmaRuntimeCallInfo *argv)
967 {
968 ASSERT(argv);
969 BUILTINS_API_TRACE(argv->GetThread(), TypedArray, GetLength);
970 JSThread *thread = argv->GetThread();
971 [[maybe_unused]] EcmaHandleScope handleScope(thread);
972 // 1. Let O be the this value.
973 JSHandle<JSTaggedValue> thisHandle = GetThis(argv);
974 // 2. If Type(O) is not Object, throw a TypeError exception.
975 if (!thisHandle->IsECMAObject()) {
976 THROW_TYPE_ERROR_AND_RETURN(thread, "This value is not an object.", JSTaggedValue::Exception());
977 }
978 // 3. If O does not have a [[TypedArrayName]] internal slot, throw a TypeError exception.
979 if (!thisHandle->IsTypedArray()) {
980 THROW_TYPE_ERROR_AND_RETURN(thread, "This value does not have a [[TypedArrayName]] internal slot.",
981 JSTaggedValue::Exception());
982 }
983 // 4. Assert: O has [[ViewedArrayBuffer]] and [[ArrayLength]] internal slots.
984 // 5. Let buffer be the value of O’s [[ViewedArrayBuffer]] internal slot.
985 JSTaggedValue buffer = JSHandle<JSTypedArray>::Cast(thisHandle)->GetViewedArrayBufferOrByteArray();
986 // 6. If IsDetachedBuffer(buffer) is true, return 0.
987 if (BuiltinsArrayBuffer::IsDetachedBuffer(buffer)) {
988 return JSTaggedValue(0);
989 }
990 // 7. Let length be the value of O’s [[ArrayLength]] internal slot.
991 uint32_t length = JSHandle<JSTypedArray>(thisHandle)->GetArrayLength();
992 // 8. Return length.
993 return JSTaggedValue(length);
994 }
995
996 // 22.2.3.18 %TypedArray%.prototype.map ( callbackfn [ , thisArg ] )
Map(EcmaRuntimeCallInfo * argv)997 JSTaggedValue BuiltinsTypedArray::Map(EcmaRuntimeCallInfo *argv)
998 {
999 ASSERT(argv);
1000 BUILTINS_API_TRACE(argv->GetThread(), TypedArray, Map);
1001 JSThread *thread = argv->GetThread();
1002 [[maybe_unused]] EcmaHandleScope handleScope(thread);
1003 // 1. Let O be the this value.
1004 JSHandle<JSTaggedValue> thisHandle = GetThis(argv);
1005 // 2. Let valid be ValidateTypedArray(O).
1006 TypedArrayHelper::ValidateTypedArray(thread, thisHandle);
1007 // 3. ReturnIfAbrupt(valid).
1008 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1009
1010 JSHandle<JSTypedArray> thisObj(thisHandle);
1011 // 4. Let len be the value of O’s [[ArrayLength]] internal slot.
1012 uint32_t len = thisObj->GetArrayLength();
1013 // 5. If IsCallable(callbackfn) is false, throw a TypeError exception.
1014 JSHandle<JSTaggedValue> callbackfnHandle = GetCallArg(argv, 0);
1015 if (!callbackfnHandle->IsCallable()) {
1016 THROW_TYPE_ERROR_AND_RETURN(thread, "the callbackfun is not callable.", JSTaggedValue::Exception());
1017 }
1018 // 6. If thisArg was supplied, let T be thisArg; else let T be undefined.
1019 JSHandle<JSTaggedValue> thisArgHandle = GetCallArg(argv, 1);
1020 // es11 5. Let A be ? TypedArraySpeciesCreate(O, « len »).
1021 JSTaggedType args[1] = {JSTaggedValue(len).GetRawData()};
1022 JSHandle<JSObject> newArrObj = TypedArrayHelper::TypedArraySpeciesCreate(thread, thisObj, 1, args); // 1: one arg.
1023 // 11. ReturnIfAbrupt(A).
1024 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1025
1026 // 12. Let k be 0.
1027 // 13. Repeat, while k < len
1028 // a. Let Pk be ToString(k).
1029 // b. Let kValue be Get(O, Pk).
1030 // c. ReturnIfAbrupt(kValue).
1031 // d. Let mappedValue be Call(callbackfn, T, «kValue, k, O»).
1032 // e. ReturnIfAbrupt(mappedValue).
1033 // f. Let status be Set(A, Pk, mappedValue, true ).
1034 // g. ReturnIfAbrupt(status).
1035 // h. Increase k by 1.
1036 JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
1037 JSMutableHandle<JSTaggedValue> mapValue(thread, JSTaggedValue::Undefined());
1038 JSMutableHandle<JSTaggedValue> kValue(thread, JSTaggedValue::Undefined());
1039 const uint32_t argsLength = 3;
1040 JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
1041 for (uint32_t k = 0; k < len; k++) {
1042 key.Update(JSTaggedValue(k));
1043 kValue.Update(ObjectFastOperator::FastGetPropertyByValue(thread, thisHandle.GetTaggedValue(),
1044 key.GetTaggedValue()));
1045 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1046 EcmaRuntimeCallInfo *info =
1047 EcmaInterpreter::NewRuntimeCallInfo(thread, callbackfnHandle, thisArgHandle, undefined, argsLength);
1048 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1049 info->SetCallArg(kValue.GetTaggedValue(), key.GetTaggedValue(), thisHandle.GetTaggedValue());
1050 JSTaggedValue callResult = JSFunction::Call(info);
1051 mapValue.Update(callResult);
1052 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1053 ObjectFastOperator::FastSetPropertyByValue(thread, newArrObj.GetTaggedValue(),
1054 key.GetTaggedValue(), mapValue.GetTaggedValue());
1055 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1056 }
1057
1058 // 14. Return A.
1059 return newArrObj.GetTaggedValue();
1060 }
1061
1062 // 22.2.3.19
Reduce(EcmaRuntimeCallInfo * argv)1063 JSTaggedValue BuiltinsTypedArray::Reduce(EcmaRuntimeCallInfo *argv)
1064 {
1065 ASSERT(argv);
1066 BUILTINS_API_TRACE(argv->GetThread(), TypedArray, Reduce);
1067 JSThread *thread = argv->GetThread();
1068 [[maybe_unused]] EcmaHandleScope handleScope(thread);
1069 JSHandle<JSTaggedValue> thisHandle = GetThis(argv);
1070 if (!thisHandle->IsTypedArray()) {
1071 THROW_TYPE_ERROR_AND_RETURN(thread, "This is not a TypedArray.", JSTaggedValue::Exception());
1072 }
1073 BuiltinsArrayBuffer::IsDetachedBuffer(thread, JSHandle<JSTypedArray>::Cast(thisHandle));
1074 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1075
1076 JSHandle<JSObject> thisObjHandle = JSTaggedValue::ToObject(thread, thisHandle);
1077 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1078 JSHandle<JSTaggedValue> thisObjVal(thisObjHandle);
1079
1080 int64_t len = JSHandle<JSTypedArray>::Cast(thisObjVal)->GetArrayLength();
1081 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1082
1083 return BuiltinsArray::ReduceInner(argv, len);
1084 }
1085
1086 // 22.2.3.20
ReduceRight(EcmaRuntimeCallInfo * argv)1087 JSTaggedValue BuiltinsTypedArray::ReduceRight(EcmaRuntimeCallInfo *argv)
1088 {
1089 ASSERT(argv);
1090 BUILTINS_API_TRACE(argv->GetThread(), TypedArray, ReduceRight);
1091 JSThread *thread = argv->GetThread();
1092 [[maybe_unused]] EcmaHandleScope handleScope(thread);
1093 JSHandle<JSTaggedValue> thisHandle = GetThis(argv);
1094 if (!thisHandle->IsTypedArray()) {
1095 THROW_TYPE_ERROR_AND_RETURN(thread, "This is not a TypedArray.", JSTaggedValue::Exception());
1096 }
1097 BuiltinsArrayBuffer::IsDetachedBuffer(thread, JSHandle<JSTypedArray>::Cast(thisHandle));
1098 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1099
1100 JSHandle<JSObject> thisObjHandle = JSTaggedValue::ToObject(thread, thisHandle);
1101 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1102 JSHandle<JSTaggedValue> thisObjVal(thisObjHandle);
1103
1104 int64_t len = JSHandle<JSTypedArray>::Cast(thisObjVal)->GetArrayLength();
1105 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1106
1107 return BuiltinsArray::ReduceRightInner(argv, len);
1108 }
1109
1110 // 22.2.3.21
Reverse(EcmaRuntimeCallInfo * argv)1111 JSTaggedValue BuiltinsTypedArray::Reverse(EcmaRuntimeCallInfo *argv)
1112 {
1113 ASSERT(argv);
1114 BUILTINS_API_TRACE(argv->GetThread(), TypedArray, Reverse);
1115 JSThread *thread = argv->GetThread();
1116 [[maybe_unused]] EcmaHandleScope handleScope(thread);
1117
1118 JSHandle<JSTaggedValue> thisHandle = GetThis(argv);
1119 TypedArrayHelper::ValidateTypedArray(thread, thisHandle);
1120 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1121
1122 // 1. Let O be ToObject(this value).
1123 JSHandle<JSObject> thisObjHandle = JSTaggedValue::ToObject(thread, thisHandle);
1124 // 2. ReturnIfAbrupt(O).
1125 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1126 JSHandle<JSTaggedValue> thisObjVal(thisObjHandle);
1127
1128 // 3. Let len be O.[[ArrayLength]]
1129 int64_t len = JSHandle<JSTypedArray>::Cast(thisHandle)->GetArrayLength();
1130
1131 // 4. ReturnIfAbrupt(len).
1132 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1133
1134 // 5. Let middle be floor(len/2).
1135 int64_t middle = std::floor(len / 2);
1136
1137 // 6. Let lower be 0.
1138 int64_t lower = 0;
1139
1140 // 7. Repeat, while lower ≠ middle,
1141 // a. Let upper be len - lower - 1.
1142 // b. Let upperP be ! ToString((upper)).
1143 // c. Let lowerP be ! ToString((lower)).
1144 // d. Let lowerValue be ! Get(O, lowerP).
1145 // e. Let upperValue be ! Get(O, upperP).
1146 // f. Perform ! Set(O, lowerP, upperValue, true).
1147 // g. Perform ! Set(O, upperP, lowerValue, true).
1148 // h. Set lower to lower + 1.
1149 JSMutableHandle<JSTaggedValue> lowerP(thread, JSTaggedValue::Undefined());
1150 JSMutableHandle<JSTaggedValue> upperP(thread, JSTaggedValue::Undefined());
1151 JSHandle<JSTaggedValue> lowerValueHandle(thread, JSTaggedValue::Undefined());
1152 JSHandle<JSTaggedValue> upperValueHandle(thread, JSTaggedValue::Undefined());
1153 while (lower != middle) {
1154 int64_t upper = len - lower - 1;
1155 lowerP.Update(JSTaggedValue(lower));
1156 upperP.Update(JSTaggedValue(upper));
1157 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1158 lowerValueHandle = JSArray::FastGetPropertyByValue(thread, thisObjVal, lowerP);
1159 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1160 upperValueHandle = JSArray::FastGetPropertyByValue(thread, thisObjVal, upperP);
1161 JSArray::FastSetPropertyByValue(thread, thisObjVal, lowerP, upperValueHandle);
1162 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1163 JSArray::FastSetPropertyByValue(thread, thisObjVal, upperP, lowerValueHandle);
1164 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1165 lower++;
1166 }
1167
1168 // 8. Return O .
1169 return thisObjHandle.GetTaggedValue();
1170 }
1171
1172 // 22.2.3.22 %TypedArray%.prototype.set ( overloaded [ , offset ])
Set(EcmaRuntimeCallInfo * argv)1173 JSTaggedValue BuiltinsTypedArray::Set(EcmaRuntimeCallInfo *argv)
1174 {
1175 ASSERT(argv);
1176 BUILTINS_API_TRACE(argv->GetThread(), TypedArray, Set);
1177 JSThread *thread = argv->GetThread();
1178 [[maybe_unused]] EcmaHandleScope handleScope(thread);
1179 // 1. Assert: array is any ECMAScript language value other than an Object with a [[TypedArrayName]] internal slot.
1180 // If it is such an Object, the definition in 22.2.3.22.2 applies.
1181 // 2. Let target be the this value.
1182 JSHandle<JSTaggedValue> target = GetThis(argv);
1183 // 3. If Type(target) is not Object, throw a TypeError exception.
1184 if (!target->IsECMAObject()) {
1185 THROW_TYPE_ERROR_AND_RETURN(thread, "This value is not an object.", JSTaggedValue::Exception());
1186 }
1187 JSHandle<JSTypedArray> targetObj(target);
1188 // 4. If target does not have a [[TypedArrayName]] internal slot, throw a TypeError exception.
1189 if (!target->IsTypedArray()) {
1190 THROW_TYPE_ERROR_AND_RETURN(thread, "This value does not have a [[TypedArrayName]] internal slot.",
1191 JSTaggedValue::Exception());
1192 }
1193
1194 // 5. Assert: target has a [[ViewedArrayBuffer]] internal slot.
1195 // 6. Let targetOffset be ToInteger (offset).
1196 const JSHandle<JSTaggedValue> srcOffset = GetCallArg(argv, 1);
1197 uint64_t targetOffset = 0;
1198 if (srcOffset->IsInt()) {
1199 if (srcOffset->GetInt() < 0) {
1200 THROW_RANGE_ERROR_AND_RETURN(thread, "The targetOffset of This value is less than 0.",
1201 JSTaggedValue::Exception());
1202 }
1203 targetOffset = static_cast<uint64_t>(srcOffset->GetInt());
1204 } else {
1205 JSTaggedNumber tTargetOffset = JSTaggedValue::ToInteger(thread, srcOffset);
1206 // 7. ReturnIfAbrupt(targetOffset).
1207 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1208 double rawTargetOffset = tTargetOffset.GetNumber();
1209 // 8. If targetOffset < 0, throw a RangeError exception.
1210 if (rawTargetOffset < 0) {
1211 THROW_RANGE_ERROR_AND_RETURN(thread, "The targetOffset of This value is less than 0.",
1212 JSTaggedValue::Exception());
1213 } else if (rawTargetOffset == base::POSITIVE_INFINITY) {
1214 THROW_RANGE_ERROR_AND_RETURN(thread, "The targetOffset is infinty, which is greater than targetLength.",
1215 JSTaggedValue::Exception());
1216 } else {
1217 targetOffset = static_cast<uint64_t>(rawTargetOffset);
1218 }
1219 }
1220 // 9. Let targetBuffer be the value of target’s [[ViewedArrayBuffer]] internal slot.
1221 JSHandle<JSTaggedValue> targetBuffer(thread, targetObj->GetViewedArrayBufferOrByteArray());
1222 // 10. If IsDetachedBuffer(targetBuffer) is true, throw a TypeError exception.
1223 if (BuiltinsArrayBuffer::IsDetachedBuffer(targetBuffer.GetTaggedValue())) {
1224 THROW_TYPE_ERROR_AND_RETURN(thread, "The targetBuffer of This value is detached buffer.",
1225 JSTaggedValue::Exception());
1226 }
1227 // 11. Let targetLength be the value of target’s [[ArrayLength]] internal slot.
1228 // 12. Let targetName be the String value of target’s [[TypedArrayName]] internal slot.
1229 // 13. Let targetElementSize be the Number value of the Element Size value specified in Table 49 for targetName.
1230 // 14. Let targetType be the String value of the Element Type value in Table 49 for targetName.
1231 // 15. Let targetByteOffset be the value of target’s [[ByteOffset]] internal slot.
1232 uint32_t targetLength = targetObj->GetArrayLength();
1233 DataViewType targetType = TypedArrayHelper::GetType(targetObj);
1234 uint32_t targetElementSize = TypedArrayHelper::GetSizeFromType(targetType);
1235 uint32_t targetByteOffset = targetObj->GetByteOffset();
1236
1237 JSHandle<JSTaggedValue> argArray = GetCallArg(argv, 0);
1238
1239 // 22.2.3.22.1 %TypedArray%.prototype.set (array [ , offset ] )
1240 if (!argArray->IsTypedArray()) {
1241 if (argArray->IsStableJSArray(thread)) {
1242 uint32_t length = JSHandle<JSArray>::Cast(argArray)->GetArrayLength();
1243 JSHandle<JSObject> argObj(argArray);
1244 uint32_t elemLength = ElementAccessor::GetElementsLength(argObj);
1245 // Load On Demand check
1246 if (elemLength >= length) {
1247 return JSStableArray::FastCopyFromArrayToTypedArray(thread, targetObj, targetType,
1248 targetOffset, length, argObj);
1249 }
1250 }
1251 // 16. Let src be ToObject(array).
1252 JSHandle<JSObject> src = JSTaggedValue::ToObject(thread, argArray);
1253 // 17. ReturnIfAbrupt(src).
1254 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1255 // 18. Let srcLength be ToLength(Get(src, "length")).
1256 JSHandle<JSTaggedValue> lengthKey = thread->GlobalConstants()->GetHandledLengthString();
1257 JSHandle<JSTaggedValue> lenResult(thread,
1258 ObjectFastOperator::FastGetPropertyByValue(thread,
1259 JSHandle<JSTaggedValue>::Cast(src).GetTaggedValue(),
1260 lengthKey.GetTaggedValue()));
1261 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1262 JSTaggedNumber tSrcLen = JSTaggedValue::ToLength(thread, lenResult);
1263 // 19. ReturnIfAbrupt(srcLength).
1264 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1265 uint64_t srcLen = static_cast<uint64_t>(tSrcLen.GetNumber());
1266 // 20. If srcLength + targetOffset > targetLength, throw a RangeError exception.
1267 if (srcLen + targetOffset > targetLength) {
1268 THROW_RANGE_ERROR_AND_RETURN(thread, "The sum of srcLength and targetOffset is greater than targetLength.",
1269 JSTaggedValue::Exception());
1270 }
1271 // 21. Let targetByteIndex be targetOffset × targetElementSize + targetByteOffset.
1272 ASSERT((targetOffset * static_cast<uint64_t>(targetElementSize) +
1273 static_cast<uint64_t>(targetByteOffset)) <= static_cast<uint64_t>(UINT32_MAX));
1274 uint32_t targetByteIndex = static_cast<uint32_t>(targetOffset * targetElementSize + targetByteOffset);
1275 // 22. Let k be 0.
1276 // 23. Let limit be targetByteIndex + targetElementSize × srcLength.
1277 uint32_t k = 0;
1278 ASSERT((static_cast<uint64_t>(targetElementSize) * srcLen +
1279 static_cast<uint64_t>(targetByteIndex)) <= static_cast<uint64_t>(UINT32_MAX));
1280 uint32_t limit = targetByteIndex + targetElementSize * srcLen;
1281 // 24. Repeat, while targetByteIndex < limit
1282 // a. Let Pk be ToString(k).
1283 // b. If target.[[ContentType]] is BigInt, set value to ? ToBigInt(value).
1284 // c. Otherwise, set value to ? ToNumber(value).
1285 // d. If IsDetachedBuffer(targetBuffer) is true, throw a TypeError exception.
1286 // e. Perform SetValueInBuffer(targetBuffer, targetByteIndex, targetType, kNumber).
1287 // f. Set k to k + 1.
1288 // g. Set targetByteIndex to targetByteIndex + targetElementSize.
1289 JSMutableHandle<JSTaggedValue> tKey(thread, JSTaggedValue::Hole());
1290 JSMutableHandle<JSTaggedValue> kValue(thread, JSTaggedValue::Hole());
1291 JSMutableHandle<JSTaggedValue> kNumberHandle(thread, JSTaggedValue::Hole());
1292 ContentType contentType = JSHandle<JSTypedArray>::Cast(target)->GetContentType();
1293 while (targetByteIndex < limit) {
1294 tKey.Update(JSTaggedValue(k));
1295 JSHandle<JSTaggedValue> kKey(JSTaggedValue::ToString(thread, tKey));
1296 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1297 kValue.Update(ObjectFastOperator::FastGetPropertyByValue(
1298 thread, JSHandle<JSTaggedValue>::Cast(src).GetTaggedValue(), kKey.GetTaggedValue()));
1299 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1300 if (BuiltinsArrayBuffer::IsDetachedBuffer(targetBuffer.GetTaggedValue())) {
1301 THROW_TYPE_ERROR_AND_RETURN(thread, "The targetBuffer of This value is detached buffer.",
1302 JSTaggedValue::Exception());
1303 }
1304 if (contentType == ContentType::BigInt) {
1305 kNumberHandle.Update(JSTaggedValue::ToBigInt(thread, kValue));
1306 } else {
1307 kNumberHandle.Update(JSTaggedValue::ToNumber(thread, kValue));
1308 }
1309 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1310 BuiltinsArrayBuffer::SetValueInBuffer(thread, targetBuffer.GetTaggedValue(), targetByteIndex,
1311 targetType, kNumberHandle, true);
1312 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1313 k++;
1314 targetByteIndex = targetByteIndex + targetElementSize;
1315 }
1316 // 25. Return undefined.
1317 return JSTaggedValue::Undefined();
1318 }
1319
1320 // 22.2.3.22.2 %TypedArray%.prototype.set(typedArray [, offset ] )
1321 JSHandle<JSTypedArray> typedArray(argArray);
1322 // 12. Let srcBuffer be the value of typedArray’s [[ViewedArrayBuffer]] internal slot.
1323 // 13. If IsDetachedBuffer(srcBuffer) is true, throw a TypeError exception.
1324 JSTaggedValue srcBuffer = typedArray->GetViewedArrayBufferOrByteArray();
1325 JSHandle<JSTaggedValue> srcBufferHandle(thread, srcBuffer);
1326 if (BuiltinsArrayBuffer::IsDetachedBuffer(srcBuffer)) {
1327 THROW_TYPE_ERROR_AND_RETURN(thread, "The ArrayBuffer of typedArray is detached buffer.",
1328 JSTaggedValue::Exception());
1329 }
1330
1331 ContentType objContentType = JSHandle<JSTypedArray>::Cast(target)->GetContentType();
1332 ContentType argArrayContentType = JSHandle<JSTypedArray>::Cast(argArray)->GetContentType();
1333 if (argArrayContentType != objContentType) {
1334 THROW_TYPE_ERROR_AND_RETURN(thread,
1335 "argArrayContentType is not equal objContentType.",
1336 JSTaggedValue::Exception());
1337 }
1338 // 18. Let srcName be the String value of typedArray’s [[TypedArrayName]] internal slot.
1339 // 19. Let srcType be the String value of the Element Type value in Table 49 for srcName .
1340 // 20. Let srcElementSize be the Number value of the Element Size value specified in Table 49 for srcName.
1341 // 21. Let srcLength be the value of typedArray’s [[ArrayLength]] internal slot.
1342 // 22. Let srcByteOffset be the value of typedArray’s [[ByteOffset]] internal slot.
1343 JSHandle<JSTaggedValue> srcName(thread, typedArray->GetTypedArrayName());
1344 DataViewType srcType = JSTypedArray::GetTypeFromName(thread, srcName);
1345 uint32_t srcElementSize = TypedArrayHelper::GetSizeFromType(srcType);
1346 uint32_t srcLength = typedArray->GetArrayLength();
1347 uint32_t srcByteOffset = typedArray->GetByteOffset();
1348 // 23. If srcLength + targetOffset > targetLength, throw a RangeError exception.
1349 if (srcLength + targetOffset > targetLength) {
1350 THROW_RANGE_ERROR_AND_RETURN(thread, "The sum of srcLength and targetOffset is greater than targetLength.",
1351 JSTaggedValue::Exception());
1352 }
1353 // 24. If SameValue(srcBuffer, targetBuffer) is true, then
1354 // a. Let srcBuffer be CloneArrayBuffer(targetBuffer, srcByteOffset, %ArrayBuffer%).
1355 // b. NOTE: %ArrayBuffer% is used to clone targetBuffer because is it known to not have any observable
1356 // side-effects.
1357 // c. ReturnIfAbrupt(srcBuffer).
1358 // d. Let srcByteIndex be 0.
1359 // 25. Else, let srcByteIndex be srcByteOffset.
1360 uint32_t srcByteIndex = 0;
1361 if (JSTaggedValue::SameValue(srcBufferHandle.GetTaggedValue(), targetBuffer.GetTaggedValue())) {
1362 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
1363 srcBuffer =
1364 BuiltinsArrayBuffer::CloneArrayBuffer(thread, targetBuffer, srcByteOffset, env->GetArrayBufferFunction());
1365 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1366 srcBufferHandle = JSHandle<JSTaggedValue>(thread, srcBuffer);
1367 srcByteIndex = 0;
1368 } else {
1369 srcByteIndex = srcByteOffset;
1370 }
1371 // 26. Let targetByteIndex be targetOffset × targetElementSize + targetByteOffset.
1372 ASSERT((targetOffset * static_cast<uint64_t>(targetElementSize) +
1373 static_cast<uint64_t>(targetByteOffset)) <= static_cast<uint64_t>(UINT32_MAX));
1374 uint32_t targetByteIndex = static_cast<uint32_t>(targetOffset) * targetElementSize + targetByteOffset;
1375 // 27. Let limit be targetByteIndex + targetElementSize × srcLength.
1376 ASSERT((static_cast<uint64_t>(targetElementSize) * static_cast<uint64_t>(srcLength) +
1377 static_cast<uint64_t>(targetByteIndex)) <= static_cast<uint64_t>(UINT32_MAX));
1378 uint32_t limit = targetByteIndex + targetElementSize * srcLength;
1379 uint32_t count = (limit - targetByteIndex) > 0 ? (limit - targetByteIndex) : 0;
1380 // 28. If SameValue(srcType, targetType) is false, then
1381 // a. Repeat, while targetByteIndex < limit
1382 // i. Let value be GetValueFromBuffer(srcBuffer, srcByteIndex, srcType).
1383 // ii. Perform SetValueInBuffer (targetBuffer, targetByteIndex, targetType, value).
1384 // iii. Set srcByteIndex to srcByteIndex + srcElementSize.
1385 // iv. Set targetByteIndex to targetByteIndex + targetElementSize.
1386 JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
1387 if (srcType != targetType) {
1388 while (targetByteIndex < limit) {
1389 JSTaggedValue taggedData =
1390 BuiltinsArrayBuffer::GetValueFromBuffer(thread, srcBufferHandle.GetTaggedValue(),
1391 srcByteIndex, srcType, true);
1392 value.Update(taggedData);
1393 BuiltinsArrayBuffer::SetValueInBuffer(thread, targetBuffer.GetTaggedValue(), targetByteIndex,
1394 targetType, value, true);
1395 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1396 srcByteIndex = srcByteIndex + srcElementSize;
1397 targetByteIndex = targetByteIndex + targetElementSize;
1398 }
1399 } else if (count > 0) {
1400 // 29. Else,
1401 // a. NOTE: If srcType and targetType are the same the transfer must be performed in a manner that preserves
1402 // the bit-level encoding of the source data.
1403 // b. Repeat, while targetByteIndex < limit
1404 // i. Let value be GetValueFromBuffer(srcBuffer, srcByteIndex, "Uint8").
1405 // ii. Perform SetValueInBuffer (targetBuffer, targetByteIndex, "Uint8", value).
1406 // iii. Set srcByteIndex to srcByteIndex + 1.
1407 // iv. Set targetByteIndex to targetByteIndex + 1.
1408 void *srcBuf = BuiltinsArrayBuffer::GetDataPointFromBuffer(srcBufferHandle.GetTaggedValue(), srcByteIndex);
1409 void *targetBuf = BuiltinsArrayBuffer::GetDataPointFromBuffer(targetBuffer.GetTaggedValue(), targetByteIndex);
1410 if (memcpy_s(targetBuf, srcLength * srcElementSize, srcBuf, srcLength * srcElementSize) != EOK) {
1411 LOG_FULL(FATAL) << "memcpy_s failed";
1412 UNREACHABLE();
1413 }
1414 }
1415 // 30. Return undefined.
1416 return JSTaggedValue::Undefined();
1417 } // namespace panda::ecmascript::builtins
1418
1419 // 22.2.3.23 %TypedArray%.prototype.slice ( start, end )
Slice(EcmaRuntimeCallInfo * argv)1420 JSTaggedValue BuiltinsTypedArray::Slice(EcmaRuntimeCallInfo *argv)
1421 {
1422 ASSERT(argv);
1423 BUILTINS_API_TRACE(argv->GetThread(), TypedArray, Slice);
1424 JSThread *thread = argv->GetThread();
1425 [[maybe_unused]] EcmaHandleScope handleScope(thread);
1426 // 1. Let O be the this value.
1427 JSHandle<JSTaggedValue> thisHandle = GetThis(argv);
1428 // 2. Let valid be ValidateTypedArray(O).
1429 TypedArrayHelper::ValidateTypedArray(thread, thisHandle);
1430 // 3. ReturnIfAbrupt(valid).
1431 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1432
1433 JSHandle<JSTypedArray> thisObj(thisHandle);
1434 // 4. Let len be the value of O’s [[ArrayLength]] internal slot.
1435 uint32_t len = thisObj->GetArrayLength();
1436
1437 // 5. Let relativeStart be ToInteger(start).
1438 JSTaggedNumber tRelativeStart = JSTaggedValue::ToInteger(thread, GetCallArg(argv, 0));
1439 // 6. ReturnIfAbrupt(relativeStart).
1440 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1441 double relativeStart = tRelativeStart.GetNumber();
1442 // 7. If relativeStart < 0, let k be max((len + relativeStart),0); else let k be min(relativeStart, len).
1443
1444 uint32_t k = relativeStart < 0 ?
1445 std::max((static_cast<double>(len) + relativeStart), 0.0) :
1446 std::min(relativeStart, static_cast<double>(len));
1447 // 8. If end is undefined, let relativeEnd be len; else let relativeEnd be ToInteger(end).
1448 double relativeEnd = len;
1449 JSHandle<JSTaggedValue> end = GetCallArg(argv, 1);
1450 if (!end->IsUndefined()) {
1451 JSTaggedNumber tRelativeEnd = JSTaggedValue::ToInteger(thread, end);
1452 // 9. ReturnIfAbrupt(relativeEnd).
1453 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1454 relativeEnd = tRelativeEnd.GetNumber();
1455 }
1456
1457 // 10. If relativeEnd < 0, let final be max((len + relativeEnd),0); else let final be min(relativeEnd, len).
1458
1459 uint32_t final = relativeEnd < 0 ?
1460 std::max((static_cast<double>(len) + relativeEnd), 0.0) :
1461 std::min(relativeEnd, static_cast<double>(len));
1462 // 11. Let count be max(final – k, 0).
1463 uint32_t count = final > k ? (final - k) : 0;
1464 // es11 9. Let A be ? TypedArraySpeciesCreate(O, « count »).
1465 JSTaggedType args[1] = {JSTaggedValue(count).GetRawData()};
1466 JSHandle<JSObject> newArrObj = TypedArrayHelper::TypedArraySpeciesCreate(thread, thisObj, 1, args);
1467 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1468 // 17. Let srcName be the String value of O’s [[TypedArrayName]] internal slot.
1469 // 18. Let srcType be the String value of the Element Type value in Table 49 for srcName.
1470 JSHandle<JSTaggedValue> srcName(thread, thisObj->GetTypedArrayName());
1471 DataViewType srcType = JSTypedArray::GetTypeFromName(thread, srcName);
1472 // 19. Let targetName be the String value of A’s [[TypedArrayName]] internal slot.
1473 // 20. Let targetType be the String value of the Element Type value in Table 49 for targetName.
1474 JSHandle<JSTaggedValue> targetName(thread, JSTypedArray::Cast(*newArrObj)->GetTypedArrayName());
1475 DataViewType targetType = JSTypedArray::GetTypeFromName(thread, targetName);
1476 // 21. If SameValue(srcType, targetType) is false, then
1477 // a. Let n be 0.
1478 // b. Repeat, while k < final
1479 // i. Let Pk be ToString(k).
1480 // ii. Let kValue be Get(O, Pk).
1481 // iii. ReturnIfAbrupt(kValue).
1482 // iv. Let status be Set(A, ToString(n), kValue, true ).
1483 // v. ReturnIfAbrupt(status).
1484 // vi. Increase k by 1.
1485 // vii. Increase n by 1.
1486 JSMutableHandle<JSTaggedValue> tKey(thread, JSTaggedValue::Undefined());
1487 JSMutableHandle<JSTaggedValue> kValue(thread, JSTaggedValue::Undefined());
1488 JSMutableHandle<JSTaggedValue> ntKey(thread, JSTaggedValue::Undefined());
1489 if (srcType != targetType) {
1490 uint32_t n = 0;
1491 while (k < final) {
1492 tKey.Update(JSTaggedValue(k));
1493 kValue.Update(ObjectFastOperator::FastGetPropertyByValue(thread, thisHandle.GetTaggedValue(),
1494 tKey.GetTaggedValue()));
1495 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1496 ntKey.Update(JSTaggedValue(n));
1497 ObjectFastOperator::FastSetPropertyByValue(thread, newArrObj.GetTaggedValue(),
1498 ntKey.GetTaggedValue(), kValue.GetTaggedValue());
1499 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1500 n++;
1501 k++;
1502 }
1503 } else if (count > 0) {
1504 // 22. Else if count > 0,
1505 // a. Let srcBuffer be the value of O’s [[ViewedArrayBuffer]] internal slot.
1506 // b. If IsDetachedBuffer(srcBuffer) is true, throw a TypeError exception.
1507 JSTaggedValue srcBuffer = thisObj->GetViewedArrayBufferOrByteArray();
1508 if (!srcBuffer.IsSendableArrayBuffer() && BuiltinsArrayBuffer::IsDetachedBuffer(srcBuffer)) {
1509 THROW_TYPE_ERROR_AND_RETURN(thread, "The ArrayBuffer of this value is detached buffer.",
1510 JSTaggedValue::Exception());
1511 }
1512 if (srcBuffer.IsSendableArrayBuffer() && BuiltinsSendableArrayBuffer::IsDetachedBuffer(srcBuffer)) {
1513 THROW_TYPE_ERROR_AND_RETURN(thread, "The SendableArrayBuffer of this value is detached sendable buffer.",
1514 JSTaggedValue::Exception());
1515 }
1516 // c. Let targetBuffer be the value of A’s [[ViewedArrayBuffer]] internal slot.
1517 JSTaggedValue targetBuffer = JSTypedArray::Cast(*newArrObj)->GetViewedArrayBufferOrByteArray();
1518 // d. Let elementSize be the Number value of the Element Size value specified in Table 49 for srcType.
1519 uint32_t elementSize = TypedArrayHelper::GetSizeFromType(srcType);
1520 // e. NOTE: If srcType and targetType are the same the transfer must be performed in a manner that
1521 // preserves the bit-level encoding of the source data.
1522 // f. Let srcByteOffset be the value of O’s[[ByteOffset]] internal slot.
1523 uint32_t srcByteOffset = thisObj->GetByteOffset();
1524 // h. Let srcByteIndex be (k × elementSize) + srcByteOffset.
1525 uint32_t srcByteIndex = k * elementSize + srcByteOffset;
1526 // g. Let targetByteIndex be A.[[ByteOffset]].
1527 uint32_t targetByteIndex = JSTypedArray::Cast(*newArrObj)->GetByteOffset();
1528 // i. Repeat, while targetByteIndex < count × elementSize
1529 // i. Let value be GetValueFromBuffer(srcBuffer, srcByteIndex, "Uint8").
1530 // ii. Perform SetValueInBuffer (targetBuffer, targetByteIndex, "Uint8", value).
1531 // iii. Increase srcByteIndex by 1.
1532 // iv. Increase targetByteIndex by 1.
1533 uint8_t *srcBuf = (uint8_t *)BuiltinsArrayBuffer::GetDataPointFromBuffer(srcBuffer, srcByteIndex);
1534 uint8_t *targetBuf = (uint8_t *)BuiltinsArrayBuffer::GetDataPointFromBuffer(targetBuffer, targetByteIndex);
1535 if (srcBuffer != targetBuffer && memmove_s(
1536 targetBuf, elementSize * count, srcBuf, elementSize * count) != EOK) {
1537 LOG_FULL(FATAL) << "memcpy_s failed";
1538 UNREACHABLE();
1539 }
1540 while (srcBuffer == targetBuffer && count > 0) {
1541 count--;
1542 if (memcpy_s(targetBuf, elementSize, srcBuf, elementSize) != EOK) {
1543 LOG_FULL(FATAL) << "memcpy_s failed";
1544 UNREACHABLE();
1545 }
1546 srcBuf += elementSize;
1547 targetBuf += elementSize;
1548 }
1549 }
1550 // 23. Return A.
1551 return newArrObj.GetTaggedValue();
1552 }
1553
1554 // 22.2.3.24
Some(EcmaRuntimeCallInfo * argv)1555 JSTaggedValue BuiltinsTypedArray::Some(EcmaRuntimeCallInfo *argv)
1556 {
1557 ASSERT(argv);
1558 JSThread *thread = argv->GetThread();
1559 BUILTINS_API_TRACE(thread, TypedArray, Some);
1560 JSHandle<JSTaggedValue> thisHandle = GetThis(argv);
1561 // 2. Let valid be ValidateTypedArray(O).
1562 TypedArrayHelper::ValidateTypedArray(thread, thisHandle);
1563 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1564
1565 // 1. Let O be ToObject(this value).
1566 JSHandle<JSObject> thisObjHandle = JSTaggedValue::ToObject(thread, thisHandle);
1567 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1568 JSHandle<JSTaggedValue> thisObjVal(thisObjHandle);
1569
1570 // 3. Let len be ToLength(Get(O, "length")).
1571 int64_t len = JSHandle<JSTypedArray>::Cast(thisObjVal)->GetArrayLength();
1572 return TypedArrayHelper::someCommon(argv, thisObjVal, len);
1573 }
1574
1575 // 22.2.3.25
Sort(EcmaRuntimeCallInfo * argv)1576 JSTaggedValue BuiltinsTypedArray::Sort(EcmaRuntimeCallInfo *argv)
1577 {
1578 ASSERT(argv);
1579 BUILTINS_API_TRACE(argv->GetThread(), TypedArray, Sort);
1580 JSThread *thread = argv->GetThread();
1581 [[maybe_unused]] EcmaHandleScope handleScope(thread);
1582
1583 // 1. Let obj be ToObject(this value).
1584 JSHandle<JSTaggedValue> thisHandle = GetThis(argv);
1585 if (!thisHandle->IsTypedArray()) {
1586 THROW_TYPE_ERROR_AND_RETURN(argv->GetThread(), "This is not a TypedArray.", JSTaggedValue::Exception());
1587 }
1588
1589 JSHandle<JSObject> thisObjHandle = JSTaggedValue::ToObject(thread, thisHandle);
1590 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1591 JSHandle<JSTaggedValue> thisObjVal(thisObjHandle);
1592
1593 JSHandle<JSTaggedValue> buffer;
1594 buffer = JSHandle<JSTaggedValue>(thread, TypedArrayHelper::ValidateTypedArray(thread, thisHandle));
1595 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1596 uint32_t len = JSHandle<JSTypedArray>::Cast(thisObjHandle)->GetArrayLength();
1597
1598 JSHandle<JSTaggedValue> callbackFnHandle = GetCallArg(argv, 0);
1599 if (!callbackFnHandle->IsUndefined() && !callbackFnHandle->IsCallable()) {
1600 THROW_TYPE_ERROR_AND_RETURN(thread, "Callable is false", JSTaggedValue::Exception());
1601 }
1602 JSMutableHandle<JSTaggedValue> presentValue(thread, JSTaggedValue::Undefined());
1603 JSMutableHandle<JSTaggedValue> middleValue(thread, JSTaggedValue::Undefined());
1604 JSMutableHandle<JSTaggedValue> previousValue(thread, JSTaggedValue::Undefined());
1605 JSMutableHandle<JSTaggedValue> key1(thread, JSTaggedValue::Undefined());
1606 JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
1607 JSMutableHandle<JSTaggedValue> key2(thread, JSTaggedValue::Undefined());
1608 for (uint32_t i = 1; i < len; i++) {
1609 uint32_t beginIndex = 0;
1610 uint32_t endIndex = i;
1611 key.Update(JSTaggedValue(i));
1612 presentValue.Update(ObjectFastOperator::FastGetPropertyByValue(thread, thisObjHandle.GetTaggedValue(),
1613 key.GetTaggedValue()));
1614 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1615 while (beginIndex < endIndex) {
1616 uint32_t middleIndex = beginIndex + (endIndex - beginIndex) / 2; // 2 : half
1617 key1.Update(JSTaggedValue(middleIndex));
1618 middleValue.Update(ObjectFastOperator::FastGetPropertyByValue(thread, thisObjHandle.GetTaggedValue(),
1619 key1.GetTaggedValue()));
1620 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1621 int32_t compareResult = TypedArrayHelper::SortCompare(thread, callbackFnHandle, buffer,
1622 middleValue, presentValue);
1623 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1624 compareResult > 0 ? (endIndex = middleIndex) : (beginIndex = middleIndex + 1);
1625 }
1626
1627 if (endIndex < i) {
1628 for (uint32_t j = i; j > endIndex; j--) {
1629 key2.Update(JSTaggedValue(j - 1));
1630 previousValue.Update(
1631 ObjectFastOperator::FastGetPropertyByValue(thread, thisObjHandle.GetTaggedValue(),
1632 key2.GetTaggedValue()));
1633 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1634 ObjectFastOperator::FastSetPropertyByIndex(thread, thisObjHandle.GetTaggedValue(), j,
1635 previousValue.GetTaggedValue());
1636 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1637 }
1638 ObjectFastOperator::FastSetPropertyByIndex(thread, thisObjHandle.GetTaggedValue(), endIndex,
1639 presentValue.GetTaggedValue());
1640 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1641 }
1642 }
1643 return thisObjHandle.GetTaggedValue();
1644 }
1645
1646 // 22.2.3.26 %TypedArray%.prototype.subarray( [ begin [ , end ] ] )
Subarray(EcmaRuntimeCallInfo * argv)1647 JSTaggedValue BuiltinsTypedArray::Subarray(EcmaRuntimeCallInfo *argv)
1648 {
1649 ASSERT(argv);
1650 BUILTINS_API_TRACE(argv->GetThread(), TypedArray, Subarray);
1651 JSThread *thread = argv->GetThread();
1652 [[maybe_unused]] EcmaHandleScope handleScope(thread);
1653 // 1. Let O be the this value.
1654 JSHandle<JSTaggedValue> thisHandle = GetThis(argv);
1655 // 2. If Type(O) is not Object, throw a TypeError exception.
1656 if (!thisHandle->IsECMAObject()) {
1657 THROW_TYPE_ERROR_AND_RETURN(thread, "This value is not an object.", JSTaggedValue::Exception());
1658 }
1659 JSHandle<JSTypedArray> thisObj(thisHandle);
1660 // 3. If O does not have a [[TypedArrayName]] internal slot, throw a TypeError exception.
1661 if (!thisHandle->IsTypedArray()) {
1662 THROW_TYPE_ERROR_AND_RETURN(thread, "This value does not have a [[TypedArrayName]] internal slot.",
1663 JSTaggedValue::Exception());
1664 }
1665 // 4. Assert: O has a [[ViewedArrayBuffer]] internal slot.
1666 // 6. Let srcLength be the value of O’s [[ArrayLength]] internal slot.
1667 uint32_t srcLength = thisObj->GetArrayLength();
1668 // 7. Let relativeBegin be ToInteger(begin).
1669 JSTaggedNumber tRelativeBegin = JSTaggedValue::ToInteger(thread, GetCallArg(argv, 0));
1670 // 8. ReturnIfAbrupt(relativeBegin).
1671 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1672 double relativeBegin = tRelativeBegin.GetNumber();
1673
1674 uint32_t beginIndex = 0;
1675 // 9. If relativeBegin < 0, let beginIndex be max((srcLength + relativeBegin), 0); else let beginIndex be
1676 // min(relativeBegin, srcLength).
1677 if (relativeBegin < 0) {
1678 double tempBeginIndex = relativeBegin + static_cast<double>(srcLength);
1679 beginIndex = tempBeginIndex > 0 ? static_cast<uint32_t>(tempBeginIndex) : 0;
1680 } else {
1681 beginIndex = relativeBegin < static_cast<double>(srcLength) ?
1682 static_cast<uint32_t>(relativeBegin) : srcLength;
1683 }
1684
1685 // 10. If end is undefined, let relativeEnd be srcLength; else, let relativeEnd be ToInteger(end).
1686 double relativeEnd = srcLength;
1687 JSHandle<JSTaggedValue> end = GetCallArg(argv, 1);
1688 if (!end->IsUndefined()) {
1689 JSTaggedNumber tRelativeEnd = JSTaggedValue::ToInteger(thread, end);
1690 // 11. ReturnIfAbrupt(relativeEnd).
1691 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1692 relativeEnd = tRelativeEnd.GetNumber();
1693 }
1694 // 12. If relativeEnd < 0, let endIndex be max((srcLength + relativeEnd), 0); else let endIndex be
1695 // min(relativeEnd, srcLength).
1696 uint32_t endIndex;
1697 if (relativeEnd < 0) {
1698 double tempEndIndex = relativeEnd + static_cast<double>(srcLength);
1699 endIndex = tempEndIndex > 0 ? static_cast<uint32_t>(tempEndIndex) : 0;
1700 } else {
1701 endIndex = relativeEnd < static_cast<double>(srcLength) ?
1702 static_cast<uint32_t>(relativeEnd) : srcLength;
1703 }
1704 // 13. Let newLength be max(endIndex – beginIndex, 0).
1705 uint32_t newLength = endIndex > beginIndex ? (endIndex - beginIndex) : 0;
1706 // 14. Let constructorName be the String value of O’s [[TypedArrayName]] internal slot.
1707 // 15. Let elementSize be the Number value of the Element Size value specified in Table 49 for constructorName.
1708 // 16. Let srcByteOffset be the value of O’s [[ByteOffset]] internal slot.
1709 // 17. Let beginByteOffset be srcByteOffset + beginIndex × elementSize.
1710 JSHandle<JSTaggedValue> constructorName(thread, thisObj->GetTypedArrayName());
1711 DataViewType elementType = JSTypedArray::GetTypeFromName(thread, constructorName);
1712 uint32_t elementSize = TypedArrayHelper::GetSizeFromType(elementType);
1713 uint32_t srcByteOffset = thisObj->GetByteOffset();
1714 ASSERT((static_cast<uint64_t>(srcByteOffset) + static_cast<uint64_t>(beginIndex) *
1715 static_cast<uint64_t>(elementSize)) <= static_cast<uint64_t>(UINT32_MAX));
1716 uint32_t beginByteOffset = srcByteOffset + beginIndex * elementSize;
1717 JSTaggedValue buffer = JSTypedArray::GetOffHeapBuffer(thread, thisObj);
1718 // 21. Let argumentsList be «buffer, beginByteOffset, newLength».
1719 // 5. Let buffer be the value of O’s [[ViewedArrayBuffer]] internal slot.
1720 // 22. Return Construct(constructor, argumentsList).
1721 const uint32_t argsLength = 3;
1722 JSTaggedType args[argsLength] = {
1723 buffer.GetRawData(),
1724 JSTaggedValue(beginByteOffset).GetRawData(),
1725 JSTaggedValue(newLength).GetRawData()
1726 };
1727 JSHandle<JSObject> newArr = TypedArrayHelper::TypedArraySpeciesCreate(thread, thisObj, argsLength, args);
1728 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1729 return newArr.GetTaggedValue();
1730 }
1731
1732 // 22.2.3.27
ToLocaleString(EcmaRuntimeCallInfo * argv)1733 JSTaggedValue BuiltinsTypedArray::ToLocaleString(EcmaRuntimeCallInfo *argv)
1734 {
1735 ASSERT(argv);
1736 BUILTINS_API_TRACE(argv->GetThread(), TypedArray, ToLocaleString);
1737 if (!GetThis(argv)->IsTypedArray()) {
1738 THROW_TYPE_ERROR_AND_RETURN(argv->GetThread(), "This is not a TypedArray.", JSTaggedValue::Exception());
1739 }
1740 return BuiltinsArray::ToLocaleString(argv);
1741 }
1742
1743 // 22.2.3.28
ToString(EcmaRuntimeCallInfo * argv)1744 JSTaggedValue BuiltinsTypedArray::ToString(EcmaRuntimeCallInfo *argv)
1745 {
1746 ASSERT(argv);
1747 BUILTINS_API_TRACE(argv->GetThread(), TypedArray, ToString);
1748 if (!GetThis(argv)->IsTypedArray()) {
1749 THROW_TYPE_ERROR_AND_RETURN(argv->GetThread(), "This is not a TypedArray.", JSTaggedValue::Exception());
1750 }
1751 return BuiltinsArray::ToString(argv);
1752 }
1753
1754 // 22.2.3.29
Values(EcmaRuntimeCallInfo * argv)1755 JSTaggedValue BuiltinsTypedArray::Values(EcmaRuntimeCallInfo *argv)
1756 {
1757 ASSERT(argv);
1758 BUILTINS_API_TRACE(argv->GetThread(), TypedArray, Values);
1759 JSThread *thread = argv->GetThread();
1760 [[maybe_unused]] EcmaHandleScope handleScope(thread);
1761 // 1. Let O be the this value.
1762 JSHandle<JSTaggedValue> thisHandle = GetThis(argv);
1763 // 2. Let valid be ValidateTypedArray(O).
1764 TypedArrayHelper::ValidateTypedArray(thread, thisHandle);
1765 // 3. ReturnIfAbrupt(valid).
1766 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(argv->GetThread());
1767 JSHandle<JSObject> self(thisHandle);
1768 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1769 // 4. Return CreateArrayIterator(O, "value").
1770 JSHandle<JSArrayIterator> iter(factory->NewJSArrayIterator(self, IterationKind::VALUE));
1771 return iter.GetTaggedValue();
1772 }
1773
1774 // 22.2.3.31
ToStringTag(EcmaRuntimeCallInfo * argv)1775 JSTaggedValue BuiltinsTypedArray::ToStringTag(EcmaRuntimeCallInfo *argv)
1776 {
1777 ASSERT(argv);
1778 BUILTINS_API_TRACE(argv->GetThread(), TypedArray, ToStringTag);
1779 JSThread *thread = argv->GetThread();
1780 [[maybe_unused]] EcmaHandleScope handleScope(thread);
1781 // 1. Let O be the this value.
1782 JSHandle<JSTaggedValue> thisHandle = GetThis(argv);
1783 // 2. If Type(O) is not Object, return undefined.
1784 if (!thisHandle->IsECMAObject()) {
1785 return JSTaggedValue::Undefined();
1786 }
1787 // 3. If O does not have a [[TypedArrayName]] internal slot, return undefined.
1788 if (!thisHandle->IsTypedArray()) {
1789 return JSTaggedValue::Undefined();
1790 }
1791 // 4. Let name be the value of O’s [[TypedArrayName]] internal slot.
1792 JSTaggedValue name = JSHandle<JSTypedArray>::Cast(thisHandle)->GetTypedArrayName();
1793 // 5. Assert: name is a String value.
1794 ASSERT(name.IsString());
1795 // 6. Return name.
1796 return name;
1797 }
1798
1799 // 23.2.3.1
At(EcmaRuntimeCallInfo * argv)1800 JSTaggedValue BuiltinsTypedArray::At(EcmaRuntimeCallInfo *argv)
1801 {
1802 ASSERT(argv);
1803 BUILTINS_API_TRACE(argv->GetThread(), TypedArray, At);
1804 JSThread *thread = argv->GetThread();
1805 [[maybe_unused]] EcmaHandleScope handleScope(thread);
1806
1807 // 1. Let O be ToObject(this value).
1808 JSHandle<JSTaggedValue> thisHandle = GetThis(argv);
1809 // 2. Let valid be ValidateTypedArray(O).
1810 TypedArrayHelper::ValidateTypedArray(thread, thisHandle);
1811 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1812 JSHandle<JSObject> thisObjHandle = JSTaggedValue::ToObject(thread, thisHandle);
1813 // ReturnIfAbrupt(O).
1814 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1815
1816 // 3. Let len be O.[[ArrayLength]].
1817 uint32_t len = JSHandle<JSTypedArray>::Cast(thisObjHandle)->GetArrayLength();
1818 // ReturnIfAbrupt(len).
1819 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1820
1821 // 4. Let relativeIndex be ? ToIntegerOrInfinity(index).
1822 JSTaggedNumber indexVal = JSTaggedValue::ToInteger(thread, GetCallArg(argv, 0));
1823 // ReturnIfAbrupt(indexVal).
1824 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1825 int64_t relativeIndex = indexVal.GetNumber();
1826 int64_t k = 0;
1827 // 5. If relativeIndex ≥ 0, then Let k be relativeIndex.
1828 // 6. Else, Let k be len + relativeIndex.
1829 k = relativeIndex >= 0 ? relativeIndex : static_cast<int64_t>(len) + relativeIndex;
1830 // 7. If k < 0 or k ≥ len, return undefined.
1831 if (k < 0 || k >= len) {
1832 return JSTaggedValue::Undefined();
1833 }
1834 // 8. Return ! Get(O, ! ToString((k))).
1835 JSHandle<JSTaggedValue> kValue = JSTypedArray::GetProperty(thread, thisHandle, k).GetValue();
1836 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1837 return kValue.GetTaggedValue();
1838 }
1839
1840 // 23.2.3.33
ToSorted(EcmaRuntimeCallInfo * argv)1841 JSTaggedValue BuiltinsTypedArray::ToSorted(EcmaRuntimeCallInfo* argv)
1842 {
1843 ASSERT(argv);
1844 BUILTINS_API_TRACE(argv->GetThread(), TypedArray, ToSorted);
1845 JSThread* thread = argv->GetThread();
1846 [[maybe_unused]] EcmaHandleScope handleScope(thread);
1847
1848 // 1. If comparefn is not undefined and IsCallable(comparefn) is false, throw a TypeError exception.
1849 JSHandle<JSTaggedValue> comparefnHandle = GetCallArg(argv, 0);
1850 if (!comparefnHandle->IsUndefined() && !comparefnHandle->IsCallable()) {
1851 THROW_TYPE_ERROR_AND_RETURN(thread, "the comparefn is not callable.", JSTaggedValue::Exception());
1852 }
1853 // 2. Let O be the this value.
1854 JSHandle<JSTaggedValue> thisHandle = GetThis(argv);
1855 // 3. Perform ? ValidateTypedArray(O).
1856 TypedArrayHelper::ValidateTypedArray(thread, thisHandle);
1857 // ReturnIfAbrupt(valid).
1858 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1859
1860 JSHandle<JSTypedArray> thisObj(thisHandle);
1861 // 4. Let len be O.[[ArrayLength]].
1862 uint32_t len = thisObj->GetArrayLength();
1863
1864 // 5. Let A be ? TypedArrayCreateSameType(O, « (len) »).
1865 JSTaggedType args[1] = { JSTaggedValue(len).GetRawData() };
1866 JSHandle<JSObject> newArrObj = TypedArrayHelper::TypedArrayCreateSameType(thread, thisObj, 1, args); // 1: one arg.
1867 // ReturnIfAbrupt(A).
1868 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1869
1870 JSHandle<JSTaggedValue> buffer =
1871 JSHandle<JSTaggedValue>(thread, TypedArrayHelper::ValidateTypedArray(thread, thisHandle));
1872 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1873
1874 JSMutableHandle<JSTaggedValue> presentValue(thread, JSTaggedValue::Undefined());
1875 JSMutableHandle<JSTaggedValue> middleValue(thread, JSTaggedValue::Undefined());
1876 JSMutableHandle<JSTaggedValue> previousValue(thread, JSTaggedValue::Undefined());
1877 JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
1878 JSMutableHandle<JSTaggedValue> key1(thread, JSTaggedValue::Undefined());
1879 JSMutableHandle<JSTaggedValue> key2(thread, JSTaggedValue::Undefined());
1880 if (len > 0) {
1881 previousValue.Update(
1882 ObjectFastOperator::FastGetPropertyByValue(thread, thisHandle.GetTaggedValue(), JSTaggedValue(0)));
1883 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1884 ObjectFastOperator::FastSetPropertyByIndex(
1885 thread, newArrObj.GetTaggedValue(), 0, previousValue.GetTaggedValue());
1886 }
1887 for (uint32_t i = 1; i < len; i++) {
1888 uint32_t beginIndex = 0;
1889 uint32_t endIndex = i;
1890 key.Update(JSTaggedValue(i));
1891 presentValue.Update(
1892 ObjectFastOperator::FastGetPropertyByValue(thread, thisHandle.GetTaggedValue(), key.GetTaggedValue()));
1893 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1894 while (beginIndex < endIndex) {
1895 uint32_t middleIndex = beginIndex + (endIndex - beginIndex) / 2; // 2 : half
1896 key1.Update(JSTaggedValue(middleIndex));
1897 middleValue.Update(
1898 ObjectFastOperator::FastGetPropertyByValue(thread, newArrObj.GetTaggedValue(), key1.GetTaggedValue()));
1899 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1900 int32_t compareResult =
1901 TypedArrayHelper::SortCompare(thread, comparefnHandle, buffer, middleValue, presentValue);
1902 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1903 compareResult > 0 ? (endIndex = middleIndex) : (beginIndex = middleIndex + 1);
1904 }
1905
1906 if (endIndex < i) {
1907 for (uint32_t j = i; j > endIndex; j--) {
1908 key2.Update(JSTaggedValue(j - 1));
1909 previousValue.Update(ObjectFastOperator::FastGetPropertyByValue(
1910 thread, newArrObj.GetTaggedValue(), key2.GetTaggedValue()));
1911 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1912 ObjectFastOperator::FastSetPropertyByIndex(
1913 thread, newArrObj.GetTaggedValue(), j, previousValue.GetTaggedValue());
1914 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1915 }
1916 }
1917 ObjectFastOperator::FastSetPropertyByIndex(
1918 thread, newArrObj.GetTaggedValue(), endIndex, presentValue.GetTaggedValue());
1919 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1920 }
1921 return newArrObj.GetTaggedValue();
1922 }
1923
1924 // 23.2.3.36
With(EcmaRuntimeCallInfo * argv)1925 JSTaggedValue BuiltinsTypedArray::With(EcmaRuntimeCallInfo* argv)
1926 {
1927 ASSERT(argv);
1928 BUILTINS_API_TRACE(argv->GetThread(), TypedArray, With);
1929 JSThread* thread = argv->GetThread();
1930 [[maybe_unused]] EcmaHandleScope handleScope(thread);
1931
1932 // 1. Let O be the this value.
1933 JSHandle<JSTaggedValue> thisHandle = GetThis(argv);
1934 // 2. Perform ? ValidateTypedArray(O).
1935 TypedArrayHelper::ValidateTypedArray(thread, thisHandle);
1936 // ReturnIfAbrupt(valid).
1937 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1938
1939 JSHandle<JSTypedArray> thisObj(thisHandle);
1940 // 3. Let len be O.[[ArrayLength]].
1941 uint32_t len = thisObj->GetArrayLength();
1942
1943 // 4. Let relativeIndex be ? ToIntegerOrInfinity(index).
1944 JSTaggedNumber indexVal = JSTaggedValue::ToInteger(thread, GetCallArg(argv, 0));
1945 // ReturnIfAbrupt(indexVal).
1946 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1947 int64_t relativeIndex = indexVal.GetNumber();
1948 // 5. If relativeIndex ≥ 0, let actualIndex be relativeIndex.
1949 // 6. Else, let actualIndex be len + relativeIndex.
1950 int64_t actualIndex = relativeIndex >= 0 ? relativeIndex : static_cast<int64_t>(len) + relativeIndex;
1951
1952 // 7. If O.[[ContentType]] is BigInt, let numericValue be ? ToBigInt(value).
1953 // 8. Else, let numericValue be ? ToNumber(value).
1954 JSHandle<JSTaggedValue> value = GetCallArg(argv, 1);
1955 ContentType contentType = thisObj->GetContentType();
1956 JSHandle<JSTaggedValue> numericValue;
1957 if (contentType == ContentType::BigInt) {
1958 numericValue = JSHandle<JSTaggedValue>(thread, JSTaggedValue::ToBigInt(thread, value));
1959 } else {
1960 numericValue = JSHandle<JSTaggedValue>(thread, JSTaggedValue::ToNumber(thread, value));
1961 }
1962 // ReturnIfAbrupt(numericValue).
1963 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1964
1965 // 9. If IsValidIntegerIndex(O, (actualIndex)) is false, throw a RangeError exception.
1966 if (!JSTypedArray::IsValidIntegerIndex(thisHandle, JSTaggedValue(actualIndex))) {
1967 THROW_RANGE_ERROR_AND_RETURN(thread, "Invalid typed array index", JSTaggedValue::Exception());
1968 }
1969
1970 // 10. Let A be ? TypedArrayCreateSameType(O, « (len) »).
1971 JSTaggedType args[1] = { JSTaggedValue(len).GetRawData() };
1972 JSHandle<JSObject> newArrObj = TypedArrayHelper::TypedArrayCreateSameType(thread, thisObj, 1, args); // 1: one arg.
1973 // ReturnIfAbrupt(A).
1974 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1975
1976 // 11. Let k be 0.
1977 // 12. Repeat, while k < len,
1978 // a. Let Pk be ! ToString((k)).
1979 // b. If k is actualIndex, let fromValue be numericValue.
1980 // c. Else, let fromValue be ! Get(O, Pk).
1981 // d. Perform ! Set(A, Pk, fromValue, true).
1982 // e. Set k to k + 1.
1983 JSMutableHandle<JSTaggedValue> tKey(thread, JSTaggedValue::Undefined());
1984 JSMutableHandle<JSTaggedValue> fromValue(thread, JSTaggedValue::Undefined());
1985 uint32_t k = 0;
1986 while (k < len) {
1987 tKey.Update(JSTaggedValue(k));
1988 if (k == actualIndex) {
1989 fromValue.Update(numericValue);
1990 } else {
1991 fromValue.Update(
1992 ObjectFastOperator::FastGetPropertyByValue(thread, thisHandle.GetTaggedValue(), tKey.GetTaggedValue()));
1993 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1994 }
1995 ObjectFastOperator::FastSetPropertyByValue(thread, newArrObj.GetTaggedValue(),
1996 tKey.GetTaggedValue(), fromValue.GetTaggedValue());
1997 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1998 k++;
1999 }
2000 return newArrObj.GetTaggedValue();
2001 }
2002
2003 // es12 23.2.3.13
Includes(EcmaRuntimeCallInfo * argv)2004 JSTaggedValue BuiltinsTypedArray::Includes(EcmaRuntimeCallInfo *argv)
2005 {
2006 ASSERT(argv);
2007 BUILTINS_API_TRACE(argv->GetThread(), TypedArray, Includes);
2008 if (!GetThis(argv)->IsTypedArray()) {
2009 THROW_TYPE_ERROR_AND_RETURN(argv->GetThread(), "This is not a TypedArray.", JSTaggedValue::Exception());
2010 }
2011 return BuiltinsArray::Includes(argv);
2012 }
2013
2014 // 23.2.3.32
ToReversed(EcmaRuntimeCallInfo * argv)2015 JSTaggedValue BuiltinsTypedArray::ToReversed(EcmaRuntimeCallInfo *argv)
2016 {
2017 ASSERT(argv);
2018 JSThread *thread = argv->GetThread();
2019 BUILTINS_API_TRACE(thread, TypedArray, ToReversed);
2020 [[maybe_unused]] EcmaHandleScope handleScope(thread);
2021
2022 // 1. Let O be ToObject(this value).
2023 JSHandle<JSTaggedValue> thisHandle = GetThis(argv);
2024 JSHandle<JSTypedArray> thisObj(thisHandle);
2025 // 2. Perform ? ValidateTypedArray(O).
2026 TypedArrayHelper::ValidateTypedArray(thread, thisHandle);
2027 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2028 JSHandle<JSObject> thisObjHandle = JSTaggedValue::ToObject(thread, thisHandle);
2029 // ReturnIfAbrupt(O).
2030 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2031 // 3. Let len be O.[[ArrayLength]].
2032 uint32_t len = JSHandle<JSTypedArray>::Cast(thisObjHandle)->GetArrayLength();
2033 // ReturnIfAbrupt(len).
2034 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2035 // 4. Let A be ? TypedArrayCreateSameType(O, « (length) »).
2036 JSTaggedType args[1] = {JSTaggedValue(len).GetRawData()};
2037 JSHandle<JSObject> newArrayHandle = TypedArrayHelper::TypedArrayCreateSameType(thread, thisObj, 1, args);
2038 // ReturnIfAbrupt(newObj).
2039 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2040 // 5. Let k be 0.
2041 uint32_t k = 0;
2042
2043 // 6. Repeat, while k < length,
2044 // a. Let from be ! ToString((length - k - 1)).
2045 // b. Let Pk be ! ToString((k)).
2046 // c. Let fromValue be ! Get(O, from).
2047 // d. Perform ! Set(A, Pk, fromValue, true).
2048 // e. Set k to k + 1.
2049 while (k < len) {
2050 uint32_t from = len - k - 1;
2051 JSHandle<JSTaggedValue> fromValue = JSTypedArray::GetProperty(thread, thisHandle, from).GetValue();
2052 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2053 ObjectFastOperator::FastSetPropertyByIndex(thread, newArrayHandle.GetTaggedValue(), k,
2054 fromValue.GetTaggedValue());
2055 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2056 ++k;
2057 }
2058 // 7. Return A.
2059 return newArrayHandle.GetTaggedValue();
2060 }
2061
2062 // 23.2.3.13
FindLast(EcmaRuntimeCallInfo * argv)2063 JSTaggedValue BuiltinsTypedArray::FindLast(EcmaRuntimeCallInfo *argv)
2064 {
2065 ASSERT(argv);
2066 BUILTINS_API_TRACE(argv->GetThread(), TypedArray, FindLast);
2067 if (!GetThis(argv)->IsTypedArray()) {
2068 THROW_TYPE_ERROR_AND_RETURN(argv->GetThread(), "This is not a TypedArray.", JSTaggedValue::Exception());
2069 }
2070 return BuiltinsArray::FindLast(argv);
2071 }
2072
2073 // 23.2.3.14
FindLastIndex(EcmaRuntimeCallInfo * argv)2074 JSTaggedValue BuiltinsTypedArray::FindLastIndex(EcmaRuntimeCallInfo *argv)
2075 {
2076 ASSERT(argv);
2077 BUILTINS_API_TRACE(argv->GetThread(), TypedArray, FindLastIndex);
2078 if (!GetThis(argv)->IsTypedArray()) {
2079 THROW_TYPE_ERROR_AND_RETURN(argv->GetThread(), "This is not a TypedArray.", JSTaggedValue::Exception());
2080 }
2081 return BuiltinsArray::FindLastIndex(argv);
2082 }
2083 } // namespace panda::ecmascript::builtins
2084