This crash was caused by the fact that Proxies *must* return the value of the
property on the target when that property is non-writeable and
non-configurable. Since the reactivity system always attempts to proxify the
value from the target, this crashes.
This commit fixes that by not proxifying such values. This however means that
from that point on, we have escaped the reactivity system and will not
subscribe to any changes in that object or its children.
This allows to see which objects and which keys in those objects a
component is observing, so that issues with missing renders or extra
renders can be more easily diagnosed.
With this commit, component only render child
components if they have different props (shallow
equality). Otherwise, we trust the reactivity
system to make sure that all impacted components
are updated
This commit makes the reactivity system more fine grained and makes it
more eager to stop observing keys or objects when they are modified,
this results in fewer "false positive" notifications.
t-out automatically escaped content when it is a string not marked
with the `markup` function
t-out renders the raw content if it is a Block, or if it has been marked
with the `markup` funtion.
t-esc has been kept since it is safe and is optimized to render text nodes.
all t-raw calls are in fact the same as t-out.
The deletion of a key in an observed object did clear the observers of
that key but did not clear the atoms created (if any) when the key existed
(e.g. on the key value if it was trackable). This can lead to a growing
set of atoms that are useless but kept in memory if a lot of keys are
added/deleted. The same thing can happen if a key value is changed many
times and the values are trackable.
Here we fix the problem by
- keeping tracks of the objects that have been observed by an external call
to the method "atom" (we call them seeds).
- remove all observer atoms that are not seeds for observers of at least
one key deletion or key value change.
Note the fix is in some sense partial: a user could use the "atom" primitive
making the new system uncapable of avoiding a leak (see test "atom on an
object with a getter 3" where a getter is used in a weird way in an
observed object).
Aim to replace the abstraction "Context" from OWL 1 with the new primitives
"atom" and "useState":
- notification is done only after a batch of modifications.
- observers are notified at most once for a batch.
- an observer of type component is notified (and rerendered)
only if it does not have an ancestor that has to be notified for the
same batch of operations (anywhere in the web of references!).
- notification of components is done on all levels "simultaneously".
Co-authored-by: Aaron Bohy <aab@odoo.com>
Co-authored-by: Géry Debongnie <ged@odoo.com>
Co-authored-by: Mathieu Duckerts-Antoine <dam@odoo.com>
fine grained reactivity:
existing key in source changes --> only observer having read the key are notified
add/delete key in source changes --> all source observers are notified
Co-authored-by: Aaron Bohy <aab@odoo.com>
Co-authored-by: Géry Debongnie <ged@odoo.com>
Co-authored-by: Mathieu Duckerts-Antoine <dam@odoo.com>