aboutsummaryrefslogtreecommitdiffstats
path: root/src/qmltest
diff options
context:
space:
mode:
authorAndrei Golubev <andrei.golubev@qt.io>2021-11-26 16:27:16 +0100
committerAndrei Golubev <andrei.golubev@qt.io>2021-11-30 18:42:54 +0000
commit47822b45a6832c35d2cea2fe2057fb7e06789d56 (patch)
tree65c01530e5882a865c0fd2c0309f146158b4b61d /src/qmltest
parent7b68b800ecc8daa983452890abdbfa0c22bcd3a3 (diff)
Make qmltest/SignalSpy.qml aware of recursive qtest_update() calls
Apparently looking up a property can cause it to be evaluated (and its signal handler called directly). From the debugging the following is visible: 1) assume signalName is set first and target has a pending binding (not evaluated yet) 2) once signalName setter is triggered, it calls the relevant signal handler - onSignalNameChanged, which subsequently calls qtest_update() 3) in qtest_update(): a. we first check whether there's any old state "if (qtest_prevTarget != null)" -> there's none yet, because we entered this function for the first time ever -> jump to: "if (target != null && signalName != "")" b. once at "target != null" the engine attempts to get the value of the `target` property. if the property `target` happens to have an unevaluated binding, it is evaluated immediately. [the logic is in QObjectWrapper::getQmlProperty() which calls QObjectWrapper::getProperty() and that one calls QQmlData::flushPendingBinding()] c. the binding evaluation causes onTargetChanged signal handler to trigger which in turn again enters qtest_update 4) in the "recursive" call of qtest_update(): a. same as 3.a. b. target is now evaluated and signalName is evaluated as well (due to being already set at step 2) c. "if (target != null && signalName != "")" succeeds and we proceed to connect to spy.qtest_activated d. we return from this function and get back to the outer qtest_update() 5) we are now back at 3.c in qtest_update(): a. target is evaluated, signalName is known, so "if (target != null && signalName != "")" succeeds -> again, we proceed to connect to spy.qtest_activated (for the second time now - see 4.c) b. we return from qtest_update() (the outer one) back to onSignalNameChanged 6) the end. bottom line: - two signals were connected to target[signalName] - zero signals were disconnected This seems like a very nasty thing to have in a UI-centric language but for now let's just attempt to fix the SignalSpy class Pick-to: 6.2 Task-number: QTBUG-98722 Change-Id: I70f11000b8383e6a8fc82d0034c62a2094f6d832 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'src/qmltest')
-rw-r--r--src/qmltest/SignalSpy.qml9
1 files changed, 8 insertions, 1 deletions
diff --git a/src/qmltest/SignalSpy.qml b/src/qmltest/SignalSpy.qml
index 52ed83e261..7257e4f3f3 100644
--- a/src/qmltest/SignalSpy.qml
+++ b/src/qmltest/SignalSpy.qml
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
@@ -218,9 +218,14 @@ Item {
/*! \internal */
property bool qtest_valid:false
/*! \internal */
+ property bool qtest_reentrancy_guard: false
/*! \internal */
function qtest_update() {
+ if (qtest_reentrancy_guard)
+ return;
+ qtest_reentrancy_guard = true;
+
if (qtest_prevTarget != null) {
var prevHandlerName = qtest_signalHandlerName(qtest_prevSignalName)
var prevFunc = qtest_prevTarget[prevHandlerName]
@@ -251,6 +256,8 @@ Item {
} else {
spy.qtest_valid = false
}
+
+ qtest_reentrancy_guard = false;
}
/*! \internal */