aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFabian Kosmale <fabian.kosmale@qt.io>2022-09-02 15:35:32 +0200
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2022-09-02 21:55:18 +0000
commit9628b73f6c2f5d7dbab582eced8d2a705a49cc5b (patch)
treec9a8a4a8b3107ba85c07917ba75e67eb092b6d08
parent5ab98872863f65f58789206c750360c06d2600e2 (diff)
Engine: Fix handling of attached objects in function calls
When we use an attached object as an argument to a function call, we need to properly extract it from the QmlTypeWrapper. Before this change, we simpley left the argument pointer as null, which lead to subsequent crashes when it got dereferenced. Moreover, treat passing namespaces to functions expecting a QObject as a TypeError, by returning false from CallArgument::fromValue (used to crash for the same reason as with the attached object case). Fixes: QTBUG-106119 Change-Id: Ifa6a32e20a29935aff1f265eb0edd3e35ea1c11b Reviewed-by: Ulf Hermann <ulf.hermann@qt.io> (cherry picked from commit 84483bff4f4d49e5f87abf564021647f2fb2a8d0) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper.cpp10
-rw-r--r--tests/auto/qml/qqmlecmascript/data/qmlTypeWrapperArgs.qml8
-rw-r--r--tests/auto/qml/qqmlecmascript/data/qmlTypeWrapperArgs2.qml9
-rw-r--r--tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp20
4 files changed, 43 insertions, 4 deletions
diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp
index 1a54102bf4..502b8bafa1 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper.cpp
+++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp
@@ -1958,14 +1958,16 @@ bool CallArgument::fromValue(
// Convert via QVariant below.
// TODO: Can't we just do qobjectPtr = qmlTypeWrapper->object() instead?
break;
+ } else if (QObject *obj = qmlTypeWrapper->object()) {
+ // attached object case
+ qobjectPtr = obj;
+ return true;
}
// If this is a plain type wrapper without an instance,
- // then indeed it's an undefined parameter.
- // (although we might interpret that as const QMetaObject *).
- // TODO: But what if it's an attached object?
+ // then we got a namespace, and that's a type error
type = QMetaType::UnknownType;
- return true;
+ return false;
}
qobjectPtr = nullptr;
diff --git a/tests/auto/qml/qqmlecmascript/data/qmlTypeWrapperArgs.qml b/tests/auto/qml/qqmlecmascript/data/qmlTypeWrapperArgs.qml
new file mode 100644
index 0000000000..7f1b5b0317
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/qmlTypeWrapperArgs.qml
@@ -0,0 +1,8 @@
+import QtQml
+
+QtObject {
+ id: root
+ required property QtObject invokableObject
+
+ Component.onCompleted: root.invokableObject.method_QObject(Component)
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/qmlTypeWrapperArgs2.qml b/tests/auto/qml/qqmlecmascript/data/qmlTypeWrapperArgs2.qml
new file mode 100644
index 0000000000..1904740b26
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/qmlTypeWrapperArgs2.qml
@@ -0,0 +1,9 @@
+import QtQml
+import QtQml as NS
+
+QtObject {
+ id: root
+ required property QtObject invokableObject
+
+ Component.onCompleted: root.invokableObject.method_QObject(NS)
+}
diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
index 84e89f14d3..547ccf4635 100644
--- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
+++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
@@ -3147,6 +3147,26 @@ void tst_qqmlecmascript::callQtInvokables()
QCOMPARE(o->actuals().count(), 1);
QCOMPARE(o->actuals().at(0), QVariant::fromValue((QObject *)nullptr));
+ {
+ o->reset();
+ QQmlComponent comp(&qmlengine, testFileUrl("qmlTypeWrapperArgs.qml"));
+ QScopedPointer<QObject> root {comp.createWithInitialProperties({{"invokableObject", QVariant::fromValue(o)}}) };
+ QVERIFY(root);
+ QCOMPARE(o->error(), false);
+ QCOMPARE(o->invoked(), 13);
+ QCOMPARE(o->actuals().count(), 1);
+ QCOMPARE(o->actuals().at(0).value<QObject *>()->metaObject()->className(), "QQmlComponentAttached");
+ }
+
+ {
+ o->reset();
+ QQmlComponent comp(&qmlengine, testFileUrl("qmlTypeWrapperArgs2.qml"));
+ QScopedPointer<QObject> root {comp.createWithInitialProperties({{"invokableObject", QVariant::fromValue(o)}}) };
+ QVERIFY(root);
+ QCOMPARE(o->error(), false);
+ QCOMPARE(o->invoked(), -1); // no function got called due to incompatible arguments
+ }
+
o->reset();
QVERIFY(EVALUATE_VALUE("object.method_QObject(undefined)", QV4::Primitive::undefinedValue()));
QCOMPARE(o->error(), false);