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
A component can now be mounted in different positions: either 'before' (at
the start), 'after' (at the end), or 'attach' (take possession of a target
element)
closes#539
Before this commit, when manually unmounting the portal
or one of its parents, the teleported elements were not cleaned
and stayed teleported forever
After this commit, the teleported content is brought back and
unmounted much like any component
closes#531
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
The component Portal is used to teleport the content
in its slot as a child of an element
somewhere else in the DOM, usually 'body'
It is designed to be transparent and is just here to do the teleportation task
OwlEvents (with method `Component.trigger`) are redirected from
any Component instanciated within the Portal (and therefore teleported
somewhere else) to the place it would have been without teleportation
i.e. they are re-triggered onto the Portal root node
Co-authored-by: Aaron Bohy <aab@odoo.com>
closes#184closes#466
Have a t-call having a t-raw="0"
that call is made to a template of the same form
i.e. itself as a t-call t-raw="0" structure
Before this commit, there was recursion crash
This was because the caller to which a t-raw="0" referred to
was incorrect. The caller here is the node which makes the t-call.
In particular, the caller was always set to last caller of the context
After this commit, there is no crash and this imbrication
of t-call and t-raw="0" is well rendered.
To sum up, we count the recursive calls to t-raw="0" and fetch
the caller in the context accordingly
closes#510
Before this rev, using t-component on a div (for example) node
would silently ignore the div and replace it by the root node of
the component. A way to improve this was to create an extra div
node and to put the component inside it. However, it raised
questions: what do we do with other attributes set on this tag?
Do we apply them on the div, or on the component? In addition,
some of them only make sense on the component (e.g. props), so we
have to detect them. Whatever we would have decided, it wouldn't
have been obvious from the user point of view, so we chose not to
support it, and we thus now raise an error in this case.
Closes#487.
It is important to reset the isRendered flag to false to ensure
that other (subsequent) simultaneous calls to render will be
skipped, as the currentFiber is actually no yet (re-)rendered.
Closes#483
We learn something new every day, and today is no exception. Promise.all
of a pending promise does not actually resolve as fast as possible after
the initial promise is completed, but a small delay after, because it is
put on the macrotask queue or something like that (I assume)
closes#480
It could happen that a component would crash. But then, the __render
code tried to copy the class properties into the vnode, which does not
exist, creating a new error.
So, the solution is to process the classObj only in the successful part
of the render call, which then will not crash, so the normal error
handling will occur.
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).
Owl takes care of not rendering a component that will be unmounted
immediately after, and it works. However, it also should clean
up the newly added fiber.
This rev. moves the logic of batching the notifications of changes
occurring in the same microtask tick, from the observer, to the
listeners (the context, and the render function of components).
By doing so in render, we ensure that similar renderings are
batched in a single one, wherever they come from (state change,
store change, direct call...).