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