reason:optimize for in

description:optimize for in
issue:https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/I62QDI?from=project-issue

Signed-off-by: wupengyong <wupengyong@huawei.com>
Change-Id: I54fa0fa9401e5cfbd17db16705b58cb452474c89
This commit is contained in:
wupengyong 2022-11-24 15:55:30 +08:00
parent 37a1ef241e
commit 1fdce1fc8e
41 changed files with 563 additions and 230 deletions

View File

@ -1681,8 +1681,8 @@ void JSForInIterator::Dump(std::ostream &os) const
os << "\n";
os << " - WasVisited : " << GetWasVisited();
os << "\n";
os << " - VisitedKeys : ";
GetVisitedKeys().DumpTaggedValue(os);
os << " - VisitedObjs : ";
GetVisitedObjs().DumpTaggedValue(os);
os << "\n";
os << " - RemainingKeys : ";
GetRemainingKeys().DumpTaggedValue(os);
@ -4165,7 +4165,7 @@ void JSForInIterator::DumpForSnapshot(std::vector<std::pair<CString, JSTaggedVal
{
vec.push_back(std::make_pair(CString("Object"), GetObject()));
vec.push_back(std::make_pair(CString("WasVisited"), JSTaggedValue(GetWasVisited())));
vec.push_back(std::make_pair(CString("VisitedKeys"), GetVisitedKeys()));
vec.push_back(std::make_pair(CString("VisitedObjs"), GetVisitedObjs()));
vec.push_back(std::make_pair(CString("RemainingKeys"), GetRemainingKeys()));
JSObject::DumpForSnapshot(vec);
}

View File

@ -394,15 +394,12 @@ bool JSAPIArrayList::Has(const JSTaggedValue value) const
JSHandle<TaggedArray> JSAPIArrayList::OwnKeys(JSThread *thread, const JSHandle<JSAPIArrayList> &obj)
{
uint32_t length = obj->GetLength().GetArrayLength();
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
JSHandle<TaggedArray> keys = factory->NewTaggedArray(length);
return JSObject::GetOwnPropertyKeys(thread, JSHandle<JSObject>::Cast(obj));
}
for (uint32_t i = 0; i < length; i++) {
keys->Set(thread, i, JSTaggedValue(i));
}
return keys;
JSHandle<TaggedArray> JSAPIArrayList::OwnEnumKeys(JSThread *thread, const JSHandle<JSAPIArrayList> &obj)
{
return JSObject::GetOwnEnumPropertyKeys(thread, JSHandle<JSObject>::Cast(obj));
}
bool JSAPIArrayList::GetOwnProperty(JSThread *thread, const JSHandle<JSAPIArrayList> &obj,

View File

@ -69,6 +69,7 @@ public:
bool Has(const JSTaggedValue value) const;
static JSHandle<TaggedArray> OwnKeys(JSThread *thread, const JSHandle<JSAPIArrayList> &obj);
static JSHandle<TaggedArray> OwnEnumKeys(JSThread *thread, const JSHandle<JSAPIArrayList> &obj);
static bool GetOwnProperty(JSThread *thread, const JSHandle<JSAPIArrayList> &obj,
const JSHandle<JSTaggedValue> &key);
static OperationResult GetProperty(JSThread *thread, const JSHandle<JSAPIArrayList> &obj,

View File

@ -201,8 +201,6 @@ bool JSAPIDeque::Has(JSTaggedValue value) const
JSHandle<TaggedArray> JSAPIDeque::OwnKeys(JSThread *thread, const JSHandle<JSAPIDeque> &deque)
{
uint32_t length = deque->GetSize();
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
JSHandle<TaggedArray> keys = factory->NewTaggedArray(length);
JSHandle<TaggedArray> oldElements(thread, deque->GetElements());
ASSERT(!oldElements->IsDictionaryMode());
@ -210,18 +208,32 @@ JSHandle<TaggedArray> JSAPIDeque::OwnKeys(JSThread *thread, const JSHandle<JSAPI
uint32_t newCapacity = ComputeCapacity(oldCapacity);
uint32_t firstIndex = deque->GetFirst();
uint32_t lastIndex = deque->GetLast();
uint32_t size = deque->GetSize();
JSHandle<TaggedArray> newElements =
thread->GetEcmaVM()->GetFactory()->CopyDeque(oldElements, newCapacity, size, firstIndex, lastIndex);
thread->GetEcmaVM()->GetFactory()->CopyDeque(oldElements, newCapacity, length, firstIndex, lastIndex);
deque->SetFirst(0);
deque->SetLast(size);
deque->SetLast(length);
deque->SetElements(thread, newElements);
for (uint32_t i = 0; i < size; i++) {
keys->Set(thread, i, JSTaggedValue(i));
}
return JSObject::GetOwnPropertyKeys(thread, JSHandle<JSObject>::Cast(deque));
}
return keys;
JSHandle<TaggedArray> JSAPIDeque::OwnEnumKeys(JSThread *thread, const JSHandle<JSAPIDeque> &deque)
{
uint32_t length = deque->GetSize();
JSHandle<TaggedArray> oldElements(thread, deque->GetElements());
ASSERT(!oldElements->IsDictionaryMode());
uint32_t oldCapacity = oldElements->GetLength();
uint32_t newCapacity = ComputeCapacity(oldCapacity);
uint32_t firstIndex = deque->GetFirst();
uint32_t lastIndex = deque->GetLast();
JSHandle<TaggedArray> newElements =
thread->GetEcmaVM()->GetFactory()->CopyDeque(oldElements, newCapacity, length, firstIndex, lastIndex);
deque->SetFirst(0);
deque->SetLast(length);
deque->SetElements(thread, newElements);
return JSObject::GetOwnEnumPropertyKeys(thread, JSHandle<JSObject>::Cast(deque));
}
bool JSAPIDeque::GetOwnProperty(JSThread *thread, const JSHandle<JSAPIDeque> &deque,

View File

@ -49,6 +49,8 @@ public:
static JSHandle<TaggedArray> OwnKeys(JSThread *thread, const JSHandle<JSAPIDeque> &deque);
static JSHandle<TaggedArray> OwnEnumKeys(JSThread *thread, const JSHandle<JSAPIDeque> &deque);
static bool GetOwnProperty(JSThread *thread, const JSHandle<JSAPIDeque> &deque, const JSHandle<JSTaggedValue> &key);
static OperationResult GetProperty(JSThread *thread, const JSHandle<JSAPIDeque> &obj,
const JSHandle<JSTaggedValue> &key);

View File

@ -157,14 +157,39 @@ bool JSAPIQueue::Has(JSTaggedValue value) const
JSHandle<TaggedArray> JSAPIQueue::OwnKeys(JSThread *thread, const JSHandle<JSAPIQueue> &obj)
{
uint32_t length = obj->GetLength().GetArrayLength();
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
JSHandle<TaggedArray> keys = factory->NewTaggedArray(length);
JSHandle<TaggedArray> oldElements(thread, obj->GetElements());
ASSERT(!oldElements->IsDictionaryMode());
uint32_t oldCapacity = oldElements->GetLength();
uint32_t newCapacity = ComputeCapacity(oldCapacity);
uint32_t front = obj->GetFront();
uint32_t tail = obj->GetTail();
JSHandle<TaggedArray> newElements =
thread->GetEcmaVM()->GetFactory()->CopyQueue(oldElements, newCapacity, front, tail);
obj->SetFront(0);
obj->SetTail(length);
obj->SetElements(thread, newElements);
for (uint32_t i = 0; i < length; i++) {
keys->Set(thread, i, JSTaggedValue(i));
}
return JSObject::GetOwnPropertyKeys(thread, JSHandle<JSObject>::Cast(obj));
}
return keys;
JSHandle<TaggedArray> JSAPIQueue::OwnEnumKeys(JSThread *thread, const JSHandle<JSAPIQueue> &obj)
{
uint32_t length = obj->GetLength().GetArrayLength();
JSHandle<TaggedArray> oldElements(thread, obj->GetElements());
ASSERT(!oldElements->IsDictionaryMode());
uint32_t oldCapacity = oldElements->GetLength();
uint32_t newCapacity = ComputeCapacity(oldCapacity);
uint32_t front = obj->GetFront();
uint32_t tail = obj->GetTail();
JSHandle<TaggedArray> newElements =
thread->GetEcmaVM()->GetFactory()->CopyQueue(oldElements, newCapacity, front, tail);
obj->SetFront(0);
obj->SetTail(length);
obj->SetElements(thread, newElements);
return JSObject::GetOwnEnumPropertyKeys(thread, JSHandle<JSObject>::Cast(obj));
}
bool JSAPIQueue::GetOwnProperty(JSThread *thread, const JSHandle<JSAPIQueue> &obj,

View File

@ -39,6 +39,7 @@ public:
bool Has(JSTaggedValue value) const;
static JSHandle<TaggedArray> OwnKeys(JSThread *thread, const JSHandle<JSAPIQueue> &obj);
static JSHandle<TaggedArray> OwnEnumKeys(JSThread *thread, const JSHandle<JSAPIQueue> &obj);
static bool GetOwnProperty(JSThread *thread, const JSHandle<JSAPIQueue> &obj, const JSHandle<JSTaggedValue> &key);
static OperationResult GetProperty(JSThread *thread, const JSHandle<JSAPIQueue> &obj,
const JSHandle<JSTaggedValue> &key);

View File

@ -128,15 +128,12 @@ bool JSAPIStack::Has(JSTaggedValue value) const
JSHandle<TaggedArray> JSAPIStack::OwnKeys(JSThread *thread, const JSHandle<JSAPIStack> &obj)
{
uint32_t top = static_cast<uint32_t>(obj->GetTop());
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
JSHandle<TaggedArray> keys = factory->NewTaggedArray(top + 1);
return JSObject::GetOwnPropertyKeys(thread, JSHandle<JSObject>::Cast(obj));
}
for (uint32_t i = 0; i < top + 1; i++) {
keys->Set(thread, i, JSTaggedValue(i));
}
return keys;
JSHandle<TaggedArray> JSAPIStack::OwnEnumKeys(JSThread *thread, const JSHandle<JSAPIStack> &obj)
{
return JSObject::GetOwnEnumPropertyKeys(thread, JSHandle<JSObject>::Cast(obj));
}
bool JSAPIStack::GetOwnProperty(JSThread *thread, const JSHandle<JSAPIStack> &obj,

View File

@ -34,6 +34,8 @@ public:
static JSHandle<TaggedArray> OwnKeys(JSThread *thread, const JSHandle<JSAPIStack> &obj);
static JSHandle<TaggedArray> OwnEnumKeys(JSThread *thread, const JSHandle<JSAPIStack> &obj);
static bool GetOwnProperty(JSThread *thread, const JSHandle<JSAPIStack> &obj, const JSHandle<JSTaggedValue> &key);
static OperationResult GetProperty(JSThread *thread, const JSHandle<JSAPIStack> &obj,
const JSHandle<JSTaggedValue> &key);

View File

@ -400,15 +400,12 @@ bool JSAPIVector::Has(const JSTaggedValue &value) const
JSHandle<TaggedArray> JSAPIVector::OwnKeys(JSThread *thread, const JSHandle<JSAPIVector> &obj)
{
int32_t length = obj->GetSize();
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
JSHandle<TaggedArray> keys = factory->NewTaggedArray(length);
return JSObject::GetOwnPropertyKeys(thread, JSHandle<JSObject>::Cast(obj));
}
for (int32_t i = 0; i < length; i++) {
keys->Set(thread, i, JSTaggedValue(i));
}
return keys;
JSHandle<TaggedArray> JSAPIVector::OwnEnumKeys(JSThread *thread, const JSHandle<JSAPIVector> &obj)
{
return JSObject::GetOwnEnumPropertyKeys(thread, JSHandle<JSObject>::Cast(obj));
}
bool JSAPIVector::GetOwnProperty(JSThread *thread, const JSHandle<JSAPIVector> &obj,

View File

@ -83,6 +83,7 @@ public:
bool Has(const JSTaggedValue &value) const;
static JSHandle<TaggedArray> OwnKeys(JSThread *thread, const JSHandle<JSAPIVector> &obj);
static JSHandle<TaggedArray> OwnEnumKeys(JSThread *thread, const JSHandle<JSAPIVector> &obj);
static bool GetOwnProperty(JSThread *thread, const JSHandle<JSAPIVector> &obj, const JSHandle<JSTaggedValue> &key);
static void TrimToCurrentLength(JSThread *thread, const JSHandle<JSAPIVector> &vector);

View File

@ -49,216 +49,99 @@ bool JSForInIterator::CheckObjProto(const JSThread *thread, const JSHandle<JSFor
env->GetObjectFunctionPrototypeClass().GetTaggedValue().GetTaggedObject()->GetClass();
}
void JSForInIterator::FastGetAllEnumKeys(const JSThread *thread, const JSHandle<JSForInIterator> &it,
const JSHandle<JSTaggedValue> &object)
void JSForInIterator::GetAllEnumKeys(JSThread *thread, const JSHandle<JSForInIterator> &it,
const JSHandle<JSTaggedValue> &object)
{
ASSERT(object->IsHeapObject());
JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
JSHandle<JSObject> obj(object);
uint32_t numOfElements = obj->GetNumberOfElements();
uint32_t numOfKeys = obj->GetNumberOfKeys();
JSHandle<TaggedQueue> remaining = factory->NewTaggedQueue(numOfElements + numOfKeys + 1);
if (numOfElements > 0) {
uint32_t elementIndex = 0;
if (obj->IsJSPrimitiveRef() && JSPrimitiveRef::Cast(*obj)->IsString()) {
elementIndex = JSPrimitiveRef::Cast(*obj)->GetStringLength();
for (uint32_t i = 0; i < elementIndex; i++) {
value.Update(factory->NewFromASCII(ToCString(i)).GetTaggedValue());
TaggedQueue::PushFixedQueue(thread, remaining, value);
JSMutableHandle<TaggedQueue> remaining(thread, thread->GlobalConstants()->GetEmptyTaggedQueue());
if (object->IsJSProxy()) {
JSHandle<TaggedArray> proxyArr = JSProxy::OwnPropertyKeys(thread, JSHandle<JSProxy>(object));
uint32_t length = proxyArr->GetLength();
for (uint32_t i = 0; i < length; i++) {
value.Update(proxyArr->Get(i));
PropertyDescriptor desc(thread);
JSProxy::GetOwnProperty(thread, JSHandle<JSProxy>(object), value, desc);
if (desc.IsEnumerable()) {
TaggedQueue *newQueue = TaggedQueue::Push(thread, remaining, value);
remaining.Update(JSTaggedValue(newQueue));
}
} else {
JSHandle<TaggedArray> elements(thread, obj->GetElements());
if (!elements->IsDictionaryMode()) {
uint32_t elementsLen = elements->GetLength();
for (uint32_t i = 0; i < elementsLen; ++i) {
if (!elements->Get(i).IsHole()) {
value.Update(factory->NewFromASCII(ToCString(i)).GetTaggedValue());
TaggedQueue::PushFixedQueue(thread, remaining, value);
}
}
} else {
JSHandle<NumberDictionary> numberDic(elements);
int size = numberDic->Size();
CVector<JSTaggedValue> sortArr;
for (int hashIndex = 0; hashIndex < size; hashIndex++) {
JSTaggedValue key = numberDic->GetKey(hashIndex);
if (!key.IsUndefined() && !key.IsHole()) {
PropertyAttributes attr = numberDic->GetAttributes(hashIndex);
if (attr.IsEnumerable()) {
sortArr.push_back(JSTaggedValue(static_cast<uint32_t>(key.GetInt())));
}
}
}
std::sort(sortArr.begin(), sortArr.end(), NumberDictionary::CompKey);
for (const auto &entry : sortArr) {
value.Update(factory->NewFromASCII(ToCString(entry.GetInt())).GetTaggedValue());
TaggedQueue::PushFixedQueue(thread, remaining, value);
}
}
} else {
JSHandle<TaggedArray> arr = JSTaggedValue::GetOwnEnumPropertyKeys(thread, object);
uint32_t len = arr->GetLength();
for (uint32_t i = 0; i < len; i++) {
value.Update(arr->Get(i));
if (value->IsString()) {
TaggedQueue *newQueue = TaggedQueue::Push(thread, remaining, value);
remaining.Update(JSTaggedValue(newQueue));
}
}
}
if (numOfKeys > 0) {
if (obj->IsJSGlobalObject()) {
GlobalDictionary *dict = GlobalDictionary::Cast(obj->GetProperties().GetTaggedObject());
int size = dict->Size();
CVector<std::pair<JSTaggedValue, uint32_t>> sortArr;
for (int hashIndex = 0; hashIndex < size; hashIndex++) {
JSTaggedValue key = dict->GetKey(hashIndex);
if (!key.IsUndefined() && !key.IsHole()) {
PropertyAttributes attr = dict->GetAttributes(hashIndex);
if (attr.IsEnumerable()) {
std::pair<JSTaggedValue, uint32_t> pair(key, attr.GetOffset());
sortArr.emplace_back(pair);
}
if (it->GetHasVisitObjs()) {
JSMutableHandle<TaggedQueue> remained(thread, thread->GlobalConstants()->GetEmptyTaggedQueue());
JSMutableHandle<TaggedQueue> visited(thread, it->GetVisitedObjs());
uint32_t size = visited->Size();
while (!remaining->Empty()) {
JSHandle<JSTaggedValue> key(thread, remaining->Pop(thread));
bool has = false;
for (uint32_t i = 0; i < size; i++) {
value.Update(visited->Get(i));
PropertyDescriptor desc(thread);
has = JSTaggedValue::GetOwnProperty(thread, value, key, desc);
if (has) {
break;
}
}
std::sort(sortArr.begin(), sortArr.end(), GlobalDictionary::CompKey);
for (const auto &entry : sortArr) {
JSTaggedValue nameKey = entry.first;
if (nameKey.IsString()) {
value.Update(nameKey);
TaggedQueue::PushFixedQueue(thread, remaining, value);
}
}
} else {
JSHandle<TaggedArray> propertiesArr(thread, obj->GetProperties());
if (!propertiesArr->IsDictionaryMode()) {
JSHClass *jsHclass = obj->GetJSHClass();
JSTaggedValue enumCache = jsHclass->GetEnumCache();
if (!enumCache.IsNull()) {
JSHandle<TaggedArray> cache(thread, enumCache);
uint32_t length = cache->GetLength();
if (length != numOfKeys) {
JSHandle<LayoutInfo> layoutInfoHandle(thread, jsHclass->GetLayout());
for (uint32_t i = 0; i < numOfKeys; i++) {
JSTaggedValue key = layoutInfoHandle->GetKey(i);
if (key.IsString()) {
value.Update(key);
if (layoutInfoHandle->GetAttr(i).IsEnumerable()) {
TaggedQueue::PushFixedQueue(thread, remaining, value);
}
}
}
} else {
for (uint32_t i = 0; i < length; i++) {
JSTaggedValue key = cache->Get(i);
if (key.IsString()) {
value.Update(key);
TaggedQueue::PushFixedQueue(thread, remaining, value);
}
}
}
} else {
JSHandle<LayoutInfo> layoutInfoHandle(thread, jsHclass->GetLayout());
for (uint32_t i = 0; i < numOfKeys; i++) {
JSTaggedValue key = layoutInfoHandle->GetKey(i);
if (key.IsString()) {
value.Update(key);
if (layoutInfoHandle->GetAttr(i).IsEnumerable()) {
TaggedQueue::PushFixedQueue(thread, remaining, value);
}
}
}
}
} else {
JSHandle<NameDictionary> nameDic(propertiesArr);
int size = nameDic->Size();
CVector<std::pair<JSTaggedValue, PropertyAttributes>> sortArr;
for (int hashIndex = 0; hashIndex < size; hashIndex++) {
JSTaggedValue key = nameDic->GetKey(hashIndex);
if (key.IsString()) {
PropertyAttributes attr = nameDic->GetAttributes(hashIndex);
if (attr.IsEnumerable()) {
std::pair<JSTaggedValue, PropertyAttributes> pair(key, attr);
sortArr.emplace_back(pair);
}
}
}
std::sort(sortArr.begin(), sortArr.end(), NameDictionary::CompKey);
for (const auto &entry : sortArr) {
value.Update(entry.first);
TaggedQueue::PushFixedQueue(thread, remaining, value);
}
if (!has) {
TaggedQueue *newQueue = TaggedQueue::Push(thread, remained, key);
remained.Update(JSTaggedValue(newQueue));
}
}
it->SetRemainingKeys(thread, remained);
} else {
it->SetRemainingKeys(thread, remaining);
}
it->SetRemainingKeys(thread, remaining);
it->SetWasVisited(true);
}
void JSForInIterator::SlowGetAllEnumKeys(JSThread *thread, const JSHandle<JSForInIterator> &it,
const JSHandle<JSTaggedValue> &object)
{
JSMutableHandle<TaggedQueue> visited(thread, it->GetVisitedKeys());
JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
JSMutableHandle<TaggedQueue> remaining(thread, it->GetRemainingKeys());
JSHandle<TaggedArray> arr = JSTaggedValue::GetOwnPropertyKeys(thread, object);
uint32_t len = arr->GetLength();
for (uint32_t i = 0; i < len; i++) {
value.Update(arr->Get(i));
if (value->IsString()) {
TaggedQueue *newQueue = TaggedQueue::Push(thread, remaining, value);
remaining.Update(JSTaggedValue(newQueue));
}
}
it->SetRemainingKeys(thread, remaining);
it->SetVisitedKeys(thread, visited);
it->SetWasVisited(true);
object->GetTaggedObject()->GetClass()->SetHasDeleteProperty(false);
}
std::pair<JSTaggedValue, bool> JSForInIterator::NextInternal(JSThread *thread, const JSHandle<JSForInIterator> &it)
{
bool notModiObjProto = true;
notModiObjProto = CheckObjProto(thread, it);
while (true) {
JSHandle<JSTaggedValue> object(thread, it->GetObject());
if (object->IsNull() || object->IsUndefined()) {
return std::make_pair(JSTaggedValue::Undefined(), true);
}
if (!it->GetWasVisited()) {
if (object->IsJSObject() && notModiObjProto) {
FastGetAllEnumKeys(thread, it, object);
} else {
SlowGetAllEnumKeys(thread, it, object);
}
GetAllEnumKeys(thread, it, object);
}
JSHandle<TaggedQueue> remaining(thread, it->GetRemainingKeys());
JSMutableHandle<TaggedQueue> visited(thread, it->GetVisitedKeys());
while (!remaining->Empty()) {
ASSERT(object->IsHeapObject());
JSTaggedValue r = remaining->Pop(thread);
if (object->IsJSObject() && notModiObjProto) {
bool hasDelete = object->GetTaggedObject()->GetClass()->HasDeleteProperty();
if (object->IsJSObject() && !hasDelete) {
return std::make_pair(r, false);
}
JSHandle<JSTaggedValue> key(thread, r);
bool has_same = false;
uint32_t len = visited->Size();
for (uint32_t i = 0; i < len; i++) {
if (JSTaggedValue::SameValue(r, visited->Get(i))) {
has_same = true;
break;
}
}
if (has_same) {
continue;
}
PropertyDescriptor desc(thread);
bool has = JSTaggedValue::GetOwnProperty(thread, object, key, desc);
if (has) {
auto newQueue = JSTaggedValue(TaggedQueue::Push(thread, visited, key));
visited.Update(newQueue);
it->SetVisitedKeys(thread, newQueue);
if (desc.IsEnumerable()) {
return std::make_pair(key.GetTaggedValue(), false);
}
}
}
if (notModiObjProto) {
return std::make_pair(JSTaggedValue::Undefined(), true);
}
JSMutableHandle<TaggedQueue> visited(thread, it->GetVisitedObjs());
TaggedQueue *newQueue = TaggedQueue::Push(thread, visited, object);
visited.Update(JSTaggedValue(newQueue));
it->SetVisitedObjs(thread, visited);
JSTaggedValue proto = JSTaggedValue::GetPrototype(thread, object);
it->SetObject(thread, proto);
it->SetWasVisited(false);
it->SetHasVisitObjs(true);
}
}

View File

@ -33,15 +33,12 @@ public:
static bool CheckObjProto(const JSThread *thread, const JSHandle<JSForInIterator> &it);
static void FastGetAllEnumKeys(const JSThread *thread, const JSHandle<JSForInIterator> &it,
const JSHandle<JSTaggedValue> &object);
static void SlowGetAllEnumKeys(JSThread *thread, const JSHandle<JSForInIterator> &it,
const JSHandle<JSTaggedValue> &object);
static void GetAllEnumKeys(JSThread *thread, const JSHandle<JSForInIterator> &it,
const JSHandle<JSTaggedValue> &object);
static constexpr size_t OBJECT_OFFSET = JSObject::SIZE;
ACCESSORS(Object, OBJECT_OFFSET, VISITED_KEYS_OFFSET)
ACCESSORS(VisitedKeys, VISITED_KEYS_OFFSET, REMAINING_KEYS_OFFSET)
ACCESSORS(VisitedObjs, VISITED_KEYS_OFFSET, REMAINING_KEYS_OFFSET)
ACCESSORS(RemainingKeys, REMAINING_KEYS_OFFSET, BIT_FIELD_OFFSET)
ACCESSORS_BIT_FIELD(BitField, BIT_FIELD_OFFSET, LAST_OFFSET)
DEFINE_ALIGN_SIZE(LAST_OFFSET);
@ -49,6 +46,7 @@ public:
// define BitField
static constexpr size_t WAS_VISITED_BITS = 3;
FIRST_BIT_FIELD(BitField, WasVisited, bool, WAS_VISITED_BITS)
NEXT_BIT_FIELD(BitField, HasVisitObjs, bool, 1, WasVisited)
DECL_VISIT_OBJECT_FOR_JS_OBJECT(JSObject, OBJECT_OFFSET, BIT_FIELD_OFFSET)
DECL_DUMP()

View File

@ -137,6 +137,7 @@ void JSHClass::Initialize(const JSThread *thread, uint32_t size, JSType type, ui
SetObjectType(type);
SetExtensible(true);
SetIsPrototype(false);
SetHasDeleteProperty(false);
SetElementRepresentation(Representation::NONE);
SetTransitions(thread, JSTaggedValue::Undefined());
SetProtoChangeMarker(thread, JSTaggedValue::Null());

View File

@ -303,6 +303,7 @@ public:
using InlinedPropsStartBits = NumberOfPropsBits::NextField<uint32_t,
OFFSET_MAX_OBJECT_SIZE_IN_WORDS_WITHOUT_INLINED>; // 15
using ObjectSizeInWordsBits = InlinedPropsStartBits::NextField<uint32_t, OFFSET_MAX_OBJECT_SIZE_IN_WORDS>; // 30
using HasDeletePropertyBit = ObjectSizeInWordsBits::NextFlag;
static JSHClass *Cast(const TaggedObject *object);
@ -1486,6 +1487,16 @@ public:
}
}
inline void SetHasDeleteProperty(bool flag) const
{
HasDeletePropertyBit::Set<uint32_t>(flag, GetBitField1Addr());
}
inline bool HasDeleteProperty() const
{
uint32_t bits = GetBitField1();
return HasDeletePropertyBit::Decode(bits);
}
static constexpr size_t PROTOTYPE_OFFSET = TaggedObjectSize();
ACCESSORS(Proto, PROTOTYPE_OFFSET, LAYOUT_OFFSET);
ACCESSORS(Layout, LAYOUT_OFFSET, TRANSTIONS_OFFSET);
@ -1529,6 +1540,11 @@ private:
{
return reinterpret_cast<uint32_t *>(ToUintPtr(this) + BIT_FIELD_OFFSET);
}
uint32_t *GetBitField1Addr() const
{
return reinterpret_cast<uint32_t *>(ToUintPtr(this) + BIT_FIELD1_OFFSET);
}
friend class RuntimeStubs;
};
static_assert(JSHClass::BIT_FIELD_OFFSET % static_cast<uint8_t>(MemAlignment::MEM_ALIGN_OBJECT) == 0);

View File

@ -377,6 +377,30 @@ JSHandle<TaggedArray> JSObject::GetAllEnumKeys(const JSThread *thread, const JSH
return keyArray;
}
void JSObject::GetAllEnumKeys(const JSThread *thread, const JSHandle<JSObject> &obj, int offset,
const JSHandle<TaggedArray> &keyArray)
{
TaggedArray *array = TaggedArray::Cast(obj->GetProperties().GetTaggedObject());
uint32_t keys = 0;
if (!array->IsDictionaryMode()) {
JSHClass *jsHclass = obj->GetJSHClass();
int end = static_cast<int>(jsHclass->NumberOfProps());
if (end > 0) {
LayoutInfo::Cast(jsHclass->GetLayout().GetTaggedObject())
->GetAllEnumKeys(thread, end, offset, *keyArray, &keys, obj);
}
return;
}
if (obj->IsJSGlobalObject()) {
GlobalDictionary *dict = GlobalDictionary::Cast(obj->GetProperties().GetTaggedObject());
dict->GetEnumAllKeys(thread, offset, *keyArray, &keys);
return;
}
NameDictionary *dict = NameDictionary::Cast(obj->GetProperties().GetTaggedObject());
dict->GetAllEnumKeys(thread, offset, *keyArray, &keys);
}
void JSObject::GetAllElementKeys(JSThread *thread, const JSHandle<JSObject> &obj, int offset,
const JSHandle<TaggedArray> &keyArray)
{
@ -457,6 +481,33 @@ JSHandle<TaggedArray> JSObject::GetEnumElementKeys(JSThread *thread, const JSHan
return elementArray;
}
void JSObject::GetEnumElementKeys(JSThread *thread, const JSHandle<JSObject> &obj, int offset,
const JSHandle<TaggedArray> &keyArray)
{
uint32_t elementIndex = 0;
if (obj->IsJSPrimitiveRef() && JSPrimitiveRef::Cast(*obj)->IsString()) {
elementIndex = JSPrimitiveRef::Cast(*obj)->GetStringLength() + static_cast<uint32_t>(offset);
for (uint32_t i = static_cast<uint32_t>(offset); i < elementIndex; ++i) {
auto key = base::NumberHelper::NumberToString(thread, JSTaggedValue(i));
keyArray->Set(thread, i, key);
}
}
JSHandle<TaggedArray> elements(thread, obj->GetElements());
if (!elements->IsDictionaryMode()) {
uint32_t elementsLen = elements->GetLength();
for (uint32_t i = 0, j = elementIndex; i < elementsLen; ++i) {
if (!elements->Get(i).IsHole()) {
auto key = base::NumberHelper::NumberToString(thread, JSTaggedValue(i));
keyArray->Set(thread, j++, key);
}
}
} else {
uint32_t keys = 0;
NumberDictionary::GetAllEnumKeys(thread, JSHandle<NumberDictionary>(elements), elementIndex, keyArray, &keys);
}
}
uint32_t JSObject::GetNumberOfKeys()
{
DISALLOW_GARBAGE_COLLECTION;
@ -805,6 +856,7 @@ bool JSObject::DeleteProperty(JSThread *thread, const JSHandle<JSObject> &obj, c
// 6. Return false.
if (op.IsConfigurable()) {
op.DeletePropertyInHolder();
obj->GetClass()->SetHasDeleteProperty(true);
return true;
}
return false;
@ -1123,6 +1175,21 @@ JSHandle<TaggedArray> JSObject::GetOwnPropertyKeys(JSThread *thread, const JSHan
return keyArray;
}
JSHandle<TaggedArray> JSObject::GetOwnEnumPropertyKeys(JSThread *thread, const JSHandle<JSObject> &obj)
{
[[maybe_unused]] uint32_t elementIndex = 0;
uint32_t numOfElements = obj->GetNumberOfElements();
uint32_t keyLen = numOfElements + obj->GetNumberOfKeys();
JSHandle<TaggedArray> keyArray = thread->GetEcmaVM()->GetFactory()->NewTaggedArray(keyLen);
if (numOfElements > 0) {
GetEnumElementKeys(thread, obj, 0, keyArray);
}
GetAllEnumKeys(thread, obj, static_cast<int32_t>(numOfElements), keyArray);
return keyArray;
}
JSHandle<JSObject> JSObject::ObjectCreate(JSThread *thread, const JSHandle<JSObject> &proto)
{
JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();

View File

@ -500,6 +500,8 @@ public:
// [[OwnPropertyKeys]]
static JSHandle<TaggedArray> GetOwnPropertyKeys(JSThread *thread, const JSHandle<JSObject> &obj);
static JSHandle<TaggedArray> GetOwnEnumPropertyKeys(JSThread *thread, const JSHandle<JSObject> &obj);
// 9.1.13 ObjectCreate
static JSHandle<JSObject> ObjectCreate(JSThread *thread, const JSHandle<JSObject> &proto);
@ -575,8 +577,12 @@ public:
static JSHandle<TaggedArray> GetEnumElementKeys(JSThread *thread, const JSHandle<JSObject> &obj, int offset,
uint32_t numOfElements, uint32_t *keys);
static void GetEnumElementKeys(JSThread *thread, const JSHandle<JSObject> &obj, int offset,
const JSHandle<TaggedArray> &keyArray);
static JSHandle<TaggedArray> GetAllEnumKeys(const JSThread *thread, const JSHandle<JSObject> &obj, int offset,
uint32_t numOfKeys, uint32_t *keys);
static void GetAllEnumKeys(const JSThread *thread, const JSHandle<JSObject> &obj, int offset,
const JSHandle<TaggedArray> &keyArray);
static void AddAccessor(JSThread *thread, const JSHandle<JSTaggedValue> &obj, const JSHandle<JSTaggedValue> &key,
const JSHandle<AccessorData> &value, PropertyAttributes attr);

View File

@ -845,6 +845,21 @@ JSHandle<TaggedArray> JSTaggedValue::GetOwnPropertyKeys(JSThread *thread, const
return JSObject::GetOwnPropertyKeys(thread, JSHandle<JSObject>(obj));
}
JSHandle<TaggedArray> JSTaggedValue::GetOwnEnumPropertyKeys(JSThread *thread, const JSHandle<JSTaggedValue> &obj)
{
ASSERT(!obj->IsJSProxy());
if (obj->IsTypedArray()) {
return JSTypedArray::OwnEnumPropertyKeys(thread, obj);
}
if (obj->IsSpecialContainer()) {
return GetOwnContainerEnumPropertyKeys(thread, obj);
}
if (obj->IsModuleNamespace()) {
return ModuleNamespace::OwnEnumPropertyKeys(thread, obj);
}
return JSObject::GetOwnEnumPropertyKeys(thread, JSHandle<JSObject>(obj));
}
// 7.3.10 HasProperty (O, P)
bool JSTaggedValue::HasProperty(JSThread *thread, const JSHandle<JSTaggedValue> &obj,
const JSHandle<JSTaggedValue> &key)
@ -1047,6 +1062,43 @@ JSHandle<TaggedArray> JSTaggedValue::GetOwnContainerPropertyKeys(JSThread *threa
return thread->GetEcmaVM()->GetFactory()->EmptyArray();
}
JSHandle<TaggedArray> JSTaggedValue::GetOwnContainerEnumPropertyKeys(JSThread *thread,
const JSHandle<JSTaggedValue> &obj)
{
auto *hclass = obj->GetTaggedObject()->GetClass();
JSType jsType = hclass->GetObjectType();
switch (jsType) {
case JSType::JS_API_QUEUE: {
return JSAPIQueue::OwnEnumKeys(thread, JSHandle<JSAPIQueue>::Cast(obj));
}
case JSType::JS_API_DEQUE: {
return JSAPIDeque::OwnEnumKeys(thread, JSHandle<JSAPIDeque>::Cast(obj));
}
case JSType::JS_API_LIST: {
return JSAPIList::OwnKeys(thread, JSHandle<JSAPIList>::Cast(obj));
}
case JSType::JS_API_LINKED_LIST: {
return JSAPILinkedList::OwnKeys(thread, JSHandle<JSAPILinkedList>::Cast(obj));
}
case JSType::JS_API_VECTOR:
case JSType::JS_API_STACK:
case JSType::JS_API_ARRAY_LIST:
case JSType::JS_API_PLAIN_ARRAY:
case JSType::JS_API_HASH_MAP:
case JSType::JS_API_HASH_SET:
case JSType::JS_API_LIGHT_WEIGHT_MAP:
case JSType::JS_API_LIGHT_WEIGHT_SET:
case JSType::JS_API_TREE_MAP:
case JSType::JS_API_TREE_SET: {
return JSObject::GetOwnEnumPropertyKeys(thread, JSHandle<JSObject>(obj));
}
default: {
UNREACHABLE();
}
}
return thread->GetEcmaVM()->GetFactory()->EmptyArray();
}
bool JSTaggedValue::GetContainerProperty(JSThread *thread, const JSHandle<JSTaggedValue> &obj,
const JSHandle<JSTaggedValue> &key, PropertyDescriptor &desc)
{

View File

@ -477,6 +477,7 @@ public:
static JSTaggedValue GetPrototype(JSThread *thread, const JSHandle<JSTaggedValue> &obj);
static bool PreventExtensions(JSThread *thread, const JSHandle<JSTaggedValue> &obj);
static JSHandle<TaggedArray> GetOwnPropertyKeys(JSThread *thread, const JSHandle<JSTaggedValue> &obj);
static JSHandle<TaggedArray> GetOwnEnumPropertyKeys(JSThread *thread, const JSHandle<JSTaggedValue> &obj);
static bool HasProperty(JSThread *thread, const JSHandle<JSTaggedValue> &obj, const JSHandle<JSTaggedValue> &key);
static bool HasProperty(JSThread *thread, const JSHandle<JSTaggedValue> &obj, uint32_t key);
static bool HasOwnProperty(JSThread *thread, const JSHandle<JSTaggedValue> &obj,
@ -692,6 +693,7 @@ private:
static bool HasContainerProperty(JSThread *thread, const JSHandle<JSTaggedValue> &obj,
const JSHandle<JSTaggedValue> &key);
static JSHandle<TaggedArray> GetOwnContainerPropertyKeys(JSThread *thread, const JSHandle<JSTaggedValue> &obj);
static JSHandle<TaggedArray> GetOwnContainerEnumPropertyKeys(JSThread *thread, const JSHandle<JSTaggedValue> &obj);
static bool GetContainerProperty(JSThread *thread, const JSHandle<JSTaggedValue> &obj,
const JSHandle<JSTaggedValue> &key, PropertyDescriptor &desc);
static OperationResult GetJSAPIProperty(JSThread *thread, const JSHandle<JSTaggedValue> &obj,

View File

@ -322,6 +322,42 @@ JSHandle<TaggedArray> JSTypedArray::OwnPropertyKeys(JSThread *thread, const JSHa
return factory->CopyArray(nameList, length, copyLength);
}
JSHandle<TaggedArray> JSTypedArray::OwnEnumPropertyKeys(JSThread *thread, const JSHandle<JSTaggedValue> &typedarray)
{
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
// 1. Let keys be a new empty List.
// 2. Assert: O is an Object that has [[ViewedArrayBuffer]], [[ArrayLength]], [[ByteOffset]], and
// [[TypedArrayName]] internal slots.
// 3. Let len be the value of Os [[ArrayLength]] internal slot.
JSHandle<JSTypedArray> arrayObj(typedarray);
JSHandle<TaggedArray> objKeys = JSObject::GetOwnEnumPropertyKeys(thread, JSHandle<JSObject>::Cast(arrayObj));
uint32_t objKeysLen = objKeys->GetLength();
uint32_t bufferKeysLen = arrayObj->GetArrayLength();
uint32_t length = objKeysLen + bufferKeysLen;
JSHandle<TaggedArray> nameList = factory->NewTaggedArray(length);
// 4. For each integer i starting with 0 such that i < len, in ascending order,
// a. Add ToString(i) as the last element of keys.
uint32_t copyLength = 0;
for (uint32_t k = 0; k < bufferKeysLen; k++) {
auto key = base::NumberHelper::NumberToString(thread, JSTaggedValue(k));
nameList->Set(thread, copyLength, key);
copyLength++;
}
// 5. For each own property key P of O such that Type(P) is String and P is not an integer index, in
// property creation order
// a. Add P as the last element of keys.
for (uint32_t i = 0; i < objKeysLen; i++) {
JSTaggedValue key = objKeys->Get(i);
nameList->Set(thread, copyLength, key);
copyLength++;
}
// 7. Return keys.
return factory->CopyArray(nameList, length, copyLength);
}
// 9.4.5.7 IntegerIndexedObjectCreate (prototype, internalSlotsList)
// 9.4.5.8 IntegerIndexedElementGet ( O, index )

View File

@ -77,6 +77,7 @@ public:
const JSHandle<JSTaggedValue> &key);
// 9.4.5.6 [[OwnPropertyKeys]] ( )
static JSHandle<TaggedArray> OwnPropertyKeys(JSThread *thread, const JSHandle<JSTaggedValue> &typedarray);
static JSHandle<TaggedArray> OwnEnumPropertyKeys(JSThread *thread, const JSHandle<JSTaggedValue> &typedarray);
// 9.4.5.7 IntegerIndexedObjectCreate (prototype, internalSlotsList)
// 9.4.5.8 IntegerIndexedElementGet ( O, index )
static OperationResult IntegerIndexedElementGet(JSThread *thread, const JSHandle<JSTaggedValue> &typedarray,

View File

@ -108,7 +108,6 @@ OperationResult ModuleNamespace::GetProperty(JSThread *thread, const JSHandle<JS
}
return OperationResult(thread, result, PropertyMetaData(true));
}
JSHandle<TaggedArray> ModuleNamespace::OwnPropertyKeys(JSThread *thread, const JSHandle<JSTaggedValue> &obj)
{
ASSERT(obj->IsModuleNamespace());
@ -128,6 +127,25 @@ JSHandle<TaggedArray> ModuleNamespace::OwnPropertyKeys(JSThread *thread, const J
return result;
}
JSHandle<TaggedArray> ModuleNamespace::OwnEnumPropertyKeys(JSThread *thread, const JSHandle<JSTaggedValue> &obj)
{
ASSERT(obj->IsModuleNamespace());
// 1. Let exports be a copy of O.[[Exports]].
JSHandle<ModuleNamespace> moduleNamespace = JSHandle<ModuleNamespace>::Cast(obj);
JSHandle<JSTaggedValue> exports(thread, moduleNamespace->GetExports());
JSHandle<TaggedArray> exportsArray = JSArray::ToTaggedArray(thread, exports);
if (!moduleNamespace->ValidateKeysAvailable(thread, exportsArray)) {
return exportsArray;
}
// 2. Let symbolKeys be ! OrdinaryOwnPropertyKeys(O).
JSHandle<TaggedArray> symbolKeys = JSObject::GetOwnEnumPropertyKeys(thread, JSHandle<JSObject>(obj));
// 3. Append all the entries of symbolKeys to the end of exports.
JSHandle<TaggedArray> result = TaggedArray::Append(thread, exportsArray, symbolKeys);
// 4. Return exports.
return result;
}
bool ModuleNamespace::PreventExtensions()
{
return true;

View File

@ -51,6 +51,8 @@ public:
// 9.4.6.10[[OwnPropertyKeys]]
static JSHandle<TaggedArray> OwnPropertyKeys(JSThread *thread, const JSHandle<JSTaggedValue> &proxy);
static JSHandle<TaggedArray> OwnEnumPropertyKeys(JSThread *thread, const JSHandle<JSTaggedValue> &obj);
bool ValidateKeysAvailable(JSThread *thread, const JSHandle<TaggedArray> &exports);
static constexpr size_t MODULE_OFFSET = JSObject::SIZE;

View File

@ -639,7 +639,7 @@ JSHandle<JSForInIterator> ObjectFactory::NewJSForinIterator(const JSHandle<JSTag
JSHandle<JSForInIterator> it = JSHandle<JSForInIterator>::Cast(NewJSObject(hclass));
it->SetObject(thread_, obj);
it->SetVisitedKeys(thread_, thread_->GlobalConstants()->GetEmptyTaggedQueue());
it->SetVisitedObjs(thread_, thread_->GlobalConstants()->GetEmptyTaggedQueue());
it->SetRemainingKeys(thread_, thread_->GlobalConstants()->GetEmptyTaggedQueue());
it->ClearBitField();
return it;

View File

@ -130,10 +130,9 @@ JSHandle<TaggedArray> TaggedList<Derived>::OwnKeys(JSThread *thread, const JSHan
JSHandle<TaggedArray> keys = factory->NewTaggedArray(length);
for (uint32_t i = 0; i < length; i++) {
JSTaggedValue elementData = JSTaggedValue(i);
keys->Set(thread, i, elementData);
auto key = base::NumberHelper::NumberToString(thread, JSTaggedValue(i));
keys->Set(thread, i, key);
}
return keys;
}

View File

@ -631,7 +631,8 @@ HWTEST_F_L0(JSAPIArrayListTest, OwnKeys)
JSHandle<TaggedArray> keys = JSAPIArrayList::OwnKeys(thread, arrayList);
uint32_t length = arrayList->GetLength().GetArrayLength();
for (uint32_t i = 0; i < length; i++) {
EXPECT_EQ(keys->Get(i), JSTaggedValue(i));
ASSERT_TRUE(EcmaStringAccessor::StringsAreEqual(*(base::NumberHelper::NumberToString(thread, JSTaggedValue(i))),
EcmaString::Cast(keys->Get(i).GetTaggedObject())));
}
}

View File

@ -278,7 +278,8 @@ HWTEST_F_L0(JSAPIDequeTest, OwnKeys)
EXPECT_TRUE(keyArray->GetClass()->IsTaggedArray());
EXPECT_TRUE(keyArray->GetLength() == elementsNums);
for (uint32_t i = 0; i < elementsNums; i++) {
EXPECT_EQ(keyArray->Get(i), toor->Get(i));
ASSERT_TRUE(EcmaStringAccessor::StringsAreEqual(*(base::NumberHelper::NumberToString(thread, JSTaggedValue(i))),
EcmaString::Cast(keyArray->Get(i).GetTaggedObject())));
}
}
} // namespace panda::test

View File

@ -440,7 +440,8 @@ HWTEST_F_L0(JSAPILinkedListTest, OwnKeys)
EXPECT_TRUE(keyArray->GetClass()->IsTaggedArray());
EXPECT_TRUE(keyArray->GetLength() == elementsNums);
for (uint32_t i = 0; i < elementsNums; i++) {
EXPECT_EQ(keyArray->Get(i), JSTaggedValue(i));
ASSERT_TRUE(EcmaStringAccessor::StringsAreEqual(*(base::NumberHelper::NumberToString(thread, JSTaggedValue(i))),
EcmaString::Cast(keyArray->Get(i).GetTaggedObject())));
}
}
} // namespace panda::test

View File

@ -411,7 +411,8 @@ HWTEST_F_L0(JSAPIListTest, OwnKeys)
EXPECT_TRUE(keyArray->GetClass()->IsTaggedArray());
EXPECT_TRUE(keyArray->GetLength() == elementsNums);
for (uint32_t i = 0; i < elementsNums; i++) {
EXPECT_EQ(keyArray->Get(i), JSTaggedValue(i));
ASSERT_TRUE(EcmaStringAccessor::StringsAreEqual(*(base::NumberHelper::NumberToString(thread, JSTaggedValue(i))),
EcmaString::Cast(keyArray->Get(i).GetTaggedObject())));
}
}
} // namespace panda::test

View File

@ -164,7 +164,8 @@ HWTEST_F_L0(JSAPIQueueTest, OwnKeys)
JSHandle<TaggedArray> arrayKey = JSAPIQueue::OwnKeys(thread, jsQueue);
EXPECT_EQ(arrayKey->GetLength(), DEFAULT_LENGTH);
for (int32_t i = 0; i < static_cast<int32_t>(DEFAULT_LENGTH); i++) {
EXPECT_EQ(arrayKey->Get(i).GetInt(), i);
ASSERT_TRUE(EcmaStringAccessor::StringsAreEqual(*(base::NumberHelper::NumberToString(thread, JSTaggedValue(i))),
EcmaString::Cast(arrayKey->Get(i).GetTaggedObject())));
}
}

View File

@ -329,7 +329,8 @@ HWTEST_F_L0(JSAPIStackTest, OwnKeys)
EXPECT_TRUE(keyArray->GetClass()->IsTaggedArray());
EXPECT_TRUE(keyArray->GetLength() == elementsNums);
for (uint32_t i = 0; i < elementsNums; i++) {
EXPECT_EQ(keyArray->Get(i), JSTaggedValue(i));
ASSERT_TRUE(EcmaStringAccessor::StringsAreEqual(*(base::NumberHelper::NumberToString(thread, JSTaggedValue(i))),
EcmaString::Cast(keyArray->Get(i).GetTaggedObject())));
}
}
} // namespace panda::test

View File

@ -484,7 +484,10 @@ HWTEST_F_L0(JSAPIVectorTest, OwnKeys)
EXPECT_TRUE(keyArray->GetClass()->IsTaggedArray());
EXPECT_TRUE(keyArray->GetLength() == elementsNums);
for (uint32_t i = 0; i < elementsNums; i++) {
EXPECT_EQ(keyArray->Get(i), JSTaggedValue(i));
ASSERT_TRUE(EcmaStringAccessor::StringsAreEqual(
*(base::NumberHelper::NumberToString(thread, JSTaggedValue(i))),
EcmaString::Cast(keyArray->Get(i).GetTaggedObject())
));
}
}

View File

@ -30,6 +30,7 @@ group("ark_js_moduletest") {
"dynamicimport:dynamicimportAction",
"dyninstruction:dyninstructionAction",
"ecmastringtable:ecmastringtableAction",
"forin:forinAction",
"fortest:fortestAction",
"generator:generatorAction",
"getunmappedargs:getunmappedargsAction",
@ -95,6 +96,7 @@ group("ark_asm_test") {
"dynamicimport:dynamicimportAction",
"dyninstruction:dyninstructionAsmAction",
"ecmastringtable:ecmastringtableAsmAction",
"forin:forinAsmAction",
"fortest:fortestAsmAction",
"generator:generatorAsmAction",
"getunmappedargs:getunmappedargsAsmAction",
@ -153,6 +155,7 @@ group("ark_asm_single_step_test") {
"dynamicimport:dynamicimportAction",
"dyninstruction:dyninstructionAsmSingleStepAction",
"ecmastringtable:ecmastringtableAsmSingleStepAction",
"forin:forinAsmSingleStepAction",
"fortest:fortestAsmSingleStepAction",
"generator:generatorAsmSingleStepAction",
"getunmappedargs:getunmappedargsAsmSingleStepAction",

View File

@ -239,6 +239,17 @@ if (globalThis["ArkPrivate"] != undefined) {
print("ArrayList forEach throw error fail");
}
}
let test1 = new arrayList();
for (let k = 0; k < 10; k++) {
test1.add(k);
}
var keyName = "";
for (const key in test1) {
keyName += key;
}
if (keyName != "0123456789") {
print("ArrayList for in fail")
}
if (!flag) {
print("Test ArrayList success!!!");
} else {

View File

@ -132,6 +132,17 @@ if (globalThis["ArkPrivate"] != undefined) {
print("Deque forEach throw error fail");
}
}
let test1 = new Deque();
for (let k = 0; k < 10; k++) {
test1.insertEnd(k);
}
var keyName = "";
for (const key in test1) {
keyName += key;
}
if (keyName != "0123456789") {
print("Deque for in fail")
}
if (!flag) {
print("Test Deque success!!!");
} else {

View File

@ -114,7 +114,17 @@ if (globalThis["ArkPrivate"] != undefined) {
print("Queue forEach throw error fail");
}
}
let test1 = new Queue();
for (let k = 0; k < 10; k++) {
test1.add(k);
}
var keyName = "";
for (const key in test1) {
keyName += key;
}
if (keyName != "0123456789") {
print("Queue for in fail")
}
map.forEach(elements);
if (!flag) {
print("Test Queue success!!!");

View File

@ -113,6 +113,17 @@ if (globalThis["ArkPrivate"] != undefined) {
print("Stack forEach throw error fail");
}
}
let test1 = new Stack();
for (let k = 0; k < 10; k++) {
test1.push(k);
}
var keyName = "";
for (const key in test1) {
keyName += key;
}
if (keyName != "0123456789") {
print("Stack for in fail")
}
if (!flag) {
print("Test Stack success!!!");
} else {

View File

@ -294,6 +294,17 @@ if (globalThis["ArkPrivate"] != undefined) {
}
}
map.forEach(elements);
let test1 = new FastVector();
for (let k = 0; k < 10; k++) {
test1.add(k);
}
var keyName = "";
for (const key in test1) {
keyName += key;
}
if (keyName != "0123456789") {
print("Vector for in fail")
}
if (!flag) {
print("Test Vector success!!!");
} else {

View File

@ -0,0 +1,18 @@
# 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.
import("//arkcompiler/ets_runtime/test/test_helper.gni")
host_moduletest_action("forin") {
deps = []
}

View File

@ -0,0 +1,28 @@
# 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.
1
wode
1
3
wode
1
wode
_secret
0
1
2
hhh
0
1
2

View File

@ -0,0 +1,105 @@
/*
* 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.
*/
/*
* @tc.name:builtins
* @tc.desc:test builtins
* @tc.type: FUNC
* @tc.require: issueI5NO8G
*/
var arrayLong = {"1" : "fds", "wode" : "fff"};
Object.defineProperty(arrayLong, "2", {
configurable:true,
enumerable:true,
value:"ggg",
writable:true
})
for (const key in arrayLong) {
print(key);
delete arrayLong[2];
}
Object.defineProperty(arrayLong, "3", {
configurable:true,
enumerable:true,
value:"ggg",
writable:true
})
for (const key in arrayLong) {
print(key);
Object.defineProperty(arrayLong, "3", {
configurable:true,
enumerable:false,
value:"fff",
writable:true
})
}
Object.defineProperty(arrayLong, "4", {
configurable:true,
enumerable:false,
value:"ggg",
writable:true
})
for (const key in arrayLong) {
print(key);
Object.defineProperty(arrayLong, "4", {
configurable:true,
enumerable:true,
value:"fff",
writable:true
})
arrayLong.sss = "fds";
}
const targetObj = {
_secret: 'easily scared',
eyeCount: 4
};
Object.defineProperty(targetObj, "wode", {
configurable:true,
enumerable:false,
value:"ggg",
writable:true
})
const proxy_has = new Proxy(targetObj, {
has: (target, key) => {
print("key==",key)
if (key.includes('_')) {
return false;
}
return key in target;
}
})
for (const key in proxy_has) {
print(key);
delete proxy_has.eyeCount;
}
var view = new Int16Array(3);
view[1] = 23;
view[2] = 45;
view[3] = 67;
view.hhh = "wode";
for (const key in view) {
print(key);
}
for (const key in view) {
print(key);
delete view.hhh;
}