diff options
-rw-r--r-- | src/qml/qml/qqmlobjectcreator.cpp | 22 | ||||
-rw-r--r-- | src/qml/qml/qqmlvmemetaobject.cpp | 26 | ||||
-rw-r--r-- | tests/auto/qml/qqmllanguage/data/DeepAliasOnIC.qml | 3 | ||||
-rw-r--r-- | tests/auto/qml/qqmllanguage/data/deepAliasOnICUser.qml | 1 | ||||
-rw-r--r-- | tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp | 6 |
5 files changed, 41 insertions, 17 deletions
diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp index dbe8f4dc69..2cfccf14d1 100644 --- a/src/qml/qml/qqmlobjectcreator.cpp +++ b/src/qml/qml/qqmlobjectcreator.cpp @@ -909,10 +909,13 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *bindingProper && !(bindingFlags & QV4::CompiledData::Binding::IsPropertyObserver) && !_valueTypeProperty; - if (_ddata->hasBindingBit(bindingProperty->coreIndex()) && allowedToRemoveBinding) { - QQmlPropertyPrivate::removeBinding(_bindingTarget, QQmlPropertyIndex(bindingProperty->coreIndex())); - } else if (bindingProperty->isBindable() && allowedToRemoveBinding) { - removePendingBinding(_bindingTarget, bindingProperty->coreIndex()); + if (allowedToRemoveBinding) { + if (bindingProperty->isBindable()) { + removePendingBinding(_bindingTarget, bindingProperty->coreIndex()); + } else { + QQmlPropertyPrivate::removeBinding( + _bindingTarget, QQmlPropertyIndex(bindingProperty->coreIndex())); + } } if (bindingType == QV4::CompiledData::Binding::Type_Script || binding->isTranslationBinding()) { @@ -958,6 +961,9 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *bindingProper qmlBinding = QQmlPropertyBinding::create(bindingProperty, runtimeFunction, _scopeObject, context, currentQmlContext(), _bindingTarget, index); } sharedState.data()->allQPropertyBindings.push_back(DeferredQPropertyBinding {_bindingTarget, bindingProperty->coreIndex(), qmlBinding }); + + QQmlData *data = QQmlData::get(_bindingTarget, true); + data->setBindingBit(_bindingTarget, bindingProperty->coreIndex()); } else { // When writing bindings to grouped properties implemented as value types, // such as point.x: { someExpression; }, then the binding is installed on @@ -1469,6 +1475,14 @@ bool QQmlObjectCreator::finalize(QQmlInstantiationInterrupt &interrupt) while (!sharedState->allQPropertyBindings.isEmpty()) { auto& [target, index, qmlBinding] = sharedState->allQPropertyBindings.first(); + + QQmlData *data = QQmlData::get(target); + if (!data || !data->hasBindingBit(index)) { + // The target property has been overwritten since we stashed the binding. + sharedState->allQPropertyBindings.pop_front(); + continue; + } + QUntypedBindable bindable; void *argv[] = { &bindable }; // allow interception diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp index ee64b314fa..d5c0faa891 100644 --- a/src/qml/qml/qqmlvmemetaobject.cpp +++ b/src/qml/qml/qqmlvmemetaobject.cpp @@ -1045,15 +1045,20 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void * int coreIndex = encodedIndex.coreIndex(); const int valueTypePropertyIndex = encodedIndex.valueTypeIndex(); - // Remove binding (if any) on write - if(c == QMetaObject::WriteProperty) { - int flags = *reinterpret_cast<int*>(a[3]); - if (flags & QQmlPropertyData::RemoveBindingOnAliasWrite) { - QQmlData *targetData = QQmlData::get(target); - if (targetData && targetData->hasBindingBit(coreIndex)) - QQmlPropertyPrivate::removeBinding(target, encodedIndex); + const auto removePendingBinding + = [c, a](QObject *target, int coreIndex, QQmlPropertyIndex encodedIndex) { + // Remove binding (if any) on write + if (c == QMetaObject::WriteProperty) { + int flags = *reinterpret_cast<int*>(a[3]); + if (flags & QQmlPropertyData::RemoveBindingOnAliasWrite) { + QQmlData *targetData = QQmlData::get(target); + if (targetData && targetData->hasBindingBit(coreIndex)) { + QQmlPropertyPrivate::removeBinding(target, encodedIndex); + targetData->clearBindingBit(coreIndex); + } + } } - } + }; if (valueTypePropertyIndex != -1) { if (!targetDData->propertyCache) @@ -1063,6 +1068,7 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void * QQmlGadgetPtrWrapper *valueType = QQmlGadgetPtrWrapper::instance( ctxt->engine(), pd->propType()); if (valueType) { + removePendingBinding(target, coreIndex, encodedIndex); valueType->read(target, coreIndex); int rv = QMetaObject::metacall(valueType, c, valueTypePropertyIndex, a); @@ -1075,10 +1081,14 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void * // deep alias void *argv[1] = { &target }; QMetaObject::metacall(target, QMetaObject::ReadProperty, coreIndex, argv); + removePendingBinding( + target, valueTypePropertyIndex, + QQmlPropertyIndex(valueTypePropertyIndex)); return QMetaObject::metacall(target, c, valueTypePropertyIndex, a); } } else { + removePendingBinding(target, coreIndex, encodedIndex); return QMetaObject::metacall(target, c, coreIndex, a); } diff --git a/tests/auto/qml/qqmllanguage/data/DeepAliasOnIC.qml b/tests/auto/qml/qqmllanguage/data/DeepAliasOnIC.qml index 36a8cc6078..37dd2695b0 100644 --- a/tests/auto/qml/qqmllanguage/data/DeepAliasOnIC.qml +++ b/tests/auto/qml/qqmllanguage/data/DeepAliasOnIC.qml @@ -2,6 +2,7 @@ import QtQml QtObject { id: root + objectName: "theRoot" component ObjectWithColor: QtObject { property string color @@ -10,12 +11,14 @@ QtObject { property ObjectWithColor border: ObjectWithColor { id: border + objectName: root.objectName color: root.trueBorderColor varvar: root.trueBorderVarvar } readonly property rect readonlyRect: ({x: 12, y: 13, width: 14, height: 15}) + property alias borderObjectName: border.objectName property alias borderColor: border.color property alias borderVarvar: border.varvar property alias readonlyRectX: root.readonlyRect.x diff --git a/tests/auto/qml/qqmllanguage/data/deepAliasOnICUser.qml b/tests/auto/qml/qqmllanguage/data/deepAliasOnICUser.qml index ef6001cd89..50eaa7c3e2 100644 --- a/tests/auto/qml/qqmllanguage/data/deepAliasOnICUser.qml +++ b/tests/auto/qml/qqmllanguage/data/deepAliasOnICUser.qml @@ -1,6 +1,7 @@ import QtQml DeepAliasOnIC { + borderObjectName: "theLeaf" borderColor: "black" borderVarvar: "mauve" } diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp index 8e6af745d2..89fd37536e 100644 --- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp +++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp @@ -8231,15 +8231,11 @@ void tst_qqmllanguage::deepAliasOnICOrReadonly() QScopedPointer<QObject> o(c.create()); QVERIFY(!o.isNull()); - // We are mostly testing that it doesn't crash here. The actual bug is fixed separately. - - QEXPECT_FAIL("", "QTBUG-115579 is not fixed yet", Continue); QCOMPARE(o->property("borderColor").toString(), QLatin1String("black")); + QCOMPARE(o->property("borderObjectName").toString(), QLatin1String("theLeaf")); const QVariant var = o->property("borderVarvar"); - QEXPECT_FAIL("", "QTBUG-115579 is not fixed yet", Continue); QCOMPARE(var.metaType(), QMetaType::fromType<QString>()); - QEXPECT_FAIL("", "QTBUG-115579 is not fixed yet", Continue); QCOMPARE(var.toString(), QLatin1String("mauve")); QQmlComponent c2(&engine, testFileUrl("deepAliasOnReadonly.qml")); |