diff options
author | Olivier De Cannière <olivier.decanniere@qt.io> | 2023-03-22 13:01:24 +0100 |
---|---|---|
committer | Olivier De Cannière <olivier.decanniere@qt.io> | 2023-03-27 13:52:34 +0200 |
commit | c534d6b7b0682d06225e3d801e72f5931b0c504e (patch) | |
tree | 7990ff0487316ad6715b3125894fab276b0fca6e /tests/auto/qml/qqmlengine | |
parent | 05ae4d743b76aff4cc1a1c3d5aebc96e9f16f662 (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')
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" |