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 if (sourceTimeStamp) {
41 if (!expectedSourceTimeStamp.isValid()) {
42 expectedSourceTimeStamp = QFileInfo(QCoreApplication::applicationFilePath()).lastModified();
43 if (!expectedSourceTimeStamp.isValid()) {
44 *errorString = QStringLiteral(
"Failed to get valid timestamp from application executable");
48 if (expectedSourceTimeStamp.toMSecsSinceEpoch() != sourceTimeStamp) {
49 *errorString = QStringLiteral(
"QML source file has a different time stamp than cached file.");
63 QCryptographicHash *hash, QHash<quintptr, QByteArray> *checksums)
const
65 std::vector<
int> keys (size());
67 for (
auto it = constBegin(), end = constEnd(); it != end; ++it) {
71 std::sort(keys.begin(), keys.end());
73 if (!
this->operator[](key)->addToHash(hash, checksums))
107 static const QByteArray envCachePath = qgetenv(
"QML_DISK_CACHE_PATH");
109 const QString localSourcePath = QQmlFile::urlToLocalFileOrQrc(url);
110 const QString cacheFileSuffix
111 = QFileInfo(localSourcePath + QLatin1Char(
'c')).completeSuffix();
112 QCryptographicHash fileNameHash(QCryptographicHash::Sha1);
113 fileNameHash.addData(localSourcePath.toUtf8());
114 QString directory = envCachePath.isEmpty()
115 ? QStandardPaths::writableLocation(QStandardPaths::CacheLocation)
116 + QLatin1String(
"/qmlcache/")
117 : QString::fromLocal8Bit(envCachePath) + QLatin1String(
"/");
118 QDir::root().mkpath(directory);
119 return directory + QString::fromUtf8(fileNameHash.result().toHex())
120 + QLatin1Char(
'.') + cacheFileSuffix;
124 const QUrl &url,
const QDateTime &sourceTimeStamp, QString *errorString)
126 if (!QQmlFile::isLocalFile(url)) {
127 *errorString = QStringLiteral(
"File has to be a local file.");
131 const QString sourcePath = QQmlFile::urlToLocalFileOrQrc(url);
132 auto cacheFile = std::make_unique<CompilationUnitMapper>();
134 const QStringList cachePaths = { sourcePath + QLatin1Char(
'c'), localCacheFilePath(url) };
135 for (
const QString &cachePath : cachePaths) {
136 Unit *mappedUnit = cacheFile->get(cachePath, sourceTimeStamp, errorString);
140 const Unit *oldData = unitData();
141 const Unit *
const oldDataPtr
142 = (oldData && !(oldData->flags & Unit::StaticData))
146 auto dataPtrRevert = qScopeGuard([
this, oldData](){
147 setUnitData(oldData);
149 setUnitData(mappedUnit);
151 if (mappedUnit->sourceFileIndex != 0) {
152 if (mappedUnit->sourceFileIndex >=
153 mappedUnit->stringTableSize + dynamicStrings.size()) {
154 *errorString = QStringLiteral(
"QML source file index is invalid.");
158 QQmlFile::urlToLocalFileOrQrc(stringAt(mappedUnit->sourceFileIndex))) {
159 *errorString = QStringLiteral(
"QML source file has moved to a different location.");
164 dataPtrRevert.dismiss();
165 free(
const_cast<Unit*>(oldDataPtr));
166 backingFile = std::move(cacheFile);
176 *errorString = QStringLiteral(
"Missing time stamp for source file");
180 if (!QQmlFile::isLocalFile(unitUrl)) {
181 *errorString = QStringLiteral(
"File has to be a local file.");
185 return SaveableUnitPointer(
unitData()).saveToDisk<
char>(
186 [&unitUrl, errorString](
const char *data, quint32 size) {
187 const QString cachePath = localCacheFilePath(unitUrl);
188 if (SaveableUnitPointer::writeDataToFile(
189 cachePath, data, size, errorString)) {
190 CompilationUnitMapper::invalidate(cachePath);
220 if (propertyCaches.needsVMEMetaObject(0)) {
222 if (type.isValid()) {
225 qmlType = QQmlMetaType::findCompositeType(
226 url(),
this, (unitData()->flags & CompiledData::Unit::IsSingleton)
227 ? QQmlMetaType::Singleton
228 : QQmlMetaType::NonSingleton);
231 QQmlMetaType::registerInternalCompositeType(
this);
234 auto *typeRef =
resolvedTypes.value(obj->inheritedTypeNameIndex);
236 qmlType = typeRef->type();
242 if (!dependencyHasher) {
243 for (size_t i = 0; i <
sizeof(data->dependencyMD5Checksum); ++i) {
244 if (data->dependencyMD5Checksum[i] != 0)
249 const QByteArray checksum = dependencyHasher();
250 return checksum.size() ==
sizeof(data->dependencyMD5Checksum)
251 && memcmp(data->dependencyMD5Checksum, checksum.constData(),
252 sizeof(data->dependencyMD5Checksum)) == 0;