aboutsummaryrefslogtreecommitdiffstats
path: root/tests/auto/qml/qmlcppcodegen
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2024-01-31 15:17:19 +0100
committerUlf Hermann <ulf.hermann@qt.io>2024-02-01 09:33:09 +0100
commit452929cea1be97664f886509c3bd1b1a51dcf755 (patch)
treeec688aa8c9c712d13bfcb8c66948a6a115ec6838 /tests/auto/qml/qmlcppcodegen
parent1b8b77285948813b6e74554798b06210736e521c (diff)
QmlCompiler: Reject lookups on shadowable base types
If the base type of a lookup is shadowable we cannot give any guarantees at all about what is going to happen. Only if the right hand side of the lookup is shadowable we can use our QVariant trick. Fixes: QTBUG-121734 Pick-to: 6.7 6.6 Change-Id: I969a842a6bc6d6a4446bfbfb50f1a7021b84049e Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Diffstat (limited to 'tests/auto/qml/qmlcppcodegen')
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt1
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/indirectlyShadowable.qml39
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/variantMap.qml8
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/writeback.qml7
-rw-r--r--tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp64
5 files changed, 116 insertions, 3 deletions
diff --git a/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt b/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt
index 4bf9aaab96..b896de4a1f 100644
--- a/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt
+++ b/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt
@@ -154,6 +154,7 @@ set(qml_files
immediateQuit.qml
imports/QmlBench/Globals.qml
importsFromImportPath.qml
+ indirectlyShadowable.qml
infinities.qml
infinitiesToInt.qml
intEnumCompare.qml
diff --git a/tests/auto/qml/qmlcppcodegen/data/indirectlyShadowable.qml b/tests/auto/qml/qmlcppcodegen/data/indirectlyShadowable.qml
new file mode 100644
index 0000000000..de31527e5b
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/indirectlyShadowable.qml
@@ -0,0 +1,39 @@
+import QtQml
+
+QtObject {
+ id: self
+ objectName: "self"
+
+ component Inner : QtObject {
+ property QtObject shadowable: QtObject {
+ objectName: "shadowable"
+ }
+ }
+
+ component Outer : QtObject {
+ property Inner inner: Inner {}
+ }
+
+ component Evil : Outer {
+ property string inner: "evil"
+ }
+
+ property Outer outer: Outer {}
+ property Outer evil: Evil {}
+
+ property QtObject notShadowable: QtObject {
+ objectName: "notShadowable"
+ }
+
+ function getInnerShadowable() {
+ notShadowable = outer.inner.shadowable;
+ }
+
+ function setInnerShadowable() {
+ outer.inner.shadowable = self;
+ }
+
+ function turnEvil() {
+ outer = evil;
+ }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/variantMap.qml b/tests/auto/qml/qmlcppcodegen/data/variantMap.qml
index 410727cfd6..a8ac953f8b 100644
--- a/tests/auto/qml/qmlcppcodegen/data/variantMap.qml
+++ b/tests/auto/qml/qmlcppcodegen/data/variantMap.qml
@@ -11,8 +11,14 @@ QtObject {
QtObject {}
}
+ // We need this extra function in order to coerce the result of the shadowable
+ // method call back to QtObject
+ function createShadowable() : QtObject {
+ return shadowable.createObject(this, {objectName: "a"})
+ }
+
objectName: {
- return shadowable.createObject(this, {objectName: "a"}).objectName
+ return createShadowable().objectName
+ " " + unshadowable.createObject(this, {objectName: "b"}).objectName
}
diff --git a/tests/auto/qml/qmlcppcodegen/data/writeback.qml b/tests/auto/qml/qmlcppcodegen/data/writeback.qml
index 8c6cb845c7..359f00efb7 100644
--- a/tests/auto/qml/qmlcppcodegen/data/writeback.qml
+++ b/tests/auto/qml/qmlcppcodegen/data/writeback.qml
@@ -15,6 +15,7 @@ Person {
property outer recursive
property Person shadowable: Person {
+ id: notShadowable
area.width: self.area.width
area2.height: self.area2.height
}
@@ -26,8 +27,10 @@ Person {
self.area.x = 4
self.area2.y = 5
- shadowable.area.x = 40
- shadowable.area2.y = 50
+ // You cannot do this on the shadowable Person because
+ // shadowable.area may not actually be a QRectF anymore.
+ notShadowable.area.x = 40
+ notShadowable.area2.y = 50
self.recursive.inner.i = 99;
diff --git a/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp b/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp
index 88c4e2375f..b98da74716 100644
--- a/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp
+++ b/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp
@@ -119,6 +119,7 @@ private slots:
void importsFromImportPath();
void inPlaceDecrement();
void inaccessibleProperty();
+ void indirectlyShadowable();
void infinities();
void infinitiesToInt();
void innerObjectNonShadowable();
@@ -2243,6 +2244,69 @@ void tst_QmlCppCodegen::inaccessibleProperty()
QCOMPARE(o->property("c").toInt(), 5);
}
+void tst_QmlCppCodegen::indirectlyShadowable()
+{
+ QQmlEngine engine;
+
+ const QString url = u"qrc:/qt/qml/TestTypes/indirectlyShadowable.qml"_s;
+ QQmlComponent c(&engine, QUrl(url));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+
+ const auto verifyShadowable = [&](const QString &objectName) {
+ QObject *outer = o->property("outer").value<QObject *>();
+ QVERIFY(outer);
+ QObject *inner = outer->property("inner").value<QObject *>();
+ QVERIFY(inner);
+ QObject *shadowable = inner->property("shadowable").value<QObject *>();
+ QVERIFY(shadowable);
+ QCOMPARE(shadowable->objectName(), objectName);
+ };
+
+ const auto verifyNotShadowable = [&](const QString &objectName) {
+ QObject *notShadowable = o->property("notShadowable").value<QObject *>();
+ QCOMPARE(notShadowable->objectName(), objectName);
+ };
+
+ const auto verifyEvil = [&]() {
+ QObject *outer = o->property("outer").value<QObject *>();
+ QVERIFY(outer);
+ QCOMPARE(outer->property("inner").toString(), u"evil"_s);
+ };
+
+ verifyShadowable(u"shadowable"_s);
+ verifyNotShadowable(u"notShadowable"_s);
+
+ QMetaObject::invokeMethod(o.data(), "setInnerShadowable");
+
+ verifyShadowable(u"self"_s);
+ verifyNotShadowable(u"notShadowable"_s);
+
+ QMetaObject::invokeMethod(o.data(), "getInnerShadowable");
+
+ verifyShadowable(u"self"_s);
+ verifyNotShadowable(u"self"_s);
+
+ QMetaObject::invokeMethod(o.data(), "turnEvil");
+
+ verifyEvil();
+ verifyNotShadowable(u"self"_s);
+
+ // Does not produce an error message because JavaScript.
+ QMetaObject::invokeMethod(o.data(), "setInnerShadowable");
+
+ verifyEvil();
+ verifyNotShadowable(u"self"_s);
+
+ QTest::ignoreMessage(
+ QtWarningMsg, qPrintable(url + u":29: Error: Cannot assign [undefined] to QObject*"_s));
+ QMetaObject::invokeMethod(o.data(), "getInnerShadowable");
+
+ verifyEvil();
+ verifyNotShadowable(u"self"_s);
+}
+
void tst_QmlCppCodegen::infinities()
{
QQmlEngine engine;