mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2024-10-06 23:54:03 +00:00
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:
parent
37a1ef241e
commit
1fdce1fc8e
@ -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);
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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()
|
||||
|
@ -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());
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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,
|
||||
|
@ -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 O’s [[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 )
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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())));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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())));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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())
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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",
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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!!!");
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
18
test/moduletest/forin/BUILD.gn
Normal file
18
test/moduletest/forin/BUILD.gn
Normal 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 = []
|
||||
}
|
28
test/moduletest/forin/expect_output.txt
Normal file
28
test/moduletest/forin/expect_output.txt
Normal 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
|
105
test/moduletest/forin/forin.js
Normal file
105
test/moduletest/forin/forin.js
Normal 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;
|
||||
}
|
Loading…
Reference in New Issue
Block a user