aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2019-02-21 09:39:20 +0100
committerJani Heikkinen <jani.heikkinen@qt.io>2019-02-21 11:15:38 +0000
commitdca09f09734fff19a3a5ad930662e0e9abd3cb1b (patch)
tree3a63fd06198675ccd80585d4c4066178203f9e93
parent407e2769c7b7909fdb2979090e71fa636f109a04 (diff)
Only warn about incompatible parameter types passed from QML
Throwing a TypeError is too drastic. We need to properly deprecate this pattern before we actually enforce the compatibility. Fixes: QTBUG-73943 Change-Id: I00313ad7aed4021a7368fd014e2bfc6443b177e3 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper.cpp31
-rw-r--r--tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp42
-rw-r--r--tests/auto/qml/qqmllanguage/data/SignalEmitter.qml14
3 files changed, 48 insertions, 39 deletions
diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp
index 6617dd5e89..40be6f41c8 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper.cpp
+++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp
@@ -1206,8 +1206,20 @@ static QV4::ReturnedValue CallMethod(const QQmlObjectOrGadget &object, int index
args[0].initAsType(returnType);
for (int ii = 0; ii < argCount; ++ii) {
if (!args[ii + 1].fromValue(argTypes[ii], engine, callArgs->args[ii])) {
- return engine->throwTypeError(QString::fromLatin1("Could not convert argument %1.")
- .arg(ii));
+ qWarning() << QString::fromLatin1("Could not convert argument %1 at").arg(ii);
+ const StackTrace stack = engine->stackTrace();
+ for (const StackFrame &frame : stack) {
+ qWarning() << "\t" << frame.function + QLatin1Char('@') + frame.source
+ + (frame.line > 0
+ ? (QLatin1Char(':') + QString::number(frame.line))
+ : QString());
+
+ }
+ qWarning() << QLatin1String("Passing incompatible arguments to C++ functions from "
+ "JavaScript is dangerous and deprecated.");
+ qWarning() << QLatin1String("This will throw a JavaScript TypeError in future "
+ "releases of Qt!");
+
}
}
QVarLengthArray<void *, 9> argData(args.count());
@@ -1724,6 +1736,7 @@ bool CallArgument::fromValue(int callType, QV4::ExecutionEngine *engine, const Q
type = callType;
} else if (callType == qMetaTypeId<QList<QObject*> >()) {
qlistPtr = new (&allocData) QList<QObject *>();
+ type = callType;
QV4::ScopedArrayObject array(scope, value);
if (array) {
Scoped<QV4::QObjectWrapper> qobjectWrapper(scope);
@@ -1737,14 +1750,14 @@ bool CallArgument::fromValue(int callType, QV4::ExecutionEngine *engine, const Q
qlistPtr->append(o);
}
} else {
- QObject *o = nullptr;
- if (const QV4::QObjectWrapper *qobjectWrapper = value.as<QV4::QObjectWrapper>())
- o = qobjectWrapper->object();
- else if (!value.isNull() && !value.isUndefined())
- return false;
- qlistPtr->append(o);
+ if (const QV4::QObjectWrapper *qobjectWrapper = value.as<QV4::QObjectWrapper>()) {
+ qlistPtr->append(qobjectWrapper->object());
+ } else {
+ qlistPtr->append(nullptr);
+ if (!value.isNull() && !value.isUndefined())
+ return false;
+ }
}
- type = callType;
} else if (callType == qMetaTypeId<QQmlV4Handle>()) {
handlePtr = new (&allocData) QQmlV4Handle(value.asReturnedValue());
type = callType;
diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
index 6a97fc5d8b..788ecce1c5 100644
--- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
+++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
@@ -2762,28 +2762,32 @@ void tst_qqmlecmascript::callQtInvokables()
QCOMPARE(o->actuals().at(0), QVariant(QString()));
o->reset();
- QVERIFY(!EVALUATE_VALUE("object.method_QPointF(0)", QV4::Primitive::undefinedValue()));
+ QVERIFY(EVALUATE_VALUE("object.method_QPointF(0)", QV4::Primitive::undefinedValue()));
QCOMPARE(o->error(), false);
- QCOMPARE(o->invoked(), -1);
- QCOMPARE(o->actuals().count(), 0);
+ QCOMPARE(o->invoked(), 12);
+ QCOMPARE(o->actuals().count(), 1);
+ QCOMPARE(o->actuals().at(0), QVariant(QPointF()));
o->reset();
- QVERIFY(!EVALUATE_VALUE("object.method_QPointF(null)", QV4::Primitive::undefinedValue()));
+ QVERIFY(EVALUATE_VALUE("object.method_QPointF(null)", QV4::Primitive::undefinedValue()));
QCOMPARE(o->error(), false);
- QCOMPARE(o->invoked(), -1);
- QCOMPARE(o->actuals().count(), 0);
+ QCOMPARE(o->invoked(), 12);
+ QCOMPARE(o->actuals().count(), 1);
+ QCOMPARE(o->actuals().at(0), QVariant(QPointF()));
o->reset();
- QVERIFY(!EVALUATE_VALUE("object.method_QPointF(undefined)", QV4::Primitive::undefinedValue()));
+ QVERIFY(EVALUATE_VALUE("object.method_QPointF(undefined)", QV4::Primitive::undefinedValue()));
QCOMPARE(o->error(), false);
- QCOMPARE(o->invoked(), -1);
- QCOMPARE(o->actuals().count(), 0);
+ QCOMPARE(o->invoked(), 12);
+ QCOMPARE(o->actuals().count(), 1);
+ QCOMPARE(o->actuals().at(0), QVariant(QPointF()));
o->reset();
- QVERIFY(!EVALUATE_VALUE("object.method_QPointF(object)", QV4::Primitive::undefinedValue()));
+ QVERIFY(EVALUATE_VALUE("object.method_QPointF(object)", QV4::Primitive::undefinedValue()));
QCOMPARE(o->error(), false);
- QCOMPARE(o->invoked(), -1);
- QCOMPARE(o->actuals().count(), 0);
+ QCOMPARE(o->invoked(), 12);
+ QCOMPARE(o->actuals().count(), 1);
+ QCOMPARE(o->actuals().at(0), QVariant(QPointF()));
o->reset();
QVERIFY(EVALUATE_VALUE("object.method_QPointF(object.method_get_QPointF())", QV4::Primitive::undefinedValue()));
@@ -2800,16 +2804,18 @@ void tst_qqmlecmascript::callQtInvokables()
QCOMPARE(o->actuals().at(0), QVariant(QPointF(9, 12)));
o->reset();
- QVERIFY(!EVALUATE_VALUE("object.method_QObject(0)", QV4::Primitive::undefinedValue()));
+ QVERIFY(EVALUATE_VALUE("object.method_QObject(0)", QV4::Primitive::undefinedValue()));
QCOMPARE(o->error(), false);
- QCOMPARE(o->invoked(), -1);
- QCOMPARE(o->actuals().count(), 0);
+ QCOMPARE(o->invoked(), 13);
+ QCOMPARE(o->actuals().count(), 1);
+ QCOMPARE(o->actuals().at(0), qVariantFromValue((QObject *)nullptr));
o->reset();
- QVERIFY(!EVALUATE_VALUE("object.method_QObject(\"Hello world\")", QV4::Primitive::undefinedValue()));
+ QVERIFY(EVALUATE_VALUE("object.method_QObject(\"Hello world\")", QV4::Primitive::undefinedValue()));
QCOMPARE(o->error(), false);
- QCOMPARE(o->invoked(), -1);
- QCOMPARE(o->actuals().count(), 0);
+ QCOMPARE(o->invoked(), 13);
+ QCOMPARE(o->actuals().count(), 1);
+ QCOMPARE(o->actuals().at(0), qVariantFromValue((QObject *)nullptr));
o->reset();
QVERIFY(EVALUATE_VALUE("object.method_QObject(null)", QV4::Primitive::undefinedValue()));
diff --git a/tests/auto/qml/qqmllanguage/data/SignalEmitter.qml b/tests/auto/qml/qqmllanguage/data/SignalEmitter.qml
index 31fe5e4a5e..259f45b7d2 100644
--- a/tests/auto/qml/qqmllanguage/data/SignalEmitter.qml
+++ b/tests/auto/qml/qqmllanguage/data/SignalEmitter.qml
@@ -10,18 +10,8 @@ QtObject {
signal testSignal(SignalParam spp);
function emitTestSignal() {
- var caught = false;
- try {
- testObject.expectNull = true;
- testSignal(op);
- } catch(e) {
- // good: We want a type error here
- caught = true;
- if (handleSignal)
- testObject.determineSuccess(null);
- }
- if (!caught && handleSignal)
- testObject.determineSuccess("fail");
+ testObject.expectNull = true;
+ testSignal(op);
testObject.expectNull = false;
testSignal(p);