• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 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_shared_array.h"
17 
18 
19 #include "ecmascript/builtins/builtins_array.h"
20 #include "ecmascript/builtins/builtins_string.h"
21 #include "ecmascript/interpreter/interpreter.h"
22 #include "ecmascript/js_map_iterator.h"
23 #include "ecmascript/js_stable_array.h"
24 #include "ecmascript/object_fast_operator-inl.h"
25 #include "ecmascript/base/sort_helper.h"
26 
27 namespace panda::ecmascript::builtins {
28 namespace {
29     constexpr int32_t COUNT_LENGTH_AND_INIT = 2;
30 } // namespace
31 using ArrayHelper = base::ArrayHelper;
32 using TypedArrayHelper = base::TypedArrayHelper;
33 using ContainerError = containers::ContainerError;
34 const CString STRING_SEPERATOR = ",";
35 
36 // 22.1.1
ArrayConstructor(EcmaRuntimeCallInfo * argv)37 JSTaggedValue BuiltinsSharedArray::ArrayConstructor(EcmaRuntimeCallInfo *argv)
38 {
39     BUILTINS_ENTRY_DEBUG_LOG();
40     ASSERT(argv);
41     BUILTINS_API_TRACE(argv->GetThread(), SharedArray, Constructor);
42     JSThread *thread = argv->GetThread();
43     [[maybe_unused]] EcmaHandleScope handleScope(thread);
44 
45     // 1. Let numberOfArgs be the number of arguments passed to this function call.
46     uint32_t argc = argv->GetArgsNumber();
47 
48     // 3. If NewTarget is undefined, throw exception
49     JSHandle<JSTaggedValue> newTarget = GetNewTarget(argv);
50     if (newTarget->IsUndefined()) {
51         JSTaggedValue error = containers::ContainerError::BusinessError(
52             thread, containers::ErrorFlag::IS_NULL_ERROR, "The ArkTS Array's constructor cannot be directly invoked.");
53         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
54     }
55 
56     // 4. Let proto be GetPrototypeFromConstructor(newTarget, "%ArrayPrototype%").
57     // In NewJSObjectByConstructor(), will get prototype.
58     // 5. ReturnIfAbrupt(proto).
59 
60     // 22.1.1.3 Array(...items )
61     JSTaggedValue newArray = JSSharedArray::ArrayCreate(thread, JSTaggedNumber(argc), newTarget).GetTaggedValue();
62     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
63     if (!newArray.IsJSSharedArray()) {
64         THROW_TYPE_ERROR_AND_RETURN(thread, "Failed to create array.", JSTaggedValue::Exception());
65     }
66 
67     // 22.1.1.1 Array ( )
68     if (argc == 0) {
69         // 6. Return ArrayCreate(0, proto).
70         return newArray;
71     }
72 
73     JSHandle<JSObject> newArrayHandle(thread, newArray);
74     // 8. Let k be 0.
75     // 9. Let items be a zero-origined List containing the argument items in order.
76     // 10. Repeat, while k < numberOfArgs
77     //   a. Let Pk be ToString(k).
78     //   b. Let itemK be items[k].
79     //   c. Let defineStatus be CreateDataProperty(array, Pk, itemK).
80     //   d. Assert: defineStatus is true.
81     //   e. Increase k by 1.
82     JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
83     JSMutableHandle<JSTaggedValue> itemK(thread, JSTaggedValue::Undefined());
84     for (uint32_t k = 0; k < argc; k++) {
85         key.Update(JSTaggedValue(k));
86         itemK.Update(GetCallArg(argv, k));
87         if (!itemK->IsSharedType()) {
88             auto error = ContainerError::ParamError(thread, "Parameter error.Only accept sendable value.");
89             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
90         }
91         JSObject::CreateDataProperty(thread, newArrayHandle, key, itemK);
92     }
93     // 11. Assert: the value of array’s length property is numberOfArgs.
94     // 12. Return array.
95     JSSharedArray::Cast(*newArrayHandle)->SetArrayLength(thread, argc);
96     newArrayHandle->GetJSHClass()->SetExtensible(false);
97     return newArrayHandle.GetTaggedValue();
98 }
99 
FromArrayNoMaping(JSThread * thread,const JSHandle<JSTaggedValue> & items,JSHandle<JSObject> & newArrayHandle)100 JSTaggedValue BuiltinsSharedArray::FromArrayNoMaping(JSThread *thread, const JSHandle<JSTaggedValue>& items,
101                                                      JSHandle<JSObject>& newArrayHandle)
102 {
103     JSHandle<JSObject> arrayLikeObj = JSTaggedValue::ToObject(thread, items);
104     JSHandle<JSTaggedValue> arrayLike(arrayLikeObj) ;
105     int64_t len = ArrayHelper::GetArrayLength(thread, arrayLike);
106     int k = 0;
107     JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
108     JSMutableHandle<JSTaggedValue> mapValue(thread, JSTaggedValue::Undefined());
109 
110     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
111     JSHandle<TaggedArray> eleArray = factory->NewTaggedArray(len, JSTaggedValue::Undefined(),
112                                                              MemSpaceType::SHARED_OLD_SPACE);
113     while (k < len) {
114         mapValue.Update(JSArray::FastGetPropertyByValue(thread, arrayLike, k));
115         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
116 
117         if (!mapValue->IsSharedType()) {
118             auto error = ContainerError::ParamError(thread, "Parameter error.Only accept sendable value.");
119             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
120         }
121 
122         eleArray->Set(thread, k, mapValue);
123         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
124         k++;
125         thread->CheckSafepointIfSuspended();
126     }
127     newArrayHandle->SetElements(thread, eleArray);
128     JSSharedArray::Cast(*newArrayHandle)->SetArrayLength(thread, k);
129     return newArrayHandle.GetTaggedValue();
130 }
131 
132 template<bool itemIsSharedArray>
FromArray(JSThread * thread,const JSHandle<JSTaggedValue> & items,const JSHandle<JSTaggedValue> & thisArgHandle,const JSHandle<JSTaggedValue> mapfn,JSHandle<JSObject> & newArrayHandle)133 JSTaggedValue BuiltinsSharedArray::FromArray(JSThread *thread, const JSHandle<JSTaggedValue>& items,
134                                              const JSHandle<JSTaggedValue>& thisArgHandle,
135                                              const JSHandle<JSTaggedValue> mapfn,
136                                              JSHandle<JSObject>& newArrayHandle)
137 {
138     JSHandle<JSObject> arrayLikeObj = JSTaggedValue::ToObject(thread, items);
139     JSHandle<JSTaggedValue> arrayLike(arrayLikeObj) ;
140     int64_t len = ArrayHelper::GetArrayLength(thread, arrayLike);
141     int k = 0;
142     JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
143     JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
144     CVector<JSHandle<JSTaggedValue>> valueVec(0);
145     valueVec.reserve(len);
146     JSMutableHandle<JSTaggedValue> mapValue(thread, JSTaggedValue::Undefined());
147     while (k < len) {
148         if constexpr (itemIsSharedArray) {
149             mapValue.Update(ElementAccessor::Get(thread, arrayLikeObj, k));
150             RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
151         } else {
152             mapValue.Update(JSArray::FastGetPropertyByValue(thread, arrayLike, k));
153             RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
154         }
155 
156         key.Update(JSTaggedValue(k));
157         const uint32_t argsLength = 2; // 2: «kValue, k»
158         EcmaRuntimeCallInfo *info =
159             EcmaInterpreter::NewRuntimeCallInfo(thread, mapfn, thisArgHandle, undefined, argsLength);
160         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
161         ASSERT(info != nullptr);
162         info->SetCallArg(mapValue.GetTaggedValue(), key.GetTaggedValue());
163         JSTaggedValue callResult = JSFunction::Call(info);
164         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
165         JSHandle<JSTaggedValue> result = JSHandle<JSTaggedValue>(thread, callResult);
166         len = ArrayHelper::GetArrayLength(thread, arrayLike);
167 
168         if (!result->IsSharedType()) {
169             auto error = ContainerError::ParamError(thread, "Parameter error.Only accept sendable value.");
170             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
171         }
172 
173         valueVec.push_back(result);
174         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
175         k++;
176         thread->CheckSafepointIfSuspended();
177     }
178     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
179     JSHandle<TaggedArray> eleArray = factory->NewTaggedArray(k, JSTaggedValue::Undefined(),
180                                                              MemSpaceType::SHARED_OLD_SPACE);
181     for (int idx = 0; idx < k; ++idx) {
182         eleArray->Set(thread, idx, valueVec[idx]);
183     }
184     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
185     newArrayHandle->SetElements(thread, eleArray);
186     JSSharedArray::Cast(*newArrayHandle)->SetArrayLength(thread, k);
187     return newArrayHandle.GetTaggedValue();
188 }
189 
190 template JSTaggedValue BuiltinsSharedArray::FromArray<true>(JSThread *thread, const JSHandle<JSTaggedValue>& items,
191                                                             const JSHandle<JSTaggedValue>& thisArgHandle,
192                                                             const JSHandle<JSTaggedValue> mapfn,
193                                                             JSHandle<JSObject>& newArrayHandle);
194 
195 template JSTaggedValue BuiltinsSharedArray::FromArray<false>(JSThread *thread, const JSHandle<JSTaggedValue>& items,
196                                                              const JSHandle<JSTaggedValue>& thisArgHandle,
197                                                              const JSHandle<JSTaggedValue> mapfn,
198                                                              JSHandle<JSObject>& newArrayHandle);
199 
FromSharedArray(JSThread * thread,const JSHandle<JSTaggedValue> & items,JSHandle<JSObject> & newArrayHandle)200 JSTaggedValue BuiltinsSharedArray::FromSharedArray(JSThread *thread, const JSHandle<JSTaggedValue>& items,
201                                                    JSHandle<JSObject>& newArrayHandle)
202 {
203     int64_t len = ArrayHelper::GetLength(thread, items);
204     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
205     JSHandle<TaggedArray> eleArray = factory->NewTaggedArray(len, JSTaggedValue::Undefined(),
206                                                              MemSpaceType::SHARED_OLD_SPACE);
207     JSHandle<JSObject> thisObjHandle = JSTaggedValue::ToObject(thread, items);
208     TaggedArray *element = TaggedArray::Cast(thisObjHandle->GetElements().GetTaggedObject());
209     eleArray->Copy(thread, 0, 0, element, len);
210     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
211     newArrayHandle->SetElements(thread, eleArray);
212     JSSharedArray::Cast(*newArrayHandle)->SetArrayLength(thread, len);
213     return newArrayHandle.GetTaggedValue();
214 }
215 
216 // 22.1.2.1 Array.from ( items [ , mapfn [ , thisArg ] ] )
217 // NOLINTNEXTLINE(readability-function-size)
From(EcmaRuntimeCallInfo * argv)218 JSTaggedValue BuiltinsSharedArray::From(EcmaRuntimeCallInfo *argv)
219 {
220     ASSERT(argv);
221     BUILTINS_API_TRACE(argv->GetThread(), SharedArray, From);
222     JSThread *thread = argv->GetThread();
223     [[maybe_unused]] EcmaHandleScope handleScope(thread);
224     // 1. Let C be the this value.
225     JSHandle<JSTaggedValue> thisHandle = GetThis(argv);
226     // 2. If mapfn is undefined, let mapping be false.
227     bool mapping = false;
228     // 3. else
229     // a. If IsCallable(mapfn) is false, throw a TypeError exception.
230     // b. If thisArg was supplied, let T be thisArg; else let T be undefined.
231     // c. Let mapping be true
232     JSHandle<JSTaggedValue> thisArgHandle = GetCallArg(argv, INDEX_TWO);
233     JSHandle<JSTaggedValue> mapfn = GetCallArg(argv, 1);
234     if (!mapfn->IsUndefined()) {
235         if (!mapfn->IsCallable()) {
236             THROW_TYPE_ERROR_AND_RETURN(thread, "the mapfn is not callable.", JSTaggedValue::Exception());
237         }
238         mapping = true;
239     }
240     // 4. Let usingIterator be GetMethod(items, @@iterator).
241     JSHandle<JSTaggedValue> items = GetCallArg(argv, 0);
242     if (items->IsNull()) {
243         THROW_TYPE_ERROR_AND_RETURN(thread, "The items is null.", JSTaggedValue::Exception());
244     }
245     if (!mapping && items->IsString()) {
246         JSHandle<EcmaString> strItems(items);
247         return BuiltinsString::StringToSList(thread, strItems);
248     }
249     // Fast path for TypedArray
250     if (!mapping && (items->IsTypedArray() || items->IsSharedTypedArray())) {
251         auto error = ContainerError::ParamError(thread, "Parameter error.TypedArray not support yet.");
252         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
253     }
254 
255     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
256     JSHandle<JSTaggedValue> iteratorSymbol = env->GetIteratorSymbol();
257     JSHandle<JSTaggedValue> usingIterator = JSObject::GetMethod(thread, items, iteratorSymbol);
258     // 5. ReturnIfAbrupt(usingIterator).
259     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
260     // 6. If usingIterator is not undefined, then
261     JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
262     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
263     if (!usingIterator->IsUndefined()) {
264         // Fast path for MapIterator
265         JSHandle<JSTaggedValue> iterator(thread, JSTaggedValue::Hole());
266         if (!mapping && items->IsJSMapIterator()) {
267             iterator = JSIterator::GetIterator(thread, items, usingIterator);
268             if (iterator->IsJSMapIterator()) {
269                 return JSMapIterator::MapIteratorToList(thread, iterator);
270             }
271         }
272 
273         //   a. If IsConstructor(C) is true, then
274         //     i. Let A be Construct(C).
275         //   b. Else,
276         //     i. Let A be ArrayCreate(0).
277         //   c. ReturnIfAbrupt(A).
278         JSTaggedValue newArray;
279         if (thisHandle->IsConstructor()) {
280             EcmaRuntimeCallInfo *info =
281                 EcmaInterpreter::NewRuntimeCallInfo(thread, thisHandle, undefined, undefined, 0);
282             ASSERT(info != nullptr);
283             newArray = JSFunction::Construct(info);
284             RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
285         } else {
286             newArray = JSSharedArray::ArrayCreate(thread, JSTaggedNumber(0)).GetTaggedValue();
287             RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
288         }
289         if (!newArray.IsJSSharedArray()) {
290             THROW_TYPE_ERROR_AND_RETURN(thread, "Failed to construct the array.", JSTaggedValue::Exception());
291         }
292         JSHandle<JSObject> newArrayHandle(thread, newArray);
293         //   d. Let iterator be GetIterator(items, usingIterator).
294         if (iterator->IsHole()) {
295             iterator = JSIterator::GetIterator(thread, items, usingIterator);
296             //   e. ReturnIfAbrupt(iterator).
297             RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
298         }
299         //   f. Let k be 0.
300         int k = 0;
301         //   g. Repeat
302         JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
303         JSMutableHandle<JSTaggedValue> mapValue(thread, JSTaggedValue::Undefined());
304         // fastpath for jsarray
305         if ((items->IsJSArray() && iterator->IsJSArrayIterator())) {
306             if (mapping) {
307                 return BuiltinsSharedArray::FromArray<false>(thread, items, thisArgHandle, mapfn, newArrayHandle);
308             } else {
309                 return BuiltinsSharedArray::FromArrayNoMaping(thread, items, newArrayHandle);
310             }
311         }
312 
313         if (items->IsJSSharedArray()) {
314             if (mapping) {
315                 return BuiltinsSharedArray::FromArray<true>(thread, items, thisArgHandle, mapfn, newArrayHandle);
316             } else {
317                 return BuiltinsSharedArray::FromSharedArray(thread, items, newArrayHandle);
318             }
319         }
320 
321         while (true) {
322             key.Update(JSTaggedValue(k));
323             //     i. Let Pk be ToString(k).
324             //     ii. Let next be IteratorStep(iterator).
325             JSHandle<JSTaggedValue> next = JSIterator::IteratorStep(thread, iterator);
326             //     iii. ReturnIfAbrupt(next).
327             RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
328             //     iv. If next is false, then
329             //       1. Let setStatus be Set(A, "length", k, true).
330             //       2. ReturnIfAbrupt(setStatus).
331             //       3. Return A.
332             if (next->IsFalse()) {
333                 JSSharedArray::LengthSetter(thread, newArrayHandle, key, true);
334                 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
335                 newArrayHandle->GetJSHClass()->SetExtensible(false);
336                 return newArrayHandle.GetTaggedValue();
337             }
338             //     v. Let nextValue be IteratorValue(next).
339             JSHandle<JSTaggedValue> nextValue = JSIterator::IteratorValue(thread, next);
340             //     vi. ReturnIfAbrupt(nextValue).
341             RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
342             //     vii. If mapping is true, then
343             //       1. Let mappedValue be Call(mapfn, T, «nextValue, k»).
344             //       2. If mappedValue is an abrupt completion, return IteratorClose(iterator, mappedValue).
345             //       3. Let mappedValue be mappedValue.[[value]].
346             //     viii. Else, let mappedValue be nextValue.
347             if (mapping) {
348                 const uint32_t argsLength = 2; // 2: «nextValue, k»
349                 EcmaRuntimeCallInfo *info =
350                     EcmaInterpreter::NewRuntimeCallInfo(thread, mapfn, thisArgHandle, undefined, argsLength);
351                 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
352                 ASSERT(info != nullptr);
353                 info->SetCallArg(nextValue.GetTaggedValue(), key.GetTaggedValue());
354                 JSTaggedValue callResult = JSFunction::Call(info);
355                 RETURN_VALUE_IF_ABRUPT_COMPLETION(thread,
356                     JSIterator::IteratorClose(thread, iterator, mapValue).GetTaggedValue());
357                 mapValue.Update(callResult);
358             } else {
359                 mapValue.Update(nextValue.GetTaggedValue());
360             }
361             if (!mapValue->IsSharedType()) {
362                 auto error = ContainerError::ParamError(thread, "Parameter error.Only accept sendable value.");
363                 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
364             }
365             //     ix. Let defineStatus be CreateDataPropertyOrThrow(A, Pk, mappedValue).
366             //     x. If defineStatus is an abrupt completion, return IteratorClose(iterator, defineStatus).
367             //     xi. Increase k by 1.
368             JSHandle<JSTaggedValue> defineStatus(thread, JSTaggedValue(JSObject::CreateDataPropertyOrThrow(
369                 thread, newArrayHandle, key, mapValue, SCheckMode::SKIP)));
370             RETURN_VALUE_IF_ABRUPT_COMPLETION(thread,
371                 JSIterator::IteratorClose(thread, iterator, defineStatus).GetTaggedValue());
372             k++;
373         }
374     }
375     // 7. Assert: items is not an Iterable so assume it is an array-like object.
376     // 8. Let arrayLike be ToObject(items).
377     JSHandle<JSObject> arrayLikeObj = JSTaggedValue::ToObject(thread, items);
378     // 9. ReturnIfAbrupt(arrayLike).
379     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
380     JSHandle<JSTaggedValue> arrayLike(arrayLikeObj);
381     // 10. Let len be ToLength(Get(arrayLike, "length")).
382     int64_t len = ArrayHelper::GetArrayLength(thread, arrayLike);
383     // 11. ReturnIfAbrupt(len).
384     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
385     // 12. If IsConstructor(C) is true, then
386     //   a. Let A be Construct(C, «len»).
387     // 13. Else,
388     //   a. Let A be ArrayCreate(len).
389     // 14. ReturnIfAbrupt(A).
390     JSTaggedValue newArray;
391     if (thisHandle->IsConstructor()) {
392         EcmaRuntimeCallInfo *info =
393             EcmaInterpreter::NewRuntimeCallInfo(thread, thisHandle, undefined, undefined, 1);
394         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
395         ASSERT(info != nullptr);
396         info->SetCallArg(JSTaggedValue(len));
397         newArray = JSFunction::Construct(info);
398         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
399     } else {
400         newArray = JSSharedArray::ArrayCreate(thread, JSTaggedNumber(static_cast<double>(len))).GetTaggedValue();
401         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
402     }
403     if (!newArray.IsJSSharedArray()) {
404         THROW_TYPE_ERROR_AND_RETURN(thread, "Failed to construct the array.", JSTaggedValue::Exception());
405     }
406     JSHandle<JSObject> newArrayHandle(thread, newArray);
407     // 15. Let k be 0.
408     // 16. Repeat, while k < len
409     //   a. Let Pk be ToString(k).
410     //   b. Let kValue be Get(arrayLike, Pk).
411     //   d. If mapping is true, then
412     //     i. Let mappedValue be Call(mapfn, T, «kValue, k»).
413     //   e. Else, let mappedValue be kValue.
414     //   f. Let defineStatus be CreateDataPropertyOrThrow(A, Pk, mappedValue).
415     JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
416     JSMutableHandle<JSTaggedValue> mapValue(thread, JSTaggedValue::Undefined());
417     int64_t k = 0;
418     JSHandle<TaggedArray> eleArray = factory->NewTaggedArray(len, JSTaggedValue::Undefined(),
419                                                              MemSpaceType::SHARED_OLD_SPACE);
420     while (k < len) {
421         JSHandle<JSTaggedValue> kValue = JSSharedArray::FastGetPropertyByValue(thread, arrayLike, k);
422         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
423         if (mapping) {
424             key.Update(JSTaggedValue(k));
425             const uint32_t argsLength = 2; // 2: «kValue, k»
426             EcmaRuntimeCallInfo *info =
427                 EcmaInterpreter::NewRuntimeCallInfo(thread, mapfn, thisArgHandle, undefined, argsLength);
428             RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
429             ASSERT(info != nullptr);
430             info->SetCallArg(kValue.GetTaggedValue(), key.GetTaggedValue());
431             JSTaggedValue callResult = JSFunction::Call(info);
432             RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
433             mapValue.Update(callResult);
434         } else {
435             mapValue.Update(kValue.GetTaggedValue());
436         }
437         if (!mapValue->IsSharedType()) {
438             auto error = ContainerError::ParamError(thread, "Parameter error.Only accept sendable value.");
439             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
440         }
441         eleArray->Set(thread, k, mapValue);
442         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
443         k++;
444     }
445     newArrayHandle->SetElements(thread, eleArray);
446     // 17. Let setStatus be Set(A, "length", len, true).
447     JSSharedArray::Cast(*newArrayHandle)->SetArrayLength(thread, len);
448     newArrayHandle->GetJSHClass()->SetExtensible(false);
449     // 18. ReturnIfAbrupt(setStatus).
450     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
451     // 19. Return A.
452     return newArrayHandle.GetTaggedValue();
453 }
454 
455 // Array.create ( arrayLength, initialValue )
Create(EcmaRuntimeCallInfo * argv)456 JSTaggedValue BuiltinsSharedArray::Create(EcmaRuntimeCallInfo *argv)
457 {
458     ASSERT(argv);
459     BUILTINS_API_TRACE(argv->GetThread(), SharedArray, Create);
460     JSThread *thread = argv->GetThread();
461     [[maybe_unused]] EcmaHandleScope handleScope(thread);
462     if (argv->GetArgsNumber() < COUNT_LENGTH_AND_INIT) {
463         auto error = ContainerError::ParamError(thread, "Parameter error.Not enough parameters.");
464         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
465     }
466     JSHandle<JSTaggedValue> thisHandle = GetThis(argv);
467     JSHandle<JSTaggedValue> arrayLengthValue = GetCallArg(argv, 0);
468     if (!arrayLengthValue->IsNumber()) {
469         auto error = ContainerError::ParamError(thread, "Parameter error.Invalid array length.");
470         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
471     }
472     auto arrayLength = JSTaggedValue::ToUint32(thread, arrayLengthValue);
473     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
474     if (JSTaggedNumber(arrayLengthValue.GetTaggedValue()).GetNumber() != arrayLength) {
475         auto error = ContainerError::ParamError(thread, "Parameter error.Invalid array length.");
476         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
477     }
478     JSHandle<JSTaggedValue> initValue = GetCallArg(argv, 1);
479     if (!initValue->IsSharedType()) {
480         auto error = ContainerError::ParamError(thread, "Parameter error.Only accept sendable value.");
481         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
482     }
483     JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
484     JSTaggedValue newArray;
485     if (thisHandle->IsConstructor()) {
486         EcmaRuntimeCallInfo *info =
487             EcmaInterpreter::NewRuntimeCallInfo(thread, thisHandle, undefined, undefined, 0);
488         ASSERT(info != nullptr);
489         newArray = JSFunction::Construct(info);
490         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
491     } else {
492         newArray = JSSharedArray::ArrayCreate(thread, JSTaggedNumber(0)).GetTaggedValue();
493         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
494     }
495     if (!newArray.IsJSSharedArray()) {
496         THROW_TYPE_ERROR_AND_RETURN(thread, "Failed to construct the array.", JSTaggedValue::Exception());
497     }
498     JSHandle<JSObject> newArrayHandle(thread, newArray);
499     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
500     auto elements = factory->NewSOldSpaceTaggedArray(arrayLength, JSTaggedValue::Hole());
501     for (uint32_t k = 0; k < arrayLength; k++) {
502         elements->Set(thread, k, initValue);
503     }
504     newArrayHandle->SetElements(thread, elements);
505     auto len = JSHandle<JSTaggedValue>(thread, JSTaggedValue(arrayLength));
506     JSSharedArray::LengthSetter(thread, newArrayHandle, len, true);
507     newArrayHandle->GetJSHClass()->SetExtensible(false);
508     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
509     // Return A.
510     return newArrayHandle.GetTaggedValue();
511 }
512 
513 // Array.isArray ( arg )
IsArray(EcmaRuntimeCallInfo * argv)514 JSTaggedValue BuiltinsSharedArray::IsArray(EcmaRuntimeCallInfo *argv)
515 {
516     ASSERT(argv);
517     JSThread *thread = argv->GetThread();
518     BUILTINS_API_TRACE(thread, SharedArray, IsArray);
519     [[maybe_unused]] EcmaHandleScope handleScope(thread);
520     if (GetCallArg(argv, 0)->IsJSSharedArray()) {
521         return GetTaggedBoolean(true);
522     }
523     return GetTaggedBoolean(false);
524 }
525 
526 // 22.1.2.5 get Array [ @@species ]
Species(EcmaRuntimeCallInfo * argv)527 JSTaggedValue BuiltinsSharedArray::Species(EcmaRuntimeCallInfo *argv)
528 {
529     ASSERT(argv);
530     BUILTINS_API_TRACE(argv->GetThread(), SharedArray, Species);
531     // 1. Return the this value.
532     return GetThis(argv).GetTaggedValue();
533 }
534 
CalNewArrayLen(JSThread * thread,EcmaRuntimeCallInfo * argv,int argc)535 int64_t BuiltinsSharedArray::CalNewArrayLen(JSThread *thread, EcmaRuntimeCallInfo *argv, int argc)
536 {
537     int64_t newArrayLen = 0;
538     JSMutableHandle<JSTaggedValue> ele(thread, JSTaggedValue::Undefined());
539     for (int i = 0; i < argc; i++) {
540         ele.Update(GetCallArg(argv, i));
541 
542         if (!ele->IsSharedType()) {
543             auto error = ContainerError::ParamError(thread, "Parameter error.Only accept sendable value.");
544             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, newArrayLen);
545         }
546         // a. Let spreadable be ? IsConcatSpreadable(E).
547         bool isSpreadable = ArrayHelper::IsConcatSpreadable(thread, ele);
548         RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, newArrayLen);
549         // b. If spreadable is true, then
550         if (!isSpreadable) {
551             newArrayLen++;
552             continue;
553         }
554 
555         // i. Let k be 0.
556         // ii. Let len be ? LengthOfArrayLike(E).
557         // iii. If n + len > 253 - 1, throw a TypeError exception.
558         int64_t len = ArrayHelper::GetArrayLength(thread, ele);
559         RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, newArrayLen);
560         if (newArrayLen + len > base::MAX_SAFE_INTEGER || newArrayLen + len < newArrayLen) {
561             THROW_TYPE_ERROR_AND_RETURN(thread, "out of range.", newArrayLen);
562         }
563 
564         newArrayLen += len;
565     }
566 
567     return newArrayLen;
568 }
569 
FillNewTaggedArray(JSThread * thread,EcmaRuntimeCallInfo * argv,int argc,int64_t newArrayIdx,JSHandle<TaggedArray> & eleArray)570 int64_t BuiltinsSharedArray::FillNewTaggedArray(JSThread *thread, EcmaRuntimeCallInfo *argv, int argc,
571                                                 int64_t newArrayIdx, JSHandle<TaggedArray> &eleArray)
572 {
573     JSMutableHandle<JSTaggedValue> ele(thread, JSTaggedValue::Undefined());
574     JSMutableHandle<JSTaggedValue> toKey(thread, JSTaggedValue::Undefined());
575     JSMutableHandle<JSTaggedValue> kValue(thread, JSTaggedValue::Undefined());
576     for (int i = 0; i < argc; i++) {
577         ele.Update(GetCallArg(argv, i));
578 
579         // a. Let spreadable be ? IsConcatSpreadable(E).
580         bool isSpreadable = ArrayHelper::IsConcatSpreadable(thread, ele);
581         RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, newArrayIdx);
582         // b. If spreadable is true, then
583         if (!isSpreadable) {
584             // ii. If n ≥ 253 - 1, throw a TypeError exception.
585             if (newArrayIdx >= base::MAX_SAFE_INTEGER) {
586                 THROW_TYPE_ERROR_AND_RETURN(thread, "out of range.", newArrayIdx);
587             }
588             // // iii. Perform ? CreateDataPropertyOrThrow(A, ! ToString(��(n)), E).
589             // // iv. Set n to n + 1.
590             eleArray->Set(thread, newArrayIdx, ele);
591             RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, newArrayIdx);
592             newArrayIdx++;
593             continue;
594         }
595 
596         // i. Let k be 0.
597         // ii. Let len be ? LengthOfArrayLike(E).
598         // iii. If n + len > 253 - 1, throw a TypeError exception.
599         int64_t len = ArrayHelper::GetArrayLength(thread, ele);
600         int64_t k = 0;
601         RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, newArrayIdx);
602 
603         JSHandle<JSObject> eleObj = JSTaggedValue::ToObject(thread, ele);
604         while (k < len) {
605             toKey.Update(JSTaggedValue(newArrayIdx));
606             kValue.Update(BuiltinsSharedArray::GetElementByKey(thread, eleObj, k));
607             RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, newArrayIdx);
608 
609             if (!kValue->IsSharedType()) {
610                 auto error = ContainerError::ParamError(thread, "Parameter error.Only accept sendable value.");
611                 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, newArrayIdx);
612             }
613 
614             if (!kValue->IsHole()) {
615                 eleArray->Set(thread, newArrayIdx, kValue);
616                 RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, newArrayIdx);
617             }
618             newArrayIdx++;
619             k++;
620         }
621     }
622 
623     return newArrayIdx;
624 }
625 
626 // 22.1.3.1 Array.prototype.concat ( ...arguments )
Concat(EcmaRuntimeCallInfo * argv)627 JSTaggedValue BuiltinsSharedArray::Concat(EcmaRuntimeCallInfo *argv)
628 {
629     ASSERT(argv);
630     BUILTINS_API_TRACE(argv->GetThread(), SharedArray, Concat);
631     JSThread *thread = argv->GetThread();
632     [[maybe_unused]] EcmaHandleScope handleScope(thread);
633     int argc = static_cast<int>(argv->GetArgsNumber());
634 
635     // 1. Let O be ToObject(this value).
636     // thisHandle variable declare this Macro
637     ARRAY_CHECK_SHARED_ARRAY("The concat method cannot be bound.")
638 
639     JSHandle<JSObject> thisObjHandle = JSTaggedValue::ToObject(thread, thisHandle);
640     [[maybe_unused]] ConcurrentApiScope<JSSharedArray> scope(thread, thisHandle);
641     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
642 
643     // 2. Let A be ArraySpeciesCreate(O, 0).
644     JSTaggedValue newArray = JSSharedArray::ArraySpeciesCreate(thread, thisObjHandle, JSTaggedNumber(0));
645     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
646     if (!(newArray.IsECMAObject() || newArray.IsUndefined())) {
647         THROW_TYPE_ERROR_AND_RETURN(thread, "array must be object or undefined.", JSTaggedValue::Exception());
648     }
649     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
650     JSHandle<JSObject> newArrayHandle(thread, newArray);
651 
652     int64_t oldArrayLen = ArrayHelper::GetArrayLength(thread, thisHandle);
653     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
654     int64_t newArrayLen = oldArrayLen + BuiltinsSharedArray::CalNewArrayLen(thread, argv, argc);
655     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
656 
657     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
658     JSHandle<TaggedArray> eleArray = factory->NewTaggedArray(newArrayLen, JSTaggedValue::Undefined(),
659                                                              MemSpaceType::SHARED_OLD_SPACE);
660     TaggedArray *oldElement = TaggedArray::Cast(thisObjHandle->GetElements().GetTaggedObject());
661     eleArray->Copy(thread, 0, 0, oldElement, oldArrayLen);
662     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
663 
664     int64_t res = BuiltinsSharedArray::FillNewTaggedArray(thread, argv, argc, oldArrayLen, eleArray);
665     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
666 
667     if (newArrayLen != res) {
668         auto error = ContainerError::ParamError(thread, "Parameter error.Only accept sendable value.");
669         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
670     }
671 
672     newArrayHandle->SetElements(thread, eleArray);
673 
674     // 6. Perform ? Set(A, "length", ��(n), true).
675     JSHandle<JSTaggedValue> lenHandle(thread, JSTaggedValue(newArrayLen));
676     JSSharedArray::LengthSetter(thread, newArrayHandle, lenHandle, true);
677     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
678 
679     // 7. Return A.
680     return newArrayHandle.GetTaggedValue();
681 }
682 
683 // 22.1.3.4 Array.prototype.entries ( )
Entries(EcmaRuntimeCallInfo * argv)684 JSTaggedValue BuiltinsSharedArray::Entries(EcmaRuntimeCallInfo *argv)
685 {
686     ASSERT(argv);
687     BUILTINS_API_TRACE(argv->GetThread(), SharedArray, Entries);
688     JSThread *thread = argv->GetThread();
689     [[maybe_unused]] EcmaHandleScope handleScope(thread);
690     // thisHandle variable declare this Macro
691     ARRAY_CHECK_SHARED_ARRAY("The entries method cannot be bound.")
692 
693     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
694     // 1. Let O be ToObject(this value).
695     // 2. ReturnIfAbrupt(O).
696     JSHandle<JSObject> self = JSTaggedValue::ToObject(thread, GetThis(argv));
697     [[maybe_unused]] ConcurrentApiScope<JSSharedArray> scope(thread, thisHandle);
698     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
699     // 3. Return CreateArrayIterator(O, "key+value").
700     JSHandle<JSSharedArrayIterator> iter(factory->NewJSSharedArrayIterator(self, IterationKind::KEY_AND_VALUE));
701     return iter.GetTaggedValue();
702 }
CheckElementMeetReq(JSThread * thread,JSHandle<JSTaggedValue> & thisObjVal,JSHandle<JSTaggedValue> & callbackFnHandle,bool isSome)703 JSTaggedValue BuiltinsSharedArray::CheckElementMeetReq(JSThread *thread,
704                                                        JSHandle<JSTaggedValue> &thisObjVal,
705                                                        JSHandle<JSTaggedValue> &callbackFnHandle, bool isSome)
706 {
707     [[maybe_unused]] ConcurrentApiScope<JSSharedArray> scope(thread, thisObjVal);
708     JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
709     JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
710     const uint32_t argsLength = 3; // 3: «kValue, k, O»
711     JSTaggedValue callResult = GetTaggedBoolean(true);
712     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
713     // Let len be ToLength(Get(O, "length")).
714     uint64_t len = static_cast<uint64_t>(ArrayHelper::GetArrayLength(thread, thisObjVal));
715     // ReturnIfAbrupt(len).
716     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
717     uint32_t k = 0;
718     JSMutableHandle<JSTaggedValue> kValue(thread, JSTaggedValue::Undefined());
719     JSHandle<JSObject> thisObjHandle = JSTaggedValue::ToObject(thread, thisObjVal);
720     while (k < len) {
721         kValue.Update(BuiltinsSharedArray::GetElementByKey(thread, thisObjHandle, k));
722         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
723         key.Update(JSTaggedValue(k));
724         EcmaRuntimeCallInfo *info =
725             EcmaInterpreter::NewRuntimeCallInfo(thread, callbackFnHandle, undefined, undefined, argsLength);
726         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
727         ASSERT(info != nullptr);
728         info->SetCallArg(kValue.GetTaggedValue(), key.GetTaggedValue(), thisObjVal.GetTaggedValue());
729         callResult = JSFunction::Call(info);
730         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
731 
732         // isSome && callResult.ToBoolean() return true(callResult)
733         // !isSome && !callResult.ToBoolean() return false(callResult)
734         if (!(isSome ^ callResult.ToBoolean())) {
735             return GetTaggedBoolean(callResult.ToBoolean());
736         }
737 
738         k++;
739         thread->CheckSafepointIfSuspended();
740     }
741 
742     return GetTaggedBoolean(!isSome);
743 }
744 
745 // Array.prototype.every ( callbackfn [ , thisArg] )
Every(EcmaRuntimeCallInfo * argv)746 JSTaggedValue BuiltinsSharedArray::Every(EcmaRuntimeCallInfo *argv)
747 {
748     ASSERT(argv);
749     BUILTINS_API_TRACE(argv->GetThread(), SharedArray, Every);
750     JSThread *thread = argv->GetThread();
751     [[maybe_unused]] EcmaHandleScope handleScope(thread);
752 
753     // 1. Let O be ToObject(this value).
754     // thisHandle variable declare this Macro
755     ARRAY_CHECK_SHARED_ARRAY("The every method cannot be bound.")
756 
757     // 3. If IsCallable(callbackfn) is false, throw a TypeError exception.
758     JSHandle<JSTaggedValue> callbackFnHandle = GetCallArg(argv, 0);
759     if (!callbackFnHandle->IsCallable()) {
760         THROW_TYPE_ERROR_AND_RETURN(thread, "the callbackfun is not callable.", JSTaggedValue::Exception());
761     }
762 
763     // 5. Let k be 0.
764     // 6. Repeat, while k < len
765     //   a. Let Pk be ToString(k).
766     //   b. Let kPresent be HasProperty(O, Pk).
767     //   c. ReturnIfAbrupt(kPresent).
768     //   d. If kPresent is true, then
769     //     i. Let kValue be Get(O, Pk).
770     //     ii. ReturnIfAbrupt(kValue).
771     //     iii. Let testResult be ToBoolean(Call(callbackfn, T, «kValue, k, O»)).
772     //     iv. ReturnIfAbrupt(testResult).
773     //     v. If testResult is false, return false.
774     //   e. Increase k by 1.
775 
776     return CheckElementMeetReq(thread, thisHandle, callbackFnHandle, false);
777 }
778 
779 // Array.prototype.some ( callbackfn [ , thisArg ] )
Some(EcmaRuntimeCallInfo * argv)780 JSTaggedValue BuiltinsSharedArray::Some(EcmaRuntimeCallInfo *argv)
781 {
782     ASSERT(argv);
783     BUILTINS_API_TRACE(argv->GetThread(), SharedArray, Some);
784     JSThread *thread = argv->GetThread();
785     [[maybe_unused]] EcmaHandleScope handleScope(thread);
786 
787     // 1. Let O be ToObject(this value).
788     // thisHandle variable declare this Macro
789     ARRAY_CHECK_SHARED_ARRAY("The some method cannot be bound.")
790 
791     // 5. If IsCallable(callbackfn) is false, throw a TypeError exception.
792     JSHandle<JSTaggedValue> callbackFnHandle = GetCallArg(argv, 0);
793     if (!callbackFnHandle->IsCallable()) {
794         THROW_TYPE_ERROR_AND_RETURN(thread, "the callbackfun is not callable.", JSTaggedValue::Exception());
795     }
796 
797     return CheckElementMeetReq(thread, thisHandle, callbackFnHandle, true);
798 }
799 
800 // 22.1.3.6 Array.prototype.fill (value [ , start [ , end ] ] )
Fill(EcmaRuntimeCallInfo * argv)801 JSTaggedValue BuiltinsSharedArray::Fill(EcmaRuntimeCallInfo *argv)
802 {
803     ASSERT(argv);
804     BUILTINS_API_TRACE(argv->GetThread(), SharedArray, Fill);
805     JSThread *thread = argv->GetThread();
806     [[maybe_unused]] EcmaHandleScope handleScope(thread);
807 
808     // 1. Let O be ToObject(this value).
809     // thisHandle variable declare this Macro
810     ARRAY_CHECK_SHARED_ARRAY("The fill method cannot be bound.")
811 
812     JSHandle<JSObject> thisObjHandle = JSTaggedValue::ToObject(thread, thisHandle);
813     [[maybe_unused]] ConcurrentApiScope<JSSharedArray, ModType::WRITE> scope(thread, thisHandle);
814 
815     // 2. ReturnIfAbrupt(O).
816     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
817 
818     JSHandle<JSTaggedValue> value = GetCallArg(argv, 0);
819     if (!value->IsSharedType()) {
820         auto error = ContainerError::ParamError(thread, "Parameter error.Only accept sendable value.");
821         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
822     }
823 
824     // 3. Let len be ToLength(Get(O, "length")).
825     int64_t len = ArrayHelper::GetLength(thread, thisHandle);
826     // 4. ReturnIfAbrupt(len).
827     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
828 
829     // 5. Let relativeStart be ToInteger(start).
830     // 6. If relativeStart < 0, let k be max((len + relativeStart),0); else let k be min(relativeStart, len).
831     int64_t start = GetNumberArgVal(thread, argv, 1, len, 0);
832     // 7. ReturnIfAbrupt(relativeStart).
833     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
834 
835     // 8. If end is undefined, let relativeEnd be len; else let relativeEnd be ToInteger(end).
836     // 9. If relativeEnd < 0, let final be max((len + relativeEnd),0); else let final be min(relativeEnd, len).
837     int64_t end = GetNumberArgVal(thread, argv, INDEX_TWO, len, len);
838     // 10. ReturnIfAbrupt(relativeStart).
839     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
840 
841     // 11. Repeat, while k < final
842     //   a. Let Pk be ToString(k).
843     //   b. Let setStatus be Set(O, Pk, value, true).
844     //   c. ReturnIfAbrupt(setStatus).
845     //   d. Increase k by 1.
846     int64_t k = start;
847     JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
848     TaggedArray *elements = TaggedArray::Cast(thisObjHandle->GetElements().GetTaggedObject());
849     while (k < end) {
850         elements->Set(thread, k, value);
851         k++;
852     }
853 
854     // 12. Return O.
855     return thisObjHandle.GetTaggedValue();
856 }
857 
FilterArray(JSThread * thread,JSHandle<JSTaggedValue> & thisArgHandle,JSHandle<JSTaggedValue> & thisObjVal,JSHandle<JSObject> & newArrayHandle,JSHandle<JSTaggedValue> & callbackFnHandle)858 JSTaggedValue BuiltinsSharedArray::FilterArray(JSThread *thread, JSHandle<JSTaggedValue> &thisArgHandle,
859     JSHandle<JSTaggedValue> &thisObjVal, JSHandle<JSObject>& newArrayHandle,
860     JSHandle<JSTaggedValue> &callbackFnHandle)
861 {
862     JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
863     const uint32_t argsLength = 3; // 3: «kValue, k, O»
864     JSTaggedValue callResult = GetTaggedBoolean(true);
865     JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
866     JSMutableHandle<JSTaggedValue> toIndexHandle(thread, JSTaggedValue::Undefined());
867     int64_t k = 0;
868     // 3. Let len be ToLength(Get(O, "length")).
869     int64_t len = ArrayHelper::GetArrayLength(thread, thisObjVal);
870     // 4. ReturnIfAbrupt(len).
871     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
872     uint32_t toIndex = 0;
873     JSHandle<JSObject> thisObjHandle = JSTaggedValue::ToObject(thread, thisObjVal);
874     JSMutableHandle<JSTaggedValue> kValue(thread, JSTaggedValue::Undefined());
875     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
876     JSHandle<TaggedArray> eleArray = factory->NewTaggedArray(len, JSTaggedValue::Undefined(),
877     MemSpaceType::SHARED_OLD_SPACE);
878     while (k < len) {
879         kValue.Update(BuiltinsSharedArray::GetElementByKey(thread, thisObjHandle, k));
880         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
881         key.Update(JSTaggedValue(k));
882         EcmaRuntimeCallInfo *info =
883         EcmaInterpreter::NewRuntimeCallInfo(thread, callbackFnHandle, thisArgHandle, undefined, argsLength);
884         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
885         ASSERT(info != nullptr);
886         info->SetCallArg(kValue.GetTaggedValue(), key.GetTaggedValue(), thisObjVal.GetTaggedValue());
887         callResult = JSFunction::Call(info);
888         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
889         if (callResult.ToBoolean()) {
890             eleArray->Set(thread, toIndex, kValue);
891             RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
892             toIndex++;
893         }
894         k++;
895     }
896 
897     newArrayHandle->SetElements(thread, eleArray);
898     if (TaggedArray::ShouldTrim(len, toIndex)) {
899         eleArray->Trim(thread, toIndex);
900     }
901     JSSharedArray::Cast(*newArrayHandle)->SetArrayLength(thread, toIndex);
902 
903     return newArrayHandle.GetTaggedValue();
904 }
905 
906 // 22.1.3.7 Array.prototype.filter ( callbackfn [ , thisArg ] )
Filter(EcmaRuntimeCallInfo * argv)907 JSTaggedValue BuiltinsSharedArray::Filter(EcmaRuntimeCallInfo *argv)
908 {
909     ASSERT(argv);
910     JSThread *thread = argv->GetThread();
911     BUILTINS_API_TRACE(thread, SharedArray, Filter);
912     [[maybe_unused]] EcmaHandleScope handleScope(thread);
913 
914     // 1. Let O be ToObject(this value).
915     // thisHandle variable declare this Macro
916     ARRAY_CHECK_SHARED_ARRAY("The filter method cannot be bound.")
917 
918     JSHandle<JSObject> thisObjHandle = JSTaggedValue::ToObject(thread, thisHandle);
919     [[maybe_unused]] ConcurrentApiScope<JSSharedArray> scope(thread, thisHandle);
920     // 2. ReturnIfAbrupt(O).
921     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
922 
923     // 5. If IsCallable(callbackfn) is false, throw a TypeError exception.
924     JSHandle<JSTaggedValue> callbackFnHandle = GetCallArg(argv, 0);
925     if (!callbackFnHandle->IsCallable()) {
926         THROW_TYPE_ERROR_AND_RETURN(thread, "the callbackfun is not callable.", JSTaggedValue::Exception());
927     }
928 
929     // 6. If thisArg was supplied, let T be thisArg; else let T be undefined.
930     JSHandle<JSTaggedValue> thisArgHandle = GetCallArg(argv, 1);
931 
932     // 7. Let A be ArraySpeciesCreate(O, 0).
933     JSTaggedValue newArray = JSSharedArray::ArraySpeciesCreate(thread, thisObjHandle, JSTaggedNumber(0));
934     // 8. ReturnIfAbrupt(A).
935     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
936     JSHandle<JSObject> newArrayHandle(thread, newArray);
937 
938     // 9. Let k be 0.
939     // 10. Let to be 0.
940     // 11. Repeat, while k < len
941     //   a. Let Pk be ToString(k).
942     //   b. Let kPresent be HasProperty(O, Pk).
943     //   c. ReturnIfAbrupt(kPresent).
944     //   d. If kPresent is true, then
945     //     i. Let kValue be Get(O, Pk).
946     //     ii. ReturnIfAbrupt(kValue).
947     //     iii. Let selected be ToBoolean(Call(callbackfn, T, «kValue, k, O»)).
948     //     iv. ReturnIfAbrupt(selected).
949     //     v. If selected is true, then
950     //       1. Let status be CreateDataPropertyOrThrow (A, ToString(to), kValue).
951     //       2. ReturnIfAbrupt(status).
952     //       3. Increase to by 1.
953     //   e. Increase k by 1.
954     auto opResult =
955         FilterArray(thread, thisArgHandle, thisHandle, newArrayHandle, callbackFnHandle);
956 
957     return opResult;
958 }
959 
960 // 22.1.3.8 Array.prototype.find ( predicate [ , thisArg ] )
Find(EcmaRuntimeCallInfo * argv)961 JSTaggedValue BuiltinsSharedArray::Find(EcmaRuntimeCallInfo *argv)
962 {
963     ASSERT(argv);
964     BUILTINS_API_TRACE(argv->GetThread(), SharedArray, Find);
965     JSThread *thread = argv->GetThread();
966     [[maybe_unused]] EcmaHandleScope handleScope(thread);
967 
968     // 1. Let O be ToObject(this value).
969     // thisHandle variable declare this Macro
970     ARRAY_CHECK_SHARED_ARRAY("The find method cannot be bound.")
971 
972     JSHandle<JSObject> thisObjHandle = JSTaggedValue::ToObject(thread, thisHandle);
973     [[maybe_unused]] ConcurrentApiScope<JSSharedArray> scope(thread, thisHandle);
974     // 2. ReturnIfAbrupt(O).
975     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
976 
977     // 3. Let len be ToLength(Get(O, "length")).
978     int64_t len = ArrayHelper::GetLength(thread, thisHandle);
979     // 4. ReturnIfAbrupt(len).
980     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
981 
982     // 5. If IsCallable(predicate) is false, throw a TypeError exception.
983     JSHandle<JSTaggedValue> callbackFnHandle = GetCallArg(argv, 0);
984     if (!callbackFnHandle->IsCallable()) {
985         THROW_TYPE_ERROR_AND_RETURN(thread, "the predicate is not callable.", JSTaggedValue::Exception());
986     }
987 
988     // 6. If thisArg was supplied, let T be thisArg; else let T be undefined.
989     JSHandle<JSTaggedValue> thisArgHandle = GetCallArg(argv, 1);
990 
991     // 7. Let k be 0.
992     // 8. Repeat, while k < len
993     //   a. Let Pk be ToString(k).
994     //   b. Let kValue be Get(O, Pk).
995     //   c. ReturnIfAbrupt(kValue).
996     //   d. Let testResult be ToBoolean(Call(predicate, T, «kValue, k, O»)).
997     //   e. ReturnIfAbrupt(testResult).
998     //   f. If testResult is true, return kValue.
999     //   g. Increase k by 1.
1000     JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
1001     JSMutableHandle<JSTaggedValue> kValue(thread, JSTaggedValue::Undefined());
1002     int64_t k = 0;
1003     while (k < len) {
1004         kValue.Update(BuiltinsSharedArray::GetElementByKey(thread, thisObjHandle, k));
1005         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1006         key.Update(JSTaggedValue(k));
1007         const uint32_t argsLength = 3; // 3: «kValue, k, O»
1008         JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
1009         EcmaRuntimeCallInfo *info =
1010             EcmaInterpreter::NewRuntimeCallInfo(thread, callbackFnHandle, thisArgHandle, undefined, argsLength);
1011         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1012         ASSERT(info != nullptr);
1013         info->SetCallArg(kValue.GetTaggedValue(), key.GetTaggedValue(), thisHandle.GetTaggedValue());
1014         JSTaggedValue callResult = JSFunction::Call(info);
1015         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1016         if (callResult.ToBoolean()) {
1017             return kValue.GetTaggedValue();
1018         }
1019         k++;
1020     }
1021 
1022     // 9. Return undefined.
1023     return JSTaggedValue::Undefined();
1024 }
1025 
GetElementByKey(JSThread * thread,JSHandle<JSObject> & thisObjHandle,uint32_t index)1026 JSTaggedValue BuiltinsSharedArray::GetElementByKey(JSThread *thread, JSHandle<JSObject>& thisObjHandle, uint32_t index)
1027 {
1028     if (UNLIKELY(ElementAccessor::GetElementsLength(thisObjHandle) <= index)) {
1029         return JSTaggedValue::Undefined();
1030     }
1031 
1032     return ElementAccessor::Get(thread, thisObjHandle, index);
1033 }
1034 
SetElementValue(JSThread * thread,JSHandle<JSObject> arrHandle,uint32_t key,const JSHandle<JSTaggedValue> & value)1035 void BuiltinsSharedArray::SetElementValue(JSThread *thread, JSHandle<JSObject> arrHandle, uint32_t key,
1036                                           const JSHandle<JSTaggedValue> &value)
1037 {
1038     if (UNLIKELY(ElementAccessor::GetElementsLength(arrHandle) <= key)) {
1039         auto error = ContainerError::ParamError(thread, "Set element's index is exceeds the array length.");
1040         THROW_NEW_ERROR_AND_RETURN(thread, error);
1041     }
1042     if (UNLIKELY(!value->IsSharedType())) {
1043         auto error = ContainerError::ParamError(thread, "Parameter error.Only accept sendable value.");
1044         THROW_NEW_ERROR_AND_RETURN(thread, error);
1045     }
1046     ElementAccessor::Set(thread, arrHandle, key, value, false);
1047 }
1048 
1049 // 22.1.3.9 Array.prototype.findIndex ( predicate [ , thisArg ] )
FindIndex(EcmaRuntimeCallInfo * argv)1050 JSTaggedValue BuiltinsSharedArray::FindIndex(EcmaRuntimeCallInfo *argv)
1051 {
1052     ASSERT(argv);
1053     BUILTINS_API_TRACE(argv->GetThread(), SharedArray, FindIndex);
1054     JSThread *thread = argv->GetThread();
1055     [[maybe_unused]] EcmaHandleScope handleScope(thread);
1056 
1057     // 1. Let O be ToObject(this value).
1058     // thisHandle variable declare this Macro
1059     ARRAY_CHECK_SHARED_ARRAY("The findIndex method cannot be bound.")
1060 
1061     JSHandle<JSObject> thisObjHandle = JSTaggedValue::ToObject(thread, thisHandle);
1062     [[maybe_unused]] ConcurrentApiScope<JSSharedArray> scope(thread, thisHandle);
1063     // 2. ReturnIfAbrupt(O).
1064     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1065 
1066     // 3. Let len be ToLength(Get(O, "length")).
1067     uint64_t len = static_cast<uint64_t>(ArrayHelper::GetLength(thread, thisHandle));
1068     // 4. ReturnIfAbrupt(len).
1069     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1070 
1071     // 5. If IsCallable(predicate) is false, throw a TypeError exception.
1072     JSHandle<JSTaggedValue> callbackFnHandle = GetCallArg(argv, 0);
1073     if (!callbackFnHandle->IsCallable()) {
1074         THROW_TYPE_ERROR_AND_RETURN(thread, "the predicate is not callable.", JSTaggedValue::Exception());
1075     }
1076 
1077     if (UNLIKELY(ElementAccessor::GetElementsLength(thisObjHandle) < len)) {
1078         len = ElementAccessor::GetElementsLength(thisObjHandle);
1079     }
1080 
1081     const int32_t argsLength = 3; // 3: ?kValue, k, O?
1082     JSMutableHandle<JSTaggedValue> kValue(thread, JSTaggedValue::Undefined());
1083     uint32_t k = 0;
1084     // 7. Let k be 0.
1085     // 8. Repeat, while k < len
1086     //   a. Let Pk be ToString(k).
1087     //   b. Let kValue be Get(O, Pk).
1088     //   c. ReturnIfAbrupt(kValue).
1089     //   d. Let testResult be ToBoolean(Call(predicate, T, «kValue, k, O»)).
1090     //   e. ReturnIfAbrupt(testResult).
1091     //   f. If testResult is true, return k.
1092     //   g. Increase k by 1.
1093     while (k < len) {
1094         kValue.Update(BuiltinsSharedArray::GetElementByKey(thread, thisObjHandle, k));
1095         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1096         EcmaRuntimeCallInfo *info =
1097             EcmaInterpreter::NewRuntimeCallInfo(thread, callbackFnHandle.GetTaggedValue(),
1098             JSTaggedValue::Undefined(), JSTaggedValue::Undefined(), argsLength);
1099         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1100         ASSERT(info != nullptr);
1101         info->SetCallArg(kValue.GetTaggedValue(), JSTaggedValue(k), thisHandle.GetTaggedValue());
1102         auto callResult = JSFunction::Call(info);
1103         RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, callResult);
1104         if (callResult.ToBoolean()) {
1105             return GetTaggedDouble(k);
1106         }
1107         k++;
1108     }
1109 
1110     // 9. Return -1.
1111     return GetTaggedDouble(-1);
1112 }
1113 
1114 // 22.1.3.10 Array.prototype.forEach ( callbackfn [ , thisArg ] )
ForEach(EcmaRuntimeCallInfo * argv)1115 JSTaggedValue BuiltinsSharedArray::ForEach(EcmaRuntimeCallInfo *argv)
1116 {
1117     ASSERT(argv);
1118     JSThread *thread = argv->GetThread();
1119     BUILTINS_API_TRACE(thread, SharedArray, ForEach);
1120     [[maybe_unused]] EcmaHandleScope handleScope(thread);
1121 
1122     // 1. Let O be ToObject(this value).
1123     // thisHandle variable declare this Macro
1124     ARRAY_CHECK_SHARED_ARRAY("The forEach method cannot be bound.")
1125 
1126     JSHandle<JSObject> thisObjHandle = JSTaggedValue::ToObject(thread, thisHandle);
1127     [[maybe_unused]] ConcurrentApiScope<JSSharedArray> scope(thread, thisHandle);
1128     // 2. ReturnIfAbrupt(O).
1129     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1130 
1131     // 3. Let len be ToLength(Get(O, "length")).
1132     uint64_t len = static_cast<uint64_t>(ArrayHelper::GetArrayLength(thread, thisHandle));
1133     // 4. ReturnIfAbrupt(len).
1134     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1135 
1136     // 5. If IsCallable(callbackfn) is false, throw a TypeError exception.
1137     JSHandle<JSTaggedValue> callbackFnHandle = GetCallArg(argv, 0);
1138     if (!callbackFnHandle->IsCallable()) {
1139         THROW_TYPE_ERROR_AND_RETURN(thread, "the callbackfun is not callable.", JSTaggedValue::Exception());
1140     }
1141 
1142     // 6. If thisArg was supplied, let T be thisArg; else let T be undefined.
1143     JSHandle<JSTaggedValue> thisArgHandle = GetCallArg(argv, 1);
1144 
1145     // 7. Let k be 0.
1146     // 8. Repeat, while k < len
1147     //   a. Let Pk be ToString(k).
1148     //   b. Let kPresent be HasProperty(O, Pk).
1149     //   c. ReturnIfAbrupt(kPresent).
1150     //   d. If kPresent is true, then
1151     //     i. Let kValue be Get(O, Pk).
1152     //     ii. ReturnIfAbrupt(kValue).
1153     //     iii. Let funcResult be Call(callbackfn, T, «kValue, k, O»).
1154     //     iv. ReturnIfAbrupt(funcResult).
1155     //   e. Increase k by 1.
1156     JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
1157     uint32_t k = 0;
1158     const uint32_t argsLength = 3; // 3: «kValue, k, O»
1159     JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
1160     JSMutableHandle<JSTaggedValue> kValue(thread, JSTaggedValue::Undefined());
1161     while (k < len) {
1162         kValue.Update(BuiltinsSharedArray::GetElementByKey(thread, thisObjHandle, k));
1163         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1164         key.Update(JSTaggedValue(k));
1165         EcmaRuntimeCallInfo *info =
1166             EcmaInterpreter::NewRuntimeCallInfo(thread, callbackFnHandle, thisArgHandle, undefined, argsLength);
1167         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1168         ASSERT(info != nullptr);
1169         info->SetCallArg(kValue.GetTaggedValue(), key.GetTaggedValue(), thisHandle.GetTaggedValue());
1170         JSTaggedValue funcResult = JSFunction::Call(info);
1171         RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, funcResult);
1172         k++;
1173     }
1174 
1175     // 9. Return undefined.
1176     return JSTaggedValue::Undefined();
1177 }
1178 
IndexOfSlowPath(EcmaRuntimeCallInfo * argv,JSThread * thread,const JSHandle<JSTaggedValue> & thisHandle)1179 JSTaggedValue BuiltinsSharedArray::IndexOfSlowPath(
1180     EcmaRuntimeCallInfo *argv, JSThread *thread, const JSHandle<JSTaggedValue> &thisHandle)
1181 {
1182     // 1. Let O be ToObject(this value).
1183     JSHandle<JSObject> thisObjHandle = JSTaggedValue::ToObject(thread, thisHandle);
1184     // 2. ReturnIfAbrupt(O).
1185     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1186     JSHandle<JSTaggedValue> thisObjVal(thisObjHandle);
1187     // 3. Let len be ToLength(Get(O, "length")).
1188     int64_t length = ArrayHelper::GetLength(thread, thisObjVal);
1189     // 4. ReturnIfAbrupt(len).
1190     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1191     // 5. If len is 0, return −1.
1192     if (length == 0) {
1193         return JSTaggedValue(-1);
1194     }
1195     // 6. If argument fromIndex was passed let n be ToInteger(fromIndex); else let n be 0.
1196     int64_t fromIndex = ArrayHelper::GetStartIndexFromArgs(thread, argv, 1, length);
1197     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1198     return IndexOfSlowPath(argv, thread, thisObjVal, length, fromIndex);
1199 }
1200 
IndexOfSlowPath(EcmaRuntimeCallInfo * argv,JSThread * thread,const JSHandle<JSTaggedValue> & thisObjVal,int64_t length,int64_t fromIndex)1201 JSTaggedValue BuiltinsSharedArray::IndexOfSlowPath(
1202     EcmaRuntimeCallInfo *argv, JSThread *thread, const JSHandle<JSTaggedValue> &thisObjVal,
1203     int64_t length, int64_t fromIndex)
1204 {
1205     if (fromIndex >= length) {
1206         return JSTaggedValue(-1);
1207     }
1208     JSMutableHandle<JSTaggedValue> keyHandle(thread, JSTaggedValue::Undefined());
1209     JSHandle<JSTaggedValue> target = GetCallArg(argv, 0);
1210     // 11. Repeat, while k < len
1211     for (int64_t curIndex = fromIndex; curIndex < length; ++curIndex) {
1212         keyHandle.Update(JSTaggedValue(curIndex));
1213         bool found = ArrayHelper::ElementIsStrictEqualTo(thread, thisObjVal, keyHandle, target);
1214         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1215         if (UNLIKELY(found)) {
1216             return JSTaggedValue(curIndex);
1217         }
1218     }
1219     // 12. Return -1.
1220     return JSTaggedValue(-1);
1221 }
1222 
IndexOfStable(EcmaRuntimeCallInfo * argv,JSThread * thread,const JSHandle<JSTaggedValue> & thisHandle)1223 JSTaggedValue BuiltinsSharedArray::IndexOfStable(EcmaRuntimeCallInfo *argv, JSThread *thread,
1224                                                  const JSHandle<JSTaggedValue> &thisHandle)
1225 {
1226     int64_t length = ArrayHelper::GetArrayLength(thread, thisHandle);
1227     if (length == 0) {
1228         return JSTaggedValue(-1);
1229     }
1230     int64_t fromIndex = 0;
1231     uint32_t argc = argv->GetArgsNumber();
1232     // 2: [target, fromIndex]. Note that fromIndex is missing in most usage cases.
1233     if (UNLIKELY(argc >= 2)) {
1234         JSHandle<JSTaggedValue> fromIndexHandle = argv->GetCallArg(1);
1235         fromIndex = ArrayHelper::GetStartIndex(thread, fromIndexHandle, length);
1236         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1237         // Slow path when fromIndex is obtained from an ECMAObject
1238         // due to potential side effects in its 'toString' and 'valueOf' methods which modify the array object.
1239         if (UNLIKELY(fromIndexHandle->IsECMAObject())) {
1240             return IndexOfSlowPath(argv, thread, thisHandle, length, fromIndex);
1241         }
1242     }
1243     if (fromIndex >= length) {
1244         return JSTaggedValue(-1);
1245     }
1246 
1247     JSHandle<JSTaggedValue> target = GetCallArg(argv, 0);
1248     return JSStableArray::IndexOf(
1249         thread, thisHandle, target, static_cast<uint32_t>(fromIndex), static_cast<uint32_t>(length));
1250 }
1251 
1252 // 22.1.3.11 Array.prototype.indexOf ( searchElement [ , fromIndex ] )
IndexOf(EcmaRuntimeCallInfo * argv)1253 JSTaggedValue BuiltinsSharedArray::IndexOf(EcmaRuntimeCallInfo *argv)
1254 {
1255     ASSERT(argv);
1256     JSThread *thread = argv->GetThread();
1257     BUILTINS_API_TRACE(thread, SharedArray, IndexOf);
1258     [[maybe_unused]] EcmaHandleScope handleScope(thread);
1259 
1260     // thisHandle variable declare this Macro
1261     ARRAY_CHECK_SHARED_ARRAY("The indexOf method cannot be bound.")
1262 
1263     [[maybe_unused]] ConcurrentApiScope<JSSharedArray> scope(thread, thisHandle);
1264 
1265     return IndexOfStable(argv, thread, thisHandle);
1266 }
1267 
1268 // 22.1.3.12 Array.prototype.join (separator)
Join(EcmaRuntimeCallInfo * argv)1269 JSTaggedValue BuiltinsSharedArray::Join(EcmaRuntimeCallInfo *argv)
1270 {
1271     ASSERT(argv);
1272     JSThread *thread = argv->GetThread();
1273     BUILTINS_API_TRACE(argv->GetThread(), SharedArray, Join);
1274     // thisHandle variable declare this Macro
1275     ARRAY_CHECK_SHARED_ARRAY("The join method cannot be bound.")
1276 
1277     [[maybe_unused]] ConcurrentApiScope<JSSharedArray> scope(thread, thisHandle);
1278     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1279 
1280     auto factory = thread->GetEcmaVM()->GetFactory();
1281     auto context = thread->GetCurrentEcmaContext();
1282     bool noCircular = context->JoinStackPushFastPath(thisHandle);
1283     if (!noCircular) {
1284         return factory->GetEmptyString().GetTaggedValue();
1285     }
1286 
1287     return JSStableArray::Join(thisHandle, argv);
1288 }
1289 
1290 // 22.1.3.13 Array.prototype.keys ( )
Keys(EcmaRuntimeCallInfo * argv)1291 JSTaggedValue BuiltinsSharedArray::Keys(EcmaRuntimeCallInfo *argv)
1292 {
1293     ASSERT(argv);
1294     JSThread *thread = argv->GetThread();
1295     BUILTINS_API_TRACE(argv->GetThread(), SharedArray, Keys);
1296     // thisHandle variable declare this Macro
1297     ARRAY_CHECK_SHARED_ARRAY("The keys method cannot be bound.")
1298 
1299     [[maybe_unused]] ConcurrentApiScope<JSSharedArray> scope(thread, thisHandle);
1300     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1301     auto opResult = BuiltinsArray::Keys(argv);
1302     return opResult;
1303 }
1304 
1305 // 22.1.3.15 Array.prototype.map ( callbackfn [ , thisArg ] )
Map(EcmaRuntimeCallInfo * argv)1306 JSTaggedValue BuiltinsSharedArray::Map(EcmaRuntimeCallInfo *argv)
1307 {
1308     ASSERT(argv);
1309     BUILTINS_API_TRACE(argv->GetThread(), SharedArray, Map);
1310     JSThread *thread = argv->GetThread();
1311     [[maybe_unused]] EcmaHandleScope handleScope(thread);
1312 
1313     // 1. Let O be ToObject(this value).
1314     // thisHandle variable declare this Macro
1315     ARRAY_CHECK_SHARED_ARRAY("The map method cannot be bound.")
1316 
1317     JSHandle<JSObject> thisObjHandle = JSTaggedValue::ToObject(thread, thisHandle);
1318     [[maybe_unused]] ConcurrentApiScope<JSSharedArray> scope(thread, thisHandle);
1319     // 2. ReturnIfAbrupt(O).
1320     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1321 
1322     // 3. Let len be ToLength(Get(O, "length")).
1323     int64_t rawLen = ArrayHelper::GetArrayLength(thread, thisHandle);
1324     // 4. ReturnIfAbrupt(len).
1325     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1326 
1327     // 5. If IsCallable(callbackfn) is false, throw a TypeError exception.
1328     JSHandle<JSTaggedValue> callbackFnHandle = GetCallArg(argv, 0);
1329     if (!callbackFnHandle->IsCallable()) {
1330         THROW_TYPE_ERROR_AND_RETURN(thread, "the callbackfun is not callable.", JSTaggedValue::Exception());
1331     }
1332 
1333     // 6. If thisArg was supplied, let T be thisArg; else let T be undefined.
1334     JSHandle<JSTaggedValue> thisArgHandle = GetCallArg(argv, 1);
1335 
1336     // 7. Let A be ArraySpeciesCreate(O, len).
1337     JSTaggedValue newArray =
1338         JSSharedArray::ArraySpeciesCreate(thread, thisObjHandle, JSTaggedNumber(static_cast<double>(rawLen)));
1339     // 8. ReturnIfAbrupt(A).
1340     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1341     if (!newArray.IsECMAObject()) {
1342         THROW_TYPE_ERROR_AND_RETURN(thread, "Failed to create Object.", JSTaggedValue::Exception());
1343     }
1344     JSHandle<JSObject> newArrayHandle(thread, newArray);
1345 
1346     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1347     JSHandle<TaggedArray> eleArray = factory->NewTaggedArray(rawLen, JSTaggedValue::Undefined(),
1348                                                              MemSpaceType::SHARED_OLD_SPACE);
1349 
1350     // 9. Let k be 0.
1351     // 10. Repeat, while k < len
1352     //   a. Let Pk be ToString(k).
1353     //   b. Let kPresent be HasProperty(O, Pk).
1354     //   c. ReturnIfAbrupt(kPresent).
1355     //   d. If kPresent is true, then
1356     //     i. Let kValue be Get(O, Pk).
1357     //     ii. ReturnIfAbrupt(kValue).
1358     //     iii. Let mappedValue be Call(callbackfn, T, «kValue, k, O»).
1359     //     iv. ReturnIfAbrupt(mappedValue).
1360     //     v. Let status be CreateDataPropertyOrThrow (A, Pk, mappedValue).
1361     //     vi. ReturnIfAbrupt(status).
1362     //   e. Increase k by 1.
1363     uint32_t k = 0;
1364     uint32_t len = static_cast<uint32_t>(rawLen);
1365     JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
1366     JSMutableHandle<JSTaggedValue> mapResultHandle(thread, JSTaggedValue::Undefined());
1367     JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
1368     JSMutableHandle<JSTaggedValue> kValue(thread, JSTaggedValue::Undefined());
1369     const uint32_t argsLength = 3; // 3: «kValue, k, O»
1370     while (k < len) {
1371         kValue.Update(BuiltinsSharedArray::GetElementByKey(thread, thisObjHandle, k));
1372         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1373         key.Update(JSTaggedValue(k));
1374         EcmaRuntimeCallInfo *info =
1375             EcmaInterpreter::NewRuntimeCallInfo(thread, callbackFnHandle, thisArgHandle, undefined, argsLength);
1376         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1377         ASSERT(info != nullptr);
1378         info->SetCallArg(kValue.GetTaggedValue(), key.GetTaggedValue(), thisHandle.GetTaggedValue());
1379         JSTaggedValue mapResult = JSFunction::Call(info);
1380         if (!mapResult.IsSharedType()) {
1381             auto error = ContainerError::ParamError(thread, "Parameter error.Only accept sendable value.");
1382             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
1383         }
1384         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1385         mapResultHandle.Update(mapResult);
1386         eleArray->Set(thread, k, mapResultHandle);
1387         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1388         k++;
1389     }
1390     newArrayHandle->SetElements(thread, eleArray);
1391 
1392     // 11. Return A.
1393     return newArrayHandle.GetTaggedValue();
1394 }
1395 
1396 // 22.1.3.16 Array.prototype.pop ( )
Pop(EcmaRuntimeCallInfo * argv)1397 JSTaggedValue BuiltinsSharedArray::Pop(EcmaRuntimeCallInfo *argv)
1398 {
1399     ASSERT(argv);
1400     BUILTINS_API_TRACE(argv->GetThread(), SharedArray, Pop);
1401 
1402     JSThread *thread = argv->GetThread();
1403     [[maybe_unused]] EcmaHandleScope handleScope(thread);
1404 
1405     // 1. Let O be ToObject(this value).
1406     // thisHandle variable declare this Macro
1407     ARRAY_CHECK_SHARED_ARRAY("The pop method cannot be bound.")
1408 
1409     JSHandle<JSObject> thisObjHandle = JSTaggedValue::ToObject(thread, thisHandle);
1410     [[maybe_unused]] ConcurrentApiScope<JSSharedArray, ModType::WRITE> scope(thread, thisHandle);
1411     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1412 
1413     JSTaggedValue opResult = PopInner(argv, thisHandle, thisObjHandle);
1414     return opResult;
1415 }
1416 
PopInner(EcmaRuntimeCallInfo * argv,JSHandle<JSTaggedValue> & thisHandle,JSHandle<JSObject> & thisObjHandle)1417 JSTaggedValue BuiltinsSharedArray::PopInner(EcmaRuntimeCallInfo *argv, JSHandle<JSTaggedValue> &thisHandle,
1418                                             JSHandle<JSObject> &thisObjHandle)
1419 {
1420     JSThread *thread = argv->GetThread();
1421     [[maybe_unused]] EcmaHandleScope handleScope(thread);
1422 
1423     // 2. ReturnIfAbrupt(O).
1424     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1425 
1426     // 3. Let len be ToLength(Get(O, "length")).
1427     int64_t len = ArrayHelper::GetArrayLength(thread, thisHandle);
1428     // 4. ReturnIfAbrupt(len).
1429     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1430     // 5. If len is zero,
1431     //   a. Let setStatus be Set(O, "length", 0, true).
1432     //   b. ReturnIfAbrupt(setStatus).
1433     //   c. Return undefined.
1434     if (len == 0) {
1435         JSHandle<JSTaggedValue> lengthValue(thread, JSTaggedValue(0));
1436         JSSharedArray::LengthSetter(thread, thisObjHandle, lengthValue, true);
1437         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1438         return JSTaggedValue::Undefined();
1439     }
1440 
1441     // 6. Else len > 0,
1442     //   a. Let newLen be len–1.
1443     //   b. Let indx be ToString(newLen).
1444     //   c. Let element be Get(O, indx).
1445     //   d. ReturnIfAbrupt(element).
1446     //   e. Let deleteStatus be DeletePropertyOrThrow(O, indx).
1447     //   f. ReturnIfAbrupt(deleteStatus).
1448     //   g. Let setStatus be Set(O, "length", newLen, true).
1449     //   h. ReturnIfAbrupt(setStatus).
1450     //   i. Return element.
1451     int64_t newLen = len - 1;
1452     JSHandle<JSTaggedValue> element(thread, ElementAccessor::Get(thread, thisObjHandle, newLen));
1453     // BuiltinsSharedArray::GetElementByKey(thread, thisObjHandle, newLen));
1454     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1455     uint32_t capacity = ElementAccessor::GetElementsLength(thisObjHandle);
1456     if (TaggedArray::ShouldTrim(capacity, newLen)) {
1457         TaggedArray *elements = TaggedArray::Cast(thisObjHandle->GetElements().GetTaggedObject());
1458         elements->Trim(thread, newLen);
1459     }
1460 
1461     JSSharedArray::Cast(*thisObjHandle)->SetArrayLength(thread, newLen);
1462     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1463 
1464     return element.GetTaggedValue();
1465 }
1466 
1467 // 22.1.3.17 Array.prototype.push ( ...items )
Push(EcmaRuntimeCallInfo * argv)1468 JSTaggedValue BuiltinsSharedArray::Push(EcmaRuntimeCallInfo *argv)
1469 {
1470     ASSERT(argv);
1471     BUILTINS_API_TRACE(argv->GetThread(), SharedArray, Push);
1472     JSThread *thread = argv->GetThread();
1473     [[maybe_unused]] EcmaHandleScope handleScope(thread);
1474 
1475     // thisHandle variable declare this Macro
1476     ARRAY_CHECK_SHARED_ARRAY("The push method cannot be bound.")
1477 
1478     [[maybe_unused]] ConcurrentApiScope<JSSharedArray, ModType::WRITE> scope(thread, thisHandle);
1479     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1480     // 6. Let argCount be the number of elements in items.
1481     uint32_t argc = argv->GetArgsNumber();
1482 
1483     // 1. Let O be ToObject(this value).
1484     JSHandle<JSObject> thisObjHandle = JSTaggedValue::ToObject(thread, thisHandle);
1485     // 2. ReturnIfAbrupt(O).
1486     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1487 
1488     // 3. Let len be ToLength(Get(O, "length")).
1489     int64_t len = ArrayHelper::GetArrayLength(thread, thisHandle);
1490     // 4. ReturnIfAbrupt(len).
1491     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1492     // 7. If len + argCount > 253-1, throw a TypeError exception.
1493     if ((len + static_cast<int64_t>(argc)) > base::MAX_SAFE_INTEGER) {
1494         THROW_TYPE_ERROR_AND_RETURN(thread, "out of range.", JSTaggedValue::Exception());
1495     }
1496 
1497     uint32_t newLength = argc + static_cast<uint32_t>(len);
1498     TaggedArray *element = TaggedArray::Cast(thisObjHandle->GetElements().GetTaggedObject());
1499     if (newLength > ElementAccessor::GetElementsLength(thisObjHandle)) {
1500         element = *JSObject::GrowElementsCapacity(thread, thisObjHandle, newLength, true);
1501     }
1502 
1503     // 8. Repeat, while items is not empty
1504     //   a. Remove the first element from items and let E be the value of the element.
1505     //   b. Let setStatus be Set(O, ToString(len), E, true).
1506     //   c. ReturnIfAbrupt(setStatus).
1507     //   d. Let len be len+1.
1508     uint32_t k = 0;
1509     while (k < argc) {
1510         JSHandle<JSTaggedValue> kValue = GetCallArg(argv, k);
1511         if (!kValue->IsSharedType()) {
1512             auto error = ContainerError::ParamError(thread, "Parameter error.Only accept sendable value.");
1513             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
1514         }
1515         element->Set(thread, len, kValue);
1516         k++;
1517         len++;
1518     }
1519 
1520     // 9. Let setStatus be Set(O, "length", len, true).
1521     JSSharedArray::Cast(*thisObjHandle)->SetArrayLength(thread, len);
1522     // 10. ReturnIfAbrupt(setStatus).
1523     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1524 
1525     // 11. Return len.
1526     return GetTaggedDouble(len);
1527 }
1528 
ReduceUnStableJSArray(JSThread * thread,JSHandle<JSTaggedValue> & thisHandle,JSHandle<JSObject> & thisObjHandle,int64_t k,int64_t len,JSMutableHandle<JSTaggedValue> & accumulator,JSHandle<JSTaggedValue> & callbackFnHandle)1529 JSTaggedValue BuiltinsSharedArray::ReduceUnStableJSArray(JSThread *thread, JSHandle<JSTaggedValue> &thisHandle,
1530     JSHandle<JSObject> &thisObjHandle, int64_t k, int64_t len, JSMutableHandle<JSTaggedValue> &accumulator,
1531     JSHandle<JSTaggedValue> &callbackFnHandle)
1532 {
1533     JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
1534     JSMutableHandle<JSTaggedValue> kValue(thread, JSTaggedValue::Hole());
1535     JSTaggedValue callResult = JSTaggedValue::Undefined();
1536     JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
1537     const int32_t argsLength = 4; // 4: «accumulator, kValue, k, O»
1538     while (k < len) {
1539         kValue.Update(BuiltinsSharedArray::GetElementByKey(thread, thisObjHandle, k));
1540         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1541         key.Update(JSTaggedValue(k));
1542         EcmaRuntimeCallInfo *info =
1543             EcmaInterpreter::NewRuntimeCallInfo(thread, callbackFnHandle, undefined, undefined, argsLength);
1544         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1545         ASSERT(info != nullptr);
1546         info->SetCallArg(accumulator.GetTaggedValue(), kValue.GetTaggedValue(),
1547                          key.GetTaggedValue(), thisHandle.GetTaggedValue());
1548         callResult = JSFunction::Call(info);
1549         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1550         accumulator.Update(callResult);
1551         k++;
1552     }
1553 
1554     return accumulator.GetTaggedValue();
1555 }
1556 
1557 // 22.1.3.18 Array.prototype.reduce ( callbackfn [ , initialValue ] )
Reduce(EcmaRuntimeCallInfo * argv)1558 JSTaggedValue BuiltinsSharedArray::Reduce(EcmaRuntimeCallInfo *argv)
1559 {
1560     ASSERT(argv);
1561     BUILTINS_API_TRACE(argv->GetThread(), SharedArray, Reduce);
1562     JSThread *thread = argv->GetThread();
1563     [[maybe_unused]] EcmaHandleScope handleScope(thread);
1564 
1565     uint32_t argc = argv->GetArgsNumber();
1566     // 1. Let O be ToObject(this value).
1567     // thisHandle variable declare this Macro
1568     ARRAY_CHECK_SHARED_ARRAY("The reduce method cannot be bound.")
1569 
1570     JSHandle<JSObject> thisObjHandle = JSTaggedValue::ToObject(thread, thisHandle);
1571     [[maybe_unused]] ConcurrentApiScope<JSSharedArray> scope(thread, thisHandle);
1572     // 2. ReturnIfAbrupt(O).
1573     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1574 
1575     // 3. Let len be ToLength(Get(O, "length")).
1576     int64_t len = ArrayHelper::GetLength(thread, thisHandle);
1577     // 4. ReturnIfAbrupt(len).
1578     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1579 
1580     // 5. If IsCallable(callbackfn) is false, throw a TypeError exception.
1581     JSHandle<JSTaggedValue> callbackFnHandle = GetCallArg(argv, 0);
1582     if (!callbackFnHandle->IsCallable()) {
1583         THROW_TYPE_ERROR_AND_RETURN(thread, "the callbackfun is not callable.", JSTaggedValue::Exception());
1584     }
1585 
1586     // 6. If len is 0 and initialValue is not present, throw a TypeError exception.
1587     const int32_t argcLimitLength = 2; // argc limit length of the number parameters
1588     if (len == 0 && argc < argcLimitLength) {  // 2:2 means the number of parameters
1589         THROW_TYPE_ERROR_AND_RETURN(thread, "out of range.", JSTaggedValue::Exception());
1590     }
1591 
1592     // 7. Let k be len-1.
1593     int64_t k = 0;
1594     // 8. If initialValue is present, then
1595     //   a. Set accumulator to initialValue.
1596     // 9. Else initialValue is not present,
1597     //   a. Get last element initial accumulator
1598     JSMutableHandle<JSTaggedValue> accumulator(thread, JSTaggedValue::Undefined());
1599     if (argc >= argcLimitLength) { // 2:2 means the number of parameters
1600         accumulator.Update(GetCallArg(argv, 1).GetTaggedValue());
1601     } else if (len > 0) {
1602         accumulator.Update(BuiltinsSharedArray::GetElementByKey(thread, thisObjHandle, k));
1603         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1604         k++;
1605     }
1606 
1607     auto opResult = ReduceUnStableJSArray(thread, thisHandle, thisObjHandle, k, len, accumulator, callbackFnHandle);
1608     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1609 
1610     return opResult;
1611 }
1612 
1613 // 22.1.3.21 Array.prototype.shift ( )
Shift(EcmaRuntimeCallInfo * argv)1614 JSTaggedValue BuiltinsSharedArray::Shift(EcmaRuntimeCallInfo *argv)
1615 {
1616     ASSERT(argv);
1617     BUILTINS_API_TRACE(argv->GetThread(), SharedArray, Shift);
1618     JSThread *thread = argv->GetThread();
1619     [[maybe_unused]] EcmaHandleScope handleScope(thread);
1620 
1621     // 1. Let O be ToObject(this value).
1622     // thisHandle variable declare this Macro
1623     ARRAY_CHECK_SHARED_ARRAY("The shift method cannot be bound.")
1624 
1625     JSHandle<JSObject> thisObjHandle = JSTaggedValue::ToObject(thread, thisHandle);
1626     [[maybe_unused]] ConcurrentApiScope<JSSharedArray, ModType::WRITE> scope(thread, thisHandle);
1627     // 2. ReturnIfAbrupt(O).
1628     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1629 
1630     // 3. Let len be ToLength(Get(O, "length")).
1631     int64_t len = ArrayHelper::GetArrayLength(thread, thisHandle);
1632     // 4. ReturnIfAbrupt(len).
1633     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1634     // 5. If len is zero, then
1635     //   a. Let setStatus be Set(O, "length", 0, true).
1636     //   b. ReturnIfAbrupt(setStatus).
1637     //   c. Return undefined.
1638     if (len == 0) {
1639         JSHandle<JSTaggedValue> zeroLenHandle(thread, JSTaggedValue(len));
1640         JSSharedArray::LengthSetter(thread, thisObjHandle, zeroLenHandle, false);
1641         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1642         return JSTaggedValue::Undefined();
1643     }
1644 
1645     // 6. Let first be Get(O, "0").
1646     JSHandle<JSTaggedValue> firstValue(thread, BuiltinsSharedArray::GetElementByKey(thread, thisObjHandle, 0));
1647 
1648     // 7. ReturnIfAbrupt(first).
1649     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1650 
1651     // 8. Let k be 1.
1652     // 9. Repeat, while k < len
1653     //   a. Let from be ToString(k).
1654     //   b. Let to be ToString(k–1).
1655     //   c. Let fromPresent be HasProperty(O, from).
1656     //   d. ReturnIfAbrupt(fromPresent).
1657     //   e. If fromPresent is true, then
1658     //     i. Let fromVal be Get(O, from).
1659     //     ii. ReturnIfAbrupt(fromVal).
1660     //     iii. Let setStatus be Set(O, to, fromVal, true).
1661     //     iv. ReturnIfAbrupt(setStatus).
1662     //   f. Else fromPresent is false,
1663     //     i. Let deleteStatus be DeletePropertyOrThrow(O, to).
1664     //     ii. ReturnIfAbrupt(deleteStatus).
1665     //   g. Increase k by 1.
1666     TaggedArray *element = TaggedArray::Cast(thisObjHandle->GetElements().GetTaggedObject());
1667     int64_t newLen = len - 1;
1668     element->Copy<true, true>(thread, 0, 1, element, newLen);
1669     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1670 
1671     uint32_t capacity = ElementAccessor::GetElementsLength(thisObjHandle);
1672     if (TaggedArray::ShouldTrim(capacity, newLen)) {
1673         TaggedArray *elements = TaggedArray::Cast(thisObjHandle->GetElements().GetTaggedObject());
1674         elements->Trim(thread, newLen);
1675     }
1676 
1677     // 12. Let setStatus be Set(O, "length", len–1, true).
1678     JSHandle<JSTaggedValue> newLenHandle(thread, JSTaggedValue(newLen));
1679     JSSharedArray::LengthSetter(thread, thisObjHandle, newLenHandle, true);
1680     // 13. ReturnIfAbrupt(setStatus).
1681     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1682 
1683     // 14. Return first.
1684     return firstValue.GetTaggedValue();
1685 }
1686 
1687 // 22.1.3.22 Array.prototype.slice (start, end)
Slice(EcmaRuntimeCallInfo * argv)1688 JSTaggedValue BuiltinsSharedArray::Slice(EcmaRuntimeCallInfo *argv)
1689 {
1690     BUILTINS_API_TRACE(argv->GetThread(), SharedArray, Slice);
1691     ASSERT(argv);
1692     JSThread *thread = argv->GetThread();
1693     [[maybe_unused]] EcmaHandleScope handleScope(thread);
1694 
1695     // 1. Let O be ToObject(this value).
1696     // thisHandle variable declare this Macro
1697     ARRAY_CHECK_SHARED_ARRAY("The slice method cannot be bound.")
1698 
1699     JSHandle<JSObject> thisObjHandle = JSTaggedValue::ToObject(thread, thisHandle);
1700     [[maybe_unused]] ConcurrentApiScope<JSSharedArray> scope(thread, thisHandle);
1701     // 2. ReturnIfAbrupt(O).
1702     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1703 
1704     // 3. Let len be ToLength(Get(O, "length")).
1705     int64_t len = ArrayHelper::GetArrayLength(thread, thisHandle);
1706     // 4. ReturnIfAbrupt(len).
1707     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1708 
1709     // 5. Let relativeStart be ToInteger(start).
1710     int64_t start = GetNumberArgVal(thread, argv, 0, len, 0);
1711     // 6. ReturnIfAbrupt(relativeStart).
1712     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1713 
1714     // 8. If end is undefined, let relativeEnd be len; else let relativeEnd be ToInteger(end).
1715     // 9. ReturnIfAbrupt(relativeEnd).
1716     // 10. If relativeEnd < 0, let final be max((len + relativeEnd),0); else let final be min(relativeEnd, len).
1717     int64_t final = GetNumberArgVal(thread, argv, 1, len, len);
1718     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1719 
1720     // 11. Let count be max(final – k, 0).
1721     int64_t count = final > start ? (final - start) : 0;
1722 
1723     // 12. Let A be ArraySpeciesCreate(O, count).
1724     JSTaggedValue newArray =
1725         JSSharedArray::ArraySpeciesCreate(thread, thisObjHandle, JSTaggedNumber(static_cast<double>(count)));
1726     // 13. ReturnIfAbrupt(A).
1727     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1728     if (count == 0) {
1729         return newArray;
1730     }
1731     JSHandle<JSObject> newArrayHandle(thread, newArray);
1732     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1733     JSHandle<TaggedArray> eleArray = factory->NewTaggedArray(count, JSTaggedValue::Undefined(),
1734                                                              MemSpaceType::SHARED_OLD_SPACE);
1735     // 14. Let n be 0.
1736     // 15. Repeat, while start < final
1737     //   a. Let Pk be ToString(start).
1738     //   b. Let kPresent be HasProperty(O, Pk).
1739     //   c. ReturnIfAbrupt(kPresent).
1740     //   d. If kPresent is true, then
1741     //     i. Let kValue be Get(O, Pk).
1742     //     ii. ReturnIfAbrupt(kValue).
1743     //     iii. Let status be CreateDataPropertyOrThrow(A, ToString(n), kValue ).
1744     //     iv. ReturnIfAbrupt(status).
1745     //   e. Increase start by 1.
1746     //   f. Increase n by 1.
1747     int64_t n = 0;
1748     JSMutableHandle<JSTaggedValue> kValueHandle(thread, JSTaggedValue::Undefined());
1749     while (start < final) {
1750         kValueHandle.Update(BuiltinsSharedArray::GetElementByKey(thread, thisObjHandle, start));
1751         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1752         eleArray->Set(thread, n, kValueHandle);
1753         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1754         start++;
1755         n++;
1756     }
1757 
1758     newArrayHandle->SetElements(thread, eleArray);
1759     // 16. Let setStatus be Set(A, "length", n, true).
1760     JSHandle<JSTaggedValue> newLenHandle(thread, JSTaggedValue(n));
1761     JSSharedArray::LengthSetter(thread, newArrayHandle, newLenHandle, true);
1762     // 17. ReturnIfAbrupt(setStatus).
1763     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1764 
1765     // 18. Return A.
1766     return newArrayHandle.GetTaggedValue();
1767 }
1768 
1769 // 22.1.3.24 Array.prototype.sort (comparefn)
Sort(EcmaRuntimeCallInfo * argv)1770 JSTaggedValue BuiltinsSharedArray::Sort(EcmaRuntimeCallInfo *argv)
1771 {
1772     ASSERT(argv);
1773     JSThread *thread = argv->GetThread();
1774     BUILTINS_API_TRACE(thread, SharedArray, Sort);
1775     [[maybe_unused]] EcmaHandleScope handleScope(thread);
1776 
1777     // 1. If comparefn is not undefined and IsCallable(comparefn) is false, throw a TypeError exception.
1778     JSHandle<JSTaggedValue> callbackFnHandle = GetCallArg(argv, 0);
1779     if (!callbackFnHandle->IsUndefined() && !callbackFnHandle->IsCallable()) {
1780         THROW_TYPE_ERROR_AND_RETURN(thread, "Callable is false", JSTaggedValue::Exception());
1781     }
1782 
1783     // 2. Let obj be ToObject(this value).
1784     // thisHandle variable declare this Macro
1785     ARRAY_CHECK_SHARED_ARRAY("The sort method cannot be bound.")
1786 
1787     JSHandle<JSObject> thisObjHandle = JSTaggedValue::ToObject(thread, thisHandle);
1788     [[maybe_unused]] ConcurrentApiScope<JSSharedArray, ModType::WRITE> scope(thread, thisHandle);
1789     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1790 
1791     JSHandle<TaggedArray> elements(thread, thisObjHandle->GetElements());
1792     base::TimSort::Sort(thread, elements, callbackFnHandle);
1793     return thisObjHandle.GetTaggedValue();
1794 }
1795 
1796 // 22.1.3.25 Array.prototype.splice (start, deleteCount , ...items )
1797 // NOLINTNEXTLINE(readability-function-size)
Splice(EcmaRuntimeCallInfo * argv)1798 JSTaggedValue BuiltinsSharedArray::Splice(EcmaRuntimeCallInfo *argv)
1799 {
1800     ASSERT(argv);
1801     BUILTINS_API_TRACE(argv->GetThread(), SharedArray, Splice);
1802     JSThread *thread = argv->GetThread();
1803     [[maybe_unused]] EcmaHandleScope handleScope(thread);
1804     uint32_t argc = argv->GetArgsNumber();
1805     // 1. Let O be ToObject(this value).
1806     // thisHandle variable declare this Macro
1807     ARRAY_CHECK_SHARED_ARRAY("The splice method cannot be bound.")
1808 
1809     JSHandle<JSObject> thisObjHandle = JSTaggedValue::ToObject(thread, thisHandle);
1810     [[maybe_unused]] ConcurrentApiScope<JSSharedArray, ModType::WRITE> scope(
1811         thread, thisHandle);
1812     // 2. ReturnIfAbrupt(O).
1813     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1814     // 3. Let len be ToLength(Get(O, "length")).
1815     int64_t len = ArrayHelper::GetArrayLength(thread, thisHandle);
1816     // 4. ReturnIfAbrupt(len).
1817     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1818     // 5. Let relativeStart be ToInteger(start).
1819     int64_t start = 0;
1820     int64_t insertCount = 0;
1821     int64_t actualDeleteCount = 0;
1822     if (argc > 0) {
1823         // 6. ReturnIfAbrupt(relativeStart).
1824         start = GetNumberArgVal(thread, argv, 0, len, 0);
1825         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1826         actualDeleteCount = len - start;
1827     }
1828     // 8. If the number of actual arguments is 0, then
1829     //   a. Let insertCount be 0.
1830     //   b. Let actualDeleteCount be 0.
1831     // 9. Else if the number of actual arguments is 1, then
1832     //   a. Let insertCount be 0.
1833     //   b. Let actualDeleteCount be len – actualStart.
1834     // 10. Else,
1835     //   a. Let insertCount be the number of actual arguments minus 2.
1836     //   b. Let dc be ToInteger(deleteCount).
1837     //   c. ReturnIfAbrupt(dc).
1838     //   d. Let actualDeleteCount be min(max(dc,0), len – actualStart).
1839     if (argc > 1) {
1840         insertCount = argc - 2;  // 2:2 means there are two arguments before the insert items.
1841         JSHandle<JSTaggedValue> msg1 = GetCallArg(argv, 1);
1842         JSTaggedNumber argDeleteCount = JSTaggedValue::ToInteger(thread, msg1);
1843         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1844         double deleteCount = argDeleteCount.GetNumber();
1845         deleteCount = deleteCount > 0 ? deleteCount : 0;
1846         actualDeleteCount = deleteCount < (len - start) ? deleteCount : len - start;
1847     }
1848     // 11. If len+insertCount−actualDeleteCount > 253-1, throw a TypeError exception.
1849     if (len + insertCount - actualDeleteCount > base::MAX_SAFE_INTEGER) {
1850         THROW_TYPE_ERROR_AND_RETURN(thread, "out of range.", JSTaggedValue::Exception());
1851     }
1852     // 12. Let A be ArraySpeciesCreate(O, actualDeleteCount).
1853     JSTaggedValue newArray = JSSharedArray::ArraySpeciesCreate(
1854         thread, thisObjHandle, JSTaggedNumber(static_cast<double>(actualDeleteCount)));
1855     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1856     JSHandle<JSObject> newArrayHandle(thread, newArray);
1857 
1858     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1859     JSHandle<TaggedArray> DelArrEle = factory->NewTaggedArray(actualDeleteCount, JSTaggedValue::Undefined(),
1860                                                               MemSpaceType::SHARED_OLD_SPACE);
1861     TaggedArray *oldElement = TaggedArray::Cast(thisObjHandle->GetElements().GetTaggedObject());
1862     // 14. Let k be 0.
1863     // 15. Repeat, while k < actualDeleteCount
1864     //   a. Let from be ToString(actualStart+k).
1865     //   b. Let fromPresent be HasProperty(O, from).
1866     //   d. If fromPresent is true, then
1867     //     i. Let fromValue be Get(O, from).
1868     //     iii. Let status be CreateDataPropertyOrThrow(A, ToString(k), fromValue).
1869     //   e. Increase k by 1.
1870     DelArrEle->Copy(thread, 0, start, oldElement, actualDeleteCount);
1871     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1872 
1873     newArrayHandle->SetElements(thread, DelArrEle);
1874     // 16. Let setStatus be Set(A, "length", actualDeleteCount, true).
1875     JSHandle<JSTaggedValue> deleteCountHandle(thread, JSTaggedValue(actualDeleteCount));
1876     JSSharedArray::LengthSetter(thread, newArrayHandle, deleteCountHandle, true);
1877     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1878 
1879     int64_t newLen = len - actualDeleteCount + insertCount;
1880     JSHandle<TaggedArray> eleArray = factory->NewTaggedArray(newLen, JSTaggedValue::Undefined(),
1881                                                              MemSpaceType::SHARED_OLD_SPACE);
1882     if (start > 0) {
1883         eleArray->Copy(thread, 0, 0, oldElement, start);
1884         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1885     }
1886 
1887     eleArray->Copy(thread, start + insertCount, start + actualDeleteCount, oldElement,
1888                    len - actualDeleteCount - start);
1889     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1890 
1891     // 23. Repeat, while items is not empty
1892     JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
1893     for (uint32_t i = 2; i < argc; i++) {
1894         JSHandle<JSTaggedValue> itemValue = GetCallArg(argv, i);
1895         if (!itemValue->IsSharedType()) {
1896             auto error = ContainerError::ParamError(thread, "Parameter error.Only accept sendable value.");
1897             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
1898         }
1899         eleArray->Set(thread, start, itemValue);
1900         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1901         start++;
1902     }
1903 
1904     thisObjHandle->SetElements(thread, eleArray);
1905     // 24. Let setStatus be Set(O, "length", len – actualDeleteCount + itemCount, true).
1906     JSHandle<JSTaggedValue> newLenHandle(thread, JSTaggedValue(newLen));
1907     JSSharedArray::LengthSetter(thread, thisObjHandle, newLenHandle, true);
1908     // 25. ReturnIfAbrupt(setStatus).
1909     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1910     // 26. Return A.
1911     return newArrayHandle.GetTaggedValue();
1912 }
1913 
1914 // 22.1.3.27 Array.prototype.toString ( )
ToString(EcmaRuntimeCallInfo * argv)1915 JSTaggedValue BuiltinsSharedArray::ToString(EcmaRuntimeCallInfo *argv)
1916 {
1917     ASSERT(argv);
1918     BUILTINS_API_TRACE(argv->GetThread(), SharedArray, ToString);
1919     JSThread *thread = argv->GetThread();
1920     [[maybe_unused]] EcmaHandleScope handleScope(thread);
1921     auto ecmaVm = thread->GetEcmaVM();
1922 
1923     // 1. Let array be ToObject(this value).
1924     // thisHandle variable declare this Macro
1925     ARRAY_CHECK_SHARED_ARRAY("The toString method cannot be bound.")
1926 
1927     JSHandle<JSObject> thisObjHandle = JSTaggedValue::ToObject(thread, thisHandle);
1928     [[maybe_unused]] ConcurrentApiScope<JSSharedArray> scope(thread, thisHandle);
1929     // 2. ReturnIfAbrupt(array).
1930     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1931     JSHandle<JSTaggedValue> thisObjVal(thisObjHandle);
1932 
1933     // 3. Let func be Get(array, "join").
1934     JSHandle<JSTaggedValue> joinKey = thread->GlobalConstants()->GetHandledJoinString();
1935     JSHandle<JSTaggedValue> callbackFnHandle = JSTaggedValue::GetProperty(thread, thisObjVal, joinKey).GetValue();
1936 
1937     // 4. ReturnIfAbrupt(func).
1938     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1939 
1940     // 5. If IsCallable(func) is false, let func be the intrinsic function %ObjProto_toString% (19.1.3.6).
1941     if (!callbackFnHandle->IsCallable()) {
1942         JSHandle<GlobalEnv> env = ecmaVm->GetGlobalEnv();
1943         JSHandle<JSTaggedValue> objectPrototype = env->GetObjectFunctionPrototype();
1944         JSHandle<JSTaggedValue> toStringKey = thread->GlobalConstants()->GetHandledToStringString();
1945         callbackFnHandle = JSTaggedValue::GetProperty(thread, objectPrototype, toStringKey).GetValue();
1946         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1947     }
1948     const uint32_t argsLength = argv->GetArgsNumber();
1949     JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
1950     EcmaRuntimeCallInfo *info =
1951         EcmaInterpreter::NewRuntimeCallInfo(thread, callbackFnHandle, thisObjVal, undefined, argsLength);
1952     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1953     ASSERT(info != nullptr);
1954     info->SetCallArg(argsLength, 0, argv, 0);
1955     auto opResult = JSFunction::Call(info);
1956     return opResult;
1957 }
1958 
1959 // Array.prototype.toLocaleString ( [ reserved1 [ , reserved2 ] ] )
ToLocaleString(EcmaRuntimeCallInfo * argv)1960 JSTaggedValue BuiltinsSharedArray::ToLocaleString(EcmaRuntimeCallInfo *argv)
1961 {
1962     ASSERT(argv);
1963     BUILTINS_API_TRACE(argv->GetThread(), SharedArray, ToLocaleString);
1964     JSThread *thread = argv->GetThread();
1965     [[maybe_unused]] EcmaHandleScope handleScope(thread);
1966 
1967     auto ecmaVm = thread->GetEcmaVM();
1968     ObjectFactory *factory = ecmaVm->GetFactory();
1969 
1970     ARRAY_CHECK_SHARED_ARRAY("The ToLocaleString method cannot be bound.")
1971     // 1. Let O be ToObject(this value).
1972     [[maybe_unused]] ConcurrentApiScope<JSSharedArray> scope(thread, thisHandle);
1973     // add this to join stack to avoid circular call
1974     auto context = thread->GetCurrentEcmaContext();
1975     bool noCircular = context->JoinStackPushFastPath(thisHandle);
1976     if (!noCircular) {
1977         return factory->GetEmptyString().GetTaggedValue();
1978     }
1979     // 2. ReturnIfAbrupt(O).
1980     RETURN_EXCEPTION_AND_POP_JOINSTACK(thread, thisHandle);
1981     // 3. Let len be ToLength(Get(O, "length")).
1982     int64_t len = ArrayHelper::GetLength(thread, thisHandle);
1983     // 4. ReturnIfAbrupt(len).
1984     RETURN_EXCEPTION_AND_POP_JOINSTACK(thread, thisHandle);
1985     // 6. If len is zero, return the empty String.
1986     if (len == 0) {
1987         // pop this from join stack
1988         context->JoinStackPopFastPath(thisHandle);
1989         return GetTaggedString(thread, "");
1990     }
1991 
1992     return ToLocaleStringInternalHandle(argv, thread, context, factory, thisHandle, len);
1993 }
1994 
ToLocaleStringInternalHandle(EcmaRuntimeCallInfo * argv,JSThread * thread,EcmaContext * context,ObjectFactory * factory,const JSHandle<JSTaggedValue> & thisHandle,int64_t len)1995 JSTaggedValue BuiltinsSharedArray::ToLocaleStringInternalHandle(EcmaRuntimeCallInfo *argv, JSThread *thread,
1996     EcmaContext *context, ObjectFactory *factory, const JSHandle<JSTaggedValue> &thisHandle, int64_t len)
1997 {
1998     JSHandle<JSObject> thisObjHandle(thread, JSObject::Cast(thisHandle.GetTaggedValue()));
1999     // Inject locales and options argument into a taggedArray
2000     JSHandle<JSTaggedValue> locales = GetCallArg(argv, 0);
2001     JSHandle<JSTaggedValue> options = GetCallArg(argv, 1);
2002     // 7. Let firstElement be Get(array, "0").
2003     // 8. ReturnIfAbrupt(firstElement).
2004     // 9. If firstElement is undefined or null, then
2005     //   a. Let R be the empty String.
2006     // 10. Else
2007     //   a. Let R be ToString(Invoke(firstElement, "toLocaleString")).
2008     //   b. ReturnIfAbrupt(R).
2009     // 11. Let k be 1.
2010     // 12. Repeat, while k < len
2011     //   a. Let S be a String value produced by concatenating R and separator.
2012     //   b. Let nextElement be Get(array, ToString(k)).
2013     //   c. ReturnIfAbrupt(nextElement).
2014     //   d. If nextElement is undefined or null, then
2015     //     i. Let R be the empty String.
2016     //   e. Else
2017     //     i. Let R be ToString(Invoke(nextElement, "toLocaleString")).
2018     //     ii. ReturnIfAbrupt(R).
2019     //   f. Let R be a String value produced by concatenating S and R.
2020     //   g. Increase k by 1.
2021     CString concatStr;
2022     auto globalConst = thread->GlobalConstants();
2023     JSHandle<JSTaggedValue> key = globalConst->GetHandledToLocaleStringString();
2024     JSHandle<JSTaggedValue> undefined = globalConst->GetHandledUndefined();
2025     JSMutableHandle<JSTaggedValue> nextValue(thread, JSTaggedValue::Undefined());
2026     JSMutableHandle<JSTaggedValue> nextHandle(thread, JSTaggedValue::Undefined());
2027     JSTaggedValue next = globalConst->GetEmptyString();
2028     for (int64_t k = 0; k < len; k++) {
2029         nextValue.Update(BuiltinsSharedArray::GetElementByKey(thread, thisObjHandle, k));
2030         RETURN_EXCEPTION_AND_POP_JOINSTACK(thread, thisHandle);
2031         if (!nextValue->IsUndefined() && !nextValue->IsNull()) {
2032             // 2: two args
2033             EcmaRuntimeCallInfo *info =
2034                 EcmaInterpreter::NewRuntimeCallInfo(thread, undefined, nextValue, undefined, 2);
2035             RETURN_EXCEPTION_AND_POP_JOINSTACK(thread, thisHandle);
2036             ASSERT(info != nullptr);
2037             info->SetCallArg(locales.GetTaggedValue(), options.GetTaggedValue());
2038             JSTaggedValue callResult = JSFunction::Invoke(info, key);
2039             RETURN_EXCEPTION_AND_POP_JOINSTACK(thread, thisHandle);
2040             next = callResult;
2041         } else {
2042             next = globalConst->GetEmptyString();
2043         }
2044         nextHandle.Update(next);
2045         JSHandle<EcmaString> nextStringHandle = JSTaggedValue::ToString(thread, nextHandle);
2046         RETURN_EXCEPTION_AND_POP_JOINSTACK(thread, thisHandle);
2047         CString nextString = ConvertToString(*nextStringHandle);
2048         if (k > 0) {
2049             concatStr += STRING_SEPERATOR;
2050             concatStr += nextString;
2051             continue;
2052         }
2053         concatStr += nextString;
2054     }
2055 
2056     // pop this from join stack
2057     context->JoinStackPopFastPath(thisHandle);
2058     // 13. Return R.
2059     return factory->NewFromUtf8(concatStr).GetTaggedValue();
2060 }
2061 
2062 // 22.1.3.28 Array.prototype.unshift ( ...items )
Unshift(EcmaRuntimeCallInfo * argv)2063 JSTaggedValue BuiltinsSharedArray::Unshift(EcmaRuntimeCallInfo *argv)
2064 {
2065     ASSERT(argv);
2066     BUILTINS_API_TRACE(argv->GetThread(), SharedArray, Unshift);
2067     JSThread *thread = argv->GetThread();
2068     [[maybe_unused]] EcmaHandleScope handleScope(thread);
2069 
2070     // 5. Let argCount be the number of actual arguments.
2071     int64_t argc = argv->GetArgsNumber();
2072 
2073     // 1. Let O be ToObject(this value).
2074     // thisHandle variable declare this Macro
2075     ARRAY_CHECK_SHARED_ARRAY("The unshift method cannot be bound.")
2076 
2077     JSHandle<JSObject> thisObjHandle = JSTaggedValue::ToObject(thread, thisHandle);
2078     [[maybe_unused]] ConcurrentApiScope<JSSharedArray, ModType::WRITE> scope(thread, thisHandle);
2079     // 2. ReturnIfAbrupt(O).
2080     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2081 
2082     // 3. Let len be ToLength(Get(O, "length")).
2083     int64_t len = ArrayHelper::GetArrayLength(thread, thisHandle);
2084     // 4. ReturnIfAbrupt(len).
2085     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2086 
2087     int64_t newLen = len + argc;
2088     if (argc > 0) {
2089         if (newLen > base::MAX_SAFE_INTEGER) {
2090             THROW_TYPE_ERROR_AND_RETURN(thread, "out of range.", JSTaggedValue::Exception());
2091         }
2092 
2093         TaggedArray *element = TaggedArray::Cast(thisObjHandle->GetElements().GetTaggedObject());
2094         if (newLen > ElementAccessor::GetElementsLength(thisObjHandle)) {
2095             element = *JSObject::GrowElementsCapacity(thread, thisObjHandle, newLen, true);
2096         }
2097         element->Copy<true, true>(thread, argc, 0, element, len);
2098         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2099 
2100         int64_t j = 0;
2101         JSMutableHandle<JSTaggedValue> toValue(thread, JSTaggedValue::Undefined());
2102         while (j < argc) {
2103             toValue.Update(GetCallArg(argv, j));
2104             if (!toValue->IsSharedType()) {
2105                 auto error = ContainerError::ParamError(thread, "Parameter error.Only accept sendable value.");
2106                 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
2107             }
2108             element->Set(thread, j, toValue);
2109             j++;
2110         }
2111     }
2112 
2113     // 7. Let setStatus be Set(O, "length", len+argCount, true).
2114     JSHandle<JSTaggedValue> newLenHandle(thread, JSTaggedValue(newLen));
2115     JSSharedArray::LengthSetter(thread, thisObjHandle, newLenHandle, true);
2116     // 8. ReturnIfAbrupt(setStatus).
2117     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2118 
2119     // 9. Return len+argCount.
2120     return GetTaggedDouble(newLen);
2121 }
2122 
2123 // 22.1.3.29 Array.prototype.values ( )
Values(EcmaRuntimeCallInfo * argv)2124 JSTaggedValue BuiltinsSharedArray::Values(EcmaRuntimeCallInfo *argv)
2125 {
2126     ASSERT(argv);
2127     BUILTINS_API_TRACE(argv->GetThread(), SharedArray, Values);
2128     JSThread *thread = argv->GetThread();
2129     [[maybe_unused]] EcmaHandleScope handleScope(thread);
2130 
2131     // thisHandle variable declare this Macro
2132     ARRAY_CHECK_SHARED_ARRAY("The values method cannot be bound.")
2133 
2134     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
2135     // 1. Let O be ToObject(this value).
2136     // 2. ReturnIfAbrupt(O).
2137     JSHandle<JSObject> self = JSTaggedValue::ToObject(thread, GetThis(argv));
2138     [[maybe_unused]] ConcurrentApiScope<JSSharedArray> scope(thread, thisHandle);
2139     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2140     // 3. Return CreateArrayIterator(O, "value").
2141     JSHandle<JSSharedArrayIterator> iter(factory->NewJSSharedArrayIterator(self, IterationKind::VALUE));
2142     return iter.GetTaggedValue();
2143 }
2144 // 22.1.3.31 Array.prototype [ @@unscopables ]
Unscopables(EcmaRuntimeCallInfo * argv)2145 JSTaggedValue BuiltinsSharedArray::Unscopables(EcmaRuntimeCallInfo *argv)
2146 {
2147     JSThread *thread = argv->GetThread();
2148     BUILTINS_API_TRACE(thread, SharedArray, Unscopables);
2149     [[maybe_unused]] EcmaHandleScope handleScope(thread);
2150     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
2151     const GlobalEnvConstants *globalConst = thread->GlobalConstants();
2152 
2153     JSHandle<JSObject> unscopableList = factory->CreateNullJSObject();
2154 
2155     JSHandle<JSTaggedValue> trueVal(thread, JSTaggedValue::True());
2156 
2157     JSHandle<JSTaggedValue> atKey((factory->NewFromASCII("at")));
2158     JSObject::CreateDataProperty(thread, unscopableList, atKey, trueVal);
2159 
2160     JSHandle<JSTaggedValue> copyWithKey = globalConst->GetHandledCopyWithinString();
2161     JSObject::CreateDataProperty(thread, unscopableList, copyWithKey, trueVal);
2162 
2163     JSHandle<JSTaggedValue> entriesKey = globalConst->GetHandledEntriesString();
2164     JSObject::CreateDataProperty(thread, unscopableList, entriesKey, trueVal);
2165 
2166     JSHandle<JSTaggedValue> fillKey = globalConst->GetHandledFillString();
2167     JSObject::CreateDataProperty(thread, unscopableList, fillKey, trueVal);
2168 
2169     JSHandle<JSTaggedValue> findKey = globalConst->GetHandledFindString();
2170     JSObject::CreateDataProperty(thread, unscopableList, findKey, trueVal);
2171 
2172     JSHandle<JSTaggedValue> findIndexKey = globalConst->GetHandledFindIndexString();
2173     JSObject::CreateDataProperty(thread, unscopableList, findIndexKey, trueVal);
2174 
2175     JSHandle<JSTaggedValue> findLastKey((factory->NewFromASCII("findLast")));
2176     JSObject::CreateDataProperty(thread, unscopableList, findLastKey, trueVal);
2177 
2178     JSHandle<JSTaggedValue> findLastIndexKey((factory->NewFromASCII("findLastIndex")));
2179     JSObject::CreateDataProperty(thread, unscopableList, findLastIndexKey, trueVal);
2180 
2181     JSHandle<JSTaggedValue> flatKey = globalConst->GetHandledFlatString();
2182     JSObject::CreateDataProperty(thread, unscopableList, flatKey, trueVal);
2183 
2184     JSHandle<JSTaggedValue> flatMapKey = globalConst->GetHandledFlatMapString();
2185     JSObject::CreateDataProperty(thread, unscopableList, flatMapKey, trueVal);
2186 
2187     JSHandle<JSTaggedValue> includesKey = globalConst->GetHandledIncludesString();
2188     JSObject::CreateDataProperty(thread, unscopableList, includesKey, trueVal);
2189 
2190     JSHandle<JSTaggedValue> keysKey = globalConst->GetHandledKeysString();
2191     JSObject::CreateDataProperty(thread, unscopableList, keysKey, trueVal);
2192 
2193     JSHandle<JSTaggedValue> valuesKey = globalConst->GetHandledValuesString();
2194     JSObject::CreateDataProperty(thread, unscopableList, valuesKey, trueVal);
2195 
2196     JSHandle<JSTaggedValue> toReversedKey((factory->NewFromASCII("toReversed")));
2197     JSObject::CreateDataProperty(thread, unscopableList, toReversedKey, trueVal);
2198 
2199     JSHandle<JSTaggedValue> toSortedKey((factory->NewFromASCII("toSorted")));
2200     JSObject::CreateDataProperty(thread, unscopableList, toSortedKey, trueVal);
2201 
2202     JSHandle<JSTaggedValue> toSplicedKey((factory->NewFromASCII("toSpliced")));
2203     JSObject::CreateDataProperty(thread, unscopableList, toSplicedKey, trueVal);
2204     return unscopableList.GetTaggedValue();
2205 }
2206 
2207 // 23.1.3.13 Array.prototype.includes ( searchElement [ , fromIndex ] )
Includes(EcmaRuntimeCallInfo * argv)2208 JSTaggedValue BuiltinsSharedArray::Includes(EcmaRuntimeCallInfo *argv)
2209 {
2210     ASSERT(argv);
2211     BUILTINS_API_TRACE(argv->GetThread(), SharedArray, Includes);
2212     JSThread *thread = argv->GetThread();
2213     [[maybe_unused]] EcmaHandleScope handleScope(thread);
2214     // 1. Let O be ? ToObject(this value).
2215     // thisHandle variable declare this Macro
2216     ARRAY_CHECK_SHARED_ARRAY("The includes method cannot be bound.")
2217 
2218     JSHandle<JSObject> thisObjHandle = JSTaggedValue::ToObject(thread, thisHandle);
2219     [[maybe_unused]] ConcurrentApiScope<JSSharedArray> scope(thread, thisHandle);
2220     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2221 
2222     uint32_t argc = argv->GetArgsNumber();
2223     JSHandle<JSTaggedValue> thisObjVal(thisObjHandle);
2224     JSHandle<JSTaggedValue> searchElement = GetCallArg(argv, 0);
2225 
2226     // 2. Let len be ? LengthOfArrayLike(O).
2227     int64_t len = ArrayHelper::GetLength(thread, thisObjVal);
2228     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2229     // 3. If len is 0, return false.
2230     if (len == 0) {
2231         return GetTaggedBoolean(false);
2232     }
2233     // 4. Let n be ? ToIntegerOrInfinity(fromIndex).
2234     // 5. Assert: If fromIndex is undefined, then n is 0.
2235     double fromIndex = 0;
2236     if (argc > 1) {
2237         JSHandle<JSTaggedValue> msg1 = GetCallArg(argv, 1);
2238         JSTaggedNumber fromIndexTemp = JSTaggedValue::ToNumber(thread, msg1);
2239         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2240         fromIndex = base::NumberHelper::TruncateDouble(fromIndexTemp.GetNumber());
2241     }
2242 
2243     // 6. If n is +∞, return false.
2244     // 7. Else if n is -∞, set n to 0.
2245     if (fromIndex >= len) {
2246         return GetTaggedBoolean(false);
2247     } else if (fromIndex < -len) {
2248         fromIndex = 0;
2249     }
2250     // 8. If n ≥ 0, then
2251     //     a. Let k be n.
2252     // 9. Else,
2253     //     a. Let k be len + n.
2254     //     b. If k < 0, let k be 0.
2255     int64_t from = (fromIndex >= 0) ? fromIndex : ((len + fromIndex) >= 0 ? len + fromIndex : 0);
2256 
2257     // 10. Repeat, while k < len,
2258     //     a. Let elementK be ? Get(O, ! ToString(!(k))).
2259     //     b. If SameValueZero(searchElement, elementK) is true, return true.
2260     //     c. Set k to k + 1.
2261     JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
2262     JSMutableHandle<JSTaggedValue> kValueHandle(thread, JSTaggedValue::Undefined());
2263     JSHandle<EcmaString> fromStr;
2264     while (from < len) {
2265         kValueHandle.Update(BuiltinsSharedArray::GetElementByKey(thread, thisObjHandle, from));
2266         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2267         if (JSTaggedValue::SameValueZero(searchElement.GetTaggedValue(), kValueHandle.GetTaggedValue())) {
2268             return GetTaggedBoolean(true);
2269         }
2270         from++;
2271     }
2272     // 11. Return false.
2273     return GetTaggedBoolean(false);
2274 }
2275 
2276 // 23.1.3.1 Array.prototype.at ( index )
At(EcmaRuntimeCallInfo * argv)2277 JSTaggedValue BuiltinsSharedArray::At(EcmaRuntimeCallInfo *argv)
2278 {
2279     ASSERT(argv);
2280     BUILTINS_API_TRACE(argv->GetThread(), SharedArray, At);
2281     JSThread *thread = argv->GetThread();
2282     [[maybe_unused]] EcmaHandleScope handleScope(thread);
2283 
2284     // 1. Let O be ToObject(this value).
2285     // thisHandle variable declare this Macro
2286     ARRAY_CHECK_SHARED_ARRAY("The at method cannot be bound.")
2287 
2288     [[maybe_unused]] ConcurrentApiScope<JSSharedArray> scope(thread, thisHandle);
2289     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2290 
2291     JSHandle<JSObject> thisObjHandle = JSTaggedValue::ToObject(thread, thisHandle);
2292     // ReturnIfAbrupt(O).
2293     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2294 
2295     // 2. Let len be ? LengthOfArrayLike(O).
2296     int64_t len = ArrayHelper::GetLength(thread, thisHandle);
2297     // ReturnIfAbrupt(len).
2298     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2299 
2300     // 3. Let index be ? ToIntegerOrInfinity(index).
2301     JSTaggedNumber index = JSTaggedValue::ToInteger(thread, GetCallArg(argv, 0));
2302     // ReturnIfAbrupt(index).
2303     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2304 
2305     // 4. If relativeIndex ≥ 0, then
2306     //     a. Let k be relativeIndex.
2307     // 5. Else,
2308     //     a. Let k be len + relativeIndex.
2309     int64_t relativeIndex = index.GetNumber();
2310     int64_t k = 0;
2311     if (relativeIndex >= 0) {
2312         k = relativeIndex;
2313     } else {
2314         k = len + relativeIndex;
2315     }
2316 
2317     // 6. If k < 0 or k ≥ len, return undefined.
2318     if (k < 0 || k >= len) {
2319         // Return undefined.
2320         return JSTaggedValue::Undefined();
2321     }
2322     // 7. Return ? Get(O, ! ToString(��(k))).
2323     JSHandle<JSTaggedValue> element(thread, BuiltinsSharedArray::GetElementByKey(thread, thisObjHandle, k));
2324     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2325     return element.GetTaggedValue();
2326 }
2327 
2328 // Array.prototype.findLast ( predicate [ , thisArg ] )
FindLast(EcmaRuntimeCallInfo * argv)2329 JSTaggedValue BuiltinsSharedArray::FindLast(EcmaRuntimeCallInfo *argv)
2330 {
2331     ASSERT(argv);
2332     JSThread *thread = argv->GetThread();
2333     BUILTINS_API_TRACE(thread, SharedArray, FindLast);
2334     [[maybe_unused]] EcmaHandleScope handleScope(thread);
2335 
2336     // 1. Let O be ToObject(this value).
2337     ARRAY_CHECK_SHARED_ARRAY("The FindLast method cannot be bound.")
2338 
2339     JSHandle<JSObject> thisObjHandle(thread, JSObject::Cast(thisHandle.GetTaggedValue()));
2340     [[maybe_unused]] ConcurrentApiScope<JSSharedArray> scope(thread, thisHandle);
2341     // 2. ReturnIfAbrupt(O).
2342     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2343 
2344     // 3. Let len be ToLength(Get(O, "length")).
2345     int64_t len = ArrayHelper::GetLength(thread, thisHandle);
2346     // 4. ReturnIfAbrupt(len).
2347     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2348 
2349     // 5. If IsCallable(predicate) is false, throw a TypeError exception.
2350     JSHandle<JSTaggedValue> callbackFnHandle = GetCallArg(argv, 0);
2351     if (!callbackFnHandle->IsCallable()) {
2352         THROW_TYPE_ERROR_AND_RETURN(thread, "the predicate is not callable.", JSTaggedValue::Exception());
2353     }
2354 
2355     // 6. If thisArg was supplied, let T be thisArg; else let T be undefined.
2356     JSHandle<JSTaggedValue> thisArgHandle = GetCallArg(argv, 1);
2357     const uint32_t argsLength = 3; // 3: «kValue, k, O»
2358     // 7. Let k be (len - 1).
2359     int64_t k = len - 1;
2360     // 8. Repeat, while k >= 0
2361     //   a. Let Pk be ToString(k).
2362     //   b. Let kValue be Get(O, Pk).
2363     //   c. ReturnIfAbrupt(kValue).
2364     //   d. Let testResult be ToBoolean(Call(predicate, T, «kValue, k, O»)).
2365     //   e. ReturnIfAbrupt(testResult).
2366     //   f. If testResult is true, return kValue.
2367     //   g. Decrease k by 1.
2368     JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
2369     JSMutableHandle<JSTaggedValue> kValue(thread, JSTaggedValue::Undefined());
2370     JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
2371     JSTaggedValue callResult = GetTaggedBoolean(false);
2372     while (k >= 0) {
2373         kValue.Update(BuiltinsSharedArray::GetElementByKey(thread, thisObjHandle, k));
2374         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2375         key.Update(JSTaggedValue(k));
2376         EcmaRuntimeCallInfo *info =
2377             EcmaInterpreter::NewRuntimeCallInfo(thread, callbackFnHandle, thisArgHandle, undefined, argsLength);
2378         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2379         ASSERT(info != nullptr);
2380         info->SetCallArg(kValue.GetTaggedValue(), key.GetTaggedValue(), thisHandle.GetTaggedValue());
2381         callResult = JSFunction::Call(info);
2382         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2383         if (callResult.ToBoolean()) {
2384             return kValue.GetTaggedValue();
2385         }
2386         k--;
2387     }
2388 
2389     // 9. Return undefined.
2390     return JSTaggedValue::Undefined();
2391 }
2392 
2393 // Array.prototype.findLastIndex ( predicate [ , thisArg ] )
FindLastIndex(EcmaRuntimeCallInfo * argv)2394 JSTaggedValue BuiltinsSharedArray::FindLastIndex(EcmaRuntimeCallInfo *argv)
2395 {
2396     ASSERT(argv);
2397     JSThread *thread = argv->GetThread();
2398     BUILTINS_API_TRACE(thread, SharedArray, FindLastIndex);
2399     [[maybe_unused]] EcmaHandleScope handleScope(thread);
2400 
2401     // 1. Let O be ToObject(this value).
2402     ARRAY_CHECK_SHARED_ARRAY("The FindLastIndex method cannot be bound.")
2403 
2404     JSHandle<JSObject> thisObjHandle(thread, JSObject::Cast(thisHandle.GetTaggedValue()));
2405     [[maybe_unused]] ConcurrentApiScope<JSSharedArray> scope(thread, thisHandle);
2406     // 2. ReturnIfAbrupt(O).
2407     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2408 
2409     // 3. Let len be ToLength(Get(O, "length")).
2410     int64_t len = ArrayHelper::GetLength(thread, thisHandle);
2411     // 4. ReturnIfAbrupt(len).
2412     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2413 
2414     // 5. If IsCallable(predicate) is false, throw a TypeError exception.
2415     JSHandle<JSTaggedValue> callbackFnHandle = GetCallArg(argv, 0);
2416     if (!callbackFnHandle->IsCallable()) {
2417         THROW_TYPE_ERROR_AND_RETURN(thread, "the predicate is not callable.", JSTaggedValue::Exception());
2418     }
2419 
2420     // 6. If thisArg was supplied, let T be thisArg; else let T be undefined.
2421     JSHandle<JSTaggedValue> thisArgHandle = GetCallArg(argv, 1);
2422     const uint32_t argsLength = 3; // 3: «kValue, k, O»
2423     // 7. Let k be (len - 1).
2424     int64_t k = len - 1;
2425     // 8. Repeat, while k >= 0
2426     //   a. Let Pk be ToString(k).
2427     //   b. Let kValue be Get(O, Pk).
2428     //   c. ReturnIfAbrupt(kValue).
2429     //   d. Let testResult be ToBoolean(Call(predicate, T, «kValue, k, O»)).
2430     //   e. ReturnIfAbrupt(testResult).
2431     //   f. If testResult is true, return k.
2432     //   g. Decrease k by 1.
2433     JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
2434     JSMutableHandle<JSTaggedValue> kValue(thread, JSTaggedValue::Undefined());
2435     JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
2436     JSTaggedValue callResult = GetTaggedBoolean(false);
2437     while (k >= 0) {
2438         kValue.Update(BuiltinsSharedArray::GetElementByKey(thread, thisObjHandle, k));
2439         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2440         key.Update(JSTaggedValue(k));
2441         EcmaRuntimeCallInfo *info =
2442             EcmaInterpreter::NewRuntimeCallInfo(thread, callbackFnHandle, thisArgHandle, undefined, argsLength);
2443         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2444         ASSERT(info != nullptr);
2445         info->SetCallArg(kValue.GetTaggedValue(), key.GetTaggedValue(), thisHandle.GetTaggedValue());
2446         callResult = JSFunction::Call(info);
2447         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2448         if (callResult.ToBoolean()) {
2449             return GetTaggedDouble(k);
2450         }
2451         k--;
2452     }
2453 
2454     // 9. Return -1.
2455     return GetTaggedDouble(-1);
2456 }
2457 
2458 // Array.prototype.shrinkTo ( arrayLength )
ShrinkTo(EcmaRuntimeCallInfo * argv)2459 JSTaggedValue BuiltinsSharedArray::ShrinkTo(EcmaRuntimeCallInfo *argv)
2460 {
2461     ASSERT(argv);
2462     BUILTINS_API_TRACE(argv->GetThread(), SharedArray, ShrinkTo);
2463     JSThread *thread = argv->GetThread();
2464     [[maybe_unused]] EcmaHandleScope handleScope(thread);
2465     if (argv->GetArgsNumber() != 1) {
2466         auto error = ContainerError::ParamError(thread, "Parameter error.Not enough parameter.");
2467         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
2468     }
2469 
2470     // thisHandle variable declare this Macro
2471     ARRAY_CHECK_SHARED_ARRAY("The shrinkTo method cannot be bound.")
2472 
2473     JSHandle<JSObject> thisObjHandle = JSTaggedValue::ToObject(thread, thisHandle);
2474     [[maybe_unused]] ConcurrentApiScope<JSSharedArray, ModType::WRITE> scope(thread, thisHandle);
2475     JSHandle<JSTaggedValue> newLengthValue = GetCallArg(argv, 0);
2476     if (!newLengthValue->IsNumber()) {
2477         auto error = ContainerError::ParamError(thread, "Parameter error.Invalid array length.");
2478         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
2479     }
2480     auto newLength = JSTaggedValue::ToUint32(thread, newLengthValue);
2481     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2482     if (JSTaggedNumber(newLengthValue.GetTaggedValue()).GetNumber() != newLength) {
2483         auto error = ContainerError::ParamError(thread, "Parameter error.Invalid array length.");
2484         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
2485     }
2486     int64_t len = ArrayHelper::GetLength(thread, thisHandle);
2487     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2488     if (newLength >= len) {
2489         return JSTaggedValue::Undefined();
2490     }
2491     JSSharedArray::LengthSetter(thread, thisObjHandle, newLengthValue, true);
2492     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2493     return JSTaggedValue::Undefined();
2494 }
2495 
2496 // Array.prototype.ExtendTo ( arrayLength, initialValue )
ExtendTo(EcmaRuntimeCallInfo * argv)2497 JSTaggedValue BuiltinsSharedArray::ExtendTo(EcmaRuntimeCallInfo *argv)
2498 {
2499     ASSERT(argv);
2500     BUILTINS_API_TRACE(argv->GetThread(), SharedArray, ShrinkTo);
2501     JSThread *thread = argv->GetThread();
2502     [[maybe_unused]] EcmaHandleScope handleScope(thread);
2503     if (argv->GetArgsNumber() < COUNT_LENGTH_AND_INIT) {
2504         auto error = ContainerError::ParamError(thread, "Parameter error.Not enough parameters.");
2505         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
2506     }
2507 
2508     // thisHandle variable declare this Macro
2509     ARRAY_CHECK_SHARED_ARRAY("The extendTo method cannot be bound.")
2510 
2511     JSHandle<JSObject> thisObjHandle = JSTaggedValue::ToObject(thread, thisHandle);
2512     [[maybe_unused]] ConcurrentApiScope<JSSharedArray, ModType::WRITE> scope(thread, thisHandle);
2513     JSHandle<JSTaggedValue> newLengthValue = GetCallArg(argv, 0);
2514     if (!newLengthValue->IsNumber()) {
2515         auto error = ContainerError::ParamError(thread, "Parameter error.Invalid array length.");
2516         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
2517     }
2518     auto newLength = JSTaggedValue::ToUint32(thread, newLengthValue);
2519     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2520     if (JSTaggedNumber(newLengthValue.GetTaggedValue()).GetNumber() != newLength) {
2521         auto error = ContainerError::ParamError(thread, "Parameter error.Invalid array length.");
2522         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
2523     }
2524 
2525     int64_t length = ArrayHelper::GetLength(thread, thisHandle);
2526     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2527     if (newLength <= length) {
2528         return JSTaggedValue::Undefined();
2529     }
2530 
2531     JSHandle<JSTaggedValue> initValue = GetCallArg(argv, 1);
2532     if (!initValue->IsSharedType()) {
2533         auto error = ContainerError::ParamError(thread, "Parameter error.Only accept sendable value.");
2534         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
2535     }
2536 
2537     if (newLength > ElementAccessor::GetElementsLength(thisObjHandle)) {
2538         JSObject::GrowElementsCapacity(thread, thisObjHandle, newLength, true);
2539     }
2540 
2541     for (uint32_t k = static_cast<uint32_t>(length); k < newLength; k++) {
2542         BuiltinsSharedArray::SetElementValue(thread, thisObjHandle, k, initValue);
2543         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2544     }
2545 
2546     JSHandle<JSTaggedValue> key(thread, JSTaggedValue(newLength));
2547     JSSharedArray::LengthSetter(thread, thisObjHandle, key, true);
2548     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2549     return JSTaggedValue::Undefined();
2550 }
2551 
LastIndexOfSlowPath(EcmaRuntimeCallInfo * argv,JSThread * thread,const JSHandle<JSTaggedValue> & thisHandle)2552 JSTaggedValue BuiltinsSharedArray::LastIndexOfSlowPath(EcmaRuntimeCallInfo *argv, JSThread *thread,
2553                                                        const JSHandle<JSTaggedValue> &thisHandle)
2554 {
2555     // 1. Let O be ToObject(this value).
2556     JSHandle<JSObject> thisObjHandle = JSTaggedValue::ToObject(thread, thisHandle);
2557     // 2. ReturnIfAbrupt(O).
2558     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2559     JSHandle<JSTaggedValue> thisObjVal(thisObjHandle);
2560     // 3. Let len be ToLength(Get(O, "length")).
2561     int64_t length = ArrayHelper::GetLength(thread, thisObjVal);
2562     // 4. ReturnIfAbrupt(len).
2563     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2564     // 5. If len is 0, return −1.
2565     if (length == 0) {
2566         return JSTaggedValue(-1);
2567     }
2568     // 6. If argument fromIndex was passed let n be ToInteger(fromIndex); else let n be 0.
2569     int64_t fromIndex = ArrayHelper::GetLastStartIndexFromArgs(thread, argv, 1, length);
2570     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2571     return LastIndexOfSlowPath(argv, thread, thisObjVal, fromIndex);
2572 }
2573 
LastIndexOfSlowPath(EcmaRuntimeCallInfo * argv,JSThread * thread,const JSHandle<JSTaggedValue> & thisObjVal,int64_t fromIndex)2574 JSTaggedValue BuiltinsSharedArray::LastIndexOfSlowPath(EcmaRuntimeCallInfo *argv, JSThread *thread,
2575                                                        const JSHandle<JSTaggedValue> &thisObjVal, int64_t fromIndex)
2576 {
2577     if (fromIndex < 0) {
2578         return JSTaggedValue(-1);
2579     }
2580     JSMutableHandle<JSTaggedValue> keyHandle(thread, JSTaggedValue::Undefined());
2581     JSHandle<JSTaggedValue> target = base::BuiltinsBase::GetCallArg(argv, 0);
2582     // 11. Repeat, while k < len
2583     for (int64_t curIndex = fromIndex; curIndex >= 0; --curIndex) {
2584         keyHandle.Update(JSTaggedValue(curIndex));
2585         bool found = ArrayHelper::ElementIsStrictEqualTo(thread, thisObjVal, keyHandle, target);
2586         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2587         if (UNLIKELY(found)) {
2588             return JSTaggedValue(curIndex);
2589         }
2590     }
2591     // 12. Return -1.
2592     return JSTaggedValue(-1);
2593 }
2594 
2595 // Array.prototype.lastIndexOf ( searchElement [ , fromIndex ] )
LastIndexOf(EcmaRuntimeCallInfo * argv)2596 JSTaggedValue BuiltinsSharedArray::LastIndexOf(EcmaRuntimeCallInfo *argv)
2597 {
2598     ASSERT(argv);
2599     JSThread *thread = argv->GetThread();
2600     BUILTINS_API_TRACE(thread, SharedArray, LastIndexOf);
2601     [[maybe_unused]] EcmaHandleScope handleScope(thread);
2602 
2603     // thisHandle variable declare this Macro
2604     ARRAY_CHECK_SHARED_ARRAY("The lastIndexOf method cannot be bound.")
2605 
2606     [[maybe_unused]] ConcurrentApiScope<JSSharedArray> scope(thread, thisHandle);
2607     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2608 
2609     return LastIndexOfSlowPath(argv, thread, thisHandle);
2610 }
2611 
2612 // Array.of ( ...items )
Of(EcmaRuntimeCallInfo * argv)2613 JSTaggedValue BuiltinsSharedArray::Of(EcmaRuntimeCallInfo *argv)
2614 {
2615     ASSERT(argv);
2616     BUILTINS_API_TRACE(argv->GetThread(), SharedArray, Of);
2617     JSThread *thread = argv->GetThread();
2618     [[maybe_unused]] EcmaHandleScope handleScope(thread);
2619     const GlobalEnvConstants *globalConst = thread->GlobalConstants();
2620 
2621     // 1. Let len be the actual number of arguments passed to this function.
2622     uint32_t argc = argv->GetArgsNumber();
2623 
2624     // 3. Let C be the this value.
2625     // thisHandle variable declare this Macro
2626     JSHandle<JSTaggedValue> thisHandle = GetThis(argv);
2627 
2628     // 4. If IsConstructor(C) is true, then
2629     //   a. Let A be Construct(C, «len»).
2630     // 5. Else,
2631     //   a. Let A be ArrayCreate(len).
2632     // 6. ReturnIfAbrupt(A).
2633     JSHandle<JSTaggedValue> newArray;
2634     if (thisHandle->IsConstructor()) {
2635         JSHandle<JSTaggedValue> undefined = globalConst->GetHandledUndefined();
2636         EcmaRuntimeCallInfo *info =
2637             EcmaInterpreter::NewRuntimeCallInfo(thread, thisHandle, undefined, undefined, 1);
2638         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2639         ASSERT(info != nullptr);
2640         info->SetCallArg(JSTaggedValue(argc));
2641         JSTaggedValue taggedArray = JSFunction::Construct(info);
2642         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2643         newArray = JSHandle<JSTaggedValue>(thread, taggedArray);
2644     } else {
2645         newArray = JSSharedArray::ArrayCreate(thread, JSTaggedNumber(argc));
2646         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2647     }
2648 
2649     if (!newArray->IsJSSharedArray()) {
2650         THROW_TYPE_ERROR_AND_RETURN(thread, "Failed to create Object.", JSTaggedValue::Exception());
2651     }
2652 
2653     JSHandle<JSObject> newArrayHandle(newArray);
2654     if (UNLIKELY(argc > ElementAccessor::GetElementsLength(newArrayHandle))) {
2655         JSObject::GrowElementsCapacity(thread, JSHandle<JSObject>::Cast(newArrayHandle), argc, true);
2656     }
2657 
2658     // 7. Let k be 0.
2659     // 8. Repeat, while k < len
2660     //   a. Let kValue be items[k].
2661     //   b. Let Pk be ToString(k).
2662     //   c. Let defineStatus be CreateDataPropertyOrThrow(A,Pk, kValue).
2663     //   d. ReturnIfAbrupt(defineStatus).
2664     //   e. Increase k by 1.
2665     for (uint32_t k = 0; k < argc; k++) {
2666         JSHandle<JSTaggedValue> value = argv->GetCallArg(k);
2667         BuiltinsSharedArray::SetElementValue(thread, newArrayHandle, k, value);
2668         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2669     }
2670     JSSharedArray::Cast(*newArrayHandle)->SetArrayLength(thread, argc);
2671     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2672 
2673     return newArrayHandle.GetTaggedValue();
2674 }
2675 
ConvertTagValueToInteger(JSThread * thread,JSHandle<JSTaggedValue> & number,int64_t len)2676 int64_t BuiltinsSharedArray::ConvertTagValueToInteger(JSThread *thread, JSHandle<JSTaggedValue>& number, int64_t len)
2677 {
2678     JSTaggedNumber targetTemp = JSTaggedValue::ToInteger(thread, number);
2679     RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, 0);
2680     double target = targetTemp.GetNumber();
2681     // If relativeTarget < 0, let to be max((len + relativeTarget),0); else let to be min(relativeTarget, len).
2682     if (target < 0) {
2683         return target + len > 0 ? static_cast<int64_t>(target + len) : 0;
2684     } else {
2685         return target < len ? static_cast<int64_t>(target) : len;
2686     }
2687 }
2688 
GetNumberArgVal(JSThread * thread,EcmaRuntimeCallInfo * argv,uint32_t idx,int64_t len,int64_t defVal)2689 int64_t BuiltinsSharedArray::GetNumberArgVal(JSThread *thread, EcmaRuntimeCallInfo *argv, uint32_t idx, int64_t len,
2690                                              int64_t defVal)
2691 {
2692     JSHandle<JSTaggedValue> argValue = GetCallArg(argv, idx);
2693 
2694     return argValue->IsUndefined() ? defVal : BuiltinsSharedArray::ConvertTagValueToInteger(thread, argValue, len);
2695 }
2696 
GetNumberArgValThrow(JSThread * thread,EcmaRuntimeCallInfo * argv,uint32_t idx,int64_t len,const char * err)2697 int64_t BuiltinsSharedArray::GetNumberArgValThrow(JSThread *thread, EcmaRuntimeCallInfo *argv, uint32_t idx,
2698                                                   int64_t len, const char* err)
2699 {
2700     JSHandle<JSTaggedValue> argValue = GetCallArg(argv, idx);
2701     if (UNLIKELY(argValue->IsUndefined())) {
2702         auto error = ContainerError::BindError(thread, err);
2703         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, 0);
2704     }
2705 
2706     return BuiltinsSharedArray::ConvertTagValueToInteger(thread, argValue, len);
2707 }
2708 
2709 // Array.prototype.copyWithin (target, start [ , end ] )
CopyWithin(EcmaRuntimeCallInfo * argv)2710 JSTaggedValue BuiltinsSharedArray::CopyWithin(EcmaRuntimeCallInfo *argv)
2711 {
2712     ASSERT(argv);
2713     BUILTINS_API_TRACE(argv->GetThread(), SharedArray, CopyWithin);
2714     JSThread *thread = argv->GetThread();
2715     [[maybe_unused]] EcmaHandleScope handleScope(thread);
2716 
2717     // 1. Let O be ToObject(this value).
2718     // 3. Let C be the this value.
2719     // thisHandle variable declare this Macro
2720     ARRAY_CHECK_SHARED_ARRAY("The CopyWithin method cannot be bound.")
2721 
2722     JSHandle<JSObject> thisObjHandle = JSTaggedValue::ToObject(thread, thisHandle);
2723     // 2. ReturnIfAbrupt(O).
2724     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2725 
2726     [[maybe_unused]] ConcurrentApiScope<JSSharedArray, ModType::WRITE> scope(thread, thisHandle);
2727     // 3. Let len be ToLength(Get(O, "length")).
2728     int64_t len = ArrayHelper::GetLength(thread, thisHandle);
2729     // 4. ReturnIfAbrupt(len).
2730     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2731 
2732     int64_t copyTo = GetNumberArgValThrow(thread, argv, 0, len, "Target index cannot be undefined.");
2733     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2734 
2735     // 5. Let relativeStart be ToInteger(start).
2736     int64_t copyFrom = GetNumberArgVal(thread, argv, 1, len, 0);
2737     // 6. ReturnIfAbrupt(relativeStart).
2738     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2739 
2740     // 7. If end is undefined, let relativeEnd be len; else let relativeEnd be ToInteger(end).
2741     int64_t copyEnd = GetNumberArgVal(thread, argv, 2, len, len);
2742     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2743 
2744     // 14. Let count be min(final-from, len-to).
2745     int64_t count = std::min(copyEnd - copyFrom, len - copyTo);
2746 
2747     // 15. If from<to and to<from+count
2748     //   a. Let direction be -1.
2749     //   b. Let from be from + count -1.
2750     //   c. Let to be to + count -1.
2751     // 16. Else,
2752     //   a. Let direction = 1.
2753     if (count > 0) {
2754         TaggedArray *element = TaggedArray::Cast(thisObjHandle->GetElements().GetTaggedObject());
2755         element->Copy<true, true>(thread, copyTo, copyFrom, element, count);
2756         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2757     }
2758 
2759     // 18. Return O.
2760     return thisObjHandle.GetTaggedValue();
2761 }
2762 
FastReverse(JSThread * thread,JSHandle<TaggedArray> & elements,uint32_t lower,uint32_t len,ElementsKind kind)2763 JSTaggedValue BuiltinsSharedArray::FastReverse(JSThread *thread, JSHandle<TaggedArray> &elements,
2764                                                uint32_t lower, uint32_t len, ElementsKind kind)
2765 {
2766     JSMutableHandle<JSTaggedValue> lowerValueHandle(thread, JSTaggedValue::Undefined());
2767     JSMutableHandle<JSTaggedValue> upperValueHandle(thread, JSTaggedValue::Undefined());
2768     uint32_t middle = std::floor(len / 2);
2769     while (lower != middle) {
2770         uint32_t upper = len - lower - 1;
2771         lowerValueHandle.Update(ElementAccessor::FastGet(elements, lower, kind));
2772         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2773         upperValueHandle.Update(ElementAccessor::FastGet(elements, upper, kind));
2774         ElementAccessor::FastSet(thread, elements, lower, upperValueHandle, kind);
2775         ElementAccessor::FastSet(thread, elements, upper, lowerValueHandle, kind);
2776         lower++;
2777     }
2778     return base::BuiltinsBase::GetTaggedDouble(true);
2779 }
2780 
2781 // Array.prototype.reverse ( )
Reverse(EcmaRuntimeCallInfo * argv)2782 JSTaggedValue BuiltinsSharedArray::Reverse(EcmaRuntimeCallInfo *argv)
2783 {
2784     ASSERT(argv);
2785     BUILTINS_API_TRACE(argv->GetThread(), SharedArray, Reverse);
2786     JSThread *thread = argv->GetThread();
2787     [[maybe_unused]] EcmaHandleScope handleScope(thread);
2788 
2789     // 1. Let O be ToObject(this value).
2790     // thisHandle variable declare this Macro
2791     ARRAY_CHECK_SHARED_ARRAY("The Reverse method cannot be bound.")
2792     JSHandle<JSObject> thisObjHandle(thread, JSObject::Cast(thisHandle.GetTaggedValue()));
2793     [[maybe_unused]] ConcurrentApiScope<JSSharedArray, ModType::WRITE> scope(thread, thisHandle);
2794     // 2. ReturnIfAbrupt(O).
2795     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2796     JSHandle<JSTaggedValue> thisObjVal(thisObjHandle);
2797 
2798     // 3. Let len be ToLength(Get(O, "length")).
2799     int64_t len = ArrayHelper::GetLength(thread, thisObjVal);
2800     // 4. ReturnIfAbrupt(len).
2801     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2802 
2803     // 7. Repeat, while lower != middle
2804     //   a. Let upper be len-lower-1.
2805     //   b. Let upperP be ToString(upper).
2806 
2807     //   c. Let lowerP be ToString(lower).
2808     //   d. Let lowerExists be HasProperty(O, lowerP).
2809     //   e. ReturnIfAbrupt(lowerExists).
2810     //   f. If lowerExists is true, then
2811     //     i. Let lowerValue be Get(O, lowerP).
2812     //     ii. ReturnIfAbrupt(lowerValue).
2813     //   g. Let upperExists be HasProperty(O, upperP).
2814     //   h. ReturnIfAbrupt(upperExists).
2815     //     i. If upperExists is true, then
2816     //     i. Let upperValue be Get(O, upperP).
2817     //     ii. ReturnIfAbrupt(upperValue).
2818     //   j. If lowerExists is true and upperExists is true, then
2819     //     i. Let setStatus be Set(O, lowerP, upperValue, true).
2820     //     ii. ReturnIfAbrupt(setStatus).
2821     //     iii. Let setStatus be Set(O, upperP, lowerValue, true).
2822     //     iv. ReturnIfAbrupt(setStatus).
2823     //   k. Else if lowerExists is false and upperExists is true, then
2824     //     i. Let setStatus be Set(O, lowerP, upperValue, true).
2825     //     ii. ReturnIfAbrupt(setStatus).
2826     //     iii. Let deleteStatus be DeletePropertyOrThrow (O, upperP).
2827     //     iv. ReturnIfAbrupt(deleteStatus).
2828     //   l. Else if lowerExists is true and upperExists is false, then
2829     //     i. Let deleteStatus be DeletePropertyOrThrow (O, lowerP).
2830     //     ii. ReturnIfAbrupt(deleteStatus).
2831     //     iii. Let setStatus be Set(O, upperP, lowerValue, true).
2832     //     iv. ReturnIfAbrupt(setStatus).
2833     //   m. Else both lowerExists and upperExists are false,
2834     //     i. No action is required.
2835     //   n. Increase lower by 1.
2836     ElementsKind kind = thisObjHandle->GetClass()->GetElementsKind();
2837     JSHandle<TaggedArray> elements(thread, thisObjHandle->GetElements());
2838     bool enableElementsKind = thread->GetEcmaVM()->IsEnableElementsKind();
2839     if (enableElementsKind) {
2840         if (kind == ElementsKind::INT || kind == ElementsKind::HOLE_INT) {
2841             FastReverse(thread, elements, 0, len, ElementsKind::INT);
2842             return thisObjHandle.GetTaggedValue();
2843         } else if (kind == ElementsKind::NUMBER || kind == ElementsKind::HOLE_NUMBER) {
2844             FastReverse(thread, elements, 0, len, ElementsKind::NUMBER);
2845             return thisObjHandle.GetTaggedValue();
2846         }
2847     }
2848     FastReverse(thread, elements, 0, len, ElementsKind::TAGGED);
2849 
2850     // 8. Return O .
2851     return thisObjHandle.GetTaggedValue();
2852 }
2853 
2854 // Array.prototype.reduceRight ( callbackfn [ , initialValue ] )
ReduceRight(EcmaRuntimeCallInfo * argv)2855 JSTaggedValue BuiltinsSharedArray::ReduceRight(EcmaRuntimeCallInfo *argv)
2856 {
2857     ASSERT(argv);
2858     BUILTINS_API_TRACE(argv->GetThread(), SharedArray, ReduceRight);
2859     JSThread *thread = argv->GetThread();
2860     [[maybe_unused]] EcmaHandleScope handleScope(thread);
2861 
2862     uint32_t argc = argv->GetArgsNumber();
2863     // 1. Let O be ToObject(this value).
2864     // thisHandle variable declare this Macro
2865     ARRAY_CHECK_SHARED_ARRAY("The ReduceRight method cannot be bound.")
2866 
2867     JSHandle<JSObject> thisObjHandle(thread, JSObject::Cast(thisHandle.GetTaggedValue()));
2868     [[maybe_unused]] ConcurrentApiScope<JSSharedArray> scope(thread, thisHandle);
2869     // 2. ReturnIfAbrupt(O).
2870     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2871 
2872     // 3. Let len be ToLength(Get(O, "length")).
2873     int64_t len = ArrayHelper::GetArrayLength(thread, thisHandle);
2874     // 4. ReturnIfAbrupt(len).
2875     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2876     return ReduceRightInternalHandle(argv, thread, thisHandle, thisObjHandle, argc, len);
2877 }
2878 
ReduceRightInternalHandle(EcmaRuntimeCallInfo * argv,JSThread * thread,const JSHandle<JSTaggedValue> & thisHandle,JSHandle<JSObject> & thisObjHandle,uint32_t argc,int64_t len)2879 JSTaggedValue BuiltinsSharedArray::ReduceRightInternalHandle(EcmaRuntimeCallInfo *argv, JSThread *thread,
2880     const JSHandle<JSTaggedValue> &thisHandle, JSHandle<JSObject> &thisObjHandle, uint32_t argc, int64_t len)
2881 {
2882     JSHandle<JSTaggedValue> callbackFnHandle = GetCallArg(argv, 0);
2883     if (!callbackFnHandle->IsCallable()) {
2884         THROW_TYPE_ERROR_AND_RETURN(thread, "the callbackfun is not callable.", JSTaggedValue::Exception());
2885     }
2886 
2887     // 6. If len is 0 and initialValue is not present, throw a TypeError exception.
2888     const int32_t argcLimitLength = 2; // argc limit length of the number parameters
2889     if (len == 0 && argc < argcLimitLength) {
2890         THROW_TYPE_ERROR_AND_RETURN(thread, "out of range.", JSTaggedValue::Exception());
2891     }
2892     // 7. Let k be len-1.
2893     int64_t k = len - 1;
2894     // 8. If initialValue is present, then
2895     //   a. Set accumulator to initialValue.
2896     // 9. Else initialValue is not present,
2897     //   a. Get last element initial accumulator
2898     JSMutableHandle<JSTaggedValue> accumulator(thread, JSTaggedValue::Undefined());
2899     if (argc >= argcLimitLength) { // 2:2 means the number of parameters
2900         accumulator.Update(GetCallArg(argv, 1).GetTaggedValue());
2901     } else if (k >= 0) {
2902         accumulator.Update(BuiltinsSharedArray::GetElementByKey(thread, thisObjHandle, k));
2903         k--;
2904     }
2905 
2906     // 10. Repeat, while k ≥ 0
2907     //   a. Let Pk be ToString(k).
2908     //   b. Let kPresent be HasProperty(O, Pk).
2909     //   c. ReturnIfAbrupt(kPresent).
2910     //   d. If kPresent is true, then
2911     //     i. Let kValue be Get(O, Pk).
2912     //     ii. ReturnIfAbrupt(kValue).
2913     //     iii. Let accumulator be Call(callbackfn, undefined, «accumulator, kValue, k, O»).
2914     //     iv. ReturnIfAbrupt(accumulator).
2915     //   e. Decrease k by 1.
2916     JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
2917     JSMutableHandle<JSTaggedValue> kValue(thread, JSTaggedValue::Hole());
2918     JSTaggedValue callResult = JSTaggedValue::Undefined();
2919     JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
2920     const int32_t argsLength = 4; // 4: «accumulator, kValue, k, O»
2921     while (k >= 0) {
2922         kValue.Update(BuiltinsSharedArray::GetElementByKey(thread, thisObjHandle, k));
2923         key.Update(JSTaggedValue(k));
2924         EcmaRuntimeCallInfo *info =
2925             EcmaInterpreter::NewRuntimeCallInfo(thread, callbackFnHandle, undefined, undefined, argsLength);
2926         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2927         ASSERT(info != nullptr);
2928         info->SetCallArg(accumulator.GetTaggedValue(), kValue.GetTaggedValue(),
2929             key.GetTaggedValue(), thisHandle.GetTaggedValue());
2930         callResult = JSFunction::Call(info);
2931         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2932         accumulator.Update(callResult);
2933         k--;
2934     }
2935 
2936     // 11. Return accumulator.
2937     return accumulator.GetTaggedValue();
2938 }
2939 
2940 }  // namespace panda::ecmascript::builtins
2941