diff options
author | Matthew Vogt <matthew.vogt@nokia.com> | 2012-03-21 09:17:25 +1000 |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2012-04-04 07:15:44 +0200 |
commit | 639208cc7f3ab3d8356363559e8fcf168e32cf0b (patch) | |
tree | 63e301bd3be9c67579054215f5d8a0e5a0c77943 /src/qml/qml | |
parent | 912c25633ede945fb9b64e09ecd9309e7cc2ac3c (diff) |
Do not execute overwritten bindings
During the construction of an object, internal bindings can be
overwritten by the initialization of objects with outer scope.
To yield the expected result, suppress the evaluation of inner
bindings that are overwritten by outer bindings, during the
completion phase of object creation.
Task-number: QTBUG-23138
Change-Id: I679309543a9b64c774bb99798ad5ccf518726d10
Reviewed-by: Chris Adams <christopher.adams@nokia.com>
Reviewed-by: J-P Nurmi <j-p.nurmi@nokia.com>
Diffstat (limited to 'src/qml/qml')
-rw-r--r-- | src/qml/qml/qqmlvme.cpp | 48 |
1 files changed, 39 insertions, 9 deletions
diff --git a/src/qml/qml/qqmlvme.cpp b/src/qml/qml/qqmlvme.cpp index 21f07d9688..5534583dfa 100644 --- a/src/qml/qml/qqmlvme.cpp +++ b/src/qml/qml/qqmlvme.cpp @@ -79,8 +79,16 @@ #include <QtCore/qvarlengtharray.h> #include <QtQml/qjsvalue.h> +#include <utility> + QT_BEGIN_NAMESPACE +template <typename T1, typename T2> +uint qHash(const std::pair<T1, T2> &p) +{ + return qHash(p.first) ^ qHash(p.second); +} + using namespace QQmlVMETypes; #define VME_EXCEPTION(desc, line) \ @@ -1216,18 +1224,40 @@ QQmlContextData *QQmlVME::complete(const Interrupt &interrupt) { QQmlTrace trace("VME Binding Enable"); trace.event("begin binding eval"); - while (!bindValues.isEmpty()) { - QQmlAbstractBinding *b = bindValues.pop(); - if(b) { - b->m_mePtr = 0; - b->setEnabled(true, QQmlPropertyPrivate::BypassInterceptor | - QQmlPropertyPrivate::DontRemoveBinding); - } + size_t bindValuesRemaining = bindValues.count(); + if (bindValuesRemaining > 0) { + typedef std::pair<QObject *, int> TargetProperty; - if (watcher.hasRecursed() || interrupt.shouldInterrupt()) - return 0; + QSet<TargetProperty> boundProperties; + boundProperties.reserve(bindValuesRemaining - 1); + + while (bindValuesRemaining > 0) { + QQmlAbstractBinding *b = bindValues.pop(); + --bindValuesRemaining; + + if (b) { + b->m_mePtr = 0; + + TargetProperty property(std::make_pair(b->object(), b->propertyIndex())); + if (!boundProperties.contains(property)) { + // We have not assigned a binding to this property yet + b->setEnabled(true, QQmlPropertyPrivate::BypassInterceptor | + QQmlPropertyPrivate::DontRemoveBinding); + + if (bindValuesRemaining > 0) { + boundProperties.insert(property); + } + } else { + b->destroy(); + } + } + + if (watcher.hasRecursed() || interrupt.shouldInterrupt()) + return 0; + } } + bindValues.deallocate(); } |