aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/jsruntime/qv4sequenceobject.cpp
Commit message (Collapse)AuthorAgeFilesLines
* CRA review qml/jsruntimeFabian Kosmale2025-09-161-0/+1
| | | | | | | | | | | | | | | | | | This relies heavily on the documented fact that we only support trusted QML/JS content, meaning most files are only significant, not critical. This also extends to the handling of qmlc files (as in compilationunitmapper), as we store them in a user owned, non-shared cache directory – so any vulnerability there would already mean that an attacker has write-priviledges on user data. An exception is ArrayBuffer, which can be used with arbitrary user data, and should create a valid QBA. Fixes: QTBUG-136970 Pick-to: 6.10 6.9 6.8 QUIP: 23 Change-Id: I22033fe6ab4acf8362a8183e25b92331d45cb32c Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
* QtQml: Optimize a few more methods of QV4::SequenceUlf Hermann2025-09-051-5/+143
| | | | | | | push, pop, shift, and unshift should be pretty common. Change-Id: Ia27e29e79d5909f146836bf91499fafbf3f9ce4e Reviewed-by: Sami Shalayel <sami.shalayel@qt.io>
* QtQml: Store detached Sequence objects on the JS heapUlf Hermann2025-09-021-36/+233
| | | | | | | | | | | | | | | | | | | | | While the Sequence is detached it is subject to the GC or unrelated C++ code deleting objects from its internals. Since it's then not the owning object's responsibility to track this anymore, we need to track it ourselves. The way to do it is to use the existing V4 objects. We don't have to store the sequence on the JS heap if it cannot store a QObject. Only lists of variants or pointers are affected. This independently fixes QTBUG-129972 for 6.8 where VariantAssociationObject does not exist, yet. This is because the detached sequence shown in that bug won't need to be written back to anymore in order to stay up to date. Pick-to: 6.10 6.9 6.8 Fixes: QTBUG-129972 Task-number: QTBUG-139025 Change-Id: Ib469c6c65f2f96041e2ad2fd106f8cd60a182e13 Reviewed-by: Sami Shalayel <sami.shalayel@qt.io>
* QtQml: Demote error to warning in Sequence's method_getLengthUlf Hermann2025-09-011-3/+5
| | | | | | | All other qsizetype <-> uint range violations are only warnings. Change-Id: I611e423c115483e3f72b4cc542b3154478c347ca Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
* QtQml: Consistently check isReadOnly in QV4::SequenceUlf Hermann2025-09-011-1/+10
| | | | | | | | | We want generally want to throw an exception. Except in virtualMetaCall, since that would lead to cascading exceptions. There, just return 0 to notify the caller about the metaCall failure. Change-Id: Ie3970d01a5b433100f9722a2f12843abfe8d512a Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
* QtQml: Remove obscure exception checkUlf Hermann2025-09-011-2/+0
| | | | | | | | | | There is no way we can have produced an exception in Sequence::virtualPut(). Change-Id: I1f6f4d933b34b9f86c3a9093929815e9071eb61e Reviewed-by: Luca Di Sera <luca.disera@qt.io> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
* QtQml: Extract method to create the inline storage for SequenceUlf Hermann2025-09-011-9/+19
| | | | | | | | | | | | | | | | We will get a different kind of storage in addition. The unification of the different init() methods uncovers a bug: The storage can indeed be nullptr when querying the size later. If you construct a detached sequence from a null container, there is no reason to create the internal storage. The size is evidently 0 in that case. Fix sizeInline() to tell us as much. Pick-to: 6.10 6.9 6.8 Task-number: QTBUG-129972 Task-number: QTBUG-139025 Change-Id: I33347805fc79f81c69c3191a76ff9167186b43f0 Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
* QtQml: Avoid repeated retrieval of Heap::Sequence::storagePointer()Ulf Hermann2025-09-011-4/+5
| | | | | | | | | | Each of those incurs a null check. Pick-to: 6.10 6.9 6.8 Task-number: QTBUG-129972 Task-number: QTBUG-139025 Change-Id: I7bc96755629d57e1a8f0bf69e0db8de8df737665 Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
* QtQml: Rephrase Sequence's appendInline()Ulf Hermann2025-09-011-12/+9
| | | | | | | | | | | | What we actually want is append default constructed elements. Doing this the natural way avoids needless complication. Pick-to: 6.10 6.9 6.8 Task-number: QTBUG-129972 Task-number: QTBUG-139025 Change-Id: I97318b0e093a76a3d67539ea0d4e28614db4879b Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
* QtQml: Heap::Sequence::isReference() where appropriateUlf Hermann2025-09-011-6/+6
| | | | | | | | | | | | | In order to determine whether we need to write back, conceptually we need to know whether the sequence is a reference. That happens to be the case if there is an object to write back to, but that's not how object() was meant to be used. Pick-to: 6.10 6.9 6.8 Task-number: QTBUG-129972 Task-number: QTBUG-139025 Change-Id: Ie3e0e0318ecabd6f25d545d1198c07a0037b68fe Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
* QtQml: Inline Sequence's shiftInline into its ownly userUlf Hermann2025-09-011-30/+21
| | | | | | | | | | It gets in the way if kept seperate. Pick-to: 6.10 6.9 6.8 Task-number: QTBUG-129972 Task-number: QTBUG-139025 Change-Id: I105ee78e89ce561ec27e8badc27aa94a717ace39 Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
* QtQml: Accept Heap::Sequence in doGetIndexed()Ulf Hermann2025-09-011-8/+6
| | | | | | | | | | It only operates on the heap object anyway. Pick-to: 6.10 6.9 6.8 Task-number: QTBUG-129972 Task-number: QTBUG-139025 Change-Id: I7e6c232fd68893429533e1b10363ef9922a33ae7 Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
* QtQml: Eliminate Heap::Sequence::hasData()Ulf Hermann2025-09-011-3/+4
| | | | | | | | | | We want to encapsulate the container as much as possible. Pick-to: 6.10 6.9 6.8 Task-number: QTBUG-129972 Task-number: QTBUG-139025 Change-Id: I7cf991ea7a3a879584066e7121c49e102ebadf08 Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
* QtQml: Inline Sequence::containerIsEqualTo into its only userUlf Hermann2025-09-011-17/+21
| | | | | | | | | | We don't want to expose it from Sequence's interface. Pick-to: 6.10 6.9 6.8 Task-number: QTBUG-129972 Task-number: QTBUG-139025 Change-Id: Iae144bb8a66a24660dd8da490edb0b4bd7cdc81e Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
* QtQml: Inline containerDeleteIndexedProperty into its only userUlf Hermann2025-09-011-25/+24
| | | | | | | | | | We don't want to expose it from Sequence's interface. Pick-to: 6.10 6.9 6.8 Task-number: QTBUG-129972 Task-number: QTBUG-139025 Change-Id: I35c37ea1da675a83a1a8d3a4af08e4301c8cd60c Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
* QtQml: Inline Sequence::containerPutIndex into its only userUlf Hermann2025-09-011-44/+39
| | | | | | | | | | We don't want to expose it from Sequence's interface. Pick-to: 6.10 6.9 6.8 Task-number: QTBUG-129972 Task-number: QTBUG-139025 Change-Id: I12453fed0143e5e75dfc749b87b197ec328085f7 Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
* QtQml: Inline Sequence::containerGetIndexed() into its only userUlf Hermann2025-09-011-21/+20
| | | | | | | | | | We don't want to expose it from Sequence's interface. Pick-to: 6.10 6.9 6.8 Task-number: QTBUG-129972 Task-number: QTBUG-139025 Change-Id: Ic001925c7fc1ae3be623e2fd7451f99d17899471 Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
* QtQml: Remove some methods from Sequence's public APIUlf Hermann2025-09-011-59/+50
| | | | | | | | | | | | | Inline at() into its only caller, move size() further up to be visible from all callers, and make them all static functions taking a Heap::Sequence. This prevents them from being called from elsewhere and improves encapsulation. Pick-to: 6.10 6.9 6.8 Task-number: QTBUG-129972 Task-number: QTBUG-139025 Change-Id: I65c724119c0df95f2d26116b3ff6ab0a4218d91f Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
* QtQml: Move Sequence's {load|store}Reference into the heap objectUlf Hermann2025-09-011-40/+51
| | | | | | | | | | | It's fine to call them from Sequence and its helper classes, but it shouldn't be called from outside. Pick-to: 6.10 6.9 6.8 Task-number: QTBUG-129972 Task-number: QTBUG-139025 Change-Id: I0bfe5d813ec8fdee6c814269df069935fe304ccd Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
* QtQml: Move Sequence's length accessors into SequencePrototypeUlf Hermann2025-09-011-3/+5
| | | | | | | | | | We will need to befriend them. Pick-to: 6.10 6.9 6.8 Task-number: QTBUG-129972 Task-number: QTBUG-139025 Change-Id: I0d877627f2b838f2bf06a7049cd51927e13bd24d Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
* QtQml: Inline containerOwnPropertyKeys into its only userUlf Hermann2025-09-011-7/+2
| | | | | | | | Pick-to: 6.10 6.9 6.8 Task-number: QTBUG-129972 Task-number: QTBUG-139025 Change-Id: I2062b537c1c00908b7cc86f394d95ffdf2eabbee Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
* QtQml: Factor out Sequence's variant data creationUlf Hermann2025-09-011-10/+10
| | | | | | | | | | We want to use it in other places. Pick-to: 6.10 6.9 6.8 Task-number: QTBUG-129972 Task-number: QTBUG-139025 Change-Id: I720c4a71144ab634d70a1ec0115ca81b8030d083 Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
* QtQml: Refactor QV4::Sequence's raw container operationsUlf Hermann2025-09-011-7/+44
| | | | | | | | | | We want to encapsulate the container as well as possible. Pick-to: 6.10 6.9 6.8 Task-number: QTBUG-129972 Task-number: QTBUG-139025 Change-Id: I87841fbe9a9c9f1756eddc979b82ec8b90eec8e2 Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
* Avoid unnecessary read-backs on ReferenceObjectsLuca Di Sera2025-02-051-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | When certain types are passed over from C++ to QML, QML converts them to a QML usable representation that keeps track of the original data. To do so, the QML representation of the object performs read/write-backs when required to ensure that the representation is kept in sync with the original data, by reading the latest data from the source or writing back changes that are performed on the QML side. Generally, the representation on the QML side cannot know when the original data was modified, so that it has to read the data again each time it accesses the representation to ensure that the latest data is available. The reads can be very expensive. For example, the following snippet: ``` JSON.stringify(foo) ``` Where `foo` is, for example, a `QStringList`, might need to read the data multiple times for each element in the list. For representations that provene from a QObject's property that has a NOTIFY signal, it is possible to cut down on the number of reads by reading only when the data was effectively changed since the last read, that is, the NOTIFY signal of the property was emitted. Similarly, if the property is a BINDABLE, we can subscribe to the BINDABLE itself to track whether a change was performed or not. Thus, to reduce the number of reads when possible, `ReferenceObject`, the base representation for objects that perform read/write-backs, was modified to take into account the NOTIFY signal or BINDABLE status of a property when referencing data that originally provenes from a `QObject`'s property on the C++ side. `QObjectWrapper`, `QQmlTypeWrapper`, `ReferenceObject` and `QMLValueTYpeWrapper` were modified with the usual `Q_MANAGED_TYPE` macro, to allow identifying instances of those objects, which is used to enable the new implementation. The intializer for `ReferenceObject` was modified to behave differently when the referenced data comes from a `QObjectWrapper`, which wraps a `QObject` provening from C++, or a `QQmlTypeWrapper`, which can wrap a `QObject` that is a singleton or an attached property. When it is so, and the part of the wrapped `QObject` that is referenced is a property that has a NOTIFY signal or is a BINDABLE, the `ReferenceObject` instance will now connect to the signal or subscribe to the BINDABLE. A newly added flag, `isDirty`, will be set when the signal is emitted and is used to track whether the data has changed since our last read. `QV4::ReferenceObject::readReference`, the base implementation for read-backs, was modified to take into account the new "isDirty" flag. When the flag is not set, we expect to already have the latest data, and thus do not actually perform the read anymore. Furthermore, the same implementation was modified to take care of setting the `isDirty` flag to a correct state after a read is performed. The connection to the NOTIFY signal is performed through the existing `QQmlNotifier/Endpoint` infrastructure, which allows, between others, to connect to signal emitted by a `QObject`, and should be more performant than a naked connection. Similarly, a BINDABLE is subscribed to by using its usual interface. A new callback was added to be used by `ReferenceObject` to allow setting the `isDirty` flag on the signal emission. `ReferenceObject` will now store a `QQmlNotifierEndpoint` or a `QPropertyNotifier`, that will take care of listening to upstream changes and set the dirty flag as required. A few bug-provening test cases where added to `tst_qqmllanguage` to test that the number of unnecessary reads was indeed reduced. Additional test cases were added to inspect certain aspects of the new implementation to ensure that it works in certain common or edge cases. The internal documentation for `ReferenceObject` was modified to mention this new behavior. Fixes: QTBUG-118847 Fixes: QTBUG-127322 Change-Id: Id62979ae4e03910e1165c293837e5d884727dddc Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
* QtQml: Avoid potential gc issuesFabian Kosmale2024-12-181-1/+4
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | Implicitly constructing a value from a ReturnedValue muddies the responsibility for ensuring that the gc can find the object. With this change, we disable the implicit conversion. The expectation for lifetime management is now: - If a ReturnedValue is stored on the C++ stack, it must be put into a QV4::Scoped class (or there should be a comment why not doing so is safe). Passing a ReturnedValue to a function should no longer be possible, unless the function takes a ReturnedValue, in which case the expectation is that it stores the value in a place where it can be seen by the gc, before doing anything that could trigger a gc run. Using Value::fromReturnedValue can still be used to pass a Value on, but in that case, the expectation is that there is a comment which explains why this is safe. - If a QV4::Value is obtained from a function call, it ought to be stored in a ScopedValue, too. We currently can't enforce this easily, so this should be checked during code review. A possible way forward would be to disallow returning Values, but that would be a larger change, and is deferred to the future. - If a functions has a QV4::Value parameter, it's the callers' responsibilty to ensure that the gc can find it. Pick-to: 6.9 6.8 6.5 Fixes: QTBUG-131961 Change-Id: Iea055589d35a5f1ac36fe376d4389eb81de87961 Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
* Remove unused include from "qv4sequenceobject.cpp"Luca Di Sera2024-11-061-2/+0
| | | | | Change-Id: I65fe010323475b61fc71f20820c3e30c2ab93801 Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
* QtQml: Support conversion to QJSValue when constructing value typesUlf Hermann2024-10-311-1/+1
| | | | | | | | | | Anything can be converted to QJSValue, but QMetaType::convert cannot perform the conversion. Pick-to: 6.8 Fixes: QTBUG-130522 Change-Id: I5614db21a0fcc0afa4a605cbd28ea92788aa146d Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* QML: Allow conversion between different list typesUlf Hermann2024-07-031-40/+125
| | | | | | | | | | | | | 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>
* Rework the sort implementation for SequencesLuca Di Sera2024-06-061-90/+0
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | When QML reads a property with a C++ provenance it sometimes apply certain transformations to work with the property in a JS environment. For example, certain containers, such as `QJsonArray` or `QVariantList`, are converted to a `Sequence`, an array-like object that knows how to modify the container and takes care of reflecting mutations back to the property. `Sequence` provides a specialized implementation for the built-in sort method. Generally, the default sort implementation for an array in JS converts the elements to a string and compares the stringified representation. In the case of `Sequence`, the sort implementation will treats the elements as `QVariant`s and use `QVariant::toString` to perform this part of the sorting algorithm. Due to the way `QVariant::toString` works, this can fail for certain elements. For example, `QVariant::toString` is unaware of how to produce a string from a `QJsonValue`, the type of the elements that compose a `QJsonArray`, thus failing to correctly sort a container with such elements. Other than the `Sequence` implementation, the JS runtime provides, as per specification, a sort method for the Array prototype. Contrary to other methods that are implemented for the prototype, the `sort` method is implemented so that it can only work on values that have a populated `ArrayData`, an optimized storage for certain array and array-like objects. As `Sequences` do not use an `ArrayData` storage for their elements, the method is unable to work on a `Sequence`. To broaden the ability of the sort method implementation for `Sequence` to work more generically, the default sort implementation for the Array prototype sort method was modified to work more generically on objects that do not present an `ArrayData` storage, with an implementation based on the latest draft of the JS specification. The specialized `Sequence` implementation was removed, in favor of `Sequence` delegating to the Array prototype implementation which would now support working with `Sequence`s. While this should be generally slower than the specialized implementation, foregoing some performance, it should allow a more generic foundation for the sort method for `Sequences` or other elements that act like an array but do not use the specialized `ArrayData` representation. Some specialization could later be reapplied to `Sequence` to improve the performances of the implementation. Previously, the Array prototype implementation would directly delegate to `ArrayData::sort`, the sort implementation for the specialized `ArrayData` storage. This was modified to dispatch to an implementation based on generic methods when no `ArrayData` is populated on the object of the sort. The code related to the specialized `Sequence` implementation for sort was removed and the sequence prototype was modified to not present a specialized `sort` property, so as to fallback on the Array prototype one. The `ArrayData::sort` implementation was slightly modified. `ArrayData::sort` would perform a check on the presence of a defined callback for the sorting and throw a type error if the non-undefined element is not callable, as per specification. This check was moved to the Array prototype implementation, to be shared between the specialized `ArrayData::sort` implementation and the generic implementation. As per the spec, the check should be performed as soon as the method is entered and before the receiver of the method is converted to an object. With the check moved to the start of the Array prototype sort implementation this ordering of operations is now fulfilled. The compliance test that checks for this behavior, `comparefn-nonfunction-call-throws`, that was previously failing, will now pass and was thus removed from the list of expected failures for the `ecmascript` tests. A `QEXPECT_FAIL` related to testing the default sort of a `QJsonArray` property was removed from `tst_qqmllanguage`, as the sort is now expected to work correctly. Fixes: QTBUG-125400 Change-Id: I158a9a160b8bdde2b8a06bb349a76469fc25c5a1 Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
* QtQml: Optimize QV4::Sequence's shift() methodUlf Hermann2024-05-281-0/+60
| | | | | | | | Most of the time we have a native shift() operation. Fixes: QTBUG-123882 Change-Id: I1bc50f98f29918a56b5fc70d1644eb99542a3073 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* QtQml: Check for isReference() before trying to write backUlf Hermann2023-09-251-2/+3
| | | | | | | | | | | If we neglect this we get an assert further down the line. Amends commit a824a6f060ec3a0000d7349649a3ab9e0570ecaa. Pick-to: 6.6 6.5 Change-Id: Ib8fd01d329d5b45b27dfe117e168860c6a1d267f Reviewed-by: Semih Yavuz <semih.yavuz@qt.io> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* QML: Silence warnings about converting holes in sparse arraysUlf Hermann2023-09-251-2/+3
| | | | | | | | | | | | | | Holes in sparse arrays are undefined when read via get(). QV4::Sequence does not have holes, by design. Therefore, when converting, we fill the holes with default-constructed values. This is on purpose and should not cause warnings. Furthermore, since QVariant::convert() always produces the given type, we don't need to re-initialize the variant afterwards. Change-Id: I46a675dfb71ae9f66858c97a580ec133aabef10e Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
* QQmlType: Re-organize QQmlTypePrivate to reduce memory usageUlf Hermann2023-07-061-1/+1
| | | | | | | | | | | | The iid is only used for interfaces, and re-ordering the members saves some padding. Also, avoid extra indirection where possible. QUrl is only one pointer to begin with, just like QMetaSequence. We can store them directly in the union. Finally, rename the extraData members so that we can easily recognize them. Change-Id: Ia9c524ea65f8137b264a7dfd9459369c90ce1670 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* QML: Un-specialcase QStringList and QVariantList conversionUlf Hermann2023-06-301-95/+83
| | | | | | | | | | | | | | | | | | Those are just regular sequences these days. They can be written back. Drop some now-dead code and deduplicate the value type conversion code in the process. We should try the (more common) value type conversion before the sequence conversion, but after all the "simple" conversions. [ChangeLog][QtQml][Important Behavior Changes] Converting a QVariantList to a QJSValue via, for example QJSEngine::toScriptValue() does not produce a JavaScript array anymore, but rather a better suited sequence object that behaves almost like a JavaScript array. The only difference is that its QJSValue::isArray() will return false now. Fixes: QTBUG-113690 Change-Id: Ib176c34d59c45a6b5cff68d029c4b1b87d7aa192 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* QV4: Sequence/ListWrapper: implement virtualGetLengthFabian Kosmale2023-03-311-0/+8
| | | | | | | | | Both types can provide a natural implementation for virtualGetLength, which is much more efficient than going through the base implementation in QV4::Object. Change-Id: Iefc870451e1ad54c6dbfd6f73f6a5ff9b7552871 Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
* Avoid duplicate value type creationUlf Hermann2023-02-241-4/+4
| | | | | | | | | | | We can actually produce an uninitialized but pre-allocated QVariant using QVariant::Private. Using the new in-place construction support in QMetaObject, we can minimize the amount of copying necessary for value types. Fixes: QTBUG-108789 Change-Id: I6b748794a6adbf6558e1e3086eab80fcfb3154a0 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* Recursively write back value types and sequencesUlf Hermann2022-10-191-83/+131
| | | | | | | | | | | | | | | | | Both types have functionality to write themselves back to the properties they were loaded from on change, but so far we could not nest those writes. [ChangeLog][QtQml] You can now assign to properties of nested value types and to elements of containers from QML functions. You cannot, however, take references of such values and elements. This is in contrast to non-nested value types and the containers themselves. However, passing references of value types and containers around generally leads to very confusing effects. Don't do this. Fixes: QTBUG-99766 Change-Id: I74cb89e5c3d733b0b61e42969d617b2ecc1562f4 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* QML: Track statement locations in sequence and value typesUlf Hermann2022-10-141-4/+7
| | | | | | | | | | | With this in place we can enforce that reference objects we add in the future can only be written back in the same statement as they were created. Task-number: QTBUG-99766 Change-Id: I1c74bd239caa1bb5febd1a3705d8ee29a8fc4249 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
* V4: Refactor QQmlValueType{Wrapper|Reference} and QV4::SequenceUlf Hermann2022-10-131-77/+99
| | | | | | | | | | | | | Every QQmlValueTypeWrapper is potentially a reference now. Since most were already before, the overhead of checking the vtables at every step was dubious at best. Extract a common base class that handles the reading and writing of object properties employed in both value type references and sequences. Task-number: QTBUG-99766 Change-Id: Idf72d9a20a52366e5c2d0dcd4b3a18072c0ccc41 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* QML: Drop the "succeeded" out parameters from SequencePrototypeUlf Hermann2022-10-071-16/+7
| | | | | | | | | The success of the operation is visible from the return value in all cases. Change-Id: I93177785f76b8078ddd8eeb7d77143993fe80739 Reviewed-by: Semih Yavuz <semih.yavuz@qt.io> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* Allow more options for creating value types from JS objectsUlf Hermann2022-09-241-6/+14
| | | | | | | | | | | | | | | | | | | | We allow value types to be created 1. by calling Q_INVOKABLE constructors 2. by setting their values from properties of a JS object Both have to be opted into by setting a class info. If opted into, these options override the existing methods. When a a type can be created by setting its properties, that implies you can also initialize it using an invokable constructor. However, when given a JS object, the properties method is used. We keep this internal and undocumented for now. As the last try (the create(QJSValue) methods and QJSValue ctors) was not that stellar, let's first wait a bit and see if we're getting it right this time around. Fixes: QTBUG-106480 Change-Id: I767230924afcba032d501846cc3263dad57b7bf0 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* V4: Make ExecutionEngine::toVariant() staticUlf Hermann2022-09-201-2/+2
| | | | | | | | | Wherever we need an engine in there, we also have a managed value to get it from. This relieves us from the requirement to drag an engine around wherever we want to call toVariant(). Change-Id: Ib95d02b5fbf5eaa494214e337c9b700e97e5e0df Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* QtQml: Remove unused includes in qml, final partSemih Yavuz2022-09-141-2/+0
| | | | | | | | | | | | | | Drop unnecessary includes detected by clangd-iwyu. Add new includes due to the transitive includes. Also, some of the includes were detected as unused even if they were actually in use. In those cases, use angular brackets instead of "" which deceives the tool not to complain. Affected subfolders: JsRuntime, Qml Fixes: QTBUG-106473 Change-Id: I483da15d42a8e3ce6cd3b654909665fff3075d6b Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* Fix array-like methods on V4 sequencesUlf Hermann2022-07-191-91/+101
| | | | | | | | | | | | | We need to properly convert value type lists on assignment and we need to add the "length" property to the own properties. Furthermore, the V4 sequence methods were confused about integer type ranges. We teach them about qsizetype, properly range check everything, and drop the artificial limitation to INT_MAX. Pick-to: 6.4 Task-number: QTBUG-82443 Change-Id: Ie5af1130c9e78e412c171e6fa26a28a6a7a5d498 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* Implement array methods for QQmlListPropertyUlf Hermann2022-07-161-2/+2
| | | | | | | | | | | | | | | | | | The test revealed that the fill() method of JS arrays did not properly range-check its parameters. Fix that, too. [ChangeLog][QtQml][Important Behavior Changes] QQmlListProperty behaves like a JavaScript Array now. You can use map(), reduce(), forEach() etc on it. This also includes a slight change of behavior to the push() method. push() now returns the new list length, and it checks the length to not exceed UINT_MAX. Task-number: QTBUG-58831 Fixes: QTBUG-49613 Fixes: QTBUG-99041 Change-Id: Ia64d73fb704449c280fbbc7ddcf20f4698c82e09 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> Reviewed-by: Sami Shalayel <sami.shalayel@qt.io>
* Use SPDX license identifiersLucie Gérard2022-06-111-38/+2
| | | | | | | | | | | | Replace the current license disclaimer in files by a SPDX-License-Identifier. Files that have to be modified by hand are modified. License files are organized under LICENSES directory. Pick-to: 6.4 Task-number: QTBUG-67283 Change-Id: I63563bbeb6f60f89d2c99660400dca7fab78a294 Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
* Allow retrieval of sequences from QJSValueUlf Hermann2022-06-021-403/+373
| | | | | | | | | | | | | | As we can store sequence types in QJSValue, we should be able to retrieve them, too. Move the declaration of the QV4::Sequence struct into a header to make it less of a hassle to identify sequences. Change-Id: I3e45bfe193c669107f90cd6c502765c0c9f60fb0 Reviewed-by: Andrei Golubev <andrei.golubev@qt.io> Reviewed-by: Sami Shalayel <sami.shalayel@qt.io> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
* Qml: includemocsMarc Mutz2022-04-291-0/+2
| | | | | | | | | | | | Including moc files directly into their classes' TU tends to improve codegen and enables extended compiler warnings, e.g. about unused private functions or fields. Pick-to: 6.3 6.2 5.15 Task-number: QTBUG-102948 Change-Id: Ie39c60a19ba562affe6bd52ba68b38db95298cf3 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
* QML: Clean up sequence registrations for value typesUlf Hermann2022-02-111-12/+29
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | We want to be able to construct a meaningful list type by surrounding the internal name of the type with QList<>. Usually this works because of the way we auto-register sequential containers for types. Only for the builtins we need to do some special casing. That special casing should happen in the builtins, not in QtQml, though. The generic QList<foo> sequence type is implicitly given for any value type foo these days. There is no need to mention it in .qmltypes. QtQml retains some extra container declarations that are not straight QList<foo> for a value type foo. Everything that's registered by the value type registration anyway is dropped. We keep the aliases QStringList and QVariantList in the builtins because they are really common. Since we now register QVariantList the way it's mandated by the builtins, we also have to handle it correctly in qv4sequenceobject.cpp. In particular, we need to append variants as-is rather than poking into them. As QStringList is an additional builtin now, we need to teach the type resolver about it. Change-Id: I0dfb5b780b27250f36f6886bc4e0926a03c114b4 Reviewed-by: Andrei Golubev <andrei.golubev@qt.io> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
* QML: Allow named lists of value typesUlf Hermann2022-01-281-35/+52
| | | | | | | | | | | | | | | | | | | | | | | | We register QList<T> as sequential container type for any value type T we get. This way we can always find a type to use for list<t> with t being a value type. The metatypes are shuffled around so that we have an easier time associating a type with its list and vice versa. As QQmlPropertyData's isQList flag denotes both QQmlListProperty<T> and QList<T> now, we need to use QMetaType::IsQmlList more often. Conversely, any name given to extra sequential containers registered via QML_SEQUENTIAL_CONTAINER is explicitly ignored now. As you can do list<foo> for any type foo now, there is not much of a point in having further named container registrations for the same type. It would just make things more complicated. Mind that the name had already been ignored before, just not explicitly. [ChangeLog][QtQml] You can now use lists of value types in QML. For example a property of type list<int> will hold a list of integers. Task-number: QTBUG-82443 Change-Id: I7bee61cee3963dae5d231bf59f70b8012984371d Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>