aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrei Golubev <andrei.golubev@qt.io>2022-05-18 14:37:01 +0200
committerAndrei Golubev <andrei.golubev@qt.io>2022-05-24 10:30:44 +0200
commitc02dd17a4f648ec18c6ff2ae7bfe468bd9c42732 (patch)
tree2975f030e9cbbcffa3ecb79d835507e86298ef8b
parentce441f819389d729dea63a7d1ae02fae35b35bfc (diff)
Support extension property revisions
Previously the extension's property revision would make the property unusable since extensions would've been skipped from property cache construction w.r.t. revisions This is due to the meta object cloning that we do for extension types (since we put the cloned meta object on top of the meta object hierarchy for the QQmlProxyMetaObject). Once cloned, the meta object has no associated QQmlType anymore and we need one to deal with revisions. Overcome this by registering the cloned meta object in the QQmlMetaTypeData From now on, the cloned extension meta object has an associated QQmlType, which is the *extended* type, NOT the *extension* type Change-Id: I4a6a4380278b80e49e1b9874dd458183667e5cb5 Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
-rw-r--r--src/qml/qml/qqmlmetatype.cpp16
-rw-r--r--src/qml/qml/qqmlmetatype_p.h2
-rw-r--r--src/qml/qml/qqmltype.cpp1
-rw-r--r--tests/auto/qml/qqmllanguage/testtypes.h32
-rw-r--r--tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp23
5 files changed, 71 insertions, 3 deletions
diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp
index db4ecc6397..110363ae3b 100644
--- a/src/qml/qml/qqmlmetatype.cpp
+++ b/src/qml/qml/qqmlmetatype.cpp
@@ -1430,6 +1430,14 @@ void QQmlMetaType::unregisterType(int typeIndex)
}
}
+void QQmlMetaType::registerMetaObjectForType(const QMetaObject *metaobject, QQmlTypePrivate *type)
+{
+ Q_ASSERT(type);
+
+ QQmlMetaTypeDataPtr data;
+ data->metaObjectToType.insert(metaobject, type);
+}
+
static bool hasActiveInlineComponents(const QQmlTypePrivate *d)
{
for (const QQmlType &ic : qAsConst(d->objectIdToICType)) {
@@ -1635,7 +1643,8 @@ QList<QQmlProxyMetaObject::ProxyData> QQmlMetaType::proxyData(const QMetaObject
const QQmlMetaTypeDataPtr data;
- auto createProxyMetaObject = [&](const QMetaObject *superdataBaseMetaObject,
+ auto createProxyMetaObject = [&](QQmlTypePrivate *This,
+ const QMetaObject *superdataBaseMetaObject,
const QMetaObject *extMetaObject,
QObject *(*extFunc)(QObject *)) {
if (!extMetaObject)
@@ -1652,16 +1661,17 @@ QList<QQmlProxyMetaObject::ProxyData> QQmlMetaType::proxyData(const QMetaObject
lastMetaObject->d.superdata = mmo;
QQmlProxyMetaObject::ProxyData data = { mmo, extFunc, 0, 0 };
metaObjects << data;
+ registerMetaObjectForType(mmo, This);
};
while (mo) {
QQmlTypePrivate *t = data->metaObjectToType.value(mo);
if (t) {
if (t->regType == QQmlType::CppType) {
- createProxyMetaObject(t->baseMetaObject, t->extraData.cd->extMetaObject,
+ createProxyMetaObject(t, t->baseMetaObject, t->extraData.cd->extMetaObject,
t->extraData.cd->extFunc);
} else if (t->regType == QQmlType::SingletonType) {
- createProxyMetaObject(t->baseMetaObject, t->extraData.sd->extMetaObject,
+ createProxyMetaObject(t, t->baseMetaObject, t->extraData.sd->extMetaObject,
t->extraData.sd->extFunc);
}
}
diff --git a/src/qml/qml/qqmlmetatype_p.h b/src/qml/qml/qqmlmetatype_p.h
index 2c010f516d..b9bf78b0a7 100644
--- a/src/qml/qml/qqmlmetatype_p.h
+++ b/src/qml/qml/qqmlmetatype_p.h
@@ -148,6 +148,8 @@ public:
static void unregisterType(int type);
+ static void registerMetaObjectForType(const QMetaObject *metaobject, QQmlTypePrivate *type);
+
static void registerModule(const char *uri, QTypeRevision version);
static bool protectModule(const QString &uri, QTypeRevision version,
bool weakProtectAllVersions = false);
diff --git a/src/qml/qml/qqmltype.cpp b/src/qml/qml/qqmltype.cpp
index 1d34b57fed..0bc817845d 100644
--- a/src/qml/qml/qqmltype.cpp
+++ b/src/qml/qml/qqmltype.cpp
@@ -232,6 +232,7 @@ void QQmlTypePrivate::init() const
mmo->d.superdata = mo;
QQmlProxyMetaObject::ProxyData data = { mmo, extFunc, 0, 0 };
metaObjects << data;
+ QQmlMetaType::registerMetaObjectForType(mmo, const_cast<QQmlTypePrivate *>(this));
};
if (regType == QQmlType::SingletonType)
diff --git a/tests/auto/qml/qqmllanguage/testtypes.h b/tests/auto/qml/qqmllanguage/testtypes.h
index 54022b268f..bcc6a9d9eb 100644
--- a/tests/auto/qml/qqmllanguage/testtypes.h
+++ b/tests/auto/qml/qqmllanguage/testtypes.h
@@ -1888,6 +1888,38 @@ public:
}
};
+class RevisionedExtension : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int extension READ extension WRITE setExtension REVISION(1, 0))
+public:
+ RevisionedExtension(QObject *parent = nullptr) : QObject(parent) {}
+ int extension() const { return m_ext; }
+ void setExtension(int e) { m_ext = e; }
+private:
+ int m_ext = 42;
+};
+
+class ExtendedWithRevisionOld : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+ QML_EXTENDED(RevisionedExtension)
+ QML_ADDED_IN_VERSION(0, 5)
+public:
+ ExtendedWithRevisionOld(QObject *parent = nullptr) : QObject(parent) { }
+};
+
+class ExtendedWithRevisionNew : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+ QML_EXTENDED(RevisionedExtension)
+ QML_ADDED_IN_VERSION(1, 0)
+public:
+ ExtendedWithRevisionNew(QObject *parent = nullptr) : QObject(parent) { }
+};
+
class StringSignaler : public QObject
{
Q_OBJECT
diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
index 81d6e6f6a0..73f886e217 100644
--- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
+++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
@@ -369,6 +369,7 @@ private slots:
void multiExtensionIndirect();
void multiExtensionQmlTypes();
void extensionSpecial();
+ void extensionRevision();
void invalidInlineComponent();
void warnOnInjectedParameters();
#if QT_CONFIG(wheelevent)
@@ -6540,6 +6541,28 @@ void tst_qqmllanguage::extensionSpecial()
}
}
+void tst_qqmllanguage::extensionRevision()
+{
+ QQmlEngine engine;
+ {
+ QQmlComponent c(&engine);
+ c.setData("import StaticTest 0.5\nExtendedWithRevisionOld { extension: 40\n}", QUrl());
+ QVERIFY(!c.isReady());
+ QRegularExpression error(
+ ".*\"ExtendedWithRevisionOld.extension\" is not available in StaticTest 0.5.*");
+ QVERIFY2(error.match(c.errorString()).hasMatch(),
+ qPrintable(u"Unmatched error: "_s + c.errorString()));
+ }
+
+ {
+ QQmlComponent c(&engine);
+ c.setData("import StaticTest 1.0\nExtendedWithRevisionNew { extension: 40\n}", QUrl());
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(o);
+ }
+}
+
void tst_qqmllanguage::invalidInlineComponent()
{
QQmlEngine e;