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