From 639208cc7f3ab3d8356363559e8fcf168e32cf0b Mon Sep 17 00:00:00 2001 From: Matthew Vogt Date: Wed, 21 Mar 2012 09:17:25 +1000 Subject: 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 Reviewed-by: J-P Nurmi --- src/qml/qml/qqmlvme.cpp | 48 +++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 39 insertions(+), 9 deletions(-) (limited to 'src/qml/qml/qqmlvme.cpp') 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 #include +#include + QT_BEGIN_NAMESPACE +template +uint qHash(const std::pair &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 TargetProperty; - if (watcher.hasRecursed() || interrupt.shouldInterrupt()) - return 0; + QSet 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(); } -- cgit v1.2.3