diff options
| author | Ulf Hermann <ulf.hermann@qt.io> | 2025-09-03 13:47:48 +0200 |
|---|---|---|
| committer | Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> | 2025-09-12 03:27:53 +0000 |
| commit | 2561c5221af158ed3edfefd29759623ddc470f03 (patch) | |
| tree | 9aa12e9c60deb11c3de72dfb01b51bf4b410c1ec | |
| parent | 793efe73beedc53737fa30c9c8cbea3fe61c8361 (diff) | |
QtQml: Avoid double-wrapping when converting to QVariantList
Amends commit 1b89c1edcae68351632c2755e5408410c2ff98e3
Fixes: QTBUG-139764
Pick-to: 6.8
Change-Id: I1488527a235d74fc0352c72b9bfb69589c2f3d93
Reviewed-by: Sami Shalayel <sami.shalayel@qt.io>
(cherry picked from commit ce266fbcddc48edd63c4ba8c4a6f43fb2df48153)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
(cherry picked from commit 1b33b8754573b2922ba19b143ac13f733a52630b)
| -rw-r--r-- | src/qml/jsruntime/qv4engine.cpp | 20 | ||||
| -rw-r--r-- | tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | tests/auto/qml/qmlcppcodegen/data/sequenceToIterable.h | 9 | ||||
| -rw-r--r-- | tests/auto/qml/qmlcppcodegen/data/sequenceToIterable2.qml | 6 | ||||
| -rw-r--r-- | tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp | 14 |
5 files changed, 46 insertions, 4 deletions
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index 56a209d901..133c141d20 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -2521,15 +2521,29 @@ bool convertToIterable(QMetaType metaType, void *data, Source *sequence) if (!QMetaType::view(metaType, data, QMetaType::fromType<QSequentialIterable>(), &iterable)) return false; - const QMetaType elementMetaType = iterable.valueMetaType(); + // Clear the sequence before appending. There may be stale data in there. + metaType.destruct(data); + metaType.construct(data); + QV4::Scope scope(sequence->engine()); QV4::ScopedValue v(scope); + + const QMetaType elementMetaType = iterable.valueMetaType(); + QVariant element; + void *elementData = nullptr; + if (elementMetaType == QMetaType::fromType<QVariant>()) { + elementData = &element; + } else { + element = QVariant(elementMetaType); + elementData = element.data(); + } + for (qsizetype i = 0, end = sequence->getLength(); i < end; ++i) { - QVariant element(elementMetaType); v = sequence->get(i); - ExecutionEngine::metaTypeFromJS(v, elementMetaType, element.data()); + ExecutionEngine::metaTypeFromJS(v, elementMetaType, elementData); iterable.addValue(element, QSequentialIterable::AtEnd); } + return true; } diff --git a/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt b/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt index 898db2e5d3..9060efb993 100644 --- a/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt +++ b/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt @@ -281,6 +281,7 @@ set(qml_files script.js script.mjs sequenceToIterable.qml + sequenceToIterable2.qml setLookupConversion.qml setLookupOriginalScope.qml shadowedAsCasts.qml diff --git a/tests/auto/qml/qmlcppcodegen/data/sequenceToIterable.h b/tests/auto/qml/qmlcppcodegen/data/sequenceToIterable.h index 366cadef3c..1e225b45dc 100644 --- a/tests/auto/qml/qmlcppcodegen/data/sequenceToIterable.h +++ b/tests/auto/qml/qmlcppcodegen/data/sequenceToIterable.h @@ -47,7 +47,14 @@ public: m_entries.push_back(new Entry(QStringLiteral("Item %1").arg(i), this)); } } - Q_INVOKABLE QList<Entry*> getEntries() const { return m_entries; } + Q_INVOKABLE QList<Entry *> getEntries() const { return m_entries; } + Q_INVOKABLE QList<Entry *> convertEntries(const QVariantList &entries) const + { + QList<Entry *> converted; + for (const QVariant &entry : entries) + converted.push_back(entry.value<Entry *>()); + return converted; + } private: QList<Entry*> m_entries; diff --git a/tests/auto/qml/qmlcppcodegen/data/sequenceToIterable2.qml b/tests/auto/qml/qmlcppcodegen/data/sequenceToIterable2.qml new file mode 100644 index 0000000000..d92c04c04f --- /dev/null +++ b/tests/auto/qml/qmlcppcodegen/data/sequenceToIterable2.qml @@ -0,0 +1,6 @@ +import QtQml +import TestTypes + +QtObject { + property list<Entry> converted: EntrySource.convertEntries(EntrySource.getEntries()); +} diff --git a/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp b/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp index f805d39929..47523f235c 100644 --- a/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp +++ b/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp @@ -12,6 +12,7 @@ #include <data/objectwithmethod.h> #include <data/qmlusing.h> #include <data/resettable.h> +#include <data/sequenceToIterable.h> #include <data/takenumber.h> #include <data/weathermoduleurl.h> #include <data/withlength.h> @@ -5019,6 +5020,19 @@ void tst_QmlCppCodegen::sequenceToIterable() QVERIFY(match.hasMatch()); QCOMPARE(match.captured(1), QString::number(i)); } + + QQmlComponent component2(&engine, QUrl(u"qrc:/qt/qml/TestTypes/sequenceToIterable2.qml"_s)); + QVERIFY2(!component2.isError(), component.errorString().toUtf8()); + QScopedPointer<QObject> object2(component2.create()); + QVERIFY(!object2.isNull()); + + QQmlListReference converted(object2.data(), "converted"); + QCOMPARE(converted.count(), 10); + for (int i = 0; i < 10; ++i) { + Entry *e = qobject_cast<Entry *>(converted.at(i)); + QVERIFY(e); + QCOMPARE(e->objectName(), QStringLiteral("Item %1").arg(i)); + } } void tst_QmlCppCodegen::setLookupConversion() |
