diff options
author | Ulf Hermann <ulf.hermann@qt.io> | 2023-01-03 15:45:31 +0100 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2023-01-20 20:39:11 +0100 |
commit | ec58c0ddb7fe1ebf33c80335ab9435e53fd00274 (patch) | |
tree | d30a8779fa5fb82bcc9e3b31e581d3962dc81d21 /tests/auto | |
parent | ea5200b82f21e0f4d080d3fc256b218e0ee56f3d (diff) |
QML: Add a pragma for value type behavior
Unfortunately value types behave differently when compiled to C++.
Document the difference and introduce a pragma to make them behave one
way or the other.
Pick-to: 6.5
Fixes: QTBUG-109221
Change-Id: Ib2685153c0b4ae209bafbea7a01229377fdb47dd
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'tests/auto')
4 files changed, 105 insertions, 0 deletions
diff --git a/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt b/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt index e66af303ca..be74e062c0 100644 --- a/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt +++ b/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt @@ -190,8 +190,10 @@ set(qml_files unusedAttached.qml urlString.qml usingCxxTypesFromFileImports.qml + valueTypeCopy.qml valueTypeLists.qml valueTypeProperty.qml + valueTypeReference.qml variantlist.qml versionmismatch.qml voidfunction.qml diff --git a/tests/auto/qml/qmlcppcodegen/data/valueTypeCopy.qml b/tests/auto/qml/qmlcppcodegen/data/valueTypeCopy.qml new file mode 100644 index 0000000000..cca634753d --- /dev/null +++ b/tests/auto/qml/qmlcppcodegen/data/valueTypeCopy.qml @@ -0,0 +1,34 @@ +pragma ValueTypeBehavior: Copy +import QtQml + +QtObject { + id: root + + property list<double> numbers: { + var result = []; + for (var i = 0; i < 10; ++i) + result[i] = i; + return result; + } + + property rect r: ({x: 1, y: 2, width: 3, height: 4}) + + function evil() : double { + var numbers = root.numbers; + root.numbers = []; + var a = 0; + for (var j = 0; j < 10; ++j) { + a += numbers[j]; + } + return a; + } + + function fvil() : double { + var r = root.r; + root.r = {x: 5, y: 6, width: 7, height: 8}; + return r.x; + } + + property double e: evil() + property double f: fvil() +} diff --git a/tests/auto/qml/qmlcppcodegen/data/valueTypeReference.qml b/tests/auto/qml/qmlcppcodegen/data/valueTypeReference.qml new file mode 100644 index 0000000000..568f39820c --- /dev/null +++ b/tests/auto/qml/qmlcppcodegen/data/valueTypeReference.qml @@ -0,0 +1,34 @@ +pragma ValueTypeBehavior: Reference +import QtQml + +QtObject { + id: root + + property list<double> numbers: { + var result = []; + for (var i = 0; i < 10; ++i) + result[i] = i; + return result; + } + + property rect r: ({x: 1, y: 2, width: 3, height: 4}) + + function evil() : double { + var numbers = root.numbers; + root.numbers = []; + var a = 0; + for (var j = 0; j < 10; ++j) { + a += numbers[j]; + } + return a; + } + + function fvil() : double { + var r = root.r; + root.r = {x: 5, y: 6, width: 7, height: 8}; + return r.x; + } + + property double e: evil() + property double f: fvil() +} diff --git a/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp b/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp index 1e88ecd7b7..405e65853a 100644 --- a/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp +++ b/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp @@ -162,6 +162,7 @@ private slots: void equalityVarAndNonStorable(); void equalityQObjects(); void dateConversions(); + void valueTypeBehavior(); }; void tst_QmlCppCodegen::initTestCase() @@ -3125,6 +3126,40 @@ void tst_QmlCppCodegen::dateConversions() QCOMPARE(ref->myTime(), (engine.coerceValue<QDate, QTime>(date))); } +static QRegularExpression bindingLoopMessage(const QUrl &url, char var) +{ + // The actual string depends on how many times QObject* was registered with what parameters. + return QRegularExpression( + "%1:4:1: QML [^:]+: Binding loop detected for property \"%2\""_L1 + .arg(url.toString()).arg(QLatin1Char(var))); +} + +void tst_QmlCppCodegen::valueTypeBehavior() +{ + QQmlEngine engine; + + const QUrl copy(u"qrc:/qt/qml/TestTypes/valueTypeCopy.qml"_s); + + QQmlComponent c1(&engine, copy); + QVERIFY2(c1.isReady(), qPrintable(c1.errorString())); + QTest::ignoreMessage(QtWarningMsg, bindingLoopMessage(copy, 'e')); + QTest::ignoreMessage(QtWarningMsg, bindingLoopMessage(copy, 'f')); + QScopedPointer<QObject> o1(c1.create()); + QVERIFY(!o1.isNull()); + QCOMPARE(o1->property("e").toDouble(), 45.0); + QCOMPARE(o1->property("f").toDouble(), 1.0); + + const QUrl reference(u"qrc:/qt/qml/TestTypes/valueTypeReference.qml"_s); + QQmlComponent c2(&engine, reference); + QVERIFY2(c2.isReady(), qPrintable(c2.errorString())); + QTest::ignoreMessage(QtWarningMsg, bindingLoopMessage(reference, 'e')); + QTest::ignoreMessage(QtWarningMsg, bindingLoopMessage(reference, 'f')); + QScopedPointer<QObject> o2(c2.create()); + QVERIFY(!o2.isNull()); + QVERIFY(qIsNaN(o2->property("e").toDouble())); + QCOMPARE(o2->property("f").toDouble(), 5.0); +} + QTEST_MAIN(tst_QmlCppCodegen) #include "tst_qmlcppcodegen.moc" |