Avoid unnecessary re-generation qml cache files in some circumstances
The map of name IDs to resolved types so far is copied several times during compilation and different compile passes see different copies of it. Compile passes may add things to the map, and if they do that on copies that are inaccessible to other code, we get nondeterministic results. Furthermore all the copies and pointers are confusing and inefficient. Fixes: QTBUG-69340 Change-Id: I43ad3cbeeec34f90e05570eddc901fe8aa64c709 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
This commit is contained in:
parent
2131ec383b
commit
06ec6340d0
|
@ -150,7 +150,7 @@ inline QQmlCompileError QQmlPropertyCacheCreator<ObjectContainer>::buildMetaObje
|
||||||
if (context.instantiatingProperty && QQmlValueTypeFactory::isValueType(context.instantiatingProperty->propType())) {
|
if (context.instantiatingProperty && QQmlValueTypeFactory::isValueType(context.instantiatingProperty->propType())) {
|
||||||
if (!propertyCaches->needsVMEMetaObject(context.referencingObjectIndex)) {
|
if (!propertyCaches->needsVMEMetaObject(context.referencingObjectIndex)) {
|
||||||
const CompiledObject *obj = objectContainer->objectAt(context.referencingObjectIndex);
|
const CompiledObject *obj = objectContainer->objectAt(context.referencingObjectIndex);
|
||||||
auto *typeRef = objectContainer->resolvedTypes.value(obj->inheritedTypeNameIndex);
|
auto *typeRef = objectContainer->resolvedType(obj->inheritedTypeNameIndex);
|
||||||
Q_ASSERT(typeRef);
|
Q_ASSERT(typeRef);
|
||||||
QQmlRefPointer<QQmlPropertyCache> baseTypeCache = typeRef->createPropertyCache(QQmlEnginePrivate::get(enginePrivate));
|
QQmlRefPointer<QQmlPropertyCache> baseTypeCache = typeRef->createPropertyCache(QQmlEnginePrivate::get(enginePrivate));
|
||||||
QQmlCompileError error = createMetaObject(context.referencingObjectIndex, obj, baseTypeCache);
|
QQmlCompileError error = createMetaObject(context.referencingObjectIndex, obj, baseTypeCache);
|
||||||
|
@ -214,7 +214,7 @@ inline QQmlRefPointer<QQmlPropertyCache> QQmlPropertyCacheCreator<ObjectContaine
|
||||||
if (context.instantiatingProperty) {
|
if (context.instantiatingProperty) {
|
||||||
return context.instantiatingPropertyCache(enginePrivate);
|
return context.instantiatingPropertyCache(enginePrivate);
|
||||||
} else if (obj->inheritedTypeNameIndex != 0) {
|
} else if (obj->inheritedTypeNameIndex != 0) {
|
||||||
auto *typeRef = objectContainer->resolvedTypes.value(obj->inheritedTypeNameIndex);
|
auto *typeRef = objectContainer->resolvedType(obj->inheritedTypeNameIndex);
|
||||||
Q_ASSERT(typeRef);
|
Q_ASSERT(typeRef);
|
||||||
|
|
||||||
if (typeRef->isFullyDynamicType) {
|
if (typeRef->isFullyDynamicType) {
|
||||||
|
@ -234,7 +234,8 @@ inline QQmlRefPointer<QQmlPropertyCache> QQmlPropertyCacheCreator<ObjectContaine
|
||||||
|
|
||||||
return typeRef->createPropertyCache(QQmlEnginePrivate::get(enginePrivate));
|
return typeRef->createPropertyCache(QQmlEnginePrivate::get(enginePrivate));
|
||||||
} else if (context.instantiatingBinding && context.instantiatingBinding->isAttachedProperty()) {
|
} else if (context.instantiatingBinding && context.instantiatingBinding->isAttachedProperty()) {
|
||||||
auto *typeRef = objectContainer->resolvedTypes.value(context.instantiatingBinding->propertyNameIndex);
|
auto *typeRef = objectContainer->resolvedType(
|
||||||
|
context.instantiatingBinding->propertyNameIndex);
|
||||||
Q_ASSERT(typeRef);
|
Q_ASSERT(typeRef);
|
||||||
QQmlType qmltype = typeRef->type;
|
QQmlType qmltype = typeRef->type;
|
||||||
if (!qmltype.isValid()) {
|
if (!qmltype.isValid()) {
|
||||||
|
@ -709,7 +710,7 @@ inline QQmlCompileError QQmlPropertyCacheAliasCreator<ObjectContainer>::property
|
||||||
return propertyDataForAlias(component, *targetAlias, type, minorVersion, propertyFlags);
|
return propertyDataForAlias(component, *targetAlias, type, minorVersion, propertyFlags);
|
||||||
} else if (alias.encodedMetaPropertyIndex == -1) {
|
} else if (alias.encodedMetaPropertyIndex == -1) {
|
||||||
Q_ASSERT(alias.flags & QV4::CompiledData::Alias::AliasPointsToPointerObject);
|
Q_ASSERT(alias.flags & QV4::CompiledData::Alias::AliasPointsToPointerObject);
|
||||||
auto *typeRef = objectContainer->resolvedTypes.value(targetObject.inheritedTypeNameIndex);
|
auto *typeRef = objectContainer->resolvedType(targetObject.inheritedTypeNameIndex);
|
||||||
if (!typeRef) {
|
if (!typeRef) {
|
||||||
// Can be caused by the alias target not being a valid id or property. E.g.:
|
// Can be caused by the alias target not being a valid id or property. E.g.:
|
||||||
// property alias dataValue: dataVal
|
// property alias dataValue: dataVal
|
||||||
|
|
|
@ -50,7 +50,6 @@ QQmlPropertyValidator::QQmlPropertyValidator(QQmlEnginePrivate *enginePrivate, c
|
||||||
, compilationUnit(compilationUnit)
|
, compilationUnit(compilationUnit)
|
||||||
, imports(imports)
|
, imports(imports)
|
||||||
, qmlUnit(compilationUnit->unitData())
|
, qmlUnit(compilationUnit->unitData())
|
||||||
, resolvedTypes(compilationUnit->resolvedTypes)
|
|
||||||
, propertyCaches(compilationUnit->propertyCaches)
|
, propertyCaches(compilationUnit->propertyCaches)
|
||||||
, bindingPropertyDataPerObject(&compilationUnit->bindingPropertyDataPerObject)
|
, bindingPropertyDataPerObject(&compilationUnit->bindingPropertyDataPerObject)
|
||||||
{
|
{
|
||||||
|
@ -96,7 +95,7 @@ QVector<QQmlCompileError> QQmlPropertyValidator::validateObject(int objectIndex,
|
||||||
return QVector<QQmlCompileError>();
|
return QVector<QQmlCompileError>();
|
||||||
|
|
||||||
QQmlCustomParser *customParser = nullptr;
|
QQmlCustomParser *customParser = nullptr;
|
||||||
if (auto typeRef = resolvedTypes.value(obj->inheritedTypeNameIndex)) {
|
if (auto typeRef = resolvedType(obj->inheritedTypeNameIndex)) {
|
||||||
if (typeRef->type.isValid())
|
if (typeRef->type.isValid())
|
||||||
customParser = typeRef->type.customParser();
|
customParser = typeRef->type.customParser();
|
||||||
}
|
}
|
||||||
|
@ -168,7 +167,7 @@ QVector<QQmlCompileError> QQmlPropertyValidator::validateObject(int objectIndex,
|
||||||
|
|
||||||
if (notInRevision) {
|
if (notInRevision) {
|
||||||
QString typeName = stringAt(obj->inheritedTypeNameIndex);
|
QString typeName = stringAt(obj->inheritedTypeNameIndex);
|
||||||
auto *objectType = resolvedTypes.value(obj->inheritedTypeNameIndex);
|
auto *objectType = resolvedType(obj->inheritedTypeNameIndex);
|
||||||
if (objectType && objectType->type.isValid()) {
|
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));
|
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 {
|
} else {
|
||||||
|
@ -633,7 +632,7 @@ QQmlCompileError QQmlPropertyValidator::validateObjectBinding(QQmlPropertyData *
|
||||||
bool isPropertyInterceptor = false;
|
bool isPropertyInterceptor = false;
|
||||||
|
|
||||||
const QV4::CompiledData::Object *targetObject = compilationUnit->objectAt(binding->value.objectIndex);
|
const QV4::CompiledData::Object *targetObject = compilationUnit->objectAt(binding->value.objectIndex);
|
||||||
if (auto *typeRef = resolvedTypes.value(targetObject->inheritedTypeNameIndex)) {
|
if (auto *typeRef = resolvedType(targetObject->inheritedTypeNameIndex)) {
|
||||||
QQmlRefPointer<QQmlPropertyCache> cache = typeRef->createPropertyCache(QQmlEnginePrivate::get(enginePrivate));
|
QQmlRefPointer<QQmlPropertyCache> cache = typeRef->createPropertyCache(QQmlEnginePrivate::get(enginePrivate));
|
||||||
const QMetaObject *mo = cache->firstCppMetaObject();
|
const QMetaObject *mo = cache->firstCppMetaObject();
|
||||||
QQmlType qmlType;
|
QQmlType qmlType;
|
||||||
|
|
|
@ -72,12 +72,15 @@ private:
|
||||||
Q_REQUIRED_RESULT QVector<QQmlCompileError> recordError(const QV4::CompiledData::Location &location, const QString &description) const;
|
Q_REQUIRED_RESULT QVector<QQmlCompileError> recordError(const QV4::CompiledData::Location &location, const QString &description) const;
|
||||||
Q_REQUIRED_RESULT QVector<QQmlCompileError> recordError(const QQmlCompileError &error) const;
|
Q_REQUIRED_RESULT QVector<QQmlCompileError> recordError(const QQmlCompileError &error) const;
|
||||||
QString stringAt(int index) const { return compilationUnit->stringAt(index); }
|
QString stringAt(int index) const { return compilationUnit->stringAt(index); }
|
||||||
|
QV4::CompiledData::ResolvedTypeReference *resolvedType(int id) const
|
||||||
|
{
|
||||||
|
return compilationUnit->resolvedType(id);
|
||||||
|
}
|
||||||
|
|
||||||
QQmlEnginePrivate *enginePrivate;
|
QQmlEnginePrivate *enginePrivate;
|
||||||
QQmlRefPointer<QV4::CompiledData::CompilationUnit> compilationUnit;
|
QQmlRefPointer<QV4::CompiledData::CompilationUnit> compilationUnit;
|
||||||
const QQmlImports &imports;
|
const QQmlImports &imports;
|
||||||
const QV4::CompiledData::Unit *qmlUnit;
|
const QV4::CompiledData::Unit *qmlUnit;
|
||||||
const QV4::CompiledData::ResolvedTypeReferenceMap &resolvedTypes;
|
|
||||||
const QQmlPropertyCacheVector &propertyCaches;
|
const QQmlPropertyCacheVector &propertyCaches;
|
||||||
|
|
||||||
QVector<QV4::CompiledData::BindingPropertyData> * const bindingPropertyDataPerObject;
|
QVector<QV4::CompiledData::BindingPropertyData> * const bindingPropertyDataPerObject;
|
||||||
|
|
|
@ -56,7 +56,7 @@ QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
QQmlTypeCompiler::QQmlTypeCompiler(QQmlEnginePrivate *engine, QQmlTypeData *typeData,
|
QQmlTypeCompiler::QQmlTypeCompiler(QQmlEnginePrivate *engine, QQmlTypeData *typeData,
|
||||||
QmlIR::Document *parsedQML, const QQmlRefPointer<QQmlTypeNameCache> &typeNameCache,
|
QmlIR::Document *parsedQML, const QQmlRefPointer<QQmlTypeNameCache> &typeNameCache,
|
||||||
const QV4::CompiledData::ResolvedTypeReferenceMap &resolvedTypeCache, const QV4::CompiledData::DependentTypesHasher &dependencyHasher)
|
QV4::CompiledData::ResolvedTypeReferenceMap *resolvedTypeCache, const QV4::CompiledData::DependentTypesHasher &dependencyHasher)
|
||||||
: resolvedTypes(resolvedTypeCache)
|
: resolvedTypes(resolvedTypeCache)
|
||||||
, engine(engine)
|
, engine(engine)
|
||||||
, typeData(typeData)
|
, typeData(typeData)
|
||||||
|
@ -70,7 +70,7 @@ QQmlRefPointer<QV4::CompiledData::CompilationUnit> QQmlTypeCompiler::compile()
|
||||||
{
|
{
|
||||||
// Build property caches and VME meta object data
|
// Build property caches and VME meta object data
|
||||||
|
|
||||||
for (auto it = resolvedTypes.constBegin(), end = resolvedTypes.constEnd();
|
for (auto it = resolvedTypes->constBegin(), end = resolvedTypes->constEnd();
|
||||||
it != end; ++it) {
|
it != end; ++it) {
|
||||||
QQmlCustomParser *customParser = (*it)->type.customParser();
|
QQmlCustomParser *customParser = (*it)->type.customParser();
|
||||||
if (customParser)
|
if (customParser)
|
||||||
|
@ -161,9 +161,8 @@ QQmlRefPointer<QV4::CompiledData::CompilationUnit> QQmlTypeCompiler::compile()
|
||||||
qmlGenerator.generate(*document, dependencyHasher);
|
qmlGenerator.generate(*document, dependencyHasher);
|
||||||
|
|
||||||
QQmlRefPointer<QV4::CompiledData::CompilationUnit> compilationUnit = document->javaScriptCompilationUnit;
|
QQmlRefPointer<QV4::CompiledData::CompilationUnit> compilationUnit = document->javaScriptCompilationUnit;
|
||||||
compilationUnit = document->javaScriptCompilationUnit;
|
|
||||||
compilationUnit->typeNameCache = typeNameCache;
|
compilationUnit->typeNameCache = typeNameCache;
|
||||||
compilationUnit->resolvedTypes = resolvedTypes;
|
compilationUnit->resolvedTypes = *resolvedTypes;
|
||||||
compilationUnit->propertyCaches = std::move(m_propertyCaches);
|
compilationUnit->propertyCaches = std::move(m_propertyCaches);
|
||||||
Q_ASSERT(compilationUnit->propertyCaches.count() == static_cast<int>(compilationUnit->objectCount()));
|
Q_ASSERT(compilationUnit->propertyCaches.count() == static_cast<int>(compilationUnit->objectCount()));
|
||||||
|
|
||||||
|
@ -300,7 +299,6 @@ SignalHandlerConverter::SignalHandlerConverter(QQmlTypeCompiler *typeCompiler)
|
||||||
, qmlObjects(*typeCompiler->qmlObjects())
|
, qmlObjects(*typeCompiler->qmlObjects())
|
||||||
, imports(typeCompiler->imports())
|
, imports(typeCompiler->imports())
|
||||||
, customParsers(typeCompiler->customParserCache())
|
, customParsers(typeCompiler->customParserCache())
|
||||||
, resolvedTypes(typeCompiler->resolvedTypes)
|
|
||||||
, illegalNames(typeCompiler->enginePrivate()->v8engine()->illegalNames())
|
, illegalNames(typeCompiler->enginePrivate()->v8engine()->illegalNames())
|
||||||
, propertyCaches(typeCompiler->propertyCaches())
|
, propertyCaches(typeCompiler->propertyCaches())
|
||||||
{
|
{
|
||||||
|
@ -334,7 +332,7 @@ bool SignalHandlerConverter::convertSignalHandlerExpressionsToFunctionDeclaratio
|
||||||
// Attached property?
|
// Attached property?
|
||||||
if (binding->type == QV4::CompiledData::Binding::Type_AttachedProperty) {
|
if (binding->type == QV4::CompiledData::Binding::Type_AttachedProperty) {
|
||||||
const QmlIR::Object *attachedObj = qmlObjects.at(binding->value.objectIndex);
|
const QmlIR::Object *attachedObj = qmlObjects.at(binding->value.objectIndex);
|
||||||
auto *typeRef = resolvedTypes.value(binding->propertyNameIndex);
|
auto *typeRef = resolvedType(binding->propertyNameIndex);
|
||||||
QQmlType type = typeRef ? typeRef->type : QQmlType();
|
QQmlType type = typeRef ? typeRef->type : QQmlType();
|
||||||
if (!type.isValid()) {
|
if (!type.isValid()) {
|
||||||
if (imports->resolveType(propertyName, &type, nullptr, nullptr, nullptr)) {
|
if (imports->resolveType(propertyName, &type, nullptr, nullptr, nullptr)) {
|
||||||
|
@ -405,7 +403,7 @@ bool SignalHandlerConverter::convertSignalHandlerExpressionsToFunctionDeclaratio
|
||||||
|
|
||||||
const QString &originalPropertyName = stringAt(binding->propertyNameIndex);
|
const QString &originalPropertyName = stringAt(binding->propertyNameIndex);
|
||||||
|
|
||||||
auto *typeRef = resolvedTypes.value(obj->inheritedTypeNameIndex);
|
auto *typeRef = resolvedType(obj->inheritedTypeNameIndex);
|
||||||
const QQmlType type = typeRef ? typeRef->type : QQmlType();
|
const QQmlType type = typeRef ? typeRef->type : QQmlType();
|
||||||
if (type.isValid()) {
|
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()));
|
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()));
|
||||||
|
@ -506,7 +504,6 @@ QQmlEnumTypeResolver::QQmlEnumTypeResolver(QQmlTypeCompiler *typeCompiler)
|
||||||
, qmlObjects(*typeCompiler->qmlObjects())
|
, qmlObjects(*typeCompiler->qmlObjects())
|
||||||
, propertyCaches(typeCompiler->propertyCaches())
|
, propertyCaches(typeCompiler->propertyCaches())
|
||||||
, imports(typeCompiler->imports())
|
, imports(typeCompiler->imports())
|
||||||
, resolvedTypes(&typeCompiler->resolvedTypes)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -618,7 +615,7 @@ bool QQmlEnumTypeResolver::tryQualifiedEnumAssignment(const QmlIR::Object *obj,
|
||||||
int value = 0;
|
int value = 0;
|
||||||
bool ok = false;
|
bool ok = false;
|
||||||
|
|
||||||
auto *tr = resolvedTypes->value(obj->inheritedTypeNameIndex);
|
auto *tr = resolvedType(obj->inheritedTypeNameIndex);
|
||||||
if (type.isValid() && tr && tr->type == type) {
|
if (type.isValid() && tr && tr->type == type) {
|
||||||
// When these two match, we can short cut the search
|
// When these two match, we can short cut the search
|
||||||
QMetaProperty mprop = propertyCache->firstCppMetaObject()->property(prop->coreIndex());
|
QMetaProperty mprop = propertyCache->firstCppMetaObject()->property(prop->coreIndex());
|
||||||
|
@ -785,7 +782,6 @@ QQmlComponentAndAliasResolver::QQmlComponentAndAliasResolver(QQmlTypeCompiler *t
|
||||||
, enginePrivate(typeCompiler->enginePrivate())
|
, enginePrivate(typeCompiler->enginePrivate())
|
||||||
, pool(typeCompiler->memoryPool())
|
, pool(typeCompiler->memoryPool())
|
||||||
, qmlObjects(typeCompiler->qmlObjects())
|
, qmlObjects(typeCompiler->qmlObjects())
|
||||||
, resolvedTypes(&typeCompiler->resolvedTypes)
|
|
||||||
, propertyCaches(std::move(typeCompiler->takePropertyCaches()))
|
, propertyCaches(std::move(typeCompiler->takePropertyCaches()))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -803,7 +799,7 @@ void QQmlComponentAndAliasResolver::findAndRegisterImplicitComponents(const QmlI
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const QmlIR::Object *targetObject = qmlObjects->at(binding->value.objectIndex);
|
const QmlIR::Object *targetObject = qmlObjects->at(binding->value.objectIndex);
|
||||||
auto *tr = resolvedTypes->value(targetObject->inheritedTypeNameIndex);
|
auto *tr = resolvedType(targetObject->inheritedTypeNameIndex);
|
||||||
Q_ASSERT(tr);
|
Q_ASSERT(tr);
|
||||||
|
|
||||||
const QMetaObject *firstMetaObject = nullptr;
|
const QMetaObject *firstMetaObject = nullptr;
|
||||||
|
@ -854,12 +850,12 @@ void QQmlComponentAndAliasResolver::findAndRegisterImplicitComponents(const QmlI
|
||||||
syntheticComponent->location = binding->valueLocation;
|
syntheticComponent->location = binding->valueLocation;
|
||||||
syntheticComponent->flags |= QV4::CompiledData::Object::IsComponent;
|
syntheticComponent->flags |= QV4::CompiledData::Object::IsComponent;
|
||||||
|
|
||||||
if (!resolvedTypes->contains(syntheticComponent->inheritedTypeNameIndex)) {
|
if (!containsResolvedType(syntheticComponent->inheritedTypeNameIndex)) {
|
||||||
auto typeRef = new QV4::CompiledData::ResolvedTypeReference;
|
auto typeRef = new QV4::CompiledData::ResolvedTypeReference;
|
||||||
typeRef->type = componentType;
|
typeRef->type = componentType;
|
||||||
typeRef->majorVersion = componentType.majorVersion();
|
typeRef->majorVersion = componentType.majorVersion();
|
||||||
typeRef->minorVersion = componentType.minorVersion();
|
typeRef->minorVersion = componentType.minorVersion();
|
||||||
resolvedTypes->insert(syntheticComponent->inheritedTypeNameIndex, typeRef);
|
insertResolvedType(syntheticComponent->inheritedTypeNameIndex, typeRef);
|
||||||
}
|
}
|
||||||
|
|
||||||
qmlObjects->append(syntheticComponent);
|
qmlObjects->append(syntheticComponent);
|
||||||
|
@ -897,7 +893,7 @@ bool QQmlComponentAndAliasResolver::resolve()
|
||||||
bool isExplicitComponent = false;
|
bool isExplicitComponent = false;
|
||||||
|
|
||||||
if (obj->inheritedTypeNameIndex) {
|
if (obj->inheritedTypeNameIndex) {
|
||||||
auto *tref = resolvedTypes->value(obj->inheritedTypeNameIndex);
|
auto *tref = resolvedType(obj->inheritedTypeNameIndex);
|
||||||
Q_ASSERT(tref);
|
Q_ASSERT(tref);
|
||||||
if (tref->type.metaObject() == &QQmlComponent::staticMetaObject)
|
if (tref->type.metaObject() == &QQmlComponent::staticMetaObject)
|
||||||
isExplicitComponent = true;
|
isExplicitComponent = true;
|
||||||
|
@ -1300,7 +1296,6 @@ bool QQmlDeferredAndCustomParserBindingScanner::scanObject(int objectIndex)
|
||||||
|
|
||||||
QQmlJSCodeGenerator::QQmlJSCodeGenerator(QQmlTypeCompiler *typeCompiler, QmlIR::JSCodeGen *v4CodeGen)
|
QQmlJSCodeGenerator::QQmlJSCodeGenerator(QQmlTypeCompiler *typeCompiler, QmlIR::JSCodeGen *v4CodeGen)
|
||||||
: QQmlCompilePass(typeCompiler)
|
: QQmlCompilePass(typeCompiler)
|
||||||
, resolvedTypes(typeCompiler->resolvedTypes)
|
|
||||||
, customParsers(typeCompiler->customParserCache())
|
, customParsers(typeCompiler->customParserCache())
|
||||||
, qmlObjects(*typeCompiler->qmlObjects())
|
, qmlObjects(*typeCompiler->qmlObjects())
|
||||||
, propertyCaches(typeCompiler->propertyCaches())
|
, propertyCaches(typeCompiler->propertyCaches())
|
||||||
|
@ -1339,7 +1334,7 @@ bool QQmlJSCodeGenerator::compileComponent(int contextObject)
|
||||||
m.idIndex = obj->id;
|
m.idIndex = obj->id;
|
||||||
m.type = propertyCaches->at(objectIndex);
|
m.type = propertyCaches->at(objectIndex);
|
||||||
|
|
||||||
auto *tref = resolvedTypes.value(obj->inheritedTypeNameIndex);
|
auto *tref = resolvedType(obj->inheritedTypeNameIndex);
|
||||||
if (tref && tref->isFullyDynamicType)
|
if (tref && tref->isFullyDynamicType)
|
||||||
m.type = nullptr;
|
m.type = nullptr;
|
||||||
|
|
||||||
|
|
|
@ -79,7 +79,9 @@ struct QQmlTypeCompiler
|
||||||
{
|
{
|
||||||
Q_DECLARE_TR_FUNCTIONS(QQmlTypeCompiler)
|
Q_DECLARE_TR_FUNCTIONS(QQmlTypeCompiler)
|
||||||
public:
|
public:
|
||||||
QQmlTypeCompiler(QQmlEnginePrivate *engine, QQmlTypeData *typeData, QmlIR::Document *document, const QQmlRefPointer<QQmlTypeNameCache> &typeNameCache, const QV4::CompiledData::ResolvedTypeReferenceMap &resolvedTypeCache,
|
QQmlTypeCompiler(QQmlEnginePrivate *engine, QQmlTypeData *typeData, QmlIR::Document *document,
|
||||||
|
const QQmlRefPointer<QQmlTypeNameCache> &typeNameCache,
|
||||||
|
QV4::CompiledData::ResolvedTypeReferenceMap *resolvedTypeCache,
|
||||||
const QV4::CompiledData::DependentTypesHasher &dependencyHasher);
|
const QV4::CompiledData::DependentTypesHasher &dependencyHasher);
|
||||||
|
|
||||||
// --- interface used by QQmlPropertyCacheCreator
|
// --- interface used by QQmlPropertyCacheCreator
|
||||||
|
@ -89,7 +91,7 @@ public:
|
||||||
QString stringAt(int idx) const;
|
QString stringAt(int idx) const;
|
||||||
QmlIR::PoolList<QmlIR::Function>::Iterator objectFunctionsBegin(const QmlIR::Object *object) const { return object->functionsBegin(); }
|
QmlIR::PoolList<QmlIR::Function>::Iterator objectFunctionsBegin(const QmlIR::Object *object) const { return object->functionsBegin(); }
|
||||||
QmlIR::PoolList<QmlIR::Function>::Iterator objectFunctionsEnd(const QmlIR::Object *object) const { return object->functionsEnd(); }
|
QmlIR::PoolList<QmlIR::Function>::Iterator objectFunctionsEnd(const QmlIR::Object *object) const { return object->functionsEnd(); }
|
||||||
QV4::CompiledData::ResolvedTypeReferenceMap resolvedTypes;
|
QV4::CompiledData::ResolvedTypeReferenceMap *resolvedTypes = nullptr;
|
||||||
// ---
|
// ---
|
||||||
|
|
||||||
QQmlRefPointer<QV4::CompiledData::CompilationUnit> compile();
|
QQmlRefPointer<QV4::CompiledData::CompilationUnit> compile();
|
||||||
|
@ -124,6 +126,11 @@ public:
|
||||||
|
|
||||||
void addImport(const QString &module, const QString &qualifier, int majorVersion, int minorVersion);
|
void addImport(const QString &module, const QString &qualifier, int majorVersion, int minorVersion);
|
||||||
|
|
||||||
|
QV4::CompiledData::ResolvedTypeReference *resolvedType(int id) const
|
||||||
|
{
|
||||||
|
return resolvedTypes->value(id);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QList<QQmlError> errors;
|
QList<QQmlError> errors;
|
||||||
QQmlEnginePrivate *engine;
|
QQmlEnginePrivate *engine;
|
||||||
|
@ -150,6 +157,14 @@ protected:
|
||||||
void recordError(const QQmlCompileError &error)
|
void recordError(const QQmlCompileError &error)
|
||||||
{ compiler->recordError(error); }
|
{ compiler->recordError(error); }
|
||||||
|
|
||||||
|
QV4::CompiledData::ResolvedTypeReference *resolvedType(int id) const
|
||||||
|
{ return compiler->resolvedType(id); }
|
||||||
|
bool containsResolvedType(int id) const
|
||||||
|
{ return compiler->resolvedTypes->contains(id); }
|
||||||
|
QV4::CompiledData::ResolvedTypeReferenceMap::iterator insertResolvedType(
|
||||||
|
int id, QV4::CompiledData::ResolvedTypeReference *value)
|
||||||
|
{ return compiler->resolvedTypes->insert(id, value); }
|
||||||
|
|
||||||
QQmlTypeCompiler *compiler;
|
QQmlTypeCompiler *compiler;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -172,7 +187,6 @@ private:
|
||||||
const QVector<QmlIR::Object*> &qmlObjects;
|
const QVector<QmlIR::Object*> &qmlObjects;
|
||||||
const QQmlImports *imports;
|
const QQmlImports *imports;
|
||||||
const QHash<int, QQmlCustomParser*> &customParsers;
|
const QHash<int, QQmlCustomParser*> &customParsers;
|
||||||
const QV4::CompiledData::ResolvedTypeReferenceMap &resolvedTypes;
|
|
||||||
const QSet<QString> &illegalNames;
|
const QSet<QString> &illegalNames;
|
||||||
const QQmlPropertyCacheVector * const propertyCaches;
|
const QQmlPropertyCacheVector * const propertyCaches;
|
||||||
};
|
};
|
||||||
|
@ -203,7 +217,6 @@ private:
|
||||||
const QVector<QmlIR::Object*> &qmlObjects;
|
const QVector<QmlIR::Object*> &qmlObjects;
|
||||||
const QQmlPropertyCacheVector * const propertyCaches;
|
const QQmlPropertyCacheVector * const propertyCaches;
|
||||||
const QQmlImports *imports;
|
const QQmlImports *imports;
|
||||||
QV4::CompiledData::ResolvedTypeReferenceMap *resolvedTypes;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class QQmlCustomParserScriptIndexer: public QQmlCompilePass
|
class QQmlCustomParserScriptIndexer: public QQmlCompilePass
|
||||||
|
@ -278,7 +291,6 @@ protected:
|
||||||
QMap<int, int> _idToObjectIndex;
|
QMap<int, int> _idToObjectIndex;
|
||||||
QVector<int> _objectsWithAliases;
|
QVector<int> _objectsWithAliases;
|
||||||
|
|
||||||
QV4::CompiledData::ResolvedTypeReferenceMap *resolvedTypes;
|
|
||||||
QQmlPropertyCacheVector propertyCaches;
|
QQmlPropertyCacheVector propertyCaches;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -311,7 +323,6 @@ private:
|
||||||
bool compileComponent(int componentRoot);
|
bool compileComponent(int componentRoot);
|
||||||
bool compileJavaScriptCodeInObjectsRecursively(int objectIndex, int scopeObjectIndex);
|
bool compileJavaScriptCodeInObjectsRecursively(int objectIndex, int scopeObjectIndex);
|
||||||
|
|
||||||
const QV4::CompiledData::ResolvedTypeReferenceMap &resolvedTypes;
|
|
||||||
const QHash<int, QQmlCustomParser*> &customParsers;
|
const QHash<int, QQmlCustomParser*> &customParsers;
|
||||||
const QVector<QmlIR::Object*> &qmlObjects;
|
const QVector<QmlIR::Object*> &qmlObjects;
|
||||||
const QQmlPropertyCacheVector * const propertyCaches;
|
const QQmlPropertyCacheVector * const propertyCaches;
|
||||||
|
|
|
@ -1175,6 +1175,7 @@ public:
|
||||||
|
|
||||||
QVector<QQmlRefPointer<QQmlScriptData>> dependentScripts;
|
QVector<QQmlRefPointer<QQmlScriptData>> dependentScripts;
|
||||||
ResolvedTypeReferenceMap resolvedTypes;
|
ResolvedTypeReferenceMap resolvedTypes;
|
||||||
|
ResolvedTypeReference *resolvedType(int id) const { return resolvedTypes.value(id); }
|
||||||
|
|
||||||
bool verifyChecksum(const DependentTypesHasher &dependencyHasher) const;
|
bool verifyChecksum(const DependentTypesHasher &dependencyHasher) const;
|
||||||
|
|
||||||
|
|
|
@ -75,7 +75,6 @@ QQmlObjectCreator::QQmlObjectCreator(QQmlContextData *parentContext, const QQmlR
|
||||||
QQmlIncubatorPrivate *incubator)
|
QQmlIncubatorPrivate *incubator)
|
||||||
: phase(Startup)
|
: phase(Startup)
|
||||||
, compilationUnit(compilationUnit)
|
, compilationUnit(compilationUnit)
|
||||||
, resolvedTypes(compilationUnit->resolvedTypes)
|
|
||||||
, propertyCaches(&compilationUnit->propertyCaches)
|
, propertyCaches(&compilationUnit->propertyCaches)
|
||||||
, sharedState(new QQmlObjectCreatorSharedState)
|
, sharedState(new QQmlObjectCreatorSharedState)
|
||||||
, topLevelCreator(true)
|
, topLevelCreator(true)
|
||||||
|
@ -102,7 +101,6 @@ QQmlObjectCreator::QQmlObjectCreator(QQmlContextData *parentContext, const QQmlR
|
||||||
QQmlObjectCreator::QQmlObjectCreator(QQmlContextData *parentContext, const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit, QQmlObjectCreatorSharedState *inheritedSharedState)
|
QQmlObjectCreator::QQmlObjectCreator(QQmlContextData *parentContext, const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit, QQmlObjectCreatorSharedState *inheritedSharedState)
|
||||||
: phase(Startup)
|
: phase(Startup)
|
||||||
, compilationUnit(compilationUnit)
|
, compilationUnit(compilationUnit)
|
||||||
, resolvedTypes(compilationUnit->resolvedTypes)
|
|
||||||
, propertyCaches(&compilationUnit->propertyCaches)
|
, propertyCaches(&compilationUnit->propertyCaches)
|
||||||
, sharedState(inheritedSharedState)
|
, sharedState(inheritedSharedState)
|
||||||
, topLevelCreator(false)
|
, topLevelCreator(false)
|
||||||
|
@ -785,7 +783,7 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *bindingProper
|
||||||
{
|
{
|
||||||
if (binding->type == QV4::CompiledData::Binding::Type_AttachedProperty) {
|
if (binding->type == QV4::CompiledData::Binding::Type_AttachedProperty) {
|
||||||
Q_ASSERT(stringAt(compilationUnit->objectAt(binding->value.objectIndex)->inheritedTypeNameIndex).isEmpty());
|
Q_ASSERT(stringAt(compilationUnit->objectAt(binding->value.objectIndex)->inheritedTypeNameIndex).isEmpty());
|
||||||
QV4::CompiledData::ResolvedTypeReference *tr = resolvedTypes.value(binding->propertyNameIndex);
|
QV4::CompiledData::ResolvedTypeReference *tr = resolvedType(binding->propertyNameIndex);
|
||||||
Q_ASSERT(tr);
|
Q_ASSERT(tr);
|
||||||
QQmlType attachedType = tr->type;
|
QQmlType attachedType = tr->type;
|
||||||
if (!attachedType.isValid()) {
|
if (!attachedType.isValid()) {
|
||||||
|
@ -1151,7 +1149,8 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
|
||||||
instance = component;
|
instance = component;
|
||||||
ddata = QQmlData::get(instance, /*create*/true);
|
ddata = QQmlData::get(instance, /*create*/true);
|
||||||
} else {
|
} else {
|
||||||
QV4::CompiledData::ResolvedTypeReference *typeRef = resolvedTypes.value(obj->inheritedTypeNameIndex);
|
QV4::CompiledData::ResolvedTypeReference *typeRef
|
||||||
|
= resolvedType(obj->inheritedTypeNameIndex);
|
||||||
Q_ASSERT(typeRef);
|
Q_ASSERT(typeRef);
|
||||||
installPropertyCache = !typeRef->isFullyDynamicType;
|
installPropertyCache = !typeRef->isFullyDynamicType;
|
||||||
QQmlType type = typeRef->type;
|
QQmlType type = typeRef->type;
|
||||||
|
|
|
@ -125,6 +125,10 @@ private:
|
||||||
|
|
||||||
inline QV4::QmlContext *currentQmlContext();
|
inline QV4::QmlContext *currentQmlContext();
|
||||||
Q_NEVER_INLINE void createQmlContext();
|
Q_NEVER_INLINE void createQmlContext();
|
||||||
|
QV4::CompiledData::ResolvedTypeReference *resolvedType(int id) const
|
||||||
|
{
|
||||||
|
return compilationUnit->resolvedType(id);
|
||||||
|
}
|
||||||
|
|
||||||
enum Phase {
|
enum Phase {
|
||||||
Startup,
|
Startup,
|
||||||
|
@ -141,7 +145,6 @@ private:
|
||||||
const QV4::CompiledData::Unit *qmlUnit;
|
const QV4::CompiledData::Unit *qmlUnit;
|
||||||
QQmlGuardedContextData parentContext;
|
QQmlGuardedContextData parentContext;
|
||||||
QQmlContextData *context;
|
QQmlContextData *context;
|
||||||
const QV4::CompiledData::ResolvedTypeReferenceMap &resolvedTypes;
|
|
||||||
const QQmlPropertyCacheVector *propertyCaches;
|
const QQmlPropertyCacheVector *propertyCaches;
|
||||||
QExplicitlySharedDataPointer<QQmlObjectCreatorSharedState> sharedState;
|
QExplicitlySharedDataPointer<QQmlObjectCreatorSharedState> sharedState;
|
||||||
bool topLevelCreator;
|
bool topLevelCreator;
|
||||||
|
|
|
@ -2348,7 +2348,7 @@ void QQmlTypeData::done()
|
||||||
|
|
||||||
QQmlEngine *const engine = typeLoader()->engine();
|
QQmlEngine *const engine = typeLoader()->engine();
|
||||||
|
|
||||||
const auto dependencyHasher = [engine, resolvedTypeCache, this](QCryptographicHash *hash) {
|
const auto dependencyHasher = [engine, &resolvedTypeCache, this](QCryptographicHash *hash) {
|
||||||
if (!resolvedTypeCache.addToHash(hash, engine))
|
if (!resolvedTypeCache.addToHash(hash, engine))
|
||||||
return false;
|
return false;
|
||||||
return ::addTypeReferenceChecksumsToHash(m_compositeSingletons, hash, engine);
|
return ::addTypeReferenceChecksumsToHash(m_compositeSingletons, hash, engine);
|
||||||
|
@ -2365,7 +2365,7 @@ void QQmlTypeData::done()
|
||||||
|
|
||||||
if (!m_document.isNull()) {
|
if (!m_document.isNull()) {
|
||||||
// Compile component
|
// Compile component
|
||||||
compile(typeNameCache, resolvedTypeCache, dependencyHasher);
|
compile(typeNameCache, &resolvedTypeCache, dependencyHasher);
|
||||||
} else {
|
} else {
|
||||||
createTypeAndPropertyCaches(typeNameCache, resolvedTypeCache);
|
createTypeAndPropertyCaches(typeNameCache, resolvedTypeCache);
|
||||||
}
|
}
|
||||||
|
@ -2638,7 +2638,8 @@ QString QQmlTypeData::stringAt(int index) const
|
||||||
return m_document->jsGenerator.stringTable.stringForIndex(index);
|
return m_document->jsGenerator.stringTable.stringForIndex(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QQmlTypeData::compile(const QQmlRefPointer<QQmlTypeNameCache> &typeNameCache, const QV4::CompiledData::ResolvedTypeReferenceMap &resolvedTypeCache,
|
void QQmlTypeData::compile(const QQmlRefPointer<QQmlTypeNameCache> &typeNameCache,
|
||||||
|
QV4::CompiledData::ResolvedTypeReferenceMap *resolvedTypeCache,
|
||||||
const QV4::CompiledData::DependentTypesHasher &dependencyHasher)
|
const QV4::CompiledData::DependentTypesHasher &dependencyHasher)
|
||||||
{
|
{
|
||||||
Q_ASSERT(m_compiledData.isNull());
|
Q_ASSERT(m_compiledData.isNull());
|
||||||
|
|
|
@ -485,7 +485,8 @@ private:
|
||||||
QV4::CompiledData::ResolvedTypeReferenceMap *resolvedTypeCache
|
QV4::CompiledData::ResolvedTypeReferenceMap *resolvedTypeCache
|
||||||
) const;
|
) const;
|
||||||
void compile(const QQmlRefPointer<QQmlTypeNameCache> &typeNameCache,
|
void compile(const QQmlRefPointer<QQmlTypeNameCache> &typeNameCache,
|
||||||
const QV4::CompiledData::ResolvedTypeReferenceMap &resolvedTypeCache, const QV4::CompiledData::DependentTypesHasher &dependencyHasher);
|
QV4::CompiledData::ResolvedTypeReferenceMap *resolvedTypeCache,
|
||||||
|
const QV4::CompiledData::DependentTypesHasher &dependencyHasher);
|
||||||
void createTypeAndPropertyCaches(const QQmlRefPointer<QQmlTypeNameCache> &typeNameCache,
|
void createTypeAndPropertyCaches(const QQmlRefPointer<QQmlTypeNameCache> &typeNameCache,
|
||||||
const QV4::CompiledData::ResolvedTypeReferenceMap &resolvedTypeCache);
|
const QV4::CompiledData::ResolvedTypeReferenceMap &resolvedTypeCache);
|
||||||
bool resolveType(const QString &typeName, int &majorVersion, int &minorVersion,
|
bool resolveType(const QString &typeName, int &majorVersion, int &minorVersion,
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
import QtQml 2.2
|
||||||
|
|
||||||
|
QtObject {
|
||||||
|
property Component some: QtObject {
|
||||||
|
property int rrr: 2
|
||||||
|
property Component onemore: QtObject {
|
||||||
|
property int brrrr: -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -55,6 +55,7 @@ private slots:
|
||||||
void redirect();
|
void redirect();
|
||||||
void qmlSingletonWithinModule();
|
void qmlSingletonWithinModule();
|
||||||
void multiSingletonModule();
|
void multiSingletonModule();
|
||||||
|
void implicitComponentModule();
|
||||||
};
|
};
|
||||||
|
|
||||||
void tst_QQMLTypeLoader::testLoadComplete()
|
void tst_QQMLTypeLoader::testLoadComplete()
|
||||||
|
@ -446,6 +447,31 @@ void tst_QQMLTypeLoader::qmlSingletonWithinModule()
|
||||||
QVERIFY(obj->property("ok").toBool());
|
QVERIFY(obj->property("ok").toBool());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void checkCleanCacheLoad(const QString &testCase)
|
||||||
|
{
|
||||||
|
#if QT_CONFIG(process)
|
||||||
|
const char *skipKey = "QT_TST_QQMLTYPELOADER_SKIP_MISMATCH";
|
||||||
|
if (qEnvironmentVariableIsSet(skipKey))
|
||||||
|
return;
|
||||||
|
for (int i = 0; i < 5; ++i) {
|
||||||
|
QProcess child;
|
||||||
|
child.setProgram(QCoreApplication::applicationFilePath());
|
||||||
|
child.setArguments(QStringList(testCase));
|
||||||
|
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
|
||||||
|
env.insert(QLatin1String("QT_LOGGING_RULES"), QLatin1String("qt.qml.diskcache.debug=true"));
|
||||||
|
env.insert(QLatin1String(skipKey), QLatin1String("1"));
|
||||||
|
child.setProcessEnvironment(env);
|
||||||
|
child.start();
|
||||||
|
QVERIFY(child.waitForFinished());
|
||||||
|
QCOMPARE(child.exitCode(), 0);
|
||||||
|
QVERIFY(!child.readAllStandardOutput().contains("Checksum mismatch for cached version"));
|
||||||
|
QVERIFY(!child.readAllStandardError().contains("Checksum mismatch for cached version"));
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
Q_UNUSED(testCase);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void tst_QQMLTypeLoader::multiSingletonModule()
|
void tst_QQMLTypeLoader::multiSingletonModule()
|
||||||
{
|
{
|
||||||
qmlClearTypeRegistrations();
|
qmlClearTypeRegistrations();
|
||||||
|
@ -463,25 +489,18 @@ void tst_QQMLTypeLoader::multiSingletonModule()
|
||||||
QVERIFY(!obj.isNull());
|
QVERIFY(!obj.isNull());
|
||||||
QVERIFY(obj->property("ok").toBool());
|
QVERIFY(obj->property("ok").toBool());
|
||||||
|
|
||||||
#if QT_CONFIG(process)
|
checkCleanCacheLoad(QLatin1String("multiSingletonModule"));
|
||||||
const char *skipKey = "QT_TST_QQMLTYPELOADER_SKIP_MISMATCH";
|
}
|
||||||
if (qEnvironmentVariableIsSet(skipKey))
|
|
||||||
return;
|
void tst_QQMLTypeLoader::implicitComponentModule()
|
||||||
for (int i = 0; i < 5; ++i) {
|
{
|
||||||
QProcess child;
|
QQmlEngine engine;
|
||||||
child.setProgram(QCoreApplication::applicationFilePath());
|
QQmlComponent component(&engine, testFileUrl("implicitcomponent.qml"));
|
||||||
child.setArguments(QStringList(QLatin1String("multiSingletonModule")));
|
QCOMPARE(component.status(), QQmlComponent::Ready);
|
||||||
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
|
QScopedPointer<QObject> obj(component.create());
|
||||||
env.insert(QLatin1String("QT_LOGGING_RULES"), QLatin1String("qt.qml.diskcache.debug=true"));
|
QVERIFY(!obj.isNull());
|
||||||
env.insert(QLatin1String(skipKey), QLatin1String("1"));
|
|
||||||
child.setProcessEnvironment(env);
|
checkCleanCacheLoad(QLatin1String("implicitComponentModule"));
|
||||||
child.start();
|
|
||||||
QVERIFY(child.waitForFinished());
|
|
||||||
QCOMPARE(child.exitCode(), 0);
|
|
||||||
QVERIFY(!child.readAllStandardOutput().contains("Checksum mismatch for cached version"));
|
|
||||||
QVERIFY(!child.readAllStandardError().contains("Checksum mismatch for cached version"));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QTEST_MAIN(tst_QQMLTypeLoader)
|
QTEST_MAIN(tst_QQMLTypeLoader)
|
||||||
|
|
Loading…
Reference in New Issue