aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/jsruntime/qv4engine.cpp
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2024-06-26 09:33:38 +0200
committerUlf Hermann <ulf.hermann@qt.io>2024-07-03 16:36:49 +0200
commitf2431370ad075a71b940dbd03eb3fa34f46b2405 (patch)
tree0601ae8a165c8af751a014f982e73d259a34fe6c /src/qml/jsruntime/qv4engine.cpp
parentb666cda75c38f421e35f3755c8c12a0a6a932347 (diff)
QML: Allow conversion between different list types
We universally allow this pretty much everywhere else. We should also allow it when evaluating bindings. To facilitate this, generalize the SequencePrototype::toVariant() method so that it works with any array-like and faithfully coerces the elements by the type coercion rules. Pick-to: 6.8 Fixes: QTBUG-126398 Change-Id: I520cd40e5f74bee5ac4b418aa86dc043774efcbe Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'src/qml/jsruntime/qv4engine.cpp')
-rw-r--r--src/qml/jsruntime/qv4engine.cpp61
1 files changed, 10 insertions, 51 deletions
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp
index 6754c3c887..cd1a4e033c 100644
--- a/src/qml/jsruntime/qv4engine.cpp
+++ b/src/qml/jsruntime/qv4engine.cpp
@@ -1537,6 +1537,16 @@ static QVariant toVariant(const QV4::Value &value, QMetaType metaType, JSToQVari
} else if (QV4::QmlListWrapper *l = object->as<QV4::QmlListWrapper>()) {
return l->toVariant();
} else if (QV4::Sequence *s = object->as<QV4::Sequence>()) {
+ if (metaType.isValid()
+ && metaType != QMetaType::fromType<QVariant>()
+ && metaType != s->d()->listType()) {
+ // If we can, produce an accurate result.
+ const QVariant result = QV4::SequencePrototype::toVariant(value, metaType);
+ if (result.isValid())
+ return result;
+ }
+
+ // Otherwise produce the "natural" type of the sequence.
return QV4::SequencePrototype::toVariant(s);
}
}
@@ -1565,57 +1575,6 @@ static QVariant toVariant(const QV4::Value &value, QMetaType metaType, JSToQVari
QVariant retn = QV4::SequencePrototype::toVariant(value, metaType);
if (retn.isValid())
return retn;
-
- if (metaType.isValid()) {
- retn = QVariant(metaType, nullptr);
- auto retnAsIterable = retn.value<QSequentialIterable>();
- if (retnAsIterable.metaContainer().canAddValue()) {
- QMetaType valueMetaType = retnAsIterable.metaContainer().valueMetaType();
- auto const length = a->getLength();
- QV4::ScopedValue arrayValue(scope);
- for (qint64 i = 0; i < length; ++i) {
- arrayValue = a->get(i);
- QVariant asVariant = QQmlValueTypeProvider::createValueType(
- arrayValue, valueMetaType);
- if (asVariant.isValid()) {
- retnAsIterable.metaContainer().addValue(retn.data(), asVariant.constData());
- continue;
- }
-
- if (QMetaType::canConvert(QMetaType::fromType<QJSValue>(), valueMetaType)) {
- // before attempting a conversion from the concrete types,
- // check if there exists a conversion from QJSValue -> out type
- // prefer that one for compatibility reasons
- asVariant = QVariant::fromValue(QJSValuePrivate::fromReturnedValue(
- arrayValue->asReturnedValue()));
- if (asVariant.convert(valueMetaType)) {
- retnAsIterable.metaContainer().addValue(retn.data(), asVariant.constData());
- continue;
- }
- }
-
- asVariant = toVariant(arrayValue, valueMetaType, JSToQVariantConversionBehavior::Never, visitedObjects);
- if (valueMetaType == QMetaType::fromType<QVariant>()) {
- retnAsIterable.metaContainer().addValue(retn.data(), &asVariant);
- } else {
- auto originalType = asVariant.metaType();
- bool couldConvert = asVariant.convert(valueMetaType);
- if (!couldConvert && originalType.isValid()) {
- // If the original type was void, we're converting a "hole" in a sparse
- // array. There is no point in warning about that.
- qWarning().noquote()
- << QLatin1String("Could not convert array value "
- "at position %1 from %2 to %3")
- .arg(QString::number(i),
- QString::fromUtf8(originalType.name()),
- QString::fromUtf8(valueMetaType.name()));
- }
- retnAsIterable.metaContainer().addValue(retn.data(), asVariant.constData());
- }
- }
- return retn;
- }
- }
}
if (value.isUndefined())