Emit destruction signal before child contexts are destroyed.
authorGlenn Watson <glenn.watson@nokia.com>
Mon, 21 Nov 2011 22:02:17 +0000 (08:02 +1000)
committerQt by Nokia <qt-info@nokia.com>
Tue, 22 Nov 2011 02:31:14 +0000 (03:31 +0100)
Verbatim comment from bug report:

When using a QtObject inside an item, and then we call a function
in the Component.onDestruction handler of that item, we get a
crash. This happens because the QDeclarativeContextData engine
has been invalidated before reaching
QDeclarativeExpressionPrivate::evalFunction.

Change code to emit the onDestruction signal before the child
contexts are invalidated.

Task-number: QTBUG-22535
Change-Id: Ic4983ae5fdf104ae977189c21dc202c9b02bc2bc
Reviewed-by: Chris Adams <christopher.adams@nokia.com>
src/declarative/qml/qdeclarativecontext.cpp
tests/auto/declarative/qdeclarativecontext/data/Object_22535.qml [new file with mode: 0644]
tests/auto/declarative/qdeclarativecontext/data/qtbug_22535.qml [new file with mode: 0644]
tests/auto/declarative/qdeclarativecontext/tst_qdeclarativecontext.cpp

index 1723603..50e2235 100644 (file)
@@ -529,14 +529,6 @@ QDeclarativeContextData::QDeclarativeContextData(QDeclarativeContext *ctxt)
 
 void QDeclarativeContextData::invalidate()
 {
-    while (childContexts) {
-        if (childContexts->ownedByParent) {
-            childContexts->destroy();
-        } else {
-            childContexts->invalidate();
-        }
-    }
-
     while (componentAttached) {
         QDeclarativeComponentAttached *a = componentAttached;
         componentAttached = a->next;
@@ -548,6 +540,14 @@ void QDeclarativeContextData::invalidate()
         emit a->destruction();
     }
 
+    while (childContexts) {
+        if (childContexts->ownedByParent) {
+            childContexts->destroy();
+        } else {
+            childContexts->invalidate();
+        }
+    }
+
     if (prevChild) {
         *prevChild = nextChild;
         if (nextChild) nextChild->prevChild = prevChild;
diff --git a/tests/auto/declarative/qdeclarativecontext/data/Object_22535.qml b/tests/auto/declarative/qdeclarativecontext/data/Object_22535.qml
new file mode 100644 (file)
index 0000000..294c744
--- /dev/null
@@ -0,0 +1,8 @@
+import QtQuick 2.0
+
+QtObject {
+
+    function goodBye()
+    {
+    }
+}
diff --git a/tests/auto/declarative/qdeclarativecontext/data/qtbug_22535.qml b/tests/auto/declarative/qdeclarativecontext/data/qtbug_22535.qml
new file mode 100644 (file)
index 0000000..3553f6c
--- /dev/null
@@ -0,0 +1,10 @@
+import QtQuick 2.0
+
+Rectangle {
+    width: 64
+    height: 64
+
+    Object_22535 { id:o }
+
+    Component.onDestruction: o.goodBye()
+}
index 68599a2..ba9db4f 100644 (file)
@@ -80,6 +80,7 @@ private slots:
     void refreshExpressionsCrash();
     void refreshExpressionsRootContext();
 
+    void qtbug_22535();
 private:
     QDeclarativeEngine engine;
 };
@@ -644,6 +645,18 @@ void tst_qdeclarativecontext::refreshExpressionsRootContext()
     delete o1;
 }
 
+void tst_qdeclarativecontext::qtbug_22535()
+{
+    QDeclarativeEngine engine;
+    QDeclarativeComponent component(&engine, TEST_FILE("qtbug_22535.qml"));
+    QDeclarativeContext context(engine.rootContext());
+
+    QObject *o = component.create(&context);
+
+    // Don't crash!
+    delete o;
+}
+
 QTEST_MAIN(tst_qdeclarativecontext)
 
 #include "tst_qdeclarativecontext.moc"