Compare commits
79 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9dcbbe54eb | |||
| e94428a186 | |||
| 941190dfa8 | |||
| a53e42518f | |||
| b7c37ca69a | |||
| 34489a2494 | |||
| 398df543fe | |||
| aa6a4a5d46 | |||
| db3499f5e5 | |||
| 166cada8ff | |||
| acbe316689 | |||
| fb013ccc72 | |||
| fee3eecd7f | |||
| 6037018dd2 | |||
| eec7cc4ea7 | |||
| 035895b043 | |||
| ff5ef82ea2 | |||
| 0048205636 | |||
| 0d341d9e7b | |||
| 4c7f572dbe | |||
| 610c272104 | |||
| 32e4565131 | |||
| 9b9c15e4a9 | |||
| b1690f19cc | |||
| 5dcee2564c | |||
| 752160fd85 | |||
| 3937966b74 | |||
| e7ebb92104 | |||
| c78e070636 | |||
| 610ed02373 | |||
| 4b23f51974 | |||
| b25e988628 | |||
| e0758c0e9e | |||
| ba34811f71 | |||
| 28672096a2 | |||
| 9823a4e7dd | |||
| 105ec7ced8 | |||
| 8f9ad987b9 | |||
| 6050827689 | |||
| 9b1ec5dc0e | |||
| 9b1c270501 | |||
| 9d99f8936b | |||
| 7bc9d34a64 | |||
| b1a3b322ee | |||
| ca688d8640 | |||
| ea9f533536 | |||
| 875ebdcfb0 | |||
| 2e07799250 | |||
| 0d9d21a5c1 | |||
| 836e12b1c5 | |||
| 7538aeae0e | |||
| 3e9ba9ca8e | |||
| e4c296a7d2 | |||
| 44748270da | |||
| 8b1dc4c43d | |||
| c105c6da38 | |||
| 3001420a1d | |||
| 432ff444a1 | |||
| aa3c88a6c4 | |||
| 601a98e649 | |||
| 23c7d19ef0 | |||
| 59c49b5833 | |||
| 2cca0bd819 | |||
| fbf4c4add2 | |||
| 78d6ff735e | |||
| a7f51fa666 | |||
| 5175f95289 | |||
| 3c9f4a8ae9 | |||
| 310730782c | |||
| 77a413d750 | |||
| fe31f93c94 | |||
| 9cc0f88e02 | |||
| 412fda10fd | |||
| aa441274c7 | |||
| ba20267151 | |||
| aabb7559b8 | |||
| 606d14a399 | |||
| c049022798 | |||
| cae32c5bd4 |
@@ -15,7 +15,7 @@ yarn-debug.log*
|
|||||||
yarn-error.log*
|
yarn-error.log*
|
||||||
|
|
||||||
#ide's
|
#ide's
|
||||||
.vscode
|
**/.vscode/*
|
||||||
.idea
|
.idea
|
||||||
|
|
||||||
node_modules
|
node_modules
|
||||||
@@ -26,3 +26,10 @@ release-notes.md
|
|||||||
|
|
||||||
# useful in some cases
|
# useful in some cases
|
||||||
/temp
|
/temp
|
||||||
|
|
||||||
|
# owl-vision
|
||||||
|
*/owl-vision/out/
|
||||||
|
*/owl-vision/.vs/
|
||||||
|
**/*.vsix
|
||||||
|
!*/owl-vision/.vscode/launch.json
|
||||||
|
!*/owl-vision/.vscode/tasks.json
|
||||||
|
|||||||
@@ -357,7 +357,7 @@ cleaning operation, since the component may be destroyed before it has even been
|
|||||||
mounted. The `willDestroy` hook is useful in that situation, since it is always
|
mounted. The `willDestroy` hook is useful in that situation, since it is always
|
||||||
called.
|
called.
|
||||||
|
|
||||||
The `onWillUnmount` hook is used to register a function that will be executed at
|
The `onWillDestroy` hook is used to register a function that will be executed at
|
||||||
this moment:
|
this moment:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
@@ -451,5 +451,6 @@ console.log(status(component));
|
|||||||
// logs either:
|
// logs either:
|
||||||
// - 'new', if the component is new and has not been mounted yet
|
// - 'new', if the component is new and has not been mounted yet
|
||||||
// - 'mounted', if the component is currently mounted
|
// - 'mounted', if the component is currently mounted
|
||||||
|
// - 'cancelled', if the component has not been mounted yet but will be destroyed soon
|
||||||
// - 'destroyed' if the component is currently destroyed
|
// - 'destroyed' if the component is currently destroyed
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -51,8 +51,8 @@ that render its content, and a fallback if an error happened.
|
|||||||
```js
|
```js
|
||||||
class ErrorBoundary extends Component {
|
class ErrorBoundary extends Component {
|
||||||
static template = xml`
|
static template = xml`
|
||||||
<t t-if="error" t-slot="fallback">An error occurred</t>
|
<t t-if="state.error" t-slot="fallback">An error occurred</t>
|
||||||
<t t-else="" t-slot="content"`;
|
<t t-else="" t-slot="default"/>`;
|
||||||
|
|
||||||
setup() {
|
setup() {
|
||||||
this.state = useState({ error: false });
|
this.state = useState({ error: false });
|
||||||
|
|||||||
@@ -190,12 +190,13 @@ will then be updated accordingly.
|
|||||||
### `useExternalListener`
|
### `useExternalListener`
|
||||||
|
|
||||||
The `useExternalListener` hook helps solve a very common problem: adding and removing
|
The `useExternalListener` hook helps solve a very common problem: adding and removing
|
||||||
a listener on some target whenever a component is mounted/unmounted. For example,
|
a listener on some target whenever a component is mounted/unmounted. It takes a target
|
||||||
|
as its first argument, forwards the other arguments to `addEventListener`. For example,
|
||||||
a dropdown menu (or its parent) may need to listen to a `click` event on `window`
|
a dropdown menu (or its parent) may need to listen to a `click` event on `window`
|
||||||
to be closed:
|
to be closed:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
useExternalListener(window, "click", this.closeMenu);
|
useExternalListener(window, "click", this.closeMenu, { capture: true });
|
||||||
```
|
```
|
||||||
|
|
||||||
### `useComponent`
|
### `useComponent`
|
||||||
|
|||||||
@@ -175,7 +175,7 @@ class Notebook extends Component {
|
|||||||
<div class="notebook">
|
<div class="notebook">
|
||||||
<div class="tabs">
|
<div class="tabs">
|
||||||
<t t-foreach="tabNames" t-as="tab" t-key="tab_index">
|
<t t-foreach="tabNames" t-as="tab" t-key="tab_index">
|
||||||
<span t-att-class="{active:tab_index === activeTab}" t-on-click="() => state.activeTab=tab">
|
<span t-att-class="{active:tab_index === activeTab}" t-on-click="() => state.activeTab=tab_index">
|
||||||
<t t-esc="props.slots[tab].title"/>
|
<t t-esc="props.slots[tab].title"/>
|
||||||
</span>
|
</span>
|
||||||
</t>
|
</t>
|
||||||
|
|||||||
@@ -376,15 +376,16 @@ An important difference should be made with the usual `QWeb` behaviour: Owl
|
|||||||
requires the presence of a `t-key` directive, to be able to properly reconcile
|
requires the presence of a `t-key` directive, to be able to properly reconcile
|
||||||
renderings.
|
renderings.
|
||||||
|
|
||||||
`t-foreach` can iterate on an array (the current item will be the current value)
|
`t-foreach` can iterate on any iterable, and also has special support for objects
|
||||||
or an object (the current item will be the current key).
|
and maps, it will expose the key of the current iteration as the contents of the
|
||||||
|
`t-as`, and the corresponding value with the same name and the suffix `_value`.
|
||||||
|
|
||||||
In addition to the name passed via t-as, `t-foreach` provides a few other
|
In addition to the name passed via t-as, `t-foreach` provides a few other useful
|
||||||
variables for various data points (note: `$as` will be replaced with the name
|
variables (note: `$as` will be replaced with the name passed to `t-as`):
|
||||||
passed to `t-as`):
|
|
||||||
|
|
||||||
- `$as_value`: the current iteration value, identical to `$as` for lists and
|
- `$as_value`: the current iteration value, identical to `$as` for arrays and
|
||||||
integers, but for objects, it provides the value (where `$as` provides the key)
|
other iterables, but for objects and maps, it provides the value (where `$as`
|
||||||
|
provides the key)
|
||||||
- `$as_index`: the current iteration index (the first item of the iteration has index 0)
|
- `$as_index`: the current iteration index (the first item of the iteration has index 0)
|
||||||
- `$as_first`: whether the current item is the first of the iteration
|
- `$as_first`: whether the current item is the first of the iteration
|
||||||
(equivalent to `$as_index == 0`)
|
(equivalent to `$as_index == 0`)
|
||||||
|
|||||||
@@ -35,13 +35,13 @@ The components tab is separated into two sub windows: the components tree in the
|
|||||||
the component details in the right. The components tree will display all the different
|
the component details in the right. The components tree will display all the different
|
||||||
components that are present in the tab in the form of a tree. The root of this tree is
|
components that are present in the tab in the form of a tree. The root of this tree is
|
||||||
actually the app which is not a component but can still be inspected by the devtools like
|
actually the app which is not a component but can still be inspected by the devtools like
|
||||||
one. There can also be multiple apps loaded in the page like in the following:
|
one. There can also be multiple apps loaded in the page like in website:
|
||||||
|
|
||||||
<img src="screenshots/multi_apps.png"/>
|
<img src="screenshots/multi_apps.png"/>
|
||||||
|
|
||||||
There is a convenient search bar at the top of the components tree which will help finding
|
There is a convenient search bar at the top of the components tree which will help finding
|
||||||
the components tou want in the tree and also, an element picker can be used to directly select
|
the components tou want in the tree and also, an element picker can be used to directly select
|
||||||
the component you want to focus on in the page which is especially useful when trying to find
|
the component you want to focus on in the page which is especially useful when 1trying to find
|
||||||
what you want. Just click on the elements picker icon and click on the element you want to focus
|
what you want. Just click on the elements picker icon and click on the element you want to focus
|
||||||
on in the page and it will be selected in the devtools accordingly. Hovering any element in the
|
on in the page and it will be selected in the devtools accordingly. Hovering any element in the
|
||||||
page in this mode will highlight it and the same happens anytime in the components tree.
|
page in this mode will highlight it and the same happens anytime in the components tree.
|
||||||
@@ -64,25 +64,18 @@ as its env, props, observed states and all the other variables that are present
|
|||||||
While the props and the env are already present on the actual instance of the component and are
|
While the props and the env are already present on the actual instance of the component and are
|
||||||
pretty explicit by themselves, the observed state value is a bit more complicated to grasp.
|
pretty explicit by themselves, the observed state value is a bit more complicated to grasp.
|
||||||
|
|
||||||
The observed state is actually information about which variables are observed by the component
|
The observed state is actually information about which variables are being observed by the component:
|
||||||
which will trigger a rerender of the component when it is modified. The keys represent which part of the
|
when any property of a reactive object is being read by the component, the component will subscribe
|
||||||
variable is actually observed and the target is the actual variable. For simplicity, the properties
|
to this property which means it will listen to any change that can occur on the property and render
|
||||||
that are not observed by the component are greyed out while the others are in bold. This means that
|
when such a change occurs. This can be visualized easily within the devtools inside of the observed
|
||||||
editing bold ones will trigger a rerender while the greyed out ones will not.
|
state section: observed properties of the reactive object(s) are displayed in bold while the others
|
||||||
|
are greyed out. Do keep in mind that a greyed out property in the observed state of one component
|
||||||
|
may be observed by another and the other way around is also possible. Here is an example for some
|
||||||
|
user Field component:
|
||||||
|
|
||||||
<img src="screenshots/states.png"/>
|
<img src="screenshots/states.png"/>
|
||||||
|
|
||||||
In the given example, we have two keys/target pairs for two different variables. The first one indicates
|
Navigation inside the properties is also similar to the one in console variables: properties have
|
||||||
that adding or removing an element to the array will trigger a rerender since the length will have changed.
|
|
||||||
Replacing the element at index 0, 1 or 2 will also have the same effect as implied by the keys. It doesn't
|
|
||||||
mean that editing the properties of element at index 0, 1 or 2 will rerender the component though. It may
|
|
||||||
be the case for some but this will be described in another keys/target pair. The second keys/target pair
|
|
||||||
is actually the element at index 0 of the first pair. It only has id in the keys meaning that only the
|
|
||||||
id property will actually trigger a rerender the component when modified. Be aware however that the other
|
|
||||||
properties may be in the observed state of another component like a child one in this case. A greyed out
|
|
||||||
property only implies it is not reactive for the selected component and not for the others.
|
|
||||||
|
|
||||||
The navigation inside the properties is also similar to the one in console variables: properties have
|
|
||||||
their prototype displayed and getters will get their value when clicked on (...). It is also possible to
|
their prototype displayed and getters will get their value when clicked on (...). It is also possible to
|
||||||
send any property to the console using the right-click context menu on it and functions can be inspected
|
send any property to the console using the right-click context menu on it and functions can be inspected
|
||||||
in the sources tab as well.
|
in the sources tab as well.
|
||||||
@@ -96,8 +89,10 @@ component's name. Using the left click on the component's name will focus it in
|
|||||||
It is also possible to edit any of the leaf node properties. To do so, you must double click on the
|
It is also possible to edit any of the leaf node properties. To do so, you must double click on the
|
||||||
property's value and modify it using the freshly created input then press enter to apply the changes.
|
property's value and modify it using the freshly created input then press enter to apply the changes.
|
||||||
Do note that the modified values should be written in JSON format in order to be valid (examples:
|
Do note that the modified values should be written in JSON format in order to be valid (examples:
|
||||||
89, "yes", undefined, null, \["hello", 15\], {"a": 1}, true, ...). Whether it has an impact on the
|
89, "yes", undefined, null, \["hello", 15\], {"a": 1}, true, ...). Editing any value will produce a
|
||||||
component or not and whether it produces an error is the responsability of the user.
|
manual render of the component (or the root component of the application in the case of env values).
|
||||||
|
Whether the edition has an impact on the component or not and whether it produces an error is the
|
||||||
|
responsability of the user.
|
||||||
|
|
||||||
<img src="screenshots/edit.png"/>
|
<img src="screenshots/edit.png"/>
|
||||||
|
|
||||||
@@ -117,7 +112,8 @@ are intercepted by the devtools using the record button.
|
|||||||
The second button is used to clear all the events that have been recorded. The select can be used to
|
The second button is used to clear all the events that have been recorded. The select can be used to
|
||||||
switch between the tree view (which shows the causality between renders) and the events log view which
|
switch between the tree view (which shows the causality between renders) and the events log view which
|
||||||
simply displays the events in the exact order they were triggered. In this view, you can expand the create,
|
simply displays the events in the exact order they were triggered. In this view, you can expand the create,
|
||||||
update and destroy events which reveals the component that initiated the event.
|
update and destroy events which reveals the component that initiated the event. Also, a transition line will
|
||||||
|
appear each time a new animation frame has been loaded between events.
|
||||||
|
|
||||||
<img src="screenshots/events_log.png"/>
|
<img src="screenshots/events_log.png"/>
|
||||||
|
|
||||||
@@ -131,20 +127,29 @@ There is also the Trace Renderings and Trace Subscriptions features. These featu
|
|||||||
recording of events and have no effect on the profiler tab. The Trace Renderings option is used to log in
|
recording of events and have no effect on the profiler tab. The Trace Renderings option is used to log in
|
||||||
the console all the render events and allows to show their traceback information. Similarly, the Trace
|
the console all the render events and allows to show their traceback information. Similarly, the Trace
|
||||||
Subscriptions option logs all the properties that caused a render event and also allows to see the traceback
|
Subscriptions option logs all the properties that caused a render event and also allows to see the traceback
|
||||||
of the modification
|
of the modification.
|
||||||
|
|
||||||
<img src="screenshots/trace_rendering.png"/>
|
<img src="screenshots/trace_rendering.png"/>
|
||||||
<img src="screenshots/trace_subscriptions.png"/>
|
<img src="screenshots/trace_subscriptions.png"/>
|
||||||
|
|
||||||
|
The Owl Devtools also allow to inspect iframes coded in Owl: when an Owl iframe is detected in the page,
|
||||||
|
the iframe selector will appear next to the tabs. This allows to switch from an iframe to another easily.
|
||||||
|
Be aware that switching iframes will clear all record events from the profiler tab. Iframes detection is
|
||||||
|
currently not working in the firefox version, we are aware of this issue and will try to address it in the
|
||||||
|
future.
|
||||||
|
|
||||||
|
<img src="screenshots/iframes.png"/>
|
||||||
|
|
||||||
## Options
|
## Options
|
||||||
|
|
||||||
The owl devtools extension has a dark mode feature which defaults to your general devtools settings and can
|
The owl devtools extension has a dark mode feature which defaults to your general devtools settings and can
|
||||||
be toggled using the sun/moon icon at the top-right corner of the tab. All the examples above were created
|
be toggled using the sun/moon icon at the top-right corner of the tab. There is also a refresh button to
|
||||||
with the dark mode enabled. There is also a refresh button to completely reset the owl devtools.
|
completely reset the owl devtools.
|
||||||
|
|
||||||
<img src="screenshots/darkmode.png"/>
|
<img src="screenshots/darkmode.png"/>
|
||||||
|
|
||||||
## Troubleshooting
|
## Troubleshooting
|
||||||
|
|
||||||
If the feedback from the page to the devtools seems to be cut, just close the devtools and refresh the page.
|
If the feedback from the page to the devtools seems to be cut, you can first try to use the refresh
|
||||||
|
button mentioned above but if it still doesn't seem to work, just close the devtools and refresh the page.
|
||||||
This will eventually happen any time a tab stays opened for too long without being refreshed.
|
This will eventually happen any time a tab stays opened for too long without being refreshed.
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 333 KiB After Width: | Height: | Size: 545 KiB |
|
Before Width: | Height: | Size: 210 KiB After Width: | Height: | Size: 387 KiB |
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 72 KiB |
|
Before Width: | Height: | Size: 197 KiB After Width: | Height: | Size: 266 KiB |
|
Before Width: | Height: | Size: 185 KiB After Width: | Height: | Size: 320 KiB |
|
After Width: | Height: | Size: 206 KiB |
|
Before Width: | Height: | Size: 166 KiB After Width: | Height: | Size: 329 KiB |
|
Before Width: | Height: | Size: 86 KiB After Width: | Height: | Size: 166 KiB |
|
Before Width: | Height: | Size: 311 KiB After Width: | Height: | Size: 536 KiB |
|
Before Width: | Height: | Size: 336 KiB After Width: | Height: | Size: 488 KiB |
|
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 36 KiB |
|
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 177 KiB |
|
Before Width: | Height: | Size: 146 KiB After Width: | Height: | Size: 182 KiB |
@@ -10,7 +10,7 @@
|
|||||||
<link rel="stylesheet" href="assets/milligram.css">
|
<link rel="stylesheet" href="assets/milligram.css">
|
||||||
<link rel="stylesheet" href="assets/highlight.tomorrow.css">
|
<link rel="stylesheet" href="assets/highlight.tomorrow.css">
|
||||||
<link rel="stylesheet" href="assets/main.css">
|
<link rel="stylesheet" href="assets/main.css">
|
||||||
<script src="./owl.js"></script>
|
<script type="importmap">{ "imports": { "@odoo/owl": "./owl.js" } }</script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<header class="container">
|
<header class="container">
|
||||||
@@ -68,7 +68,6 @@
|
|||||||
<p><a href=".">OWL</a> is licensed under LGPLv3.<br>Logo from <a href="https://github.com/googlefonts/noto-emoji">Google Noto Emoji Font</a>, licensed under Apache License 2.0</p>
|
<p><a href=".">OWL</a> is licensed under LGPLv3.<br>Logo from <a href="https://github.com/googlefonts/noto-emoji">Google Noto Emoji Font</a>, licensed under Apache License 2.0</p>
|
||||||
</footer>
|
</footer>
|
||||||
<script src="assets/highlight.pack.js"></script>
|
<script src="assets/highlight.pack.js"></script>
|
||||||
<script type="importmap">{ "imports": { "@odoo/owl": "./owl.js" } }</script>
|
|
||||||
<script type="module" src="display_code.js"></script>
|
<script type="module" src="display_code.js"></script>
|
||||||
<script type="module" src="counter.js"></script>
|
<script type="module" src="counter.js"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
@@ -83,65 +83,6 @@ function toggler(key, child) {
|
|||||||
// Custom error class that wraps error that happen in the owl lifecycle
|
// Custom error class that wraps error that happen in the owl lifecycle
|
||||||
class OwlError extends Error {
|
class OwlError extends Error {
|
||||||
}
|
}
|
||||||
// Maps fibers to thrown errors
|
|
||||||
const fibersInError = new WeakMap();
|
|
||||||
const nodeErrorHandlers = new WeakMap();
|
|
||||||
function _handleError(node, error) {
|
|
||||||
if (!node) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const fiber = node.fiber;
|
|
||||||
if (fiber) {
|
|
||||||
fibersInError.set(fiber, error);
|
|
||||||
}
|
|
||||||
const errorHandlers = nodeErrorHandlers.get(node);
|
|
||||||
if (errorHandlers) {
|
|
||||||
let handled = false;
|
|
||||||
// execute in the opposite order
|
|
||||||
for (let i = errorHandlers.length - 1; i >= 0; i--) {
|
|
||||||
try {
|
|
||||||
errorHandlers[i](error);
|
|
||||||
handled = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
error = e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (handled) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return _handleError(node.parent, error);
|
|
||||||
}
|
|
||||||
function handleError(params) {
|
|
||||||
let { error } = params;
|
|
||||||
// Wrap error if it wasn't wrapped by wrapError (ie when not in dev mode)
|
|
||||||
if (!(error instanceof OwlError)) {
|
|
||||||
error = Object.assign(new OwlError(`An error occured in the owl lifecycle (see this Error's "cause" property)`), { cause: error });
|
|
||||||
}
|
|
||||||
const node = "node" in params ? params.node : params.fiber.node;
|
|
||||||
const fiber = "fiber" in params ? params.fiber : node.fiber;
|
|
||||||
// resets the fibers on components if possible. This is important so that
|
|
||||||
// new renderings can be properly included in the initial one, if any.
|
|
||||||
let current = fiber;
|
|
||||||
do {
|
|
||||||
current.node.fiber = current;
|
|
||||||
current = current.parent;
|
|
||||||
} while (current);
|
|
||||||
fibersInError.set(fiber.root, error);
|
|
||||||
const handled = _handleError(node, error);
|
|
||||||
if (!handled) {
|
|
||||||
console.warn(`[Owl] Unhandled error. Destroying the root component`);
|
|
||||||
try {
|
|
||||||
node.app.destroy();
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
console.error(e);
|
|
||||||
}
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const { setAttribute: elemSetAttribute, removeAttribute } = Element.prototype;
|
const { setAttribute: elemSetAttribute, removeAttribute } = Element.prototype;
|
||||||
const tokenList = DOMTokenList.prototype;
|
const tokenList = DOMTokenList.prototype;
|
||||||
@@ -175,14 +116,24 @@ function createAttrUpdater(attr) {
|
|||||||
}
|
}
|
||||||
function attrsSetter(attrs) {
|
function attrsSetter(attrs) {
|
||||||
if (isArray(attrs)) {
|
if (isArray(attrs)) {
|
||||||
|
if (attrs[0] === "class") {
|
||||||
|
setClass.call(this, attrs[1]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
setAttribute.call(this, attrs[0], attrs[1]);
|
setAttribute.call(this, attrs[0], attrs[1]);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
for (let k in attrs) {
|
for (let k in attrs) {
|
||||||
|
if (k === "class") {
|
||||||
|
setClass.call(this, attrs[k]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
setAttribute.call(this, k, attrs[k]);
|
setAttribute.call(this, k, attrs[k]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
function attrsUpdater(attrs, oldAttrs) {
|
function attrsUpdater(attrs, oldAttrs) {
|
||||||
if (isArray(attrs)) {
|
if (isArray(attrs)) {
|
||||||
const name = attrs[0];
|
const name = attrs[0];
|
||||||
@@ -191,8 +142,13 @@ function attrsUpdater(attrs, oldAttrs) {
|
|||||||
if (val === oldAttrs[1]) {
|
if (val === oldAttrs[1]) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (name === "class") {
|
||||||
|
updateClass.call(this, val, oldAttrs[1]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
setAttribute.call(this, name, val);
|
setAttribute.call(this, name, val);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
removeAttribute.call(this, oldAttrs[0]);
|
removeAttribute.call(this, oldAttrs[0]);
|
||||||
setAttribute.call(this, name, val);
|
setAttribute.call(this, name, val);
|
||||||
@@ -201,17 +157,27 @@ function attrsUpdater(attrs, oldAttrs) {
|
|||||||
else {
|
else {
|
||||||
for (let k in oldAttrs) {
|
for (let k in oldAttrs) {
|
||||||
if (!(k in attrs)) {
|
if (!(k in attrs)) {
|
||||||
|
if (k === "class") {
|
||||||
|
updateClass.call(this, "", oldAttrs[k]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
removeAttribute.call(this, k);
|
removeAttribute.call(this, k);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
for (let k in attrs) {
|
for (let k in attrs) {
|
||||||
const val = attrs[k];
|
const val = attrs[k];
|
||||||
if (val !== oldAttrs[k]) {
|
if (val !== oldAttrs[k]) {
|
||||||
|
if (k === "class") {
|
||||||
|
updateClass.call(this, val, oldAttrs[k]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
setAttribute.call(this, k, val);
|
setAttribute.call(this, k, val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
function toClassObj(expr) {
|
function toClassObj(expr) {
|
||||||
const result = {};
|
const result = {};
|
||||||
switch (typeof expr) {
|
switch (typeof expr) {
|
||||||
@@ -286,20 +252,13 @@ function updateClass(val, oldVal) {
|
|||||||
* @returns a batched version of the original callback
|
* @returns a batched version of the original callback
|
||||||
*/
|
*/
|
||||||
function batched(callback) {
|
function batched(callback) {
|
||||||
let called = false;
|
let scheduled = false;
|
||||||
return async () => {
|
return async (...args) => {
|
||||||
// This await blocks all calls to the callback here, then releases them sequentially
|
if (!scheduled) {
|
||||||
// in the next microtick. This line decides the granularity of the batch.
|
scheduled = true;
|
||||||
await Promise.resolve();
|
await Promise.resolve();
|
||||||
if (!called) {
|
scheduled = false;
|
||||||
called = true;
|
callback(...args);
|
||||||
// wait for all calls in this microtick to fall through before resetting "called"
|
|
||||||
// so that only the first call to the batched function calls the original callback.
|
|
||||||
// Schedule this before calling the callback so that calls to the batched function
|
|
||||||
// within the callback will proceed only after resetting called to false, and have
|
|
||||||
// a chance to execute the callback again
|
|
||||||
Promise.resolve().then(() => (called = false));
|
|
||||||
callback();
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -751,12 +710,7 @@ function buildTree(node, parent = null, domParentTree = null) {
|
|||||||
info.push({ type: "child", idx: index });
|
info.push({ type: "child", idx: index });
|
||||||
el = document.createTextNode("");
|
el = document.createTextNode("");
|
||||||
}
|
}
|
||||||
const attrs = node.attributes;
|
currentNS || (currentNS = node.namespaceURI);
|
||||||
const ns = attrs.getNamedItem("block-ns");
|
|
||||||
if (ns) {
|
|
||||||
attrs.removeNamedItem("block-ns");
|
|
||||||
currentNS = ns.value;
|
|
||||||
}
|
|
||||||
if (!el) {
|
if (!el) {
|
||||||
el = currentNS
|
el = currentNS
|
||||||
? document.createElementNS(currentNS, tagName)
|
? document.createElementNS(currentNS, tagName)
|
||||||
@@ -772,6 +726,7 @@ function buildTree(node, parent = null, domParentTree = null) {
|
|||||||
const fragment = document.createElement("template").content;
|
const fragment = document.createElement("template").content;
|
||||||
fragment.appendChild(el);
|
fragment.appendChild(el);
|
||||||
}
|
}
|
||||||
|
const attrs = node.attributes;
|
||||||
for (let i = 0; i < attrs.length; i++) {
|
for (let i = 0; i < attrs.length; i++) {
|
||||||
const attrName = attrs[i].name;
|
const attrName = attrs[i].name;
|
||||||
const attrValue = attrs[i].value;
|
const attrValue = attrs[i].value;
|
||||||
@@ -1583,6 +1538,68 @@ function remove(vnode, withBeforeRemove = false) {
|
|||||||
vnode.remove();
|
vnode.remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Maps fibers to thrown errors
|
||||||
|
const fibersInError = new WeakMap();
|
||||||
|
const nodeErrorHandlers = new WeakMap();
|
||||||
|
function _handleError(node, error) {
|
||||||
|
if (!node) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const fiber = node.fiber;
|
||||||
|
if (fiber) {
|
||||||
|
fibersInError.set(fiber, error);
|
||||||
|
}
|
||||||
|
const errorHandlers = nodeErrorHandlers.get(node);
|
||||||
|
if (errorHandlers) {
|
||||||
|
let handled = false;
|
||||||
|
// execute in the opposite order
|
||||||
|
for (let i = errorHandlers.length - 1; i >= 0; i--) {
|
||||||
|
try {
|
||||||
|
errorHandlers[i](error);
|
||||||
|
handled = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
error = e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (handled) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return _handleError(node.parent, error);
|
||||||
|
}
|
||||||
|
function handleError(params) {
|
||||||
|
let { error } = params;
|
||||||
|
// Wrap error if it wasn't wrapped by wrapError (ie when not in dev mode)
|
||||||
|
if (!(error instanceof OwlError)) {
|
||||||
|
error = Object.assign(new OwlError(`An error occured in the owl lifecycle (see this Error's "cause" property)`), { cause: error });
|
||||||
|
}
|
||||||
|
const node = "node" in params ? params.node : params.fiber.node;
|
||||||
|
const fiber = "fiber" in params ? params.fiber : node.fiber;
|
||||||
|
if (fiber) {
|
||||||
|
// resets the fibers on components if possible. This is important so that
|
||||||
|
// new renderings can be properly included in the initial one, if any.
|
||||||
|
let current = fiber;
|
||||||
|
do {
|
||||||
|
current.node.fiber = current;
|
||||||
|
current = current.parent;
|
||||||
|
} while (current);
|
||||||
|
fibersInError.set(fiber.root, error);
|
||||||
|
}
|
||||||
|
const handled = _handleError(node, error);
|
||||||
|
if (!handled) {
|
||||||
|
console.warn(`[Owl] Unhandled error. Destroying the root component`);
|
||||||
|
try {
|
||||||
|
node.app.destroy();
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
}
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function makeChildFiber(node, parent) {
|
function makeChildFiber(node, parent) {
|
||||||
let current = node.fiber;
|
let current = node.fiber;
|
||||||
if (current) {
|
if (current) {
|
||||||
@@ -1632,8 +1649,7 @@ function cancelFibers(fibers) {
|
|||||||
let node = fiber.node;
|
let node = fiber.node;
|
||||||
fiber.render = throwOnRender;
|
fiber.render = throwOnRender;
|
||||||
if (node.status === 0 /* NEW */) {
|
if (node.status === 0 /* NEW */) {
|
||||||
node.destroy();
|
node.cancel();
|
||||||
delete node.parent.children[node.parentKey];
|
|
||||||
}
|
}
|
||||||
node.fiber = null;
|
node.fiber = null;
|
||||||
if (fiber.bdom) {
|
if (fiber.bdom) {
|
||||||
@@ -2057,7 +2073,7 @@ function basicProxyHandler(callback) {
|
|||||||
set(target, key, value, receiver) {
|
set(target, key, value, receiver) {
|
||||||
const hadKey = objectHasOwnProperty.call(target, key);
|
const hadKey = objectHasOwnProperty.call(target, key);
|
||||||
const originalValue = Reflect.get(target, key, receiver);
|
const originalValue = Reflect.get(target, key, receiver);
|
||||||
const ret = Reflect.set(target, key, value, receiver);
|
const ret = Reflect.set(target, key, toRaw(value), receiver);
|
||||||
if (!hadKey && objectHasOwnProperty.call(target, key)) {
|
if (!hadKey && objectHasOwnProperty.call(target, key)) {
|
||||||
notifyReactives(target, KEYCHANGES);
|
notifyReactives(target, KEYCHANGES);
|
||||||
}
|
}
|
||||||
@@ -2161,7 +2177,7 @@ function delegateAndNotify(setterName, getterName, target) {
|
|||||||
if (hadKey !== hasKey) {
|
if (hadKey !== hasKey) {
|
||||||
notifyReactives(target, KEYCHANGES);
|
notifyReactives(target, KEYCHANGES);
|
||||||
}
|
}
|
||||||
if (originalValue !== value) {
|
if (originalValue !== target[getterName](key)) {
|
||||||
notifyReactives(target, key);
|
notifyReactives(target, key);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
@@ -2360,6 +2376,9 @@ class ComponentNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
async render(deep) {
|
async render(deep) {
|
||||||
|
if (this.status >= 2 /* CANCELLED */) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
let current = this.fiber;
|
let current = this.fiber;
|
||||||
if (current && (current.root.locked || current.bdom === true)) {
|
if (current && (current.root.locked || current.bdom === true)) {
|
||||||
await Promise.resolve();
|
await Promise.resolve();
|
||||||
@@ -2385,7 +2404,7 @@ class ComponentNode {
|
|||||||
this.fiber = fiber;
|
this.fiber = fiber;
|
||||||
this.app.scheduler.addFiber(fiber);
|
this.app.scheduler.addFiber(fiber);
|
||||||
await Promise.resolve();
|
await Promise.resolve();
|
||||||
if (this.status === 2 /* DESTROYED */) {
|
if (this.status >= 2 /* CANCELLED */) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// We only want to actually render the component if the following two
|
// We only want to actually render the component if the following two
|
||||||
@@ -2403,6 +2422,18 @@ class ComponentNode {
|
|||||||
fiber.render();
|
fiber.render();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
cancel() {
|
||||||
|
this._cancel();
|
||||||
|
delete this.parent.children[this.parentKey];
|
||||||
|
this.app.scheduler.scheduleDestroy(this);
|
||||||
|
}
|
||||||
|
_cancel() {
|
||||||
|
this.status = 2 /* CANCELLED */;
|
||||||
|
const children = this.children;
|
||||||
|
for (let childKey in children) {
|
||||||
|
children[childKey]._cancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
destroy() {
|
destroy() {
|
||||||
let shouldRemove = this.status === 1 /* MOUNTED */;
|
let shouldRemove = this.status === 1 /* MOUNTED */;
|
||||||
this._destroy();
|
this._destroy();
|
||||||
@@ -2430,7 +2461,7 @@ class ComponentNode {
|
|||||||
this.app.handleError({ error: e, node: this });
|
this.app.handleError({ error: e, node: this });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.status = 2 /* DESTROYED */;
|
this.status = 3 /* DESTROYED */;
|
||||||
}
|
}
|
||||||
async updateAndRender(props, parentFiber) {
|
async updateAndRender(props, parentFiber) {
|
||||||
this.nextProps = props;
|
this.nextProps = props;
|
||||||
@@ -2963,12 +2994,20 @@ function prepareList(collection) {
|
|||||||
keys = collection;
|
keys = collection;
|
||||||
values = collection;
|
values = collection;
|
||||||
}
|
}
|
||||||
else if (collection) {
|
else if (collection instanceof Map) {
|
||||||
values = Object.keys(collection);
|
keys = [...collection.keys()];
|
||||||
keys = Object.values(collection);
|
values = [...collection.values()];
|
||||||
|
}
|
||||||
|
else if (Symbol.iterator in Object(collection)) {
|
||||||
|
keys = [...collection];
|
||||||
|
values = keys;
|
||||||
|
}
|
||||||
|
else if (collection && typeof collection === "object") {
|
||||||
|
values = Object.values(collection);
|
||||||
|
keys = Object.keys(collection);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
throw new OwlError("Invalid loop expression");
|
throw new OwlError(`Invalid loop expression: "${collection}" is not iterable`);
|
||||||
}
|
}
|
||||||
const n = values.length;
|
const n = values.length;
|
||||||
return [keys, values, n, new Array(n)];
|
return [keys, values, n, new Array(n)];
|
||||||
@@ -3158,14 +3197,25 @@ class TemplateSet {
|
|||||||
this.translateFn = config.translateFn;
|
this.translateFn = config.translateFn;
|
||||||
this.translatableAttributes = config.translatableAttributes;
|
this.translatableAttributes = config.translatableAttributes;
|
||||||
if (config.templates) {
|
if (config.templates) {
|
||||||
|
if (config.templates instanceof Document || typeof config.templates === "string") {
|
||||||
this.addTemplates(config.templates);
|
this.addTemplates(config.templates);
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
for (const name in config.templates) {
|
||||||
|
this.addTemplate(name, config.templates[name]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
static registerTemplate(name, fn) {
|
static registerTemplate(name, fn) {
|
||||||
globalTemplates[name] = fn;
|
globalTemplates[name] = fn;
|
||||||
}
|
}
|
||||||
addTemplate(name, template) {
|
addTemplate(name, template) {
|
||||||
if (name in this.rawTemplates) {
|
if (name in this.rawTemplates) {
|
||||||
|
// this check can be expensive, just silently ignore double definitions outside dev mode
|
||||||
|
if (!this.dev) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
const rawTemplate = this.rawTemplates[name];
|
const rawTemplate = this.rawTemplates[name];
|
||||||
const currentAsString = typeof rawTemplate === "string"
|
const currentAsString = typeof rawTemplate === "string"
|
||||||
? rawTemplate
|
? rawTemplate
|
||||||
@@ -3221,7 +3271,7 @@ class TemplateSet {
|
|||||||
}
|
}
|
||||||
callTemplate(owner, subTemplate, ctx, parent, key) {
|
callTemplate(owner, subTemplate, ctx, parent, key) {
|
||||||
const template = this.getTemplate(subTemplate);
|
const template = this.getTemplate(subTemplate);
|
||||||
return toggler(subTemplate, template.call(owner, ctx, parent, key));
|
return toggler(subTemplate, template.call(owner, ctx, parent, key + subTemplate));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
@@ -3809,7 +3859,7 @@ class CodeGenerator {
|
|||||||
createBlock(parentBlock, type, ctx) {
|
createBlock(parentBlock, type, ctx) {
|
||||||
const hasRoot = this.target.hasRoot;
|
const hasRoot = this.target.hasRoot;
|
||||||
const block = new BlockDescription(this.target, type);
|
const block = new BlockDescription(this.target, type);
|
||||||
if (!hasRoot && !ctx.preventRoot) {
|
if (!hasRoot) {
|
||||||
this.target.hasRoot = true;
|
this.target.hasRoot = true;
|
||||||
block.isRoot = true;
|
block.isRoot = true;
|
||||||
}
|
}
|
||||||
@@ -3832,7 +3882,7 @@ class CodeGenerator {
|
|||||||
if (ctx.tKeyExpr) {
|
if (ctx.tKeyExpr) {
|
||||||
blockExpr = `toggler(${ctx.tKeyExpr}, ${blockExpr})`;
|
blockExpr = `toggler(${ctx.tKeyExpr}, ${blockExpr})`;
|
||||||
}
|
}
|
||||||
if (block.isRoot && !ctx.preventRoot) {
|
if (block.isRoot) {
|
||||||
if (this.target.on) {
|
if (this.target.on) {
|
||||||
blockExpr = this.wrapWithEventCatcher(blockExpr, this.target.on);
|
blockExpr = this.wrapWithEventCatcher(blockExpr, this.target.on);
|
||||||
}
|
}
|
||||||
@@ -3875,6 +3925,10 @@ class CodeGenerator {
|
|||||||
})
|
})
|
||||||
.join("");
|
.join("");
|
||||||
}
|
}
|
||||||
|
translate(str) {
|
||||||
|
const match = translationRE.exec(str);
|
||||||
|
return match[1] + this.translateFn(match[2]) + match[3];
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* @returns the newly created block name, if any
|
* @returns the newly created block name, if any
|
||||||
*/
|
*/
|
||||||
@@ -3952,8 +4006,7 @@ class CodeGenerator {
|
|||||||
let { block, forceNewBlock } = ctx;
|
let { block, forceNewBlock } = ctx;
|
||||||
let value = ast.value;
|
let value = ast.value;
|
||||||
if (value && ctx.translate !== false) {
|
if (value && ctx.translate !== false) {
|
||||||
const match = translationRE.exec(value);
|
value = this.translate(value);
|
||||||
value = match[1] + this.translateFn(match[2]) + match[3];
|
|
||||||
}
|
}
|
||||||
if (!ctx.inPreTag) {
|
if (!ctx.inPreTag) {
|
||||||
value = value.replace(whitespaceRE, " ");
|
value = value.replace(whitespaceRE, " ");
|
||||||
@@ -4005,11 +4058,6 @@ class CodeGenerator {
|
|||||||
}
|
}
|
||||||
// attributes
|
// attributes
|
||||||
const attrs = {};
|
const attrs = {};
|
||||||
const nameSpace = ast.ns || ctx.nameSpace;
|
|
||||||
if (nameSpace && isNewBlock) {
|
|
||||||
// specific namespace uri
|
|
||||||
attrs["block-ns"] = nameSpace;
|
|
||||||
}
|
|
||||||
for (let key in ast.attrs) {
|
for (let key in ast.attrs) {
|
||||||
let expr, attrName;
|
let expr, attrName;
|
||||||
if (key.startsWith("t-attf")) {
|
if (key.startsWith("t-attf")) {
|
||||||
@@ -4125,7 +4173,10 @@ class CodeGenerator {
|
|||||||
const idx = block.insertData(setRefStr, "ref");
|
const idx = block.insertData(setRefStr, "ref");
|
||||||
attrs["block-ref"] = String(idx);
|
attrs["block-ref"] = String(idx);
|
||||||
}
|
}
|
||||||
const dom = xmlDoc.createElement(ast.tag);
|
const nameSpace = ast.ns || ctx.nameSpace;
|
||||||
|
const dom = nameSpace
|
||||||
|
? xmlDoc.createElementNS(nameSpace, ast.tag)
|
||||||
|
: xmlDoc.createElement(ast.tag);
|
||||||
for (const [attr, val] of Object.entries(attrs)) {
|
for (const [attr, val] of Object.entries(attrs)) {
|
||||||
if (!(attr === "class" && val === "")) {
|
if (!(attr === "class" && val === "")) {
|
||||||
dom.setAttribute(attr, val);
|
dom.setAttribute(attr, val);
|
||||||
@@ -4167,7 +4218,7 @@ class CodeGenerator {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.addLine(`let ${block.children.map((c) => c.varName)};`, codeIdx);
|
this.addLine(`let ${block.children.map((c) => c.varName).join(", ")};`, codeIdx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return block.varName;
|
return block.varName;
|
||||||
@@ -4270,7 +4321,7 @@ class CodeGenerator {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.addLine(`let ${block.children.map((c) => c.varName)};`, codeIdx);
|
this.addLine(`let ${block.children.map((c) => c.varName).join(", ")};`, codeIdx);
|
||||||
}
|
}
|
||||||
// note: this part is duplicated from end of compilemulti:
|
// note: this part is duplicated from end of compilemulti:
|
||||||
const args = block.children.map((c) => c.varName).join(", ");
|
const args = block.children.map((c) => c.varName).join(", ");
|
||||||
@@ -4299,18 +4350,18 @@ class CodeGenerator {
|
|||||||
}
|
}
|
||||||
this.addLine(`for (let ${loopVar} = 0; ${loopVar} < ${l}; ${loopVar}++) {`);
|
this.addLine(`for (let ${loopVar} = 0; ${loopVar} < ${l}; ${loopVar}++) {`);
|
||||||
this.target.indentLevel++;
|
this.target.indentLevel++;
|
||||||
this.addLine(`ctx[\`${ast.elem}\`] = ${vals}[${loopVar}];`);
|
this.addLine(`ctx[\`${ast.elem}\`] = ${keys}[${loopVar}];`);
|
||||||
if (!ast.hasNoFirst) {
|
if (!ast.hasNoFirst) {
|
||||||
this.addLine(`ctx[\`${ast.elem}_first\`] = ${loopVar} === 0;`);
|
this.addLine(`ctx[\`${ast.elem}_first\`] = ${loopVar} === 0;`);
|
||||||
}
|
}
|
||||||
if (!ast.hasNoLast) {
|
if (!ast.hasNoLast) {
|
||||||
this.addLine(`ctx[\`${ast.elem}_last\`] = ${loopVar} === ${vals}.length - 1;`);
|
this.addLine(`ctx[\`${ast.elem}_last\`] = ${loopVar} === ${keys}.length - 1;`);
|
||||||
}
|
}
|
||||||
if (!ast.hasNoIndex) {
|
if (!ast.hasNoIndex) {
|
||||||
this.addLine(`ctx[\`${ast.elem}_index\`] = ${loopVar};`);
|
this.addLine(`ctx[\`${ast.elem}_index\`] = ${loopVar};`);
|
||||||
}
|
}
|
||||||
if (!ast.hasNoValue) {
|
if (!ast.hasNoValue) {
|
||||||
this.addLine(`ctx[\`${ast.elem}_value\`] = ${keys}[${loopVar}];`);
|
this.addLine(`ctx[\`${ast.elem}_value\`] = ${vals}[${loopVar}];`);
|
||||||
}
|
}
|
||||||
this.define(`key${this.target.loopLevel}`, ast.key ? compileExpr(ast.key) : loopVar);
|
this.define(`key${this.target.loopLevel}`, ast.key ? compileExpr(ast.key) : loopVar);
|
||||||
if (this.dev) {
|
if (this.dev) {
|
||||||
@@ -4385,7 +4436,6 @@ class CodeGenerator {
|
|||||||
block,
|
block,
|
||||||
index,
|
index,
|
||||||
forceNewBlock: !isTSet,
|
forceNewBlock: !isTSet,
|
||||||
preventRoot: ctx.preventRoot,
|
|
||||||
isLast: ctx.isLast && i === l - 1,
|
isLast: ctx.isLast && i === l - 1,
|
||||||
});
|
});
|
||||||
this.compileAST(child, subCtx);
|
this.compileAST(child, subCtx);
|
||||||
@@ -4394,8 +4444,7 @@ class CodeGenerator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (isNewBlock) {
|
if (isNewBlock) {
|
||||||
if (block.hasDynamicChildren) {
|
if (block.hasDynamicChildren && block.children.length) {
|
||||||
if (block.children.length) {
|
|
||||||
const code = this.target.code;
|
const code = this.target.code;
|
||||||
const children = block.children.slice();
|
const children = block.children.slice();
|
||||||
let current = children.shift();
|
let current = children.shift();
|
||||||
@@ -4407,8 +4456,7 @@ class CodeGenerator {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.addLine(`let ${block.children.map((c) => c.varName)};`, codeIdx);
|
this.addLine(`let ${block.children.map((c) => c.varName).join(", ")};`, codeIdx);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
const args = block.children.map((c) => c.varName).join(", ");
|
const args = block.children.map((c) => c.varName).join(", ");
|
||||||
this.insertBlock(`multi([${args}])`, block, ctx);
|
this.insertBlock(`multi([${args}])`, block, ctx);
|
||||||
@@ -4422,24 +4470,23 @@ class CodeGenerator {
|
|||||||
ctxVar = generateId("ctx");
|
ctxVar = generateId("ctx");
|
||||||
this.addLine(`let ${ctxVar} = ${compileExpr(ast.context)};`);
|
this.addLine(`let ${ctxVar} = ${compileExpr(ast.context)};`);
|
||||||
}
|
}
|
||||||
|
const isDynamic = INTERP_REGEXP.test(ast.name);
|
||||||
|
const subTemplate = isDynamic ? interpolate(ast.name) : "`" + ast.name + "`";
|
||||||
|
if (block && !forceNewBlock) {
|
||||||
|
this.insertAnchor(block);
|
||||||
|
}
|
||||||
|
block = this.createBlock(block, "multi", ctx);
|
||||||
if (ast.body) {
|
if (ast.body) {
|
||||||
this.addLine(`${ctxVar} = Object.create(${ctxVar});`);
|
this.addLine(`${ctxVar} = Object.create(${ctxVar});`);
|
||||||
this.addLine(`${ctxVar}[isBoundary] = 1;`);
|
this.addLine(`${ctxVar}[isBoundary] = 1;`);
|
||||||
this.helpers.add("isBoundary");
|
this.helpers.add("isBoundary");
|
||||||
const subCtx = createContext(ctx, { preventRoot: true, ctxVar });
|
const subCtx = createContext(ctx, { ctxVar });
|
||||||
const bl = this.compileMulti({ type: 3 /* Multi */, content: ast.body }, subCtx);
|
const bl = this.compileMulti({ type: 3 /* Multi */, content: ast.body }, subCtx);
|
||||||
if (bl) {
|
if (bl) {
|
||||||
this.helpers.add("zero");
|
this.helpers.add("zero");
|
||||||
this.addLine(`${ctxVar}[zero] = ${bl};`);
|
this.addLine(`${ctxVar}[zero] = ${bl};`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const isDynamic = INTERP_REGEXP.test(ast.name);
|
|
||||||
const subTemplate = isDynamic ? interpolate(ast.name) : "`" + ast.name + "`";
|
|
||||||
if (block) {
|
|
||||||
if (!forceNewBlock) {
|
|
||||||
this.insertAnchor(block);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const key = `key + \`${this.generateComponentKey()}\``;
|
const key = `key + \`${this.generateComponentKey()}\``;
|
||||||
if (isDynamic) {
|
if (isDynamic) {
|
||||||
const templateVar = generateId("template");
|
const templateVar = generateId("template");
|
||||||
@@ -4447,7 +4494,6 @@ class CodeGenerator {
|
|||||||
this.staticDefs.push({ id: "call", expr: `app.callTemplate.bind(app)` });
|
this.staticDefs.push({ id: "call", expr: `app.callTemplate.bind(app)` });
|
||||||
}
|
}
|
||||||
this.define(templateVar, subTemplate);
|
this.define(templateVar, subTemplate);
|
||||||
block = this.createBlock(block, "multi", ctx);
|
|
||||||
this.insertBlock(`call(this, ${templateVar}, ${ctxVar}, node, ${key})`, block, {
|
this.insertBlock(`call(this, ${templateVar}, ${ctxVar}, node, ${key})`, block, {
|
||||||
...ctx,
|
...ctx,
|
||||||
forceNewBlock: !block,
|
forceNewBlock: !block,
|
||||||
@@ -4456,7 +4502,6 @@ class CodeGenerator {
|
|||||||
else {
|
else {
|
||||||
const id = generateId(`callTemplate_`);
|
const id = generateId(`callTemplate_`);
|
||||||
this.staticDefs.push({ id, expr: `app.getTemplate(${subTemplate})` });
|
this.staticDefs.push({ id, expr: `app.getTemplate(${subTemplate})` });
|
||||||
block = this.createBlock(block, "multi", ctx);
|
|
||||||
this.insertBlock(`${id}.call(this, ${ctxVar}, node, ${key})`, block, {
|
this.insertBlock(`${id}.call(this, ${ctxVar}, node, ${key})`, block, {
|
||||||
...ctx,
|
...ctx,
|
||||||
forceNewBlock: !block,
|
forceNewBlock: !block,
|
||||||
@@ -4494,11 +4539,12 @@ class CodeGenerator {
|
|||||||
else {
|
else {
|
||||||
let value;
|
let value;
|
||||||
if (ast.defaultValue) {
|
if (ast.defaultValue) {
|
||||||
|
const defaultValue = ctx.translate ? this.translate(ast.defaultValue) : ast.defaultValue;
|
||||||
if (ast.value) {
|
if (ast.value) {
|
||||||
value = `withDefault(${expr}, \`${ast.defaultValue}\`)`;
|
value = `withDefault(${expr}, \`${defaultValue}\`)`;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
value = `\`${ast.defaultValue}\``;
|
value = `\`${defaultValue}\``;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -4777,7 +4823,7 @@ function parse(xml) {
|
|||||||
}
|
}
|
||||||
function _parse(xml) {
|
function _parse(xml) {
|
||||||
normalizeXML(xml);
|
normalizeXML(xml);
|
||||||
const ctx = { inPreTag: false, inSVG: false };
|
const ctx = { inPreTag: false };
|
||||||
return parseNode(xml, ctx) || { type: 0 /* Text */, value: "" };
|
return parseNode(xml, ctx) || { type: 0 /* Text */, value: "" };
|
||||||
}
|
}
|
||||||
function parseNode(node, ctx) {
|
function parseNode(node, ctx) {
|
||||||
@@ -4791,10 +4837,10 @@ function parseNode(node, ctx) {
|
|||||||
parseTCall(node, ctx) ||
|
parseTCall(node, ctx) ||
|
||||||
parseTCallBlock(node) ||
|
parseTCallBlock(node) ||
|
||||||
parseTEscNode(node, ctx) ||
|
parseTEscNode(node, ctx) ||
|
||||||
|
parseTOutNode(node, ctx) ||
|
||||||
parseTKey(node, ctx) ||
|
parseTKey(node, ctx) ||
|
||||||
parseTTranslation(node, ctx) ||
|
parseTTranslation(node, ctx) ||
|
||||||
parseTSlot(node, ctx) ||
|
parseTSlot(node, ctx) ||
|
||||||
parseTOutNode(node, ctx) ||
|
|
||||||
parseComponent(node, ctx) ||
|
parseComponent(node, ctx) ||
|
||||||
parseDOMNode(node, ctx) ||
|
parseDOMNode(node, ctx) ||
|
||||||
parseTSetNode(node, ctx) ||
|
parseTSetNode(node, ctx) ||
|
||||||
@@ -4868,9 +4914,7 @@ function parseDOMNode(node, ctx) {
|
|||||||
if (tagName === "pre") {
|
if (tagName === "pre") {
|
||||||
ctx.inPreTag = true;
|
ctx.inPreTag = true;
|
||||||
}
|
}
|
||||||
const shouldAddSVGNS = ROOT_SVG_TAGS.has(tagName) && !ctx.inSVG;
|
let ns = !ctx.nameSpace && ROOT_SVG_TAGS.has(tagName) ? "http://www.w3.org/2000/svg" : null;
|
||||||
ctx.inSVG = ctx.inSVG || shouldAddSVGNS;
|
|
||||||
const ns = shouldAddSVGNS ? "http://www.w3.org/2000/svg" : null;
|
|
||||||
const ref = node.getAttribute("t-ref");
|
const ref = node.getAttribute("t-ref");
|
||||||
node.removeAttribute("t-ref");
|
node.removeAttribute("t-ref");
|
||||||
const nodeAttrsNames = node.getAttributeNames();
|
const nodeAttrsNames = node.getAttributeNames();
|
||||||
@@ -4879,10 +4923,10 @@ function parseDOMNode(node, ctx) {
|
|||||||
let model = null;
|
let model = null;
|
||||||
for (let attr of nodeAttrsNames) {
|
for (let attr of nodeAttrsNames) {
|
||||||
const value = node.getAttribute(attr);
|
const value = node.getAttribute(attr);
|
||||||
if (attr.startsWith("t-on")) {
|
if (attr === "t-on" || attr === "t-on-") {
|
||||||
if (attr === "t-on") {
|
|
||||||
throw new OwlError("Missing event name with t-on directive");
|
throw new OwlError("Missing event name with t-on directive");
|
||||||
}
|
}
|
||||||
|
if (attr.startsWith("t-on-")) {
|
||||||
on = on || {};
|
on = on || {};
|
||||||
on[attr.slice(5)] = value;
|
on[attr.slice(5)] = value;
|
||||||
}
|
}
|
||||||
@@ -4907,10 +4951,8 @@ function parseDOMNode(node, ctx) {
|
|||||||
const typeAttr = node.getAttribute("type");
|
const typeAttr = node.getAttribute("type");
|
||||||
const isInput = tagName === "input";
|
const isInput = tagName === "input";
|
||||||
const isSelect = tagName === "select";
|
const isSelect = tagName === "select";
|
||||||
const isTextarea = tagName === "textarea";
|
|
||||||
const isCheckboxInput = isInput && typeAttr === "checkbox";
|
const isCheckboxInput = isInput && typeAttr === "checkbox";
|
||||||
const isRadioInput = isInput && typeAttr === "radio";
|
const isRadioInput = isInput && typeAttr === "radio";
|
||||||
const isOtherInput = isInput && !isCheckboxInput && !isRadioInput;
|
|
||||||
const hasLazyMod = attr.includes(".lazy");
|
const hasLazyMod = attr.includes(".lazy");
|
||||||
const hasNumberMod = attr.includes(".number");
|
const hasNumberMod = attr.includes(".number");
|
||||||
const hasTrimMod = attr.includes(".trim");
|
const hasTrimMod = attr.includes(".trim");
|
||||||
@@ -4922,8 +4964,8 @@ function parseDOMNode(node, ctx) {
|
|||||||
specialInitTargetAttr: isRadioInput ? "checked" : null,
|
specialInitTargetAttr: isRadioInput ? "checked" : null,
|
||||||
eventType,
|
eventType,
|
||||||
hasDynamicChildren: false,
|
hasDynamicChildren: false,
|
||||||
shouldTrim: hasTrimMod && (isOtherInput || isTextarea),
|
shouldTrim: hasTrimMod,
|
||||||
shouldNumberize: hasNumberMod && (isOtherInput || isTextarea),
|
shouldNumberize: hasNumberMod,
|
||||||
};
|
};
|
||||||
if (isSelect) {
|
if (isSelect) {
|
||||||
// don't pollute the original ctx
|
// don't pollute the original ctx
|
||||||
@@ -4934,6 +4976,9 @@ function parseDOMNode(node, ctx) {
|
|||||||
else if (attr.startsWith("block-")) {
|
else if (attr.startsWith("block-")) {
|
||||||
throw new OwlError(`Invalid attribute: '${attr}'`);
|
throw new OwlError(`Invalid attribute: '${attr}'`);
|
||||||
}
|
}
|
||||||
|
else if (attr === "xmlns") {
|
||||||
|
ns = value;
|
||||||
|
}
|
||||||
else if (attr !== "t-name") {
|
else if (attr !== "t-name") {
|
||||||
if (attr.startsWith("t-") && !attr.startsWith("t-att")) {
|
if (attr.startsWith("t-") && !attr.startsWith("t-att")) {
|
||||||
throw new OwlError(`Unknown QWeb directive: '${attr}'`);
|
throw new OwlError(`Unknown QWeb directive: '${attr}'`);
|
||||||
@@ -4946,6 +4991,9 @@ function parseDOMNode(node, ctx) {
|
|||||||
attrs[attr] = value;
|
attrs[attr] = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (ns) {
|
||||||
|
ctx.nameSpace = ns;
|
||||||
|
}
|
||||||
const children = parseChildren(node, ctx);
|
const children = parseChildren(node, ctx);
|
||||||
return {
|
return {
|
||||||
type: 2 /* DomNode */,
|
type: 2 /* DomNode */,
|
||||||
@@ -4986,9 +5034,6 @@ function parseTEscNode(node, ctx) {
|
|||||||
content: [tesc],
|
content: [tesc],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (ast.type === 11 /* TComponent */) {
|
|
||||||
throw new OwlError("t-esc is not supported on Component nodes");
|
|
||||||
}
|
|
||||||
return tesc;
|
return tesc;
|
||||||
}
|
}
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
@@ -5241,14 +5286,14 @@ function parseComponent(node, ctx) {
|
|||||||
// be ignored)
|
// be ignored)
|
||||||
let el = slotNode.parentElement;
|
let el = slotNode.parentElement;
|
||||||
let isInSubComponent = false;
|
let isInSubComponent = false;
|
||||||
while (el !== clone) {
|
while (el && el !== clone) {
|
||||||
if (el.hasAttribute("t-component") || el.tagName[0] === el.tagName[0].toUpperCase()) {
|
if (el.hasAttribute("t-component") || el.tagName[0] === el.tagName[0].toUpperCase()) {
|
||||||
isInSubComponent = true;
|
isInSubComponent = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
el = el.parentElement;
|
el = el.parentElement;
|
||||||
}
|
}
|
||||||
if (isInSubComponent) {
|
if (isInSubComponent || !el) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
slotNode.removeAttribute("t-set-slot");
|
slotNode.removeAttribute("t-set-slot");
|
||||||
@@ -5430,21 +5475,23 @@ function normalizeTIf(el) {
|
|||||||
*
|
*
|
||||||
* @param el the element containing the tree that should be normalized
|
* @param el the element containing the tree that should be normalized
|
||||||
*/
|
*/
|
||||||
function normalizeTEsc(el) {
|
function normalizeTEscTOut(el) {
|
||||||
const elements = [...el.querySelectorAll("[t-esc]")].filter((el) => el.tagName[0] === el.tagName[0].toUpperCase() || el.hasAttribute("t-component"));
|
for (const d of ["t-esc", "t-out"]) {
|
||||||
|
const elements = [...el.querySelectorAll(`[${d}]`)].filter((el) => el.tagName[0] === el.tagName[0].toUpperCase() || el.hasAttribute("t-component"));
|
||||||
for (const el of elements) {
|
for (const el of elements) {
|
||||||
if (el.childNodes.length) {
|
if (el.childNodes.length) {
|
||||||
throw new OwlError("Cannot have t-esc on a component that already has content");
|
throw new OwlError(`Cannot have ${d} on a component that already has content`);
|
||||||
}
|
}
|
||||||
const value = el.getAttribute("t-esc");
|
const value = el.getAttribute(d);
|
||||||
el.removeAttribute("t-esc");
|
el.removeAttribute(d);
|
||||||
const t = el.ownerDocument.createElement("t");
|
const t = el.ownerDocument.createElement("t");
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
t.setAttribute("t-esc", value);
|
t.setAttribute(d, value);
|
||||||
}
|
}
|
||||||
el.appendChild(t);
|
el.appendChild(t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Normalizes the tree inside a given element and do some preliminary validation
|
* Normalizes the tree inside a given element and do some preliminary validation
|
||||||
* on it. This function modifies the Element in place.
|
* on it. This function modifies the Element in place.
|
||||||
@@ -5453,7 +5500,7 @@ function normalizeTEsc(el) {
|
|||||||
*/
|
*/
|
||||||
function normalizeXML(el) {
|
function normalizeXML(el) {
|
||||||
normalizeTIf(el);
|
normalizeTIf(el);
|
||||||
normalizeTEsc(el);
|
normalizeTEscTOut(el);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Parses an XML string into an XML document, throwing errors on parser errors
|
* Parses an XML string into an XML document, throwing errors on parser errors
|
||||||
@@ -5502,11 +5549,20 @@ function compile(template, options = {}) {
|
|||||||
const codeGenerator = new CodeGenerator(ast, { ...options, hasSafeContext });
|
const codeGenerator = new CodeGenerator(ast, { ...options, hasSafeContext });
|
||||||
const code = codeGenerator.generateCode();
|
const code = codeGenerator.generateCode();
|
||||||
// template function
|
// template function
|
||||||
|
try {
|
||||||
return new Function("app, bdom, helpers", code);
|
return new Function("app, bdom, helpers", code);
|
||||||
}
|
}
|
||||||
|
catch (originalError) {
|
||||||
|
const { name } = options;
|
||||||
|
const nameStr = name ? `template "${name}"` : "anonymous template";
|
||||||
|
const err = new OwlError(`Failed to compile ${nameStr}: ${originalError.message}\n\ngenerated code:\nfunction(app, bdom, helpers) {\n${code}\n}`);
|
||||||
|
err.cause = originalError;
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// do not modify manually. This file is generated by the release script.
|
// do not modify manually. This file is generated by the release script.
|
||||||
const version = "2.1.1";
|
const version = "2.2.7";
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// Scheduler
|
// Scheduler
|
||||||
@@ -5516,11 +5572,18 @@ class Scheduler {
|
|||||||
this.tasks = new Set();
|
this.tasks = new Set();
|
||||||
this.frame = 0;
|
this.frame = 0;
|
||||||
this.delayedRenders = [];
|
this.delayedRenders = [];
|
||||||
|
this.cancelledNodes = new Set();
|
||||||
this.requestAnimationFrame = Scheduler.requestAnimationFrame;
|
this.requestAnimationFrame = Scheduler.requestAnimationFrame;
|
||||||
}
|
}
|
||||||
addFiber(fiber) {
|
addFiber(fiber) {
|
||||||
this.tasks.add(fiber.root);
|
this.tasks.add(fiber.root);
|
||||||
}
|
}
|
||||||
|
scheduleDestroy(node) {
|
||||||
|
this.cancelledNodes.add(node);
|
||||||
|
if (this.frame === 0) {
|
||||||
|
this.frame = this.requestAnimationFrame(() => this.processTasks());
|
||||||
|
}
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Process all current tasks. This only applies to the fibers that are ready.
|
* Process all current tasks. This only applies to the fibers that are ready.
|
||||||
* Other tasks are left unchanged.
|
* Other tasks are left unchanged.
|
||||||
@@ -5530,22 +5593,29 @@ class Scheduler {
|
|||||||
let renders = this.delayedRenders;
|
let renders = this.delayedRenders;
|
||||||
this.delayedRenders = [];
|
this.delayedRenders = [];
|
||||||
for (let f of renders) {
|
for (let f of renders) {
|
||||||
if (f.root && f.node.status !== 2 /* DESTROYED */ && f.node.fiber === f) {
|
if (f.root && f.node.status !== 3 /* DESTROYED */ && f.node.fiber === f) {
|
||||||
f.render();
|
f.render();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (this.frame === 0) {
|
if (this.frame === 0) {
|
||||||
this.frame = this.requestAnimationFrame(() => {
|
this.frame = this.requestAnimationFrame(() => this.processTasks());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
processTasks() {
|
||||||
this.frame = 0;
|
this.frame = 0;
|
||||||
this.tasks.forEach((fiber) => this.processFiber(fiber));
|
for (let node of this.cancelledNodes) {
|
||||||
|
node._destroy();
|
||||||
|
}
|
||||||
|
this.cancelledNodes.clear();
|
||||||
for (let task of this.tasks) {
|
for (let task of this.tasks) {
|
||||||
if (task.node.status === 2 /* DESTROYED */) {
|
this.processFiber(task);
|
||||||
|
}
|
||||||
|
for (let task of this.tasks) {
|
||||||
|
if (task.node.status === 3 /* DESTROYED */) {
|
||||||
this.tasks.delete(task);
|
this.tasks.delete(task);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
processFiber(fiber) {
|
processFiber(fiber) {
|
||||||
if (fiber.root !== fiber) {
|
if (fiber.root !== fiber) {
|
||||||
@@ -5557,7 +5627,7 @@ class Scheduler {
|
|||||||
this.tasks.delete(fiber);
|
this.tasks.delete(fiber);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (fiber.node.status === 2 /* DESTROYED */) {
|
if (fiber.node.status === 3 /* DESTROYED */) {
|
||||||
this.tasks.delete(fiber);
|
this.tasks.delete(fiber);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -5581,11 +5651,8 @@ const DEV_MSG = () => {
|
|||||||
This is not suitable for production use.
|
This is not suitable for production use.
|
||||||
See https://github.com/odoo/owl/blob/${hash}/doc/reference/app.md#configuration for more information.`;
|
See https://github.com/odoo/owl/blob/${hash}/doc/reference/app.md#configuration for more information.`;
|
||||||
};
|
};
|
||||||
window.__OWL_DEVTOOLS__ || (window.__OWL_DEVTOOLS__ = {
|
const apps = new Set();
|
||||||
apps: new Set(),
|
window.__OWL_DEVTOOLS__ || (window.__OWL_DEVTOOLS__ = { apps, Fiber, RootFiber, toRaw, reactive });
|
||||||
Fiber: Fiber,
|
|
||||||
RootFiber: RootFiber,
|
|
||||||
});
|
|
||||||
class App extends TemplateSet {
|
class App extends TemplateSet {
|
||||||
constructor(Root, config = {}) {
|
constructor(Root, config = {}) {
|
||||||
super(config);
|
super(config);
|
||||||
@@ -5593,7 +5660,7 @@ class App extends TemplateSet {
|
|||||||
this.root = null;
|
this.root = null;
|
||||||
this.name = config.name || "";
|
this.name = config.name || "";
|
||||||
this.Root = Root;
|
this.Root = Root;
|
||||||
window.__OWL_DEVTOOLS__.apps.add(this);
|
apps.add(this);
|
||||||
if (config.test) {
|
if (config.test) {
|
||||||
this.dev = true;
|
this.dev = true;
|
||||||
}
|
}
|
||||||
@@ -5647,10 +5714,10 @@ class App extends TemplateSet {
|
|||||||
}
|
}
|
||||||
destroy() {
|
destroy() {
|
||||||
if (this.root) {
|
if (this.root) {
|
||||||
this.scheduler.flush();
|
|
||||||
this.root.destroy();
|
this.root.destroy();
|
||||||
|
this.scheduler.processTasks();
|
||||||
}
|
}
|
||||||
window.__OWL_DEVTOOLS__.apps.delete(this);
|
apps.delete(this);
|
||||||
}
|
}
|
||||||
createComponent(name, isStatic, hasSlotsProp, hasDynamicPropList, propList) {
|
createComponent(name, isStatic, hasSlotsProp, hasDynamicPropList, propList) {
|
||||||
const isDynamic = !isStatic;
|
const isDynamic = !isStatic;
|
||||||
@@ -5725,6 +5792,7 @@ class App extends TemplateSet {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
App.validateTarget = validateTarget;
|
App.validateTarget = validateTarget;
|
||||||
|
App.apps = apps;
|
||||||
App.version = version;
|
App.version = version;
|
||||||
async function mount(C, target, config = {}) {
|
async function mount(C, target, config = {}) {
|
||||||
return new App(C, config).mount(target, config);
|
return new App(C, config).mount(target, config);
|
||||||
@@ -5779,9 +5847,11 @@ function status(component) {
|
|||||||
switch (component.__owl__.status) {
|
switch (component.__owl__.status) {
|
||||||
case 0 /* NEW */:
|
case 0 /* NEW */:
|
||||||
return "new";
|
return "new";
|
||||||
|
case 2 /* CANCELLED */:
|
||||||
|
return "cancelled";
|
||||||
case 1 /* MOUNTED */:
|
case 1 /* MOUNTED */:
|
||||||
return "mounted";
|
return "mounted";
|
||||||
case 2 /* DESTROYED */:
|
case 3 /* DESTROYED */:
|
||||||
return "destroyed";
|
return "destroyed";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5837,8 +5907,9 @@ function useChildSubEnv(envExtension) {
|
|||||||
* will run a cleanup function before patching and before unmounting the
|
* will run a cleanup function before patching and before unmounting the
|
||||||
* the component.
|
* the component.
|
||||||
*
|
*
|
||||||
* @param {Effect} effect the effect to run on component mount and/or patch
|
* @template T
|
||||||
* @param {()=>any[]} [computeDependencies=()=>[NaN]] a callback to compute
|
* @param {Effect<T>} effect the effect to run on component mount and/or patch
|
||||||
|
* @param {()=>[...T]} [computeDependencies=()=>[NaN]] a callback to compute
|
||||||
* dependencies that will decide if the effect needs to be cleaned up and
|
* dependencies that will decide if the effect needs to be cleaned up and
|
||||||
* run again. If the dependencies did not change, the effect will not run
|
* run again. If the dependencies did not change, the effect will not run
|
||||||
* again. The default value returns an array containing only NaN because
|
* again. The default value returns an array containing only NaN because
|
||||||
@@ -5920,6 +5991,6 @@ TemplateSet.prototype._compileTemplate = function _compileTemplate(name, templat
|
|||||||
export { App, Component, EventBus, OwlError, __info__, blockDom, loadFile, markRaw, markup, mount, onError, onMounted, onPatched, onRendered, onWillDestroy, onWillPatch, onWillRender, onWillStart, onWillUnmount, onWillUpdateProps, reactive, status, toRaw, useChildSubEnv, useComponent, useEffect, useEnv, useExternalListener, useRef, useState, useSubEnv, validate, validateType, whenReady, xml };
|
export { App, Component, EventBus, OwlError, __info__, blockDom, loadFile, markRaw, markup, mount, onError, onMounted, onPatched, onRendered, onWillDestroy, onWillPatch, onWillRender, onWillStart, onWillUnmount, onWillUpdateProps, reactive, status, toRaw, useChildSubEnv, useComponent, useEffect, useEnv, useExternalListener, useRef, useState, useSubEnv, validate, validateType, whenReady, xml };
|
||||||
|
|
||||||
|
|
||||||
__info__.date = '2023-04-24T14:29:32.376Z';
|
__info__.date = '2023-12-06T13:56:01.636Z';
|
||||||
__info__.hash = 'f9d810a';
|
__info__.hash = 'e94428a';
|
||||||
__info__.url = 'https://github.com/odoo/owl';
|
__info__.url = 'https://github.com/odoo/owl';
|
||||||
|
|||||||
@@ -43,10 +43,6 @@ class TaskList {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
toggleTask(task) {
|
|
||||||
task.isCompleted = !task.isCompleted;
|
|
||||||
}
|
|
||||||
|
|
||||||
toggleTask(id) {
|
toggleTask(id) {
|
||||||
const task = this.tasks.find(t => t.id === id);
|
const task = this.tasks.find(t => t.id === id);
|
||||||
task.isCompleted = !task.isCompleted;
|
task.isCompleted = !task.isCompleted;
|
||||||
@@ -61,7 +57,7 @@ class TaskList {
|
|||||||
clearCompleted() {
|
clearCompleted() {
|
||||||
const tasks = this.tasks.filter(t => t.isCompleted);
|
const tasks = this.tasks.filter(t => t.isCompleted);
|
||||||
for (let task of tasks) {
|
for (let task of tasks) {
|
||||||
this.deleteTask(task);
|
this.deleteTask(task.id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@odoo/owl",
|
"name": "@odoo/owl",
|
||||||
"version": "2.1.2",
|
"version": "2.2.7",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@odoo/owl",
|
"name": "@odoo/owl",
|
||||||
"version": "2.1.2",
|
"version": "2.2.7",
|
||||||
"description": "Odoo Web Library (OWL)",
|
"description": "Odoo Web Library (OWL)",
|
||||||
"main": "dist/owl.cjs.js",
|
"main": "dist/owl.cjs.js",
|
||||||
"module": "dist/owl.es.js",
|
"module": "dist/owl.es.js",
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
// Custom error class that wraps error that happen in the owl lifecycle
|
||||||
|
export class OwlError extends Error {
|
||||||
|
cause?: any;
|
||||||
|
}
|
||||||
@@ -29,7 +29,7 @@ import {
|
|||||||
Attrs,
|
Attrs,
|
||||||
EventHandlers,
|
EventHandlers,
|
||||||
} from "./parser";
|
} from "./parser";
|
||||||
import { OwlError } from "../runtime/error_handling";
|
import { OwlError } from "../common/owl_error";
|
||||||
|
|
||||||
type BlockType = "block" | "text" | "multi" | "list" | "html" | "comment";
|
type BlockType = "block" | "text" | "multi" | "list" | "html" | "comment";
|
||||||
const whitespaceRE = /\s+/g;
|
const whitespaceRE = /\s+/g;
|
||||||
@@ -160,7 +160,6 @@ interface Context {
|
|||||||
block: BlockDescription | null;
|
block: BlockDescription | null;
|
||||||
index: number | string;
|
index: number | string;
|
||||||
forceNewBlock: boolean;
|
forceNewBlock: boolean;
|
||||||
preventRoot?: boolean;
|
|
||||||
isLast?: boolean;
|
isLast?: boolean;
|
||||||
translate: boolean;
|
translate: boolean;
|
||||||
tKeyExpr: string | null;
|
tKeyExpr: string | null;
|
||||||
@@ -377,7 +376,7 @@ export class CodeGenerator {
|
|||||||
): BlockDescription {
|
): BlockDescription {
|
||||||
const hasRoot = this.target.hasRoot;
|
const hasRoot = this.target.hasRoot;
|
||||||
const block = new BlockDescription(this.target, type);
|
const block = new BlockDescription(this.target, type);
|
||||||
if (!hasRoot && !ctx.preventRoot) {
|
if (!hasRoot) {
|
||||||
this.target.hasRoot = true;
|
this.target.hasRoot = true;
|
||||||
block.isRoot = true;
|
block.isRoot = true;
|
||||||
}
|
}
|
||||||
@@ -403,7 +402,7 @@ export class CodeGenerator {
|
|||||||
blockExpr = `toggler(${ctx.tKeyExpr}, ${blockExpr})`;
|
blockExpr = `toggler(${ctx.tKeyExpr}, ${blockExpr})`;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (block.isRoot && !ctx.preventRoot) {
|
if (block.isRoot) {
|
||||||
if (this.target.on) {
|
if (this.target.on) {
|
||||||
blockExpr = this.wrapWithEventCatcher(blockExpr, this.target.on);
|
blockExpr = this.wrapWithEventCatcher(blockExpr, this.target.on);
|
||||||
}
|
}
|
||||||
@@ -447,6 +446,11 @@ export class CodeGenerator {
|
|||||||
.join("");
|
.join("");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
translate(str: string): string {
|
||||||
|
const match = translationRE.exec(str) as any;
|
||||||
|
return match[1] + this.translateFn(match[2]) + match[3];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @returns the newly created block name, if any
|
* @returns the newly created block name, if any
|
||||||
*/
|
*/
|
||||||
@@ -527,8 +531,7 @@ export class CodeGenerator {
|
|||||||
|
|
||||||
let value = ast.value;
|
let value = ast.value;
|
||||||
if (value && ctx.translate !== false) {
|
if (value && ctx.translate !== false) {
|
||||||
const match = translationRE.exec(value) as any;
|
value = this.translate(value);
|
||||||
value = match[1] + this.translateFn(match[2]) + match[3];
|
|
||||||
}
|
}
|
||||||
if (!ctx.inPreTag) {
|
if (!ctx.inPreTag) {
|
||||||
value = value.replace(whitespaceRE, " ");
|
value = value.replace(whitespaceRE, " ");
|
||||||
@@ -582,11 +585,6 @@ export class CodeGenerator {
|
|||||||
}
|
}
|
||||||
// attributes
|
// attributes
|
||||||
const attrs: Attrs = {};
|
const attrs: Attrs = {};
|
||||||
const nameSpace = ast.ns || ctx.nameSpace;
|
|
||||||
if (nameSpace && isNewBlock) {
|
|
||||||
// specific namespace uri
|
|
||||||
attrs["block-ns"] = nameSpace;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let key in ast.attrs) {
|
for (let key in ast.attrs) {
|
||||||
let expr, attrName;
|
let expr, attrName;
|
||||||
@@ -715,7 +713,10 @@ export class CodeGenerator {
|
|||||||
attrs["block-ref"] = String(idx);
|
attrs["block-ref"] = String(idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
const dom = xmlDoc.createElement(ast.tag);
|
const nameSpace = ast.ns || ctx.nameSpace;
|
||||||
|
const dom = nameSpace
|
||||||
|
? xmlDoc.createElementNS(nameSpace, ast.tag)
|
||||||
|
: xmlDoc.createElement(ast.tag);
|
||||||
for (const [attr, val] of Object.entries(attrs)) {
|
for (const [attr, val] of Object.entries(attrs)) {
|
||||||
if (!(attr === "class" && val === "")) {
|
if (!(attr === "class" && val === "")) {
|
||||||
dom.setAttribute(attr, val);
|
dom.setAttribute(attr, val);
|
||||||
@@ -757,7 +758,7 @@ export class CodeGenerator {
|
|||||||
if (!current) break;
|
if (!current) break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.addLine(`let ${block!.children.map((c) => c.varName)};`, codeIdx);
|
this.addLine(`let ${block!.children.map((c) => c.varName).join(", ")};`, codeIdx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return block!.varName;
|
return block!.varName;
|
||||||
@@ -859,7 +860,7 @@ export class CodeGenerator {
|
|||||||
if (!current) break;
|
if (!current) break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.addLine(`let ${block!.children.map((c) => c.varName)};`, codeIdx);
|
this.addLine(`let ${block!.children.map((c) => c.varName).join(", ")};`, codeIdx);
|
||||||
}
|
}
|
||||||
|
|
||||||
// note: this part is duplicated from end of compilemulti:
|
// note: this part is duplicated from end of compilemulti:
|
||||||
@@ -890,18 +891,18 @@ export class CodeGenerator {
|
|||||||
}
|
}
|
||||||
this.addLine(`for (let ${loopVar} = 0; ${loopVar} < ${l}; ${loopVar}++) {`);
|
this.addLine(`for (let ${loopVar} = 0; ${loopVar} < ${l}; ${loopVar}++) {`);
|
||||||
this.target.indentLevel++;
|
this.target.indentLevel++;
|
||||||
this.addLine(`ctx[\`${ast.elem}\`] = ${vals}[${loopVar}];`);
|
this.addLine(`ctx[\`${ast.elem}\`] = ${keys}[${loopVar}];`);
|
||||||
if (!ast.hasNoFirst) {
|
if (!ast.hasNoFirst) {
|
||||||
this.addLine(`ctx[\`${ast.elem}_first\`] = ${loopVar} === 0;`);
|
this.addLine(`ctx[\`${ast.elem}_first\`] = ${loopVar} === 0;`);
|
||||||
}
|
}
|
||||||
if (!ast.hasNoLast) {
|
if (!ast.hasNoLast) {
|
||||||
this.addLine(`ctx[\`${ast.elem}_last\`] = ${loopVar} === ${vals}.length - 1;`);
|
this.addLine(`ctx[\`${ast.elem}_last\`] = ${loopVar} === ${keys}.length - 1;`);
|
||||||
}
|
}
|
||||||
if (!ast.hasNoIndex) {
|
if (!ast.hasNoIndex) {
|
||||||
this.addLine(`ctx[\`${ast.elem}_index\`] = ${loopVar};`);
|
this.addLine(`ctx[\`${ast.elem}_index\`] = ${loopVar};`);
|
||||||
}
|
}
|
||||||
if (!ast.hasNoValue) {
|
if (!ast.hasNoValue) {
|
||||||
this.addLine(`ctx[\`${ast.elem}_value\`] = ${keys}[${loopVar}];`);
|
this.addLine(`ctx[\`${ast.elem}_value\`] = ${vals}[${loopVar}];`);
|
||||||
}
|
}
|
||||||
this.define(`key${this.target.loopLevel}`, ast.key ? compileExpr(ast.key) : loopVar);
|
this.define(`key${this.target.loopLevel}`, ast.key ? compileExpr(ast.key) : loopVar);
|
||||||
if (this.dev) {
|
if (this.dev) {
|
||||||
@@ -985,7 +986,6 @@ export class CodeGenerator {
|
|||||||
block,
|
block,
|
||||||
index,
|
index,
|
||||||
forceNewBlock: !isTSet,
|
forceNewBlock: !isTSet,
|
||||||
preventRoot: ctx.preventRoot,
|
|
||||||
isLast: ctx.isLast && i === l - 1,
|
isLast: ctx.isLast && i === l - 1,
|
||||||
});
|
});
|
||||||
this.compileAST(child, subCtx);
|
this.compileAST(child, subCtx);
|
||||||
@@ -994,8 +994,7 @@ export class CodeGenerator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (isNewBlock) {
|
if (isNewBlock) {
|
||||||
if (block!.hasDynamicChildren) {
|
if (block!.hasDynamicChildren && block!.children.length) {
|
||||||
if (block!.children.length) {
|
|
||||||
const code = this.target.code;
|
const code = this.target.code;
|
||||||
const children = block!.children.slice();
|
const children = block!.children.slice();
|
||||||
let current = children.shift();
|
let current = children.shift();
|
||||||
@@ -1006,8 +1005,7 @@ export class CodeGenerator {
|
|||||||
if (!current) break;
|
if (!current) break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.addLine(`let ${block!.children.map((c) => c.varName)};`, codeIdx);
|
this.addLine(`let ${block!.children.map((c) => c.varName).join(", ")};`, codeIdx);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const args = block!.children.map((c) => c.varName).join(", ");
|
const args = block!.children.map((c) => c.varName).join(", ");
|
||||||
@@ -1023,24 +1021,24 @@ export class CodeGenerator {
|
|||||||
ctxVar = generateId("ctx");
|
ctxVar = generateId("ctx");
|
||||||
this.addLine(`let ${ctxVar} = ${compileExpr(ast.context)};`);
|
this.addLine(`let ${ctxVar} = ${compileExpr(ast.context)};`);
|
||||||
}
|
}
|
||||||
|
const isDynamic = INTERP_REGEXP.test(ast.name);
|
||||||
|
const subTemplate = isDynamic ? interpolate(ast.name) : "`" + ast.name + "`";
|
||||||
|
if (block && !forceNewBlock) {
|
||||||
|
this.insertAnchor(block);
|
||||||
|
}
|
||||||
|
block = this.createBlock(block, "multi", ctx);
|
||||||
if (ast.body) {
|
if (ast.body) {
|
||||||
this.addLine(`${ctxVar} = Object.create(${ctxVar});`);
|
this.addLine(`${ctxVar} = Object.create(${ctxVar});`);
|
||||||
this.addLine(`${ctxVar}[isBoundary] = 1;`);
|
this.addLine(`${ctxVar}[isBoundary] = 1;`);
|
||||||
this.helpers.add("isBoundary");
|
this.helpers.add("isBoundary");
|
||||||
const subCtx = createContext(ctx, { preventRoot: true, ctxVar });
|
const subCtx = createContext(ctx, { ctxVar });
|
||||||
const bl = this.compileMulti({ type: ASTType.Multi, content: ast.body }, subCtx);
|
const bl = this.compileMulti({ type: ASTType.Multi, content: ast.body }, subCtx);
|
||||||
if (bl) {
|
if (bl) {
|
||||||
this.helpers.add("zero");
|
this.helpers.add("zero");
|
||||||
this.addLine(`${ctxVar}[zero] = ${bl};`);
|
this.addLine(`${ctxVar}[zero] = ${bl};`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const isDynamic = INTERP_REGEXP.test(ast.name);
|
|
||||||
const subTemplate = isDynamic ? interpolate(ast.name) : "`" + ast.name + "`";
|
|
||||||
if (block) {
|
|
||||||
if (!forceNewBlock) {
|
|
||||||
this.insertAnchor(block);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const key = `key + \`${this.generateComponentKey()}\``;
|
const key = `key + \`${this.generateComponentKey()}\``;
|
||||||
if (isDynamic) {
|
if (isDynamic) {
|
||||||
const templateVar = generateId("template");
|
const templateVar = generateId("template");
|
||||||
@@ -1048,7 +1046,6 @@ export class CodeGenerator {
|
|||||||
this.staticDefs.push({ id: "call", expr: `app.callTemplate.bind(app)` });
|
this.staticDefs.push({ id: "call", expr: `app.callTemplate.bind(app)` });
|
||||||
}
|
}
|
||||||
this.define(templateVar, subTemplate);
|
this.define(templateVar, subTemplate);
|
||||||
block = this.createBlock(block, "multi", ctx);
|
|
||||||
this.insertBlock(`call(this, ${templateVar}, ${ctxVar}, node, ${key})`, block!, {
|
this.insertBlock(`call(this, ${templateVar}, ${ctxVar}, node, ${key})`, block!, {
|
||||||
...ctx,
|
...ctx,
|
||||||
forceNewBlock: !block,
|
forceNewBlock: !block,
|
||||||
@@ -1056,7 +1053,6 @@ export class CodeGenerator {
|
|||||||
} else {
|
} else {
|
||||||
const id = generateId(`callTemplate_`);
|
const id = generateId(`callTemplate_`);
|
||||||
this.staticDefs.push({ id, expr: `app.getTemplate(${subTemplate})` });
|
this.staticDefs.push({ id, expr: `app.getTemplate(${subTemplate})` });
|
||||||
block = this.createBlock(block, "multi", ctx);
|
|
||||||
this.insertBlock(`${id}.call(this, ${ctxVar}, node, ${key})`, block!, {
|
this.insertBlock(`${id}.call(this, ${ctxVar}, node, ${key})`, block!, {
|
||||||
...ctx,
|
...ctx,
|
||||||
forceNewBlock: !block,
|
forceNewBlock: !block,
|
||||||
@@ -1095,10 +1091,11 @@ export class CodeGenerator {
|
|||||||
} else {
|
} else {
|
||||||
let value: string;
|
let value: string;
|
||||||
if (ast.defaultValue) {
|
if (ast.defaultValue) {
|
||||||
|
const defaultValue = ctx.translate ? this.translate(ast.defaultValue) : ast.defaultValue;
|
||||||
if (ast.value) {
|
if (ast.value) {
|
||||||
value = `withDefault(${expr}, \`${ast.defaultValue}\`)`;
|
value = `withDefault(${expr}, \`${defaultValue}\`)`;
|
||||||
} else {
|
} else {
|
||||||
value = `\`${ast.defaultValue}\``;
|
value = `\`${defaultValue}\``;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
value = expr;
|
value = expr;
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import type { TemplateSet } from "../runtime/template_set";
|
|||||||
import type { BDom } from "../runtime/blockdom";
|
import type { BDom } from "../runtime/blockdom";
|
||||||
import { CodeGenerator, Config } from "./code_generator";
|
import { CodeGenerator, Config } from "./code_generator";
|
||||||
import { parse } from "./parser";
|
import { parse } from "./parser";
|
||||||
|
import { OwlError } from "../common/owl_error";
|
||||||
|
|
||||||
export type Template = (context: any, vnode: any, key?: string) => BDom;
|
export type Template = (context: any, vnode: any, key?: string) => BDom;
|
||||||
|
|
||||||
@@ -27,5 +28,15 @@ export function compile(
|
|||||||
const codeGenerator = new CodeGenerator(ast, { ...options, hasSafeContext });
|
const codeGenerator = new CodeGenerator(ast, { ...options, hasSafeContext });
|
||||||
const code = codeGenerator.generateCode();
|
const code = codeGenerator.generateCode();
|
||||||
// template function
|
// template function
|
||||||
|
try {
|
||||||
return new Function("app, bdom, helpers", code) as TemplateFunction;
|
return new Function("app, bdom, helpers", code) as TemplateFunction;
|
||||||
|
} catch (originalError: any) {
|
||||||
|
const { name } = options;
|
||||||
|
const nameStr = name ? `template "${name}"` : "anonymous template";
|
||||||
|
const err = new OwlError(
|
||||||
|
`Failed to compile ${nameStr}: ${originalError.message}\n\ngenerated code:\nfunction(app, bdom, helpers) {\n${code}\n}`
|
||||||
|
);
|
||||||
|
err.cause = originalError;
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { OwlError } from "../runtime/error_handling";
|
import { OwlError } from "../common/owl_error";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Owl QWeb Expression Parser
|
* Owl QWeb Expression Parser
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { OwlError } from "../runtime/error_handling";
|
import { OwlError } from "../common/owl_error";
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// AST Type definition
|
// AST Type definition
|
||||||
@@ -213,14 +213,14 @@ export function parse(xml: string | Element): AST {
|
|||||||
|
|
||||||
function _parse(xml: Element): AST {
|
function _parse(xml: Element): AST {
|
||||||
normalizeXML(xml);
|
normalizeXML(xml);
|
||||||
const ctx = { inPreTag: false, inSVG: false };
|
const ctx = { inPreTag: false };
|
||||||
return parseNode(xml, ctx) || { type: ASTType.Text, value: "" };
|
return parseNode(xml, ctx) || { type: ASTType.Text, value: "" };
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ParsingContext {
|
interface ParsingContext {
|
||||||
tModelInfo?: TModelInfo | null;
|
tModelInfo?: TModelInfo | null;
|
||||||
|
nameSpace?: string;
|
||||||
inPreTag: boolean;
|
inPreTag: boolean;
|
||||||
inSVG: boolean;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseNode(node: Node, ctx: ParsingContext): AST | null {
|
function parseNode(node: Node, ctx: ParsingContext): AST | null {
|
||||||
@@ -235,10 +235,10 @@ function parseNode(node: Node, ctx: ParsingContext): AST | null {
|
|||||||
parseTCall(node, ctx) ||
|
parseTCall(node, ctx) ||
|
||||||
parseTCallBlock(node, ctx) ||
|
parseTCallBlock(node, ctx) ||
|
||||||
parseTEscNode(node, ctx) ||
|
parseTEscNode(node, ctx) ||
|
||||||
|
parseTOutNode(node, ctx) ||
|
||||||
parseTKey(node, ctx) ||
|
parseTKey(node, ctx) ||
|
||||||
parseTTranslation(node, ctx) ||
|
parseTTranslation(node, ctx) ||
|
||||||
parseTSlot(node, ctx) ||
|
parseTSlot(node, ctx) ||
|
||||||
parseTOutNode(node, ctx) ||
|
|
||||||
parseComponent(node, ctx) ||
|
parseComponent(node, ctx) ||
|
||||||
parseDOMNode(node, ctx) ||
|
parseDOMNode(node, ctx) ||
|
||||||
parseTSetNode(node, ctx) ||
|
parseTSetNode(node, ctx) ||
|
||||||
@@ -323,9 +323,8 @@ function parseDOMNode(node: Element, ctx: ParsingContext): AST | null {
|
|||||||
if (tagName === "pre") {
|
if (tagName === "pre") {
|
||||||
ctx.inPreTag = true;
|
ctx.inPreTag = true;
|
||||||
}
|
}
|
||||||
const shouldAddSVGNS = ROOT_SVG_TAGS.has(tagName) && !ctx.inSVG;
|
|
||||||
ctx.inSVG = ctx.inSVG || shouldAddSVGNS;
|
let ns = !ctx.nameSpace && ROOT_SVG_TAGS.has(tagName) ? "http://www.w3.org/2000/svg" : null;
|
||||||
const ns = shouldAddSVGNS ? "http://www.w3.org/2000/svg" : null;
|
|
||||||
const ref = node.getAttribute("t-ref");
|
const ref = node.getAttribute("t-ref");
|
||||||
node.removeAttribute("t-ref");
|
node.removeAttribute("t-ref");
|
||||||
|
|
||||||
@@ -336,10 +335,10 @@ function parseDOMNode(node: Element, ctx: ParsingContext): AST | null {
|
|||||||
|
|
||||||
for (let attr of nodeAttrsNames) {
|
for (let attr of nodeAttrsNames) {
|
||||||
const value = node.getAttribute(attr)!;
|
const value = node.getAttribute(attr)!;
|
||||||
if (attr.startsWith("t-on")) {
|
if (attr === "t-on" || attr === "t-on-") {
|
||||||
if (attr === "t-on") {
|
|
||||||
throw new OwlError("Missing event name with t-on directive");
|
throw new OwlError("Missing event name with t-on directive");
|
||||||
}
|
}
|
||||||
|
if (attr.startsWith("t-on-")) {
|
||||||
on = on || {};
|
on = on || {};
|
||||||
on[attr.slice(5)] = value;
|
on[attr.slice(5)] = value;
|
||||||
} else if (attr.startsWith("t-model")) {
|
} else if (attr.startsWith("t-model")) {
|
||||||
@@ -365,10 +364,8 @@ function parseDOMNode(node: Element, ctx: ParsingContext): AST | null {
|
|||||||
const typeAttr = node.getAttribute("type");
|
const typeAttr = node.getAttribute("type");
|
||||||
const isInput = tagName === "input";
|
const isInput = tagName === "input";
|
||||||
const isSelect = tagName === "select";
|
const isSelect = tagName === "select";
|
||||||
const isTextarea = tagName === "textarea";
|
|
||||||
const isCheckboxInput = isInput && typeAttr === "checkbox";
|
const isCheckboxInput = isInput && typeAttr === "checkbox";
|
||||||
const isRadioInput = isInput && typeAttr === "radio";
|
const isRadioInput = isInput && typeAttr === "radio";
|
||||||
const isOtherInput = isInput && !isCheckboxInput && !isRadioInput;
|
|
||||||
const hasLazyMod = attr.includes(".lazy");
|
const hasLazyMod = attr.includes(".lazy");
|
||||||
const hasNumberMod = attr.includes(".number");
|
const hasNumberMod = attr.includes(".number");
|
||||||
const hasTrimMod = attr.includes(".trim");
|
const hasTrimMod = attr.includes(".trim");
|
||||||
@@ -381,8 +378,8 @@ function parseDOMNode(node: Element, ctx: ParsingContext): AST | null {
|
|||||||
specialInitTargetAttr: isRadioInput ? "checked" : null,
|
specialInitTargetAttr: isRadioInput ? "checked" : null,
|
||||||
eventType,
|
eventType,
|
||||||
hasDynamicChildren: false,
|
hasDynamicChildren: false,
|
||||||
shouldTrim: hasTrimMod && (isOtherInput || isTextarea),
|
shouldTrim: hasTrimMod,
|
||||||
shouldNumberize: hasNumberMod && (isOtherInput || isTextarea),
|
shouldNumberize: hasNumberMod,
|
||||||
};
|
};
|
||||||
if (isSelect) {
|
if (isSelect) {
|
||||||
// don't pollute the original ctx
|
// don't pollute the original ctx
|
||||||
@@ -391,6 +388,8 @@ function parseDOMNode(node: Element, ctx: ParsingContext): AST | null {
|
|||||||
}
|
}
|
||||||
} else if (attr.startsWith("block-")) {
|
} else if (attr.startsWith("block-")) {
|
||||||
throw new OwlError(`Invalid attribute: '${attr}'`);
|
throw new OwlError(`Invalid attribute: '${attr}'`);
|
||||||
|
} else if (attr === "xmlns") {
|
||||||
|
ns = value;
|
||||||
} else if (attr !== "t-name") {
|
} else if (attr !== "t-name") {
|
||||||
if (attr.startsWith("t-") && !attr.startsWith("t-att")) {
|
if (attr.startsWith("t-") && !attr.startsWith("t-att")) {
|
||||||
throw new OwlError(`Unknown QWeb directive: '${attr}'`);
|
throw new OwlError(`Unknown QWeb directive: '${attr}'`);
|
||||||
@@ -403,6 +402,9 @@ function parseDOMNode(node: Element, ctx: ParsingContext): AST | null {
|
|||||||
attrs[attr] = value;
|
attrs[attr] = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (ns) {
|
||||||
|
ctx.nameSpace = ns;
|
||||||
|
}
|
||||||
|
|
||||||
const children = parseChildren(node, ctx);
|
const children = parseChildren(node, ctx);
|
||||||
return {
|
return {
|
||||||
@@ -446,9 +448,6 @@ function parseTEscNode(node: Element, ctx: ParsingContext): AST | null {
|
|||||||
content: [tesc],
|
content: [tesc],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (ast.type === ASTType.TComponent) {
|
|
||||||
throw new OwlError("t-esc is not supported on Component nodes");
|
|
||||||
}
|
|
||||||
return tesc;
|
return tesc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -741,14 +740,14 @@ function parseComponent(node: Element, ctx: ParsingContext): AST | null {
|
|||||||
// be ignored)
|
// be ignored)
|
||||||
let el = slotNode.parentElement!;
|
let el = slotNode.parentElement!;
|
||||||
let isInSubComponent = false;
|
let isInSubComponent = false;
|
||||||
while (el !== clone) {
|
while (el && el !== clone) {
|
||||||
if (el!.hasAttribute("t-component") || el!.tagName[0] === el!.tagName[0].toUpperCase()) {
|
if (el!.hasAttribute("t-component") || el!.tagName[0] === el!.tagName[0].toUpperCase()) {
|
||||||
isInSubComponent = true;
|
isInSubComponent = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
el = el.parentElement!;
|
el = el.parentElement!;
|
||||||
}
|
}
|
||||||
if (isInSubComponent) {
|
if (isInSubComponent || !el) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -943,23 +942,25 @@ function normalizeTIf(el: Element) {
|
|||||||
*
|
*
|
||||||
* @param el the element containing the tree that should be normalized
|
* @param el the element containing the tree that should be normalized
|
||||||
*/
|
*/
|
||||||
function normalizeTEsc(el: Element) {
|
function normalizeTEscTOut(el: Element) {
|
||||||
const elements = [...el.querySelectorAll("[t-esc]")].filter(
|
for (const d of ["t-esc", "t-out"]) {
|
||||||
|
const elements = [...el.querySelectorAll(`[${d}]`)].filter(
|
||||||
(el) => el.tagName[0] === el.tagName[0].toUpperCase() || el.hasAttribute("t-component")
|
(el) => el.tagName[0] === el.tagName[0].toUpperCase() || el.hasAttribute("t-component")
|
||||||
);
|
);
|
||||||
for (const el of elements) {
|
for (const el of elements) {
|
||||||
if (el.childNodes.length) {
|
if (el.childNodes.length) {
|
||||||
throw new OwlError("Cannot have t-esc on a component that already has content");
|
throw new OwlError(`Cannot have ${d} on a component that already has content`);
|
||||||
}
|
}
|
||||||
const value = el.getAttribute("t-esc");
|
const value = el.getAttribute(d);
|
||||||
el.removeAttribute("t-esc");
|
el.removeAttribute(d);
|
||||||
const t = el.ownerDocument.createElement("t");
|
const t = el.ownerDocument.createElement("t");
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
t.setAttribute("t-esc", value);
|
t.setAttribute(d, value);
|
||||||
}
|
}
|
||||||
el.appendChild(t);
|
el.appendChild(t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Normalizes the tree inside a given element and do some preliminary validation
|
* Normalizes the tree inside a given element and do some preliminary validation
|
||||||
@@ -969,7 +970,7 @@ function normalizeTEsc(el: Element) {
|
|||||||
*/
|
*/
|
||||||
function normalizeXML(el: Element) {
|
function normalizeXML(el: Element) {
|
||||||
normalizeTIf(el);
|
normalizeTIf(el);
|
||||||
normalizeTEsc(el);
|
normalizeTEscTOut(el);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
import { version } from "../version";
|
import { version } from "../version";
|
||||||
import { Component, ComponentConstructor, Props } from "./component";
|
import { Component, ComponentConstructor, Props } from "./component";
|
||||||
import { ComponentNode } from "./component_node";
|
import { ComponentNode } from "./component_node";
|
||||||
import { nodeErrorHandlers, OwlError, handleError } from "./error_handling";
|
import { nodeErrorHandlers, handleError } from "./error_handling";
|
||||||
|
import { OwlError } from "../common/owl_error";
|
||||||
import { Fiber, RootFiber, MountOptions } from "./fibers";
|
import { Fiber, RootFiber, MountOptions } from "./fibers";
|
||||||
import { Scheduler } from "./scheduler";
|
import { Scheduler } from "./scheduler";
|
||||||
import { validateProps } from "./template_helpers";
|
import { validateProps } from "./template_helpers";
|
||||||
import { TemplateSet, TemplateSetConfig } from "./template_set";
|
import { TemplateSet, TemplateSetConfig } from "./template_set";
|
||||||
import { validateTarget } from "./utils";
|
import { validateTarget } from "./utils";
|
||||||
|
import { toRaw, reactive } from "./reactivity";
|
||||||
|
|
||||||
// reimplement dev mode stuff see last change in 0f7a8289a6fb8387c3c1af41c6664b2a8448758f
|
// reimplement dev mode stuff see last change in 0f7a8289a6fb8387c3c1af41c6664b2a8448758f
|
||||||
|
|
||||||
@@ -33,21 +35,21 @@ This is not suitable for production use.
|
|||||||
See https://github.com/odoo/owl/blob/${hash}/doc/reference/app.md#configuration for more information.`;
|
See https://github.com/odoo/owl/blob/${hash}/doc/reference/app.md#configuration for more information.`;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const apps = new Set<App>();
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface Window {
|
interface Window {
|
||||||
__OWL_DEVTOOLS__: {
|
__OWL_DEVTOOLS__: {
|
||||||
apps: Set<App>;
|
apps: Set<App>;
|
||||||
Fiber: typeof Fiber;
|
Fiber: typeof Fiber;
|
||||||
RootFiber: typeof RootFiber;
|
RootFiber: typeof RootFiber;
|
||||||
|
toRaw: typeof toRaw;
|
||||||
|
reactive: typeof reactive;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
window.__OWL_DEVTOOLS__ ||= {
|
window.__OWL_DEVTOOLS__ ||= { apps, Fiber, RootFiber, toRaw, reactive };
|
||||||
apps: new Set<App>(),
|
|
||||||
Fiber: Fiber,
|
|
||||||
RootFiber: RootFiber,
|
|
||||||
};
|
|
||||||
|
|
||||||
export class App<
|
export class App<
|
||||||
T extends abstract new (...args: any) => any = any,
|
T extends abstract new (...args: any) => any = any,
|
||||||
@@ -55,6 +57,7 @@ export class App<
|
|||||||
E = any
|
E = any
|
||||||
> extends TemplateSet {
|
> extends TemplateSet {
|
||||||
static validateTarget = validateTarget;
|
static validateTarget = validateTarget;
|
||||||
|
static apps = apps;
|
||||||
static version = version;
|
static version = version;
|
||||||
|
|
||||||
name: string;
|
name: string;
|
||||||
@@ -69,7 +72,7 @@ export class App<
|
|||||||
super(config);
|
super(config);
|
||||||
this.name = config.name || "";
|
this.name = config.name || "";
|
||||||
this.Root = Root;
|
this.Root = Root;
|
||||||
window.__OWL_DEVTOOLS__.apps.add(this);
|
apps.add(this);
|
||||||
if (config.test) {
|
if (config.test) {
|
||||||
this.dev = true;
|
this.dev = true;
|
||||||
}
|
}
|
||||||
@@ -131,10 +134,10 @@ export class App<
|
|||||||
|
|
||||||
destroy() {
|
destroy() {
|
||||||
if (this.root) {
|
if (this.root) {
|
||||||
this.scheduler.flush();
|
|
||||||
this.root.destroy();
|
this.root.destroy();
|
||||||
|
this.scheduler.processTasks();
|
||||||
}
|
}
|
||||||
window.__OWL_DEVTOOLS__.apps.delete(this);
|
apps.delete(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
createComponent<P extends Props>(
|
createComponent<P extends Props>(
|
||||||
|
|||||||
@@ -36,13 +36,21 @@ export function createAttrUpdater(attr: string): Setter<HTMLElement> {
|
|||||||
|
|
||||||
export function attrsSetter(this: HTMLElement, attrs: any) {
|
export function attrsSetter(this: HTMLElement, attrs: any) {
|
||||||
if (isArray(attrs)) {
|
if (isArray(attrs)) {
|
||||||
|
if (attrs[0] === "class") {
|
||||||
|
setClass.call(this, attrs[1]);
|
||||||
|
} else {
|
||||||
setAttribute.call(this, attrs[0], attrs[1]);
|
setAttribute.call(this, attrs[0], attrs[1]);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
for (let k in attrs) {
|
for (let k in attrs) {
|
||||||
|
if (k === "class") {
|
||||||
|
setClass.call(this, attrs[k]);
|
||||||
|
} else {
|
||||||
setAttribute.call(this, k, attrs[k]);
|
setAttribute.call(this, k, attrs[k]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function attrsUpdater(this: HTMLElement, attrs: any, oldAttrs: any) {
|
export function attrsUpdater(this: HTMLElement, attrs: any, oldAttrs: any) {
|
||||||
if (isArray(attrs)) {
|
if (isArray(attrs)) {
|
||||||
@@ -52,7 +60,11 @@ export function attrsUpdater(this: HTMLElement, attrs: any, oldAttrs: any) {
|
|||||||
if (val === oldAttrs[1]) {
|
if (val === oldAttrs[1]) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (name === "class") {
|
||||||
|
updateClass.call(this, val, oldAttrs[1]);
|
||||||
|
} else {
|
||||||
setAttribute.call(this, name, val);
|
setAttribute.call(this, name, val);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
removeAttribute.call(this, oldAttrs[0]);
|
removeAttribute.call(this, oldAttrs[0]);
|
||||||
setAttribute.call(this, name, val);
|
setAttribute.call(this, name, val);
|
||||||
@@ -60,17 +72,25 @@ export function attrsUpdater(this: HTMLElement, attrs: any, oldAttrs: any) {
|
|||||||
} else {
|
} else {
|
||||||
for (let k in oldAttrs) {
|
for (let k in oldAttrs) {
|
||||||
if (!(k in attrs)) {
|
if (!(k in attrs)) {
|
||||||
|
if (k === "class") {
|
||||||
|
updateClass.call(this, "", oldAttrs[k]);
|
||||||
|
} else {
|
||||||
removeAttribute.call(this, k);
|
removeAttribute.call(this, k);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
for (let k in attrs) {
|
for (let k in attrs) {
|
||||||
const val = attrs[k];
|
const val = attrs[k];
|
||||||
if (val !== oldAttrs[k]) {
|
if (val !== oldAttrs[k]) {
|
||||||
|
if (k === "class") {
|
||||||
|
updateClass.call(this, val, oldAttrs[k]);
|
||||||
|
} else {
|
||||||
setAttribute.call(this, k, val);
|
setAttribute.call(this, k, val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function toClassObj(expr: string | number | { [c: string]: any }) {
|
function toClassObj(expr: string | number | { [c: string]: any }) {
|
||||||
const result: { [c: string]: any } = {};
|
const result: { [c: string]: any } = {};
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { OwlError } from "../error_handling";
|
import { OwlError } from "../../common/owl_error";
|
||||||
import { attrsSetter, attrsUpdater, createAttrUpdater, setClass, updateClass } from "./attributes";
|
import { attrsSetter, attrsUpdater, createAttrUpdater, setClass, updateClass } from "./attributes";
|
||||||
import { config } from "./config";
|
import { config } from "./config";
|
||||||
import { createEventHandler } from "./events";
|
import { createEventHandler } from "./events";
|
||||||
@@ -144,12 +144,7 @@ function buildTree(
|
|||||||
info.push({ type: "child", idx: index });
|
info.push({ type: "child", idx: index });
|
||||||
el = document.createTextNode("");
|
el = document.createTextNode("");
|
||||||
}
|
}
|
||||||
const attrs = (node as Element).attributes;
|
currentNS ||= (node as Element).namespaceURI;
|
||||||
const ns = attrs.getNamedItem("block-ns");
|
|
||||||
if (ns) {
|
|
||||||
attrs.removeNamedItem("block-ns");
|
|
||||||
currentNS = ns.value;
|
|
||||||
}
|
|
||||||
if (!el) {
|
if (!el) {
|
||||||
el = currentNS
|
el = currentNS
|
||||||
? document.createElementNS(currentNS, tagName)
|
? document.createElementNS(currentNS, tagName)
|
||||||
@@ -165,6 +160,7 @@ function buildTree(
|
|||||||
const fragment = document.createElement("template").content;
|
const fragment = document.createElement("template").content;
|
||||||
fragment.appendChild(el);
|
fragment.appendChild(el);
|
||||||
}
|
}
|
||||||
|
const attrs = (node as Element).attributes;
|
||||||
for (let i = 0; i < attrs.length; i++) {
|
for (let i = 0; i < attrs.length; i++) {
|
||||||
const attrName = attrs[i].name;
|
const attrName = attrs[i].name;
|
||||||
const attrValue = attrs[i].value;
|
const attrValue = attrs[i].value;
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ export type ComponentConstructor<P extends Props = any, E = any> = (new (
|
|||||||
|
|
||||||
export class Component<Props = any, Env = any> {
|
export class Component<Props = any, Env = any> {
|
||||||
static template: string = "";
|
static template: string = "";
|
||||||
static props?: any;
|
static props?: Schema;
|
||||||
static defaultProps?: any;
|
static defaultProps?: any;
|
||||||
|
|
||||||
props: Props;
|
props: Props;
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
import type { App, Env } from "./app";
|
import type { App, Env } from "./app";
|
||||||
import { BDom, VNode } from "./blockdom";
|
import { BDom, VNode } from "./blockdom";
|
||||||
import { Component, ComponentConstructor, Props } from "./component";
|
import { Component, ComponentConstructor, Props } from "./component";
|
||||||
import { fibersInError, OwlError } from "./error_handling";
|
import { fibersInError } from "./error_handling";
|
||||||
|
import { OwlError } from "../common/owl_error";
|
||||||
import { Fiber, makeChildFiber, makeRootFiber, MountFiber, MountOptions } from "./fibers";
|
import { Fiber, makeChildFiber, makeRootFiber, MountFiber, MountOptions } from "./fibers";
|
||||||
import { clearReactivesForCallback, getSubscriptions, reactive, targets } from "./reactivity";
|
import { clearReactivesForCallback, getSubscriptions, reactive, targets } from "./reactivity";
|
||||||
import { STATUS } from "./status";
|
import { STATUS } from "./status";
|
||||||
@@ -145,6 +146,9 @@ export class ComponentNode<P extends Props = any, E = any> implements VNode<Comp
|
|||||||
}
|
}
|
||||||
|
|
||||||
async render(deep: boolean) {
|
async render(deep: boolean) {
|
||||||
|
if (this.status >= STATUS.CANCELLED) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
let current = this.fiber;
|
let current = this.fiber;
|
||||||
if (current && (current.root!.locked || (current as any).bdom === true)) {
|
if (current && (current.root!.locked || (current as any).bdom === true)) {
|
||||||
await Promise.resolve();
|
await Promise.resolve();
|
||||||
@@ -171,7 +175,7 @@ export class ComponentNode<P extends Props = any, E = any> implements VNode<Comp
|
|||||||
|
|
||||||
this.app.scheduler.addFiber(fiber);
|
this.app.scheduler.addFiber(fiber);
|
||||||
await Promise.resolve();
|
await Promise.resolve();
|
||||||
if (this.status === STATUS.DESTROYED) {
|
if (this.status >= STATUS.CANCELLED) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// We only want to actually render the component if the following two
|
// We only want to actually render the component if the following two
|
||||||
@@ -190,6 +194,20 @@ export class ComponentNode<P extends Props = any, E = any> implements VNode<Comp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cancel() {
|
||||||
|
this._cancel();
|
||||||
|
delete this.parent!.children[this.parentKey!];
|
||||||
|
this.app.scheduler.scheduleDestroy(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
_cancel() {
|
||||||
|
this.status = STATUS.CANCELLED;
|
||||||
|
const children = this.children;
|
||||||
|
for (let childKey in children) {
|
||||||
|
children[childKey]._cancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
destroy() {
|
destroy() {
|
||||||
let shouldRemove = this.status === STATUS.MOUNTED;
|
let shouldRemove = this.status === STATUS.MOUNTED;
|
||||||
this._destroy();
|
this._destroy();
|
||||||
|
|||||||
@@ -1,11 +1,7 @@
|
|||||||
|
import { OwlError } from "../common/owl_error";
|
||||||
import type { ComponentNode } from "./component_node";
|
import type { ComponentNode } from "./component_node";
|
||||||
import type { Fiber } from "./fibers";
|
import type { Fiber } from "./fibers";
|
||||||
|
|
||||||
// Custom error class that wraps error that happen in the owl lifecycle
|
|
||||||
export class OwlError extends Error {
|
|
||||||
cause?: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Maps fibers to thrown errors
|
// Maps fibers to thrown errors
|
||||||
export const fibersInError: WeakMap<Fiber, any> = new WeakMap();
|
export const fibersInError: WeakMap<Fiber, any> = new WeakMap();
|
||||||
export const nodeErrorHandlers: WeakMap<ComponentNode, ((error: any) => void)[]> = new WeakMap();
|
export const nodeErrorHandlers: WeakMap<ComponentNode, ((error: any) => void)[]> = new WeakMap();
|
||||||
@@ -51,8 +47,9 @@ export function handleError(params: ErrorParams) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
const node = "node" in params ? params.node : params.fiber.node;
|
const node = "node" in params ? params.node : params.fiber.node;
|
||||||
const fiber = "fiber" in params ? params.fiber : node.fiber!;
|
const fiber = "fiber" in params ? params.fiber : node.fiber;
|
||||||
|
|
||||||
|
if (fiber) {
|
||||||
// resets the fibers on components if possible. This is important so that
|
// resets the fibers on components if possible. This is important so that
|
||||||
// new renderings can be properly included in the initial one, if any.
|
// new renderings can be properly included in the initial one, if any.
|
||||||
let current: Fiber | null = fiber;
|
let current: Fiber | null = fiber;
|
||||||
@@ -62,6 +59,7 @@ export function handleError(params: ErrorParams) {
|
|||||||
} while (current);
|
} while (current);
|
||||||
|
|
||||||
fibersInError.set(fiber.root!, error);
|
fibersInError.set(fiber.root!, error);
|
||||||
|
}
|
||||||
|
|
||||||
const handled = _handleError(node, error);
|
const handled = _handleError(node, error);
|
||||||
if (!handled) {
|
if (!handled) {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { filterOutModifiersFromData } from "./blockdom/config";
|
import { filterOutModifiersFromData } from "./blockdom/config";
|
||||||
import { STATUS } from "./status";
|
import { STATUS } from "./status";
|
||||||
import { OwlError } from "./error_handling";
|
import { OwlError } from "../common/owl_error";
|
||||||
|
|
||||||
export const mainEventHandler = (data: any, ev: Event, currentTarget?: EventTarget | null) => {
|
export const mainEventHandler = (data: any, ev: Event, currentTarget?: EventTarget | null) => {
|
||||||
const { data: _data, modifiers } = filterOutModifiersFromData(data);
|
const { data: _data, modifiers } = filterOutModifiersFromData(data);
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { BDom, mount } from "./blockdom";
|
import { BDom, mount } from "./blockdom";
|
||||||
import type { ComponentNode } from "./component_node";
|
import type { ComponentNode } from "./component_node";
|
||||||
import { fibersInError, OwlError } from "./error_handling";
|
import { fibersInError } from "./error_handling";
|
||||||
|
import { OwlError } from "../common/owl_error";
|
||||||
import { STATUS } from "./status";
|
import { STATUS } from "./status";
|
||||||
|
|
||||||
export function makeChildFiber(node: ComponentNode, parent: Fiber): Fiber {
|
export function makeChildFiber(node: ComponentNode, parent: Fiber): Fiber {
|
||||||
@@ -55,8 +56,7 @@ function cancelFibers(fibers: Fiber[]): number {
|
|||||||
let node = fiber.node;
|
let node = fiber.node;
|
||||||
fiber.render = throwOnRender;
|
fiber.render = throwOnRender;
|
||||||
if (node.status === STATUS.NEW) {
|
if (node.status === STATUS.NEW) {
|
||||||
node.destroy();
|
node.cancel();
|
||||||
delete node.parent!.children[node.parentKey!];
|
|
||||||
}
|
}
|
||||||
node.fiber = null;
|
node.fiber = null;
|
||||||
if (fiber.bdom) {
|
if (fiber.bdom) {
|
||||||
|
|||||||
@@ -59,28 +59,35 @@ export function useChildSubEnv(envExtension: Env) {
|
|||||||
// useEffect
|
// useEffect
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
type EffectDeps<T extends unknown[]> = T | (T extends [...infer H, never] ? EffectDeps<H> : never);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {...any} dependencies the dependencies computed by computeDependencies
|
* @template T
|
||||||
|
* @param {...T} dependencies the dependencies computed by computeDependencies
|
||||||
* @returns {void|(()=>void)} a cleanup function that reverses the side
|
* @returns {void|(()=>void)} a cleanup function that reverses the side
|
||||||
* effects of the effect callback.
|
* effects of the effect callback.
|
||||||
*/
|
*/
|
||||||
type Effect = (...dependencies: any[]) => void | (() => void);
|
type Effect<T extends unknown[]> = (...dependencies: EffectDeps<T>) => void | (() => void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This hook will run a callback when a component is mounted and patched, and
|
* This hook will run a callback when a component is mounted and patched, and
|
||||||
* will run a cleanup function before patching and before unmounting the
|
* will run a cleanup function before patching and before unmounting the
|
||||||
* the component.
|
* the component.
|
||||||
*
|
*
|
||||||
* @param {Effect} effect the effect to run on component mount and/or patch
|
* @template T
|
||||||
* @param {()=>any[]} [computeDependencies=()=>[NaN]] a callback to compute
|
* @param {Effect<T>} effect the effect to run on component mount and/or patch
|
||||||
|
* @param {()=>[...T]} [computeDependencies=()=>[NaN]] a callback to compute
|
||||||
* dependencies that will decide if the effect needs to be cleaned up and
|
* dependencies that will decide if the effect needs to be cleaned up and
|
||||||
* run again. If the dependencies did not change, the effect will not run
|
* run again. If the dependencies did not change, the effect will not run
|
||||||
* again. The default value returns an array containing only NaN because
|
* again. The default value returns an array containing only NaN because
|
||||||
* NaN !== NaN, which will cause the effect to rerun on every patch.
|
* NaN !== NaN, which will cause the effect to rerun on every patch.
|
||||||
*/
|
*/
|
||||||
export function useEffect(effect: Effect, computeDependencies: () => any[] = () => [NaN]) {
|
export function useEffect<T extends unknown[]>(
|
||||||
|
effect: Effect<T>,
|
||||||
|
computeDependencies: () => [...T] = () => [NaN] as never
|
||||||
|
) {
|
||||||
let cleanup: (() => void) | void;
|
let cleanup: (() => void) | void;
|
||||||
let dependencies: any[];
|
let dependencies: T;
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
dependencies = computeDependencies();
|
dependencies = computeDependencies();
|
||||||
cleanup = effect(...dependencies);
|
cleanup = effect(...dependencies);
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ export {
|
|||||||
onError,
|
onError,
|
||||||
} from "./lifecycle_hooks";
|
} from "./lifecycle_hooks";
|
||||||
export { validate, validateType } from "./validation";
|
export { validate, validateType } from "./validation";
|
||||||
export { OwlError } from "./error_handling";
|
export { OwlError } from "../common/owl_error";
|
||||||
|
|
||||||
export const __info__ = {
|
export const __info__ = {
|
||||||
version: App.version,
|
version: App.version,
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { getCurrent } from "./component_node";
|
import { getCurrent } from "./component_node";
|
||||||
import { nodeErrorHandlers, OwlError } from "./error_handling";
|
import { nodeErrorHandlers } from "./error_handling";
|
||||||
|
import { OwlError } from "../common/owl_error";
|
||||||
|
|
||||||
const TIMEOUT = Symbol("timeout");
|
const TIMEOUT = Symbol("timeout");
|
||||||
function wrapError(fn: (...args: any[]) => any, hookName: string) {
|
function wrapError(fn: (...args: any[]) => any, hookName: string) {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { onMounted, onWillUnmount } from "./lifecycle_hooks";
|
import { onMounted, onWillUnmount } from "./lifecycle_hooks";
|
||||||
import { BDom, text, VNode } from "./blockdom";
|
import { BDom, text, VNode } from "./blockdom";
|
||||||
import { Component } from "./component";
|
import { Component } from "./component";
|
||||||
import { OwlError } from "./error_handling";
|
import { OwlError } from "../common/owl_error";
|
||||||
|
|
||||||
const VText: any = text("").constructor;
|
const VText: any = text("").constructor;
|
||||||
|
|
||||||
@@ -65,7 +65,7 @@ export class Portal extends Component {
|
|||||||
type: String,
|
type: String,
|
||||||
},
|
},
|
||||||
slots: true,
|
slots: true,
|
||||||
};
|
} as const;
|
||||||
|
|
||||||
setup() {
|
setup() {
|
||||||
const node: any = this.__owl__;
|
const node: any = this.__owl__;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import type { Callback } from "./utils";
|
import type { Callback } from "./utils";
|
||||||
import { OwlError } from "./error_handling";
|
import { OwlError } from "../common/owl_error";
|
||||||
|
|
||||||
// Special key to subscribe to, to be notified of key creation/deletion
|
// Special key to subscribe to, to be notified of key creation/deletion
|
||||||
const KEYCHANGES = Symbol("Key changes");
|
const KEYCHANGES = Symbol("Key changes");
|
||||||
@@ -249,7 +249,7 @@ function basicProxyHandler<T extends Target>(callback: Callback): ProxyHandler<T
|
|||||||
set(target, key, value, receiver) {
|
set(target, key, value, receiver) {
|
||||||
const hadKey = objectHasOwnProperty.call(target, key);
|
const hadKey = objectHasOwnProperty.call(target, key);
|
||||||
const originalValue = Reflect.get(target, key, receiver);
|
const originalValue = Reflect.get(target, key, receiver);
|
||||||
const ret = Reflect.set(target, key, value, receiver);
|
const ret = Reflect.set(target, key, toRaw(value), receiver);
|
||||||
if (!hadKey && objectHasOwnProperty.call(target, key)) {
|
if (!hadKey && objectHasOwnProperty.call(target, key)) {
|
||||||
notifyReactives(target, KEYCHANGES);
|
notifyReactives(target, KEYCHANGES);
|
||||||
}
|
}
|
||||||
@@ -368,7 +368,7 @@ function delegateAndNotify(
|
|||||||
if (hadKey !== hasKey) {
|
if (hadKey !== hasKey) {
|
||||||
notifyReactives(target, KEYCHANGES);
|
notifyReactives(target, KEYCHANGES);
|
||||||
}
|
}
|
||||||
if (originalValue !== value) {
|
if (originalValue !== target[getterName](key)) {
|
||||||
notifyReactives(target, key);
|
notifyReactives(target, key);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import type { ComponentNode } from "./component_node";
|
||||||
import { fibersInError } from "./error_handling";
|
import { fibersInError } from "./error_handling";
|
||||||
import { Fiber, RootFiber } from "./fibers";
|
import { Fiber, RootFiber } from "./fibers";
|
||||||
import { STATUS } from "./status";
|
import { STATUS } from "./status";
|
||||||
@@ -14,6 +15,7 @@ export class Scheduler {
|
|||||||
requestAnimationFrame: Window["requestAnimationFrame"];
|
requestAnimationFrame: Window["requestAnimationFrame"];
|
||||||
frame: number = 0;
|
frame: number = 0;
|
||||||
delayedRenders: Fiber[] = [];
|
delayedRenders: Fiber[] = [];
|
||||||
|
cancelledNodes: Set<ComponentNode> = new Set();
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.requestAnimationFrame = Scheduler.requestAnimationFrame;
|
this.requestAnimationFrame = Scheduler.requestAnimationFrame;
|
||||||
@@ -23,6 +25,13 @@ export class Scheduler {
|
|||||||
this.tasks.add(fiber.root!);
|
this.tasks.add(fiber.root!);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
scheduleDestroy(node: ComponentNode) {
|
||||||
|
this.cancelledNodes.add(node);
|
||||||
|
if (this.frame === 0) {
|
||||||
|
this.frame = this.requestAnimationFrame(() => this.processTasks());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Process all current tasks. This only applies to the fibers that are ready.
|
* Process all current tasks. This only applies to the fibers that are ready.
|
||||||
* Other tasks are left unchanged.
|
* Other tasks are left unchanged.
|
||||||
@@ -39,16 +48,24 @@ export class Scheduler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (this.frame === 0) {
|
if (this.frame === 0) {
|
||||||
this.frame = this.requestAnimationFrame(() => {
|
this.frame = this.requestAnimationFrame(() => this.processTasks());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
processTasks() {
|
||||||
this.frame = 0;
|
this.frame = 0;
|
||||||
this.tasks.forEach((fiber) => this.processFiber(fiber));
|
for (let node of this.cancelledNodes) {
|
||||||
|
node._destroy();
|
||||||
|
}
|
||||||
|
this.cancelledNodes.clear();
|
||||||
|
for (let task of this.tasks) {
|
||||||
|
this.processFiber(task);
|
||||||
|
}
|
||||||
for (let task of this.tasks) {
|
for (let task of this.tasks) {
|
||||||
if (task.node.status === STATUS.DESTROYED) {
|
if (task.node.status === STATUS.DESTROYED) {
|
||||||
this.tasks.delete(task);
|
this.tasks.delete(task);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
processFiber(fiber: RootFiber) {
|
processFiber(fiber: RootFiber) {
|
||||||
|
|||||||
@@ -7,15 +7,20 @@ import type { Component } from "./component";
|
|||||||
export const enum STATUS {
|
export const enum STATUS {
|
||||||
NEW,
|
NEW,
|
||||||
MOUNTED, // is ready, and in DOM. It has a valid el
|
MOUNTED, // is ready, and in DOM. It has a valid el
|
||||||
|
// component has been created, but has been replaced by a newer component before being mounted
|
||||||
|
// it is cancelled until the next animation frame where it will be destroyed
|
||||||
|
CANCELLED,
|
||||||
DESTROYED,
|
DESTROYED,
|
||||||
}
|
}
|
||||||
|
|
||||||
type STATUS_DESCR = "new" | "mounted" | "destroyed";
|
type STATUS_DESCR = "new" | "mounted" | "cancelled" | "destroyed";
|
||||||
|
|
||||||
export function status(component: Component): STATUS_DESCR {
|
export function status(component: Component): STATUS_DESCR {
|
||||||
switch (component.__owl__.status) {
|
switch (component.__owl__.status) {
|
||||||
case STATUS.NEW:
|
case STATUS.NEW:
|
||||||
return "new";
|
return "new";
|
||||||
|
case STATUS.CANCELLED:
|
||||||
|
return "cancelled";
|
||||||
case STATUS.MOUNTED:
|
case STATUS.MOUNTED:
|
||||||
return "mounted";
|
return "mounted";
|
||||||
case STATUS.DESTROYED:
|
case STATUS.DESTROYED:
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { html } from "./blockdom/index";
|
|||||||
import { isOptional, validateSchema } from "./validation";
|
import { isOptional, validateSchema } from "./validation";
|
||||||
import type { ComponentConstructor } from "./component";
|
import type { ComponentConstructor } from "./component";
|
||||||
import { markRaw } from "./reactivity";
|
import { markRaw } from "./reactivity";
|
||||||
import { OwlError } from "./error_handling";
|
import { OwlError } from "../common/owl_error";
|
||||||
import type { ComponentNode } from "./component_node";
|
import type { ComponentNode } from "./component_node";
|
||||||
|
|
||||||
const ObjectCreate = Object.create;
|
const ObjectCreate = Object.create;
|
||||||
@@ -60,18 +60,24 @@ function withKey(elem: any, k: string) {
|
|||||||
return elem;
|
return elem;
|
||||||
}
|
}
|
||||||
|
|
||||||
function prepareList(collection: any): [any[], any[], number, any[]] {
|
function prepareList(collection: unknown): [unknown[], unknown[], number, undefined[]] {
|
||||||
let keys: any[];
|
let keys: unknown[];
|
||||||
let values: any[];
|
let values: unknown[];
|
||||||
|
|
||||||
if (Array.isArray(collection)) {
|
if (Array.isArray(collection)) {
|
||||||
keys = collection;
|
keys = collection;
|
||||||
values = collection;
|
values = collection;
|
||||||
} else if (collection) {
|
} else if (collection instanceof Map) {
|
||||||
values = Object.keys(collection);
|
keys = [...collection.keys()];
|
||||||
keys = Object.values(collection);
|
values = [...collection.values()];
|
||||||
|
} else if (Symbol.iterator in Object(collection)) {
|
||||||
|
keys = [...(<Iterable<unknown>>collection)];
|
||||||
|
values = keys;
|
||||||
|
} else if (collection && typeof collection === "object") {
|
||||||
|
values = Object.values(collection);
|
||||||
|
keys = Object.keys(collection);
|
||||||
} else {
|
} else {
|
||||||
throw new OwlError("Invalid loop expression");
|
throw new OwlError(`Invalid loop expression: "${collection}" is not iterable`);
|
||||||
}
|
}
|
||||||
const n = values.length;
|
const n = values.length;
|
||||||
return [keys, values, n, new Array(n)];
|
return [keys, values, n, new Array(n)];
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { comment, createBlock, html, list, multi, text, toggler } from "./blockd
|
|||||||
import { getCurrent } from "./component_node";
|
import { getCurrent } from "./component_node";
|
||||||
import { Portal, portalTemplate } from "./portal";
|
import { Portal, portalTemplate } from "./portal";
|
||||||
import { helpers } from "./template_helpers";
|
import { helpers } from "./template_helpers";
|
||||||
import { OwlError } from "./error_handling";
|
import { OwlError } from "../common/owl_error";
|
||||||
|
|
||||||
const bdom = { text, createBlock, list, multi, html, toggler, comment };
|
const bdom = { text, createBlock, list, multi, html, toggler, comment };
|
||||||
|
|
||||||
@@ -41,7 +41,7 @@ export interface TemplateSetConfig {
|
|||||||
dev?: boolean;
|
dev?: boolean;
|
||||||
translatableAttributes?: string[];
|
translatableAttributes?: string[];
|
||||||
translateFn?: (s: string) => string;
|
translateFn?: (s: string) => string;
|
||||||
templates?: string | Document;
|
templates?: string | Document | Record<string, string>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class TemplateSet {
|
export class TemplateSet {
|
||||||
@@ -60,12 +60,22 @@ export class TemplateSet {
|
|||||||
this.translateFn = config.translateFn;
|
this.translateFn = config.translateFn;
|
||||||
this.translatableAttributes = config.translatableAttributes;
|
this.translatableAttributes = config.translatableAttributes;
|
||||||
if (config.templates) {
|
if (config.templates) {
|
||||||
|
if (config.templates instanceof Document || typeof config.templates === "string") {
|
||||||
this.addTemplates(config.templates);
|
this.addTemplates(config.templates);
|
||||||
|
} else {
|
||||||
|
for (const name in config.templates) {
|
||||||
|
this.addTemplate(name, config.templates[name]);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
addTemplate(name: string, template: string | Element) {
|
addTemplate(name: string, template: string | Element) {
|
||||||
if (name in this.rawTemplates) {
|
if (name in this.rawTemplates) {
|
||||||
|
// this check can be expensive, just silently ignore double definitions outside dev mode
|
||||||
|
if (!this.dev) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
const rawTemplate = this.rawTemplates[name];
|
const rawTemplate = this.rawTemplates[name];
|
||||||
const currentAsString =
|
const currentAsString =
|
||||||
typeof rawTemplate === "string"
|
typeof rawTemplate === "string"
|
||||||
@@ -125,7 +135,7 @@ export class TemplateSet {
|
|||||||
|
|
||||||
callTemplate(owner: any, subTemplate: string, ctx: any, parent: any, key: any): any {
|
callTemplate(owner: any, subTemplate: string, ctx: any, parent: any, key: any): any {
|
||||||
const template = this.getTemplate(subTemplate);
|
const template = this.getTemplate(subTemplate);
|
||||||
return toggler(subTemplate, template.call(owner, ctx, parent, key));
|
return toggler(subTemplate, template.call(owner, ctx, parent, key + subTemplate));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { OwlError } from "./error_handling";
|
import { OwlError } from "../common/owl_error";
|
||||||
export type Callback = () => void;
|
export type Callback = () => void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -9,20 +9,13 @@ export type Callback = () => void;
|
|||||||
* @returns a batched version of the original callback
|
* @returns a batched version of the original callback
|
||||||
*/
|
*/
|
||||||
export function batched(callback: Callback): Callback {
|
export function batched(callback: Callback): Callback {
|
||||||
let called = false;
|
let scheduled = false;
|
||||||
return async () => {
|
return async (...args) => {
|
||||||
// This await blocks all calls to the callback here, then releases them sequentially
|
if (!scheduled) {
|
||||||
// in the next microtick. This line decides the granularity of the batch.
|
scheduled = true;
|
||||||
await Promise.resolve();
|
await Promise.resolve();
|
||||||
if (!called) {
|
scheduled = false;
|
||||||
called = true;
|
callback(...args);
|
||||||
// wait for all calls in this microtick to fall through before resetting "called"
|
|
||||||
// so that only the first call to the batched function calls the original callback.
|
|
||||||
// Schedule this before calling the callback so that calls to the batched function
|
|
||||||
// within the callback will proceed only after resetting called to false, and have
|
|
||||||
// a chance to execute the callback again
|
|
||||||
Promise.resolve().then(() => (called = false));
|
|
||||||
callback();
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { OwlError } from "./error_handling";
|
import { OwlError } from "../common/owl_error";
|
||||||
import { toRaw } from "./reactivity";
|
import { toRaw } from "./reactivity";
|
||||||
|
|
||||||
type BaseType =
|
type BaseType =
|
||||||
@@ -8,6 +8,7 @@ type BaseType =
|
|||||||
| typeof Date
|
| typeof Date
|
||||||
| typeof Object
|
| typeof Object
|
||||||
| typeof Array
|
| typeof Array
|
||||||
|
| typeof Function
|
||||||
| true
|
| true
|
||||||
| "*";
|
| "*";
|
||||||
|
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
// do not modify manually. This file is generated by the release script.
|
// do not modify manually. This file is generated by the release script.
|
||||||
export const version = "2.1.2";
|
export const version = "2.2.7";
|
||||||
|
|||||||
@@ -353,7 +353,7 @@ exports[`Reactivity: useState useless atoms should be deleted 1`] = `
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block2, v_block2, l_block2, c_block2] = prepareList(Object.keys(ctx['state']));;
|
const [k_block2, v_block2, l_block2, c_block2] = prepareList(Object.keys(ctx['state']));;
|
||||||
for (let i1 = 0; i1 < l_block2; i1++) {
|
for (let i1 = 0; i1 < l_block2; i1++) {
|
||||||
ctx[\`id\`] = v_block2[i1];
|
ctx[\`id\`] = k_block2[i1];
|
||||||
const key1 = ctx['id'];
|
const key1 = ctx['id'];
|
||||||
c_block2[i1] = withKey(comp1({id: ctx['id']}, key + \`__1__\${key1}\`, node, this, null), key1);
|
c_block2[i1] = withKey(comp1({id: ctx['id']}, key + \`__1__\${key1}\`, node, this, null), key1);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,34 @@ exports[`app App supports env with getters/setters 1`] = `
|
|||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`app app: clear scheduler tasks and destroy cancelled nodes immediately on destroy 1`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
const comp1 = app.createComponent(\`B\`, true, false, false, []);
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
let b2, b3;
|
||||||
|
b2 = text(\`A\`);
|
||||||
|
if (ctx['state'].value) {
|
||||||
|
b3 = comp1({}, key + \`__1\`, node, this, null);
|
||||||
|
}
|
||||||
|
return multi([b2, b3]);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`app app: clear scheduler tasks and destroy cancelled nodes immediately on destroy 3`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
return text(\`B\`);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`app can configure an app with props 1`] = `
|
exports[`app can configure an app with props 1`] = `
|
||||||
"function anonymous(app, bdom, helpers
|
"function anonymous(app, bdom, helpers
|
||||||
) {
|
) {
|
||||||
@@ -29,6 +57,19 @@ exports[`app can configure an app with props 1`] = `
|
|||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`app can load templates from an object name-string 1`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
|
||||||
|
let block1 = createBlock(\`<div class=\\"hello\\">hello</div>\`);
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
return block1();
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`app can mount app in an iframe 1`] = `
|
exports[`app can mount app in an iframe 1`] = `
|
||||||
"function anonymous(app, bdom, helpers
|
"function anonymous(app, bdom, helpers
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -1,6 +1,15 @@
|
|||||||
import { App, Component, mount, xml } from "../../src";
|
import { App, Component, mount, onWillStart, useState, xml } from "../../src";
|
||||||
import { status } from "../../src/runtime/status";
|
import { status } from "../../src/runtime/status";
|
||||||
import { makeTestFixture, snapshotEverything, nextTick, elem } from "../helpers";
|
import {
|
||||||
|
makeTestFixture,
|
||||||
|
snapshotEverything,
|
||||||
|
nextTick,
|
||||||
|
elem,
|
||||||
|
useLogLifecycle,
|
||||||
|
makeDeferred,
|
||||||
|
nextMicroTick,
|
||||||
|
steps,
|
||||||
|
} from "../helpers";
|
||||||
|
|
||||||
let fixture: HTMLElement;
|
let fixture: HTMLElement;
|
||||||
|
|
||||||
@@ -94,4 +103,85 @@ describe("app", () => {
|
|||||||
expect(iframeDoc.contains(div)).toBe(false);
|
expect(iframeDoc.contains(div)).toBe(false);
|
||||||
expect(status(comp)).toBe("destroyed");
|
expect(status(comp)).toBe("destroyed");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("app: clear scheduler tasks and destroy cancelled nodes immediately on destroy", async () => {
|
||||||
|
let def = makeDeferred();
|
||||||
|
class B extends Component {
|
||||||
|
static template = xml`B`;
|
||||||
|
setup() {
|
||||||
|
useLogLifecycle();
|
||||||
|
onWillStart(() => def);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class A extends Component {
|
||||||
|
static template = xml`A<t t-if="state.value"><B/></t>`;
|
||||||
|
static components = { B };
|
||||||
|
state = useState({ value: false });
|
||||||
|
setup() {
|
||||||
|
useLogLifecycle();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const app = new App(A);
|
||||||
|
const comp = await app.mount(fixture);
|
||||||
|
expect(steps.splice(0)).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
|
"A:setup",
|
||||||
|
"A:willStart",
|
||||||
|
"A:willRender",
|
||||||
|
"A:rendered",
|
||||||
|
"A:mounted",
|
||||||
|
]
|
||||||
|
`);
|
||||||
|
|
||||||
|
comp.state.value = true;
|
||||||
|
await nextTick();
|
||||||
|
expect(steps.splice(0)).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
|
"A:willRender",
|
||||||
|
"B:setup",
|
||||||
|
"B:willStart",
|
||||||
|
"A:rendered",
|
||||||
|
]
|
||||||
|
`);
|
||||||
|
|
||||||
|
// rerender to force the instantiation of a new B component (and cancelling the first)
|
||||||
|
comp.render();
|
||||||
|
await nextMicroTick();
|
||||||
|
expect(steps.splice(0)).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
|
"A:willRender",
|
||||||
|
"B:setup",
|
||||||
|
"B:willStart",
|
||||||
|
"A:rendered",
|
||||||
|
]
|
||||||
|
`);
|
||||||
|
|
||||||
|
app.destroy();
|
||||||
|
expect(steps.splice(0)).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
|
"A:willUnmount",
|
||||||
|
"B:willDestroy",
|
||||||
|
"A:willDestroy",
|
||||||
|
"B:willDestroy",
|
||||||
|
]
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("can load templates from an object name-string", async () => {
|
||||||
|
const templates = {
|
||||||
|
hello: `<div class="hello">hello</div>`,
|
||||||
|
world: `<div>world</div>`,
|
||||||
|
};
|
||||||
|
class SomeComponent extends Component {
|
||||||
|
static template = "hello";
|
||||||
|
}
|
||||||
|
|
||||||
|
const app = new App(SomeComponent, { templates });
|
||||||
|
await app.mount(fixture);
|
||||||
|
expect(fixture.querySelector(".hello")).toBeDefined();
|
||||||
|
// Only the "hello" template is used, so the "world" template is not yet loaded
|
||||||
|
expect(Object.keys(app.templates)).toEqual(["hello"]);
|
||||||
|
expect(Object.keys(app.rawTemplates)).toEqual(["hello", "world"]);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -244,12 +244,14 @@ describe("misc", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test("namespace is not propagated to siblings", () => {
|
test("namespace is not propagated to siblings", () => {
|
||||||
const block = createBlock(`<div><svg block-ns="someNameSpace"><g/></svg><div></div></div>`);
|
const block = createBlock(`<div><svg xmlns="someNameSpace"><g/></svg><div></div></div>`);
|
||||||
|
|
||||||
const fixture = makeTestFixture();
|
const fixture = makeTestFixture();
|
||||||
mount(block(), fixture);
|
mount(block(), fixture);
|
||||||
|
|
||||||
expect(fixture.innerHTML).toBe("<div><svg><g></g></svg><div></div></div>");
|
expect(fixture.innerHTML).toBe(
|
||||||
|
'<div><svg xmlns="someNameSpace"><g></g></svg><div></div></div>'
|
||||||
|
);
|
||||||
expect(fixture.querySelector("svg")!.namespaceURI).toBe("someNameSpace");
|
expect(fixture.querySelector("svg")!.namespaceURI).toBe("someNameSpace");
|
||||||
expect(fixture.querySelector("g")!.namespaceURI).toBe("someNameSpace");
|
expect(fixture.querySelector("g")!.namespaceURI).toBe("someNameSpace");
|
||||||
const allDivs = fixture.querySelectorAll("div");
|
const allDivs = fixture.querySelectorAll("div");
|
||||||
|
|||||||
@@ -145,3 +145,34 @@ test("class attribute (with a preexisting value", async () => {
|
|||||||
patch(tree, block([""]));
|
patch(tree, block([""]));
|
||||||
expect(fixture.innerHTML).toBe(`<div class="tomato"></div>`);
|
expect(fixture.innerHTML).toBe(`<div class="tomato"></div>`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("block-class attributes with preexisting class attribute", async () => {
|
||||||
|
const block = createBlock('<div block-attributes="0" class="owl"></div>');
|
||||||
|
const tree = block([{ class: "eagle" }]);
|
||||||
|
|
||||||
|
mount(tree, fixture);
|
||||||
|
expect(fixture.innerHTML).toBe(`<div class="owl eagle"></div>`);
|
||||||
|
|
||||||
|
patch(tree, block([{ class: "falcon" }]));
|
||||||
|
expect(fixture.innerHTML).toBe(`<div class="owl falcon"></div>`);
|
||||||
|
|
||||||
|
patch(tree, block([{}]));
|
||||||
|
expect(fixture.innerHTML).toBe(`<div class="owl"></div>`);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("block-class attributes (array syntax) with preexisting class attribute", async () => {
|
||||||
|
const block = createBlock('<div block-attributes="0" class="owl"></div>');
|
||||||
|
const tree = block([["class", "eagle"]]);
|
||||||
|
|
||||||
|
mount(tree, fixture);
|
||||||
|
expect(fixture.innerHTML).toBe(`<div class="owl eagle"></div>`);
|
||||||
|
|
||||||
|
patch(tree, block([["class", "falcon"]]));
|
||||||
|
expect(fixture.innerHTML).toBe(`<div class="owl falcon"></div>`);
|
||||||
|
|
||||||
|
patch(tree, block([["class", ""]]));
|
||||||
|
expect(fixture.innerHTML).toBe(`<div class="owl"></div>`);
|
||||||
|
|
||||||
|
patch(tree, block([["class", "buzzard"]]));
|
||||||
|
expect(fixture.innerHTML).toBe(`<div class="owl buzzard"></div>`);
|
||||||
|
});
|
||||||
|
|||||||
@@ -30,22 +30,22 @@ describe("namespace", () => {
|
|||||||
expect(fixture.firstElementChild!.namespaceURI).toBe(XHTML_URI);
|
expect(fixture.firstElementChild!.namespaceURI).toBe(XHTML_URI);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("namespace can be changed with block-ns", () => {
|
test("namespace can be changed with xmlns", () => {
|
||||||
const block = createBlock(`<tag block-ns="${SVG_URI}"/>`);
|
const block = createBlock(`<tag xmlns="${SVG_URI}"/>`);
|
||||||
const tree = block();
|
const tree = block();
|
||||||
mount(tree, fixture);
|
mount(tree, fixture);
|
||||||
expect(fixture.innerHTML).toBe("<tag></tag>");
|
expect(fixture.innerHTML).toBe(`<tag xmlns="${SVG_URI}"></tag>`);
|
||||||
expect(fixture.firstElementChild!.namespaceURI).toBe(SVG_URI);
|
expect(fixture.firstElementChild!.namespaceURI).toBe(SVG_URI);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("namespace is kept for children", () => {
|
test("namespace is kept for children", () => {
|
||||||
const block = createBlock(
|
const block = createBlock(
|
||||||
`<parent block-ns="${SVG_URI}"><child><subchild/></child><child/></parent>`
|
`<parent xmlns="${SVG_URI}"><child><subchild/></child><child/></parent>`
|
||||||
);
|
);
|
||||||
const tree = block();
|
const tree = block();
|
||||||
mount(tree, fixture);
|
mount(tree, fixture);
|
||||||
expect(fixture.innerHTML).toBe(
|
expect(fixture.innerHTML).toBe(
|
||||||
"<parent><child><subchild></subchild></child><child></child></parent>"
|
`<parent xmlns="${SVG_URI}"><child><subchild></subchild></child><child></child></parent>`
|
||||||
);
|
);
|
||||||
const parent = fixture.firstElementChild!;
|
const parent = fixture.firstElementChild!;
|
||||||
const child1 = parent.firstElementChild!;
|
const child1 = parent.firstElementChild!;
|
||||||
@@ -58,10 +58,10 @@ describe("namespace", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test("various namespaces in same block", () => {
|
test("various namespaces in same block", () => {
|
||||||
const block = createBlock(`<none><one block-ns="one"/><two block-ns="two"/></none>`);
|
const block = createBlock(`<none><one xmlns="one"/><two xmlns="two"/></none>`);
|
||||||
const tree = block();
|
const tree = block();
|
||||||
mount(tree, fixture);
|
mount(tree, fixture);
|
||||||
expect(fixture.innerHTML).toBe("<none><one></one><two></two></none>");
|
expect(fixture.innerHTML).toBe('<none><one xmlns="one"></one><two xmlns="two"></two></none>');
|
||||||
const none = fixture.firstElementChild!;
|
const none = fixture.firstElementChild!;
|
||||||
const one = none.firstElementChild!;
|
const one = none.firstElementChild!;
|
||||||
const two = one.nextElementSibling!;
|
const two = one.nextElementSibling!;
|
||||||
|
|||||||
@@ -707,6 +707,123 @@ exports[`attributes updating classes (with obj notation) 1`] = `
|
|||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`attributes various combinations of class, t-att-class, and t-att 1`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
|
||||||
|
let block1 = createBlock(\`<div block-attributes=\\"0\\" class=\\"c\\">content</div>\`);
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
let attr1 = {class:'a'};
|
||||||
|
return block1([attr1]);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`attributes various combinations of class, t-att-class, and t-att 2`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
|
||||||
|
let block1 = createBlock(\`<div block-attributes=\\"0\\" block-attribute-1=\\"class\\" class=\\"c\\">content</div>\`);
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
let attr1 = {class:'a'};
|
||||||
|
let attr2 = {'b':true};
|
||||||
|
return block1([attr1, attr2]);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`attributes various combinations of class, t-att-class, and t-att 3`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
|
||||||
|
let block1 = createBlock(\`<div block-attributes=\\"0\\" class=\\"c\\" block-attribute-1=\\"class\\">content</div>\`);
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
let attr1 = {class:'a'};
|
||||||
|
let attr2 = {'b':true};
|
||||||
|
return block1([attr1, attr2]);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`attributes various combinations of class, t-att-class, and t-att 4`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
|
||||||
|
let block1 = createBlock(\`<div class=\\"c\\" block-attributes=\\"0\\" block-attribute-1=\\"class\\">content</div>\`);
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
let attr1 = {class:'a'};
|
||||||
|
let attr2 = {'b':true};
|
||||||
|
return block1([attr1, attr2]);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`attributes various combinations of class, t-att-class, and t-att 5`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
|
||||||
|
let block1 = createBlock(\`<div class=\\"c\\" block-attribute-0=\\"class\\" block-attributes=\\"1\\">content</div>\`);
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
let attr1 = {'b':true};
|
||||||
|
let attr2 = {class:'a'};
|
||||||
|
return block1([attr1, attr2]);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`attributes various combinations of class, t-att-class, and t-att 6`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
|
||||||
|
let block1 = createBlock(\`<div class=\\"c\\" block-attribute-0=\\"class\\">content</div>\`);
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
let attr1 = {'b':true};
|
||||||
|
return block1([attr1]);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`attributes various combinations of class, t-att-class, and t-att 7`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
|
||||||
|
let block1 = createBlock(\`<div class=\\"c\\" block-attribute-0=\\"class\\">content</div>\`);
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
let attr1 = ('b');
|
||||||
|
return block1([attr1]);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`attributes various combinations of class, t-att-class, and t-att 8`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
|
||||||
|
let block1 = createBlock(\`<div block-attributes=\\"0\\" block-attribute-1=\\"class\\">content</div>\`);
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
let attr1 = {class:'a'};
|
||||||
|
let attr2 = {'b':true};
|
||||||
|
return block1([attr1, attr2]);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`attributes various escapes 1`] = `
|
exports[`attributes various escapes 1`] = `
|
||||||
"function anonymous(app, bdom, helpers
|
"function anonymous(app, bdom, helpers
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ exports[`t-on can bind handlers with empty object (with non empty inner string)
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block2, v_block2, l_block2, c_block2] = prepareList(['someval']);;
|
const [k_block2, v_block2, l_block2, c_block2] = prepareList(['someval']);;
|
||||||
for (let i1 = 0; i1 < l_block2; i1++) {
|
for (let i1 = 0; i1 < l_block2; i1++) {
|
||||||
ctx[\`action\`] = v_block2[i1];
|
ctx[\`action\`] = k_block2[i1];
|
||||||
ctx[\`action_index\`] = i1;
|
ctx[\`action_index\`] = i1;
|
||||||
const key1 = ctx['action_index'];
|
const key1 = ctx['action_index'];
|
||||||
const v1 = ctx['activate'];
|
const v1 = ctx['activate'];
|
||||||
@@ -142,7 +142,7 @@ exports[`t-on handler is bound to proper owner, part 2 1`] = `
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block1, v_block1, l_block1, c_block1] = prepareList([1]);;
|
const [k_block1, v_block1, l_block1, c_block1] = prepareList([1]);;
|
||||||
for (let i1 = 0; i1 < l_block1; i1++) {
|
for (let i1 = 0; i1 < l_block1; i1++) {
|
||||||
ctx[\`value\`] = v_block1[i1];
|
ctx[\`value\`] = k_block1[i1];
|
||||||
const key1 = ctx['value'];
|
const key1 = ctx['value'];
|
||||||
let hdlr1 = [ctx['add'], ctx];
|
let hdlr1 = [ctx['add'], ctx];
|
||||||
c_block1[i1] = withKey(block2([hdlr1]), key1);
|
c_block1[i1] = withKey(block2([hdlr1]), key1);
|
||||||
@@ -189,11 +189,11 @@ exports[`t-on handler is bound to proper owner, part 4 1`] = `
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block1, v_block1, l_block1, c_block1] = prepareList([1]);;
|
const [k_block1, v_block1, l_block1, c_block1] = prepareList([1]);;
|
||||||
for (let i1 = 0; i1 < l_block1; i1++) {
|
for (let i1 = 0; i1 < l_block1; i1++) {
|
||||||
ctx[\`value\`] = v_block1[i1];
|
ctx[\`value\`] = k_block1[i1];
|
||||||
ctx[\`value_first\`] = i1 === 0;
|
ctx[\`value_first\`] = i1 === 0;
|
||||||
ctx[\`value_last\`] = i1 === v_block1.length - 1;
|
ctx[\`value_last\`] = i1 === k_block1.length - 1;
|
||||||
ctx[\`value_index\`] = i1;
|
ctx[\`value_index\`] = i1;
|
||||||
ctx[\`value_value\`] = k_block1[i1];
|
ctx[\`value_value\`] = v_block1[i1];
|
||||||
const key1 = ctx['value'];
|
const key1 = ctx['value'];
|
||||||
c_block1[i1] = withKey(callTemplate_1.call(this, ctx, node, key + \`__1__\${key1}\`), key1);
|
c_block1[i1] = withKey(callTemplate_1.call(this, ctx, node, key + \`__1__\${key1}\`), key1);
|
||||||
}
|
}
|
||||||
@@ -348,7 +348,7 @@ exports[`t-on t-on modifiers (native listener) t-on with prevent modifier in t-f
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['projects']);;
|
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['projects']);;
|
||||||
for (let i1 = 0; i1 < l_block2; i1++) {
|
for (let i1 = 0; i1 < l_block2; i1++) {
|
||||||
ctx[\`project\`] = v_block2[i1];
|
ctx[\`project\`] = k_block2[i1];
|
||||||
const key1 = ctx['project'];
|
const key1 = ctx['project'];
|
||||||
const v1 = ctx['onEdit'];
|
const v1 = ctx['onEdit'];
|
||||||
const v2 = ctx['project'];
|
const v2 = ctx['project'];
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ exports[`misc complex template 1`] = `
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block4, v_block4, l_block4, c_block4] = prepareList(ctx['batch'].slot_ids.filter(_slot=>_slot.build_id.id&&!_slot.trigger_id.manual&&(ctx['options'].trigger_display[_slot.trigger_id.id])));;
|
const [k_block4, v_block4, l_block4, c_block4] = prepareList(ctx['batch'].slot_ids.filter(_slot=>_slot.build_id.id&&!_slot.trigger_id.manual&&(ctx['options'].trigger_display[_slot.trigger_id.id])));;
|
||||||
for (let i1 = 0; i1 < l_block4; i1++) {
|
for (let i1 = 0; i1 < l_block4; i1++) {
|
||||||
ctx[\`slot\`] = v_block4[i1];
|
ctx[\`slot\`] = k_block4[i1];
|
||||||
const key1 = ctx['slot'].id;
|
const key1 = ctx['slot'].id;
|
||||||
c_block4[i1] = withKey(comp1({class: ctx['slot_container'],slot: ctx['slot']}, key + \`__1__\${key1}\`, node, this, null), key1);
|
c_block4[i1] = withKey(comp1({class: ctx['slot_container'],slot: ctx['slot']}, key + \`__1__\${key1}\`, node, this, null), key1);
|
||||||
}
|
}
|
||||||
@@ -42,7 +42,7 @@ exports[`misc complex template 1`] = `
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block6, v_block6, l_block6, c_block6] = prepareList([1,2,3,4]);;
|
const [k_block6, v_block6, l_block6, c_block6] = prepareList([1,2,3,4]);;
|
||||||
for (let i1 = 0; i1 < l_block6; i1++) {
|
for (let i1 = 0; i1 < l_block6; i1++) {
|
||||||
ctx[\`x\`] = v_block6[i1];
|
ctx[\`x\`] = k_block6[i1];
|
||||||
const key1 = ctx['x'];
|
const key1 = ctx['x'];
|
||||||
c_block6[i1] = withKey(block7(), key1);
|
c_block6[i1] = withKey(block7(), key1);
|
||||||
}
|
}
|
||||||
@@ -51,7 +51,7 @@ exports[`misc complex template 1`] = `
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block8, v_block8, l_block8, c_block8] = prepareList(ctx['commit_links']);;
|
const [k_block8, v_block8, l_block8, c_block8] = prepareList(ctx['commit_links']);;
|
||||||
for (let i1 = 0; i1 < l_block8; i1++) {
|
for (let i1 = 0; i1 < l_block8; i1++) {
|
||||||
ctx[\`commit_link\`] = v_block8[i1];
|
ctx[\`commit_link\`] = k_block8[i1];
|
||||||
const key1 = ctx['commit_link'].id;
|
const key1 = ctx['commit_link'].id;
|
||||||
let b10, b11, b12, b13;
|
let b10, b11, b12, b13;
|
||||||
let attr5 = \`/runbot/commit/\${ctx['commit_link'].commit_id}\`;
|
let attr5 = \`/runbot/commit/\${ctx['commit_link'].commit_id}\`;
|
||||||
@@ -99,11 +99,11 @@ exports[`misc global 1`] = `
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block2, v_block2, l_block2, c_block2] = prepareList([4,5,6]);;
|
const [k_block2, v_block2, l_block2, c_block2] = prepareList([4,5,6]);;
|
||||||
for (let i1 = 0; i1 < l_block2; i1++) {
|
for (let i1 = 0; i1 < l_block2; i1++) {
|
||||||
ctx[\`value\`] = v_block2[i1];
|
ctx[\`value\`] = k_block2[i1];
|
||||||
ctx[\`value_first\`] = i1 === 0;
|
ctx[\`value_first\`] = i1 === 0;
|
||||||
ctx[\`value_last\`] = i1 === v_block2.length - 1;
|
ctx[\`value_last\`] = i1 === k_block2.length - 1;
|
||||||
ctx[\`value_index\`] = i1;
|
ctx[\`value_index\`] = i1;
|
||||||
ctx[\`value_value\`] = k_block2[i1];
|
ctx[\`value_value\`] = v_block2[i1];
|
||||||
const key1 = ctx['value'];
|
const key1 = ctx['value'];
|
||||||
let txt1 = ctx['value'];
|
let txt1 = ctx['value'];
|
||||||
const b4 = block4([txt1]);
|
const b4 = block4([txt1]);
|
||||||
@@ -112,16 +112,16 @@ exports[`misc global 1`] = `
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
ctx[isBoundary] = 1;
|
ctx[isBoundary] = 1;
|
||||||
setContextValue(ctx, \\"foo\\", 'aaa');
|
setContextValue(ctx, \\"foo\\", 'aaa');
|
||||||
const b6 = callTemplate_1.call(this, ctx, node, key + \`__1__\${key1}\`);
|
const b7 = callTemplate_1.call(this, ctx, node, key + \`__1__\${key1}\`);
|
||||||
ctx = ctx.__proto__;
|
ctx = ctx.__proto__;
|
||||||
const b7 = callTemplate_2.call(this, ctx, node, key + \`__2__\${key1}\`);
|
const b8 = callTemplate_2.call(this, ctx, node, key + \`__2__\${key1}\`);
|
||||||
setContextValue(ctx, \\"foo\\", 'bbb');
|
setContextValue(ctx, \\"foo\\", 'bbb');
|
||||||
const b8 = callTemplate_3.call(this, ctx, node, key + \`__3__\${key1}\`);
|
const b9 = callTemplate_3.call(this, ctx, node, key + \`__3__\${key1}\`);
|
||||||
const b5 = multi([b6, b7, b8]);
|
const b6 = multi([b7, b8, b9]);
|
||||||
ctx[zero] = b5;
|
ctx[zero] = b6;
|
||||||
const b9 = callTemplate_4.call(this, ctx, node, key + \`__4__\${key1}\`);
|
const b5 = callTemplate_4.call(this, ctx, node, key + \`__4__\${key1}\`);
|
||||||
ctx = ctx.__proto__;
|
ctx = ctx.__proto__;
|
||||||
c_block2[i1] = withKey(multi([b4, b9]), key1);
|
c_block2[i1] = withKey(multi([b4, b5]), key1);
|
||||||
}
|
}
|
||||||
ctx = ctx.__proto__;
|
ctx = ctx.__proto__;
|
||||||
const b2 = list(c_block2);
|
const b2 = list(c_block2);
|
||||||
@@ -223,7 +223,7 @@ exports[`misc other complex template 1`] = `
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['projects']);;
|
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['projects']);;
|
||||||
for (let i1 = 0; i1 < l_block2; i1++) {
|
for (let i1 = 0; i1 < l_block2; i1++) {
|
||||||
ctx[\`project\`] = v_block2[i1];
|
ctx[\`project\`] = k_block2[i1];
|
||||||
const key1 = ctx['project'].id;
|
const key1 = ctx['project'].id;
|
||||||
let hdlr1 = [ctx['selectProject'](ctx['project']), ctx];
|
let hdlr1 = [ctx['selectProject'](ctx['project']), ctx];
|
||||||
let txt2 = ctx['project'].name;
|
let txt2 = ctx['project'].name;
|
||||||
@@ -263,7 +263,7 @@ exports[`misc other complex template 1`] = `
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block15, v_block15, l_block15, c_block15] = prepareList(ctx['categories']);;
|
const [k_block15, v_block15, l_block15, c_block15] = prepareList(ctx['categories']);;
|
||||||
for (let i1 = 0; i1 < l_block15; i1++) {
|
for (let i1 = 0; i1 < l_block15; i1++) {
|
||||||
ctx[\`category\`] = v_block15[i1];
|
ctx[\`category\`] = k_block15[i1];
|
||||||
const key1 = ctx['category'].id;
|
const key1 = ctx['category'].id;
|
||||||
let attr6 = ctx['category'].id;
|
let attr6 = ctx['category'].id;
|
||||||
let prop1 = new Boolean(ctx['category'].id==ctx['options'].active_category_id);
|
let prop1 = new Boolean(ctx['category'].id==ctx['options'].active_category_id);
|
||||||
@@ -284,7 +284,7 @@ exports[`misc other complex template 1`] = `
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block18, v_block18, l_block18, c_block18] = prepareList(ctx['triggers']);;
|
const [k_block18, v_block18, l_block18, c_block18] = prepareList(ctx['triggers']);;
|
||||||
for (let i1 = 0; i1 < l_block18; i1++) {
|
for (let i1 = 0; i1 < l_block18; i1++) {
|
||||||
ctx[\`trigger\`] = v_block18[i1];
|
ctx[\`trigger\`] = k_block18[i1];
|
||||||
const key1 = ctx['trigger'].id;
|
const key1 = ctx['trigger'].id;
|
||||||
let b20;
|
let b20;
|
||||||
if (!ctx['trigger'].manual&&ctx['trigger'].project_id===ctx['project'].id&&ctx['trigger'].category_id===ctx['options'].active_category_id) {
|
if (!ctx['trigger'].manual&&ctx['trigger'].project_id===ctx['project'].id&&ctx['trigger'].category_id===ctx['options'].active_category_id) {
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ exports[`memory t-foreach does not leak stuff in global scope 1`] = `
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block2, v_block2, l_block2, c_block2] = prepareList([3,2,1]);;
|
const [k_block2, v_block2, l_block2, c_block2] = prepareList([3,2,1]);;
|
||||||
for (let i1 = 0; i1 < l_block2; i1++) {
|
for (let i1 = 0; i1 < l_block2; i1++) {
|
||||||
ctx[\`item\`] = v_block2[i1];
|
ctx[\`item\`] = k_block2[i1];
|
||||||
ctx[\`item_index\`] = i1;
|
ctx[\`item_index\`] = i1;
|
||||||
const key1 = ctx['item_index'];
|
const key1 = ctx['item_index'];
|
||||||
c_block2[i1] = withKey(text(ctx['item']), key1);
|
c_block2[i1] = withKey(text(ctx['item']), key1);
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ exports[`properly support svg add proper namespace to g tags 1`] = `
|
|||||||
) {
|
) {
|
||||||
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
|
||||||
let block1 = createBlock(\`<g block-ns=\\"http://www.w3.org/2000/svg\\"><circle cx=\\"50\\" cy=\\"50\\" r=\\"4\\" stroke=\\"green\\" stroke-width=\\"1\\" fill=\\"yellow\\"/> </g>\`);
|
let block1 = createBlock(\`<g xmlns=\\"http://www.w3.org/2000/svg\\"><circle cx=\\"50\\" cy=\\"50\\" r=\\"4\\" stroke=\\"green\\" stroke-width=\\"1\\" fill=\\"yellow\\"/> </g>\`);
|
||||||
|
|
||||||
return function template(ctx, node, key = \\"\\") {
|
return function template(ctx, node, key = \\"\\") {
|
||||||
return block1();
|
return block1();
|
||||||
@@ -18,7 +18,7 @@ exports[`properly support svg add proper namespace to svg 1`] = `
|
|||||||
) {
|
) {
|
||||||
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
|
||||||
let block1 = createBlock(\`<svg block-ns=\\"http://www.w3.org/2000/svg\\" width=\\"100px\\" height=\\"90px\\"><circle cx=\\"50\\" cy=\\"50\\" r=\\"4\\" stroke=\\"green\\" stroke-width=\\"1\\" fill=\\"yellow\\"/> </svg>\`);
|
let block1 = createBlock(\`<svg xmlns=\\"http://www.w3.org/2000/svg\\" width=\\"100px\\" height=\\"90px\\"><circle cx=\\"50\\" cy=\\"50\\" r=\\"4\\" stroke=\\"green\\" stroke-width=\\"1\\" fill=\\"yellow\\"/> </svg>\`);
|
||||||
|
|
||||||
return function template(ctx, node, key = \\"\\") {
|
return function template(ctx, node, key = \\"\\") {
|
||||||
return block1();
|
return block1();
|
||||||
@@ -31,7 +31,7 @@ exports[`properly support svg namespace to g tags not added if already in svg na
|
|||||||
) {
|
) {
|
||||||
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
|
||||||
let block1 = createBlock(\`<svg block-ns=\\"http://www.w3.org/2000/svg\\"><g/></svg>\`);
|
let block1 = createBlock(\`<svg xmlns=\\"http://www.w3.org/2000/svg\\"><g/></svg>\`);
|
||||||
|
|
||||||
return function template(ctx, node, key = \\"\\") {
|
return function template(ctx, node, key = \\"\\") {
|
||||||
return block1();
|
return block1();
|
||||||
@@ -44,7 +44,7 @@ exports[`properly support svg namespace to svg tags added even if already in svg
|
|||||||
) {
|
) {
|
||||||
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
|
||||||
let block1 = createBlock(\`<svg block-ns=\\"http://www.w3.org/2000/svg\\"><svg/></svg>\`);
|
let block1 = createBlock(\`<svg xmlns=\\"http://www.w3.org/2000/svg\\"><svg/></svg>\`);
|
||||||
|
|
||||||
return function template(ctx, node, key = \\"\\") {
|
return function template(ctx, node, key = \\"\\") {
|
||||||
return block1();
|
return block1();
|
||||||
@@ -58,8 +58,8 @@ exports[`properly support svg svg creates new block if it is within html -- 2 1`
|
|||||||
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
|
||||||
let block1 = createBlock(\`<div><block-child-0/></div>\`);
|
let block1 = createBlock(\`<div><block-child-0/></div>\`);
|
||||||
let block2 = createBlock(\`<svg block-ns=\\"http://www.w3.org/2000/svg\\"><polygon fill=\\"#000000\\" points=\\"0 0 4 4 8 0\\" transform=\\"translate(5 7)\\"/><block-child-0/></svg>\`);
|
let block2 = createBlock(\`<svg xmlns=\\"http://www.w3.org/2000/svg\\"><polygon fill=\\"#000000\\" points=\\"0 0 4 4 8 0\\" transform=\\"translate(5 7)\\"/><block-child-0 xmlns=\\"\\"/></svg>\`);
|
||||||
let block3 = createBlock(\`<path block-ns=\\"http://www.w3.org/2000/svg\\"/>\`);
|
let block3 = createBlock(\`<path xmlns=\\"http://www.w3.org/2000/svg\\"/>\`);
|
||||||
|
|
||||||
return function template(ctx, node, key = \\"\\") {
|
return function template(ctx, node, key = \\"\\") {
|
||||||
let b3;
|
let b3;
|
||||||
@@ -78,7 +78,7 @@ exports[`properly support svg svg creates new block if it is within html 1`] = `
|
|||||||
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
|
||||||
let block1 = createBlock(\`<div><block-child-0/></div>\`);
|
let block1 = createBlock(\`<div><block-child-0/></div>\`);
|
||||||
let block2 = createBlock(\`<svg block-ns=\\"http://www.w3.org/2000/svg\\"><polygon fill=\\"#000000\\" points=\\"0 0 4 4 8 0\\" transform=\\"translate(5 7)\\"/></svg>\`);
|
let block2 = createBlock(\`<svg xmlns=\\"http://www.w3.org/2000/svg\\"><polygon fill=\\"#000000\\" points=\\"0 0 4 4 8 0\\" transform=\\"translate(5 7)\\"/></svg>\`);
|
||||||
|
|
||||||
return function template(ctx, node, key = \\"\\") {
|
return function template(ctx, node, key = \\"\\") {
|
||||||
const b2 = block2();
|
const b2 = block2();
|
||||||
@@ -93,7 +93,7 @@ exports[`properly support svg svg namespace added to sub templates if root tag i
|
|||||||
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
const callTemplate_1 = app.getTemplate(\`path\`);
|
const callTemplate_1 = app.getTemplate(\`path\`);
|
||||||
|
|
||||||
let block1 = createBlock(\`<svg block-ns=\\"http://www.w3.org/2000/svg\\"><block-child-0/></svg>\`);
|
let block1 = createBlock(\`<svg xmlns=\\"http://www.w3.org/2000/svg\\"><block-child-0 xmlns=\\"\\"/></svg>\`);
|
||||||
|
|
||||||
return function template(ctx, node, key = \\"\\") {
|
return function template(ctx, node, key = \\"\\") {
|
||||||
const b2 = callTemplate_1.call(this, ctx, node, key + \`__1\`);
|
const b2 = callTemplate_1.call(this, ctx, node, key + \`__1\`);
|
||||||
@@ -107,7 +107,7 @@ exports[`properly support svg svg namespace added to sub templates if root tag i
|
|||||||
) {
|
) {
|
||||||
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
|
||||||
let block1 = createBlock(\`<path block-ns=\\"http://www.w3.org/2000/svg\\"/>\`);
|
let block1 = createBlock(\`<path xmlns=\\"http://www.w3.org/2000/svg\\"/>\`);
|
||||||
|
|
||||||
return function template(ctx, node, key = \\"\\") {
|
return function template(ctx, node, key = \\"\\") {
|
||||||
return block1();
|
return block1();
|
||||||
@@ -120,8 +120,8 @@ exports[`properly support svg svg namespace added to sub-blocks 1`] = `
|
|||||||
) {
|
) {
|
||||||
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
|
||||||
let block1 = createBlock(\`<svg block-ns=\\"http://www.w3.org/2000/svg\\"><block-child-0/></svg>\`);
|
let block1 = createBlock(\`<svg xmlns=\\"http://www.w3.org/2000/svg\\"><block-child-0 xmlns=\\"\\"/></svg>\`);
|
||||||
let block2 = createBlock(\`<path block-ns=\\"http://www.w3.org/2000/svg\\"/>\`);
|
let block2 = createBlock(\`<path xmlns=\\"http://www.w3.org/2000/svg\\"/>\`);
|
||||||
|
|
||||||
return function template(ctx, node, key = \\"\\") {
|
return function template(ctx, node, key = \\"\\") {
|
||||||
let b2;
|
let b2;
|
||||||
|
|||||||
@@ -61,19 +61,19 @@ exports[`t-call (template calling) call with several sub nodes on same line 1`]
|
|||||||
const callTemplate_1 = app.getTemplate(\`sub\`);
|
const callTemplate_1 = app.getTemplate(\`sub\`);
|
||||||
|
|
||||||
let block1 = createBlock(\`<div><block-child-0/></div>\`);
|
let block1 = createBlock(\`<div><block-child-0/></div>\`);
|
||||||
let block3 = createBlock(\`<span>hey</span>\`);
|
let block4 = createBlock(\`<span>hey</span>\`);
|
||||||
let block5 = createBlock(\`<span>yay</span>\`);
|
let block6 = createBlock(\`<span>yay</span>\`);
|
||||||
|
|
||||||
return function template(ctx, node, key = \\"\\") {
|
return function template(ctx, node, key = \\"\\") {
|
||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
ctx[isBoundary] = 1;
|
ctx[isBoundary] = 1;
|
||||||
const b3 = block3();
|
const b4 = block4();
|
||||||
const b4 = text(\` \`);
|
const b5 = text(\` \`);
|
||||||
const b5 = block5();
|
const b6 = block6();
|
||||||
const b2 = multi([b3, b4, b5]);
|
const b3 = multi([b4, b5, b6]);
|
||||||
ctx[zero] = b2;
|
ctx[zero] = b3;
|
||||||
const b6 = callTemplate_1.call(this, ctx, node, key + \`__1\`);
|
const b2 = callTemplate_1.call(this, ctx, node, key + \`__1\`);
|
||||||
return block1([], [b6]);
|
return block1([], [b2]);
|
||||||
}
|
}
|
||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
@@ -101,19 +101,19 @@ exports[`t-call (template calling) cascading t-call t-out='0' 1`] = `
|
|||||||
const callTemplate_1 = app.getTemplate(\`subTemplate\`);
|
const callTemplate_1 = app.getTemplate(\`subTemplate\`);
|
||||||
|
|
||||||
let block1 = createBlock(\`<div><block-child-0/></div>\`);
|
let block1 = createBlock(\`<div><block-child-0/></div>\`);
|
||||||
let block3 = createBlock(\`<span>hey</span>\`);
|
let block4 = createBlock(\`<span>hey</span>\`);
|
||||||
let block5 = createBlock(\`<span>yay</span>\`);
|
let block6 = createBlock(\`<span>yay</span>\`);
|
||||||
|
|
||||||
return function template(ctx, node, key = \\"\\") {
|
return function template(ctx, node, key = \\"\\") {
|
||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
ctx[isBoundary] = 1;
|
ctx[isBoundary] = 1;
|
||||||
const b3 = block3();
|
const b4 = block4();
|
||||||
const b4 = text(\` \`);
|
const b5 = text(\` \`);
|
||||||
const b5 = block5();
|
const b6 = block6();
|
||||||
const b2 = multi([b3, b4, b5]);
|
const b3 = multi([b4, b5, b6]);
|
||||||
ctx[zero] = b2;
|
ctx[zero] = b3;
|
||||||
const b6 = callTemplate_1.call(this, ctx, node, key + \`__1\`);
|
const b2 = callTemplate_1.call(this, ctx, node, key + \`__1\`);
|
||||||
return block1([], [b6]);
|
return block1([], [b2]);
|
||||||
}
|
}
|
||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
@@ -126,17 +126,17 @@ exports[`t-call (template calling) cascading t-call t-out='0' 2`] = `
|
|||||||
const callTemplate_1 = app.getTemplate(\`subSubTemplate\`);
|
const callTemplate_1 = app.getTemplate(\`subSubTemplate\`);
|
||||||
|
|
||||||
let block1 = createBlock(\`<div><block-child-0/></div>\`);
|
let block1 = createBlock(\`<div><block-child-0/></div>\`);
|
||||||
let block3 = createBlock(\`<span>cascade 0</span>\`);
|
let block4 = createBlock(\`<span>cascade 0</span>\`);
|
||||||
|
|
||||||
return function template(ctx, node, key = \\"\\") {
|
return function template(ctx, node, key = \\"\\") {
|
||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
ctx[isBoundary] = 1;
|
ctx[isBoundary] = 1;
|
||||||
const b3 = block3();
|
const b4 = block4();
|
||||||
const b4 = ctx[zero];
|
const b5 = ctx[zero];
|
||||||
const b2 = multi([b3, b4]);
|
const b3 = multi([b4, b5]);
|
||||||
ctx[zero] = b2;
|
ctx[zero] = b3;
|
||||||
const b5 = callTemplate_1.call(this, ctx, node, key + \`__1\`);
|
const b2 = callTemplate_1.call(this, ctx, node, key + \`__1\`);
|
||||||
return block1([], [b5]);
|
return block1([], [b2]);
|
||||||
}
|
}
|
||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
@@ -149,17 +149,17 @@ exports[`t-call (template calling) cascading t-call t-out='0' 3`] = `
|
|||||||
const callTemplate_1 = app.getTemplate(\`finalTemplate\`);
|
const callTemplate_1 = app.getTemplate(\`finalTemplate\`);
|
||||||
|
|
||||||
let block1 = createBlock(\`<div><block-child-0/></div>\`);
|
let block1 = createBlock(\`<div><block-child-0/></div>\`);
|
||||||
let block3 = createBlock(\`<span>cascade 1</span>\`);
|
let block4 = createBlock(\`<span>cascade 1</span>\`);
|
||||||
|
|
||||||
return function template(ctx, node, key = \\"\\") {
|
return function template(ctx, node, key = \\"\\") {
|
||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
ctx[isBoundary] = 1;
|
ctx[isBoundary] = 1;
|
||||||
const b3 = block3();
|
const b4 = block4();
|
||||||
const b4 = ctx[zero];
|
const b5 = ctx[zero];
|
||||||
const b2 = multi([b3, b4]);
|
const b3 = multi([b4, b5]);
|
||||||
ctx[zero] = b2;
|
ctx[zero] = b3;
|
||||||
const b5 = callTemplate_1.call(this, ctx, node, key + \`__1\`);
|
const b2 = callTemplate_1.call(this, ctx, node, key + \`__1\`);
|
||||||
return block1([], [b5]);
|
return block1([], [b2]);
|
||||||
}
|
}
|
||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
@@ -186,17 +186,17 @@ exports[`t-call (template calling) cascading t-call t-out='0', without external
|
|||||||
let { isBoundary, zero } = helpers;
|
let { isBoundary, zero } = helpers;
|
||||||
const callTemplate_1 = app.getTemplate(\`subTemplate\`);
|
const callTemplate_1 = app.getTemplate(\`subTemplate\`);
|
||||||
|
|
||||||
let block2 = createBlock(\`<span>hey</span>\`);
|
let block3 = createBlock(\`<span>hey</span>\`);
|
||||||
let block4 = createBlock(\`<span>yay</span>\`);
|
let block5 = createBlock(\`<span>yay</span>\`);
|
||||||
|
|
||||||
return function template(ctx, node, key = \\"\\") {
|
return function template(ctx, node, key = \\"\\") {
|
||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
ctx[isBoundary] = 1;
|
ctx[isBoundary] = 1;
|
||||||
const b2 = block2();
|
const b3 = block3();
|
||||||
const b3 = text(\` \`);
|
const b4 = text(\` \`);
|
||||||
const b4 = block4();
|
const b5 = block5();
|
||||||
const b1 = multi([b2, b3, b4]);
|
const b2 = multi([b3, b4, b5]);
|
||||||
ctx[zero] = b1;
|
ctx[zero] = b2;
|
||||||
return callTemplate_1.call(this, ctx, node, key + \`__1\`);
|
return callTemplate_1.call(this, ctx, node, key + \`__1\`);
|
||||||
}
|
}
|
||||||
}"
|
}"
|
||||||
@@ -209,15 +209,15 @@ exports[`t-call (template calling) cascading t-call t-out='0', without external
|
|||||||
let { isBoundary, zero } = helpers;
|
let { isBoundary, zero } = helpers;
|
||||||
const callTemplate_1 = app.getTemplate(\`subSubTemplate\`);
|
const callTemplate_1 = app.getTemplate(\`subSubTemplate\`);
|
||||||
|
|
||||||
let block2 = createBlock(\`<span>cascade 0</span>\`);
|
let block3 = createBlock(\`<span>cascade 0</span>\`);
|
||||||
|
|
||||||
return function template(ctx, node, key = \\"\\") {
|
return function template(ctx, node, key = \\"\\") {
|
||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
ctx[isBoundary] = 1;
|
ctx[isBoundary] = 1;
|
||||||
const b2 = block2();
|
const b3 = block3();
|
||||||
const b3 = ctx[zero];
|
const b4 = ctx[zero];
|
||||||
const b1 = multi([b2, b3]);
|
const b2 = multi([b3, b4]);
|
||||||
ctx[zero] = b1;
|
ctx[zero] = b2;
|
||||||
return callTemplate_1.call(this, ctx, node, key + \`__1\`);
|
return callTemplate_1.call(this, ctx, node, key + \`__1\`);
|
||||||
}
|
}
|
||||||
}"
|
}"
|
||||||
@@ -230,15 +230,15 @@ exports[`t-call (template calling) cascading t-call t-out='0', without external
|
|||||||
let { isBoundary, zero } = helpers;
|
let { isBoundary, zero } = helpers;
|
||||||
const callTemplate_1 = app.getTemplate(\`finalTemplate\`);
|
const callTemplate_1 = app.getTemplate(\`finalTemplate\`);
|
||||||
|
|
||||||
let block2 = createBlock(\`<span>cascade 1</span>\`);
|
let block3 = createBlock(\`<span>cascade 1</span>\`);
|
||||||
|
|
||||||
return function template(ctx, node, key = \\"\\") {
|
return function template(ctx, node, key = \\"\\") {
|
||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
ctx[isBoundary] = 1;
|
ctx[isBoundary] = 1;
|
||||||
const b2 = block2();
|
const b3 = block3();
|
||||||
const b3 = ctx[zero];
|
const b4 = ctx[zero];
|
||||||
const b1 = multi([b2, b3]);
|
const b2 = multi([b3, b4]);
|
||||||
ctx[zero] = b1;
|
ctx[zero] = b2;
|
||||||
return callTemplate_1.call(this, ctx, node, key + \`__1\`);
|
return callTemplate_1.call(this, ctx, node, key + \`__1\`);
|
||||||
}
|
}
|
||||||
}"
|
}"
|
||||||
@@ -342,15 +342,15 @@ exports[`t-call (template calling) nested t-calls with magic variable 0 1`] = `
|
|||||||
const callTemplate_1 = app.getTemplate(\`grandchild\`);
|
const callTemplate_1 = app.getTemplate(\`grandchild\`);
|
||||||
const callTemplate_2 = app.getTemplate(\`child\`);
|
const callTemplate_2 = app.getTemplate(\`child\`);
|
||||||
|
|
||||||
let block1 = createBlock(\`<p>Some content...</p>\`);
|
let block3 = createBlock(\`<p>Some content...</p>\`);
|
||||||
|
|
||||||
return function template(ctx, node, key = \\"\\") {
|
return function template(ctx, node, key = \\"\\") {
|
||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
ctx[isBoundary] = 1;
|
ctx[isBoundary] = 1;
|
||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
ctx[isBoundary] = 1;
|
ctx[isBoundary] = 1;
|
||||||
const b1 = block1();
|
const b3 = block3();
|
||||||
ctx[zero] = b1;
|
ctx[zero] = b3;
|
||||||
const b2 = callTemplate_1.call(this, ctx, node, key + \`__1\`);
|
const b2 = callTemplate_1.call(this, ctx, node, key + \`__1\`);
|
||||||
ctx = ctx.__proto__;
|
ctx = ctx.__proto__;
|
||||||
ctx[zero] = b2;
|
ctx[zero] = b2;
|
||||||
@@ -440,11 +440,11 @@ exports[`t-call (template calling) recursive template, part 2 2`] = `
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['node'].children||[]);;
|
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['node'].children||[]);;
|
||||||
for (let i1 = 0; i1 < l_block2; i1++) {
|
for (let i1 = 0; i1 < l_block2; i1++) {
|
||||||
ctx[\`subtree\`] = v_block2[i1];
|
ctx[\`subtree\`] = k_block2[i1];
|
||||||
ctx[\`subtree_first\`] = i1 === 0;
|
ctx[\`subtree_first\`] = i1 === 0;
|
||||||
ctx[\`subtree_last\`] = i1 === v_block2.length - 1;
|
ctx[\`subtree_last\`] = i1 === k_block2.length - 1;
|
||||||
ctx[\`subtree_index\`] = i1;
|
ctx[\`subtree_index\`] = i1;
|
||||||
ctx[\`subtree_value\`] = k_block2[i1];
|
ctx[\`subtree_value\`] = v_block2[i1];
|
||||||
const key1 = ctx['subtree_index'];
|
const key1 = ctx['subtree_index'];
|
||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
ctx[isBoundary] = 1;
|
ctx[isBoundary] = 1;
|
||||||
@@ -495,11 +495,11 @@ exports[`t-call (template calling) recursive template, part 3 2`] = `
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['node'].children||[]);;
|
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['node'].children||[]);;
|
||||||
for (let i1 = 0; i1 < l_block2; i1++) {
|
for (let i1 = 0; i1 < l_block2; i1++) {
|
||||||
ctx[\`subtree\`] = v_block2[i1];
|
ctx[\`subtree\`] = k_block2[i1];
|
||||||
ctx[\`subtree_first\`] = i1 === 0;
|
ctx[\`subtree_first\`] = i1 === 0;
|
||||||
ctx[\`subtree_last\`] = i1 === v_block2.length - 1;
|
ctx[\`subtree_last\`] = i1 === k_block2.length - 1;
|
||||||
ctx[\`subtree_index\`] = i1;
|
ctx[\`subtree_index\`] = i1;
|
||||||
ctx[\`subtree_value\`] = k_block2[i1];
|
ctx[\`subtree_value\`] = v_block2[i1];
|
||||||
const key1 = ctx['subtree_index'];
|
const key1 = ctx['subtree_index'];
|
||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
ctx[isBoundary] = 1;
|
ctx[isBoundary] = 1;
|
||||||
@@ -553,11 +553,11 @@ exports[`t-call (template calling) recursive template, part 4: with t-set recurs
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['node'].children||[]);;
|
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['node'].children||[]);;
|
||||||
for (let i1 = 0; i1 < l_block2; i1++) {
|
for (let i1 = 0; i1 < l_block2; i1++) {
|
||||||
ctx[\`subtree\`] = v_block2[i1];
|
ctx[\`subtree\`] = k_block2[i1];
|
||||||
ctx[\`subtree_first\`] = i1 === 0;
|
ctx[\`subtree_first\`] = i1 === 0;
|
||||||
ctx[\`subtree_last\`] = i1 === v_block2.length - 1;
|
ctx[\`subtree_last\`] = i1 === k_block2.length - 1;
|
||||||
ctx[\`subtree_index\`] = i1;
|
ctx[\`subtree_index\`] = i1;
|
||||||
ctx[\`subtree_value\`] = k_block2[i1];
|
ctx[\`subtree_value\`] = v_block2[i1];
|
||||||
const key1 = ctx['subtree_index'];
|
const key1 = ctx['subtree_index'];
|
||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
ctx[isBoundary] = 1;
|
ctx[isBoundary] = 1;
|
||||||
@@ -571,6 +571,134 @@ exports[`t-call (template calling) recursive template, part 4: with t-set recurs
|
|||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`t-call (template calling) root t-call with body: t-foreach 1`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
let { isBoundary, prepareList, withKey, zero } = helpers;
|
||||||
|
const callTemplate_1 = app.getTemplate(\`subTemplate\`);
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
ctx = Object.create(ctx);
|
||||||
|
ctx[isBoundary] = 1;
|
||||||
|
ctx = Object.create(ctx);
|
||||||
|
const [k_block2, v_block2, l_block2, c_block2] = prepareList([1]);;
|
||||||
|
for (let i1 = 0; i1 < l_block2; i1++) {
|
||||||
|
ctx[\`i\`] = k_block2[i1];
|
||||||
|
const key1 = ctx['i'];
|
||||||
|
c_block2[i1] = withKey(text(\`1\`), key1);
|
||||||
|
}
|
||||||
|
ctx = ctx.__proto__;
|
||||||
|
const b2 = list(c_block2);
|
||||||
|
ctx[zero] = b2;
|
||||||
|
return callTemplate_1.call(this, ctx, node, key + \`__1\`);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`t-call (template calling) root t-call with body: t-foreach 2`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
return text(\`sub\`);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`t-call (template calling) root t-call with body: t-if false 1`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
let { isBoundary, zero } = helpers;
|
||||||
|
const callTemplate_1 = app.getTemplate(\`subTemplate\`);
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
ctx = Object.create(ctx);
|
||||||
|
ctx[isBoundary] = 1;
|
||||||
|
let b3;
|
||||||
|
if (false) {
|
||||||
|
b3 = text(\`zero\`);
|
||||||
|
}
|
||||||
|
const b2 = multi([b3]);
|
||||||
|
ctx[zero] = b2;
|
||||||
|
return callTemplate_1.call(this, ctx, node, key + \`__1\`);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`t-call (template calling) root t-call with body: t-if false 2`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
return text(\`sub\`);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`t-call (template calling) root t-call with body: t-if true 1`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
let { isBoundary, zero } = helpers;
|
||||||
|
const callTemplate_1 = app.getTemplate(\`subTemplate\`);
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
ctx = Object.create(ctx);
|
||||||
|
ctx[isBoundary] = 1;
|
||||||
|
let b3;
|
||||||
|
if (true) {
|
||||||
|
b3 = text(\`zero\`);
|
||||||
|
}
|
||||||
|
const b2 = multi([b3]);
|
||||||
|
ctx[zero] = b2;
|
||||||
|
return callTemplate_1.call(this, ctx, node, key + \`__1\`);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`t-call (template calling) root t-call with body: t-if true 2`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
return text(\`sub\`);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`t-call (template calling) root t-call with body: t-out with default 1`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
let { isBoundary, safeOutput, zero } = helpers;
|
||||||
|
const callTemplate_1 = app.getTemplate(\`subTemplate\`);
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
ctx = Object.create(ctx);
|
||||||
|
ctx[isBoundary] = 1;
|
||||||
|
const b2 = safeOutput(ctx['nothing']);
|
||||||
|
ctx[zero] = b2;
|
||||||
|
return callTemplate_1.call(this, ctx, node, key + \`__1\`);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`t-call (template calling) root t-call with body: t-out with default 2`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
return text(\`sub\`);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`t-call (template calling) scoped parameters 1`] = `
|
exports[`t-call (template calling) scoped parameters 1`] = `
|
||||||
"function anonymous(app, bdom, helpers
|
"function anonymous(app, bdom, helpers
|
||||||
) {
|
) {
|
||||||
@@ -705,13 +833,13 @@ exports[`t-call (template calling) t-call with body content as root of a templat
|
|||||||
let { isBoundary, zero } = helpers;
|
let { isBoundary, zero } = helpers;
|
||||||
const callTemplate_1 = app.getTemplate(\`antony\`);
|
const callTemplate_1 = app.getTemplate(\`antony\`);
|
||||||
|
|
||||||
let block1 = createBlock(\`<p>antony</p>\`);
|
let block2 = createBlock(\`<p>antony</p>\`);
|
||||||
|
|
||||||
return function template(ctx, node, key = \\"\\") {
|
return function template(ctx, node, key = \\"\\") {
|
||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
ctx[isBoundary] = 1;
|
ctx[isBoundary] = 1;
|
||||||
const b1 = block1();
|
const b2 = block2();
|
||||||
ctx[zero] = b1;
|
ctx[zero] = b2;
|
||||||
return callTemplate_1.call(this, ctx, node, key + \`__1\`);
|
return callTemplate_1.call(this, ctx, node, key + \`__1\`);
|
||||||
}
|
}
|
||||||
}"
|
}"
|
||||||
@@ -813,11 +941,11 @@ exports[`t-call (template calling) t-call with t-set inside and outside 1`] = `
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['list']);;
|
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['list']);;
|
||||||
for (let i1 = 0; i1 < l_block2; i1++) {
|
for (let i1 = 0; i1 < l_block2; i1++) {
|
||||||
ctx[\`v\`] = v_block2[i1];
|
ctx[\`v\`] = k_block2[i1];
|
||||||
ctx[\`v_first\`] = i1 === 0;
|
ctx[\`v_first\`] = i1 === 0;
|
||||||
ctx[\`v_last\`] = i1 === v_block2.length - 1;
|
ctx[\`v_last\`] = i1 === k_block2.length - 1;
|
||||||
ctx[\`v_index\`] = i1;
|
ctx[\`v_index\`] = i1;
|
||||||
ctx[\`v_value\`] = k_block2[i1];
|
ctx[\`v_value\`] = v_block2[i1];
|
||||||
const key1 = ctx['v_index'];
|
const key1 = ctx['v_index'];
|
||||||
setContextValue(ctx, \\"val\\", ctx['v'].val);
|
setContextValue(ctx, \\"val\\", ctx['v'].val);
|
||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
@@ -880,11 +1008,11 @@ exports[`t-call (template calling) t-call with t-set inside and outside. 2 2`] =
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['list']);;
|
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['list']);;
|
||||||
for (let i1 = 0; i1 < l_block2; i1++) {
|
for (let i1 = 0; i1 < l_block2; i1++) {
|
||||||
ctx[\`v\`] = v_block2[i1];
|
ctx[\`v\`] = k_block2[i1];
|
||||||
ctx[\`v_first\`] = i1 === 0;
|
ctx[\`v_first\`] = i1 === 0;
|
||||||
ctx[\`v_last\`] = i1 === v_block2.length - 1;
|
ctx[\`v_last\`] = i1 === k_block2.length - 1;
|
||||||
ctx[\`v_index\`] = i1;
|
ctx[\`v_index\`] = i1;
|
||||||
ctx[\`v_value\`] = k_block2[i1];
|
ctx[\`v_value\`] = v_block2[i1];
|
||||||
const key1 = ctx['v_index'];
|
const key1 = ctx['v_index'];
|
||||||
setContextValue(ctx, \\"val\\", ctx['v'].val);
|
setContextValue(ctx, \\"val\\", ctx['v'].val);
|
||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
@@ -1075,8 +1203,8 @@ exports[`t-call (template calling) with unused body 1`] = `
|
|||||||
return function template(ctx, node, key = \\"\\") {
|
return function template(ctx, node, key = \\"\\") {
|
||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
ctx[isBoundary] = 1;
|
ctx[isBoundary] = 1;
|
||||||
const b1 = text(\`WHEEE\`);
|
const b2 = text(\`WHEEE\`);
|
||||||
ctx[zero] = b1;
|
ctx[zero] = b2;
|
||||||
return callTemplate_1.call(this, ctx, node, key + \`__1\`);
|
return callTemplate_1.call(this, ctx, node, key + \`__1\`);
|
||||||
}
|
}
|
||||||
}"
|
}"
|
||||||
@@ -1136,8 +1264,8 @@ exports[`t-call (template calling) with used body 1`] = `
|
|||||||
return function template(ctx, node, key = \\"\\") {
|
return function template(ctx, node, key = \\"\\") {
|
||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
ctx[isBoundary] = 1;
|
ctx[isBoundary] = 1;
|
||||||
const b1 = text(\`ok\`);
|
const b2 = text(\`ok\`);
|
||||||
ctx[zero] = b1;
|
ctx[zero] = b2;
|
||||||
return callTemplate_1.call(this, ctx, node, key + \`__1\`);
|
return callTemplate_1.call(this, ctx, node, key + \`__1\`);
|
||||||
}
|
}
|
||||||
}"
|
}"
|
||||||
|
|||||||
@@ -180,15 +180,15 @@ exports[`t-esc t-esc=0 is escaped 1`] = `
|
|||||||
const callTemplate_1 = app.getTemplate(\`sub\`);
|
const callTemplate_1 = app.getTemplate(\`sub\`);
|
||||||
|
|
||||||
let block1 = createBlock(\`<div><block-child-0/></div>\`);
|
let block1 = createBlock(\`<div><block-child-0/></div>\`);
|
||||||
let block2 = createBlock(\`<p>escaped</p>\`);
|
let block3 = createBlock(\`<p>escaped</p>\`);
|
||||||
|
|
||||||
return function template(ctx, node, key = \\"\\") {
|
return function template(ctx, node, key = \\"\\") {
|
||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
ctx[isBoundary] = 1;
|
ctx[isBoundary] = 1;
|
||||||
const b2 = block2();
|
const b3 = block3();
|
||||||
ctx[zero] = b2;
|
ctx[zero] = b3;
|
||||||
const b3 = callTemplate_1.call(this, ctx, node, key + \`__1\`);
|
const b2 = callTemplate_1.call(this, ctx, node, key + \`__1\`);
|
||||||
return block1([], [b3]);
|
return block1([], [b2]);
|
||||||
}
|
}
|
||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ exports[`t-foreach does not pollute the rendering context 1`] = `
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block2, v_block2, l_block2, c_block2] = prepareList([1]);;
|
const [k_block2, v_block2, l_block2, c_block2] = prepareList([1]);;
|
||||||
for (let i1 = 0; i1 < l_block2; i1++) {
|
for (let i1 = 0; i1 < l_block2; i1++) {
|
||||||
ctx[\`item\`] = v_block2[i1];
|
ctx[\`item\`] = k_block2[i1];
|
||||||
const key1 = ctx['item'];
|
const key1 = ctx['item'];
|
||||||
c_block2[i1] = withKey(text(ctx['item']), key1);
|
c_block2[i1] = withKey(text(ctx['item']), key1);
|
||||||
}
|
}
|
||||||
@@ -35,7 +35,7 @@ exports[`t-foreach iterate on items (on a element node) 1`] = `
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block2, v_block2, l_block2, c_block2] = prepareList([1,2]);;
|
const [k_block2, v_block2, l_block2, c_block2] = prepareList([1,2]);;
|
||||||
for (let i1 = 0; i1 < l_block2; i1++) {
|
for (let i1 = 0; i1 < l_block2; i1++) {
|
||||||
ctx[\`item\`] = v_block2[i1];
|
ctx[\`item\`] = k_block2[i1];
|
||||||
const key1 = ctx['item'];
|
const key1 = ctx['item'];
|
||||||
let txt1 = ctx['item'];
|
let txt1 = ctx['item'];
|
||||||
c_block2[i1] = withKey(block3([txt1]), key1);
|
c_block2[i1] = withKey(block3([txt1]), key1);
|
||||||
@@ -58,9 +58,9 @@ exports[`t-foreach iterate on items 1`] = `
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block2, v_block2, l_block2, c_block2] = prepareList([3,2,1]);;
|
const [k_block2, v_block2, l_block2, c_block2] = prepareList([3,2,1]);;
|
||||||
for (let i1 = 0; i1 < l_block2; i1++) {
|
for (let i1 = 0; i1 < l_block2; i1++) {
|
||||||
ctx[\`item\`] = v_block2[i1];
|
ctx[\`item\`] = k_block2[i1];
|
||||||
ctx[\`item_index\`] = i1;
|
ctx[\`item_index\`] = i1;
|
||||||
ctx[\`item_value\`] = k_block2[i1];
|
ctx[\`item_value\`] = v_block2[i1];
|
||||||
const key1 = ctx['item'];
|
const key1 = ctx['item'];
|
||||||
const b4 = text(\` [\`);
|
const b4 = text(\` [\`);
|
||||||
const b5 = text(ctx['item_index']);
|
const b5 = text(ctx['item_index']);
|
||||||
@@ -77,6 +77,62 @@ exports[`t-foreach iterate on items 1`] = `
|
|||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`t-foreach iterate, Map param 1`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
let { prepareList, withKey } = helpers;
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
ctx = Object.create(ctx);
|
||||||
|
const [k_block1, v_block1, l_block1, c_block1] = prepareList(ctx['value']);;
|
||||||
|
for (let i1 = 0; i1 < l_block1; i1++) {
|
||||||
|
ctx[\`item\`] = k_block1[i1];
|
||||||
|
ctx[\`item_index\`] = i1;
|
||||||
|
ctx[\`item_value\`] = v_block1[i1];
|
||||||
|
const key1 = ctx['item_index'];
|
||||||
|
const b3 = text(\` [\`);
|
||||||
|
const b4 = text(ctx['item_index']);
|
||||||
|
const b5 = text(\`: \`);
|
||||||
|
const b6 = text(ctx['item']);
|
||||||
|
const b7 = text(\` \`);
|
||||||
|
const b8 = text(ctx['item_value']);
|
||||||
|
const b9 = text(\`] \`);
|
||||||
|
c_block1[i1] = withKey(multi([b3, b4, b5, b6, b7, b8, b9]), key1);
|
||||||
|
}
|
||||||
|
return list(c_block1);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`t-foreach iterate, Set param 1`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
let { prepareList, withKey } = helpers;
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
ctx = Object.create(ctx);
|
||||||
|
const [k_block1, v_block1, l_block1, c_block1] = prepareList(ctx['value']);;
|
||||||
|
for (let i1 = 0; i1 < l_block1; i1++) {
|
||||||
|
ctx[\`item\`] = k_block1[i1];
|
||||||
|
ctx[\`item_index\`] = i1;
|
||||||
|
ctx[\`item_value\`] = v_block1[i1];
|
||||||
|
const key1 = ctx['item_index'];
|
||||||
|
const b3 = text(\` [\`);
|
||||||
|
const b4 = text(ctx['item_index']);
|
||||||
|
const b5 = text(\`: \`);
|
||||||
|
const b6 = text(ctx['item']);
|
||||||
|
const b7 = text(\` \`);
|
||||||
|
const b8 = text(ctx['item_value']);
|
||||||
|
const b9 = text(\`] \`);
|
||||||
|
c_block1[i1] = withKey(multi([b3, b4, b5, b6, b7, b8, b9]), key1);
|
||||||
|
}
|
||||||
|
return list(c_block1);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`t-foreach iterate, dict param 1`] = `
|
exports[`t-foreach iterate, dict param 1`] = `
|
||||||
"function anonymous(app, bdom, helpers
|
"function anonymous(app, bdom, helpers
|
||||||
) {
|
) {
|
||||||
@@ -89,9 +145,9 @@ exports[`t-foreach iterate, dict param 1`] = `
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['value']);;
|
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['value']);;
|
||||||
for (let i1 = 0; i1 < l_block2; i1++) {
|
for (let i1 = 0; i1 < l_block2; i1++) {
|
||||||
ctx[\`item\`] = v_block2[i1];
|
ctx[\`item\`] = k_block2[i1];
|
||||||
ctx[\`item_index\`] = i1;
|
ctx[\`item_index\`] = i1;
|
||||||
ctx[\`item_value\`] = k_block2[i1];
|
ctx[\`item_value\`] = v_block2[i1];
|
||||||
const key1 = ctx['item_index'];
|
const key1 = ctx['item_index'];
|
||||||
const b4 = text(\` [\`);
|
const b4 = text(\` [\`);
|
||||||
const b5 = text(ctx['item_index']);
|
const b5 = text(ctx['item_index']);
|
||||||
@@ -108,6 +164,62 @@ exports[`t-foreach iterate, dict param 1`] = `
|
|||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`t-foreach iterate, generator param 1`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
let { prepareList, withKey } = helpers;
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
ctx = Object.create(ctx);
|
||||||
|
const [k_block1, v_block1, l_block1, c_block1] = prepareList(ctx['gen']());;
|
||||||
|
for (let i1 = 0; i1 < l_block1; i1++) {
|
||||||
|
ctx[\`item\`] = k_block1[i1];
|
||||||
|
ctx[\`item_index\`] = i1;
|
||||||
|
ctx[\`item_value\`] = v_block1[i1];
|
||||||
|
const key1 = ctx['item_index'];
|
||||||
|
const b3 = text(\` [\`);
|
||||||
|
const b4 = text(ctx['item_index']);
|
||||||
|
const b5 = text(\`: \`);
|
||||||
|
const b6 = text(ctx['item']);
|
||||||
|
const b7 = text(\` \`);
|
||||||
|
const b8 = text(ctx['item_value']);
|
||||||
|
const b9 = text(\`] \`);
|
||||||
|
c_block1[i1] = withKey(multi([b3, b4, b5, b6, b7, b8, b9]), key1);
|
||||||
|
}
|
||||||
|
return list(c_block1);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`t-foreach iterate, iterable param 1`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
let { prepareList, withKey } = helpers;
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
ctx = Object.create(ctx);
|
||||||
|
const [k_block1, v_block1, l_block1, c_block1] = prepareList(ctx['map'].values());;
|
||||||
|
for (let i1 = 0; i1 < l_block1; i1++) {
|
||||||
|
ctx[\`item\`] = k_block1[i1];
|
||||||
|
ctx[\`item_index\`] = i1;
|
||||||
|
ctx[\`item_value\`] = v_block1[i1];
|
||||||
|
const key1 = ctx['item_index'];
|
||||||
|
const b3 = text(\` [\`);
|
||||||
|
const b4 = text(ctx['item_index']);
|
||||||
|
const b5 = text(\`: \`);
|
||||||
|
const b6 = text(ctx['item']);
|
||||||
|
const b7 = text(\` \`);
|
||||||
|
const b8 = text(ctx['item_value']);
|
||||||
|
const b9 = text(\`] \`);
|
||||||
|
c_block1[i1] = withKey(multi([b3, b4, b5, b6, b7, b8, b9]), key1);
|
||||||
|
}
|
||||||
|
return list(c_block1);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`t-foreach iterate, position 1`] = `
|
exports[`t-foreach iterate, position 1`] = `
|
||||||
"function anonymous(app, bdom, helpers
|
"function anonymous(app, bdom, helpers
|
||||||
) {
|
) {
|
||||||
@@ -120,9 +232,9 @@ exports[`t-foreach iterate, position 1`] = `
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block2, v_block2, l_block2, c_block2] = prepareList(Array(5));;
|
const [k_block2, v_block2, l_block2, c_block2] = prepareList(Array(5));;
|
||||||
for (let i1 = 0; i1 < l_block2; i1++) {
|
for (let i1 = 0; i1 < l_block2; i1++) {
|
||||||
ctx[\`elem\`] = v_block2[i1];
|
ctx[\`elem\`] = k_block2[i1];
|
||||||
ctx[\`elem_first\`] = i1 === 0;
|
ctx[\`elem_first\`] = i1 === 0;
|
||||||
ctx[\`elem_last\`] = i1 === v_block2.length - 1;
|
ctx[\`elem_last\`] = i1 === k_block2.length - 1;
|
||||||
ctx[\`elem_index\`] = i1;
|
ctx[\`elem_index\`] = i1;
|
||||||
const key1 = ctx['elem'];
|
const key1 = ctx['elem'];
|
||||||
let b4, b5, b6, b7, b8, b9;
|
let b4, b5, b6, b7, b8, b9;
|
||||||
@@ -144,6 +256,34 @@ exports[`t-foreach iterate, position 1`] = `
|
|||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`t-foreach iterate, string param 1`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
let { prepareList, withKey } = helpers;
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
ctx = Object.create(ctx);
|
||||||
|
const [k_block1, v_block1, l_block1, c_block1] = prepareList('abc');;
|
||||||
|
for (let i1 = 0; i1 < l_block1; i1++) {
|
||||||
|
ctx[\`item\`] = k_block1[i1];
|
||||||
|
ctx[\`item_index\`] = i1;
|
||||||
|
ctx[\`item_value\`] = v_block1[i1];
|
||||||
|
const key1 = ctx['item_index'];
|
||||||
|
const b3 = text(\` [\`);
|
||||||
|
const b4 = text(ctx['item_index']);
|
||||||
|
const b5 = text(\`: \`);
|
||||||
|
const b6 = text(ctx['item']);
|
||||||
|
const b7 = text(\` \`);
|
||||||
|
const b8 = text(ctx['item_value']);
|
||||||
|
const b9 = text(\`] \`);
|
||||||
|
c_block1[i1] = withKey(multi([b3, b4, b5, b6, b7, b8, b9]), key1);
|
||||||
|
}
|
||||||
|
return list(c_block1);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`t-foreach simple iteration (in a node) 1`] = `
|
exports[`t-foreach simple iteration (in a node) 1`] = `
|
||||||
"function anonymous(app, bdom, helpers
|
"function anonymous(app, bdom, helpers
|
||||||
) {
|
) {
|
||||||
@@ -156,7 +296,7 @@ exports[`t-foreach simple iteration (in a node) 1`] = `
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block2, v_block2, l_block2, c_block2] = prepareList([3,2,1]);;
|
const [k_block2, v_block2, l_block2, c_block2] = prepareList([3,2,1]);;
|
||||||
for (let i1 = 0; i1 < l_block2; i1++) {
|
for (let i1 = 0; i1 < l_block2; i1++) {
|
||||||
ctx[\`item\`] = v_block2[i1];
|
ctx[\`item\`] = k_block2[i1];
|
||||||
const key1 = ctx['item'];
|
const key1 = ctx['item'];
|
||||||
c_block2[i1] = withKey(text(ctx['item']), key1);
|
c_block2[i1] = withKey(text(ctx['item']), key1);
|
||||||
}
|
}
|
||||||
@@ -176,7 +316,7 @@ exports[`t-foreach simple iteration 1`] = `
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block1, v_block1, l_block1, c_block1] = prepareList([3,2,1]);;
|
const [k_block1, v_block1, l_block1, c_block1] = prepareList([3,2,1]);;
|
||||||
for (let i1 = 0; i1 < l_block1; i1++) {
|
for (let i1 = 0; i1 < l_block1; i1++) {
|
||||||
ctx[\`item\`] = v_block1[i1];
|
ctx[\`item\`] = k_block1[i1];
|
||||||
const key1 = ctx['item'];
|
const key1 = ctx['item'];
|
||||||
c_block1[i1] = withKey(text(ctx['item']), key1);
|
c_block1[i1] = withKey(text(ctx['item']), key1);
|
||||||
}
|
}
|
||||||
@@ -198,7 +338,7 @@ exports[`t-foreach simple iteration with two nodes inside 1`] = `
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block1, v_block1, l_block1, c_block1] = prepareList([3,2,1]);;
|
const [k_block1, v_block1, l_block1, c_block1] = prepareList([3,2,1]);;
|
||||||
for (let i1 = 0; i1 < l_block1; i1++) {
|
for (let i1 = 0; i1 < l_block1; i1++) {
|
||||||
ctx[\`item\`] = v_block1[i1];
|
ctx[\`item\`] = k_block1[i1];
|
||||||
const key1 = ctx['item'];
|
const key1 = ctx['item'];
|
||||||
let txt1 = ctx['item'];
|
let txt1 = ctx['item'];
|
||||||
const b3 = block3([txt1]);
|
const b3 = block3([txt1]);
|
||||||
@@ -227,20 +367,20 @@ exports[`t-foreach t-call with body in t-foreach in t-foreach 1`] = `
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['numbers']);;
|
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['numbers']);;
|
||||||
for (let i1 = 0; i1 < l_block2; i1++) {
|
for (let i1 = 0; i1 < l_block2; i1++) {
|
||||||
ctx[\`a\`] = v_block2[i1];
|
ctx[\`a\`] = k_block2[i1];
|
||||||
ctx[\`a_first\`] = i1 === 0;
|
ctx[\`a_first\`] = i1 === 0;
|
||||||
ctx[\`a_last\`] = i1 === v_block2.length - 1;
|
ctx[\`a_last\`] = i1 === k_block2.length - 1;
|
||||||
ctx[\`a_index\`] = i1;
|
ctx[\`a_index\`] = i1;
|
||||||
ctx[\`a_value\`] = k_block2[i1];
|
ctx[\`a_value\`] = v_block2[i1];
|
||||||
const key1 = ctx['a'];
|
const key1 = ctx['a'];
|
||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block4, v_block4, l_block4, c_block4] = prepareList(ctx['letters']);;
|
const [k_block4, v_block4, l_block4, c_block4] = prepareList(ctx['letters']);;
|
||||||
for (let i2 = 0; i2 < l_block4; i2++) {
|
for (let i2 = 0; i2 < l_block4; i2++) {
|
||||||
ctx[\`b\`] = v_block4[i2];
|
ctx[\`b\`] = k_block4[i2];
|
||||||
ctx[\`b_first\`] = i2 === 0;
|
ctx[\`b_first\`] = i2 === 0;
|
||||||
ctx[\`b_last\`] = i2 === v_block4.length - 1;
|
ctx[\`b_last\`] = i2 === k_block4.length - 1;
|
||||||
ctx[\`b_index\`] = i2;
|
ctx[\`b_index\`] = i2;
|
||||||
ctx[\`b_value\`] = k_block4[i2];
|
ctx[\`b_value\`] = v_block4[i2];
|
||||||
const key2 = ctx['b'];
|
const key2 = ctx['b'];
|
||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
ctx[isBoundary] = 1;
|
ctx[isBoundary] = 1;
|
||||||
@@ -296,20 +436,20 @@ exports[`t-foreach t-call without body in t-foreach in t-foreach 1`] = `
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['numbers']);;
|
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['numbers']);;
|
||||||
for (let i1 = 0; i1 < l_block2; i1++) {
|
for (let i1 = 0; i1 < l_block2; i1++) {
|
||||||
ctx[\`a\`] = v_block2[i1];
|
ctx[\`a\`] = k_block2[i1];
|
||||||
ctx[\`a_first\`] = i1 === 0;
|
ctx[\`a_first\`] = i1 === 0;
|
||||||
ctx[\`a_last\`] = i1 === v_block2.length - 1;
|
ctx[\`a_last\`] = i1 === k_block2.length - 1;
|
||||||
ctx[\`a_index\`] = i1;
|
ctx[\`a_index\`] = i1;
|
||||||
ctx[\`a_value\`] = k_block2[i1];
|
ctx[\`a_value\`] = v_block2[i1];
|
||||||
const key1 = ctx['a'];
|
const key1 = ctx['a'];
|
||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block4, v_block4, l_block4, c_block4] = prepareList(ctx['letters']);;
|
const [k_block4, v_block4, l_block4, c_block4] = prepareList(ctx['letters']);;
|
||||||
for (let i2 = 0; i2 < l_block4; i2++) {
|
for (let i2 = 0; i2 < l_block4; i2++) {
|
||||||
ctx[\`b\`] = v_block4[i2];
|
ctx[\`b\`] = k_block4[i2];
|
||||||
ctx[\`b_first\`] = i2 === 0;
|
ctx[\`b_first\`] = i2 === 0;
|
||||||
ctx[\`b_last\`] = i2 === v_block4.length - 1;
|
ctx[\`b_last\`] = i2 === k_block4.length - 1;
|
||||||
ctx[\`b_index\`] = i2;
|
ctx[\`b_index\`] = i2;
|
||||||
ctx[\`b_value\`] = k_block4[i2];
|
ctx[\`b_value\`] = v_block4[i2];
|
||||||
const key2 = ctx['b'];
|
const key2 = ctx['b'];
|
||||||
c_block4[i2] = withKey(callTemplate_1.call(this, ctx, node, key + \`__1__\${key1}__\${key2}\`), key2);
|
c_block4[i2] = withKey(callTemplate_1.call(this, ctx, node, key + \`__1__\${key1}__\${key2}\`), key2);
|
||||||
}
|
}
|
||||||
@@ -363,12 +503,12 @@ exports[`t-foreach t-foreach in t-foreach 1`] = `
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['numbers']);;
|
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['numbers']);;
|
||||||
for (let i1 = 0; i1 < l_block2; i1++) {
|
for (let i1 = 0; i1 < l_block2; i1++) {
|
||||||
ctx[\`number\`] = v_block2[i1];
|
ctx[\`number\`] = k_block2[i1];
|
||||||
const key1 = ctx['number'];
|
const key1 = ctx['number'];
|
||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block3, v_block3, l_block3, c_block3] = prepareList(ctx['letters']);;
|
const [k_block3, v_block3, l_block3, c_block3] = prepareList(ctx['letters']);;
|
||||||
for (let i2 = 0; i2 < l_block3; i2++) {
|
for (let i2 = 0; i2 < l_block3; i2++) {
|
||||||
ctx[\`letter\`] = v_block3[i2];
|
ctx[\`letter\`] = k_block3[i2];
|
||||||
const key2 = ctx['letter'];
|
const key2 = ctx['letter'];
|
||||||
const b5 = text(\` [\`);
|
const b5 = text(\` [\`);
|
||||||
const b6 = text(ctx['number']);
|
const b6 = text(ctx['number']);
|
||||||
@@ -397,7 +537,7 @@ exports[`t-foreach t-foreach with t-if inside (no external node) 1`] = `
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block1, v_block1, l_block1, c_block1] = prepareList(ctx['elems']);;
|
const [k_block1, v_block1, l_block1, c_block1] = prepareList(ctx['elems']);;
|
||||||
for (let i1 = 0; i1 < l_block1; i1++) {
|
for (let i1 = 0; i1 < l_block1; i1++) {
|
||||||
ctx[\`elem\`] = v_block1[i1];
|
ctx[\`elem\`] = k_block1[i1];
|
||||||
const key1 = ctx['elem'].id;
|
const key1 = ctx['elem'].id;
|
||||||
let b3;
|
let b3;
|
||||||
if (ctx['elem'].id<3) {
|
if (ctx['elem'].id<3) {
|
||||||
@@ -424,7 +564,7 @@ exports[`t-foreach t-foreach with t-if inside 1`] = `
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['elems']);;
|
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['elems']);;
|
||||||
for (let i1 = 0; i1 < l_block2; i1++) {
|
for (let i1 = 0; i1 < l_block2; i1++) {
|
||||||
ctx[\`elem\`] = v_block2[i1];
|
ctx[\`elem\`] = k_block2[i1];
|
||||||
const key1 = ctx['elem'].id;
|
const key1 = ctx['elem'].id;
|
||||||
let b4;
|
let b4;
|
||||||
if (ctx['elem'].id<3) {
|
if (ctx['elem'].id<3) {
|
||||||
@@ -452,7 +592,7 @@ exports[`t-foreach t-key on t-foreach 1`] = `
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['things']);;
|
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['things']);;
|
||||||
for (let i1 = 0; i1 < l_block2; i1++) {
|
for (let i1 = 0; i1 < l_block2; i1++) {
|
||||||
ctx[\`thing\`] = v_block2[i1];
|
ctx[\`thing\`] = k_block2[i1];
|
||||||
const key1 = ctx['thing'];
|
const key1 = ctx['thing'];
|
||||||
c_block2[i1] = withKey(block3(), key1);
|
c_block2[i1] = withKey(block3(), key1);
|
||||||
}
|
}
|
||||||
@@ -475,7 +615,7 @@ exports[`t-foreach throws error if invalid loop expression 1`] = `
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['abc']);;
|
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['abc']);;
|
||||||
for (let i1 = 0; i1 < l_block2; i1++) {
|
for (let i1 = 0; i1 < l_block2; i1++) {
|
||||||
ctx[\`item\`] = v_block2[i1];
|
ctx[\`item\`] = k_block2[i1];
|
||||||
ctx[\`item_index\`] = i1;
|
ctx[\`item_index\`] = i1;
|
||||||
const key1 = ctx['item'];
|
const key1 = ctx['item'];
|
||||||
const tKey_1 = ctx['item_index'];
|
const tKey_1 = ctx['item_index'];
|
||||||
@@ -502,7 +642,7 @@ exports[`t-foreach with t-memo 1`] = `
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['items']);;
|
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['items']);;
|
||||||
for (let i1 = 0; i1 < l_block2; i1++) {
|
for (let i1 = 0; i1 < l_block2; i1++) {
|
||||||
ctx[\`item\`] = v_block2[i1];
|
ctx[\`item\`] = k_block2[i1];
|
||||||
const key1 = ctx['item'].id;
|
const key1 = ctx['item'].id;
|
||||||
const memo1 = [ctx['item'].x];
|
const memo1 = [ctx['item'].x];
|
||||||
const vnode1 = cache[key1];;
|
const vnode1 = cache[key1];;
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ exports[`t-key t-key directive in a list 1`] = `
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['beers']);;
|
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['beers']);;
|
||||||
for (let i1 = 0; i1 < l_block2; i1++) {
|
for (let i1 = 0; i1 < l_block2; i1++) {
|
||||||
ctx[\`beer\`] = v_block2[i1];
|
ctx[\`beer\`] = k_block2[i1];
|
||||||
const key1 = ctx['beer'].id;
|
const key1 = ctx['beer'].id;
|
||||||
let txt1 = ctx['beer'].name;
|
let txt1 = ctx['beer'].name;
|
||||||
c_block2[i1] = withKey(block3([txt1]), key1);
|
c_block2[i1] = withKey(block3([txt1]), key1);
|
||||||
|
|||||||
@@ -35,15 +35,15 @@ exports[`t-out multiple calls to t-out 1`] = `
|
|||||||
const callTemplate_1 = app.getTemplate(\`sub\`);
|
const callTemplate_1 = app.getTemplate(\`sub\`);
|
||||||
|
|
||||||
let block1 = createBlock(\`<div><block-child-0/></div>\`);
|
let block1 = createBlock(\`<div><block-child-0/></div>\`);
|
||||||
let block2 = createBlock(\`<span>coucou</span>\`);
|
let block3 = createBlock(\`<span>coucou</span>\`);
|
||||||
|
|
||||||
return function template(ctx, node, key = \\"\\") {
|
return function template(ctx, node, key = \\"\\") {
|
||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
ctx[isBoundary] = 1;
|
ctx[isBoundary] = 1;
|
||||||
const b2 = block2();
|
const b3 = block3();
|
||||||
ctx[zero] = b2;
|
ctx[zero] = b3;
|
||||||
const b3 = callTemplate_1.call(this, ctx, node, key + \`__1\`);
|
const b2 = callTemplate_1.call(this, ctx, node, key + \`__1\`);
|
||||||
return block1([], [b3]);
|
return block1([], [b2]);
|
||||||
}
|
}
|
||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
@@ -102,15 +102,15 @@ exports[`t-out t-out 0 1`] = `
|
|||||||
const callTemplate_1 = app.getTemplate(\`_basic-callee\`);
|
const callTemplate_1 = app.getTemplate(\`_basic-callee\`);
|
||||||
|
|
||||||
let block1 = createBlock(\`<div><block-child-0/></div>\`);
|
let block1 = createBlock(\`<div><block-child-0/></div>\`);
|
||||||
let block2 = createBlock(\`<div>zero</div>\`);
|
let block3 = createBlock(\`<div>zero</div>\`);
|
||||||
|
|
||||||
return function template(ctx, node, key = \\"\\") {
|
return function template(ctx, node, key = \\"\\") {
|
||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
ctx[isBoundary] = 1;
|
ctx[isBoundary] = 1;
|
||||||
const b2 = block2();
|
const b3 = block3();
|
||||||
ctx[zero] = b2;
|
ctx[zero] = b3;
|
||||||
const b3 = callTemplate_1.call(this, ctx, node, key + \`__1\`);
|
const b2 = callTemplate_1.call(this, ctx, node, key + \`__1\`);
|
||||||
return block1([], [b3]);
|
return block1([], [b2]);
|
||||||
}
|
}
|
||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ exports[`t-ref refs in a loop 1`] = `
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['items']);;
|
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['items']);;
|
||||||
for (let i1 = 0; i1 < l_block2; i1++) {
|
for (let i1 = 0; i1 < l_block2; i1++) {
|
||||||
ctx[\`item\`] = v_block2[i1];
|
ctx[\`item\`] = k_block2[i1];
|
||||||
const key1 = ctx['item'];
|
const key1 = ctx['item'];
|
||||||
const tKey_1 = ctx['item'];
|
const tKey_1 = ctx['item'];
|
||||||
const v1 = ctx['item'];
|
const v1 = ctx['item'];
|
||||||
|
|||||||
@@ -351,7 +351,7 @@ exports[`t-set t-set outside modified in t-foreach 1`] = `
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block2, v_block2, l_block2, c_block2] = prepareList(['a','b']);;
|
const [k_block2, v_block2, l_block2, c_block2] = prepareList(['a','b']);;
|
||||||
for (let i1 = 0; i1 < l_block2; i1++) {
|
for (let i1 = 0; i1 < l_block2; i1++) {
|
||||||
ctx[\`val\`] = v_block2[i1];
|
ctx[\`val\`] = k_block2[i1];
|
||||||
const key1 = ctx['val'];
|
const key1 = ctx['val'];
|
||||||
let txt1 = ctx['iter'];
|
let txt1 = ctx['iter'];
|
||||||
c_block2[i1] = withKey(block3([txt1]), key1);
|
c_block2[i1] = withKey(block3([txt1]), key1);
|
||||||
@@ -381,7 +381,7 @@ exports[`t-set t-set outside modified in t-foreach increment-after operator 1`]
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block2, v_block2, l_block2, c_block2] = prepareList(['a','b']);;
|
const [k_block2, v_block2, l_block2, c_block2] = prepareList(['a','b']);;
|
||||||
for (let i1 = 0; i1 < l_block2; i1++) {
|
for (let i1 = 0; i1 < l_block2; i1++) {
|
||||||
ctx[\`val\`] = v_block2[i1];
|
ctx[\`val\`] = k_block2[i1];
|
||||||
const key1 = ctx['val'];
|
const key1 = ctx['val'];
|
||||||
let txt1 = ctx['iter'];
|
let txt1 = ctx['iter'];
|
||||||
c_block2[i1] = withKey(block3([txt1]), key1);
|
c_block2[i1] = withKey(block3([txt1]), key1);
|
||||||
@@ -411,7 +411,7 @@ exports[`t-set t-set outside modified in t-foreach increment-before operator 1`]
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block2, v_block2, l_block2, c_block2] = prepareList(['a','b']);;
|
const [k_block2, v_block2, l_block2, c_block2] = prepareList(['a','b']);;
|
||||||
for (let i1 = 0; i1 < l_block2; i1++) {
|
for (let i1 = 0; i1 < l_block2; i1++) {
|
||||||
ctx[\`val\`] = v_block2[i1];
|
ctx[\`val\`] = k_block2[i1];
|
||||||
const key1 = ctx['val'];
|
const key1 = ctx['val'];
|
||||||
let txt1 = ctx['iter'];
|
let txt1 = ctx['iter'];
|
||||||
c_block2[i1] = withKey(block3([txt1]), key1);
|
c_block2[i1] = withKey(block3([txt1]), key1);
|
||||||
@@ -441,7 +441,7 @@ exports[`t-set t-set should reuse variable if possible 1`] = `
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['list']);;
|
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['list']);;
|
||||||
for (let i1 = 0; i1 < l_block2; i1++) {
|
for (let i1 = 0; i1 < l_block2; i1++) {
|
||||||
ctx[\`elem\`] = v_block2[i1];
|
ctx[\`elem\`] = k_block2[i1];
|
||||||
ctx[\`elem_index\`] = i1;
|
ctx[\`elem_index\`] = i1;
|
||||||
const key1 = ctx['elem_index'];
|
const key1 = ctx['elem_index'];
|
||||||
let txt1 = ctx['v'];
|
let txt1 = ctx['v'];
|
||||||
|
|||||||
@@ -1,5 +1,79 @@
|
|||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`translation support body of t-sets are translated 1`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
let { isBoundary, withDefault, setContextValue } = helpers;
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
ctx = Object.create(ctx);
|
||||||
|
ctx[isBoundary] = 1
|
||||||
|
setContextValue(ctx, \\"label\\", \`translated\`);
|
||||||
|
return text(ctx['label']);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`translation support body of t-sets inside translation=off are not translated 1`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
let { isBoundary, withDefault, setContextValue } = helpers;
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
ctx = Object.create(ctx);
|
||||||
|
ctx[isBoundary] = 1
|
||||||
|
setContextValue(ctx, \\"label\\", \`untranslated\`);
|
||||||
|
return text(ctx['label']);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`translation support body of t-sets with html content are translated 1`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
let { isBoundary, withDefault, LazyValue, safeOutput } = helpers;
|
||||||
|
|
||||||
|
let block1 = createBlock(\`<div>translated</div>\`);
|
||||||
|
|
||||||
|
function value1(ctx, node, key = \\"\\") {
|
||||||
|
return block1();
|
||||||
|
}
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
ctx = Object.create(ctx);
|
||||||
|
ctx[isBoundary] = 1
|
||||||
|
ctx[\`label\`] = new LazyValue(value1, ctx, this, node, key);
|
||||||
|
return safeOutput(ctx['label']);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`translation support body of t-sets with text and html content are translated 1`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
let { isBoundary, withDefault, LazyValue, safeOutput } = helpers;
|
||||||
|
|
||||||
|
let block3 = createBlock(\`<div>translated</div>\`);
|
||||||
|
|
||||||
|
function value1(ctx, node, key = \\"\\") {
|
||||||
|
const b2 = text(\` translated \`);
|
||||||
|
const b3 = block3();
|
||||||
|
return multi([b2, b3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
ctx = Object.create(ctx);
|
||||||
|
ctx[isBoundary] = 1
|
||||||
|
ctx[\`label\`] = new LazyValue(value1, ctx, this, node, key);
|
||||||
|
return safeOutput(ctx['label']);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`translation support can set and remove translatable attributes 1`] = `
|
exports[`translation support can set and remove translatable attributes 1`] = `
|
||||||
"function anonymous(app, bdom, helpers
|
"function anonymous(app, bdom, helpers
|
||||||
) {
|
) {
|
||||||
@@ -52,6 +126,21 @@ exports[`translation support some attributes are translated 1`] = `
|
|||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`translation support t-set and falsy t-value: t-body are translated 1`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
let { isBoundary, withDefault, setContextValue } = helpers;
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
ctx = Object.create(ctx);
|
||||||
|
ctx[isBoundary] = 1
|
||||||
|
setContextValue(ctx, \\"label\\", withDefault(false, \`translated\`));
|
||||||
|
return text(ctx['label']);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`translation support translation is done on the trimmed text, with extra spaces readded after 1`] = `
|
exports[`translation support translation is done on the trimmed text, with extra spaces readded after 1`] = `
|
||||||
"function anonymous(app, bdom, helpers
|
"function anonymous(app, bdom, helpers
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -371,4 +371,33 @@ describe("attributes", () => {
|
|||||||
// not sure about this. maybe we want to remove the attribute?
|
// not sure about this. maybe we want to remove the attribute?
|
||||||
expect(fixture.innerHTML).toBe('<div class="hoy a b"></div>');
|
expect(fixture.innerHTML).toBe('<div class="hoy a b"></div>');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("various combinations of class, t-att-class, and t-att", () => {
|
||||||
|
const template1 = `<div t-att="{ class: 'a' }" class="c">content</div>`;
|
||||||
|
expect(renderToString(template1)).toBe('<div class="c a">content</div>');
|
||||||
|
|
||||||
|
const template2 = `<div t-att="{ class: 'a' }" t-att-class="{'b': true}" class="c">content</div>`;
|
||||||
|
expect(renderToString(template2)).toBe('<div class="c a b">content</div>');
|
||||||
|
|
||||||
|
const template3 = `<div t-att="{ class: 'a' }" class="c" t-att-class="{'b': true}">content</div>`;
|
||||||
|
expect(renderToString(template3)).toBe('<div class="c a b">content</div>');
|
||||||
|
|
||||||
|
const template4 = `<div class="c" t-att="{ class: 'a' }" t-att-class="{'b': true}">content</div>`;
|
||||||
|
expect(renderToString(template4)).toBe('<div class="c a b">content</div>');
|
||||||
|
|
||||||
|
const template5 = `<div class="c" t-att-class="{'b': true}" t-att="{ class: 'a' }">content</div>`;
|
||||||
|
expect(renderToString(template5)).toBe('<div class="c b a">content</div>');
|
||||||
|
|
||||||
|
const template6 = `<div class="c" t-att-class="{'b': true}">content</div>`;
|
||||||
|
expect(renderToString(template6)).toBe('<div class="c b">content</div>');
|
||||||
|
|
||||||
|
const template7 = `<div class="c" t-attf-class="{{'b'}}">content</div>`;
|
||||||
|
expect(renderToString(template7)).toBe('<div class="c b">content</div>');
|
||||||
|
|
||||||
|
const template8 = `<div t-att="{ class: 'a' }" class="c" t-att-class="{'b': true}">content</div>`;
|
||||||
|
expect(renderToString(template8)).toBe('<div class="c a b">content</div>');
|
||||||
|
|
||||||
|
const template9 = `<div t-att="{ class: 'a' }" t-att-class="{'b': true}">content</div>`;
|
||||||
|
expect(renderToString(template9)).toBe('<div class="a b">content</div>');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1147,6 +1147,24 @@ describe("qweb parser", () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("t-onclick without dash", async () => {
|
||||||
|
expect(() => parse(`<button t-onclick="add">Click</button>`)).toThrowError(
|
||||||
|
"Unknown QWeb directive: 't-onclick'"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("t-on without event", async () => {
|
||||||
|
expect(() => parse(`<button t-on="add">Click</button>`)).toThrowError(
|
||||||
|
"Missing event name with t-on directive"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("t-on- without event", async () => {
|
||||||
|
expect(() => parse(`<button t-on-="add">Click</button>`)).toThrowError(
|
||||||
|
"Missing event name with t-on directive"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// t-model
|
// t-model
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
@@ -1275,6 +1293,12 @@ describe("qweb parser", () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("component with event handler", async () => {
|
||||||
|
expect(() => parse(`<MyComponent t-onclick="someMethod"/>`)).toThrowError(
|
||||||
|
"unsupported directive on Component: t-onclick"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
test("component with t-ref", async () => {
|
test("component with t-ref", async () => {
|
||||||
expect(() => parse(`<MyComponent t-ref="something"/>`)).toThrow(
|
expect(() => parse(`<MyComponent t-ref="something"/>`)).toThrow(
|
||||||
"t-ref is no longer supported on components. Consider exposing only the public part of the component's API through a callback prop."
|
"t-ref is no longer supported on components. Consider exposing only the public part of the component's API through a callback prop."
|
||||||
@@ -1545,6 +1569,12 @@ describe("qweb parser", () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("component with t-out", async () => {
|
||||||
|
expect(parse(`<MyComponent t-out="someValue"/>`)).toEqual(
|
||||||
|
parse(`<MyComponent><t t-out="someValue"/></MyComponent>`)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
test("component with t-esc and content", async () => {
|
test("component with t-esc and content", async () => {
|
||||||
expect(() => parse(`<MyComponent t-esc="someValue">Some content</MyComponent>`)).toThrow(
|
expect(() => parse(`<MyComponent t-esc="someValue">Some content</MyComponent>`)).toThrow(
|
||||||
"Cannot have t-esc on a component that already has content"
|
"Cannot have t-esc on a component that already has content"
|
||||||
@@ -1967,8 +1997,8 @@ describe("qweb parser", () => {
|
|||||||
baseExpr: "state",
|
baseExpr: "state",
|
||||||
expr: "'stuff'",
|
expr: "'stuff'",
|
||||||
eventType: "click",
|
eventType: "click",
|
||||||
shouldNumberize: false,
|
shouldNumberize: true,
|
||||||
shouldTrim: false,
|
shouldTrim: true,
|
||||||
targetAttr: "value",
|
targetAttr: "value",
|
||||||
hasDynamicChildren: false,
|
hasDynamicChildren: false,
|
||||||
specialInitTargetAttr: "checked",
|
specialInitTargetAttr: "checked",
|
||||||
|
|||||||
@@ -9,20 +9,20 @@ describe("properly support svg", () => {
|
|||||||
test("add proper namespace to svg", () => {
|
test("add proper namespace to svg", () => {
|
||||||
const template = `<svg width="100px" height="90px"><circle cx="50" cy="50" r="4" stroke="green" stroke-width="1" fill="yellow"/> </svg>`;
|
const template = `<svg width="100px" height="90px"><circle cx="50" cy="50" r="4" stroke="green" stroke-width="1" fill="yellow"/> </svg>`;
|
||||||
expect(renderToString(template)).toBe(
|
expect(renderToString(template)).toBe(
|
||||||
`<svg width=\"100px\" height=\"90px\"><circle cx=\"50\" cy=\"50\" r=\"4\" stroke=\"green\" stroke-width=\"1\" fill=\"yellow\"></circle> </svg>`
|
`<svg xmlns="http://www.w3.org/2000/svg" width="100px" height="90px"><circle cx="50" cy="50" r="4" stroke="green" stroke-width="1" fill="yellow"></circle> </svg>`
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("add proper namespace to g tags", () => {
|
test("add proper namespace to g tags", () => {
|
||||||
const template = `<g><circle cx="50" cy="50" r="4" stroke="green" stroke-width="1" fill="yellow"/> </g>`;
|
const template = `<g><circle cx="50" cy="50" r="4" stroke="green" stroke-width="1" fill="yellow"/> </g>`;
|
||||||
expect(renderToString(template)).toBe(
|
expect(renderToString(template)).toBe(
|
||||||
`<g><circle cx=\"50\" cy=\"50\" r=\"4\" stroke=\"green\" stroke-width=\"1\" fill=\"yellow\"></circle> </g>`
|
`<g xmlns="http://www.w3.org/2000/svg"><circle cx="50" cy="50" r="4" stroke="green" stroke-width="1" fill="yellow"></circle> </g>`
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("namespace to g tags not added if already in svg namespace", () => {
|
test("namespace to g tags not added if already in svg namespace", () => {
|
||||||
const template = `<svg><g/></svg>`;
|
const template = `<svg><g/></svg>`;
|
||||||
expect(renderToString(template)).toBe(`<svg><g></g></svg>`);
|
expect(renderToString(template)).toBe(`<svg xmlns="http://www.w3.org/2000/svg"><g></g></svg>`);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("namespace to svg tags added even if already in svg namespace", () => {
|
test("namespace to svg tags added even if already in svg namespace", () => {
|
||||||
@@ -41,8 +41,13 @@ describe("properly support svg", () => {
|
|||||||
test("svg namespace added to sub-blocks", () => {
|
test("svg namespace added to sub-blocks", () => {
|
||||||
const template = `<svg><path t-if="path"/></svg>`;
|
const template = `<svg><path t-if="path"/></svg>`;
|
||||||
|
|
||||||
expect(renderToString(template, { path: false })).toBe(`<svg></svg>`);
|
expect(renderToString(template, { path: false })).toBe(
|
||||||
expect(renderToString(template, { path: true })).toBe(`<svg><path></path></svg>`);
|
`<svg xmlns="http://www.w3.org/2000/svg"></svg>`
|
||||||
|
);
|
||||||
|
// Because the path is its own block, it has its own xmlns attribute
|
||||||
|
expect(renderToString(template, { path: true })).toBe(
|
||||||
|
`<svg xmlns="http://www.w3.org/2000/svg"><path xmlns="http://www.w3.org/2000/svg"></path></svg>`
|
||||||
|
);
|
||||||
|
|
||||||
const bdom = renderToBdom(template, { path: true });
|
const bdom = renderToBdom(template, { path: true });
|
||||||
const fixture = makeTestFixture();
|
const fixture = makeTestFixture();
|
||||||
|
|||||||
@@ -430,6 +430,48 @@ describe("t-call (template calling)", () => {
|
|||||||
expect(context.renderToString("main")).toBe(expected);
|
expect(context.renderToString("main")).toBe(expected);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("root t-call with body: t-if true", () => {
|
||||||
|
const context = new TestContext();
|
||||||
|
const subTemplate = `sub`;
|
||||||
|
const main = `<t t-call="subTemplate"><t t-if="true">zero</t></t>`;
|
||||||
|
context.addTemplate("subTemplate", subTemplate);
|
||||||
|
context.addTemplate("main", main);
|
||||||
|
const expected = "sub";
|
||||||
|
expect(context.renderToString("main")).toBe(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("root t-call with body: t-if false", () => {
|
||||||
|
const context = new TestContext();
|
||||||
|
const subTemplate = `sub`;
|
||||||
|
const main = `<t t-call="subTemplate"><t t-if="false">zero</t></t>`;
|
||||||
|
context.addTemplate("subTemplate", subTemplate);
|
||||||
|
context.addTemplate("main", main);
|
||||||
|
const expected = "sub";
|
||||||
|
expect(context.renderToString("main")).toBe(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("root t-call with body: t-out with default", () => {
|
||||||
|
const context = new TestContext();
|
||||||
|
const subTemplate = `sub`;
|
||||||
|
const main = `<t t-call="subTemplate"><t t-out="nothing">default</t></t>`;
|
||||||
|
context.addTemplate("subTemplate", subTemplate);
|
||||||
|
context.addTemplate("main", main);
|
||||||
|
const expected = "sub";
|
||||||
|
expect(context.renderToString("main")).toBe(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("root t-call with body: t-foreach", () => {
|
||||||
|
const context = new TestContext();
|
||||||
|
const subTemplate = `sub`;
|
||||||
|
const main = `<t t-call="subTemplate">
|
||||||
|
<t t-foreach="[1]" t-as="i" t-key="i">1</t>
|
||||||
|
</t>`;
|
||||||
|
context.addTemplate("subTemplate", subTemplate);
|
||||||
|
context.addTemplate("main", main);
|
||||||
|
const expected = "sub";
|
||||||
|
expect(context.renderToString("main")).toBe(expected);
|
||||||
|
});
|
||||||
|
|
||||||
test("dynamic t-call", () => {
|
test("dynamic t-call", () => {
|
||||||
const context = new TestContext();
|
const context = new TestContext();
|
||||||
const foo = `<foo><t t-esc="val"/></foo>`;
|
const foo = `<foo><t t-esc="val"/></foo>`;
|
||||||
|
|||||||
@@ -105,6 +105,73 @@ describe("t-foreach", () => {
|
|||||||
expect(renderToString(template, context)).toBe(expected);
|
expect(renderToString(template, context)).toBe(expected);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("iterate, Map param", () => {
|
||||||
|
const template = `
|
||||||
|
<t t-foreach="value" t-as="item" t-key="item_index">
|
||||||
|
[<t t-esc="item_index"/>: <t t-esc="item"/> <t t-esc="item_value"/>]
|
||||||
|
</t>`;
|
||||||
|
const expected = ` [0: a 1] [1: b 2] [2: c 3] `;
|
||||||
|
const context = {
|
||||||
|
value: new Map([
|
||||||
|
["a", 1],
|
||||||
|
["b", 2],
|
||||||
|
["c", 3],
|
||||||
|
]),
|
||||||
|
};
|
||||||
|
expect(renderToString(template, context)).toBe(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("iterate, Set param", () => {
|
||||||
|
const template = `
|
||||||
|
<t t-foreach="value" t-as="item" t-key="item_index">
|
||||||
|
[<t t-esc="item_index"/>: <t t-esc="item"/> <t t-esc="item_value"/>]
|
||||||
|
</t>`;
|
||||||
|
const expected = ` [0: 1 1] [1: 2 2] [2: 3 3] `;
|
||||||
|
const context = { value: new Set([1, 2, 3]) };
|
||||||
|
expect(renderToString(template, context)).toBe(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("iterate, string param", () => {
|
||||||
|
const template = `
|
||||||
|
<t t-foreach="'abc'" t-as="item" t-key="item_index">
|
||||||
|
[<t t-esc="item_index"/>: <t t-esc="item"/> <t t-esc="item_value"/>]
|
||||||
|
</t>`;
|
||||||
|
const expected = ` [0: a a] [1: b b] [2: c c] `;
|
||||||
|
expect(renderToString(template)).toBe(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("iterate, iterable param", () => {
|
||||||
|
const template = `
|
||||||
|
<t t-foreach="map.values()" t-as="item" t-key="item_index">
|
||||||
|
[<t t-esc="item_index"/>: <t t-esc="item"/> <t t-esc="item_value"/>]
|
||||||
|
</t>`;
|
||||||
|
const expected = ` [0: 1 1] [1: 2 2] [2: 3 3] `;
|
||||||
|
const context = {
|
||||||
|
map: new Map([
|
||||||
|
["a", 1],
|
||||||
|
["b", 2],
|
||||||
|
["c", 3],
|
||||||
|
]),
|
||||||
|
};
|
||||||
|
expect(renderToString(template, context)).toBe(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("iterate, generator param", () => {
|
||||||
|
const template = `
|
||||||
|
<t t-foreach="gen()" t-as="item" t-key="item_index">
|
||||||
|
[<t t-esc="item_index"/>: <t t-esc="item"/> <t t-esc="item_value"/>]
|
||||||
|
</t>`;
|
||||||
|
const expected = ` [0: 1 1] [1: 2 2] [2: 3 3] `;
|
||||||
|
const context = {
|
||||||
|
*gen() {
|
||||||
|
yield 1;
|
||||||
|
yield 2;
|
||||||
|
yield 3;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
expect(renderToString(template, context)).toBe(expected);
|
||||||
|
});
|
||||||
|
|
||||||
test("does not pollute the rendering context", () => {
|
test("does not pollute the rendering context", () => {
|
||||||
const template = `
|
const template = `
|
||||||
<div>
|
<div>
|
||||||
@@ -193,7 +260,9 @@ describe("t-foreach", () => {
|
|||||||
|
|
||||||
test("throws error if invalid loop expression", () => {
|
test("throws error if invalid loop expression", () => {
|
||||||
const test = `<div><t t-foreach="abc" t-as="item" t-key="item"><span t-key="item_index"/></t></div>`;
|
const test = `<div><t t-foreach="abc" t-as="item" t-key="item"><span t-key="item_index"/></t></div>`;
|
||||||
expect(() => renderToString(test)).toThrow("Invalid loop expression");
|
expect(() => renderToString(test)).toThrow(
|
||||||
|
'Invalid loop expression: "undefined" is not iterable'
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("t-foreach with t-if inside", () => {
|
test("t-foreach with t-if inside", () => {
|
||||||
|
|||||||
@@ -100,4 +100,74 @@ describe("translation support", () => {
|
|||||||
expect(translateFn).toHaveBeenCalledWith("some word");
|
expect(translateFn).toHaveBeenCalledWith("some word");
|
||||||
expect(fixture.innerHTML).toBe("<div>un mot</div>");
|
expect(fixture.innerHTML).toBe("<div>un mot</div>");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("body of t-sets are translated", async () => {
|
||||||
|
class SomeComponent extends Component {
|
||||||
|
static template = xml`
|
||||||
|
<t t-set="label">untranslated</t>
|
||||||
|
<t t-esc="label"/>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const translateFn = () => "translated";
|
||||||
|
|
||||||
|
await mount(SomeComponent, fixture, { translateFn });
|
||||||
|
expect(fixture.innerHTML).toBe("translated");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("body of t-sets inside translation=off are not translated", async () => {
|
||||||
|
class SomeComponent extends Component {
|
||||||
|
static template = xml`
|
||||||
|
<t t-translation="off">
|
||||||
|
<t t-set="label">untranslated</t>
|
||||||
|
<t t-esc="label"/>
|
||||||
|
</t>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const translateFn = () => "translated";
|
||||||
|
|
||||||
|
await mount(SomeComponent, fixture, { translateFn });
|
||||||
|
expect(fixture.innerHTML).toBe("untranslated");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("body of t-sets with html content are translated", async () => {
|
||||||
|
class SomeComponent extends Component {
|
||||||
|
static template = xml`
|
||||||
|
<t t-set="label"><div>untranslated</div></t>
|
||||||
|
<t t-out="label"/>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const translateFn = () => "translated";
|
||||||
|
|
||||||
|
await mount(SomeComponent, fixture, { translateFn });
|
||||||
|
expect(fixture.innerHTML).toBe("<div>translated</div>");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("body of t-sets with text and html content are translated", async () => {
|
||||||
|
class SomeComponent extends Component {
|
||||||
|
static template = xml`
|
||||||
|
<t t-set="label">
|
||||||
|
some text
|
||||||
|
<div>untranslated</div>
|
||||||
|
</t>
|
||||||
|
<t t-out="label"/>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const translateFn = () => "translated";
|
||||||
|
|
||||||
|
await mount(SomeComponent, fixture, { translateFn });
|
||||||
|
expect(fixture.innerHTML).toBe(" translated <div>translated</div>");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("t-set and falsy t-value: t-body are translated", async () => {
|
||||||
|
class SomeComponent extends Component {
|
||||||
|
static template = xml`
|
||||||
|
<t t-set="label" t-value="false">untranslated</t>
|
||||||
|
<t t-esc="label"/>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const translateFn = () => "translated";
|
||||||
|
|
||||||
|
await mount(SomeComponent, fixture, { translateFn });
|
||||||
|
expect(fixture.innerHTML).toBe("translated");
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -11,8 +11,8 @@ describe("basic validation", () => {
|
|||||||
expect(() => context.getTemplate("invalidname")).toThrow("Missing template");
|
expect(() => context.getTemplate("invalidname")).toThrow("Missing template");
|
||||||
});
|
});
|
||||||
|
|
||||||
test("cannot add a different template with the same name", () => {
|
test("cannot add a different template with the same name in dev mode", () => {
|
||||||
const context = new TemplateSet();
|
const context = new TemplateSet({ dev: true });
|
||||||
context.addTemplate("test", `<t/>`);
|
context.addTemplate("test", `<t/>`);
|
||||||
// Same template with the same name is fine
|
// Same template with the same name is fine
|
||||||
expect(() => context.addTemplate("test", "<t/>")).not.toThrow();
|
expect(() => context.addTemplate("test", "<t/>")).not.toThrow();
|
||||||
@@ -20,6 +20,13 @@ describe("basic validation", () => {
|
|||||||
expect(() => context.addTemplate("test", "<div/>")).toThrow("already defined");
|
expect(() => context.addTemplate("test", "<div/>")).toThrow("already defined");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("adding different template with same name outside dev mode silently ignores it", () => {
|
||||||
|
const context = new TemplateSet({ dev: false });
|
||||||
|
context.addTemplate("test", `<t/>`);
|
||||||
|
expect(() => context.addTemplate("test", "<div/>")).not.toThrow();
|
||||||
|
expect(context.rawTemplates.test).toBe("<t/>");
|
||||||
|
});
|
||||||
|
|
||||||
test("invalid xml", () => {
|
test("invalid xml", () => {
|
||||||
const template = "<div>";
|
const template = "<div>";
|
||||||
expect(() => snapshotTemplate(template)).toThrow("Invalid XML in template");
|
expect(() => snapshotTemplate(template)).toThrow("Invalid XML in template");
|
||||||
@@ -37,4 +44,22 @@ describe("basic validation", () => {
|
|||||||
const template = `<div t-best-beer="rochefort 10">test</div>`;
|
const template = `<div t-best-beer="rochefort 10">test</div>`;
|
||||||
expect(() => renderToString(template)).toThrow("Unknown QWeb directive: 't-best-beer'");
|
expect(() => renderToString(template)).toThrow("Unknown QWeb directive: 't-best-beer'");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("compilation error", () => {
|
||||||
|
const template = `<div t-att-class="a b">test</div>`;
|
||||||
|
expect(() => renderToString(template))
|
||||||
|
.toThrow(`Failed to compile anonymous template: Unexpected identifier
|
||||||
|
|
||||||
|
generated code:
|
||||||
|
function(app, bdom, helpers) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
|
||||||
|
let block1 = createBlock(\`<div block-attribute-0="class">test</div>\`);
|
||||||
|
|
||||||
|
return function template(ctx, node, key = "") {
|
||||||
|
let attr1 = ctx['a']ctx['b'];
|
||||||
|
return block1([attr1]);
|
||||||
|
}
|
||||||
|
}`);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -492,7 +492,7 @@ exports[`basics list of two sub components inside other nodes 1`] = `
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['state'].blips);;
|
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['state'].blips);;
|
||||||
for (let i1 = 0; i1 < l_block2; i1++) {
|
for (let i1 = 0; i1 < l_block2; i1++) {
|
||||||
ctx[\`blip\`] = v_block2[i1];
|
ctx[\`blip\`] = k_block2[i1];
|
||||||
const key1 = ctx['blip'].id;
|
const key1 = ctx['blip'].id;
|
||||||
const b4 = comp1({}, key + \`__1__\${key1}\`, node, this, null);
|
const b4 = comp1({}, key + \`__1__\${key1}\`, node, this, null);
|
||||||
const b5 = comp2({}, key + \`__2__\${key1}\`, node, this, null);
|
const b5 = comp2({}, key + \`__2__\${key1}\`, node, this, null);
|
||||||
@@ -1084,7 +1084,7 @@ exports[`basics updating a component with t-foreach as root 1`] = `
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block1, v_block1, l_block1, c_block1] = prepareList(ctx['items']);;
|
const [k_block1, v_block1, l_block1, c_block1] = prepareList(ctx['items']);;
|
||||||
for (let i1 = 0; i1 < l_block1; i1++) {
|
for (let i1 = 0; i1 < l_block1; i1++) {
|
||||||
ctx[\`item\`] = v_block1[i1];
|
ctx[\`item\`] = k_block1[i1];
|
||||||
const key1 = ctx['item'];
|
const key1 = ctx['item'];
|
||||||
c_block1[i1] = withKey(text(ctx['item']), key1);
|
c_block1[i1] = withKey(text(ctx['item']), key1);
|
||||||
}
|
}
|
||||||
@@ -1135,7 +1135,7 @@ exports[`basics widget after a t-foreach 1`] = `
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block2, v_block2, l_block2, c_block2] = prepareList(Array(2));;
|
const [k_block2, v_block2, l_block2, c_block2] = prepareList(Array(2));;
|
||||||
for (let i1 = 0; i1 < l_block2; i1++) {
|
for (let i1 = 0; i1 < l_block2; i1++) {
|
||||||
ctx[\`elem\`] = v_block2[i1];
|
ctx[\`elem\`] = k_block2[i1];
|
||||||
ctx[\`elem_index\`] = i1;
|
ctx[\`elem_index\`] = i1;
|
||||||
const key1 = ctx['elem_index'];
|
const key1 = ctx['elem_index'];
|
||||||
c_block2[i1] = withKey(text(\`txt\`), key1);
|
c_block2[i1] = withKey(text(\`txt\`), key1);
|
||||||
@@ -1248,7 +1248,7 @@ exports[`support svg components add proper namespace to svg 1`] = `
|
|||||||
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
const comp1 = app.createComponent(\`GComp\`, true, false, false, []);
|
const comp1 = app.createComponent(\`GComp\`, true, false, false, []);
|
||||||
|
|
||||||
let block1 = createBlock(\`<svg block-ns=\\"http://www.w3.org/2000/svg\\"><block-child-0/></svg>\`);
|
let block1 = createBlock(\`<svg xmlns=\\"http://www.w3.org/2000/svg\\"><block-child-0 xmlns=\\"\\"/></svg>\`);
|
||||||
|
|
||||||
return function template(ctx, node, key = \\"\\") {
|
return function template(ctx, node, key = \\"\\") {
|
||||||
const b2 = comp1({}, key + \`__1\`, node, this, null);
|
const b2 = comp1({}, key + \`__1\`, node, this, null);
|
||||||
@@ -1262,7 +1262,7 @@ exports[`support svg components add proper namespace to svg 2`] = `
|
|||||||
) {
|
) {
|
||||||
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
|
||||||
let block1 = createBlock(\`<g block-ns=\\"http://www.w3.org/2000/svg\\"><circle cx=\\"50\\" cy=\\"50\\" r=\\"4\\" stroke=\\"green\\" stroke-width=\\"1\\" fill=\\"yellow\\"/></g>\`);
|
let block1 = createBlock(\`<g xmlns=\\"http://www.w3.org/2000/svg\\"><circle cx=\\"50\\" cy=\\"50\\" r=\\"4\\" stroke=\\"green\\" stroke-width=\\"1\\" fill=\\"yellow\\"/></g>\`);
|
||||||
|
|
||||||
return function template(ctx, node, key = \\"\\") {
|
return function template(ctx, node, key = \\"\\") {
|
||||||
return block1();
|
return block1();
|
||||||
@@ -1282,7 +1282,7 @@ exports[`t-out in components can render list of t-out 1`] = `
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['state'].items);;
|
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['state'].items);;
|
||||||
for (let i1 = 0; i1 < l_block2; i1++) {
|
for (let i1 = 0; i1 < l_block2; i1++) {
|
||||||
ctx[\`item\`] = v_block2[i1];
|
ctx[\`item\`] = k_block2[i1];
|
||||||
const key1 = ctx['item'];
|
const key1 = ctx['item'];
|
||||||
const b4 = text(ctx['item']);
|
const b4 = text(ctx['item']);
|
||||||
const b5 = safeOutput(ctx['item']);
|
const b5 = safeOutput(ctx['item']);
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ exports[`Cascading renders after microtaskTick 1`] = `
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block4, v_block4, l_block4, c_block4] = prepareList(ctx['state']);;
|
const [k_block4, v_block4, l_block4, c_block4] = prepareList(ctx['state']);;
|
||||||
for (let i1 = 0; i1 < l_block4; i1++) {
|
for (let i1 = 0; i1 < l_block4; i1++) {
|
||||||
ctx[\`elem\`] = v_block4[i1];
|
ctx[\`elem\`] = k_block4[i1];
|
||||||
const key1 = ctx['elem'].id;
|
const key1 = ctx['elem'].id;
|
||||||
c_block4[i1] = withKey(text(ctx['elem'].id), key1);
|
c_block4[i1] = withKey(text(ctx['elem'].id), key1);
|
||||||
}
|
}
|
||||||
@@ -34,7 +34,7 @@ exports[`Cascading renders after microtaskTick 2`] = `
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block1, v_block1, l_block1, c_block1] = prepareList(ctx['state']);;
|
const [k_block1, v_block1, l_block1, c_block1] = prepareList(ctx['state']);;
|
||||||
for (let i1 = 0; i1 < l_block1; i1++) {
|
for (let i1 = 0; i1 < l_block1; i1++) {
|
||||||
ctx[\`elem\`] = v_block1[i1];
|
ctx[\`elem\`] = k_block1[i1];
|
||||||
const key1 = ctx['elem'].id;
|
const key1 = ctx['elem'].id;
|
||||||
c_block1[i1] = withKey(comp1({id: ctx['elem'].id}, key + \`__1__\${key1}\`, node, this, null), key1);
|
c_block1[i1] = withKey(comp1({id: ctx['elem'].id}, key + \`__1__\${key1}\`, node, this, null), key1);
|
||||||
}
|
}
|
||||||
@@ -184,7 +184,7 @@ exports[`changing state before first render does not trigger a render (with pare
|
|||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`changing state before first render does not trigger a render (with parent) 2`] = `
|
exports[`changing state before first render does not trigger a render (with parent) 3`] = `
|
||||||
"function anonymous(app, bdom, helpers
|
"function anonymous(app, bdom, helpers
|
||||||
) {
|
) {
|
||||||
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
@@ -212,6 +212,73 @@ exports[`changing state before first render does not trigger a render 1`] = `
|
|||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`component destroyed just after render 1`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
const comp1 = app.createComponent(\`B\`, true, false, false, []);
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
return comp1({}, key + \`__1\`, node, this, null);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`component destroyed just after render 2`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
const b2 = text(\`B\`);
|
||||||
|
const b3 = text(ctx['state'].value);
|
||||||
|
return multi([b2, b3]);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`components are not destroyed between animation frame 1`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
const comp1 = app.createComponent(\`B\`, true, false, false, []);
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
let b2, b3;
|
||||||
|
b2 = text(\`A\`);
|
||||||
|
if (ctx['state'].flag) {
|
||||||
|
b3 = comp1({}, key + \`__1\`, node, this, null);
|
||||||
|
}
|
||||||
|
return multi([b2, b3]);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`components are not destroyed between animation frame 3`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
const comp1 = app.createComponent(\`C\`, true, false, false, []);
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
const b2 = text(\`B\`);
|
||||||
|
const b3 = comp1({}, key + \`__1\`, node, this, null);
|
||||||
|
return multi([b2, b3]);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`components are not destroyed between animation frame 5`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
return text(\`C\`);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`concurrent renderings scenario 1 1`] = `
|
exports[`concurrent renderings scenario 1 1`] = `
|
||||||
"function anonymous(app, bdom, helpers
|
"function anonymous(app, bdom, helpers
|
||||||
) {
|
) {
|
||||||
@@ -681,7 +748,7 @@ exports[`concurrent renderings scenario 10 2`] = `
|
|||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`concurrent renderings scenario 10 3`] = `
|
exports[`concurrent renderings scenario 10 4`] = `
|
||||||
"function anonymous(app, bdom, helpers
|
"function anonymous(app, bdom, helpers
|
||||||
) {
|
) {
|
||||||
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
@@ -926,7 +993,7 @@ exports[`concurrent renderings scenario 16 3`] = `
|
|||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`concurrent renderings scenario 16 4`] = `
|
exports[`concurrent renderings scenario 16 6`] = `
|
||||||
"function anonymous(app, bdom, helpers
|
"function anonymous(app, bdom, helpers
|
||||||
) {
|
) {
|
||||||
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
@@ -957,7 +1024,7 @@ exports[`creating two async components, scenario 1 1`] = `
|
|||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`creating two async components, scenario 1 2`] = `
|
exports[`creating two async components, scenario 1 3`] = `
|
||||||
"function anonymous(app, bdom, helpers
|
"function anonymous(app, bdom, helpers
|
||||||
) {
|
) {
|
||||||
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
@@ -971,7 +1038,7 @@ exports[`creating two async components, scenario 1 2`] = `
|
|||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`creating two async components, scenario 1 3`] = `
|
exports[`creating two async components, scenario 1 5`] = `
|
||||||
"function anonymous(app, bdom, helpers
|
"function anonymous(app, bdom, helpers
|
||||||
) {
|
) {
|
||||||
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
@@ -1018,7 +1085,7 @@ exports[`creating two async components, scenario 2 2`] = `
|
|||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`creating two async components, scenario 2 3`] = `
|
exports[`creating two async components, scenario 2 5`] = `
|
||||||
"function anonymous(app, bdom, helpers
|
"function anonymous(app, bdom, helpers
|
||||||
) {
|
) {
|
||||||
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
@@ -1066,7 +1133,7 @@ exports[`creating two async components, scenario 3 (patching in the same frame)
|
|||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`creating two async components, scenario 3 (patching in the same frame) 3`] = `
|
exports[`creating two async components, scenario 3 (patching in the same frame) 5`] = `
|
||||||
"function anonymous(app, bdom, helpers
|
"function anonymous(app, bdom, helpers
|
||||||
) {
|
) {
|
||||||
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
@@ -1241,7 +1308,7 @@ exports[`delayed render does not go through when t-component value changed 2`] =
|
|||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`delayed render does not go through when t-component value changed 3`] = `
|
exports[`delayed render does not go through when t-component value changed 4`] = `
|
||||||
"function anonymous(app, bdom, helpers
|
"function anonymous(app, bdom, helpers
|
||||||
) {
|
) {
|
||||||
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
@@ -1550,7 +1617,7 @@ exports[`destroyed component causes other soon to be destroyed component to rere
|
|||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`destroyed component causes other soon to be destroyed component to rerender, weird stuff happens 2`] = `
|
exports[`destroyed component causes other soon to be destroyed component to rerender, weird stuff happens 3`] = `
|
||||||
"function anonymous(app, bdom, helpers
|
"function anonymous(app, bdom, helpers
|
||||||
) {
|
) {
|
||||||
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
@@ -1561,7 +1628,7 @@ exports[`destroyed component causes other soon to be destroyed component to rere
|
|||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`destroyed component causes other soon to be destroyed component to rerender, weird stuff happens 3`] = `
|
exports[`destroyed component causes other soon to be destroyed component to rerender, weird stuff happens 4`] = `
|
||||||
"function anonymous(app, bdom, helpers
|
"function anonymous(app, bdom, helpers
|
||||||
) {
|
) {
|
||||||
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
@@ -1589,7 +1656,7 @@ exports[`destroying/recreating a subcomponent, other scenario 1`] = `
|
|||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`destroying/recreating a subcomponent, other scenario 2`] = `
|
exports[`destroying/recreating a subcomponent, other scenario 3`] = `
|
||||||
"function anonymous(app, bdom, helpers
|
"function anonymous(app, bdom, helpers
|
||||||
) {
|
) {
|
||||||
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
@@ -1618,7 +1685,7 @@ exports[`destroying/recreating a subwidget with different props (if start is not
|
|||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`destroying/recreating a subwidget with different props (if start is not over) 2`] = `
|
exports[`destroying/recreating a subwidget with different props (if start is not over) 3`] = `
|
||||||
"function anonymous(app, bdom, helpers
|
"function anonymous(app, bdom, helpers
|
||||||
) {
|
) {
|
||||||
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
@@ -1720,7 +1787,7 @@ exports[`rendering component again in next microtick 1`] = `
|
|||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`rendering component again in next microtick 2`] = `
|
exports[`rendering component again in next microtick 3`] = `
|
||||||
"function anonymous(app, bdom, helpers
|
"function anonymous(app, bdom, helpers
|
||||||
) {
|
) {
|
||||||
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
@@ -1834,7 +1901,7 @@ exports[`t-foreach with dynamic async component 1`] = `
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block1, v_block1, l_block1, c_block1] = prepareList(ctx['list']);;
|
const [k_block1, v_block1, l_block1, c_block1] = prepareList(ctx['list']);;
|
||||||
for (let i1 = 0; i1 < l_block1; i1++) {
|
for (let i1 = 0; i1 < l_block1; i1++) {
|
||||||
ctx[\`arr\`] = v_block1[i1];
|
ctx[\`arr\`] = k_block1[i1];
|
||||||
ctx[\`arr_index\`] = i1;
|
ctx[\`arr_index\`] = i1;
|
||||||
const key1 = ctx['arr_index'];
|
const key1 = ctx['arr_index'];
|
||||||
let b3;
|
let b3;
|
||||||
|
|||||||
@@ -12,6 +12,18 @@ exports[`basics display a nice error if a component is not a component 1`] = `
|
|||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`basics display a nice error if a non-root component template fails to compile 1`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
const comp1 = app.createComponent(\`Child\`, true, false, false, []);
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
return comp1({}, key + \`__1\`, node, this, null);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`basics display a nice error if it cannot find component (in dev mode) 1`] = `
|
exports[`basics display a nice error if it cannot find component (in dev mode) 1`] = `
|
||||||
"function anonymous(app, bdom, helpers
|
"function anonymous(app, bdom, helpers
|
||||||
) {
|
) {
|
||||||
@@ -229,7 +241,7 @@ exports[`can catch errors an error in onWillDestroy, variation 1`] = `
|
|||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`can catch errors an error in onWillDestroy, variation 2`] = `
|
exports[`can catch errors an error in onWillDestroy, variation 3`] = `
|
||||||
"function anonymous(app, bdom, helpers
|
"function anonymous(app, bdom, helpers
|
||||||
) {
|
) {
|
||||||
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
@@ -938,7 +950,7 @@ exports[`can catch errors catching error, rethrow, render parent -- a main comp
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block1, v_block1, l_block1, c_block1] = prepareList(Object.values(ctx['state'].cps));;
|
const [k_block1, v_block1, l_block1, c_block1] = prepareList(Object.values(ctx['state'].cps));;
|
||||||
for (let i1 = 0; i1 < l_block1; i1++) {
|
for (let i1 = 0; i1 < l_block1; i1++) {
|
||||||
ctx[\`cp\`] = v_block1[i1];
|
ctx[\`cp\`] = k_block1[i1];
|
||||||
const key1 = ctx['cp'].id;
|
const key1 = ctx['cp'].id;
|
||||||
const v1 = ctx['this'];
|
const v1 = ctx['this'];
|
||||||
const v2 = ctx['cp'];
|
const v2 = ctx['cp'];
|
||||||
@@ -1017,7 +1029,7 @@ exports[`can catch errors catching in child makes parent render 1`] = `
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block1, v_block1, l_block1, c_block1] = prepareList(Object.entries(ctx['this'].elements));;
|
const [k_block1, v_block1, l_block1, c_block1] = prepareList(Object.entries(ctx['this'].elements));;
|
||||||
for (let i1 = 0; i1 < l_block1; i1++) {
|
for (let i1 = 0; i1 < l_block1; i1++) {
|
||||||
ctx[\`elem\`] = v_block1[i1];
|
ctx[\`elem\`] = k_block1[i1];
|
||||||
const key1 = ctx['elem'][0];
|
const key1 = ctx['elem'][0];
|
||||||
const v1 = ctx['this'];
|
const v1 = ctx['this'];
|
||||||
const v2 = ctx['elem'];
|
const v2 = ctx['elem'];
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ exports[`event handling objects from scope are properly captured by t-on 1`] = `
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['items']);;
|
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['items']);;
|
||||||
for (let i1 = 0; i1 < l_block2; i1++) {
|
for (let i1 = 0; i1 < l_block2; i1++) {
|
||||||
ctx[\`item\`] = v_block2[i1];
|
ctx[\`item\`] = k_block2[i1];
|
||||||
const key1 = ctx['item'];
|
const key1 = ctx['item'];
|
||||||
const v1 = ctx['onClick'];
|
const v1 = ctx['onClick'];
|
||||||
const v2 = ctx['item'];
|
const v2 = ctx['item'];
|
||||||
@@ -158,7 +158,7 @@ exports[`event handling t-on with handler bound to dynamic argument on a t-forea
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['items']);;
|
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['items']);;
|
||||||
for (let i1 = 0; i1 < l_block2; i1++) {
|
for (let i1 = 0; i1 < l_block2; i1++) {
|
||||||
ctx[\`item\`] = v_block2[i1];
|
ctx[\`item\`] = k_block2[i1];
|
||||||
const key1 = ctx['item'];
|
const key1 = ctx['item'];
|
||||||
const v1 = ctx['onClick'];
|
const v1 = ctx['onClick'];
|
||||||
const v2 = ctx['item'];
|
const v2 = ctx['item'];
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ exports[`lifecycle hooks component semantics 5`] = `
|
|||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`lifecycle hooks component semantics 6`] = `
|
exports[`lifecycle hooks component semantics 7`] = `
|
||||||
"function anonymous(app, bdom, helpers
|
"function anonymous(app, bdom, helpers
|
||||||
) {
|
) {
|
||||||
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
@@ -185,7 +185,7 @@ exports[`lifecycle hooks destroy new children before being mountged 1`] = `
|
|||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`lifecycle hooks destroy new children before being mountged 2`] = `
|
exports[`lifecycle hooks destroy new children before being mountged 3`] = `
|
||||||
"function anonymous(app, bdom, helpers
|
"function anonymous(app, bdom, helpers
|
||||||
) {
|
) {
|
||||||
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
@@ -291,7 +291,7 @@ exports[`lifecycle hooks lifecycle semantics, part 2 1`] = `
|
|||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`lifecycle hooks lifecycle semantics, part 2 2`] = `
|
exports[`lifecycle hooks lifecycle semantics, part 2 3`] = `
|
||||||
"function anonymous(app, bdom, helpers
|
"function anonymous(app, bdom, helpers
|
||||||
) {
|
) {
|
||||||
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
@@ -303,7 +303,7 @@ exports[`lifecycle hooks lifecycle semantics, part 2 2`] = `
|
|||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`lifecycle hooks lifecycle semantics, part 2 3`] = `
|
exports[`lifecycle hooks lifecycle semantics, part 2 4`] = `
|
||||||
"function anonymous(app, bdom, helpers
|
"function anonymous(app, bdom, helpers
|
||||||
) {
|
) {
|
||||||
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
@@ -348,7 +348,7 @@ exports[`lifecycle hooks lifecycle semantics, part 4 1`] = `
|
|||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`lifecycle hooks lifecycle semantics, part 4 2`] = `
|
exports[`lifecycle hooks lifecycle semantics, part 4 3`] = `
|
||||||
"function anonymous(app, bdom, helpers
|
"function anonymous(app, bdom, helpers
|
||||||
) {
|
) {
|
||||||
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
@@ -360,7 +360,7 @@ exports[`lifecycle hooks lifecycle semantics, part 4 2`] = `
|
|||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`lifecycle hooks lifecycle semantics, part 4 3`] = `
|
exports[`lifecycle hooks lifecycle semantics, part 4 4`] = `
|
||||||
"function anonymous(app, bdom, helpers
|
"function anonymous(app, bdom, helpers
|
||||||
) {
|
) {
|
||||||
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ exports[`.alike suffix in a list 1`] = `
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block1, v_block1, l_block1, c_block1] = prepareList(ctx['state'].elems);;
|
const [k_block1, v_block1, l_block1, c_block1] = prepareList(ctx['state'].elems);;
|
||||||
for (let i1 = 0; i1 < l_block1; i1++) {
|
for (let i1 = 0; i1 < l_block1; i1++) {
|
||||||
ctx[\`elem\`] = v_block1[i1];
|
ctx[\`elem\`] = k_block1[i1];
|
||||||
const key1 = ctx['elem'].id;
|
const key1 = ctx['elem'].id;
|
||||||
const v1 = ctx['this'];
|
const v1 = ctx['this'];
|
||||||
const v2 = ctx['elem'];
|
const v2 = ctx['elem'];
|
||||||
@@ -106,7 +106,7 @@ exports[`basics arrow functions as prop correctly capture their scope 1`] = `
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block1, v_block1, l_block1, c_block1] = prepareList(ctx['items']);;
|
const [k_block1, v_block1, l_block1, c_block1] = prepareList(ctx['items']);;
|
||||||
for (let i1 = 0; i1 < l_block1; i1++) {
|
for (let i1 = 0; i1 < l_block1; i1++) {
|
||||||
ctx[\`item\`] = v_block1[i1];
|
ctx[\`item\`] = k_block1[i1];
|
||||||
const key1 = ctx['item'].val;
|
const key1 = ctx['item'].val;
|
||||||
const v1 = ctx['onClick'];
|
const v1 = ctx['onClick'];
|
||||||
const v2 = ctx['item'];
|
const v2 = ctx['item'];
|
||||||
|
|||||||
@@ -1066,6 +1066,45 @@ exports[`slots multiple slots containing components 3`] = `
|
|||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`slots named slot inside named slot in t-component 1`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
let { capture, markRaw } = helpers;
|
||||||
|
const comp1 = app.createComponent(null, false, true, false, []);
|
||||||
|
const comp2 = app.createComponent(\`Child\`, true, true, false, []);
|
||||||
|
|
||||||
|
function slot1(ctx, node, key = \\"\\") {
|
||||||
|
const b2 = text(\` outer \`);
|
||||||
|
const ctx2 = capture(ctx);
|
||||||
|
const Comp1 = ctx['Child'];
|
||||||
|
const b4 = toggler(Comp1, comp1({slots: markRaw({'brol': {__render: slot2.bind(this), __ctx: ctx2}})}, (Comp1).name + key + \`__1\`, node, this, Comp1));
|
||||||
|
return multi([b2, b4]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function slot2(ctx, node, key = \\"\\") {
|
||||||
|
return text(ctx['value']);
|
||||||
|
}
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
const ctx1 = capture(ctx);
|
||||||
|
return comp2({slots: markRaw({'brol': {__render: slot1.bind(this), __ctx: ctx1}})}, key + \`__2\`, node, this, null);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`slots named slot inside named slot in t-component 2`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
let { callSlot } = helpers;
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
return callSlot(ctx, node, key, 'brol', false, {});
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`slots named slot inside slot 1`] = `
|
exports[`slots named slot inside slot 1`] = `
|
||||||
"function anonymous(app, bdom, helpers
|
"function anonymous(app, bdom, helpers
|
||||||
) {
|
) {
|
||||||
@@ -2140,7 +2179,7 @@ exports[`slots slot in t-foreach locations 2`] = `
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block1, v_block1, l_block1, c_block1] = prepareList(ctx['props'].list);;
|
const [k_block1, v_block1, l_block1, c_block1] = prepareList(ctx['props'].list);;
|
||||||
for (let i1 = 0; i1 < l_block1; i1++) {
|
for (let i1 = 0; i1 < l_block1; i1++) {
|
||||||
ctx[\`elem\`] = v_block1[i1];
|
ctx[\`elem\`] = k_block1[i1];
|
||||||
ctx[\`elem_index\`] = i1;
|
ctx[\`elem_index\`] = i1;
|
||||||
const key1 = ctx['elem_index'];
|
const key1 = ctx['elem_index'];
|
||||||
let txt1 = ctx['elem'];
|
let txt1 = ctx['elem'];
|
||||||
@@ -2430,7 +2469,7 @@ exports[`slots slots are rendered with proper context, part 2 1`] = `
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['state'].users);;
|
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['state'].users);;
|
||||||
for (let i1 = 0; i1 < l_block2; i1++) {
|
for (let i1 = 0; i1 < l_block2; i1++) {
|
||||||
ctx[\`user\`] = v_block2[i1];
|
ctx[\`user\`] = k_block2[i1];
|
||||||
const key1 = ctx['user'].id;
|
const key1 = ctx['user'].id;
|
||||||
const ctx1 = capture(ctx);
|
const ctx1 = capture(ctx);
|
||||||
const b7 = comp1({to: '/user/'+ctx['user'].id,slots: markRaw({'default': {__render: slot1.bind(this), __ctx: ctx1}})}, key + \`__1__\${key1}\`, node, this, null);
|
const b7 = comp1({to: '/user/'+ctx['user'].id,slots: markRaw({'default': {__render: slot1.bind(this), __ctx: ctx1}})}, key + \`__1__\${key1}\`, node, this, null);
|
||||||
@@ -2478,7 +2517,7 @@ exports[`slots slots are rendered with proper context, part 3 1`] = `
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['state'].users);;
|
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['state'].users);;
|
||||||
for (let i1 = 0; i1 < l_block2; i1++) {
|
for (let i1 = 0; i1 < l_block2; i1++) {
|
||||||
ctx[\`user\`] = v_block2[i1];
|
ctx[\`user\`] = k_block2[i1];
|
||||||
const key1 = ctx['user'].id;
|
const key1 = ctx['user'].id;
|
||||||
setContextValue(ctx, \\"userdescr\\", 'User '+ctx['user'].name);
|
setContextValue(ctx, \\"userdescr\\", 'User '+ctx['user'].name);
|
||||||
const ctx1 = capture(ctx);
|
const ctx1 = capture(ctx);
|
||||||
@@ -2625,7 +2664,7 @@ exports[`slots slots in t-foreach and re-rendering 1`] = `
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block2, v_block2, l_block2, c_block2] = prepareList(Array(2));;
|
const [k_block2, v_block2, l_block2, c_block2] = prepareList(Array(2));;
|
||||||
for (let i1 = 0; i1 < l_block2; i1++) {
|
for (let i1 = 0; i1 < l_block2; i1++) {
|
||||||
ctx[\`n\`] = v_block2[i1];
|
ctx[\`n\`] = k_block2[i1];
|
||||||
ctx[\`n_index\`] = i1;
|
ctx[\`n_index\`] = i1;
|
||||||
const key1 = ctx['n_index'];
|
const key1 = ctx['n_index'];
|
||||||
const ctx1 = capture(ctx);
|
const ctx1 = capture(ctx);
|
||||||
@@ -2674,14 +2713,14 @@ exports[`slots slots in t-foreach in t-foreach 1`] = `
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['tree']);;
|
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['tree']);;
|
||||||
for (let i1 = 0; i1 < l_block2; i1++) {
|
for (let i1 = 0; i1 < l_block2; i1++) {
|
||||||
ctx[\`node1\`] = v_block2[i1];
|
ctx[\`node1\`] = k_block2[i1];
|
||||||
const key1 = ctx['node1'].key;
|
const key1 = ctx['node1'].key;
|
||||||
let txt1 = ctx['node1'].value;
|
let txt1 = ctx['node1'].value;
|
||||||
const b4 = block4([txt1]);
|
const b4 = block4([txt1]);
|
||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block6, v_block6, l_block6, c_block6] = prepareList(ctx['node1'].nodes);;
|
const [k_block6, v_block6, l_block6, c_block6] = prepareList(ctx['node1'].nodes);;
|
||||||
for (let i2 = 0; i2 < l_block6; i2++) {
|
for (let i2 = 0; i2 < l_block6; i2++) {
|
||||||
ctx[\`node2\`] = v_block6[i2];
|
ctx[\`node2\`] = k_block6[i2];
|
||||||
const key2 = ctx['node2'].key;
|
const key2 = ctx['node2'].key;
|
||||||
const ctx1 = capture(ctx);
|
const ctx1 = capture(ctx);
|
||||||
c_block6[i2] = withKey(comp1({slots: markRaw({'default': {__render: slot1.bind(this), __ctx: ctx1}})}, key + \`__1__\${key1}__\${key2}\`, node, this, null), key2);
|
c_block6[i2] = withKey(comp1({slots: markRaw({'default': {__render: slot1.bind(this), __ctx: ctx1}})}, key + \`__1__\${key1}__\${key2}\`, node, this, null), key2);
|
||||||
@@ -2731,7 +2770,7 @@ exports[`slots slots in t-foreach with t-set and re-rendering 1`] = `
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block2, v_block2, l_block2, c_block2] = prepareList(Array(2));;
|
const [k_block2, v_block2, l_block2, c_block2] = prepareList(Array(2));;
|
||||||
for (let i1 = 0; i1 < l_block2; i1++) {
|
for (let i1 = 0; i1 < l_block2; i1++) {
|
||||||
ctx[\`n\`] = v_block2[i1];
|
ctx[\`n\`] = k_block2[i1];
|
||||||
ctx[\`n_index\`] = i1;
|
ctx[\`n_index\`] = i1;
|
||||||
const key1 = ctx['n_index'];
|
const key1 = ctx['n_index'];
|
||||||
setContextValue(ctx, \\"dummy\\", ctx['n_index']);
|
setContextValue(ctx, \\"dummy\\", ctx['n_index']);
|
||||||
@@ -2881,11 +2920,11 @@ exports[`slots t-slot in recursive templates 1`] = `
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block3, v_block3, l_block3, c_block3] = prepareList(ctx['items']);;
|
const [k_block3, v_block3, l_block3, c_block3] = prepareList(ctx['items']);;
|
||||||
for (let i1 = 0; i1 < l_block3; i1++) {
|
for (let i1 = 0; i1 < l_block3; i1++) {
|
||||||
ctx[\`item\`] = v_block3[i1];
|
ctx[\`item\`] = k_block3[i1];
|
||||||
ctx[\`item_first\`] = i1 === 0;
|
ctx[\`item_first\`] = i1 === 0;
|
||||||
ctx[\`item_last\`] = i1 === v_block3.length - 1;
|
ctx[\`item_last\`] = i1 === k_block3.length - 1;
|
||||||
ctx[\`item_index\`] = i1;
|
ctx[\`item_index\`] = i1;
|
||||||
ctx[\`item_value\`] = k_block3[i1];
|
ctx[\`item_value\`] = v_block3[i1];
|
||||||
const key1 = ctx['item'].name;
|
const key1 = ctx['item'].name;
|
||||||
let b5, b6;
|
let b5, b6;
|
||||||
if (!ctx['item'].children.length) {
|
if (!ctx['item'].children.length) {
|
||||||
|
|||||||
@@ -10,8 +10,8 @@ exports[`t-call dynamic t-call 1`] = `
|
|||||||
return function template(ctx, node, key = \\"\\") {
|
return function template(ctx, node, key = \\"\\") {
|
||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
ctx[isBoundary] = 1;
|
ctx[isBoundary] = 1;
|
||||||
const b1 = text(\` owl \`);
|
const b2 = text(\` owl \`);
|
||||||
ctx[zero] = b1;
|
ctx[zero] = b2;
|
||||||
const template1 = (ctx['current'].template);
|
const template1 = (ctx['current'].template);
|
||||||
return call(this, template1, ctx, node, key + \`__1\`);
|
return call(this, template1, ctx, node, key + \`__1\`);
|
||||||
}
|
}
|
||||||
@@ -42,6 +42,56 @@ exports[`t-call dynamic t-call 3`] = `
|
|||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`t-call dynamic t-call with same sub component 1`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
const call = app.callTemplate.bind(app);
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
const b2 = text(ctx['current'].template);
|
||||||
|
const template1 = (ctx['current'].template);
|
||||||
|
const b3 = call(this, template1, ctx, node, key + \`__1\`);
|
||||||
|
return multi([b2, b3]);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`t-call dynamic t-call with same sub component 2`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
const comp1 = app.createComponent(\`Child\`, true, false, false, []);
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
return comp1({}, key + \`__1\`, node, this, null);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`t-call dynamic t-call with same sub component 3`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
return text(\`child\`);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`t-call dynamic t-call with same sub component 4`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
const comp1 = app.createComponent(\`Child\`, true, false, false, []);
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
return comp1({}, key + \`__1\`, node, this, null);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`t-call dynamic t-call: key is propagated 1`] = `
|
exports[`t-call dynamic t-call: key is propagated 1`] = `
|
||||||
"function anonymous(app, bdom, helpers
|
"function anonymous(app, bdom, helpers
|
||||||
) {
|
) {
|
||||||
@@ -365,11 +415,11 @@ exports[`t-call t-call in t-foreach and children component 1`] = `
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block2, v_block2, l_block2, c_block2] = prepareList(['a','b','c']);;
|
const [k_block2, v_block2, l_block2, c_block2] = prepareList(['a','b','c']);;
|
||||||
for (let i1 = 0; i1 < l_block2; i1++) {
|
for (let i1 = 0; i1 < l_block2; i1++) {
|
||||||
ctx[\`val\`] = v_block2[i1];
|
ctx[\`val\`] = k_block2[i1];
|
||||||
ctx[\`val_first\`] = i1 === 0;
|
ctx[\`val_first\`] = i1 === 0;
|
||||||
ctx[\`val_last\`] = i1 === v_block2.length - 1;
|
ctx[\`val_last\`] = i1 === k_block2.length - 1;
|
||||||
ctx[\`val_index\`] = i1;
|
ctx[\`val_index\`] = i1;
|
||||||
ctx[\`val_value\`] = k_block2[i1];
|
ctx[\`val_value\`] = v_block2[i1];
|
||||||
const key1 = ctx['val'];
|
const key1 = ctx['val'];
|
||||||
c_block2[i1] = withKey(callTemplate_1.call(this, ctx, node, key + \`__1__\${key1}\`), key1);
|
c_block2[i1] = withKey(callTemplate_1.call(this, ctx, node, key + \`__1__\${key1}\`), key1);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -180,7 +180,7 @@ exports[`t-component switching dynamic component 2`] = `
|
|||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`t-component switching dynamic component 3`] = `
|
exports[`t-component switching dynamic component 4`] = `
|
||||||
"function anonymous(app, bdom, helpers
|
"function anonymous(app, bdom, helpers
|
||||||
) {
|
) {
|
||||||
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ exports[`list of components components in a node in a t-foreach 1`] = `
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['items']);;
|
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['items']);;
|
||||||
for (let i1 = 0; i1 < l_block2; i1++) {
|
for (let i1 = 0; i1 < l_block2; i1++) {
|
||||||
ctx[\`item\`] = v_block2[i1];
|
ctx[\`item\`] = k_block2[i1];
|
||||||
const key1 = 'li_'+ctx['item'];
|
const key1 = 'li_'+ctx['item'];
|
||||||
const b4 = comp1({item: ctx['item']}, key + \`__1__\${key1}\`, node, this, null);
|
const b4 = comp1({item: ctx['item']}, key + \`__1__\${key1}\`, node, this, null);
|
||||||
c_block2[i1] = withKey(block3([], [b4]), key1);
|
c_block2[i1] = withKey(block3([], [b4]), key1);
|
||||||
@@ -51,7 +51,7 @@ exports[`list of components crash on duplicate key in dev mode 1`] = `
|
|||||||
const [k_block1, v_block1, l_block1, c_block1] = prepareList([1,2]);;
|
const [k_block1, v_block1, l_block1, c_block1] = prepareList([1,2]);;
|
||||||
const keys1 = new Set();
|
const keys1 = new Set();
|
||||||
for (let i1 = 0; i1 < l_block1; i1++) {
|
for (let i1 = 0; i1 < l_block1; i1++) {
|
||||||
ctx[\`item\`] = v_block1[i1];
|
ctx[\`item\`] = k_block1[i1];
|
||||||
const key1 = 'child';
|
const key1 = 'child';
|
||||||
if (keys1.has(String(key1))) { throw new OwlError(\`Got duplicate key in t-foreach: \${key1}\`)}
|
if (keys1.has(String(key1))) { throw new OwlError(\`Got duplicate key in t-foreach: \${key1}\`)}
|
||||||
keys1.add(String(key1));
|
keys1.add(String(key1));
|
||||||
@@ -87,7 +87,7 @@ exports[`list of components crash when using object as keys that serialize to th
|
|||||||
const [k_block1, v_block1, l_block1, c_block1] = prepareList([{},{}]);;
|
const [k_block1, v_block1, l_block1, c_block1] = prepareList([{},{}]);;
|
||||||
const keys1 = new Set();
|
const keys1 = new Set();
|
||||||
for (let i1 = 0; i1 < l_block1; i1++) {
|
for (let i1 = 0; i1 < l_block1; i1++) {
|
||||||
ctx[\`item\`] = v_block1[i1];
|
ctx[\`item\`] = k_block1[i1];
|
||||||
const key1 = ctx['item'];
|
const key1 = ctx['item'];
|
||||||
if (keys1.has(String(key1))) { throw new OwlError(\`Got duplicate key in t-foreach: \${key1}\`)}
|
if (keys1.has(String(key1))) { throw new OwlError(\`Got duplicate key in t-foreach: \${key1}\`)}
|
||||||
keys1.add(String(key1));
|
keys1.add(String(key1));
|
||||||
@@ -125,7 +125,7 @@ exports[`list of components list of sub components inside other nodes 1`] = `
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['state'].blips);;
|
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['state'].blips);;
|
||||||
for (let i1 = 0; i1 < l_block2; i1++) {
|
for (let i1 = 0; i1 < l_block2; i1++) {
|
||||||
ctx[\`blip\`] = v_block2[i1];
|
ctx[\`blip\`] = k_block2[i1];
|
||||||
const key1 = ctx['blip'].id;
|
const key1 = ctx['blip'].id;
|
||||||
const b4 = comp1({}, key + \`__1__\${key1}\`, node, this, null);
|
const b4 = comp1({}, key + \`__1__\${key1}\`, node, this, null);
|
||||||
c_block2[i1] = withKey(block3([], [b4]), key1);
|
c_block2[i1] = withKey(block3([], [b4]), key1);
|
||||||
@@ -191,7 +191,7 @@ exports[`list of components order is correct when slots are not of same type 2`]
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block1, v_block1, l_block1, c_block1] = prepareList(ctx['slotNames']);;
|
const [k_block1, v_block1, l_block1, c_block1] = prepareList(ctx['slotNames']);;
|
||||||
for (let i1 = 0; i1 < l_block1; i1++) {
|
for (let i1 = 0; i1 < l_block1; i1++) {
|
||||||
ctx[\`slotName\`] = v_block1[i1];
|
ctx[\`slotName\`] = k_block1[i1];
|
||||||
const key1 = ctx['slotName'];
|
const key1 = ctx['slotName'];
|
||||||
const slot1 = (ctx['slotName']);
|
const slot1 = (ctx['slotName']);
|
||||||
c_block1[i1] = withKey(toggler(slot1, callSlot(ctx, node, key1 + \`__1__\${key1}\`, slot1, true, {})), key1);
|
c_block1[i1] = withKey(toggler(slot1, callSlot(ctx, node, key1 + \`__1__\${key1}\`, slot1, true, {})), key1);
|
||||||
@@ -214,13 +214,13 @@ exports[`list of components reconciliation alg works for t-foreach in t-foreach
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['state'].s);;
|
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['state'].s);;
|
||||||
for (let i1 = 0; i1 < l_block2; i1++) {
|
for (let i1 = 0; i1 < l_block2; i1++) {
|
||||||
ctx[\`section\`] = v_block2[i1];
|
ctx[\`section\`] = k_block2[i1];
|
||||||
ctx[\`section_index\`] = i1;
|
ctx[\`section_index\`] = i1;
|
||||||
const key1 = ctx['section_index'];
|
const key1 = ctx['section_index'];
|
||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block3, v_block3, l_block3, c_block3] = prepareList(ctx['section'].blips);;
|
const [k_block3, v_block3, l_block3, c_block3] = prepareList(ctx['section'].blips);;
|
||||||
for (let i2 = 0; i2 < l_block3; i2++) {
|
for (let i2 = 0; i2 < l_block3; i2++) {
|
||||||
ctx[\`blip\`] = v_block3[i2];
|
ctx[\`blip\`] = k_block3[i2];
|
||||||
ctx[\`blip_index\`] = i2;
|
ctx[\`blip_index\`] = i2;
|
||||||
const key2 = ctx['blip_index'];
|
const key2 = ctx['blip_index'];
|
||||||
c_block3[i2] = withKey(comp1({blip: ctx['blip']}, key + \`__1__\${key1}__\${key2}\`, node, this, null), key2);
|
c_block3[i2] = withKey(comp1({blip: ctx['blip']}, key + \`__1__\${key1}__\${key2}\`, node, this, null), key2);
|
||||||
@@ -263,12 +263,12 @@ exports[`list of components reconciliation alg works for t-foreach in t-foreach,
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['state'].rows);;
|
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['state'].rows);;
|
||||||
for (let i1 = 0; i1 < l_block2; i1++) {
|
for (let i1 = 0; i1 < l_block2; i1++) {
|
||||||
ctx[\`row\`] = v_block2[i1];
|
ctx[\`row\`] = k_block2[i1];
|
||||||
const key1 = ctx['row'];
|
const key1 = ctx['row'];
|
||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block4, v_block4, l_block4, c_block4] = prepareList(ctx['state'].cols);;
|
const [k_block4, v_block4, l_block4, c_block4] = prepareList(ctx['state'].cols);;
|
||||||
for (let i2 = 0; i2 < l_block4; i2++) {
|
for (let i2 = 0; i2 < l_block4; i2++) {
|
||||||
ctx[\`col\`] = v_block4[i2];
|
ctx[\`col\`] = k_block4[i2];
|
||||||
const key2 = ctx['col'];
|
const key2 = ctx['col'];
|
||||||
const b6 = comp1({row: ctx['row'],col: ctx['col']}, key + \`__1__\${key1}__\${key2}\`, node, this, null);
|
const b6 = comp1({row: ctx['row'],col: ctx['col']}, key + \`__1__\${key1}__\${key2}\`, node, this, null);
|
||||||
c_block4[i2] = withKey(block5([], [b6]), key2);
|
c_block4[i2] = withKey(block5([], [b6]), key2);
|
||||||
@@ -308,7 +308,7 @@ exports[`list of components simple list 1`] = `
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block1, v_block1, l_block1, c_block1] = prepareList(ctx['state'].elems);;
|
const [k_block1, v_block1, l_block1, c_block1] = prepareList(ctx['state'].elems);;
|
||||||
for (let i1 = 0; i1 < l_block1; i1++) {
|
for (let i1 = 0; i1 < l_block1; i1++) {
|
||||||
ctx[\`elem\`] = v_block1[i1];
|
ctx[\`elem\`] = k_block1[i1];
|
||||||
const key1 = ctx['elem'].id;
|
const key1 = ctx['elem'].id;
|
||||||
c_block1[i1] = withKey(comp1({value: ctx['elem'].value}, key + \`__1__\${key1}\`, node, this, null), key1);
|
c_block1[i1] = withKey(comp1({value: ctx['elem'].value}, key + \`__1__\${key1}\`, node, this, null), key1);
|
||||||
}
|
}
|
||||||
@@ -344,7 +344,7 @@ exports[`list of components sub components rendered in a loop 1`] = `
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['state'].numbers);;
|
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['state'].numbers);;
|
||||||
for (let i1 = 0; i1 < l_block2; i1++) {
|
for (let i1 = 0; i1 < l_block2; i1++) {
|
||||||
ctx[\`number\`] = v_block2[i1];
|
ctx[\`number\`] = k_block2[i1];
|
||||||
const key1 = ctx['number'];
|
const key1 = ctx['number'];
|
||||||
c_block2[i1] = withKey(comp1({n: ctx['number']}, key + \`__1__\${key1}\`, node, this, null), key1);
|
c_block2[i1] = withKey(comp1({n: ctx['number']}, key + \`__1__\${key1}\`, node, this, null), key1);
|
||||||
}
|
}
|
||||||
@@ -381,7 +381,7 @@ exports[`list of components sub components with some state rendered in a loop 1`
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['state'].numbers);;
|
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['state'].numbers);;
|
||||||
for (let i1 = 0; i1 < l_block2; i1++) {
|
for (let i1 = 0; i1 < l_block2; i1++) {
|
||||||
ctx[\`number\`] = v_block2[i1];
|
ctx[\`number\`] = k_block2[i1];
|
||||||
const key1 = ctx['number'];
|
const key1 = ctx['number'];
|
||||||
c_block2[i1] = withKey(comp1({}, key + \`__1__\${key1}\`, node, this, null), key1);
|
c_block2[i1] = withKey(comp1({}, key + \`__1__\${key1}\`, node, this, null), key1);
|
||||||
}
|
}
|
||||||
@@ -418,7 +418,7 @@ exports[`list of components switch component position 1`] = `
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['clist']);;
|
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['clist']);;
|
||||||
for (let i1 = 0; i1 < l_block2; i1++) {
|
for (let i1 = 0; i1 < l_block2; i1++) {
|
||||||
ctx[\`c\`] = v_block2[i1];
|
ctx[\`c\`] = k_block2[i1];
|
||||||
const key1 = ctx['c'];
|
const key1 = ctx['c'];
|
||||||
c_block2[i1] = withKey(comp1({key: ctx['c']}, key + \`__1__\${key1}\`, node, this, null), key1);
|
c_block2[i1] = withKey(comp1({key: ctx['c']}, key + \`__1__\${key1}\`, node, this, null), key1);
|
||||||
}
|
}
|
||||||
@@ -455,7 +455,7 @@ exports[`list of components t-foreach with t-component, and update 1`] = `
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block2, v_block2, l_block2, c_block2] = prepareList(Array(2));;
|
const [k_block2, v_block2, l_block2, c_block2] = prepareList(Array(2));;
|
||||||
for (let i1 = 0; i1 < l_block2; i1++) {
|
for (let i1 = 0; i1 < l_block2; i1++) {
|
||||||
ctx[\`n\`] = v_block2[i1];
|
ctx[\`n\`] = k_block2[i1];
|
||||||
ctx[\`n_index\`] = i1;
|
ctx[\`n_index\`] = i1;
|
||||||
const key1 = ctx['n_index'];
|
const key1 = ctx['n_index'];
|
||||||
c_block2[i1] = withKey(comp1({val: ctx['n_index']}, key + \`__1__\${key1}\`, node, this, null), key1);
|
c_block2[i1] = withKey(comp1({val: ctx['n_index']}, key + \`__1__\${key1}\`, node, this, null), key1);
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ exports[`t-key t-foreach with t-key switch component position 1`] = `
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['clist']);;
|
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['clist']);;
|
||||||
for (let i1 = 0; i1 < l_block2; i1++) {
|
for (let i1 = 0; i1 < l_block2; i1++) {
|
||||||
ctx[\`c\`] = v_block2[i1];
|
ctx[\`c\`] = k_block2[i1];
|
||||||
const key1 = ctx['c'];
|
const key1 = ctx['c'];
|
||||||
const tKey_1 = ctx['key1'];
|
const tKey_1 = ctx['key1'];
|
||||||
c_block2[i1] = withKey(comp1({key: ctx['c']+ctx['key1']}, tKey_1 + key + \`__1__\${key1}\`, node, this, null), tKey_1 + key1);
|
c_block2[i1] = withKey(comp1({key: ctx['c']+ctx['key1']}, tKey_1 + key + \`__1__\${key1}\`, node, this, null), tKey_1 + key1);
|
||||||
|
|||||||
@@ -196,7 +196,7 @@ exports[`t-model directive in a t-foreach 1`] = `
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['state']);;
|
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['state']);;
|
||||||
for (let i1 = 0; i1 < l_block2; i1++) {
|
for (let i1 = 0; i1 < l_block2; i1++) {
|
||||||
ctx[\`thing\`] = v_block2[i1];
|
ctx[\`thing\`] = k_block2[i1];
|
||||||
const key1 = ctx['thing'].id;
|
const key1 = ctx['thing'].id;
|
||||||
const bExpr1 = ctx['thing'];
|
const bExpr1 = ctx['thing'];
|
||||||
const expr1 = 'f';
|
const expr1 = 'f';
|
||||||
@@ -223,7 +223,7 @@ exports[`t-model directive in a t-foreach, part 2 1`] = `
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['state']);;
|
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['state']);;
|
||||||
for (let i1 = 0; i1 < l_block2; i1++) {
|
for (let i1 = 0; i1 < l_block2; i1++) {
|
||||||
ctx[\`thing\`] = v_block2[i1];
|
ctx[\`thing\`] = k_block2[i1];
|
||||||
ctx[\`thing_index\`] = i1;
|
ctx[\`thing_index\`] = i1;
|
||||||
const key1 = ctx['thing_index'];
|
const key1 = ctx['thing_index'];
|
||||||
const bExpr1 = ctx['state'];
|
const bExpr1 = ctx['state'];
|
||||||
@@ -251,7 +251,7 @@ exports[`t-model directive in a t-foreach, part 3 1`] = `
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['names']);;
|
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['names']);;
|
||||||
for (let i1 = 0; i1 < l_block2; i1++) {
|
for (let i1 = 0; i1 < l_block2; i1++) {
|
||||||
ctx[\`name\`] = v_block2[i1];
|
ctx[\`name\`] = k_block2[i1];
|
||||||
ctx[\`name_index\`] = i1;
|
ctx[\`name_index\`] = i1;
|
||||||
const key1 = ctx['name_index'];
|
const key1 = ctx['name_index'];
|
||||||
const bExpr1 = ctx['state'].values;
|
const bExpr1 = ctx['state'].values;
|
||||||
@@ -468,6 +468,36 @@ exports[`t-model directive t-model on select with static options 1`] = `
|
|||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`t-model directive t-model with dynamic number values on select options in foreach 1`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
let { toNumber, prepareList, withKey } = helpers;
|
||||||
|
|
||||||
|
let block1 = createBlock(\`<select block-handler-0=\\"change\\"><block-child-0/></select>\`);
|
||||||
|
let block3 = createBlock(\`<option block-attribute-0=\\"value\\" block-attribute-1=\\"selected\\"><block-text-2/></option>\`);
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
const bExpr1 = ctx['state'];
|
||||||
|
const expr1 = 'value';
|
||||||
|
const bValue1 = bExpr1[expr1];
|
||||||
|
let hdlr1 = [(ev) => { bExpr1[expr1] = toNumber(ev.target.value); }];
|
||||||
|
ctx = Object.create(ctx);
|
||||||
|
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['state'].options);;
|
||||||
|
for (let i1 = 0; i1 < l_block2; i1++) {
|
||||||
|
ctx[\`o\`] = k_block2[i1];
|
||||||
|
const key1 = ctx['o'].value;
|
||||||
|
let attr1 = ctx['o'].value;
|
||||||
|
let attr2 = bValue1 === ctx['o'].value;
|
||||||
|
let txt1 = ctx['o'].value;
|
||||||
|
c_block2[i1] = withKey(block3([attr1, attr2, txt1]), key1);
|
||||||
|
}
|
||||||
|
const b2 = list(c_block2);
|
||||||
|
return block1([hdlr1], [b2]);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`t-model directive t-model with dynamic values on select options -- 2 1`] = `
|
exports[`t-model directive t-model with dynamic values on select options -- 2 1`] = `
|
||||||
"function anonymous(app, bdom, helpers
|
"function anonymous(app, bdom, helpers
|
||||||
) {
|
) {
|
||||||
@@ -556,7 +586,7 @@ exports[`t-model directive t-model with dynamic values on select options in fore
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['options']);;
|
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['options']);;
|
||||||
for (let i1 = 0; i1 < l_block2; i1++) {
|
for (let i1 = 0; i1 < l_block2; i1++) {
|
||||||
ctx[\`v\`] = v_block2[i1];
|
ctx[\`v\`] = k_block2[i1];
|
||||||
const key1 = ctx['v'];
|
const key1 = ctx['v'];
|
||||||
let attr1 = ctx['v'];
|
let attr1 = ctx['v'];
|
||||||
let attr2 = bValue1 === ctx['v'];
|
let attr2 = bValue1 === ctx['v'];
|
||||||
@@ -583,7 +613,7 @@ exports[`t-model directive t-model with radio button group in t-foreach 1`] = `
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['options']);;
|
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['options']);;
|
||||||
for (let i1 = 0; i1 < l_block2; i1++) {
|
for (let i1 = 0; i1 < l_block2; i1++) {
|
||||||
ctx[\`opt\`] = v_block2[i1];
|
ctx[\`opt\`] = k_block2[i1];
|
||||||
const key1 = ctx['opt'];
|
const key1 = ctx['opt'];
|
||||||
let prop1 = new String((ctx['opt']) === 0 ? 0 : ((ctx['opt']) || \\"\\"));
|
let prop1 = new String((ctx['opt']) === 0 ? 0 : ((ctx['opt']) || \\"\\"));
|
||||||
let attr1 = ctx['opt'];
|
let attr1 = ctx['opt'];
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ exports[`t-on t-on expression captured in t-foreach 1`] = `
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['arr']);;
|
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['arr']);;
|
||||||
for (let i1 = 0; i1 < l_block2; i1++) {
|
for (let i1 = 0; i1 < l_block2; i1++) {
|
||||||
ctx[\`val\`] = v_block2[i1];
|
ctx[\`val\`] = k_block2[i1];
|
||||||
const key1 = ctx['val'];
|
const key1 = ctx['val'];
|
||||||
const v1 = ctx['otherState'];
|
const v1 = ctx['otherState'];
|
||||||
const v2 = ctx['iter'];
|
const v2 = ctx['iter'];
|
||||||
@@ -43,7 +43,7 @@ exports[`t-on t-on expression in t-foreach 1`] = `
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['state'].values);;
|
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['state'].values);;
|
||||||
for (let i1 = 0; i1 < l_block2; i1++) {
|
for (let i1 = 0; i1 < l_block2; i1++) {
|
||||||
ctx[\`val\`] = v_block2[i1];
|
ctx[\`val\`] = k_block2[i1];
|
||||||
ctx[\`val_index\`] = i1;
|
ctx[\`val_index\`] = i1;
|
||||||
const key1 = ctx['val'];
|
const key1 = ctx['val'];
|
||||||
let txt1 = ctx['val_index'];
|
let txt1 = ctx['val_index'];
|
||||||
@@ -75,7 +75,7 @@ exports[`t-on t-on expression in t-foreach with t-set 1`] = `
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['state'].values);;
|
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['state'].values);;
|
||||||
for (let i1 = 0; i1 < l_block2; i1++) {
|
for (let i1 = 0; i1 < l_block2; i1++) {
|
||||||
ctx[\`val\`] = v_block2[i1];
|
ctx[\`val\`] = k_block2[i1];
|
||||||
ctx[\`val_index\`] = i1;
|
ctx[\`val_index\`] = i1;
|
||||||
const key1 = ctx['val'];
|
const key1 = ctx['val'];
|
||||||
setContextValue(ctx, \\"bossa\\", ctx['bossa']+'_'+ctx['val_index']);
|
setContextValue(ctx, \\"bossa\\", ctx['bossa']+'_'+ctx['val_index']);
|
||||||
@@ -106,7 +106,7 @@ exports[`t-on t-on method call in t-foreach 1`] = `
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['state'].values);;
|
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['state'].values);;
|
||||||
for (let i1 = 0; i1 < l_block2; i1++) {
|
for (let i1 = 0; i1 < l_block2; i1++) {
|
||||||
ctx[\`val\`] = v_block2[i1];
|
ctx[\`val\`] = k_block2[i1];
|
||||||
ctx[\`val_index\`] = i1;
|
ctx[\`val_index\`] = i1;
|
||||||
const key1 = ctx['val'];
|
const key1 = ctx['val'];
|
||||||
let txt1 = ctx['val_index'];
|
let txt1 = ctx['val_index'];
|
||||||
@@ -196,7 +196,7 @@ exports[`t-on t-on on components and t-foreach 1`] = `
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block1, v_block1, l_block1, c_block1] = prepareList(['John','Raoul','Gérald']);;
|
const [k_block1, v_block1, l_block1, c_block1] = prepareList(['John','Raoul','Gérald']);;
|
||||||
for (let i1 = 0; i1 < l_block1; i1++) {
|
for (let i1 = 0; i1 < l_block1; i1++) {
|
||||||
ctx[\`name\`] = v_block1[i1];
|
ctx[\`name\`] = k_block1[i1];
|
||||||
const key1 = ctx['name'];
|
const key1 = ctx['name'];
|
||||||
const v1 = ctx['this'];
|
const v1 = ctx['this'];
|
||||||
const v2 = ctx['name'];
|
const v2 = ctx['name'];
|
||||||
@@ -493,7 +493,7 @@ exports[`t-on t-on when first component child is an empty component 2`] = `
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block1, v_block1, l_block1, c_block1] = prepareList(ctx['props'].list);;
|
const [k_block1, v_block1, l_block1, c_block1] = prepareList(ctx['props'].list);;
|
||||||
for (let i1 = 0; i1 < l_block1; i1++) {
|
for (let i1 = 0; i1 < l_block1; i1++) {
|
||||||
ctx[\`c\`] = v_block1[i1];
|
ctx[\`c\`] = k_block1[i1];
|
||||||
ctx[\`c_index\`] = i1;
|
ctx[\`c_index\`] = i1;
|
||||||
const key1 = ctx['c_index'];
|
const key1 = ctx['c_index'];
|
||||||
let txt1 = ctx['c'];
|
let txt1 = ctx['c'];
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ exports[`components in t-out simple list 1`] = `
|
|||||||
ctx = Object.create(ctx);
|
ctx = Object.create(ctx);
|
||||||
const [k_block1, v_block1, l_block1, c_block1] = prepareList([1,2]);;
|
const [k_block1, v_block1, l_block1, c_block1] = prepareList([1,2]);;
|
||||||
for (let i1 = 0; i1 < l_block1; i1++) {
|
for (let i1 = 0; i1 < l_block1; i1++) {
|
||||||
ctx[\`n\`] = v_block1[i1];
|
ctx[\`n\`] = k_block1[i1];
|
||||||
const key1 = ctx['n'];
|
const key1 = ctx['n'];
|
||||||
ctx[\`blabla\`] = new LazyValue(value1, ctx, this, node, key1);
|
ctx[\`blabla\`] = new LazyValue(value1, ctx, this, node, key1);
|
||||||
c_block1[i1] = withKey(safeOutput(ctx['blabla']), key1);
|
c_block1[i1] = withKey(safeOutput(ctx['blabla']), key1);
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import {
|
|||||||
nextAppError,
|
nextAppError,
|
||||||
nextTick,
|
nextTick,
|
||||||
snapshotEverything,
|
snapshotEverything,
|
||||||
|
steps,
|
||||||
useLogLifecycle,
|
useLogLifecycle,
|
||||||
} from "../helpers";
|
} from "../helpers";
|
||||||
import { markup } from "../../src/runtime/utils";
|
import { markup } from "../../src/runtime/utils";
|
||||||
@@ -868,19 +869,26 @@ describe("basics", () => {
|
|||||||
|
|
||||||
const parent = await mount(Parent, fixture);
|
const parent = await mount(Parent, fixture);
|
||||||
expect(Object.keys(parent.__owl__.children).length).toStrictEqual(1);
|
expect(Object.keys(parent.__owl__.children).length).toStrictEqual(1);
|
||||||
expect([
|
expect(steps.splice(0)).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
"Child:setup",
|
"Child:setup",
|
||||||
"Child:willStart",
|
"Child:willStart",
|
||||||
"Child:willRender",
|
"Child:willRender",
|
||||||
"Child:rendered",
|
"Child:rendered",
|
||||||
"Child:mounted",
|
"Child:mounted",
|
||||||
]).toBeLogged();
|
]
|
||||||
|
`);
|
||||||
|
|
||||||
parent.ifVar = false;
|
parent.ifVar = false;
|
||||||
parent.render();
|
parent.render();
|
||||||
await nextTick();
|
await nextTick();
|
||||||
expect(Object.keys(parent.__owl__.children).length).toStrictEqual(0);
|
expect(Object.keys(parent.__owl__.children).length).toStrictEqual(0);
|
||||||
expect(["Child:willUnmount", "Child:willDestroy"]).toBeLogged();
|
expect(steps.splice(0)).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
|
"Child:willUnmount",
|
||||||
|
"Child:willDestroy",
|
||||||
|
]
|
||||||
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("component children doesn't leak (t-key case)", async () => {
|
test("component children doesn't leak (t-key case)", async () => {
|
||||||
@@ -899,19 +907,22 @@ describe("basics", () => {
|
|||||||
|
|
||||||
const parent = await mount(Parent, fixture);
|
const parent = await mount(Parent, fixture);
|
||||||
expect(Object.keys(parent.__owl__.children).length).toStrictEqual(1);
|
expect(Object.keys(parent.__owl__.children).length).toStrictEqual(1);
|
||||||
expect([
|
expect(steps.splice(0)).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
"Child:setup",
|
"Child:setup",
|
||||||
"Child:willStart",
|
"Child:willStart",
|
||||||
"Child:willRender",
|
"Child:willRender",
|
||||||
"Child:rendered",
|
"Child:rendered",
|
||||||
"Child:mounted",
|
"Child:mounted",
|
||||||
]).toBeLogged();
|
]
|
||||||
|
`);
|
||||||
|
|
||||||
parent.keyVar = 2;
|
parent.keyVar = 2;
|
||||||
parent.render();
|
parent.render();
|
||||||
await nextTick();
|
await nextTick();
|
||||||
expect(Object.keys(parent.__owl__.children).length).toStrictEqual(1);
|
expect(Object.keys(parent.__owl__.children).length).toStrictEqual(1);
|
||||||
expect([
|
expect(steps.splice(0)).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
"Child:setup",
|
"Child:setup",
|
||||||
"Child:willStart",
|
"Child:willStart",
|
||||||
"Child:willRender",
|
"Child:willRender",
|
||||||
@@ -919,7 +930,8 @@ describe("basics", () => {
|
|||||||
"Child:willUnmount",
|
"Child:willUnmount",
|
||||||
"Child:willDestroy",
|
"Child:willDestroy",
|
||||||
"Child:mounted",
|
"Child:mounted",
|
||||||
]).toBeLogged();
|
]
|
||||||
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("GrandChild display is controlled by its GrandParent", async () => {
|
test("GrandChild display is controlled by its GrandParent", async () => {
|
||||||
@@ -943,20 +955,27 @@ describe("basics", () => {
|
|||||||
|
|
||||||
const parent = await mount(Parent, fixture);
|
const parent = await mount(Parent, fixture);
|
||||||
expect(fixture.innerHTML).toBe("<div></div>");
|
expect(fixture.innerHTML).toBe("<div></div>");
|
||||||
expect([
|
expect(steps.splice(0)).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
"GrandChild:setup",
|
"GrandChild:setup",
|
||||||
"GrandChild:willStart",
|
"GrandChild:willStart",
|
||||||
"GrandChild:willRender",
|
"GrandChild:willRender",
|
||||||
"GrandChild:rendered",
|
"GrandChild:rendered",
|
||||||
"GrandChild:mounted",
|
"GrandChild:mounted",
|
||||||
]).toBeLogged();
|
]
|
||||||
|
`);
|
||||||
|
|
||||||
parent.displayGrandChild = false;
|
parent.displayGrandChild = false;
|
||||||
parent.render();
|
parent.render();
|
||||||
await nextTick();
|
await nextTick();
|
||||||
expect(fixture.innerHTML).toBe("");
|
expect(fixture.innerHTML).toBe("");
|
||||||
|
|
||||||
expect(["GrandChild:willUnmount", "GrandChild:willDestroy"]).toBeLogged();
|
expect(steps.splice(0)).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
|
"GrandChild:willUnmount",
|
||||||
|
"GrandChild:willDestroy",
|
||||||
|
]
|
||||||
|
`);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1024,7 +1043,7 @@ describe("support svg components", () => {
|
|||||||
await mount(Svg, fixture);
|
await mount(Svg, fixture);
|
||||||
|
|
||||||
expect(fixture.innerHTML).toBe(
|
expect(fixture.innerHTML).toBe(
|
||||||
'<svg><g><circle cx="50" cy="50" r="4" stroke="green" stroke-width="1" fill="yellow"></circle></g></svg>'
|
'<svg xmlns="http://www.w3.org/2000/svg"><g xmlns="http://www.w3.org/2000/svg"><circle cx="50" cy="50" r="4" stroke="green" stroke-width="1" fill="yellow"></circle></g></svg>'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -19,8 +19,9 @@ import {
|
|||||||
snapshotEverything,
|
snapshotEverything,
|
||||||
useLogLifecycle,
|
useLogLifecycle,
|
||||||
nextAppError,
|
nextAppError,
|
||||||
|
steps,
|
||||||
} from "../helpers";
|
} from "../helpers";
|
||||||
import { OwlError } from "../../src/runtime/error_handling";
|
import { OwlError } from "../../src/common/owl_error";
|
||||||
|
|
||||||
let fixture: HTMLElement;
|
let fixture: HTMLElement;
|
||||||
|
|
||||||
@@ -143,6 +144,66 @@ describe("basics", () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("display a nice error if the root component template fails to compile", async () => {
|
||||||
|
// This is a special case: mount throws synchronously and we don't have any
|
||||||
|
// node which can handle the error, hence the different structure of this test
|
||||||
|
class Comp extends Component {
|
||||||
|
static template = xml`<div t-att-class="a b">test</div>`;
|
||||||
|
}
|
||||||
|
const app = new App(Comp);
|
||||||
|
let error: Error;
|
||||||
|
try {
|
||||||
|
await app.mount(fixture);
|
||||||
|
} catch (e) {
|
||||||
|
error = e as Error;
|
||||||
|
}
|
||||||
|
const expectedErrorMessage = `Failed to compile anonymous template: Unexpected identifier
|
||||||
|
|
||||||
|
generated code:
|
||||||
|
function(app, bdom, helpers) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
|
||||||
|
let block1 = createBlock(\`<div block-attribute-0="class">test</div>\`);
|
||||||
|
|
||||||
|
return function template(ctx, node, key = "") {
|
||||||
|
let attr1 = ctx['a']ctx['b'];
|
||||||
|
return block1([attr1]);
|
||||||
|
}
|
||||||
|
}`;
|
||||||
|
expect(error!).toBeDefined();
|
||||||
|
expect(error!.message).toBe(expectedErrorMessage);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("display a nice error if a non-root component template fails to compile", async () => {
|
||||||
|
class Child extends Component {
|
||||||
|
static template = xml`<div t-att-class="a b">test</div>`;
|
||||||
|
}
|
||||||
|
class Parent extends Component {
|
||||||
|
static components = { Child };
|
||||||
|
static template = xml`<Child/>`;
|
||||||
|
}
|
||||||
|
const expectedErrorMessage = `Failed to compile anonymous template: Unexpected identifier
|
||||||
|
|
||||||
|
generated code:
|
||||||
|
function(app, bdom, helpers) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
|
||||||
|
let block1 = createBlock(\`<div block-attribute-0="class">test</div>\`);
|
||||||
|
|
||||||
|
return function template(ctx, node, key = "") {
|
||||||
|
let attr1 = ctx['a']ctx['b'];
|
||||||
|
return block1([attr1]);
|
||||||
|
}
|
||||||
|
}`;
|
||||||
|
const app = new App(Parent as typeof Component);
|
||||||
|
let error: Error;
|
||||||
|
const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
|
||||||
|
await expect(nextAppError(app)).resolves.toThrow(expectedErrorMessage);
|
||||||
|
await mountProm;
|
||||||
|
expect(error!).toBeDefined();
|
||||||
|
expect(error!.message).toBe(expectedErrorMessage);
|
||||||
|
});
|
||||||
|
|
||||||
test("simple catchError", async () => {
|
test("simple catchError", async () => {
|
||||||
class Boom extends Component {
|
class Boom extends Component {
|
||||||
static template = xml`<div t-esc="a.b.c"/>`;
|
static template = xml`<div t-esc="a.b.c"/>`;
|
||||||
@@ -888,7 +949,8 @@ describe("can catch errors", () => {
|
|||||||
}
|
}
|
||||||
await mount(Root, fixture);
|
await mount(Root, fixture);
|
||||||
expect(fixture.innerHTML).toBe("<div><div>Error handled</div></div>");
|
expect(fixture.innerHTML).toBe("<div><div>Error handled</div></div>");
|
||||||
expect([
|
expect(steps.splice(0)).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
"Root:setup",
|
"Root:setup",
|
||||||
"Root:willStart",
|
"Root:willStart",
|
||||||
"Root:willRender",
|
"Root:willRender",
|
||||||
@@ -907,7 +969,8 @@ describe("can catch errors", () => {
|
|||||||
"ErrorBoundary:rendered",
|
"ErrorBoundary:rendered",
|
||||||
"ErrorBoundary:mounted",
|
"ErrorBoundary:mounted",
|
||||||
"Root:mounted",
|
"Root:mounted",
|
||||||
]).toBeLogged();
|
]
|
||||||
|
`);
|
||||||
expect(mockConsoleError).toBeCalledTimes(0);
|
expect(mockConsoleError).toBeCalledTimes(0);
|
||||||
expect(mockConsoleWarn).toBeCalledTimes(0);
|
expect(mockConsoleWarn).toBeCalledTimes(0);
|
||||||
});
|
});
|
||||||
@@ -938,7 +1001,8 @@ describe("can catch errors", () => {
|
|||||||
}
|
}
|
||||||
await mount(Root, fixture);
|
await mount(Root, fixture);
|
||||||
expect(fixture.innerHTML).toBe("<div>Error handled</div>");
|
expect(fixture.innerHTML).toBe("<div>Error handled</div>");
|
||||||
expect([
|
expect(steps.splice(0)).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
"Root:setup",
|
"Root:setup",
|
||||||
"Root:willStart",
|
"Root:willStart",
|
||||||
"Root:willRender",
|
"Root:willRender",
|
||||||
@@ -952,7 +1016,8 @@ describe("can catch errors", () => {
|
|||||||
"Root:willRender",
|
"Root:willRender",
|
||||||
"Root:rendered",
|
"Root:rendered",
|
||||||
"Root:mounted",
|
"Root:mounted",
|
||||||
]).toBeLogged();
|
]
|
||||||
|
`);
|
||||||
expect(mockConsoleError).toBeCalledTimes(0);
|
expect(mockConsoleError).toBeCalledTimes(0);
|
||||||
expect(mockConsoleWarn).toBeCalledTimes(0);
|
expect(mockConsoleWarn).toBeCalledTimes(0);
|
||||||
});
|
});
|
||||||
@@ -999,7 +1064,8 @@ describe("can catch errors", () => {
|
|||||||
}
|
}
|
||||||
await mount(A, fixture);
|
await mount(A, fixture);
|
||||||
expect(fixture.innerHTML).toBe("<div><div>Error handled</div></div>");
|
expect(fixture.innerHTML).toBe("<div><div>Error handled</div></div>");
|
||||||
expect([
|
expect(steps.splice(0)).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
"A:setup",
|
"A:setup",
|
||||||
"A:willStart",
|
"A:willStart",
|
||||||
"A:willRender",
|
"A:willRender",
|
||||||
@@ -1023,7 +1089,8 @@ describe("can catch errors", () => {
|
|||||||
"C:mounted",
|
"C:mounted",
|
||||||
"B:mounted",
|
"B:mounted",
|
||||||
"A:mounted",
|
"A:mounted",
|
||||||
]).toBeLogged();
|
]
|
||||||
|
`);
|
||||||
expect(mockConsoleError).toBeCalledTimes(0);
|
expect(mockConsoleError).toBeCalledTimes(0);
|
||||||
expect(mockConsoleWarn).toBeCalledTimes(0);
|
expect(mockConsoleWarn).toBeCalledTimes(0);
|
||||||
});
|
});
|
||||||
@@ -1070,7 +1137,8 @@ describe("can catch errors", () => {
|
|||||||
}
|
}
|
||||||
await mount(Root, fixture);
|
await mount(Root, fixture);
|
||||||
expect(fixture.innerHTML).toBe("<div>OK<div>Error handled</div></div>");
|
expect(fixture.innerHTML).toBe("<div>OK<div>Error handled</div></div>");
|
||||||
expect([
|
expect(steps.splice(0)).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
"Root:setup",
|
"Root:setup",
|
||||||
"Root:willStart",
|
"Root:willStart",
|
||||||
"Root:willRender",
|
"Root:willRender",
|
||||||
@@ -1094,7 +1162,8 @@ describe("can catch errors", () => {
|
|||||||
"ErrorBoundary:mounted",
|
"ErrorBoundary:mounted",
|
||||||
"OK:mounted",
|
"OK:mounted",
|
||||||
"Root:mounted",
|
"Root:mounted",
|
||||||
]).toBeLogged();
|
]
|
||||||
|
`);
|
||||||
expect(mockConsoleError).toBeCalledTimes(0);
|
expect(mockConsoleError).toBeCalledTimes(0);
|
||||||
expect(mockConsoleWarn).toBeCalledTimes(0);
|
expect(mockConsoleWarn).toBeCalledTimes(0);
|
||||||
});
|
});
|
||||||
@@ -1421,7 +1490,8 @@ describe("can catch errors", () => {
|
|||||||
|
|
||||||
const parent = await mount(Parent, fixture);
|
const parent = await mount(Parent, fixture);
|
||||||
expect(fixture.innerHTML).toBe("1<div>abc</div>");
|
expect(fixture.innerHTML).toBe("1<div>abc</div>");
|
||||||
expect([
|
expect(steps.splice(0)).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
"Parent:setup",
|
"Parent:setup",
|
||||||
"Parent:willStart",
|
"Parent:willStart",
|
||||||
"Parent:willRender",
|
"Parent:willRender",
|
||||||
@@ -1432,23 +1502,27 @@ describe("can catch errors", () => {
|
|||||||
"Child:rendered",
|
"Child:rendered",
|
||||||
"Child:mounted",
|
"Child:mounted",
|
||||||
"Parent:mounted",
|
"Parent:mounted",
|
||||||
]).toBeLogged();
|
]
|
||||||
|
`);
|
||||||
parent.state.hasChild = false;
|
parent.state.hasChild = false;
|
||||||
await nextTick();
|
await nextTick();
|
||||||
await nextTick();
|
await nextTick();
|
||||||
await nextTick();
|
await nextTick();
|
||||||
await nextTick();
|
await nextTick();
|
||||||
expect([
|
expect(steps.splice(0)).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
"Parent:willRender",
|
"Parent:willRender",
|
||||||
"Parent:rendered",
|
"Parent:rendered",
|
||||||
"Parent:willPatch",
|
"Parent:willPatch",
|
||||||
"Child:willUnmount",
|
"Child:willUnmount",
|
||||||
"Child:willDestroy",
|
"Child:willDestroy",
|
||||||
|
"Parent:patched",
|
||||||
"Parent:willRender",
|
"Parent:willRender",
|
||||||
"Parent:rendered",
|
"Parent:rendered",
|
||||||
"Parent:willPatch",
|
"Parent:willPatch",
|
||||||
"Parent:patched",
|
"Parent:patched",
|
||||||
]).toBeLogged();
|
]
|
||||||
|
`);
|
||||||
expect(fixture.innerHTML).toBe("2");
|
expect(fixture.innerHTML).toBe("2");
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1481,13 +1555,15 @@ describe("can catch errors", () => {
|
|||||||
const parent = await mount(Parent, fixture);
|
const parent = await mount(Parent, fixture);
|
||||||
expect(fixture.innerHTML).toBe("1");
|
expect(fixture.innerHTML).toBe("1");
|
||||||
|
|
||||||
expect([
|
expect(steps.splice(0)).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
"Parent:setup",
|
"Parent:setup",
|
||||||
"Parent:willStart",
|
"Parent:willStart",
|
||||||
"Parent:willRender",
|
"Parent:willRender",
|
||||||
"Parent:rendered",
|
"Parent:rendered",
|
||||||
"Parent:mounted",
|
"Parent:mounted",
|
||||||
]).toBeLogged();
|
]
|
||||||
|
`);
|
||||||
|
|
||||||
parent.state.hasChild = true;
|
parent.state.hasChild = true;
|
||||||
await nextMicroTick();
|
await nextMicroTick();
|
||||||
@@ -1495,23 +1571,35 @@ describe("can catch errors", () => {
|
|||||||
await nextMicroTick();
|
await nextMicroTick();
|
||||||
await nextMicroTick();
|
await nextMicroTick();
|
||||||
await nextMicroTick();
|
await nextMicroTick();
|
||||||
expect([
|
expect(steps.splice(0)).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
"Parent:willRender",
|
"Parent:willRender",
|
||||||
"Child:setup",
|
"Child:setup",
|
||||||
"Child:willStart",
|
"Child:willStart",
|
||||||
"Parent:rendered",
|
"Parent:rendered",
|
||||||
"Child:willRender",
|
"Child:willRender",
|
||||||
"Child:rendered",
|
"Child:rendered",
|
||||||
]).toBeLogged();
|
]
|
||||||
|
`);
|
||||||
parent.state.hasChild = false;
|
parent.state.hasChild = false;
|
||||||
await nextTick();
|
await nextTick();
|
||||||
expect([
|
expect(steps.splice(0)).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
|
"Parent:willRender",
|
||||||
|
"Parent:rendered",
|
||||||
"Child:willDestroy",
|
"Child:willDestroy",
|
||||||
"Parent:willRender",
|
"Parent:willRender",
|
||||||
"Parent:rendered",
|
"Parent:rendered",
|
||||||
|
]
|
||||||
|
`);
|
||||||
|
expect(fixture.innerHTML).toBe("1");
|
||||||
|
await nextTick();
|
||||||
|
expect(steps.splice(0)).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
"Parent:willPatch",
|
"Parent:willPatch",
|
||||||
"Parent:patched",
|
"Parent:patched",
|
||||||
]).toBeLogged();
|
]
|
||||||
|
`);
|
||||||
expect(fixture.innerHTML).toBe("2");
|
expect(fixture.innerHTML).toBe("2");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -641,6 +641,56 @@ describe("hooks", () => {
|
|||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("effect types are inferred from dependencies", async () => {
|
||||||
|
// @ts-ignore (declared but never used)
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
class MyComponent extends Component {
|
||||||
|
static template = xml`<div/>`;
|
||||||
|
|
||||||
|
setup() {
|
||||||
|
useEffect(
|
||||||
|
(a, b) => {
|
||||||
|
expectType<number>(a);
|
||||||
|
expectType<string>(b);
|
||||||
|
},
|
||||||
|
() => [3, "hello"]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
test("effect type allows an effect with partial dependencies parameters", async () => {
|
||||||
|
// @ts-ignore (declared but never used)
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
class MyComponent extends Component {
|
||||||
|
static template = xml`<div/>`;
|
||||||
|
|
||||||
|
setup() {
|
||||||
|
useEffect(
|
||||||
|
(a) => {
|
||||||
|
expectType<number>(a);
|
||||||
|
},
|
||||||
|
() => [3, "hello"]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
test("effect type allows an effect with no dependency parameter", async () => {
|
||||||
|
// @ts-ignore (declared but never used)
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
class MyComponent extends Component {
|
||||||
|
static template = xml`<div/>`;
|
||||||
|
|
||||||
|
setup() {
|
||||||
|
useEffect(
|
||||||
|
() => {},
|
||||||
|
() => [3, "hello"]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
test("properly behaves when the effect function throws", async () => {
|
test("properly behaves when the effect function throws", async () => {
|
||||||
let originalconsoleError = console.error;
|
let originalconsoleError = console.error;
|
||||||
let originalconsoleWarn = console.warn;
|
let originalconsoleWarn = console.warn;
|
||||||
@@ -673,3 +723,5 @@ describe("hooks", () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function expectType<T>(t: T) {}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import {
|
|||||||
nextMicroTick,
|
nextMicroTick,
|
||||||
nextTick,
|
nextTick,
|
||||||
snapshotEverything,
|
snapshotEverything,
|
||||||
|
steps,
|
||||||
useLogLifecycle,
|
useLogLifecycle,
|
||||||
} from "../helpers";
|
} from "../helpers";
|
||||||
|
|
||||||
@@ -455,7 +456,8 @@ describe("lifecycle hooks", () => {
|
|||||||
|
|
||||||
const parent = await mount(Parent, fixture);
|
const parent = await mount(Parent, fixture);
|
||||||
expect(fixture.innerHTML).toBe("<div><span>0</span></div>");
|
expect(fixture.innerHTML).toBe("<div><span>0</span></div>");
|
||||||
expect([
|
expect(steps.splice(0)).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
"Parent:setup",
|
"Parent:setup",
|
||||||
"Parent:willStart",
|
"Parent:willStart",
|
||||||
"Parent:willRender",
|
"Parent:willRender",
|
||||||
@@ -466,12 +468,14 @@ describe("lifecycle hooks", () => {
|
|||||||
"Child:rendered",
|
"Child:rendered",
|
||||||
"Child:mounted",
|
"Child:mounted",
|
||||||
"Parent:mounted",
|
"Parent:mounted",
|
||||||
]).toBeLogged();
|
]
|
||||||
|
`);
|
||||||
|
|
||||||
parent.increment();
|
parent.increment();
|
||||||
await nextTick();
|
await nextTick();
|
||||||
expect(fixture.innerHTML).toBe("<div><span>1</span></div>");
|
expect(fixture.innerHTML).toBe("<div><span>1</span></div>");
|
||||||
expect([
|
expect(steps.splice(0)).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
"Parent:willRender",
|
"Parent:willRender",
|
||||||
"Child:willUpdateProps",
|
"Child:willUpdateProps",
|
||||||
"Parent:rendered",
|
"Parent:rendered",
|
||||||
@@ -481,19 +485,22 @@ describe("lifecycle hooks", () => {
|
|||||||
"Child:willPatch",
|
"Child:willPatch",
|
||||||
"Child:patched",
|
"Child:patched",
|
||||||
"Parent:patched",
|
"Parent:patched",
|
||||||
]).toBeLogged();
|
]
|
||||||
|
`);
|
||||||
|
|
||||||
parent.toggleSubWidget();
|
parent.toggleSubWidget();
|
||||||
await nextTick();
|
await nextTick();
|
||||||
expect(fixture.innerHTML).toBe("");
|
expect(fixture.innerHTML).toBe("");
|
||||||
expect([
|
expect(steps.splice(0)).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
"Parent:willRender",
|
"Parent:willRender",
|
||||||
"Parent:rendered",
|
"Parent:rendered",
|
||||||
"Parent:willPatch",
|
"Parent:willPatch",
|
||||||
"Child:willUnmount",
|
"Child:willUnmount",
|
||||||
"Child:willDestroy",
|
"Child:willDestroy",
|
||||||
"Parent:patched",
|
"Parent:patched",
|
||||||
]).toBeLogged();
|
]
|
||||||
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("hooks are called in proper order in widget creation/destruction", async () => {
|
test("hooks are called in proper order in widget creation/destruction", async () => {
|
||||||
@@ -514,7 +521,8 @@ describe("lifecycle hooks", () => {
|
|||||||
|
|
||||||
const app = new App(Parent);
|
const app = new App(Parent);
|
||||||
await app.mount(fixture);
|
await app.mount(fixture);
|
||||||
expect([
|
expect(steps.splice(0)).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
"Parent:setup",
|
"Parent:setup",
|
||||||
"Parent:willStart",
|
"Parent:willStart",
|
||||||
"Parent:willRender",
|
"Parent:willRender",
|
||||||
@@ -525,15 +533,18 @@ describe("lifecycle hooks", () => {
|
|||||||
"Child:rendered",
|
"Child:rendered",
|
||||||
"Child:mounted",
|
"Child:mounted",
|
||||||
"Parent:mounted",
|
"Parent:mounted",
|
||||||
]).toBeLogged();
|
]
|
||||||
|
`);
|
||||||
|
|
||||||
app.destroy();
|
app.destroy();
|
||||||
expect([
|
expect(steps.splice(0)).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
"Parent:willUnmount",
|
"Parent:willUnmount",
|
||||||
"Child:willUnmount",
|
"Child:willUnmount",
|
||||||
"Child:willDestroy",
|
"Child:willDestroy",
|
||||||
"Parent:willDestroy",
|
"Parent:willDestroy",
|
||||||
]).toBeLogged();
|
]
|
||||||
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("willUpdateProps hook is called", async () => {
|
test("willUpdateProps hook is called", async () => {
|
||||||
@@ -632,7 +643,8 @@ describe("lifecycle hooks", () => {
|
|||||||
|
|
||||||
const app = new App(Parent);
|
const app = new App(Parent);
|
||||||
await app.mount(fixture);
|
await app.mount(fixture);
|
||||||
expect([
|
expect(steps.splice(0)).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
"Parent:setup",
|
"Parent:setup",
|
||||||
"Parent:willStart",
|
"Parent:willStart",
|
||||||
"Parent:willRender",
|
"Parent:willRender",
|
||||||
@@ -643,15 +655,18 @@ describe("lifecycle hooks", () => {
|
|||||||
"Child:rendered",
|
"Child:rendered",
|
||||||
"Child:mounted",
|
"Child:mounted",
|
||||||
"Parent:mounted",
|
"Parent:mounted",
|
||||||
]).toBeLogged();
|
]
|
||||||
|
`);
|
||||||
|
|
||||||
app.destroy();
|
app.destroy();
|
||||||
expect([
|
expect(steps.splice(0)).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
"Parent:willUnmount",
|
"Parent:willUnmount",
|
||||||
"Child:willUnmount",
|
"Child:willUnmount",
|
||||||
"Child:willDestroy",
|
"Child:willDestroy",
|
||||||
"Parent:willDestroy",
|
"Parent:willDestroy",
|
||||||
]).toBeLogged();
|
]
|
||||||
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("lifecycle semantics, part 2", async () => {
|
test("lifecycle semantics, part 2", async () => {
|
||||||
@@ -680,17 +695,20 @@ describe("lifecycle hooks", () => {
|
|||||||
|
|
||||||
const app = new App(Parent);
|
const app = new App(Parent);
|
||||||
const parent = await app.mount(fixture);
|
const parent = await app.mount(fixture);
|
||||||
expect([
|
expect(steps.splice(0)).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
"Parent:setup",
|
"Parent:setup",
|
||||||
"Parent:willStart",
|
"Parent:willStart",
|
||||||
"Parent:willRender",
|
"Parent:willRender",
|
||||||
"Parent:rendered",
|
"Parent:rendered",
|
||||||
"Parent:mounted",
|
"Parent:mounted",
|
||||||
]).toBeLogged();
|
]
|
||||||
|
`);
|
||||||
|
|
||||||
parent.state.hasChild = true;
|
parent.state.hasChild = true;
|
||||||
await nextTick();
|
await nextTick();
|
||||||
expect([
|
expect(steps.splice(0)).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
"Parent:willRender",
|
"Parent:willRender",
|
||||||
"Child:setup",
|
"Child:setup",
|
||||||
"Child:willStart",
|
"Child:willStart",
|
||||||
@@ -705,17 +723,20 @@ describe("lifecycle hooks", () => {
|
|||||||
"GrandChild:mounted",
|
"GrandChild:mounted",
|
||||||
"Child:mounted",
|
"Child:mounted",
|
||||||
"Parent:patched",
|
"Parent:patched",
|
||||||
]).toBeLogged();
|
]
|
||||||
|
`);
|
||||||
|
|
||||||
app.destroy();
|
app.destroy();
|
||||||
expect([
|
expect(steps.splice(0)).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
"Parent:willUnmount",
|
"Parent:willUnmount",
|
||||||
"Child:willUnmount",
|
"Child:willUnmount",
|
||||||
"GrandChild:willUnmount",
|
"GrandChild:willUnmount",
|
||||||
"GrandChild:willDestroy",
|
"GrandChild:willDestroy",
|
||||||
"Child:willDestroy",
|
"Child:willDestroy",
|
||||||
"Parent:willDestroy",
|
"Parent:willDestroy",
|
||||||
]).toBeLogged();
|
]
|
||||||
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("lifecycle semantics, part 3", async () => {
|
test("lifecycle semantics, part 3", async () => {
|
||||||
@@ -744,19 +765,26 @@ describe("lifecycle hooks", () => {
|
|||||||
|
|
||||||
const app = new App(Parent);
|
const app = new App(Parent);
|
||||||
const parent = await app.mount(fixture);
|
const parent = await app.mount(fixture);
|
||||||
expect([
|
expect(steps.splice(0)).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
"Parent:setup",
|
"Parent:setup",
|
||||||
"Parent:willStart",
|
"Parent:willStart",
|
||||||
"Parent:willRender",
|
"Parent:willRender",
|
||||||
"Parent:rendered",
|
"Parent:rendered",
|
||||||
"Parent:mounted",
|
"Parent:mounted",
|
||||||
]).toBeLogged();
|
]
|
||||||
|
`);
|
||||||
|
|
||||||
parent.state.hasChild = true;
|
parent.state.hasChild = true;
|
||||||
// immediately destroy everything
|
// immediately destroy everything
|
||||||
app.destroy();
|
app.destroy();
|
||||||
await nextTick();
|
await nextTick();
|
||||||
expect(["Parent:willUnmount", "Parent:willDestroy"]).toBeLogged();
|
expect(steps.splice(0)).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
|
"Parent:willUnmount",
|
||||||
|
"Parent:willDestroy",
|
||||||
|
]
|
||||||
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("lifecycle semantics, part 4", async () => {
|
test("lifecycle semantics, part 4", async () => {
|
||||||
@@ -789,17 +817,20 @@ describe("lifecycle hooks", () => {
|
|||||||
const app = new App(Parent);
|
const app = new App(Parent);
|
||||||
const parent = await app.mount(fixture);
|
const parent = await app.mount(fixture);
|
||||||
|
|
||||||
expect([
|
expect(steps.splice(0)).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
"Parent:setup",
|
"Parent:setup",
|
||||||
"Parent:willStart",
|
"Parent:willStart",
|
||||||
"Parent:willRender",
|
"Parent:willRender",
|
||||||
"Parent:rendered",
|
"Parent:rendered",
|
||||||
"Parent:mounted",
|
"Parent:mounted",
|
||||||
]).toBeLogged();
|
]
|
||||||
|
`);
|
||||||
|
|
||||||
parent.state.hasChild = true;
|
parent.state.hasChild = true;
|
||||||
await nextTick();
|
await nextTick();
|
||||||
expect([
|
expect(steps.splice(0)).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
"Parent:willRender",
|
"Parent:willRender",
|
||||||
"Child:setup",
|
"Child:setup",
|
||||||
"Child:willStart",
|
"Child:willStart",
|
||||||
@@ -808,15 +839,18 @@ describe("lifecycle hooks", () => {
|
|||||||
"GrandChild:setup",
|
"GrandChild:setup",
|
||||||
"GrandChild:willStart",
|
"GrandChild:willStart",
|
||||||
"Child:rendered",
|
"Child:rendered",
|
||||||
]).toBeLogged();
|
]
|
||||||
|
`);
|
||||||
|
|
||||||
app.destroy();
|
app.destroy();
|
||||||
expect([
|
expect(steps.splice(0)).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
"Parent:willUnmount",
|
"Parent:willUnmount",
|
||||||
"GrandChild:willDestroy",
|
"GrandChild:willDestroy",
|
||||||
"Child:willDestroy",
|
"Child:willDestroy",
|
||||||
"Parent:willDestroy",
|
"Parent:willDestroy",
|
||||||
]).toBeLogged();
|
]
|
||||||
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("lifecycle semantics, part 5", async () => {
|
test("lifecycle semantics, part 5", async () => {
|
||||||
@@ -837,7 +871,8 @@ describe("lifecycle hooks", () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const parent = await mount(Parent, fixture);
|
const parent = await mount(Parent, fixture);
|
||||||
expect([
|
expect(steps.splice(0)).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
"Parent:setup",
|
"Parent:setup",
|
||||||
"Parent:willStart",
|
"Parent:willStart",
|
||||||
"Parent:willRender",
|
"Parent:willRender",
|
||||||
@@ -848,18 +883,21 @@ describe("lifecycle hooks", () => {
|
|||||||
"Child:rendered",
|
"Child:rendered",
|
||||||
"Child:mounted",
|
"Child:mounted",
|
||||||
"Parent:mounted",
|
"Parent:mounted",
|
||||||
]).toBeLogged();
|
]
|
||||||
|
`);
|
||||||
|
|
||||||
parent.state.hasChild = false;
|
parent.state.hasChild = false;
|
||||||
await nextTick();
|
await nextTick();
|
||||||
expect([
|
expect(steps.splice(0)).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
"Parent:willRender",
|
"Parent:willRender",
|
||||||
"Parent:rendered",
|
"Parent:rendered",
|
||||||
"Parent:willPatch",
|
"Parent:willPatch",
|
||||||
"Child:willUnmount",
|
"Child:willUnmount",
|
||||||
"Child:willDestroy",
|
"Child:willDestroy",
|
||||||
"Parent:patched",
|
"Parent:patched",
|
||||||
]).toBeLogged();
|
]
|
||||||
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("lifecycle semantics, part 6", async () => {
|
test("lifecycle semantics, part 6", async () => {
|
||||||
@@ -880,7 +918,8 @@ describe("lifecycle hooks", () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const parent = await mount(Parent, fixture);
|
const parent = await mount(Parent, fixture);
|
||||||
expect([
|
expect(steps.splice(0)).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
"Parent:setup",
|
"Parent:setup",
|
||||||
"Parent:willStart",
|
"Parent:willStart",
|
||||||
"Parent:willRender",
|
"Parent:willRender",
|
||||||
@@ -891,11 +930,13 @@ describe("lifecycle hooks", () => {
|
|||||||
"Child:rendered",
|
"Child:rendered",
|
||||||
"Child:mounted",
|
"Child:mounted",
|
||||||
"Parent:mounted",
|
"Parent:mounted",
|
||||||
]).toBeLogged();
|
]
|
||||||
|
`);
|
||||||
|
|
||||||
parent.state.value = 2;
|
parent.state.value = 2;
|
||||||
await nextTick();
|
await nextTick();
|
||||||
expect([
|
expect(steps.splice(0)).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
"Parent:willRender",
|
"Parent:willRender",
|
||||||
"Child:willUpdateProps",
|
"Child:willUpdateProps",
|
||||||
"Parent:rendered",
|
"Parent:rendered",
|
||||||
@@ -905,7 +946,8 @@ describe("lifecycle hooks", () => {
|
|||||||
"Child:willPatch",
|
"Child:willPatch",
|
||||||
"Child:patched",
|
"Child:patched",
|
||||||
"Parent:patched",
|
"Parent:patched",
|
||||||
]).toBeLogged();
|
]
|
||||||
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("onWillRender", async () => {
|
test("onWillRender", async () => {
|
||||||
@@ -937,7 +979,8 @@ describe("lifecycle hooks", () => {
|
|||||||
|
|
||||||
const parent = await mount(Parent, fixture);
|
const parent = await mount(Parent, fixture);
|
||||||
expect(fixture.innerHTML).toBe("<button>1</button>");
|
expect(fixture.innerHTML).toBe("<button>1</button>");
|
||||||
expect([
|
expect(steps.splice(0)).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
"Parent:setup",
|
"Parent:setup",
|
||||||
"Parent:willStart",
|
"Parent:willStart",
|
||||||
"Parent:willRender",
|
"Parent:willRender",
|
||||||
@@ -948,32 +991,41 @@ describe("lifecycle hooks", () => {
|
|||||||
"Child:rendered",
|
"Child:rendered",
|
||||||
"Child:mounted",
|
"Child:mounted",
|
||||||
"Parent:mounted",
|
"Parent:mounted",
|
||||||
]).toBeLogged();
|
]
|
||||||
|
`);
|
||||||
|
|
||||||
parent.state.value++; // to block child render
|
parent.state.value++; // to block child render
|
||||||
await nextTick();
|
await nextTick();
|
||||||
expect(["Parent:willRender", "Child:willUpdateProps", "Parent:rendered"]).toBeLogged();
|
expect(steps.splice(0)).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
|
"Parent:willRender",
|
||||||
|
"Child:willUpdateProps",
|
||||||
|
"Parent:rendered",
|
||||||
|
]
|
||||||
|
`);
|
||||||
|
|
||||||
fixture.querySelector("button")!.click();
|
fixture.querySelector("button")!.click();
|
||||||
await nextTick();
|
await nextTick();
|
||||||
expect([]).toBeLogged();
|
expect(steps.splice(0)).toMatchInlineSnapshot(`Array []`);
|
||||||
|
|
||||||
fixture.querySelector("button")!.click();
|
fixture.querySelector("button")!.click();
|
||||||
await nextTick();
|
await nextTick();
|
||||||
expect([]).toBeLogged();
|
expect(steps.splice(0)).toMatchInlineSnapshot(`Array []`);
|
||||||
expect(fixture.innerHTML).toBe("<button>1</button>");
|
expect(fixture.innerHTML).toBe("<button>1</button>");
|
||||||
|
|
||||||
def.resolve();
|
def.resolve();
|
||||||
await nextTick();
|
await nextTick();
|
||||||
expect(fixture.innerHTML).toBe("<button>3</button>");
|
expect(fixture.innerHTML).toBe("<button>3</button>");
|
||||||
expect([
|
expect(steps.splice(0)).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
"Child:willRender",
|
"Child:willRender",
|
||||||
"Child:rendered",
|
"Child:rendered",
|
||||||
"Parent:willPatch",
|
"Parent:willPatch",
|
||||||
"Child:willPatch",
|
"Child:willPatch",
|
||||||
"Child:patched",
|
"Child:patched",
|
||||||
"Parent:patched",
|
"Parent:patched",
|
||||||
]).toBeLogged();
|
]
|
||||||
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
// TODO: rename (remove? seems covered by lifecycle semantics)
|
// TODO: rename (remove? seems covered by lifecycle semantics)
|
||||||
@@ -1054,7 +1106,8 @@ describe("lifecycle hooks", () => {
|
|||||||
|
|
||||||
await mount(A, fixture);
|
await mount(A, fixture);
|
||||||
expect(fixture.innerHTML).toBe(`<div>A<div>B</div><div>C<div>D</div><div>E</div></div></div>`);
|
expect(fixture.innerHTML).toBe(`<div>A<div>B</div><div>C<div>D</div><div>E</div></div></div>`);
|
||||||
expect([
|
expect(steps.splice(0)).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
"A:setup",
|
"A:setup",
|
||||||
"A:willStart",
|
"A:willStart",
|
||||||
"A:willRender",
|
"A:willRender",
|
||||||
@@ -1080,12 +1133,14 @@ describe("lifecycle hooks", () => {
|
|||||||
"C:mounted",
|
"C:mounted",
|
||||||
"B:mounted",
|
"B:mounted",
|
||||||
"A:mounted",
|
"A:mounted",
|
||||||
]).toBeLogged();
|
]
|
||||||
|
`);
|
||||||
|
|
||||||
// update
|
// update
|
||||||
c!.state.flag = false;
|
c!.state.flag = false;
|
||||||
await nextTick();
|
await nextTick();
|
||||||
expect([
|
expect(steps.splice(0)).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
"C:willRender",
|
"C:willRender",
|
||||||
"F:setup",
|
"F:setup",
|
||||||
"F:willStart",
|
"F:willStart",
|
||||||
@@ -1097,7 +1152,8 @@ describe("lifecycle hooks", () => {
|
|||||||
"E:willDestroy",
|
"E:willDestroy",
|
||||||
"F:mounted",
|
"F:mounted",
|
||||||
"C:patched",
|
"C:patched",
|
||||||
]).toBeLogged();
|
]
|
||||||
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("mounted hook is called on every mount, not just the first one", async () => {
|
test("mounted hook is called on every mount, not just the first one", async () => {
|
||||||
@@ -1118,7 +1174,8 @@ describe("lifecycle hooks", () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const parent = await mount(Parent, fixture);
|
const parent = await mount(Parent, fixture);
|
||||||
expect([
|
expect(steps.splice(0)).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
"Parent:setup",
|
"Parent:setup",
|
||||||
"Parent:willStart",
|
"Parent:willStart",
|
||||||
"Parent:willRender",
|
"Parent:willRender",
|
||||||
@@ -1129,22 +1186,26 @@ describe("lifecycle hooks", () => {
|
|||||||
"Child:rendered",
|
"Child:rendered",
|
||||||
"Child:mounted",
|
"Child:mounted",
|
||||||
"Parent:mounted",
|
"Parent:mounted",
|
||||||
]).toBeLogged();
|
]
|
||||||
|
`);
|
||||||
|
|
||||||
parent.state.hasChild = false;
|
parent.state.hasChild = false;
|
||||||
await nextTick();
|
await nextTick();
|
||||||
expect([
|
expect(steps.splice(0)).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
"Parent:willRender",
|
"Parent:willRender",
|
||||||
"Parent:rendered",
|
"Parent:rendered",
|
||||||
"Parent:willPatch",
|
"Parent:willPatch",
|
||||||
"Child:willUnmount",
|
"Child:willUnmount",
|
||||||
"Child:willDestroy",
|
"Child:willDestroy",
|
||||||
"Parent:patched",
|
"Parent:patched",
|
||||||
]).toBeLogged();
|
]
|
||||||
|
`);
|
||||||
|
|
||||||
parent.state.hasChild = true;
|
parent.state.hasChild = true;
|
||||||
await nextTick();
|
await nextTick();
|
||||||
expect([
|
expect(steps.splice(0)).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
"Parent:willRender",
|
"Parent:willRender",
|
||||||
"Child:setup",
|
"Child:setup",
|
||||||
"Child:willStart",
|
"Child:willStart",
|
||||||
@@ -1154,7 +1215,8 @@ describe("lifecycle hooks", () => {
|
|||||||
"Parent:willPatch",
|
"Parent:willPatch",
|
||||||
"Child:mounted",
|
"Child:mounted",
|
||||||
"Parent:patched",
|
"Parent:patched",
|
||||||
]).toBeLogged();
|
]
|
||||||
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("render in mounted", async () => {
|
test("render in mounted", async () => {
|
||||||
@@ -1172,7 +1234,8 @@ describe("lifecycle hooks", () => {
|
|||||||
|
|
||||||
await mount(Parent, fixture);
|
await mount(Parent, fixture);
|
||||||
expect(fixture.innerHTML).toBe("<span></span>");
|
expect(fixture.innerHTML).toBe("<span></span>");
|
||||||
expect([
|
expect(steps.splice(0)).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
"Parent:setup",
|
"Parent:setup",
|
||||||
"Parent:willStart",
|
"Parent:willStart",
|
||||||
"Parent:willRender",
|
"Parent:willRender",
|
||||||
@@ -1180,11 +1243,17 @@ describe("lifecycle hooks", () => {
|
|||||||
"Parent:mounted",
|
"Parent:mounted",
|
||||||
"Parent:willRender",
|
"Parent:willRender",
|
||||||
"Parent:rendered",
|
"Parent:rendered",
|
||||||
]).toBeLogged();
|
]
|
||||||
|
`);
|
||||||
|
|
||||||
await nextTick();
|
await nextTick();
|
||||||
expect(fixture.innerHTML).toBe("<span>Patched</span>");
|
expect(fixture.innerHTML).toBe("<span>Patched</span>");
|
||||||
expect(["Parent:willPatch", "Parent:patched"]).toBeLogged();
|
expect(steps.splice(0)).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
|
"Parent:willPatch",
|
||||||
|
"Parent:patched",
|
||||||
|
]
|
||||||
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("render in patched", async () => {
|
test("render in patched", async () => {
|
||||||
@@ -1205,29 +1274,38 @@ describe("lifecycle hooks", () => {
|
|||||||
|
|
||||||
const parent = await mount(Parent, fixture);
|
const parent = await mount(Parent, fixture);
|
||||||
expect(fixture.innerHTML).toBe("<span></span>");
|
expect(fixture.innerHTML).toBe("<span></span>");
|
||||||
expect([
|
expect(steps.splice(0)).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
"Parent:setup",
|
"Parent:setup",
|
||||||
"Parent:willStart",
|
"Parent:willStart",
|
||||||
"Parent:willRender",
|
"Parent:willRender",
|
||||||
"Parent:rendered",
|
"Parent:rendered",
|
||||||
"Parent:mounted",
|
"Parent:mounted",
|
||||||
]).toBeLogged();
|
]
|
||||||
|
`);
|
||||||
|
|
||||||
parent.render();
|
parent.render();
|
||||||
await nextTick();
|
await nextTick();
|
||||||
expect(fixture.innerHTML).toBe("<span></span>");
|
expect(fixture.innerHTML).toBe("<span></span>");
|
||||||
expect([
|
expect(steps.splice(0)).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
"Parent:willRender",
|
"Parent:willRender",
|
||||||
"Parent:rendered",
|
"Parent:rendered",
|
||||||
"Parent:willPatch",
|
"Parent:willPatch",
|
||||||
"Parent:patched",
|
"Parent:patched",
|
||||||
"Parent:willRender",
|
"Parent:willRender",
|
||||||
"Parent:rendered",
|
"Parent:rendered",
|
||||||
]).toBeLogged();
|
]
|
||||||
|
`);
|
||||||
|
|
||||||
await nextTick();
|
await nextTick();
|
||||||
expect(fixture.innerHTML).toBe("<span>Patched</span>");
|
expect(fixture.innerHTML).toBe("<span>Patched</span>");
|
||||||
expect(["Parent:willPatch", "Parent:patched"]).toBeLogged();
|
expect(steps.splice(0)).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
|
"Parent:willPatch",
|
||||||
|
"Parent:patched",
|
||||||
|
]
|
||||||
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("render in willPatch", async () => {
|
test("render in willPatch", async () => {
|
||||||
@@ -1248,29 +1326,38 @@ describe("lifecycle hooks", () => {
|
|||||||
|
|
||||||
const parent = await mount(Parent, fixture);
|
const parent = await mount(Parent, fixture);
|
||||||
expect(fixture.innerHTML).toBe("<span></span>");
|
expect(fixture.innerHTML).toBe("<span></span>");
|
||||||
expect([
|
expect(steps.splice(0)).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
"Parent:setup",
|
"Parent:setup",
|
||||||
"Parent:willStart",
|
"Parent:willStart",
|
||||||
"Parent:willRender",
|
"Parent:willRender",
|
||||||
"Parent:rendered",
|
"Parent:rendered",
|
||||||
"Parent:mounted",
|
"Parent:mounted",
|
||||||
]).toBeLogged();
|
]
|
||||||
|
`);
|
||||||
|
|
||||||
parent.render();
|
parent.render();
|
||||||
await nextTick();
|
await nextTick();
|
||||||
expect(fixture.innerHTML).toBe("<span></span>");
|
expect(fixture.innerHTML).toBe("<span></span>");
|
||||||
|
|
||||||
expect([
|
expect(steps.splice(0)).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
"Parent:willRender",
|
"Parent:willRender",
|
||||||
"Parent:rendered",
|
"Parent:rendered",
|
||||||
"Parent:willPatch",
|
"Parent:willPatch",
|
||||||
"Parent:patched",
|
"Parent:patched",
|
||||||
"Parent:willRender",
|
"Parent:willRender",
|
||||||
"Parent:rendered",
|
"Parent:rendered",
|
||||||
]).toBeLogged();
|
]
|
||||||
|
`);
|
||||||
|
|
||||||
await nextTick();
|
await nextTick();
|
||||||
expect(["Parent:willPatch", "Parent:patched"]).toBeLogged();
|
expect(steps.splice(0)).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
|
"Parent:willPatch",
|
||||||
|
"Parent:patched",
|
||||||
|
]
|
||||||
|
`);
|
||||||
expect(fixture.innerHTML).toBe("<span>Patched</span>");
|
expect(fixture.innerHTML).toBe("<span>Patched</span>");
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1313,7 +1400,8 @@ describe("lifecycle hooks", () => {
|
|||||||
await nextTick();
|
await nextTick();
|
||||||
app.destroy();
|
app.destroy();
|
||||||
|
|
||||||
expect([
|
expect(steps.splice(0)).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
"onWillStart",
|
"onWillStart",
|
||||||
"onWillRender",
|
"onWillRender",
|
||||||
"onRendered",
|
"onRendered",
|
||||||
@@ -1325,7 +1413,8 @@ describe("lifecycle hooks", () => {
|
|||||||
"onPatched",
|
"onPatched",
|
||||||
"onWillUnmount",
|
"onWillUnmount",
|
||||||
"onWillDestroy",
|
"onWillDestroy",
|
||||||
]).toBeLogged();
|
]
|
||||||
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("destroy new children before being mountged", async () => {
|
test("destroy new children before being mountged", async () => {
|
||||||
@@ -1357,19 +1446,22 @@ describe("lifecycle hooks", () => {
|
|||||||
const app = new App(Parent);
|
const app = new App(Parent);
|
||||||
const parent = await app.mount(fixture);
|
const parent = await app.mount(fixture);
|
||||||
expect(fixture.innerHTML).toBe("beforeafter");
|
expect(fixture.innerHTML).toBe("beforeafter");
|
||||||
expect([
|
expect(steps.splice(0)).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
"Parent:setup",
|
"Parent:setup",
|
||||||
"Parent:willStart",
|
"Parent:willStart",
|
||||||
"Parent:willRender",
|
"Parent:willRender",
|
||||||
"Parent:rendered",
|
"Parent:rendered",
|
||||||
"Parent:mounted",
|
"Parent:mounted",
|
||||||
]).toBeLogged();
|
]
|
||||||
|
`);
|
||||||
|
|
||||||
parent.state.flag = true;
|
parent.state.flag = true;
|
||||||
|
|
||||||
await nextTick();
|
await nextTick();
|
||||||
expect(fixture.innerHTML).toBe("");
|
expect(fixture.innerHTML).toBe("");
|
||||||
expect([
|
expect(steps.splice(0)).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
"Parent:willRender",
|
"Parent:willRender",
|
||||||
"Child:setup",
|
"Child:setup",
|
||||||
"Child:willStart",
|
"Child:willStart",
|
||||||
@@ -1377,6 +1469,7 @@ describe("lifecycle hooks", () => {
|
|||||||
"Parent:willUnmount",
|
"Parent:willUnmount",
|
||||||
"Child:willDestroy",
|
"Child:willDestroy",
|
||||||
"Parent:willDestroy",
|
"Parent:willDestroy",
|
||||||
]).toBeLogged();
|
]
|
||||||
|
`);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Component, mount, onWillUpdateProps, useState, xml } from "../../src";
|
import { Component, mount, onWillUpdateProps, useState, xml } from "../../src";
|
||||||
import { makeTestFixture, nextTick, snapshotEverything, useLogLifecycle } from "../helpers";
|
import { makeTestFixture, nextTick, snapshotEverything, steps, useLogLifecycle } from "../helpers";
|
||||||
|
|
||||||
let fixture: HTMLElement;
|
let fixture: HTMLElement;
|
||||||
|
|
||||||
@@ -272,7 +272,8 @@ test("bound functions are considered 'alike'", async () => {
|
|||||||
|
|
||||||
const parent = await mount(Parent, fixture);
|
const parent = await mount(Parent, fixture);
|
||||||
expect(fixture.innerHTML).toBe("1child");
|
expect(fixture.innerHTML).toBe("1child");
|
||||||
expect([
|
expect(steps.splice(0)).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
"Parent:setup",
|
"Parent:setup",
|
||||||
"Parent:willStart",
|
"Parent:willStart",
|
||||||
"Parent:willRender",
|
"Parent:willRender",
|
||||||
@@ -283,15 +284,18 @@ test("bound functions are considered 'alike'", async () => {
|
|||||||
"Child:rendered",
|
"Child:rendered",
|
||||||
"Child:mounted",
|
"Child:mounted",
|
||||||
"Parent:mounted",
|
"Parent:mounted",
|
||||||
]).toBeLogged();
|
]
|
||||||
|
`);
|
||||||
parent.state.val = 3;
|
parent.state.val = 3;
|
||||||
await nextTick();
|
await nextTick();
|
||||||
expect([
|
expect(steps.splice(0)).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
"Parent:willRender",
|
"Parent:willRender",
|
||||||
"Parent:rendered",
|
"Parent:rendered",
|
||||||
"Parent:willPatch",
|
"Parent:willPatch",
|
||||||
"Parent:patched",
|
"Parent:patched",
|
||||||
]).toBeLogged();
|
]
|
||||||
|
`);
|
||||||
expect(fixture.innerHTML).toBe("3child");
|
expect(fixture.innerHTML).toBe("3child");
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -330,7 +334,8 @@ test(".alike suffix in a simple case", async () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const parent = await mount(Parent, fixture);
|
const parent = await mount(Parent, fixture);
|
||||||
expect([
|
expect(steps.splice(0)).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
"Parent:setup",
|
"Parent:setup",
|
||||||
"Parent:willStart",
|
"Parent:willStart",
|
||||||
"Parent:willRender",
|
"Parent:willRender",
|
||||||
@@ -341,18 +346,21 @@ test(".alike suffix in a simple case", async () => {
|
|||||||
"Child:rendered",
|
"Child:rendered",
|
||||||
"Child:mounted",
|
"Child:mounted",
|
||||||
"Parent:mounted",
|
"Parent:mounted",
|
||||||
]).toBeLogged();
|
]
|
||||||
|
`);
|
||||||
|
|
||||||
expect(fixture.innerHTML).toBe("01");
|
expect(fixture.innerHTML).toBe("01");
|
||||||
parent.state.counter++;
|
parent.state.counter++;
|
||||||
await nextTick();
|
await nextTick();
|
||||||
expect(fixture.innerHTML).toBe("11");
|
expect(fixture.innerHTML).toBe("11");
|
||||||
expect([
|
expect(steps.splice(0)).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
"Parent:willRender",
|
"Parent:willRender",
|
||||||
"Parent:rendered",
|
"Parent:rendered",
|
||||||
"Parent:willPatch",
|
"Parent:willPatch",
|
||||||
"Parent:patched",
|
"Parent:patched",
|
||||||
]).toBeLogged();
|
]
|
||||||
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
test(".alike suffix in a list", async () => {
|
test(".alike suffix in a list", async () => {
|
||||||
@@ -388,7 +396,8 @@ test(".alike suffix in a list", async () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
await mount(Parent, fixture);
|
await mount(Parent, fixture);
|
||||||
expect([
|
expect(steps.splice(0)).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
"Parent:setup",
|
"Parent:setup",
|
||||||
"Parent:willStart",
|
"Parent:willStart",
|
||||||
"Parent:willRender",
|
"Parent:willRender",
|
||||||
@@ -404,13 +413,15 @@ test(".alike suffix in a list", async () => {
|
|||||||
"Todo:mounted",
|
"Todo:mounted",
|
||||||
"Todo:mounted",
|
"Todo:mounted",
|
||||||
"Parent:mounted",
|
"Parent:mounted",
|
||||||
]).toBeLogged();
|
]
|
||||||
|
`);
|
||||||
|
|
||||||
expect(fixture.innerHTML).toBe("<button>1</button><button>2V</button>");
|
expect(fixture.innerHTML).toBe("<button>1</button><button>2V</button>");
|
||||||
fixture.querySelector("button")?.click();
|
fixture.querySelector("button")?.click();
|
||||||
await nextTick();
|
await nextTick();
|
||||||
expect(fixture.innerHTML).toBe("<button>1V</button><button>2V</button>");
|
expect(fixture.innerHTML).toBe("<button>1V</button><button>2V</button>");
|
||||||
expect([
|
expect(steps.splice(0)).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
"Parent:willRender",
|
"Parent:willRender",
|
||||||
"Parent:rendered",
|
"Parent:rendered",
|
||||||
"Todo:willRender",
|
"Todo:willRender",
|
||||||
@@ -419,5 +430,6 @@ test(".alike suffix in a list", async () => {
|
|||||||
"Todo:patched",
|
"Todo:patched",
|
||||||
"Parent:willPatch",
|
"Parent:willPatch",
|
||||||
"Parent:patched",
|
"Parent:patched",
|
||||||
]).toBeLogged();
|
]
|
||||||
|
`);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -594,7 +594,7 @@ describe("props validation", () => {
|
|||||||
|
|
||||||
test("props: can be defined with a boolean", async () => {
|
test("props: can be defined with a boolean", async () => {
|
||||||
class SubComp extends Component {
|
class SubComp extends Component {
|
||||||
static props = { message: true };
|
static props = { message: true } as const;
|
||||||
}
|
}
|
||||||
expect(() => {
|
expect(() => {
|
||||||
validateProps(SubComp as any, {});
|
validateProps(SubComp as any, {});
|
||||||
@@ -636,7 +636,7 @@ describe("props validation", () => {
|
|||||||
|
|
||||||
test("props: extra props cause an error, part 2", async () => {
|
test("props: extra props cause an error, part 2", async () => {
|
||||||
class SubComp extends Component {
|
class SubComp extends Component {
|
||||||
static props = { message: true };
|
static props = { message: true } as const;
|
||||||
}
|
}
|
||||||
expect(() => {
|
expect(() => {
|
||||||
validateProps(SubComp as any, { message: 1, flag: true });
|
validateProps(SubComp as any, { message: 1, flag: true });
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import {
|
|||||||
xml,
|
xml,
|
||||||
toRaw,
|
toRaw,
|
||||||
} from "../../src";
|
} from "../../src";
|
||||||
import { makeTestFixture, nextTick, snapshotEverything, useLogLifecycle } from "../helpers";
|
import { makeTestFixture, nextTick, snapshotEverything, steps, useLogLifecycle } from "../helpers";
|
||||||
|
|
||||||
let fixture: HTMLElement;
|
let fixture: HTMLElement;
|
||||||
|
|
||||||
@@ -175,7 +175,8 @@ describe("reactivity in lifecycle", () => {
|
|||||||
|
|
||||||
const parent = await mount(Parent, fixture);
|
const parent = await mount(Parent, fixture);
|
||||||
expect(fixture.innerHTML).toBe("2");
|
expect(fixture.innerHTML).toBe("2");
|
||||||
expect([
|
expect(steps.splice(0)).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
"Parent:setup",
|
"Parent:setup",
|
||||||
"Parent:willStart",
|
"Parent:willStart",
|
||||||
"Parent:willRender",
|
"Parent:willRender",
|
||||||
@@ -186,19 +187,22 @@ describe("reactivity in lifecycle", () => {
|
|||||||
"Child:rendered",
|
"Child:rendered",
|
||||||
"Child:mounted",
|
"Child:mounted",
|
||||||
"Parent:mounted",
|
"Parent:mounted",
|
||||||
]).toBeLogged();
|
]
|
||||||
|
`);
|
||||||
|
|
||||||
parent.state.content = null;
|
parent.state.content = null;
|
||||||
parent.state.renderChild = false;
|
parent.state.renderChild = false;
|
||||||
await nextTick();
|
await nextTick();
|
||||||
expect([
|
expect(steps.splice(0)).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
"Parent:willRender",
|
"Parent:willRender",
|
||||||
"Parent:rendered",
|
"Parent:rendered",
|
||||||
"Parent:willPatch",
|
"Parent:willPatch",
|
||||||
"Child:willUnmount",
|
"Child:willUnmount",
|
||||||
"Child:willDestroy",
|
"Child:willDestroy",
|
||||||
"Parent:patched",
|
"Parent:patched",
|
||||||
]).toBeLogged();
|
]
|
||||||
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Component is automatically subscribed to reactive object received as prop", async () => {
|
test("Component is automatically subscribed to reactive object received as prop", async () => {
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import {
|
|||||||
useLogLifecycle,
|
useLogLifecycle,
|
||||||
makeDeferred,
|
makeDeferred,
|
||||||
nextMicroTick,
|
nextMicroTick,
|
||||||
|
steps,
|
||||||
} from "../helpers";
|
} from "../helpers";
|
||||||
|
|
||||||
let fixture: HTMLElement;
|
let fixture: HTMLElement;
|
||||||
@@ -41,7 +42,8 @@ describe("rendering semantics", () => {
|
|||||||
const parent = await mount(Parent, fixture);
|
const parent = await mount(Parent, fixture);
|
||||||
|
|
||||||
expect(fixture.innerHTML).toBe("Achild");
|
expect(fixture.innerHTML).toBe("Achild");
|
||||||
expect([
|
expect(steps.splice(0)).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
"Parent:setup",
|
"Parent:setup",
|
||||||
"Parent:willStart",
|
"Parent:willStart",
|
||||||
"Parent:willRender",
|
"Parent:willRender",
|
||||||
@@ -52,17 +54,20 @@ describe("rendering semantics", () => {
|
|||||||
"Child:rendered",
|
"Child:rendered",
|
||||||
"Child:mounted",
|
"Child:mounted",
|
||||||
"Parent:mounted",
|
"Parent:mounted",
|
||||||
]).toBeLogged();
|
]
|
||||||
|
`);
|
||||||
|
|
||||||
parent.state.value = "B";
|
parent.state.value = "B";
|
||||||
await nextTick();
|
await nextTick();
|
||||||
expect(fixture.innerHTML).toBe("Bchild");
|
expect(fixture.innerHTML).toBe("Bchild");
|
||||||
expect([
|
expect(steps.splice(0)).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
"Parent:willRender",
|
"Parent:willRender",
|
||||||
"Parent:rendered",
|
"Parent:rendered",
|
||||||
"Parent:willPatch",
|
"Parent:willPatch",
|
||||||
"Parent:patched",
|
"Parent:patched",
|
||||||
]).toBeLogged();
|
]
|
||||||
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("can force a render to update sub tree", async () => {
|
test("can force a render to update sub tree", async () => {
|
||||||
@@ -167,7 +172,8 @@ describe("rendering semantics", () => {
|
|||||||
const parent = await mount(Parent, fixture, { env });
|
const parent = await mount(Parent, fixture, { env });
|
||||||
|
|
||||||
expect(fixture.innerHTML).toBe("parentAchild3");
|
expect(fixture.innerHTML).toBe("parentAchild3");
|
||||||
expect([
|
expect(steps.splice(0)).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
"Parent:setup",
|
"Parent:setup",
|
||||||
"Parent:willStart",
|
"Parent:willStart",
|
||||||
"Parent:willRender",
|
"Parent:willRender",
|
||||||
@@ -178,7 +184,8 @@ describe("rendering semantics", () => {
|
|||||||
"Child:rendered",
|
"Child:rendered",
|
||||||
"Child:mounted",
|
"Child:mounted",
|
||||||
"Parent:mounted",
|
"Parent:mounted",
|
||||||
]).toBeLogged();
|
]
|
||||||
|
`);
|
||||||
|
|
||||||
value = 4;
|
value = 4;
|
||||||
parent.render(true);
|
parent.render(true);
|
||||||
@@ -187,20 +194,23 @@ describe("rendering semantics", () => {
|
|||||||
await nextMicroTick();
|
await nextMicroTick();
|
||||||
await nextMicroTick();
|
await nextMicroTick();
|
||||||
await nextMicroTick();
|
await nextMicroTick();
|
||||||
expect([
|
expect(steps.splice(0)).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
"Parent:willRender",
|
"Parent:willRender",
|
||||||
"Child:willUpdateProps",
|
"Child:willUpdateProps",
|
||||||
"Parent:rendered",
|
"Parent:rendered",
|
||||||
"Child:willRender",
|
"Child:willRender",
|
||||||
"Child:rendered",
|
"Child:rendered",
|
||||||
]).toBeLogged();
|
]
|
||||||
|
`);
|
||||||
|
|
||||||
parent.state.value = "B";
|
parent.state.value = "B";
|
||||||
|
|
||||||
await nextTick();
|
await nextTick();
|
||||||
|
|
||||||
expect(fixture.innerHTML).toBe("parentBchild4");
|
expect(fixture.innerHTML).toBe("parentBchild4");
|
||||||
expect([
|
expect(steps.splice(0)).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
"Parent:willRender",
|
"Parent:willRender",
|
||||||
"Child:willUpdateProps",
|
"Child:willUpdateProps",
|
||||||
"Parent:rendered",
|
"Parent:rendered",
|
||||||
@@ -210,7 +220,8 @@ describe("rendering semantics", () => {
|
|||||||
"Child:willPatch",
|
"Child:willPatch",
|
||||||
"Child:patched",
|
"Child:patched",
|
||||||
"Parent:patched",
|
"Parent:patched",
|
||||||
]).toBeLogged();
|
]
|
||||||
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("props are reactive", async () => {
|
test("props are reactive", async () => {
|
||||||
@@ -235,7 +246,8 @@ describe("rendering semantics", () => {
|
|||||||
|
|
||||||
const parent = await mount(Parent, fixture);
|
const parent = await mount(Parent, fixture);
|
||||||
expect(fixture.innerHTML).toBe("1");
|
expect(fixture.innerHTML).toBe("1");
|
||||||
expect([
|
expect(steps.splice(0)).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
"Parent:setup",
|
"Parent:setup",
|
||||||
"Parent:willStart",
|
"Parent:willStart",
|
||||||
"Parent:willRender",
|
"Parent:willRender",
|
||||||
@@ -246,12 +258,20 @@ describe("rendering semantics", () => {
|
|||||||
"Child:rendered",
|
"Child:rendered",
|
||||||
"Child:mounted",
|
"Child:mounted",
|
||||||
"Parent:mounted",
|
"Parent:mounted",
|
||||||
]).toBeLogged();
|
]
|
||||||
|
`);
|
||||||
|
|
||||||
parent.state.b = 3;
|
parent.state.b = 3;
|
||||||
await nextTick();
|
await nextTick();
|
||||||
expect(fixture.innerHTML).toBe("3");
|
expect(fixture.innerHTML).toBe("3");
|
||||||
expect(["Child:willRender", "Child:rendered", "Child:willPatch", "Child:patched"]).toBeLogged();
|
expect(steps.splice(0)).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
|
"Child:willRender",
|
||||||
|
"Child:rendered",
|
||||||
|
"Child:willPatch",
|
||||||
|
"Child:patched",
|
||||||
|
]
|
||||||
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("props are reactive (nested prop)", async () => {
|
test("props are reactive (nested prop)", async () => {
|
||||||
@@ -278,7 +298,8 @@ describe("rendering semantics", () => {
|
|||||||
|
|
||||||
const parent = await mount(Parent, fixture);
|
const parent = await mount(Parent, fixture);
|
||||||
expect(fixture.innerHTML).toBe("1");
|
expect(fixture.innerHTML).toBe("1");
|
||||||
expect([
|
expect(steps.splice(0)).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
"Parent:setup",
|
"Parent:setup",
|
||||||
"Parent:willStart",
|
"Parent:willStart",
|
||||||
"Parent:willRender",
|
"Parent:willRender",
|
||||||
@@ -289,17 +310,26 @@ describe("rendering semantics", () => {
|
|||||||
"Child:rendered",
|
"Child:rendered",
|
||||||
"Child:mounted",
|
"Child:mounted",
|
||||||
"Parent:mounted",
|
"Parent:mounted",
|
||||||
]).toBeLogged();
|
]
|
||||||
|
`);
|
||||||
|
|
||||||
parent.state.b.c = 3; // parent is now subscribed to 'b' key
|
parent.state.b.c = 3; // parent is now subscribed to 'b' key
|
||||||
await nextTick();
|
await nextTick();
|
||||||
expect(fixture.innerHTML).toBe("3");
|
expect(fixture.innerHTML).toBe("3");
|
||||||
expect(["Child:willRender", "Child:rendered", "Child:willPatch", "Child:patched"]).toBeLogged();
|
expect(steps.splice(0)).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
|
"Child:willRender",
|
||||||
|
"Child:rendered",
|
||||||
|
"Child:willPatch",
|
||||||
|
"Child:patched",
|
||||||
|
]
|
||||||
|
`);
|
||||||
|
|
||||||
parent.state.b = { c: 444 }; // triggers a parent and a child render
|
parent.state.b = { c: 444 }; // triggers a parent and a child render
|
||||||
await nextTick();
|
await nextTick();
|
||||||
expect(fixture.innerHTML).toBe("444");
|
expect(fixture.innerHTML).toBe("444");
|
||||||
expect([
|
expect(steps.splice(0)).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
"Parent:willRender",
|
"Parent:willRender",
|
||||||
"Parent:rendered",
|
"Parent:rendered",
|
||||||
"Child:willRender",
|
"Child:willRender",
|
||||||
@@ -308,7 +338,8 @@ describe("rendering semantics", () => {
|
|||||||
"Parent:patched",
|
"Parent:patched",
|
||||||
"Child:willPatch",
|
"Child:willPatch",
|
||||||
"Child:patched",
|
"Child:patched",
|
||||||
]).toBeLogged();
|
]
|
||||||
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("works as expected for dynamic number of props", async () => {
|
test("works as expected for dynamic number of props", async () => {
|
||||||
@@ -366,7 +397,8 @@ describe("rendering semantics", () => {
|
|||||||
|
|
||||||
const parent = await mount(A, fixture);
|
const parent = await mount(A, fixture);
|
||||||
expect(fixture.innerHTML).toBe("11");
|
expect(fixture.innerHTML).toBe("11");
|
||||||
expect([
|
expect(steps.splice(0)).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
"A:setup",
|
"A:setup",
|
||||||
"A:willStart",
|
"A:willStart",
|
||||||
"A:willRender",
|
"A:willRender",
|
||||||
@@ -382,12 +414,14 @@ describe("rendering semantics", () => {
|
|||||||
"C:mounted",
|
"C:mounted",
|
||||||
"B:mounted",
|
"B:mounted",
|
||||||
"A:mounted",
|
"A:mounted",
|
||||||
]).toBeLogged();
|
]
|
||||||
|
`);
|
||||||
|
|
||||||
parent.state.obj.val = 3;
|
parent.state.obj.val = 3;
|
||||||
await nextTick();
|
await nextTick();
|
||||||
expect(fixture.innerHTML).toBe("33");
|
expect(fixture.innerHTML).toBe("33");
|
||||||
expect([
|
expect(steps.splice(0)).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
"A:willRender",
|
"A:willRender",
|
||||||
"A:rendered",
|
"A:rendered",
|
||||||
"C:willRender",
|
"C:willRender",
|
||||||
@@ -396,11 +430,12 @@ describe("rendering semantics", () => {
|
|||||||
"A:patched",
|
"A:patched",
|
||||||
"C:willPatch",
|
"C:willPatch",
|
||||||
"C:patched",
|
"C:patched",
|
||||||
]).toBeLogged();
|
]
|
||||||
|
`);
|
||||||
|
|
||||||
def.resolve();
|
def.resolve();
|
||||||
await nextTick();
|
await nextTick();
|
||||||
expect([]).toBeLogged();
|
expect(steps.splice(0)).toMatchInlineSnapshot(`Array []`);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -431,7 +466,8 @@ test("force render in case of existing render", async () => {
|
|||||||
}
|
}
|
||||||
const parent = await mount(A, fixture);
|
const parent = await mount(A, fixture);
|
||||||
expect(fixture.innerHTML).toBe("C1");
|
expect(fixture.innerHTML).toBe("C1");
|
||||||
expect([
|
expect(steps.splice(0)).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
"A:setup",
|
"A:setup",
|
||||||
"A:willStart",
|
"A:willStart",
|
||||||
"A:willRender",
|
"A:willRender",
|
||||||
@@ -447,23 +483,37 @@ test("force render in case of existing render", async () => {
|
|||||||
"C:mounted",
|
"C:mounted",
|
||||||
"B:mounted",
|
"B:mounted",
|
||||||
"A:mounted",
|
"A:mounted",
|
||||||
]).toBeLogged();
|
]
|
||||||
|
`);
|
||||||
|
|
||||||
// trigger a new rendering, blocked in B
|
// trigger a new rendering, blocked in B
|
||||||
parent.state.val = 2;
|
parent.state.val = 2;
|
||||||
await nextTick();
|
await nextTick();
|
||||||
expect(["A:willRender", "B:willUpdateProps", "A:rendered"]).toBeLogged();
|
expect(steps.splice(0)).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
|
"A:willRender",
|
||||||
|
"B:willUpdateProps",
|
||||||
|
"A:rendered",
|
||||||
|
]
|
||||||
|
`);
|
||||||
|
|
||||||
// initiate a new render with deep=true. it should cancel the current render
|
// initiate a new render with deep=true. it should cancel the current render
|
||||||
// and also be blocked in B
|
// and also be blocked in B
|
||||||
parent.render(true);
|
parent.render(true);
|
||||||
await nextTick();
|
await nextTick();
|
||||||
expect(["A:willRender", "B:willUpdateProps", "A:rendered"]).toBeLogged();
|
expect(steps.splice(0)).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
|
"A:willRender",
|
||||||
|
"B:willUpdateProps",
|
||||||
|
"A:rendered",
|
||||||
|
]
|
||||||
|
`);
|
||||||
|
|
||||||
def.resolve();
|
def.resolve();
|
||||||
await nextTick();
|
await nextTick();
|
||||||
// we check here that the render reaches C (so, that it was properly forced)
|
// we check here that the render reaches C (so, that it was properly forced)
|
||||||
expect([
|
expect(steps.splice(0)).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
"B:willRender",
|
"B:willRender",
|
||||||
"C:willUpdateProps",
|
"C:willUpdateProps",
|
||||||
"B:rendered",
|
"B:rendered",
|
||||||
@@ -475,7 +525,8 @@ test("force render in case of existing render", async () => {
|
|||||||
"C:patched",
|
"C:patched",
|
||||||
"B:patched",
|
"B:patched",
|
||||||
"A:patched",
|
"A:patched",
|
||||||
]).toBeLogged();
|
]
|
||||||
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("children, default props and renderings", async () => {
|
test("children, default props and renderings", async () => {
|
||||||
@@ -503,7 +554,8 @@ test("children, default props and renderings", async () => {
|
|||||||
const parent = await mount(Parent, fixture);
|
const parent = await mount(Parent, fixture);
|
||||||
|
|
||||||
expect(fixture.innerHTML).toBe("Achild");
|
expect(fixture.innerHTML).toBe("Achild");
|
||||||
expect([
|
expect(steps.splice(0)).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
"Parent:setup",
|
"Parent:setup",
|
||||||
"Parent:willStart",
|
"Parent:willStart",
|
||||||
"Parent:willRender",
|
"Parent:willRender",
|
||||||
@@ -514,15 +566,18 @@ test("children, default props and renderings", async () => {
|
|||||||
"Child:rendered",
|
"Child:rendered",
|
||||||
"Child:mounted",
|
"Child:mounted",
|
||||||
"Parent:mounted",
|
"Parent:mounted",
|
||||||
]).toBeLogged();
|
]
|
||||||
|
`);
|
||||||
|
|
||||||
parent.state.value = "B";
|
parent.state.value = "B";
|
||||||
await nextTick();
|
await nextTick();
|
||||||
expect(fixture.innerHTML).toBe("Bchild");
|
expect(fixture.innerHTML).toBe("Bchild");
|
||||||
expect([
|
expect(steps.splice(0)).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
"Parent:willRender",
|
"Parent:willRender",
|
||||||
"Parent:rendered",
|
"Parent:rendered",
|
||||||
"Parent:willPatch",
|
"Parent:willPatch",
|
||||||
"Parent:patched",
|
"Parent:patched",
|
||||||
]).toBeLogged();
|
]
|
||||||
|
`);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1673,6 +1673,31 @@ describe("slots", () => {
|
|||||||
expect(fixture.innerHTML).toBe("<div><div><p>Ablip</p><div><p>Bblip</p></div></div></div>");
|
expect(fixture.innerHTML).toBe("<div><div><p>Ablip</p><div><p>Bblip</p></div></div></div>");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("named slot inside named slot in t-component", async () => {
|
||||||
|
class Child extends Component {
|
||||||
|
static template = xml`<t t-slot="brol"/>`;
|
||||||
|
}
|
||||||
|
class Parent extends Component {
|
||||||
|
static template = xml`
|
||||||
|
<Child>
|
||||||
|
<t t-set-slot="brol">
|
||||||
|
outer
|
||||||
|
<t t-component="Child">
|
||||||
|
<t t-set-slot="brol">
|
||||||
|
<t t-esc="value"/>
|
||||||
|
</t>
|
||||||
|
</t>
|
||||||
|
</t>
|
||||||
|
</Child>`;
|
||||||
|
static components = { Child };
|
||||||
|
Child = Child;
|
||||||
|
value = "inner";
|
||||||
|
}
|
||||||
|
await mount(Parent, fixture);
|
||||||
|
|
||||||
|
expect(fixture.innerHTML).toBe(" outer inner");
|
||||||
|
});
|
||||||
|
|
||||||
test("can render only empty slot", async () => {
|
test("can render only empty slot", async () => {
|
||||||
class Parent extends Component {
|
class Parent extends Component {
|
||||||
static template = xml`<t t-slot="default"/>`;
|
static template = xml`<t t-slot="default"/>`;
|
||||||
|
|||||||