diff options
-rw-r--r-- | src/qml/inlinecomponentutils_p.h | 3 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4executablecompilationunit.cpp | 78 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4executablecompilationunit_p.h | 6 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4function.cpp | 3 | ||||
-rw-r--r-- | src/qml/qml/qqmlimport.cpp | 39 | ||||
-rw-r--r-- | src/qml/qml/qqmlmetatype.cpp | 2 | ||||
-rw-r--r-- | src/qml/qml/qqmlobjectcreator.cpp | 21 | ||||
-rw-r--r-- | src/qml/qml/qqmlpropertycachecreator_p.h | 12 | ||||
-rw-r--r-- | src/qml/qml/qqmltype.cpp | 59 | ||||
-rw-r--r-- | src/qml/qml/qqmltype_p.h | 9 | ||||
-rw-r--r-- | src/qml/qml/qqmltype_p_p.h | 4 | ||||
-rw-r--r-- | src/qml/qml/qqmltypecompiler.cpp | 4 | ||||
-rw-r--r-- | src/qml/qml/qqmltypecompiler_p.h | 2 | ||||
-rw-r--r-- | src/qml/qml/qqmltypedata.cpp | 53 | ||||
-rw-r--r-- | src/qml/qml/qqmltypedata_p.h | 4 | ||||
-rw-r--r-- | tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp | 2 |
16 files changed, 144 insertions, 157 deletions
diff --git a/src/qml/inlinecomponentutils_p.h b/src/qml/inlinecomponentutils_p.h index 5a4d8272e5..92ae719750 100644 --- a/src/qml/inlinecomponentutils_p.h +++ b/src/qml/inlinecomponentutils_p.h @@ -77,7 +77,8 @@ void fillAdjacencyListForInlineComponents(ObjectContainer *objectContainer, if (targetType.isInlineComponentType() && targetType.containingType() == currentICTypeRef->type().containingType()) { auto icIt = std::find_if(allICs.cbegin(), allICs.cend(), [&](const QV4::CompiledData::InlineComponent &icSearched){ - return int(icSearched.objectIndex) == targetType.inlineComponentObjectId(); + return objectContainer->stringAt(icSearched.nameIndex) + == targetType.elementName(); }); Q_ASSERT(icIt != allICs.cend()); Node& target = nodes[i]; diff --git a/src/qml/jsruntime/qv4executablecompilationunit.cpp b/src/qml/jsruntime/qv4executablecompilationunit.cpp index a4293310c4..0bdf5acba4 100644 --- a/src/qml/jsruntime/qv4executablecompilationunit.cpp +++ b/src/qml/jsruntime/qv4executablecompilationunit.cpp @@ -357,6 +357,31 @@ IdentifierHash ExecutableCompilationUnit::createNamedObjectsPerComponent(int com return *namedObjectsPerComponentCache.insert(componentObjectIndex, namedObjectCache); } +template<typename F> +void processInlinComponentType( + const QQmlType &type, const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit, + F &&populateIcData) +{ + if (type.isInlineComponentType()) { + QString icRootName; + if (compilationUnit->icRootName) { + icRootName = type.elementName(); + std::swap(*compilationUnit->icRootName, icRootName); + } else { + compilationUnit->icRootName = std::make_unique<QString>(type.elementName()); + } + + populateIcData(); + + if (icRootName.isEmpty()) + compilationUnit->icRootName.reset(); + else + std::swap(*compilationUnit->icRootName, icRootName); + } else { + populateIcData(); + } +} + void ExecutableCompilationUnit::finalizeCompositeType(CompositeMetaTypeIds types) { // Add to type registry of composites @@ -402,7 +427,7 @@ void ExecutableCompilationUnit::finalizeCompositeType(CompositeMetaTypeIds types // and in that case we need to add its object count for (auto nodeIt = nodesSorted.rbegin(); nodeIt != nodesSorted.rend(); ++nodeIt) { const auto &ic = allICs.at(nodeIt->index()); - int lastICRoot = ic.objectIndex; + const int lastICRoot = ic.objectIndex; for (int i = ic.objectIndex; i<objectCount(); ++i) { const QV4::CompiledData::Object *obj = objectAt(i); bool leftCurrentInlineComponent @@ -411,24 +436,24 @@ void ExecutableCompilationUnit::finalizeCompositeType(CompositeMetaTypeIds types || !obj->hasFlag(QV4::CompiledData::Object::IsPartOfInlineComponent); if (leftCurrentInlineComponent) break; - inlineComponentData[lastICRoot].totalBindingCount += obj->nBindings; + const QString lastICRootName = stringAt(ic.nameIndex); + inlineComponentData[lastICRootName].totalBindingCount += obj->nBindings; if (auto *typeRef = resolvedTypes.value(obj->inheritedTypeNameIndex)) { const auto type = typeRef->type(); if (type.isValid() && type.parserStatusCast() != -1) - ++inlineComponentData[lastICRoot].totalParserStatusCount; + ++inlineComponentData[lastICRootName].totalParserStatusCount; - ++inlineComponentData[lastICRoot].totalObjectCount; + ++inlineComponentData[lastICRootName].totalObjectCount; if (const auto compilationUnit = typeRef->compilationUnit()) { // if the type is an inline component type, we have to extract the information from it // This requires that inline components are visited in the correct order - auto icRoot = compilationUnit->icRoot; - if (type.isInlineComponentType()) - icRoot = type.inlineComponentId(); - QScopedValueRollback<int> rollback {compilationUnit->icRoot, icRoot}; - inlineComponentData[lastICRoot].totalBindingCount += compilationUnit->totalBindingsCount(); - inlineComponentData[lastICRoot].totalParserStatusCount += compilationUnit->totalParserStatusCount(); - inlineComponentData[lastICRoot].totalObjectCount += compilationUnit->totalObjectCount(); + processInlinComponentType(type, compilationUnit, [&]() { + auto &icData = inlineComponentData[lastICRootName]; + icData.totalBindingCount += compilationUnit->totalBindingsCount(); + icData.totalParserStatusCount += compilationUnit->totalParserStatusCount(); + icData.totalObjectCount += compilationUnit->totalObjectCount(); + }); } } } @@ -448,13 +473,11 @@ void ExecutableCompilationUnit::finalizeCompositeType(CompositeMetaTypeIds types ++parserStatusCount; ++objectCount; if (const auto compilationUnit = typeRef->compilationUnit()) { - auto icRoot = compilationUnit->icRoot; - if (type.isInlineComponentType()) - icRoot = type.inlineComponentId(); - QScopedValueRollback<int> rollback {compilationUnit->icRoot, icRoot}; - bindingCount += compilationUnit->totalBindingsCount(); - parserStatusCount += compilationUnit->totalParserStatusCount(); - objectCount += compilationUnit->totalObjectCount(); + processInlinComponentType(type, compilationUnit, [&](){ + bindingCount += compilationUnit->totalBindingsCount(); + parserStatusCount += compilationUnit->totalParserStatusCount(); + objectCount += compilationUnit->totalObjectCount(); + }); } } } @@ -465,21 +488,21 @@ void ExecutableCompilationUnit::finalizeCompositeType(CompositeMetaTypeIds types } int ExecutableCompilationUnit::totalBindingsCount() const { - if (icRoot == -1) + if (!icRootName) return m_totalBindingsCount; - return inlineComponentData[icRoot].totalBindingCount; + return inlineComponentData[*icRootName].totalBindingCount; } int ExecutableCompilationUnit::totalObjectCount() const { - if (icRoot == -1) + if (!icRootName) return m_totalObjectCount; - return inlineComponentData[icRoot].totalObjectCount; + return inlineComponentData[*icRootName].totalObjectCount; } int ExecutableCompilationUnit::totalParserStatusCount() const { - if (icRoot == -1) + if (!icRootName) return m_totalParserStatusCount; - return inlineComponentData[icRoot].totalParserStatusCount; + return inlineComponentData[*icRootName].totalParserStatusCount; } bool ExecutableCompilationUnit::verifyChecksum(const CompiledData::DependentTypesHasher &dependencyHasher) const @@ -497,11 +520,12 @@ bool ExecutableCompilationUnit::verifyChecksum(const CompiledData::DependentType sizeof(data->dependencyMD5Checksum)) == 0; } -CompositeMetaTypeIds ExecutableCompilationUnit::typeIdsForComponent(int objectid) const +CompositeMetaTypeIds ExecutableCompilationUnit::typeIdsForComponent( + const QString &inlineComponentName) const { - if (objectid == 0) + if (inlineComponentName.isEmpty()) return typeIds; - return inlineComponentData[objectid].typeIds; + return inlineComponentData[inlineComponentName].typeIds; } QStringList ExecutableCompilationUnit::moduleRequests() const diff --git a/src/qml/jsruntime/qv4executablecompilationunit_p.h b/src/qml/jsruntime/qv4executablecompilationunit_p.h index 3a0efa467e..b110ea3fd1 100644 --- a/src/qml/jsruntime/qv4executablecompilationunit_p.h +++ b/src/qml/jsruntime/qv4executablecompilationunit_p.h @@ -131,7 +131,7 @@ public: int m_totalBindingsCount = 0; // Number of bindings used in this type int m_totalParserStatusCount = 0; // Number of instantiated types that are QQmlParserStatus subclasses int m_totalObjectCount = 0; // Number of objects explicitly instantiated - int icRoot = -1; + std::unique_ptr<QString> icRootName; int totalBindingsCount() const; int totalParserStatusCount() const; @@ -143,12 +143,12 @@ public: bool verifyChecksum(const CompiledData::DependentTypesHasher &dependencyHasher) const; - CompositeMetaTypeIds typeIdsForComponent(int objectid = 0) const; + CompositeMetaTypeIds typeIdsForComponent(const QString &inlineComponentName = QString()) const; CompositeMetaTypeIds typeIds; bool isRegistered = false; - QHash<int, InlineComponentData> inlineComponentData; + QHash<QString, InlineComponentData> inlineComponentData; int inlineComponentId(const QString &inlineComponentName) const { diff --git a/src/qml/jsruntime/qv4function.cpp b/src/qml/jsruntime/qv4function.cpp index 5edccafa3c..42f952ff19 100644 --- a/src/qml/jsruntime/qv4function.cpp +++ b/src/qml/jsruntime/qv4function.cpp @@ -163,8 +163,7 @@ Function::Function(ExecutionEngine *engine, ExecutableCompilationUnit *unit, if (!qmltype.isComposite()) { if (!qmltype.isInlineComponentType()) return QMetaType(); - const CompositeMetaTypeIds typeIds - = unit->typeIdsForComponent(qmltype.inlineComponentId()); + const CompositeMetaTypeIds typeIds = unit->typeIdsForComponent(qmltype.elementName()); return param.isList() ? typeIds.listId : typeIds.id; } diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp index 874f642283..65fbd498c9 100644 --- a/src/qml/qml/qqmlimport.cpp +++ b/src/qml/qml/qqmlimport.cpp @@ -584,10 +584,10 @@ bool QQmlImportInstance::resolveType(QQmlTypeLoader *typeLoader, const QHashedSt Q_ASSERT(!type_return->isValid()); auto createICType = [&]() { auto typePriv = new QQmlTypePrivate {QQmlType::RegistrationType::InlineComponentType}; - bool ok = false; - typePriv->extraData.id->objectId = QUrl(this->url).fragment().toInt(&ok); - Q_ASSERT(ok); - typePriv->extraData.id->url = QUrl(this->url); + const QUrl ownUrl = QUrl(url); + typePriv->elementName = ownUrl.fragment(); + Q_ASSERT(!typePriv->elementName.isEmpty()); + typePriv->extraData.id->url = ownUrl; auto icType = QQmlType(typePriv); typePriv->release(); return icType; @@ -595,12 +595,13 @@ bool QQmlImportInstance::resolveType(QQmlTypeLoader *typeLoader, const QHashedSt if (containingType.isValid()) { // we currently cannot reference a Singleton inside itself // in that case, containingType is still invalid - if (int icID = containingType.lookupInlineComponentIdByName(typeStr); icID != -1) { - *type_return = containingType.lookupInlineComponentById(icID); + if (QQmlType icID = containingType.lookupInlineComponentByName(typeStr); + icID.isValid()) { + *type_return = icID; } else { auto icType = createICType(); - int placeholderId = containingType.generatePlaceHolderICId(); - const_cast<QQmlImportInstance*>(this)->containingType.associateInlineComponent(typeStr, placeholderId, CompositeMetaTypeIds {}, icType); + const_cast<QQmlImportInstance*>(this)->containingType.associateInlineComponent( + typeStr, CompositeMetaTypeIds {}, icType); *type_return = QQmlType(icType); } } else { @@ -766,18 +767,17 @@ bool QQmlImports::resolveType( if (resolveTypeInNamespace(splitName.at(0), &m_unqualifiedset, nullptr)) { // either simple type + inline component auto const icName = splitName.at(1).toString(); - auto objectIndex = type_return->lookupInlineComponentIdByName(icName); - if (objectIndex != -1) { - *type_return = type_return->lookupInlineComponentById(objectIndex); + auto ic = type_return->lookupInlineComponentByName(icName); + if (ic.isValid()) { + *type_return = ic; } else { auto icTypePriv = new QQmlTypePrivate(QQmlType::RegistrationType::InlineComponentType); icTypePriv->setContainingType(type_return); icTypePriv->extraData.id->url = type_return->sourceUrl(); - int placeholderId = type_return->generatePlaceHolderICId(); - icTypePriv->extraData.id->url.setFragment(QString::number(placeholderId)); + icTypePriv->extraData.id->url.setFragment(icName); auto icType = QQmlType(icTypePriv); icTypePriv->release(); - type_return->associateInlineComponent(icName, placeholderId, CompositeMetaTypeIds {}, icType); + type_return->associateInlineComponent(icName, CompositeMetaTypeIds {}, icType); *type_return = icType; } Q_ASSERT(type_return->containingType().isValid()); @@ -803,18 +803,17 @@ bool QQmlImports::resolveType( } else { if (resolveTypeInNamespace(splitName.at(1), s, nullptr)) { auto const icName = splitName.at(2).toString(); - auto objectIndex = type_return->lookupInlineComponentIdByName(icName); - if (objectIndex != -1) - *type_return = type_return->lookupInlineComponentById(objectIndex); + QQmlType ic = type_return->lookupInlineComponentByName(icName); + if (ic.isValid()) + *type_return = ic; else { auto icTypePriv = new QQmlTypePrivate(QQmlType::RegistrationType::InlineComponentType); icTypePriv->setContainingType(type_return); icTypePriv->extraData.id->url = type_return->sourceUrl(); - int placeholderId = type_return->generatePlaceHolderICId(); - icTypePriv->extraData.id->url.setFragment(QString::number(placeholderId)); + icTypePriv->extraData.id->url.setFragment(icName); auto icType = QQmlType(icTypePriv); icTypePriv->release(); - type_return->associateInlineComponent(icName, placeholderId, CompositeMetaTypeIds {}, icType); + type_return->associateInlineComponent(icName, CompositeMetaTypeIds {}, icType); *type_return = icType; } type_return->setPendingResolutionName(icName); diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp index d1123f3c4e..415bee061c 100644 --- a/src/qml/qml/qqmlmetatype.cpp +++ b/src/qml/qml/qqmlmetatype.cpp @@ -1440,7 +1440,7 @@ void QQmlMetaType::registerMetaObjectForType(const QMetaObject *metaobject, QQml static bool hasActiveInlineComponents(const QQmlTypePrivate *d) { - for (const QQmlType &ic : std::as_const(d->objectIdToICType)) { + for (const QQmlType &ic : std::as_const(d->namesToInlineComponentType)) { const QQmlTypePrivate *icPriv = ic.priv(); if (icPriv && icPriv->count() > 1) return true; diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp index f7d2b94059..ea31ff0b56 100644 --- a/src/qml/qml/qqmlobjectcreator.cpp +++ b/src/qml/qml/qqmlobjectcreator.cpp @@ -1275,11 +1275,26 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo return nullptr; } } else { - int subObjectId = type.inlineComponentId(); - QScopedValueRollback<int> rollback {compilationUnit->icRoot, subObjectId}; + QString subObjectName; + if (compilationUnit->icRootName) { + subObjectName = type.elementName(); + std::swap(*compilationUnit->icRootName, subObjectName); + } else { + compilationUnit->icRootName = std::make_unique<QString>(type.elementName()); + } + + const auto guard = qScopeGuard([&] { + if (subObjectName.isEmpty()) + compilationUnit->icRootName.reset(); + else + std::swap(*compilationUnit->icRootName, subObjectName); + }); + QQmlObjectCreator subCreator(context, compilationUnit, sharedState.data(), isContextObject); - instance = subCreator.create(subObjectId, nullptr, nullptr, CreationFlags::InlineComponent); + instance = subCreator.create( + compilationUnit->inlineComponentId(*compilationUnit->icRootName), + nullptr, nullptr, CreationFlags::InlineComponent); if (!instance) { errors += subCreator.errors; return nullptr; diff --git a/src/qml/qml/qqmlpropertycachecreator_p.h b/src/qml/qml/qqmlpropertycachecreator_p.h index 7c6c54c611..d8f22a06ba 100644 --- a/src/qml/qml/qqmlpropertycachecreator_p.h +++ b/src/qml/qml/qqmlpropertycachecreator_p.h @@ -628,16 +628,16 @@ inline QQmlError QQmlPropertyCacheCreator<ObjectContainer>::createMetaObject( if (qmltype.isComposite() || qmltype.isInlineComponentType()) { CompositeMetaTypeIds typeIds; if (qmltype.isInlineComponentType()) { - auto objectId = qmltype.inlineComponentId(); + const QString icName = qmltype.elementName(); auto containingType = qmltype.containingType(); if (containingType.isValid()) { - auto icType = containingType.lookupInlineComponentById(objectId); + auto icType = containingType.lookupInlineComponentByName(icName); typeIds = {icType.typeId(), icType.qListTypeId()}; } else { typeIds = {}; } if (!typeIds.isValid()) // type has not been registered yet, we must be in containing type - typeIds = objectContainer->typeIdsForComponent(objectId); + typeIds = objectContainer->typeIdsForComponent(icName); Q_ASSERT(typeIds.isValid()); } else if (selfReference) { typeIds = objectContainer->typeIdsForComponent(); @@ -713,8 +713,7 @@ inline QMetaType QQmlPropertyCacheCreator<ObjectContainer>::metaTypeForParameter if (!qmltype.isComposite()) { const QMetaType typeId = param.isList() ? qmltype.qListTypeId() : qmltype.typeId(); if (!typeId.isValid() && qmltype.isInlineComponentType()) { - const int objectId = qmltype.inlineComponentId(); - const auto typeIds = objectContainer->typeIdsForComponent(objectId); + const auto typeIds = objectContainer->typeIdsForComponent(qmltype.elementName()); return param.isList() ? typeIds.listId : typeIds.id; } else { return typeId; @@ -825,8 +824,7 @@ inline QQmlError QQmlPropertyCacheAliasCreator<ObjectContainer>::propertyDataFor if (referencedType.isValid()) { *type = referencedType.typeId(); if (!type->isValid() && referencedType.isInlineComponentType()) { - int objectId = referencedType.inlineComponentId(); - *type = objectContainer->typeIdsForComponent(objectId).id; + *type = objectContainer->typeIdsForComponent(referencedType.elementName()).id; Q_ASSERT(type->isValid()); } } else { diff --git a/src/qml/qml/qqmltype.cpp b/src/qml/qml/qqmltype.cpp index d01aa5ba11..85e3f8295a 100644 --- a/src/qml/qml/qqmltype.cpp +++ b/src/qml/qml/qqmltype.cpp @@ -743,24 +743,9 @@ bool QQmlType::isInlineComponentType() const { return d ? d->regType == QQmlType::InlineComponentType : false; } -int QQmlType::inlineComponentId() const { - bool ok = false; - if (d->regType == QQmlType::RegistrationType::InlineComponentType) { - Q_ASSERT(d->extraData.id->objectId != -1); - return d->extraData.id->objectId; - } - int subObjectId = sourceUrl().fragment().toInt(&ok); - return ok ? subObjectId : -1; -} - QUrl QQmlType::sourceUrl() const { - auto url = d ? d->sourceUrl() : QUrl(); - if (url.isValid() && d->regType == QQmlType::RegistrationType::InlineComponentType && d->extraData.id->objectId) { - Q_ASSERT(url.hasFragment()); - url.setFragment(QString::number(inlineComponentId())); - } - return url; + return d ? d->sourceUrl() : QUrl(); } int QQmlType::enumValue(QQmlEnginePrivate *engine, const QHashedStringRef &name, bool *ok) const @@ -926,19 +911,6 @@ int QQmlType::scopedEnumValue(QQmlEnginePrivate *engine, QStringView scopedEnumN return -1; } -int QQmlType::inlineComponentObjectId() const -{ - if (!isInlineComponentType()) - return -1; - return d->extraData.id->objectId; -} - -void QQmlType::setInlineComponentObjectId(int id) const -{ - Q_ASSERT(d && d->regType == QQmlType::InlineComponentType); - d->extraData.id->objectId = id; -} - void QQmlType::refHandle(const QQmlTypePrivate *priv) { if (priv) @@ -958,10 +930,10 @@ int QQmlType::refCount(const QQmlTypePrivate *priv) return -1; } -int QQmlType::lookupInlineComponentIdByName(const QString &name) const +QQmlType QQmlType::lookupInlineComponentByName(const QString &name) const { Q_ASSERT(d); - return d->namesToInlineComponentObjectIndex.value(name, -1); + return d->namesToInlineComponentType.value(name); } QQmlType QQmlType::containingType() const @@ -972,37 +944,20 @@ QQmlType QQmlType::containingType() const return ret; } -QQmlType QQmlType::lookupInlineComponentById(int objectid) const -{ - Q_ASSERT(d); - return d->objectIdToICType.value(objectid, QQmlType(nullptr)); -} - -int QQmlType::generatePlaceHolderICId() const -{ - Q_ASSERT(d); - int id = -2; - for (auto it = d->objectIdToICType.keyBegin(); it != d->objectIdToICType.keyEnd(); ++it) - if (*it < id) - id = *it; - return id; -} - -void QQmlType::associateInlineComponent(const QString &name, int objectID, const CompositeMetaTypeIds &metaTypeIds, QQmlType existingType) +void QQmlType::associateInlineComponent( + const QString &name, const CompositeMetaTypeIds &metaTypeIds, QQmlType existingType) { bool const reuseExistingType = existingType.isValid(); auto priv = reuseExistingType ? const_cast<QQmlTypePrivate *>(existingType.d.data()) : new QQmlTypePrivate { RegistrationType::InlineComponentType } ; priv->setName( QString::fromUtf8(typeName()), name); auto icUrl = QUrl(sourceUrl()); - icUrl.setFragment(QString::number(objectID)); + icUrl.setFragment(name); priv->extraData.id->url = icUrl; priv->extraData.id->containingType = d.data(); - priv->extraData.id->objectId = objectID; priv->typeId = metaTypeIds.id; priv->listId = metaTypeIds.listId; - d->namesToInlineComponentObjectIndex.insert(name, objectID); QQmlType icType(priv); - d->objectIdToICType.insert(objectID, icType); + d->namesToInlineComponentType.insert(name, icType); if (!reuseExistingType) priv->release(); } diff --git a/src/qml/qml/qqmltype_p.h b/src/qml/qml/qqmltype_p.h index c2c85c9c2e..a92381b803 100644 --- a/src/qml/qml/qqmltype_p.h +++ b/src/qml/qml/qqmltype_p.h @@ -119,7 +119,6 @@ public: int index() const; bool isInlineComponentType() const; - int inlineComponentId() const; struct Q_QML_PRIVATE_EXPORT SingletonInstanceInfo { @@ -143,8 +142,6 @@ public: int scopedEnumValue(QQmlEnginePrivate *engine, int index, const QString &, bool *ok) const; int scopedEnumValue(QQmlEnginePrivate *engine, const QByteArray &, const QByteArray &, bool *ok) const; int scopedEnumValue(QQmlEnginePrivate *engine, QStringView, QStringView, bool *ok) const; - int inlineComponentObjectId() const; - void setInlineComponentObjectId(int id) const; // TODO: const setters are BAD const QQmlTypePrivate *priv() const { return d.data(); } static void refHandle(const QQmlTypePrivate *priv); @@ -163,11 +160,9 @@ public: }; QQmlType containingType() const; - int lookupInlineComponentIdByName(const QString &name) const; - QQmlType lookupInlineComponentById(int objectid) const; - int generatePlaceHolderICId() const; + QQmlType lookupInlineComponentByName(const QString &name) const; - void associateInlineComponent(const QString &name, int objectID, const CompositeMetaTypeIds &metaTypeIds, QQmlType existingType); + void associateInlineComponent(const QString &name, const CompositeMetaTypeIds &metaTypeIds, QQmlType existingType); void setPendingResolutionName(const QString &name); QString pendingResolutionName() const; diff --git a/src/qml/qml/qqmltype_p_p.h b/src/qml/qml/qqmltype_p_p.h index d2b282955f..d5ef381299 100644 --- a/src/qml/qml/qqmltype_p_p.h +++ b/src/qml/qml/qqmltype_p_p.h @@ -117,7 +117,6 @@ public: // this should still be fine QQmlTypePrivate const * containingType = nullptr; QString inlineComponentName = QString(); - int objectId = -1; }; using QQmlSequenceTypeData = QMetaSequence; @@ -153,8 +152,7 @@ public: mutable QList<QStringHash<int>*> scopedEnums; void setName(const QString &uri, const QString &element); - mutable QHash<QString, int> namesToInlineComponentObjectIndex; - mutable QHash<int, QQmlType> objectIdToICType; + mutable QHash<QString, QQmlType> namesToInlineComponentType; private: ~QQmlTypePrivate() override; diff --git a/src/qml/qml/qqmltypecompiler.cpp b/src/qml/qml/qqmltypecompiler.cpp index 9e6b88ba96..7b9ee544ea 100644 --- a/src/qml/qml/qqmltypecompiler.cpp +++ b/src/qml/qml/qqmltypecompiler.cpp @@ -259,9 +259,9 @@ void QQmlTypeCompiler::addImport(const QString &module, const QString &qualifier document->imports.append(import); } -CompositeMetaTypeIds QQmlTypeCompiler::typeIdsForComponent(int objectId) const +CompositeMetaTypeIds QQmlTypeCompiler::typeIdsForComponent(const QString &inlineComponentName) const { - return typeData->typeIds(objectId); + return typeData->typeIds(inlineComponentName); } QQmlCompilePass::QQmlCompilePass(QQmlTypeCompiler *typeCompiler) diff --git a/src/qml/qml/qqmltypecompiler_p.h b/src/qml/qml/qqmltypecompiler_p.h index d07f42fb47..54c5710ecd 100644 --- a/src/qml/qml/qqmltypecompiler_p.h +++ b/src/qml/qml/qqmltypecompiler_p.h @@ -108,7 +108,7 @@ public: return resolvedTypes->value(id); } - CompositeMetaTypeIds typeIdsForComponent(int objectId = 0) const; + CompositeMetaTypeIds typeIdsForComponent(const QString &inlineComponentName = QString()) const; private: QList<QQmlError> errors; diff --git a/src/qml/qml/qqmltypedata.cpp b/src/qml/qml/qqmltypedata.cpp index faab11a9ae..643824a20e 100644 --- a/src/qml/qml/qqmltypedata.cpp +++ b/src/qml/qml/qqmltypedata.cpp @@ -74,11 +74,11 @@ void QQmlTypeData::unregisterCallback(TypeDataCallback *callback) Q_ASSERT(!m_callbacks.contains(callback)); } -CompositeMetaTypeIds QQmlTypeData::typeIds(int objectId) const +CompositeMetaTypeIds QQmlTypeData::typeIds(const QString &inlineComponentName) const { - if (objectId != 0) - return m_inlineComponentData[objectId].typeIds; - return m_typeIds; + if (inlineComponentName.isEmpty()) + return m_typeIds; + return m_inlineComponentData[inlineComponentName].typeIds; } bool QQmlTypeData::tryLoadFromDiskCache() @@ -166,7 +166,7 @@ bool QQmlTypeData::tryLoadFromDiskCache() for (auto&& ic: ics) { QString const nameString = m_compiledData->stringAt(ic.nameIndex); auto importUrl = finalUrl(); - importUrl.setFragment(QString::number(ic.objectIndex)); + importUrl.setFragment(nameString); auto import = new QQmlImportInstance(); m_importCache->addInlineComponentImport(import, nameString, importUrl, QQmlType()); } @@ -287,14 +287,16 @@ static bool addTypeReferenceChecksumsToHash( // local helper function for inline components namespace { template<typename ObjectContainer> -void setupICs(const ObjectContainer &container, QHash<int, InlineComponentData> *icData, const QUrl &finalUrl) { +void setupICs( + const ObjectContainer &container, QHash<QString, InlineComponentData> *icData, + const QUrl &finalUrl) { Q_ASSERT(icData->empty()); for (int i = 0; i != container->objectCount(); ++i) { auto root = container->objectAt(i); for (auto it = root->inlineComponentsBegin(); it != root->inlineComponentsEnd(); ++it) { const QByteArray &className = QQmlPropertyCacheCreatorBase::createClassNameForInlineComponent(finalUrl, it->objectIndex); InlineComponentData icDatum(CompositeMetaTypeIds::fromCompositeName(className), int(it->objectIndex), int(it->nameIndex), 0, 0, 0); - icData->insert(it->objectIndex, icDatum); + icData->insert(container->stringAt(it->nameIndex), icDatum); } } }; @@ -370,14 +372,14 @@ void QQmlTypeData::done() Q_ASSERT(!type.typeData || type.typeData->isCompleteOrError() || type.type.isInlineComponentType()); if (type.type.isInlineComponentType() && !type.type.pendingResolutionName().isEmpty()) { auto containingType = type.type.containingType(); - auto objectId = containingType.lookupInlineComponentIdByName(type.type.pendingResolutionName()); - if (objectId < 0) { // can be any negative number if we tentatively resolved it in QQmlImport but it actually was not an inline component + auto ic = containingType.lookupInlineComponentByName(type.type.pendingResolutionName()); + + // Only if we create the IC from an actual CU, we have valid metatypes. + if (!ic.typeId().isValid()) { const QString &typeName = stringAt(it.key()); int lastDot = typeName.lastIndexOf(u'.'); createError(type, QQmlTypeLoader::tr("Type %1 has no inline component type called %2").arg(QStringView{typeName}.left(lastDot), type.type.pendingResolutionName())); return; - } else { - type.type.setInlineComponentObjectId(objectId); } } if (type.typeData && type.typeData->isError()) { @@ -533,9 +535,9 @@ void QQmlTypeData::done() if (type.isValid()) { for (auto const &icDatum : std::as_const(m_inlineComponentData)) { Q_ASSERT(icDatum.typeIds.isValid()); - QQmlType existingType = type.lookupInlineComponentById(type.lookupInlineComponentIdByName(m_compiledData->stringAt(icDatum.nameIndex))); - type.associateInlineComponent(m_compiledData->stringAt(icDatum.nameIndex), - icDatum.objectIndex, icDatum.typeIds, existingType); + const QString icName = m_compiledData->stringAt(icDatum.nameIndex); + QQmlType existingType = type.lookupInlineComponentByName(icName); + type.associateInlineComponent(icName, icDatum.typeIds, existingType); } } } @@ -698,7 +700,7 @@ void QQmlTypeData::continueLoadFromIR() for (auto it = object->inlineComponentsBegin(); it != object->inlineComponentsEnd(); ++it) { QString const nameString = m_document->stringAt(it->nameIndex); auto importUrl = finalUrl(); - importUrl.setFragment(QString::number(it->objectIndex)); + importUrl.setFragment(nameString); auto import = new QQmlImportInstance(); // Note: The cache takes ownership of the QQmlImportInstance m_importCache->addInlineComponentImport(import, nameString, importUrl, containingType); } @@ -955,15 +957,16 @@ QQmlError QQmlTypeData::buildTypeResolutionCaches( ref->setCompilationUnit(resolvedType->typeData->compilationUnit()); if (resolvedType->type.isInlineComponentType()) { // Inline component which is part of an already resolved type - int objectId = -1; - if (qmlType.containingType().isValid()) { - objectId = qmlType.containingType().lookupInlineComponentIdByName(QString::fromUtf8(qmlType.typeName())); - qmlType.setInlineComponentObjectId(objectId); - } else { - objectId = resolvedType->type.inlineComponentId(); - } - Q_ASSERT(objectId != -1); - ref->setTypePropertyCache(resolvedType->typeData->compilationUnit()->propertyCaches.at(objectId)); + QString icName; + if (qmlType.containingType().isValid()) + icName = qmlType.elementName(); + else + icName = resolvedType->type.elementName(); + Q_ASSERT(!icName.isEmpty()); + + const auto compilationUnit = resolvedType->typeData->compilationUnit(); + ref->setTypePropertyCache(compilationUnit->propertyCaches.at( + compilationUnit->inlineComponentId(icName))); ref->setType(qmlType); Q_ASSERT(ref->type().isInlineComponentType()); } @@ -972,7 +975,7 @@ QQmlError QQmlTypeData::buildTypeResolutionCaches( ref->setType(qmlType); if (qmlType.isValid()) { // this is required for inline components in singletons - auto type = qmlType.lookupInlineComponentById(qmlType.inlineComponentId()).typeId(); + auto type = qmlType.lookupInlineComponentByName(qmlType.elementName()).typeId(); auto exUnit = QQmlMetaType::obtainExecutableCompilationUnit(type); if (exUnit) { ref->setCompilationUnit(exUnit); diff --git a/src/qml/qml/qqmltypedata_p.h b/src/qml/qml/qqmltypedata_p.h index 9e4f85974b..2c9058dc26 100644 --- a/src/qml/qml/qqmltypedata_p.h +++ b/src/qml/qml/qqmltypedata_p.h @@ -68,7 +68,7 @@ public: void registerCallback(TypeDataCallback *); void unregisterCallback(TypeDataCallback *); - CompositeMetaTypeIds typeIds(int objectId = 0) const; + CompositeMetaTypeIds typeIds(const QString &inlineComponentName = QString()) const; QByteArray typeClassName() const { return m_typeClassName; } SourceCodeData backupSourceCode() const { return m_backupSourceCode; } @@ -126,7 +126,7 @@ private: using ExecutableCompilationUnitPtr = QQmlRefPointer<QV4::ExecutableCompilationUnit>; - QHash<int, InlineComponentData> m_inlineComponentData; + QHash<QString, InlineComponentData> m_inlineComponentData; ExecutableCompilationUnitPtr m_compiledData; diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp index f171d55d03..25dc754826 100644 --- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp +++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp @@ -6767,7 +6767,7 @@ void tst_qqmllanguage::bareInlineComponent() if (type.elementName() == QStringLiteral("Tab1")) { QVERIFY(type.module().isEmpty()); tab1Found = true; - const auto ics = type.priv()->objectIdToICType; + const auto ics = type.priv()->namesToInlineComponentType; QVERIFY(ics.size() > 0); for (const QQmlType &ic : ics) QVERIFY(ic.containingType() == type); |