/* * Copyright (c) 2022 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "ecmascript/containers/containers_lightweightset.h" #include "ecmascript/containers/containers_errors.h" #include "ecmascript/js_api/js_api_lightweightset.h" #include "ecmascript/js_api/js_api_lightweightset_iterator.h" #include "ecmascript/js_array.h" namespace panda::ecmascript::containers { JSTaggedValue ContainersLightWeightSet::LightWeightSetConstructor(EcmaRuntimeCallInfo *argv) { ASSERT(argv != nullptr); JSThread *thread = argv->GetThread(); BUILTINS_API_TRACE(thread, LightWeightSet, Constructor); [[maybe_unused]] EcmaHandleScope handleScope(thread); ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle newTarget = GetNewTarget(argv); if (newTarget->IsUndefined()) { JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::IS_NULL_ERROR, "The LightWeightSet's constructor cannot be directly invoked"); THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); } JSHandle constructor = GetConstructor(argv); JSHandle obj = factory->NewJSObjectByConstructor(JSHandle(constructor), newTarget); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); JSHandle lightweightSet = JSHandle::Cast(obj); JSHandle hashes = JSAPILightWeightSet::CreateSlot(thread, JSAPILightWeightSet::DEFAULT_CAPACITY_LENGTH); JSHandle values = JSAPILightWeightSet::CreateSlot(thread, JSAPILightWeightSet::DEFAULT_CAPACITY_LENGTH); lightweightSet->SetHashes(thread, hashes); lightweightSet->SetValues(thread, values); return obj.GetTaggedValue(); } JSTaggedValue ContainersLightWeightSet::Add(EcmaRuntimeCallInfo *argv) { ASSERT(argv != nullptr); JSThread *thread = argv->GetThread(); BUILTINS_API_TRACE(thread, LightWeightSet, Add); [[maybe_unused]] EcmaHandleScope handleScope(thread); JSHandle self = GetThis(argv); if (!self->IsJSAPILightWeightSet()) { if (self->IsJSProxy() && JSHandle::Cast(self)->GetTarget(thread).IsJSAPILightWeightSet()) { self = JSHandle(thread, JSHandle::Cast(self)->GetTarget(thread)); } else { JSTaggedValue error = ContainerError::BusinessError(thread, BIND_ERROR, "The add method cannot be bound"); THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); } } JSHandle value(GetCallArg(argv, 0)); bool flag = JSAPILightWeightSet::Add(thread, JSHandle::Cast(self), value); return JSTaggedValue(flag); } JSTaggedValue ContainersLightWeightSet::AddAll(EcmaRuntimeCallInfo *argv) { ASSERT(argv != nullptr); JSThread *thread = argv->GetThread(); BUILTINS_API_TRACE(thread, LightWeightSet, AddAll); [[maybe_unused]] EcmaHandleScope handleScope(thread); JSHandle self = GetThis(argv); if (!self->IsJSAPILightWeightSet()) { if (self->IsJSProxy() && JSHandle::Cast(self)->GetTarget(thread).IsJSAPILightWeightSet()) { self = JSHandle(thread, JSHandle::Cast(self)->GetTarget(thread)); } else { JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR, "The addAll method cannot be bound"); THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); } } JSHandle value(GetCallArg(argv, 0)); if (!value->IsJSAPILightWeightSet()) { if (value->IsJSProxy() && JSHandle::Cast(value)->GetTarget(thread).IsJSAPILightWeightSet()) { value = JSHandle(thread, JSHandle::Cast(value)->GetTarget(thread)); } else { JSHandle result = JSTaggedValue::ToString(thread, value.GetTaggedValue()); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); CString errorMsg = "The type of \"set\" must be LightWeightSet. Received value is: " + ConvertToString(thread, *result); JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str()); THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); } } return JSTaggedValue(JSAPILightWeightSet::AddAll(thread, JSHandle::Cast(self), value)); } JSTaggedValue ContainersLightWeightSet::IsEmpty(EcmaRuntimeCallInfo *argv) { ASSERT(argv != nullptr); JSThread *thread = argv->GetThread(); BUILTINS_API_TRACE(thread, LightWeightSet, IsEmpty); [[maybe_unused]] EcmaHandleScope handleScope(thread); JSHandle self = GetThis(argv); if (!self->IsJSAPILightWeightSet()) { if (self->IsJSProxy() && JSHandle::Cast(self)->GetTarget(thread).IsJSAPILightWeightSet()) { self = JSHandle(thread, JSHandle::Cast(self)->GetTarget(thread)); } else { JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR, "The isEmpty method cannot be bound"); THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); } } JSAPILightWeightSet *set = JSAPILightWeightSet::Cast(self->GetTaggedObject()); return JSTaggedValue(set->IsEmpty()); } JSTaggedValue ContainersLightWeightSet::GetValueAt(EcmaRuntimeCallInfo *argv) { ASSERT(argv != nullptr); JSThread *thread = argv->GetThread(); BUILTINS_API_TRACE(thread, LightWeightSet, GetValueAt); [[maybe_unused]] EcmaHandleScope handleScope(thread); JSHandle self = GetThis(argv); if (!self->IsJSAPILightWeightSet()) { if (self->IsJSProxy() && JSHandle::Cast(self)->GetTarget(thread).IsJSAPILightWeightSet()) { self = JSHandle(thread, JSHandle::Cast(self)->GetTarget(thread)); } else { JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR, "The getValueAt method cannot be bound"); THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); } } JSHandle value(GetCallArg(argv, 0)); if (value->IsDouble()) { value = JSHandle(thread, JSTaggedValue::TryCastDoubleToInt32(value->GetDouble())); } if (!value->IsInt()) { JSHandle result = JSTaggedValue::ToString(thread, value.GetTaggedValue()); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); CString errorMsg = "The type of \"index\" must be small integer. Received value is: " + ConvertToString(thread, *result); JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str()); THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); } JSAPILightWeightSet *set = JSAPILightWeightSet::Cast(self->GetTaggedObject()); return set->GetValueAt(thread, value->GetInt()); } JSTaggedValue ContainersLightWeightSet::HasAll(EcmaRuntimeCallInfo *argv) { ASSERT(argv != nullptr); JSThread *thread = argv->GetThread(); BUILTINS_API_TRACE(thread, LightWeightSet, HasAll); [[maybe_unused]] EcmaHandleScope handleScope(thread); JSHandle self = GetThis(argv); if (!self->IsJSAPILightWeightSet()) { if (self->IsJSProxy() && JSHandle::Cast(self)->GetTarget(thread).IsJSAPILightWeightSet()) { self = JSHandle(thread, JSHandle::Cast(self)->GetTarget(thread)); } else { JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR, "The hasAll method cannot be bound"); THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); } } JSHandle value(GetCallArg(argv, 0)); if (!value->IsJSAPILightWeightSet()) { if (value->IsJSProxy() && JSHandle::Cast(value)->GetTarget(thread).IsJSAPILightWeightSet()) { value = JSHandle(thread, JSHandle::Cast(value)->GetTarget(thread)); } else { JSHandle result = JSTaggedValue::ToString(thread, value.GetTaggedValue()); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); CString errorMsg = "The type of \"set\" must be LightWeightSet. Received value is: " + ConvertToString(thread, *result); JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str()); THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); } } JSAPILightWeightSet *set = JSAPILightWeightSet::Cast(self->GetTaggedObject()); return JSTaggedValue(set->HasAll(thread, value)); } JSTaggedValue ContainersLightWeightSet::Has(EcmaRuntimeCallInfo *argv) { ASSERT(argv != nullptr); JSThread *thread = argv->GetThread(); BUILTINS_API_TRACE(thread, LightWeightSet, Has); [[maybe_unused]] EcmaHandleScope handleScope(thread); JSHandle self = GetThis(argv); if (!self->IsJSAPILightWeightSet()) { if (self->IsJSProxy() && JSHandle::Cast(self)->GetTarget(thread).IsJSAPILightWeightSet()) { self = JSHandle(thread, JSHandle::Cast(self)->GetTarget(thread)); } else { JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR, "The has method cannot be bound"); THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); } } JSHandle value(GetCallArg(argv, 0)); JSAPILightWeightSet *set = JSAPILightWeightSet::Cast(self->GetTaggedObject()); return JSTaggedValue(set->Has(thread, value)); } JSTaggedValue ContainersLightWeightSet::HasHash(EcmaRuntimeCallInfo *argv) { ASSERT(argv != nullptr); JSThread *thread = argv->GetThread(); BUILTINS_API_TRACE(thread, LightWeightSet, HasHash); [[maybe_unused]] EcmaHandleScope handleScope(thread); JSHandle self = GetThis(argv); if (!self->IsJSAPILightWeightSet()) { if (self->IsJSProxy() && JSHandle::Cast(self)->GetTarget(thread).IsJSAPILightWeightSet()) { self = JSHandle(thread, JSHandle::Cast(self)->GetTarget(thread)); } else { JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR, "The hasHash method cannot be bound"); THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); } } JSHandle value(GetCallArg(argv, 0)); JSAPILightWeightSet *set = JSAPILightWeightSet::Cast(self->GetTaggedObject()); return JSTaggedValue(set->HasHash(thread, value)); } JSTaggedValue ContainersLightWeightSet::Equal(EcmaRuntimeCallInfo *argv) { ASSERT(argv != nullptr); JSThread *thread = argv->GetThread(); BUILTINS_API_TRACE(thread, LightWeightSet, Equal); [[maybe_unused]] EcmaHandleScope handleScope(thread); JSHandle self = GetThis(argv); if (!self->IsJSAPILightWeightSet()) { if (self->IsJSProxy() && JSHandle::Cast(self)->GetTarget(thread).IsJSAPILightWeightSet()) { self = JSHandle(thread, JSHandle::Cast(self)->GetTarget(thread)); } else { JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR, "The equal method cannot be bound"); THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); } } JSHandle value(GetCallArg(argv, 0)); return JSTaggedValue(JSAPILightWeightSet::Equal(thread, JSHandle::Cast(self), value)); } JSTaggedValue ContainersLightWeightSet::IncreaseCapacityTo(EcmaRuntimeCallInfo *argv) { ASSERT(argv != nullptr); JSThread *thread = argv->GetThread(); BUILTINS_API_TRACE(thread, LightWeightSet, IncreaseCapacityTo); [[maybe_unused]] EcmaHandleScope handleScope(thread); JSHandle self = GetThis(argv); if (!self->IsJSAPILightWeightSet()) { if (self->IsJSProxy() && JSHandle::Cast(self)->GetTarget(thread).IsJSAPILightWeightSet()) { self = JSHandle(thread, JSHandle::Cast(self)->GetTarget(thread)); } else { JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR, "The increaseCapacityTo method cannot be bound"); THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); } } JSHandle value(GetCallArg(argv, 0)); // for case like Math.foor(1.3), it gives double 1.0; if (value->IsDouble()) { value = JSHandle(thread, JSTaggedValue::TryCastDoubleToInt32(value->GetDouble())); } if (!value->IsInt()) { JSHandle result = JSTaggedValue::ToString(thread, value.GetTaggedValue()); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); CString errorMsg = "The type of \"minimumCapacity\" must be small integer. Received value is: " + ConvertToString(thread, *result); JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str()); THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); } int32_t minCapacity = value->GetInt(); JSAPILightWeightSet::IncreaseCapacityTo(thread, JSHandle::Cast(self), minCapacity); RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::False()); return JSTaggedValue::Undefined(); } JSTaggedValue ContainersLightWeightSet::GetIteratorObj(EcmaRuntimeCallInfo *argv) { ASSERT(argv != nullptr); JSThread *thread = argv->GetThread(); BUILTINS_API_TRACE(thread, LightWeightSet, GetIteratorObj); [[maybe_unused]] EcmaHandleScope handleScope(thread); JSHandle self = GetThis(argv); if (!self->IsJSAPILightWeightSet()) { if (self->IsJSProxy() && JSHandle::Cast(self)->GetTarget(thread).IsJSAPILightWeightSet()) { self = JSHandle(thread, JSHandle::Cast(self)->GetTarget(thread)); } else { JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR, "The Symbol.iterator method cannot be bound"); THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); } } JSHandle iter = JSAPILightWeightSet::GetIteratorObj(thread, JSHandle::Cast(self), IterationKind::VALUE); return iter.GetTaggedValue(); } JSTaggedValue ContainersLightWeightSet::Values(EcmaRuntimeCallInfo *argv) { ASSERT(argv != nullptr); JSThread *thread = argv->GetThread(); BUILTINS_API_TRACE(thread, LightWeightSet, Values); [[maybe_unused]] EcmaHandleScope handleScope(thread); JSHandle self = GetThis(argv); if (!self->IsJSAPILightWeightSet()) { if (self->IsJSProxy() && JSHandle::Cast(self)->GetTarget(thread).IsJSAPILightWeightSet()) { self = JSHandle(thread, JSHandle::Cast(self)->GetTarget(thread)); } else { JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR, "The values method cannot be bound"); THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); } } JSHandle iter = JSAPILightWeightSet::GetIteratorObj(thread, JSHandle::Cast(self), IterationKind::VALUE); return iter.GetTaggedValue(); } JSTaggedValue ContainersLightWeightSet::Entries(EcmaRuntimeCallInfo *argv) { ASSERT(argv != nullptr); JSThread *thread = argv->GetThread(); BUILTINS_API_TRACE(thread, LightWeightSet, Entries); [[maybe_unused]] EcmaHandleScope handleScope(thread); JSHandle self = GetThis(argv); if (!self->IsJSAPILightWeightSet()) { if (self->IsJSProxy() && JSHandle::Cast(self)->GetTarget(thread).IsJSAPILightWeightSet()) { self = JSHandle(thread, JSHandle::Cast(self)->GetTarget(thread)); } else { JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR, "The entries method cannot be bound"); THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); } } JSHandle iter = JSAPILightWeightSet::GetIteratorObj(thread, JSHandle::Cast(self), IterationKind::KEY_AND_VALUE); return iter.GetTaggedValue(); } JSTaggedValue ContainersLightWeightSet::ForEach(EcmaRuntimeCallInfo *argv) { ASSERT(argv != nullptr); JSThread *thread = argv->GetThread(); BUILTINS_API_TRACE(thread, LightWeightSet, ForEach); [[maybe_unused]] EcmaHandleScope handleScope(thread); JSHandle thisHandle = GetThis(argv); JSHandle callbackFnHandle = GetCallArg(argv, 0); if (!thisHandle->IsJSAPILightWeightSet()) { if (thisHandle->IsJSProxy() && JSHandle::Cast(thisHandle)->GetTarget(thread).IsJSAPILightWeightSet()) { thisHandle = JSHandle(thread, JSHandle::Cast(thisHandle)->GetTarget(thread)); } else { JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR, "The forEach method cannot be bound"); THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); } } if (!callbackFnHandle->IsCallable()) { JSHandle result = JSTaggedValue::ToString(thread, callbackFnHandle.GetTaggedValue()); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); CString errorMsg = "The type of \"callbackfn\" must be callable. Received value is: " + ConvertToString(thread, *result); JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str()); THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); } JSHandle thisArgHandle = GetCallArg(argv, 1); return JSAPILightWeightSet::ForEach(thread, thisHandle, callbackFnHandle, thisArgHandle); } JSTaggedValue ContainersLightWeightSet::GetIndexOf(EcmaRuntimeCallInfo *argv) { ASSERT(argv != nullptr); JSThread *thread = argv->GetThread(); BUILTINS_API_TRACE(thread, LightWeightSet, GetIndexOf); [[maybe_unused]] EcmaHandleScope handleScope(thread); JSHandle self = GetThis(argv); if (!self->IsJSAPILightWeightSet()) { if (self->IsJSProxy() && JSHandle::Cast(self)->GetTarget(thread).IsJSAPILightWeightSet()) { self = JSHandle(thread, JSHandle::Cast(self)->GetTarget(thread)); } else { JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR, "The getIndexOf method cannot be bound"); THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); } } JSHandle value(GetCallArg(argv, 0)); JSAPILightWeightSet *set = JSAPILightWeightSet::Cast(self->GetTaggedObject()); int32_t result = set->GetIndexOf(thread, value); return JSTaggedValue(result); } JSTaggedValue ContainersLightWeightSet::Remove(EcmaRuntimeCallInfo *argv) { ASSERT(argv != nullptr); JSThread *thread = argv->GetThread(); BUILTINS_API_TRACE(thread, LightWeightSet, Remove); [[maybe_unused]] EcmaHandleScope handleScope(thread); JSHandle self = GetThis(argv); if (!self->IsJSAPILightWeightSet()) { if (self->IsJSProxy() && JSHandle::Cast(self)->GetTarget(thread).IsJSAPILightWeightSet()) { self = JSHandle(thread, JSHandle::Cast(self)->GetTarget(thread)); } else { JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR, "The remove method cannot be bound"); THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); } } JSHandle key(GetCallArg(argv, 0)); JSHandle lightweightset(self); JSAPILightWeightSet::CheckAndCopyValues(thread, lightweightset); JSAPILightWeightSet *set = JSAPILightWeightSet::Cast(lightweightset.GetTaggedValue().GetTaggedObject()); return set->Remove(thread, key); } JSTaggedValue ContainersLightWeightSet::RemoveAt(EcmaRuntimeCallInfo *argv) { ASSERT(argv != nullptr); JSThread *thread = argv->GetThread(); BUILTINS_API_TRACE(thread, LightWeightSet, RemoveAt); [[maybe_unused]] EcmaHandleScope handleScope(thread); JSHandle self = GetThis(argv); if (!self->IsJSAPILightWeightSet()) { if (self->IsJSProxy() && JSHandle::Cast(self)->GetTarget(thread).IsJSAPILightWeightSet()) { self = JSHandle(thread, JSHandle::Cast(self)->GetTarget(thread)); } else { JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR, "The removeAt method cannot be bound"); THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); } } JSHandle value(GetCallArg(argv, 0)); if (value->IsDouble()) { value = JSHandle(thread, JSTaggedValue::TryCastDoubleToInt32(value->GetDouble())); } if (!value->IsInt()) { JSHandle result = JSTaggedValue::ToString(thread, value.GetTaggedValue()); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); CString errorMsg = "The type of \"index\" must be small integer. Received value is: " + ConvertToString(thread, *result); JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str()); THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); } JSHandle lightweightset(self); JSAPILightWeightSet::CheckAndCopyValues(thread, lightweightset); JSAPILightWeightSet *set = JSAPILightWeightSet::Cast(lightweightset.GetTaggedValue().GetTaggedObject()); return JSTaggedValue(set->RemoveAt(thread, value->GetInt())); } JSTaggedValue ContainersLightWeightSet::Clear(EcmaRuntimeCallInfo *argv) { ASSERT(argv != nullptr); JSThread *thread = argv->GetThread(); BUILTINS_API_TRACE(thread, LightWeightSet, Clear); [[maybe_unused]] EcmaHandleScope handleScope(thread); JSHandle self = GetThis(argv); if (!self->IsJSAPILightWeightSet()) { if (self->IsJSProxy() && JSHandle::Cast(self)->GetTarget(thread).IsJSAPILightWeightSet()) { self = JSHandle(thread, JSHandle::Cast(self)->GetTarget(thread)); } else { JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR, "The clear method cannot be bound"); THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); } } JSAPILightWeightSet *set = JSAPILightWeightSet::Cast(self->GetTaggedObject()); set->Clear(thread); return JSTaggedValue::Undefined(); } JSTaggedValue ContainersLightWeightSet::ToString(EcmaRuntimeCallInfo *argv) { ASSERT(argv != nullptr); JSThread *thread = argv->GetThread(); BUILTINS_API_TRACE(thread, LightWeightSet, ToString); [[maybe_unused]] EcmaHandleScope handleScope(thread); JSHandle self = GetThis(argv); if (!self->IsJSAPILightWeightSet()) { if (self->IsJSProxy() && JSHandle::Cast(self)->GetTarget(thread).IsJSAPILightWeightSet()) { self = JSHandle(thread, JSHandle::Cast(self)->GetTarget(thread)); } else { JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR, "The toString method cannot be bound"); THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); } } JSTaggedValue value = JSAPILightWeightSet::ToString(thread, JSHandle::Cast(self)); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); return value; } JSTaggedValue ContainersLightWeightSet::ToArray(EcmaRuntimeCallInfo *argv) { ASSERT(argv != nullptr); JSThread *thread = argv->GetThread(); BUILTINS_API_TRACE(thread, LightWeightSet, ToArray); [[maybe_unused]] EcmaHandleScope handleScope(thread); JSHandle self = GetThis(argv); if (!self->IsJSAPILightWeightSet()) { if (self->IsJSProxy() && JSHandle::Cast(self)->GetTarget(thread).IsJSAPILightWeightSet()) { self = JSHandle(thread, JSHandle::Cast(self)->GetTarget(thread)); } else { JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR, "The toArray method cannot be bound"); THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); } } JSHandle lightweightset = JSHandle::Cast(self); auto factory = thread->GetEcmaVM()->GetFactory(); JSHandle array = factory->NewJSArray(); uint32_t length = lightweightset->GetLength(); array->SetArrayLength(thread, length); JSHandle srcArray(thread, lightweightset->GetValues(thread)); if (srcArray.GetTaggedValue().IsCOWArray()) { array->SetElements(thread, srcArray.GetTaggedValue()); return array.GetTaggedValue(); } auto newElements = factory->CopyArray(srcArray, srcArray->GetLength(), srcArray->GetLength(), JSTaggedValue::Hole(), MemSpaceType::NON_MOVABLE); lightweightset->SetValues(thread, newElements.GetTaggedValue()); array->SetElements(thread, newElements); return array.GetTaggedValue(); } JSTaggedValue ContainersLightWeightSet::GetSize(EcmaRuntimeCallInfo *argv) { ASSERT(argv != nullptr); JSThread *thread = argv->GetThread(); BUILTINS_API_TRACE(thread, LightWeightSet, GetSize); [[maybe_unused]] EcmaHandleScope handleScope(thread); JSHandle self = GetThis(argv); if (!self->IsJSAPILightWeightSet()) { if (self->IsJSProxy() && JSHandle::Cast(self)->GetTarget(thread).IsJSAPILightWeightSet()) { self = JSHandle(thread, JSHandle::Cast(self)->GetTarget(thread)); } else { JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR, "The getLength method cannot be bound"); THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); } } return JSTaggedValue(JSHandle::Cast(self)->GetSize()); } } // namespace panda::ecmascript::containers