From: Aaron Kennedy Date: Wed, 4 Apr 2012 11:17:59 +0000 (+0100) Subject: Do not execute overwritten bindings X-Git-Url: http://git.silmor.de/gitweb/?a=commitdiff_plain;h=8b0831f0b09847331eb59598a09ad6865800ef01;p=konrad%2Fqtdeclarative.git Do not execute overwritten bindings During the construction of an object, internal bindings can be overwritten by the initialization of objects with outer scope. Task-number: QTBUG-23138 Change-Id: I46a187d9cdc41f4dd96d068f39788a2255b8888d Reviewed-by: Roberto Raggi --- diff --git a/src/qml/qml/qqmlvme.cpp b/src/qml/qml/qqmlvme.cpp index f5a6954..9115e47 100644 --- a/src/qml/qml/qqmlvme.cpp +++ b/src/qml/qml/qqmlvme.cpp @@ -205,13 +205,19 @@ inline bool fastHasBinding(QObject *o, int index) { QQmlData *ddata = static_cast(QObjectPrivate::get(o)->declarativeData); + index &= 0xFFFFFF; // To handle value types + return ddata && (ddata->bindingBitsSize > index) && (ddata->bindingBits[index / 32] & (1 << (index % 32))); } static void removeBindingOnProperty(QObject *o, int index) { - QQmlAbstractBinding *binding = QQmlPropertyPrivate::setBinding(o, index, -1, 0); + int coreIndex = index & 0xFFFFFF; + int valueTypeIndex = index & 0xFF000000; + if (!valueTypeIndex) valueTypeIndex = -1; + + QQmlAbstractBinding *binding = QQmlPropertyPrivate::setBinding(o, coreIndex, valueTypeIndex, 0); if (binding) binding->destroy(); } @@ -782,6 +788,8 @@ QObject *QQmlVME::run(QList *errors, Q_ASSERT(bind->propertyIndex() == QDPP::bindingIndex(instr.property)); Q_ASSERT(bind->object() == target); + CLEAN_PROPERTY(target, QDPP::bindingIndex(instr.property)); + bind->addToObject(); } QML_END_INSTR(StoreBinding) @@ -805,6 +813,8 @@ QObject *QQmlVME::run(QList *errors, Q_ASSERT(binding->propertyIndex() == (property & 0xFF00FFFF)); Q_ASSERT(binding->object() == target); + CLEAN_PROPERTY(target, property & 0xFF00FFFF); + binding->addToObject(); QML_END_INSTR(StoreV4Binding) @@ -835,6 +845,8 @@ QObject *QQmlVME::run(QList *errors, Q_ASSERT(binding->propertyIndex() == QDPP::bindingIndex(instr.property)); Q_ASSERT(binding->object() == target); + CLEAN_PROPERTY(target, QDPP::bindingIndex(instr.property)); + binding->addToObject(); } } diff --git a/tests/auto/qml/qqmlecmascript/data/InnerObject.qml b/tests/auto/qml/qqmlecmascript/data/InnerObject.qml new file mode 100644 index 0000000..a8ed959 --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/InnerObject.qml @@ -0,0 +1,13 @@ +import QtQuick 2.0 + +QtObject { + property int foo1: 100 + property int foo2: 100 + property int foo3: { return 100; } + property int foo4: { return 100; } + + property string bar1: 'Hello' + property string bar2: 'Hello' + property string bar3: { return 'Hello'; } + property string bar4: { return 'Hello'; } +} diff --git a/tests/auto/qml/qqmlecmascript/data/OuterObject.qml b/tests/auto/qml/qqmlecmascript/data/OuterObject.qml new file mode 100644 index 0000000..da571a9 --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/OuterObject.qml @@ -0,0 +1,5 @@ +import QtQuick 2.0 + +Item { + property InnerObject inner: InnerObject {} +} diff --git a/tests/auto/qml/qqmlecmascript/data/replaceBinding.qml b/tests/auto/qml/qqmlecmascript/data/replaceBinding.qml new file mode 100644 index 0000000..670231a --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/replaceBinding.qml @@ -0,0 +1,26 @@ +import QtQuick 2.0 + +OuterObject { + property bool success: false + + inner.foo1: 200 + inner.foo2: { return 200; } + inner.foo3: 200 + inner.foo4: { return 200; } + + inner.bar1: 'Goodbye' + inner.bar2: { return 'Goodbye' } + inner.bar3: 'Goodbye' + inner.bar4: { return 'Goodbye' } + + Component.onCompleted: { + success = (inner.foo1 == 200 && + inner.foo2 == 200 && + inner.foo3 == 200 && + inner.foo4 == 200 && + inner.bar1 == 'Goodbye' && + inner.bar2 == 'Goodbye' && + inner.bar3 == 'Goodbye' && + inner.bar4 == 'Goodbye'); + } +} diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp index ee9c7ee..273cd07 100644 --- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp +++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp @@ -252,6 +252,7 @@ private slots: void switchStatement(); void withStatement(); void tryStatement(); + void replaceBinding(); private: static void propertyVarWeakRefCallback(v8::Persistent object, void* parameter); @@ -6416,6 +6417,18 @@ void tst_qqmlecmascript::registeredFlagMethod() delete object; } +// QTBUG-23138 +void tst_qqmlecmascript::replaceBinding() +{ + QQmlEngine engine; + QQmlComponent c(&engine, testFileUrl("replaceBinding.qml")); + QObject *obj = c.create(); + QVERIFY(obj != 0); + + QVERIFY(obj->property("success").toBool()); + delete obj; +} + QTEST_MAIN(tst_qqmlecmascript) #include "tst_qqmlecmascript.moc"