diff options
author | Qt Forward Merge Bot <qt_forward_merge_bot@qt-project.org> | 2019-10-09 01:01:34 +0200 |
---|---|---|
committer | Qt Forward Merge Bot <qt_forward_merge_bot@qt-project.org> | 2019-10-09 01:01:34 +0200 |
commit | 1b71204d81ec2f1ea4a577f8eddc1cad6613895c (patch) | |
tree | 99fb5c9400e99cff1193671bc5858669830d504d /src/qml | |
parent | f7b17eed645639a4586402ecbf7d3cdf50a67706 (diff) | |
parent | a02b5d48cf63228ed8faf6abf4724df2c4500269 (diff) |
Merge remote-tracking branch 'origin/5.15' into dev
Change-Id: I68014bc552793b6dea930744325876a8863aaef3
Diffstat (limited to 'src/qml')
25 files changed, 187 insertions, 125 deletions
diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp index fbb6a07b1b..940d61ba97 100644 --- a/src/qml/compiler/qqmlirbuilder.cpp +++ b/src/qml/compiler/qqmlirbuilder.cpp @@ -971,7 +971,7 @@ QStringRef IRBuilder::asStringRef(QQmlJS::AST::Node *node) return textRefAt(node->firstSourceLocation(), node->lastSourceLocation()); } -void IRBuilder::extractVersion(QStringRef string, int *maj, int *min) +void IRBuilder::extractVersion(const QStringRef &string, int *maj, int *min) { *maj = -1; *min = -1; diff --git a/src/qml/compiler/qqmlirbuilder_p.h b/src/qml/compiler/qqmlirbuilder_p.h index c366c8e459..4279f5b768 100644 --- a/src/qml/compiler/qqmlirbuilder_p.h +++ b/src/qml/compiler/qqmlirbuilder_p.h @@ -453,7 +453,7 @@ public: static QString asString(QQmlJS::AST::UiQualifiedId *node); QStringRef asStringRef(QQmlJS::AST::Node *node); - static void extractVersion(QStringRef string, int *maj, int *min); + static void extractVersion(const QStringRef &string, int *maj, int *min); QStringRef textRefAt(const QQmlJS::AST::SourceLocation &loc) const { return QStringRef(&sourceCode, loc.offset, loc.length); } QStringRef textRefAt(const QQmlJS::AST::SourceLocation &first, diff --git a/src/qml/doc/src/qmlfunctions.qdoc b/src/qml/doc/src/qmlfunctions.qdoc index b083012eab..b2d322465d 100644 --- a/src/qml/doc/src/qmlfunctions.qdoc +++ b/src/qml/doc/src/qmlfunctions.qdoc @@ -628,8 +628,7 @@ */ /*! - \fn int qmlRegisterSingletonInstance(const char *uri, int versionMajor, int - versionMinor, const char *typeName, QObject* cppObject) + \fn int qmlRegisterSingletonInstance(const char *uri, int versionMajor, int versionMinor, const char *typeName, QObject* cppObject) \relates QQmlEngine \since 5.14 diff --git a/src/qml/jsruntime/qv4dateobject.cpp b/src/qml/jsruntime/qv4dateobject.cpp index 5616b1450b..520b715189 100644 --- a/src/qml/jsruntime/qv4dateobject.cpp +++ b/src/qml/jsruntime/qv4dateobject.cpp @@ -601,8 +601,7 @@ static inline double ParseString(const QString &s, double localTZA) QStringLiteral("d MMMM, yyyy hh:mm:ss"), }; - for (uint i = 0; i < sizeof(formats) / sizeof(formats[0]); ++i) { - const QString &format(formats[i]); + for (const QString &format : formats) { dt = format.indexOf(QLatin1String("hh:mm")) < 0 ? QDateTime(QDate::fromString(s, format), QTime(0, 0, 0), Qt::UTC) diff --git a/src/qml/qml/qqml.cpp b/src/qml/qml/qqml.cpp index a3ca48d6d9..a33936647f 100644 --- a/src/qml/qml/qqml.cpp +++ b/src/qml/qml/qqml.cpp @@ -61,7 +61,7 @@ void qmlClearTypeRegistrations() // Declared in qqml.h //From qqml.h bool qmlProtectModule(const char *uri, int majVersion) { - return QQmlMetaType::protectModule(uri, majVersion); + return QQmlMetaType::protectModule(QString::fromUtf8(uri), majVersion); } //From qqml.h @@ -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/qqmlcontext.cpp b/src/qml/qml/qqmlcontext.cpp index 668f00b136..254b6cc3db 100644 --- a/src/qml/qml/qqmlcontext.cpp +++ b/src/qml/qml/qqmlcontext.cpp @@ -358,7 +358,7 @@ void QQmlContext::setContextProperties(const QVector<PropertyPair> &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/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp index 5feea9daa8..d69c2ac903 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; } } @@ -1997,12 +1997,25 @@ void QQmlImportDatabase::setImportPathList(const QStringList &paths) /*! \internal */ -bool QQmlImportDatabase::registerPluginTypes(QObject *instance, const QString &basePath, - const QString &uri, const QString &typeNamespace, int vmaj, QList<QQmlError> *errors) +static bool registerPluginTypes(QObject *instance, const QString &basePath, const QString &uri, + const QString &typeNamespace, int vmaj, QList<QQmlError> *errors) { if (qmlImportTrace()) qDebug().nospace() << "QQmlImportDatabase::registerPluginTypes: " << uri << " from " << basePath; - return QQmlMetaType::registerPluginTypes(instance, basePath, uri, typeNamespace, vmaj, errors); + + if (!QQmlMetaType::registerPluginTypes(instance, basePath, uri, typeNamespace, vmaj, errors)) + return false; + + if (vmaj >= 0 && !typeNamespace.isEmpty() && !QQmlMetaType::protectModule(uri, vmaj)) { + QQmlError error; + error.setDescription( + QString::fromLatin1("Cannot protect module %1 %2 as it was never registered") + .arg(uri).arg(vmaj)); + errors->append(error); + return false; + } + + return true; } /*! diff --git a/src/qml/qml/qqmlimport_p.h b/src/qml/qml/qqmlimport_p.h index ea9c2eafb5..e24b3c447c 100644 --- a/src/qml/qml/qqmlimport_p.h +++ b/src/qml/qml/qqmlimport_p.h @@ -235,8 +235,6 @@ private: const QString &baseName); bool importStaticPlugin(QObject *instance, const QString &basePath, const QString &uri, const QString &typeNamespace, int vmaj, QList<QQmlError> *errors); - bool registerPluginTypes(QObject *instance, const QString &basePath, - const QString &uri, const QString &typeNamespace, int vmaj, QList<QQmlError> *errors); void clearDirCache(); struct QmldirCache { diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp index 268d58a856..1a5affb0ad 100644 --- a/src/qml/qml/qqmlmetatype.cpp +++ b/src/qml/qml/qqmlmetatype.cpp @@ -342,7 +342,7 @@ QString registrationTypeString(QQmlType::RegistrationType typeType) // NOTE: caller must hold a QMutexLocker on "data" bool checkRegistration(QQmlType::RegistrationType typeType, QQmlMetaTypeData *data, - const char *uri, const QString &typeName, int majorVersion = -1) + const char *uri, const QString &typeName, int majorVersion) { if (!typeName.isEmpty()) { if (typeName.at(0).isLower()) { @@ -363,27 +363,16 @@ bool checkRegistration(QQmlType::RegistrationType typeType, QQmlMetaTypeData *da if (uri && !typeName.isEmpty()) { QString nameSpace = QString::fromUtf8(uri); - - if (data->typeRegistrationNamespace.isEmpty() && !nameSpace.isEmpty()) { - // Is the target namespace protected against further registrations? - if (data->protectedNamespaces.contains(nameSpace)) { + QQmlMetaTypeData::VersionedUri versionedUri; + versionedUri.uri = nameSpace; + versionedUri.majorVersion = majorVersion; + if (QQmlTypeModule* qqtm = data->uriToModule.value(versionedUri, 0)){ + if (qqtm->isLocked()){ QString failure(QCoreApplication::translate("qmlRegisterType", - "Cannot install %1 '%2' into protected namespace '%3'")); - data->recordTypeRegFailure(failure.arg(registrationTypeString(typeType)).arg(typeName).arg(nameSpace)); + "Cannot install %1 '%2' into protected module '%3' version '%4'")); + data->recordTypeRegFailure(failure.arg(registrationTypeString(typeType)).arg(typeName).arg(nameSpace).arg(majorVersion)); return false; } - } else if (majorVersion >= 0) { - QQmlMetaTypeData::VersionedUri versionedUri; - versionedUri.uri = nameSpace; - versionedUri.majorVersion = majorVersion; - if (QQmlTypeModule* qqtm = data->uriToModule.value(versionedUri, 0)){ - if (qqtm->isLocked()){ - QString failure(QCoreApplication::translate("qmlRegisterType", - "Cannot install %1 '%2' into protected module '%3' version '%4'")); - data->recordTypeRegFailure(failure.arg(registrationTypeString(typeType)).arg(typeName).arg(nameSpace).arg(majorVersion)); - return false; - } - } } } @@ -477,8 +466,10 @@ QQmlType QQmlMetaType::registerCompositeSingletonType(const QQmlPrivate::Registe bool fileImport = false; if (*(type.uri) == '\0') fileImport = true; - if (!checkRegistration(QQmlType::CompositeSingletonType, data, fileImport ? nullptr : type.uri, typeName)) + if (!checkRegistration(QQmlType::CompositeSingletonType, data, fileImport ? nullptr : type.uri, + typeName, type.versionMajor)) { return QQmlType(); + } QQmlTypePrivate *priv = createQQmlType(data, typeName, type); addTypeToData(priv, data); @@ -560,12 +551,12 @@ int QQmlMetaType::registerUnitCacheHook( return 0; } -bool QQmlMetaType::protectModule(const char *uri, int majVersion) +bool QQmlMetaType::protectModule(const QString &uri, int majVersion) { QQmlMetaTypeDataPtr data; QQmlMetaTypeData::VersionedUri versionedUri; - versionedUri.uri = QString::fromUtf8(uri); + versionedUri.uri = uri; versionedUri.majorVersion = majVersion; if (QQmlTypeModule* qqtm = data->uriToModule.value(versionedUri, 0)) { @@ -683,8 +674,6 @@ bool QQmlMetaType::registerPluginTypes(QObject *instance, const QString &basePat } return false; } - - data->protectedNamespaces.insert(uri); } else { // This is not an identified module - provide a warning qWarning().nospace() << qPrintable( @@ -698,11 +687,9 @@ bool QQmlMetaType::registerPluginTypes(QObject *instance, const QString &basePat = QQmlImports::urlFromLocalFileOrQrcOrUrl(basePath); } - data->typeRegistrationNamespace = typeNamespace; const QByteArray bytes = uri.toUtf8(); const char *moduleId = bytes.constData(); iface->registerTypes(moduleId); - data->typeRegistrationNamespace.clear(); } if (!failures.isEmpty()) { diff --git a/src/qml/qml/qqmlmetatype_p.h b/src/qml/qml/qqmlmetatype_p.h index 6c2b0bb2a6..35d5386e1f 100644 --- a/src/qml/qml/qqmlmetatype_p.h +++ b/src/qml/qml/qqmlmetatype_p.h @@ -84,7 +84,7 @@ public: static void unregisterInternalCompositeType(QV4::ExecutableCompilationUnit *compilationUnit); static void registerModule(const char *uri, int versionMajor, int versionMinor); - static bool protectModule(const char *uri, int majVersion); + static bool protectModule(const QString &uri, int majVersion); static int typeId(const char *uri, int versionMajor, int versionMinor, const char *qmlName); 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/qqmlmetatypedata_p.h b/src/qml/qml/qqmlmetatypedata_p.h index 5239b635ce..ea796ee7c6 100644 --- a/src/qml/qml/qqmlmetatypedata_p.h +++ b/src/qml/qml/qqmlmetatypedata_p.h @@ -106,10 +106,6 @@ struct QQmlMetaTypeData QList<QQmlPrivate::AutoParentFunction> parentFunctions; QVector<QQmlPrivate::QmlUnitCacheLookupFunction> lookupCachedQmlUnit; - QSet<QString> protectedNamespaces; - - QString typeRegistrationNamespace; - QHash<int, int> qmlLists; QHash<const QMetaObject *, QQmlPropertyCache *> propertyCaches; diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp index dfcab6181d..cf1795aafa 100644 --- a/src/qml/qml/qqmlobjectcreator.cpp +++ b/src/qml/qml/qqmlobjectcreator.cpp @@ -446,6 +446,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); } diff --git a/src/qml/qml/qqmlprivate.h b/src/qml/qml/qqmlprivate.h index 8111178320..27dac71571 100644 --- a/src/qml/qml/qqmlprivate.h +++ b/src/qml/qml/qqmlprivate.h @@ -62,6 +62,7 @@ #include <QtCore/qglobal.h> #include <QtCore/qvariant.h> #include <QtCore/qurl.h> +#include <QPointer> #include <QtCore/qmetaobject.h> #include <QtCore/qdebug.h> @@ -489,7 +490,7 @@ namespace QQmlPrivate { QObject *operator()(QQmlEngine *, QJSEngine *); - QObject *m_object; + QPointer<QObject> m_object; bool alreadyCalled = false; }; 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<int> *objectsWithAliases) const; @@ -610,7 +610,7 @@ inline QQmlPropertyCacheAliasCreator<ObjectContainer>::QQmlPropertyCacheAliasCre } template <typename ObjectContainer> -inline void QQmlPropertyCacheAliasCreator<ObjectContainer>::appendAliasPropertiesToMetaObjects() +inline void QQmlPropertyCacheAliasCreator<ObjectContainer>::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<ObjectContainer>::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 <typename ObjectContainer> -inline void QQmlPropertyCacheAliasCreator<ObjectContainer>::appendAliasPropertiesInMetaObjectsWithinComponent(const CompiledObject &component, int firstObjectIndex) +inline void QQmlPropertyCacheAliasCreator<ObjectContainer>::appendAliasPropertiesInMetaObjectsWithinComponent(const CompiledObject &component, int firstObjectIndex, QQmlEnginePrivate *enginePriv) { QVector<int> objectsWithAliases; collectObjectsWithAliasesRecursively(firstObjectIndex, &objectsWithAliases); @@ -668,7 +668,7 @@ inline void QQmlPropertyCacheAliasCreator<ObjectContainer>::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<ObjectContainer>::collectObjectsWithAl } template <typename ObjectContainer> -inline QQmlJS::DiagnosticMessage QQmlPropertyCacheAliasCreator<ObjectContainer>::propertyDataForAlias( - const CompiledObject &component, const QV4::CompiledData::Alias &alias, int *type, int *minorVersion, - QQmlPropertyData::Flags *propertyFlags) +inline QQmlJS::DiagnosticMessage QQmlPropertyCacheAliasCreator<ObjectContainer>::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<ObjectContainer>: 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<ObjectContainer>: 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<ObjectContainer>: template <typename ObjectContainer> inline QQmlJS::DiagnosticMessage QQmlPropertyCacheAliasCreator<ObjectContainer>::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<ObjectContainer>: 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/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/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<QV4::ExecutableCompilationUnit> aliasCreator( &m_compiledData->propertyCaches, m_compiledData.data()); - aliasCreator.appendAliasPropertiesToMetaObjects(); + aliasCreator.appendAliasPropertiesToMetaObjects(engine); pendingGroupPropertyBindings.resolveMissingPropertyCaches(engine, &m_compiledData->propertyCaches); } diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp index 42e7d2c4b4..c62f760ee3 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<QQmlQmldirData> data = typeLoader()->getQmldir(url); - data->setImport(this, import); + data->setImport(this, std::move(import)); data->setPriority(this, priority); if (data->status() == Error) { @@ -563,13 +563,7 @@ bool QQmlTypeLoader::Blob::addImport(QQmlTypeLoader::Blob::PendingImportPtr impo QString qmldirFilePath; QString qmldirUrl; - if (QQmlMetaType::isLockedModule(import->uri, import->majorVersion)) { - //Locked modules are checked first, to save on filesystem checks - if (!m_importCache.addLibraryImport(importDatabase, import->uri, import->qualifier, import->majorVersion, - import->minorVersion, QString(), QString(), false, errors)) - return false; - - } else if (m_importCache.locateQmldir(importDatabase, import->uri, import->majorVersion, import->minorVersion, + if (m_importCache.locateQmldir(importDatabase, import->uri, import->majorVersion, import->minorVersion, &qmldirFilePath, &qmldirUrl)) { // This is a local library import if (!m_importCache.addLibraryImport(importDatabase, import->uri, import->qualifier, import->majorVersion, 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<QQmlError> QQmlTypeLoaderQmldirContent::errors(const QString &uri) const { QList<QQmlError> 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); diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp index a67ac7384d..9b5490b6e5 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); diff --git a/src/qml/types/qqmlbind.cpp b/src/qml/types/qqmlbind.cpp index 9d305cd24c..36de16a818 100644 --- a/src/qml/types/qqmlbind.cpp +++ b/src/qml/types/qqmlbind.cpp @@ -78,7 +78,7 @@ public: QQmlNullableValue<bool> when; QPointer<QObject> obj; QString propName; - QQmlNullableValue<QVariant> value; + QQmlNullableValue<QJSValue> value; QQmlProperty prop; QQmlAbstractBinding::Ptr prevBind; QV4::PersistentValue v4Value; @@ -293,13 +293,13 @@ void QQmlBind::setProperty(const QString &p) The value to be set on the target object and property. This can be a constant (which isn't very useful), or a bound expression. */ -QVariant QQmlBind::value() const +QJSValue QQmlBind::value() const { Q_D(const QQmlBind); return d->value.value; } -void QQmlBind::setValue(const QVariant &v) +void QQmlBind::setValue(const QJSValue &v) { Q_D(QQmlBind); d->value = v; @@ -359,7 +359,8 @@ void QQmlBind::setDelayed(bool delayed) \li Binding.RestoreBindingOrValue The original value is always restored. \endlist - The default value is Binding.RestoreBinding. + \warning The default value is Binding.RestoreBinding. This will change in + Qt 5.15 to Binding.RestoreBindingOrValue. If you rely on any specific behavior regarding the restoration of plain values when bindings get disabled you should migrate to explicitly set the @@ -456,11 +457,23 @@ void QQmlBind::eval() Q_ASSERT(vmemo); vmemo->setVMEProperty(propPriv->core.coreIndex(), *d->v4Value.valueRef()); d->clearPrev(); + } else if (!d->restoreModeExplicit) { + qmlWarning(this) + << "Not restoring previous value because restoreMode has not been set." + << "This behavior is deprecated." + << "In Qt < 5.15 the default is Binding.RestoreBinding." + << "In Qt >= 5.15 the default is Binding.RestoreBindingOrValue."; } } else if (d->prevIsVariant) { if (d->restoreValue) { d->prop.write(d->prevValue); d->clearPrev(); + } else if (!d->restoreModeExplicit) { + qmlWarning(this) + << "Not restoring previous value because restoreMode has not been set." + << "This behavior is deprecated." + << "In Qt < 5.15 the default is Binding.RestoreBinding." + << "In Qt >= 5.15 the default is Binding.RestoreBindingOrValue."; } } return; @@ -489,7 +502,7 @@ void QQmlBind::eval() QQmlPropertyPrivate::removeBinding(d->prop); } - d->prop.write(d->value.value); + d->prop.write(d->value.value.toVariant()); } QT_END_NAMESPACE diff --git a/src/qml/types/qqmlbind_p.h b/src/qml/types/qqmlbind_p.h index e7c7e01a0d..a100b1552c 100644 --- a/src/qml/types/qqmlbind_p.h +++ b/src/qml/types/qqmlbind_p.h @@ -75,7 +75,7 @@ private: Q_INTERFACES(QQmlPropertyValueSource) Q_PROPERTY(QObject *target READ object WRITE setObject) Q_PROPERTY(QString property READ property WRITE setProperty) - Q_PROPERTY(QVariant value READ value WRITE setValue) + Q_PROPERTY(QJSValue value READ value WRITE setValue) Q_PROPERTY(bool when READ when WRITE setWhen) Q_PROPERTY(bool delayed READ delayed WRITE setDelayed REVISION 8) Q_PROPERTY(RestorationMode restoreMode READ restoreMode WRITE setRestoreMode @@ -96,8 +96,8 @@ public: QString property() const; void setProperty(const QString &); - QVariant value() const; - void setValue(const QVariant &); + QJSValue value() const; + void setValue(const QJSValue &); bool delayed() const; void setDelayed(bool); |