The goal is to get closer to the possibility of using Owl without the
compiler. This commit removes Portal dependency on the compiler, and
opens the way to register pre-compiled template functions.
This commit reworks the props validation code in order to extract a
generic validate utility function. The validation should be more robust,
with better error messages, and at the same time, it supports `*` in a
shape object.
And as a bonus, it is now typesafe, and the static props object is now
typed.
closes#1190
Previously, the support for the "in" operator was iffy, and "new" was
not supported at all, "in" would fail when checking if a nested property
was in something else, as the leading space would be stripped, and "new"
would fail because the following space would be stripped.
This commit fixes that by preserving the significant whitespace where
necessary.
Previously, components would automatically call useState on their props,
so that changes deeply within props would automatically cause the
component to be rendered. This can be useful when passing a piece of
state to children or descendants.
One problem with this is that all props implicitly become reactive, even
if the object that was passed as a props was not. The problem with that
being that since the original object is not reactive, any change made by
the parent will not go through the reactivity system and the children
won't be notified of the change, in essence, this reactive object is
essentially useless, while having a real cost: traversing reactive
objects creates more reactive objects, and those objects are all
proxies. This is expensive for basically no benefit, while also making
it more difficult to debug code that involves those objects.
This commit fixes that by only calling useState on objects that are
already reactive, allowing the usecase described in the first paragraph
without the drawbacks described in the second.
With this commit, props validation error messages will include a more
developer-friendly error message, avoiding the need to investigate in
the Developer Tools why a complex props structure is invalid.
If you declare a child component which is not actually a Component,
the error message is not very friendly and not very helpfull to find
what happens and which child component is wrong.
```
const ChildComponent = "not a component constructor";
class MyComponent extends Component {
static components = { ChildComponent };
}
```
This commit improves the type declaration for those working with Typescript
and adds a runtime check for javascript codebases
Before this commit, there were 2 different ways of generating variable
identifiers. And it was possible to have a situation with two different
variable in a template with the same identifier, which caused a crash.
This commit ensures that we go through a unique helper method, so this
cannot occur anymore. Also, the code is slightly simpler.
Previously, we used an option to allow duplicate templates, if that
option was passed, we would always replace the existing template with
the new template, and if it wasn't, we would always throw an error even
if the template's content was the same.
Allowing to replace a template with a different one is problematic, as
it may or may not have already been compiled, which may cause various
problems. On the other hand, if the template is the same, there is no
point in throwing an error, as we can just silently ignore the second
addition.
Previously, if a fiber was delayed because one of its ancestors was
rendering, and that fiber was not a root fiber, it would be rendered
after all its ancestors had finished rendering even if one of those
ancestor renderings cancelled it.
This commit fixes that by simply checking that a delayed fiber is still
its component node's current fiber before rendering it.
With this commit, we make sure that the `render` method was explicitely
called with the deep === true argument, instead of assuming that it is a
boolean. This prevents errors when some unrelated value is given to the
render method. This could happen in some cases, such as
useBus(someBus, 'someevent', this.render)
In that case, the `useBus` code would simply call the this.render with a
customevent, which would be considered truthy before, and not anymore
Before this commit, the list of all children was managed at the level of
the root fiber, but this could cause issue when subfibers would be
reused. With this commit, we use the childrenMap object that exists on
each fiber instead.
Canceling a fiber may cause user code to be run, which means that some
new renderings could be scheduled, but this could interfere with the
current renderings!
A little typo was preventing a dynamic t-slot with a scope
(`<t t-slot="{{ state.name }}" myScope="someValue" />`)
to work properly.
This commit corrects this.
Before this commit, a t-set-slot that has no content was not even compiled, and thus not passed
to the component for which it has was defined
After this commit, we allow a t-set-slot to have no content (because it can have slot props)
This is a breaking semantic change. With this commit, the UI is frozen
whenever owl is waiting for a parent to change
Also, this allows Owl not to render components that will be removed
later.
Previously, calling the batched function from within the callback being
batched would fail as it would be treated as part of the same batch.
This commit fixes that by scheduling the reset of the "called" flag
before calling the callback. This means that all microtasks that were
already in the microtask queue when a batch is about to run are treated
as part of the batch, and all microtasks that will be added by the
callback are not.
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.
In 3536f41f00 we added a fallback when setting a
property to a falsy value so that the property was set to the empty string. The
objective being to not get the string "undefined"/"null"/"false" as property
value. However, using t-att- to set a property to 0 is perfectly reasonable and
in fact quite common.
This commit adds a warning when an async hook
(onWillUpdateProps/onWillStart) takes longer than 3 seconds, as these
hooks block the rendering and patching of the application, it is rarely
desirable and often a sign of a deadlock. This warning will contain the
stack trace of the call to the hook to help in debugging.
Before this commit, if the effect function would throw, then the cleanup
function would not be properly assigned, which caused additional errors
later, when the cleanup code would try to call it.
closes#1149
Previously, we were wrapping the entire renderFn in a try/catch, causing
errors during template execution to be caught and wrapped by
onWillRender/onRendered which is undesirable. Now we only wrap the hook
that's being registered.
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
Previously, a crash in a lifecycle hook for any reason would throw an
error whose stack trace started from the scheduler and contained only
the place where the hook was called by owl, but not the place where the
hook was registered by the user. This proved very difficult for users to
debug as they cannot really tell which component registered that hook.
This commit alleviates the issue by creating a new Error when the hook
is originally called, and wrapping the registered callback in a try
catch, throwing an error with the correct stack trace instead of the
error in the hook, and setting the error in the hook as the cause of
this synthetic error.