diff options
| author | Fabian Kosmale <fabian.kosmale@qt.io> | 2025-02-27 15:10:06 +0100 |
|---|---|---|
| committer | Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> | 2025-09-03 16:33:14 +0000 |
| commit | 2f76b2f140b2cfe95b287a2742f44d24a46f75ad (patch) | |
| tree | 189c5a44233e7dbcce4414c91860c6338e361221 | |
| parent | 6efdecd3612bd4a5688ac1b701590413888b3d8e (diff) | |
Binding: Avoid inconsistent state transition
When a QML element gets destroyed, it will at some point call
QQmlData::destroyed, which then sets addedToObject to false for all
bindings. It will also decrement the reference count of the bindings.
However, that doesn't necessarily result in the destruction of the
bindings, something else might still be referencing them.
Moerover, we also didn't disable the bindigs at this point. That means
that the bindings would still evaluate, even after the object has been
destroyed – and if the object is compleltely gone, QQmlData::wasDeleted
as used in QQmlBinding::update won't save us as we only have a pointer
to freed memory.
We avoid this whole mess by ensuring that a binding can't be in a state
where it's not attached to an object, but enabled.
This is based on changes from bbf2c03226c330b934294c5e3332e341deb0b78d
"Add sticky bit to QQmlAbstractBinding", and therefore the actualy
change only needs to be added to older branches. We cherry-pick to dev
to get the test together with the context from the commit message.
Fixes: QTBUG-139306
Change-Id: I70d063a85c005afa9795d55095e5e834c88c1985
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
(cherry picked from commit 55ebad523db84b132b1b95d4e37881fd44068a52)
(cherry picked from commit 1e302b9d1288022d9059b9bbc9d4fec0ef362109)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
| -rw-r--r-- | tests/auto/qml/qqmlecmascript/data/bindingNoEvaluationIfObjectGone.qml | 9 | ||||
| -rw-r--r-- | tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp | 22 |
2 files changed, 31 insertions, 0 deletions
diff --git a/tests/auto/qml/qqmlecmascript/data/bindingNoEvaluationIfObjectGone.qml b/tests/auto/qml/qqmlecmascript/data/bindingNoEvaluationIfObjectGone.qml new file mode 100644 index 0000000000..488d1d248a --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/bindingNoEvaluationIfObjectGone.qml @@ -0,0 +1,9 @@ +import QtQml + +QtObject { + id: root + property int x: 42 + property QtObject obj: QtObject { + property int y: root.x + } +} diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp index 90fec70ab8..189d491640 100644 --- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp +++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp @@ -132,6 +132,7 @@ private slots: void exceptionClearsOnReeval(); void exceptionSlotProducesWarning(); void exceptionBindingProducesWarning(); + void bindingNoEvaluationIfObjectGone(); void compileInvalidBinding(); void transientErrors(); void shutdownErrors(); @@ -2535,6 +2536,27 @@ void tst_qqmlecmascript::exceptionBindingProducesWarning() QVERIFY(object != nullptr); } +void tst_qqmlecmascript::bindingNoEvaluationIfObjectGone() +{ + QQmlEngine engine; + QQmlComponent component(&engine, testFileUrl("bindingNoEvaluationIfObjectGone.qml")); + std::unique_ptr<QObject> root(component.create()); + QVERIFY(root); + QObject *targetObject = root->property("obj").value<QObject *>(); + QVERIFY(targetObject); + QQmlProperty yProp(targetObject, u"y"_s, &engine); + // hold a reference to the binding to keep it alive + auto binding = QQmlAnyBinding::ofProperty(yProp); + QVERIFY(binding.asAbstractBinding()); + QCOMPARE(binding.asAbstractBinding()->targetObject(), targetObject); + delete targetObject; + // the target object pointer of the binding hasn't been reset; we might + // want to change this in the future; that line can be then adapted + QVERIFY(binding.asAbstractBinding()->targetObject()); + // trigger a binding reevaluation + root->setProperty("x", 10); // no ASAN warning/crash +} + void tst_qqmlecmascript::compileInvalidBinding() { // QTBUG-23387: ensure that invalid bindings don't cause a crash. |
