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