diff options
author | Simon Hausmann <[email protected]> | 2017-08-16 14:56:31 +0200 |
---|---|---|
committer | Simon Hausmann <[email protected]> | 2017-08-18 11:46:11 +0200 |
commit | 43a615e309e70978711f5c2c56a9881876b96349 (patch) | |
tree | a8d0899cbc1e7775f52056fc56db58b2fcf305de /src/qml | |
parent | 6034d89bdd907d4795c19e8ac752f4eb51c82a94 (diff) | |
parent | 3513995d8fde7f002977275463fcea1b86f4a693 (diff) |
Merge remote-tracking branch 'origin/5.9' into dev
Conflicts:
src/qml/compiler/qqmltypecompiler.cpp
src/qml/jsruntime/qv4qmlcontext.cpp
src/qml/jsruntime/qv4qobjectwrapper.cpp
src/qml/qml/qqmlcustomparser.cpp
src/qml/qml/qqmlimport.cpp
src/qml/qml/qqmlimport_p.h
src/qml/qml/qqmlmetatype.cpp
src/qml/qml/qqmlmetatype_p.h
src/qml/qml/qqmltypenamecache.cpp
src/qml/qml/qqmltypenamecache_p.h
src/qml/qml/qqmltypewrapper.cpp
src/qml/qml/qqmltypewrapper_p.h
src/qml/qml/qqmlvmemetaobject.cpp
src/qml/util/qqmladaptormodel.cpp
Change-Id: Ic959d03e6f9c328fb02710d9abbb0f27cddde131
Diffstat (limited to 'src/qml')
38 files changed, 1277 insertions, 1014 deletions
diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp index e05c38e14a..b58920d812 100644 --- a/src/qml/compiler/qqmlirbuilder.cpp +++ b/src/qml/compiler/qqmlirbuilder.cpp @@ -1777,7 +1777,7 @@ enum MetaObjectResolverFlags { }; static void initMetaObjectResolver(QV4::IR::MemberExpressionResolver *resolver, QQmlPropertyCache *metaObject); -static void initScopedEnumResolver(QV4::IR::MemberExpressionResolver *resolver, QQmlType *qmlType, int index); +static void initScopedEnumResolver(QV4::IR::MemberExpressionResolver *resolver, const QQmlType &qmlType, int index); static QV4::IR::DiscoveredType resolveQmlType(QQmlEnginePrivate *qmlEngine, const QV4::IR::MemberExpressionResolver *resolver, @@ -1785,16 +1785,16 @@ static QV4::IR::DiscoveredType resolveQmlType(QQmlEnginePrivate *qmlEngine, { QV4::IR::Type result = QV4::IR::VarType; - QQmlType *type = static_cast<QQmlType*>(resolver->data); + QQmlType type = resolver->qmlType; if (member->name->constData()->isUpper()) { bool ok = false; - int value = type->enumValue(qmlEngine, *member->name, &ok); + int value = type.enumValue(qmlEngine, *member->name, &ok); if (ok) { member->setEnumValue(value); return QV4::IR::SInt32Type; } else { - int index = type->scopedEnumIndex(qmlEngine, *member->name, &ok); + int index = type.scopedEnumIndex(qmlEngine, *member->name, &ok); if (ok) { auto newResolver = resolver->owner->New<QV4::IR::MemberExpressionResolver>(); newResolver->owner = resolver->owner; @@ -1804,8 +1804,8 @@ static QV4::IR::DiscoveredType resolveQmlType(QQmlEnginePrivate *qmlEngine, } } - if (type->isCompositeSingleton()) { - QQmlRefPointer<QQmlTypeData> tdata = qmlEngine->typeLoader.getType(type->singletonInstanceInfo()->url); + if (type.isCompositeSingleton()) { + QQmlRefPointer<QQmlTypeData> tdata = qmlEngine->typeLoader.getType(type.singletonInstanceInfo()->url); Q_ASSERT(tdata); tdata->release(); // Decrease the reference count added from QQmlTypeLoader::getType() // When a singleton tries to reference itself, it may not be complete yet. @@ -1816,8 +1816,8 @@ static QV4::IR::DiscoveredType resolveQmlType(QQmlEnginePrivate *qmlEngine, newResolver->flags |= AllPropertiesAreFinal; return newResolver->resolveMember(qmlEngine, newResolver, member); } - } else if (type->isSingleton()) { - const QMetaObject *singletonMeta = type->singletonInstanceInfo()->instanceMetaObject; + } else if (type.isSingleton()) { + const QMetaObject *singletonMeta = type.singletonInstanceInfo()->instanceMetaObject; if (singletonMeta) { // QJSValue-based singletons cannot be accelerated auto newResolver = resolver->owner->New<QV4::IR::MemberExpressionResolver>(); newResolver->owner = resolver->owner; @@ -1842,13 +1842,13 @@ static QV4::IR::DiscoveredType resolveQmlType(QQmlEnginePrivate *qmlEngine, return result; } -static void initQmlTypeResolver(QV4::IR::MemberExpressionResolver *resolver, QQmlType *qmlType) +static void initQmlTypeResolver(QV4::IR::MemberExpressionResolver *resolver, const QQmlType &qmlType) { Q_ASSERT(resolver); resolver->resolveMember = &resolveQmlType; - resolver->data = qmlType; - resolver->extraData = 0; + resolver->qmlType = qmlType; + resolver->typenameCache = 0; resolver->flags = 0; } @@ -1857,8 +1857,8 @@ static QV4::IR::DiscoveredType resolveImportNamespace( QV4::IR::Member *member) { QV4::IR::Type result = QV4::IR::VarType; - QQmlTypeNameCache *typeNamespace = static_cast<QQmlTypeNameCache*>(resolver->extraData); - void *importNamespace = resolver->data; + QQmlTypeNameCache *typeNamespace = resolver->typenameCache; + const QQmlImportRef *importNamespace = resolver->import; QQmlTypeNameCache::Result r = typeNamespace->query(*member->name, importNamespace); if (r.isValid()) { @@ -1866,11 +1866,11 @@ static QV4::IR::DiscoveredType resolveImportNamespace( if (r.scriptIndex != -1) { // TODO: remember the index and replace with subscript later. result = QV4::IR::VarType; - } else if (r.type) { + } else if (r.type.isValid()) { // TODO: Propagate singleton information, so that it is loaded // through the singleton getter in the run-time. Until then we // can't accelerate access :( - if (!r.type->isSingleton()) { + if (!r.type.isSingleton()) { auto newResolver = resolver->owner->New<QV4::IR::MemberExpressionResolver>(); newResolver->owner = resolver->owner; initQmlTypeResolver(newResolver, r.type); @@ -1885,11 +1885,11 @@ static QV4::IR::DiscoveredType resolveImportNamespace( } static void initImportNamespaceResolver(QV4::IR::MemberExpressionResolver *resolver, - QQmlTypeNameCache *imports, const void *importNamespace) + QQmlTypeNameCache *imports, const QQmlImportRef *importNamespace) { resolver->resolveMember = &resolveImportNamespace; - resolver->data = const_cast<void*>(importNamespace); - resolver->extraData = imports; + resolver->import = importNamespace; + resolver->typenameCache = imports; resolver->flags = 0; } @@ -1898,7 +1898,7 @@ static QV4::IR::DiscoveredType resolveMetaObjectProperty( QV4::IR::Member *member) { QV4::IR::Type result = QV4::IR::VarType; - QQmlPropertyCache *metaObject = static_cast<QQmlPropertyCache*>(resolver->data); + QQmlPropertyCache *metaObject = resolver->propertyCache; if (member->name->constData()->isUpper() && (resolver->flags & LookupsIncludeEnums)) { const QMetaObject *mo = metaObject->createMetaObject(); @@ -1980,7 +1980,7 @@ static void initMetaObjectResolver(QV4::IR::MemberExpressionResolver *resolver, Q_ASSERT(resolver); resolver->resolveMember = &resolveMetaObjectProperty; - resolver->data = metaObject; + resolver->propertyCache = metaObject; resolver->flags = 0; } @@ -1991,24 +1991,23 @@ static QV4::IR::DiscoveredType resolveScopedEnum(QQmlEnginePrivate *qmlEngine, if (!member->name->constData()->isUpper()) return QV4::IR::VarType; - QQmlType *type = static_cast<QQmlType*>(resolver->data); + QQmlType type = resolver->qmlType; int index = resolver->flags; bool ok = false; - int value = type->scopedEnumValue(qmlEngine, index, *member->name, &ok); + int value = type.scopedEnumValue(qmlEngine, index, *member->name, &ok); if (!ok) return QV4::IR::VarType; member->setEnumValue(value); return QV4::IR::SInt32Type; } -static void initScopedEnumResolver(QV4::IR::MemberExpressionResolver *resolver, QQmlType *qmlType, int index) +static void initScopedEnumResolver(QV4::IR::MemberExpressionResolver *resolver, const QQmlType &qmlType, int index) { Q_ASSERT(resolver); resolver->resolveMember = &resolveScopedEnum; - resolver->data = qmlType; - resolver->extraData = 0; + resolver->qmlType = qmlType; resolver->flags = index; } @@ -2077,10 +2076,10 @@ QV4::IR::Expr *JSCodeGen::fallbackNameLookup(const QString &name, int line, int if (r.scriptIndex != -1) { return _block->SUBSCRIPT(_block->TEMP(_importedScriptsTemp), _block->CONST(QV4::IR::SInt32Type, r.scriptIndex)); - } else if (r.type) { + } else if (r.type.isValid()) { QV4::IR::Name *typeName = _block->NAME(name, line, col); // Make sure the run-time loads this through the more efficient singleton getter. - typeName->qmlSingleton = r.type->isCompositeSingleton(); + typeName->qmlSingleton = r.type.isCompositeSingleton(); typeName->freeOfSideEffects = true; QV4::IR::Temp *result = _block->TEMP(_block->newTemp()); _block->MOVE(result, typeName); diff --git a/src/qml/compiler/qqmlpropertycachecreator_p.h b/src/qml/compiler/qqmlpropertycachecreator_p.h index 5901e4e13e..b33deac045 100644 --- a/src/qml/compiler/qqmlpropertycachecreator_p.h +++ b/src/qml/compiler/qqmlpropertycachecreator_p.h @@ -211,12 +211,12 @@ inline QQmlPropertyCache *QQmlPropertyCacheCreator<ObjectContainer>::propertyCac } else if (context.instantiatingBinding && context.instantiatingBinding->isAttachedProperty()) { auto *typeRef = objectContainer->resolvedTypes.value(context.instantiatingBinding->propertyNameIndex); Q_ASSERT(typeRef); - QQmlType *qmltype = typeRef->type; - if (!qmltype) { + QQmlType qmltype = typeRef->type; + if (!qmltype.isValid()) { QString propertyName = stringAt(context.instantiatingBinding->propertyNameIndex); if (imports->resolveType(propertyName, &qmltype, 0, 0, 0)) { - if (qmltype->isComposite()) { - QQmlTypeData *tdata = enginePrivate->typeLoader.getType(qmltype->sourceUrl()); + if (qmltype.isComposite()) { + QQmlTypeData *tdata = enginePrivate->typeLoader.getType(qmltype.sourceUrl()); Q_ASSERT(tdata); Q_ASSERT(tdata->isComplete()); @@ -228,7 +228,7 @@ inline QQmlPropertyCache *QQmlPropertyCacheCreator<ObjectContainer>::propertyCac } } - const QMetaObject *attachedMo = qmltype ? qmltype->attachedPropertiesType(enginePrivate) : 0; + const QMetaObject *attachedMo = qmltype.attachedPropertiesType(enginePrivate); if (!attachedMo) { *error = QQmlCompileError(context.instantiatingBinding->location, QQmlPropertyCacheCreatorBase::tr("Non-existent attached object")); return nullptr; @@ -410,12 +410,12 @@ inline QQmlCompileError QQmlPropertyCacheCreator<ObjectContainer>::createMetaObj // lazily resolved type Q_ASSERT(param->type == QV4::CompiledData::Property::Custom); const QString customTypeName = stringAt(param->customTypeNameIndex); - QQmlType *qmltype = 0; + QQmlType qmltype; if (!imports->resolveType(customTypeName, &qmltype, 0, 0, 0)) return QQmlCompileError(s->location, QQmlPropertyCacheCreatorBase::tr("Invalid signal parameter type: %1").arg(customTypeName)); - if (qmltype->isComposite()) { - QQmlTypeData *tdata = enginePrivate->typeLoader.getType(qmltype->sourceUrl()); + if (qmltype.isComposite()) { + QQmlTypeData *tdata = enginePrivate->typeLoader.getType(qmltype.sourceUrl()); Q_ASSERT(tdata); Q_ASSERT(tdata->isComplete()); @@ -425,7 +425,7 @@ inline QQmlCompileError QQmlPropertyCacheCreator<ObjectContainer>::createMetaObj tdata->release(); } else { - paramTypes[i + 1] = qmltype->typeId(); + paramTypes[i + 1] = qmltype.typeId(); } } } @@ -490,14 +490,14 @@ inline QQmlCompileError QQmlPropertyCacheCreator<ObjectContainer>::createMetaObj Q_ASSERT(p->type == QV4::CompiledData::Property::CustomList || p->type == QV4::CompiledData::Property::Custom); - QQmlType *qmltype = 0; + QQmlType qmltype; if (!imports->resolveType(stringAt(p->customTypeNameIndex), &qmltype, 0, 0, 0)) { return QQmlCompileError(p->location, QQmlPropertyCacheCreatorBase::tr("Invalid property type")); } - Q_ASSERT(qmltype); - if (qmltype->isComposite()) { - QQmlTypeData *tdata = enginePrivate->typeLoader.getType(qmltype->sourceUrl()); + Q_ASSERT(qmltype.isValid()); + if (qmltype.isComposite()) { + QQmlTypeData *tdata = enginePrivate->typeLoader.getType(qmltype.sourceUrl()); Q_ASSERT(tdata); Q_ASSERT(tdata->isComplete()); @@ -512,9 +512,9 @@ inline QQmlCompileError QQmlPropertyCacheCreator<ObjectContainer>::createMetaObj tdata->release(); } else { if (p->type == QV4::CompiledData::Property::Custom) { - propertyType = qmltype->typeId(); + propertyType = qmltype.typeId(); } else { - propertyType = qmltype->qListTypeId(); + propertyType = qmltype.qListTypeId(); } } @@ -690,8 +690,8 @@ inline void QQmlPropertyCacheAliasCreator<ObjectContainer>::propertyDataForAlias auto *typeRef = objectContainer->resolvedTypes.value(targetObject.inheritedTypeNameIndex); Q_ASSERT(typeRef); - if (typeRef->type) - *type = typeRef->type->typeId(); + if (typeRef->type.isValid()) + *type = typeRef->type.typeId(); else *type = typeRef->compilationUnit->metaTypeId; diff --git a/src/qml/compiler/qqmlpropertyvalidator.cpp b/src/qml/compiler/qqmlpropertyvalidator.cpp index 383c20239f..4ac7aad553 100644 --- a/src/qml/compiler/qqmlpropertyvalidator.cpp +++ b/src/qml/compiler/qqmlpropertyvalidator.cpp @@ -106,8 +106,8 @@ QVector<QQmlCompileError> QQmlPropertyValidator::validateObject(int objectIndex, QQmlCustomParser *customParser = 0; if (auto typeRef = resolvedTypes.value(obj->inheritedTypeNameIndex)) { - if (typeRef->type) - customParser = typeRef->type->customParser(); + if (typeRef->type.isValid()) + customParser = typeRef->type.customParser(); } QList<const QV4::CompiledData::Binding*> customBindings; @@ -178,8 +178,8 @@ QVector<QQmlCompileError> QQmlPropertyValidator::validateObject(int objectIndex, if (notInRevision) { QString typeName = stringAt(obj->inheritedTypeNameIndex); auto *objectType = resolvedTypes.value(obj->inheritedTypeNameIndex); - if (objectType && objectType->type) { - return recordError(binding->location, tr("\"%1.%2\" is not available in %3 %4.%5.").arg(typeName).arg(name).arg(objectType->type->module()).arg(objectType->majorVersion).arg(objectType->minorVersion)); + if (objectType && objectType->type.isValid()) { + return recordError(binding->location, tr("\"%1.%2\" is not available in %3 %4.%5.").arg(typeName).arg(name).arg(objectType->type.module()).arg(objectType->majorVersion).arg(objectType->minorVersion)); } else { return recordError(binding->location, tr("\"%1.%2\" is not available due to component versioning.").arg(typeName).arg(name)); } @@ -197,7 +197,7 @@ QVector<QQmlCompileError> QQmlPropertyValidator::validateObject(int objectIndex, collectedBindingPropertyData[i] = pd; if (name.constData()->isUpper() && !binding->isAttachedProperty()) { - QQmlType *type = 0; + QQmlType type; QQmlImportNamespace *typeNamespace = 0; imports.resolveType(stringAt(binding->propertyNameIndex), &type, 0, 0, &typeNamespace); if (typeNamespace) @@ -628,21 +628,19 @@ QQmlCompileError QQmlPropertyValidator::validateObjectBinding(QQmlPropertyData * bool isValueSource = false; bool isPropertyInterceptor = false; - QQmlType *qmlType = 0; const QV4::CompiledData::Object *targetObject = qmlUnit->objectAt(binding->value.objectIndex); if (auto *typeRef = resolvedTypes.value(targetObject->inheritedTypeNameIndex)) { QQmlPropertyCache *cache = typeRef->createPropertyCache(QQmlEnginePrivate::get(enginePrivate)); const QMetaObject *mo = cache->firstCppMetaObject(); - while (mo && !qmlType) { + QQmlType qmlType; + while (mo && !qmlType.isValid()) { qmlType = QQmlMetaType::qmlType(mo); mo = mo->superClass(); } - Q_ASSERT(qmlType); - } + Q_ASSERT(qmlType.isValid()); - if (qmlType) { - isValueSource = qmlType->propertyValueSourceCast() != -1; - isPropertyInterceptor = qmlType->propertyValueInterceptorCast() != -1; + isValueSource = qmlType.propertyValueSourceCast() != -1; + isPropertyInterceptor = qmlType.propertyValueInterceptorCast() != -1; } if (!isValueSource && !isPropertyInterceptor) { diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp index c09fde86f1..9058a6c78f 100644 --- a/src/qml/compiler/qqmltypecompiler.cpp +++ b/src/qml/compiler/qqmltypecompiler.cpp @@ -75,7 +75,7 @@ QV4::CompiledData::CompilationUnit *QQmlTypeCompiler::compile() for (auto it = resolvedTypes.constBegin(), end = resolvedTypes.constEnd(); it != end; ++it) { - QQmlCustomParser *customParser = (*it)->type ? (*it)->type->customParser() : 0; + QQmlCustomParser *customParser = (*it)->type.customParser(); if (customParser) customParsers.insert(it.key(), customParser); } @@ -171,7 +171,6 @@ QV4::CompiledData::CompilationUnit *QQmlTypeCompiler::compile() compilationUnit->propertyCaches = std::move(m_propertyCaches); Q_ASSERT(compilationUnit->propertyCaches.count() == static_cast<int>(compilationUnit->data->nObjects)); - if (errors.isEmpty()) return compilationUnit; else @@ -345,11 +344,11 @@ bool SignalHandlerConverter::convertSignalHandlerExpressionsToFunctionDeclaratio if (binding->type == QV4::CompiledData::Binding::Type_AttachedProperty) { const QmlIR::Object *attachedObj = qmlObjects.at(binding->value.objectIndex); auto *typeRef = resolvedTypes.value(binding->propertyNameIndex); - QQmlType *type = typeRef ? typeRef->type : 0; - if (!type) { + QQmlType type = typeRef ? typeRef->type : QQmlType(); + if (!type.isValid()) { if (imports->resolveType(propertyName, &type, 0, 0, 0)) { - if (type->isComposite()) { - QQmlTypeData *tdata = enginePrivate->typeLoader.getType(type->sourceUrl()); + if (type.isComposite()) { + QQmlTypeData *tdata = enginePrivate->typeLoader.getType(type.sourceUrl()); Q_ASSERT(tdata); Q_ASSERT(tdata->isComplete()); @@ -361,7 +360,7 @@ bool SignalHandlerConverter::convertSignalHandlerExpressionsToFunctionDeclaratio } } - const QMetaObject *attachedType = type ? type->attachedPropertiesType(enginePrivate) : 0; + const QMetaObject *attachedType = type.attachedPropertiesType(enginePrivate); if (!attachedType) COMPILE_EXCEPTION(binding, tr("Non-existent attached object")); QQmlPropertyCache *cache = compiler->enginePrivate()->cache(attachedType); @@ -418,9 +417,9 @@ bool SignalHandlerConverter::convertSignalHandlerExpressionsToFunctionDeclaratio const QString &originalPropertyName = stringAt(binding->propertyNameIndex); auto *typeRef = resolvedTypes.value(obj->inheritedTypeNameIndex); - const QQmlType *type = typeRef ? typeRef->type : 0; - if (type) { - COMPILE_EXCEPTION(binding, tr("\"%1.%2\" is not available in %3 %4.%5.").arg(typeName).arg(originalPropertyName).arg(type->module()).arg(type->majorVersion()).arg(type->minorVersion())); + const QQmlType type = typeRef->type; + if (type.isValid()) { + COMPILE_EXCEPTION(binding, tr("\"%1.%2\" is not available in %3 %4.%5.").arg(typeName).arg(originalPropertyName).arg(type.module()).arg(type.majorVersion()).arg(type.minorVersion())); } else { COMPILE_EXCEPTION(binding, tr("\"%1.%2\" is not available due to component versioning.").arg(typeName).arg(originalPropertyName)); } @@ -623,17 +622,17 @@ bool QQmlEnumTypeResolver::tryQualifiedEnumAssignment(const QmlIR::Object *obj, } return true; } - QQmlType *type = 0; + QQmlType type; imports->resolveType(typeName, &type, 0, 0, 0); - if (!type && !isQtObject) + if (!type.isValid() && !isQtObject) return true; int value = 0; bool ok = false; auto *tr = resolvedTypes->value(obj->inheritedTypeNameIndex); - if (type && tr && tr->type == type) { + if (type.isValid() && tr && tr->type == type) { // When these two match, we can short cut the search QMetaProperty mprop = propertyCache->firstCppMetaObject()->property(prop->coreIndex()); QMetaEnum menum = mprop.enumerator(); @@ -648,11 +647,11 @@ bool QQmlEnumTypeResolver::tryQualifiedEnumAssignment(const QmlIR::Object *obj, } } else { // Otherwise we have to search the whole type - if (type) { + if (type.isValid()) { if (!scopedEnumName.isEmpty()) - value = type->scopedEnumValue(compiler->enginePrivate(), scopedEnumName, enumValue, &ok); + value = type.scopedEnumValue(compiler->enginePrivate(), scopedEnumName, enumValue, &ok); else - value = type->enumValue(compiler->enginePrivate(), QHashedStringRef(enumValue), &ok); + value = type.enumValue(compiler->enginePrivate(), QHashedStringRef(enumValue), &ok); } else { QByteArray enumName = enumValue.toUtf8(); const QMetaObject *metaObject = StaticQtMetaObject::get(); @@ -675,13 +674,13 @@ int QQmlEnumTypeResolver::evaluateEnum(const QString &scope, const QStringRef &e *ok = false; if (scope != QLatin1String("Qt")) { - QQmlType *type = 0; + QQmlType type; imports->resolveType(scope, &type, 0, 0, 0); - if (!type) + if (!type.isValid()) return -1; if (!enumName.isEmpty()) - return type->scopedEnumValue(compiler->enginePrivate(), enumName, enumValue, ok); - return type->enumValue(compiler->enginePrivate(), QHashedStringRef(enumValue.constData(), enumValue.length()), ok); + return type.scopedEnumValue(compiler->enginePrivate(), enumName, enumValue, ok); + return type.enumValue(compiler->enginePrivate(), QHashedStringRef(enumValue.constData(), enumValue.length()), ok); } const QMetaObject *mo = StaticQtMetaObject::get(); @@ -820,8 +819,8 @@ void QQmlComponentAndAliasResolver::findAndRegisterImplicitComponents(const QmlI const QmlIR::Object *targetObject = qmlObjects->at(binding->value.objectIndex); auto *tr = resolvedTypes->value(targetObject->inheritedTypeNameIndex); Q_ASSERT(tr); - if (QQmlType *targetType = tr->type) { - if (targetType->metaObject() == &QQmlComponent::staticMetaObject) + if (tr->type.isValid()) { + if (tr->type.metaObject() == &QQmlComponent::staticMetaObject) continue; } else if (tr->compilationUnit) { if (tr->compilationUnit->rootPropertyCache()->firstCppMetaObject() == &QQmlComponent::staticMetaObject) @@ -850,22 +849,22 @@ void QQmlComponentAndAliasResolver::findAndRegisterImplicitComponents(const QmlI continue; // emulate "import Qml 2.0 as QmlInternals" and then wrap the component in "QmlInternals.Component {}" - QQmlType *componentType = QQmlMetaType::qmlType(&QQmlComponent::staticMetaObject); - Q_ASSERT(componentType); + QQmlType componentType = QQmlMetaType::qmlType(&QQmlComponent::staticMetaObject); + Q_ASSERT(componentType.isValid()); const QString qualifier = QStringLiteral("QmlInternals"); - compiler->addImport(componentType->module(), qualifier, componentType->majorVersion(), componentType->minorVersion()); + compiler->addImport(componentType.module(), qualifier, componentType.majorVersion(), componentType.minorVersion()); QmlIR::Object *syntheticComponent = pool->New<QmlIR::Object>(); - syntheticComponent->init(pool, compiler->registerString(qualifier + QLatin1Char('.') + componentType->elementName()), compiler->registerString(QString())); + syntheticComponent->init(pool, compiler->registerString(qualifier + QLatin1Char('.') + componentType.elementName()), compiler->registerString(QString())); syntheticComponent->location = binding->valueLocation; syntheticComponent->flags |= QV4::CompiledData::Object::IsComponent; if (!resolvedTypes->contains(syntheticComponent->inheritedTypeNameIndex)) { auto typeRef = new QV4::CompiledData::ResolvedTypeReference; typeRef->type = componentType; - typeRef->majorVersion = componentType->majorVersion(); - typeRef->minorVersion = componentType->minorVersion(); + typeRef->majorVersion = componentType.majorVersion(); + typeRef->minorVersion = componentType.minorVersion(); resolvedTypes->insert(syntheticComponent->inheritedTypeNameIndex, typeRef); } @@ -906,7 +905,7 @@ bool QQmlComponentAndAliasResolver::resolve() if (obj->inheritedTypeNameIndex) { auto *tref = resolvedTypes->value(obj->inheritedTypeNameIndex); Q_ASSERT(tref); - if (tref->type && tref->type->metaObject() == &QQmlComponent::staticMetaObject) + if (tref->type.metaObject() == &QQmlComponent::staticMetaObject) isExplicitComponent = true; } if (!isExplicitComponent) { diff --git a/src/qml/compiler/qv4compileddata.cpp b/src/qml/compiler/qv4compileddata.cpp index be7429df41..96b76d8cfd 100644 --- a/src/qml/compiler/qv4compileddata.cpp +++ b/src/qml/compiler/qv4compileddata.cpp @@ -57,6 +57,7 @@ #include <QScopedValueRollback> #include <QStandardPaths> #include <QDir> +#include <private/qv4identifiertable_p.h> #endif #include <private/qqmlirbuilder_p.h> #include <QCoreApplication> @@ -127,7 +128,7 @@ QV4::Function *CompilationUnit::linkToEngine(ExecutionEngine *engine) // memset the strings to 0 in case a GC run happens while we're within the loop below memset(runtimeStrings, 0, data->stringTableSize * sizeof(QV4::Heap::String*)); for (uint i = 0; i < data->stringTableSize; ++i) - runtimeStrings[i] = engine->newIdentifier(data->stringAt(i)); + runtimeStrings[i] = engine->newString(data->stringAt(i)); runtimeRegularExpressions = new QV4::Value[data->regexpTableSize]; // memset the regexps to 0 in case a GC run happens while we're within the loop below @@ -179,7 +180,7 @@ QV4::Function *CompilationUnit::linkToEngine(ExecutionEngine *engine) const CompiledData::JSClassMember *member = data->jsClassAt(i, &memberCount); QV4::InternalClass *klass = engine->internalClasses[QV4::ExecutionEngine::Class_Object]; for (int j = 0; j < memberCount; ++j, ++member) - klass = klass->addMember(runtimeStrings[member->nameOffset]->identifier, member->isAccessor ? QV4::Attr_Accessor : QV4::Attr_Data); + klass = klass->addMember(engine->identifierTable->identifier(runtimeStrings[member->nameOffset]), member->isAccessor ? QV4::Attr_Accessor : QV4::Attr_Data); runtimeClasses[i] = klass; } @@ -210,8 +211,9 @@ void CompilationUnit::unlink() if (isRegisteredWithEngine) { Q_ASSERT(data && quint32(propertyCaches.count()) > data->indexOfRootObject && propertyCaches.at(data->indexOfRootObject)); - QQmlEnginePrivate *qmlEngine = QQmlEnginePrivate::get(propertyCaches.at(data->indexOfRootObject)->engine); - qmlEngine->unregisterInternalCompositeType(this); + if (engine) + QQmlEnginePrivate::get(engine)->unregisterInternalCompositeType(this); + QQmlMetaType::unregisterInternalCompositeType(this); isRegisteredWithEngine = false; } @@ -284,9 +286,10 @@ IdentifierHash<int> CompilationUnit::namedObjectsPerComponent(int componentObjec void CompilationUnit::finalize(QQmlEnginePrivate *engine) { // Add to type registry of composites - if (propertyCaches.needsVMEMetaObject(data->indexOfRootObject)) + if (propertyCaches.needsVMEMetaObject(data->indexOfRootObject)) { + QQmlMetaType::registerInternalCompositeType(this); engine->registerInternalCompositeType(this); - else { + } else { const QV4::CompiledData::Object *obj = objectAt(data->indexOfRootObject); auto *typeRef = resolvedTypes.value(obj->inheritedTypeNameIndex); Q_ASSERT(typeRef); @@ -294,8 +297,8 @@ void CompilationUnit::finalize(QQmlEnginePrivate *engine) metaTypeId = typeRef->compilationUnit->metaTypeId; listMetaTypeId = typeRef->compilationUnit->listMetaTypeId; } else { - metaTypeId = typeRef->type->typeId(); - listMetaTypeId = typeRef->type->qListTypeId(); + metaTypeId = typeRef->type.typeId(); + listMetaTypeId = typeRef->type.qListTypeId(); } } @@ -307,8 +310,8 @@ void CompilationUnit::finalize(QQmlEnginePrivate *engine) const QV4::CompiledData::Object *obj = data->objectAt(i); bindingCount += obj->nBindings; if (auto *typeRef = resolvedTypes.value(obj->inheritedTypeNameIndex)) { - if (QQmlType *qmlType = typeRef->type) { - if (qmlType->parserStatusCast() != -1) + if (typeRef->type.isValid()) { + if (typeRef->type.parserStatusCast() != -1) ++parserStatusCount; } ++objectCount; @@ -672,7 +675,7 @@ Returns the property cache, if one alread exists. The cache is not referenced. */ QQmlPropertyCache *ResolvedTypeReference::propertyCache() const { - if (type) + if (type.isValid()) return typePropertyCache; else return compilationUnit->rootPropertyCache(); @@ -685,8 +688,8 @@ QQmlPropertyCache *ResolvedTypeReference::createPropertyCache(QQmlEngine *engine { if (typePropertyCache) { return typePropertyCache; - } else if (type) { - typePropertyCache = QQmlEnginePrivate::get(engine)->cache(type->metaObject()); + } else if (type.isValid()) { + typePropertyCache = QQmlEnginePrivate::get(engine)->cache(type.metaObject()); return typePropertyCache; } else { return compilationUnit->rootPropertyCache(); @@ -695,7 +698,7 @@ QQmlPropertyCache *ResolvedTypeReference::createPropertyCache(QQmlEngine *engine bool ResolvedTypeReference::addToHash(QCryptographicHash *hash, QQmlEngine *engine) { - if (type) { + if (type.isValid()) { bool ok = false; hash->addData(createPropertyCache(engine)->checksum(&ok)); return ok; @@ -719,8 +722,8 @@ void ResolvedTypeReference::doDynamicTypeCheck() const QMetaObject *mo = 0; if (typePropertyCache) mo = typePropertyCache->firstCppMetaObject(); - else if (type) - mo = type->metaObject(); + else if (type.isValid()) + mo = type.metaObject(); else if (compilationUnit) mo = compilationUnit->rootPropertyCache()->firstCppMetaObject(); isFullyDynamicType = qtTypeInherits<QQmlPropertyMap>(mo); diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h index b28f77e6e6..6ad53fca4f 100644 --- a/src/qml/compiler/qv4compileddata_p.h +++ b/src/qml/compiler/qv4compileddata_p.h @@ -967,13 +967,12 @@ protected: struct ResolvedTypeReference { ResolvedTypeReference() - : type(0) - , majorVersion(0) + : majorVersion(0) , minorVersion(0) , isFullyDynamicType(false) {} - QQmlType *type; + QQmlType type; QQmlRefPointer<QQmlPropertyCache> typePropertyCache; QQmlRefPointer<QV4::CompiledData::CompilationUnit> compilationUnit; diff --git a/src/qml/compiler/qv4jsir_p.h b/src/qml/compiler/qv4jsir_p.h index 190fb1bd5b..fb65eb4d8c 100644 --- a/src/qml/compiler/qv4jsir_p.h +++ b/src/qml/compiler/qv4jsir_p.h @@ -54,6 +54,9 @@ #include <private/qqmljsmemorypool_p.h> #include <private/qqmljsastfwd_p.h> #include <private/qflagpointer_p.h> +#ifndef V4_BOOTSTRAP +#include <private/qqmlmetatype_p.h> +#endif #include <QtCore/private/qnumeric_p.h> #include <QtCore/QVector> @@ -77,6 +80,8 @@ class QQmlType; class QQmlPropertyData; class QQmlPropertyCache; class QQmlEnginePrivate; +struct QQmlImportRef; +class QQmlTypeNameCache; namespace QV4 { @@ -248,14 +253,18 @@ struct MemberExpressionResolver Member *member); MemberExpressionResolver() - : resolveMember(0), data(0), extraData(0), owner(nullptr), flags(0) {} + : resolveMember(0), import(nullptr), propertyCache(nullptr), typenameCache(nullptr), owner(nullptr), flags(0) {} bool isValid() const { return !!resolveMember; } void clear() { *this = MemberExpressionResolver(); } ResolveFunction resolveMember; - void *data; // Could be pointer to meta object, importNameSpace, etc. - depends on resolveMember implementation - void *extraData; // Could be QQmlTypeNameCache +#ifndef V4_BOOTSTRAP + QQmlType qmlType; +#endif + const QQmlImportRef *import; + QQmlPropertyCache *propertyCache; + QQmlTypeNameCache *typenameCache; Function *owner; unsigned int flags; }; diff --git a/src/qml/jsapi/qjsengine.cpp b/src/qml/jsapi/qjsengine.cpp index c678f8037a..d5b8b295a7 100644 --- a/src/qml/jsapi/qjsengine.cpp +++ b/src/qml/jsapi/qjsengine.cpp @@ -730,10 +730,7 @@ QJSEnginePrivate *QJSEnginePrivate::get(QV4::ExecutionEngine *e) QJSEnginePrivate::~QJSEnginePrivate() { - typedef QHash<const QMetaObject *, QQmlPropertyCache *>::Iterator PropertyCacheIt; - - for (PropertyCacheIt iter = propertyCache.begin(), end = propertyCache.end(); iter != end; ++iter) - (*iter)->release(); + QQmlMetaType::freeUnusedTypesAndCaches(); } void QJSEnginePrivate::addToDebugServer(QJSEngine *q) @@ -756,20 +753,6 @@ void QJSEnginePrivate::removeFromDebugServer(QJSEngine *q) server->removeEngine(q); } -QQmlPropertyCache *QJSEnginePrivate::createCache(const QMetaObject *mo) -{ - if (!mo->superClass()) { - QQmlPropertyCache *rv = new QQmlPropertyCache(QV8Engine::getV4(q_func()), mo); - propertyCache.insert(mo, rv); - return rv; - } else { - QQmlPropertyCache *super = cache(mo->superClass()); - QQmlPropertyCache *rv = super->copyAndAppend(mo); - propertyCache.insert(mo, rv); - return rv; - } -} - /*! \since 5.5 \relates QJSEngine diff --git a/src/qml/jsapi/qjsengine_p.h b/src/qml/jsapi/qjsengine_p.h index 2b462451ed..cbfe0f14a3 100644 --- a/src/qml/jsapi/qjsengine_p.h +++ b/src/qml/jsapi/qjsengine_p.h @@ -55,6 +55,7 @@ #include <QtCore/qmutex.h> #include "qjsengine.h" #include "private/qtqmlglobal_p.h" +#include <private/qqmlmetatype_p.h> QT_BEGIN_NAMESPACE @@ -110,14 +111,6 @@ public: // These methods may be called from the QML loader thread inline QQmlPropertyCache *cache(QObject *obj); inline QQmlPropertyCache *cache(const QMetaObject *); - -private: - // Must be called locked - QQmlPropertyCache *createCache(const QMetaObject *); - - // These members must be protected by a QJSEnginePrivate::Locker as they are required by - // the threaded loader. Only access them through their respective accessor methods. - QHash<const QMetaObject *, QQmlPropertyCache *> propertyCache; }; QJSEnginePrivate::Locker::Locker(const QJSEngine *e) @@ -174,9 +167,7 @@ QQmlPropertyCache *QJSEnginePrivate::cache(QObject *obj) Locker locker(this); const QMetaObject *mo = obj->metaObject(); - QQmlPropertyCache *rv = propertyCache.value(mo); - if (!rv) rv = createCache(mo); - return rv; + return QQmlMetaType::propertyCache(mo); } /*! @@ -193,9 +184,7 @@ QQmlPropertyCache *QJSEnginePrivate::cache(const QMetaObject *metaObject) Q_ASSERT(metaObject); Locker locker(this); - QQmlPropertyCache *rv = propertyCache.value(metaObject); - if (!rv) rv = createCache(metaObject); - return rv; + return QQmlMetaType::propertyCache(metaObject); } diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index 019936767a..caa6e8b7ac 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -813,10 +813,10 @@ ReturnedValue ExecutionEngine::qmlSingletonWrapper(String *name) QQmlTypeNameCache::Result r = ctx->imports->query(name); Q_ASSERT(r.isValid()); - Q_ASSERT(r.type); - Q_ASSERT(r.type->isSingleton()); + Q_ASSERT(r.type.isValid()); + Q_ASSERT(r.type.isSingleton()); - QQmlType::SingletonInstanceInfo *siinfo = r.type->singletonInstanceInfo(); + QQmlType::SingletonInstanceInfo *siinfo = r.type.singletonInstanceInfo(); QQmlEngine *e = qmlEngine(); siinfo->init(e); diff --git a/src/qml/jsruntime/qv4function.cpp b/src/qml/jsruntime/qv4function.cpp index d1bdab1b3c..4b88d85e68 100644 --- a/src/qml/jsruntime/qv4function.cpp +++ b/src/qml/jsruntime/qv4function.cpp @@ -44,6 +44,7 @@ #include "qv4engine_p.h" #include "qv4lookup_p.h" #include <private/qv4mm_p.h> +#include <private/qv4identifiertable_p.h> QT_BEGIN_NAMESPACE @@ -57,8 +58,6 @@ Function::Function(ExecutionEngine *engine, CompiledData::CompilationUnit *unit, , codeData(0) , hasQmlDependencies(function->hasQmlDependencies()) { - Q_UNUSED(engine); - internalClass = engine->internalClasses[EngineBase::Class_Empty]; const quint32_le *formalsIndices = compiledFunction->formalsTable(); // iterate backwards, so we get the right ordering for duplicate names @@ -81,7 +80,7 @@ Function::Function(ExecutionEngine *engine, CompiledData::CompilationUnit *unit, const quint32_le *localsIndices = compiledFunction->localsTable(); for (quint32 i = 0; i < compiledFunction->nLocals; ++i) - internalClass = internalClass->addMember(compilationUnit->runtimeStrings[localsIndices[i]]->identifier, Attr_NotConfigurable); + internalClass = internalClass->addMember(engine->identifierTable->identifier(compilationUnit->runtimeStrings[localsIndices[i]]), Attr_NotConfigurable); canUseSimpleCall = compiledFunction->flags & CompiledData::Function::CanUseSimpleCall; } @@ -113,7 +112,7 @@ void Function::updateInternalClass(ExecutionEngine *engine, const QList<QByteArr const quint32_le *localsIndices = compiledFunction->localsTable(); for (quint32 i = 0; i < compiledFunction->nLocals; ++i) - internalClass = internalClass->addMember(compilationUnit->runtimeStrings[localsIndices[i]]->identifier, Attr_NotConfigurable); + internalClass = internalClass->addMember(engine->identifierTable->identifier(compilationUnit->runtimeStrings[localsIndices[i]]), Attr_NotConfigurable); canUseSimpleCall = false; } diff --git a/src/qml/jsruntime/qv4lookup.cpp b/src/qml/jsruntime/qv4lookup.cpp index d943ae1340..afadf59bd5 100644 --- a/src/qml/jsruntime/qv4lookup.cpp +++ b/src/qml/jsruntime/qv4lookup.cpp @@ -40,6 +40,7 @@ #include "qv4functionobject_p.h" #include "qv4scopedvalue_p.h" #include "qv4string_p.h" +#include <private/qv4identifiertable_p.h> QT_BEGIN_NAMESPACE @@ -49,7 +50,7 @@ using namespace QV4; ReturnedValue Lookup::lookup(const Value &thisObject, Object *o, PropertyAttributes *attrs) { ExecutionEngine *engine = o->engine(); - Identifier *name = engine->current->compilationUnit->runtimeStrings[nameIndex]->identifier; + Identifier *name = engine->identifierTable->identifier(engine->current->compilationUnit->runtimeStrings[nameIndex]); int i = 0; Heap::Object *obj = o->d(); while (i < Size && obj) { @@ -85,7 +86,7 @@ ReturnedValue Lookup::lookup(const Object *thisObject, PropertyAttributes *attrs { Heap::Object *obj = thisObject->d(); ExecutionEngine *engine = thisObject->engine(); - Identifier *name = engine->current->compilationUnit->runtimeStrings[nameIndex]->identifier; + Identifier *name = engine->identifierTable->identifier(engine->current->compilationUnit->runtimeStrings[nameIndex]); int i = 0; while (i < Size && obj) { classList[i] = obj->internalClass; diff --git a/src/qml/jsruntime/qv4qmlcontext.cpp b/src/qml/jsruntime/qv4qmlcontext.cpp index 89770d269a..c483fdb7e7 100644 --- a/src/qml/jsruntime/qv4qmlcontext.cpp +++ b/src/qml/jsruntime/qv4qmlcontext.cpp @@ -142,7 +142,7 @@ ReturnedValue QQmlContextWrapper::get(const Managed *m, String *name, bool *hasP if (r.scriptIndex != -1) { QV4::ScopedObject scripts(scope, context->importedScripts.valueRef()); return scripts->getIndexed(r.scriptIndex); - } else if (r.type) { + } else if (r.type.isValid()) { return QQmlTypeWrapper::create(v4, scopeObject, r.type); } else if (r.importNamespace) { return QQmlTypeWrapper::create(v4, scopeObject, context->imports, r.importNamespace); diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp index 91650f16e2..72ad0ce7b7 100644 --- a/src/qml/jsruntime/qv4qobjectwrapper.cpp +++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp @@ -296,7 +296,7 @@ ReturnedValue QObjectWrapper::getQmlProperty(QQmlContextData *qmlContext, String if (r.isValid()) { if (r.scriptIndex != -1) { return QV4::Encode::undefined(); - } else if (r.type) { + } else if (r.type.isValid()) { return QQmlTypeWrapper::create(v4, d()->object(), r.type, Heap::QQmlTypeWrapper::ExcludeEnums); } else if (r.importNamespace) { diff --git a/src/qml/qml/qqmlcustomparser.cpp b/src/qml/qml/qqmlcustomparser.cpp index 6ad641b8b1..cc6e75a39c 100644 --- a/src/qml/qml/qqmlcustomparser.cpp +++ b/src/qml/qml/qqmlcustomparser.cpp @@ -135,7 +135,7 @@ int QQmlCustomParser::evaluateEnum(const QByteArray& script, bool *ok) const if (scope != QLatin1String("Qt")) { if (imports.isNull()) return -1; - QQmlType *type = 0; + QQmlType type; if (imports.isT1()) { imports.asT1()->resolveType(scope, &type, 0, 0, 0); @@ -145,7 +145,7 @@ int QQmlCustomParser::evaluateEnum(const QByteArray& script, bool *ok) const type = result.type; } - if (!type) + if (!type.isValid()) return -1; int dot2 = script.indexOf('.', dot+1); @@ -153,9 +153,9 @@ int QQmlCustomParser::evaluateEnum(const QByteArray& script, bool *ok) const QByteArray enumValue = script.mid(dot2Valid ? dot2 + 1 : dot + 1); QByteArray scopedEnumName = (dot2Valid ? script.mid(dot + 1, dot2 - dot - 1) : QByteArray()); if (!scopedEnumName.isEmpty()) - return type->scopedEnumValue(engine, scopedEnumName, enumValue, ok); + return type.scopedEnumValue(engine, scopedEnumName, enumValue, ok); else - return type->enumValue(engine, QHashedCStringRef(enumValue.constData(), enumValue.length()), ok); + return type.enumValue(engine, QHashedCStringRef(enumValue.constData(), enumValue.length()), ok); } QByteArray enumValue = script.mid(dot + 1); @@ -177,12 +177,10 @@ const QMetaObject *QQmlCustomParser::resolveType(const QString& name) const { if (!imports.isT1()) return nullptr; - QQmlType *qmltype = 0; + QQmlType qmltype; if (!imports.asT1()->resolveType(name, &qmltype, 0, 0, 0)) return nullptr; - if (!qmltype) - return nullptr; - return qmltype->metaObject(); + return qmltype.metaObject(); } QT_END_NAMESPACE diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp index 38a2978712..eb2fbcdd73 100644 --- a/src/qml/qml/qqmlengine.cpp +++ b/src/qml/qml/qqmlengine.cpp @@ -683,8 +683,6 @@ QQmlEnginePrivate::QQmlEnginePrivate(QQmlEngine *e) QQmlEnginePrivate::~QQmlEnginePrivate() { - typedef QHash<QPair<QQmlType *, int>, QQmlPropertyCache *>::const_iterator TypePropertyCacheIt; - if (inProgressCreations) qWarning() << QQmlEngine::tr("There are still \"%1\" items in the process of being created at engine destruction.").arg(inProgressCreations); @@ -702,8 +700,8 @@ QQmlEnginePrivate::~QQmlEnginePrivate() if (incubationController) incubationController->d = 0; incubationController = 0; - for (TypePropertyCacheIt iter = typePropertyCache.cbegin(), end = typePropertyCache.cend(); iter != end; ++iter) - (*iter)->release(); + QQmlMetaType::freeUnusedTypesAndCaches(); + for (auto iter = m_compositeTypes.cbegin(), end = m_compositeTypes.cend(); iter != end; ++iter) { iter.value()->isRegisteredWithEngine = false; @@ -1028,9 +1026,9 @@ QQmlEngine::~QQmlEngine() // we do this here and not in the private dtor since otherwise a crash can // occur (if we are the QObject parent of the QObject singleton instance) // XXX TODO: performance -- store list of singleton types separately? - const QList<QQmlType*> singletonTypes = QQmlMetaType::qmlSingletonTypes(); - for (QQmlType *currType : singletonTypes) - currType->singletonInstanceInfo()->destroy(this); + QList<QQmlType> singletonTypes = QQmlMetaType::qmlSingletonTypes(); + for (const QQmlType &currType : singletonTypes) + currType.singletonInstanceInfo()->destroy(this); delete d->rootContext; d->rootContext = 0; @@ -2224,108 +2222,6 @@ QString QQmlEnginePrivate::offlineStorageDatabaseDirectory() const return q->offlineStoragePath() + QDir::separator() + QLatin1String("Databases") + QDir::separator(); } -QQmlPropertyCache *QQmlEnginePrivate::createCache(QQmlType *type, int minorVersion) -{ - QList<QQmlType *> types; - - int maxMinorVersion = 0; - - const QMetaObject *metaObject = type->metaObject(); - - while (metaObject) { - QQmlType *t = QQmlMetaType::qmlType(metaObject, type->module(), - type->majorVersion(), minorVersion); - if (t) { - maxMinorVersion = qMax(maxMinorVersion, t->minorVersion()); - types << t; - } else { - types << 0; - } - - metaObject = metaObject->superClass(); - } - - if (QQmlPropertyCache *c = typePropertyCache.value(qMakePair(type, maxMinorVersion))) { - c->addref(); - typePropertyCache.insert(qMakePair(type, minorVersion), c); - return c; - } - - QQmlPropertyCache *raw = cache(type->metaObject()); - - bool hasCopied = false; - - for (int ii = 0; ii < types.count(); ++ii) { - QQmlType *currentType = types.at(ii); - if (!currentType) - continue; - - int rev = currentType->metaObjectRevision(); - int moIndex = types.count() - 1 - ii; - - if (raw->allowedRevisionCache[moIndex] != rev) { - if (!hasCopied) { - raw = raw->copy(); - hasCopied = true; - } - raw->allowedRevisionCache[moIndex] = rev; - } - } - - // Test revision compatibility - the basic rule is: - // * Anything that is excluded, cannot overload something that is not excluded * - - // Signals override: - // * other signals and methods of the same name. - // * properties named on<Signal Name> - // * automatic <property name>Changed notify signals - - // Methods override: - // * other methods of the same name - - // Properties override: - // * other elements of the same name - -#if 0 - bool overloadError = false; - QString overloadName; - - for (QQmlPropertyCache::StringCache::ConstIterator iter = raw->stringCache.begin(); - !overloadError && iter != raw->stringCache.end(); - ++iter) { - - QQmlPropertyData *d = *iter; - if (raw->isAllowedInRevision(d)) - continue; // Not excluded - no problems - - // check that a regular "name" overload isn't happening - QQmlPropertyData *current = d; - while (!overloadError && current) { - current = d->overrideData(current); - if (current && raw->isAllowedInRevision(current)) - overloadError = true; - } - } - - if (overloadError) { - if (hasCopied) raw->release(); - - error.setDescription(QLatin1String("Type ") + type->qmlTypeName() + QLatin1Char(' ') + QString::number(type->majorVersion()) + QLatin1Char('.') + QString::number(minorVersion) + QLatin1String(" contains an illegal property \"") + overloadName + QLatin1String("\". This is an error in the type's implementation.")); - return 0; - } -#endif - - if (!hasCopied) raw->addref(); - typePropertyCache.insert(qMakePair(type, minorVersion), raw); - - if (minorVersion != maxMinorVersion) { - raw->addref(); - typePropertyCache.insert(qMakePair(type, maxMinorVersion), raw); - } - - return raw; -} - bool QQmlEnginePrivate::isQObject(int t) { Locker locker(this); @@ -2349,26 +2245,17 @@ QQmlMetaType::TypeCategory QQmlEnginePrivate::typeCategory(int t) const Locker locker(this); if (m_compositeTypes.contains(t)) return QQmlMetaType::Object; - else if (m_qmlLists.contains(t)) - return QQmlMetaType::List; - else - return QQmlMetaType::typeCategory(t); + return QQmlMetaType::typeCategory(t); } bool QQmlEnginePrivate::isList(int t) const { - Locker locker(this); - return m_qmlLists.contains(t) || QQmlMetaType::isList(t); + return QQmlMetaType::isList(t); } int QQmlEnginePrivate::listType(int t) const { - Locker locker(this); - QHash<int, int>::ConstIterator iter = m_qmlLists.constFind(t); - if (iter != m_qmlLists.cend()) - return *iter; - else - return QQmlMetaType::listType(t); + return QQmlMetaType::listType(t); } QQmlMetaObject QQmlEnginePrivate::rawMetaObjectForType(int t) const @@ -2378,8 +2265,8 @@ QQmlMetaObject QQmlEnginePrivate::rawMetaObjectForType(int t) const if (iter != m_compositeTypes.cend()) { return QQmlMetaObject((*iter)->rootPropertyCache()); } else { - QQmlType *type = QQmlMetaType::qmlType(t); - return QQmlMetaObject(type?type->baseMetaObject():0); + QQmlType type = QQmlMetaType::qmlType(t); + return QQmlMetaObject(type.baseMetaObject()); } } @@ -2390,8 +2277,8 @@ QQmlMetaObject QQmlEnginePrivate::metaObjectForType(int t) const if (iter != m_compositeTypes.cend()) { return QQmlMetaObject((*iter)->rootPropertyCache()); } else { - QQmlType *type = QQmlMetaType::qmlType(t); - return QQmlMetaObject(type?type->metaObject():0); + QQmlType type = QQmlMetaType::qmlType(t); + return QQmlMetaObject(type.metaObject()); } } @@ -2402,9 +2289,9 @@ QQmlPropertyCache *QQmlEnginePrivate::propertyCacheForType(int t) if (iter != m_compositeTypes.cend()) { return (*iter)->rootPropertyCache(); } else { - QQmlType *type = QQmlMetaType::qmlType(t); + QQmlType type = QQmlMetaType::qmlType(t); locker.unlock(); - return type?cache(type->metaObject()):0; + return type.isValid() ? cache(type.metaObject()) : 0; } } @@ -2415,54 +2302,28 @@ QQmlPropertyCache *QQmlEnginePrivate::rawPropertyCacheForType(int t) if (iter != m_compositeTypes.cend()) { return (*iter)->rootPropertyCache(); } else { - QQmlType *type = QQmlMetaType::qmlType(t); + QQmlType type = QQmlMetaType::qmlType(t); locker.unlock(); - return type?cache(type->baseMetaObject()):0; + return type.isValid() ? cache(type.baseMetaObject()) : 0; } } void QQmlEnginePrivate::registerInternalCompositeType(QV4::CompiledData::CompilationUnit *compilationUnit) { - QByteArray name = compilationUnit->rootPropertyCache()->className(); - - QByteArray ptr = name + '*'; - QByteArray lst = "QQmlListProperty<" + name + '>'; - - int ptr_type = QMetaType::registerNormalizedType(ptr, - QtMetaTypePrivate::QMetaTypeFunctionHelper<QObject*>::Destruct, - QtMetaTypePrivate::QMetaTypeFunctionHelper<QObject*>::Construct, - sizeof(QObject*), - static_cast<QFlags<QMetaType::TypeFlag> >(QtPrivate::QMetaTypeTypeFlags<QObject*>::Flags), - 0); - int lst_type = QMetaType::registerNormalizedType(lst, - QtMetaTypePrivate::QMetaTypeFunctionHelper<QQmlListProperty<QObject> >::Destruct, - QtMetaTypePrivate::QMetaTypeFunctionHelper<QQmlListProperty<QObject> >::Construct, - sizeof(QQmlListProperty<QObject>), - static_cast<QFlags<QMetaType::TypeFlag> >(QtPrivate::QMetaTypeTypeFlags<QQmlListProperty<QObject> >::Flags), - static_cast<QMetaObject*>(0)); - - compilationUnit->metaTypeId = ptr_type; - compilationUnit->listMetaTypeId = lst_type; compilationUnit->isRegisteredWithEngine = true; Locker locker(this); - m_qmlLists.insert(lst_type, ptr_type); // The QQmlCompiledData is not referenced here, but it is removed from this // hash in the QQmlCompiledData destructor - m_compositeTypes.insert(ptr_type, compilationUnit); + m_compositeTypes.insert(compilationUnit->metaTypeId, compilationUnit); } void QQmlEnginePrivate::unregisterInternalCompositeType(QV4::CompiledData::CompilationUnit *compilationUnit) { - int ptr_type = compilationUnit->metaTypeId; - int lst_type = compilationUnit->listMetaTypeId; + compilationUnit->isRegisteredWithEngine = false; Locker locker(this); - m_qmlLists.remove(lst_type); - m_compositeTypes.remove(ptr_type); - - QMetaType::unregisterType(ptr_type); - QMetaType::unregisterType(lst_type); + m_compositeTypes.remove(compilationUnit->metaTypeId); } bool QQmlEnginePrivate::isTypeLoaded(const QUrl &url) const diff --git a/src/qml/qml/qqmlengine_p.h b/src/qml/qml/qqmlengine_p.h index 1bdeacd524..da8ea24ea0 100644 --- a/src/qml/qml/qqmlengine_p.h +++ b/src/qml/qml/qqmlengine_p.h @@ -208,7 +208,7 @@ public: QString offlineStorageDatabaseDirectory() const; // These methods may be called from the loader thread - inline QQmlPropertyCache *cache(QQmlType *, int); + inline QQmlPropertyCache *cache(const QQmlType &, int); using QJSEnginePrivate::cache; // These methods may be called from the loader thread @@ -259,13 +259,8 @@ public: mutable QMutex networkAccessManagerMutex; private: - // Must be called locked - QQmlPropertyCache *createCache(QQmlType *, int); - // These members must be protected by a QQmlEnginePrivate::Locker as they are required by // the threaded loader. Only access them through their respective accessor methods. - QHash<QPair<QQmlType *, int>, QQmlPropertyCache *> typePropertyCache; - QHash<int, int> m_qmlLists; QHash<int, QV4::CompiledData::CompilationUnit *> m_compositeTypes; static bool s_designerMode; @@ -375,17 +370,15 @@ Returns a QQmlPropertyCache for \a type with \a minorVersion. The returned cache is not referenced, so if it is to be stored, call addref(). */ -QQmlPropertyCache *QQmlEnginePrivate::cache(QQmlType *type, int minorVersion) +QQmlPropertyCache *QQmlEnginePrivate::cache(const QQmlType &type, int minorVersion) { - Q_ASSERT(type); + Q_ASSERT(type.isValid()); - if (minorVersion == -1 || !type->containsRevisionedAttributes()) - return cache(type->metaObject()); + if (minorVersion == -1 || !type.containsRevisionedAttributes()) + return cache(type.metaObject()); Locker locker(this); - QQmlPropertyCache *rv = typePropertyCache.value(qMakePair(type, minorVersion)); - if (!rv) rv = createCache(type, minorVersion); - return rv; + return QQmlMetaType::propertyCache(type, minorVersion); } QV8Engine *QQmlEnginePrivate::getV8Engine(QQmlEngine *e) diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp index fc8e60e3f2..7c9dcb1826 100644 --- a/src/qml/qml/qqmlimport.cpp +++ b/src/qml/qml/qqmlimport.cpp @@ -142,13 +142,13 @@ bool isPathAbsolute(const QString &path) Errors (if there are any) are placed into \a errors, if it is nonzero. Note that errors are treated as fatal if \a errors is not set. */ -QQmlType *fetchOrCreateTypeForUrl(const QString &urlString, const QHashedStringRef& typeName, +QQmlType fetchOrCreateTypeForUrl(const QString &urlString, const QHashedStringRef& typeName, bool isCompositeSingleton, QList<QQmlError> *errors, int majorVersion=-1, int minorVersion=-1) { QUrl url(urlString); // ### unfortunate (costly) conversion - QQmlType *ret = QQmlMetaType::qmlType(url); - if (ret) + QQmlType ret = QQmlMetaType::qmlType(url); + if (ret.isValid()) return ret; int dot = typeName.indexOf(QLatin1Char('.')); @@ -183,7 +183,7 @@ QQmlType *fetchOrCreateTypeForUrl(const QString &urlString, const QHashedStringR minorVersion, buf.constData() }; - ret = QQmlMetaType::qmlTypeFromIndex(QQmlPrivate::qmlregister(QQmlPrivate::CompositeSingletonRegistration, ®)); + ret = QQmlMetaType::registerCompositeSingletonType(reg); } else { QQmlPrivate::RegisterCompositeType reg = { url, @@ -192,13 +192,13 @@ QQmlType *fetchOrCreateTypeForUrl(const QString &urlString, const QHashedStringR minorVersion, buf.constData() }; - ret = QQmlMetaType::qmlTypeFromIndex(QQmlPrivate::qmlregister(QQmlPrivate::CompositeRegistration, ®)); + ret = QQmlMetaType::registerCompositeType(reg); } // This means that the type couldn't be found by URL, but could not be // registered either, meaning we most likely were passed some kind of bad // data. - if (!ret) { + if (!ret.isValid()) { if (!errors) // Cannot list errors properly, just quit qFatal("%s", QQmlMetaType::typeRegistrationFailures().join('\n').toLatin1().constData()); QQmlError error; @@ -295,7 +295,7 @@ public: QList<QQmlError> *errors); bool resolveType(const QHashedStringRef &type, int *vmajor, int *vminor, - QQmlType** type_return, QList<QQmlError> *errors, + QQmlType* type_return, QList<QQmlError> *errors, QQmlImport::RecursionRestriction recursionRestriction = QQmlImport::PreventRecursion); QUrl baseUrl; @@ -421,13 +421,14 @@ void QQmlImports::populateCache(QQmlTypeNameCache *cache) const const QQmlImportNamespace &set = *ns; // positioning is important; we must create the namespace even if there is no module. - QQmlTypeNameCache::Import &typeimport = cache->m_namedImports[set.prefix]; + QQmlImportRef &typeimport = cache->m_namedImports[set.prefix]; typeimport.m_qualifier = set.prefix; for (int ii = set.imports.count() - 1; ii >= 0; --ii) { const QQmlImportInstance *import = set.imports.at(ii); QQmlTypeModule *module = QQmlMetaType::typeModule(import->uri, import->majversion); if (module) { + QQmlImportRef &typeimport = cache->m_namedImports[set.prefix]; typeimport.modules.append(QQmlTypeModuleVersion(module, import->minversion)); } } @@ -620,7 +621,7 @@ QString QQmlImports::versionString(int vmaj, int vmin, ImportVersion version) \sa addFileImport(), addLibraryImport */ bool QQmlImports::resolveType(const QHashedStringRef &type, - QQmlType** type_return, int *vmaj, int *vmin, + QQmlType* type_return, int *vmaj, int *vmin, QQmlImportNamespace** ns_return, QList<QQmlError> *errors, QQmlImport::RecursionRestriction recursionRestriction) const { @@ -631,17 +632,19 @@ bool QQmlImports::resolveType(const QHashedStringRef &type, return true; } if (type_return) { - if (d->resolveType(type,vmaj,vmin,type_return, errors, recursionRestriction)) { + if (d->resolveType(type, vmaj, vmin, type_return, errors, recursionRestriction)) { if (qmlImportTrace()) { #define RESOLVE_TYPE_DEBUG qDebug().nospace() << "QQmlImports(" << qPrintable(baseUrl().toString()) \ << ')' << "::resolveType: " << type.toString() << " => " - if (type_return && *type_return && (*type_return)->isCompositeSingleton()) - RESOLVE_TYPE_DEBUG << (*type_return)->typeName() << ' ' << (*type_return)->sourceUrl() << " TYPE/URL-SINGLETON"; - else if (type_return && *type_return && (*type_return)->isComposite()) - RESOLVE_TYPE_DEBUG << (*type_return)->typeName() << ' ' << (*type_return)->sourceUrl() << " TYPE/URL"; - else if (type_return && *type_return) - RESOLVE_TYPE_DEBUG << (*type_return)->typeName() << " TYPE"; + if (type_return && type_return->isValid()) { + if (type_return->isCompositeSingleton()) + RESOLVE_TYPE_DEBUG << type_return->typeName() << ' ' << type_return->sourceUrl() << " TYPE/URL-SINGLETON"; + else if (type_return->isComposite()) + RESOLVE_TYPE_DEBUG << type_return->typeName() << ' ' << type_return->sourceUrl() << " TYPE/URL"; + else + RESOLVE_TYPE_DEBUG << type_return->typeName() << " TYPE"; + } #undef RESOLVE_TYPE_DEBUG } return true; @@ -706,20 +709,20 @@ QQmlDirScripts QQmlImportInstance::getVersionedScripts(const QQmlDirScripts &qml If the return pointer is 0, the corresponding search is not done. */ -bool QQmlImports::resolveType(QQmlImportNamespace* ns, const QHashedStringRef &type, - QQmlType** type_return, int *vmaj, int *vmin) const +bool QQmlImports::resolveType(QQmlImportNamespace *ns, const QHashedStringRef &type, + QQmlType *type_return, int *vmaj, int *vmin) const { - return ns->resolveType(d->typeLoader,type,vmaj,vmin,type_return); + return ns->resolveType(d->typeLoader, type, vmaj, vmin, type_return); } bool QQmlImportInstance::resolveType(QQmlTypeLoader *typeLoader, const QHashedStringRef& type, int *vmajor, int *vminor, - QQmlType** type_return, QString *base, bool *typeRecursionDetected, + QQmlType* type_return, QString *base, bool *typeRecursionDetected, QQmlImport::RecursionRestriction recursionRestriction) const { if (majversion >= 0 && minversion >= 0) { - QQmlType *t = QQmlMetaType::qmlType(type, uri, majversion, minversion); - if (t) { + QQmlType t = QQmlMetaType::qmlType(type, uri, majversion, minversion); + if (t.isValid()) { if (vmajor) *vmajor = majversion; if (vminor) *vminor = minversion; if (type_return) @@ -769,11 +772,11 @@ bool QQmlImportInstance::resolveType(QQmlTypeLoader *typeLoader, componentUrl = resolveLocalUrl(QString(url + candidate->typeName + dotqml_string), candidate->fileName); int major = vmajor ? *vmajor : -1; int minor = vminor ? *vminor : -1; - QQmlType *returnType = fetchOrCreateTypeForUrl(componentUrl, type, isCompositeSingleton, 0, + QQmlType returnType = fetchOrCreateTypeForUrl(componentUrl, type, isCompositeSingleton, 0, major, minor); if (type_return) *type_return = returnType; - return returnType != 0; + return returnType.isValid(); } } else if (!isLibrary) { QString qmlUrl; @@ -797,10 +800,10 @@ bool QQmlImportInstance::resolveType(QQmlTypeLoader *typeLoader, if (typeRecursionDetected) *typeRecursionDetected = true; } else { - QQmlType *returnType = fetchOrCreateTypeForUrl(qmlUrl, type, false, 0); + QQmlType returnType = fetchOrCreateTypeForUrl(qmlUrl, type, false, 0); if (type_return) *type_return = returnType; - return returnType != 0; + return returnType.isValid(); } } } @@ -809,7 +812,7 @@ bool QQmlImportInstance::resolveType(QQmlTypeLoader *typeLoader, } bool QQmlImportsPrivate::resolveType(const QHashedStringRef& type, int *vmajor, int *vminor, - QQmlType** type_return, QList<QQmlError> *errors, + QQmlType* type_return, QList<QQmlError> *errors, QQmlImport::RecursionRestriction recursionRestriction) { QQmlImportNamespace *s = 0; @@ -839,12 +842,12 @@ bool QQmlImportsPrivate::resolveType(const QHashedStringRef& type, int *vmajor, } QHashedStringRef unqualifiedtype = dot < 0 ? type : QHashedStringRef(type.constData()+dot+1, type.length()-dot-1); if (s) { - if (s->resolveType(typeLoader,unqualifiedtype,vmajor,vminor,type_return, &base, errors, recursionRestriction)) + if (s->resolveType(typeLoader, unqualifiedtype, vmajor, vminor, type_return, &base, errors, recursionRestriction)) return true; if (s->imports.count() == 1 && !s->imports.at(0)->isLibrary && type_return && s != &unqualifiedset) { // qualified, and only 1 url *type_return = fetchOrCreateTypeForUrl(resolveLocalUrl(s->imports.at(0)->url, unqualifiedtype.toString() + QLatin1String(".qml")), type, false, errors); - return (*type_return != 0); + return type_return->isValid(); } } @@ -861,7 +864,7 @@ QQmlImportInstance *QQmlImportNamespace::findImport(const QString &uri) const } bool QQmlImportNamespace::resolveType(QQmlTypeLoader *typeLoader, const QHashedStringRef &type, - int *vmajor, int *vminor, QQmlType** type_return, + int *vmajor, int *vminor, QQmlType* type_return, QString *base, QList<QQmlError> *errors, QQmlImport::RecursionRestriction recursionRestriction) { diff --git a/src/qml/qml/qqmlimport_p.h b/src/qml/qml/qqmlimport_p.h index 1a50d5c16a..0b4a0e6f80 100644 --- a/src/qml/qml/qqmlimport_p.h +++ b/src/qml/qml/qqmlimport_p.h @@ -90,7 +90,7 @@ struct QQmlImportInstance static QQmlDirScripts getVersionedScripts(const QQmlDirScripts &qmldirscripts, int vmaj, int vmin); bool resolveType(QQmlTypeLoader *typeLoader, const QHashedStringRef &type, - int *vmajor, int *vminor, QQmlType** type_return, + int *vmajor, int *vminor, QQmlType* type_return, QString *base = 0, bool *typeRecursionDetected = 0, QQmlImport::RecursionRestriction recursionRestriction = QQmlImport::PreventRecursion) const; }; @@ -106,7 +106,7 @@ public: QQmlImportInstance *findImport(const QString &uri) const; bool resolveType(QQmlTypeLoader *typeLoader, const QHashedStringRef& type, - int *vmajor, int *vminor, QQmlType** type_return, + int *vmajor, int *vminor, QQmlType* type_return, QString *base = 0, QList<QQmlError> *errors = 0, QQmlImport::RecursionRestriction recursionRestriction = QQmlImport::PreventRecursion); @@ -131,14 +131,14 @@ public: QUrl baseUrl() const; bool resolveType(const QHashedStringRef &type, - QQmlType** type_return, + QQmlType *type_return, int *version_major, int *version_minor, - QQmlImportNamespace** ns_return, + QQmlImportNamespace **ns_return, QList<QQmlError> *errors = 0, QQmlImport::RecursionRestriction recursionRestriction = QQmlImport::PreventRecursion) const; - bool resolveType(QQmlImportNamespace*, + bool resolveType(QQmlImportNamespace *, const QHashedStringRef& type, - QQmlType** type_return, int *version_major, int *version_minor) const; + QQmlType *type_return, int *version_major, int *version_minor) const; bool addImplicitImport(QQmlImportDatabase *importDb, QList<QQmlError> *errors); diff --git a/src/qml/qml/qqmllist.cpp b/src/qml/qml/qqmllist.cpp index 2c71293363..71be2e82a3 100644 --- a/src/qml/qml/qqmllist.cpp +++ b/src/qml/qml/qqmllist.cpp @@ -148,7 +148,7 @@ QQmlListReference::QQmlListReference(QObject *object, const char *property, QQml d = new QQmlListReferencePrivate; d->object = object; - d->elementType = p?p->rawMetaObjectForType(listType):QQmlMetaType::qmlType(listType)->baseMetaObject(); + d->elementType = p ? p->rawMetaObjectForType(listType) : QQmlMetaType::qmlType(listType).baseMetaObject(); d->propertyType = data->propType(); void *args[] = { &d->property, 0 }; diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp index b75508e1e5..9bc35b3b52 100644 --- a/src/qml/qml/qqmlmetatype.cpp +++ b/src/qml/qml/qqmlmetatype.cpp @@ -69,18 +69,20 @@ struct QQmlMetaTypeData { QQmlMetaTypeData(); ~QQmlMetaTypeData(); - QList<QQmlType *> types; - typedef QHash<int, QQmlType *> Ids; + void registerType(QQmlTypePrivate *priv); + QList<QQmlType> types; + QSet<QQmlType> undeletableTypes; + typedef QHash<int, QQmlTypePrivate *> Ids; Ids idToType; - typedef QHash<QHashedStringRef,QQmlType *> Names; + typedef QHash<QHashedStringRef, QQmlTypePrivate *> Names; Names nameToType; - typedef QHash<QUrl, QQmlType *> Files; //For file imported composite types only + typedef QHash<QUrl, QQmlTypePrivate *> Files; //For file imported composite types only Files urlToType; Files urlToNonFileImportType; // For non-file imported composite and composite // singleton types. This way we can locate any // of them by url, even if it was registered as // a module via QQmlPrivate::RegisterCompositeType - typedef QHash<const QMetaObject *, QQmlType *> MetaObjects; + typedef QHash<const QMetaObject *, QQmlTypePrivate *> MetaObjects; MetaObjects metaObjectToType; typedef QHash<int, QQmlMetaType::StringConverter> StringConverters; StringConverters stringConverters; @@ -110,6 +112,12 @@ struct QQmlMetaTypeData QString typeRegistrationNamespace; QStringList typeRegistrationFailures; + + QHash<int, int> qmlLists; + + QHash<const QMetaObject *, QQmlPropertyCache *> propertyCaches; + QQmlPropertyCache *propertyCache(const QMetaObject *metaObject); + QQmlPropertyCache *propertyCache(const QQmlType &type, int minorVersion); }; class QQmlTypeModulePrivate @@ -126,10 +134,11 @@ public: int maxMinorVersion; bool locked; - void add(QQmlType *); + void add(QQmlTypePrivate *); + void remove(const QQmlTypePrivate *type); - QStringHash<QList<QQmlType *> > typeHash; - QList<QQmlType *> types; + typedef QStringHash<QList<QQmlTypePrivate *> > TypeHash; + TypeHash typeHash; }; Q_GLOBAL_STATIC(QQmlMetaTypeData, metaTypeData) @@ -146,15 +155,16 @@ QQmlMetaTypeData::QQmlMetaTypeData() QQmlMetaTypeData::~QQmlMetaTypeData() { - for (int i = 0; i < types.count(); ++i) - delete types.at(i); - for (TypeModules::const_iterator i = uriToModule.constBegin(), cend = uriToModule.constEnd(); i != cend; ++i) delete *i; + for (QHash<const QMetaObject *, QQmlPropertyCache *>::Iterator it = propertyCaches.begin(), end = propertyCaches.end(); + it != end; ++it) + (*it)->release(); } class QQmlTypePrivate { + Q_DISABLE_COPY(QQmlTypePrivate) public: QQmlTypePrivate(QQmlType::RegistrationType type); ~QQmlTypePrivate(); @@ -164,6 +174,7 @@ public: void insertEnums(const QMetaObject *metaObject) const; void insertEnumsFromPropertyCache(const QQmlPropertyCache *cache) const; + QAtomicInt refCount; QQmlType::RegistrationType regType; struct QQmlCppTypeData @@ -208,7 +219,7 @@ public: int listId; int revision; mutable bool containsRevisionedAttributes; - mutable QQmlType *superType; + mutable QQmlType superType; const QMetaObject *baseMetaObject; int index; @@ -221,8 +232,32 @@ public: mutable QList<QStringHash<int>*> scopedEnums; static QHash<const QMetaObject *, int> attachedPropertyIds; + + struct PropertyCacheByMinorVersion + { + PropertyCacheByMinorVersion() : cache(Q_NULLPTR), minorVersion(-1) {} + explicit PropertyCacheByMinorVersion(QQmlPropertyCache *pc, int ver) : cache(pc), minorVersion(ver) {} + QQmlPropertyCachePtr cache; + int minorVersion; + }; + QVector<PropertyCacheByMinorVersion> propertyCaches; + QQmlPropertyCache *propertyCacheForMinorVersion(int minorVersion) const; + void setPropertyCacheForMinorVersion(int minorVersion, QQmlPropertyCache *cache); }; +void QQmlMetaTypeData::registerType(QQmlTypePrivate *priv) +{ + for (int i = 0; i < types.count(); ++i) { + if (!types.at(i).isValid()) { + types[i] = QQmlType(priv); + priv->index = i; + return; + } + } + types.append(QQmlType(priv)); + priv->index = types.count() - 1; +} + void QQmlType::SingletonInstanceInfo::init(QQmlEngine *e) { QV4::ExecutionEngine *v4 = QV8Engine::getV4(e->handle()); @@ -281,8 +316,8 @@ QJSValue QQmlType::SingletonInstanceInfo::scriptApi(QQmlEngine *e) const QHash<const QMetaObject *, int> QQmlTypePrivate::attachedPropertyIds; QQmlTypePrivate::QQmlTypePrivate(QQmlType::RegistrationType type) -: regType(type), iid(0), typeId(0), listId(0), revision(0), - containsRevisionedAttributes(false), superType(0), baseMetaObject(0), +: refCount(1), regType(type), iid(0), typeId(0), listId(0), revision(0), + containsRevisionedAttributes(false), baseMetaObject(0), index(-1), isSetup(false), isEnumSetup(false), haveSuperType(false) { switch (type) { @@ -335,21 +370,23 @@ QQmlTypePrivate::~QQmlTypePrivate() } } -QQmlType::QQmlType(int index, const QQmlPrivate::RegisterInterface &interface) -: d(new QQmlTypePrivate(InterfaceType)) +QQmlType::QQmlType(QQmlMetaTypeData *data, const QQmlPrivate::RegisterInterface &interface) + : d(new QQmlTypePrivate(InterfaceType)) { d->iid = interface.iid; d->typeId = interface.typeId; d->listId = interface.listId; - d->index = index; d->isSetup = true; d->version_maj = 0; d->version_min = 0; + data->registerType(d); } -QQmlType::QQmlType(int index, const QString &elementName, const QQmlPrivate::RegisterSingletonType &type) -: d(new QQmlTypePrivate(SingletonType)) +QQmlType::QQmlType(QQmlMetaTypeData *data, const QString &elementName, const QQmlPrivate::RegisterSingletonType &type) + : d(new QQmlTypePrivate(SingletonType)) { + data->registerType(d); + d->elementName = elementName; d->module = QString::fromUtf8(type.uri); @@ -365,8 +402,6 @@ QQmlType::QQmlType(int index, const QString &elementName, const QQmlPrivate::Reg d->revision = type.revision; } - d->index = index; - d->extraData.sd->singletonInstanceInfo = new SingletonInstanceInfo; d->extraData.sd->singletonInstanceInfo->scriptCallback = type.scriptApi; d->extraData.sd->singletonInstanceInfo->qobjectCallback = type.qobjectApi; @@ -375,25 +410,27 @@ QQmlType::QQmlType(int index, const QString &elementName, const QQmlPrivate::Reg = (type.qobjectApi && type.version >= 1) ? type.instanceMetaObject : 0; } -QQmlType::QQmlType(int index, const QString &elementName, const QQmlPrivate::RegisterCompositeSingletonType &type) - : d(new QQmlTypePrivate(CompositeSingletonType)) +QQmlType::QQmlType(QQmlMetaTypeData *data, const QString &elementName, const QQmlPrivate::RegisterCompositeSingletonType &type) + : d(new QQmlTypePrivate(CompositeSingletonType)) { + data->registerType(d); + d->elementName = elementName; d->module = QString::fromUtf8(type.uri); d->version_maj = type.versionMajor; d->version_min = type.versionMinor; - d->index = index; - d->extraData.sd->singletonInstanceInfo = new SingletonInstanceInfo; d->extraData.sd->singletonInstanceInfo->url = type.url; d->extraData.sd->singletonInstanceInfo->typeName = QString::fromUtf8(type.typeName); } -QQmlType::QQmlType(int index, const QString &elementName, const QQmlPrivate::RegisterType &type) -: d(new QQmlTypePrivate(CppType)) +QQmlType::QQmlType(QQmlMetaTypeData *data, const QString &elementName, const QQmlPrivate::RegisterType &type) + : d(new QQmlTypePrivate(CppType)) { + data->registerType(d); + d->elementName = elementName; d->module = QString::fromUtf8(type.uri); @@ -412,7 +449,7 @@ QQmlType::QQmlType(int index, const QString &elementName, const QQmlPrivate::Reg if (d->extraData.cd->attachedPropertiesType) { QHash<const QMetaObject *, int>::Iterator iter = d->attachedPropertyIds.find(d->baseMetaObject); if (iter == d->attachedPropertyIds.end()) - iter = d->attachedPropertyIds.insert(d->baseMetaObject, index); + iter = d->attachedPropertyIds.insert(d->baseMetaObject, d->index); d->extraData.cd->attachedPropertiesId = *iter; } else { d->extraData.cd->attachedPropertiesId = -1; @@ -422,16 +459,16 @@ QQmlType::QQmlType(int index, const QString &elementName, const QQmlPrivate::Reg d->extraData.cd->propertyValueInterceptorCast = type.valueInterceptorCast; d->extraData.cd->extFunc = type.extensionObjectCreate; d->extraData.cd->customParser = type.customParser; - d->index = index; if (type.extensionMetaObject) d->extraData.cd->extMetaObject = type.extensionMetaObject; } -QQmlType::QQmlType(int index, const QString &elementName, const QQmlPrivate::RegisterCompositeType &type) -: d(new QQmlTypePrivate(CompositeType)) +QQmlType::QQmlType(QQmlMetaTypeData *data, const QString &elementName, const QQmlPrivate::RegisterCompositeType &type) + : d(new QQmlTypePrivate(CompositeType)) { - d->index = index; + data->registerType(d); + d->elementName = elementName; d->module = QString::fromUtf8(type.uri); @@ -441,44 +478,88 @@ QQmlType::QQmlType(int index, const QString &elementName, const QQmlPrivate::Reg d->extraData.fd->url = type.url; } +QQmlType::QQmlType() + : d(0) +{ +} + +QQmlType::QQmlType(const QQmlType &other) + : d(other.d) +{ + if (d) + d->refCount.ref(); +} + +QQmlType &QQmlType::operator =(const QQmlType &other) +{ + if (d != other.d) { + if (d && !d->refCount.deref()) + delete d; + d = other.d; + if (d) + d->refCount.ref(); + } + return *this; +} + +QQmlType::QQmlType(QQmlTypePrivate *priv) + : d(priv) +{ + if (d) + d->refCount.ref(); +} + QQmlType::~QQmlType() { - delete d; + if (d && !d->refCount.deref()) + delete d; } -const QHashedString &QQmlType::module() const +QHashedString QQmlType::module() const { + if (!d) + return QHashedString(); return d->module; } int QQmlType::majorVersion() const { + if (!d) + return -1; return d->version_maj; } int QQmlType::minorVersion() const { + if (!d) + return -1; return d->version_min; } bool QQmlType::availableInVersion(int vmajor, int vminor) const { Q_ASSERT(vmajor >= 0 && vminor >= 0); + if (!d) + return false; return vmajor == d->version_maj && vminor >= d->version_min; } bool QQmlType::availableInVersion(const QHashedStringRef &module, int vmajor, int vminor) const { Q_ASSERT(vmajor >= 0 && vminor >= 0); + if (!d) + return false; return module == d->module && vmajor == d->version_maj && vminor >= d->version_min; } // returns the nearest _registered_ super class -QQmlType *QQmlType::superType() const +QQmlType QQmlType::superType() const { + if (!d) + return QQmlType(); if (!d->haveSuperType && d->baseMetaObject) { const QMetaObject *mo = d->baseMetaObject->superClass(); - while (mo && !d->superType) { + while (mo && !d->superType.isValid()) { d->superType = QQmlMetaType::qmlType(mo, d->module, d->version_maj, d->version_min); mo = mo->superClass(); } @@ -488,14 +569,14 @@ QQmlType *QQmlType::superType() const return d->superType; } -QQmlType *QQmlType::resolveCompositeBaseType(QQmlEnginePrivate *engine) const +QQmlType QQmlType::resolveCompositeBaseType(QQmlEnginePrivate *engine) const { Q_ASSERT(isComposite()); - if (!engine) - return 0; + if (!engine || !d) + return QQmlType(); QQmlRefPointer<QQmlTypeData> td(engine->typeLoader.getType(sourceUrl()), QQmlRefPointer<QQmlTypeData>::Adopt); if (td.isNull() || !td->isComplete()) - return 0; + return QQmlType(); QV4::CompiledData::CompilationUnit *compilationUnit = td->compilationUnit(); const QMetaObject *mo = compilationUnit->rootPropertyCache()->firstCppMetaObject(); return QQmlMetaType::qmlType(mo); @@ -631,18 +712,18 @@ void QQmlTypePrivate::init() const mo = mo->d.superdata; while(mo) { - QQmlType *t = metaTypeData()->metaObjectToType.value(mo); + QQmlTypePrivate *t = metaTypeData()->metaObjectToType.value(mo); if (t) { - if (t->d->regType == QQmlType::CppType) { - if (t->d->extraData.cd->extFunc) { + if (t->regType == QQmlType::CppType) { + if (t->extraData.cd->extFunc) { QMetaObjectBuilder builder; - clone(builder, t->d->extraData.cd->extMetaObject, t->d->baseMetaObject, baseMetaObject); + clone(builder, t->extraData.cd->extMetaObject, t->baseMetaObject, baseMetaObject); builder.setFlags(QMetaObjectBuilder::DynamicMetaObject); QMetaObject *mmo = builder.toMetaObject(); mmo->d.superdata = baseMetaObject; if (!metaObjects.isEmpty()) metaObjects.constLast().metaObject->d.superdata = mmo; - QQmlProxyMetaObject::ProxyData data = { mmo, t->d->extraData.cd->extFunc, 0, 0 }; + QQmlProxyMetaObject::ProxyData data = { mmo, t->extraData.cd->extFunc, 0, 0 }; metaObjects << data; } } @@ -754,23 +835,47 @@ void QQmlTypePrivate::insertEnumsFromPropertyCache(const QQmlPropertyCache *cach } +QQmlPropertyCache *QQmlTypePrivate::propertyCacheForMinorVersion(int minorVersion) const +{ + for (int i = 0; i < propertyCaches.count(); ++i) + if (propertyCaches.at(i).minorVersion == minorVersion) + return propertyCaches.at(i).cache; + return Q_NULLPTR; +} + +void QQmlTypePrivate::setPropertyCacheForMinorVersion(int minorVersion, QQmlPropertyCache *cache) +{ + for (int i = 0; i < propertyCaches.count(); ++i) { + if (propertyCaches.at(i).minorVersion == minorVersion) { + propertyCaches[i].cache = cache; + return; + } + } + propertyCaches.append(PropertyCacheByMinorVersion(cache, minorVersion)); +} + QByteArray QQmlType::typeName() const { - if (d->regType == SingletonType || d->regType == CompositeSingletonType) - return d->extraData.sd->singletonInstanceInfo->typeName.toUtf8(); - else if (d->baseMetaObject) - return d->baseMetaObject->className(); - else - return QByteArray(); + if (d) { + if (d->regType == SingletonType || d->regType == CompositeSingletonType) + return d->extraData.sd->singletonInstanceInfo->typeName.toUtf8(); + else if (d->baseMetaObject) + return d->baseMetaObject->className(); + } + return QByteArray(); } -const QString &QQmlType::elementName() const +QString QQmlType::elementName() const { + if (!d) + return QString(); return d->elementName; } -const QString &QQmlType::qmlTypeName() const +QString QQmlType::qmlTypeName() const { + if (!d) + return QString(); if (d->name.isEmpty()) { if (!d->module.isEmpty()) d->name = static_cast<QString>(d->module) + QLatin1Char('/') + d->elementName; @@ -783,7 +888,7 @@ const QString &QQmlType::qmlTypeName() const QObject *QQmlType::create() const { - if (!isCreatable()) + if (!d || !isCreatable()) return 0; d->init(); @@ -799,7 +904,7 @@ QObject *QQmlType::create() const void QQmlType::create(QObject **out, void **memory, size_t additionalMemory) const { - if (!isCreatable()) + if (!d || !isCreatable()) return; d->init(); @@ -816,6 +921,8 @@ void QQmlType::create(QObject **out, void **memory, size_t additionalMemory) con QQmlType::SingletonInstanceInfo *QQmlType::singletonInstanceInfo() const { + if (!d) + return 0; if (d->regType != SingletonType && d->regType != CompositeSingletonType) return 0; return d->extraData.sd->singletonInstanceInfo; @@ -823,6 +930,8 @@ QQmlType::SingletonInstanceInfo *QQmlType::singletonInstanceInfo() const QQmlCustomParser *QQmlType::customParser() const { + if (!d) + return 0; if (d->regType != CppType) return 0; return d->extraData.cd->customParser; @@ -830,32 +939,34 @@ QQmlCustomParser *QQmlType::customParser() const QQmlType::CreateFunc QQmlType::createFunction() const { - if (d->regType != CppType) + if (!d || d->regType != CppType) return 0; return d->extraData.cd->newFunc; } QString QQmlType::noCreationReason() const { - if (d->regType != CppType) + if (!d || d->regType != CppType) return QString(); return d->extraData.cd->noCreationReason; } int QQmlType::createSize() const { - if (d->regType != CppType) + if (!d || d->regType != CppType) return 0; return d->extraData.cd->allocationSize; } bool QQmlType::isCreatable() const { - return d->regType == CppType && d->extraData.cd->newFunc; + return d && d->regType == CppType && d->extraData.cd->newFunc; } bool QQmlType::isExtendedType() const { + if (!d) + return false; d->init(); return !d->metaObjects.isEmpty(); @@ -863,36 +974,38 @@ bool QQmlType::isExtendedType() const bool QQmlType::isSingleton() const { - return d->regType == SingletonType || d->regType == CompositeSingletonType; + return d && (d->regType == SingletonType || d->regType == CompositeSingletonType); } bool QQmlType::isInterface() const { - return d->regType == InterfaceType; + return d && d->regType == InterfaceType; } bool QQmlType::isComposite() const { - return d->regType == CompositeType || d->regType == CompositeSingletonType; + return d && (d->regType == CompositeType || d->regType == CompositeSingletonType); } bool QQmlType::isCompositeSingleton() const { - return d->regType == CompositeSingletonType; + return d && d->regType == CompositeSingletonType; } int QQmlType::typeId() const { - return d->typeId; + return d ? d->typeId : -1; } int QQmlType::qListTypeId() const { - return d->listId; + return d ? d->listId : -1; } const QMetaObject *QQmlType::metaObject() const { + if (!d) + return 0; d->init(); if (d->metaObjects.isEmpty()) @@ -904,11 +1017,13 @@ const QMetaObject *QQmlType::metaObject() const const QMetaObject *QQmlType::baseMetaObject() const { - return d->baseMetaObject; + return d ? d->baseMetaObject : 0; } bool QQmlType::containsRevisionedAttributes() const { + if (!d) + return false; d->init(); return d->containsRevisionedAttributes; @@ -916,29 +1031,33 @@ bool QQmlType::containsRevisionedAttributes() const int QQmlType::metaObjectRevision() const { - return d->revision; + return d ? d->revision : -1; } QQmlAttachedPropertiesFunc QQmlType::attachedPropertiesFunction(QQmlEnginePrivate *engine) const { + if (!d) + return 0; if (d->regType == CppType) return d->extraData.cd->attachedPropertiesFunc; - QQmlType *base = 0; + QQmlType base; if (d->regType == CompositeType) base = resolveCompositeBaseType(engine); - return base ? base->attachedPropertiesFunction(engine) : 0; + return base.attachedPropertiesFunction(engine); } const QMetaObject *QQmlType::attachedPropertiesType(QQmlEnginePrivate *engine) const { + if (!d) + return 0; if (d->regType == CppType) return d->extraData.cd->attachedPropertiesType; - QQmlType *base = 0; + QQmlType base; if (d->regType == CompositeType) base = resolveCompositeBaseType(engine); - return base ? base->attachedPropertiesType(engine) : 0; + return base.attachedPropertiesType(engine); } /* @@ -948,70 +1067,75 @@ Qt 4.7 and QtQuick 1.0). */ int QQmlType::attachedPropertiesId(QQmlEnginePrivate *engine) const { + if (!d) + return -1; if (d->regType == CppType) return d->extraData.cd->attachedPropertiesId; - QQmlType *base = 0; + QQmlType base; if (d->regType == CompositeType) base = resolveCompositeBaseType(engine); - return base ? base->attachedPropertiesId(engine) : 0; + return base.attachedPropertiesId(engine); } int QQmlType::parserStatusCast() const { - if (d->regType != CppType) + if (!d || d->regType != CppType) return -1; return d->extraData.cd->parserStatusCast; } int QQmlType::propertyValueSourceCast() const { - if (d->regType != CppType) + if (!d || d->regType != CppType) return -1; return d->extraData.cd->propertyValueSourceCast; } int QQmlType::propertyValueInterceptorCast() const { - if (d->regType != CppType) + if (!d || d->regType != CppType) return -1; return d->extraData.cd->propertyValueInterceptorCast; } const char *QQmlType::interfaceIId() const { - if (d->regType != InterfaceType) + if (!d || d->regType != InterfaceType) return 0; return d->iid; } int QQmlType::index() const { - return d->index; + return d ? d->index : -1; } QUrl QQmlType::sourceUrl() const { - if (d->regType == CompositeType) - return d->extraData.fd->url; - else if (d->regType == CompositeSingletonType) - return d->extraData.sd->singletonInstanceInfo->url; - else - return QUrl(); + if (d) { + if (d->regType == CompositeType) + return d->extraData.fd->url; + else if (d->regType == CompositeSingletonType) + return d->extraData.sd->singletonInstanceInfo->url; + } + return QUrl(); } int QQmlType::enumValue(QQmlEnginePrivate *engine, const QHashedStringRef &name, bool *ok) const { Q_ASSERT(ok); - const QQmlPropertyCache *cache = isComposite() ? compositePropertyCache(engine) : 0; + if (d) { + const QQmlPropertyCache *cache = isComposite() ? compositePropertyCache(engine) : 0; - *ok = true; + *ok = true; - d->initEnums(cache); + d->initEnums(cache); - int *rv = d->enums.value(name); - if (rv) - return *rv; + int *rv = d->enums.value(name); + if (rv) + return *rv; + } *ok = false; return -1; @@ -1020,15 +1144,17 @@ int QQmlType::enumValue(QQmlEnginePrivate *engine, const QHashedStringRef &name, int QQmlType::enumValue(QQmlEnginePrivate *engine, const QHashedCStringRef &name, bool *ok) const { Q_ASSERT(ok); - const QQmlPropertyCache *cache = isComposite() ? compositePropertyCache(engine) : 0; + if (d) { + const QQmlPropertyCache *cache = isComposite() ? compositePropertyCache(engine) : 0; - *ok = true; + *ok = true; - d->initEnums(cache); + d->initEnums(cache); - int *rv = d->enums.value(name); - if (rv) - return *rv; + int *rv = d->enums.value(name); + if (rv) + return *rv; + } *ok = false; return -1; @@ -1037,14 +1163,16 @@ int QQmlType::enumValue(QQmlEnginePrivate *engine, const QHashedCStringRef &name int QQmlType::enumValue(QQmlEnginePrivate *engine, const QV4::String *name, bool *ok) const { Q_ASSERT(ok); - const QQmlPropertyCache *cache = isComposite() ? compositePropertyCache(engine) : 0; - *ok = true; + if (d) { + const QQmlPropertyCache *cache = isComposite() ? compositePropertyCache(engine) : 0; + *ok = true; - d->initEnums(cache); + d->initEnums(cache); - int *rv = d->enums.value(name); - if (rv) - return *rv; + int *rv = d->enums.value(name); + if (rv) + return *rv; + } *ok = false; return -1; @@ -1053,14 +1181,16 @@ int QQmlType::enumValue(QQmlEnginePrivate *engine, const QV4::String *name, bool int QQmlType::scopedEnumIndex(QQmlEnginePrivate *engine, const QV4::String *name, bool *ok) const { Q_ASSERT(ok); - const QQmlPropertyCache *cache = isComposite() ? compositePropertyCache(engine) : 0; - *ok = true; + if (d) { + const QQmlPropertyCache *cache = isComposite() ? compositePropertyCache(engine) : 0; + *ok = true; - d->initEnums(cache); + d->initEnums(cache); - int *rv = d->scopedEnumIndex.value(name); - if (rv) - return *rv; + int *rv = d->scopedEnumIndex.value(name); + if (rv) + return *rv; + } *ok = false; return -1; @@ -1069,14 +1199,16 @@ int QQmlType::scopedEnumIndex(QQmlEnginePrivate *engine, const QV4::String *name int QQmlType::scopedEnumIndex(QQmlEnginePrivate *engine, const QString &name, bool *ok) const { Q_ASSERT(ok); - const QQmlPropertyCache *cache = isComposite() ? compositePropertyCache(engine) : 0; - *ok = true; + if (d) { + const QQmlPropertyCache *cache = isComposite() ? compositePropertyCache(engine) : 0; + *ok = true; - d->initEnums(cache); + d->initEnums(cache); - int *rv = d->scopedEnumIndex.value(name); - if (rv) - return *rv; + int *rv = d->scopedEnumIndex.value(name); + if (rv) + return *rv; + } *ok = false; return -1; @@ -1088,10 +1220,12 @@ int QQmlType::scopedEnumValue(QQmlEnginePrivate *engine, int index, const QV4::S Q_ASSERT(ok); *ok = true; - Q_ASSERT(index > -1 && index < d->scopedEnums.count()); - int *rv = d->scopedEnums.at(index)->value(name); - if (rv) - return *rv; + if (d) { + Q_ASSERT(index > -1 && index < d->scopedEnums.count()); + int *rv = d->scopedEnums.at(index)->value(name); + if (rv) + return *rv; + } *ok = false; return -1; @@ -1103,10 +1237,12 @@ int QQmlType::scopedEnumValue(QQmlEnginePrivate *engine, int index, const QStrin Q_ASSERT(ok); *ok = true; - Q_ASSERT(index > -1 && index < d->scopedEnums.count()); - int *rv = d->scopedEnums.at(index)->value(name); - if (rv) - return *rv; + if (d) { + Q_ASSERT(index > -1 && index < d->scopedEnums.count()); + int *rv = d->scopedEnums.at(index)->value(name); + if (rv) + return *rv; + } *ok = false; return -1; @@ -1115,18 +1251,20 @@ int QQmlType::scopedEnumValue(QQmlEnginePrivate *engine, int index, const QStrin int QQmlType::scopedEnumValue(QQmlEnginePrivate *engine, const QByteArray &scopedEnumName, const QByteArray &name, bool *ok) const { Q_ASSERT(ok); - const QQmlPropertyCache *cache = isComposite() ? compositePropertyCache(engine) : 0; - *ok = true; - - d->initEnums(cache); - - int *rv = d->scopedEnumIndex.value(QHashedCStringRef(scopedEnumName.constData(), scopedEnumName.length())); - if (rv) { - int index = *rv; - Q_ASSERT(index > -1 && index < d->scopedEnums.count()); - rv = d->scopedEnums.at(index)->value(QHashedCStringRef(name.constData(), name.length())); - if (rv) - return *rv; + if (d) { + const QQmlPropertyCache *cache = isComposite() ? compositePropertyCache(engine) : 0; + *ok = true; + + d->initEnums(cache); + + int *rv = d->scopedEnumIndex.value(QHashedCStringRef(scopedEnumName.constData(), scopedEnumName.length())); + if (rv) { + int index = *rv; + Q_ASSERT(index > -1 && index < d->scopedEnums.count()); + rv = d->scopedEnums.at(index)->value(QHashedCStringRef(name.constData(), name.length())); + if (rv) + return *rv; + } } *ok = false; @@ -1136,24 +1274,59 @@ int QQmlType::scopedEnumValue(QQmlEnginePrivate *engine, const QByteArray &scope int QQmlType::scopedEnumValue(QQmlEnginePrivate *engine, const QStringRef &scopedEnumName, const QStringRef &name, bool *ok) const { Q_ASSERT(ok); - const QQmlPropertyCache *cache = isComposite() ? compositePropertyCache(engine) : 0; - *ok = true; - - d->initEnums(cache); - - int *rv = d->scopedEnumIndex.value(QHashedStringRef(scopedEnumName)); - if (rv) { - int index = *rv; - Q_ASSERT(index > -1 && index < d->scopedEnums.count()); - rv = d->scopedEnums.at(index)->value(QHashedStringRef(name)); - if (rv) - return *rv; + if (d) { + const QQmlPropertyCache *cache = isComposite() ? compositePropertyCache(engine) : 0; + *ok = true; + + d->initEnums(cache); + + int *rv = d->scopedEnumIndex.value(QHashedStringRef(scopedEnumName)); + if (rv) { + int index = *rv; + Q_ASSERT(index > -1 && index < d->scopedEnums.count()); + rv = d->scopedEnums.at(index)->value(QHashedStringRef(name)); + if (rv) + return *rv; + } } *ok = false; return -1; } +void QQmlType::refHandle(QQmlTypePrivate *priv) +{ + if (priv) + priv->refCount.ref(); +} + +void QQmlType::derefHandle(QQmlTypePrivate *priv) +{ + if (priv && !priv->refCount.deref()) + delete priv; +} + +namespace { +template <typename QQmlTypeContainer> +void removeQQmlTypePrivate(QQmlTypeContainer &container, const QQmlTypePrivate *reference) +{ + for (typename QQmlTypeContainer::iterator it = container.begin(); it != container.end();) { + if (*it == reference) + it = container.erase(it); + else + ++it; + } +} + +struct IsQQmlTypePrivate +{ + const QQmlTypePrivate *reference; + explicit IsQQmlTypePrivate(const QQmlTypePrivate *ref) : reference(ref) {} + + bool operator()(const QQmlTypePrivate *priv) const { return reference == priv; } +}; +} + QQmlTypeModule::QQmlTypeModule() : d(new QQmlTypeModulePrivate) { @@ -1184,14 +1357,16 @@ int QQmlTypeModule::maximumMinorVersion() const return d->maxMinorVersion; } -void QQmlTypeModulePrivate::add(QQmlType *type) +void QQmlTypeModulePrivate::add(QQmlTypePrivate *type) { - minMinorVersion = qMin(minMinorVersion, type->minorVersion()); - maxMinorVersion = qMax(maxMinorVersion, type->minorVersion()); + int minVersion = type->version_min; + minMinorVersion = qMin(minMinorVersion, minVersion); + maxMinorVersion = qMax(maxMinorVersion, minVersion); - QList<QQmlType *> &list = typeHash[type->elementName()]; + QList<QQmlTypePrivate *> &list = typeHash[type->elementName]; for (int ii = 0; ii < list.count(); ++ii) { - if (list.at(ii)->minorVersion() < type->minorVersion()) { + Q_ASSERT(list.at(ii)); + if (list.at(ii)->version_min < minVersion) { list.insert(ii, type); return; } @@ -1199,46 +1374,50 @@ void QQmlTypeModulePrivate::add(QQmlType *type) list.append(type); } -QQmlType *QQmlTypeModule::type(const QHashedStringRef &name, int minor) const +void QQmlTypeModulePrivate::remove(const QQmlTypePrivate *type) { - QMutexLocker lock(metaTypeDataLock()); + for (TypeHash::ConstIterator elementIt = typeHash.begin(); elementIt != typeHash.end();) { + QList<QQmlTypePrivate *> &list = typeHash[elementIt.key()]; - QList<QQmlType *> *types = d->typeHash.value(name); - if (!types) return 0; + removeQQmlTypePrivate(list, type); - for (int ii = 0; ii < types->count(); ++ii) - if (types->at(ii)->minorVersion() <= minor) - return types->at(ii); - - return 0; +#if 0 + if (list.isEmpty()) + elementIt = typeHash.erase(elementIt); + else + ++elementIt; +#else + ++elementIt; +#endif + } } -QQmlType *QQmlTypeModule::type(const QV4::String *name, int minor) const +QQmlType QQmlTypeModule::type(const QHashedStringRef &name, int minor) const { QMutexLocker lock(metaTypeDataLock()); - QList<QQmlType *> *types = d->typeHash.value(name); - if (!types) return 0; - - for (int ii = 0; ii < types->count(); ++ii) - if (types->at(ii)->minorVersion() <= minor) - return types->at(ii); + QList<QQmlTypePrivate *> *types = d->typeHash.value(name); + if (types) { + for (int ii = 0; ii < types->count(); ++ii) + if (types->at(ii)->version_min <= minor) + return QQmlType(types->at(ii)); + } - return 0; + return QQmlType(); } -QList<QQmlType*> QQmlTypeModule::singletonTypes(int minor) const +QQmlType QQmlTypeModule::type(const QV4::String *name, int minor) const { QMutexLocker lock(metaTypeDataLock()); - QList<QQmlType *> retn; - for (int ii = 0; ii < d->types.count(); ++ii) { - QQmlType *curr = d->types.at(ii); - if (curr->isSingleton() && curr->minorVersion() <= minor) - retn.append(curr); + QList<QQmlTypePrivate *> *types = d->typeHash.value(name); + if (types) { + for (int ii = 0; ii < types->count(); ++ii) + if (types->at(ii)->version_min <= minor) + return QQmlType(types->at(ii)); } - return retn; + return QQmlType(); } QQmlTypeModuleVersion::QQmlTypeModuleVersion() @@ -1275,16 +1454,18 @@ int QQmlTypeModuleVersion::minorVersion() const return m_minor; } -QQmlType *QQmlTypeModuleVersion::type(const QHashedStringRef &name) const +QQmlType QQmlTypeModuleVersion::type(const QHashedStringRef &name) const { - if (m_module) return m_module->type(name, m_minor); - else return 0; + if (!m_module) + return QQmlType(); + return m_module->type(name, m_minor); } -QQmlType *QQmlTypeModuleVersion::type(const QV4::String *name) const +QQmlType QQmlTypeModuleVersion::type(const QV4::String *name) const { - if (m_module) return m_module->type(name, m_minor); - else return 0; + if (!m_module) + return QQmlType(); + return m_module->type(name, m_minor); } void qmlClearTypeRegistrations() // Declared in qqml.h @@ -1293,9 +1474,6 @@ void qmlClearTypeRegistrations() // Declared in qqml.h QMutexLocker lock(metaTypeDataLock()); QQmlMetaTypeData *data = metaTypeData(); - for (int i = 0; i < data->types.count(); ++i) - delete data->types.at(i); - for (QQmlMetaTypeData::TypeModules::const_iterator i = data->uriToModule.constBegin(), cend = data->uriToModule.constEnd(); i != cend; ++i) delete *i; @@ -1313,7 +1491,7 @@ void qmlClearTypeRegistrations() // Declared in qqml.h #endif } -int registerAutoParentFunction(QQmlPrivate::RegisterAutoParent &autoparent) +static int registerAutoParentFunction(QQmlPrivate::RegisterAutoParent &autoparent) { QMutexLocker lock(metaTypeDataLock()); QQmlMetaTypeData *data = metaTypeData(); @@ -1323,7 +1501,7 @@ int registerAutoParentFunction(QQmlPrivate::RegisterAutoParent &autoparent) return data->parentFunctions.count() - 1; } -int registerInterface(const QQmlPrivate::RegisterInterface &interface) +QQmlType registerInterface(const QQmlPrivate::RegisterInterface &interface) { if (interface.version > 0) qFatal("qmlRegisterType(): Cannot mix incompatible QML versions."); @@ -1331,16 +1509,15 @@ int registerInterface(const QQmlPrivate::RegisterInterface &interface) QMutexLocker lock(metaTypeDataLock()); QQmlMetaTypeData *data = metaTypeData(); - int index = data->types.count(); + QQmlType type(data, interface); + QQmlTypePrivate *priv = type.priv(); + Q_ASSERT(priv); - QQmlType *type = new QQmlType(index, interface); - - data->types.append(type); - data->idToType.insert(type->typeId(), type); - data->idToType.insert(type->qListTypeId(), type); + data->idToType.insert(priv->typeId, priv); + data->idToType.insert(priv->listId, priv); // XXX No insertMulti, so no multi-version interfaces? - if (!type->elementName().isEmpty()) - data->nameToType.insert(type->elementName(), type); + if (!priv->elementName.isEmpty()) + data->nameToType.insert(priv->elementName, priv); if (data->interfaces.size() <= interface.typeId) data->interfaces.resize(interface.typeId + 16); @@ -1349,7 +1526,7 @@ int registerInterface(const QQmlPrivate::RegisterInterface &interface) data->interfaces.setBit(interface.typeId, true); data->lists.setBit(interface.listId, true); - return index; + return type; } QString registrationTypeString(QQmlType::RegistrationType typeType) @@ -1431,76 +1608,72 @@ QQmlTypeModule *getTypeModule(const QHashedString &uri, int majorVersion, QQmlMe } // NOTE: caller must hold a QMutexLocker on "data" -void addTypeToData(QQmlType* type, QQmlMetaTypeData *data) +void addTypeToData(QQmlTypePrivate *type, QQmlMetaTypeData *data) { - if (!type->elementName().isEmpty()) - data->nameToType.insertMulti(type->elementName(), type); + Q_ASSERT(type); + + if (!type->elementName.isEmpty()) + data->nameToType.insertMulti(type->elementName, type); - if (type->baseMetaObject()) - data->metaObjectToType.insertMulti(type->baseMetaObject(), type); + if (type->baseMetaObject) + data->metaObjectToType.insertMulti(type->baseMetaObject, type); - if (type->typeId()) { - data->idToType.insert(type->typeId(), type); - if (data->objects.size() <= type->typeId()) - data->objects.resize(type->typeId() + 16); - data->objects.setBit(type->typeId(), true); + if (type->typeId) { + data->idToType.insert(type->typeId, type); + if (data->objects.size() <= type->typeId) + data->objects.resize(type->typeId + 16); + data->objects.setBit(type->typeId, true); } - if (type->qListTypeId()) { - if (data->lists.size() <= type->qListTypeId()) - data->lists.resize(type->qListTypeId() + 16); - data->lists.setBit(type->qListTypeId(), true); - data->idToType.insert(type->qListTypeId(), type); + if (type->listId) { + if (data->lists.size() <= type->listId) + data->lists.resize(type->listId + 16); + data->lists.setBit(type->listId, true); + data->idToType.insert(type->listId, type); } - if (!type->module().isEmpty()) { - const QHashedString &mod = type->module(); + if (!type->module.isEmpty()) { + const QHashedString &mod = type->module; - QQmlTypeModule *module = getTypeModule(mod, type->majorVersion(), data); + QQmlTypeModule *module = getTypeModule(mod, type->version_maj, data); Q_ASSERT(module); module->d->add(type); } } -int registerType(const QQmlPrivate::RegisterType &type) +QQmlType registerType(const QQmlPrivate::RegisterType &type) { QMutexLocker lock(metaTypeDataLock()); QQmlMetaTypeData *data = metaTypeData(); QString elementName = QString::fromUtf8(type.elementName); if (!checkRegistration(QQmlType::CppType, data, type.uri, elementName, type.versionMajor)) - return -1; - - int index = data->types.count(); + return QQmlType(); - QQmlType *dtype = new QQmlType(index, elementName, type); + QQmlType dtype(data, elementName, type); - data->types.append(dtype); - addTypeToData(dtype, data); + addTypeToData(dtype.priv(), data); if (!type.typeId) - data->idToType.insert(dtype->typeId(), dtype); + data->idToType.insert(dtype.typeId(), dtype.priv()); - return index; + return dtype; } -int registerSingletonType(const QQmlPrivate::RegisterSingletonType &type) +QQmlType registerSingletonType(const QQmlPrivate::RegisterSingletonType &type) { QMutexLocker lock(metaTypeDataLock()); QQmlMetaTypeData *data = metaTypeData(); QString typeName = QString::fromUtf8(type.typeName); if (!checkRegistration(QQmlType::SingletonType, data, type.uri, typeName, type.versionMajor)) - return -1; - - int index = data->types.count(); + return QQmlType(); - QQmlType *dtype = new QQmlType(index, typeName, type); + QQmlType dtype(data, typeName, type); - data->types.append(dtype); - addTypeToData(dtype, data); + addTypeToData(dtype.priv(), data); - return index; + return dtype; } -int registerCompositeSingletonType(const QQmlPrivate::RegisterCompositeSingletonType &type) +QQmlType QQmlMetaType::registerCompositeSingletonType(const QQmlPrivate::RegisterCompositeSingletonType &type) { // Assumes URL is absolute and valid. Checking of user input should happen before the URL enters type. QMutexLocker lock(metaTypeDataLock()); @@ -1510,22 +1683,19 @@ int registerCompositeSingletonType(const QQmlPrivate::RegisterCompositeSingleton if (*(type.uri) == '\0') fileImport = true; if (!checkRegistration(QQmlType::CompositeSingletonType, data, fileImport ? 0 : type.uri, typeName)) - return -1; - - int index = data->types.count(); + return QQmlType(); - QQmlType *dtype = new QQmlType(index, typeName, type); + QQmlType dtype(data, typeName, type); - data->types.append(dtype); - addTypeToData(dtype, data); + addTypeToData(dtype.priv(), data); QQmlMetaTypeData::Files *files = fileImport ? &(data->urlToType) : &(data->urlToNonFileImportType); - files->insertMulti(type.url, dtype); + files->insertMulti(type.url, dtype.priv()); - return index; + return dtype; } -int registerCompositeType(const QQmlPrivate::RegisterCompositeType &type) +QQmlType QQmlMetaType::registerCompositeType(const QQmlPrivate::RegisterCompositeType &type) { // Assumes URL is absolute and valid. Checking of user input should happen before the URL enters type. QMutexLocker lock(metaTypeDataLock()); @@ -1535,18 +1705,56 @@ int registerCompositeType(const QQmlPrivate::RegisterCompositeType &type) if (*(type.uri) == '\0') fileImport = true; if (!checkRegistration(QQmlType::CompositeType, data, fileImport?0:type.uri, typeName, type.versionMajor)) - return -1; - - int index = data->types.count(); + return QQmlType(); - QQmlType *dtype = new QQmlType(index, typeName, type); - data->types.append(dtype); - addTypeToData(dtype, data); + QQmlType dtype(data, typeName, type); + addTypeToData(dtype.priv(), data); QQmlMetaTypeData::Files *files = fileImport ? &(data->urlToType) : &(data->urlToNonFileImportType); - files->insertMulti(type.url, dtype); + files->insertMulti(type.url, dtype.priv()); - return index; + return dtype; +} + +void QQmlMetaType::registerInternalCompositeType(QV4::CompiledData::CompilationUnit *compilationUnit) +{ + QByteArray name = compilationUnit->rootPropertyCache()->className(); + + QByteArray ptr = name + '*'; + QByteArray lst = "QQmlListProperty<" + name + '>'; + + int ptr_type = QMetaType::registerNormalizedType(ptr, + QtMetaTypePrivate::QMetaTypeFunctionHelper<QObject*>::Destruct, + QtMetaTypePrivate::QMetaTypeFunctionHelper<QObject*>::Construct, + sizeof(QObject*), + static_cast<QFlags<QMetaType::TypeFlag> >(QtPrivate::QMetaTypeTypeFlags<QObject*>::Flags), + 0); + int lst_type = QMetaType::registerNormalizedType(lst, + QtMetaTypePrivate::QMetaTypeFunctionHelper<QQmlListProperty<QObject> >::Destruct, + QtMetaTypePrivate::QMetaTypeFunctionHelper<QQmlListProperty<QObject> >::Construct, + sizeof(QQmlListProperty<QObject>), + static_cast<QFlags<QMetaType::TypeFlag> >(QtPrivate::QMetaTypeTypeFlags<QQmlListProperty<QObject> >::Flags), + static_cast<QMetaObject*>(0)); + + compilationUnit->metaTypeId = ptr_type; + compilationUnit->listMetaTypeId = lst_type; + + QMutexLocker lock(metaTypeDataLock()); + QQmlMetaTypeData *d = metaTypeData(); + d->qmlLists.insert(lst_type, ptr_type); +} + +void QQmlMetaType::unregisterInternalCompositeType(QV4::CompiledData::CompilationUnit *compilationUnit) +{ + int ptr_type = compilationUnit->metaTypeId; + int lst_type = compilationUnit->listMetaTypeId; + + QMutexLocker lock(metaTypeDataLock()); + QQmlMetaTypeData *d = metaTypeData(); + d->qmlLists.remove(lst_type); + + QMetaType::unregisterType(ptr_type); + QMetaType::unregisterType(lst_type); } int registerQmlUnitCacheHook(const QQmlPrivate::RegisterQmlUnitCacheHook &hookRegistration) @@ -1565,22 +1773,30 @@ the future without adding exported symbols. */ int QQmlPrivate::qmlregister(RegistrationType type, void *data) { - if (type == TypeRegistration) { - return registerType(*reinterpret_cast<RegisterType *>(data)); - } else if (type == InterfaceRegistration) { - return registerInterface(*reinterpret_cast<RegisterInterface *>(data)); - } else if (type == AutoParentRegistration) { + if (type == AutoParentRegistration) return registerAutoParentFunction(*reinterpret_cast<RegisterAutoParent *>(data)); - } else if (type == SingletonRegistration) { - return registerSingletonType(*reinterpret_cast<RegisterSingletonType *>(data)); - } else if (type == CompositeRegistration) { - return registerCompositeType(*reinterpret_cast<RegisterCompositeType *>(data)); - } else if (type == CompositeSingletonRegistration) { - return registerCompositeSingletonType(*reinterpret_cast<RegisterCompositeSingletonType *>(data)); - } else if (type == QmlUnitCacheHookRegistration) { + else if (type == QmlUnitCacheHookRegistration) return registerQmlUnitCacheHook(*reinterpret_cast<RegisterQmlUnitCacheHook *>(data)); - } - return -1; + + QQmlType dtype; + if (type == TypeRegistration) + dtype = registerType(*reinterpret_cast<RegisterType *>(data)); + else if (type == InterfaceRegistration) + dtype = registerInterface(*reinterpret_cast<RegisterInterface *>(data)); + else if (type == SingletonRegistration) + dtype = registerSingletonType(*reinterpret_cast<RegisterSingletonType *>(data)); + else if (type == CompositeRegistration) + dtype = QQmlMetaType::registerCompositeType(*reinterpret_cast<RegisterCompositeType *>(data)); + else if (type == CompositeSingletonRegistration) + dtype = QQmlMetaType::registerCompositeSingletonType(*reinterpret_cast<RegisterCompositeSingletonType *>(data)); + else + return -1; + + QMutexLocker lock(metaTypeDataLock()); + QQmlMetaTypeData *typeData = metaTypeData(); + typeData->undeletableTypes.insert(dtype); + + return dtype.index(); } //From qqml.h @@ -1620,8 +1836,8 @@ bool QQmlMetaType::namespaceContainsRegistrations(const QString &uri, int majorV // Has any type previously been installed to this namespace? QHashedString nameSpace(uri); - for (const QQmlType *type : data->types) - if (type->module() == nameSpace && type->majorVersion() == majorVersion) + for (const QQmlType &type : data->types) + if (type.module() == nameSpace && type.majorVersion() == majorVersion) return true; return false; @@ -1753,9 +1969,12 @@ int QQmlMetaType::listType(int id) { QMutexLocker lock(metaTypeDataLock()); QQmlMetaTypeData *data = metaTypeData(); - QQmlType *type = data->idToType.value(id); - if (type && type->qListTypeId() == id) - return type->typeId(); + QHash<int, int>::ConstIterator iter = data->qmlLists.constFind(id); + if (iter != data->qmlLists.cend()) + return *iter; + QQmlTypePrivate *type = data->idToType.value(id); + if (type && type->listId == id) + return type->typeId; else return 0; } @@ -1765,9 +1984,9 @@ int QQmlMetaType::attachedPropertiesFuncId(QQmlEnginePrivate *engine, const QMet QMutexLocker lock(metaTypeDataLock()); QQmlMetaTypeData *data = metaTypeData(); - QQmlType *type = data->metaObjectToType.value(mo); - if (type && type->attachedPropertiesFunction(engine)) - return type->attachedPropertiesId(engine); + QQmlType type(data->metaObjectToType.value(mo)); + if (type.attachedPropertiesFunction(engine)) + return type.attachedPropertiesId(engine); else return -1; } @@ -1778,7 +1997,7 @@ QQmlAttachedPropertiesFunc QQmlMetaType::attachedPropertiesFuncById(QQmlEnginePr return 0; QMutexLocker lock(metaTypeDataLock()); QQmlMetaTypeData *data = metaTypeData(); - return data->types.at(id)->attachedPropertiesFunction(engine); + return data->types.at(id).attachedPropertiesFunction(engine); } QMetaProperty QQmlMetaType::defaultProperty(const QMetaObject *metaObject) @@ -1842,7 +2061,9 @@ QQmlMetaType::TypeCategory QQmlMetaType::typeCategory(int userType) QMutexLocker lock(metaTypeDataLock()); QQmlMetaTypeData *data = metaTypeData(); - if (userType < data->objects.size() && data->objects.testBit(userType)) + if (data->qmlLists.contains(userType)) + return List; + else if (userType < data->objects.size() && data->objects.testBit(userType)) return Object; else if (userType < data->lists.size() && data->lists.testBit(userType)) return List; @@ -1861,10 +2082,10 @@ const char *QQmlMetaType::interfaceIId(int userType) { QMutexLocker lock(metaTypeDataLock()); QQmlMetaTypeData *data = metaTypeData(); - QQmlType *type = data->idToType.value(userType); + QQmlType type(data->idToType.value(userType)); lock.unlock(); - if (type && type->isInterface() && type->typeId() == userType) - return type->interfaceIId(); + if (type.isInterface() && type.typeId() == userType) + return type.interfaceIId(); else return 0; } @@ -1873,6 +2094,8 @@ bool QQmlMetaType::isList(int userType) { QMutexLocker lock(metaTypeDataLock()); QQmlMetaTypeData *data = metaTypeData(); + if (data->qmlLists.contains(userType)) + return true; return userType >= 0 && userType < data->lists.size() && data->lists.testBit(userType); } @@ -1917,11 +2140,11 @@ QQmlMetaType::StringConverter QQmlMetaType::customStringConverter(int type) Returns the type (if any) of URI-qualified named \a qualifiedName and version specified by \a version_major and \a version_minor. */ -QQmlType *QQmlMetaType::qmlType(const QString &qualifiedName, int version_major, int version_minor) +QQmlType QQmlMetaType::qmlType(const QString &qualifiedName, int version_major, int version_minor) { int slash = qualifiedName.indexOf(QLatin1Char('/')); if (slash <= 0) - return 0; + return QQmlType(); QHashedStringRef module(qualifiedName.constData(), slash); QHashedStringRef name(qualifiedName.constData() + slash + 1, qualifiedName.length() - slash - 1); @@ -1933,7 +2156,7 @@ QQmlType *QQmlMetaType::qmlType(const QString &qualifiedName, int version_major, Returns the type (if any) of \a name in \a module and version specified by \a version_major and \a version_minor. */ -QQmlType *QQmlMetaType::qmlType(const QHashedStringRef &name, const QHashedStringRef &module, int version_major, int version_minor) +QQmlType QQmlMetaType::qmlType(const QHashedStringRef &name, const QHashedStringRef &module, int version_major, int version_minor) { Q_ASSERT(version_major >= 0 && version_minor >= 0); QMutexLocker lock(metaTypeDataLock()); @@ -1941,25 +2164,26 @@ QQmlType *QQmlMetaType::qmlType(const QHashedStringRef &name, const QHashedStrin QQmlMetaTypeData::Names::ConstIterator it = data->nameToType.constFind(name); while (it != data->nameToType.cend() && it.key() == name) { + QQmlType t(*it); // XXX version_major<0 just a kludge for QQmlPropertyPrivate::initProperty - if (version_major < 0 || module.isEmpty() || (*it)->availableInVersion(module, version_major,version_minor)) - return (*it); + if (version_major < 0 || module.isEmpty() || t.availableInVersion(module, version_major,version_minor)) + return t; ++it; } - return 0; + return QQmlType(); } /*! Returns the type (if any) that corresponds to the \a metaObject. Returns null if no type is registered. */ -QQmlType *QQmlMetaType::qmlType(const QMetaObject *metaObject) +QQmlType QQmlMetaType::qmlType(const QMetaObject *metaObject) { QMutexLocker lock(metaTypeDataLock()); QQmlMetaTypeData *data = metaTypeData(); - return data->metaObjectToType.value(metaObject); + return QQmlType(data->metaObjectToType.value(metaObject)); } /*! @@ -1967,7 +2191,7 @@ QQmlType *QQmlMetaType::qmlType(const QMetaObject *metaObject) by \a version_major and \a version_minor in module specified by \a uri. Returns null if no type is registered. */ -QQmlType *QQmlMetaType::qmlType(const QMetaObject *metaObject, const QHashedStringRef &module, int version_major, int version_minor) +QQmlType QQmlMetaType::qmlType(const QMetaObject *metaObject, const QHashedStringRef &module, int version_major, int version_minor) { Q_ASSERT(version_major >= 0 && version_minor >= 0); QMutexLocker lock(metaTypeDataLock()); @@ -1975,29 +2199,29 @@ QQmlType *QQmlMetaType::qmlType(const QMetaObject *metaObject, const QHashedStri QQmlMetaTypeData::MetaObjects::const_iterator it = data->metaObjectToType.constFind(metaObject); while (it != data->metaObjectToType.cend() && it.key() == metaObject) { - QQmlType *t = *it; - if (version_major < 0 || module.isEmpty() || t->availableInVersion(module, version_major,version_minor)) + QQmlType t(*it); + if (version_major < 0 || module.isEmpty() || t.availableInVersion(module, version_major,version_minor)) return t; ++it; } - return 0; + return QQmlType(); } /*! Returns the type (if any) that corresponds to the QVariant::Type \a userType. Returns null if no type is registered. */ -QQmlType *QQmlMetaType::qmlType(int userType) +QQmlType QQmlMetaType::qmlType(int userType) { QMutexLocker lock(metaTypeDataLock()); QQmlMetaTypeData *data = metaTypeData(); - QQmlType *type = data->idToType.value(userType); - if (type && type->typeId() == userType) - return type; + QQmlTypePrivate *type = data->idToType.value(userType); + if (type && type->typeId == userType) + return QQmlType(type); else - return 0; + return QQmlType(); } /*! @@ -2006,34 +2230,209 @@ QQmlType *QQmlMetaType::qmlType(int userType) Returns null if no such type is registered. */ -QQmlType *QQmlMetaType::qmlType(const QUrl &url, bool includeNonFileImports /* = false */) +QQmlType QQmlMetaType::qmlType(const QUrl &url, bool includeNonFileImports /* = false */) { QMutexLocker lock(metaTypeDataLock()); QQmlMetaTypeData *data = metaTypeData(); - QQmlType *type = data->urlToType.value(url); - if (!type && includeNonFileImports) - type = data->urlToNonFileImportType.value(url); + QQmlType type(data->urlToType.value(url)); + if (!type.isValid() && includeNonFileImports) + type = QQmlType(data->urlToNonFileImportType.value(url)); - if (type && type->sourceUrl() == url) + if (type.sourceUrl() == url) return type; else + return QQmlType(); +} + +QQmlPropertyCache *QQmlMetaTypeData::propertyCache(const QMetaObject *metaObject) +{ + if (QQmlPropertyCache *rv = propertyCaches.value(metaObject)) + return rv; + + if (!metaObject->superClass()) { + QQmlPropertyCache *rv = new QQmlPropertyCache(metaObject); + propertyCaches.insert(metaObject, rv); + return rv; + } + QQmlPropertyCache *super = propertyCache(metaObject->superClass()); + QQmlPropertyCache *rv = super->copyAndAppend(metaObject); + propertyCaches.insert(metaObject, rv); + return rv; +} + +QQmlPropertyCache *QQmlMetaType::propertyCache(const QMetaObject *metaObject) +{ + QMutexLocker lock(metaTypeDataLock()); + QQmlMetaTypeData *data = metaTypeData(); + return data->propertyCache(metaObject); +} + +QQmlPropertyCache *QQmlMetaTypeData::propertyCache(const QQmlType &type, int minorVersion) +{ + Q_ASSERT(type.isValid()); + + if (QQmlPropertyCache *pc = type.key()->propertyCacheForMinorVersion(minorVersion)) + return pc; + + QVector<QQmlType> types; + + int maxMinorVersion = 0; + + const QMetaObject *metaObject = type.metaObject(); + + while (metaObject) { + QQmlType t = QQmlMetaType::qmlType(metaObject, type.module(), type.majorVersion(), minorVersion); + if (t.isValid()) { + maxMinorVersion = qMax(maxMinorVersion, t.minorVersion()); + types << t; + } else { + types << QQmlType(); + } + + metaObject = metaObject->superClass(); + } + + if (QQmlPropertyCache *pc = type.key()->propertyCacheForMinorVersion(maxMinorVersion)) { + const_cast<QQmlTypePrivate*>(type.key())->setPropertyCacheForMinorVersion(minorVersion, pc); + return pc; + } + + QQmlPropertyCache *raw = propertyCache(type.metaObject()); + + bool hasCopied = false; + + for (int ii = 0; ii < types.count(); ++ii) { + QQmlType currentType = types.at(ii); + if (!currentType.isValid()) + continue; + + int rev = currentType.metaObjectRevision(); + int moIndex = types.count() - 1 - ii; + + if (raw->allowedRevisionCache[moIndex] != rev) { + if (!hasCopied) { + raw = raw->copy(); + hasCopied = true; + } + raw->allowedRevisionCache[moIndex] = rev; + } + } + + // Test revision compatibility - the basic rule is: + // * Anything that is excluded, cannot overload something that is not excluded * + + // Signals override: + // * other signals and methods of the same name. + // * properties named on<Signal Name> + // * automatic <property name>Changed notify signals + + // Methods override: + // * other methods of the same name + + // Properties override: + // * other elements of the same name + +#if 0 + bool overloadError = false; + QString overloadName; + + for (QQmlPropertyCache::StringCache::ConstIterator iter = raw->stringCache.begin(); + !overloadError && iter != raw->stringCache.end(); + ++iter) { + + QQmlPropertyData *d = *iter; + if (raw->isAllowedInRevision(d)) + continue; // Not excluded - no problems + + // check that a regular "name" overload isn't happening + QQmlPropertyData *current = d; + while (!overloadError && current) { + current = d->overrideData(current); + if (current && raw->isAllowedInRevision(current)) + overloadError = true; + } + } + + if (overloadError) { + if (hasCopied) raw->release(); + + error.setDescription(QLatin1String("Type ") + type.qmlTypeName() + QLatin1Char(' ') + QString::number(type.majorVersion()) + QLatin1Char('.') + QString::number(minorVersion) + QLatin1String(" contains an illegal property \"") + overloadName + QLatin1String("\". This is an error in the type's implementation.")); return 0; + } +#endif + + const_cast<QQmlTypePrivate*>(type.key())->setPropertyCacheForMinorVersion(minorVersion, raw); + + if (hasCopied) + raw->release(); + + if (minorVersion != maxMinorVersion) + const_cast<QQmlTypePrivate*>(type.key())->setPropertyCacheForMinorVersion(maxMinorVersion, raw); + + return raw; } -/*! - Returns the type (if any) with the given \a index in the global type store. - This is for use when you just got the index back from a qmlRegister function. - Returns null if the index is out of bounds. -*/ -QQmlType *QQmlMetaType::qmlTypeFromIndex(int idx) +QQmlPropertyCache *QQmlMetaType::propertyCache(const QQmlType &type, int minorVersion) +{ + QMutexLocker lock(metaTypeDataLock()); + QQmlMetaTypeData *data = metaTypeData(); + return data->propertyCache(type, minorVersion); +} + +void QQmlMetaType::freeUnusedTypesAndCaches() { QMutexLocker lock(metaTypeDataLock()); QQmlMetaTypeData *data = metaTypeData(); - if (idx < 0 || idx >= data->types.count()) - return 0; - return data->types.at(idx); + { + bool deletedAtLeastOneType; + do { + deletedAtLeastOneType = false; + QList<QQmlType>::Iterator it = data->types.begin(); + while (it != data->types.end()) { + const QQmlTypePrivate *d = (*it).priv(); + if (d && d->refCount == 1) { + deletedAtLeastOneType = true; + + removeQQmlTypePrivate(data->idToType, d); + removeQQmlTypePrivate(data->nameToType, d); + removeQQmlTypePrivate(data->urlToType, d); + removeQQmlTypePrivate(data->urlToNonFileImportType, d); + removeQQmlTypePrivate(data->metaObjectToType, d); + + for (QQmlMetaTypeData::TypeModules::Iterator module = data->uriToModule.begin(); module != data->uriToModule.end(); ++module) { + QQmlTypeModulePrivate *modulePrivate = (*module)->priv(); + modulePrivate->remove(d); + } + + *it = QQmlType(); + } else { + ++it; + } + } + } while (deletedAtLeastOneType); + } + + { + bool deletedAtLeastOneCache; + do { + deletedAtLeastOneCache = false; + QHash<const QMetaObject *, QQmlPropertyCache *>::Iterator it = data->propertyCaches.begin(); + while (it != data->propertyCaches.end()) { + + if ((*it)->count() == 1) { + QQmlPropertyCache *pc = Q_NULLPTR; + qSwap(pc, *it); + it = data->propertyCaches.erase(it); + pc->release(); + deletedAtLeastOneCache = true; + } else { + ++it; + } + } + } while (deletedAtLeastOneCache); + } } /*! @@ -2048,7 +2447,8 @@ QList<QString> QQmlMetaType::qmlTypeNames() names.reserve(data->nameToType.count()); QQmlMetaTypeData::Names::ConstIterator it = data->nameToType.cbegin(); while (it != data->nameToType.cend()) { - names += (*it)->qmlTypeName(); + QQmlType t(*it); + names += t.qmlTypeName(); ++it; } @@ -2058,18 +2458,22 @@ QList<QString> QQmlMetaType::qmlTypeNames() /*! Returns the list of registered QML types. */ -QList<QQmlType*> QQmlMetaType::qmlTypes() +QList<QQmlType> QQmlMetaType::qmlTypes() { QMutexLocker lock(metaTypeDataLock()); - QQmlMetaTypeData *data = metaTypeData(); + const QQmlMetaTypeData *data = metaTypeData(); + + QList<QQmlType> types; + for (QQmlTypePrivate *t : data->nameToType) + types.append(QQmlType(t)); - return data->nameToType.values(); + return types; } /*! Returns the list of all registered types. */ -QList<QQmlType*> QQmlMetaType::qmlAllTypes() +QList<QQmlType> QQmlMetaType::qmlAllTypes() { QMutexLocker lock(metaTypeDataLock()); QQmlMetaTypeData *data = metaTypeData(); @@ -2080,14 +2484,15 @@ QList<QQmlType*> QQmlMetaType::qmlAllTypes() /*! Returns the list of registered QML singleton types. */ -QList<QQmlType*> QQmlMetaType::qmlSingletonTypes() +QList<QQmlType> QQmlMetaType::qmlSingletonTypes() { QMutexLocker lock(metaTypeDataLock()); QQmlMetaTypeData *data = metaTypeData(); - QList<QQmlType*> retn; - for (const auto type : qAsConst(data->nameToType)) { - if (type->isSingleton()) + QList<QQmlType> retn; + for (const auto t : qAsConst(data->nameToType)) { + QQmlType type(t); + if (type.isSingleton()) retn.append(type); } return retn; @@ -2115,9 +2520,9 @@ QString QQmlMetaType::prettyTypeName(const QObject *object) if (!object) return typeName; - const QQmlType *type = QQmlMetaType::qmlType(object->metaObject()); - if (type) { - typeName = type->qmlTypeName(); + QQmlType type = QQmlMetaType::qmlType(object->metaObject()); + if (type.isValid()) { + typeName = type.qmlTypeName(); const int lastSlash = typeName.lastIndexOf(QLatin1Char('/')); if (lastSlash != -1) typeName = typeName.mid(lastSlash + 1); @@ -2133,8 +2538,8 @@ QString QQmlMetaType::prettyTypeName(const QObject *object) if (marker != -1) { typeName = typeName.leftRef(marker) + QLatin1Char('*'); type = QQmlMetaType::qmlType(QMetaType::type(typeName.toLatin1())); - if (type) { - QString qmlTypeName = type->qmlTypeName(); + if (type.isValid()) { + QString qmlTypeName = type.qmlTypeName(); const int lastSlash = qmlTypeName.lastIndexOf(QLatin1Char('/')); if (lastSlash != -1) qmlTypeName = qmlTypeName.mid(lastSlash + 1); diff --git a/src/qml/qml/qqmlmetatype_p.h b/src/qml/qml/qqmlmetatype_p.h index ead4f130ec..8eb91f321a 100644 --- a/src/qml/qml/qqmlmetatype_p.h +++ b/src/qml/qml/qqmlmetatype_p.h @@ -70,24 +70,36 @@ class QQmlTypeModule; class QHashedString; class QHashedStringRef; class QMutex; +class QQmlPropertyCache; +class QQmlCompiledData; namespace QV4 { struct String; } class Q_QML_PRIVATE_EXPORT QQmlMetaType { public: + static QQmlType registerCompositeSingletonType(const QQmlPrivate::RegisterCompositeSingletonType &type); + static QQmlType registerCompositeType(const QQmlPrivate::RegisterCompositeType &type); + + static void registerInternalCompositeType(QV4::CompiledData::CompilationUnit *compilationUnit); + static void unregisterInternalCompositeType(QV4::CompiledData::CompilationUnit *compilationUnit); + static QList<QString> qmlTypeNames(); - static QList<QQmlType*> qmlTypes(); - static QList<QQmlType*> qmlSingletonTypes(); - static QList<QQmlType*> qmlAllTypes(); - - static QQmlType *qmlType(const QString &qualifiedName, int, int); - static QQmlType *qmlType(const QHashedStringRef &name, const QHashedStringRef &module, int, int); - static QQmlType *qmlType(const QMetaObject *); - static QQmlType *qmlType(const QMetaObject *metaObject, const QHashedStringRef &module, int version_major, int version_minor); - static QQmlType *qmlType(int); - static QQmlType *qmlType(const QUrl &url, bool includeNonFileImports = false); - static QQmlType *qmlTypeFromIndex(int); + static QList<QQmlType> qmlTypes(); + static QList<QQmlType> qmlSingletonTypes(); + static QList<QQmlType> qmlAllTypes(); + + static QQmlType qmlType(const QString &qualifiedName, int, int); + static QQmlType qmlType(const QHashedStringRef &name, const QHashedStringRef &module, int, int); + static QQmlType qmlType(const QMetaObject *); + static QQmlType qmlType(const QMetaObject *metaObject, const QHashedStringRef &module, int version_major, int version_minor); + static QQmlType qmlType(int); + static QQmlType qmlType(const QUrl &url, bool includeNonFileImports = false); + + static QQmlPropertyCache *propertyCache(const QMetaObject *metaObject); + static QQmlPropertyCache *propertyCache(const QQmlType &type, int minorVersion); + + static void freeUnusedTypesAndCaches(); static QMetaProperty defaultProperty(const QMetaObject *); static QMetaProperty defaultProperty(QObject *); @@ -139,11 +151,24 @@ class QQmlPropertyCache; class Q_QML_PRIVATE_EXPORT QQmlType { public: + QQmlType(); + QQmlType(const QQmlType &other); + QQmlType &operator =(const QQmlType &other); + explicit QQmlType(QQmlTypePrivate *priv); + ~QQmlType(); + + bool operator ==(const QQmlType &other) const { + return d == other.d; + } + + bool isValid() const { return d != 0; } + const QQmlTypePrivate *key() const { return d; } + QByteArray typeName() const; - const QString &qmlTypeName() const; - const QString &elementName() const; + QString qmlTypeName() const; + QString elementName() const; - const QHashedString &module() const; + QHashedString module() const; int majorVersion() const; int minorVersion() const; @@ -225,12 +250,9 @@ public: int scopedEnumValue(QQmlEnginePrivate *engine, const QByteArray &, const QByteArray &, bool *ok) const; int scopedEnumValue(QQmlEnginePrivate *engine, const QStringRef &, const QStringRef &, bool *ok) const; -private: - QQmlType *superType() const; - QQmlType *resolveCompositeBaseType(QQmlEnginePrivate *engine) const; - QQmlPropertyCache *compositePropertyCache(QQmlEnginePrivate *engine) const; - friend class QQmlTypePrivate; - friend struct QQmlMetaTypeData; + QQmlTypePrivate *priv() const { return d; } + static void refHandle(QQmlTypePrivate *priv); + static void derefHandle(QQmlTypePrivate *priv); enum RegistrationType { CppType = 0, @@ -239,25 +261,39 @@ private: CompositeType = 3, CompositeSingletonType = 4 }; + +private: + QQmlType superType() const; + QQmlType resolveCompositeBaseType(QQmlEnginePrivate *engine) const; + int resolveCompositeEnumValue(QQmlEnginePrivate *engine, const QString &name, bool *ok) const; + QQmlPropertyCache *compositePropertyCache(QQmlEnginePrivate *engine) const; + friend class QQmlTypePrivate; + friend QString registrationTypeString(RegistrationType); friend bool checkRegistration(RegistrationType, QQmlMetaTypeData *, const char *, const QString &, int); - friend int registerType(const QQmlPrivate::RegisterType &); - friend int registerSingletonType(const QQmlPrivate::RegisterSingletonType &); - friend int registerInterface(const QQmlPrivate::RegisterInterface &); - friend int registerCompositeType(const QQmlPrivate::RegisterCompositeType &); - friend int registerCompositeSingletonType(const QQmlPrivate::RegisterCompositeSingletonType &); + friend QQmlType registerType(const QQmlPrivate::RegisterType &); + friend QQmlType registerSingletonType(const QQmlPrivate::RegisterSingletonType &); + friend QQmlType registerInterface(const QQmlPrivate::RegisterInterface &); friend int registerQmlUnitCacheHook(const QQmlPrivate::RegisterQmlUnitCacheHook &); + friend uint qHash(const QQmlType &t, uint seed); friend Q_QML_EXPORT void qmlClearTypeRegistrations(); - QQmlType(int, const QQmlPrivate::RegisterInterface &); - QQmlType(int, const QString &, const QQmlPrivate::RegisterSingletonType &); - QQmlType(int, const QString &, const QQmlPrivate::RegisterType &); - QQmlType(int, const QString &, const QQmlPrivate::RegisterCompositeType &); - QQmlType(int, const QString &, const QQmlPrivate::RegisterCompositeSingletonType &); - ~QQmlType(); + friend class QQmlMetaType; + + QQmlType(QQmlMetaTypeData *data, const QQmlPrivate::RegisterInterface &); + QQmlType(QQmlMetaTypeData *data, const QString &, const QQmlPrivate::RegisterSingletonType &); + QQmlType(QQmlMetaTypeData *data, const QString &, const QQmlPrivate::RegisterType &); + QQmlType(QQmlMetaTypeData *data, const QString &, const QQmlPrivate::RegisterCompositeType &); + QQmlType(QQmlMetaTypeData *data, const QString &, const QQmlPrivate::RegisterCompositeSingletonType &); QQmlTypePrivate *d; }; +Q_DECLARE_TYPEINFO(QQmlMetaType, Q_MOVABLE_TYPE); + + +inline uint qHash(const QQmlType &t, uint seed = 0) { return qHash(reinterpret_cast<quintptr>(t.d), seed); } + + class QQmlTypeModulePrivate; class QQmlTypeModule { @@ -268,15 +304,14 @@ public: int minimumMinorVersion() const; int maximumMinorVersion() const; - QQmlType *type(const QHashedStringRef &, int) const; - QQmlType *type(const QV4::String *, int) const; - - QList<QQmlType*> singletonTypes(int) const; + QQmlType type(const QHashedStringRef &, int) const; + QQmlType type(const QV4::String *, int) const; + QQmlTypeModulePrivate *priv() { return d; } private: //Used by register functions and creates the QQmlTypeModule for them friend QQmlTypeModule *getTypeModule(const QHashedString &uri, int majorVersion, QQmlMetaTypeData *data); - friend void addTypeToData(QQmlType* type, QQmlMetaTypeData *data); + friend void addTypeToData(QQmlTypePrivate *type, QQmlMetaTypeData *data); friend struct QQmlMetaTypeData; friend Q_QML_EXPORT void qmlClearTypeRegistrations(); friend class QQmlTypeModulePrivate; @@ -297,8 +332,8 @@ public: QQmlTypeModule *module() const; int minorVersion() const; - QQmlType *type(const QHashedStringRef &) const; - QQmlType *type(const QV4::String *) const; + QQmlType type(const QHashedStringRef &) const; + QQmlType type(const QV4::String *) const; private: QQmlTypeModule *m_module; diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp index 9206395c8f..cc9cc889d0 100644 --- a/src/qml/qml/qqmlobjectcreator.cpp +++ b/src/qml/qml/qqmlobjectcreator.cpp @@ -613,11 +613,11 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const } } -static QQmlType *qmlTypeForObject(QObject *object) +static QQmlType qmlTypeForObject(QObject *object) { - QQmlType *type = 0; + QQmlType type; const QMetaObject *mo = object->metaObject(); - while (mo && !type) { + while (mo && !type.isValid()) { type = QQmlMetaType::qmlType(mo); mo = mo->superClass(); } @@ -654,7 +654,7 @@ void QQmlObjectCreator::setupBindings(bool applyDeferredBindings) } else if (binding) { QQmlValueTypeProxyBinding *proxy = static_cast<QQmlValueTypeProxyBinding *>(binding); - if (qmlTypeForObject(_bindingTarget)) { + if (qmlTypeForObject(_bindingTarget).isValid()) { quint32 bindingSkipList = 0; QQmlPropertyData *defaultProperty = _compiledObject->indexOfDefaultPropertyOrAlias != -1 ? _propertyCache->parent()->defaultProperty() : _propertyCache->defaultProperty(); @@ -712,15 +712,15 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *property, con Q_ASSERT(stringAt(qmlUnit->objectAt(binding->value.objectIndex)->inheritedTypeNameIndex).isEmpty()); QV4::CompiledData::ResolvedTypeReference *tr = resolvedTypes.value(binding->propertyNameIndex); Q_ASSERT(tr); - QQmlType *attachedType = tr->type; - if (!attachedType) { + QQmlType attachedType = tr->type; + if (!attachedType.isValid()) { QQmlTypeNameCache::Result res = context->imports->query(stringAt(binding->propertyNameIndex)); if (res.isValid()) attachedType = res.type; else return false; } - const int id = attachedType->attachedPropertiesId(QQmlEnginePrivate::get(engine)); + const int id = attachedType.attachedPropertiesId(QQmlEnginePrivate::get(engine)); QObject *qmlObject = qmlAttachedPropertiesObjectById(id, _qobject); if (!populateInstance(binding->value.objectIndex, qmlObject, qmlObject, /*value type property*/0)) return false; @@ -851,10 +851,10 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *property, con if (binding->type == QV4::CompiledData::Binding::Type_Object) { if (binding->flags & QV4::CompiledData::Binding::IsOnAssignment) { // ### determine value source and interceptor casts ahead of time. - QQmlType *type = qmlTypeForObject(createdSubObject); - Q_ASSERT(type); + QQmlType type = qmlTypeForObject(createdSubObject); + Q_ASSERT(type.isValid()); - int valueSourceCast = type->propertyValueSourceCast(); + int valueSourceCast = type.propertyValueSourceCast(); if (valueSourceCast != -1) { QQmlPropertyValueSource *vs = reinterpret_cast<QQmlPropertyValueSource *>(reinterpret_cast<char *>(createdSubObject) + valueSourceCast); QObject *target = createdSubObject->parent(); @@ -866,7 +866,7 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *property, con vs->setTarget(prop); return true; } - int valueInterceptorCast = type->propertyValueInterceptorCast(); + int valueInterceptorCast = type.propertyValueInterceptorCast(); if (valueInterceptorCast != -1) { QQmlPropertyValueInterceptor *vi = reinterpret_cast<QQmlPropertyValueInterceptor *>(reinterpret_cast<char *>(createdSubObject) + valueInterceptorCast); QObject *target = createdSubObject->parent(); @@ -1061,13 +1061,13 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo QV4::CompiledData::ResolvedTypeReference *typeRef = resolvedTypes.value(obj->inheritedTypeNameIndex); Q_ASSERT(typeRef); installPropertyCache = !typeRef->isFullyDynamicType; - QQmlType *type = typeRef->type; - if (type) { + QQmlType type = typeRef->type; + if (type.isValid()) { Q_QML_OC_PROFILE(sharedState->profiler, profiler.update( - compilationUnit, obj, type->qmlTypeName(), context->url())); + compilationUnit, obj, type.qmlTypeName(), context->url())); void *ddataMemory = 0; - type->create(&instance, &ddataMemory, sizeof(QQmlData)); + type.create(&instance, &ddataMemory, sizeof(QQmlData)); if (!instance) { recordError(obj->location, tr("Unable to create object of type %1").arg(stringAt(obj->inheritedTypeNameIndex))); return 0; @@ -1081,11 +1081,11 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo p->declarativeData = ddata; } - const int parserStatusCast = type->parserStatusCast(); + const int parserStatusCast = type.parserStatusCast(); if (parserStatusCast != -1) parserStatus = reinterpret_cast<QQmlParserStatus*>(reinterpret_cast<char *>(instance) + parserStatusCast); - customParser = type->customParser(); + customParser = type.customParser(); if (sharedState->rootContext && sharedState->rootContext->isRootObjectInCreation) { QQmlData *ddata = QQmlData::get(instance, /*create*/true); @@ -1326,7 +1326,7 @@ bool QQmlObjectCreator::populateInstance(int index, QObject *instance, QObject * if (propertyCaches->needsVMEMetaObject(_compiledObjectIndex)) { Q_ASSERT(!cache.isNull()); // install on _object - vmeMetaObject = new QQmlVMEMetaObject(_qobject, cache, compilationUnit, _compiledObjectIndex); + vmeMetaObject = new QQmlVMEMetaObject(v4, _qobject, cache, compilationUnit, _compiledObjectIndex); if (_ddata->propertyCache) _ddata->propertyCache->release(); _ddata->propertyCache = cache; diff --git a/src/qml/qml/qqmlopenmetaobject.cpp b/src/qml/qml/qqmlopenmetaobject.cpp index 49f02476a2..fc85030b3d 100644 --- a/src/qml/qml/qqmlopenmetaobject.cpp +++ b/src/qml/qml/qqmlopenmetaobject.cpp @@ -376,7 +376,7 @@ void QQmlOpenMetaObject::setCached(bool c) QQmlData *qmldata = QQmlData::get(d->object, true); if (d->cacheProperties) { if (!d->type->d->cache) - d->type->d->cache = new QQmlPropertyCache(QV8Engine::getV4(d->type->d->engine), this); + d->type->d->cache = new QQmlPropertyCache(this); qmldata->propertyCache = d->type->d->cache; d->type->d->cache->addref(); } else { diff --git a/src/qml/qml/qqmlproperty.cpp b/src/qml/qml/qqmlproperty.cpp index 9b5f7b0a06..21bbcadb1c 100644 --- a/src/qml/qml/qqmlproperty.cpp +++ b/src/qml/qml/qqmlproperty.cpp @@ -253,24 +253,24 @@ void QQmlPropertyPrivate::initProperty(QObject *obj, const QString &name) if (typeNameCache) { QQmlTypeNameCache::Result r = typeNameCache->query(pathName); if (r.isValid()) { - if (r.type) { + if (r.type.isValid()) { QQmlEnginePrivate *enginePrivate = QQmlEnginePrivate::get(engine); - QQmlAttachedPropertiesFunc func = r.type->attachedPropertiesFunction(enginePrivate); + QQmlAttachedPropertiesFunc func = r.type.attachedPropertiesFunction(enginePrivate); if (!func) return; // Not an attachable type - currentObject = qmlAttachedPropertiesObjectById(r.type->attachedPropertiesId(enginePrivate), currentObject); + currentObject = qmlAttachedPropertiesObjectById(r.type.attachedPropertiesId(enginePrivate), currentObject); if (!currentObject) return; // Something is broken with the attachable type } else if (r.importNamespace) { if ((ii + 1) == path.count()) return; // No type following the namespace ++ii; r = typeNameCache->query(path.at(ii), r.importNamespace); - if (!r.type) return; // Invalid type in namespace + if (!r.type.isValid()) return; // Invalid type in namespace QQmlEnginePrivate *enginePrivate = QQmlEnginePrivate::get(engine); - QQmlAttachedPropertiesFunc func = r.type->attachedPropertiesFunction(enginePrivate); + QQmlAttachedPropertiesFunc func = r.type.attachedPropertiesFunction(enginePrivate); if (!func) return; // Not an attachable type - currentObject = qmlAttachedPropertiesObjectById(r.type->attachedPropertiesId(enginePrivate), currentObject); + currentObject = qmlAttachedPropertiesObjectById(r.type.attachedPropertiesId(enginePrivate), currentObject); if (!currentObject) return; // Something is broken with the attachable type } else if (r.scriptIndex != -1) { @@ -1275,10 +1275,10 @@ bool QQmlPropertyPrivate::write(QObject *object, if (enginePriv) { listType = enginePriv->rawMetaObjectForType(enginePriv->listType(property.propType())); } else { - QQmlType *type = QQmlMetaType::qmlType(QQmlMetaType::listType(property.propType())); - if (!type) + QQmlType type = QQmlMetaType::qmlType(QQmlMetaType::listType(property.propType())); + if (!type.isValid()) return false; - listType = type->baseMetaObject(); + listType = type.baseMetaObject(); } if (listType.isNull()) return false; @@ -1393,8 +1393,9 @@ QQmlMetaObject QQmlPropertyPrivate::rawMetaObjectForType(QQmlEnginePrivate *engi return metaType.metaObject(); if (engine) return engine->rawMetaObjectForType(userType); - if (QQmlType *type = QQmlMetaType::qmlType(userType)) - return QQmlMetaObject(type->baseMetaObject()); + QQmlType type = QQmlMetaType::qmlType(userType); + if (type.isValid()) + return QQmlMetaObject(type.baseMetaObject()); return QQmlMetaObject(); } diff --git a/src/qml/qml/qqmlpropertycache.cpp b/src/qml/qml/qqmlpropertycache.cpp index 15b9fe8312..7178dffa8b 100644 --- a/src/qml/qml/qqmlpropertycache.cpp +++ b/src/qml/qml/qqmlpropertycache.cpp @@ -99,7 +99,7 @@ static QQmlPropertyData::Flags fastFlagsForProperty(const QMetaProperty &p) // Flags that do depend on the property's QMetaProperty::userType() and thus are slow to // load -static void flagsForPropertyType(int propType, QQmlEngine *engine, QQmlPropertyData::Flags &flags) +static void flagsForPropertyType(int propType, QQmlPropertyData::Flags &flags) { Q_ASSERT(propType != -1); @@ -116,9 +116,7 @@ static void flagsForPropertyType(int propType, QQmlEngine *engine, QQmlPropertyD } else if (propType == qMetaTypeId<QQmlV4Handle>()) { flags.type = QQmlPropertyData::Flags::V4HandleType; } else { - QQmlMetaType::TypeCategory cat = - engine ? QQmlEnginePrivate::get(engine)->typeCategory(propType) - : QQmlMetaType::typeCategory(propType); + QQmlMetaType::TypeCategory cat = QQmlMetaType::typeCategory(propType); if (cat == QQmlMetaType::Object || QMetaType::typeFlags(propType) & QMetaType::PointerToQObject) flags.type = QQmlPropertyData::Flags::QObjectDerivedType; @@ -136,10 +134,10 @@ static int metaObjectSignalCount(const QMetaObject *metaObject) } QQmlPropertyData::Flags -QQmlPropertyData::flagsForProperty(const QMetaProperty &p, QQmlEngine *engine) +QQmlPropertyData::flagsForProperty(const QMetaProperty &p) { auto flags = fastFlagsForProperty(p); - flagsForPropertyType(p.userType(), engine, flags); + flagsForPropertyType(p.userType(), flags); return flags; } @@ -166,13 +164,13 @@ void QQmlPropertyData::lazyLoad(const QMetaProperty &p) } } -void QQmlPropertyData::load(const QMetaProperty &p, QQmlEngine *engine) +void QQmlPropertyData::load(const QMetaProperty &p) { setPropType(p.userType()); setCoreIndex(p.propertyIndex()); setNotifyIndex(QMetaObjectPrivate::signalIndex(p.notifySignal())); setFlags(fastFlagsForProperty(p)); - flagsForPropertyType(propType(), engine, _flags); + flagsForPropertyType(propType(), _flags); Q_ASSERT(p.revision() <= Q_INT16_MAX); setRevision(p.revision()); } @@ -244,19 +242,18 @@ void QQmlPropertyData::lazyLoad(const QMetaMethod &m) /*! Creates a new empty QQmlPropertyCache. */ -QQmlPropertyCache::QQmlPropertyCache(QV4::ExecutionEngine *e) - : engine(e), _parent(0), propertyIndexCacheStart(0), methodIndexCacheStart(0), +QQmlPropertyCache::QQmlPropertyCache() + : _parent(0), propertyIndexCacheStart(0), methodIndexCacheStart(0), signalHandlerIndexCacheStart(0), _hasPropertyOverrides(false), _ownMetaObject(false), _metaObject(0), argumentsCache(0), _jsFactoryMethodIndex(-1) { - Q_ASSERT(engine); } /*! Creates a new QQmlPropertyCache of \a metaObject. */ -QQmlPropertyCache::QQmlPropertyCache(QV4::ExecutionEngine *e, const QMetaObject *metaObject) - : QQmlPropertyCache(e) +QQmlPropertyCache::QQmlPropertyCache(const QMetaObject *metaObject) + : QQmlPropertyCache() { Q_ASSERT(metaObject); @@ -265,8 +262,6 @@ QQmlPropertyCache::QQmlPropertyCache(QV4::ExecutionEngine *e, const QMetaObject QQmlPropertyCache::~QQmlPropertyCache() { - clear(); - QQmlPropertyCacheMethodArguments *args = argumentsCache; while (args) { QQmlPropertyCacheMethodArguments *next = args->next; @@ -284,24 +279,11 @@ QQmlPropertyCache::~QQmlPropertyCache() if (_ownMetaObject) free(const_cast<QMetaObject *>(_metaObject)); _metaObject = 0; _parent = 0; - engine = 0; -} - -void QQmlPropertyCache::destroy() -{ - delete this; -} - -// This is inherited from QQmlCleanup, so it should only clear the things -// that are tied to the specific QQmlEngine. -void QQmlPropertyCache::clear() -{ - engine = 0; } QQmlPropertyCache *QQmlPropertyCache::copy(int reserve) { - QQmlPropertyCache *cache = new QQmlPropertyCache(engine); + QQmlPropertyCache *cache = new QQmlPropertyCache(); cache->_parent = this; cache->_parent->addref(); cache->propertyIndexCacheStart = propertyIndexCache.count() + propertyIndexCacheStart; @@ -720,7 +702,7 @@ void QQmlPropertyCache::resolve(QQmlPropertyData *data) const data->setPropType(registerResult == -1 ? QMetaType::UnknownType : registerResult); } } - flagsForPropertyType(data->propType(), engine->qmlEngine(), data->_flags); + flagsForPropertyType(data->propType(), data->_flags); } } @@ -791,7 +773,11 @@ void QQmlPropertyCache::invalidate(const QMetaObject *metaObject) QQmlPropertyData *QQmlPropertyCache::findProperty(StringCache::ConstIterator it, QObject *object, QQmlContextData *context) const { QQmlData *data = (object ? QQmlData::get(object) : 0); - const QQmlVMEMetaObject *vmemo = (data && data->hasVMEMetaObject ? static_cast<const QQmlVMEMetaObject *>(object->metaObject()) : 0); + const QQmlVMEMetaObject *vmemo = 0; + if (data && data->hasVMEMetaObject) { + QObjectPrivate *op = QObjectPrivate::get(object); + vmemo = static_cast<const QQmlVMEMetaObject *>(op->metaObject); + } return findProperty(it, vmemo, context); } @@ -835,9 +821,9 @@ QQmlPropertyData *QQmlPropertyCache::findProperty(StringCache::ConstIterator it, } if (vmemo) { - const int methodCount = vmemo->methodCount(); - const int signalCount = vmemo->signalCount(); - const int propertyCount = vmemo->propertyCount(); + const int methodCount = vmemo->cache->methodCount(); + const int signalCount = vmemo->cache->signalCount(); + const int propertyCount = vmemo->cache->propertyCount(); // Ensure that the property we resolve to is accessible from this meta-object do { diff --git a/src/qml/qml/qqmlpropertycache_p.h b/src/qml/qml/qqmlpropertycache_p.h index 392768c1b1..6cdb82bd46 100644 --- a/src/qml/qml/qqmlpropertycache_p.h +++ b/src/qml/qml/qqmlpropertycache_p.h @@ -288,8 +288,8 @@ public: inline bool operator==(const QQmlPropertyRawData &); - static Flags flagsForProperty(const QMetaProperty &, QQmlEngine *engine = 0); - void load(const QMetaProperty &, QQmlEngine *engine = 0); + static Flags flagsForProperty(const QMetaProperty &); + void load(const QMetaProperty &); void load(const QMetaMethod &); QString name(QObject *) const; QString name(const QMetaObject *) const; @@ -364,11 +364,11 @@ struct QQmlEnumData }; class QQmlPropertyCacheMethodArguments; -class Q_QML_PRIVATE_EXPORT QQmlPropertyCache : public QQmlRefCount, public QQmlCleanup +class Q_QML_PRIVATE_EXPORT QQmlPropertyCache : public QQmlRefCount { public: - QQmlPropertyCache(QV4::ExecutionEngine *); - QQmlPropertyCache(QV4::ExecutionEngine *, const QMetaObject *); + QQmlPropertyCache(); + QQmlPropertyCache(const QMetaObject *); virtual ~QQmlPropertyCache(); void update(const QMetaObject *); @@ -462,11 +462,6 @@ public: static bool addToHash(QCryptographicHash &hash, const QMetaObject &mo); QByteArray checksum(bool *ok); - -protected: - void destroy() override; - void clear() override; - private: friend class QQmlEnginePrivate; friend class QQmlCompiler; @@ -474,6 +469,7 @@ private: template <typename T> friend class QQmlPropertyCacheAliasCreator; friend class QQmlComponentAndAliasResolver; friend class QQmlMetaObject; + friend struct QQmlMetaTypeData; inline QQmlPropertyCache *copy(int reserve); @@ -510,9 +506,6 @@ private: _hasPropertyOverrides |= isOverride; } -public: - QV4::ExecutionEngine *engine; - private: QQmlPropertyCache *_parent; int propertyIndexCacheStart; @@ -537,6 +530,8 @@ private: QByteArray _checksum; }; +typedef QQmlRefPointer<QQmlPropertyCache> QQmlPropertyCachePtr; + // QQmlMetaObject serves as a wrapper around either QMetaObject or QQmlPropertyCache. // This is necessary as we delay creation of QMetaObject for synthesized QObjects, but // we don't want to needlessly generate QQmlPropertyCaches every time we encounter a diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp index 151a7cd883..8721ec507a 100644 --- a/src/qml/qml/qqmltypeloader.cpp +++ b/src/qml/qml/qqmltypeloader.cpp @@ -1778,23 +1778,21 @@ QString QQmlTypeLoader::absoluteFilePath(const QString &path) #endif int lastSlash = path.lastIndexOf(QLatin1Char('/')); - QStringRef dirPath(&path, 0, lastSlash); + QString dirPath(path.left(lastSlash)); - StringSet **fileSet = m_importDirCache.value(QHashedStringRef(dirPath.constData(), dirPath.length())); - if (!fileSet) { - QHashedString dirPathString(dirPath.toString()); - bool exists = QDir(dirPathString).exists(); - QStringHash<bool> *files = exists ? new QStringHash<bool> : 0; - m_importDirCache.insert(dirPathString, files); - fileSet = m_importDirCache.value(dirPathString); + if (!m_importDirCache.contains(dirPath)) { + bool exists = QDir(dirPath).exists(); + QCache<QString, bool> *entry = exists ? new QCache<QString, bool> : 0; + m_importDirCache.insert(dirPath, entry); } - if (!(*fileSet)) + QCache<QString, bool> *fileSet = m_importDirCache.object(dirPath); + if (!fileSet) return QString(); QString absoluteFilePath; - QHashedStringRef fileName(path.constData()+lastSlash+1, path.length()-lastSlash-1); + QString fileName(path.mid(lastSlash+1, path.length()-lastSlash-1)); - bool *value = (*fileSet)->value(fileName); + bool *value = fileSet->object(fileName); if (value) { if (*value) absoluteFilePath = path; @@ -1808,7 +1806,7 @@ QString QQmlTypeLoader::absoluteFilePath(const QString &path) #else exists = QFile::exists(path); #endif - (*fileSet)->insert(fileName.toString(), exists); + fileSet->insert(fileName, new bool(exists)); if (exists) absoluteFilePath = path; } @@ -1843,18 +1841,16 @@ bool QQmlTypeLoader::directoryExists(const QString &path) int length = path.length(); if (path.endsWith(QLatin1Char('/'))) --length; - QStringRef dirPath(&path, 0, length); + QString dirPath(path.left(length)); - StringSet **fileSet = m_importDirCache.value(QHashedStringRef(dirPath.constData(), dirPath.length())); - if (!fileSet) { - QHashedString dirPathString(dirPath.toString()); - bool exists = QDir(dirPathString).exists(); - QStringHash<bool> *files = exists ? new QStringHash<bool> : 0; - m_importDirCache.insert(dirPathString, files); - fileSet = m_importDirCache.value(dirPathString); + if (!m_importDirCache.contains(dirPath)) { + bool exists = QDir(dirPath).exists(); + QCache<QString, bool> *files = exists ? new QCache<QString, bool> : 0; + m_importDirCache.insert(dirPath, files); } - return (*fileSet); + QCache<QString, bool> *fileSet = m_importDirCache.object(dirPath); + return fileSet != 0; } @@ -1938,7 +1934,7 @@ void QQmlTypeLoader::clearCache() (*iter)->release(); for (QmldirCache::Iterator iter = m_qmldirCache.begin(), end = m_qmldirCache.end(); iter != end; ++iter) (*iter)->release(); - qDeleteAll(m_importDirCache); + qDeleteAll(m_importQmlDirCache); m_typeCache.clear(); @@ -1947,6 +1943,7 @@ void QQmlTypeLoader::clearCache() m_qmldirCache.clear(); m_importDirCache.clear(); m_importQmlDirCache.clear(); + QQmlMetaType::freeUnusedTypesAndCaches(); } void QQmlTypeLoader::updateTypeCacheTrimThreshold() @@ -1988,6 +1985,8 @@ void QQmlTypeLoader::trimCache() updateTypeCacheTrimThreshold(); + QQmlMetaType::freeUnusedTypesAndCaches(); + // TODO: release any scripts which are no longer referenced by any types } @@ -2013,7 +2012,7 @@ QString QQmlTypeData::TypeReference::qualifiedName() const if (!prefix.isEmpty()) { result = prefix + QLatin1Char('.'); } - result.append(type->qmlTypeName()); + result.append(type.qmlTypeName()); return result; } @@ -2168,8 +2167,8 @@ static bool addTypeReferenceChecksumsToHash(const QList<QQmlTypeData::TypeRefere if (typeRef.typeData) { const auto unit = typeRef.typeData->compilationUnit(); hash->addData(unit->data->md5Checksum, sizeof(unit->data->md5Checksum)); - } else if (typeRef.type) { - const auto propertyCache = QQmlEnginePrivate::get(engine)->cache(typeRef.type->metaObject()); + } else if (typeRef.type.isValid()) { + const auto propertyCache = QQmlEnginePrivate::get(engine)->cache(typeRef.type.metaObject()); bool ok = false; hash->addData(propertyCache->checksum(&ok)); if (!ok) @@ -2233,7 +2232,7 @@ void QQmlTypeData::done() const TypeReference &type = m_compositeSingletons.at(ii); Q_ASSERT(!type.typeData || type.typeData->isCompleteOrError()); if (type.typeData && type.typeData->isError()) { - QString typeName = type.type->qmlTypeName(); + QString typeName = type.type.qmlTypeName(); QList<QQmlError> errors = type.typeData->errors(); QQmlError error; @@ -2300,24 +2299,24 @@ void QQmlTypeData::done() } { - QQmlType *type = QQmlMetaType::qmlType(finalUrl(), true); + QQmlType type = QQmlMetaType::qmlType(finalUrl(), true); if (m_compiledData && m_compiledData->data->flags & QV4::CompiledData::Unit::IsSingleton) { - if (!type) { + if (!type.isValid()) { QQmlError error; error.setDescription(QQmlTypeLoader::tr("No matching type found, pragma Singleton files cannot be used by QQmlComponent.")); setError(error); return; - } else if (!type->isCompositeSingleton()) { + } else if (!type.isCompositeSingleton()) { QQmlError error; - error.setDescription(QQmlTypeLoader::tr("pragma Singleton used with a non composite singleton type %1").arg(type->qmlTypeName())); + error.setDescription(QQmlTypeLoader::tr("pragma Singleton used with a non composite singleton type %1").arg(type.qmlTypeName())); setError(error); return; } } else { // If the type is CompositeSingleton but there was no pragma Singleton in the // QML file, lets report an error. - if (type && type->isCompositeSingleton()) { - QString typeName = type->qmlTypeName(); + if (type.isValid() && type.isCompositeSingleton()) { + QString typeName = type.qmlTypeName(); setError(QQmlTypeLoader::tr("qmldir defines type as singleton, but no pragma Singleton found in type %1.").arg(typeName)); return; } @@ -2609,8 +2608,8 @@ void QQmlTypeData::resolveTypes() if (!resolveType(typeName, majorVersion, minorVersion, ref)) return; - if (ref.type->isCompositeSingleton()) { - ref.typeData = typeLoader()->getType(ref.type->sourceUrl()); + if (ref.type.isCompositeSingleton()) { + ref.typeData = typeLoader()->getType(ref.type.sourceUrl()); addDependency(ref.typeData); ref.prefix = csRef.prefix; @@ -2637,8 +2636,8 @@ void QQmlTypeData::resolveTypes() if (!resolveType(name, majorVersion, minorVersion, ref, unresolvedRef->location.line, unresolvedRef->location.column, reportErrors) && reportErrors) return; - if (ref.type && ref.type->isComposite()) { - ref.typeData = typeLoader()->getType(ref.type->sourceUrl()); + if (ref.type.isComposite()) { + ref.typeData = typeLoader()->getType(ref.type.sourceUrl()); addDependency(ref.typeData); } ref.majorVersion = majorVersion; @@ -2669,7 +2668,7 @@ QQmlCompileError QQmlTypeData::buildTypeResolutionCaches( // Add any Composite Singletons that were used to the import cache for (const QQmlTypeData::TypeReference &singleton: m_compositeSingletons) - (*typeNameCache)->add(singleton.type->qmlTypeName(), singleton.type->sourceUrl(), singleton.prefix); + (*typeNameCache)->add(singleton.type.qmlTypeName(), singleton.type.sourceUrl(), singleton.prefix); m_importCache.populateCache(*typeNameCache); @@ -2677,24 +2676,24 @@ QQmlCompileError QQmlTypeData::buildTypeResolutionCaches( for (auto resolvedType = m_resolvedTypes.constBegin(), end = m_resolvedTypes.constEnd(); resolvedType != end; ++resolvedType) { QScopedPointer<QV4::CompiledData::ResolvedTypeReference> ref(new QV4::CompiledData::ResolvedTypeReference); - QQmlType *qmlType = resolvedType->type; + QQmlType qmlType = resolvedType->type; if (resolvedType->typeData) { - if (resolvedType->needsCreation && qmlType->isCompositeSingleton()) { - return QQmlCompileError(resolvedType->location, tr("Composite Singleton Type %1 is not creatable.").arg(qmlType->qmlTypeName())); + if (resolvedType->needsCreation && qmlType.isCompositeSingleton()) { + return QQmlCompileError(resolvedType->location, tr("Composite Singleton Type %1 is not creatable.").arg(qmlType.qmlTypeName())); } ref->compilationUnit = resolvedType->typeData->compilationUnit(); - } else if (qmlType) { + } else if (qmlType.isValid()) { ref->type = qmlType; - Q_ASSERT(ref->type); + Q_ASSERT(ref->type.isValid()); - if (resolvedType->needsCreation && !ref->type->isCreatable()) { - QString reason = ref->type->noCreationReason(); + if (resolvedType->needsCreation && !ref->type.isCreatable()) { + QString reason = ref->type.noCreationReason(); if (reason.isEmpty()) reason = tr("Element is not creatable."); return QQmlCompileError(resolvedType->location, reason); } - if (ref->type->containsRevisionedAttributes()) { + if (ref->type.containsRevisionedAttributes()) { ref->typePropertyCache = engine->cache(ref->type, resolvedType->minorVersion); } diff --git a/src/qml/qml/qqmltypeloader_p.h b/src/qml/qml/qqmltypeloader_p.h index f367fa6f58..05923f77e8 100644 --- a/src/qml/qml/qqmltypeloader_p.h +++ b/src/qml/qml/qqmltypeloader_p.h @@ -55,6 +55,7 @@ #include <QtCore/qobject.h> #include <QtCore/qatomic.h> #include <QtCore/qfileinfo.h> +#include <QtCore/qcache.h> #if QT_CONFIG(qml_network) #include <QtNetwork/qnetworkreply.h> #endif @@ -362,8 +363,7 @@ private: typedef QHash<QUrl, QQmlTypeData *> TypeCache; typedef QHash<QUrl, QQmlScriptBlob *> ScriptCache; typedef QHash<QUrl, QQmlQmldirData *> QmldirCache; - typedef QStringHash<bool> StringSet; - typedef QStringHash<StringSet*> ImportDirCache; + typedef QCache<QString, QCache<QString, bool> > ImportDirCache; typedef QStringHash<QQmlTypeLoaderQmldirContent *> ImportQmlDirCache; QQmlEngine *m_engine; @@ -393,10 +393,10 @@ class Q_AUTOTEST_EXPORT QQmlTypeData : public QQmlTypeLoader::Blob public: struct TypeReference { - TypeReference() : type(0), majorVersion(0), minorVersion(0), typeData(0), needsCreation(true) {} + TypeReference() : majorVersion(0), minorVersion(0), typeData(0), needsCreation(true) {} QV4::CompiledData::Location location; - QQmlType *type; + QQmlType type; int majorVersion; int minorVersion; QQmlTypeData *typeData; diff --git a/src/qml/qml/qqmltypenamecache.cpp b/src/qml/qml/qqmltypenamecache.cpp index 35ef8ada57..136614d332 100644 --- a/src/qml/qml/qqmltypenamecache.cpp +++ b/src/qml/qml/qqmltypenamecache.cpp @@ -55,7 +55,7 @@ QQmlTypeNameCache::~QQmlTypeNameCache() void QQmlTypeNameCache::add(const QHashedString &name, const QUrl &url, const QHashedString &nameSpace) { if (nameSpace.length() != 0) { - Import *i = m_namedImports.value(nameSpace); + QQmlImportRef *i = m_namedImports.value(nameSpace); Q_ASSERT(i != 0); i->compositeSingletons.insert(name, url); return; @@ -69,12 +69,12 @@ void QQmlTypeNameCache::add(const QHashedString &name, const QUrl &url, const QH void QQmlTypeNameCache::add(const QHashedString &name, int importedScriptIndex, const QHashedString &nameSpace) { - Import import; + QQmlImportRef import; import.scriptIndex = importedScriptIndex; import.m_qualifier = name; if (nameSpace.length() != 0) { - Import *i = m_namedImports.value(nameSpace); + QQmlImportRef *i = m_namedImports.value(nameSpace); Q_ASSERT(i != 0); m_namespacedImports[i].insert(name, import); return; @@ -100,7 +100,7 @@ QQmlTypeNameCache::Result QQmlTypeNameCache::query(const QHashedStringRef &name) // Look up anonymous types from the imports of this document QQmlImportNamespace *typeNamespace = 0; QList<QQmlError> errors; - QQmlType *t = 0; + QQmlType t; bool typeFound = m_imports.resolveType(name, &t, 0, 0, &typeNamespace, &errors); if (typeFound) { return Result(t); @@ -112,25 +112,23 @@ QQmlTypeNameCache::Result QQmlTypeNameCache::query(const QHashedStringRef &name) } QQmlTypeNameCache::Result QQmlTypeNameCache::query(const QHashedStringRef &name, - const void *importNamespace) const + const QQmlImportRef *importNamespace) const { - Q_ASSERT(importNamespace); - const Import *i = static_cast<const Import *>(importNamespace); - Q_ASSERT(i->scriptIndex == -1); + Q_ASSERT(importNamespace && importNamespace->scriptIndex == -1); - Result result = typeSearch(i->modules, name); + Result result = typeSearch(importNamespace->modules, name); if (!result.isValid()) - result = query(i->compositeSingletons, name); + result = query(importNamespace->compositeSingletons, name); if (!result.isValid()) { // Look up types from the imports of this document // ### it would be nice if QQmlImports allowed us to resolve a namespace // first, and then types on it. - QString qualifiedTypeName = i->m_qualifier + QLatin1Char('.') + name.toString(); + QString qualifiedTypeName = importNamespace->m_qualifier + QLatin1Char('.') + name.toString(); QQmlImportNamespace *typeNamespace = 0; QList<QQmlError> errors; - QQmlType *t = 0; + QQmlType t; bool typeFound = m_imports.resolveType(qualifiedTypeName, &t, 0, 0, &typeNamespace, &errors); if (typeFound) { return Result(t); @@ -155,7 +153,7 @@ QQmlTypeNameCache::Result QQmlTypeNameCache::query(const QV4::String *name, QQml QString typeName = name->toQStringNoThrow(); QQmlImportNamespace *typeNamespace = 0; QList<QQmlError> errors; - QQmlType *t = 0; + QQmlType t; bool typeFound = m_imports.resolveType(typeName, &t, 0, 0, &typeNamespace, &errors, recursionRestriction); if (typeFound) { return Result(t); @@ -166,32 +164,30 @@ QQmlTypeNameCache::Result QQmlTypeNameCache::query(const QV4::String *name, QQml return result; } -QQmlTypeNameCache::Result QQmlTypeNameCache::query(const QV4::String *name, const void *importNamespace) const +QQmlTypeNameCache::Result QQmlTypeNameCache::query(const QV4::String *name, const QQmlImportRef *importNamespace) const { - Q_ASSERT(importNamespace); - const Import *i = static_cast<const Import *>(importNamespace); - Q_ASSERT(i->scriptIndex == -1); + Q_ASSERT(importNamespace && importNamespace->scriptIndex == -1); - QMap<const Import *, QStringHash<Import> >::const_iterator it = m_namespacedImports.constFind(i); + QMap<const QQmlImportRef *, QStringHash<QQmlImportRef> >::const_iterator it = m_namespacedImports.constFind(importNamespace); if (it != m_namespacedImports.constEnd()) { Result r = query(*it, name); if (r.isValid()) return r; } - Result r = typeSearch(i->modules, name); + Result r = typeSearch(importNamespace->modules, name); if (!r.isValid()) - r = query(i->compositeSingletons, name); + r = query(importNamespace->compositeSingletons, name); if (!r.isValid()) { // Look up types from the imports of this document // ### it would be nice if QQmlImports allowed us to resolve a namespace // first, and then types on it. - QString qualifiedTypeName = i->m_qualifier + QLatin1Char('.') + name->toQStringNoThrow(); + QString qualifiedTypeName = importNamespace->m_qualifier + QLatin1Char('.') + name->toQStringNoThrow(); QQmlImportNamespace *typeNamespace = 0; QList<QQmlError> errors; - QQmlType *t = 0; + QQmlType t; bool typeFound = m_imports.resolveType(qualifiedTypeName, &t, 0, 0, &typeNamespace, &errors); if (typeFound) { return Result(t); diff --git a/src/qml/qml/qqmltypenamecache_p.h b/src/qml/qml/qqmltypenamecache_p.h index f7ba2a91b7..6e5cd0fb54 100644 --- a/src/qml/qml/qqmltypenamecache_p.h +++ b/src/qml/qml/qqmltypenamecache_p.h @@ -62,6 +62,23 @@ QT_BEGIN_NAMESPACE +struct QQmlImportRef { + inline QQmlImportRef() + : scriptIndex(-1) + {} + // Imported module + QVector<QQmlTypeModuleVersion> modules; + + // Or, imported script + int scriptIndex; + + // Or, imported compositeSingletons + QStringHash<QUrl> compositeSingletons; + + // The qualifier of this import + QString m_qualifier; +}; + class QQmlType; class QQmlEngine; class QQmlTypeNameCache : public QQmlRefCount @@ -77,50 +94,35 @@ public: struct Result { inline Result(); - inline Result(const void *importNamespace); - inline Result(QQmlType *type); + inline Result(const QQmlImportRef *importNamespace); + inline Result(const QQmlType &type); inline Result(int scriptIndex); inline Result(const Result &); inline bool isValid() const; - QQmlType *type; - const void *importNamespace; + QQmlType type; + const QQmlImportRef *importNamespace; int scriptIndex; }; Result query(const QHashedStringRef &) const; - Result query(const QHashedStringRef &, const void *importNamespace) const; + Result query(const QHashedStringRef &, const QQmlImportRef *importNamespace) const; Result query(const QV4::String *, QQmlImport::RecursionRestriction recursionRestriction = QQmlImport::PreventRecursion) const; - Result query(const QV4::String *, const void *importNamespace) const; + Result query(const QV4::String *, const QQmlImportRef *importNamespace) const; private: friend class QQmlImports; - struct Import { - inline Import(); - // Imported module - QVector<QQmlTypeModuleVersion> modules; - - // Or, imported script - int scriptIndex; - - // Or, imported compositeSingletons - QStringHash<QUrl> compositeSingletons; - - // The qualifier of this import - QString m_qualifier; - }; - template<typename Key> - Result query(const QStringHash<Import> &imports, Key key) const + Result query(const QStringHash<QQmlImportRef> &imports, Key key) const { - Import *i = imports.value(key); + QQmlImportRef *i = imports.value(key); if (i) { Q_ASSERT(!i->m_qualifier.isEmpty()); if (i->scriptIndex != -1) { return Result(i->scriptIndex); } else { - return Result(static_cast<const void *>(i)); + return Result(i); } } @@ -132,9 +134,8 @@ private: { QUrl *url = urls.value(key); if (url) { - QQmlType *type = QQmlMetaType::qmlType(*url); - if (type) - return Result(type); + QQmlType type = QQmlMetaType::qmlType(*url); + return Result(type); } return Result(); @@ -145,37 +146,38 @@ private: { QVector<QQmlTypeModuleVersion>::const_iterator end = modules.constEnd(); for (QVector<QQmlTypeModuleVersion>::const_iterator it = modules.constBegin(); it != end; ++it) { - if (QQmlType *type = it->type(key)) + QQmlType type = it->type(key); + if (type.isValid()) return Result(type); } return Result(); } - QStringHash<Import> m_namedImports; - QMap<const Import *, QStringHash<Import> > m_namespacedImports; + QStringHash<QQmlImportRef> m_namedImports; + QMap<const QQmlImportRef *, QStringHash<QQmlImportRef> > m_namespacedImports; QVector<QQmlTypeModuleVersion> m_anonymousImports; QStringHash<QUrl> m_anonymousCompositeSingletons; QQmlImports m_imports; }; QQmlTypeNameCache::Result::Result() -: type(0), importNamespace(0), scriptIndex(-1) +: importNamespace(0), scriptIndex(-1) { } -QQmlTypeNameCache::Result::Result(const void *importNamespace) -: type(0), importNamespace(importNamespace), scriptIndex(-1) +QQmlTypeNameCache::Result::Result(const QQmlImportRef *importNamespace) +: importNamespace(importNamespace), scriptIndex(-1) { } -QQmlTypeNameCache::Result::Result(QQmlType *type) +QQmlTypeNameCache::Result::Result(const QQmlType &type) : type(type), importNamespace(0), scriptIndex(-1) { } QQmlTypeNameCache::Result::Result(int scriptIndex) -: type(0), importNamespace(0), scriptIndex(scriptIndex) +: importNamespace(0), scriptIndex(scriptIndex) { } @@ -186,12 +188,7 @@ QQmlTypeNameCache::Result::Result(const Result &o) bool QQmlTypeNameCache::Result::isValid() const { - return type || importNamespace || scriptIndex != -1; -} - -QQmlTypeNameCache::Import::Import() -: scriptIndex(-1) -{ + return type.isValid() || importNamespace || scriptIndex != -1; } bool QQmlTypeNameCache::isEmpty() const diff --git a/src/qml/qml/qqmltypewrapper.cpp b/src/qml/qml/qqmltypewrapper.cpp index 7a06077c11..404bc0612e 100644 --- a/src/qml/qml/qqmltypewrapper.cpp +++ b/src/qml/qml/qqmltypewrapper.cpp @@ -64,15 +64,22 @@ void Heap::QQmlTypeWrapper::init() void Heap::QQmlTypeWrapper::destroy() { + QQmlType::derefHandle(typePrivate); + typePrivate = nullptr; if (typeNamespace) typeNamespace->release(); object.destroy(); Object::destroy(); } +QQmlType Heap::QQmlTypeWrapper::type() const +{ + return QQmlType(typePrivate); +} + bool QQmlTypeWrapper::isSingleton() const { - return d()->type && d()->type->isSingleton(); + return d()->type().isSingleton(); } QObject* QQmlTypeWrapper::singletonObject() const @@ -81,22 +88,16 @@ QObject* QQmlTypeWrapper::singletonObject() const return 0; QQmlEngine *e = engine()->qmlEngine(); - QQmlType::SingletonInstanceInfo *siinfo = d()->type->singletonInstanceInfo(); + QQmlType::SingletonInstanceInfo *siinfo = d()->type().singletonInstanceInfo(); siinfo->init(e); return siinfo->qobjectApi(e); } QVariant QQmlTypeWrapper::toVariant() const { - if (d()->type && d()->type->isSingleton()) { - QQmlEngine *e = engine()->qmlEngine(); - QQmlType::SingletonInstanceInfo *siinfo = d()->type->singletonInstanceInfo(); - siinfo->init(e); // note: this will also create QJSValue singleton which isn't strictly required. - QObject *qobjectSingleton = siinfo->qobjectApi(e); - if (qobjectSingleton) { - return QVariant::fromValue<QObject*>(qobjectSingleton); - } - } + QObject *qobjectSingleton = singletonObject(); + if (qobjectSingleton) + return QVariant::fromValue<QObject*>(qobjectSingleton); // only QObject Singleton Type can be converted to a variant. return QVariant(); @@ -104,20 +105,22 @@ QVariant QQmlTypeWrapper::toVariant() const // Returns a type wrapper for type t on o. This allows access of enums, and attached properties. -ReturnedValue QQmlTypeWrapper::create(QV4::ExecutionEngine *engine, QObject *o, QQmlType *t, +ReturnedValue QQmlTypeWrapper::create(QV4::ExecutionEngine *engine, QObject *o, const QQmlType &t, Heap::QQmlTypeWrapper::TypeNameMode mode) { - Q_ASSERT(t); + Q_ASSERT(t.isValid()); Scope scope(engine); Scoped<QQmlTypeWrapper> w(scope, engine->memoryManager->allocObject<QQmlTypeWrapper>()); - w->d()->mode = mode; w->d()->object = o; w->d()->type = t; + w->d()->mode = mode; w->d()->object = o; + w->d()->typePrivate = t.priv(); + QQmlType::refHandle(w->d()->typePrivate); return w.asReturnedValue(); } // Returns a type wrapper for importNamespace (of t) on o. This allows nested resolution of a type in a // namespace. -ReturnedValue QQmlTypeWrapper::create(QV4::ExecutionEngine *engine, QObject *o, QQmlTypeNameCache *t, const void *importNamespace, +ReturnedValue QQmlTypeWrapper::create(QV4::ExecutionEngine *engine, QObject *o, QQmlTypeNameCache *t, const QQmlImportRef *importNamespace, Heap::QQmlTypeWrapper::TypeNameMode mode) { Q_ASSERT(t); @@ -131,10 +134,10 @@ ReturnedValue QQmlTypeWrapper::create(QV4::ExecutionEngine *engine, QObject *o, } static int enumForSingleton(QV4::ExecutionEngine *v4, String *name, QObject *qobjectSingleton, - QQmlType *type) + const QQmlType &type) { bool ok; - int value = type->enumValue(QQmlEnginePrivate::get(v4->qmlEngine()), name, &ok); + int value = type.enumValue(QQmlEnginePrivate::get(v4->qmlEngine()), name, &ok); if (ok) return value; @@ -150,11 +153,11 @@ static int enumForSingleton(QV4::ExecutionEngine *v4, String *name, QObject *qob return -1; } -static ReturnedValue throwLowercaseEnumError(QV4::ExecutionEngine *v4, String *name, QQmlType *type) +static ReturnedValue throwLowercaseEnumError(QV4::ExecutionEngine *v4, String *name, const QQmlType &type) { const QString message = QStringLiteral("Cannot access enum value '%1' of '%2', enum values need to start with an uppercase letter.") - .arg(name->toQString()).arg(QLatin1String(type->typeName())); + .arg(name->toQString()).arg(QLatin1String(type.typeName())); return v4->throwTypeError(message); } @@ -173,14 +176,14 @@ ReturnedValue QQmlTypeWrapper::get(const Managed *m, String *name, bool *hasProp QQmlContextData *context = v4->callingQmlContext(); QObject *object = w->d()->object; - QQmlType *type = w->d()->type; + QQmlType type = w->d()->type(); - if (type) { + if (type.isValid()) { // singleton types are handled differently to other types. - if (type->isSingleton()) { + if (type.isSingleton()) { QQmlEngine *e = v4->qmlEngine(); - QQmlType::SingletonInstanceInfo *siinfo = type->singletonInstanceInfo(); + QQmlType::SingletonInstanceInfo *siinfo = type.singletonInstanceInfo(); siinfo->init(e); QObject *qobjectSingleton = siinfo->qobjectApi(e); @@ -221,14 +224,15 @@ ReturnedValue QQmlTypeWrapper::get(const Managed *m, String *name, bool *hasProp if (name->startsWithUpper()) { bool ok = false; - int value = type->enumValue(QQmlEnginePrivate::get(v4->qmlEngine()), name, &ok); + int value = type.enumValue(QQmlEnginePrivate::get(v4->qmlEngine()), name, &ok); if (ok) return QV4::Primitive::fromInt32(value).asReturnedValue(); - value = type->scopedEnumIndex(QQmlEnginePrivate::get(v4->qmlEngine()), name, &ok); + value = type.scopedEnumIndex(QQmlEnginePrivate::get(v4->qmlEngine()), name, &ok); if (ok) { Scoped<QQmlScopedEnumWrapper> enumWrapper(scope, v4->memoryManager->allocObject<QQmlScopedEnumWrapper>()); - enumWrapper->d()->type = type; + enumWrapper->d()->typePrivate = type.priv(); + QQmlType::refHandle(enumWrapper->d()->typePrivate); enumWrapper->d()->scopeEnumIndex = value; return enumWrapper.asReturnedValue(); } @@ -236,7 +240,7 @@ ReturnedValue QQmlTypeWrapper::get(const Managed *m, String *name, bool *hasProp // Fall through to base implementation } else if (w->d()->object) { - QObject *ao = qmlAttachedPropertiesObjectById(type->attachedPropertiesId(QQmlEnginePrivate::get(v4->qmlEngine())), object); + QObject *ao = qmlAttachedPropertiesObjectById(type.attachedPropertiesId(QQmlEnginePrivate::get(v4->qmlEngine())), object); if (ao) return QV4::QObjectWrapper::getQmlProperty(v4, context, ao, name, QV4::QObjectWrapper::IgnoreRevision, hasProperty); @@ -253,7 +257,7 @@ ReturnedValue QQmlTypeWrapper::get(const Managed *m, String *name, bool *hasProp QQmlTypeNameCache::Result r = w->d()->typeNamespace->query(name, w->d()->importNamespace); if (r.isValid()) { - if (r.type) { + if (r.type.isValid()) { return create(scope.engine, object, r.type, w->d()->mode); } else if (r.scriptIndex != -1) { QV4::ScopedObject scripts(scope, context->importedScripts.valueRef()); @@ -278,9 +282,9 @@ ReturnedValue QQmlTypeWrapper::get(const Managed *m, String *name, bool *hasProp *hasProperty = ok; // Warn when attempting to access a lowercased enum value, non-singleton case - if (!ok && type && !type->isSingleton() && !name->startsWithUpper()) { + if (!ok && type.isValid() && !type.isSingleton() && !name->startsWithUpper()) { bool enumOk = false; - type->enumValue(QQmlEnginePrivate::get(v4->qmlEngine()), name, &enumOk); + type.enumValue(QQmlEnginePrivate::get(v4->qmlEngine()), name, &enumOk); if (enumOk) return throwLowercaseEnumError(v4, name, type); } @@ -300,17 +304,17 @@ bool QQmlTypeWrapper::put(Managed *m, String *name, const Value &value) QV4::Scope scope(v4); QQmlContextData *context = v4->callingQmlContext(); - QQmlType *type = w->d()->type; - if (type && !type->isSingleton() && w->d()->object) { + QQmlType type = w->d()->type(); + if (type.isValid() && !type.isSingleton() && w->d()->object) { QObject *object = w->d()->object; QQmlEngine *e = scope.engine->qmlEngine(); - QObject *ao = qmlAttachedPropertiesObjectById(type->attachedPropertiesId(QQmlEnginePrivate::get(e)), object); + QObject *ao = qmlAttachedPropertiesObjectById(type.attachedPropertiesId(QQmlEnginePrivate::get(e)), object); if (ao) return QV4::QObjectWrapper::setQmlProperty(v4, context, ao, name, QV4::QObjectWrapper::IgnoreRevision, value); return false; - } else if (type && type->isSingleton()) { + } else if (type.isSingleton()) { QQmlEngine *e = scope.engine->qmlEngine(); - QQmlType::SingletonInstanceInfo *siinfo = type->singletonInstanceInfo(); + QQmlType::SingletonInstanceInfo *siinfo = type.singletonInstanceInfo(); siinfo->init(e); QObject *qobjectSingleton = siinfo->qobjectApi(e); @@ -368,7 +372,7 @@ ReturnedValue QQmlTypeWrapper::instanceOf(const Object *typeObject, const Value if (!wrapperObject) return engine->throwTypeError(); - const int myTypeId = typeWrapper->d()->type->typeId(); + const int myTypeId = typeWrapper->d()->type().typeId(); QQmlMetaObject myQmlType; if (myTypeId == 0) { // we're a composite type; a composite type cannot be equal to a @@ -379,7 +383,7 @@ ReturnedValue QQmlTypeWrapper::instanceOf(const Object *typeObject, const Value if (!theirDData->compilationUnit) return Encode(false); - QQmlTypeData *td = qenginepriv->typeLoader.getType(typeWrapper->d()->type->sourceUrl()); + QQmlTypeData *td = qenginepriv->typeLoader.getType(typeWrapper->d()->type().sourceUrl()); CompiledData::CompilationUnit *cu = td->compilationUnit(); myQmlType = qenginepriv->metaObjectForType(cu->metaTypeId); } else { @@ -391,6 +395,18 @@ ReturnedValue QQmlTypeWrapper::instanceOf(const Object *typeObject, const Value return QV4::Encode(QQmlMetaObject::canConvert(theirType, myQmlType)); } +void Heap::QQmlScopedEnumWrapper::destroy() +{ + QQmlType::derefHandle(typePrivate); + typePrivate = nullptr; + Object::destroy(); +} + +QQmlType Heap::QQmlScopedEnumWrapper::type() const +{ + return QQmlType(typePrivate); +} + ReturnedValue QQmlScopedEnumWrapper::get(const Managed *m, String *name, bool *hasProperty) { Q_ASSERT(m->as<QQmlScopedEnumWrapper>()); @@ -398,11 +414,11 @@ ReturnedValue QQmlScopedEnumWrapper::get(const Managed *m, String *name, bool *h QV4::ExecutionEngine *v4 = resource->engine(); QV4::Scope scope(v4); - QQmlType *type = resource->d()->type; + QQmlType type = resource->d()->type(); int index = resource->d()->scopeEnumIndex; bool ok = false; - int value = type->scopedEnumValue(QQmlEnginePrivate::get(v4->qmlEngine()), index, name, &ok); + int value = type.scopedEnumValue(QQmlEnginePrivate::get(v4->qmlEngine()), index, name, &ok); if (hasProperty) *hasProperty = ok; if (ok) diff --git a/src/qml/qml/qqmltypewrapper_p.h b/src/qml/qml/qqmltypewrapper_p.h index 730bfd6d12..bb65093163 100644 --- a/src/qml/qml/qqmltypewrapper_p.h +++ b/src/qml/qml/qqmltypewrapper_p.h @@ -76,16 +76,19 @@ struct QQmlTypeWrapper : Object { TypeNameMode mode; QQmlQPointer<QObject> object; - QQmlType *type; + QQmlType type() const; + + QQmlTypePrivate *typePrivate; QQmlTypeNameCache *typeNamespace; - const void *importNamespace; + const QQmlImportRef *importNamespace; }; struct QQmlScopedEnumWrapper : Object { void init() { Object::init(); } - void destroy() { Object::destroy(); } + void destroy(); int scopeEnumIndex; - QQmlType *type; + QQmlTypePrivate *typePrivate; + QQmlType type() const; }; } @@ -100,9 +103,9 @@ struct Q_QML_EXPORT QQmlTypeWrapper : Object QVariant toVariant() const; - static ReturnedValue create(ExecutionEngine *, QObject *, QQmlType *, + static ReturnedValue create(ExecutionEngine *, QObject *, const QQmlType &, Heap::QQmlTypeWrapper::TypeNameMode = Heap::QQmlTypeWrapper::IncludeEnums); - static ReturnedValue create(ExecutionEngine *, QObject *, QQmlTypeNameCache *, const void *, + static ReturnedValue create(ExecutionEngine *, QObject *, QQmlTypeNameCache *, const QQmlImportRef *, Heap::QQmlTypeWrapper::TypeNameMode = Heap::QQmlTypeWrapper::IncludeEnums); diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp index a2ab9bdfed..67f8ec840e 100644 --- a/src/qml/qml/qqmlvmemetaobject.cpp +++ b/src/qml/qml/qqmlvmemetaobject.cpp @@ -313,24 +313,25 @@ QAbstractDynamicMetaObject *QQmlInterceptorMetaObject::toDynamicMetaObject(QObje return this; } -QQmlVMEMetaObject::QQmlVMEMetaObject(QObject *obj, +QQmlVMEMetaObject::QQmlVMEMetaObject(QV4::ExecutionEngine *engine, + QObject *obj, QQmlPropertyCache *cache, QV4::CompiledData::CompilationUnit *qmlCompilationUnit, int qmlObjectId) : QQmlInterceptorMetaObject(obj, cache), + engine(engine), ctxt(QQmlData::get(obj, true)->outerContext), aliasEndpoints(0), compilationUnit(qmlCompilationUnit), compiledObject(0) { + Q_ASSERT(engine); QQmlData::get(obj)->hasVMEMetaObject = true; if (compilationUnit && qmlObjectId >= 0) { compiledObject = compilationUnit->data->objectAt(qmlObjectId); if (compiledObject->nProperties || compiledObject->nFunctions) { - Q_ASSERT(cache && cache->engine); - QV4::ExecutionEngine *v4 = cache->engine; uint size = compiledObject->nProperties + compiledObject->nFunctions; if (size) { - QV4::Heap::MemberData *data = QV4::MemberData::allocate(v4, size); - propertyAndMethodStorage.set(v4, data); + QV4::Heap::MemberData *data = QV4::MemberData::allocate(engine, size); + propertyAndMethodStorage.set(engine, data); std::fill(data->values.values, data->values.values + data->values.size, QV4::Encode::undefined()); } @@ -366,77 +367,77 @@ void QQmlVMEMetaObject::writeProperty(int id, int v) { QV4::MemberData *md = propertyAndMethodStorageAsMemberData(); if (md) - md->set(cache->engine, id, QV4::Primitive::fromInt32(v)); + md->set(engine, id, QV4::Primitive::fromInt32(v)); } void QQmlVMEMetaObject::writeProperty(int id, bool v) { QV4::MemberData *md = propertyAndMethodStorageAsMemberData(); if (md) - md->set(cache->engine, id, QV4::Primitive::fromBoolean(v)); + md->set(engine, id, QV4::Primitive::fromBoolean(v)); } void QQmlVMEMetaObject::writeProperty(int id, double v) { QV4::MemberData *md = propertyAndMethodStorageAsMemberData(); if (md) - md->set(cache->engine, id, QV4::Primitive::fromDouble(v)); + md->set(engine, id, QV4::Primitive::fromDouble(v)); } void QQmlVMEMetaObject::writeProperty(int id, const QString& v) { QV4::MemberData *md = propertyAndMethodStorageAsMemberData(); if (md) - md->set(cache->engine, id, cache->engine->newString(v)); + md->set(engine, id, engine->newString(v)); } void QQmlVMEMetaObject::writeProperty(int id, const QUrl& v) { QV4::MemberData *md = propertyAndMethodStorageAsMemberData(); if (md) - md->set(cache->engine, id, cache->engine->newVariantObject(QVariant::fromValue(v))); + md->set(engine, id, engine->newVariantObject(QVariant::fromValue(v))); } void QQmlVMEMetaObject::writeProperty(int id, const QDate& v) { QV4::MemberData *md = propertyAndMethodStorageAsMemberData(); if (md) - md->set(cache->engine, id, cache->engine->newVariantObject(QVariant::fromValue(v))); + md->set(engine, id, engine->newVariantObject(QVariant::fromValue(v))); } void QQmlVMEMetaObject::writeProperty(int id, const QDateTime& v) { QV4::MemberData *md = propertyAndMethodStorageAsMemberData(); if (md) - md->set(cache->engine, id, cache->engine->newVariantObject(QVariant::fromValue(v))); + md->set(engine, id, engine->newVariantObject(QVariant::fromValue(v))); } void QQmlVMEMetaObject::writeProperty(int id, const QPointF& v) { QV4::MemberData *md = propertyAndMethodStorageAsMemberData(); if (md) - md->set(cache->engine, id, cache->engine->newVariantObject(QVariant::fromValue(v))); + md->set(engine, id, engine->newVariantObject(QVariant::fromValue(v))); } void QQmlVMEMetaObject::writeProperty(int id, const QSizeF& v) { QV4::MemberData *md = propertyAndMethodStorageAsMemberData(); if (md) - md->set(cache->engine, id, cache->engine->newVariantObject(QVariant::fromValue(v))); + md->set(engine, id, engine->newVariantObject(QVariant::fromValue(v))); } void QQmlVMEMetaObject::writeProperty(int id, const QRectF& v) { QV4::MemberData *md = propertyAndMethodStorageAsMemberData(); if (md) - md->set(cache->engine, id, cache->engine->newVariantObject(QVariant::fromValue(v))); + md->set(engine, id, engine->newVariantObject(QVariant::fromValue(v))); } void QQmlVMEMetaObject::writeProperty(int id, QObject* v) { QV4::MemberData *md = propertyAndMethodStorageAsMemberData(); if (md) - md->set(cache->engine, id, QV4::Value::fromReturnedValue(QV4::QObjectWrapper::wrap(cache->engine, v))); + md->set(engine, id, QV4::Value::fromReturnedValue(QV4::QObjectWrapper::wrap(engine, v))); QQmlVMEVariantQObjectPtr *guard = getQObjectGuardForProperty(id); if (v && !guard) { @@ -453,7 +454,7 @@ int QQmlVMEMetaObject::readPropertyAsInt(int id) const if (!md) return 0; - QV4::Scope scope(cache->engine); + QV4::Scope scope(engine); QV4::ScopedValue sv(scope, *(md->data() + id)); if (!sv->isInt32()) return 0; @@ -466,7 +467,7 @@ bool QQmlVMEMetaObject::readPropertyAsBool(int id) const if (!md) return false; - QV4::Scope scope(cache->engine); + QV4::Scope scope(engine); QV4::ScopedValue sv(scope, *(md->data() + id)); if (!sv->isBoolean()) return false; @@ -479,7 +480,7 @@ double QQmlVMEMetaObject::readPropertyAsDouble(int id) const if (!md) return 0.0; - QV4::Scope scope(cache->engine); + QV4::Scope scope(engine); QV4::ScopedValue sv(scope, *(md->data() + id)); if (!sv->isDouble()) return 0.0; @@ -492,7 +493,7 @@ QString QQmlVMEMetaObject::readPropertyAsString(int id) const if (!md) return QString(); - QV4::Scope scope(cache->engine); + QV4::Scope scope(engine); QV4::ScopedValue sv(scope, *(md->data() + id)); if (QV4::String *s = sv->stringValue()) return s->toQString(); @@ -505,7 +506,7 @@ QUrl QQmlVMEMetaObject::readPropertyAsUrl(int id) const if (!md) return QUrl(); - QV4::Scope scope(cache->engine); + QV4::Scope scope(engine); QV4::ScopedValue sv(scope, *(md->data() + id)); const QV4::VariantObject *v = sv->as<QV4::VariantObject>(); if (!v || v->d()->data().type() != QVariant::Url) @@ -519,7 +520,7 @@ QDate QQmlVMEMetaObject::readPropertyAsDate(int id) const if (!md) return QDate(); - QV4::Scope scope(cache->engine); + QV4::Scope scope(engine); QV4::ScopedValue sv(scope, *(md->data() + id)); const QV4::VariantObject *v = sv->as<QV4::VariantObject>(); if (!v || v->d()->data().type() != QVariant::Date) @@ -533,7 +534,7 @@ QDateTime QQmlVMEMetaObject::readPropertyAsDateTime(int id) if (!md) return QDateTime(); - QV4::Scope scope(cache->engine); + QV4::Scope scope(engine); QV4::ScopedValue sv(scope, *(md->data() + id)); const QV4::VariantObject *v = sv->as<QV4::VariantObject>(); if (!v || v->d()->data().type() != QVariant::DateTime) @@ -547,7 +548,7 @@ QSizeF QQmlVMEMetaObject::readPropertyAsSizeF(int id) const if (!md) return QSizeF(); - QV4::Scope scope(cache->engine); + QV4::Scope scope(engine); QV4::ScopedValue sv(scope, *(md->data() + id)); const QV4::VariantObject *v = sv->as<QV4::VariantObject>(); if (!v || v->d()->data().type() != QVariant::SizeF) @@ -561,7 +562,7 @@ QPointF QQmlVMEMetaObject::readPropertyAsPointF(int id) const if (!md) return QPointF(); - QV4::Scope scope(cache->engine); + QV4::Scope scope(engine); QV4::ScopedValue sv(scope, *(md->data() + id)); const QV4::VariantObject *v = sv->as<QV4::VariantObject>(); if (!v || v->d()->data().type() != QVariant::PointF) @@ -575,7 +576,7 @@ QObject* QQmlVMEMetaObject::readPropertyAsQObject(int id) const if (!md) return 0; - QV4::Scope scope(cache->engine); + QV4::Scope scope(engine); QV4::ScopedValue sv(scope, *(md->data() + id)); const QV4::QObjectWrapper *wrapper = sv->as<QV4::QObjectWrapper>(); if (!wrapper) @@ -589,12 +590,12 @@ QList<QObject *> *QQmlVMEMetaObject::readPropertyAsList(int id) const if (!md) return 0; - QV4::Scope scope(cache->engine); + QV4::Scope scope(engine); QV4::Scoped<QV4::VariantObject> v(scope, *(md->data() + id)); if (!v || (int)v->d()->data().userType() != qMetaTypeId<QList<QObject *> >()) { QVariant variant(qVariantFromValue(QList<QObject*>())); - v = cache->engine->newVariantObject(variant); - md->set(cache->engine, id, v); + v = engine->newVariantObject(variant); + md->set(engine, id, v); } return static_cast<QList<QObject *> *>(v->d()->data().data()); } @@ -605,7 +606,7 @@ QRectF QQmlVMEMetaObject::readPropertyAsRectF(int id) const if (!md) return QRectF(); - QV4::Scope scope(cache->engine); + QV4::Scope scope(engine); QV4::ScopedValue sv(scope, *(md->data() + id)); const QV4::VariantObject *v = sv->as<QV4::VariantObject>(); if (!v || v->d()->data().type() != QVariant::RectF) @@ -819,7 +820,7 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void * if (QV4::MemberData *md = propertyAndMethodStorageAsMemberData()) { const QV4::VariantObject *v = (md->data() + id)->as<QV4::VariantObject>(); if (!v) { - md->set(cache->engine, id, cache->engine->newVariantObject(QVariant())); + md->set(engine, id, engine->newVariantObject(QVariant())); v = (md->data() + id)->as<QV4::VariantObject>(); QQml_valueTypeProvider()->initValueType(fallbackMetaType, v->d()->data()); } @@ -1015,7 +1016,7 @@ QVariant QQmlVMEMetaObject::readPropertyAsVariant(int id) const const QV4::VariantObject *v = (md->data() + id)->as<QV4::VariantObject>(); if (v) return v->d()->data(); - return cache->engine->toVariant(*(md->data() + id), -1); + return engine->toVariant(*(md->data() + id), -1); } return QVariant(); } @@ -1056,7 +1057,7 @@ void QQmlVMEMetaObject::writeVarProperty(int id, const QV4::Value &value) guard->setGuardedValue(valueObject, this, id); // Write the value and emit change signal as appropriate. - md->set(cache->engine, id, value); + md->set(engine, id, value); activate(object, methodOffset() + id, 0); } @@ -1075,15 +1076,15 @@ void QQmlVMEMetaObject::writeProperty(int id, const QVariant &value) // And, if the new value is a scarce resource, we need to ensure that it does not get // automatically released by the engine until no other references to it exist. - QV4::Scope scope(cache->engine); - QV4::ScopedValue newv(scope, cache->engine->fromVariant(value)); + QV4::Scope scope(engine); + QV4::ScopedValue newv(scope, engine->fromVariant(value)); QV4::Scoped<QV4::VariantObject> v(scope, newv); if (!!v) v->addVmePropertyReference(); // Write the value and emit change signal as appropriate. QVariant currentValue = readPropertyAsVariant(id); - md->set(cache->engine, id, newv); + md->set(engine, id, newv); if ((currentValue.userType() != value.userType() || currentValue != value)) activate(object, methodOffset() + id, 0); } else { @@ -1101,7 +1102,7 @@ void QQmlVMEMetaObject::writeProperty(int id, const QVariant &value) v->d()->data() != value); if (v) v->removeVmePropertyReference(); - md->set(cache->engine, id, cache->engine->newVariantObject(value)); + md->set(engine, id, engine->newVariantObject(value)); v = static_cast<const QV4::VariantObject *>(md->data() + id); v->addVmePropertyReference(); } @@ -1141,7 +1142,7 @@ void QQmlVMEMetaObject::setVmeMethod(int index, const QV4::Value &function) QV4::MemberData *md = propertyAndMethodStorageAsMemberData(); if (!md) return; - md->set(cache->engine, methodIndex + compiledObject->nProperties, function); + md->set(engine, methodIndex + compiledObject->nProperties, function); } QV4::ReturnedValue QQmlVMEMetaObject::vmeProperty(int index) const @@ -1165,15 +1166,13 @@ void QQmlVMEMetaObject::setVMEProperty(int index, const QV4::Value &v) void QQmlVMEMetaObject::ensureQObjectWrapper() { - Q_ASSERT(cache && cache->engine); - QV4::ExecutionEngine *v4 = cache->engine; - QV4::QObjectWrapper::wrap(v4, object); + Q_ASSERT(cache); + QV4::QObjectWrapper::wrap(engine, object); } void QQmlVMEMetaObject::mark(QV4::MarkStack *markStack) { - QV4::ExecutionEngine *v4 = cache ? cache->engine : 0; - if (v4 != markStack->engine) + if (engine != markStack->engine) return; propertyAndMethodStorage.markOnce(markStack); diff --git a/src/qml/qml/qqmlvmemetaobject_p.h b/src/qml/qml/qqmlvmemetaobject_p.h index 031a9a9ddd..ea5e9c0904 100644 --- a/src/qml/qml/qqmlvmemetaobject_p.h +++ b/src/qml/qml/qqmlvmemetaobject_p.h @@ -144,7 +144,7 @@ class QQmlVMEMetaObjectEndpoint; class Q_QML_PRIVATE_EXPORT QQmlVMEMetaObject : public QQmlInterceptorMetaObject { public: - QQmlVMEMetaObject(QObject *obj, QQmlPropertyCache *cache, QV4::CompiledData::CompilationUnit *qmlCompilationUnit, int qmlObjectId); + QQmlVMEMetaObject(QV4::ExecutionEngine *engine, QObject *obj, QQmlPropertyCache *cache, QV4::CompiledData::CompilationUnit *qmlCompilationUnit, int qmlObjectId); ~QQmlVMEMetaObject(); bool aliasTarget(int index, QObject **target, int *coreIndex, int *valueTypeIndex) const; @@ -164,6 +164,7 @@ protected: int metaCall(QObject *o, QMetaObject::Call _c, int _id, void **_a) Q_DECL_OVERRIDE; public: + QV4::ExecutionEngine *engine; QQmlGuardedContextData ctxt; inline int propOffset() const; diff --git a/src/qml/types/qqmldelegatemodel.cpp b/src/qml/types/qqmldelegatemodel.cpp index 9620df6af9..d54bdeede6 100644 --- a/src/qml/types/qqmldelegatemodel.cpp +++ b/src/qml/types/qqmldelegatemodel.cpp @@ -941,7 +941,7 @@ QObject *QQmlDelegateModelPrivate::object(Compositor::Group group, int index, bo QQmlDelegateModelItem *cacheItem = it->inCache() ? m_cache.at(it.cacheIndex) : 0; if (!cacheItem) { - cacheItem = m_adaptorModel.createItem(m_cacheMetaType, m_context->engine(), it.modelIndex()); + cacheItem = m_adaptorModel.createItem(m_cacheMetaType, it.modelIndex()); if (!cacheItem) return 0; @@ -1623,7 +1623,7 @@ bool QQmlDelegateModelPrivate::insert(Compositor::insert_iterator &before, const if (!m_context || !m_context->isValid()) return false; - QQmlDelegateModelItem *cacheItem = m_adaptorModel.createItem(m_cacheMetaType, m_context->engine(), -1); + QQmlDelegateModelItem *cacheItem = m_adaptorModel.createItem(m_cacheMetaType, -1); if (!cacheItem) return false; if (!object.isObject()) @@ -2450,7 +2450,7 @@ QQmlV4Handle QQmlDelegateModelGroup::get(int index) if (!cacheItem) { cacheItem = model->m_adaptorModel.createItem( - model->m_cacheMetaType, model->m_context->engine(), it.modelIndex()); + model->m_cacheMetaType, it.modelIndex()); if (!cacheItem) return QQmlV4Handle(QV4::Encode::undefined()); cacheItem->groups = it->flags; diff --git a/src/qml/util/qqmladaptormodel.cpp b/src/qml/util/qqmladaptormodel.cpp index b9f6ea461a..11fed281b7 100644 --- a/src/qml/util/qqmladaptormodel.cpp +++ b/src/qml/util/qqmladaptormodel.cpp @@ -515,16 +515,15 @@ public: QQmlDelegateModelItem *createItem( QQmlAdaptorModel &model, QQmlDelegateModelItemMetaType *metaType, - QQmlEngine *engine, int index) const override { VDMAbstractItemModelDataType *dataType = const_cast<VDMAbstractItemModelDataType *>(this); if (!metaObject) - dataType->initializeMetaType(model, engine); + dataType->initializeMetaType(model); return new QQmlDMAbstractItemModelData(metaType, dataType, index); } - void initializeMetaType(QQmlAdaptorModel &model, QQmlEngine *engine) + void initializeMetaType(QQmlAdaptorModel &model) { QMetaObjectBuilder builder; setModelDataType<QQmlDMAbstractItemModelData>(&builder, this); @@ -549,7 +548,7 @@ public: metaObject = builder.toMetaObject(); *static_cast<QMetaObject *>(this) = *metaObject; - propertyCache = new QQmlPropertyCache(QV8Engine::getV4(engine), metaObject); + propertyCache = new QQmlPropertyCache(metaObject); } }; @@ -661,7 +660,6 @@ public: QQmlDelegateModelItem *createItem( QQmlAdaptorModel &model, QQmlDelegateModelItemMetaType *metaType, - QQmlEngine *, int index) const override { return new QQmlDMListAccessorData( @@ -746,7 +744,6 @@ public: QQmlDelegateModelItem *createItem( QQmlAdaptorModel &model, QQmlDelegateModelItemMetaType *metaType, - QQmlEngine *, int index) const override { VDMObjectDelegateDataType *dataType = const_cast<VDMObjectDelegateDataType *>(this); diff --git a/src/qml/util/qqmladaptormodel_p.h b/src/qml/util/qqmladaptormodel_p.h index 78d964236e..7bbddcff07 100644 --- a/src/qml/util/qqmladaptormodel_p.h +++ b/src/qml/util/qqmladaptormodel_p.h @@ -82,7 +82,6 @@ public: virtual QQmlDelegateModelItem *createItem( QQmlAdaptorModel &, QQmlDelegateModelItemMetaType *, - QQmlEngine *, int) const { return 0; } virtual bool notify( @@ -122,8 +121,8 @@ public: inline int count() const { return qMax(0, accessors->count(*this)); } inline QVariant value(int index, const QString &role) const { return accessors->value(*this, index, role); } - inline QQmlDelegateModelItem *createItem(QQmlDelegateModelItemMetaType *metaType, QQmlEngine *engine, int index) { - return accessors->createItem(*this, metaType, engine, index); } + inline QQmlDelegateModelItem *createItem(QQmlDelegateModelItemMetaType *metaType, int index) { + return accessors->createItem(*this, metaType, index); } inline bool hasProxyObject() const { return list.type() == QQmlListAccessor::Instance || list.type() == QQmlListAccessor::ListProperty; } |