summaryrefslogtreecommitdiff
path: root/tests/auto
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2023-04-28 14:02:20 +0200
committerUlf Hermann <ulf.hermann@qt.io>2023-05-04 16:44:44 +0200
commit4634b6bf54e5ba15aa2e8efc12feb156e3d9c309 (patch)
treebe5109708b5729475b58ddb6f1d164caf7928c6a /tests/auto
parent8fab8cf39c9ce7247b8e5b72d123c9dd806ea870 (diff)
downloadqtdeclarative-4634b6bf54e5ba15aa2e8efc12feb156e3d9c309.tar.gz
QmlCompiler: Disallow reading from values affected by side effects
Instead of accepting the inconsistency between interpreter and compiled code here, we can just detect whether a value can be affected by side effects and refrain from reading it then. Since you can always explicitly reload a value that may have been changed, the resulting compile warnings are easily worked around in user code. Refactoring user code this way also makes it much clearer what is actually going on. Pick-to: 6.5 Task-number: QTBUG-109221 Change-Id: Ica832e39838ef732b0d181364630737fd7709b74 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'tests/auto')
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt1
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/valueTypeDefault.qml34
-rw-r--r--tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp75
3 files changed, 81 insertions, 29 deletions
diff --git a/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt b/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt
index 74f56f0bb3..ad8bcf32a9 100644
--- a/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt
+++ b/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt
@@ -219,6 +219,7 @@ set(qml_files
usingCxxTypesFromFileImports.qml
valueTypeCast.qml
valueTypeCopy.qml
+ valueTypeDefault.qml
valueTypeLists.qml
valueTypeProperty.qml
valueTypeReference.qml
diff --git a/tests/auto/qml/qmlcppcodegen/data/valueTypeDefault.qml b/tests/auto/qml/qmlcppcodegen/data/valueTypeDefault.qml
new file mode 100644
index 0000000000..42a55e832d
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/valueTypeDefault.qml
@@ -0,0 +1,34 @@
+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 9991688943..20a1bac8af 100644
--- a/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp
+++ b/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp
@@ -3693,42 +3693,59 @@ void tst_QmlCppCodegen::valueTypeBehavior()
{
QQmlEngine engine;
- const QUrl copy(u"qrc:/qt/qml/TestTypes/valueTypeCopy.qml"_s);
+ {
+ const QUrl url(u"qrc:/qt/qml/TestTypes/valueTypeCopy.qml"_s);
+ QQmlComponent c(&engine, url);
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QTest::ignoreMessage(QtWarningMsg, bindingLoopMessage(url, 'e'));
+ QTest::ignoreMessage(QtWarningMsg, bindingLoopMessage(url, 'f'));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+ QCOMPARE(o->property("e").toDouble(), 45.0);
+ QCOMPARE(o->property("f").toDouble(), 1.0);
+ }
- 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 url(u"qrc:/qt/qml/TestTypes/valueTypeReference.qml"_s);
+ QQmlComponent c(&engine, url);
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QTest::ignoreMessage(QtWarningMsg, bindingLoopMessage(url, 'e'));
+ QTest::ignoreMessage(QtWarningMsg, bindingLoopMessage(url, 'f'));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+ QVERIFY(qIsNaN(o->property("e").toDouble()));
+ QCOMPARE(o->property("f").toDouble(), 5.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);
+ {
+ const QUrl url(u"qrc:/qt/qml/TestTypes/valueTypeDefault.qml"_s);
+ QQmlComponent c(&engine, url);
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QTest::ignoreMessage(QtWarningMsg, bindingLoopMessage(url, 'e'));
+ QTest::ignoreMessage(QtWarningMsg, bindingLoopMessage(url, 'f'));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+ QVERIFY(qIsNaN(o->property("e").toDouble()));
+ QCOMPARE(o->property("f").toDouble(), 5.0);
+ }
- const QUrl cast(u"qrc:/qt/qml/TestTypes/valueTypeCast.qml"_s);
- QQmlComponent c3(&engine, cast);
- QVERIFY2(c3.isReady(), qPrintable(c3.errorString()));
- QScopedPointer o3(c3.create());
- QVERIFY(!o3.isNull());
- QCOMPARE(o3->property("x"), 10);
+ {
+ const QUrl url(u"qrc:/qt/qml/TestTypes/valueTypeCast.qml"_s);
+ QQmlComponent c(&engine, url);
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer o(c.create());
+ QVERIFY(!o.isNull());
+ QCOMPARE(o->property("x"), 10);
- QTest::ignoreMessage(
+ QTest::ignoreMessage(
QtWarningMsg,
- qPrintable(cast.toString()
+ qPrintable(url.toString()
+ u":8: TypeError: Cannot read property 'x' of undefined"_s));
- o3->setProperty("v", QLatin1String("not a rect"));
+ o->setProperty("v", QLatin1String("not a rect"));
- // If the binding throws an exception, the value doesn't change.
- QCOMPARE(o3->property("x"), 10);
+ // If the binding throws an exception, the value doesn't change.
+ QCOMPARE(o->property("x"), 10);
+ }
}
void tst_QmlCppCodegen::valueTypeLists()