diff options
| author | Ulf Hermann <ulf.hermann@qt.io> | 2024-11-08 09:26:27 +0100 |
|---|---|---|
| committer | Ulf Hermann <ulf.hermann@qt.io> | 2024-11-12 08:46:32 +0100 |
| commit | 80c6d3c08b593471f3279f45c54fdd85222072eb (patch) | |
| tree | fc89e5f8708d77ad738beea0c3d8eb31c5b2036e /tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp | |
| parent | 257431aed3f238560a785bb7fbf184b14cfb952a (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.cpp | 34 |
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; |
