aboutsummaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2022-03-01 11:37:53 +0100
committerUlf Hermann <ulf.hermann@qt.io>2022-03-04 14:18:35 +0100
commitb386b6491d3486a78aee88e432f0d33f8ae39d06 (patch)
tree3fd95c519e60e7ebbde56ab2305e9e8a3c5d1391 /tests
parent97a7ab0fed67da7d446127a1dddba989ca95df27 (diff)
QML: Handle dynamic meta objects in AOT lookups
If we are dealing with dynamic metaobjects, the QML engine may not create property caches. We cannot see this at compile time. Therefore, we need to establish a fallback infrastructure that does the same operations on plain QMetaObject. Fixes: QTBUG-101349 Change-Id: I8c936fc077b0018df71196620b6987825253cb39 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> (cherry picked from commit 1e722f5e8e6510f3a1bc10436f8262c918ca9599)
Diffstat (limited to 'tests')
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt2
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/dynamicmeta.h78
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/fallbacklookups.qml34
-rw-r--r--tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp34
4 files changed, 148 insertions, 0 deletions
diff --git a/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt b/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt
index 3d05ffcf1d..4d585b62f0 100644
--- a/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt
+++ b/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt
@@ -1,6 +1,7 @@
set(cpp_sources
birthdayparty.cpp birthdayparty.h
cppbaseclass.h
+ dynamicmeta.h
objectwithmethod.h
person.cpp person.h
theme.cpp theme.h
@@ -61,6 +62,7 @@ set(qml_files
excessiveParameters.qml
extendedTypes.qml
failures.qml
+ fallbacklookups.qml
fileDialog.qml
functionLookup.qml
funcWithParams.qml
diff --git a/tests/auto/qml/qmlcppcodegen/data/dynamicmeta.h b/tests/auto/qml/qmlcppcodegen/data/dynamicmeta.h
new file mode 100644
index 0000000000..3f02e460e7
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/dynamicmeta.h
@@ -0,0 +1,78 @@
+#ifndef DYNAMICMETA_H
+#define DYNAMICMETA_H
+
+#include <private/qobject_p.h>
+#include <QtQmlIntegration/qqmlintegration.h>
+
+struct FreeDeleter {
+ void operator()(QMetaObject *meta) { free(meta); }
+};
+
+template<typename T>
+class MetaObjectData : public QDynamicMetaObjectData
+{
+ Q_DISABLE_COPY_MOVE(MetaObjectData)
+public:
+ MetaObjectData() = default;
+ ~MetaObjectData() = default;
+
+ QMetaObject *toDynamicMetaObject(QObject *) override
+ {
+ return const_cast<QMetaObject *>(&T::staticMetaObject);
+ }
+ int metaCall(QObject *o, QMetaObject::Call call, int idx, void **argv) override
+ {
+ return o->qt_metacall(call, idx, argv);
+ }
+};
+
+class DynamicMeta : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int foo READ foo WRITE setFoo NOTIFY fooChanged FINAL)
+ QML_ELEMENT
+public:
+
+ DynamicMeta(QObject *parent = nullptr)
+ : QObject(parent)
+ {
+ // deletes itself
+ QObjectPrivate::get(this)->metaObject = new MetaObjectData<DynamicMeta>;
+ }
+
+ int foo() const { return m_foo; }
+ void setFoo(int newFoo)
+ {
+ if (m_foo != newFoo) {
+ m_foo = newFoo;
+ emit fooChanged();
+ }
+ }
+
+ Q_INVOKABLE int bar(int baz) { return baz + 12; }
+
+Q_SIGNALS:
+ void fooChanged();
+
+private:
+ int m_foo = 0;
+};
+
+class DynamicMetaSingleton : public DynamicMeta
+{
+ Q_OBJECT
+ QML_ELEMENT
+ QML_SINGLETON
+ Q_PROPERTY(DynamicMetaSingleton *itself READ itself CONSTANT FINAL)
+public:
+ DynamicMetaSingleton(QObject *parent = nullptr) : DynamicMeta(parent)
+ {
+ QObjectPrivate *d = QObjectPrivate::get(this);
+ delete d->metaObject;
+ d->metaObject = new MetaObjectData<DynamicMetaSingleton>;
+ }
+
+ DynamicMetaSingleton *itself() { return this; }
+};
+
+#endif // DYNAMICMETA_H
diff --git a/tests/auto/qml/qmlcppcodegen/data/fallbacklookups.qml b/tests/auto/qml/qmlcppcodegen/data/fallbacklookups.qml
new file mode 100644
index 0000000000..4b58cd344d
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/fallbacklookups.qml
@@ -0,0 +1,34 @@
+import TestTypes
+import QtQml
+
+DynamicMeta {
+ id: self
+
+ function getSingleton(): QtObject {
+ return DynamicMetaSingleton.itself
+ }
+
+ function withContext(): int {
+ foo = 93;
+ objectName = "aa" + foo;
+ return bar(4);
+ }
+
+ function withId(): int {
+ self.foo = 94;
+ self.objectName = "bb" + foo;
+ return self.bar(5);
+ }
+
+ function withSingleton(): int {
+ DynamicMetaSingleton.foo = 95;
+ DynamicMetaSingleton.objectName = "cc" + DynamicMetaSingleton.foo;
+ return DynamicMetaSingleton.bar(6);
+ }
+
+ function withProperty(): int {
+ DynamicMetaSingleton.itself.foo = 96;
+ DynamicMetaSingleton.itself.objectName = "dd" + DynamicMetaSingleton.itself.foo;
+ return DynamicMetaSingleton.itself.bar(7);
+ }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp b/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp
index d1b8565afc..acc117d967 100644
--- a/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp
+++ b/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp
@@ -124,6 +124,7 @@ private slots:
void functionLookup();
void objectInVar();
void testIsnan();
+ void fallbackLookups();
};
void tst_QmlCppCodegen::simpleBinding()
@@ -1846,6 +1847,39 @@ void tst_QmlCppCodegen::testIsnan()
QVERIFY(b.toBool());
}
+void tst_QmlCppCodegen::fallbackLookups()
+{
+ QQmlEngine engine;
+ const QUrl document(u"qrc:/TestTypes/fallbacklookups.qml"_qs);
+ QQmlComponent c(&engine, document);
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(o);
+
+ QCOMPARE(o->objectName(), QString());
+ int result = 0;
+
+ QMetaObject::invokeMethod(o.data(), "withContext", Q_RETURN_ARG(int, result));
+ QCOMPARE(result, 16);
+ QCOMPARE(o->objectName(), QStringLiteral("aa93"));
+
+ QMetaObject::invokeMethod(o.data(), "withId", Q_RETURN_ARG(int, result));
+ QCOMPARE(result, 17);
+ QCOMPARE(o->objectName(), QStringLiteral("bb94"));
+
+ QObject *singleton = nullptr;
+ QMetaObject::invokeMethod(o.data(), "getSingleton", Q_RETURN_ARG(QObject*, singleton));
+ QVERIFY(singleton);
+
+ QMetaObject::invokeMethod(o.data(), "withSingleton", Q_RETURN_ARG(int, result));
+ QCOMPARE(result, 18);
+ QCOMPARE(singleton->objectName(), QStringLiteral("cc95"));
+
+ QMetaObject::invokeMethod(o.data(), "withProperty", Q_RETURN_ARG(int, result));
+ QCOMPARE(result, 19);
+ QCOMPARE(singleton->objectName(), QStringLiteral("dd96"));
+}
+
void tst_QmlCppCodegen::runInterpreted()
{
if (qEnvironmentVariableIsSet("QV4_FORCE_INTERPRETER"))