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