aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2025-09-03 13:47:48 +0200
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2025-09-12 03:27:53 +0000
commit2561c5221af158ed3edfefd29759623ddc470f03 (patch)
tree9aa12e9c60deb11c3de72dfb01b51bf4b410c1ec
parent793efe73beedc53737fa30c9c8cbea3fe61c8361 (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.cpp20
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt1
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/sequenceToIterable.h9
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/sequenceToIterable2.qml6
-rw-r--r--tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp14
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()