aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/jsruntime/qv4arrayobject.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>
* Reduce access to uninitialized scoped allocationsLuca Di Sera2025-07-081-12/+12
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | `Scope` provides a mean of performing uninitialized scoped allocations on the JS stack. This can generally be unsafe as this form of allocation temporarily leaves an element representing garbage memory on the JS stack, which could be accessed by other parts of the program. Indeed, a set of bugs related to this kind of behavior was recently solved. Hence, to reduce the surface of those kind of bugs, the usages of uninitialized scoped allocations were reduced to a minimum. The solution to the recent set of bugs related to uninitialized scoped allocations introduced a series of `construct` methods that ensure that the uninitialized allocation and the initialization of the allocated elements are performed as a single step of computation, reducing the surface for incorrect usages of those kind of allocations. The solution was expanded by the introduction of new `construct` methods that cover initialization from other types and some different means of initialization that were used around the code-base to work with uninitialized scoped allocations. Similarly, the various allocation methods in `Scope` were subsumed by the new `construct` methods, with the only remaining means of allocation being the uninitialized one that is used as a building block for the `construct` methods. In particular, `Scope` provided three forms of allocation under the various `alloc` methods. The aforementioned uninitialized allocation and an allocation that performed initialization to either the Undefined or the Empty value. The latter two forms of allocation were converted to forms of `construct`. Since they directly map to the same concept of allocation plus initialization, the conversion avoids having two names for the same concept. More specifically, the form of allocation that initialized to the Undefined value was converted to the new `constructUndefined` which keeps the same behavior. The different naming from the basic `construct` methods is justified by the different interface, which doesn't require choosing a initial value, and the different implementation which is built on the more general `construct` methods rather than the lower level allocation routines. The form of allocation that initialized to the Empty value was removed as it was found to be unused in the code-base. The converted allocation methods generally provides the same interface and behavior with the exception of always requiring the user to specify the amount of allocate objects. This is a change compared to the previous interface which allowed a zero-argument version that allocated a single element. The writer of the patch considered the additional terseness inconsequential compared to the required additional code so that the possibility was not preserved. The code related to the converted allocation forms was removed as a consequence of the conversion. The remaining uninitialized allocation form was made private, to avoid general usage outside of `Scope`, and favoring usages of the substitute `construct` methods. A comment that was related to usages of uninitialized scoped allocations was moved to the lower level `jsAlloca`, which forms the basis for those allocations and creates the abovementioned issues, where it was expanded upon. Usages of the non-uninitialized allocation forms around the code-base were modified to use the new `constructUndefined` method. Most usages of the uninitialized allocation form were modified to use the new `construct` methods that were added to replace them. Exceptions were made for those cases where the initialization routine is either very complex or depends on details that shouldn't belong to `Scope` such that they cannot be trivially encapsulated in a `construct` method. Instead, the relevant function or object was friended by `Scope` to allow accesses to the now private form of allocation. Those usages were previously checked and are supposed to be safe but should be scrutinized if they are modified or the code around them is modified. One of the friended functions, `callDatafromJs`, previously offered a default argument that was not made use of in the code-base. The default value for the argument was removed to simplify friending the function, considering the difficulty the language has with friended function with default arguments and considering that it would have required the default value to be moved out of the function definition into a forward declaration in the unrelated header that defines `Scope`. It is expected that the changes will reduce the surface of usage of uninitialized scoped allocations in favor of a slightly safer approach, make the issue that those usages can produce more apparent and generally centralize the usages as much as possible to make them easier to evaluate and keep track of. Change-Id: I351329f2c139201e0728791df6da297698170f55 Reviewed-by: Ulf Hermann <ulf.hermann@qt.io> Reviewed-by: Sami Shalayel <sami.shalayel@qt.io>
* QtQml: Avoid infinite recursion in Array.joinFabian Kosmale2025-06-271-0/+1
| | | | | | | | | | | | | So far, self-referencing arrays can lead to infinite recursion in Array.join. The standard allows us to throw an exception in this case, just like we already do in ObjectPrototype.toString(). This is not what browsers do, but arguably they are diverging from the spec. Pick-to: 6.10 6.9 6.8 6.5 Fixes: QTBUG-124157 Change-Id: Iac241a90ba7e583e53f52ec635add7b5cf05b200 Reviewed-by: Ulf Hermann <ulf.hermann@qt.io> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* Rework the sort implementation for SequencesLuca Di Sera2024-06-061-3/+56
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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>
* V4: Slim down FunctionObjectUlf Hermann2024-05-141-2/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | Most FunctionObjects do not actually need their custom jsCall members. They will only call the functions from the vtable anyway. FunctionObject can therefore be split into a static and a dynamic variant. Only the dyanmic variant needs to carry (and invoke) the extra pointer. The jsCallWithMetaTypes pointer is completely pointless because none of the dynamic functions actually implement it. Furthermore, the QV4::Function and QV4::ExecutionContext pointers in FunctionObject are only needed by actual JavaScript functions. The builtins that like to be dynamic functions never need them. Therefore, split out another class for this. In the generic FunctionObject, we need the capability to decide at run time whether the function shall be a constructor or not. Add a flag to replace the check for jsCallAsConstructor. Also, where we can, avoid the pessimization of checking whether a function is a constructor before trying to call it as constructor. Rather have the default implementation throw the exception. As a side effect, for most functions we don't need an ExecutionContext anymore. The engine is enough. Task-number: QTBUG-124662 Change-Id: Iac657fa71288dd6ec230a33de2986ba3bcf4628c Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* V4: Eliminate "done" from iteratorsUlf Hermann2023-09-081-7/+4
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Instead of dragging another stack value around to mark if the iterator was done, rather pass it an offset it should jump to if so. It can then jump over any IteratorClose instruction while the ExceptionHandler can still point to the IteratorClose instruction. For this to work, we also have to refrain from checking for exceptions as part of IteratorNext or IteratorClose. If IteratorNext generates an exception, it also jumps to the "done" label, after which we dispatch the exception. We don't want to jump to the exception handler for other instructions in between as that would close the iterator. The iterator should _not_ be closed if it has just thrown an exception, though. The same holds for IteratorClose: If it throws an exception, we don't want to jump back to the beginning of the loop's exception handler, since that would produce an infinite loop. We also don't want to reset the exception handler before IteratorClose because it needs to also be reset if the iterator does not need to be closed. This saves quite a few instructions and stack variables on actual iteration. For destructuring, we have to change the execution flow a bit. We need to first perform the iteration for non-rest parameters, saving the results in separate stack slots. This way we can apply our new "jump if done" behavior if the iterator runs out or produces an exception itself. We then save the "done" state in a separate stack slot, as before. During the assignment of the iteration results to the actual variables, we install an exception handler, so that we can still close the iterator if one of the initializers throws an exception. This produces a few more instructions than before: 1. We need to set and read the "needsClose" variable explicitly rather than having IteratorNext and IteratorDone do it implicitly. 2. We need an additional CheckException after the iteration. 3. We need an additional conditional Jump over the IteratorDone. Everything considered, the savings we get for regular iteration and the more consistent semantics of the instructions involved are well worth the few extra instructions on destructuring, especially since everything those extra instructions do was done implicitly by the iterator instructions before. For consistency, the IteratorNextForYieldStar instruction is refactored to work the same way as IteratorNext: In case of either an exception or "done" it jumps to an offset, and we refrain from individually exception-checking each IteratorNextForYieldStart instruction. Task-number: QTBUG-116725 Change-Id: I9e2ad4319495aecabafdbbd3dd0cbf3c6191f942 Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io> Reviewed-by: Sami Shalayel <sami.shalayel@qt.io>
* Replace CallElement with separate instructionsUlf Hermann2022-11-071-1/+15
| | | | | | | | | | We need to do the subscript lookup before generating the arguments since the arguments may change the array. Fixes: QTBUG-106708 Change-Id: Ia3a0dd34c6ed8d39e86ad20911a632d691826322 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* QtQml: Remove unused includes in qml, first partSemih Yavuz2022-09-141-5/+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: Debugger, Compiler, JsApi, JsRuntime, Memory, Parser Task-number: QTBUG-106473 Change-Id: I01d996a2a2ba31cbbc5f60f5454c8f850298f528 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* Implement array methods for QQmlListPropertyUlf Hermann2022-07-161-16/+23
| | | | | | | | | | | | | | | | | | 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-39/+3
| | | | | | | | | | | | 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>
* Use QV4::Scope::hasException() where applicableUlf Hermann2021-06-301-3/+3
| | | | | | | It is shorter and encapsulates the exception handling a bit. Change-Id: I8e2dc0eb3b930e222b8cb4852b73d99ca18a0379 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* Assert that pointer is non-nullFabian Kosmale2021-03-181-0/+2
| | | | | | | | | | | | ...else the analyser gets confused. mapFn only is true when argc is greater than 2, and the second argument is actually a function. In that case, we know that mapArguments is not null, as we've called scope.alloc. Silences report 0b232fda14. Change-Id: I8d20ad2fcb0b9fcc4a6451e85f61e9a63679ee26 Reviewed-by: Andrei Golubev <andrei.golubev@qt.io> Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
* Merge remote-tracking branch 'origin/5.14' into 5.15Qt Forward Merge Bot2020-01-291-1/+7
|\ | | | | | | | | | | | | Conflicts: src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp Change-Id: I133bfd4bd9dd6f704252c956c90f05e8a8a40d6a
| * V4: Check for exceptions before we use the result of a JS callUlf Hermann2020-01-231-1/+6
| | | | | | | | | | | | | | | | If the call resulted in an exception the return value is undefined. Task-number: QTBUG-81581 Change-Id: Ibfdd5e1229cf5437f270232d3b1a91308adeec72 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
| * ArrayPrototype::method_filter: Check for exception after callbackUlf Hermann2020-01-231-0/+1
| | | | | | | | | | | | | | | | | | If there was an exception we cannot assume the returned value holds anything sensible. Also, we should immediately return. Fixes: QTBUG-81581 Change-Id: I822c204c476e05d6de78124b66ab2f939ca38ffd Reviewed-by: Lars Knoll <lars.knoll@qt.io>
* | Merge remote-tracking branch 'origin/5.14' into 5.15Qt Forward Merge Bot2020-01-091-1/+2
|\| | | | | | | | | | | | | | | | | Conflicts: src/particles/qquickitemparticle.cpp src/qmlmodels/qqmladaptormodel.cpp tests/auto/particles/qquickitemparticle/tst_qquickitemparticle.cpp Change-Id: Ibd8fbb91da6893a09f4ffe61ad0b95d8149bbc87
| * QV4: Array.includes: Support large arraysFabian Kosmale2020-01-071-1/+2
| | | | | | | | | | | | | | | | | | Creating new ScopedValues in the loop was quite wasteful, and would trigger a crash. We now simply reuse the ScopedValue. Fixes: QTBUG-81104 Change-Id: Ie1efd144886861a21c8f6827d7fd23699a1e0dcc Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
* | Clean up ArrayPrototype::method_joinUlf Hermann2019-10-211-37/+35
|/ | | | | | | | | | | | | The code was really convoluted. Calling join() on anything that doesn't look like an array results in an empty string. Everything else can be handled by the same algorithm. While we're at it, clean up IntrinsicTypedArrayPrototype::method_join in the same way. Change-Id: I016cd2fe069d23387797a7e58020d40cdb8d60cc Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
* Split QV4::Value into a static and a dynamic partUlf Hermann2019-05-311-1/+2
| | | | | | | | The static part can be used for compilation and won't resolve managed objects. This allows us to remove all the remaining V4_BOOTSTRAP. Change-Id: Id2f6feb64c48beb2a407697881aea8c0d791a532 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
* Merge remote-tracking branch 'origin/5.13' into devQt Forward Merge Bot2019-03-291-1/+3
|\ | | | | | | Change-Id: I9ba374f0c652628b7c84c36893c32b22529e384f
| * Scope intermediate values when allocating objectsUlf Hermann2019-03-271-1/+3
| | | | | | | | | | | | | | | | | | Otherwise the garbage collector might interfere and we might end up with dangling pointers in random places. Task-number: QTBUG-74190 Change-Id: I253c526ef930b8f0be14e96a42af8b66fda3b22d Reviewed-by: Lars Knoll <lars.knoll@qt.io>
* | V4: Clean up the runtime functions declarationsErik Verbruggen2019-02-051-6/+6
|/ | | | | | | | | | | | | | | | | | | | | | | | | The declarations and usage of runtime functions have seen a number of changes: - we don't use the array of method pointers anymore because we don't use cross-platform AOT JITting - the check if a method can throw a JS exception was invalid, and was not used anymore - value-pointer vs. const-value-ref was inconsistent This patch cleans that up. By fixing the exception checking, we can now use it in the baseline JIT to automatically insert those checks. To make that work correctly, all runtime methods are in a struct, which gets annotated to indicate if that method throws. (The old way of checking which type of engine was used is fragile: some non-throwing methods do not take an engine parameter at all, and those got flagged as throwing). By using a struct, we can also get rid of a bunch of interesting macros. The flags in the struct (as mentioned above) can later be extended to capture more information, e.g. if a method will change the context. Change-Id: I1e0b9ba62a0bf538eb728b4378e2678136e29a64 Reviewed-by: Lars Knoll <lars.knoll@qt.io>
* Ensure our builtin constructors are subclassableLars Knoll2018-11-221-1/+3
| | | | | | | | | Respect the newTarget passed into those constructors and make sure we set up the proto chain correctly. Change-Id: I3d12c7dbef4b33660a6715d73e9fb0f89105167a Fixes: QTBUG-71138 Reviewed-by: Erik Verbruggen <erik.verbruggen@qt.io>
* Get rid of ArrayData::ComplexLars Knoll2018-09-271-1/+1
| | | | | | | It's been pretty much unused. ArrayData::Simple does the job. Change-Id: I0fbd0b7787499244f4c8ca00b3ba7330a6640b75 Reviewed-by: Erik Verbruggen <erik.verbruggen@qt.io>
* Cleanups in Value/PrimitiveLars Knoll2018-09-171-51/+51
| | | | | | | | | | | | Get rid of Primitive and move the corresponding methods directly into Value. Mark many methods in Value as constexpr and turn Value into a POD type again. Keep Primitive as a pure alias to Value for source compatibility of other modules that might be using it. Change-Id: Icb47458947dd3482c8852e95782123ea4346f5ec Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
* Fix remaining test failures for Array.isArrayLars Knoll2018-08-291-3/+5
| | | | | Change-Id: I6258cae2933392c260ce4c4d7f90a2838d91cd51 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
* Implement IsConstructor for Function objectsLars Knoll2018-08-231-13/+3
| | | | | | | | Use the jsConstruct member in the function object for this and set it to a nullptr for methods that are not a constructor. Change-Id: I63d2971b23b2596a8e3b6d2781f0d9ed3208693b Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
* Fix toLocaleString implementations in (Typed)Array.prototypeLars Knoll2018-08-231-3/+30
| | | | | Change-Id: Idcabd68b1651ad3cae315a16cb0e1361cba21253 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
* Implement TypedArray.prototype.copyWithinLars Knoll2018-08-231-1/+1
| | | | | Change-Id: If0d33cc40e79d0609ad205cfe5a08d2266403867 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
* Add support for @@unscopablesLars Knoll2018-07-301-8/+27
| | | | | | | See ES7 spec, chapter 22.1.3.32 Change-Id: Ibe7df71cbc1bc848e205b9ca682f24841adfa2d9 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
* Make Array.prototype.concat comply better with the specLars Knoll2018-07-301-10/+19
| | | | | | | | There are still some failures in the test cases, but at least less than before. Change-Id: I5bad4ddb1e9d6fe120e981f806a6d986fd43b64d Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
* Implement support for new.targetLars Knoll2018-07-031-2/+2
| | | | | | | | | Support the new.target meta property in the codegen, and add support for passing the newtarget into the constructor vtable methods and the execution context. Change-Id: I62ea58e5e92d894035a76e35776203e9837c383b Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
* Prefix vtable methods with virtualLars Knoll2018-07-031-3/+3
| | | | | | | | | Turns out that the overloading of vtable methods and regular ones is problematic in some cases. So let's rather make it explicit which methods are part of the vtable, and which aren't. Change-Id: Ifee32a26104d30f3c82bca8b5a9cdea2d4f4f526 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
* Replace Identifier by PropertyKeyLars Knoll2018-07-021-13/+13
| | | | | | | | Change all uses of Identifier to use the new PropertyKey class and get rid of Identifier. Change-Id: Ib7e83b06a3c923235e145b6e083fe980dc240452 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
* Unify the get and getIndexed vtable functions of QV4::ObjectLars Knoll2018-07-021-29/+29
| | | | | | | | This finalizes the refactoring of Object's vtable API. Also added the receiver argument to the method as required by the ES7 spec. Change-Id: I36f9989211c47458788fe9f7e929862bcfe7b845 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
* Unify put and putIndexedLars Knoll2018-07-021-10/+10
| | | | | | | | | | Pass an Identifier through those virtual methods to unify the string and integer based versions. Also add the receiver that's required in ES7 Change-Id: I4e7f01b4c97cc80bcb3c485f6343f28213dc9e6b Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
* Unify deleteProperty and deleteIndexedProperty vtable methodsLars Knoll2018-06-261-10/+10
| | | | | Change-Id: I25245818c6ff2104642594476cb9684bac824f29 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
* Implement a virtual interface for getOwnPropertyLars Knoll2018-06-251-3/+3
| | | | | | | | | | | | This is required to support Proxy properly, and at the same time fixes a couple of test failures. The new interface also replaces the old query and queryIndexed virtual interfaces, as those where doing a subset of what getOwnProperty does. Change-Id: I750e366b475ce971d6d9edf35fa17b7a2b07f771 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
* Add the start of a Set from ES7Robin Burchell2018-05-301-3/+3
| | | | | | | | | | Based on top of an ArrayObject for now, which is admittedly a bit of a cheat and not matching the "spirit" of the spec. OTOH, that makes it easy to write, and is presumably quite lightweight, so perhaps this is acceptable as a starting point. Change-Id: Ibc98137965b3e75635b960a2f88c251d45e6e837 Reviewed-by: Lars Knoll <lars.knoll@qt.io>
* qv4arrayobject: Implement Array.from from ES7Robin Burchell2018-05-301-15/+167
| | | | | | | | The remaining failures look to be down to the constructor hack, but this gets us a good part of the way there already. Change-Id: I6e57828a56edddd5cb70560b6f50dfc6311c88ae Reviewed-by: Lars Knoll <lars.knoll@qt.io>
* qv4arrayobject: Implement Array.prototype.copyWithin as per ES7Robin Burchell2018-05-301-0/+71
| | | | | | | The remaining two failures are due to Proxy being missing. Change-Id: I6cc5177cd958d98600cc2ba3b1e1a18bc420530c Reviewed-by: Lars Knoll <lars.knoll@qt.io>
* qv4arrayobject: Implement Array.of from ES7Robin Burchell2018-05-271-0/+45
| | | | | | | | | | | | | | | | | | | | | | | One small difficulty: We can't accurately tell whether a thisObject is a constructor or not, so right now we're just swallowing all exceptions and creating an array if they occur. This isn't correct, but it isn't trivial to fix, either: I think we would have to somehow mark our builtins that are constructors, and allow those, but use the array fallback for other builtins, calling user functions and bubbling up if they throw. This is probably good enough for the time being though, as writing something like: function Test() { throw "Foo"; } Array.of.call(Test) ... is probably not very likely, compared to more "usual" use. Change-Id: Ied341a7fa9c3a7fd907e2815c019bc431171ce62 Reviewed-by: Lars Knoll <lars.knoll@qt.io>
* qv4arrayobject: Implement Array.prototype.includes from ES7Robin Burchell2018-05-251-0/+40
| | | | | | | | | | | | | | We also add a sameValueZero helper, to make life easier. Remaining failures: built-ins/Array/prototype/includes/get-prop.js fails (due to missing Proxy) built-ins/Array/prototype/includes/length-boundaries.js fails length-boundaries failure is due to strange treatment of edge number values in Value, I think, I haven't yet been able to rectify that one. Change-Id: Idacca528d88fb052d19a5d244662927f502f20d2 Reviewed-by: Lars Knoll <lars.knoll@qt.io>
* qv4arrayobject: Implement Array.prototype.fill according to ES7Robin Burchell2018-05-251-0/+37
| | | | | | Task-number: QTBUG-56824 Change-Id: Ib12b9fe5ebdd5375f17cf4927eb9b4e292731932 Reviewed-by: Lars Knoll <lars.knoll@qt.io>
* Fix the length property of various functionsLars Knoll2018-05-241-1/+1
| | | | | Change-Id: Ic782c8c9e211db25ac9e51840957db72ac1116fb Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
* Implement Symbol.species getter functionsLars Knoll2018-05-151-0/+7
| | | | | Change-Id: I18b3e382e679f95d7cb53b4ed03be2513ea0204b Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
* Implement support for arguments[Symbol.iterator]Lars Knoll2018-05-021-2/+5
| | | | | Change-Id: Ieb60e2d8f41c38146b588bc8cd225a2a567e0956 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
* Add Array Iterator objects from ES6 (22.1.5)Robin Burchell2018-05-021-0/+42
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | And implement / expose them via: 22.1.3.4 - Array.prototype.entries() 22.1.3.13 - Array.prototype.keys() 22.1.3.29 - Array.prototype.values() 22.1.3.31 - Array.prototype[Symbol.iterator] Most tests for Array iterators now pass. At the same time, expose them on TypedArray's prototype: - 22.2.3.15 %TypedArray%.prototype.keys - 22.2.3.29 %TypedArray%.prototype.values - 22.2.3.6 %TypedArray%.prototype.entries - 22.2.3.31 %TypedArray%.prototype[Symbol.iterator] For TypedArray, test coverage improves a tiny bit (3 passing tests), but the vast majority fail as it seems like the object structure for TypedArray is currently incomplete as far as ES6 expects. It seems that ES6 expects the object structure to be: * %TypedArray% (inherits FunctionObject) (this is the TypedArray intrinsic object, and responsible for initializing the TypedArray instances) * All the TypedArray ctors (e.g. UInt8Array) These inherit %TypedArray%, and make a super call to it to do their work * %TypedArrayPrototype% (inherits Object) (this is the initial prototype for %TypedArray%) * All the ctors have their own separate instance of this * The instances also make use it So, for instance, a lot of the tests attempt to access the prototype like: var proto = Object.getPrototypeOf(Int8Array) var keys = proto.prototype.keys As ES6 expects Int8Array.prototype to be %TypedArray% (22.2.5), this expands to: Object.getPrototypeOf(%TypedArray%) which it expects to be %TypedArrayPrototype%. But since we have no intrinsic object, and the ctors inherit FunctionObject, we instead return the wrong prototype into 'var proto'. Change-Id: I5e1a95a0420ecb70a0e35a5df3f65557510c5925 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
* Fixes when using getLength()Lars Knoll2018-05-021-3/+6
| | | | | | | Do some more bounds checking to avoid crashes. Change-Id: I44e838c3577a9176628aa5e382d712eac9800203 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
* Correctly check length limit in Array.push()Lars Knoll2018-05-021-2/+2
| | | | | | | | getLength() returns a 64 bit value, so check against UINT_MAX instead of checking for an implicit overflow Change-Id: I9ac7f582a85bc696faa42dd10170b9b03b33bcf9 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>