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