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