aboutsummaryrefslogtreecommitdiffstats
path: root/tests/auto
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2018-11-29 11:28:49 +0100
committerUlf Hermann <ulf.hermann@qt.io>2018-11-30 09:09:36 +0000
commitb17091b0006e41c0bb4ddf77dbbc09621d809aea (patch)
treefd27f9b48ee209b13d545fa8df46d147b0566d24 /tests/auto
parentd0a52c72b5756787ceb6094117cd71d935badc06 (diff)
QML: Also clear outerContext's contextObject on destruction
A QObject can not only be set as contextObject of the own context, but also as contextObject of the outerContext of a respective QQmlData. This can be seen in QQmlObjectCreator::createInstance(...) if isContextObject is true. Therefore, when catching a QObject deletion we need to clear the pointer in the outerContext if that refers to the object being deleted. Fixes: QTBUG-71037 Change-Id: Ib6ba99bd5336f7582486b2128515021245370c60 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'tests/auto')
-rw-r--r--tests/auto/qml/qqmlcontext/data/MyItem.qml5
-rw-r--r--tests/auto/qml/qqmlcontext/data/outerContextObject.qml18
-rw-r--r--tests/auto/qml/qqmlcontext/tst_qqmlcontext.cpp58
3 files changed, 81 insertions, 0 deletions
diff --git a/tests/auto/qml/qqmlcontext/data/MyItem.qml b/tests/auto/qml/qqmlcontext/data/MyItem.qml
new file mode 100644
index 0000000000..2ffd984dfa
--- /dev/null
+++ b/tests/auto/qml/qqmlcontext/data/MyItem.qml
@@ -0,0 +1,5 @@
+import QtQuick 2.0
+
+QtObject {
+ Component.onCompleted: 5 + 5
+}
diff --git a/tests/auto/qml/qqmlcontext/data/outerContextObject.qml b/tests/auto/qml/qqmlcontext/data/outerContextObject.qml
new file mode 100644
index 0000000000..992b760915
--- /dev/null
+++ b/tests/auto/qml/qqmlcontext/data/outerContextObject.qml
@@ -0,0 +1,18 @@
+import QtQml 2.2
+
+QtObject {
+ id: window
+
+ property Component itemComponent: Qt.createComponent("MyItem.qml")
+ property MyItem item
+
+ property Timer timer: Timer {
+ running: true
+ interval: 10
+ repeat: true
+ onTriggered: {
+ item = itemComponent.createObject(null, {});
+ gc();
+ }
+ }
+}
diff --git a/tests/auto/qml/qqmlcontext/tst_qqmlcontext.cpp b/tests/auto/qml/qqmlcontext/tst_qqmlcontext.cpp
index 990e364c76..5838193a6b 100644
--- a/tests/auto/qml/qqmlcontext/tst_qqmlcontext.cpp
+++ b/tests/auto/qml/qqmlcontext/tst_qqmlcontext.cpp
@@ -28,6 +28,7 @@
#include <qtest.h>
#include <QDebug>
+#include <QTimer>
#include <QQmlEngine>
#include <QQmlContext>
#include <QQmlComponent>
@@ -68,6 +69,8 @@ private slots:
void contextViaClosureAfterDestruction();
void contextLeak();
+ void outerContextObject();
+
private:
QQmlEngine engine;
};
@@ -815,6 +818,61 @@ void tst_qqmlcontext::contextLeak()
QVERIFY(scriptContext.isNull());
}
+
+static bool buildObjectList(QQmlContext *ctxt)
+{
+ static QHash<QObject *, QString> deletedObjects;
+ QQmlContextData *p = QQmlContextData::get(ctxt);
+ QObject *object = p->contextObject;
+ if (object) {
+ // If the object was actually deleted this is likely to crash in one way or another.
+ // Either the memory is still intact, then we will probably find the objectName, or it is
+ // not, then the connect() below is likely to fail.
+ if (deletedObjects.contains(object) && deletedObjects[object] == object->objectName())
+ return false;
+ QObject::connect(object, &QObject::destroyed, [object]() {
+ object->setObjectName(QString::number(deletedObjects.size()));
+ deletedObjects.insert(object, object->objectName());
+ });
+ }
+
+ QQmlContextData *child = p->childContexts;
+ while (child) {
+ if (!buildObjectList(child->asQQmlContext()))
+ return false;
+ child = child->nextChild;
+ }
+
+ return true;
+}
+
+void tst_qqmlcontext::outerContextObject()
+{
+ QQmlEngine engine;
+
+ QQmlComponent component(&engine, testFileUrl("outerContextObject.qml"));
+ QVERIFY(component.isReady());
+
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+
+ int iterations = 0;
+ QTimer timer;
+ timer.setInterval(1);
+ QObject::connect(&timer, &QTimer::timeout, &engine, [&]() {
+ if (!buildObjectList(engine.rootContext())) {
+ iterations = 100;
+ timer.stop();
+ QFAIL("Deleted object found as context object");
+ } else {
+ ++iterations;
+ }
+ });
+ timer.start();
+
+ QTRY_VERIFY(iterations >= 100);
+}
+
QTEST_MAIN(tst_qqmlcontext)
#include "tst_qqmlcontext.moc"