• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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