aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/compiler/qv4codegen.cpp
Commit message (Collapse)AuthorAgeFilesLines
* QtQml: Straighten out some logging categoriesUlf Hermann2 days1-2/+2
| | | | | | | | | | | 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>
* qv4codegen: Store the location of binary expressionsOlivier De Cannière2024-04-221-4/+7
| | | | | | | | | | | | | | | | | | | | | | | | | | | | This location is then used later, for example, to improve the accuracy of warnings. OLD Warning: Main.qml:22:30: function without return type annotation returns double of double [compiler] function type() { return 1 + 1 } ^^^^^^ NEW Warning: Main.qml:22:30: function without return type annotation returns double of double [compiler] function type() { return 1 + 1 } ^^^^^ The location stored is the combined locations of the left operand, the operator, and the right operator. We should investigate if this is the right approach. Created QTBUG-124548. Task-number: QTBUG-124548 Task-number: QTBUG-124220 Pick-to: 6.7 Change-Id: Icac335d53349c05d0e9ee6e436bc6ab08ad970d2 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
* QtQml: Make base CU a member of ExecutableCompilationUnitUlf Hermann2024-01-101-6/+8
| | | | | | | | | | | | 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>
* qv4codegen: Do not call functions on null objects inside optional chainsOlivier De Cannière2024-01-081-1/+1
| | | | | | | | | Amends: 86c48761dc7ba5bcac7dc6740e94efbfb8678403 Fixes: QTBUG-120504 Pick-to: 6.7 Change-Id: Id77236a07d7c1a16e2f60238909eff245c5c354a Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
* QtQml: Pass Codegen::Reference as referenceUlf Hermann2024-01-081-1/+1
| | | | | | | | | Despite its name, it's really large. Coverity-Id: 434159 Change-Id: I7ccdfbdf0582edd13011d89dbb50a17ea1455637 Reviewed-by: Sami Shalayel <sami.shalayel@qt.io> Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
* QtQml: Do optional chain finalization also on string-y element lookupUlf Hermann2023-12-201-0/+1
| | | | | | | | | | Amends commit 86c48761dc7ba5bcac7dc6740e94efbfb8678403. Pick-to: 6.7 Fixes: QTBUG-120168 Change-Id: I5848d8394498bafb1e897eca865d405224eaf997 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
* Engine: Group 'bad' case handling for optional chainsOlivier De Cannière2023-11-201-149/+139
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This patch changes the way optional chains are dealt with in the bytecode. Instead of dealing with the 'bad' case (where the base of the lookup is null or undefined) of each instruction separately, all optional operations point to the same piece of code at the end of the optional chain to deal with bad accesses. In practice, for the lookup `root?.foo.bar?.baz` the following bytecode instructions are generated. LoadQmlContextPropertyLookup // root GetOptionalLookup --v // ?.foo GetLookup | // .bar GetOptionalLookup --v // ?.baz Jump done ------------v undefined: <----< | LoadUndefined | done: <------< In this way, the 'bad' case is handled in one place at the undefined label. If, on the other hand, the chain evaluation reaches the bottom, one jump takes the resulting value to the rest of the program. In this way, the 'bad' case has a constant size relative to the length of the chain. If no optional operation is performed at all. The 'bad' case handler is not generated at all. For this to work, GetOptionalLookup now jumps to the undefined label when its base is null of undefined. Other operations such as function calls `f?.()`, array access `a?.[0]` and delete expressions `delete foo?.bar` have also been adapted to point to the undefined label. Change-Id: I07158efc8767d84a7588299cae9fb763b0f6e253 Reviewed-by: Ulf Hermann <ulf.hermann@qt.io> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* V4: Eliminate "done" from iteratorsUlf Hermann2023-09-081-43/+72
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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>
* QtQml: Add more fine grained logging categories for qv4codegen.cppUlf Hermann2023-09-081-3/+4
| | | | | | | | | | | We want to control the warnings about variables used before declaration and injected signal parameters separately, and they are not necessarily part of the compiler warnings. Fixes: QTBUG-116764 Change-Id: If3f28f99b539a069cbdb7854d701c027debc77be Reviewed-by: Andreas Aardal Hanssen <andrhans@cisco.com> Reviewed-by: Sami Shalayel <sami.shalayel@qt.io>
* qv4codegen: Eliminate redundant SetUnwindHandler for try-catch-finallyOlivier De Cannière2023-08-301-1/+2
| | | | | | | | | | | | | | For try-catch-finally sequences with a catch block, the generator would start by setting the unwind handler to code from the finally block and immediately after that set the handler to code from the catch block, overwriting the last instruction. In cases with catch blocks, do not emit the first instruction setting the unwind handler. Change-Id: I588433c1ad2521b1750f77f2084315a707577a8a Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
* qv4codegen: Remove redundant jump instruction for coalesce expressionsOlivier De Cannière2023-08-291-8/+2
| | | | | | | | | | | | | | | | | | | For binary expressions with the ?? operator, two cases must be handled in two code paths. When the lhs is defined, it is used as the result of the expression. When the lhs is undefined, the rhs expression is used as a fallback instead. Distinguishing between these two branches can be done with a test such as CmpEqNull and a conditional jump based on it.. Previously, on top of a conditional JumpTrue to jump to the correct location based on the test, a second JumpFalse was emitted to perform the same operation a second time. This is redundant. The second jump was removed and the logic was slightly reorganized. Change-Id: I65479752d9fac8c18ef2475b062dd2b5262c372e Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
* QtQml: Don't generate an unwind handler for for..in loopsUlf Hermann2023-08-251-5/+6
| | | | | | | | We only need the unwind handler for for..of loops in order to close the iterator. Change-Id: Ieae67cf852fd858e0c1956889d4cf5b40a660b7e Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* UndefinedBehavior: fix some things found with -sanitize undefinedOlivier De Cannière2023-08-011-1/+1
| | | | | | | | | | | | | | | | | | Here are the sorts of things that were found: - Uninitialized variables containing garbage. - Calling member function through nullptr (where this is not actually used inside the function because that would trigger a segfault). - static_cast'ing double to int where the double is either +/-infinity or is outside the range of min and max values for int. Additionally, the uses of QJSNumberCoercion::isInteger() in the code generator have been replaced by QJSNumberCoercion::isArrayIndex() and the former was deprecated as it is no longer being used. Pick-to: 6.5 6.6 Change-Id: I9318671ccbda37e5519f4fcb84a1537585c2103f Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* Compiler: Allow dumping the basic blocks for visualization and debuggingOlivier De Cannière2023-07-101-2/+3
| | | | | | | | | | | | | | | | | | | | If the QV4_DUMP_BASIC_BLOCKS environment variable is set, the compiler will output the details of the basic blocks of the compiled functions to the console. It will also generate a control flow graph containing the byte code in DOT format for easier visualization and debugging of the program execution and of the structure of the generated code. The value of QV4_DUMP_BASIC_BLOCKS will be used as the path to the folder in which to output the DOT files. If the path is any of ["-", "1", "true"] or if files can't be opened, it will be dumped to stdout instead. The logic in dumpByteCode has been adapted to use a QTextStream. This way it can continue to be used to dump the byte code of the whole program as before and also to construct the CFG. Change-Id: If398d795e4fc0950b5fa8ee1349e80b1ae262deb Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
* qv4codegen: Remove static disable_lookup debug aidFabian Kosmale2023-03-111-7/+5
| | | | | | | | | | | | | This variable, introduced in aabf2196016d96bd171a7d632b6e1cc5622d05ae, allows to turn of the use of lookups in a few places. However, there is no apparent need for doing so, and the commit message of the change that introduced it does not give any reason for it. As the variable is always false, and given that we run the lookup code path by default since quite a while, simply remove it. Change-Id: I62e00739a58fc748a1239087fa0374861ec73e64 Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
* QML: Allow pragmas with multiple valuesUlf Hermann2023-02-221-0/+5
| | | | | | | | | This will be needed in follow-up changes. Task-number: QTBUG-94807 Change-Id: I6243ea31290251c30dd0aceaae878568bc1c0525 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
* Fix CMake Unity (Jumbo) builds on WindowsFriedemann Kleint2023-02-151-2/+2
| | | | | | | | | | Rename some variables to prevent clashes with the "interface" on Windows. Pick-to: 6.5 Task-number: QTBUG-109394 Change-Id: I54cd35c2d06b30c21cddd8650282687ec8ccf5ee Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
* QML: Do not crash on CallWithSpreadUlf Hermann2022-11-221-7/+19
| | | | | | | | | | | | | | We need to check for subscripts also when creating CallWithSpread and TailCall instructions. Furthermore, the == operator of Reference needs to take into account whether the subscript has been loaded or not. Amends commit 872e91612fd83de6dd1193014b5e2a0f5e8c30af. Fixes: QTBUG-108441 Change-Id: I2d1a7a11f9cdcb4320a87df979d9ca4457620d3f Reviewed-by: Sami Shalayel <sami.shalayel@qt.io> Reviewed-by: Semih Yavuz <semih.yavuz@qt.io> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* QML: Require TDZ checks variables declared in case blocksUlf Hermann2022-11-151-26/+25
| | | | | | | | | ... and check the tdz only once on function calls. Task-number: QTBUG-108362 Change-Id: I534e2604fb68b3b9145b7b7dd003e988e9df17d0 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* QML: Fix the most blatant TDZ violationsUlf Hermann2022-11-141-20/+53
| | | | | | | | | | | When reading a let or const register before its declaration we can be sure this is invalid. Task-number: QTBUG-108362 Fixes: QTBUG-77428 Change-Id: I7e8f8b46079860f00c051c1a91f773dc8cdd5595 Reviewed-by: Sami Shalayel <sami.shalayel@qt.io> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* Replace CallElement with separate instructionsUlf Hermann2022-11-071-5/+20
| | | | | | | | | | 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 to new Q_UNREACHABLE_RETURN()Marc Mutz2022-10-201-54/+27
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This is a semantic patch using ClangTidyTransformator to convert sequences of Q_UNREACHABLE() + return into Q_UNREACHABLE_RETURN(), newly added to qtbase. const std::string unr = "unr", val = "val", ret = "ret"; auto makeUnreachableReturn = cat("Q_UNREACHABLE_RETURN(", ifBound(val, cat(node(val)), cat("")), ")"); auto ignoringSwitchCases = [](auto stmt) { return anyOf(stmt, switchCase(subStmt(stmt))); }; makeRule(stmt(ignoringSwitchCases(stmt(isExpandedFromMacro("Q_UNREACHABLE")).bind(unr)), nextStmt(returnStmt(optionally(hasReturnValue(expr().bind(val)))).bind(ret))), {changeTo(node(unr), cat(makeUnreachableReturn, ";")), // TODO: why is the ; lost w/o this? changeTo(node(ret), cat(""))}, cat("use ", makeUnreachableReturn)); a.k.a qt-use-unreachable-return. subStmt() and nextStmt() are non-standard matchers. There was one false positive, suppressed it with NOLINTNEXTLINE. It's not really a false positiive, it's just that Clang sees the world in one way and if conditonal compilation (#if) differs for other compilers, Clang doesn't know better. This is an artifact of matching two consecutive statements. Change-Id: I3855b2dc8523db1ea860f72ad9818738162495c6 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* QML: Track the statement indices together with line numbersUlf Hermann2022-10-131-1/+3
| | | | | | | | | | We will need the statement indices when tracking value type references. New value type references shall only be written back in the same statement they were created in. Task-number: QTBUG-99766 Change-Id: I83f908df034e7da8ba46ccacaa29bd9d78020d20 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* Port from container::count() and length() to size()Marc Mutz2022-10-071-3/+3
| | | | | | | | | | | | | | | | | | | | 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>
* Do not store the accumulator in optional chaining callFabian Kosmale2022-09-301-2/+0
| | | | | | | | | | | | | | | | There are two cases: - Either the optional value is nullish, then we overwrite the accumulator with undefined, or - the value is not nullish, in which case we do a call. None of the call instructions read the accumulator, and all of them overwrite it. So in both cases we do not need the current value in the accumulator, and can thus skip saving and restoring it. Fixes: QTBUG-107047 Pick-to: 6.4 Change-Id: I620e525d59990a5d7a0af15e2ee48795163c6575 Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
* QML: Optimize QObject method callsUlf Hermann2022-09-201-8/+17
| | | | | | | | | | | | | | | | | | | | | | So far, for each method call we had to allocate a new QObjectMethod as we didn't have any lookup to cache the methods. Introduce a new lookup for that and use it for all QObject methods. Since QObjectMethod contains a pointer to the concrete QObject the method was retrieved from, some more care has to be taken: If we are going to call the method right away, we don't need the object since we always have a thisObject and any further retrieval of the same method will result in a call again. This enables us to cache the method for any instance of the same class. When storing the method elsewhere, though, we need to hold on to the object since you can defer the call or connect a handler to a signal or similar. For such operations we do need the object. We can still optimize a bit by re-using the method cache we build the first time around. Fixes: QTBUG-95628 Change-Id: I5991180c5e0234cdc179c2b78a43dafc9083e525 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* QtQml: Remove unused includes in qml, first partSemih Yavuz2022-09-141-1/+0
| | | | | | | | | | | | | | | Drop unnecessary includes detected by clangd-iwyu. Add new includes due to the transitive includes. Also, some of the includes were detected as unused even if they were actually in use. In those cases, use angular brackets instead of "" which deceives the tool not to complain. Affected subfolders: Debugger, Compiler, JsApi, JsRuntime, Memory, Parser Task-number: QTBUG-106473 Change-Id: I01d996a2a2ba31cbbc5f60f5454c8f850298f528 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* Codegen: Remove unnecessary checkUlf Hermann2022-07-181-1/+2
| | | | | | | | | | | The following cast() checks its argument again. However, as the "statement" member is not checked for null anywhere else, we can be pretty sure it actually is never null. So even the check in cast() should be unnecessary. Coverity-Id: 190165 Change-Id: I5a966a52fb3b509b2f3fee4e20c357679d422567 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* QmlCompiler: Handle trivial signal handler constructionsUlf Hermann2022-07-071-3/+4
| | | | | | | | | | | | | | If the signal handler does nothing but return a closure, we have to compile the closure using the same signature as the outer signal handler. In order for this to work, we also have to detect unresolved argument types for signal handlers. Those are just as bad as unresolved argument types for other functions. Fixes: QTBUG-101531 Change-Id: Idb5b3994809d91a4b4ce936282685435eb75e670 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>
* Replace uses of deprecated _qs with _s/QStringLiteralSona Kurazyan2022-04-291-1/+3
| | | | | | Task-number: QTBUG-101408 Change-Id: Ic925751b73f52d8fa5add5cacc52d6dd6ea2dc27 Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
* JavaScript: Make "this" available in blocks inside arrow functionsUlf Hermann2022-02-021-5/+10
| | | | | | | Fixes: QTBUG-98039 Pick-to: 6.2 6.3 Change-Id: I51ff36994fa0f3f3568c8114cb6841f677f64bc4 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* QML/JS: Reject yield expression not directly in generator functionsFabian Kosmale2021-11-181-0/+11
| | | | | | | | | | | If an inner function contains a yield expression, we need to reject the program even if that function is inside of a generator function. Fixes: QTBUG-98356 Pick-to: 6.2 5.15 Change-Id: I2e820a1ca5f0da4080e313fd9809aa8bfdc1b681 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
* qmllint: Move use-before-declaration warning out of checkidentifiersMaximilian Goldstein2021-08-041-14/+23
| | | | | | | Another step to making checkidentifiers obsolete. Change-Id: I14be7491387200101b66e0930faf16e9b61d4159 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* qv4codegen: Improve source location reportingMaximilian Goldstein2021-08-021-1/+4
| | | | | | | | Properly report the source location of FieldMemberExpressions and also report them properly when the FieldMemberExpression ends in a CallPropertyLookup. Change-Id: I2c0eb719e98d19dec97d46cda1530208ad0120cd Reviewed-by: Andrei Golubev <andrei.golubev@qt.io> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* qv4codegen: Provide more accurate SourceLocationsMaximilian Goldstein2021-07-141-4/+17
| | | | | | | | Previously the source locations in the bytecodegenerator were often imprecise due to them not being updated often enough. This change makes sure that FieldMemberExpressions and IdentifierExpressions report more accurate locations instead. Change-Id: Ib53cda5cc927551c25ed32ed34d4b65d82f5e199 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* qv4bytecodegenerator: Supply SourceLocations in compiler contextMaximilian Goldstein2021-07-131-4/+3
| | | | | | | | | | This is required for better warnings in qmlcompiler's type propagator. Remains optional as to not consume superfluous memory when not needed (during normal QML engine operation). Change-Id: I50293f878e4f6659935925f5f2266427d2f64d7b Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> Reviewed-by: Ulf Hermann <ulf.hermann@qt.io> Reviewed-by: Andrei Golubev <andrei.golubev@qt.io>
* Replace "fall through" comments with Q_FALLTHROUGHThiago Macieira2021-06-221-2/+2
| | | | | | | | 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>
* Evaluate type assertions in QMLUlf Hermann2021-05-261-3/+9
| | | | | | | | | | | | | | | | | | 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>
* Implement optional chainingMaximilian Goldstein2021-04-131-13/+231
| | | | | | | | | | | | | | | | | 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>
* QML: Warn about usage of injected signal parametersUlf Hermann2021-02-121-0/+9
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | You should declare functions with formal parameters if you want to use parameters passed by the signal. We need to generate two different warnings because there are two code paths by which such parameters are injected. If we compile with qmlcachegen, it simply inserts a lookup instruction in to the byte code. This lookup then triggers our special hack expressly made for signal parameters. If we don't compile using qmlcachegen, a function declaration with formal parameters is synthesized. We mark those formal parameters as injected and warn if we see one of them used. [ChangeLog][QML][Important Behavior Changes] The automatic injection of signal parameters into signal handlers is deprecated. This is because we cannot determine the names of the signal parameters at compile time. Furthermore, also for human readers it is difficult to discern between arguments, context properties, properties of the current object, and properties of the root object of the component. Requiring the signal parameters to be explicitly named resolves some of this confusion. You can turn the deprecation warning off using the "qt.qml.compiler" and "qt.qml.context" logging categories. Task-number: QTBUG-89943 Pick-to: 6.1 Change-Id: If0a5082adb735a73efd793868b3a55bc7d694cbe Reviewed-by: Mitch Curtis <mitch.curtis@qt.io> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> Reviewed-by: Andrei Golubev <andrei.golubev@qt.io>
* QML: Warn about variables being used before their declarationUlf Hermann2021-02-111-1/+18
| | | | | | | | | | | | | | | | | | This collides with injected signal parameters. qmlcachegen cannot tell those cases apart. [ChangeLog][QML][Important Behavior Changes] QML warns about JavaScript variables being used before their declaration now. This is almost always a mistake. It is particularly dangerous in the presence of injected signal parameters because qmlcachegen cannot identify a name collision between an injected signal parameter and a variable being used before its declaration. It therefore miscompiles such code. You can turn off the deprecation warning using the "qt.qml.compiler" logging category. Pick-to: 6.1 Task-number: QTBUG-89943 Change-Id: I8a9424ca8c6edd562402fe5c560ba7e8344b5585 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* Port QtDeclarative from QStringRef to QStringViewKarsten Heimrich2020-06-161-3/+3
| | | | | | | | 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>
* Restore offset/length in QQmlJS::DiagnosticMessageSimon Hausmann2020-03-021-3/+2
| | | | | | | | | | | | This is needed in a few places outside of declarative, so this change restores the loc member in DiagnosticMessage and moves QQmlJS::AST::SourceLocation into common's QQmlJS namespace/directory. QQmlError is unaffected and retains only line/column. Amends d4d197d06279f9257647628f7e1ccc9ec763a6bb Change-Id: Ifb9d344228e3c6e9e26fc4fe112686f9336ea2b2 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* qml/parser: Implement nullish coalescingMaximilian Goldstein2019-12-051-0/+34
| | | | | | | | | | Implements the '??' operator as specified in https://github.com/tc39/proposal-nullish-coalescing. Also adds a few tests. Task-number: QTBUG-77926 Change-Id: I3993450c192d11bf1ade0662d945c1553b4c6976 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* Add (and ignore for now) type assertions to QMLUlf Hermann2019-11-271-1/+3
| | | | | | | | | | You can write "(something as Foo)" to give hints to any tools that you expect something to be a Foo at this place. This is not a conversion and ignored at runtime for now. Eventually the compiler will verify that the type assertions are plausible and error out if they aren't. Change-Id: I21c8705bb387f7ab2cbc153293dbf477663afe87 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* Split compiler and runtime more clearlyUlf Hermann2019-07-111-1/+0
| | | | | | | | Provide different export macros and different top level headers for each, don't include runtime headers from compiler sources. Change-Id: I7dc3f8c95839a00a871ba045ec65af87123154be Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
* Disentangle includes and namespacesUlf Hermann2019-07-111-0/+1
| | | | | | | | Avoid using namespace in headers and include only the headers we actually need. Change-Id: I526a0f874dc09b07693fd87070665be396d3b637 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
* Add basic type annotation support for QML functions to the grammarSimon Hausmann2019-07-091-0/+8
| | | | | | | | | | | | | | | | | | | | | | | | | Inspired by TypeScript syntax, allow optional type annotations in the style of ": <name of type>" in for the parameters of functions and their return type. These annotations are not used at the moment, so by default we produce an error message when encountering them in the AST. In addition their usage is limited to functions declared in the QML scope. All other uses attempt to produce readable syntax errors. So for example this is okay: Item { function blah(param: string) string { ... } } And this is not okay: // some file.js function blah(param: string) : string { ... } Change-Id: I12d20b4e2ce92e01108132975a06cfd13ba4a254 Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
* Simplify codegen error handlingUlf Hermann2019-07-041-148/+141
| | | | | | | | | | There can only ever be one error, either a syntax error or a reference error. We record the error type as we want to get rid of the virtual throw<X>Error methods in favor of an explicit compilation result. Change-Id: Ie228490aad8efb7885083f6485f931299567f54c Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>