Details
-
Bug
-
Resolution: Done
-
P2: Important
-
6.0.0 Alpha
-
43d0eae81e30ae8c8502e68d56c6c8b7e2c30215 (qt/qtdeclarative/dev)
Description
Interesting issue spotted while fixing QtPIM tests to work with Qt6. It seems like the QML engine has some change which means a different method overload will be chosen than in Qt5 times.
Consider the following QML file:
import QtQuick 2.0 Rectangle { color: "lightsteelblue" width: 200 height: 200 Timer { running: true repeat: false interval: 1000 onTriggered: { var strings = helper.getValues() console.log("JS got strings: " + strings) helper.printValues(strings) } } }
And the following C++:
#include <QtCore/QCoreApplication> #include <QtCore/QVariantMap> #include <QtCore/QString> #include <QtCore/QStringList> #include <QtCore/QTimer> #include <QtCore/QObject> #include <QtGui/QGuiApplication> #include <QtQml/QQmlEngine> #include <QtQml/QQmlComponent> #include <QtQml/QQmlContext> #include <QtQuick/QQuickView> #include <QtDebug> class CustomElement : public QObject { Q_OBJECT public: CustomElement(QObject *parent = nullptr) : QObject(parent) {} }; QML_DECLARE_TYPE(CustomElement) class Helper : public QObject { Q_OBJECT public: Helper(QQuickView *parent) : QObject(parent), m_view(parent) {} Q_INVOKABLE void doQuit() { QCoreApplication::instance()->quit(); } Q_INVOKABLE void doShow() { m_view->setSource(QUrl(QStringLiteral("main.qml"))); m_view->show(); } Q_INVOKABLE QStringList getValues() const { return QStringList() << QStringLiteral("one") << QStringLiteral("two"); } Q_INVOKABLE void printValues(const QStringList &strings) { qWarning() << "Printing strings from C++: " << strings; } Q_INVOKABLE void printValues(const QList<CustomElement> &elements) { qWarning() << "Printing elements from C++: "; for (const auto &e : elements) qWarning() << e.objectName(); } private: QQuickView *m_view; }; int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); QQuickView view; Helper *h = new Helper(&view); QTimer::singleShot(1, h, &Helper::doShow); view.rootContext()->setContextProperty("helper", QVariant::fromValue<QObject*>(h)); return app.exec(); } #include "main.moc"
With Qt5 we get:
$ ./testqstringlist qml: JS got strings: one,two Printing strings from C++: ("one", "two")
With Qt6 we get:
$ ./testqstringlist qml: JS got strings: one,two "Could not convert argument 0 at" "onTriggered@file:///home/qinetic/Qt/testapps/testqstringlist/main.qml:15" file:///home/qinetic/Qt/testapps/testqstringlist/main.qml:15: TypeError: Passing incompatible arguments to C++ functions from JavaScript is not allowed.
despite the QML_DECLARE_TYPE(CustomElement), and the fact that the first overload (with QStringList parameter) should be chosen for this call, I think.
Note that if we change the declaration of the second printValues() overload to look like:
Q_INVOKABLE void printValues(const QList<CustomElement*> &elements) { qWarning() << "Printing elements from C++: "; for (auto e : elements) qWarning() << e->objectName(); }
Then we see the following in Qt5:
qml: JS got strings: one,two "Could not convert argument 0 at" "onTriggered@file:///home/qinetic/Qt/testapps/testqstringlist/main.qml:15" "Passing incompatible arguments to C++ functions from JavaScript is dangerous and deprecated." "This will throw a JavaScript TypeError in future releases of Qt!" Printing elements from C++:
i.e. triggering the issue described in https://stackoverflow.com/questions/60915460/call-c-function-from-qml-js-with-c-object-as-argument
In short: I know that the second printValues() overload is bad (and I'm not sure why an example like this existed in the QtPIM unit tests to begin with; my solution will definitely be to remove it entirely). However, I still think it is strange that the QML engine is choosing the second overload even when the call parameter type should perfectly match the signature of the first method.
Attachments
For Gerrit Dashboard: QTBUG-87616 | ||||||
---|---|---|---|---|---|---|
# | Subject | Branch | Project | Status | CR | V |
320289,3 | QML engine: fix conversion scores for sequences in CallOverloaded | dev | qt/qtdeclarative | Status: MERGED | +2 | 0 |