Add a checksum to QQmlPropertyCache
By running an md5 hash over the meta-object data and string tables this will allow us to detect changes to meta-objects and invalidate QML disk caches. Change-Id: I15b92de4cdf0cb525281b86e1c7b8ba0b11347a0 Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
This commit is contained in:
parent
897eb7f129
commit
143f22babb
|
@ -1413,6 +1413,48 @@ bool QQmlPropertyCache::determineMetaObjectSizes(const QMetaObject &mo, int *fie
|
|||
return true;
|
||||
}
|
||||
|
||||
bool QQmlPropertyCache::addToHash(QCryptographicHash &hash, const QMetaObject &mo)
|
||||
{
|
||||
int fieldCount = 0;
|
||||
int stringCount = 0;
|
||||
if (!determineMetaObjectSizes(mo, &fieldCount, &stringCount)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
hash.addData(reinterpret_cast<const char *>(mo.d.data), fieldCount * sizeof(uint));
|
||||
for (int i = 0; i < stringCount; ++i) {
|
||||
const QByteArrayDataPtr data = { const_cast<QByteArrayData*>(&mo.d.stringdata[i]) };
|
||||
hash.addData(QByteArray(data));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
QByteArray QQmlPropertyCache::checksum(bool *ok)
|
||||
{
|
||||
if (!_checksum.isEmpty()) {
|
||||
*ok = true;
|
||||
return _checksum;
|
||||
}
|
||||
|
||||
QCryptographicHash hash(QCryptographicHash::Md5);
|
||||
|
||||
if (_parent) {
|
||||
hash.addData(_parent->checksum(ok));
|
||||
if (!*ok)
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
if (!addToHash(hash, *createMetaObject())) {
|
||||
*ok = false;
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
_checksum = hash.result();
|
||||
*ok = !_checksum.isEmpty();
|
||||
return _checksum;
|
||||
}
|
||||
|
||||
/*! \internal
|
||||
\a index MUST be in the signal index range (see QObjectPrivate::signalIndex()).
|
||||
This is different from QMetaMethod::methodIndex().
|
||||
|
|
|
@ -65,6 +65,7 @@
|
|||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QCryptographicHash;
|
||||
class QMetaProperty;
|
||||
class QQmlEngine;
|
||||
class QJSEngine;
|
||||
|
@ -367,6 +368,9 @@ public:
|
|||
void toMetaObjectBuilder(QMetaObjectBuilder &);
|
||||
|
||||
static bool determineMetaObjectSizes(const QMetaObject &mo, int *fieldCount, int *stringCount);
|
||||
static bool addToHash(QCryptographicHash &hash, const QMetaObject &mo);
|
||||
|
||||
QByteArray checksum(bool *ok);
|
||||
|
||||
protected:
|
||||
virtual void destroy();
|
||||
|
@ -437,6 +441,7 @@ private:
|
|||
QByteArray _dynamicStringData;
|
||||
QString _defaultPropertyName;
|
||||
QQmlPropertyCacheMethodArguments *argumentsCache;
|
||||
QByteArray _checksum;
|
||||
};
|
||||
|
||||
// QQmlMetaObject serves as a wrapper around either QMetaObject or QQmlPropertyCache.
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include <QtQml/qqmlengine.h>
|
||||
#include <private/qv8engine_p.h>
|
||||
#include <private/qmetaobjectbuilder_p.h>
|
||||
#include <QCryptographicHash>
|
||||
#include "../../shared/util.h"
|
||||
|
||||
class tst_qqmlpropertycache : public QObject
|
||||
|
@ -48,6 +49,7 @@ private slots:
|
|||
void signalHandlersDerived();
|
||||
void metaObjectSize_data();
|
||||
void metaObjectSize();
|
||||
void metaObjectChecksum();
|
||||
|
||||
private:
|
||||
QQmlEngine engine;
|
||||
|
@ -361,4 +363,40 @@ void tst_qqmlpropertycache::metaObjectSize()
|
|||
QCOMPARE(stringDataSize, expectedStringCount);
|
||||
}
|
||||
|
||||
void tst_qqmlpropertycache::metaObjectChecksum()
|
||||
{
|
||||
QMetaObjectBuilder builder;
|
||||
builder.setClassName("Test");
|
||||
builder.addClassInfo("foo", "bar");
|
||||
|
||||
QCryptographicHash hash(QCryptographicHash::Md5);
|
||||
|
||||
QScopedPointer<QMetaObject, QScopedPointerPodDeleter> mo(builder.toMetaObject());
|
||||
QVERIFY(!mo.isNull());
|
||||
|
||||
QVERIFY(QQmlPropertyCache::addToHash(hash, *mo.data()));
|
||||
QByteArray initialHash = hash.result();
|
||||
QVERIFY(!initialHash.isEmpty());
|
||||
hash.reset();
|
||||
|
||||
{
|
||||
QVERIFY(QQmlPropertyCache::addToHash(hash, *mo.data()));
|
||||
QByteArray nextHash = hash.result();
|
||||
QVERIFY(!nextHash.isEmpty());
|
||||
hash.reset();
|
||||
QCOMPARE(initialHash, nextHash);
|
||||
}
|
||||
|
||||
builder.addProperty("testProperty", "int", -1);
|
||||
|
||||
mo.reset(builder.toMetaObject());
|
||||
{
|
||||
QVERIFY(QQmlPropertyCache::addToHash(hash, *mo.data()));
|
||||
QByteArray nextHash = hash.result();
|
||||
QVERIFY(!nextHash.isEmpty());
|
||||
hash.reset();
|
||||
QVERIFY(initialHash != nextHash);
|
||||
}
|
||||
}
|
||||
|
||||
QTEST_MAIN(tst_qqmlpropertycache)
|
||||
|
|
Loading…
Reference in New Issue