• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-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/js_typed_array.h"
17 
18 #include "ecmascript/base/typed_array_helper-inl.h"
19 #include "ecmascript/ecma_string-inl.h"
20 #include "ecmascript/shared_objects/js_sendable_arraybuffer.h"
21 
22 namespace panda::ecmascript {
23 using TypedArrayHelper = base::TypedArrayHelper;
24 using BuiltinsArrayBuffer = builtins::BuiltinsArrayBuffer;
25 using BuiltinsSendableArrayBuffer = builtins::BuiltinsSendableArrayBuffer;
26 
ToPropKey(JSThread * thread,const JSHandle<JSTaggedValue> & key)27 JSHandle<JSTaggedValue> JSTypedArray::ToPropKey(JSThread *thread, const JSHandle<JSTaggedValue> &key)
28 {
29     if (key->IsSymbol()) {
30         return key;
31     }
32     return JSHandle<JSTaggedValue>(JSTaggedValue::ToString(thread, key));
33 }
34 // 9.4.5.1 [[GetOwnProperty]] ( P )
GetOwnProperty(JSThread * thread,const JSHandle<JSTaggedValue> & typedarray,const JSHandle<JSTaggedValue> & key,PropertyDescriptor & desc)35 bool JSTypedArray::GetOwnProperty(JSThread *thread, const JSHandle<JSTaggedValue> &typedarray,
36                                   const JSHandle<JSTaggedValue> &key, PropertyDescriptor &desc)
37 {
38     // 1. Assert : IsPropertyKey(P) is true.
39     ASSERT(JSTaggedValue::IsPropertyKey(key));
40     // 2. Assert: O is an Object that has a [[ViewedArrayBuffer]] internal slot.
41     // 3. If Type(P) is String, then
42     //   a. Let numericIndex be CanonicalNumericIndexString(P).
43     //   b. Assert: numericIndex is not an abrupt completion.
44     //   c. If numericIndex is not undefined, then
45     //     i. Let value be IntegerIndexedElementGet (O, numericIndex).
46     //     ii. ReturnIfAbrupt(value).
47     //     iii. If value is undefined, return undefined.
48     //     iv. Return a PropertyDescriptor{ [[Value]]: value, [[Enumerable]]: true, [[Writable]]: true,
49     //         [[Configurable]]: false }.
50     if (key->IsString() || key->IsNumber()) {
51         JSTaggedValue numericIndex = JSTaggedValue::CanonicalNumericIndexString(thread, key);
52         RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false);
53         if (!numericIndex.IsUndefined()) {
54             JSHandle<JSTaggedValue> value =
55                 JSTypedArray::IntegerIndexedElementGet(thread, typedarray, numericIndex).GetValue();
56             RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false);
57             if (value->IsUndefined()) {
58                 return false;
59             }
60             desc.SetValue(value);
61             desc.SetEnumerable(true);
62             desc.SetWritable(true);
63             desc.SetConfigurable(true);
64             return true;
65         }
66     }
67     // 4. Return OrdinaryGetOwnProperty(O, P).
68     return JSObject::OrdinaryGetOwnProperty(thread, JSHandle<JSObject>(typedarray), key, desc);
69 }
70 
71 // 9.4.5.2 [[HasProperty]] ( P )
HasProperty(JSThread * thread,const JSHandle<JSTaggedValue> & typedarray,const JSHandle<JSTaggedValue> & key)72 bool JSTypedArray::HasProperty(JSThread *thread, const JSHandle<JSTaggedValue> &typedarray,
73                                const JSHandle<JSTaggedValue> &key)
74 {
75     // 1. Assert: IsPropertyKey(P) is true.
76     ASSERT(JSTaggedValue::IsPropertyKey(key));
77     // 2. Assert: O is an Object that has a [[ViewedArrayBuffer]] internal slot.
78     // 3. If Type(P) is String, then
79     //   a. Let numericIndex be CanonicalNumericIndexString(P).
80     //   b. Assert: numericIndex is not an abrupt completion.
81     //   c. If numericIndex is not undefined, then
82     //     i. Let buffer be the value of O’s [[ViewedArrayBuffer]] internal slot.
83     //     ii. If IsDetachedBuffer(buffer) is true, throw a TypeError exception.
84     //     iii. If IsInteger(numericIndex) is false, return false
85     //     iv. If numericIndex = −0, return false.
86     //     v. If numericIndex < 0, return false.
87     //     vi. If numericIndex ≥ the value of O’s [[ArrayLength]] internal slot, return false.
88     //     vii. Return true.
89     JSHandle<JSTypedArray> typedarrayObj(typedarray);
90     if (key->IsString() || key->IsNumber()) {
91         JSTaggedValue numericIndex = JSTaggedValue::CanonicalNumericIndexString(thread, key);
92         RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false);
93         if (!numericIndex.IsUndefined()) {
94             JSTaggedValue buffer = typedarrayObj->GetViewedArrayBufferOrByteArray(thread);
95             if (IsArrayBufferDetached(thread, buffer)) {
96                 THROW_TYPE_ERROR_AND_RETURN(thread, "Is Detached Buffer", false);
97             }
98             if (!numericIndex.IsInteger()) {
99                 return false;
100             }
101             JSHandle<JSTaggedValue> numericIndexHandle(thread, numericIndex);
102             JSTaggedNumber numericIndexNumber = JSTaggedValue::ToNumber(thread, numericIndexHandle);
103             RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false);
104             double tNegZero = -0.0;
105             auto eZero = JSTaggedNumber(tNegZero);
106             JSHandle<JSTaggedValue> zero(thread, JSTaggedValue(0));
107             if (JSTaggedNumber::SameValue(numericIndexNumber, eZero)) {
108                 return false;
109             }
110 
111             if (JSTaggedValue::Less(thread, numericIndexHandle, zero)) {
112                 return false;
113             }
114             uint32_t arrLen = typedarrayObj->GetArrayLength();
115             JSHandle<JSTaggedValue> arrLenHandle(thread, JSTaggedValue(arrLen));
116             return JSTaggedValue::Less(thread, numericIndexHandle, arrLenHandle);
117         }
118     }
119     // 4. Return OrdinaryHasProperty(O, P).
120     PropertyDescriptor desc(thread);
121     if (JSObject::OrdinaryGetOwnProperty(thread, JSHandle<JSObject>::Cast(typedarrayObj), key, desc)) {
122         return true;
123     }
124     JSTaggedValue parent = JSTaggedValue::GetPrototype(thread, JSHandle<JSTaggedValue>::Cast(typedarrayObj));
125     RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false);
126     if (!parent.IsNull()) {
127         return JSTaggedValue::HasProperty(thread, JSHandle<JSTaggedValue>(thread, parent), key);
128     }
129     return false;
130 }
131 
132 // 9.4.5.3 [[DefineOwnProperty]] ( P, Desc )
DefineOwnProperty(JSThread * thread,const JSHandle<JSTaggedValue> & typedarray,const JSHandle<JSTaggedValue> & key,const PropertyDescriptor & desc)133 bool JSTypedArray::DefineOwnProperty(JSThread *thread, const JSHandle<JSTaggedValue> &typedarray,
134                                      const JSHandle<JSTaggedValue> &key, const PropertyDescriptor &desc)
135 {
136     // 1. Assert: IsPropertyKey(P) is true.
137     ASSERT(JSTaggedValue::IsPropertyKey(key));
138     // 2. Assert: O is an Object that has a [[ViewedArrayBuffer]] internal slot.
139     // 3. If Type(P) is String, then
140     //   a. Let numericIndex be CanonicalNumericIndexString (P).
141     //   b. Assert: numericIndex is not an abrupt completion.
142     //   c. If numericIndex is not undefined, then
143     JSHandle<JSTypedArray> typedarrayObj(typedarray);
144     if (key->IsString() || key->IsNumber()) {
145         JSTaggedValue numericIndex = JSTaggedValue::CanonicalNumericIndexString(thread, key);
146         RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false);
147         if (!numericIndex.IsUndefined()) {
148             // i. If IsInteger(numericIndex) is false, return false
149             // ii. Let intIndex be numericIndex.
150             // iii. If intIndex = −0, return false.
151             // iv. If intIndex < 0, return false.
152             // v. Let length be the value of O’s [[ArrayLength]] internal slot.
153             // vi. If intIndex ≥ length, return false.
154             // vii. If IsAccessorDescriptor(Desc) is true, return false.
155             // viii. If Desc has a [[Configurable]] field and if Desc.[[Configurable]] is true, return false.
156             // ix. If Desc has an [[Enumerable]] field and if Desc.[[Enumerable]] is false, return false.
157             // x. If Desc has a [[Writable]] field and if Desc.[[Writable]] is false, return false.
158             // xi. If Desc has a [[Value]] field, then
159             //   1. Let value be Desc.[[Value]].
160             //   2. Return IntegerIndexedElementSet (O, intIndex, value).
161             // xii. Return true.
162             if (!numericIndex.IsInteger()) {
163                 return false;
164             }
165             JSHandle<JSTaggedValue> numericIndexHandle(thread, numericIndex);
166             JSTaggedNumber numericIndexNumber = JSTaggedValue::ToNumber(thread, numericIndexHandle);
167             RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false);
168             double tNegZero = -0.0;
169             auto eZero = JSTaggedNumber(tNegZero);
170             JSHandle<JSTaggedValue> zero(thread, JSTaggedValue(0));
171             if (JSTaggedNumber::SameValue(numericIndexNumber, eZero)) {
172                 return false;
173             }
174             if (JSTaggedValue::Less(thread, numericIndexHandle, zero)) {
175                 return false;
176             }
177             uint32_t arrLen = typedarrayObj->GetArrayLength();
178             JSHandle<JSTaggedValue> arrLenHandle(thread, JSTaggedValue(arrLen));
179             if (!JSTaggedValue::Less(thread, numericIndexHandle, arrLenHandle)) {
180                 return false;
181             }
182             if (desc.IsAccessorDescriptor()) {
183                 return false;
184             }
185             if (desc.HasConfigurable() && !desc.IsConfigurable()) {
186                 return false;
187             }
188             if (desc.HasEnumerable() && !desc.IsEnumerable()) {
189                 return false;
190             }
191             if (desc.HasWritable() && !desc.IsWritable()) {
192                 return false;
193             }
194             if (desc.HasValue()) {
195                 JSHandle<JSTaggedValue> value = desc.GetValue();
196                 return (JSTypedArray::IntegerIndexedElementSet(thread, typedarray, numericIndex, value));
197             }
198             return true;
199         }
200     }
201     // 4. Return OrdinaryDefineOwnProperty(O, P, Desc).
202     return JSObject::OrdinaryDefineOwnProperty(thread, JSHandle<JSObject>::Cast(typedarrayObj), key, desc);
203 }
204 
205 // 9.4.5.4 [[Get]] ( P, Receiver )
GetProperty(JSThread * thread,const JSHandle<JSTaggedValue> & typedarray,const JSHandle<JSTaggedValue> & key,const JSHandle<JSTaggedValue> & receiver)206 OperationResult JSTypedArray::GetProperty(JSThread *thread, const JSHandle<JSTaggedValue> &typedarray,
207                                           const JSHandle<JSTaggedValue> &key, const JSHandle<JSTaggedValue> &receiver)
208 {
209     // 1. Assert : IsPropertyKey(P) is true.
210     ASSERT(JSTaggedValue::IsPropertyKey(key));
211     // 2. If Type(P) is String and if SameValue(O, Receiver) is true, then
212     if ((key->IsString() || key->IsNumber()) && JSTaggedValue::SameValue(thread, typedarray, receiver)) {
213         //   a. Let numericIndex be CanonicalNumericIndexString (P).
214         //   b. Assert: numericIndex is not an abrupt completion.
215         //   c. If numericIndex is not undefined, then
216         //     i. Return IntegerIndexedElementGet (O, numericIndex).
217         JSTaggedValue numericIndex = JSTaggedValue::CanonicalNumericIndexString(thread, key);
218         RETURN_VALUE_IF_ABRUPT_COMPLETION(
219             thread, OperationResult(thread, JSTaggedValue::Exception(), PropertyMetaData(false)));
220         if (!numericIndex.IsUndefined()) {
221             return JSTypedArray::IntegerIndexedElementGet(thread, typedarray, numericIndex);
222         }
223     }
224 
225     // 3. Return the result of calling the default ordinary object [[Get]] internal method (9.1.8) on O
226     //   passing P and Receiver as arguments.
227     return JSObject::GetProperty(thread, typedarray, key, receiver);
228 }
229 
230 // 9.4.5.5 [[Set]] ( P, V, Receiver )
SetProperty(JSThread * thread,const JSHandle<JSTaggedValue> & typedarray,const JSHandle<JSTaggedValue> & key,const JSHandle<JSTaggedValue> & value,const JSHandle<JSTaggedValue> & receiver,bool mayThrow)231 bool JSTypedArray::SetProperty(JSThread *thread, const JSHandle<JSTaggedValue> &typedarray,
232                                const JSHandle<JSTaggedValue> &key, const JSHandle<JSTaggedValue> &value,
233                                const JSHandle<JSTaggedValue> &receiver, bool mayThrow)
234 {
235     // 1. Assert : IsPropertyKey(P) is true.
236     ASSERT(JSTaggedValue::IsPropertyKey(key));
237     // 2. If Type(P) is String and if SameValue(O, Receiver) is true, then
238     if ((key->IsString() || key->IsNumber()) && JSTaggedValue::SameValue(thread, typedarray, receiver)) {
239         //   a. Let numericIndex be CanonicalNumericIndexString (P).
240         //   b. Assert: numericIndex is not an abrupt completion.
241         //   c. If numericIndex is not undefined, then
242         //     i. Return IntegerIndexedElementSet (O, numericIndex, V).
243         JSTaggedValue numericIndex = JSTaggedValue::CanonicalNumericIndexString(thread, key);
244         RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false);
245         if (!numericIndex.IsUndefined()) {
246             return JSTypedArray::IntegerIndexedElementSet(thread, typedarray, numericIndex, value);
247         }
248     }
249     // 3. Return the result of calling the default ordinary object [[Set]] internal method (9.1.8) on O passing
250     // P, V, and Receiver as arguments.
251     return JSObject::SetProperty(thread, typedarray, key, value, receiver, mayThrow);
252 }
253 
254 // s12 10.4.5.6 [[Delete]] ( P )
DeleteProperty(JSThread * thread,const JSHandle<JSTaggedValue> & typedarray,const JSHandle<JSTaggedValue> & key)255 bool JSTypedArray::DeleteProperty(JSThread *thread, const JSHandle<JSTaggedValue> &typedarray,
256                                   const JSHandle<JSTaggedValue> &key)
257 {
258     // 1. Assert: IsPropertyKey(P) is true.
259     // 2. Assert: O is an Integer-Indexed exotic object.
260     ASSERT(JSTaggedValue::IsPropertyKey(key));
261     // 3. If Type(P) is String, then
262         // a. Let numericIndex be CanonicalNumericIndexString(P).
263         // b. If numericIndex is not undefined, then
264            // i. If IsValidIntegerIndex(O, numericIndex) is false, return true; else return false.
265     if (key->IsString() || key->IsNumber()) {
266         JSTaggedValue numericIndex = JSTaggedValue::CanonicalNumericIndexString(thread, key);
267         if (!numericIndex.IsUndefined()) {
268             if (!IsValidIntegerIndex(thread, typedarray, numericIndex)) {
269                 return true;
270             }
271             return false;
272         }
273     }
274     // 4. Return ? OrdinaryDelete(O, P).
275     return JSObject::DeleteProperty(thread, JSHandle<JSObject>(typedarray), key);
276 }
277 
278 // 9.4.5.6 [[OwnPropertyKeys]] ( )
OwnPropertyKeys(JSThread * thread,const JSHandle<JSTaggedValue> & typedarray)279 JSHandle<TaggedArray> JSTypedArray::OwnPropertyKeys(JSThread *thread, const JSHandle<JSTaggedValue> &typedarray)
280 {
281     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
282     // 1. Let keys be a new empty List.
283     // 2. Assert: O is an Object that has [[ViewedArrayBuffer]], [[ArrayLength]], [[ByteOffset]], and
284     // [[TypedArrayName]] internal slots.
285     // 3. Let len be the value of O’s [[ArrayLength]] internal slot.
286     JSHandle<JSTypedArray> arrayObj(typedarray);
287     JSHandle<TaggedArray> objKeys = JSObject::GetOwnPropertyKeys(thread, JSHandle<JSObject>::Cast(arrayObj));
288     uint32_t objKeysLen = objKeys->GetLength();
289     uint32_t bufferKeysLen = arrayObj->GetArrayLength();
290     uint32_t length = objKeysLen + bufferKeysLen;
291     JSHandle<TaggedArray> nameList = factory->NewTaggedArray(length);
292 
293     // 4. For each integer i starting with 0 such that i < len, in ascending order,
294     //   a. Add ToString(i) as the last element of keys.
295     uint32_t copyLength = 0;
296     JSMutableHandle<JSTaggedValue> tKey(thread, JSTaggedValue::Undefined());
297     for (uint32_t k = 0; k < bufferKeysLen; k++) {
298         tKey.Update(JSTaggedValue(k));
299         JSHandle<JSTaggedValue> sKey(JSTaggedValue::ToString(thread, tKey));
300         RETURN_HANDLE_IF_ABRUPT_COMPLETION(TaggedArray, thread);
301         nameList->Set(thread, copyLength, sKey.GetTaggedValue());
302         copyLength++;
303     }
304 
305     // 5. For each own property key P of O such that Type(P) is String and P is not an integer index, in
306     // property creation order
307     //   a. Add P as the last element of keys.
308     for (uint32_t i = 0; i < objKeysLen; i++) {
309         JSTaggedValue key = objKeys->Get(thread, i);
310         if (JSTaggedValue(key).IsString()) {
311             nameList->Set(thread, copyLength, key);
312             copyLength++;
313         }
314     }
315 
316     // 6. For each own property key P of O such that Type(P) is Symbol, in property creation order
317     //   a. Add P as the last element of keys.
318     for (uint32_t i = 0; i < objKeysLen; i++) {
319         JSTaggedValue key = objKeys->Get(thread, i);
320         if (JSTaggedValue(key).IsSymbol()) {
321             nameList->Set(thread, copyLength, key);
322             copyLength++;
323         }
324     }
325 
326     // 7. Return keys.
327     return factory->CopyArray(nameList, length, copyLength);
328 }
329 
OwnEnumPropertyKeys(JSThread * thread,const JSHandle<JSTaggedValue> & typedarray)330 JSHandle<TaggedArray> JSTypedArray::OwnEnumPropertyKeys(JSThread *thread, const JSHandle<JSTaggedValue> &typedarray)
331 {
332     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
333     // 1. Let keys be a new empty List.
334     // 2. Assert: O is an Object that has [[ViewedArrayBuffer]], [[ArrayLength]], [[ByteOffset]], and
335     // [[TypedArrayName]] internal slots.
336     // 3. Let len be the value of O’s [[ArrayLength]] internal slot.
337     JSHandle<JSTypedArray> arrayObj(typedarray);
338     JSHandle<TaggedArray> objKeys = JSObject::GetOwnEnumPropertyKeys(thread, JSHandle<JSObject>::Cast(arrayObj));
339     uint32_t objKeysLen = objKeys->GetLength();
340     uint32_t bufferKeysLen = arrayObj->GetArrayLength();
341     uint32_t length = objKeysLen + bufferKeysLen;
342     JSHandle<TaggedArray> nameList = factory->NewTaggedArray(length);
343 
344     // 4. For each integer i starting with 0 such that i < len, in ascending order,
345     //   a. Add ToString(i) as the last element of keys.
346     uint32_t copyLength = 0;
347     for (uint32_t k = 0; k < bufferKeysLen; k++) {
348         auto key = base::NumberHelper::IntToEcmaString(thread, k);
349         nameList->Set(thread, copyLength, key);
350         copyLength++;
351     }
352 
353     // 5. For each own property key P of O such that Type(P) is String and P is not an integer index, in
354     // property creation order
355     //   a. Add P as the last element of keys.
356     for (uint32_t i = 0; i < objKeysLen; i++) {
357         JSTaggedValue key = objKeys->Get(thread, i);
358         nameList->Set(thread, copyLength, key);
359         copyLength++;
360     }
361 
362     // 7. Return keys.
363     return factory->CopyArray(nameList, length, copyLength);
364 }
365 
366 // 9.4.5.7 IntegerIndexedObjectCreate (prototype, internalSlotsList)
367 
368 // 9.4.5.8 IntegerIndexedElementGet ( O, index )
IntegerIndexedElementGet(JSThread * thread,const JSHandle<JSTaggedValue> & typedarray,JSTaggedValue index)369 OperationResult JSTypedArray::IntegerIndexedElementGet(JSThread *thread, const JSHandle<JSTaggedValue> &typedarray,
370                                                        JSTaggedValue index)
371 {
372     // 1. Assert: Type(index) is Number.
373     ASSERT(index.IsNumber());
374     // 2. Assert: O is an Object that has [[ViewedArrayBuffer]], [[ArrayLength]], [[ByteOffset]], and
375     // [[TypedArrayName]] internal slots.
376     ASSERT(typedarray->IsTypedArray() || typedarray->IsSharedTypedArray());
377     // 3. Let buffer be the value of O’s [[ViewedArrayBuffer]] internal slot.
378     JSHandle<JSTypedArray> typedarrayObj(typedarray);
379     JSTaggedValue buffer = typedarrayObj->GetViewedArrayBufferOrByteArray(thread);
380     // 4. If IsDetachedBuffer(buffer) is true, throw a TypeError exception.
381     if (!buffer.IsSendableArrayBuffer() && BuiltinsArrayBuffer::IsDetachedBuffer(thread, buffer)) {
382         if (index == JSTaggedValue(0)) {
383             return OperationResult(thread, JSTaggedValue::Undefined(), PropertyMetaData(true));
384         }
385         THROW_TYPE_ERROR_AND_RETURN(thread, "Is Detached Buffer",
386                                     OperationResult(thread, JSTaggedValue::Exception(), PropertyMetaData(false)));
387     }
388     if (buffer.IsSendableArrayBuffer() && BuiltinsSendableArrayBuffer::IsDetachedBuffer(thread, buffer)) {
389         THROW_TYPE_ERROR_AND_RETURN(thread, "Is Detached Buffer",
390                                     OperationResult(thread, JSTaggedValue::Exception(), PropertyMetaData(false)));
391     }
392     // 5. If IsInteger(index) is false, return undefined
393     if (!index.IsInteger()) {
394         return OperationResult(thread, JSTaggedValue::Undefined(), PropertyMetaData(true));
395     }
396 
397     // 6. If index = −0, return undefined.
398     // 7. Let length be the value of O’s [[ArrayLength]] internal slot.
399     // 8. If index < 0 or index ≥ length, return undefined.
400     JSHandle<JSTaggedValue> indexHandle(thread, index);
401     JSTaggedNumber indexNumber = JSTaggedValue::ToNumber(thread, indexHandle);
402     RETURN_VALUE_IF_ABRUPT_COMPLETION(
403         thread, OperationResult(thread, JSTaggedValue::Exception(), PropertyMetaData(false)));
404     double tNegZero = -0.0;
405     auto eZero = JSTaggedNumber(tNegZero);
406     JSHandle<JSTaggedValue> zero(thread, JSTaggedValue(0));
407     if (JSTaggedNumber::SameValue(indexNumber, eZero)) {
408         return OperationResult(thread, JSTaggedValue::Undefined(), PropertyMetaData(true));
409     }
410     uint32_t arrLen = typedarrayObj->GetArrayLength();
411     JSHandle<JSTaggedValue> arrLenHandle(thread, JSTaggedValue(arrLen));
412     if (JSTaggedValue::Less(thread, indexHandle, zero) || !JSTaggedValue::Less(thread, indexHandle, arrLenHandle)) {
413         return OperationResult(thread, JSTaggedValue::Undefined(), PropertyMetaData(true));
414     }
415     // 9. Let offset be the value of O’s [[ByteOffset]] internal slot.
416     uint32_t offset = typedarrayObj->GetByteOffset();
417     // 10. Let arrayTypeName be the String value of O’s [[TypedArrayName]] internal slot.
418     // 11. Let elementSize be the Number value of the Element Size value specified in Table 49 for
419     // arrayTypeName.
420     uint32_t elementSize = TypedArrayHelper::GetElementSize(typedarrayObj);
421     // 12. Let indexedPosition = (index × elementSize) + offset.
422     JSTaggedNumber integerValue = JSTaggedValue::ToInteger(thread, indexHandle);
423     RETURN_VALUE_IF_ABRUPT_COMPLETION(
424         thread, OperationResult(thread, JSTaggedValue::Exception(), PropertyMetaData(false)));
425     uint32_t k = static_cast<uint32_t>(integerValue.ToInt32());
426     uint32_t byteIndex = k * elementSize + offset;
427     // 13. Let elementType be the String value of the Element Type value in Table 49 for arrayTypeName.
428     DataViewType elementType = TypedArrayHelper::GetType(typedarrayObj);
429     // 14. Return GetValueFromBuffer(buffer, indexedPosition, elementType).
430     JSTaggedValue result = BuiltinsArrayBuffer::GetValueFromBuffer(thread, buffer, byteIndex, elementType, true);
431     return OperationResult(thread, result, PropertyMetaData(true));
432 }
433 
434 // s12 10.4.5.9 IsValidIntegerIndex ( O, index )
IsValidIntegerIndex(JSThread * thread,const JSHandle<JSTaggedValue> & typedArray,JSTaggedValue index)435 bool JSTypedArray::IsValidIntegerIndex(JSThread *thread, const JSHandle<JSTaggedValue> &typedArray, JSTaggedValue index)
436 {
437     // 1. Assert: O is an Integer-Indexed exotic object.
438     ASSERT(typedArray->IsTypedArray() || typedArray->IsSharedTypedArray());
439     // 2. If IsDetachedBuffer(O.[[ViewedArrayBuffer]]) is true, return false.
440     JSHandle<JSTypedArray> typedarrayObj(typedArray);
441     JSTaggedValue buffer = typedarrayObj->GetViewedArrayBufferOrByteArray(thread);
442     if (IsArrayBufferDetached(thread, buffer)) {
443         return false;
444     }
445     // 3. If ! IsIntegralNumber(index) is false, return false.
446     if (!index.IsInteger()) {
447         return false;
448     }
449     // 4. If index is -0��, return false.
450     double val = index.GetNumber();
451     if (val == 0 && std::signbit(val)) {
452         return false;
453     }
454 
455     uint32_t arrLen = typedarrayObj->GetArrayLength();
456     // 5. If ℝ(index) < 0 or ℝ(index) ≥ O.[[ArrayLength]], return false.
457     if (val < 0 || val >= arrLen) {
458         return false;
459     }
460     // 6. Return true.
461     return true;
462 }
463 
GetTypeFromName(JSThread * thread,const JSHandle<JSTaggedValue> & typeName)464 DataViewType JSTypedArray::GetTypeFromName(JSThread *thread, const JSHandle<JSTaggedValue> &typeName)
465 {
466     auto type = thread->GetEcmaVM()->GetDataViewType(typeName.GetTaggedType());
467     if (type != -1) {
468         return DataViewType(type);
469     }
470     const GlobalEnvConstants *globalConst = thread->GlobalConstants();
471     if (JSTaggedValue::SameValue(thread, typeName, globalConst->GetHandledInt8ArrayString()) ||
472         JSTaggedValue::SameValue(thread, typeName, globalConst->GetHandledSharedInt8ArrayString())) {
473         return DataViewType::INT8;
474     }
475     if (JSTaggedValue::SameValue(thread, typeName, globalConst->GetHandledUint8ArrayString()) ||
476         JSTaggedValue::SameValue(thread, typeName, globalConst->GetHandledSharedUint8ArrayString())) {
477         return DataViewType::UINT8;
478     }
479     if (JSTaggedValue::SameValue(thread, typeName, globalConst->GetHandledUint8ClampedArrayString()) ||
480         JSTaggedValue::SameValue(thread, typeName, globalConst->GetHandledSharedUint8ClampedArrayString())) {
481         return DataViewType::UINT8_CLAMPED;
482     }
483     if (JSTaggedValue::SameValue(thread, typeName, globalConst->GetHandledInt16ArrayString()) ||
484         JSTaggedValue::SameValue(thread, typeName, globalConst->GetHandledSharedInt16ArrayString())) {
485         return DataViewType::INT16;
486     }
487     if (JSTaggedValue::SameValue(thread, typeName, globalConst->GetHandledUint16ArrayString()) ||
488         JSTaggedValue::SameValue(thread, typeName, globalConst->GetHandledSharedUint16ArrayString())) {
489         return DataViewType::UINT16;
490     }
491     if (JSTaggedValue::SameValue(thread, typeName, globalConst->GetHandledInt32ArrayString()) ||
492         JSTaggedValue::SameValue(thread, typeName, globalConst->GetHandledSharedInt32ArrayString())) {
493         return DataViewType::INT32;
494     }
495     if (JSTaggedValue::SameValue(thread, typeName, globalConst->GetHandledUint32ArrayString()) ||
496         JSTaggedValue::SameValue(thread, typeName, globalConst->GetHandledSharedUint32ArrayString())) {
497         return DataViewType::UINT32;
498     }
499     if (JSTaggedValue::SameValue(thread, typeName, globalConst->GetHandledFloat32ArrayString()) ||
500         JSTaggedValue::SameValue(thread, typeName, globalConst->GetHandledSharedFloat32ArrayString())) {
501         return DataViewType::FLOAT32;
502     }
503     if (JSTaggedValue::SameValue(thread, typeName, globalConst->GetHandledFloat64ArrayString()) ||
504         JSTaggedValue::SameValue(thread, typeName, globalConst->GetHandledSharedFloat64ArrayString())) {
505         return DataViewType::FLOAT64;
506     }
507     if (JSTaggedValue::SameValue(thread, typeName, globalConst->GetHandledBigInt64ArrayString()) ||
508         JSTaggedValue::SameValue(thread, typeName, globalConst->GetHandledSharedBigInt64ArrayString())) {
509         return DataViewType::BIGINT64;
510     }
511     return DataViewType::BIGUINT64;
512 }
513 
514 // static
FastCopyElementToArray(JSThread * thread,const JSHandle<JSTaggedValue> & typedArray,JSHandle<TaggedArray> & array)515 bool JSTypedArray::FastCopyElementToArray(JSThread *thread, const JSHandle<JSTaggedValue> &typedArray,
516                                           JSHandle<TaggedArray> &array)
517 {
518     // 2. Assert: O is an Object that has [[ViewedArrayBuffer]], [[ArrayLength]], [[ByteOffset]], and
519     // [[TypedArrayName]] internal slots.
520     ASSERT(typedArray->IsTypedArray() || typedArray->IsSharedTypedArray());
521     // 3. Let buffer be the value of O’s [[ViewedArrayBuffer]] internal slot.
522     JSHandle<JSTypedArray> typedarrayObj(typedArray);
523     // 4. If IsDetachedBuffer(buffer) is true, throw a TypeError exception.
524     JSHandle<JSTaggedValue> bufferHandle =
525         JSHandle<JSTaggedValue>(thread, typedarrayObj->GetViewedArrayBufferOrByteArray(thread));
526     if (IsArrayBufferDetached(thread, bufferHandle.GetTaggedValue())) {
527         THROW_TYPE_ERROR_AND_RETURN(thread, "Is Detached Buffer", false);
528     }
529 
530     // 7. Let length be the value of O’s [[ArrayLength]] internal slot.
531     // 8. If index < 0 or index ≥ length, return undefined.
532     uint32_t arrLen = typedarrayObj->GetArrayLength();
533 
534     // 9. Let offset be the value of O’s [[ByteOffset]] internal slot.
535     uint32_t offset = typedarrayObj->GetByteOffset();
536     // 11. Let elementSize be the Number value of the Element Size value specified in Table 49 for arrayTypeName.
537     uint32_t elementSize = TypedArrayHelper::GetElementSize(typedarrayObj);
538     // 13. Let elementType be the String value of the Element Type value in Table 49 for arrayTypeName.
539     DataViewType elementType = TypedArrayHelper::GetType(typedarrayObj);
540     for (uint32_t index = 0; index < arrLen; index++) {
541         // 12. Let indexedPosition = (index × elementSize) + offset.
542         uint32_t byteIndex = index * elementSize + offset;
543         // 14. Return GetValueFromBuffer(buffer, indexedPosition, elementType).
544         JSTaggedValue result = BuiltinsArrayBuffer::GetValueFromBuffer(thread, bufferHandle.GetTaggedValue(),
545                                                                        byteIndex, elementType, true);
546         array->Set(thread, index, result);
547     }
548     return true;
549 }
550 
551 // static
FastElementGet(JSThread * thread,const JSHandle<JSTaggedValue> & typedarray,uint32_t index)552 OperationResult JSTypedArray::FastElementGet(JSThread *thread, const JSHandle<JSTaggedValue> &typedarray,
553                                              uint32_t index)
554 {
555     // 2. Assert: O is an Object that has [[ViewedArrayBuffer]], [[ArrayLength]], [[ByteOffset]], and
556     // [[TypedArrayName]] internal slots.
557     ASSERT(typedarray->IsTypedArray() || typedarray->IsSharedTypedArray());
558     // 3. Let buffer be the value of O’s [[ViewedArrayBuffer]] internal slot.
559     JSHandle<JSTypedArray> typedarrayObj(typedarray);
560     JSTaggedValue buffer = typedarrayObj->GetViewedArrayBufferOrByteArray(thread);
561     // 10.4.5.15 TypedArrayGetElement ( O, index )
562     //  1. If IsValidIntegerIndex(O, index) is false, return undefined.
563     if (IsArrayBufferDetached(thread, buffer)) {
564         return OperationResult(thread, JSTaggedValue::Undefined(), PropertyMetaData(true));
565     }
566 
567     // 7. Let length be the value of O’s [[ArrayLength]] internal slot.
568     // 8. If index < 0 or index ≥ length, return undefined.
569     uint32_t arrLen = typedarrayObj->GetArrayLength();
570     if (index >= arrLen) {
571         return OperationResult(thread, JSTaggedValue::Undefined(), PropertyMetaData(true));
572     }
573     // 9. Let offset be the value of O’s [[ByteOffset]] internal slot.
574     uint32_t offset = typedarrayObj->GetByteOffset();
575     // 11. Let elementSize be the Number value of the Element Size value specified in Table 49 for arrayTypeName.
576     uint32_t elementSize = TypedArrayHelper::GetElementSize(typedarrayObj);
577     // 12. Let indexedPosition = (index × elementSize) + offset.
578     uint32_t byteIndex = index * elementSize + offset;
579     // 13. Let elementType be the String value of the Element Type value in Table 49 for arrayTypeName.
580     DataViewType elementType = TypedArrayHelper::GetType(typedarrayObj);
581     // 14. Return GetValueFromBuffer(buffer, indexedPosition, elementType).
582     JSTaggedValue result = BuiltinsArrayBuffer::GetValueFromBuffer(thread, buffer, byteIndex, elementType, true);
583     return OperationResult(thread, result, PropertyMetaData(true));
584 }
585 
586 // 9.4.5.9 IntegerIndexedElementSet ( O, index, value )
IntegerIndexedElementSet(JSThread * thread,const JSHandle<JSTaggedValue> & typedarray,JSTaggedValue index,const JSHandle<JSTaggedValue> & value)587 bool JSTypedArray::IntegerIndexedElementSet(JSThread *thread, const JSHandle<JSTaggedValue> &typedarray,
588                                             JSTaggedValue index, const JSHandle<JSTaggedValue> &value)
589 {
590     // 1. Assert: Type(index) is Number.
591     ASSERT(index.IsNumber());
592     // 2. Assert: O is an Object that has [[ViewedArrayBuffer]], [[ArrayLength]], [[ByteOffset]], and
593     // [[TypedArrayName]] internal slots.
594     ASSERT(typedarray->IsTypedArray() || typedarray->IsSharedTypedArray());
595     // 3. If O.[[ContentType]] is BigInt, let numValue be ? ToBigInt(value).
596     JSHandle<JSTaggedValue> numValueHandle;
597     ContentType contentType = JSHandle<JSTypedArray>::Cast(typedarray)->GetContentType();
598     if (UNLIKELY(contentType == ContentType::BigInt)) {
599         numValueHandle = JSHandle<JSTaggedValue>(thread, JSTaggedValue::ToBigInt(thread, value));
600         RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false);
601     } else {
602         numValueHandle = JSHandle<JSTaggedValue>(thread, JSTaggedValue::ToNumber(thread, value));
603         RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false);
604     }
605 
606     JSHandle<JSTypedArray> typedarrayObj(typedarray);
607     JSTaggedValue buffer = typedarrayObj->GetViewedArrayBufferOrByteArray(thread);
608     JSHandle<JSTaggedValue> indexHandle(thread, index);
609     // 5. If ! IsValidIntegerIndex(O, index) is true, then
610     if (IsValidIntegerIndex(thread, typedarray, index)) {
611         // 6. Let offset be the value of O’s [[ByteOffset]] internal slot.
612         uint32_t offset = typedarrayObj->GetByteOffset();
613         // 7. Let arrayTypeName be the String value of O’s [[TypedArrayName]] internal slot.
614         // 8. Let elementSize be the Number value of the Element Size value specified in Table 49 for
615         // arrayTypeName.
616         uint32_t elementSize = TypedArrayHelper::GetElementSize(typedarrayObj);
617         // 9. Let indexedPosition = (index × elementSize) + offset.
618         JSTaggedNumber integerValue = JSTaggedValue::ToInteger(thread, indexHandle);
619         RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false);
620         uint32_t k = integerValue.ToUint32();
621         uint32_t byteIndex = k * elementSize + offset;
622         // 10. Let elementType be the String value of the Element Type value in Table 49 for arrayTypeName.
623         DataViewType elementType = TypedArrayHelper::GetType(typedarrayObj);
624         // 11. Perform SetValueInBuffer(buffer, indexedPosition, elementType, numValue).
625         BuiltinsArrayBuffer::SetValueInBuffer(thread, buffer, byteIndex, elementType, numValueHandle, true);
626         RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false);
627     }
628     return true;
629 }
630 
631 // only use in TypeArray fast set property
NonEcmaObjectToNumber(JSThread * thread,const JSTaggedValue tagged)632 JSTaggedNumber JSTypedArray::NonEcmaObjectToNumber(JSThread *thread, const JSTaggedValue tagged)
633 {
634     ASSERT_PRINT(!tagged.IsECMAObject(), "tagged must not be EcmaObject");
635     if (tagged.IsInt() || tagged.IsDouble()) {
636         return JSTaggedNumber(tagged);
637     }
638     if (tagged.IsString()) {
639         return JSTaggedValue::StringToDouble(thread, tagged);
640     }
641     switch (tagged.GetRawData()) {
642         case JSTaggedValue::VALUE_UNDEFINED:
643         case JSTaggedValue::VALUE_HOLE: {
644             return JSTaggedNumber(base::NAN_VALUE);
645         }
646         case JSTaggedValue::VALUE_TRUE: {
647             return JSTaggedNumber(1);
648         }
649         case JSTaggedValue::VALUE_FALSE:
650         case JSTaggedValue::VALUE_NULL: {
651             return JSTaggedNumber(0);
652         }
653         default: {
654             break;
655         }
656     }
657     if (tagged.IsSymbol()) {
658         THROW_TYPE_ERROR_AND_RETURN(thread, "Cannot convert a Symbol value to a number", JSTaggedNumber::Exception());
659     }
660     if (tagged.IsBigInt()) {
661         THROW_TYPE_ERROR_AND_RETURN(thread, "Cannot convert a BigInt value to a number", JSTaggedNumber::Exception());
662     }
663     THROW_TYPE_ERROR_AND_RETURN(thread, "Cannot convert a Unknown value to a number", JSTaggedNumber::Exception());
664 }
665 
FastGetPropertyByIndex(JSThread * thread,const JSTaggedValue typedarray,uint32_t index,JSType jsType)666 JSTaggedValue JSTypedArray::FastGetPropertyByIndex(JSThread *thread, const JSTaggedValue typedarray, uint32_t index,
667                                                    JSType jsType)
668 {
669     // Assert: O is an Object that has [[ViewedArrayBuffer]], [[ArrayLength]], [[ByteOffset]], and
670     // [[TypedArrayName]] internal slots.
671     ASSERT(typedarray.IsTypedArray() || typedarray.IsSharedTypedArray());
672     // Let buffer be the value of O’s [[ViewedArrayBuffer]] internal slot.
673     JSTypedArray *typedarrayObj = JSTypedArray::Cast(typedarray.GetTaggedObject());
674     JSTaggedValue buffer = typedarrayObj->GetViewedArrayBufferOrByteArray(thread);
675     if (IsArrayBufferDetached(thread, buffer)) {
676         return JSTaggedValue::Undefined();
677     }
678 
679     // Let length be the value of O’s [[ArrayLength]] internal slot.
680     // If arrLen < 0 or index ≥ length, return undefined.
681     uint32_t arrLen = typedarrayObj->GetArrayLength();
682     if (index >= arrLen) {
683         return JSTaggedValue::Undefined();
684     }
685     // Let offset be the value of O’s [[ByteOffset]] internal slot.
686     uint32_t offset = typedarrayObj->GetByteOffset();
687     // Let elementSize be the Number value of the Element Size value specified in Table 49 for arrayTypeName.
688     uint32_t elementSize = TypedArrayHelper::GetElementSize(jsType);
689     // Let indexedPosition = (index × elementSize) + offset.
690     uint32_t byteIndex = index * elementSize + offset;
691     // Let elementType be the String value of the Element Type value in Table 49 for arrayTypeName.
692     DataViewType elementType = TypedArrayHelper::GetType(jsType);
693     // Return GetValueFromBuffer(buffer, indexedPosition, elementType).
694     return BuiltinsArrayBuffer::GetValueFromBuffer(thread, buffer, byteIndex, elementType, true);
695 }
696 
FastSetPropertyByIndex(JSThread * thread,const JSTaggedValue typedarray,uint32_t index,JSTaggedValue value,JSType jsType)697 JSTaggedValue JSTypedArray::FastSetPropertyByIndex(JSThread *thread, const JSTaggedValue typedarray, uint32_t index,
698                                                    JSTaggedValue value, JSType jsType)
699 {
700     // Assert: O is an Object that has [[ViewedArrayBuffer]], [[ArrayLength]], [[ByteOffset]], and
701     // [[TypedArrayName]] internal slots.
702     ASSERT(typedarray.IsTypedArray() || typedarray.IsSharedTypedArray());
703     // If O.[[ContentType]] is BigInt, let numValue be ? ToBigInt(value).
704     JSTypedArray *typedarrayObj = JSTypedArray::Cast(typedarray.GetTaggedObject());
705     if (UNLIKELY(typedarrayObj->GetContentType() == ContentType::BigInt || value.IsECMAObject())) {
706         return JSTaggedValue::Hole();
707     }
708     JSTaggedNumber numValue = JSTypedArray::NonEcmaObjectToNumber(thread, value);
709     // ReturnIfAbrupt(numValue).
710     RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception());
711 
712     DISALLOW_GARBAGE_COLLECTION;
713     JSTaggedValue buffer = typedarrayObj->GetViewedArrayBufferOrByteArray(thread);
714 
715     // If ℝ(index) < 0 or ℝ(index) ≥ O.[[ArrayLength]], return false.
716     uint32_t arrLen = typedarrayObj->GetArrayLength();
717     if (index >= arrLen) {
718         return JSTaggedValue::Undefined();
719     }
720     // Let offset be the value of O’s [[ByteOffset]] internal slot.
721     uint32_t offset = typedarrayObj->GetByteOffset();
722     // Let arrayTypeName be the String value of O’s [[TypedArrayName]]
723     // Let elementSize be the Number value of the Element Size value specified in Table 49 for
724     // arrayTypeName.
725     uint32_t elementSize = TypedArrayHelper::GetElementSize(jsType);
726     // Let indexedPosition = (index × elementSize) + offset.
727     uint32_t byteIndex = index * elementSize + offset;
728     // Let elementType be the String value of the Element Type value in Table 49 for arrayTypeName.
729     DataViewType elementType = TypedArrayHelper::GetType(jsType);
730     // Perform SetValueInBuffer(buffer, indexedPosition, elementType, numValue).
731     return BuiltinsArrayBuffer::FastSetValueInBuffer(thread,
732         buffer, byteIndex, elementType, numValue.GetNumber(), true);
733 }
734 
GetOffHeapBuffer(JSThread * thread,JSHandle<JSTypedArray> & typedArray)735 JSTaggedValue JSTypedArray::GetOffHeapBuffer(JSThread *thread, JSHandle<JSTypedArray> &typedArray)
736 {
737     JSTaggedValue arrBuf = typedArray->GetViewedArrayBufferOrByteArray(thread);
738     if (arrBuf.IsArrayBuffer() || arrBuf.IsSharedArrayBuffer()) {
739         return arrBuf;
740     }
741 
742     ByteArray *byteArray = ByteArray::Cast(arrBuf.GetTaggedObject());
743     int32_t length = static_cast<int32_t>(byteArray->GetArrayLength() * byteArray->GetByteLength());
744     JSHandle<JSArrayBuffer> arrayBuffer = thread->GetEcmaVM()->GetFactory()->NewJSArrayBuffer(length);
745 
746     if (length > 0) {
747         void *fromBuf = reinterpret_cast<void *>(ToUintPtr(
748             ByteArray::Cast(typedArray->GetViewedArrayBufferOrByteArray(thread).GetTaggedObject())->GetData()));
749         JSTaggedValue data = arrayBuffer->GetArrayBufferData(thread);
750         void *toBuf = reinterpret_cast<void *>(
751             ToUintPtr(JSNativePointer::Cast(data.GetTaggedObject())->GetExternalPointer()));
752         JSArrayBuffer::CopyDataPointBytes(toBuf, fromBuf, 0, length);
753     }
754     typedArray->SetViewedArrayBufferOrByteArray(thread, arrayBuffer.GetTaggedValue());
755     JSHandle<JSTaggedValue> typeName(thread, typedArray->GetTypedArrayName(thread));
756     DataViewType arrayType = JSTypedArray::GetTypeFromName(thread, typeName);
757     JSHandle<JSHClass> notOnHeapHclass = TypedArrayHelper::GetNotOnHeapHclassFromType(
758         thread, typedArray, arrayType);
759 #if ECMASCRIPT_ENABLE_IC
760     JSHClass::NotifyHclassChanged(thread, JSHandle<JSHClass>(thread, typedArray->GetJSHClass()), notOnHeapHclass);
761 #endif
762     TaggedObject::Cast(*typedArray)->SynchronizedTransitionClass(thread, *notOnHeapHclass); // onHeap->notOnHeap
763 
764     return arrayBuffer.GetTaggedValue();
765 }
766 
GetSharedOffHeapBuffer(JSThread * thread,JSHandle<JSSharedTypedArray> typedArray)767 JSTaggedValue JSSharedTypedArray::GetSharedOffHeapBuffer(JSThread *thread, JSHandle<JSSharedTypedArray> typedArray)
768 {
769     JSTaggedValue arrBuf = typedArray->GetViewedArrayBufferOrByteArray(thread);
770     if (arrBuf.IsSendableArrayBuffer()) {
771         return arrBuf;
772     }
773 
774     ByteArray *byteArray = ByteArray::Cast(arrBuf.GetTaggedObject());
775     int32_t length = static_cast<int32_t>(byteArray->GetArrayLength() * byteArray->GetByteLength());
776     JSHandle<JSSendableArrayBuffer> arrayBuffer = thread->GetEcmaVM()->GetFactory()->NewJSSendableArrayBuffer(length);
777 
778     if (length > 0) {
779         void *fromBuf = reinterpret_cast<void *>(ToUintPtr(
780             ByteArray::Cast(typedArray->GetViewedArrayBufferOrByteArray(thread).GetTaggedObject())->GetData()));
781         JSTaggedValue data = arrayBuffer->GetArrayBufferData(thread);
782         void *toBuf = reinterpret_cast<void *>(
783             ToUintPtr(JSNativePointer::Cast(data.GetTaggedObject())->GetExternalPointer()));
784         JSSendableArrayBuffer::CopyDataPointBytes(toBuf, fromBuf, 0, length);
785     }
786     typedArray->SetViewedArrayBufferOrByteArray(thread, arrayBuffer.GetTaggedValue());
787     JSHandle<JSTaggedValue> typeName(thread, typedArray->GetTypedArrayName(thread));
788     DataViewType arrayType = JSTypedArray::GetTypeFromName(thread, typeName);
789     JSHandle<JSHClass> notOnHeapHclass = TypedArrayHelper::GetSharedNotOnHeapHclassFromType(
790         thread, typedArray, arrayType);
791 #if ECMASCRIPT_ENABLE_IC
792     JSHClass::NotifyHclassChanged(thread, JSHandle<JSHClass>(thread, typedArray->GetJSHClass()), notOnHeapHclass);
793 #endif
794     TaggedObject::Cast(*typedArray)->SynchronizedTransitionClass(thread, *notOnHeapHclass); // onHeap->notOnHeap
795 
796     return arrayBuffer.GetTaggedValue();
797 }
798 
FastTypedArrayFill(JSThread * thread,const JSHandle<JSTaggedValue> & typedArray,const JSHandle<JSTaggedValue> & value,uint32_t start,uint32_t end)799 bool JSTypedArray::FastTypedArrayFill(JSThread *thread, const JSHandle<JSTaggedValue> &typedArray,
800                                       const JSHandle<JSTaggedValue> &value, uint32_t start, uint32_t end)
801 {
802     // Assert: O is an Object that has [[ViewedArrayBuffer]], [[ArrayLength]], [[ByteOffset]], and
803     // [[TypedArrayName]] internal slots.
804     ASSERT(typedArray->IsTypedArray() || typedArray->IsSharedTypedArray());
805     // If O.[[ContentType]] is BigInt, let numValue be ? ToBigInt(value).
806     JSHandle<JSTypedArray> typedArrayObj = JSHandle<JSTypedArray>::Cast(typedArray);
807     if (UNLIKELY(typedArrayObj->GetContentType() == ContentType::BigInt || value->IsECMAObject())) {
808         return false;
809     }
810     JSTaggedNumber numValue = JSTypedArray::NonEcmaObjectToNumber(thread, value.GetTaggedValue());
811     // ReturnIfAbrupt(numValue).
812     RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, true);
813     JSTaggedValue buffer = typedArrayObj->GetViewedArrayBufferOrByteArray(thread);
814     // If ℝ(index) < 0 or ℝ(index) ≥ O.[[ArrayLength]], return false.
815     uint32_t arrLen = typedArrayObj->GetArrayLength();
816     // Let offset be the value of O’s [[ByteOffset]] internal slot.
817     uint32_t offset = typedArrayObj->GetByteOffset();
818     // Let arrayTypeName be the String value of O’s [[TypedArrayName]]
819     // Let elementSize be the Number value of the Element Size value specified in Table 49 for arrayTypeName.
820     JSType jsType = typedArrayObj->GetClass()->GetObjectType();
821     uint32_t elementSize = TypedArrayHelper::GetElementSize(jsType);
822     // Let elementType be the String value of the Element Type value in Table 49 for arrayTypeName.
823     DataViewType elementType = TypedArrayHelper::GetType(jsType);
824     uint64_t byteBeginOffset = start * elementSize + offset;
825     uint64_t byteEndOffset = std::min(end, arrLen) * elementSize + offset;
826     if (byteBeginOffset < byteEndOffset) {
827         BuiltinsArrayBuffer::TryFastSetValueInBuffer(thread, buffer,
828             byteBeginOffset, byteEndOffset, elementType, numValue.GetNumber(), true);
829     }
830     return true;
831 }
832 
IsArrayBufferDetached(JSThread * thread,JSTaggedValue buffer)833 inline bool JSTypedArray::IsArrayBufferDetached(JSThread *thread, JSTaggedValue buffer)
834 {
835     if (!buffer.IsSendableArrayBuffer() && BuiltinsArrayBuffer::IsDetachedBuffer(thread, buffer)) {
836         return true;
837     }
838     if (buffer.IsSendableArrayBuffer() && BuiltinsSendableArrayBuffer::IsDetachedBuffer(thread, buffer)) {
839         return true;
840     }
841     return false;
842 }
843 }  // namespace panda::ecmascript
844