From 138f09bd63b8070686ed8a282375dbcf3ce7674f Mon Sep 17 00:00:00 2001 From: Albert Astals Cid Date: Fri, 4 Oct 2019 12:18:50 +0200 Subject: Convert a few sizeof(array)/sizeof(element0) fors to range fors Increases readability Change-Id: I46d82fac83e538988cea79a053d70b954a3cb9f1 Reviewed-by: Fabian Kosmale Reviewed-by: Simon Hausmann --- src/qml/qml/qqmlimport.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/qml/qml') diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp index 5feea9daa8..8b5e11c890 100644 --- a/src/qml/qml/qqmlimport.cpp +++ b/src/qml/qml/qqmlimport.cpp @@ -780,12 +780,12 @@ bool QQmlImportInstance::resolveType(QQmlTypeLoader *typeLoader, const QHashedSt typeStr + dotqml_string, // Type -> Type.qml typeStr + dotuidotqml_string // Type -> Type.ui.qml }; - for (uint i = 0; i < sizeof(urlsToTry) / sizeof(urlsToTry[0]); ++i) { - exists = typeLoader->fileExists(localDirectoryPath, urlsToTry[i]); + for (const QString &urlToTry : urlsToTry) { + exists = typeLoader->fileExists(localDirectoryPath, urlToTry); if (exists) { #if defined(Q_OS_MACOS) || defined(Q_OS_WIN) // don't let function.qml confuse the use of "new Function(...)" for example. - if (!QQml_isFileCaseCorrect(localDirectoryPath + urlsToTry[i])) { + if (!QQml_isFileCaseCorrect(localDirectoryPath + urlToTry)) { exists = false; if (errors) { QQmlError caseError; @@ -797,7 +797,7 @@ bool QQmlImportInstance::resolveType(QQmlTypeLoader *typeLoader, const QHashedSt #else Q_UNUSED(errors); #endif - qmlUrl = url + urlsToTry[i]; + qmlUrl = url + urlToTry; break; } } -- cgit v1.2.3 From 2b371a50cbc1f54284fcea3834834ca58fc28fd0 Mon Sep 17 00:00:00 2001 From: Fabian Kosmale Date: Fri, 4 Oct 2019 16:20:29 +0200 Subject: qmlRegisterSingletonInstance: Do not crash if instance gets deleted Use a QPointer, so that we notice if the object has been deleted. Also ensure that in the documentation the function is in a single line, as qdoc will otherwise silently omit it. Change-Id: Idecd370d00089997cd18b3247ad2290a561b2b69 Reviewed-by: Simon Hausmann Reviewed-by: Ulf Hermann --- src/qml/qml/qqml.cpp | 7 +++++++ src/qml/qml/qqmlprivate.h | 3 ++- 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'src/qml/qml') diff --git a/src/qml/qml/qqml.cpp b/src/qml/qml/qqml.cpp index 8a50b51b5d..5b16a3c9e2 100644 --- a/src/qml/qml/qqml.cpp +++ b/src/qml/qml/qqml.cpp @@ -79,6 +79,13 @@ int qmlTypeId(const char *uri, int versionMajor, int versionMinor, const char *q // From qqmlprivate.h QObject *QQmlPrivate::RegisterSingletonFunctor::operator()(QQmlEngine *qeng, QJSEngine *) { + if (!m_object) { + QQmlError error; + error.setDescription(QLatin1String("The registered singleton has already been deleted. Ensure that it outlives the engine.")); + QQmlEnginePrivate::get(qeng)->warning(qeng, error); + return nullptr; + } + if (qeng->thread() != m_object->thread()) { QQmlError error; error.setDescription(QLatin1String("Registered object must live in the same thread as the engine it was registered with")); diff --git a/src/qml/qml/qqmlprivate.h b/src/qml/qml/qqmlprivate.h index e6dd5e0b16..bfd3611fb8 100644 --- a/src/qml/qml/qqmlprivate.h +++ b/src/qml/qml/qqmlprivate.h @@ -58,6 +58,7 @@ #include #include #include +#include QT_BEGIN_NAMESPACE @@ -326,7 +327,7 @@ namespace QQmlPrivate { QObject *operator()(QQmlEngine *, QJSEngine *); - QObject *m_object; + QPointer m_object; bool alreadyCalled = false; }; } -- cgit v1.2.3 From ce94b847c87e2606c5f189d2ad3715c1d025b9cf Mon Sep 17 00:00:00 2001 From: Albert Astals Cid Date: Fri, 4 Oct 2019 14:13:36 +0200 Subject: Small performance improvements suggested by clang-tidy mostly add const &, a few std::move and in particular case, remove const so the std::move being done over the variable actually has effect Change-Id: Id611cd31bc012f219d7a17d4626b1c2a5fbddd66 Reviewed-by: Fabian Kosmale Reviewed-by: Ulf Hermann --- src/qml/qml/qqmlcontext.cpp | 2 +- src/qml/qml/qqmldatablob.cpp | 2 +- src/qml/qml/qqmldirdata.cpp | 2 +- src/qml/qml/qqmlmetatypedata.cpp | 2 +- src/qml/qml/qqmltype.cpp | 2 +- src/qml/qml/qqmltypeloader.cpp | 2 +- src/qml/qml/qqmltypeloaderqmldircontent.cpp | 3 ++- 7 files changed, 8 insertions(+), 7 deletions(-) (limited to 'src/qml/qml') diff --git a/src/qml/qml/qqmlcontext.cpp b/src/qml/qml/qqmlcontext.cpp index 14892bd6ad..af8deb085c 100644 --- a/src/qml/qml/qqmlcontext.cpp +++ b/src/qml/qml/qqmlcontext.cpp @@ -358,7 +358,7 @@ void QQmlContext::setContextProperties(const QVector &properties) data->expressions = nullptr; data->childContexts = nullptr; - for (auto property : properties) + for (const auto &property : properties) setContextProperty(property.name, property.value); data->expressions = expressions; diff --git a/src/qml/qml/qqmldatablob.cpp b/src/qml/qml/qqmldatablob.cpp index 2183721d32..750fc6de50 100644 --- a/src/qml/qml/qqmldatablob.cpp +++ b/src/qml/qml/qqmldatablob.cpp @@ -351,7 +351,7 @@ void QQmlDataBlob::addDependency(QQmlDataBlob *blob) status() == Error || status() == Complete || m_isDone) return; - for (auto existingDep: qAsConst(m_waitingFor)) + for (const auto &existingDep: qAsConst(m_waitingFor)) if (existingDep.data() == blob) return; diff --git a/src/qml/qml/qqmldirdata.cpp b/src/qml/qml/qqmldirdata.cpp index 7652cec322..de74dfdf9b 100644 --- a/src/qml/qml/qqmldirdata.cpp +++ b/src/qml/qml/qqmldirdata.cpp @@ -61,7 +61,7 @@ QQmlTypeLoader::Blob::PendingImportPtr QQmlQmldirData::import(QQmlTypeLoader::Bl void QQmlQmldirData::setImport(QQmlTypeLoader::Blob *blob, QQmlTypeLoader::Blob::PendingImportPtr import) { - m_imports[blob] = import; + m_imports[blob] = std::move(import); } int QQmlQmldirData::priority(QQmlTypeLoader::Blob *blob) const diff --git a/src/qml/qml/qqmlmetatypedata.cpp b/src/qml/qml/qqmlmetatypedata.cpp index 41a7778da3..775bc8bdb4 100644 --- a/src/qml/qml/qqmlmetatypedata.cpp +++ b/src/qml/qml/qqmlmetatypedata.cpp @@ -150,7 +150,7 @@ QQmlPropertyCache *QQmlMetaTypeData::propertyCache(const QQmlType &type, int min bool hasCopied = false; for (int ii = 0; ii < types.count(); ++ii) { - QQmlType currentType = types.at(ii); + const QQmlType ¤tType = types.at(ii); if (!currentType.isValid()) continue; diff --git a/src/qml/qml/qqmltype.cpp b/src/qml/qml/qqmltype.cpp index 3615749da1..2db3ad6b2a 100644 --- a/src/qml/qml/qqmltype.cpp +++ b/src/qml/qml/qqmltype.cpp @@ -393,7 +393,7 @@ void QQmlTypePrivate::createEnumConflictReport(const QMetaObject *metaObject, co qWarning().noquote() << QLatin1String("Possible conflicting items:"); // find items with conflicting key - for (const auto i : enumInfoList) { + for (const auto &i : qAsConst(enumInfoList)) { if (i.enumKey == conflictingKey) qWarning().noquote().nospace() << " " << i.metaObjectName << "." << i.enumName << "." << i.enumKey << " from scope " << i.metaEnumScope << " injected by " << i.path.join(QLatin1String("->")); diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp index 42e7d2c4b4..62007effdd 100644 --- a/src/qml/qml/qqmltypeloader.cpp +++ b/src/qml/qml/qqmltypeloader.cpp @@ -491,7 +491,7 @@ bool QQmlTypeLoader::Blob::fetchQmldir(const QUrl &url, PendingImportPtr import, { QQmlRefPointer data = typeLoader()->getQmldir(url); - data->setImport(this, import); + data->setImport(this, std::move(import)); data->setPriority(this, priority); if (data->status() == Error) { diff --git a/src/qml/qml/qqmltypeloaderqmldircontent.cpp b/src/qml/qml/qqmltypeloaderqmldircontent.cpp index 238af9b710..8e983db756 100644 --- a/src/qml/qml/qqmltypeloaderqmldircontent.cpp +++ b/src/qml/qml/qqmltypeloaderqmldircontent.cpp @@ -55,7 +55,8 @@ QList QQmlTypeLoaderQmldirContent::errors(const QString &uri) const { QList errors; const QUrl url(uri); - for (const auto parseError : m_parser.errors(uri)) { + const auto parseErrors = m_parser.errors(uri); + for (const auto &parseError : parseErrors) { QQmlError error; error.setUrl(url); error.setLine(parseError.line); -- cgit v1.2.3 From 00f903f3b4cd46ddf8361876401e5405030f97f1 Mon Sep 17 00:00:00 2001 From: Fabian Kosmale Date: Mon, 7 Oct 2019 10:01:46 +0200 Subject: QML Binding: do not convert strings The root cause for the issue is that QQmlObjectCreator::setPropertyValue calls QQmlStringConverters::variantFromString on strings if the property is of type QVariant. Unfortunately, this cannot be changed easily as the current behavior is explicitly documented and tested in tst_qqmllanguage, thus making it a breaking change. As a workaround, QML Binding does now take a QJSValue instead of a QVariant (making value a var property), which does not trigger the conversion path. Fixes: QTBUG-78943 Change-Id: I0b64dffdb6b84b2bab2bb85a8cb263e530c18570 Reviewed-by: Ulf Hermann --- src/qml/qml/qqmlobjectcreator.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/qml/qml') diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp index f89608cd5d..a4270628e8 100644 --- a/src/qml/qml/qqmlobjectcreator.cpp +++ b/src/qml/qml/qqmlobjectcreator.cpp @@ -445,6 +445,8 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const QV4::ScopedString s(scope, v4->newString(stringValue)); _vmeMetaObject->setVMEProperty(property->coreIndex(), s); } else { + // ### Qt 6: Doing the conversion here where we don't know the eventual target type is rather strange + // and caused for instance QTBUG-78943 QVariant value = QQmlStringConverters::variantFromString(stringValue); property->writeProperty(_qobject, &value, propertyWriteFlags); } -- cgit v1.2.3 From e5f3e7149b7e130c375c1419f1f804dfeaf578aa Mon Sep 17 00:00:00 2001 From: Fabian Kosmale Date: Mon, 30 Sep 2019 08:32:02 +0200 Subject: Add initial support for deep aliases This patch reuses the existing support for value types to support aliases of depth 2. This covers the initial use case in QTBUG-48150. Adding support for "deeper" aliases would require storing the complete "property path", which in turn would require increasing the size of the Alias data. This is currently considered out of scope, at least until a clear use-case appears. Fixes: QTBUG-48150 Change-Id: Id2ac4dd175003a37eba2919e7604d0a3be54d29f Reviewed-by: Simon Hausmann --- src/qml/qml/qqmlpropertycachecreator_p.h | 76 +++++++++++++++++++------------- src/qml/qml/qqmltypecompiler.cpp | 51 ++++++++++++++------- src/qml/qml/qqmltypedata.cpp | 2 +- src/qml/qml/qqmlvmemetaobject.cpp | 33 ++++++++++---- 4 files changed, 107 insertions(+), 55 deletions(-) (limited to 'src/qml/qml') diff --git a/src/qml/qml/qqmlpropertycachecreator_p.h b/src/qml/qml/qqmlpropertycachecreator_p.h index 94bf3cbdc3..39778aa328 100644 --- a/src/qml/qml/qqmlpropertycachecreator_p.h +++ b/src/qml/qml/qqmlpropertycachecreator_p.h @@ -585,13 +585,13 @@ public: QQmlPropertyCacheAliasCreator(QQmlPropertyCacheVector *propertyCaches, const ObjectContainer *objectContainer); - void appendAliasPropertiesToMetaObjects(); + void appendAliasPropertiesToMetaObjects(QQmlEnginePrivate *enginePriv); - QQmlJS::DiagnosticMessage appendAliasesToPropertyCache(const CompiledObject &component, int objectIndex); + QQmlJS::DiagnosticMessage appendAliasesToPropertyCache(const CompiledObject &component, int objectIndex, QQmlEnginePrivate *enginePriv); private: - void appendAliasPropertiesInMetaObjectsWithinComponent(const CompiledObject &component, int firstObjectIndex); - QQmlJS::DiagnosticMessage propertyDataForAlias(const CompiledObject &component, const QV4::CompiledData::Alias &alias, int *type, int *rev, QQmlPropertyData::Flags *propertyFlags); + void appendAliasPropertiesInMetaObjectsWithinComponent(const CompiledObject &component, int firstObjectIndex, QQmlEnginePrivate *enginePriv); + QQmlJS::DiagnosticMessage propertyDataForAlias(const CompiledObject &component, const QV4::CompiledData::Alias &alias, int *type, int *rev, QQmlPropertyData::Flags *propertyFlags, QQmlEnginePrivate *enginePriv); void collectObjectsWithAliasesRecursively(int objectIndex, QVector *objectsWithAliases) const; @@ -610,7 +610,7 @@ inline QQmlPropertyCacheAliasCreator::QQmlPropertyCacheAliasCre } template -inline void QQmlPropertyCacheAliasCreator::appendAliasPropertiesToMetaObjects() +inline void QQmlPropertyCacheAliasCreator::appendAliasPropertiesToMetaObjects(QQmlEnginePrivate *enginePriv) { // skip the root object (index 0) as that one does not have a first object index originating // from a binding. @@ -620,15 +620,15 @@ inline void QQmlPropertyCacheAliasCreator::appendAliasPropertie continue; const auto rootBinding = component.bindingsBegin(); - appendAliasPropertiesInMetaObjectsWithinComponent(component, rootBinding->value.objectIndex); + appendAliasPropertiesInMetaObjectsWithinComponent(component, rootBinding->value.objectIndex, enginePriv); } const int rootObjectIndex = 0; - appendAliasPropertiesInMetaObjectsWithinComponent(*objectContainer->objectAt(rootObjectIndex), rootObjectIndex); + appendAliasPropertiesInMetaObjectsWithinComponent(*objectContainer->objectAt(rootObjectIndex), rootObjectIndex, enginePriv); } template -inline void QQmlPropertyCacheAliasCreator::appendAliasPropertiesInMetaObjectsWithinComponent(const CompiledObject &component, int firstObjectIndex) +inline void QQmlPropertyCacheAliasCreator::appendAliasPropertiesInMetaObjectsWithinComponent(const CompiledObject &component, int firstObjectIndex, QQmlEnginePrivate *enginePriv) { QVector objectsWithAliases; collectObjectsWithAliasesRecursively(firstObjectIndex, &objectsWithAliases); @@ -668,7 +668,7 @@ inline void QQmlPropertyCacheAliasCreator::appendAliasPropertie const CompiledObject &object = *objectContainer->objectAt(objectIndex); if (allAliasTargetsExist(object)) { - appendAliasesToPropertyCache(component, objectIndex); + appendAliasesToPropertyCache(component, objectIndex, enginePriv); } else { pendingObjects.append(objectIndex); } @@ -702,9 +702,8 @@ inline void QQmlPropertyCacheAliasCreator::collectObjectsWithAl } template -inline QQmlJS::DiagnosticMessage QQmlPropertyCacheAliasCreator::propertyDataForAlias( - const CompiledObject &component, const QV4::CompiledData::Alias &alias, int *type, int *minorVersion, - QQmlPropertyData::Flags *propertyFlags) +inline QQmlJS::DiagnosticMessage QQmlPropertyCacheAliasCreator::propertyDataForAlias(const CompiledObject &component, const QV4::CompiledData::Alias &alias, int *type, int *minorVersion, + QQmlPropertyData::Flags *propertyFlags, QQmlEnginePrivate *enginePriv) { *type = 0; bool writable = false; @@ -736,7 +735,7 @@ inline QQmlJS::DiagnosticMessage QQmlPropertyCacheAliasCreator: lastAlias = targetAlias; } while (lastAlias->aliasToLocalAlias); - return propertyDataForAlias(component, *lastAlias, type, minorVersion, propertyFlags); + return propertyDataForAlias(component, *lastAlias, type, minorVersion, propertyFlags, enginePriv); } const int targetObjectIndex = objectForId(component, alias.targetObjectId); @@ -768,29 +767,46 @@ inline QQmlJS::DiagnosticMessage QQmlPropertyCacheAliasCreator: QQmlPropertyCache *targetCache = propertyCaches->at(targetObjectIndex); Q_ASSERT(targetCache); + QQmlPropertyData *targetProperty = targetCache->property(coreIndex); Q_ASSERT(targetProperty); - *type = targetProperty->propType(); + // for deep aliases, valueTypeIndex is always set + if (!QQmlValueTypeFactory::isValueType(targetProperty->propType()) && valueTypeIndex != -1) { + // deep alias property + *type = targetProperty->propType(); + targetCache = enginePriv->propertyCacheForType(*type); + Q_ASSERT(targetCache); + targetProperty = targetCache->property(valueTypeIndex); - writable = targetProperty->isWritable(); - resettable = targetProperty->isResettable(); - if (valueTypeIndex != -1) { - const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType(*type); - if (valueTypeMetaObject->property(valueTypeIndex).isEnumType()) - *type = QVariant::Int; - else - *type = valueTypeMetaObject->property(valueTypeIndex).userType(); + *type = targetProperty->propType(); + writable = targetProperty->isWritable(); + resettable = targetProperty->isResettable(); + } else { - if (targetProperty->isEnum()) { - *type = QVariant::Int; + // value type or primitive type or enum + *type = targetProperty->propType(); + + writable = targetProperty->isWritable(); + resettable = targetProperty->isResettable(); + + if (valueTypeIndex != -1) { + const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType(*type); + if (valueTypeMetaObject->property(valueTypeIndex).isEnumType()) + *type = QVariant::Int; + else + *type = valueTypeMetaObject->property(valueTypeIndex).userType(); } else { - // Copy type flags - propertyFlags->copyPropertyTypeFlags(targetProperty->flags()); + if (targetProperty->isEnum()) { + *type = QVariant::Int; + } else { + // Copy type flags + propertyFlags->copyPropertyTypeFlags(targetProperty->flags()); - if (targetProperty->isVarProperty()) - propertyFlags->type = QQmlPropertyData::Flags::QVariantType; + if (targetProperty->isVarProperty()) + propertyFlags->type = QQmlPropertyData::Flags::QVariantType; + } } } } @@ -802,7 +818,7 @@ inline QQmlJS::DiagnosticMessage QQmlPropertyCacheAliasCreator: template inline QQmlJS::DiagnosticMessage QQmlPropertyCacheAliasCreator::appendAliasesToPropertyCache( - const CompiledObject &component, int objectIndex) + const CompiledObject &component, int objectIndex, QQmlEnginePrivate *enginePriv) { const CompiledObject &object = *objectContainer->objectAt(objectIndex); if (!object.aliasCount()) @@ -823,7 +839,7 @@ inline QQmlJS::DiagnosticMessage QQmlPropertyCacheAliasCreator: int type = 0; int minorVersion = 0; QQmlPropertyData::Flags propertyFlags; - QQmlJS::DiagnosticMessage error = propertyDataForAlias(component, *alias, &type, &minorVersion, &propertyFlags); + QQmlJS::DiagnosticMessage error = propertyDataForAlias(component, *alias, &type, &minorVersion, &propertyFlags, enginePriv); if (error.isValid()) return error; diff --git a/src/qml/qml/qqmltypecompiler.cpp b/src/qml/qml/qqmltypecompiler.cpp index bbeaf7be9a..9ff0e3fb9e 100644 --- a/src/qml/qml/qqmltypecompiler.cpp +++ b/src/qml/qml/qqmltypecompiler.cpp @@ -1016,7 +1016,7 @@ bool QQmlComponentAndAliasResolver::resolveAliases(int componentIndex) } if (result == AllAliasesResolved) { - QQmlJS::DiagnosticMessage error = aliasCacheCreator.appendAliasesToPropertyCache(*qmlObjects->at(componentIndex), objectIndex); + QQmlJS::DiagnosticMessage error = aliasCacheCreator.appendAliasesToPropertyCache(*qmlObjects->at(componentIndex), objectIndex, enginePrivate); if (error.isValid()) { recordError(error); return false; @@ -1143,23 +1143,42 @@ QQmlComponentAndAliasResolver::resolveAliasesInObject(int objectIndex, if (!subProperty.isEmpty()) { const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType(targetProperty->propType()); if (!valueTypeMetaObject) { - *error = qQmlCompileError( - alias->referenceLocation, - tr("Invalid alias target location: %1").arg(subProperty.toString())); - break; - } + // could be a deep alias + bool isDeepAlias = subProperty.at(0).isLower(); + if (isDeepAlias) { + isDeepAlias = false; + for (auto it = targetObject->bindingsBegin(); it != targetObject->bindingsEnd(); ++it) { + auto binding = *it; + if (compiler->stringAt(binding.propertyNameIndex) == property) { + resolver = QQmlPropertyResolver(propertyCaches.at(binding.value.objectIndex)); + QQmlPropertyData *actualProperty = resolver.property(subProperty.toString()); + if (actualProperty) { + propIdx = QQmlPropertyIndex(propIdx.coreIndex(), actualProperty->coreIndex()); + isDeepAlias = true; + } + } + } + } + if (!isDeepAlias) { + *error = qQmlCompileError( + alias->referenceLocation, + tr("Invalid alias target location: %1").arg(subProperty.toString())); + break; + } + } else { - int valueTypeIndex = - valueTypeMetaObject->indexOfProperty(subProperty.toString().toUtf8().constData()); - if (valueTypeIndex == -1) { - *error = qQmlCompileError( - alias->referenceLocation, - tr("Invalid alias target location: %1").arg(subProperty.toString())); - break; - } - Q_ASSERT(valueTypeIndex <= 0x0000FFFF); + int valueTypeIndex = + valueTypeMetaObject->indexOfProperty(subProperty.toString().toUtf8().constData()); + if (valueTypeIndex == -1) { + *error = qQmlCompileError( + alias->referenceLocation, + tr("Invalid alias target location: %1").arg(subProperty.toString())); + break; + } + Q_ASSERT(valueTypeIndex <= 0x0000FFFF); - propIdx = QQmlPropertyIndex(propIdx.coreIndex(), valueTypeIndex); + propIdx = QQmlPropertyIndex(propIdx.coreIndex(), valueTypeIndex); + } } else { if (targetProperty->isQObject()) alias->flags |= QV4::CompiledData::Alias::AliasPointsToPointerObject; diff --git a/src/qml/qml/qqmltypedata.cpp b/src/qml/qml/qqmltypedata.cpp index 99fe069685..cfdcf6aad5 100644 --- a/src/qml/qml/qqmltypedata.cpp +++ b/src/qml/qml/qqmltypedata.cpp @@ -209,7 +209,7 @@ void QQmlTypeData::createTypeAndPropertyCaches( QQmlPropertyCacheAliasCreator aliasCreator( &m_compiledData->propertyCaches, m_compiledData.data()); - aliasCreator.appendAliasPropertiesToMetaObjects(); + aliasCreator.appendAliasPropertiesToMetaObjects(engine); pendingGroupPropertyBindings.resolveMissingPropertyCaches(engine, &m_compiledData->propertyCaches); } diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp index b9d8fed243..abdc686ec2 100644 --- a/src/qml/qml/qqmlvmemetaobject.cpp +++ b/src/qml/qml/qqmlvmemetaobject.cpp @@ -164,8 +164,19 @@ void QQmlVMEMetaObjectEndpoint::tryConnect() QQmlData *targetDData = QQmlData::get(target, /*create*/false); if (!targetDData) return; - int coreIndex = QQmlPropertyIndex::fromEncoded(aliasData->encodedMetaPropertyIndex).coreIndex(); + QQmlPropertyIndex encodedIndex = QQmlPropertyIndex::fromEncoded(aliasData->encodedMetaPropertyIndex); + int coreIndex = encodedIndex.coreIndex(); + int valueTypeIndex = encodedIndex.valueTypeIndex(); const QQmlPropertyData *pd = targetDData->propertyCache->property(coreIndex); + if (pd && valueTypeIndex != -1 && !QQmlValueTypeFactory::valueType(pd->propType())) { + // deep alias + QQmlEnginePrivate *enginePriv = QQmlEnginePrivate::get(metaObject->compilationUnit->engine->qmlEngine()); + auto const *newPropertyCache = enginePriv->propertyCacheForType(pd->propType()); + void *argv[1] = { &target }; + QMetaObject::metacall(target, QMetaObject::ReadProperty, coreIndex, argv); + Q_ASSERT(newPropertyCache); + pd = newPropertyCache->property(valueTypeIndex); + } if (!pd) return; @@ -858,17 +869,23 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void * if (!targetDData->propertyCache) return -1; const QQmlPropertyData *pd = targetDData->propertyCache->property(coreIndex); - // Value type property + // Value type property or deep alias QQmlValueType *valueType = QQmlValueTypeFactory::valueType(pd->propType()); - Q_ASSERT(valueType); + if (valueType) { - valueType->read(target, coreIndex); - int rv = QMetaObject::metacall(valueType, c, valueTypePropertyIndex, a); + valueType->read(target, coreIndex); + int rv = QMetaObject::metacall(valueType, c, valueTypePropertyIndex, a); - if (c == QMetaObject::WriteProperty) - valueType->write(target, coreIndex, nullptr); + if (c == QMetaObject::WriteProperty) + valueType->write(target, coreIndex, nullptr); - return rv; + return rv; + } else { + // deep alias + void *argv[1] = { &target }; + QMetaObject::metacall(target, QMetaObject::ReadProperty, coreIndex, argv); + return QMetaObject::metacall(target, c, valueTypePropertyIndex, a); + } } else { return QMetaObject::metacall(target, c, coreIndex, a); -- cgit v1.2.3