From 47678c682f168eb6d5020383ea75fe1700e8c4f6 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Fri, 5 May 2023 14:59:37 +0200 Subject: QML: Don't try to convert objects with prototypes to QVariant This is likely to lose some properties. Fixes: QTBUG-106266 Change-Id: Ib5a2567d61635a5cf7b3abee7cfef0c073d59e63 Reviewed-by: Fabian Kosmale (cherry picked from commit 43077556550c6b17226a7d393ec844b605c9c678) Reviewed-by: Qt Cherry-pick Bot --- src/qml/jsruntime/qv4engine.cpp | 8 ++++---- tests/auto/qml/qqmlcomponent/data/complexObjectArgument.qml | 10 ++++++++++ tests/auto/qml/qqmlcomponent/data/dynamic.qml | 6 ++++++ tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp | 11 +++++++++++ 4 files changed, 31 insertions(+), 4 deletions(-) create mode 100644 tests/auto/qml/qqmlcomponent/data/complexObjectArgument.qml create mode 100644 tests/auto/qml/qqmlcomponent/data/dynamic.qml diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index 82c85b18e8..2e4fdcc200 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -1709,10 +1709,7 @@ static QVariant objectToVariant(const QV4::Object *o, V4ObjectSet *visitedObject } result = list; - } else if (const FunctionObject *f = o->as()) { - // If it's a FunctionObject, we can only save it as QJSValue. - result = QVariant::fromValue(QJSValuePrivate::fromReturnedValue(f->asReturnedValue())); - } else { + } else if (o->getPrototypeOf() == o->engine()->objectPrototype()->d()) { QVariantMap map; QV4::Scope scope(o->engine()); QV4::ObjectIterator it(scope, o, QV4::ObjectIterator::EnumerableOnly); @@ -1730,6 +1727,9 @@ static QVariant objectToVariant(const QV4::Object *o, V4ObjectSet *visitedObject } result = map; + } else { + // If it's not a plain object, we can only save it as QJSValue. + result = QVariant::fromValue(QJSValuePrivate::fromReturnedValue(o->asReturnedValue())); } visitedObjects->remove(o->d()); diff --git a/tests/auto/qml/qqmlcomponent/data/complexObjectArgument.qml b/tests/auto/qml/qqmlcomponent/data/complexObjectArgument.qml new file mode 100644 index 0000000000..89c9242110 --- /dev/null +++ b/tests/auto/qml/qqmlcomponent/data/complexObjectArgument.qml @@ -0,0 +1,10 @@ +import QtQml 2.15 + +QtObject { + id: root + Component.onCompleted: { + let comp = Qt.createComponent("dynamic.qml"); + let inst = comp.createObject(root, { testObj: new Set(), }); + objectName = inst.use(); + } +} diff --git a/tests/auto/qml/qqmlcomponent/data/dynamic.qml b/tests/auto/qml/qqmlcomponent/data/dynamic.qml new file mode 100644 index 0000000000..b9a54d53ff --- /dev/null +++ b/tests/auto/qml/qqmlcomponent/data/dynamic.qml @@ -0,0 +1,6 @@ +import QtQml + +QtObject { + property var testObj + function use() { return testObj.has(1) ? 25 : 26; } +} diff --git a/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp b/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp index d6a53b9950..0af3db58fa 100644 --- a/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp +++ b/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp @@ -146,6 +146,7 @@ private slots: void loadFromModuleRequired(); void loadFromQrc(); void removeBinding(); + void complexObjectArgument(); private: QQmlEngine engine; @@ -1450,6 +1451,16 @@ void tst_qqmlcomponent::removeBinding() QCOMPARE(o->property("result"), QStringLiteral("42")); } +void tst_qqmlcomponent::complexObjectArgument() +{ + QQmlEngine e; + QQmlComponent c(&e, testFileUrl("complexObjectArgument.qml")); + QVERIFY2(c.isReady(), qPrintable(c.errorString())); + QScopedPointer o(c.create()); + QVERIFY(!o.isNull()); + QCOMPARE(o->objectName(), QStringLiteral("26")); +} + QTEST_MAIN(tst_qqmlcomponent) #include "tst_qqmlcomponent.moc" -- cgit v1.2.1