|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
`VariantAssociationObject` is an object in QV4 that is used to convert
C++ provening `QVarianMap`/`QVariantHash` objects.
As a `ReferenceObject`, `VariantAssociationObject` implements a
read/write-back behavior, allowing the original data that an instance of
it is produced from to remain synchronized with the instance and
viceversa.
Furthermore, elements stored in a `VariantAssociationObject` can
themselves instantiate a read/write-back relationship to subparts of the
`VariantAssociationObject` instance itself.
The infrastructure for read/write backs recognizes subparts/properties
of an object that needs to be read/wrote-back to based on naked integer
indexes.
Thus for an association-like entity we have to generally keep track of a
mapping from those indexes to a property key to ensure that a
read/write-back is performed on the correct element of a
`VariantAssociationObject`.
Currently, this mapping is stored in an heap allocated `std::vector`,
with the heap allocation being required due to triviality constraints on
types that are stored in managed memory, as JS-side types are in QV4.
To avoid the double indirection that an heap allocated `std::vector`
produces, instead allocate on JS managed memory as an `ArrayObject`
which should reduce the level of indirection and is expected to provide
faster access.
Furthermore, previously the mapping was allocated and populated on
instance construction.
In practice, we only need to map keys that are accessed and from
which a derivate `ReferenceObject` providing read/write-back behavior to
an instance of a `VariantAssociationObject` can be created.
Thus, avoid paying the allocation and population cost on object creation
and segregate it to element access, so that is payed on demand when
actually required.
Change-Id: Ica696f43ef96c95c372ac0e2e1eafd0dc16d2f56
Reviewed-by: Ulf Hermann <[email protected]>
|
|
When QML receives something from the C++ side, it, sometimes, tries to
set up a read/"write-back" mechanism to allow changes on the QML side to
be reflected on the C++ side and changes to the original element being
synchronized with the QML side.
This can happen, for example, when accessing a property of a C++ object
that was registered to QML directly from QML.
Similarly, it can do so when nesting some of its internal representation
of an object with C++ provenance.
For example, a `QVariantList` that is passed to the QML side and
converted to a `Sequence` type might require some of its stored element
to perform a write-back when accessed and modified to ensure that
mutations are permanent.
For `QVariantMap` and `QVariantHash` this was currently not implemented,
with `QVariantMap` being generally converted to a Javascript object and
support for `QVariantHash` not necessarily entirely implemented.
This can produce surprising results. For example, a `QVariantMap` that
is stored in a `QVariantList`, where the list is passed over to the QML
side from the C++ side, might incur into its mutations being lost when
accessed as a member of the converted `QVariantList`.
To ensure that this does not happen, `QVariantMap` and `QVariantHash`
will now be converted to a representation that is a `ReferenceObject`,
that is, it uses the general read/write-back mechanism in QML.
Introduce a new QV4 Object, `VariantAssociationObject`, that can store
either a `QVariantMap` or a `QVariantHash` and has read/write-back
behavior.
The prototype for the object is now registered by the engine and can be
accessed through the `variantAssociationPrototype` method.
A `QVariantMap`/`QVariantHash` that is being converted to a JS
representation will now be converted to the newly introduced object
instead of being mapped to a generic JS object.
`variantMapToJS` and `variantToJs` in "qv4egnine.cpp", that were used
during the conversion of `QVariantMap` to a Javascript object were
removed as they are now unused.
Some additional cases were added to support conversion from/to
`QVariantHash` and conversion from the newly added object.
The newly added object supports a small subset of an object
functionality and is not intended, at least currently, to support the
whole breadth of interactions that a Javascript object would.
In particular it aims to support setting properties, retrieving
properties, deleting properties, basic iteration and
`Object.hasOwnProperty`.
It further implements basic read/write-back behavior for those
interactions and allows for recursive read/write-backs through the
general `virtualMetacall` interface.
Additionally, the code `QQmlVMEMetaObject::writeVarProperty` was
modified to ensure that the new reference object is detached when
assigned to a `var` property, so as to be consistent with the general
behavior of the other reference objects.
As a drive-by, a comment in the above code that stated that some of the
code should be adjusted if a new case was added to it was modified to
state that the code should be adjusted with no additional clause, as a
new element was added but the adjustment will not be performed as part
of this patch.
Some general test cases were introduced in `tst_qqmllanguage` for the
new object. In particular to test the most basic interactions of the
above subset of an object interaction, some of the read/write-back
behavior and the behavior of detached when being assigned to a var
property.
Fixes: QTBUG-129972
Change-Id: Ib655ba6001aef07a74ccf235d2e3223b74d7be59
Reviewed-by: Fabian Kosmale <[email protected]>
|