aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2023-05-05 12:21:08 +0200
committerUlf Hermann <ulf.hermann@qt.io>2023-05-06 08:21:16 +0200
commitef6e9f6b75848dfdacdd98cf9e7530f651b3dfca (patch)
treebba9e3010246aa84c5ec7a41fd0ed72ac3a6bcc4
parent567130e2d06a37b8615db7858050dfa0579ced93 (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.cpp29
-rw-r--r--src/qml/qml/qqmlobjectcreator.cpp6
-rw-r--r--src/qml/qml/qqmlobjectcreator_p.h10
-rw-r--r--tests/auto/qml/qqmlcomponent/data/removeBinding.qml21
-rw-r--r--tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp11
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"