Remove references transforms have to items in QQuickItem's destructor.
authorMitch Curtis <mitch.curtis@digia.com>
Fri, 22 Aug 2014 07:52:59 +0000 (09:52 +0200)
committerMitch Curtis <mitch.curtis@digia.com>
Mon, 25 Aug 2014 12:41:34 +0000 (14:41 +0200)
In case they try to remove themselves from our list of transforms when
that list has already been destroyed after ~QQuickItem() has run.

Task-number: QTBUG-40877
Change-Id: Ie57f5dd1e8b791846f08629183974c771553c4bf
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
Reviewed-by: Alan Alpert <aalpert@blackberry.com>
src/quick/items/qquickitem.cpp
tests/auto/quick/qquickitem/data/objectChildTransform.qml [new file with mode: 0644]
tests/auto/quick/qquickitem/tst_qquickitem.cpp

index 7b031f3..a6c83fb 100644 (file)
@@ -2161,6 +2161,17 @@ QQuickItem::~QQuickItem()
 
     d->changeListeners.clear();
 
+    /*
+       Remove any references our transforms have to us, in case they try to
+       remove themselves from our list of transforms when that list has already
+       been destroyed after ~QQuickItem() has run.
+    */
+    for (int ii = 0; ii < d->transforms.count(); ++ii) {
+        QQuickTransform *t = d->transforms.at(ii);
+        QQuickTransformPrivate *tp = QQuickTransformPrivate::get(t);
+        tp->items.removeOne(this);
+    }
+
     if (d->extra.isAllocated()) {
         delete d->extra->contents; d->extra->contents = 0;
         delete d->extra->layer; d->extra->layer = 0;
diff --git a/tests/auto/quick/qquickitem/data/objectChildTransform.qml b/tests/auto/quick/qquickitem/data/objectChildTransform.qml
new file mode 100644 (file)
index 0000000..fecb9ac
--- /dev/null
@@ -0,0 +1,31 @@
+import QtQuick 2.3
+
+Rectangle {
+    width: 360
+    height: 360
+
+    property alias loaderSource: loader.source
+
+    Component {
+        id: crashComponent
+
+        Item {
+            Image {
+                transform: scale
+            }
+
+            Scale {
+                id: scale
+                xScale: 1
+                yScale: 1
+            }
+        }
+    }
+
+    Loader {
+        id: loader
+        anchors.fill: parent
+        sourceComponent: crashComponent
+    }
+}
+
index a689887..38dc8e0 100644 (file)
@@ -167,6 +167,8 @@ private slots:
 
     void testSGInitializeAndInvalidate();
 
+    void objectChildTransform();
+
 private:
 
     enum PaintOrderOp {
@@ -1906,7 +1908,18 @@ void tst_qquickitem::testSGInitializeAndInvalidate()
         delete view.take();
         QCOMPARE(invalidateSpy.size(), expected);
     }
+}
+
+void tst_qquickitem::objectChildTransform()
+{
+    QQuickView view;
+    view.setSource(testFileUrl("objectChildTransform.qml"));
+
+    QQuickItem *root = qobject_cast<QQuickItem*>(view.rootObject());
+    QVERIFY(root);
 
+    root->setProperty("source", QString());
+    // Shouldn't crash.
 }
 
 QTEST_MAIN(tst_qquickitem)