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