diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index 334148f79c..a2f6565c4a 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -2516,15 +2516,29 @@ bool convertToIterable(QMetaType metaType, void *data, Source *sequence) if (!QMetaType::view(metaType, data, QMetaType::fromType(), &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()) { + 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 c0da4370fc..efd95ce64f 100644 --- a/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt +++ b/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt @@ -285,6 +285,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 getEntries() const { return m_entries; } + Q_INVOKABLE QList getEntries() const { return m_entries; } + Q_INVOKABLE QList convertEntries(const QVariantList &entries) const + { + QList converted; + for (const QVariant &entry : entries) + converted.push_back(entry.value()); + return converted; + } private: QList 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 converted: EntrySource.convertEntries(EntrySource.getEntries()); +} diff --git a/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp b/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp index 406bcb1da8..579f279e93 100644 --- a/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp +++ b/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -5086,6 +5087,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 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(converted.at(i)); + QVERIFY(e); + QCOMPARE(e->objectName(), QStringLiteral("Item %1").arg(i)); + } } void tst_QmlCppCodegen::setLookupConversion()