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 <roberto.raggi@nokia.com>
This commit is contained in:
Aaron Kennedy 2012-04-04 12:17:59 +01:00 committed by Qt by Nokia
parent 03a6db7fc1
commit 8b0831f0b0
5 changed files with 70 additions and 1 deletions

View File

@ -205,13 +205,19 @@ inline bool fastHasBinding(QObject *o, int index)
{
QQmlData *ddata = static_cast<QQmlData *>(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<QQmlError> *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<QQmlError> *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<QQmlError> *errors,
Q_ASSERT(binding->propertyIndex() == QDPP::bindingIndex(instr.property));
Q_ASSERT(binding->object() == target);
CLEAN_PROPERTY(target, QDPP::bindingIndex(instr.property));
binding->addToObject();
}
}

View File

@ -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'; }
}

View File

@ -0,0 +1,5 @@
import QtQuick 2.0
Item {
property InnerObject inner: InnerObject {}
}

View File

@ -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');
}
}

View File

@ -252,6 +252,7 @@ private slots:
void switchStatement();
void withStatement();
void tryStatement();
void replaceBinding();
private:
static void propertyVarWeakRefCallback(v8::Persistent<v8::Value> 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"