diff options
author | Andrei Golubev <andrei.golubev@qt.io> | 2021-11-26 16:27:16 +0100 |
---|---|---|
committer | Andrei Golubev <andrei.golubev@qt.io> | 2021-11-30 18:42:54 +0000 |
commit | 47822b45a6832c35d2cea2fe2057fb7e06789d56 (patch) | |
tree | 65c01530e5882a865c0fd2c0309f146158b4b61d /src/qmltest | |
parent | 7b68b800ecc8daa983452890abdbfa0c22bcd3a3 (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.qml | 9 |
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 */ |