aboutsummaryrefslogtreecommitdiffstats
path: root/tests/auto/qml/qqmlengine
diff options
context:
space:
mode:
authorOlivier De Cannière <olivier.decanniere@qt.io>2023-03-22 13:01:24 +0100
committerOlivier De Cannière <olivier.decanniere@qt.io>2023-03-27 13:52:34 +0200
commitc534d6b7b0682d06225e3d801e72f5931b0c504e (patch)
tree7990ff0487316ad6715b3125894fab276b0fca6e /tests/auto/qml/qqmlengine
parent05ae4d743b76aff4cc1a1c3d5aebc96e9f16f662 (diff)
QV4: Mark singletons as deleted before actually deleting them
In cases where a singleton A holds a reference to another singleton B at the end of the program and if B is destroyed before A, then the update from B's destruction updates any binding A has on B. If the binding tries to access B's members then "TypeError: Cannot read property <property_name> of null" happens. This fix marks all singletons as deleted before actually deleting them so that bindings targeting them won't be reevaluated on update. Randomness, likely due to a random seed in the QHash holding the singletons changes the order of destruction of the singletons making the issue sporadic. To account for this in the accompanying test, both singletons hold a reference to the other. Pick-to: 6.5 Fixes: QTBUG-111918 Change-Id: I30450fa08f89f7686c4a41fa46dde2174ce83606 Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
Diffstat (limited to 'tests/auto/qml/qqmlengine')
-rw-r--r--tests/auto/qml/qqmlengine/data/crossReferencingSingletonsDeletion/Module/Main.qml5
-rw-r--r--tests/auto/qml/qqmlengine/data/crossReferencingSingletonsDeletion/Module/SingletonA.qml11
-rw-r--r--tests/auto/qml/qqmlengine/data/crossReferencingSingletonsDeletion/Module/SingletonB.qml11
-rw-r--r--tests/auto/qml/qqmlengine/data/crossReferencingSingletonsDeletion/Module/TestItem.qml5
-rw-r--r--tests/auto/qml/qqmlengine/data/crossReferencingSingletonsDeletion/Module/qmldir3
-rw-r--r--tests/auto/qml/qqmlengine/tst_qqmlengine.cpp13
6 files changed, 48 insertions, 0 deletions
diff --git a/tests/auto/qml/qqmlengine/data/crossReferencingSingletonsDeletion/Module/Main.qml b/tests/auto/qml/qqmlengine/data/crossReferencingSingletonsDeletion/Module/Main.qml
new file mode 100644
index 0000000000..3be706ee29
--- /dev/null
+++ b/tests/auto/qml/qqmlengine/data/crossReferencingSingletonsDeletion/Module/Main.qml
@@ -0,0 +1,5 @@
+import QtQuick
+
+Item {
+ property string s: SingletonA.name
+}
diff --git a/tests/auto/qml/qqmlengine/data/crossReferencingSingletonsDeletion/Module/SingletonA.qml b/tests/auto/qml/qqmlengine/data/crossReferencingSingletonsDeletion/Module/SingletonA.qml
new file mode 100644
index 0000000000..dc3bfd23fd
--- /dev/null
+++ b/tests/auto/qml/qqmlengine/data/crossReferencingSingletonsDeletion/Module/SingletonA.qml
@@ -0,0 +1,11 @@
+pragma Singleton
+import QtQuick
+
+Item {
+ readonly property string name: "SingletonA"
+
+ readonly property TestItem itemA: TestItem{}
+
+ property TestItem crossRef: SingletonB.itemB
+ property int testItemInt: crossRef.i
+}
diff --git a/tests/auto/qml/qqmlengine/data/crossReferencingSingletonsDeletion/Module/SingletonB.qml b/tests/auto/qml/qqmlengine/data/crossReferencingSingletonsDeletion/Module/SingletonB.qml
new file mode 100644
index 0000000000..7f0335ee89
--- /dev/null
+++ b/tests/auto/qml/qqmlengine/data/crossReferencingSingletonsDeletion/Module/SingletonB.qml
@@ -0,0 +1,11 @@
+pragma Singleton
+import QtQuick
+
+Item {
+ readonly property string name: "SingletonB"
+
+ readonly property TestItem itemB: TestItem{}
+
+ property TestItem crossRef: SingletonA.itemA
+ property int testItemInt: crossRef.i
+}
diff --git a/tests/auto/qml/qqmlengine/data/crossReferencingSingletonsDeletion/Module/TestItem.qml b/tests/auto/qml/qqmlengine/data/crossReferencingSingletonsDeletion/Module/TestItem.qml
new file mode 100644
index 0000000000..81d931f14c
--- /dev/null
+++ b/tests/auto/qml/qqmlengine/data/crossReferencingSingletonsDeletion/Module/TestItem.qml
@@ -0,0 +1,5 @@
+import QtQuick
+
+Item {
+ property int i: 3
+}
diff --git a/tests/auto/qml/qqmlengine/data/crossReferencingSingletonsDeletion/Module/qmldir b/tests/auto/qml/qqmlengine/data/crossReferencingSingletonsDeletion/Module/qmldir
new file mode 100644
index 0000000000..8bf691d10d
--- /dev/null
+++ b/tests/auto/qml/qqmlengine/data/crossReferencingSingletonsDeletion/Module/qmldir
@@ -0,0 +1,3 @@
+module Module
+singleton SingletonA 1.0 SingletonA.qml
+singleton SingletonB 1.0 SingletonB.qml
diff --git a/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp b/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp
index 895513d822..804cced33c 100644
--- a/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp
+++ b/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp
@@ -77,6 +77,7 @@ private slots:
void qtNamespaceInQtObject();
void nativeModuleImport();
void lockedRootObject();
+ void crossReferencingSingletonsDeletion();
public slots:
QObject *createAQObjectForOwnershipTest ()
@@ -1683,6 +1684,18 @@ void tst_qqmlengine::lockedRootObject()
QCOMPARE(o->property("defineProperty2").toBool(), false);
}
+void tst_qqmlengine::crossReferencingSingletonsDeletion()
+{
+ QQmlEngine engine;
+ engine.addImportPath(testFileUrl("crossReferencingSingletonsDeletion").url());
+ QQmlComponent c(&engine, testFileUrl("crossReferencingSingletonsDeletion/Module/Main.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+
+ std::unique_ptr<QObject> o{ c.create() };
+ QVERIFY(o);
+ QCOMPARE(o->property("s").toString(), "SingletonA");
+}
+
QTEST_MAIN(tst_qqmlengine)
#include "tst_qqmlengine.moc"