aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/qml/compiler/qv4compileddata.cpp17
-rw-r--r--src/qml/compiler/qv4compileddata_p.h2
-rw-r--r--src/qml/compiler/qv4compiler.cpp1
-rw-r--r--src/qml/compiler/qv4jsir_p.h2
-rw-r--r--src/qml/qml/qqmltypeloader.cpp17
-rw-r--r--src/qml/qml/qqmltypeloader_p.h2
-rw-r--r--tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp5
7 files changed, 32 insertions, 14 deletions
diff --git a/src/qml/compiler/qv4compileddata.cpp b/src/qml/compiler/qv4compileddata.cpp
index 6a30faba19..3f7c8df973 100644
--- a/src/qml/compiler/qv4compileddata.cpp
+++ b/src/qml/compiler/qv4compileddata.cpp
@@ -339,14 +339,6 @@ bool CompilationUnit::loadFromDisk(const QUrl &url, QString *errorString)
QScopedPointer<QFile> cacheFile(new QFile(url.toLocalFile() + QLatin1Char('c')));
- {
- QFileInfo sourceCode(url.toLocalFile());
- if (sourceCode.exists() && sourceCode.lastModified() >= QFileInfo(*cacheFile).lastModified()) {
- *errorString = QStringLiteral("QML source file is equal or newer than cached file.");
- return false;
- }
- }
-
if (!cacheFile->open(QIODevice::ReadOnly)) {
*errorString = cacheFile->errorString();
return false;
@@ -360,6 +352,15 @@ bool CompilationUnit::loadFromDisk(const QUrl &url, QString *errorString)
QScopedValueRollback<const Unit *> dataPtrChange(data, reinterpret_cast<const Unit *>(cacheData));
+ {
+ QFileInfo sourceCode(url.toLocalFile());
+ if (sourceCode.exists() && sourceCode.lastModified().toMSecsSinceEpoch() != data->sourceTimeStamp) {
+ *errorString = QStringLiteral("QML source file has a different time stamp than cached file.");
+ return false;
+ }
+ }
+
+
if (!memoryMapCode(errorString))
return false;
diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h
index 0f85460a08..20b68026e9 100644
--- a/src/qml/compiler/qv4compileddata_p.h
+++ b/src/qml/compiler/qv4compileddata_p.h
@@ -96,6 +96,7 @@ typedef QJsonPrivate::q_littleendian<quint16> LEUInt16;
typedef QJsonPrivate::q_littleendian<quint32> LEUInt32;
typedef QJsonPrivate::q_littleendian<qint32> LEInt32;
typedef QJsonPrivate::q_littleendian<quint64> LEUInt64;
+typedef QJsonPrivate::q_littleendian<qint64> LEInt64;
struct String;
struct Function;
@@ -599,6 +600,7 @@ struct Unit
char magic[8];
LEInt16 architecture;
LEInt16 version;
+ LEInt64 sourceTimeStamp;
LEUInt32 unitSize; // Size of the Unit and any depending data.
enum : unsigned int {
diff --git a/src/qml/compiler/qv4compiler.cpp b/src/qml/compiler/qv4compiler.cpp
index fc462bb1c6..5d13734247 100644
--- a/src/qml/compiler/qv4compiler.cpp
+++ b/src/qml/compiler/qv4compiler.cpp
@@ -404,6 +404,7 @@ QV4::CompiledData::Unit QV4::Compiler::JSUnitGenerator::generateHeader(QV4::Comp
}
unit.indexOfRootFunction = -1;
unit.sourceFileIndex = getStringId(irModule->fileName);
+ unit.sourceTimeStamp = irModule->sourceTimeStamp;
unit.nImports = 0;
unit.offsetToImports = 0;
unit.nObjects = 0;
diff --git a/src/qml/compiler/qv4jsir_p.h b/src/qml/compiler/qv4jsir_p.h
index 2d6d7d728f..de84accbb1 100644
--- a/src/qml/compiler/qv4jsir_p.h
+++ b/src/qml/compiler/qv4jsir_p.h
@@ -932,6 +932,7 @@ struct Q_QML_PRIVATE_EXPORT Module {
QVector<Function *> functions;
Function *rootFunction;
QString fileName;
+ qint64 sourceTimeStamp;
bool isQmlModule; // implies rootFunction is always 0
bool debugMode;
@@ -939,6 +940,7 @@ struct Q_QML_PRIVATE_EXPORT Module {
Module(bool debugMode)
: rootFunction(0)
+ , sourceTimeStamp(0)
, isQmlModule(false)
, debugMode(debugMode)
{}
diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp
index 8deb41c505..adeec52b74 100644
--- a/src/qml/qml/qqmltypeloader.cpp
+++ b/src/qml/qml/qqmltypeloader.cpp
@@ -2305,14 +2305,16 @@ void QQmlTypeData::dataReceived(const Data &data)
if (tryLoadFromDiskCache())
return;
+ qint64 sourceTimeStamp;
QString error;
- QString code = QString::fromUtf8(data.readAll(&error));
+ QString code = QString::fromUtf8(data.readAll(&error, &sourceTimeStamp));
if (!error.isEmpty()) {
setError(error);
return;
}
QQmlEngine *qmlEngine = typeLoader()->engine();
m_document.reset(new QmlIR::Document(QV8Engine::getV4(qmlEngine)->debugger != 0));
+ m_document->jsModule.sourceTimeStamp = sourceTimeStamp;
QmlIR::IRBuilder compiler(QV8Engine::get(qmlEngine)->illegalNames());
if (!compiler.generateFromQml(code, finalUrlString(), m_document.data())) {
QList<QQmlError> errors;
@@ -2833,15 +2835,16 @@ struct EmptyCompilationUnit : public QV4::CompiledData::CompilationUnit
void QQmlScriptBlob::dataReceived(const Data &data)
{
+ QV4::ExecutionEngine *v4 = QV8Engine::getV4(m_typeLoader->engine());
+ QmlIR::Document irUnit(v4->debugger != 0);
+
QString error;
- QString source = QString::fromUtf8(data.readAll(&error));
+ QString source = QString::fromUtf8(data.readAll(&error, &irUnit.jsModule.sourceTimeStamp));
if (!error.isEmpty()) {
setError(error);
return;
}
- QV4::ExecutionEngine *v4 = QV8Engine::getV4(m_typeLoader->engine());
- QmlIR::Document irUnit(v4->debugger != 0);
QmlIR::ScriptDirectivesCollector collector(&irUnit.jsParserEngine, &irUnit.jsGenerator);
QList<QQmlError> errors;
@@ -3006,11 +3009,13 @@ void QQmlQmldirData::initializeFromCachedUnit(const QQmlPrivate::CachedQmlUnit *
Q_UNIMPLEMENTED();
}
-QByteArray QQmlDataBlob::Data::readAll(QString *error) const
+QByteArray QQmlDataBlob::Data::readAll(QString *error, qint64 *sourceTimeStamp) const
{
Q_ASSERT(!d.isNull());
error->clear();
if (d.isT1()) {
+ if (sourceTimeStamp)
+ *sourceTimeStamp = 0;
return *d.asT1();
}
QFile f(*d.asT2());
@@ -3018,6 +3023,8 @@ QByteArray QQmlDataBlob::Data::readAll(QString *error) const
*error = f.errorString();
return QByteArray();
}
+ if (sourceTimeStamp)
+ *sourceTimeStamp = QFileInfo(f).lastModified().toMSecsSinceEpoch();
QByteArray data(f.size(), Qt::Uninitialized);
if (f.read(data.data(), data.length()) != data.length()) {
*error = f.errorString();
diff --git a/src/qml/qml/qqmltypeloader_p.h b/src/qml/qml/qqmltypeloader_p.h
index 3e815878f8..4c57306ed7 100644
--- a/src/qml/qml/qqmltypeloader_p.h
+++ b/src/qml/qml/qqmltypeloader_p.h
@@ -131,7 +131,7 @@ public:
class Data {
public:
- QByteArray readAll(QString *error) const;
+ QByteArray readAll(QString *error, qint64 *sourceTimeStamp = 0) const;
private:
friend class QQmlDataBlob;
friend class QQmlTypeLoader;
diff --git a/tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp b/tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp
index b4697a4a3b..f85f66378a 100644
--- a/tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp
+++ b/tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp
@@ -31,6 +31,7 @@
#include <private/qv4compileddata_p.h>
#include <QQmlComponent>
#include <QQmlEngine>
+#include <QThread>
class tst_qmldiskcache: public QObject
{
@@ -63,6 +64,10 @@ struct TestCompiler
}
mappedFile.close();
+ // Qt API limits the precision of QFileInfo::modificationTime() to seconds, so to ensure that
+ // the newly written file has a modification date newer than an existing cache file, we must
+ // wait.
+ QThread::sleep(1);
{
QFile f(testFilePath);
if (!f.open(QIODevice::WriteOnly | QIODevice::Truncate)) {