aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml
Commit message (Collapse)AuthorAgeFilesLines
* Fix C4267 warning in qqmlirbuilder.cppKai Köhne2021-04-201-2/+2
| | | | | | | Fixes: QTBUG-92966 Pick-to: 6.1 Change-Id: I9acdb0d624a0950f9e28c6463530b27d282123e2 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* Optimize property capture for known property cachesUlf Hermann2021-04-193-31/+61
| | | | | | | | If we already know the property cache and data we don't have to look them up again in captureProperty(). Such lookups can be expensive. Change-Id: I94553260311912c5acee3105295f124721203e01 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* qqmlirbuilder: Fix treating parser warnings as errrosMaximilian Goldstein2021-04-191-1/+3
| | | | | | | | | | Previously parser warnings (i.e. inline components having lowercase names) were treated as errors. Because these were not handled properly this also resulted in the QQmlComponent with the warning never becoming ready. This resulted applications hanging instead of terminating. Pick-to: 5.15 6.0 6.1 Change-Id: Ia5ad3b54edc1b94dd94d0bf771c3494691abec71 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* Document that QML_SINGLETON only works with QObjectsMitch Curtis2021-04-191-7/+8
| | | | | | Pick-to: 6.1 6.0 5.15 Change-Id: I18c38037cd635fa3300c761b16038b67ac3b0d74 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* Optimize the case of AOT functions returning QObject*Ulf Hermann2021-04-191-6/+17
| | | | | | | | | | We don't need to go through all the metatype construction, conversion, and destruction if we know that both the expected and the actual return types are QObject pointers. We can just check if they're compatible and assign if they are. Change-Id: Ic5ab13536cf2e0e2a982ed9a9be81eb5927e85c2 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* Adjust to QProperty using eager evaluationFabian Kosmale2021-04-193-8/+10
| | | | | | | | | | | | Besides API changes, we need to - adjust QQmlBind to unlink the binding properly (that probably was broken already before, but did not cause issues so far, as the old binding would not have been evaluated without a read access) and - skip tests in tst_qmlcompiler_manual, as the bindings are executed before the engine is correctly set. Change-Id: I97b0ac32b428c1a033664fe8593effadb69cd348 Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
* Don't pre-resolve the QQmlContext for AOT functionsUlf Hermann2021-04-194-8/+14
| | | | | | | | We only ever need it to retrieve the QQmlEngine. However, resolving the context can involve an allocation. Change-Id: I064fd528fa7ab9bd37043c5dd1c62d17ea9380e3 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* Fix build without features.qml-sequence-objectTasuku Suzuki2021-04-191-0/+2
| | | | | Change-Id: I2da9712201f3057b4d20aa0176716442d69d0ab9 Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
* Fix documentation of QQmlListReference::sizeVolker Hilsheimer2021-04-161-1/+1
| | | | | | | | | Amends ca06d488f3c5d899c008b431f6939793813243cb. count was already documented. Pick-to: 6.1 Change-Id: I2f79d132f29ae03f03dd7204ea09e4841971d650 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* Rework qmljsrootgenUlf Hermann2021-04-163-3/+21
| | | | | | | | | This way it actually generates interesting data about the JavaScript types, for example the functions of the String prototype. Add a helper method to create a symbol to QJSEngine. This should be generally useful. Change-Id: I6c7b253b9d6cdb61602ceeae0955aed8d942c139 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* Fix QQmlContext::nameForObject()Ulf Hermann2021-04-162-14/+42
| | | | | | | | | | | | | nameForObject() should not search the linked contexts. Linked contexts are not reachable from the "head" context in QML. However, it should search context objects, just like contextProperty() does. [ChangeLog][QtQml][Important Behavior Changes] QQmlContext::nameForObject() now finds properties of context objects, but it does not search unrelated other ("linked") contexts anymore. Change-Id: Ic6e01fddf3e2d4b3a1bc7308e126f47fae7cd6d1 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* Provide an objectForName() function in QQmlContextUlf Hermann2021-04-162-7/+53
| | | | | | | | This is the reverse of nameForObject(). We don't need to wrap id'd objects in QVariant just to unwrap them again at the call site. Change-Id: Ie1c5382af33b5c05b0b931fcc5bcf8d232d27c21 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* CMake: Fix qml module version to use the repo project versionAlexandru Croitor2021-04-151-1/+1
| | | | | | | | | | | Use PROJECT_VERSION instead of CMAKE_PROJECT_VERSION, so that the repo project version is used in a top-level build, rather than the version of the qt5 project. Pick-to: 6.1 6.0 Task-number: QTBUG-92861 Change-Id: I5a7a09baf81353558e512800746ac24e8e8b9a47 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* Streamline retrieval of context property names and IDsUlf Hermann2021-04-157-45/+51
| | | | | | | | Most of this can be inline, and we never need to copy the actual identifier hash. Change-Id: I6468b6b1a571e4854c00c865a2aa57c3b2f0ca8c Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* Fix build without features.itemmodelTasuku Suzuki2021-04-153-26/+20
| | | | | Change-Id: I12073e43b34d7c72b441aaf081e4210a3161b4e8 Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
* Check thisObject when calling various methods on URLUlf Hermann2021-04-141-38/+122
| | | | | | | | | We should not crash when you try to call them on the wrong object. Rather, throw a type error. Pick-to: 6.1.0 6.1 Change-Id: I1b146d9c77d838e013408988e02a65a623641f1f Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* Increment QV4_DATA_STRUCTURE_VERSIONFabian Kosmale2021-04-141-1/+1
| | | | | | | | | The bytecode format has been changed, as two new instructions were added. Amends 5f7ecce23321f499b1b002c32a27c63815535baa. Change-Id: Ie81651a48eec38b014e3bc859cc8ecb0cf8396d0 Reviewed-by: Maximilian Goldstein <max.goldstein@qt.io> Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
* qmldom: Improve basic infrastructureFawzi Mohamed2021-04-141-0/+13
| | | | | | | | | | | | | | | * introduce function_ref to represent a reference to a function and use it consistently (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p0792r5.html) * restricted errormessage levels to those of QtMsgType * made path iterate on its segments * made path methods mirror the DomItem methods, so that path construction and access are similar * AttachedInfo to keep the location information * SourceLocation::combine Change-Id: I152c4cc2c601e867f205a4f4b7b3f24884d60ad9 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* qv4codegen: Fix codecheker warning about invalid base referencesMaximilian Goldstein2021-04-141-0/+1
| | | | | Change-Id: Ie5a229d7e62d8df356359094e7e6d38530672a43 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* Implement optional chainingMaximilian Goldstein2021-04-1316-18/+460
| | | | | | | | | | | | | | | | | This change implements optional chaining (https://github.com/tc39/proposal-optional-chaining) by adding a new type of optional lookup with an offset to the end of a chain. If `undefined` or `null` is encountered during an access marked as optional, we jump to that end offset. Features: - Full support for all kinds of optional chain - With some codegen overhead but zero overhead during normal non-optional FieldMemberExpression resolution - Properly retains this contexts and does not need to resolve anything twice (this has been an issue previously) - No extra AST structures, just flags for existing ones [ChangeLog][QtQml] Added support for optional chaining (https://github.com/tc39/proposal-optional-chaining) Fixes: QTBUG-77926 Change-Id: I9a41cdc4ca272066c79c72b9b22206498a546843 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* QV4::EngineBase: Remove pragma packFabian Kosmale2021-04-131-7/+0
| | | | | | | | | | | This was only used on a subset of our compilers, and caused issues with pointer alignment. We have static_assert's in place to verify that the struct members are in the correct place, and pack had no effect anyway after we added the alignment padding to the struct. Change-Id: I162664ec01d4b5d97ac800afc354d0ab2e04de42 Reviewed-by: Ulf Hermann <ulf.hermann@qt.io> Reviewed-by: Andrei Golubev <andrei.golubev@qt.io>
* QQmlJSLexer: Add support for peeking one QCharFabian Kosmale2021-04-132-0/+9
| | | | | | | | | This is helpful for the upcoming handling of ?., which needs to be treated as a single token (T_QUESTION_DOT), unless it is followed by a number literal. Change-Id: Id5e992bd037c2df88ef6e66905ec58a39bb67d73 Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
* QV4EngineBase: Do not create zero-sized array on 32 bit platformsFabian Kosmale2021-04-121-1/+3
| | | | | | | | | | | Zero-sized arrays are a non-standard extension, and do not work on MSVC. We can instead conditionally add an explicit padding member on platforms where POINTER_SIZE == 8. Fixes: QTBUG-92562 Pick-to: 6.1 6.1.0 Change-Id: I8462eb05e16c42045c0c95f026321c6e20e5c6bb Reviewed-by: Maximilian Goldstein <max.goldstein@qt.io>
* Remove QString overload forwarding to QStringViewFabian Kosmale2021-04-091-7/+0
| | | | | | Change-Id: Ia97aefc3dbedae1e979db93638836b366eee153f Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
* Do not auto-clean components with live inline componentsUlf Hermann2021-04-091-1/+11
| | | | | | | | | | The inline components do not hold a strong reference to their outer type because that would be a reference cycle. Fixes: QTBUG-92236 Pick-to: 5.15 6.0 6.1 Change-Id: I6d76a114352653210f0ece6c198cf761d3b4eda1 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* Resolve inline components before root componentFabian Kosmale2021-04-073-38/+115
| | | | | | | | | | | | | | | | | | | | | | | During instantiation of a component, we might need access to the meta-objects of its referenced objects in the QQmlPropertyCacheCreator. In the case of inline components, those might have however not been complete: If they contained alias properties (which change the shape of the metaobject), we would not be aware of it, as those are only resolved when QQmlComponentAndAliasResolver has run. QQmlComponentAndAliasResolver runs however necessarily after the QQmlPropertyCacheCreator, as the alias resolver needs the metaobject to know about the non-alias properties. We fix this by restructuring the passes, so that we first run both passes for each inline component, and only afterwards for the component containing them. This is done by making QQmlPropertyCacheCreator resumable: resumableBuildMetaObjects processes one (inline) component at a time, and remembers enough state to continue. Fixes: QTBUG-91143 Fixes: QTBUG-85980 Change-Id: Ib0d0bc5ff6cf067b2443b2e0cfb5400a9bd96754 Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
* Run QQmlDefaultPropertyMerger after alias resolverFabian Kosmale2021-04-071-5/+5
| | | | | | | | | There is no dependency between them. This is done in preparation of a restructuring of the PropertyCacheCreator and AliasAndComponentResolver passes. Change-Id: I2695435ca9b2aed5c4c34c281cd1611f5373e3f8 Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
* Don't run into UB when converting doubles to int on property assignmentUlf Hermann2021-04-061-1/+1
| | | | | | | | | We cannot just do a straight cast in this case. The floor()/ceil() toInteger() does actually has no effect if the value overflows. We need to do a full JavaScript coercion in order to be safe. Change-Id: I122974de5f0b9bdba9133b8503e328c4f7185934 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* CMake: Disable JIT for arm64 when doing macOS universal buildsAlexandru Croitor2021-04-037-3/+46
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Our current approach to building universal macOS Qt is to pass 2 -arch flags to clang, which underneath spawn 2 clang invocations with each separate arch and lipo-s the result together. This approah also meanss that we do only one set of config tests for the main (first) architecture. Currently Qml doesn't support JITing for macOS on Apple Silicon (arm64), but if the first architecture is x86_64, the qml_jit feature will be set to 'true', and cause compilation errors when trying to build the arm slice of the jit source files. To circumvent that, and allow skipping compilation of JIT specific code, we have to apply the same trick we do in qtbase, which is to set a compile definition that takes the current architecture into account, and surround all relevant code with an #if block taking to account both the feature and current architecture. Use a custom hacky qt_extra_definition call to redefine the value of QT_FEATURE_qml_jit based on the original feature value and the current architecture. Additionally, surround the jit source files with #if QT_CONFIG(qml_jit). Amends 561a2cec9b95b22783a00b48078b532010357066 Task-number: QTBUG-85447 Change-Id: I28b286d218333076223177c456175f180888a667 Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
* Optimize invocation of signal handlersUlf Hermann2021-04-013-11/+27
| | | | | | | | | We don't have to do any argument conversion if there are no arguments. Furthermore, we don't need to do the metatype-to-JS conversion if the handler to be invoked is AOT-compiled. Change-Id: I03d8fd7ad07d311d64c39adfd39febbe94396d2f Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* QV4QObjectWrapper: Store the whole signalFabian Kosmale2021-04-013-9/+10
| | | | | | | | | | | | | | | | | | | | | 90be89d771425044a84e9e79e4e668e065acc825 changed the connection logic to actually pass the receiver to connect in order to fix disconnect cleanup. However, we omitted to change QObjectSlotDispatcher::impl accordingly. The previous logic was: - store the index of the signal in signalIndex - In impl, in the call case, we would get passed the emitting object (sic!) as the receiver parameter. Then we would use the object and the signal index to obtain the QMetaMethod. - From the QMetaMethod, we could get the signal's number of parameters. After the aforementioned change, that does not work anymore: The receiver is now the actual receiver of the signal, thus we get the wrong method, and potentially the wrong number of parameters. To fix this, we now store the complete QMetaMethod of the signal. Pick-to: 6.1 Change-Id: I868c51edf24a61d14eaf958ed7942da27f54a5c3 Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
* Simplify populateJSCallArguments a bitUlf Hermann2021-04-011-4/+2
| | | | | Change-Id: I7e2f09c3ddf4a855c87c36a16b9f48af3dadf978 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* Un-special case QQmlPropertyValueTypeFabian Kosmale2021-03-314-28/+7
| | | | | Change-Id: I5123f72fea4198505c27678dbaaea26313b2327c Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
* Move type registration into their own headerFabian Kosmale2021-03-313-96/+143
| | | | | | | | | | | For now, this simply gives us a more lightweight header than qqml.h. In the future, we could move this completely out of QML, to ease optional QML integration in libraries that do not want to directly depend on QtQml. Task-number: QTBUG-92258 Change-Id: I3583ce85905ed8fa0a45abb360728178c774d679 Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
* Do not throw an exception in the optimized AOT lookup pathUlf Hermann2021-03-311-5/+1
| | | | | | | | | | | | The method already returns a bool status which tells the caller "something is wrong". If something is wrong, the caller will try a different method to retrieve the value, and that will generate the exception again. We should not shortcut the procedure as generating the exception requires the instruction pointer to be set, which is additional overhead on the caller's side. Change-Id: Ia2d3a90c897b14660a18a5740498a0e5016dc49a Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* Fix missing 'We mean it' warning for generated qml_compile_hash_p.hKai Köhne2021-03-311-0/+15
| | | | | | Pick-to: 6.1 Change-Id: I327d377c80749741274a76dfa609417c005bf6c7 Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
* Use CLASS_NAME rather than CLASSNAME for qt6_add_qml_module()Craig Scott2021-03-312-21/+47
| | | | | | | Task-number: QTBUG-88763 Change-Id: I118227ec418ac59eb6603d236b38b1a4319a51c2 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
* CMake: Account for qtbase refactoring in qt_internal_add_plugin()Craig Scott2021-03-311-15/+44
| | | | | | | | | Task-number: QTBUG-88763 Pick-to: 6.1 Change-Id: I66c22f876be66ca64cd364f574a6f3e862e4abf5 Reviewed-by: Ulf Hermann <ulf.hermann@qt.io> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> Reviewed-by: Andrei Golubev <andrei.golubev@qt.io>
* Prevent CMP0116 warning with CMake 3.20 or laterCraig Scott2021-03-311-9/+16
| | | | | | | | | | | | | | | | CMake 3.20 introduced a change in the handling of relative paths in *.d depfiles referenced by custom commands. To avoid a CMP0116 policy warning, we have to explicitly set the policy to NEW and also change the relative path(s) we embed in the depfiles to be relative to CMAKE_CURRENT_BINARY_DIR rather than the top level binary directory. Fixes: QTBUG-92026 Pick-to: 6.1 6.0 Change-Id: I1a84d29f1a8d5c48bae5bc11596806f1e0e07919 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> Reviewed-by: Andrei Golubev <andrei.golubev@qt.io> Reviewed-by: Ulf Hermann <ulf.hermann@qt.io> Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
* QV4CompilerScanFunctions: Silence code checker warningFabian Kosmale2021-03-302-3/+8
| | | | | | | | | | | | The AST is constructed in such a way that having exportAll set always implies that a fromClause exists. Also, clean up exportAll: We do not need a separate member to track it. Its value is fully determined by the presence of fromClause and exportsClause. Thus, replace it with a function. Change-Id: Ib7db2bbaf326ecc36a7f4a2986a7c1fb54db6cd5 Reviewed-by: Andrei Golubev <andrei.golubev@qt.io> Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
* QQmlMetaTypeData: Purge custom string convertersFabian Kosmale2021-03-306-63/+4
| | | | | | | | | Those were never exposed anyway. color, date, etc. are handled by the less generic converters in qqmlstringconverters_p.h. Change-Id: I43a94acda08344de742440dd3b956a7077096b11 Reviewed-by: Ulf Hermann <ulf.hermann@qt.io> Reviewed-by: Andrei Golubev <andrei.golubev@qt.io>
* Adjust to metaobject revision changeFabian Kosmale2021-03-301-1/+3
| | | | | | | | | | And make sure that we notice that at compile time the next time it happens. Change-Id: I552481e0f9f7178ec3f1450d8050ae9434894e5a Reviewed-by: Maximilian Goldstein <max.goldstein@qt.io> Reviewed-by: Ulf Hermann <ulf.hermann@qt.io> Reviewed-by: Andrei Golubev <andrei.golubev@qt.io>
* qv4qobjectwrapper_p.h: Work around MinGW bugFabian Kosmale2021-03-301-0/+2
| | | | | | | | | | mingw 8.1 does not handle the access to privates in a SFINAE context correctly. Publically expose MultiplyWrappedQObjectMap::value_type to work around this issue. Change-Id: I9cddeaca8ebaaa77a786fac2c4e210dd3b852d4d Reviewed-by: Andrei Golubev <andrei.golubev@qt.io> Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
* Avoid needless construction and destruction of return valuesUlf Hermann2021-03-294-14/+15
| | | | | | | | | | In most cases the AOT compiled function will successfully placement-new the return value. Therefore, we can provide uninitialized space. Only do the construct/destruct dance in the cases when it's already slow. Change-Id: Ia339774fde03e459f290f167ddadd1c47a644b8e Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> Reviewed-by: Andrei Golubev <andrei.golubev@qt.io>
* Provide an AOT-optimized code path for binding evaluationUlf Hermann2021-03-294-62/+213
| | | | | | | | | We don't need to convert the results of calling binding functions back and forth. Change-Id: Icb997532ebc3092f3e3882a804173346b450e435 Reviewed-by: Andrei Golubev <andrei.golubev@qt.io> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* Optimize some common lookups for AOT compiled codeUlf Hermann2021-03-292-0/+73
| | | | | | | | Getting a property of an object and getting an object by ID should not require any type transformations. Change-Id: I7ba06cf7c09cdf4ce7b0093b670fd7879ecf799a Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* Allow a bare lookup capture, without executing the lookupUlf Hermann2021-03-292-0/+55
| | | | | | | | This is useful when we know how to read the property directly. Change-Id: Ibc314a8e8bf9e51b3a15d934f6a1f17a53ea168a Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> Reviewed-by: Andrei Golubev <andrei.golubev@qt.io>
* Ensure that empty tokens in the AST are emptyFawzi Mohamed2021-03-262-6/+36
| | | | | | | | | | | | | | | | Arrow functions introduce a virtual functions and return statements to simplify code generation (arrow function look like normal function definitions), but to have correct firstSourceLocation / lastSourcelocation other tokens were reused. Use an empty SourceLocation at the correct position instead, so code that expects the correct location (for error messages,...) works and code that expects the correct token content (rewriter in QtCreator for example) also works. Introduce helper SourceLocation::startZeroLengthLocation/ endZeroLengthLocation to simplify such code. Change-Id: I1c5df16e1704df2df9b7cbd1a039ce56be3727d3 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* Consider only default constructed SourceLocation invalidFawzi Mohamed2021-03-261-1/+3
| | | | | | | | | | | | | | | | | | | SourceLocation::isValid consider invalid all SourceLocations with length == 0. This is misleading because we already have several SourceLocations that contain correct information but have zero length like: * In the Ast several places, especially related to the use of Semicolon in the grammar, which might be an automatic semicolon and have length 0, but still be at the correct place, see ReturnStatement and many others. * Parser error messages, which (even worse) set only line/column Note that SourceLocation() == SourceLocation(0,0,0,0) is indeed invalid, as the first location of a file is SourceLocation(0,0,1,1) because both column and line number start at 1. Change-Id: Ib9184f2ee4842e85c505c94ccbbcefb119925492 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* QV4::Engine::toVariant: Use metatype instead of metatype idFabian Kosmale2021-03-2512-41/+41
| | | | | | | | | | This way, we can avoid the costly id to metatype lookup in case where we actually need the full metatype. Task-number: QTBUG-88766 Change-Id: Ibe29b323007f00d2f8d1807fb9b64f9a8f87e807 Reviewed-by: Ulf Hermann <ulf.hermann@qt.io> Reviewed-by: Andrei Golubev <andrei.golubev@qt.io>