QObjectWrapper: Use metaTypeFromJS for call arguments

We want the precise type there, not some approximation that happens to
be a QVariant. This exposes that we had a few conversions that were
possible with QVariant::convert() but not with our builtin type
coercion.

Pick-to: 6.5 6.6
Change-Id: I44c57a22bad8268de3d4398721e1c63b18009dfc
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
This commit is contained in:
Ulf Hermann 2023-06-01 11:07:25 +02:00
parent 7bcac62265
commit 67d0c08212
4 changed files with 17 additions and 30 deletions

View File

@ -2192,37 +2192,10 @@ bool CallArgument::fromValue(QMetaType metaType, ExecutionEngine *engine, const
}
// Convert via QVariant through the QML engine.
qvariantPtr = new (&allocData) QVariant();
qvariantPtr = new (&allocData) QVariant(metaType);
type = QVariantWrappedType;
QVariant v = ExecutionEngine::toVariant(value, metaType);
if (v.metaType() == metaType) {
*qvariantPtr = std::move(v);
return true;
}
if (v.canConvert(metaType)) {
*qvariantPtr = std::move(v);
qvariantPtr->convert(metaType);
return true;
}
const QQmlMetaObject mo = QQmlMetaType::rawMetaObjectForType(metaType);
if (!mo.isNull() && v.metaType().flags().testFlag(QMetaType::PointerToQObject)) {
QObject *obj = QQmlMetaType::toQObject(v);
if (obj != nullptr && !QQmlMetaObject::canConvert(obj, mo)) {
*qvariantPtr = QVariant(metaType, nullptr);
return false;
}
*qvariantPtr = QVariant(metaType, &obj);
return true;
}
*qvariantPtr = QVariant(metaType, (void *)nullptr);
return false;
return ExecutionEngine::metaTypeFromJS(value, metaType, qvariantPtr->data());
}
ReturnedValue CallArgument::toValue(ExecutionEngine *engine)

View File

@ -40,10 +40,13 @@ MyTypeObject {
r2 = {x: 9, y: 10, width: 11, height: 12};
c3 = 99;
b2 = {i: 11, c: 15, p: {x: 4} }
acceptConstructible(object)
c4 = {foo: 11};
}
barren: ({i: 17})
function changeBarren() { barren = "foos" }
property QtObject object: QtObject {}
property constructible fromObject: object
}

View File

@ -33,6 +33,7 @@ struct ConstructibleValueType
public:
ConstructibleValueType() = default;
Q_INVOKABLE ConstructibleValueType(int foo) : m_foo(foo) {}
Q_INVOKABLE ConstructibleValueType(QObject *) : m_foo(67) {}
int foo() const { return m_foo; }
@ -350,6 +351,11 @@ public:
emit barrenChanged();
}
Q_INVOKABLE void acceptConstructible(const ConstructibleValueType &a)
{
setAVariant(QVariant::fromValue(a));
}
signals:
void changed();
void runScript();

View File

@ -358,6 +358,11 @@ void tst_qqmlvaluetypeproviders::structured()
QMetaObject::invokeMethod(o.data(), "changeBarren");
QCOMPARE(o->property("barren").value<BarrenValueType>(), BarrenValueType(QString()));
QCOMPARE(o->property("fromObject").value<ConstructibleValueType>(),
ConstructibleValueType(nullptr));
QCOMPARE(o->property("aVariant").value<ConstructibleValueType>(),
ConstructibleValueType(nullptr));
}
void tst_qqmlvaluetypeproviders::recursive()