aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/qml
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2018-08-02 15:44:12 +0200
committerLars Knoll <lars.knoll@qt.io>2018-08-02 20:25:41 +0000
commit0754f55287f4652382332bce42cd8c7d27846ef1 (patch)
tree490bbd3c5d66586a1427ba21dde76b2af65230dc /src/qml/qml
parent57640959320c87850315eae44c783803d113dc85 (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/qml')
-rw-r--r--src/qml/qml/qqmllistwrapper.cpp30
-rw-r--r--src/qml/qml/qqmllistwrapper_p.h1
-rw-r--r--src/qml/qml/qqmlvaluetypewrapper.cpp40
-rw-r--r--src/qml/qml/qqmlvaluetypewrapper_p.h1
-rw-r--r--src/qml/qml/v8/qqmlbuiltinfunctions.cpp9
-rw-r--r--src/qml/qml/v8/qqmlbuiltinfunctions_p.h1
6 files changed, 82 insertions, 0 deletions
diff --git a/src/qml/qml/qqmllistwrapper.cpp b/src/qml/qml/qqmllistwrapper.cpp
index 7c35f73e6c..d491cd6166 100644
--- a/src/qml/qml/qqmllistwrapper.cpp
+++ b/src/qml/qml/qqmllistwrapper.cpp
@@ -157,6 +157,36 @@ void QmlListWrapper::virtualAdvanceIterator(Managed *m, ObjectIterator *it, Valu
return QV4::Object::virtualAdvanceIterator(m, it, name, index, p, attrs);
}
+struct QmlListWrapperOwnPropertyKeyIterator : ObjectOwnPropertyKeyIterator
+{
+ ~QmlListWrapperOwnPropertyKeyIterator() override = default;
+ PropertyKey next(const Object *o, Property *pd = nullptr, PropertyAttributes *attrs = nullptr) override;
+
+};
+
+PropertyKey QmlListWrapperOwnPropertyKeyIterator::next(const Object *o, Property *pd, PropertyAttributes *attrs)
+{
+ const QmlListWrapper *w = static_cast<const QmlListWrapper *>(o);
+
+ quint32 count = w->d()->property().count ? w->d()->property().count(&w->d()->property()) : 0;
+ if (arrayIndex < count) {
+ uint index = arrayIndex;
+ ++arrayIndex;
+ if (attrs)
+ *attrs = QV4::Attr_Data;
+ if (pd)
+ pd->value = QV4::QObjectWrapper::wrap(w->engine(), w->d()->property().at(&w->d()->property(), index));
+ return PropertyKey::fromArrayIndex(index);
+ }
+
+ return ObjectOwnPropertyKeyIterator::next(o, pd, attrs);
+}
+
+OwnPropertyKeyIterator *QmlListWrapper::virtualOwnPropertyKeys(const Object *)
+{
+ return new QmlListWrapperOwnPropertyKeyIterator;
+}
+
void PropertyListPrototype::init(ExecutionEngine *)
{
defineDefaultProperty(QStringLiteral("push"), method_push, 1);
diff --git a/src/qml/qml/qqmllistwrapper_p.h b/src/qml/qml/qqmllistwrapper_p.h
index 2d6a0880e3..e78b779344 100644
--- a/src/qml/qml/qqmllistwrapper_p.h
+++ b/src/qml/qml/qqmllistwrapper_p.h
@@ -96,6 +96,7 @@ struct Q_QML_EXPORT QmlListWrapper : Object
static ReturnedValue virtualGet(const Managed *m, PropertyKey id, const Value *receiver, bool *hasProperty);
static bool virtualPut(Managed *m, PropertyKey id, const Value &value, Value *receiver);
static void virtualAdvanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes);
+ static OwnPropertyKeyIterator *virtualOwnPropertyKeys(const Object *m);
};
struct PropertyListPrototype : Object
diff --git a/src/qml/qml/qqmlvaluetypewrapper.cpp b/src/qml/qml/qqmlvaluetypewrapper.cpp
index 1fde5945ba..29f37fc217 100644
--- a/src/qml/qml/qqmlvaluetypewrapper.cpp
+++ b/src/qml/qml/qqmlvaluetypewrapper.cpp
@@ -282,6 +282,46 @@ void QQmlValueTypeWrapper::virtualAdvanceIterator(Managed *m, ObjectIterator *it
QV4::Object::virtualAdvanceIterator(m, it, name, index, p, attributes);
}
+struct QQmlValueTypeWrapperOwnPropertyKeyIterator : ObjectOwnPropertyKeyIterator
+{
+ int propertyIndex = 0;
+ ~QQmlValueTypeWrapperOwnPropertyKeyIterator() override = default;
+ PropertyKey next(const Object *o, Property *pd = nullptr, PropertyAttributes *attrs = nullptr) override;
+
+};
+
+PropertyKey QQmlValueTypeWrapperOwnPropertyKeyIterator::next(const Object *o, Property *pd, PropertyAttributes *attrs) {
+ const QQmlValueTypeWrapper *that = static_cast<const QQmlValueTypeWrapper *>(o);
+
+ if (const QQmlValueTypeReference *ref = that->as<QQmlValueTypeReference>()) {
+ if (!ref->readReferenceValue())
+ return PropertyKey::invalid();
+ }
+
+ if (that->d()->propertyCache()) {
+ const QMetaObject *mo = that->d()->propertyCache()->createMetaObject();
+ const int propertyCount = mo->propertyCount();
+ if (propertyIndex < propertyCount) {
+ Scope scope(that->engine());
+ ScopedString propName(scope, that->engine()->newString(QString::fromUtf8(mo->property(propertyIndex).name())));
+ ++propertyIndex;
+ if (attrs)
+ *attrs = QV4::Attr_Data;
+ if (pd)
+ pd->value = that->QV4::Object::get(propName);
+ return propName->toPropertyKey();
+ }
+ }
+
+ return ObjectOwnPropertyKeyIterator::next(o, pd, attrs);
+}
+
+
+OwnPropertyKeyIterator *QQmlValueTypeWrapper::virtualOwnPropertyKeys(const Object *)
+{
+ return new QQmlValueTypeWrapperOwnPropertyKeyIterator;
+}
+
bool QQmlValueTypeWrapper::isEqual(const QVariant& value) const
{
if (const QQmlValueTypeReference *ref = as<const QQmlValueTypeReference>())
diff --git a/src/qml/qml/qqmlvaluetypewrapper_p.h b/src/qml/qml/qqmlvaluetypewrapper_p.h
index ff8ab98bb6..2df4dbb257 100644
--- a/src/qml/qml/qqmlvaluetypewrapper_p.h
+++ b/src/qml/qml/qqmlvaluetypewrapper_p.h
@@ -111,6 +111,7 @@ public:
static bool virtualIsEqualTo(Managed *m, Managed *other);
static PropertyAttributes virtualGetOwnProperty(Managed *m, PropertyKey id, Property *p);
static void virtualAdvanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes);
+ static OwnPropertyKeyIterator *virtualOwnPropertyKeys(const Object *m);
static ReturnedValue method_toString(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
index e6f68a30b3..1ad4a5aa9e 100644
--- a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
+++ b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
@@ -229,6 +229,15 @@ void QtObject::virtualAdvanceIterator(Managed *m, ObjectIterator *it, Value *nam
QV4::Object::virtualAdvanceIterator(m, it, name, index, p, attributes);
}
+OwnPropertyKeyIterator *QtObject::virtualOwnPropertyKeys(const Object *m)
+{
+ auto that = static_cast<const QtObject*>(m);
+ if (!that->d()->isComplete())
+ const_cast<QtObject *>(that)->addAll();
+
+ return Object::virtualOwnPropertyKeys(m);
+}
+
/*!
\qmlmethod bool Qt::isQtObject(object)
Returns true if \c object is a valid reference to a Qt or QML object, otherwise false.
diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions_p.h b/src/qml/qml/v8/qqmlbuiltinfunctions_p.h
index 4b3814c8b8..896a9960b9 100644
--- a/src/qml/qml/v8/qqmlbuiltinfunctions_p.h
+++ b/src/qml/qml/v8/qqmlbuiltinfunctions_p.h
@@ -95,6 +95,7 @@ struct QtObject : Object
static ReturnedValue virtualGet(const Managed *m, PropertyKey id, const Value *receiver, bool *hasProperty);
static void virtualAdvanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes);
+ static OwnPropertyKeyIterator *virtualOwnPropertyKeys(const Object *m);
static ReturnedValue method_isQtObject(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
static ReturnedValue method_rgba(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);