Fix incorrectly initialized property cache on group objects
authorSimon Hausmann <simon.hausmann@digia.com>
Tue, 11 Mar 2014 12:12:38 +0000 (13:12 +0100)
committerThe Qt Project <gerrit-noreply@qt-project.org>
Tue, 11 Mar 2014 17:31:21 +0000 (18:31 +0100)
When initializing bindings on group objects, we would accidentally set the
property cache for the property type instead of preserving a possibly earlier
initialized cache on the ddata of the QObject.

Task-number: QTBUG-37390

Change-Id: I4d6a4ce6b3382f378f9a9ddfe11924860a15979d
Reviewed-by: Sérgio Martins <sergio.martins@kdab.com>
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
src/qml/qml/qqmlobjectcreator.cpp
tests/auto/qml/qqmllanguage/data/GroupPropertyBase.qml [new file with mode: 0644]
tests/auto/qml/qqmllanguage/data/GroupType.qml [new file with mode: 0644]
tests/auto/qml/qqmllanguage/data/preservePropertyCacheOnGroupObjects.qml [new file with mode: 0644]
tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp

index ac438b2..150401a 100644 (file)
@@ -796,12 +796,6 @@ bool QQmlObjectCreator::setPropertyBinding(QQmlPropertyData *property, const QV4
                 groupObject = valueType;
                 valueTypeProperty = property;
             } else {
-                groupObjectPropertyCache = enginePrivate->propertyCacheForType(property->propType);
-                if (!groupObjectPropertyCache) {
-                    recordError(binding->location, tr("Invalid grouped property access"));
-                    return false;
-                }
-
                 void *argv[1] = { &groupObject };
                 QMetaObject::metacall(_qobject, QMetaObject::ReadProperty, property->coreIndex, argv);
                 if (!groupObject) {
@@ -809,6 +803,16 @@ bool QQmlObjectCreator::setPropertyBinding(QQmlPropertyData *property, const QV4
                     return false;
                 }
 
+                if (QQmlData *groupDeclarativeData = QQmlData::get(groupObject))
+                    groupObjectPropertyCache = groupDeclarativeData->propertyCache;
+                if (!groupObjectPropertyCache)
+                    groupObjectPropertyCache = enginePrivate->propertyCacheForType(property->propType);
+                if (!groupObjectPropertyCache) {
+                    recordError(binding->location, tr("Invalid grouped property access"));
+                    return false;
+                }
+
+
                 bindingTarget = groupObject;
             }
 
@@ -1284,6 +1288,7 @@ bool QQmlObjectCreator::populateInstance(int index, QObject *instance, QQmlRefPo
         vmeMetaObject = new QQmlVMEMetaObject(_qobject, _propertyCache, reinterpret_cast<const QQmlVMEMetaData*>(data.constData()));
         if (_ddata->propertyCache)
             _ddata->propertyCache->release();
+        Q_ASSERT(installPropertyCache);
         scopeObjectProtector = _ddata->jsWrapper.value();
     } else {
         vmeMetaObject = QQmlVMEMetaObject::get(_qobject);
diff --git a/tests/auto/qml/qqmllanguage/data/GroupPropertyBase.qml b/tests/auto/qml/qqmllanguage/data/GroupPropertyBase.qml
new file mode 100644 (file)
index 0000000..a253435
--- /dev/null
@@ -0,0 +1,6 @@
+import QtQml 2.0
+QtObject {
+    property GroupType subObject: GroupType {
+        property int newProperty: 100;
+    }
+}
diff --git a/tests/auto/qml/qqmllanguage/data/GroupType.qml b/tests/auto/qml/qqmllanguage/data/GroupType.qml
new file mode 100644 (file)
index 0000000..d1219de
--- /dev/null
@@ -0,0 +1,4 @@
+import QtQml 2.0
+QtObject {
+    property int value: 10
+}
diff --git a/tests/auto/qml/qqmllanguage/data/preservePropertyCacheOnGroupObjects.qml b/tests/auto/qml/qqmllanguage/data/preservePropertyCacheOnGroupObjects.qml
new file mode 100644 (file)
index 0000000..031cf3b
--- /dev/null
@@ -0,0 +1,6 @@
+import QtQml 2.0
+GroupPropertyBase {
+    subObject {
+        value: 42
+    }
+}
index 3a52d58..c7a26c7 100644 (file)
@@ -218,6 +218,8 @@ private slots:
     void customParserBindingScopes();
     void customParserEvaluateEnum();
 
+    void preservePropertyCacheOnGroupObjects();
+
 private:
     QQmlEngine engine;
     QStringList defaultImportPathList;
@@ -3581,6 +3583,25 @@ void tst_qqmllanguage::customParserEvaluateEnum()
     QVERIFY(!o.isNull());
 }
 
+void tst_qqmllanguage::preservePropertyCacheOnGroupObjects()
+{
+    QQmlComponent component(&engine, testFile("preservePropertyCacheOnGroupObjects.qml"));
+    VERIFY_ERRORS(0);
+    QScopedPointer<QObject> o(component.create());
+    QVERIFY(!o.isNull());
+    QObject *subObject = qvariant_cast<QObject*>(o->property("subObject"));
+    QVERIFY(subObject);
+    QCOMPARE(subObject->property("value").toInt(), 42);
+
+    QQmlData *ddata = QQmlData::get(subObject);
+    QVERIFY(ddata);
+    QQmlPropertyCache *subCache = ddata->propertyCache;
+    QVERIFY(subCache);
+    QQmlPropertyData *pd = subCache->property(QStringLiteral("newProperty"), /*object*/0, /*context*/0);
+    QVERIFY(pd);
+    QCOMPARE(pd->propType, qMetaTypeId<int>());
+}
+
 QTEST_MAIN(tst_qqmllanguage)
 
 #include "tst_qqmllanguage.moc"