aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper.cpp2
-rw-r--r--tests/auto/qml/qqmlecmascript/data/methodTypeMismatch.qml25
-rw-r--r--tests/auto/qml/qqmlecmascript/testtypes.h26
-rw-r--r--tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp77
4 files changed, 129 insertions, 1 deletions
diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp
index 3d1d129b38..942c0a70f9 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper.cpp
+++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp
@@ -1992,7 +1992,7 @@ bool CallArgument::fromValue(QMetaType metaType, QV4::ExecutionEngine *engine, c
qvariantPtr->convert(callMetaType);
} else {
QQmlMetaObject mo = ep ? ep->rawMetaObjectForType(callType) : QQmlMetaObject();
- if (!mo.isNull()) {
+ if (!mo.isNull() && v.metaType().flags().testFlag(QMetaType::PointerToQObject)) {
QObject *obj = QQmlMetaType::toQObject(v);
if (obj != nullptr && !QQmlMetaObject::canConvert(obj, mo)) {
diff --git a/tests/auto/qml/qqmlecmascript/data/methodTypeMismatch.qml b/tests/auto/qml/qqmlecmascript/data/methodTypeMismatch.qml
new file mode 100644
index 0000000000..fdf5f4ea11
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/methodTypeMismatch.qml
@@ -0,0 +1,25 @@
+import QtQuick 2.0
+
+Item {
+ id: self
+ property font myFont
+ property int notMyFont
+
+ property var object
+
+ function callWithFont() {
+ object.method_gadget(myFont) // should be fine
+ }
+ function callWithInt() {
+ object.method_gadget(123)
+ }
+ function callWithInt2() {
+ object.method_gadget(notMyFont)
+ }
+ function callWithNull() {
+ object.method_gadget(null)
+ }
+ function callWithAllowedNull() {
+ object.method_qobject(null)
+ }
+}
diff --git a/tests/auto/qml/qqmlecmascript/testtypes.h b/tests/auto/qml/qqmlecmascript/testtypes.h
index acc066fddd..8198218f8b 100644
--- a/tests/auto/qml/qqmlecmascript/testtypes.h
+++ b/tests/auto/qml/qqmlecmascript/testtypes.h
@@ -833,12 +833,38 @@ public:
Q_INVOKABLE void method_unknown(NonRegisteredType) { invoke(28); }
+ Q_PROPERTY(QFont someFont READ someFont WRITE setSomeFont NOTIFY someFontChanged);
+ QFont someFont() { return m_someFont; }
+ void setSomeFont(const QFont &f)
+ {
+ if (f == m_someFont)
+ return;
+ m_someFont = f;
+ emit someFontChanged();
+ }
+ Q_INVOKABLE void method_gadget(QFont f)
+ {
+ invoke(40);
+ m_actuals << f;
+ }
+ Q_INVOKABLE void method_qobject(QObject *o)
+ {
+ invoke(41);
+ m_actuals << QVariant::fromValue(o);
+ }
+
private:
friend class MyInvokableBaseObject;
void invoke(int idx) { if (m_invoked != -1) m_invokedError = true; m_invoked = idx;}
int m_invoked;
bool m_invokedError;
QVariantList m_actuals;
+
+ QFont m_someFont;
+
+public:
+Q_SIGNALS:
+ void someFontChanged();
};
MyInvokableBaseObject::~MyInvokableBaseObject() {}
diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
index 2d38bf0524..47941c8a7d 100644
--- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
+++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
@@ -428,6 +428,7 @@ private slots:
void functionAsDefaultArgument();
void internalClassParentGc();
+ void methodTypeMismatch();
private:
// static void propertyVarWeakRefCallback(v8::Persistent<v8::Value> object, void* parameter);
@@ -3331,6 +3332,19 @@ void tst_qqmlecmascript::callQtInvokables()
QJSValue callback = qvariant_cast<QJSValue>(o->actuals().at(1));
QVERIFY(!callback.isNull());
QVERIFY(callback.isCallable());
+
+ o->reset();
+ QVERIFY(EVALUATE_VALUE("object.method_gadget(object.someFont)",
+ QV4::Primitive::undefinedValue()));
+ QCOMPARE(o->error(), false);
+ QCOMPARE(o->invoked(), 40);
+ QCOMPARE(o->actuals(), QVariantList() << QVariant(o->someFont()));
+
+ o->reset();
+ QVERIFY(EVALUATE_ERROR("object.method_gadget(123)"));
+ QCOMPARE(o->error(), false);
+ QCOMPARE(o->invoked(), -1);
+ QCOMPARE(o->actuals(), QVariantList());
}
void tst_qqmlecmascript::resolveClashingProperties()
@@ -9978,6 +9992,69 @@ void tst_qqmlecmascript::internalClassParentGc()
QCOMPARE(root->objectName(), "3");
}
+void tst_qqmlecmascript::methodTypeMismatch()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("methodTypeMismatch.qml"));
+
+ QScopedPointer<MyInvokableObject> object(new MyInvokableObject());
+
+ QScopedPointer<QObject> o(component.create());
+ QVERIFY2(o, qPrintable(component.errorString()));
+ o->setProperty("object", QVariant::fromValue(object.get()));
+
+ auto mo = o->metaObject();
+ QVERIFY(mo);
+
+ auto method = mo->method(mo->indexOfMethod("callWithFont()"));
+ QVERIFY(method.isValid());
+ QVERIFY(method.invoke(o.get()));
+ QCOMPARE(object->actuals(), QVariantList() << QVariant(object->someFont()));
+
+ QRegularExpression argumentConversionErrorMatcher("Could not convert argument 0");
+ QRegularExpression argumentConversionErrorMatcher2(".*/methodTypeMismatch.qml");
+ QRegularExpression typeErrorMatcher(
+ ".*/methodTypeMismatch\\.qml:..: TypeError: Passing incompatible arguments to C\\+\\+ "
+ "functions from JavaScript is not allowed.");
+
+ QTest::ignoreMessage(QtWarningMsg, argumentConversionErrorMatcher);
+ QTest::ignoreMessage(QtWarningMsg, argumentConversionErrorMatcher2);
+ QTest::ignoreMessage(QtWarningMsg, typeErrorMatcher);
+ object->reset();
+ method = mo->method(mo->indexOfMethod("callWithInt()"));
+ QVERIFY(method.isValid());
+ QVERIFY(method.invoke(o.get()));
+ QCOMPARE(object->actuals().size(),
+ 0); // actuals() should not contain reinterpret_cast<QFont>(123) !!!
+
+ QTest::ignoreMessage(QtWarningMsg, argumentConversionErrorMatcher);
+ QTest::ignoreMessage(QtWarningMsg, argumentConversionErrorMatcher2);
+ QTest::ignoreMessage(QtWarningMsg, typeErrorMatcher);
+ object->reset();
+ method = mo->method(mo->indexOfMethod("callWithInt2()"));
+ QVERIFY(method.isValid());
+ QVERIFY(method.invoke(o.get()));
+ QCOMPARE(object->actuals().size(),
+ 0); // actuals() should not contain reinterpret_cast<QFont>(0) !!!
+
+ QTest::ignoreMessage(QtWarningMsg, argumentConversionErrorMatcher);
+ QTest::ignoreMessage(QtWarningMsg, argumentConversionErrorMatcher2);
+ QTest::ignoreMessage(QtWarningMsg, typeErrorMatcher);
+ object->reset();
+ method = mo->method(mo->indexOfMethod("callWithNull()"));
+ QVERIFY(method.isValid());
+ QVERIFY(method.invoke(o.get()));
+ QCOMPARE(object->actuals().size(),
+ 0); // actuals() should not contain reinterpret_cast<QFont>(nullptr) !!!
+
+ // make sure that null is still accepted by functions accepting, e.g., a QObject*!
+ object->reset();
+ method = mo->method(mo->indexOfMethod("callWithAllowedNull()"));
+ QVERIFY(method.isValid());
+ QVERIFY(method.invoke(o.get()));
+ QCOMPARE(object->actuals(), QVariantList() << QVariant::fromValue((QObject *)nullptr));
+}
+
QTEST_MAIN(tst_qqmlecmascript)
#include "tst_qqmlecmascript.moc"