diff options
author | Lars Knoll <lars.knoll@qt.io> | 2018-08-02 15:44:12 +0200 |
---|---|---|
committer | Lars Knoll <lars.knoll@qt.io> | 2018-08-02 20:25:41 +0000 |
commit | 0754f55287f4652382332bce42cd8c7d27846ef1 (patch) | |
tree | 490bbd3c5d66586a1427ba21dde76b2af65230dc /src/qml/jsapi/qjsvalueiterator.cpp | |
parent | 57640959320c87850315eae44c783803d113dc85 (diff) |
Introduce a new mechanism to iterate over object properties
The old advanceIterator schema was extremely ugly and in addition
not flexible enough to support the requirements for Proxy.ownKeys
and some of the methods in Object
Implemented a new scheme through a OwnPropertyKeys method in the
Object VTable that creates and returns an iterator object. Ported
QJSValueIterator and for-in to use the new mechanism.
There's still many places where we use the old ObjectIterator (that
relies on advanceIterator). Those will be ported in subsequent
commits.
Change-Id: I091a9bea9ff6b2b63630cc336814700757a718be
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'src/qml/jsapi/qjsvalueiterator.cpp')
-rw-r--r-- | src/qml/jsapi/qjsvalueiterator.cpp | 132 |
1 files changed, 58 insertions, 74 deletions
diff --git a/src/qml/jsapi/qjsvalueiterator.cpp b/src/qml/jsapi/qjsvalueiterator.cpp index 35c6ecc668..5add9d4b0a 100644 --- a/src/qml/jsapi/qjsvalueiterator.cpp +++ b/src/qml/jsapi/qjsvalueiterator.cpp @@ -47,19 +47,50 @@ QT_BEGIN_NAMESPACE QJSValueIteratorPrivate::QJSValueIteratorPrivate(const QJSValue &v) - : value(v) - , currentIndex(UINT_MAX) - , nextIndex(UINT_MAX) { + init(v); +} + +void QJSValueIteratorPrivate::init(const QJSValue &v) +{ + engine = nullptr; + QV4::ExecutionEngine *e = QJSValuePrivate::engine(&v); if (!e) return; + QV4::Object *o = QJSValuePrivate::getValue(&v)->objectValue(); + if (!o) + return; - QV4::Scope scope(e); - QV4::ScopedObject o(scope, QJSValuePrivate::getValue(&v)); - iterator.set(e, e->newForInIteratorObject(o)); + engine = e; + object = o; + iterator.reset(o->ownPropertyKeys()); + next(); } +void QJSValueIteratorPrivate::next() +{ + QV4::Object *o = object.as<QV4::Object>(); + if (!o) + return; + + QV4::PropertyKey key; + while (1) { + key = iterator->next(o); + if (!key.isSymbol()) + break; + } + currentKey = nextKey; + nextKey.set(engine, key.id()); +} + +bool QJSValueIteratorPrivate::isValid() const +{ + if (!engine) + return false; + QV4::Value *val = object.valueRef(); + return (val && val->isObject()); +} /*! \class QJSValueIterator @@ -98,17 +129,6 @@ QJSValueIteratorPrivate::QJSValueIteratorPrivate(const QJSValue &v) QJSValueIterator::QJSValueIterator(const QJSValue& object) : d_ptr(new QJSValueIteratorPrivate(object)) { - QV4::ExecutionEngine *v4 = d_ptr->iterator.engine(); - if (!v4) - return; - QV4::Scope scope(v4); - QV4::Scoped<QV4::ForInIteratorObject> it(scope, d_ptr->iterator.value()); - it->d()->it().flags = QV4::ObjectIterator::NoFlags; - QV4::ScopedString nm(scope); - QV4::Property nextProperty; - QV4::PropertyAttributes nextAttributes; - it->d()->it().next(nm.getRef(), &d_ptr->nextIndex, &nextProperty, &nextAttributes); - d_ptr->nextName.set(v4, nm.asReturnedValue()); } /*! @@ -127,10 +147,9 @@ QJSValueIterator::~QJSValueIterator() */ bool QJSValueIterator::hasNext() const { - QV4::Value *val = QJSValuePrivate::getValue(&d_ptr->value); - if (!val || !val->isObject()) + if (!d_ptr->isValid()) return false; - return d_ptr->nextName.as<QV4::String>() || d_ptr->nextIndex != UINT_MAX; + return QV4::PropertyKey::fromId(d_ptr->nextKey.value()).isValid(); } /*! @@ -143,23 +162,10 @@ bool QJSValueIterator::hasNext() const */ bool QJSValueIterator::next() { - QV4::Value *val = QJSValuePrivate::getValue(&d_ptr->value); - if (!val || !val->isObject()) - return false; - d_ptr->currentName = d_ptr->nextName; - d_ptr->currentIndex = d_ptr->nextIndex; - - QV4::ExecutionEngine *v4 = d_ptr->iterator.engine(); - if (!v4) + if (!d_ptr->isValid()) return false; - QV4::Scope scope(v4); - QV4::Scoped<QV4::ForInIteratorObject> it(scope, d_ptr->iterator.value()); - QV4::ScopedString nm(scope); - QV4::Property nextProperty; - QV4::PropertyAttributes nextAttributes; - it->d()->it().next(nm.getRef(), &d_ptr->nextIndex, &nextProperty, &nextAttributes); - d_ptr->nextName.set(v4, nm.asReturnedValue()); - return d_ptr->currentName.as<QV4::String>() || d_ptr->currentIndex != UINT_MAX; + d_ptr->next(); + return QV4::PropertyKey::fromId(d_ptr->currentKey.value()).isValid(); } /*! @@ -170,14 +176,14 @@ bool QJSValueIterator::next() */ QString QJSValueIterator::name() const { - QV4::Value *val = QJSValuePrivate::getValue(&d_ptr->value); - if (!val || !val->isObject()) + if (!d_ptr->isValid()) return QString(); - if (QV4::String *s = d_ptr->currentName.as<QV4::String>()) - return s->toQString(); - if (d_ptr->currentIndex < UINT_MAX) - return QString::number(d_ptr->currentIndex); - return QString(); + QV4::Scope scope(d_ptr->engine); + QV4::ScopedPropertyKey key(scope, QV4::PropertyKey::fromId(d_ptr->currentKey.value())); + if (!key->isValid()) + return QString(); + Q_ASSERT(!key->isSymbol()); + return key->toStringOrSymbol(d_ptr->engine)->toQString(); } @@ -189,23 +195,21 @@ QString QJSValueIterator::name() const */ QJSValue QJSValueIterator::value() const { - QV4::ExecutionEngine *engine = d_ptr->iterator.engine(); - if (!engine) + if (!d_ptr->isValid()) return QJSValue(); - QV4::Scope scope(engine); - QV4::ScopedObject obj(scope, QJSValuePrivate::getValue(&d_ptr->value)); - if (!obj) + QV4::Scope scope(d_ptr->engine); + QV4::ScopedPropertyKey key(scope, QV4::PropertyKey::fromId(d_ptr->currentKey.value())); + if (!key->isValid()) return QJSValue(); - if (!d_ptr->currentName.as<QV4::String>() && d_ptr->currentIndex == UINT_MAX) - return QJSValue(); + QV4::ScopedObject obj(scope, d_ptr->object.asManaged()); + QV4::ScopedValue val(scope, obj->get(key)); - QV4::ScopedValue v(scope, d_ptr->currentIndex == UINT_MAX ? obj->get(d_ptr->currentName.as<QV4::String>()) : obj->get(d_ptr->currentIndex)); if (scope.hasException()) { - engine->catchException(); + scope.engine->catchException(); return QJSValue(); } - return QJSValue(engine, v->asReturnedValue()); + return QJSValue(scope.engine, val->asReturnedValue()); } @@ -216,27 +220,7 @@ QJSValue QJSValueIterator::value() const */ QJSValueIterator& QJSValueIterator::operator=(QJSValue& object) { - d_ptr->value = object; - d_ptr->currentIndex = UINT_MAX; - d_ptr->nextIndex = UINT_MAX; - d_ptr->currentName.clear(); - d_ptr->nextName.clear(); - QV4::ExecutionEngine *v4 = d_ptr->iterator.engine(); - if (!v4) { - d_ptr->iterator.clear(); - return *this; - } - - QV4::Scope scope(v4); - QV4::ScopedObject o(scope, QJSValuePrivate::getValue(&object)); - 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; - QV4::PropertyAttributes nextAttributes; - it->d()->it().next(nm.getRef(), &d_ptr->nextIndex, &nextProperty, &nextAttributes); - d_ptr->nextName.set(v4, nm.asReturnedValue()); + d_ptr->init(object); return *this; } |