Rename ForeachIterator to ForInIterator
As it's being used for for(... in ...) loops. Also add a ES6 compatible iterator interface to it, so that we can unify the handling of for-in and for-of. Change-Id: I264f88ed049484945f5ea7e8bdf0227187456ba2 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
This commit is contained in:
parent
cff55a7a0d
commit
4f086e3aac
|
@ -57,7 +57,7 @@ QJSValueIteratorPrivate::QJSValueIteratorPrivate(const QJSValue &v)
|
|||
|
||||
QV4::Scope scope(e);
|
||||
QV4::ScopedObject o(scope, QJSValuePrivate::getValue(&v));
|
||||
iterator.set(e, e->newForEachIteratorObject(o));
|
||||
iterator.set(e, e->newForInIteratorObject(o));
|
||||
}
|
||||
|
||||
|
||||
|
@ -102,7 +102,7 @@ QJSValueIterator::QJSValueIterator(const QJSValue& object)
|
|||
if (!v4)
|
||||
return;
|
||||
QV4::Scope scope(v4);
|
||||
QV4::Scoped<QV4::ForEachIteratorObject> it(scope, d_ptr->iterator.value());
|
||||
QV4::Scoped<QV4::ForInIteratorObject> it(scope, d_ptr->iterator.value());
|
||||
it->d()->it().flags = QV4::ObjectIterator::NoFlags;
|
||||
QV4::ScopedString nm(scope);
|
||||
QV4::Property nextProperty;
|
||||
|
@ -153,7 +153,7 @@ bool QJSValueIterator::next()
|
|||
if (!v4)
|
||||
return false;
|
||||
QV4::Scope scope(v4);
|
||||
QV4::Scoped<QV4::ForEachIteratorObject> it(scope, d_ptr->iterator.value());
|
||||
QV4::Scoped<QV4::ForInIteratorObject> it(scope, d_ptr->iterator.value());
|
||||
QV4::ScopedString nm(scope);
|
||||
QV4::Property nextProperty;
|
||||
QV4::PropertyAttributes nextAttributes;
|
||||
|
@ -229,8 +229,8 @@ QJSValueIterator& QJSValueIterator::operator=(QJSValue& object)
|
|||
|
||||
QV4::Scope scope(v4);
|
||||
QV4::ScopedObject o(scope, QJSValuePrivate::getValue(&object));
|
||||
d_ptr->iterator.set(v4, v4->newForEachIteratorObject(o));
|
||||
QV4::Scoped<QV4::ForEachIteratorObject> it(scope, d_ptr->iterator.value());
|
||||
d_ptr->iterator.set(v4, v4->newForInIteratorObject(o));
|
||||
QV4::Scoped<QV4::ForInIteratorObject> it(scope, d_ptr->iterator.value());
|
||||
it->d()->it().flags = QV4::ObjectIterator::NoFlags;
|
||||
QV4::ScopedString nm(scope);
|
||||
QV4::Property nextProperty;
|
||||
|
|
|
@ -415,6 +415,7 @@ ExecutionEngine::ExecutionEngine(QJSEngine *jsEngine)
|
|||
jsObjects[TypeError_Ctor] = memoryManager->allocate<TypeErrorCtor>(global);
|
||||
jsObjects[URIError_Ctor] = memoryManager->allocate<URIErrorCtor>(global);
|
||||
jsObjects[IteratorProto] = memoryManager->allocate<IteratorPrototype>();
|
||||
jsObjects[ForInIteratorProto] = memoryManager->allocObject<ForInIteratorPrototype>(newInternalClass(ForInIteratorPrototype::staticVTable(), iteratorPrototype()));
|
||||
jsObjects[ArrayIteratorProto] = memoryManager->allocObject<ArrayIteratorPrototype>(newInternalClass(ArrayIteratorPrototype::staticVTable(), iteratorPrototype()));
|
||||
jsObjects[StringIteratorProto] = memoryManager->allocObject<StringIteratorPrototype>(newInternalClass(StringIteratorPrototype::staticVTable(), iteratorPrototype()));
|
||||
|
||||
|
@ -438,6 +439,7 @@ ExecutionEngine::ExecutionEngine(QJSEngine *jsEngine)
|
|||
static_cast<URIErrorPrototype *>(uRIErrorPrototype())->init(this, uRIErrorCtor());
|
||||
|
||||
static_cast<IteratorPrototype *>(iteratorPrototype())->init(this);
|
||||
static_cast<ForInIteratorPrototype *>(forInIteratorPrototype())->init(this);
|
||||
static_cast<ArrayIteratorPrototype *>(arrayIteratorPrototype())->init(this);
|
||||
static_cast<StringIteratorPrototype *>(stringIteratorPrototype())->init(this);
|
||||
|
||||
|
@ -790,10 +792,10 @@ Heap::Object *ExecutionEngine::newVariantObject(const QVariant &v)
|
|||
return memoryManager->allocate<VariantObject>(v);
|
||||
}
|
||||
|
||||
Heap::Object *ExecutionEngine::newForEachIteratorObject(Object *o)
|
||||
Heap::Object *ExecutionEngine::newForInIteratorObject(Object *o)
|
||||
{
|
||||
Scope scope(this);
|
||||
ScopedObject obj(scope, memoryManager->allocate<ForEachIteratorObject>(o));
|
||||
ScopedObject obj(scope, memoryManager->allocate<ForInIteratorObject>(o));
|
||||
return obj->d();
|
||||
}
|
||||
|
||||
|
|
|
@ -190,6 +190,7 @@ public:
|
|||
ValueTypeProto,
|
||||
SignalHandlerProto,
|
||||
IteratorProto,
|
||||
ForInIteratorProto,
|
||||
ArrayIteratorProto,
|
||||
StringIteratorProto,
|
||||
|
||||
|
@ -274,6 +275,7 @@ public:
|
|||
Object *valueTypeWrapperPrototype() const { return reinterpret_cast<Object *>(jsObjects + ValueTypeProto); }
|
||||
Object *signalHandlerPrototype() const { return reinterpret_cast<Object *>(jsObjects + SignalHandlerProto); }
|
||||
Object *iteratorPrototype() const { return reinterpret_cast<Object *>(jsObjects + IteratorProto); }
|
||||
Object *forInIteratorPrototype() const { return reinterpret_cast<Object *>(jsObjects + ForInIteratorProto); }
|
||||
Object *arrayIteratorPrototype() const { return reinterpret_cast<Object *>(jsObjects + ArrayIteratorProto); }
|
||||
Object *stringIteratorPrototype() const { return reinterpret_cast<Object *>(jsObjects + StringIteratorProto); }
|
||||
|
||||
|
@ -489,7 +491,7 @@ public:
|
|||
|
||||
Heap::Object *newVariantObject(const QVariant &v);
|
||||
|
||||
Heap::Object *newForEachIteratorObject(Object *o);
|
||||
Heap::Object *newForInIteratorObject(Object *o);
|
||||
Heap::Object *newArrayIteratorObject(Object *o);
|
||||
|
||||
Heap::QmlContext *qmlContext() const;
|
||||
|
|
|
@ -42,9 +42,29 @@
|
|||
#include "qv4identifier_p.h"
|
||||
#include "qv4argumentsobject_p.h"
|
||||
#include "qv4string_p.h"
|
||||
#include "qv4iterator_p.h"
|
||||
|
||||
using namespace QV4;
|
||||
|
||||
void ForInIteratorPrototype::init(ExecutionEngine *)
|
||||
{
|
||||
defineDefaultProperty(QStringLiteral("next"), method_next, 0);
|
||||
}
|
||||
|
||||
ReturnedValue ForInIteratorPrototype::method_next(const FunctionObject *b, const Value *thisObject, const Value *, int)
|
||||
{
|
||||
const ForInIteratorObject *forIn = thisObject->as<ForInIteratorObject>();
|
||||
Q_ASSERT(forIn);
|
||||
Scope scope(b->engine());
|
||||
ScopedValue n(scope, forIn->nextPropertyName());
|
||||
bool done = false;
|
||||
if (n->asReturnedValue() == Encode::null()) {
|
||||
done = true;
|
||||
n = Primitive::undefinedValue();
|
||||
}
|
||||
return IteratorPrototype::createIterResultObject(scope.engine, n, done);
|
||||
}
|
||||
|
||||
void ObjectIterator::init(const Object *o)
|
||||
{
|
||||
object->setM(o ? o->m() : nullptr);
|
||||
|
@ -175,11 +195,11 @@ ReturnedValue ObjectIterator::nextPropertyNameAsString()
|
|||
}
|
||||
|
||||
|
||||
DEFINE_OBJECT_VTABLE(ForEachIteratorObject);
|
||||
DEFINE_OBJECT_VTABLE(ForInIteratorObject);
|
||||
|
||||
void Heap::ForEachIteratorObject::markObjects(Heap::Base *that, MarkStack *markStack)
|
||||
void Heap::ForInIteratorObject::markObjects(Heap::Base *that, MarkStack *markStack)
|
||||
{
|
||||
ForEachIteratorObject *o = static_cast<ForEachIteratorObject *>(that);
|
||||
ForInIteratorObject *o = static_cast<ForInIteratorObject *>(that);
|
||||
o->workArea[0].mark(markStack);
|
||||
o->workArea[1].mark(markStack);
|
||||
Object::markObjects(that, markStack);
|
||||
|
|
|
@ -111,7 +111,7 @@ private:
|
|||
};
|
||||
|
||||
namespace Heap {
|
||||
struct ForEachIteratorObject : Object {
|
||||
struct ForInIteratorObject : Object {
|
||||
void init(QV4::Object *o);
|
||||
ObjectIterator &it() { return *reinterpret_cast<ObjectIterator*>(&itData); }
|
||||
Value workArea[2];
|
||||
|
@ -123,15 +123,24 @@ private:
|
|||
|
||||
}
|
||||
|
||||
struct ForEachIteratorObject: Object {
|
||||
V4_OBJECT2(ForEachIteratorObject, Object)
|
||||
Q_MANAGED_TYPE(ForeachIteratorObject)
|
||||
struct ForInIteratorPrototype : Object
|
||||
{
|
||||
V4_PROTOTYPE(iteratorPrototype)
|
||||
void init(ExecutionEngine *engine);
|
||||
|
||||
ReturnedValue nextPropertyName() { return d()->it().nextPropertyNameAsString(); }
|
||||
static ReturnedValue method_next(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
|
||||
};
|
||||
|
||||
struct ForInIteratorObject: Object {
|
||||
V4_OBJECT2(ForInIteratorObject, Object)
|
||||
Q_MANAGED_TYPE(ForeachIteratorObject)
|
||||
V4_PROTOTYPE(forInIteratorPrototype)
|
||||
|
||||
ReturnedValue nextPropertyName() const { return d()->it().nextPropertyNameAsString(); }
|
||||
};
|
||||
|
||||
inline
|
||||
void Heap::ForEachIteratorObject::init(QV4::Object *o)
|
||||
void Heap::ForInIteratorObject::init(QV4::Object *o)
|
||||
{
|
||||
Object::init();
|
||||
it() = ObjectIterator(internalClass->engine, workArea, workArea + 1, o,
|
||||
|
|
|
@ -701,15 +701,15 @@ ReturnedValue Runtime::method_foreachIterator(ExecutionEngine *engine, const Val
|
|||
ScopedObject o(scope, (Object *)nullptr);
|
||||
if (!in.isNullOrUndefined())
|
||||
o = in.toObject(engine);
|
||||
return engine->newForEachIteratorObject(o)->asReturnedValue();
|
||||
return engine->newForInIteratorObject(o)->asReturnedValue();
|
||||
}
|
||||
|
||||
ReturnedValue Runtime::method_foreachNextPropertyName(const Value &foreach_iterator)
|
||||
{
|
||||
Q_ASSERT(foreach_iterator.isObject());
|
||||
|
||||
ForEachIteratorObject *it = static_cast<ForEachIteratorObject *>(foreach_iterator.objectValue());
|
||||
Q_ASSERT(it->as<ForEachIteratorObject>());
|
||||
ForInIteratorObject *it = static_cast<ForInIteratorObject *>(foreach_iterator.objectValue());
|
||||
Q_ASSERT(it->as<ForInIteratorObject>());
|
||||
|
||||
return it->nextPropertyName();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue