1/* 2 * Copyright (c) 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/builtins/builtins_shared_array.h" 17 18#include <cmath> 19 20#include "ecmascript/builtins/builtins_array.h" 21#include "ecmascript/builtins/builtins_string.h" 22#include "ecmascript/interpreter/interpreter.h" 23#include "ecmascript/js_map_iterator.h" 24#include "ecmascript/js_stable_array.h" 25#include "ecmascript/object_fast_operator-inl.h" 26 27namespace panda::ecmascript::builtins { 28namespace { 29 constexpr int32_t COUNT_LENGTH_AND_INIT = 2; 30} // namespace 31using ArrayHelper = base::ArrayHelper; 32using TypedArrayHelper = base::TypedArrayHelper; 33using ContainerError = containers::ContainerError; 34 35// 22.1.1 36JSTaggedValue BuiltinsSharedArray::ArrayConstructor(EcmaRuntimeCallInfo *argv) 37{ 38 BUILTINS_ENTRY_DEBUG_LOG(); 39 ASSERT(argv); 40 BUILTINS_API_TRACE(argv->GetThread(), SharedArray, Constructor); 41 JSThread *thread = argv->GetThread(); 42 [[maybe_unused]] EcmaHandleScope handleScope(thread); 43 44 // 1. Let numberOfArgs be the number of arguments passed to this function call. 45 uint32_t argc = argv->GetArgsNumber(); 46 47 // 3. If NewTarget is undefined, throw exception 48 JSHandle<JSTaggedValue> newTarget = GetNewTarget(argv); 49 if (newTarget->IsUndefined()) { 50 JSTaggedValue error = containers::ContainerError::BusinessError( 51 thread, containers::ErrorFlag::IS_NULL_ERROR, "The ArkTS Array's constructor cannot be directly invoked."); 52 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 53 } 54 55 // 4. Let proto be GetPrototypeFromConstructor(newTarget, "%ArrayPrototype%"). 56 // In NewJSObjectByConstructor(), will get prototype. 57 // 5. ReturnIfAbrupt(proto). 58 59 // 22.1.1.1 Array ( ) 60 if (argc == 0) { 61 // 6. Return ArrayCreate(0, proto). 62 return JSSharedArray::ArrayCreate(thread, JSTaggedNumber(0), newTarget).GetTaggedValue(); 63 } 64 65 // 22.1.1.3 Array(...items ) 66 JSTaggedValue newArray = JSSharedArray::ArrayCreate(thread, JSTaggedNumber(argc), newTarget).GetTaggedValue(); 67 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 68 if (!newArray.IsJSSharedArray()) { 69 THROW_TYPE_ERROR_AND_RETURN(thread, "Failed to create array.", JSTaggedValue::Exception()); 70 } 71 JSHandle<JSObject> newArrayHandle(thread, newArray); 72 // 8. Let k be 0. 73 // 9. Let items be a zero-origined List containing the argument items in order. 74 // 10. Repeat, while k < numberOfArgs 75 // a. Let Pk be ToString(k). 76 // b. Let itemK be items[k]. 77 // c. Let defineStatus be CreateDataProperty(array, Pk, itemK). 78 // d. Assert: defineStatus is true. 79 // e. Increase k by 1. 80 JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined()); 81 JSMutableHandle<JSTaggedValue> itemK(thread, JSTaggedValue::Undefined()); 82 for (uint32_t k = 0; k < argc; k++) { 83 key.Update(JSTaggedValue(k)); 84 itemK.Update(GetCallArg(argv, k)); 85 if (!itemK->IsSharedType()) { 86 auto error = ContainerError::ParamError(thread, "Parameter error.Only accept sendable value."); 87 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 88 } 89 JSObject::CreateDataProperty(thread, newArrayHandle, key, itemK); 90 } 91 // 11. Assert: the value of array’s length property is numberOfArgs. 92 // 12. Return array. 93 JSSharedArray::Cast(*newArrayHandle)->SetArrayLength(thread, argc); 94 newArrayHandle->GetJSHClass()->SetExtensible(false); 95 return newArrayHandle.GetTaggedValue(); 96} 97 98// 22.1.2.1 Array.from ( items [ , mapfn [ , thisArg ] ] ) 99// NOLINTNEXTLINE(readability-function-size) 100JSTaggedValue BuiltinsSharedArray::From(EcmaRuntimeCallInfo *argv) 101{ 102 ASSERT(argv); 103 BUILTINS_API_TRACE(argv->GetThread(), SharedArray, From); 104 JSThread *thread = argv->GetThread(); 105 [[maybe_unused]] EcmaHandleScope handleScope(thread); 106 // 1. Let C be the this value. 107 JSHandle<JSTaggedValue> thisHandle = GetThis(argv); 108 // 2. If mapfn is undefined, let mapping be false. 109 bool mapping = false; 110 // 3. else 111 // a. If IsCallable(mapfn) is false, throw a TypeError exception. 112 // b. If thisArg was supplied, let T be thisArg; else let T be undefined. 113 // c. Let mapping be true 114 JSHandle<JSTaggedValue> thisArgHandle = GetCallArg(argv, INDEX_TWO); 115 JSHandle<JSTaggedValue> mapfn = GetCallArg(argv, 1); 116 if (!mapfn->IsUndefined()) { 117 if (!mapfn->IsCallable()) { 118 THROW_TYPE_ERROR_AND_RETURN(thread, "the mapfn is not callable.", JSTaggedValue::Exception()); 119 } 120 mapping = true; 121 } 122 // 4. Let usingIterator be GetMethod(items, @@iterator). 123 JSHandle<JSTaggedValue> items = GetCallArg(argv, 0); 124 if (items->IsNull()) { 125 THROW_TYPE_ERROR_AND_RETURN(thread, "The items is null.", JSTaggedValue::Exception()); 126 } 127 if (!mapping && items->IsString()) { 128 JSHandle<EcmaString> strItems(items); 129 return BuiltinsString::StringToSList(thread, strItems); 130 } 131 // Fast path for TypedArray 132 if (!mapping && (items->IsTypedArray() || items->IsSharedTypedArray())) { 133 auto error = ContainerError::ParamError(thread, "Parameter error.TypedArray not support yet."); 134 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 135 } 136 137 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv(); 138 JSHandle<JSTaggedValue> iteratorSymbol = env->GetIteratorSymbol(); 139 JSHandle<JSTaggedValue> usingIterator = JSObject::GetMethod(thread, items, iteratorSymbol); 140 // 5. ReturnIfAbrupt(usingIterator). 141 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 142 // 6. If usingIterator is not undefined, then 143 JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined(); 144 if (!usingIterator->IsUndefined()) { 145 // Fast path for MapIterator 146 JSHandle<JSTaggedValue> iterator(thread, JSTaggedValue::Hole()); 147 if (!mapping && items->IsJSMapIterator()) { 148 iterator = JSIterator::GetIterator(thread, items, usingIterator); 149 if (iterator->IsJSMapIterator()) { 150 return JSMapIterator::MapIteratorToList(thread, iterator); 151 } 152 } 153 154 // a. If IsConstructor(C) is true, then 155 // i. Let A be Construct(C). 156 // b. Else, 157 // i. Let A be ArrayCreate(0). 158 // c. ReturnIfAbrupt(A). 159 JSTaggedValue newArray; 160 if (thisHandle->IsConstructor()) { 161 EcmaRuntimeCallInfo *info = 162 EcmaInterpreter::NewRuntimeCallInfo(thread, thisHandle, undefined, undefined, 0); 163 newArray = JSFunction::Construct(info); 164 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 165 } else { 166 newArray = JSSharedArray::ArrayCreate(thread, JSTaggedNumber(0)).GetTaggedValue(); 167 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 168 } 169 if (!newArray.IsJSSharedArray()) { 170 THROW_TYPE_ERROR_AND_RETURN(thread, "Failed to construct the array.", JSTaggedValue::Exception()); 171 } 172 JSHandle<JSObject> newArrayHandle(thread, newArray); 173 // d. Let iterator be GetIterator(items, usingIterator). 174 if (iterator->IsHole()) { 175 iterator = JSIterator::GetIterator(thread, items, usingIterator); 176 // e. ReturnIfAbrupt(iterator). 177 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 178 } 179 // f. Let k be 0. 180 int k = 0; 181 // g. Repeat 182 JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined()); 183 JSMutableHandle<JSTaggedValue> mapValue(thread, JSTaggedValue::Undefined()); 184 while (true) { 185 key.Update(JSTaggedValue(k)); 186 // i. Let Pk be ToString(k). 187 // ii. Let next be IteratorStep(iterator). 188 JSHandle<JSTaggedValue> next = JSIterator::IteratorStep(thread, iterator); 189 // iii. ReturnIfAbrupt(next). 190 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 191 // iv. If next is false, then 192 // 1. Let setStatus be Set(A, "length", k, true). 193 // 2. ReturnIfAbrupt(setStatus). 194 // 3. Return A. 195 if (next->IsFalse()) { 196 JSSharedArray::LengthSetter(thread, newArrayHandle, key, true); 197 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 198 newArrayHandle->GetJSHClass()->SetExtensible(false); 199 return newArrayHandle.GetTaggedValue(); 200 } 201 // v. Let nextValue be IteratorValue(next). 202 JSHandle<JSTaggedValue> nextValue = JSIterator::IteratorValue(thread, next); 203 // vi. ReturnIfAbrupt(nextValue). 204 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 205 // vii. If mapping is true, then 206 // 1. Let mappedValue be Call(mapfn, T, «nextValue, k»). 207 // 2. If mappedValue is an abrupt completion, return IteratorClose(iterator, mappedValue). 208 // 3. Let mappedValue be mappedValue.[[value]]. 209 // viii. Else, let mappedValue be nextValue. 210 if (mapping) { 211 const uint32_t argsLength = 2; // 2: «nextValue, k» 212 EcmaRuntimeCallInfo *info = 213 EcmaInterpreter::NewRuntimeCallInfo(thread, mapfn, thisArgHandle, undefined, argsLength); 214 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 215 info->SetCallArg(nextValue.GetTaggedValue(), key.GetTaggedValue()); 216 JSTaggedValue callResult = JSFunction::Call(info); 217 RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, 218 JSIterator::IteratorClose(thread, iterator, mapValue).GetTaggedValue()); 219 mapValue.Update(callResult); 220 } else { 221 mapValue.Update(nextValue.GetTaggedValue()); 222 } 223 if (!mapValue->IsSharedType()) { 224 auto error = ContainerError::ParamError(thread, "Parameter error.Only accept sendable value."); 225 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 226 } 227 // ix. Let defineStatus be CreateDataPropertyOrThrow(A, Pk, mappedValue). 228 // x. If defineStatus is an abrupt completion, return IteratorClose(iterator, defineStatus). 229 // xi. Increase k by 1. 230 JSHandle<JSTaggedValue> defineStatus(thread, JSTaggedValue(JSObject::CreateDataPropertyOrThrow( 231 thread, newArrayHandle, key, mapValue, SCheckMode::SKIP))); 232 RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, 233 JSIterator::IteratorClose(thread, iterator, defineStatus).GetTaggedValue()); 234 k++; 235 } 236 } 237 // 7. Assert: items is not an Iterable so assume it is an array-like object. 238 // 8. Let arrayLike be ToObject(items). 239 JSHandle<JSObject> arrayLikeObj = JSTaggedValue::ToObject(thread, items); 240 // 9. ReturnIfAbrupt(arrayLike). 241 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 242 JSHandle<JSTaggedValue> arrayLike(arrayLikeObj); 243 // 10. Let len be ToLength(Get(arrayLike, "length")). 244 int64_t len = ArrayHelper::GetArrayLength(thread, arrayLike); 245 // 11. ReturnIfAbrupt(len). 246 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 247 // 12. If IsConstructor(C) is true, then 248 // a. Let A be Construct(C, «len»). 249 // 13. Else, 250 // a. Let A be ArrayCreate(len). 251 // 14. ReturnIfAbrupt(A). 252 JSTaggedValue newArray; 253 if (thisHandle->IsConstructor()) { 254 EcmaRuntimeCallInfo *info = 255 EcmaInterpreter::NewRuntimeCallInfo(thread, thisHandle, undefined, undefined, 1); 256 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 257 info->SetCallArg(JSTaggedValue(len)); 258 newArray = JSFunction::Construct(info); 259 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 260 } else { 261 newArray = JSSharedArray::ArrayCreate(thread, JSTaggedNumber(static_cast<double>(len))).GetTaggedValue(); 262 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 263 } 264 if (!newArray.IsJSSharedArray()) { 265 THROW_TYPE_ERROR_AND_RETURN(thread, "Failed to construct the array.", JSTaggedValue::Exception()); 266 } 267 JSHandle<JSObject> newArrayHandle(thread, newArray); 268 // 15. Let k be 0. 269 // 16. Repeat, while k < len 270 // a. Let Pk be ToString(k). 271 // b. Let kValue be Get(arrayLike, Pk). 272 // d. If mapping is true, then 273 // i. Let mappedValue be Call(mapfn, T, «kValue, k»). 274 // e. Else, let mappedValue be kValue. 275 // f. Let defineStatus be CreateDataPropertyOrThrow(A, Pk, mappedValue). 276 JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined()); 277 JSMutableHandle<JSTaggedValue> mapValue(thread, JSTaggedValue::Undefined()); 278 int64_t k = 0; 279 while (k < len) { 280 JSHandle<JSTaggedValue> kValue = JSSharedArray::FastGetPropertyByValue(thread, arrayLike, k); 281 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 282 if (mapping) { 283 key.Update(JSTaggedValue(k)); 284 const uint32_t argsLength = 2; // 2: «kValue, k» 285 EcmaRuntimeCallInfo *info = 286 EcmaInterpreter::NewRuntimeCallInfo(thread, mapfn, thisArgHandle, undefined, argsLength); 287 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 288 info->SetCallArg(kValue.GetTaggedValue(), key.GetTaggedValue()); 289 JSTaggedValue callResult = JSFunction::Call(info); 290 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 291 mapValue.Update(callResult); 292 } else { 293 mapValue.Update(kValue.GetTaggedValue()); 294 } 295 if (!mapValue->IsSharedType()) { 296 auto error = ContainerError::ParamError(thread, "Parameter error.Only accept sendable value."); 297 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 298 } 299 JSObject::CreateDataPropertyOrThrow(thread, newArrayHandle, k, mapValue, SCheckMode::SKIP); 300 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 301 k++; 302 } 303 // 17. Let setStatus be Set(A, "length", len, true). 304 JSHandle<JSTaggedValue> lenHandle(thread, JSTaggedValue(len)); 305 JSSharedArray::LengthSetter(thread, newArrayHandle, lenHandle, true); 306 newArrayHandle->GetJSHClass()->SetExtensible(false); 307 // 18. ReturnIfAbrupt(setStatus). 308 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 309 // 19. Return A. 310 return newArrayHandle.GetTaggedValue(); 311} 312 313// Array.create ( arrayLength, initialValue ) 314JSTaggedValue BuiltinsSharedArray::Create(EcmaRuntimeCallInfo *argv) 315{ 316 ASSERT(argv); 317 BUILTINS_API_TRACE(argv->GetThread(), SharedArray, From); 318 JSThread *thread = argv->GetThread(); 319 [[maybe_unused]] EcmaHandleScope handleScope(thread); 320 if (argv->GetArgsNumber() < COUNT_LENGTH_AND_INIT) { 321 auto error = ContainerError::ParamError(thread, "Parameter error.Not enough parameters."); 322 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 323 } 324 JSHandle<JSTaggedValue> thisHandle = GetThis(argv); 325 JSHandle<JSTaggedValue> arrayLengthValue = GetCallArg(argv, 0); 326 if (!arrayLengthValue->IsNumber()) { 327 auto error = ContainerError::ParamError(thread, "Parameter error.Invalid array length."); 328 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 329 } 330 auto arrayLength = JSTaggedValue::ToUint32(thread, arrayLengthValue); 331 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 332 if (JSTaggedNumber(arrayLengthValue.GetTaggedValue()).GetNumber() != arrayLength) { 333 auto error = ContainerError::ParamError(thread, "Parameter error.Invalid array length."); 334 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 335 } 336 JSHandle<JSTaggedValue> initValue = GetCallArg(argv, 1); 337 if (!initValue->IsSharedType()) { 338 auto error = ContainerError::ParamError(thread, "Parameter error.Only accept sendable value."); 339 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 340 } 341 JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined(); 342 JSTaggedValue newArray; 343 if (thisHandle->IsConstructor()) { 344 EcmaRuntimeCallInfo *info = 345 EcmaInterpreter::NewRuntimeCallInfo(thread, thisHandle, undefined, undefined, 0); 346 newArray = JSFunction::Construct(info); 347 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 348 } else { 349 newArray = JSSharedArray::ArrayCreate(thread, JSTaggedNumber(0)).GetTaggedValue(); 350 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 351 } 352 if (!newArray.IsJSSharedArray()) { 353 THROW_TYPE_ERROR_AND_RETURN(thread, "Failed to construct the array.", JSTaggedValue::Exception()); 354 } 355 JSHandle<JSObject> newArrayHandle(thread, newArray); 356 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 357 auto elements = factory->NewSOldSpaceTaggedArray(arrayLength, JSTaggedValue::Hole()); 358 for (uint32_t k = 0; k < arrayLength; k++) { 359 elements->Set(thread, k, initValue); 360 } 361 newArrayHandle->SetElements(thread, elements); 362 auto len = JSHandle<JSTaggedValue>(thread, JSTaggedValue(arrayLength)); 363 JSSharedArray::LengthSetter(thread, newArrayHandle, len, true); 364 newArrayHandle->GetJSHClass()->SetExtensible(false); 365 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 366 // Return A. 367 return newArrayHandle.GetTaggedValue(); 368} 369 370// Array.isArray ( arg ) 371JSTaggedValue BuiltinsSharedArray::IsArray(EcmaRuntimeCallInfo *argv) 372{ 373 ASSERT(argv); 374 JSThread *thread = argv->GetThread(); 375 BUILTINS_API_TRACE(thread, SharedArray, IsArray); 376 [[maybe_unused]] EcmaHandleScope handleScope(thread); 377 if (GetCallArg(argv, 0)->IsJSSharedArray()) { 378 return GetTaggedBoolean(true); 379 } 380 return GetTaggedBoolean(false); 381} 382 383// 22.1.2.5 get Array [ @@species ] 384JSTaggedValue BuiltinsSharedArray::Species(EcmaRuntimeCallInfo *argv) 385{ 386 ASSERT(argv); 387 BUILTINS_API_TRACE(argv->GetThread(), SharedArray, Species); 388 return BuiltinsArray::Species(argv); 389} 390 391// 22.1.3.1 Array.prototype.concat ( ...arguments ) 392JSTaggedValue BuiltinsSharedArray::Concat(EcmaRuntimeCallInfo *argv) 393{ 394 ASSERT(argv); 395 BUILTINS_API_TRACE(argv->GetThread(), SharedArray, Concat); 396 JSThread *thread = argv->GetThread(); 397 [[maybe_unused]] EcmaHandleScope handleScope(thread); 398 int argc = static_cast<int>(argv->GetArgsNumber()); 399 400 // 1. Let O be ToObject(this value). 401 JSHandle<JSTaggedValue> thisHandle = GetThis(argv); 402 if (!thisHandle->IsJSSharedArray()) { 403 auto error = ContainerError::BindError(thread, "The concat method cannot be bound."); 404 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 405 } 406 JSHandle<JSObject> thisObjHandle = JSTaggedValue::ToObject(thread, thisHandle); 407 [[maybe_unused]] ConcurrentApiScope<JSSharedArray> scope(thread, thisHandle); 408 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 409 JSHandle<JSTaggedValue> thisObjVal(thisObjHandle); 410 411 // 2. Let A be ArraySpeciesCreate(O, 0). 412 uint32_t arrayLen = 0; 413 JSTaggedValue newArray = JSSharedArray::ArraySpeciesCreate(thread, thisObjHandle, JSTaggedNumber(arrayLen)); 414 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 415 if (!(newArray.IsECMAObject() || newArray.IsUndefined())) { 416 THROW_TYPE_ERROR_AND_RETURN(thread, "array must be object or undefined.", JSTaggedValue::Exception()); 417 } 418 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 419 JSHandle<JSObject> newArrayHandle(thread, newArray); 420 421 // 3. Let n be 0. 422 int64_t n = 0; 423 JSMutableHandle<JSTaggedValue> ele(thread, JSTaggedValue::Undefined()); 424 JSMutableHandle<JSTaggedValue> fromKey(thread, JSTaggedValue::Undefined()); 425 JSMutableHandle<JSTaggedValue> toKey(thread, JSTaggedValue::Undefined()); 426 // 4. Prepend O to items. 427 // 5. For each element E of items, do 428 for (int i = -1; i < argc; i++) { 429 if (i < 0) { 430 ele.Update(thisObjHandle.GetTaggedValue()); 431 } else { 432 ele.Update(GetCallArg(argv, i)); 433 } 434 if (!ele->IsSharedType()) { 435 auto error = ContainerError::ParamError(thread, "Parameter error.Only accept sendable value."); 436 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 437 } 438 // a. Let spreadable be ? IsConcatSpreadable(E). 439 bool isSpreadable = ArrayHelper::IsConcatSpreadable(thread, ele); 440 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 441 // b. If spreadable is true, then 442 if (isSpreadable) { 443 // i. Let k be 0. 444 // ii. Let len be ? LengthOfArrayLike(E). 445 // iii. If n + len > 253 - 1, throw a TypeError exception. 446 int64_t len = ArrayHelper::GetArrayLength(thread, ele); 447 int64_t k = 0; 448 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 449 if (n + len > base::MAX_SAFE_INTEGER) { 450 THROW_TYPE_ERROR_AND_RETURN(thread, "out of range.", JSTaggedValue::Exception()); 451 } 452 453 if (ele->IsStableJSArray(thread)) { 454 JSStableArray::Concat(thread, newArrayHandle, JSHandle<JSObject>::Cast(ele), k, n); 455 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 456 } 457 // iv. Repeat, while k < len, 458 while (k < len) { 459 // 1. Let P be ToString(k). 460 // 2. Let exists be HasProperty(E, P). 461 // 3. If exists is true, then 462 fromKey.Update(JSTaggedValue::ToString(thread, JSTaggedValue(k))); 463 toKey.Update(JSTaggedValue(n)); 464 bool exists = JSTaggedValue::HasProperty(thread, ele, fromKey); 465 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 466 if (exists) { 467 // a. Let subElement be Get(E, P). 468 JSHandle<JSTaggedValue> fromValHandle = 469 JSSharedArray::FastGetPropertyByValue(thread, ele, fromKey); 470 if (!fromValHandle->IsSharedType()) { 471 auto error = ContainerError::ParamError(thread, "Parameter error.Only accept sendable value."); 472 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 473 } 474 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 475 // b. Perform ? CreateDataPropertyOrThrow(A, ! ToString((n)), subElement). 476 JSObject::CreateDataPropertyOrThrow(thread, newArrayHandle, toKey, fromValHandle, SCheckMode::SKIP); 477 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 478 } 479 // 4. Set n to n + 1. 480 // 5. Set k to k + 1. 481 n++; 482 k++; 483 } 484 //c. Else 485 } else { 486 // ii. If n ≥ 253 - 1, throw a TypeError exception. 487 if (n >= base::MAX_SAFE_INTEGER) { 488 THROW_TYPE_ERROR_AND_RETURN(thread, "out of range.", JSTaggedValue::Exception()); 489 } 490 // iii. Perform ? CreateDataPropertyOrThrow(A, ! ToString((n)), E). 491 // iv. Set n to n + 1. 492 JSObject::CreateDataPropertyOrThrow(thread, newArrayHandle, n, ele, SCheckMode::SKIP); 493 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 494 n++; 495 } 496 } 497 // 6. Perform ? Set(A, "length", (n), true). 498 JSHandle<JSTaggedValue> lenHandle(thread, JSTaggedValue(n)); 499 JSSharedArray::LengthSetter(thread, newArrayHandle, lenHandle, true); 500 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 501 502 // 7. Return A. 503 return newArrayHandle.GetTaggedValue(); 504} 505 506// 22.1.3.4 Array.prototype.entries ( ) 507JSTaggedValue BuiltinsSharedArray::Entries(EcmaRuntimeCallInfo *argv) 508{ 509 ASSERT(argv); 510 BUILTINS_API_TRACE(argv->GetThread(), SharedArray, Entries); 511 JSThread *thread = argv->GetThread(); 512 [[maybe_unused]] EcmaHandleScope handleScope(thread); 513 JSHandle<JSTaggedValue> thisHandle = GetThis(argv); 514 if (!thisHandle->IsJSSharedArray()) { 515 auto error = ContainerError::BindError(thread, "The entries method cannot be bound."); 516 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 517 } 518 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 519 // 1. Let O be ToObject(this value). 520 // 2. ReturnIfAbrupt(O). 521 JSHandle<JSObject> self = JSTaggedValue::ToObject(thread, GetThis(argv)); 522 [[maybe_unused]] ConcurrentApiScope<JSSharedArray> scope(thread, thisHandle); 523 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 524 // 3. Return CreateArrayIterator(O, "key+value"). 525 JSHandle<JSSharedArrayIterator> iter(factory->NewJSSharedArrayIterator(self, IterationKind::KEY_AND_VALUE)); 526 return iter.GetTaggedValue(); 527} 528JSTaggedValue BuiltinsSharedArray::CheckElementForEvery(JSThread *thread, 529 JSHandle<JSTaggedValue> &thisObjVal, 530 JSHandle<JSTaggedValue> &callbackFnHandle, 531 JSHandle<JSTaggedValue> &thisArgHandle, 532 uint32_t &k) 533{ 534 JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined()); 535 JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined(); 536 const uint32_t argsLength = 3; // 3: «kValue, k, O» 537 JSTaggedValue callResult = GetTaggedBoolean(true); 538 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 539 // Let len be ToLength(Get(O, "length")). 540 uint64_t len = static_cast<uint64_t>(ArrayHelper::GetArrayLength(thread, thisObjVal)); 541 // ReturnIfAbrupt(len). 542 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 543 while (k < len) { 544 bool exists = JSTaggedValue::HasProperty(thread, thisObjVal, k); 545 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 546 if (exists) { 547 JSHandle<JSTaggedValue> kValue = JSSharedArray::FastGetPropertyByValue(thread, thisObjVal, k); 548 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 549 key.Update(JSTaggedValue(k)); 550 EcmaRuntimeCallInfo *info = 551 EcmaInterpreter::NewRuntimeCallInfo(thread, callbackFnHandle, thisArgHandle, undefined, argsLength); 552 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 553 info->SetCallArg(kValue.GetTaggedValue(), key.GetTaggedValue(), thisObjVal.GetTaggedValue()); 554 callResult = JSFunction::Call(info); 555 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 556 if (!callResult.ToBoolean()) { 557 return GetTaggedBoolean(false); 558 } 559 } 560 k++; 561 thread->CheckSafepointIfSuspended(); 562 } 563 return GetTaggedBoolean(true); 564} 565 566// Array.prototype.every ( callbackfn [ , thisArg] ) 567JSTaggedValue BuiltinsSharedArray::Every(EcmaRuntimeCallInfo *argv) 568{ 569 ASSERT(argv); 570 BUILTINS_API_TRACE(argv->GetThread(), SharedArray, Every); 571 JSThread *thread = argv->GetThread(); 572 [[maybe_unused]] EcmaHandleScope handleScope(thread); 573 574 // 1. Let O be ToObject(this value). 575 JSHandle<JSTaggedValue> thisHandle = GetThis(argv); 576 if (!thisHandle->IsJSSharedArray()) { 577 auto error = ContainerError::BindError(thread, "The every method cannot be bound."); 578 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 579 } 580 JSHandle<JSObject> thisObjHandle = JSTaggedValue::ToObject(thread, thisHandle); 581 // 2. ReturnIfAbrupt(O). 582 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 583 JSHandle<JSTaggedValue> thisObjVal(thisObjHandle); 584 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 585 586 // 3. If IsCallable(callbackfn) is false, throw a TypeError exception. 587 JSHandle<JSTaggedValue> callbackFnHandle = GetCallArg(argv, 0); 588 if (!callbackFnHandle->IsCallable()) { 589 THROW_TYPE_ERROR_AND_RETURN(thread, "the callbackfun is not callable.", JSTaggedValue::Exception()); 590 } 591 592 // 4. If thisArg was supplied, let T be thisArg; else let T be undefined. 593 JSHandle<JSTaggedValue> thisArgHandle = GetCallArg(argv, 1); 594 595 // 5. Let k be 0. 596 // 6. Repeat, while k < len 597 // a. Let Pk be ToString(k). 598 // b. Let kPresent be HasProperty(O, Pk). 599 // c. ReturnIfAbrupt(kPresent). 600 // d. If kPresent is true, then 601 // i. Let kValue be Get(O, Pk). 602 // ii. ReturnIfAbrupt(kValue). 603 // iii. Let testResult be ToBoolean(Call(callbackfn, T, «kValue, k, O»)). 604 // iv. ReturnIfAbrupt(testResult). 605 // v. If testResult is false, return false. 606 // e. Increase k by 1. 607 uint32_t k = 0; 608 JSTaggedValue callResult = GetTaggedBoolean(true); 609 if (thisObjVal->IsStableJSArray(thread)) { 610 callResult = JSStableArray::HandleEveryOfStable(thread, thisObjHandle, callbackFnHandle, thisArgHandle, k); 611 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 612 if (!callResult.ToBoolean()) { 613 return GetTaggedBoolean(false); 614 } 615 } 616 return CheckElementForEvery(thread, thisObjVal, callbackFnHandle, thisArgHandle, k); 617} 618 619// Array.prototype.some ( callbackfn [ , thisArg ] ) 620JSTaggedValue BuiltinsSharedArray::Some(EcmaRuntimeCallInfo *argv) 621{ 622 ASSERT(argv); 623 BUILTINS_API_TRACE(argv->GetThread(), SharedArray, Some); 624 JSThread *thread = argv->GetThread(); 625 [[maybe_unused]] EcmaHandleScope handleScope(thread); 626 627 // 1. Let O be ToObject(this value). 628 JSHandle<JSTaggedValue> thisHandle = GetThis(argv); 629 if (!thisHandle->IsJSSharedArray()) { 630 auto error = ContainerError::BindError(thread, "The some method cannot be bound."); 631 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 632 } 633 JSHandle<JSObject> thisObjHandle = JSTaggedValue::ToObject(thread, thisHandle); 634 // 2. ReturnIfAbrupt(O). 635 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 636 JSHandle<JSTaggedValue> thisObjVal(thisObjHandle); 637 638 // 3. Let len be ToLength(Get(O, "length")). 639 int64_t len = ArrayHelper::GetArrayLength(thread, thisObjVal); 640 // 4. ReturnIfAbrupt(len). 641 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 642 643 // 5. If IsCallable(callbackfn) is false, throw a TypeError exception. 644 JSHandle<JSTaggedValue> callbackFnHandle = GetCallArg(argv, 0); 645 if (!callbackFnHandle->IsCallable()) { 646 THROW_TYPE_ERROR_AND_RETURN(thread, "the callbackfun is not callable.", JSTaggedValue::Exception()); 647 } 648 649 // 6. If thisArg was supplied, let T be thisArg; else let T be undefined. 650 JSHandle<JSTaggedValue> thisArgHandle = GetCallArg(argv, 1); 651 652 // 7. Let k be 0. 653 // 8. Repeat, while k < len 654 // a. Let Pk be ToString(k). 655 // b. Let kPresent be HasProperty(O, Pk). 656 // c. ReturnIfAbrupt(kPresent). 657 // d. If kPresent is true, then 658 // i. Let kValue be Get(O, Pk). 659 // ii. ReturnIfAbrupt(kValue). 660 // iii. Let testResult be ToBoolean(Call(callbackfn, T, «kValue, k, and O»)). 661 // iv. ReturnIfAbrupt(testResult). 662 // v. If testResult is true, return true. 663 // e. Increase k by 1. 664 JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined()); 665 JSMutableHandle<JSTaggedValue> kValue(thread, JSTaggedValue::Undefined()); 666 uint32_t k = 0; 667 JSTaggedValue callResult = GetTaggedBoolean(false); 668 if (thisObjVal->IsStableJSArray(thread)) { 669 callResult = JSStableArray::HandleSomeOfStable(thread, thisObjHandle, callbackFnHandle, thisArgHandle, k); 670 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 671 if (callResult.ToBoolean()) { 672 return GetTaggedBoolean(true); 673 } 674 } 675 while (k < len) { 676 bool exists = (thisHandle->IsTypedArray() || thisHandle->IsSharedTypedArray() || 677 JSTaggedValue::HasProperty(thread, thisObjVal, k)); 678 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 679 if (exists) { 680 key.Update(JSTaggedValue(k)); 681 kValue.Update(JSArray::FastGetPropertyByValue(thread, thisObjVal, key)); 682 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 683 const uint32_t argsLength = 3; // 3: «kValue, k, O» 684 JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined(); 685 EcmaRuntimeCallInfo *info = 686 EcmaInterpreter::NewRuntimeCallInfo(thread, callbackFnHandle, thisArgHandle, undefined, argsLength); 687 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 688 info->SetCallArg(kValue.GetTaggedValue(), key.GetTaggedValue(), thisObjVal.GetTaggedValue()); 689 callResult = JSFunction::Call(info); 690 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 691 if (callResult.ToBoolean()) { 692 return GetTaggedBoolean(true); 693 } 694 } 695 k++; 696 thread->CheckSafepointIfSuspended(); 697 } 698 699 // 9. Return false. 700 return GetTaggedBoolean(false); 701} 702 703// 22.1.3.6 Array.prototype.fill (value [ , start [ , end ] ] ) 704JSTaggedValue BuiltinsSharedArray::Fill(EcmaRuntimeCallInfo *argv) 705{ 706 ASSERT(argv); 707 BUILTINS_API_TRACE(argv->GetThread(), SharedArray, Fill); 708 JSThread *thread = argv->GetThread(); 709 [[maybe_unused]] EcmaHandleScope handleScope(thread); 710 711 // 1. Let O be ToObject(this value). 712 JSHandle<JSTaggedValue> thisObjVal = GetThis(argv); 713 if (!thisObjVal->IsJSSharedArray()) { 714 auto error = ContainerError::BindError(thread, "The fill method cannot be bound."); 715 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 716 } 717 JSHandle<JSObject> thisObjHandle = JSTaggedValue::ToObject(thread, thisObjVal); 718 [[maybe_unused]] ConcurrentApiScope<JSSharedArray, ModType::WRITE> scope(thread, thisObjVal); 719 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 720 if (thisObjVal->IsJSSharedArray()) { 721 bool isDictionary = thisObjHandle->GetJSHClass()->IsDictionaryElement(); 722 if (isDictionary) { 723 uint32_t length = JSSharedArray::Cast(*thisObjHandle)->GetLength(); 724 uint32_t size = thisObjHandle->GetNumberOfElements(); 725 if (length - size > JSObject::MAX_GAP) { 726 JSObject::TryOptimizeAsFastElements(thread, thisObjHandle); 727 } 728 } 729 } 730 731 // 2. ReturnIfAbrupt(O). 732 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 733 734 JSHandle<JSTaggedValue> value = GetCallArg(argv, 0); 735 if (!value->IsSharedType()) { 736 auto error = ContainerError::ParamError(thread, "Parameter error.Only accept sendable value."); 737 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 738 } 739 if (thisObjVal->IsTypedArray() || thisObjVal->IsSharedTypedArray()) { 740 ContentType contentType = JSHandle<JSTypedArray>::Cast(thisObjVal)->GetContentType(); 741 if (contentType == ContentType::BigInt) { 742 value = JSHandle<JSTaggedValue>(thread, JSTaggedValue::ToBigInt(thread, value)); 743 } else { 744 value = JSHandle<JSTaggedValue>(thread, JSTaggedValue::ToNumber(thread, value)); 745 } 746 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 747 } 748 749 // 3. Let len be ToLength(Get(O, "length")). 750 int64_t len = ArrayHelper::GetLength(thread, thisObjVal); 751 // 4. ReturnIfAbrupt(len). 752 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 753 754 // 5. Let relativeStart be ToInteger(start). 755 JSHandle<JSTaggedValue> startArg = GetCallArg(argv, 1); 756 JSTaggedNumber argStartTemp = JSTaggedValue::ToInteger(thread, startArg); 757 // 6. ReturnIfAbrupt(relativeStart). 758 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 759 double argStart = argStartTemp.GetNumber(); 760 // 7. If relativeStart < 0, let k be max((len + relativeStart),0); else let k be min(relativeStart, len). 761 int64_t start = 0; 762 if (argStart < 0) { 763 double tempStart = argStart + len; 764 start = tempStart > 0 ? tempStart : 0; 765 } else { 766 start = argStart < len ? argStart : len; 767 } 768 769 // 8. If end is undefined, let relativeEnd be len; else let relativeEnd be ToInteger(end). 770 double argEnd = len; 771 JSHandle<JSTaggedValue> endArg = GetCallArg(argv, INDEX_TWO); 772 if (!endArg->IsUndefined()) { 773 JSTaggedNumber argEndTemp = JSTaggedValue::ToInteger(thread, endArg); 774 // 9. ReturnIfAbrupt(relativeEnd). 775 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 776 argEnd = argEndTemp.GetNumber(); 777 } 778 779 // 10. If relativeEnd < 0, let final be max((len + relativeEnd),0); else let final be min(relativeEnd, len). 780 int64_t end = len; 781 if (argEnd < 0) { 782 double tempEnd = argEnd + len; 783 end = tempEnd > 0 ? tempEnd : 0; 784 } else { 785 end = argEnd < len ? argEnd : len; 786 } 787 // 11. Repeat, while k < final 788 // a. Let Pk be ToString(k). 789 // b. Let setStatus be Set(O, Pk, value, true). 790 // c. ReturnIfAbrupt(setStatus). 791 // d. Increase k by 1. 792 793 if (thisObjVal->IsStableJSArray(thread) && !startArg->IsJSObject() && !endArg->IsJSObject()) { 794 auto opResult = JSStableArray::Fill(thread, thisObjHandle, value, start, end, len); 795 return opResult; 796 } 797 798 if (thisObjVal->IsTypedArray() || thisObjVal->IsSharedTypedArray()) { 799 bool result = JSTypedArray::FastTypedArrayFill(thread, thisObjVal, value, start, end); 800 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 801 if (result) { 802 return thisObjHandle.GetTaggedValue(); 803 } 804 } 805 806 int64_t k = start; 807 JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined()); 808 while (k < end) { 809 key.Update(JSTaggedValue(k)); 810 JSSharedArray::FastSetPropertyByValue(thread, thisObjVal, key, value); 811 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 812 k++; 813 } 814 815 // 12. Return O. 816 return thisObjHandle.GetTaggedValue(); 817} 818 819JSTaggedValue BuiltinsSharedArray::FilterUnStableJSArray(JSThread *thread, JSHandle<JSTaggedValue> &thisArgHandle, 820 JSHandle<JSTaggedValue> &thisObjVal, int64_t k, int64_t len, uint32_t toIndex, JSHandle<JSObject> newArrayHandle, 821 JSHandle<JSTaggedValue> &callbackFnHandle) 822{ 823 JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined(); 824 const uint32_t argsLength = 3; // 3: «kValue, k, O» 825 JSTaggedValue callResult = GetTaggedBoolean(true); 826 JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined()); 827 JSMutableHandle<JSTaggedValue> toIndexHandle(thread, JSTaggedValue::Undefined()); 828 while (k < len) { 829 bool exists = JSTaggedValue::HasProperty(thread, thisObjVal, k); 830 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 831 if (exists) { 832 JSHandle<JSTaggedValue> kValue = JSSharedArray::FastGetPropertyByValue(thread, thisObjVal, k); 833 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 834 key.Update(JSTaggedValue(k)); 835 EcmaRuntimeCallInfo *info = 836 EcmaInterpreter::NewRuntimeCallInfo(thread, callbackFnHandle, thisArgHandle, undefined, argsLength); 837 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 838 info->SetCallArg(kValue.GetTaggedValue(), key.GetTaggedValue(), thisObjVal.GetTaggedValue()); 839 callResult = JSFunction::Call(info); 840 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 841 if (callResult.ToBoolean()) { 842 toIndexHandle.Update(JSTaggedValue(toIndex)); 843 JSObject::CreateDataPropertyOrThrow(thread, newArrayHandle, toIndexHandle, kValue, SCheckMode::SKIP); 844 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 845 toIndex++; 846 } 847 } 848 k++; 849 } 850 return newArrayHandle.GetTaggedValue(); 851} 852 853// 22.1.3.7 Array.prototype.filter ( callbackfn [ , thisArg ] ) 854JSTaggedValue BuiltinsSharedArray::Filter(EcmaRuntimeCallInfo *argv) 855{ 856 ASSERT(argv); 857 JSThread *thread = argv->GetThread(); 858 BUILTINS_API_TRACE(thread, SharedArray, Filter); 859 [[maybe_unused]] EcmaHandleScope handleScope(thread); 860 861 // 1. Let O be ToObject(this value). 862 JSHandle<JSTaggedValue> thisHandle = GetThis(argv); 863 if (!thisHandle->IsJSSharedArray()) { 864 auto error = ContainerError::BindError(thread, "The filter method cannot be bound."); 865 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 866 } 867 JSHandle<JSObject> thisObjHandle = JSTaggedValue::ToObject(thread, thisHandle); 868 [[maybe_unused]] ConcurrentApiScope<JSSharedArray> scope(thread, thisHandle); 869 // 2. ReturnIfAbrupt(O). 870 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 871 JSHandle<JSTaggedValue> thisObjVal(thisObjHandle); 872 873 // 3. Let len be ToLength(Get(O, "length")). 874 uint64_t len = static_cast<uint64_t>(ArrayHelper::GetArrayLength(thread, thisObjVal)); 875 // 4. ReturnIfAbrupt(len). 876 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 877 878 // 5. If IsCallable(callbackfn) is false, throw a TypeError exception. 879 JSHandle<JSTaggedValue> callbackFnHandle = GetCallArg(argv, 0); 880 if (!callbackFnHandle->IsCallable()) { 881 THROW_TYPE_ERROR_AND_RETURN(thread, "the callbackfun is not callable.", JSTaggedValue::Exception()); 882 } 883 884 // 6. If thisArg was supplied, let T be thisArg; else let T be undefined. 885 JSHandle<JSTaggedValue> thisArgHandle = GetCallArg(argv, 1); 886 887 // 7. Let A be ArraySpeciesCreate(O, 0). 888 int32_t arrayLen = 0; 889 JSTaggedValue newArray = JSSharedArray::ArraySpeciesCreate(thread, thisObjHandle, JSTaggedNumber(arrayLen)); 890 // 8. ReturnIfAbrupt(A). 891 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 892 JSHandle<JSObject> newArrayHandle(thread, newArray); 893 894 // 9. Let k be 0. 895 // 10. Let to be 0. 896 // 11. Repeat, while k < len 897 // a. Let Pk be ToString(k). 898 // b. Let kPresent be HasProperty(O, Pk). 899 // c. ReturnIfAbrupt(kPresent). 900 // d. If kPresent is true, then 901 // i. Let kValue be Get(O, Pk). 902 // ii. ReturnIfAbrupt(kValue). 903 // iii. Let selected be ToBoolean(Call(callbackfn, T, «kValue, k, O»)). 904 // iv. ReturnIfAbrupt(selected). 905 // v. If selected is true, then 906 // 1. Let status be CreateDataPropertyOrThrow (A, ToString(to), kValue). 907 // 2. ReturnIfAbrupt(status). 908 // 3. Increase to by 1. 909 // e. Increase k by 1. 910 uint32_t toIndex = 0; 911 JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined()); 912 JSMutableHandle<JSTaggedValue> toIndexHandle(thread, JSTaggedValue::Undefined()); 913 uint32_t k = 0; 914 if (thisObjVal->IsStableJSArray(thread)) { 915 JSStableArray::Filter(newArrayHandle, thisObjHandle, argv, k, toIndex); 916 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 917 } 918 auto opResult = 919 FilterUnStableJSArray(thread, thisArgHandle, thisObjVal, k, len, toIndex, newArrayHandle, callbackFnHandle); 920 921 return opResult; 922} 923 924// 22.1.3.8 Array.prototype.find ( predicate [ , thisArg ] ) 925JSTaggedValue BuiltinsSharedArray::Find(EcmaRuntimeCallInfo *argv) 926{ 927 ASSERT(argv); 928 BUILTINS_API_TRACE(argv->GetThread(), SharedArray, Find); 929 JSThread *thread = argv->GetThread(); 930 [[maybe_unused]] EcmaHandleScope handleScope(thread); 931 932 // 1. Let O be ToObject(this value). 933 JSHandle<JSTaggedValue> thisHandle = GetThis(argv); 934 if (!thisHandle->IsJSSharedArray()) { 935 auto error = ContainerError::BindError(thread, "The find method cannot be bound."); 936 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 937 } 938 JSHandle<JSObject> thisObjHandle = JSTaggedValue::ToObject(thread, thisHandle); 939 [[maybe_unused]] ConcurrentApiScope<JSSharedArray> scope(thread, thisHandle); 940 // 2. ReturnIfAbrupt(O). 941 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 942 JSHandle<JSTaggedValue> thisObjVal(thisObjHandle); 943 944 // 3. Let len be ToLength(Get(O, "length")). 945 int64_t len = ArrayHelper::GetLength(thread, thisObjVal); 946 // 4. ReturnIfAbrupt(len). 947 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 948 949 // 5. If IsCallable(predicate) is false, throw a TypeError exception. 950 JSHandle<JSTaggedValue> callbackFnHandle = GetCallArg(argv, 0); 951 if (!callbackFnHandle->IsCallable()) { 952 THROW_TYPE_ERROR_AND_RETURN(thread, "the predicate is not callable.", JSTaggedValue::Exception()); 953 } 954 955 // 6. If thisArg was supplied, let T be thisArg; else let T be undefined. 956 JSHandle<JSTaggedValue> thisArgHandle = GetCallArg(argv, 1); 957 958 // 7. Let k be 0. 959 // 8. Repeat, while k < len 960 // a. Let Pk be ToString(k). 961 // b. Let kValue be Get(O, Pk). 962 // c. ReturnIfAbrupt(kValue). 963 // d. Let testResult be ToBoolean(Call(predicate, T, «kValue, k, O»)). 964 // e. ReturnIfAbrupt(testResult). 965 // f. If testResult is true, return kValue. 966 // g. Increase k by 1. 967 JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined()); 968 int64_t k = 0; 969 while (k < len) { 970 JSHandle<JSTaggedValue> kValue = JSSharedArray::FastGetPropertyByValue(thread, thisObjVal, k); 971 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 972 key.Update(JSTaggedValue(k)); 973 const uint32_t argsLength = 3; // 3: «kValue, k, O» 974 JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined(); 975 EcmaRuntimeCallInfo *info = 976 EcmaInterpreter::NewRuntimeCallInfo(thread, callbackFnHandle, thisArgHandle, undefined, argsLength); 977 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 978 info->SetCallArg(kValue.GetTaggedValue(), key.GetTaggedValue(), thisObjVal.GetTaggedValue()); 979 JSTaggedValue callResult = JSFunction::Call(info); 980 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 981 if (callResult.ToBoolean()) { 982 return kValue.GetTaggedValue(); 983 } 984 k++; 985 } 986 987 // 9. Return undefined. 988 return JSTaggedValue::Undefined(); 989} 990 991// 22.1.3.9 Array.prototype.findIndex ( predicate [ , thisArg ] ) 992JSTaggedValue BuiltinsSharedArray::FindIndex(EcmaRuntimeCallInfo *argv) 993{ 994 ASSERT(argv); 995 BUILTINS_API_TRACE(argv->GetThread(), SharedArray, FindIndex); 996 JSThread *thread = argv->GetThread(); 997 [[maybe_unused]] EcmaHandleScope handleScope(thread); 998 999 // 1. Let O be ToObject(this value). 1000 JSHandle<JSTaggedValue> thisHandle = GetThis(argv); 1001 if (!thisHandle->IsJSSharedArray()) { 1002 auto error = ContainerError::BindError(thread, "The findIndex method cannot be bound."); 1003 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 1004 } 1005 JSHandle<JSObject> thisObjHandle = JSTaggedValue::ToObject(thread, thisHandle); 1006 [[maybe_unused]] ConcurrentApiScope<JSSharedArray> scope(thread, thisHandle); 1007 // 2. ReturnIfAbrupt(O). 1008 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1009 JSHandle<JSTaggedValue> thisObjVal(thisObjHandle); 1010 1011 // 3. Let len be ToLength(Get(O, "length")). 1012 uint64_t len = static_cast<uint64_t>(ArrayHelper::GetLength(thread, thisObjVal)); 1013 // 4. ReturnIfAbrupt(len). 1014 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1015 1016 // 5. If IsCallable(predicate) is false, throw a TypeError exception. 1017 JSHandle<JSTaggedValue> callbackFnHandle = GetCallArg(argv, 0); 1018 if (!callbackFnHandle->IsCallable()) { 1019 THROW_TYPE_ERROR_AND_RETURN(thread, "the predicate is not callable.", JSTaggedValue::Exception()); 1020 } 1021 1022 // 6. If thisArg was supplied, let T be thisArg; else let T be undefined. 1023 JSHandle<JSTaggedValue> thisArgHandle = GetCallArg(argv, 1); 1024 1025 // 7. Let k be 0. 1026 // 8. Repeat, while k < len 1027 // a. Let Pk be ToString(k). 1028 // b. Let kValue be Get(O, Pk). 1029 // c. ReturnIfAbrupt(kValue). 1030 // d. Let testResult be ToBoolean(Call(predicate, T, «kValue, k, O»)). 1031 // e. ReturnIfAbrupt(testResult). 1032 // f. If testResult is true, return k. 1033 // g. Increase k by 1. 1034 uint32_t k = 0; 1035 JSTaggedValue callResult = GetTaggedBoolean(true); 1036 if (thisObjVal->IsStableJSArray(thread)) { 1037 callResult = JSStableArray::HandleFindIndexOfStable(thread, thisObjHandle, callbackFnHandle, thisArgHandle, k); 1038 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1039 if (callResult.ToBoolean()) { 1040 return GetTaggedDouble(k); 1041 } 1042 } 1043 JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined()); 1044 JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined(); 1045 const uint32_t argsLength = 3; // 3: «kValue, k, O» 1046 while (k < len) { 1047 JSHandle<JSTaggedValue> kValue = JSSharedArray::FastGetPropertyByValue(thread, thisObjVal, k); 1048 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1049 key.Update(JSTaggedValue(k)); 1050 EcmaRuntimeCallInfo *info = 1051 EcmaInterpreter::NewRuntimeCallInfo(thread, callbackFnHandle, thisArgHandle, undefined, argsLength); 1052 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1053 info->SetCallArg(kValue.GetTaggedValue(), key.GetTaggedValue(), thisObjVal.GetTaggedValue()); 1054 callResult = JSFunction::Call(info); 1055 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1056 if (callResult.ToBoolean()) { 1057 return GetTaggedDouble(k); 1058 } 1059 k++; 1060 } 1061 1062 // 9. Return -1. 1063 return GetTaggedDouble(-1); 1064} 1065 1066// 22.1.3.10 Array.prototype.forEach ( callbackfn [ , thisArg ] ) 1067JSTaggedValue BuiltinsSharedArray::ForEach(EcmaRuntimeCallInfo *argv) 1068{ 1069 ASSERT(argv); 1070 JSThread *thread = argv->GetThread(); 1071 BUILTINS_API_TRACE(thread, SharedArray, ForEach); 1072 [[maybe_unused]] EcmaHandleScope handleScope(thread); 1073 1074 // 1. Let O be ToObject(this value). 1075 JSHandle<JSTaggedValue> thisHandle = GetThis(argv); 1076 if (!thisHandle->IsJSSharedArray()) { 1077 auto error = ContainerError::BindError(thread, "The forEach method cannot be bound."); 1078 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 1079 } 1080 JSHandle<JSObject> thisObjHandle = JSTaggedValue::ToObject(thread, thisHandle); 1081 [[maybe_unused]] ConcurrentApiScope<JSSharedArray> scope(thread, thisHandle); 1082 // 2. ReturnIfAbrupt(O). 1083 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1084 JSHandle<JSTaggedValue> thisObjVal(thisObjHandle); 1085 1086 // 3. Let len be ToLength(Get(O, "length")). 1087 uint64_t len = static_cast<uint64_t>(ArrayHelper::GetArrayLength(thread, thisObjVal)); 1088 // 4. ReturnIfAbrupt(len). 1089 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1090 1091 // 5. If IsCallable(callbackfn) is false, throw a TypeError exception. 1092 JSHandle<JSTaggedValue> callbackFnHandle = GetCallArg(argv, 0); 1093 if (!callbackFnHandle->IsCallable()) { 1094 THROW_TYPE_ERROR_AND_RETURN(thread, "the callbackfun is not callable.", JSTaggedValue::Exception()); 1095 } 1096 1097 // 6. If thisArg was supplied, let T be thisArg; else let T be undefined. 1098 JSHandle<JSTaggedValue> thisArgHandle = GetCallArg(argv, 1); 1099 1100 // 7. Let k be 0. 1101 // 8. Repeat, while k < len 1102 // a. Let Pk be ToString(k). 1103 // b. Let kPresent be HasProperty(O, Pk). 1104 // c. ReturnIfAbrupt(kPresent). 1105 // d. If kPresent is true, then 1106 // i. Let kValue be Get(O, Pk). 1107 // ii. ReturnIfAbrupt(kValue). 1108 // iii. Let funcResult be Call(callbackfn, T, «kValue, k, O»). 1109 // iv. ReturnIfAbrupt(funcResult). 1110 // e. Increase k by 1. 1111 JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined()); 1112 uint32_t k = 0; 1113 if (thisObjVal->IsStableJSArray(thread)) { 1114 JSStableArray::HandleforEachOfStable(thread, thisObjHandle, callbackFnHandle, thisArgHandle, len, k); 1115 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1116 } 1117 const uint32_t argsLength = 3; // 3: «kValue, k, O» 1118 JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined(); 1119 while (k < len) { 1120 bool exists = JSTaggedValue::HasProperty(thread, thisObjVal, k); 1121 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1122 if (exists) { 1123 JSHandle<JSTaggedValue> kValue = JSSharedArray::FastGetPropertyByValue(thread, thisObjVal, k); 1124 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1125 key.Update(JSTaggedValue(k)); 1126 EcmaRuntimeCallInfo *info = 1127 EcmaInterpreter::NewRuntimeCallInfo(thread, callbackFnHandle, thisArgHandle, undefined, argsLength); 1128 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1129 info->SetCallArg(kValue.GetTaggedValue(), key.GetTaggedValue(), thisObjVal.GetTaggedValue()); 1130 JSTaggedValue funcResult = JSFunction::Call(info); 1131 RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, funcResult); 1132 } 1133 k++; 1134 } 1135 1136 // 9. Return undefined. 1137 return JSTaggedValue::Undefined(); 1138} 1139 1140JSTaggedValue BuiltinsSharedArray::IndexOfSlowPath( 1141 EcmaRuntimeCallInfo *argv, JSThread *thread, const JSHandle<JSTaggedValue> &thisHandle) 1142{ 1143 // 1. Let O be ToObject(this value). 1144 JSHandle<JSObject> thisObjHandle = JSTaggedValue::ToObject(thread, thisHandle); 1145 // 2. ReturnIfAbrupt(O). 1146 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1147 JSHandle<JSTaggedValue> thisObjVal(thisObjHandle); 1148 // 3. Let len be ToLength(Get(O, "length")). 1149 int64_t length = ArrayHelper::GetLength(thread, thisObjVal); 1150 // 4. ReturnIfAbrupt(len). 1151 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1152 // 5. If len is 0, return −1. 1153 if (length == 0) { 1154 return JSTaggedValue(-1); 1155 } 1156 // 6. If argument fromIndex was passed let n be ToInteger(fromIndex); else let n be 0. 1157 int64_t fromIndex = ArrayHelper::GetStartIndexFromArgs(thread, argv, 1, length); 1158 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1159 return IndexOfSlowPath(argv, thread, thisObjVal, length, fromIndex); 1160} 1161 1162JSTaggedValue BuiltinsSharedArray::IndexOfSlowPath( 1163 EcmaRuntimeCallInfo *argv, JSThread *thread, const JSHandle<JSTaggedValue> &thisObjVal, 1164 int64_t length, int64_t fromIndex) 1165{ 1166 if (fromIndex >= length) { 1167 return JSTaggedValue(-1); 1168 } 1169 JSMutableHandle<JSTaggedValue> keyHandle(thread, JSTaggedValue::Undefined()); 1170 JSHandle<JSTaggedValue> target = GetCallArg(argv, 0); 1171 // 11. Repeat, while k < len 1172 for (int64_t curIndex = fromIndex; curIndex < length; ++curIndex) { 1173 keyHandle.Update(JSTaggedValue(curIndex)); 1174 bool found = ArrayHelper::ElementIsStrictEqualTo(thread, thisObjVal, keyHandle, target); 1175 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1176 if (UNLIKELY(found)) { 1177 return JSTaggedValue(curIndex); 1178 } 1179 } 1180 // 12. Return -1. 1181 return JSTaggedValue(-1); 1182} 1183 1184// 22.1.3.11 Array.prototype.indexOf ( searchElement [ , fromIndex ] ) 1185JSTaggedValue BuiltinsSharedArray::IndexOf(EcmaRuntimeCallInfo *argv) 1186{ 1187 ASSERT(argv); 1188 JSThread *thread = argv->GetThread(); 1189 BUILTINS_API_TRACE(thread, SharedArray, IndexOf); 1190 [[maybe_unused]] EcmaHandleScope handleScope(thread); 1191 1192 JSHandle<JSTaggedValue> thisHandle = GetThis(argv); 1193 if (!thisHandle->IsJSSharedArray()) { 1194 auto error = ContainerError::BindError(thread, "The indexOf method cannot be bound."); 1195 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 1196 } 1197 [[maybe_unused]] ConcurrentApiScope<JSSharedArray> scope(thread, thisHandle); 1198 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1199 1200 JSTaggedValue opResult; 1201 if (thisHandle->IsStableJSArray(thread)) { 1202 auto error = ContainerError::BindError(thread, "The indexOf method not support stable array."); 1203 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 1204 } else { 1205 opResult = IndexOfSlowPath(argv, thread, thisHandle); 1206 } 1207 1208 return opResult; 1209} 1210 1211// 22.1.3.12 Array.prototype.join (separator) 1212JSTaggedValue BuiltinsSharedArray::Join(EcmaRuntimeCallInfo *argv) 1213{ 1214 ASSERT(argv); 1215 JSThread *thread = argv->GetThread(); 1216 BUILTINS_API_TRACE(argv->GetThread(), SharedArray, Join); 1217 JSHandle<JSTaggedValue> thisHandle = GetThis(argv); 1218 if (!thisHandle->IsJSSharedArray()) { 1219 auto error = ContainerError::BindError(thread, "The join method cannot be bound."); 1220 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 1221 } 1222 [[maybe_unused]] ConcurrentApiScope<JSSharedArray> scope(thread, thisHandle); 1223 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1224 auto opResult = BuiltinsArray::Join(argv); 1225 return opResult; 1226} 1227 1228// 22.1.3.13 Array.prototype.keys ( ) 1229JSTaggedValue BuiltinsSharedArray::Keys(EcmaRuntimeCallInfo *argv) 1230{ 1231 ASSERT(argv); 1232 JSThread *thread = argv->GetThread(); 1233 BUILTINS_API_TRACE(argv->GetThread(), SharedArray, Keys); 1234 JSHandle<JSTaggedValue> thisHandle = GetThis(argv); 1235 if (!thisHandle->IsJSSharedArray()) { 1236 auto error = ContainerError::BindError(thread, "The keys method cannot be bound."); 1237 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 1238 } 1239 [[maybe_unused]] ConcurrentApiScope<JSSharedArray> scope(thread, thisHandle); 1240 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1241 auto opResult = BuiltinsArray::Keys(argv); 1242 return opResult; 1243} 1244 1245// 22.1.3.15 Array.prototype.map ( callbackfn [ , thisArg ] ) 1246JSTaggedValue BuiltinsSharedArray::Map(EcmaRuntimeCallInfo *argv) 1247{ 1248 ASSERT(argv); 1249 BUILTINS_API_TRACE(argv->GetThread(), SharedArray, Map); 1250 JSThread *thread = argv->GetThread(); 1251 [[maybe_unused]] EcmaHandleScope handleScope(thread); 1252 1253 // 1. Let O be ToObject(this value). 1254 JSHandle<JSTaggedValue> thisHandle = GetThis(argv); 1255 if (!thisHandle->IsJSSharedArray()) { 1256 auto error = ContainerError::BindError(thread, "The map method cannot be bound."); 1257 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 1258 } 1259 JSHandle<JSObject> thisObjHandle = JSTaggedValue::ToObject(thread, thisHandle); 1260 [[maybe_unused]] ConcurrentApiScope<JSSharedArray> scope(thread, thisHandle); 1261 // 2. ReturnIfAbrupt(O). 1262 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1263 JSHandle<JSTaggedValue> thisObjVal(thisObjHandle); 1264 1265 // 3. Let len be ToLength(Get(O, "length")). 1266 int64_t rawLen = ArrayHelper::GetArrayLength(thread, thisObjVal); 1267 // 4. ReturnIfAbrupt(len). 1268 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1269 1270 // 5. If IsCallable(callbackfn) is false, throw a TypeError exception. 1271 JSHandle<JSTaggedValue> callbackFnHandle = GetCallArg(argv, 0); 1272 if (!callbackFnHandle->IsCallable()) { 1273 THROW_TYPE_ERROR_AND_RETURN(thread, "the callbackfun is not callable.", JSTaggedValue::Exception()); 1274 } 1275 1276 // 6. If thisArg was supplied, let T be thisArg; else let T be undefined. 1277 JSHandle<JSTaggedValue> thisArgHandle = GetCallArg(argv, 1); 1278 1279 // 7. Let A be ArraySpeciesCreate(O, len). 1280 JSTaggedValue newArray = 1281 JSSharedArray::ArraySpeciesCreate(thread, thisObjHandle, JSTaggedNumber(static_cast<double>(rawLen))); 1282 // 8. ReturnIfAbrupt(A). 1283 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1284 if (!newArray.IsECMAObject()) { 1285 THROW_TYPE_ERROR_AND_RETURN(thread, "Failed to create Object.", JSTaggedValue::Exception()); 1286 } 1287 JSHandle<JSObject> newArrayHandle(thread, newArray); 1288 1289 // 9. Let k be 0. 1290 // 10. Repeat, while k < len 1291 // a. Let Pk be ToString(k). 1292 // b. Let kPresent be HasProperty(O, Pk). 1293 // c. ReturnIfAbrupt(kPresent). 1294 // d. If kPresent is true, then 1295 // i. Let kValue be Get(O, Pk). 1296 // ii. ReturnIfAbrupt(kValue). 1297 // iii. Let mappedValue be Call(callbackfn, T, «kValue, k, O»). 1298 // iv. ReturnIfAbrupt(mappedValue). 1299 // v. Let status be CreateDataPropertyOrThrow (A, Pk, mappedValue). 1300 // vi. ReturnIfAbrupt(status). 1301 // e. Increase k by 1. 1302 uint32_t k = 0; 1303 uint32_t len = static_cast<uint32_t>(rawLen); 1304 if (thisObjVal->IsStableJSArray(thread)) { 1305 JSStableArray::Map(newArrayHandle, thisObjHandle, argv, k, len); 1306 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1307 } 1308 JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined()); 1309 JSMutableHandle<JSTaggedValue> mapResultHandle(thread, JSTaggedValue::Undefined()); 1310 JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined(); 1311 const uint32_t argsLength = 3; // 3: «kValue, k, O» 1312 while (k < len) { 1313 bool exists = JSTaggedValue::HasProperty(thread, thisObjVal, k); 1314 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1315 if (exists) { 1316 JSHandle<JSTaggedValue> kValue = JSSharedArray::FastGetPropertyByValue(thread, thisObjVal, k); 1317 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1318 key.Update(JSTaggedValue(k)); 1319 EcmaRuntimeCallInfo *info = 1320 EcmaInterpreter::NewRuntimeCallInfo(thread, callbackFnHandle, thisArgHandle, undefined, argsLength); 1321 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1322 info->SetCallArg(kValue.GetTaggedValue(), key.GetTaggedValue(), thisObjVal.GetTaggedValue()); 1323 JSTaggedValue mapResult = JSFunction::Call(info); 1324 if (!mapResult.IsSharedType()) { 1325 auto error = ContainerError::ParamError(thread, "Parameter error.Only accept sendable value."); 1326 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 1327 } 1328 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1329 mapResultHandle.Update(mapResult); 1330 JSObject::CreateDataPropertyOrThrow(thread, newArrayHandle, k, mapResultHandle, SCheckMode::SKIP); 1331 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1332 } 1333 k++; 1334 } 1335 1336 // 11. Return A. 1337 return newArrayHandle.GetTaggedValue(); 1338} 1339 1340// 22.1.3.16 Array.prototype.pop ( ) 1341JSTaggedValue BuiltinsSharedArray::Pop(EcmaRuntimeCallInfo *argv) 1342{ 1343 ASSERT(argv); 1344 BUILTINS_API_TRACE(argv->GetThread(), SharedArray, Pop); 1345 1346 JSThread *thread = argv->GetThread(); 1347 [[maybe_unused]] EcmaHandleScope handleScope(thread); 1348 1349 // 1. Let O be ToObject(this value). 1350 JSHandle<JSTaggedValue> thisHandle = GetThis(argv); 1351 if (!thisHandle->IsJSSharedArray()) { 1352 auto error = ContainerError::BindError(thread, "The pop method cannot be bound."); 1353 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 1354 } 1355 JSHandle<JSObject> thisObjHandle = JSTaggedValue::ToObject(thread, thisHandle); 1356 [[maybe_unused]] ConcurrentApiScope<JSSharedArray, ModType::WRITE> scope(thread, thisHandle); 1357 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1358 1359 JSTaggedValue opResult = PopInner(argv, thisHandle, thisObjHandle); 1360 return opResult; 1361} 1362 1363JSTaggedValue BuiltinsSharedArray::PopInner(EcmaRuntimeCallInfo *argv, JSHandle<JSTaggedValue> &thisHandle, 1364 JSHandle<JSObject> &thisObjHandle) 1365{ 1366 JSThread *thread = argv->GetThread(); 1367 [[maybe_unused]] EcmaHandleScope handleScope(thread); 1368 1369 // 1. Let O be ToObject(this value). 1370 if (thisHandle->IsStableJSArray(thread) && JSObject::IsArrayLengthWritable(thread, thisObjHandle)) { 1371 return JSStableArray::Pop(JSHandle<JSSharedArray>::Cast(thisHandle), argv); 1372 } 1373 1374 // 2. ReturnIfAbrupt(O). 1375 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1376 JSHandle<JSTaggedValue> thisObjVal(thisObjHandle); 1377 1378 // 3. Let len be ToLength(Get(O, "length")). 1379 int64_t len = ArrayHelper::GetArrayLength(thread, thisObjVal); 1380 // 4. ReturnIfAbrupt(len). 1381 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1382 // 5. If len is zero, 1383 // a. Let setStatus be Set(O, "length", 0, true). 1384 // b. ReturnIfAbrupt(setStatus). 1385 // c. Return undefined. 1386 if (len == 0) { 1387 JSHandle<JSTaggedValue> lengthValue(thread, JSTaggedValue(0)); 1388 JSSharedArray::LengthSetter(thread, thisObjHandle, lengthValue, true); 1389 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1390 return JSTaggedValue::Undefined(); 1391 } 1392 1393 // 6. Else len > 0, 1394 // a. Let newLen be len–1. 1395 // b. Let indx be ToString(newLen). 1396 // c. Let element be Get(O, indx). 1397 // d. ReturnIfAbrupt(element). 1398 // e. Let deleteStatus be DeletePropertyOrThrow(O, indx). 1399 // f. ReturnIfAbrupt(deleteStatus). 1400 // g. Let setStatus be Set(O, "length", newLen, true). 1401 // h. ReturnIfAbrupt(setStatus). 1402 // i. Return element. 1403 int64_t newLen = len - 1; 1404 JSHandle<JSTaggedValue> indexHandle(thread, JSTaggedValue(newLen)); 1405 JSHandle<JSTaggedValue> element = 1406 JSTaggedValue::GetProperty(thread, thisObjVal, indexHandle, SCheckMode::SKIP).GetValue(); 1407 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1408 JSTaggedValue::DeletePropertyOrThrow(thread, thisObjVal, indexHandle); 1409 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1410 JSSharedArray::LengthSetter(thread, thisObjHandle, indexHandle, true); 1411 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1412 1413 return element.GetTaggedValue(); 1414} 1415 1416// 22.1.3.17 Array.prototype.push ( ...items ) 1417JSTaggedValue BuiltinsSharedArray::Push(EcmaRuntimeCallInfo *argv) 1418{ 1419 ASSERT(argv); 1420 BUILTINS_API_TRACE(argv->GetThread(), SharedArray, Push); 1421 JSThread *thread = argv->GetThread(); 1422 [[maybe_unused]] EcmaHandleScope handleScope(thread); 1423 JSHandle<JSTaggedValue> thisHandle = GetThis(argv); 1424 if (!thisHandle->IsJSSharedArray()) { 1425 auto error = ContainerError::BindError(thread, "The push method cannot be bound."); 1426 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 1427 } 1428 [[maybe_unused]] ConcurrentApiScope<JSSharedArray, ModType::WRITE> scope(thread, thisHandle); 1429 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1430 if (thisHandle->IsStableJSArray(thread)) { 1431 auto opResult = JSStableArray::Push(JSHandle<JSSharedArray>::Cast(thisHandle), argv); 1432 return opResult; 1433 } 1434 // 6. Let argCount be the number of elements in items. 1435 uint32_t argc = argv->GetArgsNumber(); 1436 1437 // 1. Let O be ToObject(this value). 1438 JSHandle<JSObject> thisObjHandle = JSTaggedValue::ToObject(thread, thisHandle); 1439 // 2. ReturnIfAbrupt(O). 1440 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1441 JSHandle<JSTaggedValue> thisObjVal(thisObjHandle); 1442 1443 // 3. Let len be ToLength(Get(O, "length")). 1444 int64_t len = ArrayHelper::GetArrayLength(thread, thisObjVal); 1445 // 4. ReturnIfAbrupt(len). 1446 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1447 // 7. If len + argCount > 253-1, throw a TypeError exception. 1448 if ((len + static_cast<int64_t>(argc)) > base::MAX_SAFE_INTEGER) { 1449 THROW_TYPE_ERROR_AND_RETURN(thread, "out of range.", JSTaggedValue::Exception()); 1450 } 1451 1452 // 8. Repeat, while items is not empty 1453 // a. Remove the first element from items and let E be the value of the element. 1454 // b. Let setStatus be Set(O, ToString(len), E, true). 1455 // c. ReturnIfAbrupt(setStatus). 1456 // d. Let len be len+1. 1457 uint32_t k = 0; 1458 JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined()); 1459 while (k < argc) { 1460 key.Update(JSTaggedValue(len)); 1461 JSHandle<JSTaggedValue> kValue = GetCallArg(argv, k); 1462 if (!kValue->IsSharedType()) { 1463 auto error = ContainerError::ParamError(thread, "Parameter error.Only accept sendable value."); 1464 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 1465 } 1466 JSSharedArray::FastSetPropertyByValue(thread, thisObjVal, key, kValue); 1467 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1468 k++; 1469 len++; 1470 } 1471 1472 // 9. Let setStatus be Set(O, "length", len, true). 1473 key.Update(JSTaggedValue(len)); 1474 JSSharedArray::LengthSetter(thread, thisObjHandle, key, true); 1475 // 10. ReturnIfAbrupt(setStatus). 1476 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1477 1478 // 11. Return len. 1479 return GetTaggedDouble(len); 1480} 1481 1482JSTaggedValue BuiltinsSharedArray::ReduceUnStableJSArray(JSThread *thread, JSHandle<JSTaggedValue> &thisHandle, 1483 JSHandle<JSTaggedValue> &thisObjVal, int64_t k, int64_t len, JSMutableHandle<JSTaggedValue> &accumulator, 1484 JSHandle<JSTaggedValue> &callbackFnHandle) 1485{ 1486 const GlobalEnvConstants *globalConst = thread->GlobalConstants(); 1487 JSTaggedValue callResult = JSTaggedValue::Undefined(); 1488 JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined()); 1489 while (k < len) { 1490 bool exists = (thisHandle->IsTypedArray() || JSTaggedValue::HasProperty(thread, thisObjVal, k)); 1491 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1492 if (exists) { 1493 JSHandle<JSTaggedValue> kValue = JSSharedArray::FastGetPropertyByValue(thread, thisObjVal, k); 1494 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1495 key.Update(JSTaggedValue(k)); 1496 JSHandle<JSTaggedValue> thisArgHandle = globalConst->GetHandledUndefined(); 1497 const uint32_t argsLength = 4; // 4: «accumulator, kValue, k, O» 1498 JSHandle<JSTaggedValue> undefined = globalConst->GetHandledUndefined(); 1499 EcmaRuntimeCallInfo *info = 1500 EcmaInterpreter::NewRuntimeCallInfo(thread, callbackFnHandle, thisArgHandle, undefined, argsLength); 1501 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1502 info->SetCallArg(accumulator.GetTaggedValue(), kValue.GetTaggedValue(), key.GetTaggedValue(), 1503 thisObjVal.GetTaggedValue()); 1504 callResult = JSFunction::Call(info); 1505 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1506 accumulator.Update(callResult); 1507 } 1508 k++; 1509 } 1510 return accumulator.GetTaggedValue(); 1511} 1512 1513// 22.1.3.18 Array.prototype.reduce ( callbackfn [ , initialValue ] ) 1514JSTaggedValue BuiltinsSharedArray::Reduce(EcmaRuntimeCallInfo *argv) 1515{ 1516 ASSERT(argv); 1517 BUILTINS_API_TRACE(argv->GetThread(), SharedArray, Reduce); 1518 JSThread *thread = argv->GetThread(); 1519 [[maybe_unused]] EcmaHandleScope handleScope(thread); 1520 1521 uint32_t argc = argv->GetArgsNumber(); 1522 // 1. Let O be ToObject(this value). 1523 JSHandle<JSTaggedValue> thisHandle = GetThis(argv); 1524 if (!thisHandle->IsJSSharedArray()) { 1525 auto error = ContainerError::BindError(thread, "The reduce method cannot be bound."); 1526 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 1527 } 1528 JSHandle<JSObject> thisObjHandle = JSTaggedValue::ToObject(thread, thisHandle); 1529 [[maybe_unused]] ConcurrentApiScope<JSSharedArray> scope(thread, thisHandle); 1530 // 2. ReturnIfAbrupt(O). 1531 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1532 JSHandle<JSTaggedValue> thisObjVal(thisObjHandle); 1533 1534 // 3. Let len be ToLength(Get(O, "length")). 1535 int64_t len = ArrayHelper::GetLength(thread, thisObjVal); 1536 // 4. ReturnIfAbrupt(len). 1537 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1538 1539 // 5. If IsCallable(callbackfn) is false, throw a TypeError exception. 1540 JSHandle<JSTaggedValue> callbackFnHandle = GetCallArg(argv, 0); 1541 if (!callbackFnHandle->IsCallable()) { 1542 THROW_TYPE_ERROR_AND_RETURN(thread, "the callbackfun is not callable.", JSTaggedValue::Exception()); 1543 } 1544 1545 // 6. If len is 0 and initialValue is not present, throw a TypeError exception. 1546 if (len == 0 && argc < 2) { // 2:2 means the number of parameters 1547 THROW_TYPE_ERROR_AND_RETURN(thread, "out of range.", JSTaggedValue::Exception()); 1548 } 1549 1550 // 7. Let k be 0. 1551 // 8. If initialValue is present, then 1552 // a. Set accumulator to initialValue. 1553 // 9. Else initialValue is not present, 1554 // a. Let kPresent be false. 1555 // b. Repeat, while kPresent is false and k < len 1556 // i. Let Pk be ToString(k). 1557 // ii. Let kPresent be HasProperty(O, Pk). 1558 // iii. ReturnIfAbrupt(kPresent). 1559 // iv. If kPresent is true, then 1560 // 1. Let accumulator be Get(O, Pk). 1561 // 2. ReturnIfAbrupt(accumulator). 1562 // v. Increase k by 1. 1563 // c. If kPresent is false, throw a TypeError exception. 1564 int64_t k = 0; 1565 JSMutableHandle<JSTaggedValue> accumulator(thread, JSTaggedValue::Undefined()); 1566 if (argc == 2) { // 2:2 means the number of parameters 1567 accumulator.Update(GetCallArg(argv, 1).GetTaggedValue()); 1568 } else { 1569 bool kPresent = false; 1570 while (!kPresent && k < len) { 1571 kPresent = (thisHandle->IsTypedArray() || thisHandle->IsSharedTypedArray() || 1572 JSTaggedValue::HasProperty(thread, thisObjVal, k)); 1573 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1574 if (kPresent) { 1575 accumulator.Update(JSSharedArray::FastGetPropertyByValue(thread, thisObjVal, k).GetTaggedValue()); 1576 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1577 } 1578 k++; 1579 } 1580 if (!kPresent) { 1581 THROW_TYPE_ERROR_AND_RETURN(thread, "accumulator can't be initialized.", JSTaggedValue::Exception()); 1582 } 1583 } 1584 1585 if (thisObjVal->IsStableJSArray(thread)) { 1586 JSStableArray::Reduce(thread, thisObjHandle, callbackFnHandle, accumulator, k, len); 1587 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1588 } 1589 auto opResult = ReduceUnStableJSArray(thread, thisHandle, thisObjVal, k, len, accumulator, callbackFnHandle); 1590 return opResult; 1591} 1592 1593// 22.1.3.21 Array.prototype.shift ( ) 1594JSTaggedValue BuiltinsSharedArray::Shift(EcmaRuntimeCallInfo *argv) 1595{ 1596 ASSERT(argv); 1597 BUILTINS_API_TRACE(argv->GetThread(), SharedArray, Shift); 1598 JSThread *thread = argv->GetThread(); 1599 [[maybe_unused]] EcmaHandleScope handleScope(thread); 1600 1601 // 1. Let O be ToObject(this value). 1602 JSHandle<JSTaggedValue> thisHandle = GetThis(argv); 1603 if (!thisHandle->IsJSSharedArray()) { 1604 auto error = ContainerError::BindError(thread, "The shift method cannot be bound."); 1605 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 1606 } 1607 JSHandle<JSObject> thisObjHandle = JSTaggedValue::ToObject(thread, thisHandle); 1608 [[maybe_unused]] ConcurrentApiScope<JSSharedArray, ModType::WRITE> scope(thread, thisHandle); 1609 // 2. ReturnIfAbrupt(O). 1610 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1611 if (thisHandle->IsStableJSArray(thread) && JSObject::IsArrayLengthWritable(thread, thisObjHandle)) { 1612 auto opResult = JSStableArray::Shift(JSHandle<JSSharedArray>::Cast(thisHandle), argv); 1613 return opResult; 1614 } 1615 JSHandle<JSTaggedValue> thisObjVal(thisObjHandle); 1616 1617 // 3. Let len be ToLength(Get(O, "length")). 1618 int64_t len = ArrayHelper::GetArrayLength(thread, thisObjVal); 1619 // 4. ReturnIfAbrupt(len). 1620 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1621 // 5. If len is zero, then 1622 // a. Let setStatus be Set(O, "length", 0, true). 1623 // b. ReturnIfAbrupt(setStatus). 1624 // c. Return undefined. 1625 if (len == 0) { 1626 JSHandle<JSTaggedValue> zeroLenHandle(thread, JSTaggedValue(len)); 1627 JSSharedArray::LengthSetter(thread, thisObjHandle, zeroLenHandle, false); 1628 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1629 return JSTaggedValue::Undefined(); 1630 } 1631 1632 // 6. Let first be Get(O, "0"). 1633 JSHandle<JSTaggedValue> firstKey(thread, JSTaggedValue(0)); 1634 JSHandle<JSTaggedValue> firstValue = 1635 JSTaggedValue::GetProperty(thread, thisObjVal, firstKey, SCheckMode::SKIP).GetValue(); 1636 // 7. ReturnIfAbrupt(first). 1637 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1638 1639 // 8. Let k be 1. 1640 // 9. Repeat, while k < len 1641 // a. Let from be ToString(k). 1642 // b. Let to be ToString(k–1). 1643 // c. Let fromPresent be HasProperty(O, from). 1644 // d. ReturnIfAbrupt(fromPresent). 1645 // e. If fromPresent is true, then 1646 // i. Let fromVal be Get(O, from). 1647 // ii. ReturnIfAbrupt(fromVal). 1648 // iii. Let setStatus be Set(O, to, fromVal, true). 1649 // iv. ReturnIfAbrupt(setStatus). 1650 // f. Else fromPresent is false, 1651 // i. Let deleteStatus be DeletePropertyOrThrow(O, to). 1652 // ii. ReturnIfAbrupt(deleteStatus). 1653 // g. Increase k by 1. 1654 JSMutableHandle<JSTaggedValue> toKey(thread, JSTaggedValue::Undefined()); 1655 int64_t k = 1; 1656 while (k < len) { 1657 bool exists = JSTaggedValue::HasProperty(thread, thisObjVal, k); 1658 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1659 if (exists) { 1660 JSHandle<JSTaggedValue> fromValue = JSSharedArray::FastGetPropertyByValue(thread, thisObjVal, k); 1661 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1662 JSSharedArray::FastSetPropertyByValue(thread, thisObjVal, k - 1, fromValue); 1663 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1664 } else { 1665 toKey.Update(JSTaggedValue(k - 1)); 1666 JSTaggedValue::DeletePropertyOrThrow(thread, thisObjVal, toKey); 1667 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1668 } 1669 k++; 1670 } 1671 // 10. Let deleteStatus be DeletePropertyOrThrow(O, ToString(len–1)). 1672 JSHandle<JSTaggedValue> deleteKey(thread, JSTaggedValue(len - 1)); 1673 JSTaggedValue::DeletePropertyOrThrow(thread, thisObjVal, deleteKey); 1674 // 11. ReturnIfAbrupt(deleteStatus). 1675 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1676 1677 // 12. Let setStatus be Set(O, "length", len–1, true). 1678 JSHandle<JSTaggedValue> newLenHandle(thread, JSTaggedValue(len - 1)); 1679 JSSharedArray::LengthSetter(thread, thisObjHandle, newLenHandle, true); 1680 // 13. ReturnIfAbrupt(setStatus). 1681 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1682 1683 // 14. Return first. 1684 return firstValue.GetTaggedValue(); 1685} 1686 1687// 22.1.3.22 Array.prototype.slice (start, end) 1688JSTaggedValue BuiltinsSharedArray::Slice(EcmaRuntimeCallInfo *argv) 1689{ 1690 BUILTINS_API_TRACE(argv->GetThread(), SharedArray, Slice); 1691 ASSERT(argv); 1692 JSThread *thread = argv->GetThread(); 1693 [[maybe_unused]] EcmaHandleScope handleScope(thread); 1694 1695 // 1. Let O be ToObject(this value). 1696 JSHandle<JSTaggedValue> thisHandle = GetThis(argv); 1697 if (!thisHandle->IsJSSharedArray()) { 1698 auto error = ContainerError::BindError(thread, "The slice method cannot be bound."); 1699 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 1700 } 1701 JSHandle<JSObject> thisObjHandle = JSTaggedValue::ToObject(thread, thisHandle); 1702 [[maybe_unused]] ConcurrentApiScope<JSSharedArray> scope(thread, thisHandle); 1703 // 2. ReturnIfAbrupt(O). 1704 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1705 JSHandle<JSTaggedValue> thisObjVal(thisObjHandle); 1706 1707 // 3. Let len be ToLength(Get(O, "length")). 1708 int64_t len = ArrayHelper::GetArrayLength(thread, thisObjVal); 1709 // 4. ReturnIfAbrupt(len). 1710 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1711 1712 JSHandle<JSTaggedValue> msg0 = GetCallArg(argv, 0); 1713 double argStart; 1714 if (msg0->IsInt()) { 1715 argStart = msg0->GetInt(); 1716 } else { 1717 // 5. Let relativeStart be ToInteger(start). 1718 JSTaggedNumber argStartTemp = JSTaggedValue::ToInteger(thread, msg0); 1719 // 6. ReturnIfAbrupt(relativeStart). 1720 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1721 argStart = argStartTemp.GetNumber(); 1722 } 1723 1724 // 7. If relativeStart < 0, let k be max((len + relativeStart),0); else let k be min(relativeStart, len). 1725 int64_t k = 0; 1726 if (argStart < 0) { 1727 double tempStart = len + argStart; 1728 k = tempStart > 0 ? tempStart : 0; 1729 } else { 1730 k = argStart < len ? argStart : len; 1731 } 1732 1733 // 8. If end is undefined, let relativeEnd be len; else let relativeEnd be ToInteger(end). 1734 // 9. ReturnIfAbrupt(relativeEnd). 1735 // 10. If relativeEnd < 0, let final be max((len + relativeEnd),0); else let final be min(relativeEnd, len). 1736 JSHandle<JSTaggedValue> msg1 = GetCallArg(argv, 1); 1737 double argEnd = len; 1738 if (!msg1->IsUndefined()) { 1739 if (msg1->IsInt()) { 1740 argEnd = msg1->GetInt(); 1741 } else { 1742 JSTaggedNumber argEndTemp = JSTaggedValue::ToInteger(thread, msg1); 1743 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1744 argEnd = argEndTemp.GetNumber(); 1745 } 1746 } 1747 int64_t final = 0; 1748 if (argEnd < 0) { 1749 double tempFinal = len + argEnd; 1750 final = tempFinal > 0 ? tempFinal : 0; 1751 } else { 1752 final = argEnd < len ? argEnd : len; 1753 } 1754 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1755 1756 // 11. Let count be max(final – k, 0). 1757 int64_t count = final > k ? (final - k) : 0; 1758 1759 if (thisHandle->IsStableJSArray(thread) && !thisObjHandle->GetJSHClass()->HasConstructor() 1760 && JSObject::GetPrototype(thisObjHandle).IsJSArray()) { 1761 auto opResult = JSStableArray::Slice(thread, thisObjHandle, k, count); 1762 return opResult; 1763 } 1764 1765 // 12. Let A be ArraySpeciesCreate(O, count). 1766 JSTaggedValue newArray = 1767 JSSharedArray::ArraySpeciesCreate(thread, thisObjHandle, JSTaggedNumber(static_cast<double>(count))); 1768 // 13. ReturnIfAbrupt(A). 1769 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1770 if (count == 0) { 1771 return newArray; 1772 } 1773 JSHandle<JSObject> newArrayHandle(thread, newArray); 1774 1775 // 14. Let n be 0. 1776 // 15. Repeat, while k < final 1777 // a. Let Pk be ToString(k). 1778 // b. Let kPresent be HasProperty(O, Pk). 1779 // c. ReturnIfAbrupt(kPresent). 1780 // d. If kPresent is true, then 1781 // i. Let kValue be Get(O, Pk). 1782 // ii. ReturnIfAbrupt(kValue). 1783 // iii. Let status be CreateDataPropertyOrThrow(A, ToString(n), kValue ). 1784 // iv. ReturnIfAbrupt(status). 1785 // e. Increase k by 1. 1786 // f. Increase n by 1. 1787 int64_t n = 0; 1788 JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined()); 1789 JSMutableHandle<JSTaggedValue> nKey(thread, JSTaggedValue::Undefined()); 1790 while (k < final) { 1791 key.Update(JSTaggedValue(k)); 1792 bool exists = JSTaggedValue::HasProperty(thread, thisObjVal, key); 1793 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1794 if (exists) { 1795 nKey.Update(JSTaggedValue(n)); 1796 JSHandle<JSTaggedValue> kValueHandle = JSSharedArray::FastGetPropertyByValue(thread, thisObjVal, key); 1797 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1798 JSObject::CreateDataPropertyOrThrow(thread, newArrayHandle, nKey, kValueHandle, SCheckMode::SKIP); 1799 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1800 } 1801 k++; 1802 n++; 1803 } 1804 1805 // 16. Let setStatus be Set(A, "length", n, true). 1806 JSHandle<JSTaggedValue> newLenHandle(thread, JSTaggedValue(n)); 1807 JSSharedArray::LengthSetter(thread, newArrayHandle, newLenHandle, true); 1808 // 17. ReturnIfAbrupt(setStatus). 1809 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1810 1811 // 18. Return A. 1812 return newArrayHandle.GetTaggedValue(); 1813} 1814 1815// 22.1.3.24 Array.prototype.sort (comparefn) 1816JSTaggedValue BuiltinsSharedArray::Sort(EcmaRuntimeCallInfo *argv) 1817{ 1818 ASSERT(argv); 1819 JSThread *thread = argv->GetThread(); 1820 BUILTINS_API_TRACE(thread, SharedArray, Sort); 1821 [[maybe_unused]] EcmaHandleScope handleScope(thread); 1822 1823 // 1. If comparefn is not undefined and IsCallable(comparefn) is false, throw a TypeError exception. 1824 JSHandle<JSTaggedValue> callbackFnHandle = GetCallArg(argv, 0); 1825 if (!callbackFnHandle->IsUndefined() && !callbackFnHandle->IsCallable()) { 1826 THROW_TYPE_ERROR_AND_RETURN(thread, "Callable is false", JSTaggedValue::Exception()); 1827 } 1828 1829 // 2. Let obj be ToObject(this value). 1830 JSHandle<JSTaggedValue> thisHandle = GetThis(argv); 1831 if (!thisHandle->IsJSSharedArray()) { 1832 auto error = ContainerError::BindError(thread, "The sort method cannot be bound."); 1833 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 1834 } 1835 JSHandle<JSObject> thisObjHandle = JSTaggedValue::ToObject(thread, thisHandle); 1836 [[maybe_unused]] ConcurrentApiScope<JSSharedArray, ModType::WRITE> scope(thread, thisHandle); 1837 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1838 1839 // Array sort 1840 if (thisHandle->IsStableJSArray(thread) && callbackFnHandle->IsUndefined()) { 1841 JSStableArray::Sort(thread, thisObjHandle, callbackFnHandle); 1842 } else { 1843 JSSharedArray::Sort(thread, JSHandle<JSTaggedValue>::Cast(thisObjHandle), callbackFnHandle); 1844 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1845 } 1846 return thisObjHandle.GetTaggedValue(); 1847} 1848 1849// 22.1.3.25 Array.prototype.splice (start, deleteCount , ...items ) 1850// NOLINTNEXTLINE(readability-function-size) 1851JSTaggedValue BuiltinsSharedArray::Splice(EcmaRuntimeCallInfo *argv) 1852{ 1853 ASSERT(argv); 1854 BUILTINS_API_TRACE(argv->GetThread(), SharedArray, Splice); 1855 JSThread *thread = argv->GetThread(); 1856 [[maybe_unused]] EcmaHandleScope handleScope(thread); 1857 uint32_t argc = argv->GetArgsNumber(); 1858 // 1. Let O be ToObject(this value). 1859 JSHandle<JSTaggedValue> thisHandle = GetThis(argv); 1860 if (!thisHandle->IsJSSharedArray()) { 1861 auto error = ContainerError::BindError(thread, "The splice method cannot be bound."); 1862 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 1863 } 1864 JSHandle<JSObject> thisObjHandle = JSTaggedValue::ToObject(thread, thisHandle); 1865 [[maybe_unused]] ConcurrentApiScope<JSSharedArray, ModType::WRITE> scope( 1866 thread, thisHandle); 1867 // 2. ReturnIfAbrupt(O). 1868 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1869 JSHandle<JSTaggedValue> thisObjVal(thisObjHandle); 1870 // 3. Let len be ToLength(Get(O, "length")). 1871 int64_t len = ArrayHelper::GetArrayLength(thread, thisObjVal); 1872 // 4. ReturnIfAbrupt(len). 1873 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1874 // 5. Let relativeStart be ToInteger(start). 1875 int64_t start = 0; 1876 int64_t insertCount = 0; 1877 int64_t actualDeleteCount = 0; 1878 int64_t end = len; 1879 double argStart = 0; 1880 if (argc > 0) { 1881 JSHandle<JSTaggedValue> msg0 = GetCallArg(argv, 0); 1882 JSTaggedNumber argStartTemp = JSTaggedValue::ToInteger(thread, msg0); 1883 // 6. ReturnIfAbrupt(relativeStart). 1884 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1885 argStart = argStartTemp.GetNumber(); 1886 // 7. If relativeStart < 0, let actualStart be max((len + relativeStart),0); else let actualStart be 1887 // min(relativeStart, len). 1888 if (argStart < 0) { 1889 double tempStart = argStart + len; 1890 start = tempStart > 0 ? tempStart : 0; 1891 } else { 1892 start = argStart < end ? argStart : end; 1893 } 1894 actualDeleteCount = len - start; 1895 } 1896 // 8. If the number of actual arguments is 0, then 1897 // a. Let insertCount be 0. 1898 // b. Let actualDeleteCount be 0. 1899 // 9. Else if the number of actual arguments is 1, then 1900 // a. Let insertCount be 0. 1901 // b. Let actualDeleteCount be len – actualStart. 1902 // 10. Else, 1903 // a. Let insertCount be the number of actual arguments minus 2. 1904 // b. Let dc be ToInteger(deleteCount). 1905 // c. ReturnIfAbrupt(dc). 1906 // d. Let actualDeleteCount be min(max(dc,0), len – actualStart). 1907 if (argc > 1) { 1908 insertCount = argc - 2; // 2:2 means there are two arguments before the insert items. 1909 JSHandle<JSTaggedValue> msg1 = GetCallArg(argv, 1); 1910 JSTaggedNumber argDeleteCount = JSTaggedValue::ToInteger(thread, msg1); 1911 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1912 double deleteCount = argDeleteCount.GetNumber(); 1913 deleteCount = deleteCount > 0 ? deleteCount : 0; 1914 actualDeleteCount = deleteCount < (len - start) ? deleteCount : len - start; 1915 } 1916 // 11. If len+insertCount−actualDeleteCount > 253-1, throw a TypeError exception. 1917 if (len + insertCount - actualDeleteCount > base::MAX_SAFE_INTEGER) { 1918 THROW_TYPE_ERROR_AND_RETURN(thread, "out of range.", JSTaggedValue::Exception()); 1919 } 1920 // 12. Let A be ArraySpeciesCreate(O, actualDeleteCount). 1921 JSTaggedValue newArray = JSSharedArray::ArraySpeciesCreate( 1922 thread, thisObjHandle, JSTaggedNumber(static_cast<double>(actualDeleteCount))); 1923 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1924 JSHandle<JSObject> newArrayHandle(thread, newArray); 1925 if (thisHandle->IsStableJSArray(thread)) { 1926 return JSStableArray::Splice(JSHandle<JSSharedArray>::Cast(thisHandle), argv, start, insertCount, 1927 actualDeleteCount, newArrayHandle, len); 1928 } 1929 // 14. Let k be 0. 1930 // 15. Repeat, while k < actualDeleteCount 1931 // a. Let from be ToString(actualStart+k). 1932 // b. Let fromPresent be HasProperty(O, from). 1933 // d. If fromPresent is true, then 1934 // i. Let fromValue be Get(O, from). 1935 // iii. Let status be CreateDataPropertyOrThrow(A, ToString(k), fromValue). 1936 // e. Increase k by 1. 1937 JSMutableHandle<JSTaggedValue> fromKey(thread, JSTaggedValue::Undefined()); 1938 JSMutableHandle<JSTaggedValue> toKey(thread, JSTaggedValue::Undefined()); 1939 int64_t k = 0; 1940 while (k < actualDeleteCount) { 1941 int64_t from = start + k; 1942 fromKey.Update(JSTaggedValue(from)); 1943 bool exists = JSTaggedValue::HasProperty(thread, thisObjVal, fromKey); 1944 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1945 if (exists) { 1946 JSHandle<JSTaggedValue> fromValue = JSSharedArray::FastGetPropertyByValue(thread, thisObjVal, fromKey); 1947 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1948 toKey.Update(JSTaggedValue(k)); 1949 if (newArrayHandle->IsJSProxy()) { 1950 toKey.Update(JSTaggedValue::ToString(thread, toKey).GetTaggedValue()); 1951 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1952 } 1953 JSObject::CreateDataPropertyOrThrow(thread, newArrayHandle, toKey, fromValue); 1954 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1955 } 1956 k++; 1957 } 1958 // 16. Let setStatus be Set(A, "length", actualDeleteCount, true). 1959 JSHandle<JSTaggedValue> deleteCountHandle(thread, JSTaggedValue(actualDeleteCount)); 1960 JSSharedArray::LengthSetter(thread, newArrayHandle, deleteCountHandle, true); 1961 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1962 // 19. Let itemCount be the number of elements in items. 1963 // 20. If itemCount < actualDeleteCount, then 1964 // a. Let k be actualStart. 1965 // b. Repeat, while k < (len – actualDeleteCount) 1966 // i. Let from be ToString(k+actualDeleteCount). 1967 // ii. Let to be ToString(k+itemCount). 1968 // iii. Let fromPresent be HasProperty(O, from). 1969 // v. If fromPresent is true, then 1970 // 1. Let fromValue be Get(O, from). 1971 // 3. Let setStatus be Set(O, to, fromValue, true). 1972 // vi. Else fromPresent is false, 1973 // 1. Let deleteStatus be DeletePropertyOrThrow(O, to). 1974 // vii. Increase k by 1. 1975 // c. Let k be len. 1976 // d. Repeat, while k > (len – actualDeleteCount + itemCount) 1977 // i. Let deleteStatus be DeletePropertyOrThrow(O, ToString(k–1)). 1978 // iii. Decrease k by 1. 1979 if (insertCount < actualDeleteCount) { 1980 k = start; 1981 while (k < len - actualDeleteCount) { 1982 fromKey.Update(JSTaggedValue(k + actualDeleteCount)); 1983 toKey.Update(JSTaggedValue(k + insertCount)); 1984 bool exists = JSTaggedValue::HasProperty(thread, thisObjVal, fromKey); 1985 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1986 if (exists) { 1987 JSHandle<JSTaggedValue> fromValue = JSSharedArray::FastGetPropertyByValue(thread, thisObjVal, fromKey); 1988 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1989 JSSharedArray::FastSetPropertyByValue(thread, thisObjVal, toKey, fromValue); 1990 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1991 } else { 1992 JSTaggedValue::DeletePropertyOrThrow(thread, thisObjVal, toKey); 1993 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1994 } 1995 k++; 1996 } 1997 k = len; 1998 JSMutableHandle<JSTaggedValue> deleteKey(thread, JSTaggedValue::Undefined()); 1999 while (k > len - actualDeleteCount + insertCount) { 2000 deleteKey.Update(JSTaggedValue(k - 1)); 2001 JSTaggedValue::DeletePropertyOrThrow(thread, thisObjVal, deleteKey); 2002 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 2003 k--; 2004 } 2005 } else if (insertCount > actualDeleteCount) { 2006 // 21. Else if itemCount > actualDeleteCount, then 2007 // a. Let k be (len – actualDeleteCount). 2008 // b. Repeat, while k > actualStart 2009 // i. Let from be ToString(k + actualDeleteCount – 1). 2010 // ii. Let to be ToString(k + itemCount – 1) 2011 // iii. Let fromPresent be HasProperty(O, from). 2012 // iv. ReturnIfAbrupt(fromPresent). 2013 // v. If fromPresent is true, then 2014 // 1. Let fromValue be Get(O, from). 2015 // 2. ReturnIfAbrupt(fromValue). 2016 // 3. Let setStatus be Set(O, to, fromValue, true). 2017 // 4. ReturnIfAbrupt(setStatus). 2018 // vi. Else fromPresent is false, 2019 // 1. Let deleteStatus be DeletePropertyOrThrow(O, to). 2020 // 2. ReturnIfAbrupt(deleteStatus). 2021 // vii. Decrease k by 1. 2022 k = len - actualDeleteCount; 2023 while (k > start) { 2024 fromKey.Update(JSTaggedValue(k + actualDeleteCount - 1)); 2025 toKey.Update(JSTaggedValue(k + insertCount - 1)); 2026 bool exists = JSTaggedValue::HasProperty(thread, thisObjVal, fromKey); 2027 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 2028 if (exists) { 2029 JSHandle<JSTaggedValue> fromValue = JSSharedArray::FastGetPropertyByValue(thread, thisObjVal, fromKey); 2030 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 2031 JSSharedArray::FastSetPropertyByValue(thread, thisObjVal, toKey, fromValue); 2032 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 2033 } else { 2034 JSTaggedValue::DeletePropertyOrThrow(thread, thisObjVal, toKey); 2035 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 2036 } 2037 k--; 2038 } 2039 } 2040 // 22. Let k be actualStart. 2041 k = start; 2042 // 23. Repeat, while items is not empty 2043 JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined()); 2044 for (uint32_t i = 2; i < argc; i++) { 2045 JSHandle<JSTaggedValue> itemValue = GetCallArg(argv, i); 2046 if (!itemValue->IsSharedType()) { 2047 auto error = ContainerError::ParamError(thread, "Parameter error.Only accept sendable value."); 2048 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 2049 } 2050 key.Update(JSTaggedValue(k)); 2051 JSSharedArray::FastSetPropertyByValue(thread, thisObjVal, key, itemValue); 2052 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 2053 k++; 2054 } 2055 // 24. Let setStatus be Set(O, "length", len – actualDeleteCount + itemCount, true). 2056 int64_t newLen = len - actualDeleteCount + insertCount; 2057 JSHandle<JSTaggedValue> newLenHandle(thread, JSTaggedValue(newLen)); 2058 JSSharedArray::LengthSetter(thread, thisObjHandle, newLenHandle, true); 2059 // 25. ReturnIfAbrupt(setStatus). 2060 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 2061 // 26. Return A. 2062 return newArrayHandle.GetTaggedValue(); 2063} 2064 2065// 22.1.3.27 Array.prototype.toString ( ) 2066JSTaggedValue BuiltinsSharedArray::ToString(EcmaRuntimeCallInfo *argv) 2067{ 2068 ASSERT(argv); 2069 BUILTINS_API_TRACE(argv->GetThread(), SharedArray, ToString); 2070 JSThread *thread = argv->GetThread(); 2071 [[maybe_unused]] EcmaHandleScope handleScope(thread); 2072 auto ecmaVm = thread->GetEcmaVM(); 2073 2074 // 1. Let array be ToObject(this value). 2075 JSHandle<JSTaggedValue> thisHandle = GetThis(argv); 2076 if (!thisHandle->IsJSSharedArray()) { 2077 auto error = ContainerError::BindError(thread, "The toString method cannot be bound."); 2078 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 2079 } 2080 JSHandle<JSObject> thisObjHandle = JSTaggedValue::ToObject(thread, thisHandle); 2081 [[maybe_unused]] ConcurrentApiScope<JSSharedArray> scope(thread, thisHandle); 2082 // 2. ReturnIfAbrupt(array). 2083 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 2084 JSHandle<JSTaggedValue> thisObjVal(thisObjHandle); 2085 2086 // 3. Let func be Get(array, "join"). 2087 JSHandle<JSTaggedValue> joinKey = thread->GlobalConstants()->GetHandledJoinString(); 2088 JSHandle<JSTaggedValue> callbackFnHandle = JSTaggedValue::GetProperty(thread, thisObjVal, joinKey).GetValue(); 2089 2090 // 4. ReturnIfAbrupt(func). 2091 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 2092 2093 // 5. If IsCallable(func) is false, let func be the intrinsic function %ObjProto_toString% (19.1.3.6). 2094 if (!callbackFnHandle->IsCallable()) { 2095 JSHandle<GlobalEnv> env = ecmaVm->GetGlobalEnv(); 2096 JSHandle<JSTaggedValue> objectPrototype = env->GetObjectFunctionPrototype(); 2097 JSHandle<JSTaggedValue> toStringKey = thread->GlobalConstants()->GetHandledToStringString(); 2098 callbackFnHandle = JSTaggedValue::GetProperty(thread, objectPrototype, toStringKey).GetValue(); 2099 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 2100 } 2101 const uint32_t argsLength = argv->GetArgsNumber(); 2102 JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined(); 2103 EcmaRuntimeCallInfo *info = 2104 EcmaInterpreter::NewRuntimeCallInfo(thread, callbackFnHandle, thisObjVal, undefined, argsLength); 2105 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 2106 info->SetCallArg(argsLength, 0, argv, 0); 2107 auto opResult = JSFunction::Call(info); 2108 return opResult; 2109} 2110 2111// 22.1.3.28 Array.prototype.unshift ( ...items ) 2112JSTaggedValue BuiltinsSharedArray::Unshift(EcmaRuntimeCallInfo *argv) 2113{ 2114 ASSERT(argv); 2115 BUILTINS_API_TRACE(argv->GetThread(), SharedArray, Unshift); 2116 JSThread *thread = argv->GetThread(); 2117 [[maybe_unused]] EcmaHandleScope handleScope(thread); 2118 2119 // 5. Let argCount be the number of actual arguments. 2120 int64_t argc = argv->GetArgsNumber(); 2121 2122 // 1. Let O be ToObject(this value). 2123 JSHandle<JSTaggedValue> thisHandle = GetThis(argv); 2124 if (!thisHandle->IsJSSharedArray()) { 2125 auto error = ContainerError::BindError(thread, "The unshift method cannot be bound."); 2126 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 2127 } 2128 JSHandle<JSObject> thisObjHandle = JSTaggedValue::ToObject(thread, thisHandle); 2129 [[maybe_unused]] ConcurrentApiScope<JSSharedArray, ModType::WRITE> scope(thread, thisHandle); 2130 // 2. ReturnIfAbrupt(O). 2131 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 2132 JSHandle<JSTaggedValue> thisObjVal(thisObjHandle); 2133 2134 // 3. Let len be ToLength(Get(O, "length")). 2135 int64_t len = ArrayHelper::GetArrayLength(thread, thisObjVal); 2136 // 4. ReturnIfAbrupt(len). 2137 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 2138 2139 // 6. If argCount > 0, then 2140 // a. If len+ argCount > 253-1, throw a TypeError exception. 2141 // b. Let k be len. 2142 // c. Repeat, while k > 0, 2143 // i. Let from be ToString(k–1). 2144 // ii. Let to be ToString(k+argCount –1). 2145 // iii. Let fromPresent be HasProperty(O, from). 2146 // iv. ReturnIfAbrupt(fromPresent). 2147 // v. If fromPresent is true, then 2148 // 1. Let fromValue be Get(O, from). 2149 // 2. ReturnIfAbrupt(fromValue). 2150 // 3. Let setStatus be Set(O, to, fromValue, true). 2151 // 4. ReturnIfAbrupt(setStatus). 2152 // vi. Else fromPresent is false, 2153 // 1. Let deleteStatus be DeletePropertyOrThrow(O, to). 2154 // 2. ReturnIfAbrupt(deleteStatus). 2155 // vii. Decrease k by 1. 2156 if (argc > 0) { 2157 if (len + argc > base::MAX_SAFE_INTEGER) { 2158 THROW_TYPE_ERROR_AND_RETURN(thread, "out of range.", JSTaggedValue::Exception()); 2159 } 2160 JSMutableHandle<JSTaggedValue> fromKey(thread, JSTaggedValue::Undefined()); 2161 JSMutableHandle<JSTaggedValue> toKey(thread, JSTaggedValue::Undefined()); 2162 int64_t k = len; 2163 while (k > 0) { 2164 fromKey.Update(JSTaggedValue(k - 1)); 2165 toKey.Update(JSTaggedValue(k + argc - 1)); 2166 bool exists = JSTaggedValue::HasProperty(thread, thisObjVal, fromKey); 2167 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 2168 if (exists) { 2169 JSHandle<JSTaggedValue> fromValue = JSSharedArray::FastGetPropertyByValue(thread, thisObjVal, fromKey); 2170 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 2171 JSSharedArray::FastSetPropertyByValue(thread, thisObjVal, toKey, fromValue); 2172 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 2173 } else { 2174 JSTaggedValue::DeletePropertyOrThrow(thread, thisObjVal, toKey); 2175 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 2176 } 2177 k--; 2178 } 2179 // d. Let j be 0. 2180 // e. Let items be a List whose elements are, in left to right order, the arguments that were passed to this 2181 // function invocation. 2182 // f. Repeat, while items is not empty 2183 // i. Remove the first element from items and let E be the value of that element. 2184 // ii. Let setStatus be Set(O, ToString(j), E, true). 2185 // iii. ReturnIfAbrupt(setStatus). 2186 // iv. Increase j by 1. 2187 int64_t j = 0; 2188 while (j < argc) { 2189 toKey.Update(JSTaggedValue(j)); 2190 JSHandle<JSTaggedValue> toValue = GetCallArg(argv, j); 2191 if (!toValue->IsSharedType()) { 2192 auto error = ContainerError::ParamError(thread, "Parameter error.Only accept sendable value."); 2193 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 2194 } 2195 JSSharedArray::FastSetPropertyByValue(thread, thisObjVal, toKey, toValue); 2196 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 2197 j++; 2198 } 2199 } 2200 2201 // 7. Let setStatus be Set(O, "length", len+argCount, true). 2202 int64_t newLen = len + argc; 2203 JSHandle<JSTaggedValue> newLenHandle(thread, JSTaggedValue(newLen)); 2204 JSSharedArray::LengthSetter(thread, thisObjHandle, newLenHandle, true); 2205 // 8. ReturnIfAbrupt(setStatus). 2206 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 2207 2208 // 9. Return len+argCount. 2209 return GetTaggedDouble(newLen); 2210} 2211 2212// 22.1.3.29 Array.prototype.values ( ) 2213JSTaggedValue BuiltinsSharedArray::Values(EcmaRuntimeCallInfo *argv) 2214{ 2215 ASSERT(argv); 2216 BUILTINS_API_TRACE(argv->GetThread(), SharedArray, Values); 2217 JSThread *thread = argv->GetThread(); 2218 [[maybe_unused]] EcmaHandleScope handleScope(thread); 2219 JSHandle<JSTaggedValue> thisHandle = GetThis(argv); 2220 if (!thisHandle->IsJSSharedArray()) { 2221 auto error = ContainerError::BindError(thread, "The values method cannot be bound."); 2222 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 2223 } 2224 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 2225 // 1. Let O be ToObject(this value). 2226 // 2. ReturnIfAbrupt(O). 2227 JSHandle<JSObject> self = JSTaggedValue::ToObject(thread, GetThis(argv)); 2228 [[maybe_unused]] ConcurrentApiScope<JSSharedArray> scope(thread, thisHandle); 2229 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 2230 // 3. Return CreateArrayIterator(O, "value"). 2231 JSHandle<JSSharedArrayIterator> iter(factory->NewJSSharedArrayIterator(self, IterationKind::VALUE)); 2232 return iter.GetTaggedValue(); 2233} 2234// 22.1.3.31 Array.prototype [ @@unscopables ] 2235JSTaggedValue BuiltinsSharedArray::Unscopables(EcmaRuntimeCallInfo *argv) 2236{ 2237 JSThread *thread = argv->GetThread(); 2238 BUILTINS_API_TRACE(thread, SharedArray, Unscopables); 2239 [[maybe_unused]] EcmaHandleScope handleScope(thread); 2240 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 2241 const GlobalEnvConstants *globalConst = thread->GlobalConstants(); 2242 2243 JSHandle<JSObject> unscopableList = factory->CreateNullJSObject(); 2244 2245 JSHandle<JSTaggedValue> trueVal(thread, JSTaggedValue::True()); 2246 2247 JSHandle<JSTaggedValue> atKey((factory->NewFromASCII("at"))); 2248 JSObject::CreateDataProperty(thread, unscopableList, atKey, trueVal); 2249 2250 JSHandle<JSTaggedValue> copyWithKey = globalConst->GetHandledCopyWithinString(); 2251 JSObject::CreateDataProperty(thread, unscopableList, copyWithKey, trueVal); 2252 2253 JSHandle<JSTaggedValue> entriesKey = globalConst->GetHandledEntriesString(); 2254 JSObject::CreateDataProperty(thread, unscopableList, entriesKey, trueVal); 2255 2256 JSHandle<JSTaggedValue> fillKey = globalConst->GetHandledFillString(); 2257 JSObject::CreateDataProperty(thread, unscopableList, fillKey, trueVal); 2258 2259 JSHandle<JSTaggedValue> findKey = globalConst->GetHandledFindString(); 2260 JSObject::CreateDataProperty(thread, unscopableList, findKey, trueVal); 2261 2262 JSHandle<JSTaggedValue> findIndexKey = globalConst->GetHandledFindIndexString(); 2263 JSObject::CreateDataProperty(thread, unscopableList, findIndexKey, trueVal); 2264 2265 JSHandle<JSTaggedValue> findLastKey((factory->NewFromASCII("findLast"))); 2266 JSObject::CreateDataProperty(thread, unscopableList, findLastKey, trueVal); 2267 2268 JSHandle<JSTaggedValue> findLastIndexKey((factory->NewFromASCII("findLastIndex"))); 2269 JSObject::CreateDataProperty(thread, unscopableList, findLastIndexKey, trueVal); 2270 2271 JSHandle<JSTaggedValue> flatKey = globalConst->GetHandledFlatString(); 2272 JSObject::CreateDataProperty(thread, unscopableList, flatKey, trueVal); 2273 2274 JSHandle<JSTaggedValue> flatMapKey = globalConst->GetHandledFlatMapString(); 2275 JSObject::CreateDataProperty(thread, unscopableList, flatMapKey, trueVal); 2276 2277 JSHandle<JSTaggedValue> includesKey = globalConst->GetHandledIncludesString(); 2278 JSObject::CreateDataProperty(thread, unscopableList, includesKey, trueVal); 2279 2280 JSHandle<JSTaggedValue> keysKey = globalConst->GetHandledKeysString(); 2281 JSObject::CreateDataProperty(thread, unscopableList, keysKey, trueVal); 2282 2283 JSHandle<JSTaggedValue> valuesKey = globalConst->GetHandledValuesString(); 2284 JSObject::CreateDataProperty(thread, unscopableList, valuesKey, trueVal); 2285 2286 JSHandle<JSTaggedValue> toReversedKey((factory->NewFromASCII("toReversed"))); 2287 JSObject::CreateDataProperty(thread, unscopableList, toReversedKey, trueVal); 2288 2289 JSHandle<JSTaggedValue> toSortedKey((factory->NewFromASCII("toSorted"))); 2290 JSObject::CreateDataProperty(thread, unscopableList, toSortedKey, trueVal); 2291 2292 JSHandle<JSTaggedValue> toSplicedKey((factory->NewFromASCII("toSpliced"))); 2293 JSObject::CreateDataProperty(thread, unscopableList, toSplicedKey, trueVal); 2294 return unscopableList.GetTaggedValue(); 2295} 2296 2297// 23.1.3.13 Array.prototype.includes ( searchElement [ , fromIndex ] ) 2298JSTaggedValue BuiltinsSharedArray::Includes(EcmaRuntimeCallInfo *argv) 2299{ 2300 ASSERT(argv); 2301 BUILTINS_API_TRACE(argv->GetThread(), SharedArray, Includes); 2302 JSThread *thread = argv->GetThread(); 2303 [[maybe_unused]] EcmaHandleScope handleScope(thread); 2304 // 1. Let O be ? ToObject(this value). 2305 JSHandle<JSTaggedValue> thisHandle = GetThis(argv); 2306 if (!thisHandle->IsJSSharedArray()) { 2307 auto error = ContainerError::BindError(thread, "The includes method cannot be bound."); 2308 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 2309 } 2310 JSHandle<JSObject> thisObjHandle = JSTaggedValue::ToObject(thread, thisHandle); 2311 [[maybe_unused]] ConcurrentApiScope<JSSharedArray> scope(thread, thisHandle); 2312 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 2313 2314 uint32_t argc = argv->GetArgsNumber(); 2315 JSHandle<JSTaggedValue> thisObjVal(thisObjHandle); 2316 JSHandle<JSTaggedValue> searchElement = GetCallArg(argv, 0); 2317 2318 // 2. Let len be ? LengthOfArrayLike(O). 2319 int64_t len = ArrayHelper::GetLength(thread, thisObjVal); 2320 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 2321 // 3. If len is 0, return false. 2322 if (len == 0) { 2323 return GetTaggedBoolean(false); 2324 } 2325 // 4. Let n be ? ToIntegerOrInfinity(fromIndex). 2326 // 5. Assert: If fromIndex is undefined, then n is 0. 2327 double fromIndex = 0; 2328 if (argc > 1) { 2329 JSHandle<JSTaggedValue> msg1 = GetCallArg(argv, 1); 2330 JSTaggedNumber fromIndexTemp = JSTaggedValue::ToNumber(thread, msg1); 2331 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 2332 fromIndex = base::NumberHelper::TruncateDouble(fromIndexTemp.GetNumber()); 2333 } 2334 2335 // 6. If n is +∞, return false. 2336 // 7. Else if n is -∞, set n to 0. 2337 if (fromIndex >= len) { 2338 return GetTaggedBoolean(false); 2339 } else if (fromIndex < -len) { 2340 fromIndex = 0; 2341 } 2342 // 8. If n ≥ 0, then 2343 // a. Let k be n. 2344 // 9. Else, 2345 // a. Let k be len + n. 2346 // b. If k < 0, let k be 0. 2347 int64_t from = (fromIndex >= 0) ? fromIndex : ((len + fromIndex) >= 0 ? len + fromIndex : 0); 2348 2349 // 10. Repeat, while k < len, 2350 // a. Let elementK be ? Get(O, ! ToString(!(k))). 2351 // b. If SameValueZero(searchElement, elementK) is true, return true. 2352 // c. Set k to k + 1. 2353 JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined()); 2354 JSMutableHandle<JSTaggedValue> kValueHandle(thread, JSTaggedValue::Undefined()); 2355 JSHandle<EcmaString> fromStr; 2356 while (from < len) { 2357 JSHandle<JSTaggedValue> handledFrom(thread, JSTaggedValue(from)); 2358 fromStr = JSTaggedValue::ToString(thread, handledFrom); 2359 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 2360 key.Update(fromStr.GetTaggedValue()); 2361 kValueHandle.Update(JSSharedArray::FastGetPropertyByValue(thread, thisObjVal, key).GetTaggedValue()); 2362 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 2363 if (JSTaggedValue::SameValueZero(searchElement.GetTaggedValue(), kValueHandle.GetTaggedValue())) { 2364 return GetTaggedBoolean(true); 2365 } 2366 from++; 2367 } 2368 // 11. Return false. 2369 return GetTaggedBoolean(false); 2370} 2371 2372// 23.1.3.1 Array.prototype.at ( index ) 2373JSTaggedValue BuiltinsSharedArray::At(EcmaRuntimeCallInfo *argv) 2374{ 2375 ASSERT(argv); 2376 BUILTINS_API_TRACE(argv->GetThread(), SharedArray, At); 2377 JSThread *thread = argv->GetThread(); 2378 [[maybe_unused]] EcmaHandleScope handleScope(thread); 2379 2380 // 1. Let O be ToObject(this value). 2381 JSHandle<JSTaggedValue> thisHandle = GetThis(argv); 2382 if (!thisHandle->IsJSSharedArray()) { 2383 auto error = ContainerError::BindError(thread, "The at method cannot be bound."); 2384 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 2385 } 2386 [[maybe_unused]] ConcurrentApiScope<JSSharedArray> scope(thread, thisHandle); 2387 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 2388 if (thisHandle->IsStableJSArray(thread)) { 2389 auto opResult = JSStableArray::At(JSHandle<JSSharedArray>::Cast(thisHandle), argv); 2390 return opResult; 2391 } 2392 JSHandle<JSObject> thisObjHandle = JSTaggedValue::ToObject(thread, thisHandle); 2393 // ReturnIfAbrupt(O). 2394 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 2395 JSHandle<JSTaggedValue> thisObjVal(thisObjHandle); 2396 2397 // 2. Let len be ? LengthOfArrayLike(O). 2398 int64_t len = ArrayHelper::GetLength(thread, thisObjVal); 2399 // ReturnIfAbrupt(len). 2400 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 2401 2402 // 3. Let index be ? ToIntegerOrInfinity(index). 2403 JSTaggedNumber index = JSTaggedValue::ToInteger(thread, GetCallArg(argv, 0)); 2404 // ReturnIfAbrupt(index). 2405 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 2406 2407 // 4. If relativeIndex ≥ 0, then 2408 // a. Let k be relativeIndex. 2409 // 5. Else, 2410 // a. Let k be len + relativeIndex. 2411 int64_t relativeIndex = index.GetNumber(); 2412 int64_t k = 0; 2413 if (relativeIndex >= 0) { 2414 k = relativeIndex; 2415 } else { 2416 k = len + relativeIndex; 2417 } 2418 2419 // 6. If k < 0 or k ≥ len, return undefined. 2420 if (k < 0 || k >= len) { 2421 // Return undefined. 2422 return JSTaggedValue::Undefined(); 2423 } 2424 // 7. Return ? Get(O, ! ToString((k))). 2425 JSHandle<JSTaggedValue> element = JSSharedArray::FastGetPropertyByValue(thread, thisObjVal, k); 2426 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 2427 return element.GetTaggedValue(); 2428} 2429 2430// Array.prototype.shrinkTo ( arrayLength ) 2431JSTaggedValue BuiltinsSharedArray::ShrinkTo(EcmaRuntimeCallInfo *argv) 2432{ 2433 ASSERT(argv); 2434 BUILTINS_API_TRACE(argv->GetThread(), SharedArray, ShrinkTo); 2435 JSThread *thread = argv->GetThread(); 2436 [[maybe_unused]] EcmaHandleScope handleScope(thread); 2437 if (argv->GetArgsNumber() != 1) { 2438 auto error = ContainerError::ParamError(thread, "Parameter error.Not enough parameter."); 2439 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 2440 } 2441 JSHandle<JSTaggedValue> thisHandle = GetThis(argv); 2442 if (!thisHandle->IsJSSharedArray()) { 2443 auto error = ContainerError::BindError(thread, "The ShrinkTo method cannot be bound."); 2444 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 2445 } 2446 JSHandle<JSObject> thisObjHandle = JSTaggedValue::ToObject(thread, thisHandle); 2447 [[maybe_unused]] ConcurrentApiScope<JSSharedArray, ModType::WRITE> scope(thread, thisHandle); 2448 JSHandle<JSTaggedValue> newLengthValue = GetCallArg(argv, 0); 2449 if (!newLengthValue->IsNumber()) { 2450 auto error = ContainerError::ParamError(thread, "Parameter error.Invalid array length."); 2451 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 2452 } 2453 auto newLength = JSTaggedValue::ToUint32(thread, newLengthValue); 2454 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 2455 if (JSTaggedNumber(newLengthValue.GetTaggedValue()).GetNumber() != newLength) { 2456 auto error = ContainerError::ParamError(thread, "Parameter error.Invalid array length."); 2457 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 2458 } 2459 int64_t len = ArrayHelper::GetLength(thread, thisHandle); 2460 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 2461 if (newLength >= len) { 2462 return JSTaggedValue::Undefined(); 2463 } 2464 JSSharedArray::LengthSetter(thread, thisObjHandle, newLengthValue, true); 2465 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 2466 return JSTaggedValue::Undefined(); 2467} 2468 2469// Array.prototype.ExtendTo ( arrayLength, initialValue ) 2470JSTaggedValue BuiltinsSharedArray::ExtendTo(EcmaRuntimeCallInfo *argv) 2471{ 2472 ASSERT(argv); 2473 BUILTINS_API_TRACE(argv->GetThread(), SharedArray, ShrinkTo); 2474 JSThread *thread = argv->GetThread(); 2475 [[maybe_unused]] EcmaHandleScope handleScope(thread); 2476 if (argv->GetArgsNumber() < COUNT_LENGTH_AND_INIT) { 2477 auto error = ContainerError::ParamError(thread, "Parameter error.Not enough parameters."); 2478 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 2479 } 2480 JSHandle<JSTaggedValue> thisHandle = GetThis(argv); 2481 if (!thisHandle->IsJSSharedArray()) { 2482 auto error = ContainerError::BindError(thread, "The ExtendTo method cannot be bound."); 2483 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 2484 } 2485 JSHandle<JSObject> thisObjHandle = JSTaggedValue::ToObject(thread, thisHandle); 2486 [[maybe_unused]] ConcurrentApiScope<JSSharedArray, ModType::WRITE> scope(thread, thisHandle); 2487 JSHandle<JSTaggedValue> newLengthValue = GetCallArg(argv, 0); 2488 if (!newLengthValue->IsNumber()) { 2489 auto error = ContainerError::ParamError(thread, "Parameter error.Invalid array length."); 2490 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 2491 } 2492 auto newLength = JSTaggedValue::ToUint32(thread, newLengthValue); 2493 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 2494 if (JSTaggedNumber(newLengthValue.GetTaggedValue()).GetNumber() != newLength) { 2495 auto error = ContainerError::ParamError(thread, "Parameter error.Invalid array length."); 2496 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 2497 } 2498 2499 int64_t length = ArrayHelper::GetLength(thread, thisHandle); 2500 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 2501 if (newLength <= length) { 2502 return JSTaggedValue::Undefined(); 2503 } 2504 2505 JSHandle<JSTaggedValue> initValue = GetCallArg(argv, 1); 2506 if (!initValue->IsSharedType()) { 2507 auto error = ContainerError::ParamError(thread, "Parameter error.Only accept sendable value."); 2508 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 2509 } 2510 JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined()); 2511 for (uint32_t k = static_cast<uint32_t>(length); k < newLength; k++) { 2512 key.Update(JSTaggedValue(k)); 2513 JSObject::CreateDataPropertyOrThrow(thread, thisObjHandle, key, initValue, SCheckMode::SKIP); 2514 } 2515 key.Update(JSTaggedValue(newLength)); 2516 JSSharedArray::LengthSetter(thread, thisObjHandle, key, true); 2517 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 2518 return JSTaggedValue::Undefined(); 2519} 2520 2521JSTaggedValue BuiltinsSharedArray::LastIndexOfSlowPath(EcmaRuntimeCallInfo *argv, JSThread *thread, 2522 const JSHandle<JSTaggedValue> &thisHandle) 2523{ 2524 // 1. Let O be ToObject(this value). 2525 JSHandle<JSObject> thisObjHandle = JSTaggedValue::ToObject(thread, thisHandle); 2526 // 2. ReturnIfAbrupt(O). 2527 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 2528 JSHandle<JSTaggedValue> thisObjVal(thisObjHandle); 2529 // 3. Let len be ToLength(Get(O, "length")). 2530 int64_t length = ArrayHelper::GetLength(thread, thisObjVal); 2531 // 4. ReturnIfAbrupt(len). 2532 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 2533 // 5. If len is 0, return −1. 2534 if (length == 0) { 2535 return JSTaggedValue(-1); 2536 } 2537 // 6. If argument fromIndex was passed let n be ToInteger(fromIndex); else let n be 0. 2538 int64_t fromIndex = ArrayHelper::GetLastStartIndexFromArgs(thread, argv, 1, length); 2539 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 2540 return LastIndexOfSlowPath(argv, thread, thisObjVal, fromIndex); 2541} 2542 2543JSTaggedValue BuiltinsSharedArray::LastIndexOfSlowPath(EcmaRuntimeCallInfo *argv, JSThread *thread, 2544 const JSHandle<JSTaggedValue> &thisObjVal, int64_t fromIndex) 2545{ 2546 if (fromIndex < 0) { 2547 return JSTaggedValue(-1); 2548 } 2549 JSMutableHandle<JSTaggedValue> keyHandle(thread, JSTaggedValue::Undefined()); 2550 JSHandle<JSTaggedValue> target = base::BuiltinsBase::GetCallArg(argv, 0); 2551 // 11. Repeat, while k < len 2552 for (int64_t curIndex = fromIndex; curIndex >= 0; --curIndex) { 2553 keyHandle.Update(JSTaggedValue(curIndex)); 2554 bool found = ArrayHelper::ElementIsStrictEqualTo(thread, thisObjVal, keyHandle, target); 2555 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 2556 if (UNLIKELY(found)) { 2557 return JSTaggedValue(curIndex); 2558 } 2559 } 2560 // 12. Return -1. 2561 return JSTaggedValue(-1); 2562} 2563 2564// Array.prototype.lastIndexOf ( searchElement [ , fromIndex ] ) 2565JSTaggedValue BuiltinsSharedArray::LastIndexOf(EcmaRuntimeCallInfo *argv) 2566{ 2567 ASSERT(argv); 2568 JSThread *thread = argv->GetThread(); 2569 BUILTINS_API_TRACE(thread, SharedArray, LastIndexOf); 2570 [[maybe_unused]] EcmaHandleScope handleScope(thread); 2571 2572 JSHandle<JSTaggedValue> thisHandle = GetThis(argv); 2573 if (UNLIKELY(!thisHandle->IsJSSharedArray())) { 2574 auto error = ContainerError::BindError(thread, "The lastIndexOf method cannot be bound."); 2575 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 2576 } 2577 [[maybe_unused]] ConcurrentApiScope<JSSharedArray> scope(thread, thisHandle); 2578 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 2579 2580 if (thisHandle->IsStableJSArray(thread)) { 2581 auto error = ContainerError::BindError(thread, "The lastIndexOf method not support stable array."); 2582 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 2583 } 2584 return LastIndexOfSlowPath(argv, thread, thisHandle); 2585} 2586 2587} // namespace panda::ecmascript::builtins 2588