Clean up file/error handling in the type loader
Fold the functionality of reading QFile contents via QQmlFile into QQmlDataBlob::Data. This reduces the dependency on QQmlFile - which is scheduled for removal - and it makes it possible in the future to avoid reading the file altogether if we have a cached compilation unit on disk. Change-Id: Ieeaf52b6fb1d25665cd3c3b196819e25aba3dd15 Reviewed-by: Lars Knoll <lars.knoll@qt.io>
This commit is contained in:
parent
8a33d37006
commit
156d10e165
|
@ -445,6 +445,14 @@ void QQmlDataBlob::setError(const QQmlCompileError &error)
|
|||
setError(e);
|
||||
}
|
||||
|
||||
void QQmlDataBlob::setError(const QString &description)
|
||||
{
|
||||
QQmlError e;
|
||||
e.setDescription(description);
|
||||
e.setUrl(finalUrl());
|
||||
setError(e);
|
||||
}
|
||||
|
||||
/*!
|
||||
Wait for \a blob to become complete or to error. If \a blob is already
|
||||
complete or in error, or this blob is already complete, this has no effect.
|
||||
|
@ -1091,13 +1099,9 @@ void QQmlTypeLoader::loadThread(QQmlDataBlob *blob)
|
|||
QML_MEMORY_SCOPE_URL(blob->m_url);
|
||||
|
||||
if (QQmlFile::isSynchronous(blob->m_url)) {
|
||||
QQmlFile file(m_engine, blob->m_url);
|
||||
|
||||
if (file.isError()) {
|
||||
QQmlError error;
|
||||
error.setUrl(blob->m_url);
|
||||
error.setDescription(file.error());
|
||||
blob->setError(error);
|
||||
const QString fileName = QQmlFile::urlToLocalFileOrQrc(blob->m_url);
|
||||
if (!QQml_isFileCaseCorrect(fileName)) {
|
||||
blob->setError(QLatin1String("File name case mismatch"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1105,7 +1109,7 @@ void QQmlTypeLoader::loadThread(QQmlDataBlob *blob)
|
|||
if (blob->m_data.isAsync())
|
||||
m_thread->callDownloadProgressChanged(blob, 1.);
|
||||
|
||||
setData(blob, &file);
|
||||
setData(blob, fileName);
|
||||
|
||||
} else {
|
||||
#ifndef QT_NO_NETWORK
|
||||
|
@ -1225,11 +1229,11 @@ void QQmlTypeLoader::setData(QQmlDataBlob *blob, const QByteArray &data)
|
|||
setData(blob, d);
|
||||
}
|
||||
|
||||
void QQmlTypeLoader::setData(QQmlDataBlob *blob, QQmlFile *file)
|
||||
void QQmlTypeLoader::setData(QQmlDataBlob *blob, const QString &fileName)
|
||||
{
|
||||
QML_MEMORY_SCOPE_URL(blob->url());
|
||||
QQmlDataBlob::Data d;
|
||||
d.d = file;
|
||||
d.d = &fileName;
|
||||
setData(blob, d);
|
||||
}
|
||||
|
||||
|
@ -2122,11 +2126,7 @@ void QQmlTypeData::done()
|
|||
QQmlType *type = QQmlMetaType::qmlType(url(), true);
|
||||
if (!isError() && type && type->isCompositeSingleton() && !m_isSingleton) {
|
||||
QString typeName = type->qmlTypeName();
|
||||
|
||||
QQmlError error;
|
||||
error.setDescription(QQmlTypeLoader::tr("qmldir defines type as singleton, but no pragma Singleton found in type %1.").arg(typeName));
|
||||
error.setUrl(finalUrl());
|
||||
setError(error);
|
||||
setError(QQmlTypeLoader::tr("qmldir defines type as singleton, but no pragma Singleton found in type %1.").arg(typeName));
|
||||
}
|
||||
|
||||
// Compile component
|
||||
|
@ -2170,7 +2170,12 @@ bool QQmlTypeData::loadImplicitImport()
|
|||
|
||||
void QQmlTypeData::dataReceived(const Data &data)
|
||||
{
|
||||
QString code = QString::fromUtf8(data.data(), data.size());
|
||||
QString error;
|
||||
QString code = QString::fromUtf8(data.readAll(&error));
|
||||
if (!error.isEmpty()) {
|
||||
setError(error);
|
||||
return;
|
||||
}
|
||||
QQmlEngine *qmlEngine = typeLoader()->engine();
|
||||
m_document.reset(new QmlIR::Document(QV8Engine::getV4(qmlEngine)->debugger != 0));
|
||||
QmlIR::IRBuilder compiler(QV8Engine::get(qmlEngine)->illegalNames());
|
||||
|
@ -2699,7 +2704,12 @@ struct EmptyCompilationUnit : public QV4::CompiledData::CompilationUnit
|
|||
|
||||
void QQmlScriptBlob::dataReceived(const Data &data)
|
||||
{
|
||||
QString source = QString::fromUtf8(data.data(), data.size());
|
||||
QString error;
|
||||
QString source = QString::fromUtf8(data.readAll(&error));
|
||||
if (!error.isEmpty()) {
|
||||
setError(error);
|
||||
return;
|
||||
}
|
||||
|
||||
QV4::ExecutionEngine *v4 = QV8Engine::getV4(m_typeLoader->engine());
|
||||
QmlIR::Document irUnit(v4->debugger != 0);
|
||||
|
@ -2854,7 +2864,12 @@ void QQmlQmldirData::setPriority(int priority)
|
|||
|
||||
void QQmlQmldirData::dataReceived(const Data &data)
|
||||
{
|
||||
m_content = QString::fromUtf8(data.data(), data.size());
|
||||
QString error;
|
||||
m_content = QString::fromUtf8(data.readAll(&error));
|
||||
if (!error.isEmpty()) {
|
||||
setError(error);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void QQmlQmldirData::initializeFromCachedUnit(const QQmlPrivate::CachedQmlUnit *)
|
||||
|
@ -2862,6 +2877,26 @@ void QQmlQmldirData::initializeFromCachedUnit(const QQmlPrivate::CachedQmlUnit *
|
|||
Q_UNIMPLEMENTED();
|
||||
}
|
||||
|
||||
QByteArray QQmlDataBlob::Data::readAll(QString *error) const
|
||||
{
|
||||
Q_ASSERT(!d.isNull());
|
||||
error->clear();
|
||||
if (d.isT1()) {
|
||||
return *d.asT1();
|
||||
}
|
||||
QFile f(*d.asT2());
|
||||
if (!f.open(QIODevice::ReadOnly)) {
|
||||
*error = f.errorString();
|
||||
return QByteArray();
|
||||
}
|
||||
QByteArray data(f.size(), Qt::Uninitialized);
|
||||
if (f.read(data.data(), data.length()) != data.length()) {
|
||||
*error = f.errorString();
|
||||
return QByteArray();
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#include "qqmltypeloader.moc"
|
||||
|
|
|
@ -131,21 +131,14 @@ public:
|
|||
|
||||
class Data {
|
||||
public:
|
||||
inline const char *data() const;
|
||||
inline int size() const;
|
||||
|
||||
inline QByteArray asByteArray() const;
|
||||
|
||||
inline bool isFile() const;
|
||||
inline QQmlFile *asFile() const;
|
||||
|
||||
QByteArray readAll(QString *error) const;
|
||||
private:
|
||||
friend class QQmlDataBlob;
|
||||
friend class QQmlTypeLoader;
|
||||
inline Data();
|
||||
Data(const Data &);
|
||||
Data &operator=(const Data &);
|
||||
QBiPointer<const QByteArray, QQmlFile> d;
|
||||
QBiPointer<const QByteArray, const QString> d;
|
||||
};
|
||||
|
||||
protected:
|
||||
|
@ -153,6 +146,7 @@ protected:
|
|||
void setError(const QQmlError &);
|
||||
void setError(const QList<QQmlError> &errors);
|
||||
void setError(const QQmlCompileError &error);
|
||||
void setError(const QString &description);
|
||||
void addDependency(QQmlDataBlob *);
|
||||
|
||||
// Callbacks made in load thread
|
||||
|
@ -342,7 +336,7 @@ private:
|
|||
#endif
|
||||
|
||||
void setData(QQmlDataBlob *, const QByteArray &);
|
||||
void setData(QQmlDataBlob *, QQmlFile *);
|
||||
void setData(QQmlDataBlob *, const QString &fileName);
|
||||
void setData(QQmlDataBlob *, const QQmlDataBlob::Data &);
|
||||
void setCachedUnit(QQmlDataBlob *blob, const QQmlPrivate::CachedQmlUnit *unit);
|
||||
|
||||
|
@ -582,40 +576,7 @@ QQmlDataBlob::Data::Data()
|
|||
{
|
||||
}
|
||||
|
||||
const char *QQmlDataBlob::Data::data() const
|
||||
{
|
||||
Q_ASSERT(!d.isNull());
|
||||
|
||||
if (d.isT1()) return d.asT1()->constData();
|
||||
else return d.asT2()->data();
|
||||
}
|
||||
|
||||
int QQmlDataBlob::Data::size() const
|
||||
{
|
||||
Q_ASSERT(!d.isNull());
|
||||
|
||||
if (d.isT1()) return d.asT1()->size();
|
||||
else return d.asT2()->size();
|
||||
}
|
||||
|
||||
bool QQmlDataBlob::Data::isFile() const
|
||||
{
|
||||
return d.isT2();
|
||||
}
|
||||
|
||||
QByteArray QQmlDataBlob::Data::asByteArray() const
|
||||
{
|
||||
Q_ASSERT(!d.isNull());
|
||||
|
||||
if (d.isT1()) return *d.asT1();
|
||||
else return d.asT2()->dataByteArray();
|
||||
}
|
||||
|
||||
QQmlFile *QQmlDataBlob::Data::asFile() const
|
||||
{
|
||||
if (d.isT2()) return d.asT2();
|
||||
else return 0;
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
3:1:Type RegisteredCompositeType2 unavailable
|
||||
-1:-1:File not found
|
||||
-1:-1:No such file or directory
|
||||
|
|
|
@ -2898,7 +2898,7 @@ void tst_qqmllanguage::importIncorrectCase()
|
|||
QCOMPARE(errors.count(), 1);
|
||||
|
||||
const QString expectedError = isCaseSensitiveFileSystem(dataDirectory()) ?
|
||||
QStringLiteral("File not found") :
|
||||
QStringLiteral("No such file or directory") :
|
||||
QStringLiteral("File name case mismatch");
|
||||
QCOMPARE(errors.at(0).description(), expectedError);
|
||||
|
||||
|
|
|
@ -213,7 +213,7 @@ void tst_QQuickLoader::sourceOrComponent_data()
|
|||
QTest::newRow("source with encoded subdir binding") << "source" << "source: encodeURIComponent('subdir/Test.qml')\n" << testFileUrl("subdir/Test.qml") << "";
|
||||
QTest::newRow("sourceComponent") << "component" << "Component { id: comp; Rectangle { width: 100; height: 50 } }\n sourceComponent: comp\n" << QUrl() << "";
|
||||
QTest::newRow("invalid source") << "source" << "source: 'IDontExist.qml'\n" << testFileUrl("IDontExist.qml")
|
||||
<< QString(testFileUrl("IDontExist.qml").toString() + ": File not found");
|
||||
<< QString(testFileUrl("IDontExist.qml").toString() + ": No such file or directory");
|
||||
}
|
||||
|
||||
void tst_QQuickLoader::clear()
|
||||
|
@ -748,7 +748,7 @@ void tst_QQuickLoader::initialPropertyValuesError_data()
|
|||
<< (QStringList() << QString(testFileUrl("initialPropertyValues.error.1.qml").toString() + ":6:5: QML Loader: setSource: value is not an object"));
|
||||
|
||||
QTest::newRow("nonexistent source url") << testFileUrl("initialPropertyValues.error.2.qml")
|
||||
<< (QStringList() << QString(testFileUrl("NonexistentSourceComponent.qml").toString() + ": File not found"));
|
||||
<< (QStringList() << QString(testFileUrl("NonexistentSourceComponent.qml").toString() + ": No such file or directory"));
|
||||
|
||||
QTest::newRow("invalid source url") << testFileUrl("initialPropertyValues.error.3.qml")
|
||||
<< (QStringList() << QString(testFileUrl("InvalidSourceComponent.qml").toString() + ":5:1: Syntax error"));
|
||||
|
@ -901,7 +901,7 @@ void tst_QQuickLoader::asynchronous_data()
|
|||
<< QStringList();
|
||||
|
||||
QTest::newRow("Non-existent component") << testFileUrl("IDoNotExist.qml")
|
||||
<< (QStringList() << QString(testFileUrl("IDoNotExist.qml").toString() + ": File not found"));
|
||||
<< (QStringList() << QString(testFileUrl("IDoNotExist.qml").toString() + ": No such file or directory"));
|
||||
|
||||
QTest::newRow("Invalid component") << testFileUrl("InvalidSourceComponent.qml")
|
||||
<< (QStringList() << QString(testFileUrl("InvalidSourceComponent.qml").toString() + ":5:1: Syntax error"));
|
||||
|
|
Loading…
Reference in New Issue