aboutsummaryrefslogtreecommitdiffstats
path: root/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2024-11-08 09:26:27 +0100
committerUlf Hermann <ulf.hermann@qt.io>2024-11-12 08:46:32 +0100
commit80c6d3c08b593471f3279f45c54fdd85222072eb (patch)
treefc89e5f8708d77ad738beea0c3d8eb31c5b2036e /tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp
parent257431aed3f238560a785bb7fbf184b14cfb952a (diff)
QtQml: Never check the type in AOT lookup initializations
qmlcachegen will never generate code that calls these with mismatched types. Checking the type at run time is wasteful. With QML_USING, you can make qmlcachegen generate code with types we cannot recognize as compatible. However, those need to be layout-compatible so that they can be reinterpret_cast'ed into each other. If they aren't that's a user error in C++. We can crash on such a thing. However, in StoreNameSloppy and in the variant lookup cases, we do need to convert types. Since the QML_USING type conversions are unknown to the QML engine, we have to provide a fallback via QMetaType::convert() here. So, despite the layout compatibility requirement, the QML_USING types also need to register metatype converters before any QML code accesses them. As a result QML_USING has quite a few complicated requirements now and is _really_ dangerous. Pick-to: 6.8 Task-number: QTBUG-127174 Change-Id: I1b8e1595e3088415ce711e910586a5dd456cb2c5 Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
Diffstat (limited to 'tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp')
-rw-r--r--tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp34
1 files changed, 34 insertions, 0 deletions
diff --git a/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp b/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp
index b8ea5477fb..0ea7346746 100644
--- a/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp
+++ b/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp
@@ -12,6 +12,7 @@
#include <data/resettable.h>
#include <data/weathermoduleurl.h>
#include <data/withlength.h>
+#include <data/qmlusing.h>
#include <QtQml/private/qqmlengine_p.h>
#include <QtQml/private/qqmlpropertycachecreator_p.h>
@@ -202,6 +203,7 @@ private slots:
void popContextAfterRet();
void prefixedType();
void propertyOfParent();
+ void qmlUsing();
void qtfont();
void reduceWithNullThis();
void readEnumFromInstance();
@@ -4221,6 +4223,38 @@ void tst_QmlCppCodegen::propertyOfParent()
}
}
+void tst_QmlCppCodegen::qmlUsing()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/qmlUsing.qml"_s));
+ QVERIFY2(component.isReady(), component.errorString().toUtf8());
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+
+ UsingUserObject *u = qobject_cast<UsingUserObject *>(object.data());
+ QVERIFY(u);
+
+ QCOMPARE(u->a(), 7);
+ QCOMPARE(u->val().a(), 24);
+ QCOMPARE(u->property("valA").toInt(), 24);
+ QCOMPARE(u->property("myA").toInt(), 7);
+ QCOMPARE(u->property("myA2").toInt(), 7);
+
+ QList<int> as;
+ QObject::connect(u, &UsingUserObject::aChanged, this, [&]() { as.append(u->a()); });
+
+ QMetaObject::invokeMethod(object.data(), "twiddle");
+
+ const QList<int> expected = { 57, 59 };
+ QCOMPARE(as, expected);
+
+ QCOMPARE(u->a(), 59);
+ QCOMPARE(u->val().a(), 55);
+ QCOMPARE(u->property("valA").toInt(), 55);
+ QCOMPARE(u->property("myA").toInt(), 59);
+ QCOMPARE(u->property("myA2").toInt(), 59);
+}
+
void tst_QmlCppCodegen::qtfont()
{
QQmlEngine engine;