diff options
author | Ulf Hermann <ulf.hermann@qt.io> | 2020-03-04 16:46:42 +0100 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2020-03-18 16:35:02 +0100 |
commit | 748411fa64412db1650e04ee7b4405b8fbc53d42 (patch) | |
tree | a3c94175c04a8465cb602d4d4deb557a37c1923d /src/qmlmodels | |
parent | 7230005ef66f22a7ee3addff95b1e8d9060dc5a1 (diff) |
Store a QV4::ReturnedValue in QJSValue
Being careful, we can now save primitive values inline. We use the heap
pointer of QV4::Value as either QString* or QV4::Value* for complex
types. We cannot store persistent managed QV4::Value without the double
indirection as those need to be allocated in a special place.
The generic QVariant case is not supported anymore. The only place where
it was actually needed were the stream operators for QJSValue. Those
were fundamentally broken:
* A managed QJSValue saved and loaded from a stream was converted to a
QVariant-type QJSValue
* QVariant-type QJSValues were not callable, could not be objects or
arrays, or any of the special types.
* Cyclic references were forcibly broken when saving to a data stream.
In general the support for saving and loading of managed types to/from
a data stream was so abysmally bad that we don't lose much by dropping
it.
[ChangeLog][QML][Important Behavior Changes] When saving a QJSValue to a
QDataStream only primitive values or strings will be retained. Support
for objects and arrays was incomplete and unreliable already before. It
cannot work correctly as we don't necessarily have a JavaScript heap
when loading a QJSValue from a stream. Therefore, we don't have a proper
place to keep any managed values. Using QVariant to keep them instead is
a bad idea because QVariant cannot represent everything a QJSValue can
contain.
Fixes: QTBUG-75174
Change-Id: I75697670639bca8d4b1668763d7020c4cf871bda
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'src/qmlmodels')
-rw-r--r-- | src/qmlmodels/qqmldelegatemodel.cpp | 9 | ||||
-rw-r--r-- | src/qmlmodels/qqmllistmodel.cpp | 13 |
2 files changed, 13 insertions, 9 deletions
diff --git a/src/qmlmodels/qqmldelegatemodel.cpp b/src/qmlmodels/qqmldelegatemodel.cpp index 095b66b379..08c91d172e 100644 --- a/src/qmlmodels/qqmldelegatemodel.cpp +++ b/src/qmlmodels/qqmldelegatemodel.cpp @@ -48,6 +48,7 @@ #include <private/qqmlchangeset_p.h> #include <private/qqmlengine_p.h> #include <private/qqmlcomponent_p.h> +#include <private/qjsvalue_p.h> #include <private/qv4value_p.h> #include <private/qv4functionobject_p.h> @@ -2656,8 +2657,10 @@ void QQmlDelegateModelGroupPrivate::emitChanges(QV4::ExecutionEngine *v4) { Q_Q(QQmlDelegateModelGroup); if (isChangedConnected() && !changeSet.isEmpty()) { - emit q->changed(QJSValue(v4, engineData(v4)->array(v4, changeSet.removes())), - QJSValue(v4, engineData(v4)->array(v4, changeSet.inserts()))); + emit q->changed(QJSValuePrivate::fromReturnedValue( + engineData(v4)->array(v4, changeSet.removes())), + QJSValuePrivate::fromReturnedValue( + engineData(v4)->array(v4, changeSet.inserts()))); } if (changeSet.difference() != 0) emit q->countChanged(); @@ -2874,7 +2877,7 @@ QJSValue QQmlDelegateModelGroup::get(int index) QV4::ScopedObject p(scope, model->m_cacheMetaType->modelItemProto.value()); o->setPrototypeOf(p); - return QJSValue(v4, o->asReturnedValue()); + return QJSValuePrivate::fromReturnedValue(o->asReturnedValue()); } bool QQmlDelegateModelGroupPrivate::parseIndex(const QV4::Value &value, int *index, Compositor::Group *group) const diff --git a/src/qmlmodels/qqmllistmodel.cpp b/src/qmlmodels/qqmllistmodel.cpp index e58fc19178..0d45d03fa6 100644 --- a/src/qmlmodels/qqmllistmodel.cpp +++ b/src/qmlmodels/qqmllistmodel.cpp @@ -589,7 +589,7 @@ void ListModel::set(int elementIndex, QV4::Object *object, QVector<int> *roles) const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::Function); QV4::ScopedFunctionObject func(scope, f); QJSValue jsv; - QJSValuePrivate::setValue(&jsv, v4, func); + QJSValuePrivate::setValue(&jsv, func); roleIndex = e->setFunctionProperty(r, jsv); } else if (QV4::Object *o = propertyValue->as<QV4::Object>()) { if (QV4::QObjectWrapper *wrapper = o->as<QV4::QObjectWrapper>()) { @@ -1434,7 +1434,7 @@ int ListElement::setJsProperty(const ListLayout::Role &role, const QV4::Value &d } else if (d.as<QV4::FunctionObject>()) { QV4::ScopedFunctionObject f(scope, d); QJSValue jsv; - QJSValuePrivate::setValue(&jsv, eng, f); + QJSValuePrivate::setValue(&jsv, f); roleIndex = setFunctionProperty(role, jsv); } else if (d.isObject()) { QV4::ScopedObject o(scope, d); @@ -1638,7 +1638,8 @@ PropertyKey ModelObjectOwnPropertyKeyIterator::next(const Object *o, Property *p auto size = recursiveListModel->count(); auto array = ScopedArrayObject{scope, v4->newArrayObject(size)}; for (auto i = 0; i < size; i++) { - array->arrayPut(i, QJSValuePrivate::convertedToValue(v4, recursiveListModel->get(i))); + array->arrayPut(i, QJSValuePrivate::convertToReturnedValue( + v4, recursiveListModel->get(i))); } pd->value = array; } else { @@ -2570,7 +2571,7 @@ QJSValue QQmlListModel::get(int index) const } } - return QJSValue(engine(), result->asReturnedValue()); + return QJSValuePrivate::fromReturnedValue(result->asReturnedValue()); } /*! @@ -2592,7 +2593,7 @@ QJSValue QQmlListModel::get(int index) const void QQmlListModel::set(int index, const QJSValue &value) { QV4::Scope scope(engine()); - QV4::ScopedObject object(scope, QJSValuePrivate::getValue(&value)); + QV4::ScopedObject object(scope, QJSValuePrivate::asReturnedValue(&value)); if (!object) { qmlWarning(this) << tr("set: value is not an object"); @@ -2791,7 +2792,7 @@ bool QQmlListModelParser::applyProperty( if (v4->hasException) v4->catchException(); else - QJSValuePrivate::setValue(&v, v4, result->asReturnedValue()); + QJSValuePrivate::setValue(&v, result->asReturnedValue()); value.setValue<QJSValue>(v); } else { QByteArray script = scriptStr.toUtf8(); |