diff options
author | Simon Hausmann <simon.hausmann@qt.io> | 2016-06-17 13:21:07 +0200 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@qt.io> | 2016-06-20 04:08:53 +0000 |
commit | 156d10e16557b0d9f6c66963019f267314e73f13 (patch) | |
tree | 15eba6c3f6a463d1fdd630090490d776fe59893b | |
parent | 8a33d37006e8ad9010fe076105ada9f1ca5d9871 (diff) |
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>
-rw-r--r-- | src/qml/qml/qqmltypeloader.cpp | 71 | ||||
-rw-r--r-- | src/qml/qml/qqmltypeloader_p.h | 47 | ||||
-rw-r--r-- | tests/auto/qml/qqmllanguage/data/badCompositeRegistration.1.errors.txt | 2 | ||||
-rw-r--r-- | tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp | 2 | ||||
-rw-r--r-- | tests/auto/quick/qquickloader/tst_qquickloader.cpp | 6 |
5 files changed, 62 insertions, 66 deletions
diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp index fef317cbbd..e11507a56a 100644 --- a/src/qml/qml/qqmltypeloader.cpp +++ b/src/qml/qml/qqmltypeloader.cpp @@ -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" diff --git a/src/qml/qml/qqmltypeloader_p.h b/src/qml/qml/qqmltypeloader_p.h index 20f701514a..d476056ef1 100644 --- a/src/qml/qml/qqmltypeloader_p.h +++ b/src/qml/qml/qqmltypeloader_p.h @@ -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 diff --git a/tests/auto/qml/qqmllanguage/data/badCompositeRegistration.1.errors.txt b/tests/auto/qml/qqmllanguage/data/badCompositeRegistration.1.errors.txt index 7a75447a62..acf0d1da84 100644 --- a/tests/auto/qml/qqmllanguage/data/badCompositeRegistration.1.errors.txt +++ b/tests/auto/qml/qqmllanguage/data/badCompositeRegistration.1.errors.txt @@ -1,2 +1,2 @@ 3:1:Type RegisteredCompositeType2 unavailable --1:-1:File not found +-1:-1:No such file or directory diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp index e800d64471..70db9aecd4 100644 --- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp +++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp @@ -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); diff --git a/tests/auto/quick/qquickloader/tst_qquickloader.cpp b/tests/auto/quick/qquickloader/tst_qquickloader.cpp index fe22a238b2..77af4796b6 100644 --- a/tests/auto/quick/qquickloader/tst_qquickloader.cpp +++ b/tests/auto/quick/qquickloader/tst_qquickloader.cpp @@ -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")); |