aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/qml/qqmltypeloader.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml/qml/qqmltypeloader.cpp')
-rw-r--r--src/qml/qml/qqmltypeloader.cpp109
1 files changed, 65 insertions, 44 deletions
diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp
index 81bda2c3bb..ed742c3681 100644
--- a/src/qml/qml/qqmltypeloader.cpp
+++ b/src/qml/qml/qqmltypeloader.cpp
@@ -984,16 +984,6 @@ void QQmlTypeLoader::setProfiler(QQmlProfiler *profiler)
}
#endif
-void QQmlTypeLoader::lock()
-{
- m_thread->lock();
-}
-
-void QQmlTypeLoader::unlock()
-{
- m_thread->unlock();
-}
-
struct PlainLoader {
void loadThread(QQmlTypeLoader *loader, QQmlDataBlob *blob) const
{
@@ -1276,6 +1266,7 @@ void QQmlTypeLoader::setData(QQmlDataBlob *blob, const QByteArray &data)
QML_MEMORY_SCOPE_URL(blob->url());
QQmlDataBlob::SourceCodeData d;
d.inlineSourceCode = QString::fromUtf8(data);
+ d.hasInlineSourceCode = true;
setData(blob, d);
}
@@ -1387,8 +1378,8 @@ bool QQmlTypeLoader::Blob::updateQmldir(QQmlQmldirData *data, const QV4::Compile
if (!importQualifier.isEmpty()) {
// Does this library contain any qualified scripts?
QUrl libraryUrl(qmldirUrl);
- const QQmlTypeLoaderQmldirContent *qmldir = typeLoader()->qmldirContent(qmldirIdentifier);
- const auto qmldirScripts = qmldir->scripts();
+ const QQmlTypeLoaderQmldirContent qmldir = typeLoader()->qmldirContent(qmldirIdentifier);
+ const auto qmldirScripts = qmldir.scripts();
for (const QQmlDirParser::Script &script : qmldirScripts) {
QUrl scriptUrl = libraryUrl.resolved(QUrl(script.fileName));
QQmlScriptBlob *blob = typeLoader()->getScript(scriptUrl);
@@ -1435,8 +1426,8 @@ bool QQmlTypeLoader::Blob::addImport(const QV4::CompiledData::Import *import, QL
if (!importQualifier.isEmpty()) {
// Does this library contain any qualified scripts?
QUrl libraryUrl(qmldirUrl);
- const QQmlTypeLoaderQmldirContent *qmldir = typeLoader()->qmldirContent(qmldirFilePath);
- const auto qmldirScripts = qmldir->scripts();
+ const QQmlTypeLoaderQmldirContent qmldir = typeLoader()->qmldirContent(qmldirFilePath);
+ const auto qmldirScripts = qmldir.scripts();
for (const QQmlDirParser::Script &script : qmldirScripts) {
QUrl scriptUrl = libraryUrl.resolved(QUrl(script.fileName));
QQmlScriptBlob *blob = typeLoader()->getScript(scriptUrl);
@@ -1601,6 +1592,7 @@ QString QQmlTypeLoaderQmldirContent::typeNamespace() const
void QQmlTypeLoaderQmldirContent::setContent(const QString &location, const QString &content)
{
+ m_hasContent = true;
m_location = location;
m_parser.parse(content);
}
@@ -1639,8 +1631,10 @@ bool QQmlTypeLoaderQmldirContent::designerSupported() const
Constructs a new type loader that uses the given \a engine.
*/
QQmlTypeLoader::QQmlTypeLoader(QQmlEngine *engine)
- : m_engine(engine), m_thread(new QQmlTypeLoaderThread(this)),
- m_typeCacheTrimThreshold(TYPELOADER_MINIMUM_TRIM_THRESHOLD)
+ : m_engine(engine)
+ , m_thread(new QQmlTypeLoaderThread(this))
+ , m_mutex(m_thread->mutex())
+ , m_typeCacheTrimThreshold(TYPELOADER_MINIMUM_TRIM_THRESHOLD)
{
}
@@ -1684,9 +1678,11 @@ QQmlTypeData *QQmlTypeLoader::getType(const QUrl &url, Mode mode)
typeData = new QQmlTypeData(url, this);
// TODO: if (compiledData == 0), is it safe to omit this insertion?
m_typeCache.insert(url, typeData);
- if (const QV4::CompiledData::Unit *cachedUnit = QQmlMetaType::findCachedCompilationUnit(typeData->url())) {
+ QQmlMetaType::CachedUnitLookupError error = QQmlMetaType::CachedUnitLookupError::NoError;
+ if (const QV4::CompiledData::Unit *cachedUnit = QQmlMetaType::findCachedCompilationUnit(typeData->url(), &error)) {
QQmlTypeLoader::loadWithCachedUnit(typeData, cachedUnit, mode);
} else {
+ typeData->setCachedUnitStatus(error);
QQmlTypeLoader::load(typeData, mode);
}
} else if ((mode == PreferSynchronous || mode == Synchronous) && QQmlFile::isSynchronous(url)) {
@@ -1745,9 +1741,11 @@ QQmlScriptBlob *QQmlTypeLoader::getScript(const QUrl &url)
scriptBlob = new QQmlScriptBlob(url, this);
m_scriptCache.insert(url, scriptBlob);
- if (const QV4::CompiledData::Unit *cachedUnit = QQmlMetaType::findCachedCompilationUnit(scriptBlob->url())) {
+ QQmlMetaType::CachedUnitLookupError error;
+ if (const QV4::CompiledData::Unit *cachedUnit = QQmlMetaType::findCachedCompilationUnit(scriptBlob->url(), &error)) {
QQmlTypeLoader::loadWithCachedUnit(scriptBlob, cachedUnit);
} else {
+ scriptBlob->setCachedUnitStatus(error);
QQmlTypeLoader::load(scriptBlob);
}
}
@@ -1831,6 +1829,7 @@ QString QQmlTypeLoader::absoluteFilePath(const QString &path)
int lastSlash = path.lastIndexOf(QLatin1Char('/'));
QString dirPath(path.left(lastSlash));
+ LockHolder<QQmlTypeLoader> holder(this);
if (!m_importDirCache.contains(dirPath)) {
bool exists = QDir(dirPath).exists();
QCache<QString, bool> *entry = exists ? new QCache<QString, bool> : nullptr;
@@ -1894,6 +1893,7 @@ bool QQmlTypeLoader::directoryExists(const QString &path)
--length;
QString dirPath(path.left(length));
+ LockHolder<QQmlTypeLoader> holder(this);
if (!m_importDirCache.contains(dirPath)) {
bool exists = QDir(dirPath).exists();
QCache<QString, bool> *files = exists ? new QCache<QString, bool> : nullptr;
@@ -1912,8 +1912,10 @@ Return a QQmlTypeLoaderQmldirContent for absoluteFilePath. The QQmlTypeLoaderQm
It can also be a remote path for a remote directory import, but it will have been cached by now in this case.
*/
-const QQmlTypeLoaderQmldirContent *QQmlTypeLoader::qmldirContent(const QString &filePathIn)
+const QQmlTypeLoaderQmldirContent QQmlTypeLoader::qmldirContent(const QString &filePathIn)
{
+ LockHolder<QQmlTypeLoader> holder(this);
+
QString filePath;
// Try to guess if filePathIn is already a URL. This is necessarily fragile, because
@@ -1927,39 +1929,39 @@ const QQmlTypeLoaderQmldirContent *QQmlTypeLoader::qmldirContent(const QString &
filePath = filePathIn;
} else {
filePath = QQmlFile::urlToLocalFileOrQrc(url);
- if (filePath.isEmpty()) // Can't load the remote here, but should be cached
- return *(m_importQmlDirCache.value(filePathIn));
+ if (filePath.isEmpty()) { // Can't load the remote here, but should be cached
+ if (auto entry = m_importQmlDirCache.value(filePathIn))
+ return **entry;
+ else
+ return QQmlTypeLoaderQmldirContent();
+ }
}
- QQmlTypeLoaderQmldirContent *qmldir;
QQmlTypeLoaderQmldirContent **val = m_importQmlDirCache.value(filePath);
- if (!val) {
- qmldir = new QQmlTypeLoaderQmldirContent;
+ if (val)
+ return **val;
+ QQmlTypeLoaderQmldirContent *qmldir = new QQmlTypeLoaderQmldirContent;
#define ERROR(description) { QQmlError e; e.setDescription(description); qmldir->setError(e); }
#define NOT_READABLE_ERROR QString(QLatin1String("module \"$$URI$$\" definition \"%1\" not readable"))
#define CASE_MISMATCH_ERROR QString(QLatin1String("cannot load module \"$$URI$$\": File name case mismatch for \"%1\""))
- QFile file(filePath);
- if (!QQml_isFileCaseCorrect(filePath)) {
- ERROR(CASE_MISMATCH_ERROR.arg(filePath));
- } else if (file.open(QFile::ReadOnly)) {
- QByteArray data = file.readAll();
- qmldir->setContent(filePath, QString::fromUtf8(data));
- } else {
- ERROR(NOT_READABLE_ERROR.arg(filePath));
- }
+ QFile file(filePath);
+ if (!QQml_isFileCaseCorrect(filePath)) {
+ ERROR(CASE_MISMATCH_ERROR.arg(filePath));
+ } else if (file.open(QFile::ReadOnly)) {
+ QByteArray data = file.readAll();
+ qmldir->setContent(filePath, QString::fromUtf8(data));
+ } else {
+ ERROR(NOT_READABLE_ERROR.arg(filePath));
+ }
#undef ERROR
#undef NOT_READABLE_ERROR
#undef CASE_MISMATCH_ERROR
- m_importQmlDirCache.insert(filePath, qmldir);
- } else {
- qmldir = *val;
- }
-
- return qmldir;
+ m_importQmlDirCache.insert(filePath, qmldir);
+ return *qmldir;
}
void QQmlTypeLoader::setQmldirContent(const QString &url, const QString &content)
@@ -2446,8 +2448,13 @@ void QQmlTypeData::dataReceived(const SourceCodeData &data)
if (isError())
return;
- if (!m_backupSourceCode.exists()) {
- setError(QQmlTypeLoader::tr("No such file or directory"));
+ if (!m_backupSourceCode.exists() || m_backupSourceCode.isEmpty()) {
+ if (m_cachedUnitStatus == QQmlMetaType::CachedUnitLookupError::VersionMismatch)
+ setError(QQmlTypeLoader::tr("File was compiled ahead of time with an incompatible version of Qt and the original file cannot be found. Please recompile"));
+ else if (!m_backupSourceCode.exists())
+ setError(QQmlTypeLoader::tr("No such file or directory"));
+ else
+ setError(QQmlTypeLoader::tr("File is empty"));
return;
}
@@ -2999,6 +3006,13 @@ void QQmlScriptBlob::dataReceived(const SourceCodeData &data)
}
}
+ if (!data.exists()) {
+ if (m_cachedUnitStatus == QQmlMetaType::CachedUnitLookupError::VersionMismatch)
+ setError(QQmlTypeLoader::tr("File was compiled ahead of time with an incompatible version of Qt and the original file cannot be found. Please recompile"));
+ else
+ setError(QQmlTypeLoader::tr("No such file or directory"));
+ return;
+ }
QmlIR::Document irUnit(isDebugging());
@@ -3196,7 +3210,7 @@ void QQmlQmldirData::initializeFromCachedUnit(const QV4::CompiledData::Unit *)
QString QQmlDataBlob::SourceCodeData::readAll(QString *error) const
{
error->clear();
- if (!inlineSourceCode.isEmpty())
+ if (hasInlineSourceCode)
return inlineSourceCode;
QFile f(fileInfo.absoluteFilePath());
@@ -3223,7 +3237,7 @@ QString QQmlDataBlob::SourceCodeData::readAll(QString *error) const
QDateTime QQmlDataBlob::SourceCodeData::sourceTimeStamp() const
{
- if (!inlineSourceCode.isEmpty())
+ if (hasInlineSourceCode)
return QDateTime();
QDateTime timeStamp = fileInfo.lastModified();
@@ -3238,11 +3252,18 @@ QDateTime QQmlDataBlob::SourceCodeData::sourceTimeStamp() const
bool QQmlDataBlob::SourceCodeData::exists() const
{
- if (!inlineSourceCode.isEmpty())
+ if (hasInlineSourceCode)
return true;
return fileInfo.exists();
}
+bool QQmlDataBlob::SourceCodeData::isEmpty() const
+{
+ if (hasInlineSourceCode)
+ return inlineSourceCode.isEmpty();
+ return fileInfo.size() == 0;
+}
+
QT_END_NAMESPACE
#include "qqmltypeloader.moc"