aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml
diff options
context:
space:
mode:
authorAlan Alpert <aalpert@rim.com>2012-12-08 13:57:12 -0800
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-03-27 20:40:28 +0100
commit1f3038d2144603c687d85b0a7962322d3c9ae422 (patch)
tree461b411e8b5b98a0f37495a51e24687d4ca675f5 /src/qml
parentf7ada9b9325c7adc10da6a3a4e7f887452682260 (diff)
Delay loading implicit import
As a performance improvement to avoid extra filesystem access, only import "." if it is needed for type resolution. Change-Id: If9be25deb3205f8c81f9f418404d9fb41bebb84f Reviewed-by: Christopher Adams <chris.adams@jollamobile.com>
Diffstat (limited to 'src/qml')
-rw-r--r--src/qml/qml/qqmlimport.cpp14
-rw-r--r--src/qml/qml/qqmltypeloader.cpp59
-rw-r--r--src/qml/qml/qqmltypeloader_p.h2
3 files changed, 55 insertions, 20 deletions
diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp
index d3ec9e67f7..f793ca9604 100644
--- a/src/qml/qml/qqmlimport.cpp
+++ b/src/qml/qml/qqmlimport.cpp
@@ -260,7 +260,7 @@ public:
QQmlImportNamespace::Import *addImportToNamespace(QQmlImportNamespace *nameSpace,
const QString &uri, const QString &url,
int vmaj, int vmin, QQmlScript::Import::Type type,
- QList<QQmlError> *errors);
+ QList<QQmlError> *errors, bool lowPrecedence = false);
};
/*!
@@ -1003,7 +1003,7 @@ QQmlImportNamespace *QQmlImportsPrivate::importNamespace(const QString &prefix)
QQmlImportNamespace::Import *QQmlImportsPrivate::addImportToNamespace(QQmlImportNamespace *nameSpace,
const QString &uri, const QString &url, int vmaj, int vmin,
QQmlScript::Import::Type type,
- QList<QQmlError> *errors)
+ QList<QQmlError> *errors, bool lowPrecedence)
{
Q_ASSERT(nameSpace);
Q_ASSERT(errors);
@@ -1017,7 +1017,11 @@ QQmlImportNamespace::Import *QQmlImportsPrivate::addImportToNamespace(QQmlImport
import->minversion = vmin;
import->isLibrary = (type == QQmlScript::Import::Library);
- nameSpace->imports.prepend(import);
+ if (lowPrecedence)
+ nameSpace->imports.append(import);
+ else
+ nameSpace->imports.prepend(import);
+
return import;
}
@@ -1162,7 +1166,7 @@ bool QQmlImportsPrivate::addFileImport(const QString& uri, const QString &prefix
if (!url.endsWith(Slash) && !url.endsWith(Backslash))
url += Slash;
- QQmlImportNamespace::Import *inserted = addImportToNamespace(nameSpace, importUri, url, vmaj, vmin, QQmlScript::Import::File, errors);
+ QQmlImportNamespace::Import *inserted = addImportToNamespace(nameSpace, importUri, url, vmaj, vmin, QQmlScript::Import::File, errors, isImplicitImport);
Q_ASSERT(inserted);
if (!incomplete && !qmldirIdentifier.isEmpty()) {
@@ -1238,6 +1242,8 @@ bool QQmlImportsPrivate::updateQmldirContent(const QString &uri, const QString &
Adds an implicit "." file import. This is equivalent to calling addFileImport(), but error
messages related to the path or qmldir file not existing are suppressed.
+
+ Additionally, this will add the import with lowest instead of highest precedence.
*/
bool QQmlImports::addImplicitImport(QQmlImportDatabase *importDb, QList<QQmlError> *errors)
{
diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp
index 9547204760..e800eb815d 100644
--- a/src/qml/qml/qqmltypeloader.cpp
+++ b/src/qml/qml/qqmltypeloader.cpp
@@ -1902,7 +1902,7 @@ QQmlTypeData::TypeDataCallback::~TypeDataCallback()
QQmlTypeData::QQmlTypeData(const QUrl &url, QQmlTypeLoader::Options options,
QQmlTypeLoader *manager)
: QQmlTypeLoader::Blob(url, QmlFile, manager), m_options(options),
- m_typesResolved(false), m_compiledData(0), m_implicitImport(0)
+ m_typesResolved(false), m_compiledData(0), m_implicitImport(0), m_implicitImportLoaded(false)
{
}
@@ -2008,23 +2008,14 @@ void QQmlTypeData::completed()
}
}
-void QQmlTypeData::dataReceived(const Data &data)
+bool QQmlTypeData::loadImplicitImport()
{
- QString code = QString::fromUtf8(data.data(), data.size());
- QByteArray preparseData;
-
- if (data.isFile()) preparseData = data.asFile()->metaData(QLatin1String("qml:preparse"));
-
- if (!scriptParser.parse(code, preparseData, finalUrl(), finalUrlString())) {
- setError(scriptParser.errors());
- return;
- }
+ m_implicitImportLoaded = true; // Even if we hit an error, count as loaded (we'd just keep hitting the error)
m_imports.setBaseUrl(finalUrl(), finalUrlString());
QQmlImportDatabase *importDatabase = typeLoader()->importDatabase();
-
- // For local urls, add an implicit import "." as first (most overridden) lookup.
+ // 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;
@@ -2032,20 +2023,41 @@ void QQmlTypeData::dataReceived(const Data &data)
if (!implicitImportErrors.isEmpty()) {
setError(implicitImportErrors);
+ return false;
+ }
+
+ return true;
+}
+
+void QQmlTypeData::dataReceived(const Data &data)
+{
+ QString code = QString::fromUtf8(data.data(), data.size());
+ QByteArray preparseData;
+
+ if (data.isFile()) preparseData = data.asFile()->metaData(QLatin1String("qml:preparse"));
+
+ if (!scriptParser.parse(code, preparseData, finalUrl(), finalUrlString())) {
+ setError(scriptParser.errors());
return;
}
- QList<QQmlError> errors;
+ m_imports.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
+ // qmldir (so we can't load it just in time).
if (!finalUrl().scheme().isEmpty()) {
QUrl qmldirUrl = finalUrl().resolved(QUrl(QLatin1String("qmldir")));
if (!QQmlImports::isLocal(qmldirUrl)) {
+ if (!loadImplicitImport())
+ return;
// This qmldir is for the implicit import
m_implicitImport = new QQmlScript::Import;
m_implicitImport->uri = QLatin1String(".");
m_implicitImport->qualifier = QString();
m_implicitImport->majorVersion = -1;
m_implicitImport->minorVersion = -1;
+ QList<QQmlError> errors;
if (!fetchQmldir(qmldirUrl, m_implicitImport, 1, &errors)) {
setError(errors);
@@ -2054,6 +2066,8 @@ void QQmlTypeData::dataReceived(const Data &data)
}
}
+ QList<QQmlError> errors;
+
foreach (const QQmlScript::Import &import, scriptParser.imports()) {
if (!addImport(import, &errors)) {
Q_ASSERT(errors.size());
@@ -2155,8 +2169,21 @@ void QQmlTypeData::resolveTypes()
QQmlImportNamespace *typeNamespace = 0;
QList<QQmlError> errors;
- if (!m_imports.resolveType(parserRef->name, &ref.type, &majorVersion, &minorVersion,
- &typeNamespace, &errors) || typeNamespace) {
+ bool typeFound = m_imports.resolveType(parserRef->name, &ref.type,
+ &majorVersion, &minorVersion, &typeNamespace, &errors);
+ if (!typeNamespace && !typeFound && !m_implicitImportLoaded) {
+ // Lazy loading of implicit import
+ if (loadImplicitImport()) {
+ // Try again to find the type
+ errors.clear();
+ typeFound = m_imports.resolveType(parserRef->name, &ref.type,
+ &majorVersion, &minorVersion, &typeNamespace, &errors);
+ } else {
+ return; //loadImplicitImport() hit an error, and called setError already
+ }
+ }
+
+ if (!typeFound || typeNamespace) {
// Known to not be a type:
// - known to be a namespace (Namespace {})
// - type with unknown namespace (UnknownNamespace.SomeType {})
diff --git a/src/qml/qml/qqmltypeloader_p.h b/src/qml/qml/qqmltypeloader_p.h
index b4ecfb77d1..68b8f33f88 100644
--- a/src/qml/qml/qqmltypeloader_p.h
+++ b/src/qml/qml/qqmltypeloader_p.h
@@ -465,6 +465,8 @@ private:
QList<TypeDataCallback *> m_callbacks;
QQmlScript::Import *m_implicitImport;
+ bool m_implicitImportLoaded;
+ bool loadImplicitImport();
};
// QQmlScriptData instances are created, uninitialized, by the loader in the