From d2c1adc6f9afc4dd1bab3c487bbde70f3b8f2e81 Mon Sep 17 00:00:00 2001 From: Glenn Watson Date: Tue, 22 Nov 2011 08:02:17 +1000 Subject: [PATCH] Emit destruction signal before child contexts are destroyed. 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 --- src/declarative/qml/qdeclarativecontext.cpp | 16 ++++++++-------- .../qdeclarativecontext/data/Object_22535.qml | 8 ++++++++ .../qdeclarativecontext/data/qtbug_22535.qml | 10 ++++++++++ .../tst_qdeclarativecontext.cpp | 13 +++++++++++++ 4 files changed, 39 insertions(+), 8 deletions(-) create mode 100644 tests/auto/declarative/qdeclarativecontext/data/Object_22535.qml create mode 100644 tests/auto/declarative/qdeclarativecontext/data/qtbug_22535.qml diff --git a/src/declarative/qml/qdeclarativecontext.cpp b/src/declarative/qml/qdeclarativecontext.cpp index 1723603..50e2235 100644 --- a/src/declarative/qml/qdeclarativecontext.cpp +++ b/src/declarative/qml/qdeclarativecontext.cpp @@ -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 index 0000000..294c744 --- /dev/null +++ b/tests/auto/declarative/qdeclarativecontext/data/Object_22535.qml @@ -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 index 0000000..3553f6c --- /dev/null +++ b/tests/auto/declarative/qdeclarativecontext/data/qtbug_22535.qml @@ -0,0 +1,10 @@ +import QtQuick 2.0 + +Rectangle { + width: 64 + height: 64 + + Object_22535 { id:o } + + Component.onDestruction: o.goodBye() +} diff --git a/tests/auto/declarative/qdeclarativecontext/tst_qdeclarativecontext.cpp b/tests/auto/declarative/qdeclarativecontext/tst_qdeclarativecontext.cpp index 68599a2..ba9db4f 100644 --- a/tests/auto/declarative/qdeclarativecontext/tst_qdeclarativecontext.cpp +++ b/tests/auto/declarative/qdeclarativecontext/tst_qdeclarativecontext.cpp @@ -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" -- 1.7.2.5