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:
Ulf Hermann 2019-02-18 14:24:45 +01:00
parent 2131ec383b
commit 06ec6340d0
12 changed files with 102 additions and 59 deletions

View File

@ -150,7 +150,7 @@ inline QQmlCompileError QQmlPropertyCacheCreator<ObjectContainer>::buildMetaObje
if (context.instantiatingProperty && QQmlValueTypeFactory::isValueType(context.instantiatingProperty->propType())) {
if (!propertyCaches->needsVMEMetaObject(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);
QQmlRefPointer<QQmlPropertyCache> baseTypeCache = typeRef->createPropertyCache(QQmlEnginePrivate::get(enginePrivate));
QQmlCompileError error = createMetaObject(context.referencingObjectIndex, obj, baseTypeCache);
@ -214,7 +214,7 @@ inline QQmlRefPointer<QQmlPropertyCache> QQmlPropertyCacheCreator<ObjectContaine
if (context.instantiatingProperty) {
return context.instantiatingPropertyCache(enginePrivate);
} else if (obj->inheritedTypeNameIndex != 0) {
auto *typeRef = objectContainer->resolvedTypes.value(obj->inheritedTypeNameIndex);
auto *typeRef = objectContainer->resolvedType(obj->inheritedTypeNameIndex);
Q_ASSERT(typeRef);
if (typeRef->isFullyDynamicType) {
@ -234,7 +234,8 @@ inline QQmlRefPointer<QQmlPropertyCache> QQmlPropertyCacheCreator<ObjectContaine
return typeRef->createPropertyCache(QQmlEnginePrivate::get(enginePrivate));
} 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);
QQmlType qmltype = typeRef->type;
if (!qmltype.isValid()) {
@ -709,7 +710,7 @@ inline QQmlCompileError QQmlPropertyCacheAliasCreator<ObjectContainer>::property
return propertyDataForAlias(component, *targetAlias, type, minorVersion, propertyFlags);
} else if (alias.encodedMetaPropertyIndex == -1) {
Q_ASSERT(alias.flags & QV4::CompiledData::Alias::AliasPointsToPointerObject);
auto *typeRef = objectContainer->resolvedTypes.value(targetObject.inheritedTypeNameIndex);
auto *typeRef = objectContainer->resolvedType(targetObject.inheritedTypeNameIndex);
if (!typeRef) {
// Can be caused by the alias target not being a valid id or property. E.g.:
// property alias dataValue: dataVal

View File

@ -50,7 +50,6 @@ QQmlPropertyValidator::QQmlPropertyValidator(QQmlEnginePrivate *enginePrivate, c
, compilationUnit(compilationUnit)
, imports(imports)
, qmlUnit(compilationUnit->unitData())
, resolvedTypes(compilationUnit->resolvedTypes)
, propertyCaches(compilationUnit->propertyCaches)
, bindingPropertyDataPerObject(&compilationUnit->bindingPropertyDataPerObject)
{
@ -96,7 +95,7 @@ QVector<QQmlCompileError> QQmlPropertyValidator::validateObject(int objectIndex,
return QVector<QQmlCompileError>();
QQmlCustomParser *customParser = nullptr;
if (auto typeRef = resolvedTypes.value(obj->inheritedTypeNameIndex)) {
if (auto typeRef = resolvedType(obj->inheritedTypeNameIndex)) {
if (typeRef->type.isValid())
customParser = typeRef->type.customParser();
}
@ -168,7 +167,7 @@ QVector<QQmlCompileError> QQmlPropertyValidator::validateObject(int objectIndex,
if (notInRevision) {
QString typeName = stringAt(obj->inheritedTypeNameIndex);
auto *objectType = resolvedTypes.value(obj->inheritedTypeNameIndex);
auto *objectType = resolvedType(obj->inheritedTypeNameIndex);
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 {
@ -633,7 +632,7 @@ QQmlCompileError QQmlPropertyValidator::validateObjectBinding(QQmlPropertyData *
bool isPropertyInterceptor = false;
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));
const QMetaObject *mo = cache->firstCppMetaObject();
QQmlType qmlType;

View File

@ -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 QQmlCompileError &error) const;
QString stringAt(int index) const { return compilationUnit->stringAt(index); }
QV4::CompiledData::ResolvedTypeReference *resolvedType(int id) const
{
return compilationUnit->resolvedType(id);
}
QQmlEnginePrivate *enginePrivate;
QQmlRefPointer<QV4::CompiledData::CompilationUnit> compilationUnit;
const QQmlImports &imports;
const QV4::CompiledData::Unit *qmlUnit;
const QV4::CompiledData::ResolvedTypeReferenceMap &resolvedTypes;
const QQmlPropertyCacheVector &propertyCaches;
QVector<QV4::CompiledData::BindingPropertyData> * const bindingPropertyDataPerObject;

View File

@ -56,7 +56,7 @@ QT_BEGIN_NAMESPACE
QQmlTypeCompiler::QQmlTypeCompiler(QQmlEnginePrivate *engine, QQmlTypeData *typeData,
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)
, engine(engine)
, typeData(typeData)
@ -70,7 +70,7 @@ QQmlRefPointer<QV4::CompiledData::CompilationUnit> QQmlTypeCompiler::compile()
{
// 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) {
QQmlCustomParser *customParser = (*it)->type.customParser();
if (customParser)
@ -161,9 +161,8 @@ QQmlRefPointer<QV4::CompiledData::CompilationUnit> QQmlTypeCompiler::compile()
qmlGenerator.generate(*document, dependencyHasher);
QQmlRefPointer<QV4::CompiledData::CompilationUnit> compilationUnit = document->javaScriptCompilationUnit;
compilationUnit = document->javaScriptCompilationUnit;
compilationUnit->typeNameCache = typeNameCache;
compilationUnit->resolvedTypes = resolvedTypes;
compilationUnit->resolvedTypes = *resolvedTypes;
compilationUnit->propertyCaches = std::move(m_propertyCaches);
Q_ASSERT(compilationUnit->propertyCaches.count() == static_cast<int>(compilationUnit->objectCount()));
@ -300,7 +299,6 @@ SignalHandlerConverter::SignalHandlerConverter(QQmlTypeCompiler *typeCompiler)
, qmlObjects(*typeCompiler->qmlObjects())
, imports(typeCompiler->imports())
, customParsers(typeCompiler->customParserCache())
, resolvedTypes(typeCompiler->resolvedTypes)
, illegalNames(typeCompiler->enginePrivate()->v8engine()->illegalNames())
, propertyCaches(typeCompiler->propertyCaches())
{
@ -334,7 +332,7 @@ bool SignalHandlerConverter::convertSignalHandlerExpressionsToFunctionDeclaratio
// Attached property?
if (binding->type == QV4::CompiledData::Binding::Type_AttachedProperty) {
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();
if (!type.isValid()) {
if (imports->resolveType(propertyName, &type, nullptr, nullptr, nullptr)) {
@ -405,7 +403,7 @@ bool SignalHandlerConverter::convertSignalHandlerExpressionsToFunctionDeclaratio
const QString &originalPropertyName = stringAt(binding->propertyNameIndex);
auto *typeRef = resolvedTypes.value(obj->inheritedTypeNameIndex);
auto *typeRef = resolvedType(obj->inheritedTypeNameIndex);
const QQmlType type = typeRef ? typeRef->type : QQmlType();
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()));
@ -506,7 +504,6 @@ QQmlEnumTypeResolver::QQmlEnumTypeResolver(QQmlTypeCompiler *typeCompiler)
, qmlObjects(*typeCompiler->qmlObjects())
, propertyCaches(typeCompiler->propertyCaches())
, imports(typeCompiler->imports())
, resolvedTypes(&typeCompiler->resolvedTypes)
{
}
@ -618,7 +615,7 @@ bool QQmlEnumTypeResolver::tryQualifiedEnumAssignment(const QmlIR::Object *obj,
int value = 0;
bool ok = false;
auto *tr = resolvedTypes->value(obj->inheritedTypeNameIndex);
auto *tr = resolvedType(obj->inheritedTypeNameIndex);
if (type.isValid() && tr && tr->type == type) {
// When these two match, we can short cut the search
QMetaProperty mprop = propertyCache->firstCppMetaObject()->property(prop->coreIndex());
@ -785,7 +782,6 @@ QQmlComponentAndAliasResolver::QQmlComponentAndAliasResolver(QQmlTypeCompiler *t
, enginePrivate(typeCompiler->enginePrivate())
, pool(typeCompiler->memoryPool())
, qmlObjects(typeCompiler->qmlObjects())
, resolvedTypes(&typeCompiler->resolvedTypes)
, propertyCaches(std::move(typeCompiler->takePropertyCaches()))
{
}
@ -803,7 +799,7 @@ void QQmlComponentAndAliasResolver::findAndRegisterImplicitComponents(const QmlI
continue;
const QmlIR::Object *targetObject = qmlObjects->at(binding->value.objectIndex);
auto *tr = resolvedTypes->value(targetObject->inheritedTypeNameIndex);
auto *tr = resolvedType(targetObject->inheritedTypeNameIndex);
Q_ASSERT(tr);
const QMetaObject *firstMetaObject = nullptr;
@ -854,12 +850,12 @@ void QQmlComponentAndAliasResolver::findAndRegisterImplicitComponents(const QmlI
syntheticComponent->location = binding->valueLocation;
syntheticComponent->flags |= QV4::CompiledData::Object::IsComponent;
if (!resolvedTypes->contains(syntheticComponent->inheritedTypeNameIndex)) {
if (!containsResolvedType(syntheticComponent->inheritedTypeNameIndex)) {
auto typeRef = new QV4::CompiledData::ResolvedTypeReference;
typeRef->type = componentType;
typeRef->majorVersion = componentType.majorVersion();
typeRef->minorVersion = componentType.minorVersion();
resolvedTypes->insert(syntheticComponent->inheritedTypeNameIndex, typeRef);
insertResolvedType(syntheticComponent->inheritedTypeNameIndex, typeRef);
}
qmlObjects->append(syntheticComponent);
@ -897,7 +893,7 @@ bool QQmlComponentAndAliasResolver::resolve()
bool isExplicitComponent = false;
if (obj->inheritedTypeNameIndex) {
auto *tref = resolvedTypes->value(obj->inheritedTypeNameIndex);
auto *tref = resolvedType(obj->inheritedTypeNameIndex);
Q_ASSERT(tref);
if (tref->type.metaObject() == &QQmlComponent::staticMetaObject)
isExplicitComponent = true;
@ -1300,7 +1296,6 @@ bool QQmlDeferredAndCustomParserBindingScanner::scanObject(int objectIndex)
QQmlJSCodeGenerator::QQmlJSCodeGenerator(QQmlTypeCompiler *typeCompiler, QmlIR::JSCodeGen *v4CodeGen)
: QQmlCompilePass(typeCompiler)
, resolvedTypes(typeCompiler->resolvedTypes)
, customParsers(typeCompiler->customParserCache())
, qmlObjects(*typeCompiler->qmlObjects())
, propertyCaches(typeCompiler->propertyCaches())
@ -1339,7 +1334,7 @@ bool QQmlJSCodeGenerator::compileComponent(int contextObject)
m.idIndex = obj->id;
m.type = propertyCaches->at(objectIndex);
auto *tref = resolvedTypes.value(obj->inheritedTypeNameIndex);
auto *tref = resolvedType(obj->inheritedTypeNameIndex);
if (tref && tref->isFullyDynamicType)
m.type = nullptr;

View File

@ -79,7 +79,9 @@ struct QQmlTypeCompiler
{
Q_DECLARE_TR_FUNCTIONS(QQmlTypeCompiler)
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);
// --- interface used by QQmlPropertyCacheCreator
@ -89,7 +91,7 @@ public:
QString stringAt(int idx) const;
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(); }
QV4::CompiledData::ResolvedTypeReferenceMap resolvedTypes;
QV4::CompiledData::ResolvedTypeReferenceMap *resolvedTypes = nullptr;
// ---
QQmlRefPointer<QV4::CompiledData::CompilationUnit> compile();
@ -124,6 +126,11 @@ public:
void addImport(const QString &module, const QString &qualifier, int majorVersion, int minorVersion);
QV4::CompiledData::ResolvedTypeReference *resolvedType(int id) const
{
return resolvedTypes->value(id);
}
private:
QList<QQmlError> errors;
QQmlEnginePrivate *engine;
@ -150,6 +157,14 @@ protected:
void recordError(const QQmlCompileError &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;
};
@ -172,7 +187,6 @@ private:
const QVector<QmlIR::Object*> &qmlObjects;
const QQmlImports *imports;
const QHash<int, QQmlCustomParser*> &customParsers;
const QV4::CompiledData::ResolvedTypeReferenceMap &resolvedTypes;
const QSet<QString> &illegalNames;
const QQmlPropertyCacheVector * const propertyCaches;
};
@ -203,7 +217,6 @@ private:
const QVector<QmlIR::Object*> &qmlObjects;
const QQmlPropertyCacheVector * const propertyCaches;
const QQmlImports *imports;
QV4::CompiledData::ResolvedTypeReferenceMap *resolvedTypes;
};
class QQmlCustomParserScriptIndexer: public QQmlCompilePass
@ -278,7 +291,6 @@ protected:
QMap<int, int> _idToObjectIndex;
QVector<int> _objectsWithAliases;
QV4::CompiledData::ResolvedTypeReferenceMap *resolvedTypes;
QQmlPropertyCacheVector propertyCaches;
};
@ -311,7 +323,6 @@ private:
bool compileComponent(int componentRoot);
bool compileJavaScriptCodeInObjectsRecursively(int objectIndex, int scopeObjectIndex);
const QV4::CompiledData::ResolvedTypeReferenceMap &resolvedTypes;
const QHash<int, QQmlCustomParser*> &customParsers;
const QVector<QmlIR::Object*> &qmlObjects;
const QQmlPropertyCacheVector * const propertyCaches;

View File

@ -1175,6 +1175,7 @@ public:
QVector<QQmlRefPointer<QQmlScriptData>> dependentScripts;
ResolvedTypeReferenceMap resolvedTypes;
ResolvedTypeReference *resolvedType(int id) const { return resolvedTypes.value(id); }
bool verifyChecksum(const DependentTypesHasher &dependencyHasher) const;

View File

@ -75,7 +75,6 @@ QQmlObjectCreator::QQmlObjectCreator(QQmlContextData *parentContext, const QQmlR
QQmlIncubatorPrivate *incubator)
: phase(Startup)
, compilationUnit(compilationUnit)
, resolvedTypes(compilationUnit->resolvedTypes)
, propertyCaches(&compilationUnit->propertyCaches)
, sharedState(new QQmlObjectCreatorSharedState)
, topLevelCreator(true)
@ -102,7 +101,6 @@ QQmlObjectCreator::QQmlObjectCreator(QQmlContextData *parentContext, const QQmlR
QQmlObjectCreator::QQmlObjectCreator(QQmlContextData *parentContext, const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit, QQmlObjectCreatorSharedState *inheritedSharedState)
: phase(Startup)
, compilationUnit(compilationUnit)
, resolvedTypes(compilationUnit->resolvedTypes)
, propertyCaches(&compilationUnit->propertyCaches)
, sharedState(inheritedSharedState)
, topLevelCreator(false)
@ -785,7 +783,7 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *bindingProper
{
if (binding->type == QV4::CompiledData::Binding::Type_AttachedProperty) {
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);
QQmlType attachedType = tr->type;
if (!attachedType.isValid()) {
@ -1151,7 +1149,8 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
instance = component;
ddata = QQmlData::get(instance, /*create*/true);
} else {
QV4::CompiledData::ResolvedTypeReference *typeRef = resolvedTypes.value(obj->inheritedTypeNameIndex);
QV4::CompiledData::ResolvedTypeReference *typeRef
= resolvedType(obj->inheritedTypeNameIndex);
Q_ASSERT(typeRef);
installPropertyCache = !typeRef->isFullyDynamicType;
QQmlType type = typeRef->type;

View File

@ -125,6 +125,10 @@ private:
inline QV4::QmlContext *currentQmlContext();
Q_NEVER_INLINE void createQmlContext();
QV4::CompiledData::ResolvedTypeReference *resolvedType(int id) const
{
return compilationUnit->resolvedType(id);
}
enum Phase {
Startup,
@ -141,7 +145,6 @@ private:
const QV4::CompiledData::Unit *qmlUnit;
QQmlGuardedContextData parentContext;
QQmlContextData *context;
const QV4::CompiledData::ResolvedTypeReferenceMap &resolvedTypes;
const QQmlPropertyCacheVector *propertyCaches;
QExplicitlySharedDataPointer<QQmlObjectCreatorSharedState> sharedState;
bool topLevelCreator;

View File

@ -2348,7 +2348,7 @@ void QQmlTypeData::done()
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))
return false;
return ::addTypeReferenceChecksumsToHash(m_compositeSingletons, hash, engine);
@ -2365,7 +2365,7 @@ void QQmlTypeData::done()
if (!m_document.isNull()) {
// Compile component
compile(typeNameCache, resolvedTypeCache, dependencyHasher);
compile(typeNameCache, &resolvedTypeCache, dependencyHasher);
} else {
createTypeAndPropertyCaches(typeNameCache, resolvedTypeCache);
}
@ -2638,7 +2638,8 @@ QString QQmlTypeData::stringAt(int index) const
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)
{
Q_ASSERT(m_compiledData.isNull());

View File

@ -485,7 +485,8 @@ private:
QV4::CompiledData::ResolvedTypeReferenceMap *resolvedTypeCache
) const;
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,
const QV4::CompiledData::ResolvedTypeReferenceMap &resolvedTypeCache);
bool resolveType(const QString &typeName, int &majorVersion, int &minorVersion,

View File

@ -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
}
}
}

View File

@ -55,6 +55,7 @@ private slots:
void redirect();
void qmlSingletonWithinModule();
void multiSingletonModule();
void implicitComponentModule();
};
void tst_QQMLTypeLoader::testLoadComplete()
@ -446,6 +447,31 @@ void tst_QQMLTypeLoader::qmlSingletonWithinModule()
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()
{
qmlClearTypeRegistrations();
@ -463,25 +489,18 @@ void tst_QQMLTypeLoader::multiSingletonModule()
QVERIFY(!obj.isNull());
QVERIFY(obj->property("ok").toBool());
#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(QLatin1String("multiSingletonModule")));
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"));
}
#endif
checkCleanCacheLoad(QLatin1String("multiSingletonModule"));
}
void tst_QQMLTypeLoader::implicitComponentModule()
{
QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("implicitcomponent.qml"));
QCOMPARE(component.status(), QQmlComponent::Ready);
QScopedPointer<QObject> obj(component.create());
QVERIFY(!obj.isNull());
checkCleanCacheLoad(QLatin1String("implicitComponentModule"));
}
QTEST_MAIN(tst_QQMLTypeLoader)