1/* 2 * Copyright (c) 2022 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/containers/containers_plainarray.h" 17 18#include "ecmascript/containers/containers_errors.h" 19#include "ecmascript/js_api/js_api_plain_array.h" 20#include "ecmascript/js_iterator.h" 21 22namespace panda::ecmascript::containers { 23JSTaggedValue ContainersPlainArray::PlainArrayConstructor(EcmaRuntimeCallInfo *argv) 24{ 25 ASSERT(argv != nullptr); 26 JSThread *thread = argv->GetThread(); 27 BUILTINS_API_TRACE(thread, PlainArray, Constructor); 28 [[maybe_unused]] EcmaHandleScope handleScope(thread); 29 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 30 JSHandle<JSTaggedValue> newTarget = GetNewTarget(argv); 31 if (newTarget->IsUndefined()) { 32 JSTaggedValue error = 33 ContainerError::BusinessError(thread, ErrorFlag::IS_NULL_ERROR, 34 "The PlainArray's constructor cannot be directly invoked"); 35 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 36 } 37 JSHandle<JSTaggedValue> constructor = GetConstructor(argv); 38 JSHandle<JSObject> obj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(constructor), newTarget); 39 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 40 JSHandle<JSAPIPlainArray> plainArray = JSHandle<JSAPIPlainArray>::Cast(obj); 41 JSHandle<TaggedArray> keys = 42 JSAPIPlainArray::CreateSlot(thread, JSAPIPlainArray::DEFAULT_CAPACITY_LENGTH); 43 JSHandle<TaggedArray> values = 44 JSAPIPlainArray::CreateSlot(thread, JSAPIPlainArray::DEFAULT_CAPACITY_LENGTH); 45 plainArray->SetKeys(thread, keys); 46 plainArray->SetValues(thread, values); 47 return obj.GetTaggedValue(); 48} 49 50JSTaggedValue ContainersPlainArray::Add(EcmaRuntimeCallInfo *argv) 51{ 52 ASSERT(argv != nullptr); 53 JSThread *thread = argv->GetThread(); 54 BUILTINS_API_TRACE(thread, PlainArray, Add); 55 [[maybe_unused]] EcmaHandleScope handleScope(thread); 56 JSHandle<JSTaggedValue> self = GetThis(argv); 57 if (!self->IsJSAPIPlainArray()) { 58 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIPlainArray()) { 59 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget()); 60 } else { 61 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR, 62 "The add method cannot be bound"); 63 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 64 } 65 } 66 JSHandle<JSTaggedValue> key(GetCallArg(argv, 0)); 67 JSHandle<JSTaggedValue> value(GetCallArg(argv, 1)); 68 if (key->IsDouble()) { 69 key = JSHandle<JSTaggedValue>(thread, JSTaggedValue::TryCastDoubleToInt32(key->GetDouble())); 70 } 71 if (!key->IsInt()) { 72 JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, key.GetTaggedValue()); 73 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 74 CString errorMsg = 75 "The type of \"key\" must be small integer. Received value is: " + ConvertToString(*result); 76 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str()); 77 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 78 } 79 JSAPIPlainArray::Add(thread, JSHandle<JSAPIPlainArray>::Cast(self), key, value); 80 return JSTaggedValue::Undefined(); 81} 82 83JSTaggedValue ContainersPlainArray::Clear(EcmaRuntimeCallInfo *argv) 84{ 85 ASSERT(argv != nullptr); 86 JSThread *thread = argv->GetThread(); 87 BUILTINS_API_TRACE(thread, PlainArray, Clear); 88 [[maybe_unused]] EcmaHandleScope handleScope(thread); 89 JSHandle<JSTaggedValue> self = GetThis(argv); 90 if (!self->IsJSAPIPlainArray()) { 91 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIPlainArray()) { 92 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget()); 93 } else { 94 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR, 95 "The clear method cannot be bound"); 96 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 97 } 98 } 99 JSAPIPlainArray *array = JSAPIPlainArray::Cast(self->GetTaggedObject()); 100 array->Clear(thread); 101 return JSTaggedValue::Undefined(); 102} 103 104JSTaggedValue ContainersPlainArray::Clone(EcmaRuntimeCallInfo *argv) 105{ 106 ASSERT(argv != nullptr); 107 JSThread *thread = argv->GetThread(); 108 BUILTINS_API_TRACE(thread, PlainArray, Clone); 109 [[maybe_unused]] EcmaHandleScope handleScope(thread); 110 JSHandle<JSTaggedValue> self = GetThis(argv); 111 if (!self->IsJSAPIPlainArray()) { 112 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIPlainArray()) { 113 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget()); 114 } else { 115 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR, 116 "The clone method cannot be bound"); 117 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 118 } 119 } 120 JSHandle<JSAPIPlainArray> newPlainArray = 121 JSAPIPlainArray::Clone(thread, JSHandle<JSAPIPlainArray>::Cast(self)); 122 return newPlainArray.GetTaggedValue(); 123} 124 125JSTaggedValue ContainersPlainArray::Has(EcmaRuntimeCallInfo *argv) 126{ 127 ASSERT(argv != nullptr); 128 JSThread *thread = argv->GetThread(); 129 BUILTINS_API_TRACE(thread, PlainArray, Has); 130 [[maybe_unused]] EcmaHandleScope handleScope(thread); 131 JSHandle<JSTaggedValue> self = GetThis(argv); 132 if (!self->IsJSAPIPlainArray()) { 133 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIPlainArray()) { 134 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget()); 135 } else { 136 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR, 137 "The has method cannot be bound"); 138 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 139 } 140 } 141 JSHandle<JSTaggedValue> value(GetCallArg(argv, 0)); 142 if (value->IsDouble()) { 143 value = JSHandle<JSTaggedValue>(thread, JSTaggedValue::TryCastDoubleToInt32(value->GetDouble())); 144 } 145 if (!value->IsInt()) { 146 JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, value.GetTaggedValue()); 147 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 148 CString errorMsg = 149 "The type of \"key\" must be small integer. Received value is: " + ConvertToString(*result); 150 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str()); 151 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 152 } 153 JSAPIPlainArray *array = JSAPIPlainArray::Cast(self->GetTaggedObject()); 154 int32_t key = value->GetNumber(); 155 bool result = array->Has(key); 156 return JSTaggedValue(result); 157} 158 159JSTaggedValue ContainersPlainArray::Get(EcmaRuntimeCallInfo *argv) 160{ 161 ASSERT(argv != nullptr); 162 JSThread *thread = argv->GetThread(); 163 BUILTINS_API_TRACE(thread, PlainArray, Get); 164 [[maybe_unused]] EcmaHandleScope handleScope(thread); 165 JSHandle<JSTaggedValue> self = GetThis(argv); 166 if (!self->IsJSAPIPlainArray()) { 167 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIPlainArray()) { 168 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget()); 169 } else { 170 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR, 171 "The get method cannot be bound"); 172 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 173 } 174 } 175 JSHandle<JSTaggedValue> key(GetCallArg(argv, 0)); 176 if (key->IsDouble()) { 177 key = JSHandle<JSTaggedValue>(thread, JSTaggedValue::TryCastDoubleToInt32(key->GetDouble())); 178 } 179 if (!key->IsInt()) { 180 JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, key.GetTaggedValue()); 181 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 182 CString errorMsg = 183 "The type of \"key\" must be small integer. Received value is: " + ConvertToString(*result); 184 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str()); 185 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 186 } 187 JSAPIPlainArray *array = JSAPIPlainArray::Cast(self->GetTaggedObject()); 188 JSTaggedValue value = array->Get(key.GetTaggedValue()); 189 190 return value; 191} 192 193JSTaggedValue ContainersPlainArray::GetIteratorObj(EcmaRuntimeCallInfo *argv) 194{ 195 ASSERT(argv != nullptr); 196 JSThread *thread = argv->GetThread(); 197 BUILTINS_API_TRACE(thread, PlainArray, GetIteratorObj); 198 [[maybe_unused]] EcmaHandleScope handleScope(thread); 199 JSHandle<JSTaggedValue> self = GetThis(argv); 200 if (!self->IsJSAPIPlainArray()) { 201 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIPlainArray()) { 202 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget()); 203 } else { 204 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR, 205 "The Symbol.iterator method cannot be bound"); 206 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 207 } 208 } 209 JSHandle<JSTaggedValue> iter = 210 JSAPIPlainArray::GetIteratorObj(thread, JSHandle<JSAPIPlainArray>::Cast(self), IterationKind::KEY_AND_VALUE); 211 return iter.GetTaggedValue(); 212} 213 214JSTaggedValue ContainersPlainArray::ForEach(EcmaRuntimeCallInfo *argv) 215{ 216 ASSERT(argv != nullptr); 217 JSThread *thread = argv->GetThread(); 218 BUILTINS_API_TRACE(thread, PlainArray, ForEach); 219 JSHandle<JSTaggedValue> thisHandle = GetThis(argv); 220 if (!thisHandle->IsJSAPIPlainArray()) { 221 if (thisHandle->IsJSProxy() && JSHandle<JSProxy>::Cast(thisHandle)->GetTarget().IsJSAPIPlainArray()) { 222 thisHandle = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(thisHandle)->GetTarget()); 223 } else { 224 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR, 225 "The forEach method cannot be bound"); 226 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 227 } 228 } 229 JSHandle<JSTaggedValue> callbackFnHandle = GetCallArg(argv, 0); 230 if (!callbackFnHandle->IsCallable()) { 231 JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, callbackFnHandle.GetTaggedValue()); 232 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 233 CString errorMsg = 234 "The type of \"callbackfn\" must be callable. Received value is: " + ConvertToString(*result); 235 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str()); 236 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 237 } 238 JSHandle<JSTaggedValue> thisArgHandle = GetCallArg(argv, 1); 239 return JSAPIPlainArray::ForEach(thread, thisHandle, callbackFnHandle, thisArgHandle); 240} 241 242JSTaggedValue ContainersPlainArray::ToString(EcmaRuntimeCallInfo *argv) 243{ 244 ASSERT(argv != nullptr); 245 JSThread *thread = argv->GetThread(); 246 BUILTINS_API_TRACE(thread, PlainArray, ToString); 247 JSHandle<JSTaggedValue> self = GetThis(argv); 248 if (!self->IsJSAPIPlainArray()) { 249 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIPlainArray()) { 250 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget()); 251 } else { 252 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR, 253 "The toString method cannot be bound"); 254 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 255 } 256 } 257 JSTaggedValue value = JSAPIPlainArray::ToString(thread, JSHandle<JSAPIPlainArray>::Cast(self)); 258 return value; 259} 260 261JSTaggedValue ContainersPlainArray::GetIndexOfKey(EcmaRuntimeCallInfo *argv) 262{ 263 ASSERT(argv != nullptr); 264 JSThread *thread = argv->GetThread(); 265 BUILTINS_API_TRACE(thread, PlainArray, GetIndexOfKey); 266 JSHandle<JSTaggedValue> self = GetThis(argv); 267 if (!self->IsJSAPIPlainArray()) { 268 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIPlainArray()) { 269 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget()); 270 } else { 271 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR, 272 "The getIndexOfKey method cannot be bound"); 273 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 274 } 275 } 276 JSHandle<JSTaggedValue> value(GetCallArg(argv, 0)); 277 if (value->IsDouble()) { 278 value = JSHandle<JSTaggedValue>(thread, JSTaggedValue::TryCastDoubleToInt32(value->GetDouble())); 279 } 280 if (!value->IsInt()) { 281 JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, value.GetTaggedValue()); 282 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 283 CString errorMsg = 284 "The type of \"key\" must be small integer. Received value is: " + ConvertToString(*result); 285 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str()); 286 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 287 } 288 JSAPIPlainArray *array = JSAPIPlainArray::Cast(self->GetTaggedObject()); 289 int32_t key = value->GetNumber(); 290 JSTaggedValue result = array->GetIndexOfKey(key); 291 return result; 292} 293 294JSTaggedValue ContainersPlainArray::GetIndexOfValue(EcmaRuntimeCallInfo *argv) 295{ 296 ASSERT(argv != nullptr); 297 JSThread *thread = argv->GetThread(); 298 BUILTINS_API_TRACE(thread, PlainArray, GetIndexOfValue); 299 JSHandle<JSTaggedValue> self = GetThis(argv); 300 if (!self->IsJSAPIPlainArray()) { 301 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIPlainArray()) { 302 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget()); 303 } else { 304 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR, 305 "The getIndexOfValue method cannot be bound"); 306 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 307 } 308 } 309 JSAPIPlainArray *array = JSAPIPlainArray::Cast(self->GetTaggedObject()); 310 JSHandle<JSTaggedValue> value(GetCallArg(argv, 0)); 311 JSTaggedValue jsValue = array->GetIndexOfValue(value.GetTaggedValue()); 312 return jsValue; 313} 314 315JSTaggedValue ContainersPlainArray::IsEmpty(EcmaRuntimeCallInfo *argv) 316{ 317 ASSERT(argv != nullptr); 318 JSThread *thread = argv->GetThread(); 319 BUILTINS_API_TRACE(thread, PlainArray, IsEmpty); 320 JSHandle<JSTaggedValue> self = GetThis(argv); 321 if (!self->IsJSAPIPlainArray()) { 322 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIPlainArray()) { 323 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget()); 324 } else { 325 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR, 326 "The isEmpty method cannot be bound"); 327 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 328 } 329 } 330 JSAPIPlainArray *array = JSAPIPlainArray::Cast(self->GetTaggedObject()); 331 bool ret = array->IsEmpty(); 332 return JSTaggedValue(ret); 333} 334 335JSTaggedValue ContainersPlainArray::GetKeyAt(EcmaRuntimeCallInfo *argv) 336{ 337 ASSERT(argv != nullptr); 338 JSThread *thread = argv->GetThread(); 339 BUILTINS_API_TRACE(thread, PlainArray, GetKeyAt); 340 JSHandle<JSTaggedValue> self = GetThis(argv); 341 if (!self->IsJSAPIPlainArray()) { 342 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIPlainArray()) { 343 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget()); 344 } else { 345 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR, 346 "The getKeyAt method cannot be bound"); 347 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 348 } 349 } 350 JSHandle<JSTaggedValue> value(GetCallArg(argv, 0)); 351 if (value->IsDouble()) { 352 value = JSHandle<JSTaggedValue>(thread, JSTaggedValue::TryCastDoubleToInt32(value->GetDouble())); 353 } 354 if (!value->IsInt()) { 355 JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, value.GetTaggedValue()); 356 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 357 CString errorMsg = 358 "The type of \"index\" must be small integer. Received value is: " + ConvertToString(*result); 359 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str()); 360 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 361 } 362 JSAPIPlainArray *array = JSAPIPlainArray::Cast(self->GetTaggedObject()); 363 int32_t index = value->GetNumber(); 364 JSTaggedValue result = array->GetKeyAt(index); 365 return result; 366} 367 368JSTaggedValue ContainersPlainArray::Remove(EcmaRuntimeCallInfo *argv) 369{ 370 ASSERT(argv != nullptr); 371 JSThread *thread = argv->GetThread(); 372 BUILTINS_API_TRACE(thread, PlainArray, Remove); 373 JSHandle<JSTaggedValue> self = GetThis(argv); 374 if (!self->IsJSAPIPlainArray()) { 375 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIPlainArray()) { 376 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget()); 377 } else { 378 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR, 379 "The remove method cannot be bound"); 380 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 381 } 382 } 383 JSHandle<JSTaggedValue> key(GetCallArg(argv, 0)); 384 if (key->IsDouble()) { 385 key = JSHandle<JSTaggedValue>(thread, JSTaggedValue::TryCastDoubleToInt32(key->GetDouble())); 386 } 387 if (!key->IsInt()) { 388 JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, key.GetTaggedValue()); 389 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 390 CString errorMsg = 391 "The type of \"key\" must be small integer. Received value is: " + ConvertToString(*result); 392 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str()); 393 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 394 } 395 JSAPIPlainArray *array = JSAPIPlainArray::Cast(self->GetTaggedObject()); 396 JSTaggedValue value = array->Remove(thread, key.GetTaggedValue()); 397 return value; 398} 399 400JSTaggedValue ContainersPlainArray::RemoveAt(EcmaRuntimeCallInfo *argv) 401{ 402 ASSERT(argv != nullptr); 403 JSThread *thread = argv->GetThread(); 404 BUILTINS_API_TRACE(thread, PlainArray, RemoveAt); 405 JSHandle<JSTaggedValue> self = GetThis(argv); 406 if (!self->IsJSAPIPlainArray()) { 407 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIPlainArray()) { 408 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget()); 409 } else { 410 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR, 411 "The removeAt method cannot be bound"); 412 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 413 } 414 } 415 JSHandle<JSTaggedValue> index(GetCallArg(argv, 0)); 416 if (index->IsDouble()) { 417 index = JSHandle<JSTaggedValue>(thread, JSTaggedValue::TryCastDoubleToInt32(index->GetDouble())); 418 } 419 if (!index->IsInt()) { 420 JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, index.GetTaggedValue()); 421 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 422 CString errorMsg = 423 "The type of \"index\" must be small integer. Received value is: " + ConvertToString(*result); 424 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str()); 425 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 426 } 427 JSAPIPlainArray *array = JSAPIPlainArray::Cast(self->GetTaggedObject()); 428 JSTaggedValue value = array->RemoveAt(thread, index.GetTaggedValue()); 429 return value; 430} 431 432JSTaggedValue ContainersPlainArray::RemoveRangeFrom(EcmaRuntimeCallInfo *argv) 433{ 434 ASSERT(argv != nullptr); 435 JSThread *thread = argv->GetThread(); 436 BUILTINS_API_TRACE(thread, PlainArray, RemoveRangeFrom); 437 JSHandle<JSTaggedValue> self = GetThis(argv); 438 if (!self->IsJSAPIPlainArray()) { 439 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIPlainArray()) { 440 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget()); 441 } else { 442 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR, 443 "The removeRangeFrom method cannot be bound"); 444 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 445 } 446 } 447 JSHandle<JSTaggedValue> valueIndex(GetCallArg(argv, 0)); 448 JSHandle<JSTaggedValue> valueSize(GetCallArg(argv, 1)); 449 if (valueIndex->IsDouble()) { 450 valueIndex = JSHandle<JSTaggedValue>(thread, JSTaggedValue::TryCastDoubleToInt32(valueIndex->GetDouble())); 451 } 452 if (valueSize->IsDouble()) { 453 valueSize = JSHandle<JSTaggedValue>(thread, JSTaggedValue::TryCastDoubleToInt32(valueSize->GetDouble())); 454 } 455 if (!valueIndex->IsInt()) { 456 JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, valueIndex.GetTaggedValue()); 457 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 458 CString errorMsg = 459 "The type of \"index\" must be small integer. Received value is: " + ConvertToString(*result); 460 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str()); 461 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 462 } 463 if (!valueSize->IsInt()) { 464 JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, valueSize.GetTaggedValue()); 465 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 466 CString errorMsg = 467 "The type of \"size\" must be small integer. Received value is: " + ConvertToString(*result); 468 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str()); 469 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 470 } 471 int32_t index = valueIndex->GetNumber(); 472 int32_t size = valueSize->GetNumber(); 473 JSAPIPlainArray *array = JSAPIPlainArray::Cast(self->GetTaggedObject()); 474 JSTaggedValue value = array->RemoveRangeFrom(thread, index, size); 475 return value; 476} 477 478JSTaggedValue ContainersPlainArray::SetValueAt(EcmaRuntimeCallInfo *argv) 479{ 480 ASSERT(argv != nullptr); 481 JSThread *thread = argv->GetThread(); 482 BUILTINS_API_TRACE(thread, PlainArray, SetValueAt); 483 [[maybe_unused]] EcmaHandleScope handleScope(thread); 484 JSHandle<JSTaggedValue> self = GetThis(argv); 485 if (!self->IsJSAPIPlainArray()) { 486 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIPlainArray()) { 487 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget()); 488 } else { 489 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR, 490 "The setValueAt method cannot be bound"); 491 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 492 } 493 } 494 JSHandle<JSTaggedValue> index(GetCallArg(argv, 0)); 495 JSHandle<JSTaggedValue> value(GetCallArg(argv, 1)); 496 if (index->IsDouble()) { 497 index = JSHandle<JSTaggedValue>(thread, JSTaggedValue::TryCastDoubleToInt32(index->GetDouble())); 498 } 499 if (!index->IsInt()) { 500 JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, index.GetTaggedValue()); 501 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 502 CString errorMsg = 503 "The type of \"index\" must be small integer. Received value is: " + ConvertToString(*result); 504 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str()); 505 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 506 } 507 JSAPIPlainArray *array = JSAPIPlainArray::Cast(self->GetTaggedObject()); 508 array->SetValueAt(thread, index.GetTaggedValue(), value.GetTaggedValue()); 509 return JSTaggedValue::Undefined(); 510} 511 512JSTaggedValue ContainersPlainArray::GetValueAt(EcmaRuntimeCallInfo *argv) 513{ 514 ASSERT(argv != nullptr); 515 JSThread *thread = argv->GetThread(); 516 BUILTINS_API_TRACE(thread, PlainArray, GetValueAt); 517 [[maybe_unused]] EcmaHandleScope handleScope(thread); 518 JSHandle<JSTaggedValue> self = GetThis(argv); 519 if (!self->IsJSAPIPlainArray()) { 520 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIPlainArray()) { 521 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget()); 522 } else { 523 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR, 524 "The getValueAt method cannot be bound"); 525 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 526 } 527 } 528 JSHandle<JSTaggedValue> idx(GetCallArg(argv, 0)); 529 if (idx->IsDouble()) { 530 idx = JSHandle<JSTaggedValue>(thread, JSTaggedValue::TryCastDoubleToInt32(idx->GetDouble())); 531 } 532 if (!idx->IsInt()) { 533 JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, idx.GetTaggedValue()); 534 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 535 CString errorMsg = 536 "The type of \"index\" must be small integer. Received value is: " + ConvertToString(*result); 537 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str()); 538 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 539 } 540 JSAPIPlainArray *array = JSAPIPlainArray::Cast(self->GetTaggedObject()); 541 int32_t index = idx->GetNumber(); 542 JSTaggedValue value = array->GetValueAt(thread, index); 543 return value; 544} 545 546JSTaggedValue ContainersPlainArray::GetSize(EcmaRuntimeCallInfo *argv) 547{ 548 ASSERT(argv != nullptr); 549 JSThread *thread = argv->GetThread(); 550 BUILTINS_API_TRACE(thread, PlainArray, GetSize); 551 JSHandle<JSTaggedValue> self = GetThis(argv); 552 if (!self->IsJSAPIPlainArray()) { 553 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIPlainArray()) { 554 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget()); 555 } else { 556 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR, 557 "The getLength method cannot be bound"); 558 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 559 } 560 } 561 uint32_t length = JSHandle<JSAPIPlainArray>::Cast(self)->GetSize(); 562 return JSTaggedValue(length); 563} 564} // namespace panda::ecmascript::containers 565