* Copyright (c) 2024 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_bitvector.h"
#include "ecmascript/containers/containers_errors.h"
#include "ecmascript/js_api/js_api_bitvector.h"
namespace panda::ecmascript::containers {
JSTaggedValue ContainersBitVector::BitVectorConstructor(EcmaRuntimeCallInfo* argv)
{
ASSERT(argv);
JSThread* thread = argv->GetThread();
BUILTINS_API_TRACE(thread, BitVector, Constructor);
[[maybe_unused]] EcmaHandleScope handleScope(thread);
ObjectFactory* factory = thread->GetEcmaVM()->GetFactory();
JSHandle<JSTaggedValue> newTarget = GetNewTarget(argv);
if (newTarget->IsUndefined()) {
JSTaggedValue error = ContainerError::BusinessError(
thread, ErrorFlag::IS_NULL_ERROR, "The BitVector's constructor cannot be directly invoked.");
THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
}
JSHandle<JSTaggedValue> constructor = GetConstructor(argv);
ASSERT(constructor->IsJSSharedFunction() && constructor.GetTaggedValue().IsInSharedHeap());
JSHandle<JSAPIBitVector> obj =
JSHandle<JSAPIBitVector>(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(constructor), newTarget));
ASSERT(obj.GetTaggedValue().IsInSharedHeap());
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
JSHandle<JSTaggedValue> length = GetCallArg(argv, 0);
if (!length->IsInteger()) {
JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, length);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
CString errorMsg =
"The type of \"length\" must be 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());
}
auto* newBitSetVector = new std::vector<std::bitset<JSAPIBitVector::BIT_SET_LENGTH>>();
if (!length->IsZero()) {
int32_t capacity = std::max(0, (length->GetInt() / JSAPIBitVector::BIT_SET_LENGTH) + 1);
std::bitset<JSAPIBitVector::BIT_SET_LENGTH> initBitSet;
newBitSetVector->resize(capacity, initBitSet);
}
JSHandle<JSNativePointer> pointer = factory->NewSJSNativePointer(newBitSetVector,
ContainersBitVector::FreeBitsetVectorPointer,
newBitSetVector);
obj->SetNativePointer(thread, pointer);
obj->SetLength(std::max(0, length->GetInt()));
return obj.GetTaggedValue();
}
JSTaggedValue ContainersBitVector::Push(EcmaRuntimeCallInfo* argv)
{
BUILTINS_API_TRACE(argv->GetThread(), BitVector, Push);
JSThread* thread = argv->GetThread();
[[maybe_unused]] EcmaHandleScope handleScope(thread);
JSHandle<JSTaggedValue> self = GetThis(argv);
if (!self->IsJSAPIBitVector()) {
if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget(thread).IsJSAPIBitVector()) {
self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget(thread));
} else {
JSTaggedValue error =
ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR, "The push method cannot be bound");
THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
}
}
JSHandle<JSTaggedValue> value = GetCallArg(argv, 0);
return GetTaggedBoolean(JSAPIBitVector::Push(thread, JSHandle<JSAPIBitVector>::Cast(self), value));
}
JSTaggedValue ContainersBitVector::Pop(EcmaRuntimeCallInfo* argv)
{
BUILTINS_API_TRACE(argv->GetThread(), BitVector, Pop);
JSThread* thread = argv->GetThread();
[[maybe_unused]] EcmaHandleScope handleScope(thread);
JSHandle<JSTaggedValue> self = GetThis(argv);
if (!self->IsJSAPIBitVector()) {
if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget(thread).IsJSAPIBitVector()) {
self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget(thread));
} else {
JSTaggedValue error =
ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR, "The pop method cannot be bound");
THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
}
}
return JSHandle<JSAPIBitVector>::Cast(self)->Pop(thread, JSHandle<JSAPIBitVector>::Cast(self));
}
JSTaggedValue ContainersBitVector::Has(EcmaRuntimeCallInfo* argv)
{
ASSERT(argv);
BUILTINS_API_TRACE(argv->GetThread(), BitVector, Has);
JSThread* thread = argv->GetThread();
[[maybe_unused]] EcmaHandleScope handleScope(thread);
JSHandle<JSTaggedValue> self = GetThis(argv);
if (!self->IsJSAPIBitVector()) {
if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget(thread).IsJSAPIBitVector()) {
self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget(thread));
} else {
JSTaggedValue error = ContainerError::BusinessError(thread, BIND_ERROR, "The has method cannot be bound");
THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
}
}
JSHandle<JSTaggedValue> value = GetCallArg(argv, 0);
JSHandle<JSTaggedValue> startIndex = GetCallArg(argv, 1);
JSHandle<JSTaggedValue> endIndex = GetCallArg(argv, 2);
if (!startIndex->IsInteger()) {
JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, startIndex);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
CString errorMsg =
"The type of \"fromIndex\" must be 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());
}
if (!endIndex->IsInteger()) {
JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, endIndex);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
CString errorMsg =
"The type of \"toIndex\" must be 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());
}
bool isHas = JSHandle<JSAPIBitVector>::Cast(self)->Has(
thread, JSHandle<JSAPIBitVector>::Cast(self), value, startIndex, endIndex);
return GetTaggedBoolean(isHas);
}
JSTaggedValue ContainersBitVector::SetBitsByRange(EcmaRuntimeCallInfo* argv)
{
ASSERT(argv);
BUILTINS_API_TRACE(argv->GetThread(), BitVector, SetBitsByRange);
JSThread* thread = argv->GetThread();
[[maybe_unused]] EcmaHandleScope handleScope(thread);
JSHandle<JSTaggedValue> self = GetThis(argv);
if (!self->IsJSAPIBitVector()) {
if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget(thread).IsJSAPIBitVector()) {
self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget(thread));
} else {
JSTaggedValue error =
ContainerError::BusinessError(thread, BIND_ERROR, "The setBitsByRange method cannot be bound");
THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
}
}
JSHandle<JSTaggedValue> value = GetCallArg(argv, 0);
JSHandle<JSTaggedValue> startIndex = GetCallArg(argv, 1);
JSHandle<JSTaggedValue> endIndex = GetCallArg(argv, 2);
if (!startIndex->IsInteger()) {
JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, startIndex);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
CString errorMsg =
"The type of \"fromIndex\" must be 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());
}
if (!endIndex->IsInteger()) {
JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, endIndex);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
CString errorMsg =
"The type of \"toIndex\" must be 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<JSAPIBitVector>::Cast(self)->SetBitsByRange(
thread, JSHandle<JSAPIBitVector>::Cast(self), value, startIndex, endIndex);
return JSTaggedValue::Undefined();
}
JSTaggedValue ContainersBitVector::GetBitsByRange(EcmaRuntimeCallInfo* argv)
{
ASSERT(argv);
BUILTINS_API_TRACE(argv->GetThread(), BitVector, GetBitsByRange);
JSThread* thread = argv->GetThread();
[[maybe_unused]] EcmaHandleScope handleScope(thread);
JSHandle<JSTaggedValue> self = GetThis(argv);
if (!self->IsJSAPIBitVector()) {
if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget(thread).IsJSAPIBitVector()) {
self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget(thread));
} else {
JSTaggedValue error =
ContainerError::BusinessError(thread, BIND_ERROR, "The getBitsByRange method cannot be bound");
THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
}
}
JSHandle<JSTaggedValue> startIndex = GetCallArg(argv, 0);
JSHandle<JSTaggedValue> endIndex = GetCallArg(argv, 1);
if (!startIndex->IsInteger()) {
JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, startIndex);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
CString errorMsg =
"The type of \"fromIndex\" must be 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());
}
if (!endIndex->IsInteger()) {
JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, endIndex);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
CString errorMsg =
"The type of \"toIndex\" must be 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());
}
return JSHandle<JSAPIBitVector>::Cast(self)->GetBitsByRange(
thread, JSHandle<JSAPIBitVector>::Cast(self), startIndex, endIndex);
}
JSTaggedValue ContainersBitVector::Resize(EcmaRuntimeCallInfo* argv)
{
ASSERT(argv);
BUILTINS_API_TRACE(argv->GetThread(), BitVector, Resize);
JSThread* thread = argv->GetThread();
[[maybe_unused]] EcmaHandleScope handleScope(thread);
JSHandle<JSTaggedValue> self = GetThis(argv);
if (!self->IsJSAPIBitVector()) {
if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget(thread).IsJSAPIBitVector()) {
self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget(thread));
} else {
JSTaggedValue error =
ContainerError::BusinessError(thread, BIND_ERROR, "The resize method cannot be bound");
THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
}
}
JSHandle<JSTaggedValue> size = GetCallArg(argv, 0);
if (!size->IsInteger()) {
JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, size);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
CString errorMsg =
"The type of \"size\" must be 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<JSAPIBitVector>::Cast(self)->Resize(
thread, JSHandle<JSAPIBitVector>::Cast(self), JSTaggedValue::ToUint32(thread, size));
return JSTaggedValue::Undefined();
}
JSTaggedValue ContainersBitVector::SetAllBits(EcmaRuntimeCallInfo* argv)
{
BUILTINS_API_TRACE(argv->GetThread(), BitVector, SetAllBits);
JSThread* thread = argv->GetThread();
[[maybe_unused]] EcmaHandleScope handleScope(thread);
JSHandle<JSTaggedValue> self = GetThis(argv);
if (!self->IsJSAPIBitVector()) {
if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget(thread).IsJSAPIBitVector()) {
self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget(thread));
} else {
JSTaggedValue error =
ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR, "The setAllBits method cannot be bound");
THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
}
}
JSHandle<JSTaggedValue> value = GetCallArg(argv, 0);
JSHandle<JSAPIBitVector>::Cast(self)->SetAllBits(thread, JSHandle<JSAPIBitVector>::Cast(self), value);
return JSTaggedValue::Undefined();
}
JSTaggedValue ContainersBitVector::GetBitCountByRange(EcmaRuntimeCallInfo* argv)
{
ASSERT(argv);
BUILTINS_API_TRACE(argv->GetThread(), BitVector, GetBitCountByRange);
JSThread* thread = argv->GetThread();
[[maybe_unused]] EcmaHandleScope handleScope(thread);
JSHandle<JSTaggedValue> self = GetThis(argv);
if (!self->IsJSAPIBitVector()) {
if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget(thread).IsJSAPIBitVector()) {
self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget(thread));
} else {
JSTaggedValue error =
ContainerError::BusinessError(thread, BIND_ERROR, "The getBitCountByRange method cannot be bound");
THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
}
}
JSHandle<JSTaggedValue> value = GetCallArg(argv, 0);
JSHandle<JSTaggedValue> startIndex = GetCallArg(argv, 1);
JSHandle<JSTaggedValue> endIndex = GetCallArg(argv, 2);
if (!startIndex->IsInteger()) {
JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, startIndex);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
CString errorMsg =
"The type of \"fromIndex\" must be 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());
}
if (!endIndex->IsInteger()) {
JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, endIndex);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
CString errorMsg =
"The type of \"toIndex\" must be 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());
}
return JSHandle<JSAPIBitVector>::Cast(self)->GetBitCountByRange(
thread, JSHandle<JSAPIBitVector>::Cast(self), value, startIndex, endIndex);
}
JSTaggedValue ContainersBitVector::GetIndexOf(EcmaRuntimeCallInfo* argv)
{
ASSERT(argv);
BUILTINS_API_TRACE(argv->GetThread(), BitVector, GetIndexOf);
JSThread* thread = argv->GetThread();
[[maybe_unused]] EcmaHandleScope handleScope(thread);
JSHandle<JSTaggedValue> self = GetThis(argv);
if (!self->IsJSAPIBitVector()) {
if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget(thread).IsJSAPIBitVector()) {
self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget(thread));
} else {
JSTaggedValue error =
ContainerError::BusinessError(thread, BIND_ERROR, "The getIndexOf method cannot be bound");
THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
}
}
JSHandle<JSTaggedValue> value = GetCallArg(argv, 0);
JSHandle<JSTaggedValue> startIndex = GetCallArg(argv, 1);
JSHandle<JSTaggedValue> endIndex = GetCallArg(argv, 2);
if (!startIndex->IsInteger()) {
JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, startIndex);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
CString errorMsg =
"The type of \"fromIndex\" must be 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());
}
if (!endIndex->IsInteger()) {
JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, endIndex);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
CString errorMsg =
"The type of \"toIndex\" must be 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());
}
return JSTaggedValue(
JSAPIBitVector::GetIndexOf(thread, JSHandle<JSAPIBitVector>::Cast(self), value, startIndex, endIndex));
}
JSTaggedValue ContainersBitVector::GetLastIndexOf(EcmaRuntimeCallInfo* argv)
{
ASSERT(argv);
BUILTINS_API_TRACE(argv->GetThread(), BitVector, GetLastIndexOf);
JSThread* thread = argv->GetThread();
[[maybe_unused]] EcmaHandleScope handleScope(thread);
JSHandle<JSTaggedValue> self = GetThis(argv);
if (!self->IsJSAPIBitVector()) {
if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget(thread).IsJSAPIBitVector()) {
self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget(thread));
} else {
JSTaggedValue error =
ContainerError::BusinessError(thread, BIND_ERROR, "The getLastIndexOf method cannot be bound");
THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
}
}
JSHandle<JSTaggedValue> value = GetCallArg(argv, 0);
JSHandle<JSTaggedValue> startIndex = GetCallArg(argv, 1);
JSHandle<JSTaggedValue> endIndex = GetCallArg(argv, 2);
if (!startIndex->IsInteger()) {
JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, startIndex);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
CString errorMsg =
"The type of \"fromIndex\" must be 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());
}
if (!endIndex->IsInteger()) {
JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, endIndex);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
CString errorMsg =
"The type of \"toIndex\" must be 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());
}
return JSTaggedValue(
JSAPIBitVector::GetLastIndexOf(thread, JSHandle<JSAPIBitVector>::Cast(self), value, startIndex, endIndex));
}
JSTaggedValue ContainersBitVector::FlipBitByIndex(EcmaRuntimeCallInfo* argv)
{
ASSERT(argv);
BUILTINS_API_TRACE(argv->GetThread(), BitVector, FlipBitByIndex);
JSThread* thread = argv->GetThread();
[[maybe_unused]] EcmaHandleScope handleScope(thread);
JSHandle<JSTaggedValue> self = GetThis(argv);
if (!self->IsJSAPIBitVector()) {
if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget(thread).IsJSAPIBitVector()) {
self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget(thread));
} else {
JSTaggedValue error =
ContainerError::BusinessError(thread, BIND_ERROR, "The flipBitByIndex method cannot be bound");
THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
}
}
JSHandle<JSTaggedValue> value = GetCallArg(argv, 0);
if (!value->IsInteger()) {
JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, value);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
CString errorMsg =
"The type of \"index\" must be 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());
}
JSAPIBitVector::FlipBitByIndex(
thread, JSHandle<JSAPIBitVector>::Cast(self), JSTaggedValue::ToUint32(thread, value));
return JSTaggedValue::Undefined();
}
JSTaggedValue ContainersBitVector::FlipBitsByRange(EcmaRuntimeCallInfo* argv)
{
ASSERT(argv);
BUILTINS_API_TRACE(argv->GetThread(), BitVector, FlipBitsByRange);
JSThread* thread = argv->GetThread();
[[maybe_unused]] EcmaHandleScope handleScope(thread);
JSHandle<JSTaggedValue> self = GetThis(argv);
if (!self->IsJSAPIBitVector()) {
if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget(thread).IsJSAPIBitVector()) {
self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget(thread));
} else {
JSTaggedValue error =
ContainerError::BusinessError(thread, BIND_ERROR, "The flipBitsByRange method cannot be bound");
THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
}
}
JSHandle<JSTaggedValue> startIndex = GetCallArg(argv, 0);
JSHandle<JSTaggedValue> endIndex = GetCallArg(argv, 1);
if (!startIndex->IsInteger()) {
JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, startIndex);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
CString errorMsg =
"The type of \"fromIndex\" must be 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());
}
if (!endIndex->IsInteger()) {
JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, endIndex);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
CString errorMsg =
"The type of \"toIndex\" must be 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<JSAPIBitVector>::Cast(self)->FlipBitsByRange(
thread, JSHandle<JSAPIBitVector>::Cast(self), startIndex, endIndex);
return JSTaggedValue::Undefined();
}
JSTaggedValue ContainersBitVector::GetSize(EcmaRuntimeCallInfo* argv)
{
ASSERT(argv);
BUILTINS_API_TRACE(argv->GetThread(), BitVector, GetSize);
JSThread* thread = argv->GetThread();
[[maybe_unused]] EcmaHandleScope handleScope(thread);
JSHandle<JSTaggedValue> self = GetThis(argv);
if (!self->IsJSAPIBitVector()) {
if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget(thread).IsJSAPIBitVector()) {
self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget(thread));
} else {
JSTaggedValue error =
ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR, "The getSize method cannot be bound");
THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
}
}
return JSTaggedValue(JSHandle<JSAPIBitVector>::Cast(self)->GetSize());
}
JSTaggedValue ContainersBitVector::GetIteratorObj(EcmaRuntimeCallInfo* argv)
{
ASSERT(argv);
BUILTINS_API_TRACE(argv->GetThread(), BitVector, GetIteratorObj);
JSThread* thread = argv->GetThread();
[[maybe_unused]] EcmaHandleScope handleScope(thread);
JSHandle<JSTaggedValue> self = GetThis(argv);
if (!self->IsJSAPIBitVector()) {
if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget(thread).IsJSAPIBitVector()) {
self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::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());
}
}
JSTaggedValue values = JSAPIBitVector::GetIteratorObj(thread, JSHandle<JSAPIBitVector>::Cast(self));
return values;
}
void ContainersBitVector::FreeBitsetVectorPointer([[maybe_unused]] void *env, void *pointer,
[[maybe_unused]] void *data)
{
if (pointer == nullptr) {
return;
}
auto bitsetVector = reinterpret_cast<std::vector<std::bitset<JSAPIBitVector::BIT_SET_LENGTH>> *>(pointer);
delete bitsetVector;
}
}