aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@qt.io>2016-07-19 10:13:26 +0200
committerSimon Hausmann <simon.hausmann@qt.io>2016-07-19 18:19:46 +0000
commit6a1667bc4e6d1074f547434d714cd47ed8ebfc41 (patch)
tree84285121878205ec1f5a2c2f5ddff3a20c1fc27f /src
parente0e50532d29d02c8bcbab01dbfb72377102eaf8f (diff)
Improve robustness of qml cache expiry checking
Instead of relying on two time stamps in the file system (source file and cache file), make the determination on whether the source file is newer than the cache solely depend on the time stamp of only the source file. This means that when cache files are stored in archives for example their modification date does not need to be preserved upon extraction. Change-Id: I0b4362663868c6fb9bd7e106028161b2d67274d4 Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Diffstat (limited to 'src')
-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
6 files changed, 27 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;