In order to determine whether an ID is visible from a referrer we need
not only determine the component boundaries of the referrer, but also
those of the candidate elements with the respective ID. Rewrite the
logic to have QQmlJSScopesById handle this. It has to iterate the
respective elements anyway and can therefore easily check if one of them
is assigned to an unknown property. It now provides low-level methods
that output all possible candidates for an ID, while also stating the
confidence associated with them. The plain id() and scope() methods only
return results we are actually certain about.
In places where we generate warnings or can allow for some fuzzy
results, we use the low-level methods, since those generally produce
more informative results.
The QML DOM was passing the JavaScript global object as referrer to the
scope() method before. This happened to work but was, of course, wrong.
Make sure that ID elements in the DOM receive a proper QML scope to
avoid that.
Pick-to: 6.10 6.9 6.8
Task-number: QTBUG-140041
Change-Id: I41cf8603ae6a5d5461d3c12d74521e68b5e28ea4
Reviewed-by: Sami Shalayel <sami.shalayel@qt.io>
Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
If the binding throws an exception, the binding wrapper internally
returns false. This should result in the value being discarded. We had a
long standing bug in qtbase that caused the value to still be accepted
in certain cases. Commit 440a63a33e7176167d91244467fa380bae684173 fixed
that.
Fixes: QTBUG-140161
Change-Id: Ib36a32909dc3d487bea887cb7f89d7fcfeca2031
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
You can override a QObject method with a JavaScript function and take
away the JavaScript function later by swapping out objects. This should
not crash.
Pick-to: 6.10 6.9
Fixes: QTBUG-140074
Change-Id: I85b17f4f619235024d0f1a27b4ff4128c7a57083
Reviewed-by: Sami Shalayel <sami.shalayel@qt.io>
If a QObject is returned from a method call, the QML engine takes
ownership of it and it needs to be deleted by the garbage collector. Our
generated C++ code so far did not actually take ownership of the object
and thereby caused it to leak.
Pick-to: 6.10 6.9 6.8
Fixes: QTBUG-138919
Change-Id: I7bd57b3612bf4b98937756e8a7a7c03aff1c9b32
Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
Keep them in a special generated struct with virtual method that gets
called from the GC for each frame.
Pick-to: 6.10 6.9 6.8
Fixes: QTBUG-139059
Change-Id: I81bcbeab6531e174a5207d03f57d241461ae9ba3
Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
While the Sequence 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.
We don't have to store the sequence on the JS heap if it cannot store a
QObject. Only lists of variants or pointers are affected.
This independently fixes QTBUG-129972 for 6.8 where
VariantAssociationObject does not exist, yet. This is because the
detached sequence shown in that bug won't need to be written back to
anymore in order to stay up to date.
Pick-to: 6.10 6.9 6.8
Fixes: QTBUG-129972
Task-number: QTBUG-139025
Change-Id: Ib469c6c65f2f96041e2ad2fd106f8cd60a182e13
Reviewed-by: Sami Shalayel <sami.shalayel@qt.io>
Without this, it tries to resolve the metaObject of QVariantMap, which
crashes.
Fixes: QTBUG-139626
Pick-to: 6.10 6.9 6.8
Change-Id: I9248f57c428810024f9983df959f475e6557576c
Reviewed-by: Sami Shalayel <sami.shalayel@qt.io>
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>
Component.onDestruction can be used to execute some code as an object is
being destructed. The code may, however, reference objects that are no
longer in a valid state because they themselves have already been
destructed. We then throw an exeception.
Commit a741271dd5 introduced the init step
for calls in which the types of arguments are resolved. For object
methods, we need to check that the object is still valid or throw an
exception otherwise. This is made more complicated by the fact that, in
some cases, the destruction of the object happens in a somewhat chaotic
manner where, for instance, the object is still alive but its method and
property storage has already been deleted.
This inconsistent state is the cause of QTBUG-138516 and existing checks
for invalid objects were not sufficient and we crashed when trying to
use the function that we were unable to resolve. We can detect this
particular problem by checking whether the ddata of the object still has
its jsWrapper.
Amends a741271dd5
Fixes: QTBUG-138516
Pick-to: 6.10 6.9
Change-Id: Ifdd7708d73ea6012d1e07aebed257b3f538183c1
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Flags declared with Q_FLAGS lack the methods for properly extracting the
typedef'd name. We need to manually register the typedef.
Amends commit 8bf5aae19b.
Pick-to: 6.10 6.9 6.8
Fixes: QTBUG-138174
Change-Id: I7c373f4d810a0c9a5590f39cc629015662a69ed4
Reviewed-by: Sami Shalayel <sami.shalayel@qt.io>
When trying to resolve all aliases on an object, we iterate over them
one by one. If all are resolved successfully, we return
AllAliasesResolved and consider this object done, if an alias fails, we
return NoAliasResolved or SomeAliasesResolved and we will try again
later. This can be the case for aliases to aliases. We defer resolving
the first one until the target alias is resolved first.
There was a bug in the logic that counts how many of the aliases were
successfully resolved and how many were skipped. When skipping an alias
to an alias, we cannot count it among the completed ones.
This leads to an alias not being resolved and added to the property
cache. Thankfully, a runtime assert then catches the discrepancy between
the number of aliases in the property cache and in the compilation unit.
Early exit when detecting that the alias points to a non-local
unresolved alias to try again later. Also update the aliasIndex as part
of the for loop update.
Amends 9e1378260a
Pick-to: 6.10
Change-Id: I6ee7a796a0b4890393d5b17ebea2686c55955394
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
Now that we discern internal and external side effects, we cannot
implicitly rely on every jump to generate a side effect anymore. We need
to actually update the virtual registers and also merge the side effects
(along with other flags).
Amends commit 6b14ba5c2f
Pick-to: 6.10 6.9 6.8 6.5
Task-number: QTBUG-137540
Change-Id: I6b46c7a4773759c8f6f30308ba72082555ce3e61
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
inlineConsoleMethod's stringConversion needs to create a string, so that
we can later append to it. Because we were missing parentheses, this did
not happen, and we would end up with code looking like
u']'.append(...)
which obviously isn't valid C++. Fix this by always adding parentheses
around the expression.
Found while trying to prove that QTBUG-109279 was fixed.
Task-number: QTBUG-109279
Pick-to: 6.10 6.9
Change-Id: I67fce5b2c1f1460a5d6b617824f3c36f9804ea76
Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
A mere jump does not cause all value types and lists to be invalidated.
Only calls to other functions or writes to other properties do that.
Pick-to: 6.10 6.9 6.8 6.5
Fixes: QTBUG-137540
Change-Id: I069c6873455c51bbea59cf876d2bc7ecd188f81b
Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
Stack-created lists of primitives or pointers cannot be affected by side
effects. We cannot write a value affected by side effects to a list that
isn't, though.
Pick-to: 6.10 6.9 6.8 6.5
Task-number: QTBUG-137540
Change-Id: I99ab4337cabc6111a81b8164fd94962edc0db25e
Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
We use the JavaScript extension as "read" type to signify that the code
generator will accept any type with such an extension. This requires
some adjustments in the type resolver.
Pick-to: 6.10 6.9 6.8 6.5
Task-number: QTBUG-137540
Change-Id: Ia34ca0a24c417c5372852268ba2f55825484639d
Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
[ChangeLog][QML] It is now possible to access unscoped enum values in a
scoped way as <component name>.<enum name>.<key>. Previously, it was
only possible to access them in an unscoped way.
Task-number: QTBUG-116513
Change-Id: Iff56cd3365516215e1e195a147fae66ee17d39e3
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
In the type propagator, when encountering back jumps, we need to run the
pass again in order to ensure that the state of the registers at the
target of the jump is fully known.
For this, we need to compare the latest state in the current pass with
states we have encountered earlier. If a match is found, no more passes
are needed.
The propagation is run multiple times and state is accumulated between
passes. For certain conversions, this will try to append types as
origins again every iteration. These would previously have been
deduplicated by QQmlJSTypeResolver::merge but, since the change at
1e095058e1, we consider 2 registers to be
equal only if their d pointers are equal. And since instructions such as
MoveRegexp create a new register for the literal type RegExpr every
time, the pointer doesn't match with the one from the register created
by the instruction during the ealier pass. This would lead to set of
origin types growing forever and to the state never matching a previous
one. This, in turn, caused an infinite loop because an additional pass
was always deemed necessary.
Therefore, restore the old logic that deduplicates based on contained
type, variant, and (recursively) scope.
Amends 1e095058e1
Fixes: QTBUG-135457
Pick-to: 6.9
Change-Id: I23167e95b958304698d12537598c1d72b03a5364
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
There is nothing to do in the compiler.
Setting the value of the property is already handled in by the object
creator or the qobjectwrapper.
Reading the value doesn't really makes sense and defeats its purpose .
Fixes: QTBUG-134790
Pick-to: 6.9 6.8
Change-Id: I4576eb528e0dec273830b0244149a92ceb325bc9
Reviewed-by: Sami Shalayel <sami.shalayel@qt.io>
Never use module-wide inclusions. They blow up build times. For QtTest
this is usually just a typo (QTest was meant instead). Add missing
includes as needed.
In the diffs I've spotted other huge inclusions (QtQuick, QtQml), but
those need more attention.
Task-number: QTQAINFRA-7110
Pick-to: 6.9 6.8
Change-Id: I74bf3fe212f50a7a3a6af2b1c80bbcaabc2516d7
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
We already do this for return types, but it's fatal on any type.
Pick-to: 6.9
Fixes: QTBUG-135342
Change-Id: I7aee2a19ffcd39d2707eceb34b5073057d8b5ebb
Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
If we can determine that the base of an optional lookup cannot hold null
or undefined, we can simply omit the optional part and generate a
regular get lookup. This is also true whenever we lookup an enum.
Amends fc4ee77116
Fixes: QTBUG-135649
Pick-to: 6.9 6.8
Change-Id: I64984fdecc75cd4dbc2274a08aa73b5274fb09b7
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
We've resolved the value type in the type propagator. Trying to do it
again in the code generator, after the iterator may have been adjusted,
is quite wrong. If we resolve the list value type on a type that's not
a list (anymore), then we get an invalid type, which subsequently
crashes.
Amends commit a173d50a9e.
Pick-to: 6.9 6.8
Fixes: QTBUG-135288
Change-Id: I1227803ed100c83f8fc11898be0a4d0199d639dd
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
This works the same as the FINAL attribute to Q_PROPERTY.
Task-number: QTBUG-98320
Change-Id: Icc2cf1afb5354fd711770f7147ded853b74cd1da
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
Reviewed-by: Sami Shalayel <sami.shalayel@qt.io>
Those have several possible representations. Besides
QQmlValueTypeWrapper, they can also be their own special heap objects
with extra methods, or VariantObject.
Also, remove some pointless restrictions in QmlCompiler that prevented
such as-casts from being compiled to C++. The code generator will
currently reject non-trivial type assertions for value types. Therefore
we don't have to take care of ValueTypeBehavior: Assertable, yet.
Also fix tst_qqmllanguage::instanceOf() to actually test something. So
far the return value of the expression was ignored for most data tags.
Pick-to: 6.9
Fixes: QTBUG-130291
Change-Id: I2facf48455a04a02a078615e5ebd4b1c26d1bd93
Reviewed-by: Sami Shalayel <sami.shalayel@qt.io>
We need to perform the redirection before inserting imports into
namespaces. Through the redirection we might discover a module that we
have already imported before. In that case we must not import it again.
Pick-to: 6.9 6.8
Fixes: QTBUG-133587
Change-Id: I47a279461763b5397137002a9e7c7d3bfc7ad15d
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Those are not mapped to regular QMetaMethods but rather come with
special method indices and need to be resolved separately.
Amends commit a741271dd5
This exposes that the override order between JavaScript extensions and
their base types was wrong. JavaScript extensions do certainly not
override their base types. Fix this, too.
We also need to always specialize the lookups for these calls. It
doesn't actually matter if there is propertyData or not since we branch
off into the special cases anyway when calling them.
Pick-to: 6.9
Fixes: QTBUG-132602
Change-Id: Iea83ce94459b0d0a3bf54731898fd62b9ad46c46
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
While those properties may be of type Component, they don't have to. We
can in fact not resolve anything resembling an ID while inside one of
those objects because we cannot determine the component boundaries.
Amends commit dea8e38d95
Pick-to: 6.9 6.8
Fixes: QTBUG-133460
Change-Id: Iac7294166d38ce591c45c0d31b139a52eda70fc1
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
The actual conversion code suggests that we may be creating a shared
list property. However, the assignment code internally won't let that
happen. Test as much.
Amends commit 3108c58b97
Task-number: QTBUG-133047
Change-Id: I66f0f043e0dabd2693aa50a30478461a5db5c5ad
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Reviewed-by: Sami Shalayel <sami.shalayel@qt.io>
At run time, not all the builtins are always available, but only those
hardcoded into the parser. If we always import all the builtins at
compile time, we introduce subtle errors when they shadow parts of the
JavaScript global object.
Now the builtins need to be actually imported. We cannot rely on the
magic that adds them to the root scope of each document anymore. To this
end, they need to become a regular module.
The builtins are now loaded using a qmldir, just like any other module.
The only thing special about is its "system" attribute which we now
take to mean "read jsroot.qmltypes". Furthermore, the builtins get a
"static" attribute so that we don't warn about them being unused. Even
though they can now technically be unused, we really want people to
still import them.
Pick-to: 6.9 6.8
Fixes: QTBUG-133461
Change-Id: I322e14ba85c939773d36143ca24e88a7c9db23f5
Reviewed-by: Sami Shalayel <sami.shalayel@qt.io>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
The comparison code was generated properly but the conversion to safely
assign the result of the comparison to the out accumulator was missing.
Amends 78b58582ba
Fixes: QTBUG-133636
Pick-to: 6.9 6.8
Change-Id: I9f790b449b48c382064954ad4235d25d221f1168
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
The QML module uses private headers; currently, this works because
qmlcachegen implicitly links the generated code against the QmlPrivate,
but we want to move away from that.
Task-number: QTBUG-87776
Pick-to: 6.9 6.8
Change-Id: If15d7b0549510ee97729e450523776691747f151
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
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>
Before the refactoring of callObjectPropertyLookup and
initCallObjectPropertyLookup this was done via a check on the resulting
function. This check is in the init method now. However, after
initialization, you can still call the (pre-resolved) method on a nullptr.
Therefore, we need a second check.
The method counts as pre-resolved even if we re-fetch it due to a
variant lookup. We can be sure that there is some method in that case
after all.
Amends commit a741271dd5
Pick-to: 6.9
Fixes: QTBUG-132499
Change-Id: Idb8c50f3698c5502cf2e8116e6341ef1a537bc64
Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
Since it's documented like this, we should actually allow it.
Pick-to: 6.9 6.8 6.5
Task-number: QTBUG-132118
Change-Id: I2192f040b8fdf545b8dbb0687b6e618a9858ed07
Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
The regular int32 coercion doesn't apply here. We have our own logic for
this case.
Pick-to: 6.9 6.8
Task-number: QTBUG-132345
Change-Id: I96596567ce83fcaa714c8372171261e8dd876480
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
The conversion is not required to produce the same type. It can also
produce something equivalent that holds the same value. For example an
integer of a different kind that on assignment gets C++-converted.
Pick-to: 6.9 6.8
Task-number: QTBUG-132345
Change-Id: I07accb38062b7c89ab60d50bf6cbd63423e68301
Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
It's not necessary anymore. We can use the read register as-is. Also,
explicitly name the type we are going to use to avoid integer range
mismatches on coercion.
Pick-to: 6.9 6.8
Task-number: QTBUG-132345
Change-Id: I98d246b03e5194235246ee8e4ebcb0a8e0094a5b
Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
The type of the register may not be the one to be passed to the method.
We cannot rely on the run time internals to coerce the value anymore
since we've moved the type determination out of the generated code.
To make this happen, we need to adjust the storage types of read
registers in the storage generalizer.
Pick-to: 6.9
Fixes: QTBUG-132329
Change-Id: I642027f349f7c05f714ec36ef4e23f9d59b4a8df
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
Now that Pane reflects its explicitly set contentWidth/Height through
implicitContentWidth/Height we can use the same expression for implicit
width/height as regular controls, which hooks us into the safe area
binding loop detection as well.
Pick-to: 6.9
Change-Id: Ie31b740a1e405341fc5f0ed9673b213292e4afd9
Reviewed-by: Oliver Eftevaag <oliver.eftevaag@qt.io>
When constructing a value type, we cannot just assume that the
most-derived type holds all the properties. We may encounter properties
from base types. Resolve those via QMetaProperty.
Pick-to: 6.9 6.8
Fixes: QTBUG-131980
Change-Id: I8e1773ccb42f86b96457c990ae5bc6486ae1acdc
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Define a pair of lookup methods for this and generate code that uses
them. Write back after calling a non-const method.
Task-number: QTBUG-127174
Change-Id: I6de22e76b63390fd7159d9c14ea2c908d961ec97
Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
With SetLookup there is always the possibility of causing a reset by
passing undefined. That's why we need to wrap the argument into QVariant
most of the time. SetValueLookup didn't take this into account, which
resulted in invalid code.
The test also reveals that a number of cases were generating different
errors depending on whether the code was run in interpreted or compiled
mode. Align those.
Pick-to: 6.8
Task-number: QTBUG-127174
Change-Id: I88f45977dcd0eeba8aaf580663d4b85b8bb26f72
Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
Reviewed-by: Alexey Edelev <alexey.edelev@qt.io>
As requested in qtbase/5d174877234477a59eb29818d3cfb99fedc3e704.
Change-Id: I5f6568921a25918a5ae3fffdff7c136d3eb455a9
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
On the engine side, types made available with QML_USING are recognizable
by their QMetaType conversions. In order to actually call the right
methods, we need to slightly prefer methods to whose arguments we can
convert over ones we have not idea about. This, however, adds the
problem of converting to QString, double, QVariant and QJSValue, which
is possible for any type. Since such conversions are less specific than
manually added converters, we de-prioritize them a bit.
On the compiler side we need to transmit the knowledge about the
overload to be called from the compiler (which has already done its own
overload selection) to the lookup methods. This is easily done using the
relative method index. This way we do not need to do any run time
overload selection at all and we do not need to pass any types to the
lookup methods. We can do this without further compatibility adaptations
because the current version of those lookup methods was only introduced
in 6.9.
Excluded, of course, are shadowable calls, which are performed with only
QVariant arguments. These carry the arguments themselves and trigger the
engine's overload selection. Internally nothing changes about them.
Passing a list of QMetaType::fromType<QVariant>() to the lookup methods
for them has always been a waste.
Only the engine changes are relevant for 6.8. In 6.8, the lookup methods
defer the overload selection to the engine and take the types on every
call. We still cannot separate the engine changes from the compiler
changes in dev because the same test is run once in interpreted and once
in compiled mode.
Pick-to: 6.8
Task-number: QTBUG-127174
Change-Id: I6ab52ddf3be65dcc94547266c5dcc5ac1050c93c
Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
qmlcachegen will never generate code that calls these with mismatched
types. Checking the type at run time is wasteful. With QML_USING, you
can make qmlcachegen generate code with types we cannot recognize as
compatible. However, those need to be layout-compatible so that they
can be reinterpret_cast'ed into each other. If they aren't that's a user
error in C++. We can crash on such a thing.
However, in StoreNameSloppy and in the variant lookup cases, we do need
to convert types. Since the QML_USING type conversions are unknown to
the QML engine, we have to provide a fallback via QMetaType::convert()
here. So, despite the layout compatibility requirement, the QML_USING
types also need to register metatype converters before any QML code
accesses them.
As a result QML_USING has quite a few complicated requirements now and
is _really_ dangerous.
Pick-to: 6.8
Task-number: QTBUG-127174
Change-Id: I1b8e1595e3088415ce711e910586a5dd456cb2c5
Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>