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