aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2022-11-24 15:15:13 +0100
committerUlf Hermann <ulf.hermann@qt.io>2022-11-28 14:11:44 +0100
commitb6ba7e9c9023d1d5c6ba543c1c551344b7a9e5b5 (patch)
tree19ab013570976ea1191134f85f8115944a2e9866
parent6acf343acb532ad0579f8261ea281af3eb59da28 (diff)
Key required properties by object and property data
Property data alone is not enough as the same property can be required in multiple objects. Fixes: QTBUG-108291 Change-Id: I3b1c899e24bb2967d05372701f9b5d0927b3c711 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.cpp4
-rw-r--r--src/qml/qml/qqmlcomponent_p.h9
-rw-r--r--src/qml/qml/qqmlobjectcreator.cpp11
-rw-r--r--src/qml/qml/qqmlobjectcreator_p.h25
-rw-r--r--tests/auto/qml/qqmllanguage/data/multiRequired.qml12
-rw-r--r--tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp13
6 files changed, 63 insertions, 11 deletions
diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp
index 0ee74cdd19..657c978c23 100644
--- a/src/qml/qml/qqmlcomponent.cpp
+++ b/src/qml/qml/qqmlcomponent.cpp
@@ -1036,7 +1036,7 @@ QObject *QQmlComponentPrivate::beginCreate(QQmlRefPointer<QQmlContextData> conte
state.ensureRequiredPropertyStorage();
RequiredPropertyInfo info;
info.propertyName = propertyData->name(rv);
- state.addPendingRequiredProperty(propertyData, info);
+ state.addPendingRequiredProperty(rv, propertyData, info);
}
}
}
@@ -1147,7 +1147,7 @@ QQmlProperty QQmlComponentPrivate::removePropertyFromRequired(
Q_ASSERT(data && data->propertyCache);
targetProp = data->propertyCache->property(targetProp->coreIndex());
}
- auto it = requiredProperties->find(targetProp);
+ auto it = requiredProperties->find({createdComponent, targetProp});
if (it != requiredProperties->end()) {
if (wasInRequiredProperties)
*wasInRequiredProperties = true;
diff --git a/src/qml/qml/qqmlcomponent_p.h b/src/qml/qml/qqmlcomponent_p.h
index 2cebd54232..d76e1c24a3 100644
--- a/src/qml/qml/qqmlcomponent_p.h
+++ b/src/qml/qml/qqmlcomponent_p.h
@@ -110,7 +110,9 @@ public:
inline void ensureRequiredPropertyStorage();
inline RequiredProperties *requiredProperties();
- inline void addPendingRequiredProperty(const QQmlPropertyData *propData, const RequiredPropertyInfo &info);
+ inline void addPendingRequiredProperty(
+ const QObject *object, const QQmlPropertyData *propData,
+ const RequiredPropertyInfo &info);
inline bool hasUnsetRequiredProperties() const;
inline void clearRequiredProperties();
@@ -193,10 +195,11 @@ inline RequiredProperties *QQmlComponentPrivate::ConstructionState::requiredProp
return m_creatorOrRequiredProperties.asT2();
}
-inline void QQmlComponentPrivate::ConstructionState::addPendingRequiredProperty(const QQmlPropertyData *propData, const RequiredPropertyInfo &info)
+inline void QQmlComponentPrivate::ConstructionState::addPendingRequiredProperty(
+ const QObject *object, const QQmlPropertyData *propData, const RequiredPropertyInfo &info)
{
Q_ASSERT(requiredProperties());
- requiredProperties()->insert(propData, info);
+ requiredProperties()->insert({object, propData}, info);
}
inline bool QQmlComponentPrivate::ConstructionState::hasUnsetRequiredProperties() const {
diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp
index b85a6c1220..b000a10b13 100644
--- a/src/qml/qml/qqmlobjectcreator.cpp
+++ b/src/qml/qml/qqmlobjectcreator.cpp
@@ -694,8 +694,9 @@ void QQmlObjectCreator::setupBindings(BindingSetupFlags mode)
QQmlData *data = QQmlData::get(targetObject);
Q_ASSERT(data && data->propertyCache);
targetProperty = data->propertyCache->property(targetIndex.coreIndex());
+ sharedState->requiredProperties.remove({targetObject, targetProperty});
}
- sharedState->requiredProperties.remove(targetProperty);
+ sharedState->requiredProperties.remove({_bindingTarget, property});
}
@@ -1563,7 +1564,7 @@ bool QQmlObjectCreator::populateInstance(int index, QObject *instance, QObject *
postHocRequired.erase(postHocIt);
if (isContextObject)
sharedState->hadTopLevelRequiredProperties = true;
- sharedState->requiredProperties.insert(propertyData,
+ sharedState->requiredProperties.insert({_qobject, propertyData},
RequiredPropertyInfo {compilationUnit->stringAt(property->nameIndex), compilationUnit->finalUrl(), property->location, {}});
}
@@ -1623,7 +1624,7 @@ bool QQmlObjectCreator::populateInstance(int index, QObject *instance, QObject *
if (isContextObject)
sharedState->hadTopLevelRequiredProperties = true;
sharedState->requiredProperties.insert(
- propertyData,
+ {_qobject, propertyData},
RequiredPropertyInfo {
name, compilationUnit->finalUrl(), _compiledObject->location, {} });
}
@@ -1654,7 +1655,7 @@ bool QQmlObjectCreator::populateInstance(int index, QObject *instance, QObject *
if (isContextObject)
sharedState->hadTopLevelRequiredProperties = true;
sharedState->requiredProperties.insert(
- propertyData,
+ {_qobject, propertyData},
RequiredPropertyInfo {
name, compilationUnit->finalUrl(), _compiledObject->location, {} });
}
@@ -1687,7 +1688,7 @@ bool QQmlObjectCreator::populateInstance(int index, QObject *instance, QObject *
const QQmlPropertyData *const targetProperty = targetDData->propertyCache->property(coreIndex);
if (!targetProperty)
continue;
- auto it = sharedState->requiredProperties.find(targetProperty);
+ auto it = sharedState->requiredProperties.find({target, targetProperty});
if (it != sharedState->requiredProperties.end())
it->aliasesToRequired.push_back(
AliasToRequiredInfo {
diff --git a/src/qml/qml/qqmlobjectcreator_p.h b/src/qml/qml/qqmlobjectcreator_p.h
index 2371facc0a..c951072dd5 100644
--- a/src/qml/qml/qqmlobjectcreator_p.h
+++ b/src/qml/qml/qqmlobjectcreator_p.h
@@ -53,7 +53,30 @@ struct RequiredPropertyInfo
QVector<AliasToRequiredInfo> aliasesToRequired;
};
-class RequiredProperties : public QHash<const QQmlPropertyData *, RequiredPropertyInfo> {};
+struct RequiredPropertyKey
+{
+ RequiredPropertyKey() = default;
+ RequiredPropertyKey(const QObject *object, const QQmlPropertyData *data)
+ : object(object)
+ , data(data)
+ {}
+
+ const QObject *object = nullptr;
+ const QQmlPropertyData *data = nullptr;
+
+private:
+ friend size_t qHash(const RequiredPropertyKey &key, size_t seed = 0)
+ {
+ return qHashMulti(seed, key.object, key.data);
+ }
+
+ friend bool operator==(const RequiredPropertyKey &a, const RequiredPropertyKey &b)
+ {
+ return a.object == b.object && a.data == b.data;
+ }
+};
+
+class RequiredProperties : public QHash<RequiredPropertyKey, RequiredPropertyInfo> {};
struct DeferredQPropertyBinding {
QObject *target = nullptr;
diff --git a/tests/auto/qml/qqmllanguage/data/multiRequired.qml b/tests/auto/qml/qqmllanguage/data/multiRequired.qml
new file mode 100644
index 0000000000..442a4d226a
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/multiRequired.qml
@@ -0,0 +1,12 @@
+import QtQml
+
+QtObject {
+ component AccessibleButton : QtObject {
+ required property string description
+ objectName: description
+ }
+ property AccessibleButton a: AccessibleButton {}
+ property AccessibleButton b: AccessibleButton {
+ description: "b"
+ }
+}
diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
index 6884826894..948b3b1bc3 100644
--- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
+++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
@@ -401,6 +401,7 @@ private slots:
void functionSignatureEnforcement();
void importPrecedence();
void nullIsNull();
+ void multiRequired();
private:
QQmlEngine engine;
@@ -7740,6 +7741,18 @@ void tst_qqmllanguage::nullIsNull()
QTRY_COMPARE(o->property("someProperty").value<QObject*>(), nullptr);
}
+void tst_qqmllanguage::multiRequired()
+{
+ QQmlEngine engine;
+ const QUrl url = testFileUrl("multiRequired.qml");
+ QQmlComponent c(&engine, url);
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(o.isNull());
+ QCOMPARE(c.errorString(),
+ qPrintable(url.toString() + ":5 Required property description was not initialized\n"));
+}
+
QTEST_MAIN(tst_qqmllanguage)
#include "tst_qqmllanguage.moc"