diff options
author | Ulf Hermann <ulf.hermann@qt.io> | 2024-04-03 17:55:45 +0200 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2024-04-05 20:38:07 +0200 |
commit | b91a26ae3b7b2ab68128f41db6ed4ccf7366dfc4 (patch) | |
tree | 172c9daaef074f9a875fb9aca8cc5ff938ccf0e4 /src/qml/qml | |
parent | 4b5f091c499b5aad66a8b39fcdab8f80d986a1f8 (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.h | 40 | ||||
-rw-r--r-- | src/qml/qml/qqmlpropertycachecreator.cpp | 7 | ||||
-rw-r--r-- | src/qml/qml/qqmlpropertycachecreator_p.h | 17 | ||||
-rw-r--r-- | src/qml/qml/qqmltypecompiler.cpp | 11 | ||||
-rw-r--r-- | src/qml/qml/qqmltypedata.cpp | 14 |
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) |