The way keys were handled in QWeb was mostly ok, but a little naive. It
is fine when we deal with a list of dom nodes, since the reconciliation
algorithm need only to be able to differentiate/reconcile nodes in that
list, but it is an issue with components, which needs to globally be
able to find themselves in their parent's children map.
Because of the way this was handled, there were situations were Owl
internal virtual dom would crash, since components wrongly assumed that
they were already rendered in a different place.
To fix this, we generalize the way keys are generated, by concatenating
all sub keys coming from each iteration loops.
closes#584
Since t-call is now a function call, we need to properly handle the
internal key used to find previous components. If a t-call is inside a
t-foreach, then we need to transfer the key to the sub template.
Otherwise, each component in the subtemplate will be associated to the
same key, which means that it will lead to big issues: components are
destroyed and reused...
closes#581
Before this commit, when template was t-call'ed and defined
t-component directive within it, there was a crash because extra.parent was never defined
After this commit, this use case works
While it is not tested, nor documented, the reference QWeb
implementation display the `false` value as "false". So, we have to
adapt the Owl implementation to match that behaviour.
At the same time, this commit uses 'let' instead of 'var' in various places,
to make the compiled code more consistant.
Before this commit, the handlers were bound to the current context,
which is often the component but not necessarily. In some cases, a sub
scope can be created (with t-foreach, or slots, or t-call), and the
context is actually an object with the actual component instance it its
prototype chain, but not the component.
- In some cases, we can simply inline a template key instead of assigning
it to a variable and then using that variable
- Add component name in generated code for components
This commit is a significant refactoring of the internal of QWeb. It
simplifies the way variables/scoping and slots interact together. The
main idea is that we use a simple scope object instead of a
context/var/scope object.
This commit also implement the actual correct QWeb semantic for the
t-call directive with a sub body. Before, we simply extracted the
variables from the body and injected them at the top of the sub
template. We now simply compile the body before the sub template.
This is a joint work with Lucas (lpe).
closes#541closes#544closes#545closes#557closes#556
This is a really interesting problem: there was a situation where a
component would not have an event handler properly bound. The reason was
that we were in a situation where the scheduler task queue was flushed
at an unfortunate timing:
- parent component template is rendered
- subcomponent is prepared:
- sub component is willStarted
- it is rendered (so, fiber counter is set to 0)
- scheduler task queue is flushed => we patch the DOM
- the code registered in the __prepare.then(handler) is executed, which
add the createHook to the vnode (but after the dom is patched)
Usually, the last two steps happen in a different order, but in an
environment with connected components, we sometimes flush the task queue
at various moments, so some code could be executed between the end of
__prepare and the registered handler.
The fix is interesting: we give a callback to the __prepare function
instead of registering a .then handler to the deferred. This callback
is then guaranteed to be called at exactly the proper timing.
Thanks seb for the hard work of finding the root cause of this issue
closes#520
Following 2922cee6ea
Previous commit was not correct: used children with a cancelled
fiber (for instance, with a new currentFiber) could be destroyed.
This commit fixes the issue differently, by directly detecting
children that are not used anymore (and not mounted), and destroy
them directly (no need to wait for willStart promise to be resolved
anymore).
We don't see any usecase for it, it makes the code more complex,
and there were still potential unresolved concurrency issues with
it.
Part of task #295
Before this rev., default values weren't taken into account when
validating props whenever a component was updated. Moreover, there
was no test attesting that props were validated at update.
it is not useful to do it in the component directive, especially since
it is done in the constructor, and the default props are not applied.
closes#379
With this commit, we can now do this:
const SUBTEMPLATE = xml`<span><t t-esc="state.n"/></span>`
class Parent extends Widget {
static template = xml`<div><t t-call="${SUBTEMPLATE}"/></div>`
state = {n: 42};
}
Big change! This commit introduces an xml function tag to easily define
inline templates.
This is a pretty big change toward single file owl components
Part of #284