Loader could leak qml contexts if interrupted
authorMartin Jones <martin.jones@nokia.com>
Tue, 20 Mar 2012 01:58:09 +0000 (11:58 +1000)
committerQt by Nokia <qt-info@nokia.com>
Tue, 20 Mar 2012 04:37:59 +0000 (05:37 +0100)
If Loader was either destroyed, or its source changed while
it was incubating the itemContext could be leaked.

Change-Id: I5b749062552954d92bf2851250f942b20ebbfe68
Reviewed-by: Andrew den Exter <andrew.den-exter@nokia.com>
src/quick/items/qquickloader.cpp
tests/auto/quick/qquickloader/tst_qquickloader.cpp

index 59cb37c..f41ba44 100644 (file)
@@ -61,6 +61,8 @@ QQuickLoaderPrivate::QQuickLoaderPrivate()
 
 QQuickLoaderPrivate::~QQuickLoaderPrivate()
 {
+    delete itemContext;
+    itemContext = 0;
     delete incubator;
     disposeInitialPropertyValues();
 }
@@ -79,12 +81,21 @@ void QQuickLoaderPrivate::itemGeometryChanged(QQuickItem *resizeItem, const QRec
 
 void QQuickLoaderPrivate::clear()
 {
+    Q_Q(QQuickLoader);
     disposeInitialPropertyValues();
 
     if (incubator)
         incubator->clear();
 
+    delete itemContext;
+    itemContext = 0;
+
     if (loadingFromSource && component) {
+        // disconnect since we deleteLater
+        QObject::disconnect(component, SIGNAL(statusChanged(QQmlComponent::Status)),
+                q, SLOT(_q_sourceLoaded()));
+        QObject::disconnect(component, SIGNAL(progressChanged(qreal)),
+                q, SIGNAL(progressChanged()));
         component->deleteLater();
         component = 0;
     }
@@ -545,6 +556,7 @@ void QQuickLoaderPrivate::setInitialState(QObject *obj)
         QQml_setParent_noEvent(itemContext, obj);
         QQml_setParent_noEvent(item, q);
         item->setParentItem(q);
+        itemContext = 0;
     }
 
     if (initialPropertyValues.IsEmpty())
index bdf47fa..01781f7 100644 (file)
@@ -929,7 +929,7 @@ void tst_QQuickLoader::asynchronous_clear()
     QVERIFY(!loader->item());
 
     QCOMPARE(loader->status(), QQuickLoader::Loading);
-    QCOMPARE(engine.incubationController()->incubatingObjectCount(), 1);
+    QTRY_COMPARE(engine.incubationController()->incubatingObjectCount(), 1);
 
     // clear before component created
     root->setProperty("comp", "");
@@ -942,7 +942,7 @@ void tst_QQuickLoader::asynchronous_clear()
     QCOMPARE(static_cast<QQuickItem*>(loader)->childItems().count(), 0);
 
     // check loading component
-    root->setProperty("comp", "Rect120x60.qml");
+    root->setProperty("comp", "BigComponent.qml");
     QMetaObject::invokeMethod(root, "loadComponent");
     QVERIFY(!loader->item());
 
@@ -953,6 +953,8 @@ void tst_QQuickLoader::asynchronous_clear()
     QCOMPARE(loader->progress(), 1.0);
     QCOMPARE(loader->status(), QQuickLoader::Ready);
     QCOMPARE(static_cast<QQuickItem*>(loader)->childItems().count(), 1);
+
+    delete root;
 }
 
 void tst_QQuickLoader::simultaneousSyncAsync()