2022-05-23 01:49:27 +00:00
|
|
|
/*
|
|
|
|
* 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 "js_api_vector.h"
|
|
|
|
|
|
|
|
#include "ecmascript/interpreter/interpreter.h"
|
|
|
|
#include "ecmascript/js_array.h"
|
|
|
|
#include "ecmascript/js_api_vector_iterator.h"
|
|
|
|
#include "ecmascript/js_handle.h"
|
|
|
|
#include "ecmascript/js_function.h"
|
|
|
|
#include "ecmascript/js_tagged_number.h"
|
|
|
|
#include "ecmascript/js_tagged_value.h"
|
|
|
|
#include "ecmascript/object_factory.h"
|
|
|
|
|
|
|
|
namespace panda::ecmascript {
|
|
|
|
static const uint32_t MAX_VALUE = 0x7fffffff;
|
|
|
|
static const uint32_t MAX_ARRAY_SIZE = MAX_VALUE - 8;
|
|
|
|
bool JSAPIVector::Add(JSThread *thread, const JSHandle<JSAPIVector> &vector, const JSHandle<JSTaggedValue> &value)
|
|
|
|
{
|
|
|
|
int32_t length = vector->GetSize();
|
|
|
|
GrowCapacity(thread, vector, length + 1);
|
|
|
|
|
2022-06-21 02:02:29 +00:00
|
|
|
TaggedArray *elements = TaggedArray::Cast(vector->GetElements().GetTaggedObject());
|
2022-05-23 01:49:27 +00:00
|
|
|
ASSERT(!elements->IsDictionaryMode());
|
|
|
|
elements->Set(thread, length, value);
|
|
|
|
vector->SetLength(++length);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void JSAPIVector::Insert(JSThread *thread, const JSHandle<JSAPIVector> &vector,
|
|
|
|
const JSHandle<JSTaggedValue> &value, int32_t index)
|
|
|
|
{
|
|
|
|
int32_t length = vector->GetSize();
|
|
|
|
if (index < 0 || index > length) {
|
|
|
|
THROW_ERROR(thread, ErrorType::RANGE_ERROR, "the index is out-of-bounds");
|
|
|
|
}
|
|
|
|
GrowCapacity(thread, vector, length + 1);
|
|
|
|
|
2022-06-21 02:02:29 +00:00
|
|
|
TaggedArray *elements = TaggedArray::Cast(vector->GetElements().GetTaggedObject());
|
2022-05-23 01:49:27 +00:00
|
|
|
ASSERT(!elements->IsDictionaryMode());
|
|
|
|
for (int32_t i = length - 1; i >= index; i--) {
|
|
|
|
elements->Set(thread, i + 1, elements->Get(i));
|
|
|
|
}
|
|
|
|
|
|
|
|
elements->Set(thread, index, value);
|
|
|
|
vector->SetLength(++length);
|
|
|
|
}
|
|
|
|
|
|
|
|
void JSAPIVector::SetLength(JSThread *thread, const JSHandle<JSAPIVector> &vector, uint32_t newSize)
|
|
|
|
{
|
2022-05-25 07:13:55 +00:00
|
|
|
uint32_t len = static_cast<uint32_t>(vector->GetSize());
|
2022-05-23 01:49:27 +00:00
|
|
|
if (newSize > len) {
|
|
|
|
GrowCapacity(thread, vector, newSize);
|
|
|
|
}
|
|
|
|
vector->SetLength(newSize);
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t JSAPIVector::GetCapacity()
|
|
|
|
{
|
2022-06-21 02:02:29 +00:00
|
|
|
TaggedArray *elementData = TaggedArray::Cast(GetElements().GetTaggedObject());
|
2022-05-23 01:49:27 +00:00
|
|
|
ASSERT(!elementData->IsDictionaryMode());
|
|
|
|
return elementData->GetLength();
|
|
|
|
}
|
|
|
|
|
|
|
|
void JSAPIVector::IncreaseCapacityTo(JSThread *thread, const JSHandle<JSAPIVector> &vector, int32_t newCapacity)
|
|
|
|
{
|
|
|
|
if (newCapacity < 0) {
|
|
|
|
THROW_ERROR(thread, ErrorType::RANGE_ERROR, "An incorrect size was set");
|
|
|
|
}
|
|
|
|
|
|
|
|
JSHandle<TaggedArray> elementData(thread, vector->GetElements());
|
|
|
|
ASSERT(!elementData->IsDictionaryMode());
|
|
|
|
uint32_t oldCapacity = elementData->GetLength();
|
2022-05-25 07:13:55 +00:00
|
|
|
uint32_t tempCapacity = static_cast<uint32_t>(newCapacity);
|
2022-05-23 01:49:27 +00:00
|
|
|
if (oldCapacity < tempCapacity) {
|
|
|
|
JSHandle<TaggedArray> newElements =
|
|
|
|
thread->GetEcmaVM()->GetFactory()->CopyArray(elementData, oldCapacity, tempCapacity);
|
|
|
|
vector->SetElements(thread, newElements);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int32_t JSAPIVector::GetIndexOf(JSThread *thread, const JSHandle<JSAPIVector> &vector,
|
|
|
|
const JSHandle<JSTaggedValue> &obj)
|
|
|
|
{
|
|
|
|
return JSAPIVector::GetIndexFrom(thread, vector, obj, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
int32_t JSAPIVector::GetIndexFrom(JSThread *thread, const JSHandle<JSAPIVector> &vector,
|
|
|
|
const JSHandle<JSTaggedValue> &obj, int32_t index)
|
|
|
|
{
|
2022-06-21 02:02:29 +00:00
|
|
|
TaggedArray *elements = TaggedArray::Cast(vector->GetElements().GetTaggedObject());
|
2022-05-23 01:49:27 +00:00
|
|
|
ASSERT(!elements->IsDictionaryMode());
|
|
|
|
int32_t length = vector->GetSize();
|
|
|
|
if (index < 0) {
|
|
|
|
index = 0;
|
|
|
|
} else if (index >= length) {
|
|
|
|
THROW_RANGE_ERROR_AND_RETURN(thread, "no-such-element", -1);
|
|
|
|
}
|
|
|
|
|
|
|
|
JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
|
|
|
|
for (int32_t i = index; i < length; i++) {
|
|
|
|
value.Update(JSTaggedValue(elements->Get(i)));
|
|
|
|
if (JSTaggedValue::StrictEqual(thread, obj, value))
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool JSAPIVector::IsEmpty() const
|
|
|
|
{
|
|
|
|
return GetSize() == 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
JSTaggedValue JSAPIVector::GetLastElement()
|
|
|
|
{
|
2022-05-25 07:13:55 +00:00
|
|
|
int32_t length = GetSize();
|
2022-05-23 01:49:27 +00:00
|
|
|
if (length == 0) {
|
|
|
|
return JSTaggedValue::Undefined();
|
|
|
|
}
|
2022-06-21 02:02:29 +00:00
|
|
|
TaggedArray *elements = TaggedArray::Cast(GetElements().GetTaggedObject());
|
2022-05-23 01:49:27 +00:00
|
|
|
ASSERT(!elements->IsDictionaryMode());
|
|
|
|
return elements->Get(length - 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
int32_t JSAPIVector::GetLastIndexOf(JSThread *thread, const JSHandle<JSAPIVector> &vector,
|
|
|
|
const JSHandle<JSTaggedValue> &obj)
|
|
|
|
{
|
2022-06-21 02:02:29 +00:00
|
|
|
int32_t index = vector->GetSize() - 1;
|
|
|
|
if (index < 0) {
|
|
|
|
return -1; // vector isEmpty, defalut return -1
|
|
|
|
}
|
|
|
|
return JSAPIVector::GetLastIndexFrom(thread, vector, obj, index);
|
2022-05-23 01:49:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int32_t JSAPIVector::GetLastIndexFrom(JSThread *thread, const JSHandle<JSAPIVector> &vector,
|
|
|
|
const JSHandle<JSTaggedValue> &obj, int32_t index)
|
|
|
|
{
|
|
|
|
int32_t length = vector->GetSize();
|
2022-06-21 02:02:29 +00:00
|
|
|
if (index >= length) {
|
2022-05-23 01:49:27 +00:00
|
|
|
THROW_RANGE_ERROR_AND_RETURN(thread, "index-out-of-bounds", -1);
|
2022-06-21 02:02:29 +00:00
|
|
|
} else if (index < 0) {
|
|
|
|
index = 0;
|
2022-05-23 01:49:27 +00:00
|
|
|
}
|
2022-06-21 02:02:29 +00:00
|
|
|
TaggedArray *elements = TaggedArray::Cast(vector->GetElements().GetTaggedObject());
|
2022-05-23 01:49:27 +00:00
|
|
|
ASSERT(!elements->IsDictionaryMode());
|
|
|
|
JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
|
|
|
|
for (int32_t i = index; i >= 0; i--) {
|
|
|
|
value.Update(elements->Get(i));
|
|
|
|
if (JSTaggedValue::StrictEqual(thread, obj, value)) {
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool JSAPIVector::Remove(JSThread *thread, const JSHandle<JSAPIVector> &vector, const JSHandle<JSTaggedValue> &obj)
|
|
|
|
{
|
|
|
|
int32_t index = GetIndexOf(thread, vector, obj);
|
|
|
|
int32_t length = vector->GetSize();
|
|
|
|
if (index >= 0) {
|
|
|
|
if (index >= length) {
|
|
|
|
THROW_RANGE_ERROR_AND_RETURN(thread, "index-out-of-bounds", false);
|
|
|
|
}
|
|
|
|
|
2022-06-21 02:02:29 +00:00
|
|
|
TaggedArray *elements = TaggedArray::Cast(vector->GetElements().GetTaggedObject());
|
2022-05-23 01:49:27 +00:00
|
|
|
ASSERT(!elements->IsDictionaryMode());
|
|
|
|
for (int32_t i = index; i < length - 1; i++) {
|
|
|
|
elements->Set(thread, i, elements->Get(i + 1));
|
|
|
|
}
|
|
|
|
length--;
|
|
|
|
vector->SetLength(length);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
JSTaggedValue JSAPIVector::RemoveByIndex(JSThread *thread, const JSHandle<JSAPIVector> &vector, int32_t index)
|
|
|
|
{
|
|
|
|
int32_t length = vector->GetSize();
|
|
|
|
if (index < 0 || index >= length) {
|
|
|
|
THROW_RANGE_ERROR_AND_RETURN(thread, "the index is out-of-bounds", JSTaggedValue::Exception());
|
|
|
|
}
|
2022-06-21 02:02:29 +00:00
|
|
|
TaggedArray *elements = TaggedArray::Cast(vector->GetElements().GetTaggedObject());
|
2022-05-23 01:49:27 +00:00
|
|
|
ASSERT(!elements->IsDictionaryMode());
|
|
|
|
JSTaggedValue oldValue = elements->Get(index);
|
|
|
|
|
|
|
|
for (int32_t i = index; i < length - 1; i++) {
|
|
|
|
elements->Set(thread, i, elements->Get(i + 1));
|
|
|
|
}
|
|
|
|
length--;
|
|
|
|
vector->SetLength(length);
|
|
|
|
|
|
|
|
return oldValue;
|
|
|
|
}
|
|
|
|
|
|
|
|
JSTaggedValue JSAPIVector::RemoveByRange(JSThread *thread, const JSHandle<JSAPIVector> &vector,
|
|
|
|
int32_t fromIndex, int32_t toIndex)
|
|
|
|
{
|
|
|
|
int32_t length = vector->GetSize();
|
|
|
|
if (toIndex <= fromIndex) {
|
|
|
|
THROW_RANGE_ERROR_AND_RETURN(thread, "the fromIndex cannot be less than or equal to toIndex",
|
|
|
|
JSTaggedValue::Exception());
|
|
|
|
}
|
|
|
|
if (fromIndex < 0 || toIndex < 0 || fromIndex >= length) {
|
|
|
|
THROW_RANGE_ERROR_AND_RETURN(thread, "the fromIndex or the toIndex is out-of-bounds",
|
|
|
|
JSTaggedValue::Exception());
|
|
|
|
}
|
|
|
|
|
|
|
|
int32_t endIndex = toIndex >= length ? length : toIndex;
|
2022-06-21 02:02:29 +00:00
|
|
|
TaggedArray *elements = TaggedArray::Cast(vector->GetElements().GetTaggedObject());
|
2022-05-23 01:49:27 +00:00
|
|
|
ASSERT(!elements->IsDictionaryMode());
|
2022-05-25 07:13:55 +00:00
|
|
|
int32_t numMoved = length - endIndex;
|
|
|
|
for (int32_t i = 0; i < numMoved; i++) {
|
2022-05-23 01:49:27 +00:00
|
|
|
elements->Set(thread, fromIndex + i, elements->Get(endIndex + i));
|
|
|
|
}
|
|
|
|
|
|
|
|
int32_t newLength = length - (endIndex - fromIndex);
|
|
|
|
vector->SetLength(newLength);
|
|
|
|
return JSTaggedValue::True();
|
|
|
|
}
|
|
|
|
|
|
|
|
JSHandle<JSAPIVector> JSAPIVector::SubVector(JSThread *thread, const JSHandle<JSAPIVector> &vector,
|
|
|
|
int32_t fromIndex, int32_t toIndex)
|
|
|
|
{
|
|
|
|
int32_t length = vector->GetSize();
|
|
|
|
if (fromIndex < 0 || toIndex < 0 || fromIndex >= length || toIndex >= length) {
|
|
|
|
THROW_RANGE_ERROR_AND_RETURN(thread, "the fromIndex or the toIndex is out-of-bounds",
|
|
|
|
JSHandle<JSAPIVector>());
|
|
|
|
}
|
|
|
|
if (toIndex <= fromIndex) {
|
|
|
|
THROW_RANGE_ERROR_AND_RETURN(thread, "the fromIndex cannot be less than or equal to toIndex",
|
|
|
|
JSHandle<JSAPIVector>());
|
|
|
|
}
|
|
|
|
|
|
|
|
int32_t newLength = toIndex - fromIndex;
|
|
|
|
JSHandle<JSAPIVector> subVector = thread->GetEcmaVM()->GetFactory()->NewJSAPIVector(newLength);
|
|
|
|
TaggedArray *elements = TaggedArray::Cast(vector->GetElements().GetTaggedObject());
|
|
|
|
|
|
|
|
subVector->SetLength(newLength);
|
|
|
|
for (int32_t i = 0; i < newLength; i++) {
|
|
|
|
subVector->Set(thread, i, elements->Get(fromIndex + i));
|
|
|
|
}
|
|
|
|
|
|
|
|
return subVector;
|
|
|
|
}
|
|
|
|
|
|
|
|
JSTaggedValue JSAPIVector::ToString(JSThread *thread, const JSHandle<JSAPIVector> &vector)
|
|
|
|
{
|
|
|
|
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
|
|
|
std::u16string sepHandle = std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> {}.from_bytes(",");
|
|
|
|
|
2022-05-25 07:13:55 +00:00
|
|
|
int32_t length = vector->GetSize();
|
2022-05-23 01:49:27 +00:00
|
|
|
std::u16string concatStr;
|
|
|
|
std::u16string concatStrNew;
|
|
|
|
JSMutableHandle<JSTaggedValue> element(thread, JSTaggedValue::Undefined());
|
2022-05-25 07:13:55 +00:00
|
|
|
for (int32_t k = 0; k < length; k++) {
|
2022-05-23 01:49:27 +00:00
|
|
|
std::u16string nextStr;
|
|
|
|
element.Update(Get(thread, vector, k));
|
|
|
|
if (!element->IsUndefined() && !element->IsNull()) {
|
|
|
|
JSHandle<EcmaString> nextStringHandle = JSTaggedValue::ToString(thread, element);
|
|
|
|
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
|
|
|
uint32_t nextLen = nextStringHandle->GetLength();
|
|
|
|
if (nextStringHandle->IsUtf16()) {
|
|
|
|
nextStr = base::StringHelper::Utf16ToU16String(nextStringHandle->GetDataUtf16(), nextLen);
|
|
|
|
} else {
|
|
|
|
nextStr = base::StringHelper::Utf8ToU16String(nextStringHandle->GetDataUtf8(), nextLen);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (k > 0) {
|
|
|
|
concatStrNew = base::StringHelper::Append(concatStr, sepHandle);
|
|
|
|
concatStr = base::StringHelper::Append(concatStrNew, nextStr);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
concatStr = base::StringHelper::Append(concatStr, nextStr);
|
|
|
|
}
|
|
|
|
|
|
|
|
char16_t *char16tData = concatStr.data();
|
|
|
|
auto *uint16tData = reinterpret_cast<uint16_t *>(char16tData);
|
2022-05-25 07:13:55 +00:00
|
|
|
uint32_t u16strSize = concatStr.size();
|
2022-05-23 01:49:27 +00:00
|
|
|
return factory->NewFromUtf16Literal(uint16tData, u16strSize).GetTaggedValue();
|
|
|
|
}
|
|
|
|
|
|
|
|
JSTaggedValue JSAPIVector::ForEach(JSThread *thread, const JSHandle<JSTaggedValue> &thisHandle,
|
|
|
|
const JSHandle<JSTaggedValue> &callbackFn,
|
|
|
|
const JSHandle<JSTaggedValue> &thisArg)
|
|
|
|
{
|
|
|
|
JSHandle<JSAPIVector> vector = JSHandle<JSAPIVector>::Cast(thisHandle);
|
|
|
|
int32_t length = vector->GetSize();
|
|
|
|
JSTaggedValue key = JSTaggedValue::Undefined();
|
|
|
|
JSMutableHandle<JSTaggedValue> kValue(thread, JSTaggedValue::Undefined());
|
2022-07-04 02:08:05 +00:00
|
|
|
const int32_t argsLength = NUM_MANDATORY_JSFUNC_ARGS;
|
2022-05-23 01:49:27 +00:00
|
|
|
JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
|
|
|
|
|
|
|
|
for (int32_t k = 0; k < length; k++) {
|
|
|
|
kValue.Update(Get(thread, vector, k));
|
|
|
|
key = JSTaggedValue(k);
|
2022-07-04 02:08:05 +00:00
|
|
|
EcmaRuntimeCallInfo *info =
|
2022-05-23 01:49:27 +00:00
|
|
|
EcmaInterpreter::NewRuntimeCallInfo(thread, callbackFn, thisArg, undefined, argsLength);
|
2022-07-04 02:08:05 +00:00
|
|
|
RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception());
|
|
|
|
info->SetCallArg(kValue.GetTaggedValue(), key, thisHandle.GetTaggedValue());
|
|
|
|
JSTaggedValue funcResult = JSFunction::Call(info);
|
2022-05-23 01:49:27 +00:00
|
|
|
RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, funcResult);
|
|
|
|
if (length != vector->GetSize()) { // prevent length change
|
|
|
|
length = vector->GetSize();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return JSTaggedValue::Undefined();
|
|
|
|
}
|
|
|
|
|
|
|
|
JSTaggedValue JSAPIVector::ReplaceAllElements(JSThread *thread, const JSHandle<JSTaggedValue> &thisHandle,
|
|
|
|
const JSHandle<JSTaggedValue> &callbackFn,
|
|
|
|
const JSHandle<JSTaggedValue> &thisArg)
|
|
|
|
{
|
|
|
|
JSHandle<JSAPIVector> vector = JSHandle<JSAPIVector>::Cast(thisHandle);
|
|
|
|
int32_t length = vector->GetSize();
|
|
|
|
JSTaggedValue key = JSTaggedValue::Undefined();
|
|
|
|
JSMutableHandle<JSTaggedValue> kValue(thread, JSTaggedValue::Undefined());
|
2022-07-04 02:08:05 +00:00
|
|
|
const int32_t argsLength = NUM_MANDATORY_JSFUNC_ARGS;
|
2022-05-23 01:49:27 +00:00
|
|
|
JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
|
|
|
|
|
|
|
|
for (int32_t k = 0; k < length; k++) {
|
|
|
|
kValue.Update(Get(thread, vector, k));
|
|
|
|
key = JSTaggedValue(k);
|
2022-07-04 02:08:05 +00:00
|
|
|
EcmaRuntimeCallInfo *info =
|
2022-05-23 01:49:27 +00:00
|
|
|
EcmaInterpreter::NewRuntimeCallInfo(thread, callbackFn, thisArg, undefined, argsLength);
|
2022-07-04 02:08:05 +00:00
|
|
|
RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception());
|
|
|
|
info->SetCallArg(kValue.GetTaggedValue(), key, thisHandle.GetTaggedValue());
|
|
|
|
JSTaggedValue funcResult = JSFunction::Call(info);
|
2022-05-23 01:49:27 +00:00
|
|
|
RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, funcResult);
|
|
|
|
if (length != vector->GetSize()) { // prevent length change
|
|
|
|
length = vector->GetSize();
|
|
|
|
}
|
|
|
|
vector->Set(thread, k, funcResult);
|
|
|
|
}
|
|
|
|
|
|
|
|
return JSTaggedValue::Undefined();
|
|
|
|
}
|
|
|
|
|
|
|
|
void JSAPIVector::GrowCapacity(JSThread *thread, const JSHandle<JSAPIVector> &vector, uint32_t minCapacity)
|
|
|
|
{
|
|
|
|
JSHandle<TaggedArray> elementData(thread, vector->GetElements());
|
|
|
|
ASSERT(!elementData->IsDictionaryMode());
|
|
|
|
uint32_t curCapacity = elementData->GetLength();
|
|
|
|
if (minCapacity > curCapacity) {
|
|
|
|
uint32_t oldCapacity = elementData->GetLength();
|
|
|
|
// 2 : 2 Capacity doubled
|
|
|
|
uint32_t newCapacity = oldCapacity * 2;
|
|
|
|
if (newCapacity < minCapacity)
|
|
|
|
newCapacity = minCapacity;
|
|
|
|
|
|
|
|
if (newCapacity > MAX_ARRAY_SIZE) {
|
|
|
|
newCapacity = (minCapacity > MAX_ARRAY_SIZE) ? MAX_VALUE : MAX_ARRAY_SIZE;
|
|
|
|
}
|
|
|
|
JSHandle<TaggedArray> newElements =
|
|
|
|
thread->GetEcmaVM()->GetFactory()->CopyArray(elementData, oldCapacity, newCapacity);
|
|
|
|
|
|
|
|
vector->SetElements(thread, newElements);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
JSTaggedValue JSAPIVector::Get(JSThread *thread, const JSHandle<JSAPIVector> &vector, int32_t index)
|
|
|
|
{
|
|
|
|
int32_t len = vector->GetSize();
|
|
|
|
if (index < 0 || index >= len) {
|
|
|
|
THROW_RANGE_ERROR_AND_RETURN(thread, "the index is out-of-bounds", JSTaggedValue::Exception());
|
|
|
|
}
|
|
|
|
|
|
|
|
TaggedArray *elements = TaggedArray::Cast(vector->GetElements().GetTaggedObject());
|
|
|
|
return elements->Get(index);
|
|
|
|
}
|
|
|
|
|
|
|
|
JSTaggedValue JSAPIVector::Set(JSThread *thread, int32_t index, const JSTaggedValue &value)
|
|
|
|
{
|
|
|
|
TaggedArray *elements = TaggedArray::Cast(GetElements().GetTaggedObject());
|
|
|
|
elements->Set(thread, index, value);
|
|
|
|
return JSTaggedValue::Undefined();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool JSAPIVector::Has(const JSTaggedValue &value) const
|
|
|
|
{
|
|
|
|
TaggedArray *elements = TaggedArray::Cast(GetElements().GetTaggedObject());
|
2022-05-25 07:13:55 +00:00
|
|
|
int32_t length = GetSize();
|
2022-05-23 01:49:27 +00:00
|
|
|
if (length == 0) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2022-05-25 07:13:55 +00:00
|
|
|
for (int32_t i = 0; i < length; i++) {
|
2022-05-23 01:49:27 +00:00
|
|
|
if (JSTaggedValue::SameValue(elements->Get(i), value)) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
JSHandle<TaggedArray> JSAPIVector::OwnKeys(JSThread *thread, const JSHandle<JSAPIVector> &obj)
|
|
|
|
{
|
2022-05-25 07:13:55 +00:00
|
|
|
int32_t length = obj->GetSize();
|
2022-05-23 01:49:27 +00:00
|
|
|
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
|
|
|
JSHandle<TaggedArray> keys = factory->NewTaggedArray(length);
|
|
|
|
|
2022-05-25 07:13:55 +00:00
|
|
|
for (int32_t i = 0; i < length; i++) {
|
2022-05-23 01:49:27 +00:00
|
|
|
keys->Set(thread, i, JSTaggedValue(i));
|
|
|
|
}
|
|
|
|
|
|
|
|
return keys;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool JSAPIVector::GetOwnProperty(JSThread *thread, const JSHandle<JSAPIVector> &obj,
|
2022-06-02 01:11:52 +00:00
|
|
|
const JSHandle<JSTaggedValue> &key)
|
2022-05-23 01:49:27 +00:00
|
|
|
{
|
|
|
|
uint32_t index = 0;
|
2022-06-02 01:11:52 +00:00
|
|
|
if (UNLIKELY(!JSTaggedValue::ToElementIndex(key.GetTaggedValue(), &index))) {
|
2022-05-23 01:49:27 +00:00
|
|
|
THROW_TYPE_ERROR_AND_RETURN(thread, "Can not obtain attributes of no-number type", false);
|
|
|
|
}
|
|
|
|
|
2022-05-25 07:13:55 +00:00
|
|
|
uint32_t length = static_cast<uint32_t>(obj->GetSize());
|
2022-05-23 01:49:27 +00:00
|
|
|
if (index >= length) {
|
|
|
|
THROW_RANGE_ERROR_AND_RETURN(thread, "GetOwnProperty index out-of-bounds", false);
|
|
|
|
}
|
2022-06-02 01:11:52 +00:00
|
|
|
|
|
|
|
JSAPIVector::Get(thread, obj, index);
|
|
|
|
RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false);
|
|
|
|
return true;
|
2022-05-23 01:49:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void JSAPIVector::TrimToCurrentLength(JSThread *thread, const JSHandle<JSAPIVector> &obj)
|
|
|
|
{
|
2022-05-25 07:13:55 +00:00
|
|
|
int32_t length = obj->GetSize();
|
2022-05-23 01:49:27 +00:00
|
|
|
TaggedArray *elements = TaggedArray::Cast(obj->GetElements().GetTaggedObject());
|
|
|
|
ASSERT(!elements->IsDictionaryMode());
|
|
|
|
elements->Trim(thread, length);
|
|
|
|
}
|
|
|
|
|
|
|
|
void JSAPIVector::Clear(const JSHandle<JSAPIVector> &obj)
|
|
|
|
{
|
|
|
|
obj->SetLength(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
JSHandle<JSAPIVector> JSAPIVector::Clone(JSThread *thread, const JSHandle<JSAPIVector> &obj)
|
|
|
|
{
|
|
|
|
uint32_t capacity = obj->GetCapacity();
|
|
|
|
int32_t length = obj->GetSize();
|
|
|
|
JSHandle<JSAPIVector> newVector = thread->GetEcmaVM()->GetFactory()->NewJSAPIVector(capacity);
|
|
|
|
newVector->SetLength(length);
|
|
|
|
for (int32_t i = 0; i < length; i++) {
|
|
|
|
newVector->Set(thread, i, Get(thread, obj, i)); // set or add
|
|
|
|
}
|
|
|
|
return newVector;
|
|
|
|
}
|
|
|
|
|
|
|
|
JSTaggedValue JSAPIVector::GetFirstElement(const JSHandle<JSAPIVector> &vector)
|
|
|
|
{
|
2022-05-25 07:13:55 +00:00
|
|
|
int32_t length = vector->GetSize();
|
2022-05-23 01:49:27 +00:00
|
|
|
if (length == 0) {
|
|
|
|
return JSTaggedValue::Undefined();
|
|
|
|
}
|
|
|
|
TaggedArray *elements = TaggedArray::Cast(vector->GetElements().GetTaggedObject());
|
|
|
|
return elements->Get(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
JSTaggedValue JSAPIVector::GetIteratorObj(JSThread *thread, const JSHandle<JSAPIVector> &obj)
|
|
|
|
{
|
|
|
|
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
|
|
|
JSHandle<JSAPIVectorIterator> iter(factory->NewJSAPIVectorIterator(obj));
|
|
|
|
|
|
|
|
return iter.GetTaggedValue();
|
|
|
|
}
|
|
|
|
} // namespace panda::ecmascript
|