diff options
author | Ulf Hermann <ulf.hermann@qt.io> | 2023-05-05 12:21:08 +0200 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2023-05-06 08:21:16 +0200 |
commit | ef6e9f6b75848dfdacdd98cf9e7530f651b3dfca (patch) | |
tree | bba9e3010246aa84c5ec7a41fd0ed72ac3a6bcc4 | |
parent | 567130e2d06a37b8615db7858050dfa0579ced93 (diff) |
QQmlComponent: Remove pending bindings when setting properties
Pick-to: 6.2 6.5
Fixes: QTBUG-99363
Change-Id: I2c731ec0b8c5947192accdeb5ef52903d9c7cd90
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
-rw-r--r-- | src/qml/qml/qqmlcomponent.cpp | 29 | ||||
-rw-r--r-- | src/qml/qml/qqmlobjectcreator.cpp | 6 | ||||
-rw-r--r-- | src/qml/qml/qqmlobjectcreator_p.h | 10 | ||||
-rw-r--r-- | tests/auto/qml/qqmlcomponent/data/removeBinding.qml | 21 | ||||
-rw-r--r-- | tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp | 11 |
5 files changed, 70 insertions, 7 deletions
diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp index 10df481106..5ad5a1e742 100644 --- a/src/qml/qml/qqmlcomponent.cpp +++ b/src/qml/qml/qqmlcomponent.cpp @@ -351,13 +351,33 @@ bool QQmlComponentPrivate::setInitialProperty( if (scope.engine->hasException) break; } - segment = scope.engine->newString(properties.last()); + const QString lastProperty = properties.last(); + segment = scope.engine->newString(lastProperty); object->put(segment, scope.engine->metaTypeToJS(value.metaType(), value.constData())); if (scope.engine->hasException) { qmlWarning(base, scope.engine->catchExceptionAsQmlError()); scope.engine->hasException = false; return false; } + if (QQmlObjectCreator *creator = state.creator()) { + if (QV4::QObjectWrapper *wrapper = object->as<QV4::QObjectWrapper>()) { + if (QObject *o = wrapper->object()) { + if (QQmlData *ddata = QQmlData::get(o)) { + if (const QQmlPropertyData *propData = ddata->propertyCache->property( + lastProperty, o, ddata->outerContext)) { + if (propData->isBindable()) + creator->removePendingBinding(o, propData->coreIndex()); + } + } else { + const QMetaObject *meta = o->metaObject(); + Q_ASSERT(meta); + const int index = meta->indexOfProperty(lastProperty.toUtf8()); + if (index != -1 && meta->property(index).isBindable()) + creator->removePendingBinding(o, index); + } + } + } + } return true; } @@ -369,7 +389,12 @@ bool QQmlComponentPrivate::setInitialProperty( prop = QQmlProperty(base, name, engine); QQmlPropertyPrivate *privProp = QQmlPropertyPrivate::get(prop); const bool isValid = prop.isValid(); - if (!isValid || !privProp->writeValueProperty(value, {})) { + if (isValid && privProp->writeValueProperty(value, {})) { + if (prop.isBindable()) { + if (QQmlObjectCreator *creator = state.creator()) + creator->removePendingBinding(prop.object(), prop.index()); + } + } else { QQmlError error{}; error.setUrl(url); if (isValid) { diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp index a4861464ad..f7d2b94059 100644 --- a/src/qml/qml/qqmlobjectcreator.cpp +++ b/src/qml/qml/qqmlobjectcreator.cpp @@ -902,11 +902,7 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *bindingProper if (_ddata->hasBindingBit(bindingProperty->coreIndex()) && allowedToRemoveBinding) { QQmlPropertyPrivate::removeBinding(_bindingTarget, QQmlPropertyIndex(bindingProperty->coreIndex())); } else if (bindingProperty->isBindable() && allowedToRemoveBinding) { - QList<DeferredQPropertyBinding> &pendingBindings = sharedState.data()->allQPropertyBindings; - auto it = std::remove_if(pendingBindings.begin(), pendingBindings.end(), [&](const DeferredQPropertyBinding &deferred) { - return deferred.properyIndex == bindingProperty->coreIndex() && deferred.target == _bindingTarget; - }); - pendingBindings.erase(it, pendingBindings.end()); + removePendingBinding(_bindingTarget, bindingProperty->coreIndex()); } if (bindingType == QV4::CompiledData::Binding::Type_Script || binding->isTranslationBinding()) { diff --git a/src/qml/qml/qqmlobjectcreator_p.h b/src/qml/qml/qqmlobjectcreator_p.h index c951072dd5..79e5685114 100644 --- a/src/qml/qml/qqmlobjectcreator_p.h +++ b/src/qml/qml/qqmlobjectcreator_p.h @@ -144,6 +144,16 @@ public: int index, QObject *parent, const QQmlRefPointer<QQmlContextData> &context); + void removePendingBinding(QObject *target, int propertyIndex) + { + QList<DeferredQPropertyBinding> &pendingBindings = sharedState.data()->allQPropertyBindings; + auto it = std::remove_if(pendingBindings.begin(), pendingBindings.end(), + [&](const DeferredQPropertyBinding &deferred) { + return deferred.properyIndex == propertyIndex && deferred.target == target; + }); + pendingBindings.erase(it, pendingBindings.end()); + } + private: QQmlObjectCreator(QQmlRefPointer<QQmlContextData> contextData, const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit, diff --git a/tests/auto/qml/qqmlcomponent/data/removeBinding.qml b/tests/auto/qml/qqmlcomponent/data/removeBinding.qml new file mode 100644 index 0000000000..08126a1db2 --- /dev/null +++ b/tests/auto/qml/qqmlcomponent/data/removeBinding.qml @@ -0,0 +1,21 @@ +import QtQml 2.15 + +QtObject { + id: root + objectName: "400" + + property Component c: Component { + id: customItem + QtObject { + objectName: root.objectName + } + } + + property string result: { + const properties = { + "objectName": "42", + } + const item = customItem.createObject(root, properties) + return item.objectName; + } +} diff --git a/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp b/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp index d76768c5d7..d6a53b9950 100644 --- a/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp +++ b/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp @@ -145,6 +145,7 @@ private slots: void loadFromModuleFailures(); void loadFromModuleRequired(); void loadFromQrc(); + void removeBinding(); private: QQmlEngine engine; @@ -1439,6 +1440,16 @@ void tst_qqmlcomponent::loadFromQrc() QVERIFY(p->compilationUnit->aotCompiledFunctions); } +void tst_qqmlcomponent::removeBinding() +{ + QQmlEngine e; + QQmlComponent c(&e, testFileUrl("removeBinding.qml")); + QVERIFY2(c.isReady(), qPrintable(c.errorString())); + QScopedPointer<QObject> o(c.create()); + QVERIFY(!o.isNull()); + QCOMPARE(o->property("result"), QStringLiteral("42")); +} + QTEST_MAIN(tst_qqmlcomponent) #include "tst_qqmlcomponent.moc" |