aboutsummaryrefslogtreecommitdiffstats
path: root/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2022-12-22 14:45:04 +0100
committerUlf Hermann <ulf.hermann@qt.io>2023-01-02 21:50:34 +0100
commit3fd3a2a9d06505d549cc4a7c18819a17c6622dfd (patch)
treeaa266f8c45a9f81537a3820223f04387e57ddeb1 /tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
parente39b4572c272f8a0a7be048a24808cb028480e82 (diff)
QObjectWrapper: Fix calling attached methods on different objects
You can generally store a method in a value and call it on a different object. However, since we've ignored the thisObject basically forever, we cannot just accept it right away. Add an opt-in mechanism via a pragma that allows you to pass (implicitly via context or explicitly via call()) specific thisObjects to QObject methods. Fixes: QTBUG-109585 Pick-to: 6.5 Change-Id: I4c81b8ecf6317af55104ac9ebb62d98862ff24e7 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp')
-rw-r--r--tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp86
1 files changed, 86 insertions, 0 deletions
diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
index efe89f61ac..fee65fcb17 100644
--- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
+++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
@@ -403,6 +403,9 @@ private slots:
void nullIsNull();
void multiRequired();
+ void objectAndGadgetMethodCallsRejectThisObject();
+ void objectAndGadgetMethodCallsAcceptThisObject();
+
private:
QQmlEngine engine;
QStringList defaultImportPathList;
@@ -7763,6 +7766,89 @@ void tst_qqmllanguage::multiRequired()
qPrintable(url.toString() + ":5 Required property description was not initialized\n"));
}
+void tst_qqmllanguage::objectAndGadgetMethodCallsRejectThisObject()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("objectAndGadgetMethodCallsRejectThisObject.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+
+ const QList<int> lines = { 15, 19, 21, 22, 24, 25, 28, 31 };
+ for (int line : lines) {
+ const QString message
+ = ".*:%1: Calling C.. methods with 'this' objects different from the one "
+ "they were retrieved from is broken, due to historical reasons. The "
+ "original object is used as 'this' object. You can allow the given "
+ "'this' object to be used by setting "
+ "'pragma NativeMethodBehavior: AcceptThisObject'"_L1.arg(QString::number(line));
+ QTest::ignoreMessage(QtWarningMsg, QRegularExpression(message));
+ }
+
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+
+ QCOMPARE(o->property("badRect"), QRectF(1, 2, 3, 4));
+ QCOMPARE(o->property("goodRect1"), QRectF(1, 2, 3, 4));
+ QCOMPARE(o->property("goodRect2"), QRectF(1, 2, 3, 4));
+
+ QCOMPARE(o->property("badString"), QStringLiteral("27"));
+ QCOMPARE(o->property("goodString1"), QStringLiteral("27"));
+ QCOMPARE(o->property("goodString2"), QStringLiteral("27"));
+ QCOMPARE(o->property("goodString3"), QStringLiteral("27"));
+
+ QVERIFY(o->property("goodString4").value<QString>().startsWith("QObject_QML_"_L1));
+ QVERIFY(o->property("badString2").value<QString>().startsWith("QObject_QML_"_L1));
+
+ QCOMPARE(o->property("badInt"), 5);
+ QCOMPARE(o->property("goodInt1"), 5);
+ QCOMPARE(o->property("goodInt2"), 5);
+ QCOMPARE(o->property("goodInt3"), 5);
+}
+
+void tst_qqmllanguage::objectAndGadgetMethodCallsAcceptThisObject()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("objectAndGadgetMethodCallsAcceptThisObject.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+
+ QTest::ignoreMessage(
+ QtWarningMsg, QRegularExpression(
+ "objectAndGadgetMethodCallsAcceptThisObject.qml:16: Error: "
+ "Cannot call method QtObject::rect on QObject_QML_"));
+ QTest::ignoreMessage(
+ QtWarningMsg, QRegularExpression(
+ "objectAndGadgetMethodCallsAcceptThisObject.qml:20: Error: "
+ "Cannot call method BaseValueType::report on QObject_QML_"));
+ QTest::ignoreMessage(
+ QtWarningMsg, QRegularExpression(
+ "objectAndGadgetMethodCallsAcceptThisObject.qml:26: Error: "
+ "Cannot call method toString on QRectF"));
+ QTest::ignoreMessage(
+ QtWarningMsg, QRegularExpression(
+ "objectAndGadgetMethodCallsAcceptThisObject.qml:29: Error: "
+ "Cannot call method OriginalSingleton::mm on QObject_QML_"));
+
+
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+
+ QCOMPARE(o->property("badRect"), QRectF());
+ QCOMPARE(o->property("goodRect1"), QRectF(1, 2, 3, 4));
+ QCOMPARE(o->property("goodRect2"), QRectF(1, 2, 3, 4));
+
+ QCOMPARE(o->property("badString"), QString());
+ QCOMPARE(o->property("goodString1"), QStringLiteral("27"));
+ QCOMPARE(o->property("goodString2"), QStringLiteral("27"));
+ QCOMPARE(o->property("goodString3"), QStringLiteral("28"));
+
+ QVERIFY(o->property("goodString4").value<QString>().startsWith("QtObject"_L1));
+ QCOMPARE(o->property("badString2"), QString());
+
+ QCOMPARE(o->property("badInt"), 0);
+ QCOMPARE(o->property("goodInt1"), 5);
+ QCOMPARE(o->property("goodInt2"), 5);
+ QCOMPARE(o->property("goodInt3"), 5);
+}
+
QTEST_MAIN(tst_qqmllanguage)
#include "tst_qqmllanguage.moc"