diff options
| author | Ulf Hermann <ulf.hermann@qt.io> | 2023-07-26 14:12:26 +0200 |
|---|---|---|
| committer | Ulf Hermann <ulf.hermann@qt.io> | 2023-07-27 14:42:00 +0200 |
| commit | afe96c4d633146df477012975824b8ab65034239 (patch) | |
| tree | 3ffc0c716de580236b173d93079ca27f5e308064 /src/qml/jsruntime/qv4engine.cpp | |
| parent | 3d74e9120583ff911fba97b21b008cf29fcbe3f7 (diff) | |
QML: Do convert objects with prototypes to QVariantMap
While we shouldn't convert to QVariantMap if only QVariant is requested,
we should convert if QVariantMap is explicitly requested. QVariant can
hold QJSValue which is a better fit for objects with properties.
QVariantMap cannot hold QJSValue. A best effort conversion is still
better than an empty map.
Amends commit 47678c682f168eb6d5020383ea75fe1700e8c4f6.
Pick-to: 6.6 6.5
Fixes: QTBUG-115523
Change-Id: Iaa96809ee411dc0db95311c641c4e3f1f51a6026
Reviewed-by: Amanda Hamblin-Trué <amanda.hamblin-true@qt.io>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'src/qml/jsruntime/qv4engine.cpp')
| -rw-r--r-- | src/qml/jsruntime/qv4engine.cpp | 43 |
1 files changed, 25 insertions, 18 deletions
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index f73d881885..087dce5295 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -1688,6 +1688,26 @@ QVariant ExecutionEngine::toVariant( return ::toVariant(value, typeHint, createJSValueForObjectsAndSymbols, nullptr); } +static QVariantMap objectToVariantMap(const QV4::Object *o, V4ObjectSet *visitedObjects) +{ + QVariantMap map; + QV4::Scope scope(o->engine()); + QV4::ObjectIterator it(scope, o, QV4::ObjectIterator::EnumerableOnly); + QV4::ScopedValue name(scope); + QV4::ScopedValue val(scope); + while (1) { + name = it.nextPropertyNameAsString(val); + if (name->isNull()) + break; + + QString key = name->toQStringNoThrow(); + map.insert(key, ::toVariant( + val, /*type hint*/ QMetaType {}, + /*createJSValueForObjectsAndSymbols*/false, visitedObjects)); + } + return map; +} + static QVariant objectToVariant(const QV4::Object *o, V4ObjectSet *visitedObjects) { Q_ASSERT(o); @@ -1722,23 +1742,7 @@ static QVariant objectToVariant(const QV4::Object *o, V4ObjectSet *visitedObject result = list; } else if (o->getPrototypeOf() == o->engine()->objectPrototype()->d()) { - QVariantMap map; - QV4::Scope scope(o->engine()); - QV4::ObjectIterator it(scope, o, QV4::ObjectIterator::EnumerableOnly); - QV4::ScopedValue name(scope); - QV4::ScopedValue val(scope); - while (1) { - name = it.nextPropertyNameAsString(val); - if (name->isNull()) - break; - - QString key = name->toQStringNoThrow(); - map.insert(key, ::toVariant( - val, /*type hint*/ QMetaType {}, - /*createJSValueForObjectsAndSymbols*/false, visitedObjects)); - } - - result = map; + result = objectToVariantMap(o, visitedObjects); } else { // If it's not a plain object, we can only save it as QJSValue. result = QVariant::fromValue(QJSValuePrivate::fromReturnedValue(o->asReturnedValue())); @@ -1961,7 +1965,10 @@ ReturnedValue ExecutionEngine::fromVariant( QVariantMap ExecutionEngine::variantMapFromJS(const Object *o) { - return objectToVariant(o).toMap(); + Q_ASSERT(o); + V4ObjectSet visitedObjects; + visitedObjects.insert(o->d()); + return objectToVariantMap(o, &visitedObjects); } // Converts a QVariantMap to JS. |
