diff options
author | Fabian Kosmale <fabian.kosmale@qt.io> | 2022-09-02 15:35:32 +0200 |
---|---|---|
committer | Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> | 2022-09-02 21:55:18 +0000 |
commit | 9628b73f6c2f5d7dbab582eced8d2a705a49cc5b (patch) | |
tree | c9a8a4a8b3107ba85c07917ba75e67eb092b6d08 | |
parent | 5ab98872863f65f58789206c750360c06d2600e2 (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>
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); |