aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/jsruntime/qv4runtime.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-3/+3
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | `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>
* Avoid accessing garbage memory on the js stackLuca Di Sera2025-07-031-3/+3
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | When allocating an object on the JS heap the garbage collector might be run as part of the allocation, in particular as a way to possibly make space when the memory space is starting to get filled up. When the garbage collector runs, it is possible, as part of its normal processing, that it will access the JS stack, and try to interact with the objects that are stored on it. In particular, while collecting from the JS stack, the garbage collector will need to mark all Managed objects that are found on it. When allocating on the JS stack it is possible that the allocation and the initialization of the allocated memory are performed in separate steps. When this is so, it is possible for the allocated element on the stack to represent garbage memory in between being allocated and being initialized. Since the garbage collector can inspect all elements on the stack as part of its processing, it is possible for it to inspect an element that represents garbage memory if it runs in between the allocation and initialization of that stack element. Furthermore, since each allocation might run the garbage collector, then any allocation in between the allocation and initialization of such a stack element can access garbage memory. In particular, if the garbage memory represents a pointer to a previously existing Managed object that was swept, the garbage collector might try to mark an object that shouldn't be marked. There are a few cases of this currently in the code-base. While instantiating a QML file, `QQmlObjectCreator` keeps track of objects that are created in the process, to avoid premature collection. As part of this, `ObjectInCreationGCAnchoList::trackObject` will be called, in turn allocating on an element on the js stack and then initializing it separately by the creation of `QObjectWrapper`. The creation of a `QObjectWrapper` generally allocates, such that it can incur into the above problem. As part of dealing with the JS spread operator, in particular when processing the spread element, we juggle with multiple allocation of uninitialized elements on the js stack. During this processing multiple part of the code can allocate. For example, the spread element is handled through the use of an iterator that, during its creation, might allocate as during the creation process we might convert the spread argument to object so that the iterator can deal with it, which would be the case for a spread argument that is a string. When allocating an element on the js stack that is bound to a certain scope, we sometime allow a conversion to be performed on the original element. This conversion routine might allocate, and it does do so for the currently existing conversion to a String and to an Object. The conversion routine is called after an uninitialized element is pushed on the stack, and can thus incur into the above issue. To fix the issue, an additional method was added, `construct`, that ensures that allocation and initialization happen sequentially with no allocation in-between, using an initialization value that is passed as an argument. The new method was applied to the code affected by the bug, in practice, reordering the operations in the affected cases such that the bug-producing allocations happens before the allocation on the stack such as to avoid the bug while keeping the same semantics. An exception was taken for the handling of the spread argument, which has a more complex control flow, where the solution that was used is to initialize the memory to the empty value as part of the allocation. A series of test cases showing an example of the issues were added to `tst_qv4mm`. The tests make use of the fact that we assert when we find a Managed object on the js stack that is not in use, as that is a logical error for the garbage collector, to observe the issue and are thus skipped when assertions are not enabled. Change-Id: Id478e16ee22e20e77d01fdfae9a0269d6d709892 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>
* Engine: Keep script context aliveFabian Kosmale2024-11-011-2/+21
| | | | | | | | | | | | | | | | | | | | A closure might need to access the imported scripts, which live in the context. The closure might however live longer than than the context is valid, and so far, the lookup would have failed. Solve that issue by not completely discarding the reference to the script, but instead downgrading it to a weak reference. Additionally, closurse will keep a reference to the scripts as an invalid property, so that the gc will keep them alive. The ignoreMessage call in importedScriptsAccessOnObjectWithInvalidContext is removed, as we keep the script value alive. Pick-to: 6.8 Fixes: QTBUG-130575 Change-Id: Ieb3044c419271473a9fc9afcf9e88ab4b3f4b88a Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
* QtQml: Call lookups based on enums rather than via function pointersUlf Hermann2024-10-241-8/+8
| | | | | | | | | | | | | | | | | While the C++ standard says that different functions need to have unique addresses, some compilers have take substantial liberties with that rule. This means we can't actually rely on the addresses of our different lookup functions to differ and therefore we cannot use them as discriminator. Introduce an enumeration for all the different lookups and use that instead. Now we can also drop all the purely redirecting methods we've introduced just to have different addresses. Change-Id: Ifa68c27c0d2fef4084893a19227dab21bd948dfd Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* JIT: storeLocal needs to go through WriteBarrierFabian Kosmale2024-06-181-0/+17
| | | | | | | | | | | | | | The interpreter already has the necessary setup, but the JIT did simply write the value without marking so far. We fix this by adding a new runtime function call, which simply uses QV4::WriteBarrier::markCustom to mark the given value. Both the StoreLocal and StoreScopedLocal bytecode instructions are handled by adding the code to BaselineAssembler::storeLocal. Pick-to: 6.8 Change-Id: I4b9226848bff029a076c0cfa6daf899ca9b84622 Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
* QtQml: Straighten out some logging categoriesUlf Hermann2024-06-171-1/+1
| | | | | | | | | | | Either make them static or declare them in a header. We want them to be static wherever possible, in order to reduce the number of visible symbols. If they can't be static, however, they should at least be declared in only one place. Task-number: QTBUG-67692 Change-Id: I91fa641b46510ea8902b478d31dfd60d34b5f580 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* QtQml: Restore as-casting of incompatible type to value typeUlf Hermann2024-05-281-1/+18
| | | | | | | | | | This used to (mistakenly) return null, which is much better than constructing the value type. Amends commit 71e259837967f1eee50c057229094c2a971a1a61. Change-Id: I3da9d0a765d118dc8d85d7c5dde91936855bbf67 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* QML: Deprecate coercion on type assertionsUlf Hermann2024-05-241-3/+19
| | | | | | | | | | | | | | | | | | | By using an "as" cast you want to check the type of the value, not coerce it. Previously, however, if you did this with a value type, it would create the value type instead of just checking for it. Add an attribute "Assertable" to the ValueTypeBehavior pragma that prevents this and enables the correct behavior. Also print a warning when coercing as part of an as-cast. [ChangeLog][QtQml] A new attribute "Assertable" has been added to the "ValueTypeBehavior" pragma. You should always use it if you want to type-check value types using "as". If you don't use it, an instance of the type is created as result of the "as" if the type doesn't match. Task-number: QTBUG-124662 Change-Id: I1d5a6ca0a6f97d7d48440330bed1f9f6472198aa Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* V4: Move FunctionObject flags into VTableUlf Hermann2024-05-141-1/+1
| | | | | | | | | | | | | | | | | | | These are really rather generic type traits that shouldn't be stored in individual objects. Moving them away slims down FunctionObject even more. FunctionObject doesn't add any extra overhead on top of Object anymore. You also cannot easily cast an object that doesn't implement any call methods to FunctionObject anymore. Therefore, we can derive from FunctionObject even if we only need to implement call methods in a further derived class. The fact that ProxyObject is not a FunctionObject but its derivatives are is already tested as part of the ecmascript test suite. Task-number: QTBUG-124662 Change-Id: I5632de8c54ac1d6a4b15c4926c655b87b475db49 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* V4: Slim down FunctionObjectUlf Hermann2024-05-141-9/+12
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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>
* QtQml: Re-allow manual calling of signal handlersUlf Hermann2024-02-131-3/+10
| | | | | | | | | | | | | | | The fact that you could do this was due to a mistake in the implementation of QQmlPropertyCache. The cache entry for the signal handler looked like the signal itself. Make it possible to call QmlSignalHandler objects, and output a categorized warning when doing so. Also, align the call code between the interpreter and the JIT. Pick-to: 6.7 Fixes: QTBUG-120573 Change-Id: Ic76d37f587d21b68c55d77a08ac2d30950bec133 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> Reviewed-by: Yifan Zhu <fanzhuyifan@gmail.com> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
* String: optimize integer conversionFabian Kosmale2024-01-181-1/+1
| | | | | | | | | If we want to append an integer to a string, there is no need to run the complete floating point formatting machinery specified by ECMAScript. Instead, simply use QString::number. Change-Id: Iea0421cc908239e75b34de2181a345a32416a803 Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
* V4: Eliminate "done" from iteratorsUlf Hermann2023-09-081-15/+17
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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>
* V4: Use memmove() for tail callsUlf Hermann2023-07-241-1/+1
| | | | | | | | | | If you have many arguments, the argument ranges can overlap. In that case memcpy is UB. Pick-to: 6.2 6.5 6.6 Fixes: QTBUG-115320 Change-Id: I54dd4d7762e7278502954b8ac2cb4af1197ce88c Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* QML: Use new coerce() method also for 'as' castsUlf Hermann2023-06-261-6/+2
| | | | | | | | | | Casting via QVariant is unreliable and inefficient. toVariant() is not required to produce the type we are requesting. Amends commit 05f56d7c78754855c643470ad4e8dfd35c96f927. Change-Id: Idabcac7420155649692ec589d637dd9ee3016716 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* Move ScopedStackFrame into qv4stackframe_p.hUlf Hermann2023-05-171-25/+27
| | | | | | | | | | | This is where it belongs. We need to apply some tricks to avoid cyclic includes, but that's better than what we have so far. Also, sort and clean up the includes in the affected files. Change-Id: Ia7a957d06c0ca284045d831417740c3f9920bc92 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
* QML: Allow as-casting to value typesUlf Hermann2023-03-031-7/+29
| | | | | | | | | | | | | | | | | | | | | | If the "Addressable" option to ValueTypeBehavior is set, you can use the "as" operator to cast a previously unknown type into either undefined or the given type. We can use this in qmlcachegen to generate efficient code for further operations on the same type. In the generated C++ it in fact only works for GetLookup because: a, We generally don't do SetLookup on value types, yet. b, We generally don't call methods on value types, yet. c, We cannot store a union of undefined and a sequence type, yet. However, getting properties of value types is the most important application of the new casts so this is well worth it. As a side effect we can also look up things in potentially undefined results of other operations now. For example list lookups. Task-number: QTBUG-94807 Change-Id: Ifdf34f1f3f67b7a0a8953b9ed0e947b74638a28c Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* QJSEngine: Fix potential JS stack overflow cauased by spread operatorFabian Kosmale2023-01-191-0/+5
| | | | | | | | | | | | createSpreadArguments could in theory allocate a (nearly) unbounded number of QV4::Values. Avoid this by checking whether we approach jsStackTop. This fixes CVE-2022-43591. Pick-to: 6.5 6.4 6.2 5.15 Change-Id: I01aecb979da47b7261688c9f185dc33a50a579a5 Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
* Change value encoding scheme to make space for larger pointersUlf Hermann2023-01-121-30/+36
| | | | | | | | | | | | | | | | | | On android and on some other platforms, the upper bits of a pointer are significant. We need to store them in our JS value encoding. Shift the bits around to make this happen. We now can store pointers of up to 57 bits. That's enough for everything we've seen so far. Fixes: QTBUG-101686 Fixes: QTBUG-91150 Pick-to: 6.5 Change-Id: I72e0fe63b27fca94840f82963e4d3936b3581b28 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> Reviewed-by: Sami Shalayel <sami.shalayel@qt.io> Reviewed-by: Ville Voutilainen <ville.voutilainen@qt.io>
* Replace CallElement with separate instructionsUlf Hermann2022-11-071-19/+0
| | | | | | | | | | 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>
* Port from container::count() and length() to size() - V5Marc Mutz2022-10-131-3/+3
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This is a semantic patch using ClangTidyTransformator as in qtbase/df9d882d41b741fef7c5beeddb0abe9d904443d8, but extended to handle typedefs and accesses through pointers, too: const std::string o = "object"; auto hasTypeIgnoringPointer = [](auto type) { return anyOf(hasType(type), hasType(pointsTo(type))); }; auto derivedFromAnyOfClasses = [&](ArrayRef<StringRef> classes) { auto exprOfDeclaredType = [&](auto decl) { return expr(hasTypeIgnoringPointer(hasUnqualifiedDesugaredType(recordType(hasDeclaration(decl))))).bind(o); }; return exprOfDeclaredType(cxxRecordDecl(isSameOrDerivedFrom(hasAnyName(classes)))); }; auto renameMethod = [&] (ArrayRef<StringRef> classes, StringRef from, StringRef to) { return makeRule(cxxMemberCallExpr(on(derivedFromAnyOfClasses(classes)), callee(cxxMethodDecl(hasName(from), parameterCountIs(0)))), changeTo(cat(access(o, cat(to)), "()")), cat("use '", to, "' instead of '", from, "'")); }; renameMethod(<classes>, "count", "size"); renameMethod(<classes>, "length", "size"); except that on() was replaced with a matcher that doesn't ignoreParens(). a.k.a qt-port-to-std-compatible-api V5 with config Scope: 'Container'. Change-Id: I58e1b41b91c34d2e860dbb5847b3752edbfc6fc9 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
* Port from qAsConst() to std::as_const()Marc Mutz2022-10-071-1/+1
| | | | | | | | | | | | | | We've been requiring C++17 since Qt 6.0, and our qAsConst use finally starts to bother us (QTBUG-99313), so time to port away from it now. Since qAsConst has exactly the same semantics as std::as_const (down to rvalue treatment, constexpr'ness and noexcept'ness), there's really nothing more to it than a global search-and-replace. Task-number: QTBUG-99313 Change-Id: I601bf70f020f511019ed28731ba53b14b765dbf0 Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
* Port from container::count() and length() to size()Marc Mutz2022-10-071-2/+2
| | | | | | | | | | | | | | | | | | | | This is a semantic patch using ClangTidyTransformator as in qtbase/df9d882d41b741fef7c5beeddb0abe9d904443d8: auto QtContainerClass = anyOf( expr(hasType(cxxRecordDecl(isSameOrDerivedFrom(hasAnyName(classes))))).bind(o), expr(hasType(namedDecl(hasAnyName(<classes>)))).bind(o)); makeRule(cxxMemberCallExpr(on(QtContainerClass), callee(cxxMethodDecl(hasAnyName({"count", "length"), parameterCountIs(0))))), changeTo(cat(access(o, cat("size"), "()"))), cat("use 'size()' instead of 'count()/length()'")) a.k.a qt-port-to-std-compatible-api with config Scope: 'Container', with the extended set of container classes recognized. Change-Id: Idb1f75dfe2323bd1d9e8b4d58d54f1b4b80c7ed7 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* V4: Use an enum to categorize functions and rename aotFunctionUlf Hermann2022-09-291-1/+1
| | | | | | | | We want to use the aotFunction member also for typed JavaScript functions. Change-Id: Iad6d12ebed3ad3069832484137ed8e4d9e7a7cf4 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* QtQml: Remove unused includes in qml, final partSemih Yavuz2022-09-141-5/+1
| | | | | | | | | | | | | | 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>
* V4: Fix exponentiation operatorUlf Hermann2022-08-031-3/+1
| | | | | | | | | | We need to use the same algorithm as for Math.pow(...). Since we have jsExponentiate() now, we can use it in all those places. The strange AIX special case is definitely not useful anymore. Task-number: QTBUG-105188 Change-Id: I43a251c71f1b547ad36855ac197080bfea8c94e3 Reviewed-by: Fabian Kosmale <fabian.kosmale@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>
* Add "As" function to symbol tableUlf Hermann2021-09-061-0/+1
| | | | | | | Fixes: QTBUG-96099 Pick-to: 6.2 Change-Id: I0bc50c0a66759c36dc50b2d6ef8e16be8fbba45c Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* Use ExecutionEngine::currentContext() where applicableUlf Hermann2021-06-301-2/+2
| | | | | Change-Id: I7e83819d4551ffc9125e5bf376ae6bc620a11d2b Reviewed-by: Fabian Kosmale <fabian.kosmale@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>
* Replace "fall through" comments with Q_FALLTHROUGHThiago Macieira2021-06-221-1/+1
| | | | | | | | Noted by GCC 11. Looks like it doesn't see the "fall through" comment (only "fallthrough"). Change-Id: I7246c3e7bb894e0d9521fffd168af15da21a2c93 Reviewed-by: Paul Wicking <paul.wicking@qt.io>
* Eliminate JS call frame from metatypes callsUlf Hermann2021-06-101-33/+94
| | | | | | | | If we call an AOT-compiled function we never need the JavaScript call frame. We can just skip its setup and save some overhead. Change-Id: I39dc2ca6eea5b5a66f3b87b642a310534cecf6cd Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* Evaluate type assertions in QMLUlf Hermann2021-05-261-0/+14
| | | | | | | | | | | | | | | | | | Type assertions actually check whether the expression matches the type, and return null if it doesn't. [ChangeLog][QtQml] You can use TypeScript-like type assertions using "as" now. In contrast to TypeScript, QML's type assertions are enforced at runtime. If the type doesn't match, null is returned for object types. Also, type assertions can only cast to object types. There is no way to create a value type or primitive type reference. As value types and primitives cannot be polymorphic, this doesn't matter, though. There are other ways of converting those. Task-number: QTBUG-93662 Change-Id: I00fce3d4ea7a8c6b4631c580eaf6c113ac485813 Reviewed-by: Cristian Maureira-Fredes <cristian.maureira-fredes@qt.io> Reviewed-by: Paul Wicking <paul.wicking@qt.io>
* Optimize stack frame setup for AOT compiled functionsUlf Hermann2021-03-231-11/+16
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | When called via the metaobject system, parameters and return values are passed as void*, with accompanying type information in the form of QMetaType. The same format is expected when calling an AOT compiled function. Previously, we would first convert all the parameters to QV4::Value, just to convert them back the moment we notice that there is an AOT compiled function. This is wasteful. This change provides a second call infrastructure that accepts void* and QMetaType as parameter and return value format, and passes them as-is all the way to any AOT compiled functions. If there is no AOT compiled function, the conversion is done when detecting this, rather than when initiating the call. This also passes the information "ignore return value" all the way down to the actual function call. If the caller is not interested in the return value, we don't have to marshal it back at all. For now, we only add the extra "callWithMetaTypes" vtable entry to ArrowFunction. However, other callables could also receive variants optimized for calling with void*/int rather than V4 values. This required changing the way how function arguments are stored in the property cache. We squeeze the return type into QQmlPropertyCacheMethodArguments now, and we use QMetaType instead of integers. In turn, we remove some unused bits. Change-Id: I946e603e623d9d985c54d3a15f6f4b7c7b7d8c60 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* Clean up JSCallData setupUlf Hermann2021-03-171-2/+2
| | | | | | | | | | | | | | | | | We either have pre-populated arguments and thisObject, then we can just use them and keep them const. Or, we want to allocate and populate the arguments and the thisObject. Then, do allocate them in a separate object, and transform that into JSCallData afterwards if necessary. Furthermore, avoid alloc(0) as that just returns the current stack top. Writing to it will clobber other data. Rather, just use nullptr and crash if it's written to. Also, remove the useless operator-> from JSCallData. That one just confuses the reader. Change-Id: I8310911fcfe005b05a07b78fcb3791d991a0c2ce Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* Don't store the scope in JSCallDataUlf Hermann2021-03-171-2/+2
| | | | | | | | | | | We only need it when generating CallData, or when filling in any thisObject or arguments that weren't provided. Provide a constructor that expects thisObject and arguments to be pre-allocated and one that allocates them in a scope passed as argument. Change-Id: Iddfba63f4dbc5b09e2b33fb22a94eea88f515902 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> Reviewed-by: Andrei Golubev <andrei.golubev@qt.io>
* Port QtDeclarative from QStringRef to QStringViewKarsten Heimrich2020-06-161-1/+1
| | | | | | | | Task-number: QTBUG-84319 Change-Id: I2dcfb8a2db98282c7a1acdad1e6f4f949f26df15 Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io> Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io> Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
* Merge remote-tracking branch 'origin/5.14' into 5.15Qt Forward Merge Bot2020-01-291-12/+23
|\ | | | | | | | | | | | | 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-12/+23
| | | | | | | | | | | | | | | | 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>
* | Merge remote-tracking branch 'origin/5.14' into 5.15Liang Qi2019-11-221-0/+9
|\| | | | | | | | | | | | | | | Conflicts: src/qml/qml/qqmlextensionplugin.cpp tests/auto/quick/qquicktableview/tst_qquicktableview.cpp Change-Id: Ic58d36a8532015bae30f2690063db9829b3bf372
| * RuntimeHelpers: Short-circuit stringToNumber on huge stringsUlf Hermann2019-11-071-0/+9
| | | | | | | | | | | | | | | | | | We don't need to iterate such a monster, or even convert it to latin1. It won't be a valid number anyway. Fixes: QTBUG-78955 Change-Id: Iaa35d924511885f804abe2d5c74235adcad55b27 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
* | JSRuntime: Provide an optional symbol tableUlf Hermann2019-10-161-0/+127
|/ | | | | | | | | | The method names are only used for debugging purposes. We don't need to pass them through production code. Centralize the names of all the runtime methods in a symbol table and only look them up when actually printing them. Change-Id: I0d9d7db04b961841242acdbaaa7a2ba29b1f4ff2 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
* Use quiet NaNs instead of signalling onesEdward Welbourne2019-09-041-1/+1
| | | | | | | | | | | I see no good reason why the NaN returned when reading "nan" as a double should be a signalling one; a quiet one should be just fine. [ChangeLog][ES][] The NaN obtained by Math.pow(+/-1, +/-infinity) and (+/-1)**(+/-infinity) is now quiet rather than signalling. Change-Id: I6b5ea469c17c028328c803f54f2a6d4422a80033 Reviewed-by: Lars Knoll <lars.knoll@qt.io>
* Split qqmltypeloader{_p.h|.cpp} into a several filesUlf Hermann2019-07-111-0/+1
| | | | | | | No one can read this mess. Change-Id: Icec4f2afc466435c1ae5e4e80fa2c1b5baf7d087 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
* Split QV4::Value into a static and a dynamic partUlf Hermann2019-05-311-74/+15
| | | | | | | | 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>
* Split CompiledData::CompilationUnit in twoUlf Hermann2019-05-161-18/+32
| | | | | | | | We need a CompilationUnit that only holds the data needed for compilation and another one that is executable by the runtime. Change-Id: I704d859ba028576a18460f5e3a59f210f64535d3 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
* Don't include qv4enginebase_p.h in qmldevtoolsUlf Hermann2019-05-101-1/+7
| | | | | | | | We don't need it and we don't need to check for V4_BOOTSTRAP in there. Shuffle some includes around to provide everything we do need. Change-Id: I3e75f1c6f9dc518006aabc9dcee21e5153899ac5 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
* Move compileModule() into qv4codegen.cppUlf Hermann2019-05-081-1/+3
| | | | | | | | | This is a better fit for the method. In turn, remove all the V4_BOOTSTRAP conditions from qv4engine_p.h and make sure we don't include or compile it in bootstrap mode. Change-Id: I5933b0724e561313ca20c420b83e4d70e63bddf5 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>