aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/qml/qqmltypedata.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml/qml/qqmltypedata.cpp')
-rw-r--r--src/qml/qml/qqmltypedata.cpp722
1 files changed, 493 insertions, 229 deletions
diff --git a/src/qml/qml/qqmltypedata.cpp b/src/qml/qml/qqmltypedata.cpp
index cfdcf6aad5..9acd801672 100644
--- a/src/qml/qml/qqmltypedata.cpp
+++ b/src/qml/qml/qqmltypedata.cpp
@@ -1,56 +1,25 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
-#include <private/qqmltypedata_p.h>
+#include <private/qqmlcomponentandaliasresolver_p.h>
#include <private/qqmlengine_p.h>
-#include <private/qqmlpropertycachecreator_p.h>
-#include <private/qqmlpropertyvalidator_p.h>
#include <private/qqmlirbuilder_p.h>
#include <private/qqmlirloader_p.h>
+#include <private/qqmlpropertycachecreator_p.h>
+#include <private/qqmlpropertyvalidator_p.h>
#include <private/qqmlscriptblob_p.h>
#include <private/qqmlscriptdata_p.h>
#include <private/qqmltypecompiler_p.h>
+#include <private/qqmltypedata_p.h>
+#include <private/qqmltypeloaderqmldircontent_p.h>
#include <QtCore/qloggingcategory.h>
#include <QtCore/qcryptographichash.h>
+#include <memory>
+
Q_DECLARE_LOGGING_CATEGORY(DBG_DISK_CACHE)
+Q_LOGGING_CATEGORY(lcCycle, "qt.qml.typeresolution.cycle", QtWarningMsg)
QT_BEGIN_NAMESPACE
@@ -82,12 +51,7 @@ QQmlTypeData::~QQmlTypeData()
m_resolvedTypes.clear();
}
-const QList<QQmlTypeData::ScriptReference> &QQmlTypeData::resolvedScripts() const
-{
- return m_scripts;
-}
-
-QV4::ExecutableCompilationUnit *QQmlTypeData::compilationUnit() const
+QV4::CompiledData::CompilationUnit *QQmlTypeData::compilationUnit() const
{
return m_compiledData.data();
}
@@ -105,19 +69,19 @@ void QQmlTypeData::unregisterCallback(TypeDataCallback *callback)
Q_ASSERT(!m_callbacks.contains(callback));
}
-bool QQmlTypeData::tryLoadFromDiskCache()
+QQmlType QQmlTypeData::qmlType(const QString &inlineComponentName) const
{
- if (diskCacheDisabled() && !diskCacheForced())
- return false;
-
- if (isDebugging())
- return false;
+ if (inlineComponentName.isEmpty())
+ return m_qmlType;
+ return m_inlineComponentData[inlineComponentName].qmlType;
+}
- QV4::ExecutionEngine *v4 = typeLoader()->engine()->handle();
- if (!v4)
+bool QQmlTypeData::tryLoadFromDiskCache()
+{
+ if (!readCacheFile())
return false;
- QQmlRefPointer<QV4::ExecutableCompilationUnit> unit = QV4::ExecutableCompilationUnit::create();
+ auto unit = QQml::makeRefPointer<QV4::CompiledData::CompilationUnit>();
{
QString error;
if (!unit->loadFromDisk(url(), m_backupSourceCode.sourceTimeStamp(), &error)) {
@@ -127,16 +91,23 @@ bool QQmlTypeData::tryLoadFromDiskCache()
}
if (unit->unitData()->flags & QV4::CompiledData::Unit::PendingTypeCompilation) {
- restoreIR(std::move(*unit));
+ restoreIR(unit);
return true;
}
- m_compiledData = unit;
+ m_compiledData = std::move(unit);
- for (int i = 0, count = m_compiledData->objectCount(); i < count; ++i)
- m_typeReferences.collectFromObject(m_compiledData->objectAt(i));
+ QVector<QV4::CompiledData::InlineComponent> ics;
+ for (int i = 0, count = m_compiledData->objectCount(); i < count; ++i) {
+ auto object = m_compiledData->objectAt(i);
+ m_typeReferences.collectFromObject(object);
+ const auto inlineComponentTable = object->inlineComponentTable();
+ for (auto i = 0; i != object->nInlineComponents; ++i) {
+ ics.push_back(inlineComponentTable[i]);
+ }
+ }
- m_importCache.setBaseUrl(finalUrl(), finalUrlString());
+ m_importCache->setBaseUrl(finalUrl(), finalUrlString());
// For remote URLs, we don't delay the loading of the implicit import
// because the loading probably requires an asynchronous fetch of the
@@ -152,10 +123,12 @@ bool QQmlTypeData::tryLoadFromDiskCache()
const QV4::CompiledData::Import *import = m_compiledData->importAt(i);
if (m_compiledData->stringAt(import->uriIndex) == QLatin1String(".")
&& import->qualifierIndex == 0
- && import->majorVersion == -1
- && import->minorVersion == -1) {
+ && !import->version.hasMajorVersion()
+ && !import->version.hasMinorVersion()) {
QList<QQmlError> errors;
- auto pendingImport = std::make_shared<PendingImport>(this, import);
+ auto pendingImport = std::make_shared<PendingImport>(
+ this, import, QQmlImports::ImportNoFlag);
+ pendingImport->precedence = QQmlImportInstance::Implicit;
if (!fetchQmldir(qmldirUrl, pendingImport, 1, &errors)) {
setError(errors);
return false;
@@ -169,61 +142,161 @@ bool QQmlTypeData::tryLoadFromDiskCache()
for (int i = 0, count = m_compiledData->importCount(); i < count; ++i) {
const QV4::CompiledData::Import *import = m_compiledData->importAt(i);
QList<QQmlError> errors;
- if (!addImport(import, &errors)) {
+ if (!addImport(import, {}, &errors)) {
Q_ASSERT(errors.size());
QQmlError error(errors.takeFirst());
- error.setUrl(m_importCache.baseUrl());
- error.setLine(import->location.line);
- error.setColumn(import->location.column);
+ error.setUrl(m_importCache->baseUrl());
+ error.setLine(qmlConvertSourceCoordinate<quint32, int>(import->location.line()));
+ error.setColumn(qmlConvertSourceCoordinate<quint32, int>(import->location.column()));
errors.prepend(error); // put it back on the list after filling out information.
setError(errors);
return false;
}
}
+ for (auto&& ic: ics) {
+ QString const nameString = m_compiledData->stringAt(ic.nameIndex);
+ auto importUrl = finalUrl();
+ importUrl.setFragment(nameString);
+ auto import = new QQmlImportInstance();
+ m_importCache->addInlineComponentImport(import, nameString, importUrl);
+ }
+
return true;
}
-void QQmlTypeData::createTypeAndPropertyCaches(
+template<>
+void QQmlComponentAndAliasResolver<QV4::CompiledData::CompilationUnit>::allocateNamedObjects(
+ const QV4::CompiledData::Object *object) const
+{
+ Q_UNUSED(object);
+}
+
+template<>
+bool QQmlComponentAndAliasResolver<QV4::CompiledData::CompilationUnit>::markAsComponent(int index) const
+{
+ return m_compiler->objectAt(index)->hasFlag(QV4::CompiledData::Object::IsComponent);
+}
+
+template<>
+void QQmlComponentAndAliasResolver<QV4::CompiledData::CompilationUnit>::setObjectId(int index) const
+{
+ Q_UNUSED(index)
+ // we cannot sanity-check the index here because bindings are sorted in a different order
+ // in the CU vs the IR.
+}
+
+template<>
+void QQmlComponentAndAliasResolver<QV4::CompiledData::CompilationUnit>::resolveGeneralizedGroupProperty(
+ const CompiledObject &component, CompiledBinding *binding)
+{
+ // We cannot make it fail here. It might be a custom-parsed property
+ for (int i = 0, count = component.namedObjectsInComponentCount(); i < count; ++i) {
+ const int candidateIndex = component.namedObjectsInComponentTable()[i];
+ if (m_compiler->objectAt(candidateIndex)->idNameIndex == binding->propertyNameIndex) {
+ m_propertyCaches->set(binding->value.objectIndex, m_propertyCaches->at(candidateIndex));
+ return;
+ }
+ }
+}
+
+template<>
+typename QQmlComponentAndAliasResolver<QV4::CompiledData::CompilationUnit>::AliasResolutionResult
+QQmlComponentAndAliasResolver<QV4::CompiledData::CompilationUnit>::resolveAliasesInObject(
+ const CompiledObject &component, int objectIndex, QQmlError *error)
+{
+ const CompiledObject *obj = m_compiler->objectAt(objectIndex);
+ for (auto alias = obj->aliasesBegin(), end = obj->aliasesEnd(); alias != end; ++alias) {
+ if (!alias->hasFlag(QV4::CompiledData::Alias::Resolved)) {
+ *error = qQmlCompileError( alias->referenceLocation, tr("Unresolved alias found"));
+ return NoAliasResolved;
+ }
+
+ if (alias->isAliasToLocalAlias() || alias->encodedMetaPropertyIndex == -1)
+ continue;
+
+ const int targetObjectIndex
+ = objectForId(m_compiler, component, alias->targetObjectId());
+ const int coreIndex
+ = QQmlPropertyIndex::fromEncoded(alias->encodedMetaPropertyIndex).coreIndex();
+
+ QQmlPropertyCache::ConstPtr targetCache = m_propertyCaches->at(targetObjectIndex);
+ Q_ASSERT(targetCache);
+
+ if (!targetCache->property(coreIndex))
+ return SomeAliasesResolved;
+ }
+
+ return AllAliasesResolved;
+}
+
+template<>
+bool QQmlComponentAndAliasResolver<QV4::CompiledData::CompilationUnit>::wrapImplicitComponent(
+ const QV4::CompiledData::Binding *binding)
+{
+ // This should have been done when creating the CU.
+ Q_UNUSED(binding);
+ return false;
+}
+
+QQmlError QQmlTypeData::createTypeAndPropertyCaches(
const QQmlRefPointer<QQmlTypeNameCache> &typeNameCache,
- const QV4::ResolvedTypeReferenceMap &resolvedTypeCache)
+ const QV4::CompiledData::ResolvedTypeReferenceMap &resolvedTypeCache)
{
Q_ASSERT(m_compiledData);
m_compiledData->typeNameCache = typeNameCache;
m_compiledData->resolvedTypes = resolvedTypeCache;
+ m_compiledData->inlineComponentData = m_inlineComponentData;
QQmlEnginePrivate * const engine = QQmlEnginePrivate::get(typeLoader()->engine());
QQmlPendingGroupPropertyBindings pendingGroupPropertyBindings;
{
- QQmlPropertyCacheCreator<QV4::ExecutableCompilationUnit> propertyCacheCreator(
+ QQmlPropertyCacheCreator<QV4::CompiledData::CompilationUnit> propertyCacheCreator(
&m_compiledData->propertyCaches, &pendingGroupPropertyBindings, engine,
- m_compiledData.data(), &m_importCache);
- QQmlJS::DiagnosticMessage error = propertyCacheCreator.buildMetaObjects();
- if (error.isValid()) {
- setError(error);
- return;
- }
- }
+ m_compiledData.data(), m_importCache.data(), typeClassName());
- QQmlPropertyCacheAliasCreator<QV4::ExecutableCompilationUnit> aliasCreator(
- &m_compiledData->propertyCaches, m_compiledData.data());
- aliasCreator.appendAliasPropertiesToMetaObjects(engine);
+ QQmlError error = propertyCacheCreator.verifyNoICCycle();
+ if (error.isValid())
+ return error;
- pendingGroupPropertyBindings.resolveMissingPropertyCaches(engine, &m_compiledData->propertyCaches);
+ QQmlPropertyCacheCreatorBase::IncrementalResult result;
+ do {
+ result = propertyCacheCreator.buildMetaObjectsIncrementally();
+ if (result.error.isValid()) {
+ return result.error;
+ } else {
+ QQmlComponentAndAliasResolver resolver(
+ m_compiledData.data(), engine, &m_compiledData->propertyCaches);
+ if (const QQmlError error = resolver.resolve(result.processedRoot);
+ error.isValid()) {
+ return error;
+ }
+ pendingGroupPropertyBindings.resolveMissingPropertyCaches(
+ &m_compiledData->propertyCaches);
+ pendingGroupPropertyBindings.clear(); // anything that can be processed is now processed
+ }
+
+ } while (result.canResume);
+ }
+
+ pendingGroupPropertyBindings.resolveMissingPropertyCaches(&m_compiledData->propertyCaches);
+ return QQmlError();
}
-static bool addTypeReferenceChecksumsToHash(const QList<QQmlTypeData::TypeReference> &typeRefs, QCryptographicHash *hash, QQmlEngine *engine)
+static bool addTypeReferenceChecksumsToHash(
+ const QList<QQmlTypeData::TypeReference> &typeRefs,
+ QHash<quintptr, QByteArray> *checksums, QCryptographicHash *hash)
{
for (const auto &typeRef: typeRefs) {
if (typeRef.typeData) {
const auto unit = typeRef.typeData->compilationUnit()->unitData();
- hash->addData(unit->md5Checksum, sizeof(unit->md5Checksum));
- } else if (typeRef.type.isValid()) {
- const auto propertyCache = QQmlEnginePrivate::get(engine)->cache(typeRef.type.metaObject());
+ hash->addData({unit->md5Checksum, sizeof(unit->md5Checksum)});
+ } else if (const QMetaObject *mo = typeRef.type.metaObject()) {
+ const auto propertyCache = QQmlMetaType::propertyCache(mo);
bool ok = false;
- hash->addData(propertyCache->checksum(&ok));
+ hash->addData(propertyCache->checksum(checksums, &ok));
if (!ok)
return false;
}
@@ -231,28 +304,78 @@ static bool addTypeReferenceChecksumsToHash(const QList<QQmlTypeData::TypeRefere
return true;
}
+// local helper function for inline components
+namespace {
+using InlineComponentData = QV4::CompiledData::InlineComponentData;
+
+template<typename ObjectContainer>
+void setupICs(
+ const ObjectContainer &container, QHash<QString, InlineComponentData> *icData,
+ const QUrl &baseUrl,
+ const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit) {
+ Q_ASSERT(icData->empty());
+ for (int i = 0; i != container->objectCount(); ++i) {
+ auto root = container->objectAt(i);
+ for (auto it = root->inlineComponentsBegin(); it != root->inlineComponentsEnd(); ++it) {
+ // We cannot re-use a previously finalized inline component type here. We need our own.
+ // We can and should re-use speculative type references, though.
+ InlineComponentData icDatum(
+ QQmlMetaType::findInlineComponentType(
+ baseUrl, container->stringAt(it->nameIndex), compilationUnit),
+ int(it->objectIndex), int(it->nameIndex), 0, 0, 0);
+
+ icData->insert(container->stringAt(it->nameIndex), icDatum);
+ }
+ }
+};
+}
+
+template<typename Container>
+void QQmlTypeData::setCompileUnit(const Container &container)
+{
+ for (int i = 0; i != container->objectCount(); ++i) {
+ auto const root = container->objectAt(i);
+ for (auto it = root->inlineComponentsBegin(); it != root->inlineComponentsEnd(); ++it) {
+ auto *typeRef = m_compiledData->resolvedType(it->nameIndex);
+
+ // We don't want the type reference to keep a strong reference to the compilation unit
+ // here. The compilation unit owns the type reference, and having a strong reference
+ // would prevent the compilation unit from ever getting deleted. We can still be sure
+ // that the compilation unit outlives the type reference, due to ownership.
+ typeRef->setReferencesCompilationUnit(false);
+
+ typeRef->setCompilationUnit(m_compiledData); // share compilation unit
+ }
+ }
+}
+
void QQmlTypeData::done()
{
auto cleanup = qScopeGuard([this]{
+ m_backupSourceCode = SourceCodeData();
m_document.reset();
m_typeReferences.clear();
- if (isError())
- m_compiledData = nullptr;
+ if (isError()) {
+ const auto encounteredErrors = errors();
+ for (const QQmlError &e : encounteredErrors)
+ qCDebug(DBG_DISK_CACHE) << e.toString();
+ m_compiledData.reset();
+ }
});
if (isError())
return;
// Check all script dependencies for errors
- for (int ii = 0; ii < m_scripts.count(); ++ii) {
+ for (int ii = 0; ii < m_scripts.size(); ++ii) {
const ScriptReference &script = m_scripts.at(ii);
Q_ASSERT(script.script->isCompleteOrError());
if (script.script->isError()) {
QList<QQmlError> errors = script.script->errors();
QQmlError error;
error.setUrl(url());
- error.setLine(script.location.line);
- error.setColumn(script.location.column);
+ error.setLine(qmlConvertSourceCoordinate<quint32, int>(script.location.line()));
+ error.setColumn(qmlConvertSourceCoordinate<quint32, int>(script.location.column()));
error.setDescription(QQmlTypeLoader::tr("Script %1 unavailable").arg(script.script->urlString()));
errors.prepend(error);
setError(errors);
@@ -261,48 +384,73 @@ void QQmlTypeData::done()
}
// Check all type dependencies for errors
- for (auto it = m_resolvedTypes.constBegin(), end = m_resolvedTypes.constEnd(); it != end;
+ auto createError = [&](const TypeReference &type , const QString &message) {
+ QList<QQmlError> errors = type.typeData ? type.typeData->errors() : QList<QQmlError>{};
+ QQmlError error;
+ error.setUrl(url());
+ error.setLine(qmlConvertSourceCoordinate<quint32, int>(type.location.line()));
+ error.setColumn(qmlConvertSourceCoordinate<quint32, int>(type.location.column()));
+ error.setDescription(message);
+ errors.prepend(error);
+ setError(errors);
+ };
+ for (auto it = std::as_const(m_resolvedTypes).begin(), end = std::as_const(m_resolvedTypes).end(); it != end;
++it) {
const TypeReference &type = *it;
- Q_ASSERT(!type.typeData || type.typeData->isCompleteOrError());
+ Q_ASSERT(!type.typeData || type.typeData->isCompleteOrError() || type.type.isInlineComponentType());
+
+ if (type.type.isInlineComponentType()) {
+ const QUrl url = type.type.sourceUrl();
+ if (!QQmlMetaType::equalBaseUrls(url, finalUrl())
+ && !QQmlMetaType::obtainCompilationUnit(type.type.typeId())) {
+ const QString &typeName = stringAt(it.key());
+ int lastDot = typeName.lastIndexOf(u'.');
+ createError(
+ type,
+ QQmlTypeLoader::tr("Type %1 has no inline component type called %2")
+ .arg(QStringView{typeName}.left(lastDot), type.type.elementName()));
+ return;
+ }
+ }
if (type.typeData && type.typeData->isError()) {
- const QString typeName = stringAt(it.key());
-
- QList<QQmlError> errors = type.typeData->errors();
- QQmlError error;
- error.setUrl(url());
- error.setLine(type.location.line);
- error.setColumn(type.location.column);
- error.setDescription(QQmlTypeLoader::tr("Type %1 unavailable").arg(typeName));
- errors.prepend(error);
- setError(errors);
+ const QString &typeName = stringAt(it.key());
+ createError(type, QQmlTypeLoader::tr("Type %1 unavailable").arg(typeName));
return;
}
}
// Check all composite singleton type dependencies for errors
- for (int ii = 0; ii < m_compositeSingletons.count(); ++ii) {
+ for (int ii = 0; ii < m_compositeSingletons.size(); ++ii) {
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();
- QList<QQmlError> errors = type.typeData->errors();
- QQmlError error;
- error.setUrl(url());
- error.setLine(type.location.line);
- error.setColumn(type.location.column);
- error.setDescription(QQmlTypeLoader::tr("Type %1 unavailable").arg(typeName));
- errors.prepend(error);
- setError(errors);
+ createError(type, QQmlTypeLoader::tr("Type %1 unavailable").arg(typeName));
return;
}
}
+ if (QQmlPropertyCacheCreatorBase::canCreateClassNameTypeByUrl(finalUrl())) {
+ const bool isSingleton = m_document
+ ? m_document.data()->isSingleton()
+ : (m_compiledData->unitData()->flags & QV4::CompiledData::Unit::IsSingleton);
+ m_qmlType = QQmlMetaType::findCompositeType(
+ finalUrl(), m_compiledData, isSingleton
+ ? QQmlMetaType::Singleton
+ : QQmlMetaType::NonSingleton);
+ m_typeClassName = QByteArray(m_qmlType.typeId().name()).chopped(1);
+ }
+
+ if (m_document)
+ setupICs(m_document, &m_inlineComponentData, finalUrl(), m_compiledData);
+ else
+ setupICs(m_compiledData, &m_inlineComponentData, finalUrl(), m_compiledData);
+
+ QV4::CompiledData::ResolvedTypeReferenceMap resolvedTypeCache;
QQmlRefPointer<QQmlTypeNameCache> typeNameCache;
- QV4::ResolvedTypeReferenceMap resolvedTypeCache;
{
- QQmlJS::DiagnosticMessage error = buildTypeResolutionCaches(&typeNameCache, &resolvedTypeCache);
+ QQmlError error = buildTypeResolutionCaches(&typeNameCache, &resolvedTypeCache);
if (error.isValid()) {
setError(error);
qDeleteAll(resolvedTypeCache);
@@ -310,48 +458,81 @@ void QQmlTypeData::done()
}
}
- QQmlEngine *const engine = typeLoader()->engine();
-
- const auto dependencyHasher = [engine, &resolvedTypeCache, this]() {
+ const auto dependencyHasher = [&resolvedTypeCache, this]() {
QCryptographicHash hash(QCryptographicHash::Md5);
- return (resolvedTypeCache.addToHash(&hash, engine)
- && ::addTypeReferenceChecksumsToHash(m_compositeSingletons, &hash, engine))
+ return (resolvedTypeCache.addToHash(&hash, typeLoader()->checksumCache())
+ && ::addTypeReferenceChecksumsToHash(
+ m_compositeSingletons, typeLoader()->checksumCache(), &hash))
? hash.result()
: QByteArray();
};
// verify if any dependencies changed if we're using a cache
- if (m_document.isNull() && !m_compiledData->verifyChecksum(dependencyHasher)) {
- qCDebug(DBG_DISK_CACHE) << "Checksum mismatch for cached version of" << m_compiledData->fileName();
- if (!loadFromSource())
- return;
- m_backupSourceCode = SourceCodeData();
- m_compiledData = nullptr;
+ if (m_document.isNull()) {
+ const QQmlError error = createTypeAndPropertyCaches(typeNameCache, resolvedTypeCache);
+ if (!error.isValid() && m_compiledData->verifyChecksum(dependencyHasher)) {
+ setCompileUnit(m_compiledData);
+ } else {
+
+ if (error.isValid()) {
+ qCDebug(DBG_DISK_CACHE)
+ << "Failed to create property caches for"
+ << m_compiledData->fileName()
+ << "because" << error.description();
+ } else {
+ qCDebug(DBG_DISK_CACHE)
+ << "Checksum mismatch for cached version of"
+ << m_compiledData->fileName();
+ }
+
+ if (!loadFromSource())
+ return;
+
+ // We want to keep our resolve types ...
+ m_compiledData->resolvedTypes.clear();
+ // ... but we don't want the property caches we've created for the broken CU.
+ for (QV4::ResolvedTypeReference *ref: std::as_const(resolvedTypeCache)) {
+ const auto compilationUnit = ref->compilationUnit();
+ if (compilationUnit.isNull()) {
+ // Inline component references without CU belong to the surrounding CU.
+ // We have to clear them. Inline component references to other documents
+ // have a CU.
+ if (!ref->type().isInlineComponentType())
+ continue;
+ } else if (compilationUnit != m_compiledData) {
+ continue;
+ }
+ ref->setTypePropertyCache(QQmlPropertyCache::ConstPtr());
+ ref->setCompilationUnit(QQmlRefPointer<QV4::CompiledData::CompilationUnit>());
+ }
+
+ m_compiledData.reset();
+ }
}
if (!m_document.isNull()) {
// Compile component
compile(typeNameCache, &resolvedTypeCache, dependencyHasher);
- } else {
- createTypeAndPropertyCaches(typeNameCache, resolvedTypeCache);
+ if (isError())
+ return;
+ else
+ setCompileUnit(m_document);
}
- if (isError())
- return;
-
{
- QQmlEnginePrivate *const enginePrivate = QQmlEnginePrivate::get(engine);
+ QQmlEnginePrivate *const enginePrivate = QQmlEnginePrivate::get(typeLoader()->engine());
+ m_compiledData->inlineComponentData = m_inlineComponentData;
{
// Sanity check property bindings
- QQmlPropertyValidator validator(enginePrivate, m_importCache, m_compiledData);
- QVector<QQmlJS::DiagnosticMessage> errors = validator.validate();
+ QQmlPropertyValidator validator(enginePrivate, m_importCache.data(), m_compiledData);
+ QVector<QQmlError> errors = validator.validate();
if (!errors.isEmpty()) {
setError(errors);
return;
}
}
- m_compiledData->finalizeCompositeType(enginePrivate);
+ m_compiledData->finalizeCompositeType(qmlType());
}
{
@@ -381,11 +562,11 @@ void QQmlTypeData::done()
{
// Collect imported scripts
- m_compiledData->dependentScripts.reserve(m_scripts.count());
- for (int scriptIndex = 0; scriptIndex < m_scripts.count(); ++scriptIndex) {
+ m_compiledData->dependentScripts.reserve(m_scripts.size());
+ for (int scriptIndex = 0; scriptIndex < m_scripts.size(); ++scriptIndex) {
const QQmlTypeData::ScriptReference &script = m_scripts.at(scriptIndex);
- QStringRef qualifier(&script.qualifier);
+ QStringView qualifier(script.qualifier);
QString enclosingNamespace;
const int lastDotIndex = qualifier.lastIndexOf(QLatin1Char('.'));
@@ -394,7 +575,8 @@ void QQmlTypeData::done()
qualifier = qualifier.mid(lastDotIndex+1);
}
- m_compiledData->typeNameCache->add(qualifier.toString(), scriptIndex, enclosingNamespace);
+ m_compiledData->typeNameCache->add(
+ qualifier.toString(), scriptIndex, enclosingNamespace);
QQmlRefPointer<QQmlScriptData> scriptData = script.script->scriptData();
m_compiledData->dependentScripts << scriptData;
}
@@ -414,14 +596,28 @@ bool QQmlTypeData::loadImplicitImport()
{
m_implicitImportLoaded = true; // Even if we hit an error, count as loaded (we'd just keep hitting the error)
- m_importCache.setBaseUrl(finalUrl(), finalUrlString());
+ m_importCache->setBaseUrl(finalUrl(), finalUrlString());
- QQmlImportDatabase *importDatabase = typeLoader()->importDatabase();
// For local urls, add an implicit import "." as most overridden lookup.
// This will also trigger the loading of the qmldir and the import of any native
// types from available plugins.
QList<QQmlError> implicitImportErrors;
- m_importCache.addImplicitImport(importDatabase, &implicitImportErrors);
+ QString localQmldir;
+ m_importCache->addImplicitImport(typeLoader(), &localQmldir, &implicitImportErrors);
+
+ // When loading with QQmlImports::ImportImplicit, the imports are _appended_ to the namespace
+ // in the order they are loaded. Therefore, the addImplicitImport above gets the highest
+ // precedence. This is in contrast to normal priority imports. Those are _prepended_ in the
+ // order they are loaded.
+ if (!localQmldir.isEmpty()) {
+ const QQmlTypeLoaderQmldirContent qmldir = typeLoader()->qmldirContent(localQmldir);
+ const QList<QQmlDirParser::Import> moduleImports
+ = QQmlMetaType::moduleImports(qmldir.typeNamespace(), QTypeRevision())
+ + qmldir.imports();
+ loadDependentImports(moduleImports, QString(), QTypeRevision(),
+ QQmlImportInstance::Implicit + 1, QQmlImports::ImportNoFlag,
+ &implicitImportErrors);
+ }
if (!implicitImportErrors.isEmpty()) {
setError(implicitImportErrors);
@@ -457,14 +653,17 @@ void QQmlTypeData::dataReceived(const SourceCodeData &data)
continueLoadFromIR();
}
-void QQmlTypeData::initializeFromCachedUnit(const QV4::CompiledData::Unit *unit)
+void QQmlTypeData::initializeFromCachedUnit(const QQmlPrivate::CachedQmlUnit *unit)
{
m_document.reset(new QmlIR::Document(isDebugging()));
- QQmlIRLoader loader(unit, m_document.data());
+ QQmlIRLoader loader(unit->qmlData, m_document.data());
loader.load();
m_document->jsModule.fileName = urlString();
m_document->jsModule.finalUrl = finalUrlString();
- m_document->javaScriptCompilationUnit = QV4::CompiledData::CompilationUnit(unit);
+ m_document->javaScriptCompilationUnit
+ = QQmlRefPointer<QV4::CompiledData::CompilationUnit>(
+ new QV4::CompiledData::CompilationUnit(unit->qmlData, unit->aotCompiledFunctions),
+ QQmlRefPointer<QV4::CompiledData::CompilationUnit>::Adopt);
continueLoadFromIR();
}
@@ -484,12 +683,12 @@ bool QQmlTypeData::loadFromSource()
if (!compiler.generateFromQml(source, finalUrlString(), m_document.data())) {
QList<QQmlError> errors;
- errors.reserve(compiler.errors.count());
- for (const QQmlJS::DiagnosticMessage &msg : qAsConst(compiler.errors)) {
+ errors.reserve(compiler.errors.size());
+ for (const QQmlJS::DiagnosticMessage &msg : std::as_const(compiler.errors)) {
QQmlError e;
e.setUrl(url());
- e.setLine(msg.line);
- e.setColumn(msg.column);
+ e.setLine(qmlConvertSourceCoordinate<quint32, int>(msg.loc.startLine));
+ e.setColumn(qmlConvertSourceCoordinate<quint32, int>(msg.loc.startColumn));
e.setDescription(msg.message);
errors << e;
}
@@ -499,21 +698,31 @@ bool QQmlTypeData::loadFromSource()
return true;
}
-void QQmlTypeData::restoreIR(QV4::CompiledData::CompilationUnit &&unit)
+void QQmlTypeData::restoreIR(const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &unit)
{
m_document.reset(new QmlIR::Document(isDebugging()));
- QQmlIRLoader loader(unit.unitData(), m_document.data());
+ QQmlIRLoader loader(unit->unitData(), m_document.data());
loader.load();
m_document->jsModule.fileName = urlString();
m_document->jsModule.finalUrl = finalUrlString();
- m_document->javaScriptCompilationUnit = std::move(unit);
+ m_document->javaScriptCompilationUnit = unit;
continueLoadFromIR();
}
void QQmlTypeData::continueLoadFromIR()
{
+ for (auto const& object: m_document->objects) {
+ for (auto it = object->inlineComponentsBegin(); it != object->inlineComponentsEnd(); ++it) {
+ QString const nameString = m_document->stringAt(it->nameIndex);
+ auto importUrl = finalUrl();
+ importUrl.setFragment(nameString);
+ auto import = new QQmlImportInstance(); // Note: The cache takes ownership of the QQmlImportInstance
+ m_importCache->addInlineComponentImport(import, nameString, importUrl);
+ }
+ }
+
m_typeReferences.collectFromObjects(m_document->objects.constBegin(), m_document->objects.constEnd());
- m_importCache.setBaseUrl(finalUrl(), finalUrlString());
+ m_importCache->setBaseUrl(finalUrl(), finalUrlString());
// For remote URLs, we don't delay the loading of the implicit import
// because the loading probably requires an asynchronous fetch of the
@@ -526,8 +735,7 @@ void QQmlTypeData::continueLoadFromIR()
// This qmldir is for the implicit import
auto implicitImport = std::make_shared<PendingImport>();
implicitImport->uri = QLatin1String(".");
- implicitImport->majorVersion = -1;
- implicitImport->minorVersion = -1;
+ implicitImport->version = QTypeRevision();
QList<QQmlError> errors;
if (!fetchQmldir(qmldirUrl, implicitImport, 1, &errors)) {
@@ -539,15 +747,18 @@ void QQmlTypeData::continueLoadFromIR()
QList<QQmlError> errors;
- for (const QV4::CompiledData::Import *import : qAsConst(m_document->imports)) {
- if (!addImport(import, &errors)) {
+ for (const QV4::CompiledData::Import *import : std::as_const(m_document->imports)) {
+ if (!addImport(import, {}, &errors)) {
Q_ASSERT(errors.size());
- QQmlError error(errors.takeFirst());
- error.setUrl(m_importCache.baseUrl());
- error.setLine(import->location.line);
- error.setColumn(import->location.column);
- errors.prepend(error); // put it back on the list after filling out information.
- setError(errors);
+
+ // We're only interested in the chronoligically last error. The previous
+ // errors might be from unsuccessfully trying to load a module from the
+ // resource file system.
+ QQmlError error = errors.first();
+ error.setUrl(m_importCache->baseUrl());
+ error.setLine(qmlConvertSourceCoordinate<quint32, int>(import->location.line()));
+ error.setColumn(qmlConvertSourceCoordinate<quint32, int>(import->location.column()));
+ setError(error);
return;
}
}
@@ -567,12 +778,14 @@ void QQmlTypeData::allDependenciesDone()
for (auto keyIt = m_unresolvedImports.constBegin(),
keyEnd = m_unresolvedImports.constEnd();
keyIt != keyEnd; ++keyIt) {
- PendingImportPtr import = *keyIt;
+ const PendingImportPtr &import = *keyIt;
QQmlError error;
error.setDescription(QQmlTypeLoader::tr("module \"%1\" is not installed").arg(import->uri));
- error.setUrl(m_importCache.baseUrl());
- error.setLine(import->location.line);
- error.setColumn(import->location.column);
+ error.setUrl(m_importCache->baseUrl());
+ error.setLine(qmlConvertSourceCoordinate<quint32, int>(
+ import->location.line()));
+ error.setColumn(qmlConvertSourceCoordinate<quint32, int>(
+ import->location.column()));
errors.prepend(error);
}
}
@@ -589,7 +802,7 @@ void QQmlTypeData::allDependenciesDone()
void QQmlTypeData::downloadProgressChanged(qreal p)
{
- for (int ii = 0; ii < m_callbacks.count(); ++ii) {
+ for (int ii = 0; ii < m_callbacks.size(); ++ii) {
TypeDataCallback *callback = m_callbacks.at(ii);
callback->typeDataProgress(this, p);
}
@@ -603,43 +816,58 @@ QString QQmlTypeData::stringAt(int index) const
}
void QQmlTypeData::compile(const QQmlRefPointer<QQmlTypeNameCache> &typeNameCache,
- QV4::ResolvedTypeReferenceMap *resolvedTypeCache,
+ QV4::CompiledData::ResolvedTypeReferenceMap *resolvedTypeCache,
const QV4::CompiledData::DependentTypesHasher &dependencyHasher)
{
Q_ASSERT(m_compiledData.isNull());
- const bool typeRecompilation = m_document && m_document->javaScriptCompilationUnit.unitData()
- && (m_document->javaScriptCompilationUnit.unitData()->flags & QV4::CompiledData::Unit::PendingTypeCompilation);
+ const bool typeRecompilation = m_document
+ && m_document->javaScriptCompilationUnit
+ && m_document->javaScriptCompilationUnit->unitData()
+ && (m_document->javaScriptCompilationUnit->unitData()->flags
+ & QV4::CompiledData::Unit::PendingTypeCompilation);
QQmlEnginePrivate * const enginePrivate = QQmlEnginePrivate::get(typeLoader()->engine());
- QQmlTypeCompiler compiler(enginePrivate, this, m_document.data(), typeNameCache, resolvedTypeCache, dependencyHasher);
- m_compiledData = compiler.compile();
- if (!m_compiledData) {
+ QQmlTypeCompiler compiler(
+ enginePrivate, this, m_document.data(), resolvedTypeCache, dependencyHasher);
+ auto compilationUnit = compiler.compile();
+ if (!compilationUnit) {
qDeleteAll(*resolvedTypeCache);
resolvedTypeCache->clear();
setError(compiler.compilationErrors());
return;
}
- const bool trySaveToDisk = (!diskCacheDisabled() || diskCacheForced())
- && !m_document->jsModule.debugMode && !typeRecompilation;
+ const bool trySaveToDisk = writeCacheFile() && !typeRecompilation;
if (trySaveToDisk) {
QString errorString;
- if (m_compiledData->saveToDisk(url(), &errorString)) {
+ if (compilationUnit->saveToDisk(url(), &errorString)) {
QString error;
- if (!m_compiledData->loadFromDisk(url(), m_backupSourceCode.sourceTimeStamp(), &error)) {
+ if (!compilationUnit->loadFromDisk(url(), m_backupSourceCode.sourceTimeStamp(), &error)) {
// ignore error, keep using the in-memory compilation unit.
}
} else {
- qCDebug(DBG_DISK_CACHE) << "Error saving cached version of" << m_compiledData->fileName() << "to disk:" << errorString;
+ qCDebug(DBG_DISK_CACHE) << "Error saving cached version of"
+ << compilationUnit->fileName() << "to disk:" << errorString;
}
}
+
+ m_compiledData = std::move(compilationUnit);
+ m_compiledData->typeNameCache = typeNameCache;
+ m_compiledData->resolvedTypes = *resolvedTypeCache;
+ m_compiledData->propertyCaches = std::move(*compiler.propertyCaches());
+ Q_ASSERT(m_compiledData->propertyCaches.count()
+ == static_cast<int>(m_compiledData->objectCount()));
}
void QQmlTypeData::resolveTypes()
{
+ // Load the implicit import since it may have additional scripts.
+ if (!m_implicitImportLoaded && !loadImplicitImport())
+ return;
+
// Add any imported scripts to our resolved set
- const auto resolvedScripts = m_importCache.resolvedScripts();
+ const auto resolvedScripts = m_importCache->resolvedScripts();
for (const QQmlImports::ScriptReference &script : resolvedScripts) {
QQmlRefPointer<QQmlScriptBlob> blob = typeLoader()->getScript(script.location);
addDependency(blob.data());
@@ -660,7 +888,7 @@ void QQmlTypeData::resolveTypes()
}
// Lets handle resolved composite singleton types
- const auto resolvedCompositeSingletons = m_importCache.resolvedCompositeSingletons();
+ const auto resolvedCompositeSingletons = m_importCache->resolvedCompositeSingletons();
for (const QQmlImports::CompositeSingletonReference &csRef : resolvedCompositeSingletons) {
TypeReference ref;
QString typeName;
@@ -672,17 +900,15 @@ void QQmlTypeData::resolveTypes()
typeName = csRef.typeName;
}
- int majorVersion = csRef.majorVersion > -1 ? csRef.majorVersion : -1;
- int minorVersion = csRef.minorVersion > -1 ? csRef.minorVersion : -1;
-
- if (!resolveType(typeName, majorVersion, minorVersion, ref, -1, -1, true,
- QQmlType::CompositeSingletonType))
+ QTypeRevision version = csRef.version;
+ if (!resolveType(typeName, version, ref, -1, -1, true, QQmlType::CompositeSingletonType))
return;
if (ref.type.isCompositeSingleton()) {
ref.typeData = typeLoader()->getType(ref.type.sourceUrl());
- if (ref.typeData->status() == QQmlDataBlob::ResolvingDependencies || m_waitingOnMe.contains(ref.typeData.data())) {
- // TODO: give an error message? If so, we should record and show the path of the cycle.
+ if (ref.typeData->isWaiting() || m_waitingOnMe.contains(ref.typeData.data())) {
+ qCDebug(lcCycle) << "Possible cyclic dependency detected between"
+ << ref.typeData->urlString() << "and" << urlString();
continue;
}
addDependency(ref.typeData.data());
@@ -699,28 +925,36 @@ void QQmlTypeData::resolveTypes()
const bool reportErrors = unresolvedRef->errorWhenNotFound;
- int majorVersion = -1;
- int minorVersion = -1;
+ QTypeRevision version;
const QString name = stringAt(unresolvedRef.key());
- if (!resolveType(name, majorVersion, minorVersion, ref, unresolvedRef->location.line,
- unresolvedRef->location.column, reportErrors,
- QQmlType::AnyRegistrationType) && reportErrors)
+ bool *selfReferenceDetection = unresolvedRef->needsCreation ? nullptr : &ref.selfReference;
+
+ if (!resolveType(name, version, ref, unresolvedRef->location.line(),
+ unresolvedRef->location.column(), reportErrors,
+ QQmlType::AnyRegistrationType, selfReferenceDetection) && reportErrors)
return;
- if (ref.type.isComposite()) {
+ if (ref.type.isComposite() && !ref.selfReference) {
ref.typeData = typeLoader()->getType(ref.type.sourceUrl());
addDependency(ref.typeData.data());
}
- ref.majorVersion = majorVersion;
- ref.minorVersion = minorVersion;
-
- ref.location.line = unresolvedRef->location.line;
- ref.location.column = unresolvedRef->location.column;
+ if (ref.type.isInlineComponentType()) {
+ QUrl containingTypeUrl = ref.type.sourceUrl();
+ containingTypeUrl.setFragment(QString());
+ if (!containingTypeUrl.isEmpty()) {
+ auto typeData = typeLoader()->getType(containingTypeUrl);
+ if (typeData.data() != this) {
+ ref.typeData = typeData;
+ addDependency(typeData.data());
+ }
+ }
+ }
+ ref.version = version;
+ ref.location = unresolvedRef->location;
ref.needsCreation = unresolvedRef->needsCreation;
-
m_resolvedTypes.insert(unresolvedRef.key(), ref);
}
@@ -729,10 +963,9 @@ void QQmlTypeData::resolveTypes()
loadImplicitImport();
}
-QQmlJS::DiagnosticMessage QQmlTypeData::buildTypeResolutionCaches(
+QQmlError QQmlTypeData::buildTypeResolutionCaches(
QQmlRefPointer<QQmlTypeNameCache> *typeNameCache,
- QV4::ResolvedTypeReferenceMap *resolvedTypeCache
- ) const
+ QV4::CompiledData::ResolvedTypeReferenceMap *resolvedTypeCache) const
{
typeNameCache->adopt(new QQmlTypeNameCache(m_importCache));
@@ -743,59 +976,88 @@ QQmlJS::DiagnosticMessage QQmlTypeData::buildTypeResolutionCaches(
for (const QQmlTypeData::TypeReference &singleton: m_compositeSingletons)
(*typeNameCache)->add(singleton.type.qmlTypeName(), singleton.type.sourceUrl(), singleton.prefix);
- m_importCache.populateCache(typeNameCache->data());
-
- QQmlEnginePrivate * const engine = QQmlEnginePrivate::get(typeLoader()->engine());
+ m_importCache->populateCache(typeNameCache->data());
for (auto resolvedType = m_resolvedTypes.constBegin(), end = m_resolvedTypes.constEnd(); resolvedType != end; ++resolvedType) {
- QScopedPointer<QV4::ResolvedTypeReference> ref(new QV4::ResolvedTypeReference);
+ auto ref = std::make_unique<QV4::ResolvedTypeReference>();
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()));
}
- ref->compilationUnit = resolvedType->typeData->compilationUnit();
- } else if (qmlType.isValid()) {
- ref->type = qmlType;
- Q_ASSERT(ref->type.isValid());
+ ref->setCompilationUnit(resolvedType->typeData->compilationUnit());
+ if (resolvedType->type.isInlineComponentType()) {
+ // Inline component which is part of an already resolved type
+ QString icName = qmlType.elementName();
+ Q_ASSERT(!icName.isEmpty());
+
+ const auto compilationUnit = resolvedType->typeData->compilationUnit();
+ ref->setTypePropertyCache(compilationUnit->propertyCaches.at(
+ compilationUnit->inlineComponentId(icName)));
+ ref->setType(std::move(qmlType));
+ Q_ASSERT(ref->type().isInlineComponentType());
+ }
+ } else if (resolvedType->type.isInlineComponentType()) {
+ ref->setType(qmlType);
+
+ // Inline component
+ // If it's defined in the same file we're currently compiling, we don't want to use it.
+ // We're going to fill in the property caches later after all.
+ if (qmlType.isValid()
+ && !QQmlMetaType::equalBaseUrls(finalUrl(), qmlType.sourceUrl())) {
+
+ // this is required for inline components in singletons
+ const QMetaType type = qmlType.typeId();
+ if (auto unit = QQmlMetaType::obtainCompilationUnit(type)) {
+ ref->setCompilationUnit(std::move(unit));
+ ref->setTypePropertyCache(QQmlMetaType::propertyCacheForType(type));
+ }
+ }
+ } else if (qmlType.isValid() && !resolvedType->selfReference) {
+ ref->setType(qmlType);
+ Q_ASSERT(ref->type().isValid());
- if (resolvedType->needsCreation && !ref->type.isCreatable()) {
- QString reason = ref->type.noCreationReason();
+ if (resolvedType->needsCreation && !qmlType.isCreatable()) {
+ QString reason = qmlType.noCreationReason();
if (reason.isEmpty())
reason = tr("Element is not creatable.");
return qQmlCompileError(resolvedType->location, reason);
}
- if (ref->type.containsRevisionedAttributes()) {
- ref->typePropertyCache = engine->cache(ref->type,
- resolvedType->minorVersion);
+ if (qmlType.containsRevisionedAttributes()) {
+ // It can only have (revisioned) properties or methods if it has a metaobject
+ Q_ASSERT(qmlType.metaObject());
+ ref->setTypePropertyCache(
+ QQmlMetaType::propertyCache(qmlType, resolvedType->version));
}
}
- ref->majorVersion = resolvedType->majorVersion;
- ref->minorVersion = resolvedType->minorVersion;
+ ref->setVersion(resolvedType->version);
ref->doDynamicTypeCheck();
- resolvedTypeCache->insert(resolvedType.key(), ref.take());
+ resolvedTypeCache->insert(resolvedType.key(), ref.release());
}
- QQmlJS::DiagnosticMessage noError;
+ QQmlError noError;
return noError;
}
-bool QQmlTypeData::resolveType(const QString &typeName, int &majorVersion, int &minorVersion,
+bool QQmlTypeData::resolveType(const QString &typeName, QTypeRevision &version,
TypeReference &ref, int lineNumber, int columnNumber,
- bool reportErrors, QQmlType::RegistrationType registrationType)
+ bool reportErrors, QQmlType::RegistrationType registrationType,
+ bool *typeRecursionDetected)
{
QQmlImportNamespace *typeNamespace = nullptr;
QList<QQmlError> errors;
- bool typeFound = m_importCache.resolveType(typeName, &ref.type, &majorVersion, &minorVersion,
- &typeNamespace, &errors, registrationType);
+ bool typeFound = m_importCache->resolveType(
+ typeLoader(), typeName, &ref.type, &version, &typeNamespace, &errors, registrationType,
+ typeRecursionDetected);
if (!typeNamespace && !typeFound && !m_implicitImportLoaded) {
// Lazy loading of implicit import
if (loadImplicitImport()) {
// Try again to find the type
errors.clear();
- typeFound = m_importCache.resolveType(typeName, &ref.type, &majorVersion, &minorVersion,
- &typeNamespace, &errors, registrationType);
+ typeFound = m_importCache->resolveType(
+ typeLoader(), typeName, &ref.type, &version, &typeNamespace, &errors,
+ registrationType, typeRecursionDetected);
} else {
return false; //loadImplicitImport() hit an error, and called setError already
}
@@ -816,7 +1078,7 @@ bool QQmlTypeData::resolveType(const QString &typeName, int &majorVersion, int &
// Description should come from error provided by addImport() function.
error.setDescription(QQmlTypeLoader::tr("Unreported error adding script import to import database"));
}
- error.setUrl(m_importCache.baseUrl());
+ error.setUrl(m_importCache->baseUrl());
error.setDescription(QQmlTypeLoader::tr("%1 %2").arg(typeName).arg(error.description()));
}
@@ -833,12 +1095,14 @@ bool QQmlTypeData::resolveType(const QString &typeName, int &majorVersion, int &
return true;
}
-void QQmlTypeData::scriptImported(const QQmlRefPointer<QQmlScriptBlob> &blob, const QV4::CompiledData::Location &location, const QString &qualifier, const QString &/*nameSpace*/)
+void QQmlTypeData::scriptImported(
+ const QQmlRefPointer<QQmlScriptBlob> &blob, const QV4::CompiledData::Location &location,
+ const QString &nameSpace, const QString &qualifier)
{
ScriptReference ref;
ref.script = blob;
ref.location = location;
- ref.qualifier = qualifier;
+ ref.qualifier = qualifier.isEmpty() ? nameSpace : qualifier + QLatin1Char('.') + nameSpace;
m_scripts << ref;
}