28 *errorString = QStringLiteral(
"Magic bytes in the header do not match");
33 *errorString = QString::fromUtf8(
"V4 data structure version mismatch. Found %1 expected %2")
38 switch (sourceTimeStamp) {
53 if (!expectedSourceTimeStamp.isValid()) {
54 expectedSourceTimeStamp = QFileInfo(QCoreApplication::applicationFilePath()).lastModified();
55 if (!expectedSourceTimeStamp.isValid()) {
57 QStringLiteral(
"Failed to get valid timestamp from application executable");
61 if (expectedSourceTimeStamp.toMSecsSinceEpoch() != sourceTimeStamp) {
63 QStringLiteral(
"QML source file has a different time stamp than cached file.");
76 QCryptographicHash *hash, QHash<quintptr, QByteArray> *checksums)
const
78 std::vector<
int> keys (size());
80 for (
auto it = constBegin(), end = constEnd(); it != end; ++it) {
84 std::sort(keys.begin(), keys.end());
86 if (!
this->operator[](key)->addToHash(hash, checksums))
120 static const QByteArray envCachePath = qgetenv(
"QML_DISK_CACHE_PATH");
122 const QString localSourcePath = QQmlFile::urlToLocalFileOrQrc(url);
123 const QString cacheFileSuffix
124 = QFileInfo(localSourcePath + QLatin1Char(
'c')).completeSuffix();
125 QCryptographicHash fileNameHash(QCryptographicHash::Sha1);
126 fileNameHash.addData(localSourcePath.toUtf8());
127 QString directory = envCachePath.isEmpty()
128 ? QStandardPaths::writableLocation(QStandardPaths::CacheLocation)
129 + QLatin1String(
"/qmlcache/")
130 : QString::fromLocal8Bit(envCachePath) + QLatin1String(
"/");
131 QDir::root().mkpath(directory);
132 return directory + QString::fromUtf8(fileNameHash.result().toHex())
133 + QLatin1Char(
'.') + cacheFileSuffix;
137 const QUrl &url,
const QDateTime &sourceTimeStamp,
140 if (!QQmlFile::isLocalFile(url)) {
141 *errorString = QStringLiteral(
"File has to be a local file.");
145 const QString sourcePath = QQmlFile::urlToLocalFileOrQrc(url);
146 auto cacheFile = std::make_unique<CompilationUnitMapper>();
148 const QStringList cachePaths = { sourcePath + QLatin1Char(
'c'), localCacheFilePath(url) };
149 for (
const QString &cachePath : cachePaths) {
150 Unit *mappedUnit = cacheFile->get(cachePath, sourceTimeStamp, errorString);
154 const Unit *oldData = unitData();
155 const Unit *
const oldDataPtr
156 = (oldData && !(oldData->flags & Unit::StaticData))
160 auto dataPtrRevert = qScopeGuard([
this, oldData](){
161 setUnitData(oldData);
163 setUnitData(mappedUnit);
165 if (mappedUnit->sourceTimeStamp == -1) {
166 const QByteArray checksum = sourceChecksum();
167 if (checksum.size() !=
sizeof(mappedUnit->sourceChecksum)
168 || memcmp(mappedUnit->sourceChecksum, checksum.constData(), checksum.size()) != 0) {
169 *errorString = QStringLiteral(
170 "QML source file has a different content checksum than cached file.");
175 if (mappedUnit->sourceFileIndex != 0) {
176 if (mappedUnit->sourceFileIndex >=
177 mappedUnit->stringTableSize + dynamicStrings.size()) {
178 *errorString = QStringLiteral(
"QML source file index is invalid.");
182 QQmlFile::urlToLocalFileOrQrc(stringAt(mappedUnit->sourceFileIndex))) {
183 *errorString = QStringLiteral(
"QML source file has moved to a different location.");
188 dataPtrRevert.dismiss();
189 free(
const_cast<Unit*>(oldDataPtr));
190 backingFile = std::move(cacheFile);
201 if (!QQmlFile::isLocalFile(unitUrl)) {
202 *errorString = QStringLiteral(
"File has to be a local file.");
207 const QByteArray checksum = sourceChecksum();
209 *errorString = QStringLiteral(
"Failed to compute source code checksum");
217 const qint64 oldTimeStamp = mutableUnit->sourceTimeStamp;
220 mutableUnit->sourceTimeStamp = -1;
222 const auto restore = qScopeGuard([&]() {
223 mutableUnit->sourceTimeStamp = oldTimeStamp;
227 return SaveableUnitPointer(
unitData()).saveToDisk<
char>(
228 [&unitUrl, errorString](
const char *data, quint32 size) {
229 const QString cachePath = localCacheFilePath(unitUrl);
230 if (SaveableUnitPointer::writeDataToFile(
231 cachePath, data, size, errorString)) {
232 CompilationUnitMapper::invalidate(cachePath);
262 if (propertyCaches.needsVMEMetaObject(0)) {
264 if (type.isValid()) {
267 qmlType = QQmlMetaType::findCompositeType(
268 url(),
this, (unitData()->flags & CompiledData::Unit::IsSingleton)
269 ? QQmlMetaType::Singleton
270 : QQmlMetaType::NonSingleton);
273 QQmlMetaType::registerInternalCompositeType(
this);
276 auto *typeRef =
resolvedTypes.value(obj->inheritedTypeNameIndex);
278 qmlType = typeRef->type();
284 if (!dependencyHasher) {
285 for (size_t i = 0; i <
sizeof(data->dependencyMD5Checksum); ++i) {
286 if (data->dependencyMD5Checksum[i] != 0)
291 const QByteArray checksum = dependencyHasher();
292 return checksum.size() ==
sizeof(data->dependencyMD5Checksum)
293 && memcmp(data->dependencyMD5Checksum, checksum.constData(),
294 sizeof(data->dependencyMD5Checksum)) == 0;