• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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 #include "ecmascript/accessor_data.h"
18 #include "ecmascript/base/typed_array_helper-inl.h"
19 #include "ecmascript/builtins/builtins_arraybuffer.h"
20 
21 namespace panda::ecmascript {
22 using TypedArrayHelper = base::TypedArrayHelper;
23 using BuiltinsArrayBuffer = builtins::BuiltinsArrayBuffer;
24 
ToPropKey(JSThread * thread,const JSHandle<JSTaggedValue> & key)25 JSHandle<JSTaggedValue> JSTypedArray::ToPropKey(JSThread *thread, const JSHandle<JSTaggedValue> &key)
26 {
27     if (key->IsSymbol()) {
28         return key;
29     }
30     return JSHandle<JSTaggedValue>(JSTaggedValue::ToString(thread, key));
31 }
32 // 9.4.5.1 [[GetOwnProperty]] ( P )
GetOwnProperty(JSThread * thread,const JSHandle<JSTaggedValue> & typedarray,const JSHandle<JSTaggedValue> & key,PropertyDescriptor & desc)33 bool JSTypedArray::GetOwnProperty(JSThread *thread, const JSHandle<JSTaggedValue> &typedarray,
34                                   const JSHandle<JSTaggedValue> &key, PropertyDescriptor &desc)
35 {
36     // 1. Assert : IsPropertyKey(P) is true.
37     ASSERT(JSTaggedValue::IsPropertyKey(key));
38     // 2. Assert: O is an Object that has a [[ViewedArrayBuffer]] internal slot.
39     // 3. If Type(P) is String, then
40     //   a. Let numericIndex be CanonicalNumericIndexString(P).
41     //   b. Assert: numericIndex is not an abrupt completion.
42     //   c. If numericIndex is not undefined, then
43     //     i. Let value be IntegerIndexedElementGet (O, numericIndex).
44     //     ii. ReturnIfAbrupt(value).
45     //     iii. If value is undefined, return undefined.
46     //     iv. Return a PropertyDescriptor{ [[Value]]: value, [[Enumerable]]: true, [[Writable]]: true,
47     //         [[Configurable]]: false }.
48     if (key->IsString()) {
49         JSTaggedValue numericIndex = JSTaggedValue::CanonicalNumericIndexString(thread, key);
50         RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false);
51         if (!numericIndex.IsUndefined()) {
52             JSHandle<JSTaggedValue> value =
53                 JSTypedArray::IntegerIndexedElementGet(thread, typedarray, numericIndex).GetValue();
54             RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false);
55             if (value->IsUndefined()) {
56                 return false;
57             }
58             desc.SetValue(value);
59             desc.SetEnumerable(true);
60             desc.SetWritable(true);
61             desc.SetConfigurable(true);
62             return true;
63         }
64     }
65     // 4. Return OrdinaryGetOwnProperty(O, P).
66     return JSObject::OrdinaryGetOwnProperty(thread, JSHandle<JSObject>(typedarray), key, desc);
67 }
68 
69 // 9.4.5.2 [[HasProperty]] ( P )
HasProperty(JSThread * thread,const JSHandle<JSTaggedValue> & typedarray,const JSHandle<JSTaggedValue> & key)70 bool JSTypedArray::HasProperty(JSThread *thread, const JSHandle<JSTaggedValue> &typedarray,
71                                const JSHandle<JSTaggedValue> &key)
72 {
73     // 1. Assert: IsPropertyKey(P) is true.
74     ASSERT(JSTaggedValue::IsPropertyKey(key));
75     // 2. Assert: O is an Object that has a [[ViewedArrayBuffer]] internal slot.
76     // 3. If Type(P) is String, then
77     //   a. Let numericIndex be CanonicalNumericIndexString(P).
78     //   b. Assert: numericIndex is not an abrupt completion.
79     //   c. If numericIndex is not undefined, then
80     //     i. Let buffer be the value of O’s [[ViewedArrayBuffer]] internal slot.
81     //     ii. If IsDetachedBuffer(buffer) is true, throw a TypeError exception.
82     //     iii. If IsInteger(numericIndex) is false, return false
83     //     iv. If numericIndex = −0, return false.
84     //     v. If numericIndex < 0, return false.
85     //     vi. If numericIndex ≥ the value of O’s [[ArrayLength]] internal slot, return false.
86     //     vii. Return true.
87     JSHandle<JSObject> typedarrayObj(typedarray);
88     if (key->IsString()) {
89         JSTaggedValue numericIndex = JSTaggedValue::CanonicalNumericIndexString(thread, key);
90         RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false);
91         if (!numericIndex.IsUndefined()) {
92             JSTaggedValue buffer = JSTypedArray::Cast(*typedarrayObj)->GetViewedArrayBuffer();
93             if (BuiltinsArrayBuffer::IsDetachedBuffer(buffer)) {
94                 THROW_TYPE_ERROR_AND_RETURN(thread, "Is Detached Buffer", false);
95             }
96             if (!numericIndex.IsInteger()) {
97                 return false;
98             }
99             JSHandle<JSTaggedValue> numericIndexHandle(thread, numericIndex);
100             JSTaggedNumber numericIndexNumber = JSTaggedValue::ToNumber(thread, numericIndexHandle);
101             double tNegZero = -0.0;
102             auto eZero = JSTaggedNumber(tNegZero);
103             JSHandle<JSTaggedValue> zero(thread, JSTaggedValue(0));
104             if (JSTaggedNumber::SameValue(numericIndexNumber, eZero)) {
105                 return false;
106             }
107 
108             if (JSTaggedValue::Less(thread, numericIndexHandle, zero)) {
109                 return false;
110             }
111             int32_t arrLen = TypedArrayHelper::GetArrayLength(thread, typedarrayObj);
112             JSHandle<JSTaggedValue> arrLenHandle(thread, JSTaggedValue(arrLen));
113             return JSTaggedValue::Less(thread, numericIndexHandle, arrLenHandle);
114         }
115     }
116     // 4. Return OrdinaryHasProperty(O, P).
117     PropertyDescriptor desc(thread);
118     if (JSObject::OrdinaryGetOwnProperty(thread, typedarrayObj, key, desc)) {
119         return true;
120     }
121     JSTaggedValue parent = typedarrayObj->GetPrototype(thread);
122     if (!parent.IsNull()) {
123         return JSTaggedValue::HasProperty(thread, JSHandle<JSTaggedValue>(thread, parent), key);
124     }
125     return false;
126 }
127 
128 // 9.4.5.3 [[DefineOwnProperty]] ( P, Desc )
DefineOwnProperty(JSThread * thread,const JSHandle<JSTaggedValue> & typedarray,const JSHandle<JSTaggedValue> & key,const PropertyDescriptor & desc)129 bool JSTypedArray::DefineOwnProperty(JSThread *thread, const JSHandle<JSTaggedValue> &typedarray,
130                                      const JSHandle<JSTaggedValue> &key, const PropertyDescriptor &desc)
131 {
132     // 1. Assert: IsPropertyKey(P) is true.
133     ASSERT(JSTaggedValue::IsPropertyKey(key));
134     // 2. Assert: O is an Object that has a [[ViewedArrayBuffer]] internal slot.
135     // 3. If Type(P) is String, then
136     //   a. Let numericIndex be CanonicalNumericIndexString (P).
137     //   b. Assert: numericIndex is not an abrupt completion.
138     //   c. If numericIndex is not undefined, then
139     JSHandle<JSObject> typedarrayObj(typedarray);
140     if (key->IsString()) {
141         JSTaggedValue numericIndex = JSTaggedValue::CanonicalNumericIndexString(thread, key);
142         RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false);
143         if (!numericIndex.IsUndefined()) {
144             // i. If IsInteger(numericIndex) is false, return false
145             // ii. Let intIndex be numericIndex.
146             // iii. If intIndex = −0, return false.
147             // iv. If intIndex < 0, return false.
148             // v. Let length be the value of O’s [[ArrayLength]] internal slot.
149             // vi. If intIndex ≥ length, return false.
150             // vii. If IsAccessorDescriptor(Desc) is true, return false.
151             // viii. If Desc has a [[Configurable]] field and if Desc.[[Configurable]] is true, return false.
152             // ix. If Desc has an [[Enumerable]] field and if Desc.[[Enumerable]] is false, return false.
153             // x. If Desc has a [[Writable]] field and if Desc.[[Writable]] is false, return false.
154             // xi. If Desc has a [[Value]] field, then
155             //   1. Let value be Desc.[[Value]].
156             //   2. Return IntegerIndexedElementSet (O, intIndex, value).
157             // xii. Return true.
158             if (!numericIndex.IsInteger()) {
159                 return false;
160             }
161             JSHandle<JSTaggedValue> numericIndexHandle(thread, numericIndex);
162             JSTaggedNumber numericIndexNumber = JSTaggedValue::ToNumber(thread, numericIndexHandle);
163             double tNegZero = -0.0;
164             auto eZero = JSTaggedNumber(tNegZero);
165             JSHandle<JSTaggedValue> zero(thread, JSTaggedValue(0));
166             if (JSTaggedNumber::SameValue(numericIndexNumber, eZero)) {
167                 return false;
168             }
169             if (JSTaggedValue::Less(thread, numericIndexHandle, zero)) {
170                 return false;
171             }
172             int32_t arrLen = TypedArrayHelper::GetArrayLength(thread, typedarrayObj);
173             JSHandle<JSTaggedValue> arrLenHandle(thread, JSTaggedValue(arrLen));
174             if (!JSTaggedValue::Less(thread, numericIndexHandle, arrLenHandle)) {
175                 return false;
176             }
177             if (desc.IsAccessorDescriptor()) {
178                 return false;
179             }
180             if (desc.HasConfigurable() && !desc.IsConfigurable()) {
181                 return false;
182             }
183             if (desc.HasEnumerable() && !desc.IsEnumerable()) {
184                 return false;
185             }
186             if (desc.HasWritable() && !desc.IsWritable()) {
187                 return false;
188             }
189             if (desc.HasValue()) {
190                 JSHandle<JSTaggedValue> value = desc.GetValue();
191                 return (JSTypedArray::IntegerIndexedElementSet(thread, typedarray, numericIndex, value));
192             }
193             return true;
194         }
195     }
196     // 4. Return OrdinaryDefineOwnProperty(O, P, Desc).
197     return JSObject::OrdinaryDefineOwnProperty(thread, typedarrayObj, key, desc);
198 }
199 
200 // 9.4.5.4 [[Get]] ( P, Receiver )
GetProperty(JSThread * thread,const JSHandle<JSTaggedValue> & typedarray,const JSHandle<JSTaggedValue> & key,const JSHandle<JSTaggedValue> & receiver)201 OperationResult JSTypedArray::GetProperty(JSThread *thread, const JSHandle<JSTaggedValue> &typedarray,
202                                           const JSHandle<JSTaggedValue> &key, const JSHandle<JSTaggedValue> &receiver)
203 {
204     // 1. Assert : IsPropertyKey(P) is true.
205     ASSERT(JSTaggedValue::IsPropertyKey(key));
206     // 2. If Type(P) is String and if SameValue(O, Receiver) is true, then
207     if (key->IsString() && JSTaggedValue::SameValue(typedarray, receiver)) {
208         //   a. Let numericIndex be CanonicalNumericIndexString (P).
209         //   b. Assert: numericIndex is not an abrupt completion.
210         //   c. If numericIndex is not undefined, then
211         //     i. Return IntegerIndexedElementGet (O, numericIndex).
212         JSTaggedValue numericIndex = JSTaggedValue::CanonicalNumericIndexString(thread, key);
213         RETURN_VALUE_IF_ABRUPT_COMPLETION(
214             thread, OperationResult(thread, JSTaggedValue::Exception(), PropertyMetaData(false)));
215         if (!numericIndex.IsUndefined()) {
216             return JSTypedArray::IntegerIndexedElementGet(thread, typedarray, numericIndex);
217         }
218     }
219 
220     // 3. Return the result of calling the default ordinary object [[Get]] internal method (9.1.8) on O
221     //   passing P and Receiver as arguments.
222     return JSObject::GetProperty(thread, typedarray, key, receiver);
223 }
224 
225 // 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)226 bool JSTypedArray::SetProperty(JSThread *thread, const JSHandle<JSTaggedValue> &typedarray,
227                                const JSHandle<JSTaggedValue> &key, const JSHandle<JSTaggedValue> &value,
228                                const JSHandle<JSTaggedValue> &receiver, bool mayThrow)
229 {
230     // 1. Assert : IsPropertyKey(P) is true.
231     ASSERT(JSTaggedValue::IsPropertyKey(key));
232     // 2. If Type(P) is String and if SameValue(O, Receiver) is true, then
233     if (key->IsString() && JSTaggedValue::SameValue(typedarray, receiver)) {
234         //   a. Let numericIndex be CanonicalNumericIndexString (P).
235         //   b. Assert: numericIndex is not an abrupt completion.
236         //   c. If numericIndex is not undefined, then
237         //     i. Return IntegerIndexedElementSet (O, numericIndex, V).
238         JSTaggedValue numericIndex = JSTaggedValue::CanonicalNumericIndexString(thread, key);
239         RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false);
240         if (!numericIndex.IsUndefined()) {
241             return JSTypedArray::IntegerIndexedElementSet(thread, typedarray, numericIndex, value);
242         }
243     }
244     // 3. Return the result of calling the default ordinary object [[Set]] internal method (9.1.8) on O passing
245     // P, V, and Receiver as arguments.
246     return JSObject::SetProperty(thread, typedarray, key, value, receiver, mayThrow);
247 }
248 
249 // 9.4.5.6 [[OwnPropertyKeys]] ( )
OwnPropertyKeys(JSThread * thread,const JSHandle<JSTaggedValue> & typedarray)250 JSHandle<TaggedArray> JSTypedArray::OwnPropertyKeys(JSThread *thread, const JSHandle<JSTaggedValue> &typedarray)
251 {
252     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
253     // 1. Let keys be a new empty List.
254     // 2. Assert: O is an Object that has [[ViewedArrayBuffer]], [[ArrayLength]], [[ByteOffset]], and
255     // [[TypedArrayName]] internal slots.
256     // 3. Let len be the value of O’s [[ArrayLength]] internal slot.
257     JSHandle<JSObject> arrayObj(typedarray);
258     JSHandle<TaggedArray> objKeys = JSObject::GetOwnPropertyKeys(thread, arrayObj);
259     uint32_t objKeysLen = objKeys->GetLength();
260     uint32_t bufferKeysLen = TypedArrayHelper::GetArrayLength(thread, arrayObj);
261     uint32_t length = objKeysLen + bufferKeysLen;
262     JSHandle<TaggedArray> nameList = factory->NewTaggedArray(length);
263 
264     // 4. For each integer i starting with 0 such that i < len, in ascending order,
265     //   a. Add ToString(i) as the last element of keys.
266     uint32_t copyLength = 0;
267     JSMutableHandle<JSTaggedValue> tKey(thread, JSTaggedValue::Undefined());
268     for (uint32_t k = 0; k < bufferKeysLen; k++) {
269         tKey.Update(JSTaggedValue(k));
270         JSHandle<JSTaggedValue> sKey(JSTaggedValue::ToString(thread, tKey));
271         nameList->Set(thread, copyLength, sKey.GetTaggedValue());
272         copyLength++;
273     }
274 
275     // 5. For each own property key P of O such that Type(P) is String and P is not an integer index, in
276     // property creation order
277     //   a. Add P as the last element of keys.
278     for (uint32_t i = 0; i < objKeysLen; i++) {
279         JSTaggedValue key = objKeys->Get(i);
280         if (JSTaggedValue(key).IsString()) {
281             nameList->Set(thread, copyLength, key);
282             copyLength++;
283         }
284     }
285 
286     // 6. For each own property key P of O such that Type(P) is Symbol, in property creation order
287     //   a. Add P as the last element of keys.
288     for (uint32_t i = 0; i < objKeysLen; i++) {
289         JSTaggedValue key = objKeys->Get(i);
290         if (JSTaggedValue(key).IsSymbol()) {
291             nameList->Set(thread, copyLength, key);
292             copyLength++;
293         }
294     }
295 
296     // 7. Return keys.
297     return factory->CopyArray(nameList, length, copyLength);
298 }
299 
300 // 9.4.5.7 IntegerIndexedObjectCreate (prototype, internalSlotsList)
301 
302 // 9.4.5.8 IntegerIndexedElementGet ( O, index )
IntegerIndexedElementGet(JSThread * thread,const JSHandle<JSTaggedValue> & typedarray,JSTaggedValue index)303 OperationResult JSTypedArray::IntegerIndexedElementGet(JSThread *thread, const JSHandle<JSTaggedValue> &typedarray,
304                                                        JSTaggedValue index)
305 {
306     // 1. Assert: Type(index) is Number.
307     ASSERT(index.IsNumber());
308     // 2. Assert: O is an Object that has [[ViewedArrayBuffer]], [[ArrayLength]], [[ByteOffset]], and
309     // [[TypedArrayName]] internal slots.
310     ASSERT(typedarray->IsTypedArray());
311     // 3. Let buffer be the value of O’s [[ViewedArrayBuffer]] internal slot.
312     JSHandle<JSObject> typedarrayObj(typedarray);
313     JSTaggedValue buffer = JSTypedArray::Cast(*typedarrayObj)->GetViewedArrayBuffer();
314     // 4. If IsDetachedBuffer(buffer) is true, throw a TypeError exception.
315     if (BuiltinsArrayBuffer::IsDetachedBuffer(buffer)) {
316         THROW_TYPE_ERROR_AND_RETURN(thread, "Is Detached Buffer",
317                                     OperationResult(thread, JSTaggedValue::Exception(), PropertyMetaData(false)));
318     }
319     // 5. If IsInteger(index) is false, return undefined
320     if (!index.IsInteger()) {
321         return OperationResult(thread, JSTaggedValue::Undefined(), PropertyMetaData(true));
322     }
323 
324     // 6. If index = −0, return undefined.
325     // 7. Let length be the value of O’s [[ArrayLength]] internal slot.
326     // 8. If index < 0 or index ≥ length, return undefined.
327     JSHandle<JSTaggedValue> indexHandle(thread, index);
328     JSTaggedNumber indexNumber = JSTaggedValue::ToNumber(thread, indexHandle);
329     double tNegZero = -0.0;
330     auto eZero = JSTaggedNumber(tNegZero);
331     JSHandle<JSTaggedValue> zero(thread, JSTaggedValue(0));
332     if (JSTaggedNumber::SameValue(indexNumber, eZero)) {
333         return OperationResult(thread, JSTaggedValue::Undefined(), PropertyMetaData(true));
334     }
335     int32_t arrLen = TypedArrayHelper::GetArrayLength(thread, typedarrayObj);
336     JSHandle<JSTaggedValue> arrLenHandle(thread, JSTaggedValue(arrLen));
337     if (JSTaggedValue::Less(thread, indexHandle, zero) || !JSTaggedValue::Less(thread, indexHandle, arrLenHandle)) {
338         return OperationResult(thread, JSTaggedValue::Undefined(), PropertyMetaData(true));
339     }
340     // 9. Let offset be the value of O’s [[ByteOffset]] internal slot.
341     int32_t offset = TypedArrayHelper::GetByteOffset(thread, typedarrayObj);
342     // 10. Let arrayTypeName be the String value of O’s [[TypedArrayName]] internal slot.
343     // 11. Let elementSize be the Number value of the Element Size value specified in Table 49 for
344     // arrayTypeName.
345     int32_t elementSize = TypedArrayHelper::GetElementSize(typedarrayObj);
346     // 12. Let indexedPosition = (index × elementSize) + offset.
347     int32_t k = JSTaggedValue::ToInteger(thread, indexHandle).ToInt32();
348     int32_t byteIndex = k * elementSize + offset;
349     // 13. Let elementType be the String value of the Element Type value in Table 49 for arrayTypeName.
350     DataViewType elementType = TypedArrayHelper::GetType(typedarrayObj);
351     // 14. Return GetValueFromBuffer(buffer, indexedPosition, elementType).
352     JSTaggedValue result = BuiltinsArrayBuffer::GetValueFromBuffer(buffer, byteIndex, elementType, true);
353     return OperationResult(thread, result, PropertyMetaData(true));
354 }
355 
356 // static
FastCopyElementToArray(JSThread * thread,const JSHandle<JSTaggedValue> & typedArray,JSHandle<TaggedArray> & array)357 bool JSTypedArray::FastCopyElementToArray(JSThread *thread, const JSHandle<JSTaggedValue> &typedArray,
358                                           JSHandle<TaggedArray> &array)
359 {
360     // 2. Assert: O is an Object that has [[ViewedArrayBuffer]], [[ArrayLength]], [[ByteOffset]], and
361     // [[TypedArrayName]] internal slots.
362     ASSERT(typedArray->IsTypedArray());
363     // 3. Let buffer be the value of O’s [[ViewedArrayBuffer]] internal slot.
364     JSHandle<JSObject> typedarrayObj(typedArray);
365     JSTaggedValue buffer = JSTypedArray::Cast(*typedarrayObj)->GetViewedArrayBuffer();
366     // 4. If IsDetachedBuffer(buffer) is true, throw a TypeError exception.
367     if (BuiltinsArrayBuffer::IsDetachedBuffer(buffer)) {
368         THROW_TYPE_ERROR_AND_RETURN(thread, "Is Detached Buffer", false);
369     }
370 
371     // 7. Let length be the value of O’s [[ArrayLength]] internal slot.
372     // 8. If index < 0 or index ≥ length, return undefined.
373     int32_t arrLen = TypedArrayHelper::GetArrayLength(thread, typedarrayObj);
374     if (arrLen < 0) {
375         return false;
376     }
377 
378     // 9. Let offset be the value of O’s [[ByteOffset]] internal slot.
379     int32_t offset = TypedArrayHelper::GetByteOffset(thread, typedarrayObj);
380     // 11. Let elementSize be the Number value of the Element Size value specified in Table 49 for arrayTypeName.
381     int32_t elementSize = TypedArrayHelper::GetElementSize(typedarrayObj);
382     // 13. Let elementType be the String value of the Element Type value in Table 49 for arrayTypeName.
383     DataViewType elementType = TypedArrayHelper::GetType(typedarrayObj);
384     for (int index = 0; index < arrLen; index++) {
385         // 12. Let indexedPosition = (index × elementSize) + offset.
386         int32_t byteIndex = index * elementSize + offset;
387         // 14. Return GetValueFromBuffer(buffer, indexedPosition, elementType).
388         JSTaggedValue result = BuiltinsArrayBuffer::GetValueFromBuffer(buffer, byteIndex, elementType, true);
389         array->Set(thread, index, result);
390     }
391     return true;
392 }
393 
394 // static
FastElementGet(JSThread * thread,const JSHandle<JSTaggedValue> & typedarray,uint32_t index)395 OperationResult JSTypedArray::FastElementGet(JSThread *thread, const JSHandle<JSTaggedValue> &typedarray,
396                                              uint32_t index)
397 {
398     // 2. Assert: O is an Object that has [[ViewedArrayBuffer]], [[ArrayLength]], [[ByteOffset]], and
399     // [[TypedArrayName]] internal slots.
400     ASSERT(typedarray->IsTypedArray());
401     // 3. Let buffer be the value of O’s [[ViewedArrayBuffer]] internal slot.
402     JSHandle<JSObject> typedarrayObj(typedarray);
403     JSTaggedValue buffer = JSTypedArray::Cast(*typedarrayObj)->GetViewedArrayBuffer();
404     // 4. If IsDetachedBuffer(buffer) is true, throw a TypeError exception.
405     if (BuiltinsArrayBuffer::IsDetachedBuffer(buffer)) {
406         THROW_TYPE_ERROR_AND_RETURN(thread, "Is Detached Buffer",
407                                     OperationResult(thread, JSTaggedValue::Exception(), PropertyMetaData(false)));
408     }
409 
410     // 7. Let length be the value of O’s [[ArrayLength]] internal slot.
411     // 8. If index < 0 or index ≥ length, return undefined.
412     int32_t arrLen = TypedArrayHelper::GetArrayLength(thread, typedarrayObj);
413     if (arrLen < 0 || index >= static_cast<uint32_t>(arrLen)) {
414         return OperationResult(thread, JSTaggedValue::Undefined(), PropertyMetaData(true));
415     }
416     // 9. Let offset be the value of O’s [[ByteOffset]] internal slot.
417     int32_t offset = TypedArrayHelper::GetByteOffset(thread, typedarrayObj);
418     // 11. Let elementSize be the Number value of the Element Size value specified in Table 49 for arrayTypeName.
419     int32_t elementSize = TypedArrayHelper::GetElementSize(typedarrayObj);
420     // 12. Let indexedPosition = (index × elementSize) + offset.
421     int32_t byteIndex = index * elementSize + offset;
422     // 13. Let elementType be the String value of the Element Type value in Table 49 for arrayTypeName.
423     DataViewType elementType = TypedArrayHelper::GetType(typedarrayObj);
424     // 14. Return GetValueFromBuffer(buffer, indexedPosition, elementType).
425     JSTaggedValue result = BuiltinsArrayBuffer::GetValueFromBuffer(buffer, byteIndex, elementType, true);
426     return OperationResult(thread, result, PropertyMetaData(true));
427 }
428 
429 // 9.4.5.9 IntegerIndexedElementSet ( O, index, value )
IntegerIndexedElementSet(JSThread * thread,const JSHandle<JSTaggedValue> & typedarray,JSTaggedValue index,const JSHandle<JSTaggedValue> & value)430 bool JSTypedArray::IntegerIndexedElementSet(JSThread *thread, const JSHandle<JSTaggedValue> &typedarray,
431                                             JSTaggedValue index, const JSHandle<JSTaggedValue> &value)
432 {
433     // 1. Assert: Type(index) is Number.
434     ASSERT(index.IsNumber());
435     // 2. Assert: O is an Object that has [[ViewedArrayBuffer]], [[ArrayLength]], [[ByteOffset]], and
436     // [[TypedArrayName]] internal slots.
437     ASSERT(typedarray->IsTypedArray());
438     // 3. Let numValue be ToNumber(value).
439     JSTaggedNumber numVal = JSTaggedValue::ToNumber(thread, value);
440     // 4. ReturnIfAbrupt(numValue).
441     RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false);
442 
443     // 5. Let buffer be the value of O’s [[ViewedArrayBuffer]] internal slot.
444     JSHandle<JSObject> typedarrayObj(typedarray);
445     JSTaggedValue buffer = JSTypedArray::Cast(*typedarrayObj)->GetViewedArrayBuffer();
446     // 6. If IsDetachedBuffer(buffer) is true, throw a TypeError exception.
447     if (BuiltinsArrayBuffer::IsDetachedBuffer(buffer)) {
448         THROW_TYPE_ERROR_AND_RETURN(thread, "Is Detached Buffer", false);
449     }
450     // 7. If IsInteger(index) is false, return false
451     if (!index.IsInteger()) {
452         return false;
453     }
454 
455     // 8. If index = −0, return false.
456     // 9. Let length be the value of O’s [[ArrayLength]] internal slot.
457     // 10. If index < 0 or index ≥ length, return false.
458     JSHandle<JSTaggedValue> indexHandle(thread, index);
459     JSTaggedNumber indexNumber = JSTaggedValue::ToNumber(thread, indexHandle);
460     double tNegZero = -0.0;
461     auto eZero = JSTaggedNumber(tNegZero);
462     JSHandle<JSTaggedValue> zero(thread, JSTaggedValue(0));
463     if (JSTaggedNumber::SameValue(indexNumber, eZero)) {
464         return false;
465     }
466     int32_t arrLen = TypedArrayHelper::GetArrayLength(thread, typedarrayObj);
467     JSHandle<JSTaggedValue> arrLenHandle(thread, JSTaggedValue(arrLen));
468     if (JSTaggedValue::Less(thread, indexHandle, zero) || !JSTaggedValue::Less(thread, indexHandle, arrLenHandle)) {
469         return false;
470     }
471 
472     // 11. Let offset be the value of O’s [[ByteOffset]] internal slot.
473     int32_t offset = TypedArrayHelper::GetByteOffset(thread, typedarrayObj);
474     // 12. Let arrayTypeName be the String value of O’s [[TypedArrayName]] internal slot.
475     // 13. Let elementSize be the Number value of the Element Size value specified in Table 49 for
476     // arrayTypeName.
477     int32_t elementSize = TypedArrayHelper::GetElementSize(typedarrayObj);
478     // 14. Let indexedPosition = (index × elementSize) + offset.
479     int32_t k = JSTaggedValue::ToInteger(thread, indexHandle).ToInt32();
480     int32_t byteIndex = k * elementSize + offset;
481     // 15. Let elementType be the String value of the Element Type value in Table 49 for arrayTypeName.
482     DataViewType elementType = TypedArrayHelper::GetType(typedarrayObj);
483     // 16. Perform SetValueInBuffer(buffer, indexedPosition, elementType, numValue).
484     BuiltinsArrayBuffer::SetValueInBuffer(buffer, byteIndex, elementType, numVal, true);
485     // 17. Return true.
486     return true;
487 }
488 }  // namespace panda::ecmascript
489