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