diff options
author | Simon Hausmann <simon.hausmann@qt.io> | 2018-03-12 15:01:06 +0100 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@qt.io> | 2018-03-12 14:32:02 +0000 |
commit | 5c2b1bee5258981800c623dc3f054b15d7875484 (patch) | |
tree | e71011620b38b74ddc989939c471db87e8fe123d | |
parent | 79964673d1587f9e6a254cb6a1f0dd0645b946e6 (diff) |
Fix doubly connected signals in SignalSequenceSpy
We call __setup() from two different onFooChanged signal handlers. If we
access the second property from within that method, we may end up being
the first one to read that property and consequently require an
initialization of the binding to that property first, which will write
the value (before returning) and trigger the signal handler, recursively
calling __setup() and thus calling connect() twice for each signal the
spy wants to connect to.
This used to be fine as we ended up with a _third_ evaluation that
called __setup() and thus cleared the connections first, but after
commit f514451cc2e3610e160b5dc8ccd1e390730ecc67 in declarative we avoid
unnecessary binding evaluations if possible and therefore uncovered this
bug.
Task-number: QTBUG-66995
Change-Id: I83ef9c80978a88c1490174d3cdb21b149733a78f
Reviewed-by: J-P Nurmi <jpnurmi@qt.io>
-rw-r--r-- | tests/auto/controls/data/SignalSequenceSpy.qml | 11 |
1 files changed, 8 insertions, 3 deletions
diff --git a/tests/auto/controls/data/SignalSequenceSpy.qml b/tests/auto/controls/data/SignalSequenceSpy.qml index fe47a3c1..d14a5ee6 100644 --- a/tests/auto/controls/data/SignalSequenceSpy.qml +++ b/tests/auto/controls/data/SignalSequenceSpy.qml @@ -72,10 +72,15 @@ QtObject { property var __connections: [] onExpectedSequenceChanged: reset() - onTargetChanged: __setup() - onSignalsChanged: __setup() - function __setup() { + // We may call __setup from onTargetChanged and as we would read the signals property + // inside __setup, we may be initializing the binding for signals for the first time, which + // will write the value to the property and trigger onSignalsChanged and call __setup + // again. One easy way to protect against it is to evaluate those two dependencies upfront + onTargetChanged: __setup(target, signals) + onSignalsChanged: __setup(target, signals) + + function __setup(target, signals) { if (__oldTarget) { __connections.forEach(function (cx) { __oldTarget[cx.name].disconnect(cx.method) |