diff options
author | Fabian Kosmale <fabian.kosmale@qt.io> | 2020-06-29 09:48:39 +0200 |
---|---|---|
committer | Fabian Kosmale <fabian.kosmale@qt.io> | 2020-08-12 15:52:12 +0200 |
commit | 89bc860ff4c51c6e02f67198fa7dcf5e1241de80 (patch) | |
tree | 57b56e535d3359603015fa18ac47fe628aeb48dd /src/qml/qml/qqmlpropertybinding.cpp | |
parent | f358188cbd2e47f82d7de3612181e628e1f1c05c (diff) |
QQmlPropertyBinding: detect binding loops
Calling markDirtyAndNotifyObservers bypasses the currently existing
mechanism in QProperty to detect binding loops. Moreover, simply
changing updating from private to protected and setting it to true does
not help us here: That would trigger a binding loop warning every time
the static callback of a QNotifiedProperty acesses its current value.
Thus, we add another bool to detect expressionChanged loops. To reduce
memory usage, we store it as a second flag in m_error (from
QQmlJavaScriptExpression).
Change-Id: If931d7ff58b5f9bb277e803826b28e133b2c15dc
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
Diffstat (limited to 'src/qml/qml/qqmlpropertybinding.cpp')
-rw-r--r-- | src/qml/qml/qqmlpropertybinding.cpp | 14 |
1 files changed, 14 insertions, 0 deletions
diff --git a/src/qml/qml/qqmlpropertybinding.cpp b/src/qml/qml/qqmlpropertybinding.cpp index 6b82614e6d..a528cf2754 100644 --- a/src/qml/qml/qqmlpropertybinding.cpp +++ b/src/qml/qml/qqmlpropertybinding.cpp @@ -38,6 +38,7 @@ ****************************************************************************/ #include "qqmlpropertybinding_p.h" +#include <qqmlinfo.h> QT_BEGIN_NAMESPACE @@ -72,7 +73,20 @@ QUntypedPropertyBinding QQmlPropertyBinding::create(const QQmlPropertyData *pd, void QQmlPropertyBinding::expressionChanged() { + const auto currentTag = m_error.tag(); + if (currentTag & InEvaluationLoop) { + QQmlError err; + auto location = QQmlJavaScriptExpression::sourceLocation(); + err.setUrl(QUrl{location.sourceFile}); + err.setLine(location.line); + err.setColumn(location.column); + err.setDescription(QString::fromLatin1("Binding loop detected")); + QtQml::qmlWarning(this->scopeObject(), err); + return; + } + m_error.setTag(currentTag | InEvaluationLoop); markDirtyAndNotifyObservers(); + m_error.setTag(currentTag); } QQmlPropertyBinding::QQmlPropertyBinding(const QMetaType &mt) |