# v2.1.2
- [FIX] t-out: does not crash when outputting null
- [FIX] playground: fix name of playground component
- [FIX] playground: use ES owl version instead of iife
- [IMP] playground: give a name so it is more explicit in devtools
- [REF] github page: move page to docs folder on master branch
- [IMP/FIX] playground: fix and improve various things
Before this commit, doing `t-out="null"` would crash, since the
safeOutput function would assume that it is a block, thanks to the fact
that `typeof null === 'object'`.
We handle here the null value just as if it was undefined: it outputs an
empty string.
Currently, some of the things on the playground must be changed directly
on the master branch while other things require checking out the
gh-pages branch and making the modifications there. Even when changes
need to be made on the master branch, all changes that are not direcly
in owl itself need to be copied by hand to the gh-pages branch.
This commit moves all files that exist on the gh-pages branch to the
master branch in the docs folder, this change will require configuring
the github page to use the docs folder instead of a separate branch, but
will make maintenance of the github page and playground easier going
forward.
The playground hasn't been touched for a while and a few things were
broken before this commit:
- Exporting as a standalone web application was broken because it still
attempted to load the templates like it was done in owl 1
- Resizing the editor tabs still tried to use `this.trigger`
While fixing the export feature, the files needed by the app were
factored out of hardcoded strings and into real files, as this makes it
easier to maintain, since these files get syntax highlighting.
The samples received the same treatment: there is now a `samples` folder
containing all the samples, it also contains a jsconfig, giving
autocompletion on owl functions while editing the files, and allowing
the owl import to look how it would when using owl as a node_module.
In the browser, this import is translated to the relative path of the
owl module using an import map.
# v2.1.1
- [FIX] components: solve missing update (concurrency issue)
- [DOC] remove old references to comp for useRef hook
- [FIX] devtools: Fix build commands for windows users
- [FIX] devtools: Fix devtools in detached window
- [IMP] devtools: Add a button to navigate to the doc
- [IMP] devtools: Add devtools documentation
- [IMP] Allow app to be mounted in shadow DOM
- [IMP] playground: allow sharing playground links
- [IMP] runtime: allow validating object values using a type description
- [FIX] devtools: Increase vertical padding of the search bar
- [FIX] devtools: Hide the collapse all button
- [FIX] devtools: Fix bad computation of highlight boxes on the page
- [FIX] package: Auto-update package-lock.json
Before this commit, in some specific situations, owl could skip updating
the DOM, even though it should. Here is what could happen:
- we have a parent component (A) and a child component (B)
- B depends on some reactive props from A
- we update some state that results in A being rendered, and B updated
- before this render is applied to the dom, we update some state again,
which causes A to be rendered again
- however, this new render is such that the B props are now identical,
so it will skip rendering B
- it will then apply the result of the render to the DOM => only A is
updated but B should also be updated!
The problem comes from the fact that Owl committed the props to the
component right after the rendering, to the new props were used in the
props comparison method to decide if B should be updated. This is
incorrect, we should always use the current props to decide what to do,
and only commit them to the component after it has been patched.
Going from owl 1.0 to 2.0, we removed the possibility of having a
reference to a component. However, the documentation was not properly
updated to reflect that.
This is useful to share editable snippets of owl code, which can be used
to paste a reproduction for a given issue or give someone an interactive
example of some feature.
In JS, objects are often used as a mapping that gives fast lookup on the
keys, in those cases, the keys themselves are not known in advance, but
the values may have a shape that they're expected to follow. This commit
adds support for a `values` key in schema for objects, which will be
checked against all values in the object during validation.
This commit adds box-sizing: border-box to the highlight elements
created by the devtools on the page. This was making some of the
boxes overflow on some pages (like on POS sessions) because
the border-box box-sizing was not the default behavior on these
pages.
This commit adds the devtools as a zip file containing both chrome
and firefox versions of the extension in the release and also updates
the doc to install it easily.
This commit adds the code of the owl devtools extension.
This extension can be added on chrome or on firefox for
developpers to be able to inspect the contents of all owl
applications that are present on any web page, see all the
components, interract with them and their content to some
extend and perform a bit of profiling with their renders.
`onWillPatch`, `onWillUnmount`, `onWillDestroy` are synchronous hooks.
Owl will not wait any promise return by the callback.
Yet, the callback return type includes `Promise<void>`,
which is confusing as one might think it means the hooks is async.
It is not really useful, but it is possible to bind an anonymous
function prop. However, with the recent change on how the bind feature
works, it now crashes.
This commit makes sure that we properly apply the `bind` operation to
the function, and not to the last term of the function.
It is common in Owl components to have anonymous function as props.
However, since each rendering create a different (but equivalent)
closure, Owl will consider the props different, so will update the child
component, but this is (often) not necessary.
This commit will help reduce the problem by introducing a new `.alike`
prop suffix, that will let Owl know that each version of that specific
prop should be considered the same, so, will be ignored by the props
comparison code.
closes#1360
Before this commit, the version number was added by the rollup
configuration script. It worked, but it meant that there was no robust
way to access the version number in many case. For example, what if I
have a page with two different version of owl? Or what if one of them
uses the ESM module system, and does not export owl as a global object?
This is not really a big deal, but accessing the version number is
useful for tooling purpose, so this commit makes it possible to read the
version number on each individual App, as a static property.
Previously, refs could get set to null incorrectly, or could stay set
when they shouldn't. This was caused by the fact that singleRefSetter
and multiRefSetters are created on every render, meaning that any render
that did not affect the status of the ref (mounted or not), would
overwrite the previous ref setter, including its closure, causing the
captured `_el` or `count` to be lost. This means that on a subsequent
render that did affect the status of the ref, the singleRefSetter would
consider that it did not set the ref, and so shouldn't unset it, causing
it to incorrectly stay keep the element, while in multiRefSetter, the
opposite problem occured: the count would be 0 on removal, causing it to
believe that it was the first call in the corresponding patch that
affected the ref, when in fact, the closure is already stale, because it
was created from the previous render, and the fresh multiRefSetter from
the latest render may already have been called by an element with that
ref that came earlier in the template.
This commit changes the ref setting strategy to work around the issue of
stale closures: we define a setRef method on ComponentNode that is
always called, this method ignores calls with `null`, meaning that the
refs object on the ComponentNode never reverts to a null value for any
key. Instead, the useRef hook will check whether the element that the
ref points to is still mounted, and return null if not.
Before this commit, the parser would remove all consecutive white spaces
for text nodes. After that, the code generator would call the translate
function with the resulting string, which then is different than what we
would expect.
With this commit, we make sure we apply the translation before removing
the additional whitespace. To do that, we have to move the code
processing the string from the parser into the code generator, which
actually makes sense, as the parser should only collect all useful
information without applying too much logic.
closes#1351
Before this commit, Owl template compiler would handle readonly
attribute as readonly properties. But this is incorrect, since the
property is actually named readOnly.
With this commit, we make sure that readonly AND readOnly are both
interpreted as the `readOnly` property. This is due to the fact that
QWeb does not discriminate between attribute and properties, so we have
to infer which is which.
closes#1362
Before this commit, properties were just handled as a special case of
attributes. But it does not make that much sense, since they are
different. For example, the `readOnly` property does not have the same
name as the `readonly` attribute. The confusion probably comes from the
fact that QWeb does not distinguish between property and attributes, so
Owl has to infer which one is which.
With this commit, we introduce a `block-property` directive in blockdom,
and change the compiler to use it in emitted code. It has the additional
benefits of slightly shrinking the runtime code, since the `isProp`
function can now be located in the compiler.
In #1161, we fixed blockdom treating 0 as falsy when patching a value,
which would result in an empty attribute. It turns out that there is
another place where we had the same fallback, which is when we compute a
dynamic attribute value, so while blockdom had the ability to set the
value to 0, when using a dynamic attribute value we would never give it
0 as a value. This commit changes the fallback strategy for dynamic
attribute values to be the same as the one in blockdom.
closes#1358
Have a t-ref on a DOM node with a t-key.
Change the t-key.
Before this commit, the old block removed its element from the component's refs *after*
the new block had been mounted, meaning that in effect, the resulting
ref at the end of the whole patch was null.
After this commit, we only remove an element from the component's ref if that very same
element was indeed the ref. (otherwise it means someone else has changed the ref.)
# v2.0.6
- [IMP] devtools: provide access to Fiber and RootFiber
- Bump shelljs and git-rev-sync
- [FIX] props validation: do not subscribe to props keys
- [FIX] reactivity: only show key in subscription if observed by callback
- [FIX] components: stop rendering stale t-component when delayed
In dev mode, owl inserts an additional props validation step. Before
this commit, the validation would iterate on all key/value pairs of each
props. If the props is reactive, this has the unfortunate side effect of
subscribing the component to each of the keys, even though it should not
be.
This commit avoids the issue by only validating the raw object.
Previously, the getSubscriptions debugging utility returned all observed
keys for a given target, instead of only the keys observed by the
callback it received as argument. This commit fixes that issues.
Previously, if the value of a t-component directive changed, but there
was already a scheduled render for the component before that change, the
rendering of the existing component would get delayed (as it should),
but after the parent's rendering was complete, the old component which
will be destroyed during the patch would still get rendered, despite
being stale. This can cause crashes if that component relies on state
that no longer exists.
This was caused by the fact that when rendering, we check the parent
chain for an active render, and also check that the component still
exists in the parent's fiber childrenMap (ie, we know that the upcoming
patch is not about to destroy the component). To do this, we use the
component's parentKey, but in the case of t-component, the parentKey for
both possible components is the same, causing the stale component to
incorrectly believe that it's not about to be destroyed, by finding the
next component in the childrenMap under the same key.
This commit fixes that by prepending the component's name to the
parentKey, meaning that if the value of the t-component changes, so will
the key, and the render will be further delayed until the new state is
patched, at which point the stale component will be destroyed and the
following attempt to render will be cancelled as expected.
The choice to use the component's name is to simplify the
implementation, this means that if using t-component and switching
between components that have the same class name, this protection will
not work. The alternative would be to generate a unique id for the
component class, eg with a WeakMap, but this both complicates the
implementation and adds runtime overhead, for a case that is likely
extremely rare. We are open to refine the implementation should this
problem occur in practice.
Previously, when having a long lived reactive object and writing a lot
of keys to it, clearing the reactive subscriptions on that object would
slow down as time went on. This is because when clearing a target's
subsctiptions for a callback, we look at all the keys that are observed, and for all
the observed keys, we remove the callback from the set of callbacks
observing that key. The problem arises from the fact that after doing
that, even if the set of callbacks observing that key is now empty, we
don't remove the key from the observed keys, meaning that any further
clearing of subscriptions will have to iterate over that key to attempt
to clear the callbacks even if there are none.
This commit fixes this problem by simply removing the key from the
observedKeys if there are no longer any callbacks observing it.
This commit also improves performance for bare reactives (reactives
created with no callback). The initial implementation simply creates a
default empty callback when creating a reactive, and treats it like any
other, meaning it can observe keys and be notified of changes even
though we know in advance that it does nothing. This can compound with
the previous issue when you're doing a lot of manipulations on a bare
reactive internally for the sole purpose of notifying outside observers,
as this creates a lot of useless work in the reactivity system.
Compiling a template with a dash ("-") in its name generates an
invalid function name in the compiled code.
A template named `"my-component"` leads to the function
`function my-component(app, bdom, helpers) { ... }` which has an
invalid name.
closes#1333
Previously, if you were not the last person to publish to the
playground, your playground branch would be behind the remote and trying
to push to it would fail.
This commit attempts to pull the changes before updating owl so that
even if you were not the last person to push to the playground, as long
as the pull is a fast-forward, publishing to the playground won't fail.
This commit also adapts some of the status number manipulation to use
bitwise or instead of addition, since return status code can be both
positive or negative and may cancel one another. Using bitwise or
ensures than any non-zero code will make the status non-zero and stay
that way.