aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/qml
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2024-04-03 17:55:45 +0200
committerUlf Hermann <ulf.hermann@qt.io>2024-04-05 20:38:07 +0200
commitb91a26ae3b7b2ab68128f41db6ed4ccf7366dfc4 (patch)
tree172c9daaef074f9a875fb9aca8cc5ff938ccf0e4 /src/qml/qml
parent4b5f091c499b5aad66a8b39fcdab8f80d986a1f8 (diff)
QtQml: Resolve generalized group properties during alias resolution
This way we can know the scope in which to search for the IDs. Pick-to: 6.7 6.5 Fixes: QTBUG-123865 Change-Id: I1dff9bdc69e3edaa80d85c757e3bb2b24e174cd0 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'src/qml/qml')
-rw-r--r--src/qml/qml/qqmlcomponentandaliasresolver_p.h40
-rw-r--r--src/qml/qml/qqmlpropertycachecreator.cpp7
-rw-r--r--src/qml/qml/qqmlpropertycachecreator_p.h17
-rw-r--r--src/qml/qml/qqmltypecompiler.cpp11
-rw-r--r--src/qml/qml/qqmltypedata.cpp14
5 files changed, 64 insertions, 25 deletions
diff --git a/src/qml/qml/qqmlcomponentandaliasresolver_p.h b/src/qml/qml/qqmlcomponentandaliasresolver_p.h
index e1c3cb2dea..a2758d385c 100644
--- a/src/qml/qml/qqmlcomponentandaliasresolver_p.h
+++ b/src/qml/qml/qqmlcomponentandaliasresolver_p.h
@@ -27,6 +27,12 @@ QT_BEGIN_NAMESPACE
Q_DECLARE_LOGGING_CATEGORY(lcQmlTypeCompiler);
+// This class primarily resolves component boundaries in a document.
+// With the information about boundaries, it then goes on to resolve aliases and generalized
+// group properties. Both rely on IDs as first part of their expressions and the IDs have
+// to be located in surrounding components. That's why we have to do this with the component
+// boundaries in mind.
+
template<typename ObjectContainer>
class QQmlComponentAndAliasResolver
{
@@ -55,12 +61,14 @@ private:
[[nodiscard]] bool markAsComponent(int index) const;
[[nodiscard]] AliasResolutionResult resolveAliasesInObject(
const CompiledObject &component, int objectIndex, QQmlError *error);
+ void resolveGeneralizedGroupProperty(const CompiledObject &component, CompiledBinding *binding);
[[nodiscard]] bool wrapImplicitComponent(CompiledBinding *binding);
[[nodiscard]] QQmlError findAndRegisterImplicitComponents(
const CompiledObject *obj, const QQmlPropertyCache::ConstPtr &propertyCache);
[[nodiscard]] QQmlError collectIdsAndAliases(int objectIndex);
[[nodiscard]] QQmlError resolveAliases(int componentIndex);
+ void resolveGeneralizedGroupProperties(int componentIndex);
[[nodiscard]] QQmlError resolveComponentsInInlineComponentRoot(int root);
QString stringAt(int idx) const { return m_compiler->stringAt(idx); }
@@ -111,6 +119,7 @@ private:
// indices of the objects that are actually Component {}
QVector<quint32> m_componentRoots;
QVector<int> m_objectsWithAliases;
+ QVector<CompiledBinding *> m_generalizedGroupProperties;
typename ObjectContainer::IdToObjectMap m_idToObjectIndex;
};
@@ -330,6 +339,7 @@ QQmlError QQmlComponentAndAliasResolver<ObjectContainer>::resolve(int root)
m_idToObjectIndex.clear();
m_objectsWithAliases.clear();
+ m_generalizedGroupProperties.clear();
if (const QQmlError error = collectIdsAndAliases(rootBinding->value.objectIndex);
error.isValid()) {
@@ -340,17 +350,24 @@ QQmlError QQmlComponentAndAliasResolver<ObjectContainer>::resolve(int root)
if (const QQmlError error = resolveAliases(m_componentRoots.at(i)); error.isValid())
return error;
+
+ resolveGeneralizedGroupProperties(m_componentRoots.at(i));
}
// Collect ids and aliases for root
m_idToObjectIndex.clear();
m_objectsWithAliases.clear();
+ m_generalizedGroupProperties.clear();
if (const QQmlError error = collectIdsAndAliases(root); error.isValid())
return error;
allocateNamedObjects(m_compiler->objectAt(root));
- return resolveAliases(root);
+ if (const QQmlError error = resolveAliases(root); error.isValid())
+ return error;
+
+ resolveGeneralizedGroupProperties(root);
+ return QQmlError();
}
template<typename ObjectContainer>
@@ -375,9 +392,19 @@ QQmlError QQmlComponentAndAliasResolver<ObjectContainer>::collectIdsAndAliases(i
for (auto binding = obj->bindingsBegin(), end = obj->bindingsEnd();
binding != end; ++binding) {
switch (binding->type()) {
+ case QV4::CompiledData::Binding::Type_GroupProperty: {
+ const auto *inner = m_compiler->objectAt(binding->value.objectIndex);
+ if (m_compiler->stringAt(inner->inheritedTypeNameIndex).isEmpty()) {
+ const auto cache = m_propertyCaches->at(objectIndex);
+ if (!cache || !cache->property(
+ m_compiler->stringAt(binding->propertyNameIndex), nullptr, nullptr)) {
+ m_generalizedGroupProperties.append(binding);
+ }
+ }
+ }
+ Q_FALLTHROUGH();
case QV4::CompiledData::Binding::Type_Object:
case QV4::CompiledData::Binding::Type_AttachedProperty:
- case QV4::CompiledData::Binding::Type_GroupProperty:
if (const QQmlError error = collectIdsAndAliases(binding->value.objectIndex);
error.isValid()) {
return error;
@@ -439,6 +466,15 @@ QQmlError QQmlComponentAndAliasResolver<ObjectContainer>::resolveAliases(int com
return QQmlError();
}
+template<typename ObjectContainer>
+void QQmlComponentAndAliasResolver<ObjectContainer>::resolveGeneralizedGroupProperties(
+ int componentIndex)
+{
+ const auto &component = *m_compiler->objectAt(componentIndex);
+ for (CompiledBinding *binding : m_generalizedGroupProperties)
+ resolveGeneralizedGroupProperty(component, binding);
+}
+
QT_END_NAMESPACE
#endif // QQMLCOMPONENTANDALIASRESOLVER_P_H
diff --git a/src/qml/qml/qqmlpropertycachecreator.cpp b/src/qml/qml/qqmlpropertycachecreator.cpp
index 780418380a..f6efe8d358 100644
--- a/src/qml/qml/qqmlpropertycachecreator.cpp
+++ b/src/qml/qml/qqmlpropertycachecreator.cpp
@@ -183,12 +183,7 @@ void QQmlPendingGroupPropertyBindings::resolveMissingPropertyCaches(
if (propertyCaches->at(groupPropertyObjectIndex))
continue;
- if (pendingBinding.instantiatingPropertyName.isEmpty()) {
- // Generalized group property.
- auto cache = propertyCaches->at(pendingBinding.referencingObjectIndex);
- propertyCaches->set(groupPropertyObjectIndex, cache);
- continue;
- }
+ Q_ASSERT(!pendingBinding.instantiatingPropertyName.isEmpty());
if (!pendingBinding.referencingObjectPropertyCache) {
pendingBinding.referencingObjectPropertyCache
diff --git a/src/qml/qml/qqmlpropertycachecreator_p.h b/src/qml/qml/qqmlpropertycachecreator_p.h
index 1067dd4c22..93987a1123 100644
--- a/src/qml/qml/qqmlpropertycachecreator_p.h
+++ b/src/qml/qml/qqmlpropertycachecreator_p.h
@@ -375,23 +375,6 @@ inline QQmlPropertyCache::ConstPtr QQmlPropertyCacheCreator<ObjectContainer>::pr
return nullptr;
}
return QQmlMetaType::propertyCache(attachedMo);
- } else if (binding->isGroupProperty()) {
- const auto *obj = objectContainer->objectAt(binding->value.objectIndex);
- if (!stringAt(obj->inheritedTypeNameIndex).isEmpty())
- return nullptr;
-
- for (int i = 0, end = objectContainer->objectCount(); i != end; ++i) {
- const auto *ext = objectContainer->objectAt(i);
- if (ext->idNameIndex != binding->propertyNameIndex)
- continue;
-
- if (ext->inheritedTypeNameIndex == 0)
- return nullptr;
-
- QQmlBindingInstantiationContext pendingContext(i, &(*binding), QString(), nullptr);
- pendingGroupPropertyBindings->append(pendingContext);
- return nullptr;
- }
}
}
return nullptr;
diff --git a/src/qml/qml/qqmltypecompiler.cpp b/src/qml/qml/qqmltypecompiler.cpp
index eb07ebc223..cdabd6d5bc 100644
--- a/src/qml/qml/qqmltypecompiler.cpp
+++ b/src/qml/qml/qqmltypecompiler.cpp
@@ -807,6 +807,17 @@ bool QQmlComponentAndAliasResolver<QQmlTypeCompiler>::wrapImplicitComponent(QmlI
}
template<>
+void QQmlComponentAndAliasResolver<QQmlTypeCompiler>::resolveGeneralizedGroupProperty(
+ const CompiledObject &component, CompiledBinding *binding)
+{
+ Q_UNUSED(component);
+ // We cannot make it fail here. It might be a custom-parsed property
+ const int targetObjectIndex = m_idToObjectIndex.value(binding->propertyNameIndex, -1);
+ if (targetObjectIndex != -1)
+ m_propertyCaches->set(binding->value.objectIndex, m_propertyCaches->at(targetObjectIndex));
+}
+
+template<>
typename QQmlComponentAndAliasResolver<QQmlTypeCompiler>::AliasResolutionResult
QQmlComponentAndAliasResolver<QQmlTypeCompiler>::resolveAliasesInObject(
const CompiledObject &component, int objectIndex, QQmlError *error)
diff --git a/src/qml/qml/qqmltypedata.cpp b/src/qml/qml/qqmltypedata.cpp
index bc456d5a7e..9acd801672 100644
--- a/src/qml/qml/qqmltypedata.cpp
+++ b/src/qml/qml/qqmltypedata.cpp
@@ -187,6 +187,20 @@ void QQmlComponentAndAliasResolver<QV4::CompiledData::CompilationUnit>::setObjec
}
template<>
+void QQmlComponentAndAliasResolver<QV4::CompiledData::CompilationUnit>::resolveGeneralizedGroupProperty(
+ const CompiledObject &component, CompiledBinding *binding)
+{
+ // We cannot make it fail here. It might be a custom-parsed property
+ for (int i = 0, count = component.namedObjectsInComponentCount(); i < count; ++i) {
+ const int candidateIndex = component.namedObjectsInComponentTable()[i];
+ if (m_compiler->objectAt(candidateIndex)->idNameIndex == binding->propertyNameIndex) {
+ m_propertyCaches->set(binding->value.objectIndex, m_propertyCaches->at(candidateIndex));
+ return;
+ }
+ }
+}
+
+template<>
typename QQmlComponentAndAliasResolver<QV4::CompiledData::CompilationUnit>::AliasResolutionResult
QQmlComponentAndAliasResolver<QV4::CompiledData::CompilationUnit>::resolveAliasesInObject(
const CompiledObject &component, int objectIndex, QQmlError *error)