aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/jsruntime/qv4engine.cpp
Commit message (Collapse)AuthorAgeFilesLines
* QtQml: Fill in the const iterator functions in the empty sequenceUlf Hermann7 days1-0/+11
| | | | | | | | | | Without these you may get an infinite sequence when trying to iterate using const iterators. Pick-to: 6.10 6.8 Task-number: QTBUG-142097 Change-Id: Iae93063b240ebe9426804197533ed7efd8e007bc Reviewed-by: Sami Shalayel <sami.shalayel@qt.io>
* Doc: Fix QDoc warnings for internal classes and functionsJerome Pasion2025-11-071-0/+5
| | | | | | | | | | -Mark internal functions with \internal -Sometimes the solution is to have a \class command and marked internal -Fixed whitespace issues when the new marking introduced them Task-number: QTBUG-141665 Change-Id: I4f744aa94ca679da74b6c5e846e49a73346e2625 Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
* QtQml: Don't delete the Qt object when clearing singletonsUlf Hermann2025-11-051-1/+12
| | | | | | | | | | | | | | | | | We need the object not only as singleton but also as member of the global object. If there is a QJSEngine, parent it to the engine and make it explicitly C++-owned. This way clearSingletons() won't delete it. If there is no QJSEngine, there can't be any clearSingletons(). Therefore we're safe in that case. The only known example for an ExecutionEngine without a QJSEngine is the WorkerScript case, but since ExecutionEngine is exported, it could be instantiated on its own in other Qt modules. Amends commit 9dc7a22b212c18215942b9a4bfa17bd16dd5151b. Pick-to: 6.10 6.8 Task-number: QTBUG-95788 Change-Id: I5a0aa35fadd552af208538ab2715efaff77f8f4e Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* Set default stack size safety margin for VxWorksKarim Pinter2025-10-211-6/+10
| | | | | | | | | | | | | The default safety margin for VxWorks is 1/8 of the stack size, which is read from the OS. Also adds environment variable QV4_STACK_SOFT_LIMIT, to overwrite V4 stack safety margin. These can be used to finetune the application with limited resources, also on other OSes. Task-number: QTBUG-115777 Change-Id: I82b5b02e75fae3f5d1971504d16a3dc0f1d5f3fd Pick-to: 6.8 6.9 6.10 Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
* 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>
* Fix build with V4_USE_VALGRIND definedAndreas Hartmetz2025-09-141-1/+1
| | | | | Change-Id: I3f3a58771d2721dc822add922c16a7efab3024ab Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
* QtQml: Avoid double-wrapping when converting to QVariantListUlf Hermann2025-09-111-3/+17
| | | | | | | | | Amends commit 1b89c1edcae68351632c2755e5408410c2ff98e3 Fixes: QTBUG-139764 Pick-to: 6.10 6.9 6.8 Change-Id: I1488527a235d74fc0352c72b9bfb69589c2f3d93 Reviewed-by: Sami Shalayel <sami.shalayel@qt.io>
* QtQml: Store detached VariantAssociation objects on the JS heapUlf Hermann2025-08-211-2/+0
| | | | | | | | | | | | While the VariantAssociation 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. Pick-to: 6.10 6.9 Task-number: QTBUG-139025 Change-Id: Ic1d5aa85171b5d91c2b9d546963268b6f09c2802 Reviewed-by: Sami Shalayel <sami.shalayel@qt.io>
* QtQml: Add method to generate a QVariantHash from a JS objectUlf Hermann2025-08-161-7/+19
| | | | | | | | | | This generalizes the QVariantMap code path. Pick-to: 6.10 6.9 6.8 Task-number: QTBUG-139025 Change-Id: Ibbdc1da974d3c166474c4bd02fb4c70d8df3e688 Reviewed-by: Semih Yavuz <semih.yavuz@qt.io> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* Expose XMLHttpRequest to qmltypesFabian Kosmale2025-07-221-2/+9
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | In QML, one can use XMLHttpRequest. Not so with a plain JS engine. The reason for that lies in the fact that a JS engine did not have any network access, because all network functionality was in the type loader, and the type loader was coupled to the QV4::Engine. This has changed in d2bc4a4330254c0c68a0ade51b59a71c4b67b470, but we stil don't expose XMLHttpRequest to a plain QJSEngine. Nevertheless, it conceptually lives in the global object, and we need to collect information about it to enable code completion and linting. Consequently, expose a function in QV4::Engine, which allows us to manually trigger the registration, and call it in qmljsrootgen. Going forward, we should arguably have a QJSEngine::Extension for XMLHttpReuqest, after which we could remove the hack. Note that as before, qmljsrootgen prints a few warnings, because we call functions in contexts in which they must not be called. As before, we ignore this for now. As a side-effect, this adds a few more entries to the qmltypes file for new entries on the global Qt object. Task-number: QTBUG-137075 Pick-to: 6.10 Change-Id: I21e9d62bf075e8d4356db8f357502feb927717e7 Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
* QtQml: Move ExecutionEngine in to QJSEnginePrivateUlf Hermann2025-06-241-0/+2
| | | | | | | | | | | | | | The ExecutionEngine can live without a QQmlEngine or a QJSEngine, but not vice versa. Therefore, the ExecutionEngine has to outlive QQmlEngine and QJSEngine on shutdown. Since the ExecutionEngine lives longer now, we also need to postpone the pruning of the type registry. The engine might still hold on to types after all. Task-number: QTBUG-137848 Change-Id: Ib574cac84b5f2d974cbc24ed79550a58b69a7a1c Reviewed-by: Sami Shalayel <sami.shalayel@qt.io>
* QtQml: Remove local file loading from qv4engine.cppUlf Hermann2025-06-181-108/+46
| | | | | | | | | | Scripts (including modules) shall be loaded via QQmlTypeLoader, to preserve network transparency. Since the last users of loadModule() and friends have been removed, we can now drop the relevant code. Task-number: QTBUG-19407 Change-Id: I8d5aa177266d376fb77f5b61f94ab1277b4c64c4 Reviewed-by: Sami Shalayel <sami.shalayel@qt.io>
* QtQml: Avoid direct file access in ECMAScript test runnerUlf Hermann2025-06-171-1/+4
| | | | | | | | | | | | | | | | | | We want the type loader to do this job rather than poorly duplicate it in the test. In particular, the local implementation didn't properly register the dependencies of loaded ECMAScript modules. So far we could only load ECMAScript modules using the type loader if their file names ended it ".mjs". The ECMAScript test suite does not follow this convention. In order to deal with that, we need to add a second characteristic. ECMAScript modules can now also be marked using a URL fragment "#module". Furthermore, since JavaScript files loaded outside any QML document get full access to the global context, we introduce another URL fragment "#global" to discern them from the same files loaded from a QML document. Change-Id: I625088335d16d5b8eeaa2673f07718367dca1605 Reviewed-by: Sami Shalayel <sami.shalayel@qt.io>
* QtQml: Register all ECMAScript module requests as dependenciesUlf Hermann2025-06-171-10/+41
| | | | | | | | | | | | | | Without this, freeUnusedTypesAndCaches() could drop dependencies of a live ECMAScript module. This would be unfortunate. Since ECMAScript modules can form cycles, we now need to clear the dependent scripts separately before clearing the compilation units. The downside of this is that actually cyclic ECMAScript modules cannot be cleared at all without clearing the whole type registry. However, this situation should be rare. Change-Id: Ib2d523f7c291bb5c472b6603bd947c3977b77b85 Reviewed-by: Sami Shalayel <sami.shalayel@qt.io>
* QtQml: Hold QQmlTypeLoader in QV4::ExecutionEngineUlf Hermann2025-06-171-14/+17
| | | | | | | | | | | ... rather than QQmlEngine. This paves the way for having the type loader attached to ExecutionEngine rather than QQmlEngine. Also, reference the execution engine in the type loader, in turn. Task-number: QTBUG-19407 Change-Id: I04e571c5c6ac5bce5e82537cb96c6940c7186f3a Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* QtQml: Move URL normalization to QQmlMetaTypeUlf Hermann2025-06-121-2/+2
| | | | | | | | We need it in many places and it's better to have it next to equalBaseUrls(). Also, it can be inline there. Change-Id: Ie83ad7a345a25a67f418c6cf9886ba8116f7a762 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* QtQml: Do not crash when registering native modules on QQmlEngineUlf Hermann2025-06-121-2/+3
| | | | | | | | | | | | We need to tell the type loader that this is an ECMAScript module since it cannot determine it from the file name. Amends commit dc60c305a20d518012d4f034c4fa2a7395ebf31f Pick-to: 6.10 6.9 6.8 Change-Id: Ie91bce86a08a81ff3df6c11d016308e3e380f15f Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> Reviewed-by: Sami Shalayel <sami.shalayel@qt.io>
* QJSEngine: Trim compilation units after evaluating a programOlivier De Cannière2025-03-121-0/+11
| | | | | | | | | | | | | | | Not doing so might lead them to accumulate until the js engine is destroyed. We only trim compilation units with the final url that was passed in to evaluate. This way, we prevent accumulation while also preserving compilation units from actual files. Fixes: QTBUG-132931 Pick-to: 6.9 6.8 Change-Id: Ie4f09287e293075de4940ced6146a862c4da3b5b Reviewed-by: Ulf Hermann <ulf.hermann@qt.io> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* QtQml: Store script CUs in QQmlMetaTypeDataUlf Hermann2025-02-061-0/+2
| | | | | | | | | | | | | | | | | | | | | | | When importing a JavaScript module again from the same QML engine, the resulting executable compilation unit should be the same as before. This only works if we use the same base compilation unit. However, so far QQmlScriptBlob did not store the compilation unit in the central type registry. Therefore, it could not be found when importing the module again. This broke when we transitioned away from storing JavaScript modules in a separate data structure and instead started treating them like any other compilation units. In order to fix this, generate synthetic QQmlType and QMetaType instances also for JavaScript compilation units and store them in the relevant data structures. This makes it possible to locate them when we need them. Pick-to: 6.9 6.8 Fixes: QTBUG-133053 Change-Id: I0425cd70a3745e793fec03105f58b708726ede06 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* QtQml: Add conversion code for QQmlListProperty to other listsUlf Hermann2025-01-241-1/+11
| | | | | | | | | | | We have the same conversion code already for lists of value types and JavaScript arrays. Specialize the common cases of QObjectList and QQmlListProperty<QObject>. Pick-to: 6.9 6.8 Fixes: QTBUG-133047 Change-Id: I10826d4a965e18471a486e19befef961ec9a4a6e Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
* QtQml: Avoid potential gc issuesFabian Kosmale2024-12-181-5/+14
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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>
* QtQml: Generalize the global/illegal namesUlf Hermann2024-12-171-13/+20
| | | | | | | | | Instead of passing them around everywhere, use the ones we statically know and only validate them when creating a new engine. Task-number: QTBUG-131721 Change-Id: I7fb93d15eb6e4194c46249727bcf7a48f5dce730 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* QtQml: Initialize ExecutionEngine members inline where possibleUlf Hermann2024-12-121-7/+0
| | | | | Change-Id: Ie343db2be7d3bdd15e5967f14f810bea03831923 Reviewed-by: Sami Shalayel <sami.shalayel@qt.io>
* QtQml: Add some consistency to QV4::RegExpUlf Hermann2024-12-121-0/+4
| | | | | | | | | | | | | | | | | | | | | | | | | | | | The RegExp JIT should behave the same as the V4 JIT. In particular, it should honor the same JIT call threshold and not second guess any manually set thresholds. To do this we need to store the match count in 32 bits. In turn we can store the 5 flags we may have in 8 bits. To make this safe, pass typed flags to the initialization functions. Also, consider the flags when calculating hash values. Finally, in the init() function, we don't need to initialize members to zero, since that is already guaranteed by the memory manager. And we can delete the flagsAsString() method since it's unused. This requires shuffling some #includes into the places where they actually belong. [ChangeLog][QtQml] The JavaScript regular expression engine now honors QV4_JIT_CALL_THRESHOLD for its own JIT. If QV4_JIT_CALL_THRESHOLD is not set, it uses the JIT after 3 interpreted matches for any regular expression, rather than the previous 5. Matching a regular expression on a string longer than 1024 bytes counts as 3 matches. This is to retain the default behavior of JIT'ing regular expressions right away when encountering long strings. Task-number: QTBUG-131957 Change-Id: I269ccea55d34b191ef18d7cd5fccd4cad8aec7cd Reviewed-by: Sami Shalayel <sami.shalayel@qt.io> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* QtQml: Model native modules as compilation unitsUlf Hermann2024-12-061-40/+75
| | | | | | | | | | | | | | | | | | | | | | | QQmlTypeLoader::injectedScript() was unsafe and impossible to fix because it had to query the engine from the type loader thread in order to find out whether to load a script from an actual file. By removing the whole special-casing of native modules, we can make the script loading thread safe. A native module is now also a compilation unit, with a regular QV4::Module as value. This means we can remove a lot of code that deals with the native modules in the engine. The downside is that native modules are now a lot larger than before. However, given that they don't appear in any examples and hardly any bugs have been filed about native modules since their introduction, we can assume that they are not a very popular feature. The reduction in complexity and the removal of the native modules map in the engine is expected to outweigh the extra memory overhead for native modules. Task-number: QTBUG-131721 Pick-to: 6.8 Change-Id: Ia7388d7ba8d71637559a791d874257fba4646330 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* QtQml: Clean up headers in qv4engine.cppUlf Hermann2024-12-041-78/+77
| | | | | Change-Id: Ie483d851938e23614a7ae996b044066756f9f304 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* Implement read/write-backs for QVariantMap and QVariantHashLuca Di Sera2024-12-011-29/+19
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | When QML receives something from the C++ side, it, sometimes, tries to set up a read/"write-back" mechanism to allow changes on the QML side to be reflected on the C++ side and changes to the original element being synchronized with the QML side. This can happen, for example, when accessing a property of a C++ object that was registered to QML directly from QML. Similarly, it can do so when nesting some of its internal representation of an object with C++ provenance. For example, a `QVariantList` that is passed to the QML side and converted to a `Sequence` type might require some of its stored element to perform a write-back when accessed and modified to ensure that mutations are permanent. For `QVariantMap` and `QVariantHash` this was currently not implemented, with `QVariantMap` being generally converted to a Javascript object and support for `QVariantHash` not necessarily entirely implemented. This can produce surprising results. For example, a `QVariantMap` that is stored in a `QVariantList`, where the list is passed over to the QML side from the C++ side, might incur into its mutations being lost when accessed as a member of the converted `QVariantList`. To ensure that this does not happen, `QVariantMap` and `QVariantHash` will now be converted to a representation that is a `ReferenceObject`, that is, it uses the general read/write-back mechanism in QML. Introduce a new QV4 Object, `VariantAssociationObject`, that can store either a `QVariantMap` or a `QVariantHash` and has read/write-back behavior. The prototype for the object is now registered by the engine and can be accessed through the `variantAssociationPrototype` method. A `QVariantMap`/`QVariantHash` that is being converted to a JS representation will now be converted to the newly introduced object instead of being mapped to a generic JS object. `variantMapToJS` and `variantToJs` in "qv4egnine.cpp", that were used during the conversion of `QVariantMap` to a Javascript object were removed as they are now unused. Some additional cases were added to support conversion from/to `QVariantHash` and conversion from the newly added object. The newly added object supports a small subset of an object functionality and is not intended, at least currently, to support the whole breadth of interactions that a Javascript object would. In particular it aims to support setting properties, retrieving properties, deleting properties, basic iteration and `Object.hasOwnProperty`. It further implements basic read/write-back behavior for those interactions and allows for recursive read/write-backs through the general `virtualMetacall` interface. Additionally, the code `QQmlVMEMetaObject::writeVarProperty` was modified to ensure that the new reference object is detached when assigned to a `var` property, so as to be consistent with the general behavior of the other reference objects. As a drive-by, a comment in the above code that stated that some of the code should be adjusted if a new case was added to it was modified to state that the code should be adjusted with no additional clause, as a new element was added but the adjustment will not be performed as part of this patch. Some general test cases were introduced in `tst_qqmllanguage` for the new object. In particular to test the most basic interactions of the above subset of an object interaction, some of the read/write-back behavior and the behavior of detached when being assigned to a var property. Fixes: QTBUG-129972 Change-Id: Ib655ba6001aef07a74ccf235d2e3223b74d7be59 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* QtQml: Support conversion to QJSValue when constructing value typesUlf Hermann2024-10-311-5/+13
| | | | | | | | | | 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>
* QtQml: Move amendException into ExecutionEngineUlf Hermann2024-10-091-0/+23
| | | | | | | | We'll need it in more places. Change-Id: I8dc23a4b8ee873c0b8e84b3aed9872d48959a021 Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* QtQml: Disable AOT compiled code when QML-previewingUlf Hermann2024-09-271-2/+11
| | | | | | | | | | | We cannot replace AOT-compiled compilation units while an object is still holding on to them and we cannot delete all objects holding on to a CU because they might not belong to the preview to begin with. Pick-to: 6.8 6.5 Fixes: QTBUG-129329 Change-Id: Icbcb7822be770a440f3216955c0ae51151390e17 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* QtQml: Decouple JavaScript library CUs from enginesUlf Hermann2024-09-201-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | In order to re-use the compilation units for JavaScript libraries, we need to eliminate the "m_value" member they are carrying, indirectly. The values are tied to specific engines and invalid in others. Luckily, we already have two suitable places to store such values: 1. In case of a "native" module without a compilation unit we have the nativeModules hash in ExecutionEngine. 2. In case of a module or library backed by a CU we have the "module" member of ExecutableCompilationUnit. This can currently only hold modules but there is no reason why it wouldn't hold JavaScript libraries equally well. By using the "empty" V4 value we can also get rid of the m_loaded bool. As a drive by, correct the QQmlScriptBlob::isNative() misnomer. We don't want to know whether the script is native (for any value of that), but rather whether it has a value. Pick-to: 6.8 Fixes: QTBUG-129052 Change-Id: I284823f4aa26e46dec8328f88f65877f59e40f79 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* QML: Allow conversion between different list typesUlf Hermann2024-07-031-51/+10
| | | | | | | | | | | | | 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>
* QtQml: Document and uphold precondition of metaTypeFromJS()Ulf Hermann2024-05-281-6/+10
| | | | | | | | | | | | | The value needs to be a default-constructed instance. Otherwise a number of branches in this method produce unwanted effects, such as appending to an already existing array rather than creating a new one. Amends commit 1b89c1edcae68351632c2755e5408410c2ff98e3. Pick-to: 6.7 6.5 Fixes: QTBUG-125429 Change-Id: If175a02b3a794573abc03df206fbddd41f2855b4 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* QtQml: Let QQmlTypeWrapper act as a constructor for its typeUlf Hermann2024-05-231-0/+1
| | | | | | | | | | | | | | This calls any invokable ctors and only invokable ctors. Any type that doesn't have an invokable ctor won't even expose a function, since functions are determined by the presence of call methods. QMetaObjectWrapper gains the same functionality since the code is shared. It can now not only create object types but also value types. Task-number: QTBUG-124662 Change-Id: Ib30098666f67aef7a1f464f52d9b0bbd70d896d1 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* V4: Slim down FunctionObjectUlf Hermann2024-05-141-34/+34
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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: Move QMetaObjectWrapper into separate header/impl filesUlf Hermann2024-04-281-0/+1
| | | | | | | | | We want to use it from QQmlTypeWrapper and avoid circular includes. Task-number: QTBUG-124662 Change-Id: I4c78a17eb262a303b7239bbdd853ec02d609c330 Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* QtQml: Fix some type conversion edge casesUlf Hermann2024-04-231-6/+5
| | | | | | | | | | | | If the type conversion code fails to convert an argument, we still need to make sure the argument has a definite value. Otherwise we may trigger undefined behavior somewhere down the line. Furthermore, we want to look at the precise type when converting list properties. Otherwise we get a list property without any methods back when converting. Pick-to: 6.7 6.5 6.2 Change-Id: I012c0360ef1578c768362d5a4648252d3e6803d8 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* QtQml: Use QHash/QMap's constFind() to avoid unnecessary detachesVladimir Belyavsky2024-04-221-6/+6
| | | | | | | | Use QHash/QMap's constFind() instead of non-const find() where applicable to avoid unnecessary detaches. Change-Id: I6b31af1d163d11deb229681ff7e2f6c9f8335d8c Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
* qv4mm: Handle running out of native heap memoryFabian Kosmale2024-03-051-2/+1
| | | | | | | | | | | | | | | | | With the current setup, we would have risked running out of native heap space if the incremental garbage collection takes too long. Remedy this by forcing the current gc run to complete immediately once we overshoot the limit by a factor of 3/2. We still need to respect that the gc must not run in a critical section: Handle this by rechecking the condition when leaving the critical section, and only forcing a gc run at that point if necessary. Note that we currently update the gc limits before the gc cycle finishes, so that the effective limit might actually not be 3/2 in that case. This will be remedied in an upcoming patch. Change-Id: I19c367bd1ff6ffc129293fc79e39b101f0728135 Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
* Prepare for white allocations during gc (9/9): ExecutableCompilationUnitFabian Kosmale2024-03-051-2/+2
| | | | | | | | | | | | | | | | | | | | | | | ExecutableCompilationUnits are meant to be part of the roots as far as the gc is concerned. However, they can be created at any point in time, notably also while the GC is running. This was safe so far because all allocations are black, and the compilation unit will only reference freshly allocated heap items. As we want to move away from that pattern, we have to change this: We could use the typical combination of QV4::Scope and usage of the WriteBarrier, however that would add overhead for a very uncommon case (except when using QV4_MM_AGGRESSIVE_GC). Instead, we temporarily block the garbage collection, reset the state of an ongoing garbage collection and at the end of the setup of the ExecutableCompilationUnit, we mark the ExecutableCompilationUnit if the GC was already running. Introduce a new blocked state (CriticalSection) to distinguish between the normal blocked state (gc is running) and the new state where we must not even run an incremental gc to completion until the section has finished. Task-number: QTBUG-121910 Change-Id: I1dba3cc8a4f8d2b741a1a5e84fdfe7736b08e166 Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
* Prepare for white allocations during gc(6/9): Engine setupFabian Kosmale2024-03-051-0/+3
| | | | | | | | | | | | | | | | We temporarily forbid the GC from running before global object is setup, as our root set marking would otherwise run into issues in incremental mode (we don't revisit roots, and roots don't generally employ write barriers, so we might miss internal classes referenced by the global object). The GC would normally never run while the engine's constructor has not completed, however this does not hold true when QV4_MM_AGGRESSIVE_GC is enabled. Task-number: QTBUG-121910 Change-Id: I08360005f66bb6e6a36da2e16704093398f0d154 Reviewed-by: Sami Shalayel <sami.shalayel@qt.io> Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io> Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
* Prepare for white allocation during gc (0/9): EngineFabian Kosmale2024-03-051-1/+16
| | | | | | | | | | | | When inserting compilation units into the engine, we don't have any write barrier, as those are treaded as roots. However, we still have to be careful when an executable compilation unit is created while the gc is already ongoing. Thus, when we insert a CU into the engine, we mark it. Change-Id: I5e7c7e9518190dd6943cf57b0a82229d6be8d3b9 Reviewed-by: Ulf Hermann <ulf.hermann@qt.io> Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
* QtQml: Make QLocale an actual value typeUlf Hermann2024-03-021-17/+0
| | | | | | | | | | | | | | | | | | | | We want to be accessible to qmllint and other QML tooling. To this end, make all legal invocations of its methods properly typed invokables. Keep two QQmlV4Function overloads to produce error messages if the methods are called with the wrong parameters. We have to do this because JavaScript is more liberal in its argument coercion than the methods would like. Un-deprecate QJSNumberCoercion::isInteger() since it's actually quite practical here. Pick-to: 6.7 Fixes: QTBUG-112366 Change-Id: I016e5edc47efaade44461c504c1b3e2b1b829b58 Reviewed-by: Oliver Eftevaag <oliver.eftevaag@qt.io> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Ulf Hermann <ulf.hermann@qt.io> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* QtQml: Drop some dead codeUlf Hermann2024-02-081-3/+1
| | | | | | Change-Id: I3a426145929d6bed1ca7af3639b88632c187e86b Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
* QtQml: Use a multihash to store executable CUsUlf Hermann2024-01-251-7/+12
| | | | | | | | | | | | | | | You can produce multiple CUs for the same URL with createQmlObject() and friends. They need to be marked during garbage collection and therefore the engine needs to keep track of them. With the multihash there can be a lot of CUs of the same URL. Searching through them can take a lot of time. However, there is no point in searching for an existing executable CU if we've just freshly compiled the base CU. So, in those cases, insert directly instead. Fixes: QTBUG-121436 Change-Id: I804dbc74d2ade118f6680a7fbde3f234699ccbc3 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* QtQml: Use CompiledData::CompilationUnit in more placesUlf Hermann2024-01-201-16/+25
| | | | | | | | | | We rarely actually need the executable CU, and where we need it, we can dynamically create or retrieve it from the engine. To that end, store all the CUs in the same container in the engine. Change-Id: I0b786048c578ac4f41ae4aee601da850fa400f2e Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* QtQml: Move creation of ExecutableCompilationUnit into engineUlf Hermann2024-01-111-6/+11
| | | | | | | This is in preparation for letting the engine cache the executable CUs. Change-Id: Ideac10d8dda0784b41304b58f9b9fbd106173ea6 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* QtQml: Get rid of the module mutexUlf Hermann2024-01-101-9/+6
| | | | | | | | | | | | | It only exists so that the type loader can query pre-compiled and native modules from the loader thread. However, the type loader already has a mutex of its own. We can use that to inject a "native" blob into its script cache for the same effect. We need to get rid of the mutex so that we can use the module map for other compilation units, too. Change-Id: I5a9c266ea36b50f5ea69214110def644f7501674 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* QtQml: Always link executable CU on creationUlf Hermann2024-01-101-8/+12
| | | | | | | | | | | | | | | We don't want floating unlinked executable CUs. They should always be tied to an engine, and the engine should not change. This gives us one definite point where to register them with the engine (to be done in subsequent change). Unfortunately, due to the refcounting, we need to remove the engine from any still-referenced CUs when the engine itself is destructed. We will be able to drop the refcounting and make the engine fully own its executable CUs once we can hold base CUs in most places. Change-Id: I9a53e83d5c4746c2b2bca896b51baa4fe7fee757 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* QtQml: Make base CU a member of ExecutableCompilationUnitUlf Hermann2024-01-101-3/+5
| | | | | | | | | | | | We want to re-use the base compilation unit across engines. For that to work it cannot be a slice of the engine-specific ExecutableCompilationUnit. Since CompiledData::CompilationUnit is refcounted on its own now, make it unmovable. Change-Id: I8418c9754d7a07e5210c1e7a7fc69355e1d57807 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>