aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/qml/qqmlpropertybinding.cpp
diff options
context:
space:
mode:
authorFabian Kosmale <fabian.kosmale@qt.io>2020-06-29 09:48:39 +0200
committerFabian Kosmale <fabian.kosmale@qt.io>2020-08-12 15:52:12 +0200
commit89bc860ff4c51c6e02f67198fa7dcf5e1241de80 (patch)
tree57b56e535d3359603015fa18ac47fe628aeb48dd /src/qml/qml/qqmlpropertybinding.cpp
parentf358188cbd2e47f82d7de3612181e628e1f1c05c (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.cpp14
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)