Compare commits

...

79 Commits

Author SHA1 Message Date
Lucas Perais (lpe) b9f5a9aa47 [FIX] compiler, component: handle change of t-key before patch
Have a dynamic children with a t-key. This child has a delayed willStart.
Change the key during a rendering.

Before this commit there was a leak: a component corresponding to an old key had been created, xwithout being destroyed.

After this commit, the outdated component is destroyed.
2022-01-11 16:06:46 +01:00
Lucas Perais (lpe) a568ca6687 [FIX] test/helpers: useLogLifeCycle supports custom key 2022-01-11 15:59:45 +01:00
Lucas Perais (lpe) 5c324fa075 [FIX] app, components: dynamic t-call should propagate the key
Have a Component which has a Component node, and a dynamic t-call itself having
a Component node.

Before this commit, both children had the same `key`, (as in the key in parent.children, which registers on the parent all its children).

As a result, the scheduler was endlessly hanging.

After this commit, it works as expected.
2022-01-10 15:29:25 +01:00
Géry Debongnie 3945c009ed [REF] compiler: factorize a common pattern 2022-01-10 12:31:37 +01:00
Géry Debongnie 5b1132f01a [FIX] compiler: handle t-set as functions 2021-12-28 13:50:35 +01:00
Géry Debongnie f014b1a33e [DOC] update quick_start and how to test pages 2021-12-22 15:03:38 +01:00
Géry Debongnie 3f09a953b0 [REM] doc: remove overview page 2021-12-22 15:03:38 +01:00
Géry Debongnie b8e7ee5ff7 [DOC] update the tutorial todo app 2021-12-22 15:03:38 +01:00
Géry Debongnie 7fdca35a74 [FIX] reactivity: work even if no callback is given 2021-12-22 14:59:28 +01:00
Géry Debongnie 489e20843c [FIX] components: make sure t-ref work with t-if/t-else 2021-12-22 13:58:02 +01:00
Samuel Degueldre 34b781aeed [IMP] compiler: scope generated ids to their prefix
This means that unrelated ids (eg the id of a template, variable or key)
not longer share the same incrementing counter, meaning that you no
longer see a variable named "v2" unless another variable "v1" was
generated previously, this is also true for block data.
2021-12-22 13:30:09 +01:00
Géry Debongnie e8b0f31da6 [IMP] compiler: improve generated compiled code 2021-12-22 13:30:09 +01:00
Géry Debongnie d160c4a628 [FIX] useEffect: can depend on dom dependencies
Because the dependencies are now computed in patched.
2021-12-22 10:47:28 +01:00
Géry Debongnie 4542171a31 [FIX] portal: do not crash in dev mode
Before this commit, the props validation would fail in dev mode because
it did not expect a slot prop.
2021-12-21 21:43:46 +01:00
Géry Debongnie 0b1c4dd4ef [IMP] app: improve API, small refactoring 2021-12-21 12:12:48 +01:00
Géry Debongnie f4da50d350 [REF] build: do not output const enum definitions
We only use 2 const enums in the codebase, but they are defined in the
output, even though this is not useful in any way. This commit reduces
the final output by about 30 loc.
2021-12-21 09:09:36 +01:00
Géry Debongnie f2921abda8 [REM] component: remove support for css tag 2021-12-21 09:09:36 +01:00
Géry Debongnie 107200fd94 [IMP] components: improve props validation
to be able to specify that additional props are allowed
2021-12-21 09:02:45 +01:00
Lucas Perais (lpe) 0f8c859d5f [FIX] component: error_handling when an error is rethrown 2021-12-20 16:55:50 +01:00
Géry Debongnie cca8438d38 [REF] components: remove .el 2021-12-20 14:43:21 +01:00
Géry Debongnie a727347d60 [REF] tests: improve test helpers
- remove snapshotApp
- remove addTemplates
- simplify helpers
- make sure snapshotted templates are snapshotted with the app config
2021-12-20 12:43:36 +01:00
Lucas Perais (lpe) f19de73b0f [FIX] fiber, lifecycle: trigger a render during the fiber.complete
Have a component which does a render in its onWillPatch, onPatched, onMounted hooks.

Before this commit, the result was incorrect: the second rendering was not taken into account.

After this commit, those renderings are correctly applied at the price of a delayed render when the fiber
is in a critical state.
2021-12-20 10:54:51 +01:00
Géry Debongnie a8ffcafd23 [FIX] blockdom: properly handle falsy attributes
This commit fixes some issues with falsy attributes not being properly
set/removed in various situations. Also, the behaviour was not
consistent between normal attribute (key/value) and generic attributes
(pair or object)
2021-12-16 15:07:27 +01:00
Géry Debongnie a2f01ef4ad [FIX] components: improve error handling
Owl provides a way to manage errors occuring in component lifecycle
methods. However, before this commit, these errors were not always
logged or visible, which is very annoying in the common developer
workflow (doing something, checking it works, seeing no error but a
broken interface).

In this commit, we make sure errors are logged/throws in all cases:

- if an error occurs in a mounting operation => the promise is rejected
(which will log the error)
- if an error occurs after the mounting operation and is not handled by
any error handlers => the error will be logged (with console.error).
Also, in that case, this commit adds a warning to explain that owl
destroys the root component, which will help developers understanding
what happened.
2021-12-16 13:29:31 +01:00
Géry Debongnie d7de25e867 [FIX] compiler: properly handle <t> tags in some cases
The problem was that the compiler is based on the assumption that the
multi block received by the parser only occurs in some cases
where the structure of the template require a multi block, and it does
not work when we have random multiblock elsewhere.

We could fix the issue by modifying the code generator code to support
these usecases, or by simply removing these cases in the parser. Since
this seems more efficient, this is the approach taken by this commit.

Note that it was a good opportunity to simplify the parser.
2021-12-15 15:32:56 +01:00
Géry Debongnie 424bc480e2 [DOC] update changelog 2021-12-14 16:03:10 +01:00
Géry Debongnie 421f400766 [DOC] reorganize doc, unskip test, fix some links 2021-12-14 09:45:25 +01:00
Géry Debongnie c37f3445f6 [FIX] blockdom: ignore attributes with undefined value 2021-12-13 15:07:03 +01:00
Géry Debongnie 4cde06d685 [IMP] component: add .bind suffix to props for easy binding 2021-12-13 12:43:23 +01:00
Lucas Perais (lpe) 7b95315b87 adapt to fix and to fixup 2021-12-13 12:39:43 +01:00
Géry Debongnie 09761ddd8e fixup, maybe 2021-12-13 12:39:43 +01:00
Lucas Perais (lpe) b3c6ec2b48 [FIX] component: render in delayed willUpdateProps
Have a child component on which a render is triggered.
This component delays its willUpdateProps and makes a rendering during the willUpdateProps

Before this commit, renderings of the child were inconsistent across
its parent's renderings.

After this commit, it works as expected.
2021-12-13 12:39:43 +01:00
Lucas Perais (lpe) b20462ada6 [FIX] app: factorize to allow smoother developments in projects
It should be usefull to allow developpers to implement mounting/unmounting
if they wish to.
2021-12-13 09:49:48 +01:00
Lucas Perais (lpe) 25000b36be [FIX] blockdom: do not propagate svg namespace to siblings 2021-12-03 14:01:44 +01:00
Lucas Perais (lpe) 144d4a253c [FIX] hooks: useSubEnv supports arbitrary descriptors in env
Before this commit, when defining a getter in the env passed to useSubEnv,
the value was read, losing the definition of the property.

After this commit, declaring a getter in the env works as expected:
the property stays a getter.
2021-12-03 08:06:29 +01:00
Lucas Perais (lpe) 9d48bda227 [FIX] app: support for arbitrary descriptors in env
Before this commit, when defining a getter in the env passed to the App,
the value was read, losing the definition of the property.

After this commit, declaring a getter in the env works as expected:
the property stays a getter.
2021-12-03 08:06:29 +01:00
Lucas Perais (lpe) c8db663869 [FIX] parser: correctly parse pre node within a div with new lines 2021-12-03 08:03:45 +01:00
Lucas Perais (lpe) 247200194f [FIX] component: error handling in class inheritance
Before this commit, class inheritance when using the onError hook was unclear nay wrong.

After this commit, error handlers are called from the bottom up  in the inheritance hierarchy.
If a handler doesn't rethrow the error, the handling stops there and no other handler is called.
If a handler does rethrow, the handlers declared in a parent class are executed.
2021-12-01 17:29:26 +01:00
Géry Debongnie 60b8817ac0 [REF] compiler: simplify all compiled templates 2021-12-01 17:25:31 +01:00
Géry Debongnie e008966291 [FIX] compiler: allow t-if with empty content 2021-12-01 13:22:32 +01:00
Géry Debongnie e2fedc6eff [REF] components: unskip concurrency test 2021-12-01 13:22:32 +01:00
Géry Debongnie b3fb9a35bf [FIX] move error handling out of fiber, fix complicated mounted issues 2021-12-01 12:07:26 +01:00
Géry Debongnie 240259568e [FIX] component: improve error handling
In the following situation: A parent of B, B parent of C, with an error
when C is mounted, caught by B and retriggering a rendering in B, then
the onMounted hook of A wasn't properly called. This commit fixes this
problem.
2021-12-01 12:07:26 +01:00
Géry Debongnie 18fb67eaad [FIX] blockdom: properly handle references
Before this commit, there were situations where the reference numbers
were not properly set, which caused the blocks generated to crash
because the algorithm could not get correct references.
2021-12-01 09:34:55 +01:00
Géry Debongnie e946967867 [IMP] component: render does not return a promise anymore 2021-11-30 08:03:17 +01:00
Géry Debongnie 777b2aae5e [IMP] add support for top level comments 2021-11-29 15:36:45 +01:00
Géry Debongnie 0831bb54e3 [REF] component: remove onDestroyed, implement onWillDestroy 2021-11-29 14:59:01 +01:00
Géry Debongnie 03f34a38dc [TESTS] test lifecycle in reactivity tests 2021-11-29 08:42:47 +01:00
Géry Debongnie dcefd26bee [REF] tests: improve useLogLifecycle and helpers 2021-11-29 08:42:47 +01:00
Samuel Degueldre 922dab8e8f [FIX] reactivity: only call clearReactivesForCallback once on unmount 2021-11-26 16:22:38 +01:00
Samuel Degueldre 99740f9993 [FIX] reactivity: fix memory leak 2021-11-26 15:55:02 +01:00
Géry Debongnie 0b79b1c8fd [FIX] compiler: readd template name in compiled code 2021-11-26 09:17:49 +01:00
Géry Debongnie 5b0dce94cf [REF] code_generator: move generating code to CodeTarget
Before this commit, we had two places with code that generate a function
code. Now, all this code is moved in a method 'generateCode' on
CodeTarget.
2021-11-26 09:17:49 +01:00
Géry Debongnie a1d435c5a5 [FIX] compiler: call dynamic templates with correct this 2021-11-25 17:29:30 +01:00
Géry Debongnie 13c3178760 [FIX] slots: properly bind this in t-on arrow functions 2021-11-25 14:45:30 +01:00
Géry Debongnie 2b565ce1b4 [REF] component: small cleanup
This commit makes it simpler to understand the way fibers are assigned
to nodes.
2021-11-25 11:34:23 +01:00
Géry Debongnie cfcf2c6714 [FIX] component: concurrency issue
When a parent and a child were rendered at the same time, it was
possible for the 2 renders to decrement the same fiber internal
counter, which meant that the render was stalled.
2021-11-25 11:12:31 +01:00
Samuel Degueldre 92174559a1 [FIX] slots: allow t-call and components in slot default content 2021-11-24 15:47:51 +01:00
Bruno Boi 840348892f [IMP] owl: upgrade rollup-plugin-typescript2 to version 0.31.1 2021-11-24 11:45:12 +01:00
Samuel Degueldre b988a68b6f [IMP] parser: normalize document before parsing 2021-11-24 11:19:45 +01:00
Samuel Degueldre 7869a1f2c6 [IMP] components: add test for template string in props 2021-11-24 10:09:52 +01:00
Samuel Degueldre 9e81d14d50 [IMP] parser: throw when using unsupported directive on component 2021-11-24 10:09:52 +01:00
Samuel Degueldre 0e4a55ba09 [FIX] components: allow prop names that are not valid bare property name 2021-11-24 10:09:52 +01:00
Mathieu Duckerts-Antoine 6e9b68dafa [FIX] props: prop names can contain - 2021-11-23 10:20:45 +01:00
Bruno Boi ba7c9063c0 Update CHANGELOG.md 2021-11-23 10:09:39 +01:00
Mathieu Duckerts-Antoine 3a361876ad [IMP] slots: via prop 'slots'
The slot inner working has been reworked. A prop "slots" is now passed
explicitely to the component. It looks like

{ slotName_1: slotInfo_1, ..., slotName_m: slotInfo_m }

with the objects slotInfo_i with mandatory keys "__render", "__ctx",
and optional key "__scope" and possibly others.

Here is how a slotInfo object can be created:
A slotInfo object is normally created by setting in a template something
like

<div>
    <t t-set-slot="foo" t-set-scope="scope" param_1="var" param_2="3">
        content
        <t t-esc="scope.bool"/>
        <t t-esc="scope.num"/>
    </t>
</div>

and it will be used somewhere like

<div>
    <t t-esc="props.slots.foo.param_1"/>
    <t t-slot="foo" bool="other_var" num="5">
</div>

In the above example, the function "__render" produces the block dom
element for the content of the t-set-slot.
The context "__ctx" will have a key "scope" with value { bool: ..., num: 5 }
and "__scope" will be set to "scope".
2021-11-22 16:36:43 +01:00
Samuel Degueldre 58b8572f0a [FIX] components: capture context in prop expressions 2021-11-22 13:18:17 +01:00
Samuel Degueldre c23637e6d8 [FIX] components: throw on duplicate t-key instead of hanging the app 2021-11-22 11:11:49 +01:00
Géry Debongnie 4a4b1fbba5 [IMP] app: add templates in app config
Also, improve the parsing code
2021-11-22 10:56:16 +01:00
Géry Debongnie 536d9e1762 [REM] tools: remove benchmarks/debug script
They are either no longer relevant, or less useful than some
alternatives (such as the js framework benchmark project)
2021-11-22 10:56:16 +01:00
Lucas Perais (lpe) 6ed68372a6 [FIX] package: bump owl version to 2.0.0-alpha1 2021-11-22 10:49:51 +01:00
Lucas Perais (lpe) efd934d2b1 [FIX] tools: adapt playground to owl 2 2021-11-19 16:11:28 +01:00
Lucas Perais (lpe) dabc24cee3 [FIX] index, reactivity: export reactive function in index 2021-11-19 16:11:28 +01:00
Samuel Degueldre 7f49796a07 [IMP] misc: update typescript to 4.5.2 2021-11-19 14:42:37 +01:00
Géry Debongnie 757dffefac [IMP] components: rename onRender->onWillRender, add onRendered 2021-11-19 13:26:44 +01:00
Samuel Degueldre bdfe058279 [IMP] reactivity: overhaul reactivity system
This commit makes the reactivity system more fine grained and makes it
more eager to stop observing keys or objects when they are modified,
this results in fewer "false positive" notifications.
2021-11-19 13:20:37 +01:00
Bruno Boi 345c44b952 fixup! [IMP] svg namespace support 2021-11-19 12:47:51 +01:00
Bruno Boi ea74739d46 [IMP] svg namespace support 2021-11-19 11:55:18 +01:00
Géry Debongnie 93b53d8017 [FIX] remove cyclic dependency, improve error typing (#982) 2021-11-18 10:44:49 +01:00
205 changed files with 15045 additions and 77028 deletions
+30 -4
View File
@@ -1,4 +1,4 @@
# ChangeLog # Changelog
This document contains an overview of all changes between Owl 1.x and This document contains an overview of all changes between Owl 1.x and
Owl 2.x, with some pointers on how to update the code. Owl 2.x, with some pointers on how to update the code.
@@ -14,7 +14,7 @@ removed after.
- components can now have empty content or multiple root nodes (htmlelement or text) ([details](#31-components-can-now-have-arbitrary-content)) - components can now have empty content or multiple root nodes (htmlelement or text) ([details](#31-components-can-now-have-arbitrary-content))
- new `useEffect` hook - new `useEffect` hook
- new `onDestroyed` and `onRender` hooks - new `onDestroyed`, `onWillRender` and `onRendered` hooks
- breaking: lifecycle methods are removed ([details](#1-component-lifecycle-methods-are-removed)) - breaking: lifecycle methods are removed ([details](#1-component-lifecycle-methods-are-removed))
- breaking: can no longer be mounted on detached DOM ([details](#2-components-can-no-longer-be-mounted-in-a-detached-dom-element)) - breaking: can no longer be mounted on detached DOM ([details](#2-components-can-no-longer-be-mounted-in-a-detached-dom-element))
- breaking: standalone `mount` method API is simpler ([details](#4-mount-method-api-is-simpler)) - breaking: standalone `mount` method API is simpler ([details](#4-mount-method-api-is-simpler))
@@ -61,6 +61,7 @@ removed after.
- breaking: `env` is now frozen ([details](#28-env-is-now-frozen)) - breaking: `env` is now frozen ([details](#28-env-is-now-frozen))
- breaking: `t-ref` does not work on components ([details](#29-t-ref-does-not-work-on-component)) - breaking: `t-ref` does not work on components ([details](#29-t-ref-does-not-work-on-component))
- breaking: `t-on` does not accept expressions, only functions ([details](#30-t-on-does-not-accept-expressions-only-functions)) - breaking: `t-on` does not accept expressions, only functions ([details](#30-t-on-does-not-accept-expressions-only-functions))
- breaking: `renderToString` function on qweb has been removed ([details](#32-rendertostring-on-qweb-has-been-removed))
## Details/Rationale/Migration ## Details/Rationale/Migration
@@ -447,8 +448,10 @@ bus.addEventListener('event-name', callback);
Rationale: it makes it easier to have just one interface to remember, it makes Rationale: it makes it easier to have just one interface to remember, it makes
the code simpler the code simpler
Migration: most bus methods need to be adapted. So, `bus.on(...)` has to be Migration: most bus methods need to be adapted. So, `bus.on("event-type", owner, (info) => {...})` has to be
rewritten like this: `bus.addEventListener(...)`. rewritten like this: `bus.addEventListener("event-type", (({detail: info}) => {...}).bind(owner))`.
Do not forget to similarly replace `bus.off(...)` by `bus.removeEventListener(...)`
### 22. `Store` is removed ### 22. `Store` is removed
@@ -584,3 +587,26 @@ So, the following template works for components:
<div>2</div> <div>2</div>
hello hello
``` ```
### 32. `renderToString` on QWeb has been removed
Rationale: the `renderToString` function was a qweb method, which made sense because
the qweb instance knew all templates. But now, the closest analogy is the `App`
class, but it is not as convenient, since the `app` instance is no longer visible
to components (while before, `qweb` was in the environment).
Also, this can easily be done in userspace, by mounting a component in a div. For example:
```js
export async function renderToString(template, context) {
class C extends Component {
static template = template;
}
const div = document.createElement('div');
document.body.appendChild(div);
const component = await mount(C, div);
const result = div.innerHTML;
app.destroy();
div.remove();
return result;
}
+55 -55
View File
@@ -1,4 +1,4 @@
<h1 align="center">🦉 <a href="https://odoo.github.io/owl/">OWL Framework</a> 🦉</h1> <h1 align="center">🦉 <a href="https://odoo.github.io/owl/">Owl Framework</a> 🦉</h1>
[![License: LGPL v3](https://img.shields.io/badge/License-LGPL%20v3-blue.svg)](https://www.gnu.org/licenses/lgpl-3.0) [![License: LGPL v3](https://img.shields.io/badge/License-LGPL%20v3-blue.svg)](https://www.gnu.org/licenses/lgpl-3.0)
[![npm version](https://badge.fury.io/js/@odoo%2Fowl.svg)](https://badge.fury.io/js/@odoo%2Fowl) [![npm version](https://badge.fury.io/js/@odoo%2Fowl.svg)](https://badge.fury.io/js/@odoo%2Fowl)
@@ -6,10 +6,12 @@
_Class based components with hooks, reactive state and concurrent mode_ _Class based components with hooks, reactive state and concurrent mode_
**Try it online!** you can experiment with the Owl framework in an online [playground](https://odoo.github.io/owl/playground).
## Project Overview ## Project Overview
The Odoo Web Library (OWL) is a smallish (~<20kb gzipped) UI framework intended to The Odoo Web Library (Owl) is a smallish (~<20kb gzipped) UI framework built by
be the basis for the [Odoo](https://www.odoo.com/) Web Client. Owl is a modern [Odoo](https://www.odoo.com/) for its products. Owl is a modern
framework, written in Typescript, taking the best ideas from React and Vue in a framework, written in Typescript, taking the best ideas from React and Vue in a
simple and consistent way. Owl's main features are: simple and consistent way. Owl's main features are:
@@ -17,39 +19,26 @@ simple and consistent way. Owl's main features are:
- a reactivity system based on hooks, - a reactivity system based on hooks,
- concurrent mode by default, - concurrent mode by default,
Owl components are defined with ES6 classes, they use QWeb templates, an Owl components are defined with ES6 classes and xml templates, uses an
underlying virtual DOM, integrates beautifully with hooks, and the rendering is underlying virtual DOM, integrates beautifully with hooks, and the rendering is
asynchronous. asynchronous.
**Try it online!** An online playground is available at Quick links:
[https://odoo.github.io/owl/playground](https://odoo.github.io/owl/playground)
to let you experiment with the Owl framework. There are some code examples to
showcase some interesting features.
Owl is currently stable. Possible future changes are explained in the - [documentation](#documentation),
[roadmap](roadmap.md). - [changelog](CHANGELOG.md) (from Owl 1.x to 2.x),
- [playground](https://odoo.github.io/owl/playground)
## Why Owl?
Why did Odoo decide to make Yet Another Framework? This is really a question
that deserves [a long answer](doc/miscellaneous/why_owl.md). But in short, we believe that
while the current state of the art frameworks are excellent, they are not
optimized for our use case, and there is still room for something else.
If you are interested in a comparison with React or Vue, you will
find some more additional information [here](doc/miscellaneous/comparison.md).
## Example ## Example
Here is a short example to illustrate interactive components: Here is a short example to illustrate interactive components:
```javascript ```javascript
const { Component, useState, mount } = owl; const { Component, useState, mount, xml } = owl;
const { xml } = owl.tags;
class Counter extends Component { class Counter extends Component {
static template = xml` static template = xml`
<button t-on-click="state.value++"> <button t-on-click="() => state.value++">
Click Me! [<t t-esc="state.value"/>] Click Me! [<t t-esc="state.value"/>]
</button>`; </button>`;
@@ -66,7 +55,7 @@ class App extends Component {
static components = { Counter }; static components = { Counter };
} }
mount(App, { target: document.body }); mount(App, document.body);
``` ```
Note that the counter component is made reactive with the [`useState` hook](doc/reference/hooks.md#usestate). Note that the counter component is made reactive with the [`useState` hook](doc/reference/hooks.md#usestate).
@@ -76,41 +65,55 @@ But this is not mandatory, many applications will load templates separately.
More interesting examples can be found on the More interesting examples can be found on the
[playground](https://odoo.github.io/owl/playground) application. [playground](https://odoo.github.io/owl/playground) application.
## Design Principles
OWL is designed to be used in highly dynamic applications where changing
requirements are common and code needs to be maintained by large teams.
- **XML based**: templates are based on the XML format, which allows interesting
applications. For example, they could be stored in a database and modified
dynamically with `xpaths`.
- **templates compilation in the browser**: this may not be a good fit for all
applications, but if you need to generate dynamically user interfaces in the
browser, this is very powerful. For example, a generic form view component
could generate a specific form user interface for each various models, from a XML view.
- **no toolchain required**: this is extremely useful for some applications, if,
for various reasons (security/deployment/dynamic modules/specific assets tools),
it is not ok to use standard web tools based on `npm`.
Owl is not designed to be fast nor small (even though it is quite good on those
two topics). It is a no nonsense framework to build applications. There is only
one way to define components (with classes). There is no black magic. It just
works.
## Documentation ## Documentation
A complete documentation for Owl can be found here: ### Learning Owl
- [Main documentation page](doc/readme.md). Are you new to Owl? This is the place to start!
Some of the most important pages are: - [Tutorial: create a TodoList application](doc/learning/tutorial_todoapp.md)
- [Tutorial: TodoList application](doc/learning/tutorial_todoapp.md)
- [How to start an Owl project](doc/learning/quick_start.md) - [How to start an Owl project](doc/learning/quick_start.md)
- [QWeb templating language](doc/reference/qweb_templating_language.md) - [How to test Components](doc/learning/how_to_test.md)
- [How to write Single File Components](doc/learning/how_to_write_sfc.md)
### Reference
You will find here a complete reference of every feature, class or object
provided by Owl.
- [Animations](doc/reference/animations.md)
- [Browser](doc/reference/browser.md)
- [Component](doc/reference/component.md) - [Component](doc/reference/component.md)
- [Content](doc/reference/content.md)
- [Concurrency Model](doc/reference/concurrency_model.md)
- [Configuration](doc/reference/config.md)
- [Context](doc/reference/context.md)
- [Environment](doc/reference/environment.md)
- [Event Bus](doc/reference/event_bus.md)
- [Event Handling](doc/reference/event_handling.md)
- [Error Handling](doc/reference/error_handling.md)
- [Hooks](doc/reference/hooks.md) - [Hooks](doc/reference/hooks.md)
- [Mounting a component](doc/reference/mounting.md)
- [Miscellaneous Components](doc/reference/misc.md)
- [Observer](doc/reference/observer.md)
- [Props](doc/reference/props.md)
- [Props Validation](doc/reference/props_validation.md)
- [QWeb Templating Language](doc/reference/qweb_templating_language.md)
- [QWeb Engine](doc/reference/qweb_engine.md)
- [Slots](doc/reference/slots.md)
- [Tags](doc/reference/tags.md)
- [Utils](doc/reference/utils.md)
### Other Topics
This section provides miscellaneous document that explains some topics
which cannot be considered either a tutorial, or reference documentation.
- [Owl architecture: the Virtual DOM](doc/miscellaneous/vdom.md)
- [Owl architecture: the rendering pipeline](doc/miscellaneous/rendering.md)
- [Comparison with React/Vue](doc/miscellaneous/comparison.md)
- [Why did Odoo built Owl?](doc/miscellaneous/why_owl.md)
## Installing Owl ## Installing Owl
@@ -125,6 +128,3 @@ If you want to use a simple `<script>` tag, the last release can be downloaded h
- [owl-1.4.7](https://github.com/odoo/owl/releases/tag/v1.4.7) - [owl-1.4.7](https://github.com/odoo/owl/releases/tag/v1.4.7)
## License
OWL is [LGPL licensed](./LICENSE).
-43
View File
@@ -1,43 +0,0 @@
# 🦉 How to debug Owl applications 🦉
Non trivial applications become quickly more difficult to understand. It is then
useful to have a solid understanding of what is going on. To help with that,
logging useful information is extremely valuable. There is a [javascript file](../../tools/debug.js) which can be evaluated in an application.
Once it is executed, it will log a lot of information on each component main hooks. The following code is a minified version to make it easier to copy/paste:
```
function debugOwl(t,e){let n,o="[OWL_DEBUG]";function r(t){let e;try{e=JSON.stringify(t||{})}catch(t){e="<JSON error>"}return e.length>200&&(e=e.slice(0,200)+"..."),e}if(Object.defineProperty(t.Component,"current",{get:()=>n,set(s){n=s;const i=s.constructor.name;if(e.componentBlackList&&e.componentBlackList.test(i))return;if(e.componentWhiteList&&!e.componentWhiteList.test(i))return;let l;Object.defineProperty(n,"__owl__",{get:()=>l,set(n){!function(n,s,i){let l=`${s}<id=${i}>`,c=t=>console.log(`${o} ${l} ${t}`),u=t=>(!e.methodBlackList||!e.methodBlackList.includes(t))&&!(e.methodWhiteList&&!e.methodWhiteList.includes(t));u("constructor")&&c(`constructor, props=${r(n.props)}`);u("willStart")&&t.hooks.onWillStart(()=>{c("willStart")});u("mounted")&&t.hooks.onMounted(()=>{c("mounted")});u("willUpdateProps")&&t.hooks.onWillUpdateProps(t=>{c(`willUpdateProps, nextprops=${r(t)}`)});u("willPatch")&&t.hooks.onWillPatch(()=>{c("willPatch")});u("patched")&&t.hooks.onPatched(()=>{c("patched")});u("willUnmount")&&t.hooks.onWillUnmount(()=>{c("willUnmount")});const d=n.__render.bind(n);n.__render=function(...t){c("rendering template"),d(...t)};const h=n.render.bind(n);n.render=function(...t){const e=n.__owl__;let o="render";return e.isMounted||e.currentFiber||(o+=" (warning: component is not mounted, this render has no effect)"),c(o),h(...t)};const p=n.mount.bind(n);n.mount=function(...t){return c("mount"),p(...t)}}(s,i,(l=n).id)}})}}),e.logScheduler){let e=t.Component.scheduler.start,n=t.Component.scheduler.stop;t.Component.scheduler.start=function(){this.isRunning||console.log(`${o} scheduler: start running tasks queue`),e.call(this)},t.Component.scheduler.stop=function(){this.isRunning&&console.log(`${o} scheduler: stop running tasks queue`),n.call(this)}}if(e.logStore){let e=t.Store.prototype.dispatch;t.Store.prototype.dispatch=function(t,...n){return console.log(`${o} store: action '${t}' dispatched. Payload: '${r(n)}'`),e.call(this,t,...n)}}}
debugOwl(owl, {
// componentBlackList: /App/, // regexp
// componentWhiteList: /SomeComponent/, // regexp
// methodBlackList: ["mounted"], // list of method names
// methodWhiteList: ["willStart"], // list of method names
logScheduler: false, // display/mute scheduler logs
logStore: true, // display/mute store logs
});
```
The above code, once pasted somewhere in the main javascript file of an owl
application, will log information looking like this:
```
[OWL_DEBUG] TodoApp<id=1> constructor, props={}
[OWL_DEBUG] TodoApp<id=1> mount
[OWL_DEBUG] TodoApp<id=1> willStart
[OWL_DEBUG] TodoApp<id=1> rendering template
[OWL_DEBUG] TodoItem<id=2> constructor, props={"id":2,"completed":false,"title":"hey"}
[OWL_DEBUG] TodoItem<id=2> willStart
[OWL_DEBUG] TodoItem<id=3> constructor, props={"id":4,"completed":false,"title":"aaa"}
[OWL_DEBUG] TodoItem<id=3> willStart
[OWL_DEBUG] TodoItem<id=2> rendering template
[OWL_DEBUG] TodoItem<id=3> rendering template
[OWL_DEBUG] TodoItem<id=3> mounted
[OWL_DEBUG] TodoItem<id=2> mounted
[OWL_DEBUG] TodoApp<id=1> mounted
```
Each component has an internal `id`, which is very useful when debugging.
Note that it is certainly useful to run this code at some point in an application,
just to get a feel of what each user action implies, for the framework.
+11 -46
View File
@@ -30,27 +30,21 @@ To help with this, it is useful to have a `helper.js` file that contains some
common utility functions: common utility functions:
```js ```js
let lastFixture = null;
export function makeTestFixture() { export function makeTestFixture() {
let fixture = document.createElement("div"); let fixture = document.createElement("div");
document.body.appendChild(fixture); document.body.appendChild(fixture);
if (lastFixture) {
lastFixture.remove();
}
lastFixture = fixture;
return fixture; return fixture;
} }
export function nextTick() { export async function nextTick() {
let requestAnimationFrame = owl.Component.scheduler.requestAnimationFrame; await new Promise((resolve) => setTimeout(resolve));
return new Promise(function(resolve) { await new Promise((resolve) => requestAnimationFrame(resolve));
setTimeout(() => requestAnimationFrame(() => resolve()));
});
}
export function makeTestEnv() {
// application specific. It needs a way to load actual templates
const templates = ...;
return {
qweb: new QWeb(templates),
..., // each service can be mocked here
};
} }
``` ```
@@ -59,7 +53,7 @@ With such a file, a typical test suite for Jest will look like this:
```js ```js
// in SomeComponent.test.js // in SomeComponent.test.js
import { SomeComponent } from "../../src/ui/SomeComponent"; import { SomeComponent } from "../../src/ui/SomeComponent";
import { nextTick, makeTestFixture, makeTestEnv} from '../helpers'; import { nextTick, makeTestFixture } from '../helpers';
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@@ -70,9 +64,6 @@ let env: Env;
beforeEach(() => { beforeEach(() => {
fixture = makeTestFixture(); fixture = makeTestFixture();
env = makeTestEnv();
// we set here the default environment for each component created in the test
Component.env = env;
}); });
afterEach(() => { afterEach(() => {
@@ -85,7 +76,7 @@ afterEach(() => {
describe("SomeComponent", () => { describe("SomeComponent", () => {
test("component behaves as expected", async () => { test("component behaves as expected", async () => {
const props = {...}; // depends on the component const props = {...}; // depends on the component
const comp = await mount(SomeComponent, { target: fixture, props }); const comp = await mount(SomeComponent, fixture, { props });
// do some assertions // do some assertions
expect(...).toBe(...); expect(...).toBe(...);
@@ -102,29 +93,3 @@ describe("SomeComponent", () => {
Note that Owl does wait for the next animation frame to actually update the DOM. Note that Owl does wait for the next animation frame to actually update the DOM.
This is why it is necessary to wait with the `nextTick` (or other methods) to This is why it is necessary to wait with the `nextTick` (or other methods) to
make sure that the DOM is up-to-date. make sure that the DOM is up-to-date.
It is sometimes useful to wait until Owl is completely done updating components
(in particular, if we have a highly concurrent user interface). This next
helper simply polls every 20ms the internal Owl task queue and returns a promise
which resolves when it is empty:
```js
function afterUpdates() {
return new Promise((resolve, reject) => {
let timer = setTimeout(poll, 20);
let counter = 0;
function poll() {
counter++;
if (owl.Component.scheduler.tasks.length) {
if (counter > 10) {
reject(new Error("timeout"));
} else {
timer = setTimeout(poll);
}
} else {
resolve();
}
}
});
}
```
-133
View File
@@ -1,133 +0,0 @@
# 🦉 Quick Overview 🦉
Owl components in an application are used to define a (dynamic) tree of components.
```
Root
/ \
A B
/ \
C D
```
**State:** each component can manage its own local state. It is a simple ES6
class, there are no special rules:
```js
class Counter extends Component {
static template = xml`
<button t-on-click="increment">
Click Me! [<t t-esc="state.value"/>]
</button>`;
state = { value: 0 };
increment() {
this.state.value++;
this.render();
}
}
```
The example above shows a component with a local state. Note that since there
is nothing magical to the `state` object, we need to manually call the `render`
function whenever we update it. This can quickly become annoying (and not
efficient if we do it too much). There is a better way: using the `useState`
hook, which transforms an object into a reactive version of itself:
```js
const { useState } = owl.hooks;
class Counter extends Component {
static template = xml`
<button t-on-click="increment">
Click Me! [<t t-esc="state.value"/>]
</button>`;
state = useState({ value: 0 });
increment() {
this.state.value++;
}
}
```
Note that the `t-on-click` handler can even be replaced by an inline statement:
```xml
<button t-on-click="state.value++">
```
**Props:** sub components often needs some information from their parents. This
is done by adding the required information to the template. This will then be
accessible by the sub component in the `props` object. Note that there is an
important rule here: the information contained in the `props` object is not
owned by the sub component, and should never be modified.
```js
class Child extends Component {
static template = xml`<div>Hello <t t-esc="props.name"/></div>`;
}
class Parent extends Component {
static template = xml`
<div>
<Child name="'Owl'" />
<Child name="'Framework'" />
</div>`;
static components = { Child };
}
```
**Communication:** there are multiple ways to communicate information between
components. However, the two most important ways are the following:
- from parent to children: by using `props`,
- from a children to one of its parent: by triggering events.
The following example illustrate both mechanisms:
```js
class OrderLine extends Component {
static template = xml`
<div t-on-click="add">
<div><t t-esc="props.line.name"/></div>
<div>Quantity: <t t-esc="props.line.quantity"/></div>
</div>`;
add() {
this.trigger("add-to-order", { line: this.props.line });
}
}
class Parent extends Component {
static template = xml`
<div t-on-add-to-order="addToOrder">
<OrderLine
t-foreach="orders"
t-as="line"
line="line" />
</div>`;
static components = { OrderLine };
orders = useState([
{ id: 1, name: "Coffee", quantity: 0 },
{ id: 2, name: "Tea", quantity: 0 },
]);
addToOrder(event) {
const line = event.detail.line;
line.quantity++;
}
}
```
In this example, the `OrderLine` component trigger a `add-to-order` event. This
will generate a DOM event which will bubble along the DOM tree. It will then be
intercepted by the parent component, which will then get the line (from the
`detail` key) and then increment its quantity. See the page on [event handling](../reference/event_handling.md)
for more details on how events work.
Note that this example would have also worked if the `OrderLine` component
directly modifies the `line` object. However, this is not a good practice: this
only works because the `props` object received by the child component is reactive,
so the child component is then coupled to the parents implementation.
+38 -47
View File
@@ -36,6 +36,8 @@ hello_owl/
The file `owl.js` can be downloaded from the last release published at The file `owl.js` can be downloaded from the last release published at
[https://github.com/odoo/owl/releases](https://github.com/odoo/owl/releases). It [https://github.com/odoo/owl/releases](https://github.com/odoo/owl/releases). It
is a single javascript file which export all Owl into the global `owl` object. is a single javascript file which export all Owl into the global `owl` object.
Note that there are multiple files, and in this case, we need one of the two
files suffixed with `.iife`: they are built to be directly used in a browser.
Now, `index.html` should contain the following: Now, `index.html` should contain the following:
@@ -45,30 +47,24 @@ Now, `index.html` should contain the following:
<head> <head>
<title>Hello Owl</title> <title>Hello Owl</title>
<script src="owl.js"></script> <script src="owl.js"></script>
<script src="app.js"></script>
</head> </head>
<body></body> <body>
<script src="app.js"></script>
</body>
</html> </html>
``` ```
And `app.js` should look like this: And `app.js` should look like this:
```js ```js
const { Component, mount } = owl; const { Component, mount, xml } = owl;
const { xml } = owl.tags;
const { whenReady } = owl.utils;
// Owl Components // Owl Components
class App extends Component { class Root extends Component {
static template = xml`<div>Hello Owl</div>`; static template = xml`<div>Hello Owl</div>`;
} }
// Setup code mount(Root, document.body);
function setup() {
mount(App, target: { document.body })
}
whenReady(setup);
``` ```
Now, simply loading this html file in a browser should display a welcome message. Now, simply loading this html file in a browser should display a welcome message.
@@ -93,14 +89,16 @@ Let us start a new project with the following file structure:
``` ```
hello_owl/ hello_owl/
src/ src/
app.js
index.html index.html
main.js main.js
owl.js owl.js
root.js
``` ```
As previously, the file `owl.js` can be downloaded from the last release published at As previously, the file `owl.js` can be downloaded from the last release published at
[https://github.com/odoo/owl/releases](https://github.com/odoo/owl/releases). [https://github.com/odoo/owl/releases](https://github.com/odoo/owl/releases).
Note that there are multiple files, and in this case, we need one of the two
files suffixed with `.iife`: they are built to be directly used in a browser.
Now, `index.html` should contain the following: Now, `index.html` should contain the following:
@@ -110,37 +108,33 @@ Now, `index.html` should contain the following:
<head> <head>
<title>Hello Owl</title> <title>Hello Owl</title>
<script src="owl.js"></script> <script src="owl.js"></script>
<script src="main.js" type="module"></script>
</head> </head>
<body></body> <body>
<script src="main.js" type="module"></script>
</body>
</html> </html>
``` ```
Not that the `main.js` script tag has the `type="module"` attribute. This means Not that the `main.js` script tag has the `type="module"` attribute. This means
that the browser will parse the script as a module, and load all its dependencies. that the browser will parse the script as a module, and load all its dependencies.
Here is the content of `app.js` and `main.js`: Here is the content of `root.js` and `main.js`:
```js ```js
// app.js ---------------------------------------------------------------------- // root.js ----------------------------------------------------------------------
const { Component, mount } = owl; const { Component, mount, xml } = owl;
const { xml } = owl.tags;
export class App extends Component { export class Root extends Component {
static template = xml`<div>Hello Owl</div>`; static template = xml`<div>Hello Owl</div>`;
} }
// main.js --------------------------------------------------------------------- // main.js ---------------------------------------------------------------------
import { App } from "./app.js"; import { Root } from "./root.js";
function setup() { mount(Root, document.body);
mount(App, { target: document.body });
}
owl.utils.whenReady(setup);
``` ```
The `main.js` file import the `app.js` file. Note that the import statement has The `main.js` file imports the `root.js` file. Note that the import statement has
a `.js` suffix, which is important. Most text editor can understand this syntax a `.js` suffix, which is important. Most text editor can understand this syntax
and will provide autocompletion. and will provide autocompletion.
@@ -193,11 +187,11 @@ hello_owl/
index.html index.html
src/ src/
components/ components/
App.js Root.js
main.js main.js
tests/ tests/
components/ components/
App.test.js Root.test.js
helpers.js helpers.js
.gitignore .gitignore
package.json package.json
@@ -224,13 +218,15 @@ Note that there are no `<script>` tag here. They will be injected by webpack.
Now, let's have a look at the javascript files: Now, let's have a look at the javascript files:
```js ```js
// src/components/App.js ------------------------------------------------------- // src/components/Root.js -------------------------------------------------------
import { Component, tags, useState } from "@odoo/owl"; import { Component, xml, useState } from "@odoo/owl";
const { xml } = tags; export class Root extends Component {
static template = xml`
<div t-on-click="update">
Hello <t t-esc="state.text"/>
</div>`;
export class App extends Component {
static template = xml`<div t-on-click="update">Hello <t t-esc="state.text"/></div>`;
state = useState({ text: "Owl" }); state = useState({ text: "Owl" });
update() { update() {
this.state.text = this.state.text === "Owl" ? "World" : "Owl"; this.state.text = this.state.text === "Owl" ? "World" : "Owl";
@@ -239,16 +235,12 @@ export class App extends Component {
// src/main.js ----------------------------------------------------------------- // src/main.js -----------------------------------------------------------------
import { utils, mount } from "@odoo/owl"; import { utils, mount } from "@odoo/owl";
import { App } from "./components/App"; import { Root } from "./components/Root";
function setup() { mount(Root, document.body);
mount(App, { target: document.body });
}
utils.whenReady(setup); // tests/components/Root.test.js ------------------------------------------------
import { Root } from "../../src/components/Root";
// tests/components/App.test.js ------------------------------------------------
import { App } from "../../src/components/App";
import { makeTestFixture, nextTick, click } from "../helpers"; import { makeTestFixture, nextTick, click } from "../helpers";
import { mount } from "@odoo/owl"; import { mount } from "@odoo/owl";
@@ -262,9 +254,9 @@ afterEach(() => {
fixture.remove(); fixture.remove();
}); });
describe("App", () => { describe("Root", () => {
test("Works as expected...", async () => { test("Works as expected...", async () => {
await mount(App, { target: fixture }); await mount(Root, fixture);
expect(fixture.innerHTML).toBe("<div>Hello Owl</div>"); expect(fixture.innerHTML).toBe("<div>Hello Owl</div>");
click(fixture, "div"); click(fixture, "div");
@@ -278,9 +270,8 @@ import { Component } from "@odoo/owl";
import "regenerator-runtime/runtime"; import "regenerator-runtime/runtime";
export async function nextTick() { export async function nextTick() {
return new Promise(function (resolve) { await new Promise((resolve) => setTimeout(resolve));
setTimeout(() => Component.scheduler.requestAnimationFrame(() => resolve())); await new Promise((resolve) => requestAnimationFrame(resolve));
});
} }
export function makeTestFixture() { export function makeTestFixture() {
+252 -280
View File
@@ -50,10 +50,11 @@ the following content:
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<title>OWL Todo App</title> <title>OWL Todo App</title>
<link rel="stylesheet" href="app.css" /> <link rel="stylesheet" href="app.css" />
</head>
<body>
<script src="owl.js"></script> <script src="owl.js"></script>
<script src="app.js"></script> <script src="app.js"></script>
</head> </body>
<body></body>
</html> </html>
``` ```
@@ -71,44 +72,34 @@ Note that we put everything inside an immediately executed function to avoid lea
anything to the global scope. anything to the global scope.
Finally, `owl.js` should be the last version downloaded from the Owl repository (you can use `owl.min.js` if you prefer). Be aware that you should download the `owl.iife.js` or `owl.iife.min.js`, because these files Finally, `owl.js` should be the last version downloaded from the Owl repository (you can use `owl.min.js` if you prefer). Be aware that you should download the `owl.iife.js` or `owl.iife.min.js`, because these files
are built to run directly on the browser (other files such as `owl.cjs.js` are are built to run directly on the browser, and rename it `owl.js` (other files such as `owl.cjs.js` are
built to be bundled by other tools). built to be bundled by other tools).
Now, the project should be ready. Loading the `index.html` file into a browser Now, the project should be ready. Loading the `index.html` file into a browser
should show an empty page, with the title `Owl Todo App`, and it should log a should show an empty page, with the title `Owl Todo App`, and it should log a
message such as `hello owl 1.0.0` in the console. message such as `hello owl 2.x.y` in the console.
## 2. Adding a first component ## 2. Adding a first component
An Owl application is made out of [components](../reference/component.md), with An Owl application is made out of [components](../reference/component.md), with
a single root component. Let us start by defining an `App` component. Replace the a single root component. Let us start by defining a `Root` component. Replace the
content of the function in `app.js` by the following code: content of the function in `app.js` by the following code:
```js ```js
const { Component, mount } = owl; const { Component, mount, xml } = owl;
const { xml } = owl.tags;
const { whenReady } = owl.utils;
// Owl Components // Owl Components
class App extends Component { class Root extends Component {
static template = xml`<div>todo app</div>`; static template = xml`<div>todo app</div>`;
} }
// Setup code mount(Root, document.body);
function setup() {
mount(App, { target: document.body });
}
whenReady(setup);
``` ```
Now, reloading the page in a browser should display a message. Now, reloading the page in a browser should display a message.
The code is pretty simple, but let us explain the last line in more detail. The The code is pretty simple: we define a component with an inline template, then
browser tries to execute the javascript code in `app.js` as quickly as possible, mount it in the document body.
and it could happen that the DOM is not ready yet when we try to mount the `App`
component. To avoid this situation, we use the [`whenReady`](../reference/utils.md#whenready)
helper to delay the execution of the `setup` function until the DOM is ready.
Note 1: in a larger project, we would split the code in multiple files, with Note 1: in a larger project, we would split the code in multiple files, with
components in a sub folder, and a main file that would initialize the application. components in a sub folder, and a main file that would initialize the application.
@@ -149,20 +140,20 @@ with the following keys:
tasks. Since the title is something created/edited by the user, it offers tasks. Since the title is something created/edited by the user, it offers
no guarantee that it is unique. So, we will generate a unique `id` number for no guarantee that it is unique. So, we will generate a unique `id` number for
each task. each task.
- `title`: a string, to explain what the task is about. - `text`: a string, to explain what the task is about.
- `isCompleted`: a boolean, to keep track of the status of the task - `isCompleted`: a boolean, to keep track of the status of the task
Now that we decided on the internal format of the state, let us add some demo Now that we decided on the internal format of the state, let us add some demo
data and a template to the `App` component: data and a template to the `App` component:
```js ```js
class App extends Component { class Root extends Component {
static template = xml/* xml */ ` static template = xml/* xml */ `
<div class="task-list"> <div class="task-list">
<t t-foreach="tasks" t-as="task" t-key="task.id"> <t t-foreach="tasks" t-as="task" t-key="task.id">
<div class="task"> <div class="task">
<input type="checkbox" t-att-checked="task.isCompleted"/> <input type="checkbox" t-att-checked="task.isCompleted"/>
<span><t t-esc="task.title"/></span> <span><t t-esc="task.text"/></span>
</div> </div>
</t> </t>
</div>`; </div>`;
@@ -170,12 +161,12 @@ class App extends Component {
tasks = [ tasks = [
{ {
id: 1, id: 1,
title: "buy milk", text: "buy milk",
isCompleted: true, isCompleted: true,
}, },
{ {
id: 2, id: 2,
title: "clean house", text: "clean house",
isCompleted: false, isCompleted: false,
}, },
]; ];
@@ -245,29 +236,25 @@ a little bit:
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
// Task Component // Task Component
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
const TASK_TEMPLATE = xml /* xml */` class Task extends Component {
static template = xml /* xml */`
<div class="task" t-att-class="props.task.isCompleted ? 'done' : ''"> <div class="task" t-att-class="props.task.isCompleted ? 'done' : ''">
<input type="checkbox" t-att-checked="props.task.isCompleted"/> <input type="checkbox" t-att-checked="props.task.isCompleted"/>
<span><t t-esc="props.task.title"/></span> <span><t t-esc="props.task.title"/></span>
</div>`; </div>`;
class Task extends Component {
static template = TASK_TEMPLATE;
static props = ["task"]; static props = ["task"];
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
// App Component // Root Component
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
const APP_TEMPLATE = xml /* xml */` class Root extends Component {
static template = xml /* xml */`
<div class="task-list"> <div class="task-list">
<t t-foreach="tasks" t-as="task" t-key="task.id"> <t t-foreach="tasks" t-as="task" t-key="task.id">
<Task task="task"/> <Task task="task"/>
</t> </t>
</div>`; </div>`;
class App extends Component {
static template = APP_TEMPLATE;
static components = { Task }; static components = { Task };
tasks = [ tasks = [
@@ -276,14 +263,9 @@ class App extends Component {
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
// Setup code // Setup
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
function setup() { mount(Root, document.body, {dev: true});
owl.config.mode = "dev";
mount(App, { target: document.body });
}
whenReady(setup);
``` ```
A lot of stuff happened here: A lot of stuff happened here:
@@ -292,24 +274,22 @@ A lot of stuff happened here:
- whenever we define a sub component, it needs to be added to the static - whenever we define a sub component, it needs to be added to the static
[`components`](../reference/component.md#static-properties) [`components`](../reference/component.md#static-properties)
key of its parent, so Owl can get a reference to it, key of its parent, so Owl can get a reference to it,
- the templates have been extracted out of the components, to make it easier to
differentiate the "view/template" code from the "script/behavior" code,
- the `Task` component has a `props` key: this is only useful for validation - the `Task` component has a `props` key: this is only useful for validation
purpose. It says that each `Task` should be given exactly one prop, named purpose. It says that each `Task` should be given exactly one prop, named
`task`. If this is not the case, Owl will throw an `task`. If this is not the case, Owl will throw an
[error](../reference/props_validation.md). This is extremely [error](../reference/props_validation.md). This is extremely
useful when refactoring components useful when refactoring components
- finally, to activate the props validation, we need to set Owl's - finally, to activate the props validation, we need to set Owl's
[mode](../reference/config.md#mode) to `dev`. This is done in the `setup` [mode](../reference/config.md#mode) to `dev`. This is done in the last argument
function. Note that this should be removed when an app is used in a real of the `mount` function. Note that this should be removed when an app is used in a real
production environment, since `dev` mode is slightly slower, due to extra production environment, since `dev` mode is slightly slower, due to extra
checks and validations. checks and validations.
## 6. Adding tasks (part 1) ## 6. Adding tasks (part 1)
We still use a list of hardcoded tasks. It's really time to give the user a way We still use a list of hardcoded tasks. It's really time to give the user a way
to add tasks himself. The first step is to add an input to the `App` component. to add tasks himself. The first step is to add an input to the `Root` component.
But this input will be outside of the task list, so we need to adapt `App` But this input will be outside of the task list, so we need to adapt `Root`
template, js, and css: template, js, and css:
```xml ```xml
@@ -327,9 +307,9 @@ template, js, and css:
addTask(ev) { addTask(ev) {
// 13 is keycode for ENTER // 13 is keycode for ENTER
if (ev.keyCode === 13) { if (ev.keyCode === 13) {
const title = ev.target.value.trim(); const text = ev.target.value.trim();
ev.target.value = ""; ev.target.value = "";
console.log('adding task', title); console.log('adding task', text);
// todo // todo
} }
} }
@@ -358,10 +338,9 @@ task. Notice that when you load the page, the input is not focused. But adding
tasks is a core feature of a task list, so let us make it as fast as possible by tasks is a core feature of a task list, so let us make it as fast as possible by
focusing the input. focusing the input.
Since `App` is a component, it has a We need to execute code when the `Root` component is ready (mounted). Let's do
[`mounted` lifecycle method](../reference/component.md#lifecycle) that we can that using the `onMounted` hook. We will also need to get a reference to the
implement. We will also need to get a reference to the input, by using the input, by using the `t-ref` directive with the [`useRef`](../reference/hooks.md#useref) hook:
`t-ref` directive with the [`useRef`](../reference/hooks.md#useref) hook:
```xml ```xml
<input placeholder="Enter a new task" t-on-keyup="addTask" t-ref="add-input"/> <input placeholder="Enter a new task" t-on-keyup="addTask" t-ref="add-input"/>
@@ -369,22 +348,21 @@ implement. We will also need to get a reference to the input, by using the
```js ```js
// on top of file: // on top of file:
const { useRef } = owl.hooks; const { Component, mount, xml, useRef, onMounted } = owl;
``` ```
```js ```js
// in App // in App
inputRef = useRef("add-input"); setup() {
const inputRef = useRef("add-input");
mounted() { onMounted(() => inputRef.el.focus());
this.inputRef.el.focus();
} }
``` ```
The `inputRef` is defined as a class field, so it is equivalent to defining it This is a very common situation: whenever we need to perform some actions depending
in the constructor. It simply instructs Owl to keep a reference to anything with on the lifecycle of a component, we need to do it in the `setup` method, by using
the corresponding `t-ref` keyword. We then implement the `mounted` lifecycle one of the lifecycle hook. Here, we first get a reference to the `inputRef`,
method, where we now have an active reference that we can use to focus the input. then in the `onMounted` hook, we simply focus the html element.
## 7. Adding tasks (part 2) ## 7. Adding tasks (part 2)
@@ -405,12 +383,12 @@ Now, the `addTask` method can be implemented:
addTask(ev) { addTask(ev) {
// 13 is keycode for ENTER // 13 is keycode for ENTER
if (ev.keyCode === 13) { if (ev.keyCode === 13) {
const title = ev.target.value.trim(); const text = ev.target.value.trim();
ev.target.value = ""; ev.target.value = "";
if (title) { if (text) {
const newTask = { const newTask = {
id: this.nextId++, id: this.nextId++,
title: title, text: text,
isCompleted: false, isCompleted: false,
}; };
this.tasks.push(newTask); this.tasks.push(newTask);
@@ -428,7 +406,7 @@ the user interface. We can fix the issue by making `tasks` reactive, with the
```js ```js
// on top of the file // on top of the file
const { useRef, useState } = owl.hooks; const { Component, mount, xml, useRef, onMounted, useState } = owl;
// replace the task definition in App with the following: // replace the task definition in App with the following:
tasks = useState([]); tasks = useState([]);
@@ -443,12 +421,8 @@ did not change in opacity. This is because there is no code to modify the
`isCompleted` flag. `isCompleted` flag.
Now, this is an interesting situation: the task is displayed by the `Task` Now, this is an interesting situation: the task is displayed by the `Task`
component, but it is not the owner of its state, so it cannot modify it. Instead, component, but it is not the owner of its state, so ideally, it should not modify it.
we want to communicate the request to toggle a task to the `App` component. However, for now, that's what we will do (this will be improved in a later step).
Since `App` is a parent of `Task`, we can
[trigger](../reference/event_handling.md) an event in `Task` and listen
for it in `App`.
In `Task`, change the `input` to: In `Task`, change the `input` to:
```xml ```xml
@@ -459,36 +433,23 @@ and add the `toggleTask` method:
```js ```js
toggleTask() { toggleTask() {
this.trigger('toggle-task', {id: this.props.task.id}); this.props.task.isCompleted = !this.props.task.isCompleted;
}
```
We now need to listen for that event in the `App` template:
```xml
<div class="task-list" t-on-toggle-task="toggleTask">
```
and implement the `toggleTask` code:
```js
toggleTask(ev) {
const task = this.tasks.find(t => t.id === ev.detail.id);
task.isCompleted = !task.isCompleted;
} }
``` ```
## 9. Deleting tasks ## 9. Deleting tasks
Let us now add the possibility do delete tasks. To do that, we first need to add Let us now add the possibility do delete tasks. This is different from the previous
a trash icon on each task, then we will proceed just like in the previous section. feature: deleting task has to be done on the task itself, but the actual operation
need to be done on the task list. So, we need to communicate the request to the
`Root` component. This is usually done by providing a callback in a prop.
First, let us update the `Task` template, css and js: First, let us update the `Task` template, css and js:
```xml ```xml
<div class="task" t-att-class="props.task.isCompleted ? 'done' : ''"> <div class="task" t-att-class="props.task.isCompleted ? 'done' : ''">
<input type="checkbox" t-att-checked="props.task.isCompleted" t-on-click="toggleTask"/> <input type="checkbox" t-att-checked="props.task.isCompleted" t-on-click="toggleTask"/>
<span><t t-esc="props.task.title"/></span> <span><t t-esc="props.task.text"/></span>
<span class="delete" t-on-click="deleteTask">🗑</span> <span class="delete" t-on-click="deleteTask">🗑</span>
</div> </div>
``` ```
@@ -517,194 +478,183 @@ First, let us update the `Task` template, css and js:
``` ```
```js ```js
static props = ["task", "onDelete"];
deleteTask() { deleteTask() {
this.trigger('delete-task', {id: this.props.task.id}); this.props.onDelete(this.props.task);
} }
``` ```
And now, we need to listen to the `delete-task` event in `App`: And now, we need to provide the `onDelete` callback to each tasks in the `Root`
component:
```xml ```xml
<div class="task-list" t-on-toggle-task="toggleTask" t-on-delete-task="deleteTask"> <Task task="task" onDelete.bind="deleteTask"/>
``` ```
```js ```js
deleteTask(ev) { deleteTask(task) {
const index = this.tasks.findIndex(t => t.id === ev.detail.id); const index = this.tasks.findIndex(t => t.id === task.id);
this.tasks.splice(index, 1); this.tasks.splice(index, 1);
} }
``` ```
Notice that the `onDelete` prop is defined with a `.bind` suffix: this is a special
suffix that makes sure the function callback is bound to the component.
## 10. Using a store ## 10. Using a store
Looking at the code, it is apparent that we now have code to handle tasks Looking at the code, it is apparent that all the code handling tasks is scattered
scattered in more than one place. Also, it mixes UI code and business logic all around the application. Also, it mixes UI code and business logic
code. Owl has a way to manage state separately from the user interface: a code. Owl does not provide any high level abstraction to manage business logic,
[`Store`](../reference/store.md). but it is easy to do it with the basic reactivity primitives (`useState` and `reactive`).
Let us use it in our application. This is a pretty large refactoring (for our Let us use it in our application to implement a central store. This is a pretty
application), since it involves extracting all task related code out of the large refactoring (for our application), since it involves extracting all task
components. Here is the new content of the `app.js` file: related code out of the components. Here is the new content of the `app.js` file:
```js ```js
const { Component, Store, mount } = owl; const { Component, mount, xml, useRef, onMounted, useState, reactive, useEnv } = owl;
const { xml } = owl.tags;
const { whenReady } = owl.utils;
const { useRef, useDispatch, useStore } = owl.hooks;
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
// Store // Store
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
const actions = { function useStore() {
addTask({ state }, title) { const env = useEnv();
title = title.trim(); return useState(env.store);
if (title) { }
// -------------------------------------------------------------------------
// TaskList
// -------------------------------------------------------------------------
class TaskList {
nextId = 1;
tasks = [];
addTask(text) {
text = text.trim();
if (text) {
const task = { const task = {
id: state.nextId++, id: this.nextId++,
title: title, text: text,
isCompleted: false, isCompleted: false,
}; };
state.tasks.push(task); this.tasks.push(task);
} }
}, }
toggleTask({ state }, id) {
const task = state.tasks.find((t) => t.id === id); toggleTask(task) {
task.isCompleted = !task.isCompleted; task.isCompleted = !task.isCompleted;
}, }
deleteTask({ state }, id) {
const index = state.tasks.findIndex((t) => t.id === id); deleteTask(task) {
state.tasks.splice(index, 1); const index = this.tasks.findIndex((t) => t.id === task.id);
}, this.tasks.splice(index, 1);
}; }
const initialState = { }
nextId: 1,
tasks: [], function createTaskStore() {
}; return reactive(new TaskList());
}
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
// Task Component // Task Component
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
const TASK_TEMPLATE = xml/* xml */ ` class Task extends Component {
static template = xml/* xml */ `
<div class="task" t-att-class="props.task.isCompleted ? 'done' : ''"> <div class="task" t-att-class="props.task.isCompleted ? 'done' : ''">
<input type="checkbox" t-att-checked="props.task.isCompleted" <input type="checkbox" t-att-checked="props.task.isCompleted" t-on-click="() => store.toggleTask(props.task)"/>
t-on-click="dispatch('toggleTask', props.task.id)"/> <span><t t-esc="props.task.text"/></span>
<span><t t-esc="props.task.title"/></span> <span class="delete" t-on-click="() => store.deleteTask(props.task)">🗑</span>
<span class="delete" t-on-click="dispatch('deleteTask', props.task.id)">🗑</span>
</div>`; </div>`;
class Task extends Component {
static template = TASK_TEMPLATE;
static props = ["task"]; static props = ["task"];
dispatch = useDispatch();
setup() {
this.store = useStore();
}
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
// App Component // Root Component
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
const APP_TEMPLATE = xml/* xml */ ` class Root extends Component {
static template = xml/* xml */ `
<div class="todo-app"> <div class="todo-app">
<input placeholder="Enter a new task" t-on-keyup="addTask" t-ref="add-input"/> <input placeholder="Enter a new task" t-on-keyup="addTask" t-ref="add-input"/>
<div class="task-list"> <div class="task-list">
<t t-foreach="tasks" t-as="task" t-key="task.id"> <t t-foreach="store.tasks" t-as="task" t-key="task.id">
<Task task="task"/> <Task task="task"/>
</t> </t>
</div> </div>
</div>`; </div>`;
class App extends Component {
static template = APP_TEMPLATE;
static components = { Task }; static components = { Task };
inputRef = useRef("add-input"); setup() {
tasks = useStore((state) => state.tasks); const inputRef = useRef("add-input");
dispatch = useDispatch(); onMounted(() => inputRef.el.focus());
this.store = useStore();
mounted() {
this.inputRef.el.focus();
} }
addTask(ev) { addTask(ev) {
// 13 is keycode for ENTER // 13 is keycode for ENTER
if (ev.keyCode === 13) { if (ev.keyCode === 13) {
this.dispatch("addTask", ev.target.value); this.store.addTask(ev.target.value);
ev.target.value = ""; ev.target.value = "";
} }
} }
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
// Setup code // Setup
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
function setup() { const env = {
owl.config.mode = "dev"; store: createTaskStore(),
const store = new Store({ actions, state: initialState }); };
App.env.store = store; mount(Root, document.body, { dev: true, env });
mount(App, { target: document.body });
}
whenReady(setup);
``` ```
## 11-Saving tasks in local storage ## 11. Saving tasks in local storage
Now, our TodoApp works great, except if the user closes or refresh the browser! Now, our TodoApp works great, except if the user closes or refresh the browser!
It is really inconvenient to only keep the state of the application in memory. It is really inconvenient to only keep the state of the application in memory.
To fix this, we will save the tasks in the local storage. With our current To fix this, we will save the tasks in the local storage. With our current
codebase, it is a simple change: only the setup code needs to be updated. codebase, it is a simple change: we need to save tasks to local storage and
listen to any change.
```js ```js
function makeStore() { class TaskList {
const localState = window.localStorage.getItem("todoapp"); constructor(tasks) {
const state = localState ? JSON.parse(localState) : initialState; this.tasks = tasks || [];
const store = new Store({ state, actions }); const taskIds = this.tasks.map((t) => t.id);
store.on("update", null, () => { this.nextId = taskIds.length ? Math.max(...taskIds) + 1 : 1;
localStorage.setItem("todoapp", JSON.stringify(store.state)); }
}); // ...
return store;
} }
function setup() { function createTaskStore() {
owl.config.mode = "dev"; const saveTasks = () => localStorage.setItem("todoapp", JSON.stringify(taskStore.tasks));
const env = { store: makeStore() }; const initialTasks = JSON.parse(localStorage.getItem("todoapp") || "[]");
mount(App, { target: document.body, env }); const taskStore = reactive(new TaskList(initialTasks), saveTasks);
saveTasks();
return taskStore;
} }
``` ```
The key point is to use the fact that the store is an The key point is that the `reactive` function takes a callback that will be called
[`EventBus`](../reference/event_bus.md) which triggers an `update` event every time an observed value is changed. Note that we need to call the `saveTasks`
whenever it is updated. method initially to make sure we observe all current values.
## 12. Filtering tasks ## 12. Filtering tasks
We are almost done, we can add/update/delete tasks. The only missing feature is We are almost done, we can add/update/delete tasks. The only missing feature is
the possibility to display the task according to their completed status. We will the possibility to display the task according to their completed status. We will
need to keep track of the state of the filter in `App`, then filter the visible need to keep track of the state of the filter in `Root`, then filter the visible
tasks according to its value. tasks according to its value.
```js ```js
// on top of file, readd useState: class Root extends Component {
const { useRef, useDispatch, useState, useStore } = owl.hooks; static template = xml /* xml */`
// in App:
filter = useState({value: "all"})
get displayedTasks() {
switch (this.filter.value) {
case "active": return this.tasks.filter(t => !t.isCompleted);
case "completed": return this.tasks.filter(t => t.isCompleted);
case "all": return this.tasks;
}
}
setFilter(filter) {
this.filter.value = filter;
}
```
Finally, we need to display the visible filters. We can do that, and at the
same time, display the number of tasks in a small panel below the main list:
```xml
<div class="todo-app"> <div class="todo-app">
<input placeholder="Enter a new task" t-on-keyup="addTask" t-ref="add-input"/> <input placeholder="Enter a new task" t-on-keyup="addTask" t-ref="add-input"/>
<div class="task-list"> <div class="task-list">
@@ -712,11 +662,11 @@ same time, display the number of tasks in a small panel below the main list:
<Task task="task"/> <Task task="task"/>
</t> </t>
</div> </div>
<div class="task-panel" t-if="tasks.length"> <div class="task-panel" t-if="store.tasks.length">
<div class="task-counter"> <div class="task-counter">
<t t-esc="displayedTasks.length"/> <t t-esc="displayedTasks.length"/>
<t t-if="displayedTasks.length lt tasks.length"> <t t-if="displayedTasks.length lt store.tasks.length">
/ <t t-esc="tasks.length"/> / <t t-esc="store.tasks.length"/>
</t> </t>
task(s) task(s)
</div> </div>
@@ -724,11 +674,30 @@ same time, display the number of tasks in a small panel below the main list:
<span t-foreach="['all', 'active', 'completed']" <span t-foreach="['all', 'active', 'completed']"
t-as="f" t-key="f" t-as="f" t-key="f"
t-att-class="{active: filter.value===f}" t-att-class="{active: filter.value===f}"
t-on-click="setFilter(f)" t-on-click="() => this.setFilter(f)"
t-esc="f"/> t-esc="f"/>
</div> </div>
</div> </div>
</div> </div>`;
setup() {
...
this.filter = useState({ value: "all" });
}
get displayedTasks() {
const tasks = this.store.tasks;
switch (this.filter.value) {
case "active": return tasks.filter(t => !t.isCompleted);
case "completed": return tasks.filter(t => t.isCompleted);
case "all": return tasks;
}
}
setFilter(filter) {
this.filter.value = filter;
}
}
``` ```
```css ```css
@@ -753,8 +722,8 @@ same time, display the number of tasks in a small panel below the main list:
} }
``` ```
Notice here that we set dynamically the class of the filter with the object Notice here that we set dynamically the css class of the filter with the object
syntax: each key is a class that we want to set if its value is truthy. syntax.
## 13. The Final Touch ## 13. The Final Touch
@@ -769,16 +738,16 @@ the user experience.
} }
``` ```
2. Make the title of a task clickable, to toggle its checkbox: 2. Make the text of a task clickable, to toggle its checkbox:
```xml ```xml
<input type="checkbox" t-att-checked="props.task.isCompleted" <input type="checkbox" t-att-checked="props.task.isCompleted"
t-att-id="props.task.id" t-att-id="props.task.id"
t-on-click="dispatch('toggleTask', props.task.id)"/> t-on-click="dispatch('toggleTask', props.task.id)"/>
<label t-att-for="props.task.id"><t t-esc="props.task.title"/></label> <label t-att-for="props.task.id"><t t-esc="props.task.text"/></label>
``` ```
3. Strike the title of completed task: 3. Strike the text of completed task:
```css ```css
.task.done label { .task.done label {
@@ -810,73 +779,94 @@ For reference, here is the final code:
```js ```js
(function () { (function () {
const { Component, Store, mount } = owl; const { Component, mount, xml, useRef, onMounted, useState, reactive, useEnv } = owl;
const { xml } = owl.tags;
const { whenReady } = owl.utils;
const { useRef, useDispatch, useState, useStore } = owl.hooks;
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
// Store // Store
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
const actions = { function useStore() {
addTask({ state }, title) { const env = useEnv();
title = title.trim(); return useState(env.store);
if (title) { }
// -------------------------------------------------------------------------
// TaskList
// -------------------------------------------------------------------------
class TaskList {
constructor(tasks) {
this.tasks = tasks || [];
const taskIds = this.tasks.map((t) => t.id);
this.nextId = taskIds.length ? Math.max(...taskIds) + 1 : 1;
}
addTask(text) {
text = text.trim();
if (text) {
const task = { const task = {
id: state.nextId++, id: this.nextId++,
title: title, text: text,
isCompleted: false, isCompleted: false,
}; };
state.tasks.push(task); this.tasks.push(task);
}
} }
},
toggleTask({ state }, id) {
const task = state.tasks.find((t) => t.id === id);
task.isCompleted = !task.isCompleted;
},
deleteTask({ state }, id) {
const index = state.tasks.findIndex((t) => t.id === id);
state.tasks.splice(index, 1);
},
};
const initialState = { toggleTask(task) {
nextId: 1, task.isCompleted = !task.isCompleted;
tasks: [], }
};
deleteTask(task) {
const index = this.tasks.findIndex((t) => t.id === task.id);
this.tasks.splice(index, 1);
}
}
function createTaskStore() {
const saveTasks = () => localStorage.setItem("todoapp", JSON.stringify(taskStore.tasks));
const initialTasks = JSON.parse(localStorage.getItem("todoapp") || "[]");
const taskStore = reactive(new TaskList(initialTasks), saveTasks);
saveTasks();
return taskStore;
}
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
// Task Component // Task Component
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
const TASK_TEMPLATE = xml/* xml */ ` class Task extends Component {
static template = xml/* xml */ `
<div class="task" t-att-class="props.task.isCompleted ? 'done' : ''"> <div class="task" t-att-class="props.task.isCompleted ? 'done' : ''">
<input type="checkbox" t-att-checked="props.task.isCompleted" <input type="checkbox"
t-att-id="props.task.id" t-att-id="props.task.id"
t-on-click="dispatch('toggleTask', props.task.id)"/> t-att-checked="props.task.isCompleted"
<label t-att-for="props.task.id"><t t-esc="props.task.title"/></label> t-on-click="() => store.toggleTask(props.task)"/>
<span class="delete" t-on-click="dispatch('deleteTask', props.task.id)">🗑</span> <label t-att-for="props.task.id"><t t-esc="props.task.text"/></label>
<span class="delete" t-on-click="() => store.deleteTask(props.task)">🗑</span>
</div>`; </div>`;
class Task extends Component {
static template = TASK_TEMPLATE;
static props = ["task"]; static props = ["task"];
dispatch = useDispatch();
setup() {
this.store = useStore();
}
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
// App Component // Root Component
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
const APP_TEMPLATE = xml/* xml */ ` class Root extends Component {
static template = xml/* xml */ `
<div class="todo-app"> <div class="todo-app">
<input placeholder="Enter a new task" t-on-keyup="addTask" t-ref="add-input"/> <input placeholder="Enter a new task" t-on-keyup="addTask" t-ref="add-input"/>
<div class="task-list"> <div class="task-list">
<Task t-foreach="displayedTasks" t-as="task" t-key="task.id" task="task"/> <t t-foreach="displayedTasks" t-as="task" t-key="task.id">
<Task task="task"/>
</t>
</div> </div>
<div class="task-panel" t-if="tasks.length"> <div class="task-panel" t-if="store.tasks.length">
<div class="task-counter"> <div class="task-counter">
<t t-esc="displayedTasks.length"/> <t t-esc="displayedTasks.length"/>
<t t-if="displayedTasks.length lt tasks.length"> <t t-if="displayedTasks.length lt store.tasks.length">
/ <t t-esc="tasks.length"/> / <t t-esc="store.tasks.length"/>
</t> </t>
task(s) task(s)
</div> </div>
@@ -884,68 +874,50 @@ For reference, here is the final code:
<span t-foreach="['all', 'active', 'completed']" <span t-foreach="['all', 'active', 'completed']"
t-as="f" t-key="f" t-as="f" t-key="f"
t-att-class="{active: filter.value===f}" t-att-class="{active: filter.value===f}"
t-on-click="setFilter(f)" t-on-click="() => this.setFilter(f)"
t-esc="f"/> t-esc="f"/>
</div> </div>
</div> </div>
</div>`; </div>`;
class App extends Component {
static template = APP_TEMPLATE;
static components = { Task }; static components = { Task };
inputRef = useRef("add-input"); setup() {
tasks = useStore((state) => state.tasks); const inputRef = useRef("add-input");
filter = useState({ value: "all" }); onMounted(() => inputRef.el.focus());
dispatch = useDispatch(); this.store = useStore();
this.filter = useState({ value: "all" });
mounted() {
this.inputRef.el.focus();
} }
addTask(ev) { addTask(ev) {
// 13 is keycode for ENTER // 13 is keycode for ENTER
if (ev.keyCode === 13) { if (ev.keyCode === 13) {
this.dispatch("addTask", ev.target.value); this.store.addTask(ev.target.value);
ev.target.value = ""; ev.target.value = "";
} }
} }
get displayedTasks() { get displayedTasks() {
const tasks = this.store.tasks;
switch (this.filter.value) { switch (this.filter.value) {
case "active": case "active":
return this.tasks.filter((t) => !t.isCompleted); return tasks.filter((t) => !t.isCompleted);
case "completed": case "completed":
return this.tasks.filter((t) => t.isCompleted); return tasks.filter((t) => t.isCompleted);
case "all": case "all":
return this.tasks; return tasks;
} }
} }
setFilter(filter) { setFilter(filter) {
this.filter.value = filter; this.filter.value = filter;
} }
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
// Setup code // Setup
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
function makeStore() { const env = { store: createTaskStore() };
const localState = window.localStorage.getItem("todoapp"); mount(Root, document.body, { dev: true, env });
const state = localState ? JSON.parse(localState) : initialState;
const store = new Store({ state, actions });
store.on("update", null, () => {
localStorage.setItem("todoapp", JSON.stringify(store.state));
});
return store;
}
function setup() {
owl.config.mode = "dev";
const env = { store: makeStore() };
mount(App, { target: document.body, env });
}
whenReady(setup);
})(); })();
``` ```
+2 -3
View File
@@ -14,8 +14,7 @@ discussed, feel free to open an issue/submit a PR to correct this text.
- [Tooling/Build Step](#toolingbuild-step) - [Tooling/Build Step](#toolingbuild-step)
- [Templating](#templating) - [Templating](#templating)
- [Asynchronous rendering](#asynchronous-rendering) - [Asynchronous rendering](#asynchronous-rendering)
- [Reactiveness](#reactiveness) - [Reactivity](#reactivity)
- [State Management](#state-management)
- [Hooks](#hooks) - [Hooks](#hooks)
## Size ## Size
@@ -173,7 +172,7 @@ more convoluted. For example, in Vue, you need to use a dynamic import keyword
that needs to be transpiled at build time in order for the component to be loaded that needs to be transpiled at build time in order for the component to be loaded
asynchronously (see [the documentation](https://vuejs.org/v2/guide/components-dynamic-async.html#Async-Components)). asynchronously (see [the documentation](https://vuejs.org/v2/guide/components-dynamic-async.html#Async-Components)).
## Reactiveness ## Reactivity
React has a simple model: whenever the state changes, it is React has a simple model: whenever the state changes, it is
replaced with a new state (via the `setState` method). Then, the DOM is patched. replaced with a new state (via the `setState` method). Then, the DOM is patched.
-55
View File
@@ -1,55 +0,0 @@
# 🦉 OWL Documentation 🦉
## Learning Owl
Are you new to Owl? This is the place to start!
- [Tutorial: create a TodoList application](learning/tutorial_todoapp.md)
- [Quick Overview](learning/overview.md)
- [How to start an Owl project](learning/quick_start.md)
- [How to test Components](learning/how_to_test.md)
- [How to write Single File Components](learning/how_to_write_sfc.md)
- [How to write debug Owl applications](learning/how_to_debug.md)
## Reference
You will find here a complete reference of every feature, class or object
provided by Owl.
- [Animations](reference/animations.md)
- [Browser](reference/browser.md)
- [Component](reference/component.md)
- [Content](reference/content.md)
- [Concurrency Model](reference/concurrency_model.md)
- [Configuration](reference/config.md)
- [Context](reference/context.md)
- [Environment](reference/environment.md)
- [Event Bus](reference/event_bus.md)
- [Event Handling](reference/event_handling.md)
- [Error Handling](reference/error_handling.md)
- [Hooks](reference/hooks.md)
- [Mounting a component](reference/mounting.md)
- [Miscellaneous Components](reference/misc.md)
- [Observer](reference/observer.md)
- [Props](reference/props.md)
- [Props Validation](reference/props_validation.md)
- [QWeb Templating Language](reference/qweb_templating_language.md)
- [QWeb Engine](reference/qweb_engine.md)
- [Slots](reference/slots.md)
- [Tags](reference/tags.md)
- [Utils](reference/utils.md)
## Other Topics
This section provides miscellaneous document that explains some topics
which cannot be considered either a tutorial, or reference documentation.
- [Owl architecture: the Virtual DOM](miscellaneous/vdom.md)
- [Owl architecture: the rendering pipeline](miscellaneous/rendering.md)
- [Comparison with React/Vue](miscellaneous/comparison.md)
- [Why did Odoo built Owl?](miscellaneous/why_owl.md)
---
Found an issue in the documentation? A broken link? Some outdated information?
Please open an issue or submit a PR!
+10
View File
@@ -372,6 +372,16 @@ to be closed:
useExternalListener(window, "click", this.closeMenu); useExternalListener(window, "click", this.closeMenu);
``` ```
### `useComponent`
The `useComponent` hook is useful as a building block for some customized hooks,
that may need a reference to the component calling them.
### `useEnv`
The `useEnv` hook is useful as a building block for some customized hooks,
that may need a reference to the env of the component calling them.
### Making customized hooks ### Making customized hooks
Hooks are a wonderful way to organize the code of a complex component by feature Hooks are a wonderful way to organize the code of a complex component by feature
+8 -7
View File
@@ -1,6 +1,6 @@
{ {
"name": "@odoo/owl", "name": "@odoo/owl",
"version": "1.4.7", "version": "2.0.0-alpha1",
"description": "Odoo Web Library (OWL)", "description": "Odoo Web Library (OWL)",
"main": "dist/owl.cjs.js", "main": "dist/owl.cjs.js",
"browser": "dist/owl.iife.js", "browser": "dist/owl.iife.js",
@@ -18,10 +18,10 @@
"test": "jest", "test": "jest",
"test:debug": "node --inspect-brk node_modules/.bin/jest --runInBand --watch", "test:debug": "node --inspect-brk node_modules/.bin/jest --runInBand --watch",
"test:watch": "jest --watch", "test:watch": "jest --watch",
"tools:serve": "python3 tools/server.py || python tools/server.py", "playground:serve": "python3 tools/server.py || python tools/server.py",
"tools": "npm run build && npm run tools:serve", "playground": "npm run build && npm run playground:serve",
"pretools:watch": "npm run build", "preplayground:watch": "npm run build",
"tools:watch": "npm-run-all --parallel tools:serve \"build:* -- --watch\"", "playground:watch": "npm-run-all --parallel playground:serve \"build:* -- --watch\"",
"prettier": "prettier {src/*.ts,src/**/*.ts,tests/*.ts,tests/**/*.ts,doc/*.md,doc/**/*.md} --write", "prettier": "prettier {src/*.ts,src/**/*.ts,tests/*.ts,tests/**/*.ts,doc/*.md,doc/**/*.md} --write",
"check-formatting": "prettier {src/*.ts,src/**/*.ts,tests/*.ts,tests/**/*.ts,doc/*.md,doc/**/*.md} --check", "check-formatting": "prettier {src/*.ts,src/**/*.ts,tests/*.ts,tests/**/*.ts,doc/*.md,doc/**/*.md} --check",
"publish": "npm run build && npm publish", "publish": "npm run build && npm publish",
@@ -46,17 +46,18 @@
"git-rev-sync": "^1.12.0", "git-rev-sync": "^1.12.0",
"github-api": "^3.3.0", "github-api": "^3.3.0",
"jest": "^27.1.0", "jest": "^27.1.0",
"jest-diff": "^27.3.1",
"jest-environment-jsdom": "^27.1.0", "jest-environment-jsdom": "^27.1.0",
"live-server": "^1.2.1", "live-server": "^1.2.1",
"npm-run-all": "^4.1.5", "npm-run-all": "^4.1.5",
"prettier": "2.4.1", "prettier": "2.4.1",
"rollup": "^2.56.3", "rollup": "^2.56.3",
"rollup-plugin-terser": "^7.0.2", "rollup-plugin-terser": "^7.0.2",
"rollup-plugin-typescript2": "^0.30.0", "rollup-plugin-typescript2": "^0.31.1",
"sass": "^1.16.1", "sass": "^1.16.1",
"source-map-support": "^0.5.10", "source-map-support": "^0.5.10",
"ts-jest": "^27.0.5", "ts-jest": "^27.0.5",
"typescript": "3.9.6", "typescript": "4.5.2",
"uglify-es": "^3.3.9" "uglify-es": "^3.3.9"
}, },
"jest": { "jest": {
+59 -26
View File
@@ -2,7 +2,8 @@ import { Component } from "../component/component";
import { ComponentNode } from "../component/component_node"; import { ComponentNode } from "../component/component_node";
import { MountOptions } from "../component/fibers"; import { MountOptions } from "../component/fibers";
import { Scheduler } from "../component/scheduler"; import { Scheduler } from "../component/scheduler";
import { TemplateSet } from "./template_set"; import { TemplateSet, TemplateSetConfig } from "./template_set";
import { nodeErrorHandlers } from "../component/error_handling";
// reimplement dev mode stuff see last change in 0f7a8289a6fb8387c3c1af41c6664b2a8448758f // reimplement dev mode stuff see last change in 0f7a8289a6fb8387c3c1af41c6664b2a8448758f
@@ -10,11 +11,9 @@ export interface Env {
[key: string]: any; [key: string]: any;
} }
export interface AppConfig { export interface AppConfig extends TemplateSetConfig {
dev?: boolean;
env?: Env; env?: Env;
translatableAttributes?: string[]; props?: any;
translateFn?: (s: string) => string;
} }
export const DEV_MSG = `Owl is running in 'dev' mode. export const DEV_MSG = `Owl is running in 'dev' mode.
@@ -25,43 +24,69 @@ See https://github.com/odoo/owl/blob/master/doc/reference/config.md#mode for mor
export class App<T extends typeof Component = any> extends TemplateSet { export class App<T extends typeof Component = any> extends TemplateSet {
Root: T; Root: T;
props: any; props: any;
env: Env = Object.freeze({}); env: Env;
scheduler = new Scheduler(window.requestAnimationFrame.bind(window)); scheduler = new Scheduler(window.requestAnimationFrame.bind(window));
root: ComponentNode | null = null; root: ComponentNode | null = null;
constructor(Root: T, props?: any) { constructor(Root: T, config: AppConfig = {}) {
super(); super(config);
this.Root = Root; this.Root = Root;
this.props = props;
}
configure(config: AppConfig): App<T> {
if (config.dev) { if (config.dev) {
this.dev = config.dev;
console.info(DEV_MSG); console.info(DEV_MSG);
} }
if (config.env) { const descrs = Object.getOwnPropertyDescriptors(config.env || {});
this.env = Object.freeze(Object.assign({}, config.env)); this.env = Object.freeze(Object.defineProperties({}, descrs));
} this.props = config.props || {};
if (config.translateFn) {
this.translateFn = config.translateFn;
}
if (config.translatableAttributes) {
this.translatableAttributes = config.translatableAttributes;
}
return this;
} }
mount(target: HTMLElement, options?: MountOptions): Promise<InstanceType<T>> { mount(target: HTMLElement, options?: MountOptions): Promise<InstanceType<T>> {
this.checkTarget(target);
const node = this.makeNode(this.Root, this.props);
const prom = this.mountNode(node, target, options);
this.root = node;
return prom;
}
checkTarget(target: HTMLElement) {
if (!(target instanceof HTMLElement)) { if (!(target instanceof HTMLElement)) {
throw new Error("Cannot mount component: the target is not a valid DOM element"); throw new Error("Cannot mount component: the target is not a valid DOM element");
} }
if (!document.body.contains(target)) { if (!document.body.contains(target)) {
throw new Error("Cannot mount a component on a detached dom node"); throw new Error("Cannot mount a component on a detached dom node");
} }
const node = new ComponentNode(this.Root, this.props, this); }
this.root = node;
return node.mountComponent(target, options); makeNode(Component: T, props: any): ComponentNode {
return new ComponentNode(Component, props, this);
}
mountNode(node: ComponentNode, target: HTMLElement, options?: MountOptions) {
const promise: any = new Promise((resolve, reject) => {
let isResolved = false;
// manually set a onMounted callback.
// that way, we are independant from the current node.
node.mounted.push(() => {
resolve(node.component);
isResolved = true;
});
// Manually add the last resort error handler on the node
let handlers = nodeErrorHandlers.get(node);
if (!handlers) {
handlers = [];
nodeErrorHandlers.set(node, handlers);
}
handlers.unshift((e) => {
if (isResolved) {
console.error(e);
} else {
reject(e);
}
throw e;
});
});
node.mountComponent(target, options);
return promise;
} }
destroy() { destroy() {
@@ -70,3 +95,11 @@ export class App<T extends typeof Component = any> extends TemplateSet {
} }
} }
} }
export async function mount<T extends typeof Component>(
C: T,
target: HTMLElement,
config: AppConfig & MountOptions = {}
): Promise<InstanceType<T>> {
return new App(C, config).mount(target, config);
}
+72 -7
View File
@@ -17,19 +17,24 @@ function callSlot(
parent: any, parent: any,
key: string, key: string,
name: string, name: string,
defaultSlot?: (ctx: any, key: string) => BDom, dynamic: boolean,
dynamic?: boolean extra: any,
defaultContent?: (ctx: any, node: any, key: string) => BDom
): BDom { ): BDom {
const slots = ctx.__owl__.slots; const slots = (ctx.props && ctx.props.slots) || {};
const slotFn = slots[name]; const { __render, __ctx, __scope } = slots[name] || {};
const slotBDom = slotFn ? slotFn(parent, key) : null; const slotScope = Object.create(__ctx || {});
if (defaultSlot) { if (__scope) {
slotScope[__scope] = extra || {};
}
const slotBDom = __render ? __render.call(__ctx.__owl__.component, slotScope, parent, key) : null;
if (defaultContent) {
let child1: BDom | undefined = undefined; let child1: BDom | undefined = undefined;
let child2: BDom | undefined = undefined; let child2: BDom | undefined = undefined;
if (slotBDom) { if (slotBDom) {
child1 = dynamic ? toggler(name, slotBDom) : slotBDom; child1 = dynamic ? toggler(name, slotBDom) : slotBDom;
} else { } else {
child2 = defaultSlot(parent, key); child2 = defaultContent.call(ctx.__owl__.component, ctx, parent, key);
} }
return multi([child1, child2]); return multi([child1, child2]);
} }
@@ -96,6 +101,25 @@ function shallowEqual(l1: any[], l2: any[]): boolean {
return true; return true;
} }
class LazyValue {
fn: any;
ctx: any;
node: any;
constructor(fn: any, ctx: any, node: any) {
this.fn = fn;
this.ctx = capture(ctx);
this.node = node;
}
evaluate(): any {
return this.fn(this.ctx, this.node);
}
toString() {
return this.evaluate().toString();
}
}
/* /*
* Safely outputs `value` as a block depending on the nature of `value` * Safely outputs `value` as a block depending on the nature of `value`
*/ */
@@ -108,6 +132,9 @@ export function safeOutput(value: any): ReturnType<typeof toggler> {
if (value instanceof Markup) { if (value instanceof Markup) {
safeKey = `string_safe`; safeKey = `string_safe`;
block = html(value as string); block = html(value as string);
} else if (value instanceof LazyValue) {
safeKey = `lazy_value`;
block = value.evaluate();
} else if (typeof value === "string") { } else if (typeof value === "string") {
safeKey = "string_unsafe"; safeKey = "string_unsafe";
block = text(value); block = text(value);
@@ -119,6 +146,41 @@ export function safeOutput(value: any): ReturnType<typeof toggler> {
return toggler(safeKey, block); return toggler(safeKey, block);
} }
let boundFunctions = new WeakMap();
function bind(ctx: any, fn: Function): Function {
let component = ctx.__owl__.component;
let boundFnMap = boundFunctions.get(component);
if (!boundFnMap) {
boundFnMap = new WeakMap();
boundFunctions.set(component, boundFnMap);
}
let boundFn = boundFnMap.get(fn);
if (!boundFn) {
boundFn = fn.bind(component);
boundFnMap.set(fn, boundFn);
}
return boundFn;
}
type RefMap = { [key: string]: HTMLElement | null };
type RefSetter = (el: HTMLElement | null) => void;
function multiRefSetter(refs: RefMap, name: string): RefSetter {
let count = 0;
return (el) => {
if (el) {
count++;
if (count > 1) {
throw new Error("Cannot have 2 elements with same ref name at the same time");
}
}
if (count === 0 || el) {
refs[name] = el;
}
};
}
export const UTILS = { export const UTILS = {
withDefault, withDefault,
zero: Symbol("zero"), zero: Symbol("zero"),
@@ -128,8 +190,11 @@ export const UTILS = {
withKey, withKey,
prepareList, prepareList,
setContextValue, setContextValue,
multiRefSetter,
shallowEqual, shallowEqual,
toNumber, toNumber,
validateProps, validateProps,
LazyValue,
safeOutput, safeOutput,
bind,
}; };
+80 -19
View File
@@ -1,28 +1,70 @@
import { createBlock, html, list, multi, text, toggler } from "../blockdom"; import { createBlock, html, list, multi, text, toggler, comment } from "../blockdom";
import { compile, Template } from "../compiler"; import { compile, Template } from "../compiler";
import { component } from "../component/component_node"; import { component } from "../component/component_node";
import { UTILS } from "./template_helpers"; import { UTILS } from "./template_helpers";
const bdom = { text, createBlock, list, multi, html, toggler, component }; const bdom = { text, createBlock, list, multi, html, toggler, component, comment };
export const globalTemplates: { [key: string]: string | Node } = {}; export const globalTemplates: { [key: string]: string | Node } = {};
function parseXML(xml: string): Document {
const parser = new DOMParser();
const doc = parser.parseFromString(xml, "text/xml");
if (doc.getElementsByTagName("parsererror").length) {
let msg = "Invalid XML in template.";
const parsererrorText = doc.getElementsByTagName("parsererror")[0].textContent;
if (parsererrorText) {
msg += "\nThe parser has produced the following error message:\n" + parsererrorText;
const re = /\d+/g;
const firstMatch = re.exec(parsererrorText);
if (firstMatch) {
const lineNumber = Number(firstMatch[0]);
const line = xml.split("\n")[lineNumber - 1];
const secondMatch = re.exec(parsererrorText);
if (line && secondMatch) {
const columnIndex = Number(secondMatch[0]) - 1;
if (line[columnIndex]) {
msg +=
`\nThe error might be located at xml line ${lineNumber} column ${columnIndex}\n` +
`${line}\n${"-".repeat(columnIndex - 1)}^`;
}
}
}
}
throw new Error(msg);
}
return doc;
}
export interface TemplateSetConfig {
dev?: boolean;
translatableAttributes?: string[];
translateFn?: (s: string) => string;
templates?: string | Document;
}
export class TemplateSet { export class TemplateSet {
dev: boolean;
rawTemplates: typeof globalTemplates = Object.create(globalTemplates); rawTemplates: typeof globalTemplates = Object.create(globalTemplates);
templates: { [name: string]: Template } = {}; templates: { [name: string]: Template } = {};
translateFn?: (s: string) => string; translateFn?: (s: string) => string;
translatableAttributes?: string[]; translatableAttributes?: string[];
utils: typeof UTILS; utils: typeof UTILS = Object.assign({}, UTILS, {
dev?: boolean; call: (owner: any, subTemplate: string, ctx: any, parent: any, key: any) => {
constructor() {
const call = (subTemplate: string, ctx: any, parent: any) => {
const template = this.getTemplate(subTemplate); const template = this.getTemplate(subTemplate);
return toggler(subTemplate, template(ctx, parent)); return toggler(subTemplate, template.call(owner, ctx, parent, key));
}; },
getTemplate: (name: string) => this.getTemplate(name),
});
const getTemplate = (name: string) => this.getTemplate(name); constructor(config: TemplateSetConfig = {}) {
this.utils = Object.assign({}, UTILS, { getTemplate, call }); this.dev = config.dev || false;
this.translateFn = config.translateFn;
this.translatableAttributes = config.translatableAttributes;
if (config.templates) {
this.addTemplates(config.templates);
}
} }
addTemplate(name: string, template: string | Node, options: { allowDuplicate?: boolean } = {}) { addTemplate(name: string, template: string | Node, options: { allowDuplicate?: boolean } = {}) {
@@ -33,7 +75,11 @@ export class TemplateSet {
} }
addTemplates(xml: string | Document, options: { allowDuplicate?: boolean } = {}) { addTemplates(xml: string | Document, options: { allowDuplicate?: boolean } = {}) {
xml = xml instanceof Document ? xml : new DOMParser().parseFromString(xml, "text/xml"); if (!xml) {
// empty string
return;
}
xml = xml instanceof Document ? xml : parseXML(xml);
for (const template of xml.querySelectorAll("[t-name]")) { for (const template of xml.querySelectorAll("[t-name]")) {
const name = template.getAttribute("t-name")!; const name = template.getAttribute("t-name")!;
template.removeAttribute("t-name"); template.removeAttribute("t-name");
@@ -47,13 +93,7 @@ export class TemplateSet {
if (rawTemplate === undefined) { if (rawTemplate === undefined) {
throw new Error(`Missing template: "${name}"`); throw new Error(`Missing template: "${name}"`);
} }
const templateFn = compile(rawTemplate, { const templateFn = this._compileTemplate(name, rawTemplate);
name,
dev: this.dev,
translateFn: this.translateFn,
translatableAttributes: this.translatableAttributes,
});
// first add a function to lazily get the template, in case there is a // first add a function to lazily get the template, in case there is a
// recursive call to the template name // recursive call to the template name
this.templates[name] = (context, parent) => this.templates[name](context, parent); this.templates[name] = (context, parent) => this.templates[name](context, parent);
@@ -62,4 +102,25 @@ export class TemplateSet {
} }
return this.templates[name]; return this.templates[name];
} }
_compileTemplate(name: string, template: string | Node) {
return compile(template, {
name,
dev: this.dev,
translateFn: this.translateFn,
translatableAttributes: this.translatableAttributes,
});
} }
}
// -----------------------------------------------------------------------------
// xml tag helper
// -----------------------------------------------------------------------------
export function xml(...args: Parameters<typeof String.raw>) {
const name = `__template__${xml.nextId++}`;
const value = String.raw(...args);
globalTemplates[name] = value;
return name;
}
xml.nextId = 1;
+16 -4
View File
@@ -1,6 +1,6 @@
import type { Setter } from "./block_compiler"; import type { Setter } from "./block_compiler";
const { setAttribute, removeAttribute } = Element.prototype; const { setAttribute: elemSetAttribute, removeAttribute } = Element.prototype;
const tokenList = DOMTokenList.prototype; const tokenList = DOMTokenList.prototype;
const tokenListAdd = tokenList.add; const tokenListAdd = tokenList.add;
const tokenListRemove = tokenList.remove; const tokenListRemove = tokenList.remove;
@@ -14,11 +14,23 @@ const wordRegexp = /\s+/;
* file. * file.
*/ */
function setAttribute(this: HTMLElement, key: string, value: any) {
switch (value) {
case false:
case undefined:
removeAttribute.call(this, key);
break;
case true:
elemSetAttribute.call(this, key, "");
break;
default:
elemSetAttribute.call(this, key, value);
}
}
export function createAttrUpdater(attr: string): Setter<HTMLElement> { export function createAttrUpdater(attr: string): Setter<HTMLElement> {
return function (this: HTMLElement, value: any) { return function (this: HTMLElement, value: any) {
if (value !== false) { setAttribute.call(this, attr, value);
setAttribute.call(this, attr, value === true ? "" : value);
}
}; };
} }
+37 -35
View File
@@ -113,9 +113,10 @@ interface IntermediateTree {
nextSibling: IntermediateTree | null; nextSibling: IntermediateTree | null;
el: Node; el: Node;
info: DynamicInfo[]; info: DynamicInfo[];
forceRef?: boolean; isRef?: boolean;
refIdx?: number; refIdx?: number;
refN: number; refN: number;
currentNS: string | null;
} }
function buildTree( function buildTree(
@@ -124,9 +125,9 @@ function buildTree(
domParentTree: IntermediateTree | null = null domParentTree: IntermediateTree | null = null
): IntermediateTree { ): IntermediateTree {
switch (node.nodeType) { switch (node.nodeType) {
case 1: { case Node.ELEMENT_NODE: {
// HTMLElement // HTMLElement
let isActive = false; let currentNS = domParentTree && domParentTree.currentNS;
const tagName = (node as Element).tagName; const tagName = (node as Element).tagName;
let el: Node | undefined = undefined; let el: Node | undefined = undefined;
const info: DynamicInfo[] = []; const info: DynamicInfo[] = [];
@@ -134,25 +135,31 @@ function buildTree(
const index = parseInt(tagName.slice(11), 10); const index = parseInt(tagName.slice(11), 10);
info.push({ type: "text", idx: index }); info.push({ type: "text", idx: index });
el = document.createTextNode(""); el = document.createTextNode("");
isActive = true;
} }
if (tagName.startsWith("block-child-")) { if (tagName.startsWith("block-child-")) {
domParentTree!.forceRef = true; if (!domParentTree!.isRef) {
addRef(domParentTree!);
}
const index = parseInt(tagName.slice(12), 10); const index = parseInt(tagName.slice(12), 10);
info.push({ type: "child", idx: index }); info.push({ type: "child", idx: index });
el = document.createTextNode(""); el = document.createTextNode("");
isActive = true; }
const attrs = (node as Element).attributes;
const ns = attrs.getNamedItem("block-ns");
if (ns) {
attrs.removeNamedItem("block-ns");
currentNS = ns.value;
} }
if (!el) { if (!el) {
el = document.createElement(tagName); el = currentNS
? document.createElementNS(currentNS, tagName)
: document.createElement(tagName);
} }
if (el instanceof HTMLElement) { if (el instanceof Element) {
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;
if (attrName.startsWith("block-handler-")) { if (attrName.startsWith("block-handler-")) {
isActive = true;
const idx = parseInt(attrName.slice(14), 10); const idx = parseInt(attrName.slice(14), 10);
info.push({ info.push({
type: "handler", type: "handler",
@@ -160,7 +167,6 @@ function buildTree(
event: attrValue, event: attrValue,
}); });
} else if (attrName.startsWith("block-attribute-")) { } else if (attrName.startsWith("block-attribute-")) {
isActive = true;
const idx = parseInt(attrName.slice(16), 10); const idx = parseInt(attrName.slice(16), 10);
info.push({ info.push({
type: "attribute", type: "attribute",
@@ -169,13 +175,11 @@ function buildTree(
tag: tagName, tag: tagName,
}); });
} else if (attrName === "block-attributes") { } else if (attrName === "block-attributes") {
isActive = true;
info.push({ info.push({
type: "attributes", type: "attributes",
idx: parseInt(attrValue, 10), idx: parseInt(attrValue, 10),
}); });
} else if (attrName === "block-ref") { } else if (attrName === "block-ref") {
isActive = true;
info.push({ info.push({
type: "ref", type: "ref",
idx: parseInt(attrValue, 10), idx: parseInt(attrValue, 10),
@@ -192,21 +196,20 @@ function buildTree(
nextSibling: null, nextSibling: null,
el, el,
info, info,
refN: isActive ? 1 : 0, refN: 0,
currentNS,
}; };
if (node.firstChild) { if (node.firstChild) {
const childNode = node.childNodes[0]; const childNode = node.childNodes[0];
if ( if (
node.childNodes.length === 1 && node.childNodes.length === 1 &&
childNode.nodeType === 1 && childNode.nodeType === Node.ELEMENT_NODE &&
(childNode as Element).tagName.startsWith("block-child-") (childNode as Element).tagName.startsWith("block-child-")
) { ) {
const tagName = (childNode as Element).tagName; const tagName = (childNode as Element).tagName;
const index = parseInt(tagName.slice(12), 10); const index = parseInt(tagName.slice(12), 10);
info.push({ idx: index, type: "child", isOnlyChild: true }); info.push({ idx: index, type: "child", isOnlyChild: true });
isActive = true;
tree.refN = 1;
} else { } else {
tree.firstChild = buildTree(node.firstChild, tree, tree); tree.firstChild = buildTree(node.firstChild, tree, tree);
el.appendChild(tree.firstChild.el); el.appendChild(tree.firstChild.el);
@@ -219,19 +222,16 @@ function buildTree(
} }
} }
} }
if (isActive) { if (tree.info.length) {
let cur: IntermediateTree | null = tree; addRef(tree);
while ((cur = cur.parent)) {
cur.refN++;
}
} }
return tree; return tree;
} }
case 3: case Node.TEXT_NODE:
case 8: { case Node.COMMENT_NODE: {
// text node or comment node // text node or comment node
const el = const el =
node.nodeType === 3 node.nodeType === Node.TEXT_NODE
? document.createTextNode(node.textContent!) ? document.createTextNode(node.textContent!)
: document.createComment(node.textContent!); : document.createComment(node.textContent!);
return { return {
@@ -241,12 +241,20 @@ function buildTree(
el, el,
info: [], info: [],
refN: 0, refN: 0,
currentNS: null,
}; };
} }
} }
throw new Error("boom"); throw new Error("boom");
} }
function addRef(tree: IntermediateTree) {
tree.isRef = true;
do {
tree.refN++;
} while ((tree = tree.parent as any));
}
function parentTree(tree: IntermediateTree): IntermediateTree | null { function parentTree(tree: IntermediateTree): IntermediateTree | null {
let parent = tree.parent; let parent = tree.parent;
while (parent && parent.nextSibling === tree) { while (parent && parent.nextSibling === tree) {
@@ -293,21 +301,15 @@ interface BlockCtx {
cbRefs: number[]; cbRefs: number[];
} }
function buildContext( function buildContext(tree: IntermediateTree, ctx?: BlockCtx, fromIdx?: number): BlockCtx {
tree: IntermediateTree,
ctx?: BlockCtx,
fromIdx?: number,
toIdx?: number
): BlockCtx {
if (!ctx) { if (!ctx) {
const children = new Array(tree.info.filter((v) => v.type === "child").length); const children = new Array(tree.info.filter((v) => v.type === "child").length);
ctx = { collectors: [], locations: [], children, cbRefs: [], refN: tree.refN }; ctx = { collectors: [], locations: [], children, cbRefs: [], refN: tree.refN };
fromIdx = 0; fromIdx = 0;
toIdx = tree.refN - 1;
} }
if (tree.refN) { if (tree.refN) {
const initialIdx = fromIdx!; const initialIdx = fromIdx!;
const isRef = tree.forceRef || tree.info.length > 0; const isRef = tree.isRef;
const firstChild = tree.firstChild ? tree.firstChild.refN : 0; const firstChild = tree.firstChild ? tree.firstChild.refN : 0;
const nextSibling = tree.nextSibling ? tree.nextSibling.refN : 0; const nextSibling = tree.nextSibling ? tree.nextSibling.refN : 0;
@@ -325,13 +327,13 @@ function buildContext(
if (nextSibling) { if (nextSibling) {
const idx = fromIdx! + firstChild; const idx = fromIdx! + firstChild;
ctx.collectors.push({ idx, prevIdx: initialIdx, getVal: nodeGetNextSibling }); ctx.collectors.push({ idx, prevIdx: initialIdx, getVal: nodeGetNextSibling });
buildContext(tree.nextSibling!, ctx, idx, toIdx); buildContext(tree.nextSibling!, ctx, idx);
} }
// left // left
if (firstChild) { if (firstChild) {
ctx.collectors.push({ idx: fromIdx!, prevIdx: initialIdx, getVal: nodeGetFirstChild }); ctx.collectors.push({ idx: fromIdx!, prevIdx: initialIdx, getVal: nodeGetFirstChild });
buildContext(tree.firstChild!, ctx, fromIdx!, toIdx! - nextSibling); buildContext(tree.firstChild!, ctx, fromIdx!);
} }
} }
+1 -1
View File
@@ -4,7 +4,7 @@ export { toggler } from "./toggler";
export { createBlock } from "./block_compiler"; export { createBlock } from "./block_compiler";
export { list } from "./list"; export { list } from "./list";
export { multi } from "./multi"; export { multi } from "./multi";
export { text } from "./text"; export { text, comment } from "./text";
export { html } from "./html"; export { html } from "./html";
export interface VNode<T = any> { export interface VNode<T = any> {
+29 -12
View File
@@ -8,18 +8,17 @@ const nodeInsertBefore = nodeProto.insertBefore;
const characterDataSetData = getDescriptor(characterDataProto, "data").set!; const characterDataSetData = getDescriptor(characterDataProto, "data").set!;
const nodeRemoveChild = nodeProto.removeChild; const nodeRemoveChild = nodeProto.removeChild;
class VText { abstract class VSimpleNode {
text: string; text: string;
parentEl?: HTMLElement | undefined; parentEl?: HTMLElement | undefined;
el?: Text; el?: any;
constructor(text: string) { constructor(text: string) {
this.text = text; this.text = text;
} }
mount(parent: HTMLElement, afterNode: Node | null) { mountNode(node: Node, parent: HTMLElement, afterNode: Node | null) {
this.parentEl = parent; this.parentEl = parent;
const node = document.createTextNode(toText(this.text));
nodeInsertBefore.call(parent, node, afterNode); nodeInsertBefore.call(parent, node, afterNode);
this.el = node; this.el = node;
} }
@@ -29,14 +28,6 @@ class VText {
nodeInsertBefore.call(this.parentEl, this.el!, target); nodeInsertBefore.call(this.parentEl, this.el!, target);
} }
patch(other: VText) {
const text2 = other.text;
if (this.text !== text2) {
characterDataSetData.call(this.el!, toText(text2));
this.text = text2;
}
}
beforeRemove() {} beforeRemove() {}
remove() { remove() {
@@ -52,10 +43,36 @@ class VText {
} }
} }
class VText extends VSimpleNode {
mount(parent: HTMLElement, afterNode: Node | null) {
this.mountNode(document.createTextNode(toText(this.text)), parent, afterNode);
}
patch(other: VText) {
const text2 = other.text;
if (this.text !== text2) {
characterDataSetData.call(this.el!, toText(text2));
this.text = text2;
}
}
}
class VComment extends VSimpleNode {
mount(parent: HTMLElement, afterNode: Node | null) {
this.mountNode(document.createComment(toText(this.text)), parent, afterNode);
}
patch() {}
}
export function text(str: string): VNode<VText> { export function text(str: string): VNode<VText> {
return new VText(str); return new VText(str);
} }
export function comment(str: string): VNode<VComment> {
return new VComment(str);
}
export function toText(value: any): string { export function toText(value: any): string {
switch (typeof value) { switch (typeof value) {
case "string": case "string":
+251 -157
View File
@@ -21,7 +21,7 @@ import {
ASTType, ASTType,
} from "./parser"; } from "./parser";
type BlockType = "block" | "text" | "multi" | "list" | "html"; type BlockType = "block" | "text" | "multi" | "list" | "html" | "comment";
export interface Config { export interface Config {
translateFn?: (s: string) => string; translateFn?: (s: string) => string;
@@ -31,6 +31,7 @@ export interface Config {
export interface CodeGenOptions extends Config { export interface CodeGenOptions extends Config {
hasSafeContext?: boolean; hasSafeContext?: boolean;
name?: string;
} }
// using a non-html document so that <inner/outer>HTML serializes as XML instead // using a non-html document so that <inner/outer>HTML serializes as XML instead
@@ -43,7 +44,11 @@ const xmlDoc = document.implementation.createDocument(null, null, null);
class BlockDescription { class BlockDescription {
static nextBlockId = 1; static nextBlockId = 1;
static nextDataId = 1; static nextDataIds: { [key: string]: number } = {};
static generateId(prefix: string) {
this.nextDataIds[prefix] = (this.nextDataIds[prefix] || 0) + 1;
return prefix + this.nextDataIds[prefix];
}
varName: string; varName: string;
blockName: string; blockName: string;
@@ -68,8 +73,8 @@ class BlockDescription {
this.type = type; this.type = type;
} }
insertData(str: string): number { insertData(str: string, prefix: string = "d"): number {
const id = "d" + BlockDescription.nextDataId++; const id = BlockDescription.generateId(prefix);
this.target.addLine(`let ${id} = ${str};`); this.target.addLine(`let ${id} = ${str};`);
return this.data.push(id) - 1; return this.data.push(id) - 1;
} }
@@ -137,12 +142,15 @@ function createContext(parentCtx: Context, params?: Partial<Context>) {
class CodeTarget { class CodeTarget {
name: string; name: string;
signature: string = "";
indentLevel = 0; indentLevel = 0;
loopLevel = 0; loopLevel = 0;
code: string[] = []; code: string[] = [];
hasRoot = false; hasRoot = false;
hasCache = false; hasCache = false;
hasRef: boolean = false;
// maps ref name to [id, expr]
refInfo: { [name: string]: [string, string] } = {};
shouldProtectScope: boolean = false;
constructor(name: string) { constructor(name: string) {
this.name = name; this.name = name;
@@ -156,6 +164,34 @@ class CodeTarget {
this.code.splice(idx, 0, prefix + line); this.code.splice(idx, 0, prefix + line);
} }
} }
generateCode(): string {
let result: string[] = [];
result.push(`function ${this.name}(ctx, node, key = "") {`);
if (this.hasRef) {
result.push(` const refs = ctx.__owl__.refs;`);
for (let name in this.refInfo) {
const [id, expr] = this.refInfo[name];
result.push(` const ${id} = ${expr};`);
}
}
if (this.shouldProtectScope) {
result.push(` ctx = Object.create(ctx);`);
result.push(` ctx[isBoundary] = 1`);
}
if (this.hasCache) {
result.push(` let cache = ctx.cache || {};`);
result.push(` let nextCache = ctx.cache = {};`);
}
for (let line of this.code) {
result.push(line);
}
if (!this.hasRoot) {
result.push(`return text('');`);
}
result.push(`}`);
return result.join("\n ");
}
} }
const TRANSLATABLE_ATTRS = ["label", "title", "placeholder", "alt"]; const TRANSLATABLE_ATTRS = ["label", "title", "placeholder", "alt"];
@@ -163,36 +199,34 @@ const translationRE = /^(\s*)([\s\S]+?)(\s*)$/;
export class CodeGenerator { export class CodeGenerator {
blocks: BlockDescription[] = []; blocks: BlockDescription[] = [];
nextId = 1; ids: { [key: string]: number } = {};
nextBlockId = 1; nextBlockId = 1;
shouldProtectScope: boolean = false;
shouldDefineAssign: boolean = false;
hasSafeContext: boolean; hasSafeContext: boolean;
hasRef: boolean = false;
isDebug: boolean = false; isDebug: boolean = false;
functions: CodeTarget[] = []; targets: CodeTarget[] = [];
target = new CodeTarget("main"); target = new CodeTarget("template");
templateName: string; templateName?: string;
dev: boolean; dev: boolean;
translateFn: (s: string) => string; translateFn: (s: string) => string;
translatableAttributes: string[]; translatableAttributes: string[];
ast: AST; ast: AST;
staticCalls: { id: string; template: string }[] = []; staticCalls: { id: string; template: string }[] = [];
helpers: Set<string> = new Set();
constructor(name: string, ast: AST, options: CodeGenOptions) { constructor(ast: AST, options: CodeGenOptions) {
this.translateFn = options.translateFn || ((s: string) => s); this.translateFn = options.translateFn || ((s: string) => s);
this.translatableAttributes = options.translatableAttributes || TRANSLATABLE_ATTRS; this.translatableAttributes = options.translatableAttributes || TRANSLATABLE_ATTRS;
this.hasSafeContext = options.hasSafeContext || false; this.hasSafeContext = options.hasSafeContext || false;
this.dev = options.dev || false; this.dev = options.dev || false;
this.ast = ast; this.ast = ast;
this.templateName = name; this.templateName = options.name;
} }
generateCode(): string { generateCode(): string {
const ast = this.ast; const ast = this.ast;
this.isDebug = ast.type === ASTType.TDebug; this.isDebug = ast.type === ASTType.TDebug;
BlockDescription.nextBlockId = 1; BlockDescription.nextBlockId = 1;
BlockDescription.nextDataId = 1; BlockDescription.nextDataIds = {};
this.compileAST(ast, { this.compileAST(ast, {
block: null, block: null,
index: 0, index: 0,
@@ -201,68 +235,50 @@ export class CodeGenerator {
translate: true, translate: true,
tKeyExpr: null, tKeyExpr: null,
}); });
let mainCode = this.target.code;
this.target.code = [];
this.target.indentLevel = 0;
// define blocks and utility functions // define blocks and utility functions
this.addLine(`let { text, createBlock, list, multi, html, toggler, component } = bdom;`); let mainCode = [
this.addLine( ` let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;`,
`let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;` ];
); if (this.helpers.size) {
if (this.shouldDefineAssign) { mainCode.push(`let { ${[...this.helpers].join(", ")} } = helpers;`);
this.addLine(`let assign = Object.assign;`); }
if (this.templateName) {
mainCode.push(`// Template name: "${this.templateName}"`);
} }
for (let { id, template } of this.staticCalls) { for (let { id, template } of this.staticCalls) {
this.addLine(`const ${id} = getTemplate(${template});`); mainCode.push(`const ${id} = getTemplate(${template});`);
} }
// define all blocks // define all blocks
if (this.blocks.length) { if (this.blocks.length) {
this.addLine(``); mainCode.push(``);
for (let block of this.blocks) { for (let block of this.blocks) {
if (block.dom) { if (block.dom) {
let xmlString = block.asXmlString(); let xmlString = block.asXmlString();
if (block.dynamicTagName) { if (block.dynamicTagName) {
xmlString = xmlString.replace(/^<\w+/, `<\${tag || '${block.dom.nodeName}'}`); xmlString = xmlString.replace(/^<\w+/, `<\${tag || '${block.dom.nodeName}'}`);
xmlString = xmlString.replace(/\w+>$/, `\${tag || '${block.dom.nodeName}'}>`); xmlString = xmlString.replace(/\w+>$/, `\${tag || '${block.dom.nodeName}'}>`);
this.addLine(`let ${block.blockName} = tag => createBlock(\`${xmlString}\`);`); mainCode.push(`let ${block.blockName} = tag => createBlock(\`${xmlString}\`);`);
} else { } else {
this.addLine(`let ${block.blockName} = createBlock(\`${xmlString}\`);`); mainCode.push(`let ${block.blockName} = createBlock(\`${xmlString}\`);`);
} }
} }
} }
} }
// define all slots // define all slots/defaultcontent function
for (let fn of this.functions) { if (this.targets.length) {
this.generateFunctions(fn); for (let fn of this.targets) {
mainCode.push("");
mainCode = mainCode.concat(fn.generateCode());
}
} }
// // generate main code // generate main code
this.target.indentLevel = 0; mainCode.push("");
this.addLine(``); mainCode = mainCode.concat("return " + this.target.generateCode());
this.addLine(`return function template(ctx, node, key = "") {`); const code = mainCode.join("\n ");
if (this.hasRef) {
this.addLine(` const refs = ctx.__owl__.refs;`);
}
if (this.shouldProtectScope) {
this.addLine(` ctx = Object.create(ctx);`);
this.addLine(` ctx[isBoundary] = 1`);
}
if (this.target.hasCache) {
this.addLine(` let cache = ctx.cache || {};`);
this.addLine(` let nextCache = ctx.cache = {};`);
}
for (let line of mainCode) {
this.addLine(line);
}
if (!this.target.hasRoot) {
throw new Error("missing root block");
}
this.addLine("}");
const code = this.target.code.join("\n");
if (this.isDebug) { if (this.isDebug) {
const msg = `[Owl Debug]\n${code}`; const msg = `[Owl Debug]\n${code}`;
@@ -271,16 +287,25 @@ export class CodeGenerator {
return code; return code;
} }
compileInNewTarget(prefix: string, ast: AST, ctx: Context): string {
const name = this.generateId(prefix);
const initialTarget = this.target;
const target = new CodeTarget(name);
this.targets.push(target);
this.target = target;
const subCtx: Context = createContext(ctx);
this.compileAST(ast, subCtx);
this.target = initialTarget;
return name;
}
addLine(line: string) { addLine(line: string) {
this.target.addLine(line); this.target.addLine(line);
} }
generateId(prefix: string = ""): string { generateId(prefix: string = ""): string {
return `${prefix}${this.nextId++}`; this.ids[prefix] = (this.ids[prefix] || 0) + 1;
} return prefix + this.ids[prefix];
generateBlockName(): string {
return `block${this.blocks.length + 1}`;
} }
insertAnchor(block: BlockDescription) { insertAnchor(block: BlockDescription) {
@@ -317,6 +342,7 @@ export class CodeGenerator {
if (tKeyExpr) { if (tKeyExpr) {
keyArg = `${tKeyExpr} + ${keyArg}`; keyArg = `${tKeyExpr} + ${keyArg}`;
} }
this.helpers.add("withKey");
this.addLine(`${block.parentVar}[${ctx.index}] = withKey(${blockExpr}, ${keyArg});`); this.addLine(`${block.parentVar}[${ctx.index}] = withKey(${blockExpr}, ${keyArg});`);
return; return;
} }
@@ -332,20 +358,23 @@ export class CodeGenerator {
} }
} }
generateFunctions(fn: CodeTarget) { /**
this.addLine(""); * Captures variables that are used inside of an expression. This is useful
this.addLine(`const ${fn.name} = ${fn.signature}`); * because in compiled code, almost all variables are accessed through the ctx
if (fn.hasCache) { * object. In the case of functions, that lookup in the context can be delayed
this.addLine(`let cache = ctx.cache || {};`); * which can cause issues if the value has changed since the function was
this.addLine(`let nextCache = ctx.cache = {};`); * defined.
*
* @param expr the expression to capture
* @param forceCapture whether the expression should capture its scope even if
* it doesn't contain a function. Useful when the expression will be used as
* a function body.
* @returns a new expression that uses the captured values
*/
captureExpression(expr: string, forceCapture: boolean = false): string {
if (!forceCapture && !expr.includes("=>")) {
return compileExpr(expr);
} }
for (let line of fn.code) {
this.addLine(line);
}
this.addLine(`}`);
}
captureExpression(expr: string): string {
const tokens = compileExprToArray(expr); const tokens = compileExprToArray(expr);
const mapping = new Map<string, string>(); const mapping = new Map<string, string>();
return tokens return tokens
@@ -436,13 +465,14 @@ export class CodeGenerator {
let { block, forceNewBlock } = ctx; let { block, forceNewBlock } = ctx;
const isNewBlock = !block || forceNewBlock; const isNewBlock = !block || forceNewBlock;
if (isNewBlock) { if (isNewBlock) {
block = this.createBlock(block, "block", ctx); block = this.createBlock(block, "comment", ctx);
this.blocks.push(block); this.insertBlock(`comment(\`${ast.value}\`)`, block, {
} ...ctx,
forceNewBlock: forceNewBlock && !block,
});
} else {
const text = xmlDoc.createComment(ast.value); const text = xmlDoc.createComment(ast.value);
block!.insert(text); block!.insert(text);
if (isNewBlock) {
this.insertBlock("", block!, ctx);
} }
} }
@@ -497,14 +527,18 @@ export class CodeGenerator {
} }
// attributes // attributes
const attrs: { [key: string]: string } = {}; const attrs: { [key: string]: string } = {};
if (ast.ns) {
// specific namespace uri
attrs["block-ns"] = ast.ns;
}
for (let key in ast.attrs) { for (let key in ast.attrs) {
if (key.startsWith("t-attf")) { if (key.startsWith("t-attf")) {
let expr = interpolate(ast.attrs[key]); let expr = interpolate(ast.attrs[key]);
const idx = block!.insertData(expr); const idx = block!.insertData(expr, "attr");
attrs["block-attribute-" + idx] = key.slice(7); attrs["block-attribute-" + idx] = key.slice(7);
} else if (key.startsWith("t-att")) { } else if (key.startsWith("t-att")) {
let expr = compileExpr(ast.attrs[key]); let expr = compileExpr(ast.attrs[key]);
const idx = block!.insertData(expr); const idx = block!.insertData(expr, "attr");
if (key === "t-att") { if (key === "t-att") {
attrs[`block-attributes`] = String(idx); attrs[`block-attributes`] = String(idx);
} else { } else {
@@ -520,24 +554,36 @@ export class CodeGenerator {
// event handlers // event handlers
for (let ev in ast.on) { for (let ev in ast.on) {
const name = this.generateHandlerCode(ev, ast.on[ev]); const name = this.generateHandlerCode(ev, ast.on[ev]);
const idx = block!.insertData(name); const idx = block!.insertData(name, "hdlr");
attrs[`block-handler-${idx}`] = ev; attrs[`block-handler-${idx}`] = ev;
} }
// t-ref // t-ref
if (ast.ref) { if (ast.ref) {
this.hasRef = true; this.target.hasRef = true;
const isDynamic = INTERP_REGEXP.test(ast.ref); const isDynamic = INTERP_REGEXP.test(ast.ref);
if (isDynamic) { if (isDynamic) {
const str = ast.ref.replace( const str = ast.ref.replace(
INTERP_REGEXP, INTERP_REGEXP,
(expr) => "${" + this.captureExpression(expr.slice(2, -2)) + "}" (expr) => "${" + this.captureExpression(expr.slice(2, -2), true) + "}"
); );
const idx = block!.insertData(`(el) => refs[\`${str}\`] = el`); const idx = block!.insertData(`(el) => refs[\`${str}\`] = el`, "ref");
attrs["block-ref"] = String(idx); attrs["block-ref"] = String(idx);
} else { } else {
const idx = block!.insertData(`(el) => refs[\`${ast.ref}\`] = el`); let name = ast.ref;
attrs["block-ref"] = String(idx); if (name in this.target.refInfo) {
// ref has already been defined
this.helpers.add("multiRefSetter");
const info = this.target.refInfo[name];
const index = block!.data.push(info[0]) - 1;
attrs["block-ref"] = String(index);
info[1] = `multiRefSetter(refs, \`${name}\`)`;
} else {
let id = this.generateId("ref");
this.target.refInfo[name] = [id, `(el) => refs[\`${name}\`] = el`];
const index = block!.data.push(id) - 1;
attrs["block-ref"] = String(index);
}
} }
} }
@@ -561,18 +607,22 @@ export class CodeGenerator {
let idx: number; let idx: number;
if (specialInitTargetAttr) { if (specialInitTargetAttr) {
idx = block!.insertData(`${baseExpression}[${expression}] === '${attrs[targetAttr]}'`); idx = block!.insertData(
`${baseExpression}[${expression}] === '${attrs[targetAttr]}'`,
"attr"
);
attrs[`block-attribute-${idx}`] = specialInitTargetAttr; attrs[`block-attribute-${idx}`] = specialInitTargetAttr;
} else { } else {
idx = block!.insertData(`${baseExpression}[${expression}]`); idx = block!.insertData(`${baseExpression}[${expression}]`, "attr");
attrs[`block-attribute-${idx}`] = targetAttr; attrs[`block-attribute-${idx}`] = targetAttr;
} }
this.helpers.add("toNumber");
let valueCode = `ev.target.${targetAttr}`; let valueCode = `ev.target.${targetAttr}`;
valueCode = shouldTrim ? `${valueCode}.trim()` : valueCode; valueCode = shouldTrim ? `${valueCode}.trim()` : valueCode;
valueCode = shouldNumberize ? `toNumber(${valueCode})` : valueCode; valueCode = shouldNumberize ? `toNumber(${valueCode})` : valueCode;
const handler = `[(ev) => { bExpr${id}[${expression}] = ${valueCode}; }]`; const handler = `[(ev) => { bExpr${id}[${expression}] = ${valueCode}; }]`;
idx = block!.insertData(handler); idx = block!.insertData(handler, "hdlr");
attrs[`block-handler-${idx}`] = eventType; attrs[`block-handler-${idx}`] = eventType;
} }
@@ -623,10 +673,12 @@ export class CodeGenerator {
let { block, forceNewBlock } = ctx; let { block, forceNewBlock } = ctx;
let expr: string; let expr: string;
if (ast.expr === "0") { if (ast.expr === "0") {
this.helpers.add("zero");
expr = `ctx[zero]`; expr = `ctx[zero]`;
} else { } else {
expr = compileExpr(ast.expr); expr = compileExpr(ast.expr);
if (ast.defaultValue) { if (ast.defaultValue) {
this.helpers.add("withDefault");
expr = `withDefault(${expr}, \`${ast.defaultValue}\`)`; expr = `withDefault(${expr}, \`${ast.defaultValue}\`)`;
} }
} }
@@ -634,7 +686,7 @@ export class CodeGenerator {
block = this.createBlock(block, "text", ctx); block = this.createBlock(block, "text", ctx);
this.insertBlock(`text(${expr})`, block, { ...ctx, forceNewBlock: forceNewBlock && !block }); this.insertBlock(`text(${expr})`, block, { ...ctx, forceNewBlock: forceNewBlock && !block });
} else { } else {
const idx = block.insertData(expr); const idx = block.insertData(expr, "txt");
const text = xmlDoc.createElement(`block-text-${idx}`); const text = xmlDoc.createElement(`block-text-${idx}`);
block.insert(text); block.insert(text);
} }
@@ -646,11 +698,13 @@ export class CodeGenerator {
this.insertAnchor(block); this.insertAnchor(block);
} }
block = this.createBlock(block, "html", ctx); block = this.createBlock(block, "html", ctx);
this.helpers.add(ast.expr === "0" ? "zero" : "safeOutput");
let expr = ast.expr === "0" ? "ctx[zero]" : `safeOutput(${compileExpr(ast.expr)})`; let expr = ast.expr === "0" ? "ctx[zero]" : `safeOutput(${compileExpr(ast.expr)})`;
if (ast.body) { if (ast.body) {
const nextId = BlockDescription.nextBlockId; const nextId = BlockDescription.nextBlockId;
const subCtx: Context = createContext(ctx); const subCtx: Context = createContext(ctx);
this.compileAST({ type: ASTType.Multi, content: ast.body }, subCtx); this.compileAST({ type: ASTType.Multi, content: ast.body }, subCtx);
this.helpers.add("withDefault");
expr = `withDefault(${expr}, b${nextId})`; expr = `withDefault(${expr}, b${nextId})`;
} }
this.insertBlock(`${expr}`, block, ctx); this.insertBlock(`${expr}`, block, ctx);
@@ -727,9 +781,14 @@ export class CodeGenerator {
const keys = `k_block${block.id}`; const keys = `k_block${block.id}`;
const l = `l_block${block.id}`; const l = `l_block${block.id}`;
const c = `c_block${block.id}`; const c = `c_block${block.id}`;
this.helpers.add("prepareList");
this.addLine( this.addLine(
`const [${keys}, ${vals}, ${l}, ${c}] = prepareList(${compileExpr(ast.collection)});` `const [${keys}, ${vals}, ${l}, ${c}] = prepareList(${compileExpr(ast.collection)});`
); );
// Throw errors on duplicate keys in dev mode
if (this.dev) {
this.addLine(`const keys${block.id} = new Set();`);
}
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}\`] = ${vals}[${loopVar}];`);
@@ -746,10 +805,16 @@ export class CodeGenerator {
this.addLine(`ctx[\`${ast.elem}_value\`] = ${keys}[${loopVar}];`); this.addLine(`ctx[\`${ast.elem}_value\`] = ${keys}[${loopVar}];`);
} }
this.addLine(`let key${this.target.loopLevel} = ${ast.key ? compileExpr(ast.key) : loopVar};`); this.addLine(`let key${this.target.loopLevel} = ${ast.key ? compileExpr(ast.key) : loopVar};`);
if (this.dev) {
// Throw error on duplicate keys in dev mode
this.addLine(
`if (keys${block.id}.has(key${this.target.loopLevel})) { throw new Error(\`Got duplicate key in t-foreach: \${key${this.target.loopLevel}}\`)}`
);
this.addLine(`keys${block.id}.add(key${this.target.loopLevel});`);
}
let id: string; let id: string;
if (ast.memo) { if (ast.memo) {
this.target.hasCache = true; this.target.hasCache = true;
this.shouldDefineAssign = true;
id = this.generateId(); id = this.generateId();
this.addLine(`let memo${id} = ${compileExpr(ast.memo)}`); this.addLine(`let memo${id} = ${compileExpr(ast.memo)}`);
this.addLine(`let vnode${id} = cache[key${this.target.loopLevel}];`); this.addLine(`let vnode${id} = cache[key${this.target.loopLevel}];`);
@@ -770,7 +835,9 @@ export class CodeGenerator {
this.compileAST(ast.body, subCtx); this.compileAST(ast.body, subCtx);
if (ast.memo) { if (ast.memo) {
this.addLine( this.addLine(
`nextCache[key${this.target.loopLevel}] = assign(${c}[${loopVar}], {memo: memo${id!}});` `nextCache[key${
this.target.loopLevel
}] = Object.assign(${c}[${loopVar}], {memo: memo${id!}});`
); );
} }
this.target.indentLevel--; this.target.indentLevel--;
@@ -850,10 +917,12 @@ export class CodeGenerator {
if (ast.body) { if (ast.body) {
this.addLine(`ctx = Object.create(ctx);`); this.addLine(`ctx = Object.create(ctx);`);
this.addLine(`ctx[isBoundary] = 1;`); this.addLine(`ctx[isBoundary] = 1;`);
this.helpers.add("isBoundary");
const nextId = BlockDescription.nextBlockId; const nextId = BlockDescription.nextBlockId;
const subCtx: Context = createContext(ctx, { preventRoot: true }); const subCtx: Context = createContext(ctx, { preventRoot: true });
this.compileAST({ type: ASTType.Multi, content: ast.body }, subCtx); this.compileAST({ type: ASTType.Multi, content: ast.body }, subCtx);
if (nextId !== BlockDescription.nextBlockId) { if (nextId !== BlockDescription.nextBlockId) {
this.helpers.add("zero");
this.addLine(`ctx[zero] = b${nextId};`); this.addLine(`ctx[zero] = b${nextId};`);
} }
} }
@@ -869,12 +938,14 @@ export class CodeGenerator {
const templateVar = this.generateId("template"); const templateVar = this.generateId("template");
this.addLine(`const ${templateVar} = ${subTemplate};`); this.addLine(`const ${templateVar} = ${subTemplate};`);
block = this.createBlock(block, "multi", ctx); block = this.createBlock(block, "multi", ctx);
this.insertBlock(`call(${templateVar}, ctx, node, ${key})`, block!, { this.helpers.add("call");
this.insertBlock(`call(this, ${templateVar}, ctx, node, ${key})`, block!, {
...ctx, ...ctx,
forceNewBlock: !block, forceNewBlock: !block,
}); });
} else { } else {
const id = this.generateId(`callTemplate_`); const id = this.generateId(`callTemplate_`);
this.helpers.add("getTemplate");
this.staticCalls.push({ id, template: subTemplate }); this.staticCalls.push({ id, template: subTemplate });
block = this.createBlock(block, "multi", ctx); block = this.createBlock(block, "multi", ctx);
this.insertBlock(`${id}.call(this, ctx, node, ${key})`, block!, { this.insertBlock(`${id}.call(this, ctx, node, ${key})`, block!, {
@@ -899,13 +970,15 @@ export class CodeGenerator {
} }
compileTSet(ast: ASTTSet, ctx: Context) { compileTSet(ast: ASTTSet, ctx: Context) {
this.shouldProtectScope = true; this.target.shouldProtectScope = true;
this.helpers.add("isBoundary").add("withDefault");
const expr = ast.value ? compileExpr(ast.value || "") : "null"; const expr = ast.value ? compileExpr(ast.value || "") : "null";
if (ast.body) { if (ast.body) {
const subCtx: Context = createContext(ctx); this.helpers.add("LazyValue");
const nextId = `b${BlockDescription.nextBlockId}`; const bodyAst: AST = { type: ASTType.Multi, content: ast.body };
this.compileAST({ type: ASTType.Multi, content: ast.body }, subCtx); const name = this.compileInNewTarget("value", bodyAst, ctx);
const value = ast.value ? (nextId ? `withDefault(${expr}, ${nextId})` : expr) : nextId; let value = `new LazyValue(${name}, ctx, node)`;
value = ast.value ? (value ? `withDefault(${expr}, ${value})` : expr) : value;
this.addLine(`ctx[\`${ast.name}\`] = ${value};`); this.addLine(`ctx[\`${ast.name}\`] = ${value};`);
} else { } else {
let value: string; let value: string;
@@ -918,6 +991,7 @@ export class CodeGenerator {
} else { } else {
value = expr; value = expr;
} }
this.helpers.add("setContextValue");
this.addLine(`setContextValue(ctx, "${ast.name}", ${value});`); this.addLine(`setContextValue(ctx, "${ast.name}", ${value});`);
} }
} }
@@ -932,13 +1006,61 @@ export class CodeGenerator {
compileComponent(ast: ASTComponent, ctx: Context) { compileComponent(ast: ASTComponent, ctx: Context) {
let { block } = ctx; let { block } = ctx;
let extraArgs: { [key: string]: string } = {};
// props // props
const props: string[] = []; const props: string[] = [];
for (let p in ast.props) { let hasSlotsProp = false;
props.push(`${p}: ${compileExpr(ast.props[p]) || undefined}`); for (let propName in ast.props) {
let propValue = this.captureExpression(ast.props[propName]) || undefined;
if (propName.includes(".")) {
let [name, suffix] = propName.split(".");
if (suffix === "bind") {
this.helpers.add("bind");
propName = name;
propValue = `bind(ctx, ${propValue})`;
} }
}
propName = /^[a-z_]+$/i.test(propName) ? propName : `'${propName}'`;
props.push(`${propName}: ${propValue}`);
if (propName === "slots") {
hasSlotsProp = true;
}
}
// slots
const hasSlot = !!Object.keys(ast.slots).length;
let slotDef: string = "";
if (hasSlot) {
let ctxStr = "ctx";
if (this.target.loopLevel || !this.hasSafeContext) {
ctxStr = this.generateId("ctx");
this.helpers.add("capture");
this.addLine(`const ${ctxStr} = capture(ctx);`);
}
let slotStr: string[] = [];
for (let slotName in ast.slots) {
const slotAst = ast.slots[slotName].content;
const name = this.compileInNewTarget("slot", slotAst, ctx);
const params = [`__render: ${name}, __ctx: ${ctxStr}`];
const scope = ast.slots[slotName].scope;
if (scope) {
params.push(`__scope: "${scope}"`);
}
if (ast.slots[slotName].attrs) {
for (const [n, v] of Object.entries(ast.slots[slotName].attrs!)) {
params.push(`${n}: ${compileExpr(v) || undefined}`);
}
}
const slotInfo = `{${params.join(", ")}}`;
slotStr.push(`'${slotName}': ${slotInfo}`);
}
slotDef = `{${slotStr.join(", ")}}`;
}
if (slotDef && !(ast.dynamicProps || hasSlotsProp)) {
props.push(`slots: ${slotDef}`);
}
const propStr = `{${props.join(",")}}`; const propStr = `{${props.join(",")}}`;
let propString = propStr; let propString = propStr;
@@ -950,6 +1072,17 @@ export class CodeGenerator {
} }
} }
let propVar: string;
if ((slotDef && (ast.dynamicProps || hasSlotsProp)) || this.dev) {
propVar = this.generateId("props");
this.addLine(`const ${propVar!} = ${propString}`);
propString = propVar!;
}
if (slotDef && (ast.dynamicProps || hasSlotsProp)) {
this.addLine(`${propVar!}.slots = Object.assign(${slotDef}, ${propVar!}.slots)`);
}
// cmap key // cmap key
const key = this.generateComponentKey(); const key = this.generateComponentKey();
let expr: string; let expr: string;
@@ -961,41 +1094,7 @@ export class CodeGenerator {
} }
if (this.dev) { if (this.dev) {
const propVar = this.generateId("props"); this.addLine(`helpers.validateProps(${expr}, ${propVar!}, ctx)`);
this.addLine(`const ${propVar} = ${propString}`);
this.addLine(`helpers.validateProps(${expr}, ${propVar}, ctx)`);
propString = propVar;
}
// slots
const hasSlot = !!Object.keys(ast.slots).length;
let slotDef: string;
if (hasSlot) {
let ctxStr = "ctx";
if (this.target.loopLevel || !this.hasSafeContext) {
ctxStr = this.generateId("ctx");
this.addLine(`const ${ctxStr} = capture(ctx);`);
}
let slotStr: string[] = [];
const initialTarget = this.target;
for (let slotName in ast.slots) {
let name = this.generateId("slot");
const slot = new CodeTarget(name);
slot.signature = "ctx => (node, key) => {";
this.functions.push(slot);
this.target = slot;
const subCtx: Context = createContext(ctx);
this.compileAST(ast.slots[slotName], subCtx);
if (this.hasRef) {
slot.code.unshift(` const refs = ctx.__owl__.refs`);
slotStr.push(`'${slotName}': ${name}(${ctxStr})`);
} else {
slotStr.push(`'${slotName}': ${name}(${ctxStr})`);
}
}
this.target = initialTarget;
slotDef = `{${slotStr.join(", ")}}`;
extraArgs.slots = slotDef;
} }
if (block && (ctx.forceNewBlock === false || ctx.tKeyExpr)) { if (block && (ctx.forceNewBlock === false || ctx.tKeyExpr)) {
@@ -1003,17 +1102,9 @@ export class CodeGenerator {
this.insertAnchor(block); this.insertAnchor(block);
} }
let keyArg = `key + \`${key}\``; const keyArg = `key+\`${key}\`,${ctx.tKeyExpr}`;
if (ctx.tKeyExpr) {
keyArg = `${ctx.tKeyExpr} + ${keyArg}`;
}
const blockArgs = `${expr}, ${propString}, ${keyArg}, node, ctx`; const blockArgs = `${expr}, ${propString}, ${keyArg}, node, ctx`;
let blockExpr = `component(${blockArgs})`; let blockExpr = `component(${blockArgs})`;
if (Object.keys(extraArgs).length) {
this.shouldDefineAssign = true;
const content = Object.keys(extraArgs).map((k) => `${k}: ${extraArgs[k]}`);
blockExpr = `assign(${blockExpr}, {${content.join(", ")}})`;
}
if (ast.isDynamic) { if (ast.isDynamic) {
blockExpr = `toggler(${expr}, ${blockExpr})`; blockExpr = `toggler(${expr}, ${blockExpr})`;
} }
@@ -1022,6 +1113,7 @@ export class CodeGenerator {
} }
compileTSlot(ast: ASTSlot, ctx: Context) { compileTSlot(ast: ASTSlot, ctx: Context) {
this.helpers.add("callSlot");
let { block } = ctx; let { block } = ctx;
let blockString: string; let blockString: string;
let slotName; let slotName;
@@ -1032,24 +1124,26 @@ export class CodeGenerator {
} else { } else {
slotName = "'" + ast.name + "'"; slotName = "'" + ast.name + "'";
} }
let scope = null;
if (ast.attrs) {
const params = [];
for (const [n, v] of Object.entries(ast.attrs!)) {
params.push(`${n}: ${compileExpr(v) || undefined}`);
}
scope = `{${params.join(", ")}}`;
}
if (ast.defaultContent) { if (ast.defaultContent) {
let name = this.generateId("defaultSlot"); const name = this.compileInNewTarget("defaultContent", ast.defaultContent, ctx);
const slot = new CodeTarget(name); blockString = `callSlot(ctx, node, key, ${slotName}, ${dynamic}, ${scope}, ${name})`;
slot.signature = "ctx => {";
this.functions.push(slot);
const initialTarget = this.target;
const subCtx: Context = createContext(ctx);
this.target = slot;
this.compileAST(ast.defaultContent, subCtx);
this.target = initialTarget;
blockString = `callSlot(ctx, node, key, ${slotName}, ${name}, ${dynamic})`;
} else { } else {
if (dynamic) { if (dynamic) {
let name = this.generateId("slot"); let name = this.generateId("slot");
this.addLine(`const ${name} = ${slotName};`); this.addLine(`const ${name} = ${slotName};`);
blockString = `toggler(${name}, callSlot(ctx, node, key, ${name}))`; blockString = `toggler(${name}, callSlot(ctx, node, key, ${name}), ${dynamic}, ${scope})`;
} else { } else {
blockString = `callSlot(ctx, node, key, ${slotName})`; blockString = `callSlot(ctx, node, key, ${slotName}, ${dynamic}, ${scope})`;
} }
} }
if (block) { if (block) {
+1 -4
View File
@@ -9,7 +9,6 @@ export type TemplateFunction = (blocks: any, utils: any) => Template;
interface CompileOptions extends Config { interface CompileOptions extends Config {
name?: string; name?: string;
} }
let nextId = 1;
export function compile(template: string | Node, options: CompileOptions = {}): TemplateFunction { export function compile(template: string | Node, options: CompileOptions = {}): TemplateFunction {
// parsing // parsing
const ast = parse(template); const ast = parse(template);
@@ -19,12 +18,10 @@ export function compile(template: string | Node, options: CompileOptions = {}):
template instanceof Node template instanceof Node
? !(template instanceof Element) || template.querySelector("[t-set], [t-call]") === null ? !(template instanceof Element) || template.querySelector("[t-set], [t-call]") === null
: !template.includes("t-set") && !template.includes("t-call"); : !template.includes("t-set") && !template.includes("t-call");
const name = options.name || `template_${nextId++}`;
// code generation // code generation
const codeGenerator = new CodeGenerator(name, ast, { ...options, hasSafeContext }); const codeGenerator = new CodeGenerator(ast, { ...options, hasSafeContext });
const code = codeGenerator.generateCode(); const code = codeGenerator.generateCode();
// template function // template function
return new Function("bdom, helpers", code) as TemplateFunction; return new Function("bdom, helpers", code) as TemplateFunction;
} }
+167 -89
View File
@@ -49,6 +49,7 @@ export interface ASTDomNode {
shouldTrim: boolean; shouldTrim: boolean;
shouldNumberize: boolean; shouldNumberize: boolean;
} | null; } | null;
ns: string | null;
} }
export interface ASTMulti { export interface ASTMulti {
@@ -117,12 +118,13 @@ export interface ASTComponent {
isDynamic: boolean; isDynamic: boolean;
dynamicProps: string | null; dynamicProps: string | null;
props: { [name: string]: string }; props: { [name: string]: string };
slots: { [name: string]: AST }; slots: { [name: string]: { content: AST; attrs?: { [key: string]: string }; scope?: string } };
} }
export interface ASTSlot { export interface ASTSlot {
type: ASTType.TSlot; type: ASTType.TSlot;
name: string; name: string;
attrs: { [key: string]: string };
defaultContent: AST | null; defaultContent: AST | null;
} }
@@ -171,11 +173,13 @@ export type AST =
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
interface ParsingContext { interface ParsingContext {
inPreTag: boolean; inPreTag: boolean;
inSVG: boolean;
} }
export function parse(xml: string | Node): AST { export function parse(xml: string | Node): AST {
const node = xml instanceof Element ? xml : parseXML(`<t>${xml}</t>`).firstChild!; const node = xml instanceof Element ? xml : (parseXML(`<t>${xml}</t>`).firstChild! as Element);
const ctx = { inPreTag: false }; normalizeXML(node);
const ctx = { inPreTag: false, inSVG: false };
const ast = parseNode(node, ctx); const ast = parseNode(node, ctx);
if (!ast) { if (!ast) {
return { type: ASTType.Text, value: "" }; return { type: ASTType.Text, value: "" };
@@ -213,24 +217,7 @@ function parseTNode(node: Element, ctx: ParsingContext): AST | null {
if (node.tagName !== "t") { if (node.tagName !== "t") {
return null; return null;
} }
const children: AST[] = []; return parseChildNodes(node, ctx);
for (let child of node.childNodes) {
const ast = parseNode(child, ctx);
if (ast) {
children.push(ast);
}
}
switch (children.length) {
case 0:
return null;
case 1:
return children[0];
default:
return {
type: ASTType.Multi,
content: children,
};
}
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@@ -240,7 +227,7 @@ const lineBreakRE = /[\r\n]/;
const whitespaceRE = /\s+/g; const whitespaceRE = /\s+/g;
function parseTextCommentNode(node: ChildNode, ctx: ParsingContext): AST | null { function parseTextCommentNode(node: ChildNode, ctx: ParsingContext): AST | null {
if (node.nodeType === 3) { if (node.nodeType === Node.TEXT_NODE) {
let value = node.textContent || ""; let value = node.textContent || "";
if (!ctx.inPreTag) { if (!ctx.inPreTag) {
if (lineBreakRE.test(value) && !value.trim()) { if (lineBreakRE.test(value) && !value.trim()) {
@@ -250,7 +237,7 @@ function parseTextCommentNode(node: ChildNode, ctx: ParsingContext): AST | null
} }
return { type: ASTType.Text, value }; return { type: ASTType.Text, value };
} else if (node.nodeType === 8) { } else if (node.nodeType === Node.COMMENT_NODE) {
return { type: ASTType.Comment, value: node.textContent || "" }; return { type: ASTType.Comment, value: node.textContent || "" };
} }
return null; return null;
@@ -289,27 +276,22 @@ const hasBracketsAtTheEnd = /\[[^\[]+\]\s*$/;
function parseDOMNode(node: Element, ctx: ParsingContext): AST | null { function parseDOMNode(node: Element, ctx: ParsingContext): AST | null {
const { tagName } = node; const { tagName } = node;
let dynamicTag = null; const dynamicTag = node.getAttribute("t-tag");
if (node.hasAttribute("t-tag")) {
dynamicTag = node.getAttribute("t-tag");
node.removeAttribute("t-tag"); node.removeAttribute("t-tag");
}
if (tagName === "t" && !dynamicTag) { if (tagName === "t" && !dynamicTag) {
return null; return null;
} }
const children: AST[] = []; ctx = Object.assign({}, ctx);
if (tagName === "pre") { if (tagName === "pre") {
ctx = { inPreTag: true }; ctx.inPreTag = true;
} }
const shouldAddSVGNS = tagName === "svg" || (tagName === "g" && !ctx.inSVG);
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");
for (let child of node.childNodes) { const children = parseChildren(node, ctx);
const ast = parseNode(child, ctx);
if (ast) {
children.push(ast);
}
}
const nodeAttrsNames = node.getAttributeNames(); const nodeAttrsNames = node.getAttributeNames();
const attrs: ASTDomNode["attrs"] = {}; const attrs: ASTDomNode["attrs"] = {};
@@ -381,6 +363,7 @@ function parseDOMNode(node: Element, ctx: ParsingContext): AST | null {
ref, ref,
content: children, content: children,
model, model,
ns,
}; };
} }
@@ -590,17 +573,11 @@ function parseTCall(node: Element, ctx: ParsingContext): AST | null {
if (ast && ast.type === ASTType.TComponent) { if (ast && ast.type === ASTType.TComponent) {
return { return {
...ast, ...ast,
slots: { default: tcall }, slots: { default: { content: tcall } },
}; };
} }
} }
const body: AST[] = []; const body = parseChildren(node, ctx);
for (let child of node.childNodes) {
const ast = parseNode(child, ctx);
if (ast) {
body.push(ast);
}
}
return { return {
type: ASTType.TCall, type: ASTType.TCall,
@@ -634,10 +611,7 @@ function parseTIf(node: Element, ctx: ParsingContext): AST | null {
} }
const condition = node.getAttribute("t-if")!; const condition = node.getAttribute("t-if")!;
node.removeAttribute("t-if"); node.removeAttribute("t-if");
const content = parseNode(node, ctx); const content = parseNode(node, ctx) || { type: ASTType.Text, value: "" };
if (!content) {
throw new Error("hmmm");
}
let nextElement = node.nextElementSibling; let nextElement = node.nextElementSibling;
// t-elifs // t-elifs
@@ -684,13 +658,7 @@ function parseTSetNode(node: Element, ctx: ParsingContext): AST | null {
const defaultValue = node.innerHTML === node.textContent ? node.textContent || null : null; const defaultValue = node.innerHTML === node.textContent ? node.textContent || null : null;
let body: AST[] | null = null; let body: AST[] | null = null;
if (node.textContent !== node.innerHTML) { if (node.textContent !== node.innerHTML) {
body = []; body = parseChildren(node, ctx);
for (let child of node.childNodes) {
let childAst = parseNode(child, ctx);
if (childAst) {
body.push(childAst);
}
}
} }
return { type: ASTType.TSet, name, value, defaultValue, body }; return { type: ASTType.TSet, name, value, defaultValue, body };
} }
@@ -699,6 +667,20 @@ function parseTSetNode(node: Element, ctx: ParsingContext): AST | null {
// Components // Components
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// Error messages when trying to use an unsupported directive on a component
const directiveErrorMap = new Map([
["t-on", "t-on is no longer supported on components. Consider passing a callback in props."],
[
"t-ref",
"t-ref is no longer supported on components. Consider exposing only the public part of the component's API through a callback prop.",
],
["t-att", "t-att makes no sense on component: props are already treated as expressions"],
[
"t-attf",
"t-attf is not supported on components: use template strings for string interpolation in props",
],
]);
function parseComponent(node: Element, ctx: ParsingContext): AST | null { function parseComponent(node: Element, ctx: ParsingContext): AST | null {
let name = node.tagName; let name = node.tagName;
const firstLetter = name[0]; const firstLetter = name[0];
@@ -722,10 +704,9 @@ function parseComponent(node: Element, ctx: ParsingContext): AST | null {
const props: ASTComponent["props"] = {}; const props: ASTComponent["props"] = {};
for (let name of node.getAttributeNames()) { for (let name of node.getAttributeNames()) {
const value = node.getAttribute(name)!; const value = node.getAttribute(name)!;
if (name.startsWith("t-on-")) { if (name.startsWith("t-")) {
throw new Error( const message = directiveErrorMap.get(name.split("-").slice(0, 2).join("-"));
"t-on is no longer supported on Component node. Consider passing a callback in props." throw new Error(message || `unsupported directive on Component: ${name}`);
);
} else { } else {
props[name] = value; props[name] = value;
} }
@@ -738,6 +719,11 @@ function parseComponent(node: Element, ctx: ParsingContext): AST | null {
// named slots // named slots
const slotNodes = Array.from(clone.querySelectorAll("[t-set-slot]")); const slotNodes = Array.from(clone.querySelectorAll("[t-set-slot]"));
for (let slotNode of slotNodes) { for (let slotNode of slotNodes) {
if (slotNode.tagName !== "t") {
throw new Error(
`Directive 't-set-slot' can only be used on <t> nodes (used on a <${slotNode.tagName}>)`
);
}
const name = slotNode.getAttribute("t-set-slot")!; const name = slotNode.getAttribute("t-set-slot")!;
// check if this is defined in a sub component (in which case it should // check if this is defined in a sub component (in which case it should
@@ -759,14 +745,27 @@ function parseComponent(node: Element, ctx: ParsingContext): AST | null {
slotNode.remove(); slotNode.remove();
const slotAst = parseNode(slotNode, ctx); const slotAst = parseNode(slotNode, ctx);
if (slotAst) { if (slotAst) {
slots[name] = slotAst; const slotInfo: any = { content: slotAst };
const attrs: { [key: string]: string } = {};
for (let attributeName of slotNode.getAttributeNames()) {
const value = slotNode.getAttribute(attributeName)!;
if (attributeName === "t-slot-scope") {
slotInfo.scope = value;
continue;
}
attrs[attributeName] = value;
}
if (Object.keys(attrs).length) {
slotInfo.attrs = attrs;
}
slots[name] = slotInfo;
} }
} }
// default slot // default slot
const defaultContent = parseChildNodes(clone, ctx); const defaultContent = parseChildNodes(clone, ctx);
if (defaultContent) { if (defaultContent) {
slots.default = defaultContent; slots.default = { content: defaultContent };
} }
} }
return { type: ASTType.TComponent, name, isDynamic, dynamicProps, props, slots }; return { type: ASTType.TComponent, name, isDynamic, dynamicProps, props, slots };
@@ -780,9 +779,17 @@ function parseTSlot(node: Element, ctx: ParsingContext): AST | null {
if (!node.hasAttribute("t-slot")) { if (!node.hasAttribute("t-slot")) {
return null; return null;
} }
const name = node.getAttribute("t-slot")!;
node.removeAttribute("t-slot");
const attrs: { [key: string]: string } = {};
for (let attributeName of node.getAttributeNames()) {
const value = node.getAttribute(attributeName)!;
attrs[attributeName] = value;
}
return { return {
type: ASTType.TSlot, type: ASTType.TSlot,
name: node.getAttribute("t-slot")!, name,
attrs,
defaultContent: parseChildNodes(node, ctx), defaultContent: parseChildNodes(node, ctx),
}; };
} }
@@ -802,14 +809,30 @@ function parseTTranslation(node: Element, ctx: ParsingContext): AST | null {
// helpers // helpers
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
function parseChildNodes(node: Element, ctx: ParsingContext): AST | null { /**
* Parse all the child nodes of a given node and return a list of ast elements
*/
function parseChildren(node: Node, ctx: ParsingContext): AST[] {
const children: AST[] = []; const children: AST[] = [];
for (let child of node.childNodes) { for (let child of node.childNodes) {
const childAst = parseNode(child, ctx); const childAst = parseNode(child, ctx);
if (childAst) { if (childAst) {
if (childAst.type === ASTType.Multi) {
children.push(...childAst.content);
} else {
children.push(childAst); children.push(childAst);
} }
} }
}
return children;
}
/**
* Parse all the child nodes of a given node and return an ast if possible.
* In the case there are multiple children, they are wrapped in a astmulti.
*/
function parseChildNodes(node: Node, ctx: ParsingContext): AST | null {
const children = parseChildren(node, ctx);
switch (children.length) { switch (children.length) {
case 0: case 0:
return null; return null;
@@ -819,34 +842,17 @@ function parseChildNodes(node: Element, ctx: ParsingContext): AST | null {
return { type: ASTType.Multi, content: children }; return { type: ASTType.Multi, content: children };
} }
} }
function parseXML(xml: string): Document {
const parser = new DOMParser();
const doc = parser.parseFromString(xml, "text/xml"); /**
if (doc.getElementsByTagName("parsererror").length) { * Normalizes the content of an Element so that t-if/t-elif/t-else directives
let msg = "Invalid XML in template."; * immediately follow one another (by removing empty text nodes or comments).
const parsererrorText = doc.getElementsByTagName("parsererror")[0].textContent; * Throws an error when a conditional branching statement is malformed. This
if (parsererrorText) { * function modifies the Element in place.
msg += "\nThe parser has produced the following error message:\n" + parsererrorText; *
const re = /\d+/g; * @param el the element containing the tree that should be normalized
const firstMatch = re.exec(parsererrorText); */
if (firstMatch) { function normalizeTIf(el: Element) {
const lineNumber = Number(firstMatch[0]); let tbranch = el.querySelectorAll("[t-elif], [t-else]");
const line = xml.split("\n")[lineNumber - 1];
const secondMatch = re.exec(parsererrorText);
if (line && secondMatch) {
const columnIndex = Number(secondMatch[0]) - 1;
if (line[columnIndex]) {
msg +=
`\nThe error might be located at xml line ${lineNumber} column ${columnIndex}\n` +
`${line}\n${"-".repeat(columnIndex - 1)}^`;
}
}
}
}
throw new Error(msg);
}
let tbranch = doc.querySelectorAll("[t-elif], [t-else]");
for (let i = 0, ilen = tbranch.length; i < ilen; i++) { for (let i = 0, ilen = tbranch.length; i < ilen; i++) {
let node = tbranch[i]; let node = tbranch[i];
let prevElem = node.previousElementSibling!; let prevElem = node.previousElementSibling!;
@@ -880,6 +886,78 @@ function parseXML(xml: string): Document {
); );
} }
} }
}
/**
* Normalizes the content of an Element so that t-esc directives on components
* are removed and instead places a <t t-esc=""> as the default slot of the
* component. Also throws if the component already has content. This function
* modifies the Element in place.
*
* @param el the element containing the tree that should be normalized
*/
function normalizeTEsc(el: Element) {
const elements = [...el.querySelectorAll("[t-esc]")].filter(
(el) => el.tagName[0] === el.tagName[0].toUpperCase() || el.hasAttribute("t-component")
);
for (const el of elements) {
if (el.childNodes.length) {
throw new Error("Cannot have t-esc on a component that already has content");
}
const value = el.getAttribute("t-esc");
el.removeAttribute("t-esc");
const t = el.ownerDocument.createElement("t");
if (value != null) {
t.setAttribute("t-esc", value);
}
el.appendChild(t);
}
}
/**
* Normalizes the tree inside a given element and do some preliminary validation
* on it. This function modifies the Element in place.
*
* @param el the element containing the tree that should be normalized
*/
function normalizeXML(el: Element) {
normalizeTIf(el);
normalizeTEsc(el);
}
/**
* Parses an XML string into an XML document, throwing errors on parser errors
* instead of returning an XML document containing the parseerror.
*
* @param xml the string to parse
* @returns an XML document corresponding to the content of the string
*/
function parseXML(xml: string): XMLDocument {
const parser = new DOMParser();
const doc = parser.parseFromString(xml, "text/xml");
if (doc.getElementsByTagName("parsererror").length) {
let msg = "Invalid XML in template.";
const parsererrorText = doc.getElementsByTagName("parsererror")[0].textContent;
if (parsererrorText) {
msg += "\nThe parser has produced the following error message:\n" + parsererrorText;
const re = /\d+/g;
const firstMatch = re.exec(parsererrorText);
if (firstMatch) {
const lineNumber = Number(firstMatch[0]);
const line = xml.split("\n")[lineNumber - 1];
const secondMatch = re.exec(parsererrorText);
if (line && secondMatch) {
const columnIndex = Number(secondMatch[0]) - 1;
if (line[columnIndex]) {
msg +=
`\nThe error might be located at xml line ${lineNumber} column ${columnIndex}\n` +
`${line}\n${"-".repeat(columnIndex - 1)}^`;
}
}
}
}
throw new Error(msg);
}
return doc; return doc;
} }
+3 -7
View File
@@ -7,7 +7,7 @@ import type { ComponentNode } from "./component_node";
export class Component { export class Component {
static template: string = ""; static template: string = "";
static style: string = ""; static props?: any;
props: any; props: any;
env: Env; env: Env;
@@ -18,14 +18,10 @@ export class Component {
this.env = env; this.env = env;
this.__owl__ = node; this.__owl__ = node;
} }
get el(): HTMLElement | Text | undefined {
const node = this.__owl__;
return node.bdom ? (node.bdom.firstNode() as any) : undefined;
}
setup() {} setup() {}
render(): Promise<void> { render() {
return this.__owl__.render(); this.__owl__.render();
} }
} }
+114 -74
View File
@@ -8,26 +8,53 @@ import {
MountFiber, MountFiber,
MountOptions, MountOptions,
RootFiber, RootFiber,
__internal__destroyed,
} from "./fibers"; } from "./fibers";
import { handleError, fibersInError } from "./error_handling"; import { handleError, fibersInError } from "./error_handling";
import { applyDefaultProps } from "./props_validation"; import { applyDefaultProps } from "./props_validation";
import { STATUS } from "./status"; import { STATUS } from "./status";
import { applyStyles } from "./style";
let currentNode: ComponentNode | null = null;
export function getCurrent(): ComponentNode | null {
return currentNode;
}
export function useComponent(): Component {
return currentNode!.component;
}
export function component( export function component(
name: string | typeof Component, name: string | typeof Component,
props: any, props: any,
key: string, key: string,
tKey: null | string,
ctx: ComponentNode, ctx: ComponentNode,
parent: any parent: any
): ComponentNode { ): ComponentNode {
let node: any = ctx.children[key]; const parentChildren = ctx.children;
const destroy = ComponentNode.prototype.destroy;
if (tKey) {
const parentMap = ctx.keyToTkey;
const oldTkey = parentMap[key];
if (oldTkey && oldTkey !== tKey) {
const oldKey = key + oldTkey;
const node = parentChildren[oldKey];
if (node && node.status < STATUS.MOUNTED) {
destroy.call(node);
delete parentChildren[oldKey];
}
}
parentMap[key] = tKey;
key = key + tKey;
}
let node: any = parentChildren[key];
let isDynamic = typeof name !== "string"; let isDynamic = typeof name !== "string";
if (node) { if (node) {
if (node.status < STATUS.MOUNTED) { if (node.status < STATUS.MOUNTED) {
node.destroy(); destroy.call(node);
node = undefined; node = undefined;
} else if (node.status === STATUS.DESTROYED) { } else if (node.status === STATUS.DESTROYED) {
node = undefined; node = undefined;
@@ -52,7 +79,7 @@ export function component(
} }
} }
node = new ComponentNode(C, props, ctx.app, ctx); node = new ComponentNode(C, props, ctx.app, ctx);
ctx.children[key] = node; parentChildren[key] = node;
const fiber = makeChildFiber(node, parentFiber); const fiber = makeChildFiber(node, parentFiber);
node.initiateRender(fiber); node.initiateRender(fiber);
@@ -64,15 +91,11 @@ export function component(
// Component VNode // Component VNode
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
let currentNode: ComponentNode | null = null;
export function getCurrent(): ComponentNode | null {
return currentNode;
}
type LifecycleHook = Function; type LifecycleHook = Function;
export class ComponentNode<T extends typeof Component = any> implements VNode<ComponentNode> { export class ComponentNode<T extends typeof Component = typeof Component>
implements VNode<ComponentNode>
{
el?: HTMLElement | Text | undefined; el?: HTMLElement | Text | undefined;
app: App; app: App;
fiber: Fiber | null = null; fiber: Fiber | null = null;
@@ -85,8 +108,8 @@ export class ComponentNode<T extends typeof Component = any> implements VNode<Co
level: number; level: number;
childEnv: Env; childEnv: Env;
children: { [key: string]: ComponentNode } = Object.create(null); children: { [key: string]: ComponentNode } = Object.create(null);
slots: any = {};
refs: any = {}; refs: any = {};
keyToTkey: any = {};
willStart: LifecycleHook[] = []; willStart: LifecycleHook[] = [];
willUpdateProps: LifecycleHook[] = []; willUpdateProps: LifecycleHook[] = [];
@@ -94,7 +117,7 @@ export class ComponentNode<T extends typeof Component = any> implements VNode<Co
mounted: LifecycleHook[] = []; mounted: LifecycleHook[] = [];
willPatch: LifecycleHook[] = []; willPatch: LifecycleHook[] = [];
patched: LifecycleHook[] = []; patched: LifecycleHook[] = [];
destroyed: LifecycleHook[] = []; willDestroy: LifecycleHook[] = [];
constructor(C: T, props: any, app: App, parent?: ComponentNode) { constructor(C: T, props: any, app: App, parent?: ComponentNode) {
currentNode = this; currentNode = this;
@@ -106,20 +129,17 @@ export class ComponentNode<T extends typeof Component = any> implements VNode<Co
this.childEnv = env; this.childEnv = env;
this.component = new C(props, env, this) as any; this.component = new C(props, env, this) as any;
this.renderFn = app.getTemplate(C.template).bind(this.component, this.component, this); this.renderFn = app.getTemplate(C.template).bind(this.component, this.component, this);
if (C.style) {
applyStyles(C);
}
this.component.setup(); this.component.setup();
} }
mountComponent(target: any, options?: MountOptions): Promise<InstanceType<T>> { mountComponent(target: any, options?: MountOptions) {
const fiber = new MountFiber(this, target, options); const fiber = new MountFiber(this, target, options);
this.app.scheduler.addFiber(fiber); this.app.scheduler.addFiber(fiber);
this.initiateRender(fiber); this.initiateRender(fiber);
return fiber.promise.then(() => this.component);
} }
async initiateRender(fiber: Fiber | MountFiber) { async initiateRender(fiber: Fiber | MountFiber) {
this.fiber = fiber;
if (this.mounted.length) { if (this.mounted.length) {
fiber.root.mounted.push(fiber); fiber.root.mounted.push(fiber);
} }
@@ -127,7 +147,7 @@ export class ComponentNode<T extends typeof Component = any> implements VNode<Co
try { try {
await Promise.all(this.willStart.map((f) => f.call(component))); await Promise.all(this.willStart.map((f) => f.call(component)));
} catch (e) { } catch (e) {
handleError(this, e as Error); handleError({ node: this, error: e });
return; return;
} }
if (this.status === STATUS.NEW && this.fiber === fiber) { if (this.status === STATUS.NEW && this.fiber === fiber) {
@@ -136,24 +156,40 @@ export class ComponentNode<T extends typeof Component = any> implements VNode<Co
} }
async render() { async render() {
let fiber = this.fiber; let current = this.fiber;
if (fiber && !fiber.bdom && !fibersInError.has(fiber)) { if (current && current.root.locked) {
return fiber.root.promise; await Promise.resolve();
// situation may have changed after the microtask tick
current = this.fiber;
} }
if (!this.bdom && !fiber) { if (current && !current.bdom && !fibersInError.has(current)) {
// should find a way to return the future mounting promise
return; return;
} }
fiber = makeRootFiber(this); if (!this.bdom && !current) {
return;
}
const fiber = makeRootFiber(this);
this.fiber = fiber;
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.DESTROYED) {
return; return;
} }
if (this.fiber === fiber) { // We only want to actually render the component if the following two
// conditions are true:
// * this.fiber: it could be null, in which case the render has been cancelled
// * (current || !fiber.parent): if current is not null, this means that the
// render function was called when a render was already occurring. In this
// case, the pending rendering was cancelled, and the fiber needs to be
// rendered to complete the work. If current is null, we check that the
// fiber has no parent. If that is the case, the fiber was downgraded from
// a root fiber to a child fiber in the previous microtick, because it was
// embedded in a rendering coming from above, so the fiber will be rendered
// in the next microtick anyway, so we should not render it again.
if (this.fiber && (current || !fiber.parent)) {
this._render(fiber); this._render(fiber);
} }
return fiber.root.promise;
} }
_render(fiber: Fiber | RootFiber) { _render(fiber: Fiber | RootFiber) {
@@ -161,50 +197,38 @@ export class ComponentNode<T extends typeof Component = any> implements VNode<Co
fiber.bdom = this.renderFn(); fiber.bdom = this.renderFn();
fiber.root.counter--; fiber.root.counter--;
} catch (e) { } catch (e) {
handleError(this, e as Error); handleError({ node: this, error: e });
} }
} }
destroy() { destroy() {
if (this.status === STATUS.MOUNTED) { let shouldRemove = this.status === STATUS.MOUNTED;
callWillUnmount(this); this._destroy();
if (shouldRemove) {
this.bdom!.remove(); this.bdom!.remove();
} }
callDestroyed(this);
function callWillUnmount(node: ComponentNode) {
const component = node.component;
for (let cb of node.willUnmount) {
cb.call(component);
}
for (let child of Object.values(node.children)) {
if (child.status === STATUS.MOUNTED) {
callWillUnmount(child);
}
}
} }
function callDestroyed(node: ComponentNode) { _destroy() {
const component = node.component; const component = this.component;
node.status = STATUS.DESTROYED; if (this.status === STATUS.MOUNTED) {
for (let child of Object.values(node.children)) { for (let cb of this.willUnmount) {
callDestroyed(child);
}
for (let cb of node.destroyed) {
cb.call(component); cb.call(component);
} }
} }
for (let child of Object.values(this.children)) {
child._destroy();
}
for (let cb of this.willDestroy) {
cb.call(component);
}
this.status = STATUS.DESTROYED;
} }
async updateAndRender(props: any, parentFiber: Fiber) { async updateAndRender(props: any, parentFiber: Fiber) {
// update // update
const fiber = makeChildFiber(this, parentFiber); const fiber = makeChildFiber(this, parentFiber);
if (this.willPatch.length) { this.fiber = fiber;
parentFiber.root.willPatch.push(fiber);
}
if (this.patched.length) {
parentFiber.root.patched.push(fiber);
}
const component = this.component; const component = this.component;
applyDefaultProps(props, component.constructor as any); applyDefaultProps(props, component.constructor as any);
const prom = Promise.all(this.willUpdateProps.map((f) => f.call(component, props))); const prom = Promise.all(this.willUpdateProps.map((f) => f.call(component, props)));
@@ -212,8 +236,40 @@ export class ComponentNode<T extends typeof Component = any> implements VNode<Co
if (fiber !== this.fiber) { if (fiber !== this.fiber) {
return; return;
} }
this.component.props = props; component.props = props;
this._render(fiber); this._render(fiber);
const parentRoot = parentFiber.root;
if (this.willPatch.length) {
parentRoot.willPatch.push(fiber);
}
if (this.patched.length) {
parentRoot.patched.push(fiber);
}
}
/**
* Finds a child that has dom that is not yet updated, and update it. This
* method is meant to be used only in the context of repatching the dom after
* a mounted hook failed and was handled.
*/
updateDom() {
if (!this.fiber) {
return;
}
if (this.bdom === this.fiber!.bdom) {
// If the error was handled by some child component, we need to find it to
// apply its change
for (let k in this.children) {
const child = this.children[k];
child.updateDom();
}
} else {
// if we get here, this is the component that handled the error and rerendered
// itself, so we can simply patch the dom
this.bdom!.patch(this.fiber!.bdom, false);
this.fiber!.appliedToDom = true;
this.fiber = null;
}
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@@ -245,26 +301,10 @@ export class ComponentNode<T extends typeof Component = any> implements VNode<Co
} }
beforeRemove() { beforeRemove() {
visitRemovedNodes(this); this._destroy();
} }
remove() { remove() {
this.bdom!.remove(); this.bdom!.remove();
} }
} }
function visitRemovedNodes(node: ComponentNode) {
if (node.status === STATUS.MOUNTED) {
const component = node.component;
for (let cb of node.willUnmount) {
cb.call(component);
}
}
for (let child of Object.values(node.children)) {
visitRemovedNodes(child);
}
node.status = STATUS.DESTROYED;
if (node.destroyed.length) {
__internal__destroyed.push(node);
}
}
+38 -32
View File
@@ -1,10 +1,11 @@
import type { ComponentNode } from "./component_node"; import type { ComponentNode } from "./component_node";
import { Fiber } from "./fibers"; import type { Fiber } from "./fibers";
export const fibersInError: WeakMap<Fiber, Error> = new WeakMap(); // Maps fibers to thrown errors
export const nodeErrorHandlers: WeakMap<ComponentNode, ((error: Error) => void)[]> = new WeakMap(); export const fibersInError: WeakMap<Fiber, any> = new WeakMap();
export const nodeErrorHandlers: WeakMap<ComponentNode, ((error: any) => void)[]> = new WeakMap();
function _handleError(node: ComponentNode | null, error: Error, isFirstRound = false): boolean { function _handleError(node: ComponentNode | null, error: any, isFirstRound = false): boolean {
if (!node) { if (!node) {
return false; return false;
} }
@@ -15,46 +16,51 @@ function _handleError(node: ComponentNode | null, error: Error, isFirstRound = f
const errorHandlers = nodeErrorHandlers.get(node); const errorHandlers = nodeErrorHandlers.get(node);
if (errorHandlers) { if (errorHandlers) {
let stopped = false;
// execute in the opposite order
for (let i = errorHandlers.length - 1; i >= 0; i--) {
try {
errorHandlers[i](error);
stopped = true;
break;
} catch (e) {
error = e;
}
}
if (stopped) {
if (isFirstRound && fiber) { if (isFirstRound && fiber) {
fiber.root.counter--; fiber.root.counter--;
} }
let propagate = true;
for (const h of errorHandlers) {
try {
h(error);
propagate = false;
} catch (e) {
error = e as Error;
}
}
if (propagate) {
return _handleError(node.parent, error);
}
return true; return true;
} else { }
}
return _handleError(node.parent, error); return _handleError(node.parent, error);
} }
}
export function handleError(entity: ComponentNode | Fiber, error: Error) { type ErrorParams = { error: any } & ({ node: ComponentNode } | { fiber: Fiber });
let node: ComponentNode; export function handleError(params: ErrorParams) {
let fiber: Fiber; const error = params.error;
if (entity instanceof Fiber) { const node = "node" in params ? params.node : params.fiber.node;
fiber = entity; const fiber = "fiber" in params ? params.fiber : node.fiber!;
node = entity.node;
} else { // resets the fibers on components if possible. This is important so that
node = entity; // new renderings can be properly included in the initial one, if any.
fiber = entity.fiber!; let current: Fiber | null = fiber;
} do {
current.node.fiber = current;
current = current.parent;
} while (current);
fibersInError.set(fiber.root, error); fibersInError.set(fiber.root, error);
const handled = _handleError(node, error, true); const handled = _handleError(node, error, true);
if (!handled) { if (!handled) {
console.warn(`[Owl] Unhandled error. Destroying the root component`);
try { try {
node.app.destroy(); node.app.destroy();
} catch (e) {} } catch (e) {
console.error(e);
}
} }
return handled;
} }
+58 -37
View File
@@ -1,18 +1,46 @@
import type { BDom } from "../blockdom"; import { BDom, mount } from "../blockdom";
import { mount } from "../blockdom";
import type { ComponentNode } from "./component_node"; import type { ComponentNode } from "./component_node";
import { STATUS } from "./status";
import { fibersInError, handleError } from "./error_handling"; import { fibersInError, handleError } from "./error_handling";
import { STATUS } from "./status";
/**
* Cleans on the root fiber the patch and willPatch fiber lists
* It is typically needed when the same root fiber needs to recycle on
* of its children or grandchildren's fiber.
*/
function cleanPatchableFiber(child: Fiber, root: RootFiber) {
const { willPatch, patched } = root;
let i = willPatch.indexOf(child);
if (i > -1) {
willPatch.splice(i, 1);
}
i = patched.indexOf(child);
if (i > -1) {
patched.splice(i, 1);
}
}
export function makeChildFiber(node: ComponentNode, parent: Fiber): Fiber { export function makeChildFiber(node: ComponentNode, parent: Fiber): Fiber {
let current = node.fiber; let current = node.fiber;
if (current) { if (current) {
// current is necessarily a rootfiber here // current is necessarily a rootfiber here
let root = parent.root; let root = parent.root;
const isSameRoot = current.root === root;
cancelFibers(root, current.children); cancelFibers(root, current.children);
current.children = []; current.children = [];
current.parent = parent; current.parent = parent;
// only increment our rendering if we were not
// already accounted for, or that we have been rendered
// already (in which case our fiber was removed from the root rendering)
if (!isSameRoot || current.bdom) {
root.counter++; root.counter++;
}
if (isSameRoot) {
cleanPatchableFiber(current, root);
}
current.bdom = null;
current.root = root; current.root = root;
return current; return current;
} }
@@ -30,10 +58,11 @@ export function makeRootFiber(node: ComponentNode): Fiber {
if (fibersInError.has(current)) { if (fibersInError.has(current)) {
fibersInError.delete(current); fibersInError.delete(current);
fibersInError.delete(root); fibersInError.delete(root);
current.appliedToDom = false;
} }
return current; return current;
} }
const fiber = new RootFiber(node); const fiber = new RootFiber(node, null);
if (node.willPatch.length) { if (node.willPatch.length) {
fiber.willPatch.push(fiber); fiber.willPatch.push(fiber);
} }
@@ -70,7 +99,6 @@ export class Fiber {
constructor(node: ComponentNode, parent: Fiber | null) { constructor(node: ComponentNode, parent: Fiber | null) {
this.node = node; this.node = node;
node.fiber = this;
this.parent = parent; this.parent = parent;
if (parent) { if (parent) {
const root = parent.root; const root = parent.root;
@@ -85,27 +113,18 @@ export class Fiber {
export class RootFiber extends Fiber { export class RootFiber extends Fiber {
counter: number = 1; counter: number = 1;
resolve: any;
promise: Promise<any>;
reject: any;
// only add stuff in this if they have registered some hooks // only add stuff in this if they have registered some hooks
willPatch: Fiber[] = []; willPatch: Fiber[] = [];
patched: Fiber[] = []; patched: Fiber[] = [];
mounted: Fiber[] = []; mounted: Fiber[] = [];
// A fiber is typically locked when it is completing and the patch has not, or is being applied.
constructor(node: ComponentNode) { // i.e.: render triggered in onWillUnmount or in willPatch will be delayed
super(node, null); locked: boolean = false;
this.counter = 1;
this.promise = new Promise((resolve, reject) => {
this.resolve = resolve;
this.reject = reject;
});
}
complete() { complete() {
const node = this.node; const node = this.node;
this.locked = true;
let current: Fiber | undefined = undefined; let current: Fiber | undefined = undefined;
try { try {
// Step 1: calling all willPatch lifecycle hooks // Step 1: calling all willPatch lifecycle hooks
@@ -127,13 +146,10 @@ export class RootFiber extends Fiber {
node.bdom!.patch(this.bdom!, Object.keys(node.children).length > 0); node.bdom!.patch(this.bdom!, Object.keys(node.children).length > 0);
this.appliedToDom = true; this.appliedToDom = true;
// Step 3: calling all destroyed hooks this.locked = false;
for (let node of __internal__destroyed) { // unregistering the fiber before mounted since it can do another render
for (let cb of node.destroyed) { // and that the current rendering is obviously completed
cb(); node.fiber = null;
}
}
__internal__destroyed.length = 0;
// Step 4: calling all mounted lifecycle hooks // Step 4: calling all mounted lifecycle hooks
let mountedFibers = this.mounted; let mountedFibers = this.mounted;
@@ -156,17 +172,12 @@ export class RootFiber extends Fiber {
} }
} }
} }
// unregistering the fiber
node.fiber = null;
} catch (e) { } catch (e) {
if (!handleError(current || this, e)) { this.locked = false;
this.reject(e); handleError({ fiber: current || this, error: e });
} }
} }
} }
}
export let __internal__destroyed: ComponentNode[] = [];
type Position = "first-child" | "last-child"; type Position = "first-child" | "last-child";
@@ -179,7 +190,7 @@ export class MountFiber extends RootFiber {
position: Position; position: Position;
constructor(node: ComponentNode, target: HTMLElement, options: MountOptions = {}) { constructor(node: ComponentNode, target: HTMLElement, options: MountOptions = {}) {
super(node); super(node, null);
this.target = target; this.target = target;
this.position = options.position || "last-child"; this.position = options.position || "last-child";
} }
@@ -187,6 +198,13 @@ export class MountFiber extends RootFiber {
let current: Fiber | undefined = this; let current: Fiber | undefined = this;
try { try {
const node = this.node; const node = this.node;
if (node.bdom) {
// this is a complicated situation: if we mount a fiber with an existing
// bdom, this means that this same fiber was already completed, mounted,
// but a crash occurred in some mounted hook. Then, it was handled and
// the new rendering is being applied.
node.updateDom();
} else {
node.bdom = this.bdom; node.bdom = this.bdom;
if (this.position === "last-child" || this.target.childNodes.length === 0) { if (this.position === "last-child" || this.target.childNodes.length === 0) {
mount(node.bdom!, this.target); mount(node.bdom!, this.target);
@@ -194,6 +212,12 @@ export class MountFiber extends RootFiber {
const firstChild = this.target.childNodes[0]; const firstChild = this.target.childNodes[0];
mount(node.bdom!, this.target, firstChild); mount(node.bdom!, this.target, firstChild);
} }
}
// unregistering the fiber before mounted since it can do another render
// and that the current rendering is obviously completed
node.fiber = null;
node.status = STATUS.MOUNTED; node.status = STATUS.MOUNTED;
this.appliedToDom = true; this.appliedToDom = true;
let mountedFibers = this.mounted; let mountedFibers = this.mounted;
@@ -204,11 +228,8 @@ export class MountFiber extends RootFiber {
} }
} }
} }
node.fiber = null;
} catch (e) { } catch (e) {
if (!handleError(current as Fiber, e)) { handleError({ fiber: current as Fiber, error: e });
this.reject(e);
}
} }
} }
} }
+17 -8
View File
@@ -35,12 +35,12 @@ export function onWillUnmount(fn: () => Promise<void> | void | any) {
node.willUnmount.unshift(fn); node.willUnmount.unshift(fn);
} }
export function onDestroyed(fn: () => Promise<void> | void | any) { export function onWillDestroy(fn: () => Promise<void> | void | any) {
const node = getCurrent()!; const node = getCurrent()!;
node.destroyed.push(fn); node.willDestroy.push(fn);
} }
export function onRender(fn: () => void | any) { export function onWillRender(fn: () => void | any) {
const node = getCurrent()!; const node = getCurrent()!;
const renderFn = node.renderFn; const renderFn = node.renderFn;
node.renderFn = () => { node.renderFn = () => {
@@ -49,14 +49,23 @@ export function onRender(fn: () => void | any) {
}; };
} }
export function onError(fn: (error: Error) => void | any) { export function onRendered(fn: () => void | any) {
const node = getCurrent()!;
const renderFn = node.renderFn;
node.renderFn = () => {
const result = renderFn();
fn();
return result;
};
}
type OnErrorCallback = (error: any) => void | any;
export function onError(callback: OnErrorCallback) {
const node = getCurrent()!; const node = getCurrent()!;
let handlers = nodeErrorHandlers.get(node); let handlers = nodeErrorHandlers.get(node);
if (handlers) { if (!handlers) {
handlers.push(fn);
} else {
handlers = []; handlers = [];
handlers.push(fn);
nodeErrorHandlers.set(node, handlers); nodeErrorHandlers.set(node, handlers);
} }
handlers.push(callback);
} }
+21 -26
View File
@@ -19,6 +19,14 @@ export function applyDefaultProps(props: { [key: string]: any }, ComponentClass:
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Prop validation helper // Prop validation helper
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
function getPropDescription(staticProps: any) {
if (staticProps instanceof Array) {
return Object.fromEntries(
staticProps.map((p) => (p.endsWith("?") ? [p.slice(0, -1), false] : [p, true]))
);
}
return staticProps || { "*": true };
}
/** /**
* Validate the component props (or next props) against the (static) props * Validate the component props (or next props) against the (static) props
@@ -26,36 +34,20 @@ export function applyDefaultProps(props: { [key: string]: any }, ComponentClass:
* visit recursively the props and all the children to check if they are valid. * visit recursively the props and all the children to check if they are valid.
* This is why it is only done in 'dev' mode. * This is why it is only done in 'dev' mode.
*/ */
// message: { type: String, default: "hello" };
export const validateProps = function (name: string | typeof Component, props: any, parent?: any) { export const validateProps = function (name: string | typeof Component, props: any, parent?: any) {
const ComponentClass = const ComponentClass = (
typeof name !== "string" ? name : parent.constructor.components[name as string]; typeof name !== "string" ? name : parent.constructor.components[name]
) as typeof Component;
applyDefaultProps(props, ComponentClass); applyDefaultProps(props, ComponentClass);
const propsDef = (<any>ComponentClass).props; let propsDef = getPropDescription(ComponentClass.props);
if (propsDef instanceof Array) { const allowAdditionalProps = "*" in propsDef;
// list of strings (prop names)
for (let i = 0, l = propsDef.length; i < l; i++) {
const propName = propsDef[i];
if (propName[propName.length - 1] === "?") {
// optional prop
break;
}
if (!(propName in props)) {
throw new Error(`Missing props '${propsDef[i]}' (component '${ComponentClass.name}')`);
}
}
for (let key in props) {
if (!propsDef.includes(key) && !propsDef.includes(key + "?")) {
throw new Error(`Unknown prop '${key}' given to component '${ComponentClass.name}'`);
}
}
} else if (propsDef) {
// propsDef is an object now
for (let propName in propsDef) { for (let propName in propsDef) {
if (propName === "*") {
continue;
}
if (props[propName] === undefined) { if (props[propName] === undefined) {
if (propsDef[propName] && !propsDef[propName].optional) { if (propsDef[propName] && !propsDef[propName].optional) {
throw new Error(`Missing props '${propName}' (component '${ComponentClass.name}')`); throw new Error(`Missing props '${propName}' (component '${ComponentClass.name}')`);
@@ -67,13 +59,16 @@ export const validateProps = function (name: string | typeof Component, props: a
try { try {
isValid = isValidProp(props[propName], propsDef[propName]); isValid = isValidProp(props[propName], propsDef[propName]);
} catch (e) { } catch (e) {
e.message = `Invalid prop '${propName}' in component ${ComponentClass.name} (${e.message})`; (e as Error).message = `Invalid prop '${propName}' in component ${ComponentClass.name} (${
(e as Error).message
})`;
throw e; throw e;
} }
if (!isValid) { if (!isValid) {
throw new Error(`Invalid Prop '${propName}' in component '${ComponentClass.name}'`); throw new Error(`Invalid Prop '${propName}' in component '${ComponentClass.name}'`);
} }
} }
if (!allowAdditionalProps) {
for (let propName in props) { for (let propName in props) {
if (!(propName in propsDef)) { if (!(propName in propsDef)) {
throw new Error(`Unknown prop '${propName}' given to component '${ComponentClass.name}'`); throw new Error(`Unknown prop '${propName}' given to component '${ComponentClass.name}'`);
+1 -9
View File
@@ -1,5 +1,5 @@
import { Fiber, RootFiber } from "./fibers";
import { fibersInError } from "./error_handling"; import { fibersInError } from "./error_handling";
import { Fiber, RootFiber } from "./fibers";
import { STATUS } from "./status"; import { STATUS } from "./status";
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@@ -38,19 +38,12 @@ export class Scheduler {
flush() { flush() {
this.tasks.forEach((fiber) => { this.tasks.forEach((fiber) => {
if (fiber.root !== fiber) { if (fiber.root !== fiber) {
// this is wrong! should be something like
// if (this.tasks.has(fiber.root)) {
// // parent rendering has completed
// fiber.resolve();
// this.tasks.delete(fiber);
// }
this.tasks.delete(fiber); this.tasks.delete(fiber);
return; return;
} }
const hasError = fibersInError.has(fiber); const hasError = fibersInError.has(fiber);
if (hasError && fiber.counter !== 0) { if (hasError && fiber.counter !== 0) {
this.tasks.delete(fiber); this.tasks.delete(fiber);
fiber.reject(fibersInError.get(fiber));
return; return;
} }
if (fiber.node.status === STATUS.DESTROYED) { if (fiber.node.status === STATUS.DESTROYED) {
@@ -61,7 +54,6 @@ export class Scheduler {
if (fiber.counter === 0) { if (fiber.counter === 0) {
if (!hasError) { if (!hasError) {
fiber.complete(); fiber.complete();
fiber.resolve();
} }
this.tasks.delete(fiber); this.tasks.delete(fiber);
} }
-88
View File
@@ -1,88 +0,0 @@
import { Component } from "./component";
export const globalStylesheets: { [key: string]: HTMLStyleElement } = {};
export function registerSheet(id: string, css: string) {
const sheet = document.createElement("style");
sheet.innerHTML = processSheet(css);
globalStylesheets[id] = sheet;
}
/**
* Apply the stylesheets defined by the component. Note that we need to make
* sure all inherited stylesheets are applied as well, in a reverse order to
* ensure that <style/> will be applied to the DOM in the order they are
* included in the document. We then delete the `style` key from the constructor
* to make sure we do not apply it again.
*/
export function applyStyles(ComponentClass: typeof Component) {
const toApply: [string, string][] = [];
while (ComponentClass && ComponentClass.style) {
if (ComponentClass.hasOwnProperty("style")) {
toApply.push([ComponentClass.style, ComponentClass.name]);
delete (ComponentClass as any).style;
}
ComponentClass = Object.getPrototypeOf(ComponentClass);
}
while (toApply.length) {
const [styleId, componentName] = toApply.pop()!;
activateSheet(styleId, componentName);
}
}
function activateSheet(id: string, name: string) {
const sheet = globalStylesheets[id];
if (!sheet) {
throw new Error(
`Invalid css stylesheet for component '${name}'. Did you forget to use the 'css' tag helper?`
);
}
sheet.dataset.component = name;
document.head.appendChild(sheet);
}
function processSheet(str: string): string {
const tokens = str.split(/(\{|\}|;)/).map((s) => s.trim());
const selectorStack: string[][] = [];
const parts: string[] = [];
let rules: string[] = [];
function generateSelector(stackIndex: number, parentSelector?: string) {
const parts: string[] = [];
for (const selector of selectorStack[stackIndex]) {
let part = (parentSelector && parentSelector + " " + selector) || selector;
if (part.includes("&")) {
part = selector.replace(/&/g, parentSelector || "");
}
if (stackIndex < selectorStack.length - 1) {
part = generateSelector(stackIndex + 1, part);
}
parts.push(part);
}
return parts.join(", ");
}
function generateRules() {
if (rules.length) {
parts.push(generateSelector(0) + " {");
parts.push(...rules);
parts.push("}");
rules = [];
}
}
while (tokens.length) {
let token = tokens.shift()!;
if (token === "}") {
generateRules();
selectorStack.pop();
} else {
if (tokens[0] === "{") {
generateRules();
selectorStack.push(token.split(/\s*,\s*/));
tokens.shift();
}
if (tokens[0] === ";") {
rules.push(" " + token + ";");
}
}
}
return parts.join("\n");
}
+11 -13
View File
@@ -1,6 +1,6 @@
import type { Env } from "./app/app"; import type { Env } from "./app/app";
import { getCurrent } from "./component/component_node"; import { getCurrent } from "./component/component_node";
import { onMounted, onPatched, onWillPatch, onWillUnmount } from "./component/lifecycle_hooks"; import { onMounted, onPatched, onWillUnmount } from "./component/lifecycle_hooks";
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// useRef // useRef
@@ -12,9 +12,10 @@ import { onMounted, onPatched, onWillPatch, onWillUnmount } from "./component/li
*/ */
export function useRef<T extends HTMLElement = HTMLElement>(name: string): { el: T | null } { export function useRef<T extends HTMLElement = HTMLElement>(name: string): { el: T | null } {
const node = getCurrent()!; const node = getCurrent()!;
const refs = node.refs;
return { return {
get el(): T | null { get el(): T | null {
return node.refs[name] || null; return refs[name] || null;
}, },
}; };
} }
@@ -38,7 +39,9 @@ export function useEnv<E extends Env>(): E {
*/ */
export function useSubEnv(envExtension: Env) { export function useSubEnv(envExtension: Env) {
const node = getCurrent()!; const node = getCurrent()!;
node.childEnv = Object.freeze(Object.assign({}, node.childEnv, envExtension)); const env = Object.create(node.childEnv);
const descrs = Object.getOwnPropertyDescriptors(envExtension);
node.childEnv = Object.freeze(Object.defineProperties(env, descrs));
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@@ -73,17 +76,12 @@ export function useEffect(effect: Effect, computeDependencies: () => any[] = ()
cleanup = effect(...dependencies) || NO_OP; cleanup = effect(...dependencies) || NO_OP;
}); });
let shouldReapplyOnPatch = false;
onWillPatch(() => {
const newDeps = computeDependencies();
shouldReapplyOnPatch = newDeps.some((val, i) => val !== dependencies[i]);
if (shouldReapplyOnPatch) {
cleanup();
dependencies = newDeps;
}
});
onPatched(() => { onPatched(() => {
if (shouldReapplyOnPatch) { const newDeps = computeDependencies();
const shouldReapply = newDeps.some((val, i) => val !== dependencies[i]);
if (shouldReapply) {
dependencies = newDeps;
cleanup();
cleanup = effect(...dependencies) || NO_OP; cleanup = effect(...dependencies) || NO_OP;
} }
}); });
+10 -26
View File
@@ -9,6 +9,7 @@ import {
remove, remove,
text, text,
toggler, toggler,
comment,
} from "./blockdom"; } from "./blockdom";
import { mainEventHandler } from "./component/handler"; import { mainEventHandler } from "./component/handler";
@@ -28,37 +29,19 @@ export const blockDom = {
toggler, toggler,
createBlock, createBlock,
html, html,
comment,
}; };
import type { AppConfig } from "./app/app"; export { App, mount } from "./app/app";
import { App } from "./app/app"; export { Component } from "./component/component";
import { Component } from "./component/component"; export { useComponent } from "./component/component_node";
import { getCurrent } from "./component/component_node";
export { App, Component };
export async function mount<T extends typeof Component>(
C: T,
target: HTMLElement,
config: AppConfig = {}
): Promise<InstanceType<T>> {
const app = new App(C);
return app.configure(config).mount(target);
}
export function useComponent(): Component {
const current = getCurrent();
return current!.component;
}
export { status } from "./component/status"; export { status } from "./component/status";
export { Portal } from "./portal"; export { Portal } from "./portal";
export { Memo } from "./memo"; export { Memo } from "./memo";
export { css, xml } from "./tags"; export { xml } from "./app/template_set";
export { useState } from "./reactivity"; export { useState, reactive } from "./reactivity";
export { useEffect, useEnv, useExternalListener, useRef, useSubEnv } from "./hooks"; export { useEffect, useEnv, useExternalListener, useRef, useSubEnv } from "./hooks";
export { EventBus, whenReady, loadFile, markup } from "./utils"; export { EventBus, whenReady, loadFile, markup } from "./utils";
export { export {
onWillStart, onWillStart,
onMounted, onMounted,
@@ -66,8 +49,9 @@ export {
onWillUpdateProps, onWillUpdateProps,
onWillPatch, onWillPatch,
onPatched, onPatched,
onRender, onWillRender,
onDestroyed, onRendered,
onWillDestroy,
onError, onError,
} from "./component/lifecycle_hooks"; } from "./component/lifecycle_hooks";
+2 -2
View File
@@ -1,6 +1,6 @@
import { Component } from "./component/component"; import { Component } from "./component/component";
import type { ComponentNode } from "./component/component_node"; import type { ComponentNode } from "./component/component_node";
import { xml } from "./tags"; import { xml } from "./app/template_set";
import { Fiber } from "./component/fibers"; import { Fiber } from "./component/fibers";
export class Memo extends Component { export class Memo extends Component {
@@ -39,7 +39,7 @@ export class Memo extends Component {
*/ */
function shallowEqual(p1: any, p2: any): boolean { function shallowEqual(p1: any, p2: any): boolean {
for (let k in p1) { for (let k in p1) {
if (p1[k] !== p2[k]) { if (k !== "slots" && p1[k] !== p2[k]) {
return false; return false;
} }
} }
+2 -1
View File
@@ -1,6 +1,6 @@
import type { ComponentNode } from "./component/component_node"; import type { ComponentNode } from "./component/component_node";
import { Component } from "./component/component"; import { Component } from "./component/component";
import { xml } from "./tags"; import { xml } from "./app/template_set";
import { BDom, text, VNode } from "./blockdom"; import { BDom, text, VNode } from "./blockdom";
const VText: any = text("").constructor; const VText: any = text("").constructor;
@@ -57,6 +57,7 @@ export class Portal extends Component {
target: { target: {
type: String, type: String,
}, },
slots: true,
}; };
constructor(props: any, env: any, node: ComponentNode) { constructor(props: any, env: any, node: ComponentNode) {
+219 -255
View File
@@ -1,132 +1,28 @@
import { ComponentNode, getCurrent } from "./component/component_node";
import { onWillUnmount } from "./component/lifecycle_hooks"; import { onWillUnmount } from "./component/lifecycle_hooks";
import { ComponentNode, getCurrent } from "./component/component_node";
type Observer = ComponentNode | Function; // Allows to get the target of a Reactive (used for making a new Reactive from the underlying object)
type Atom = any; // proxy linked to a unique observer and source const TARGET = Symbol("Target");
type Source = any; // trackable that is not an atom // Special key to subscribe to, to be notified of key creation/deletion
const KEYCHANGES = Symbol("Key changes");
const sourceAtoms: WeakMap<Source, Map<any, ObserverSet>> = new WeakMap(); type ObjectKey = string | number | symbol;
const observerSourceAtom: WeakMap<Observer, Map<any, Atom>> = new WeakMap(); type Target = object;
type Callback = () => void;
type Reactive<T extends Target = Target> = T & {
[TARGET]: any;
};
const SOURCE = Symbol("source"); /**
const OBSERVER = Symbol("observer"); * Checks whether a given value can be made into a reactive object.
const KEYS = Symbol("keys"); *
const ROOT = Symbol("root"); * @param value the value to check
const SEED = Symbol("Seed"); * @returns whether the value can be made reactive
*/
export function observe(source: any, observer: Observer): [Atom, Function] { function canBeMadeReactive(value: any): boolean {
if (!isTrackable(source)) {
throw new Error("First argument is not trackable");
}
const unregisterObserver = registerObserver(observer);
const newAtom = atom(source, observer);
return [newAtom, unregisterObserver];
}
function atom(source: any, observer: Observer) {
return _atom(source, observer, true);
}
function _atom(source: any, observer: Observer, seed = false) {
if (isTrackable(source) && observerSourceAtom.has(observer)) {
source = (source as any)[SOURCE] || source;
const oldAtom = observerSourceAtom.get(observer)!.get(source);
if (oldAtom) {
if (seed) {
oldAtom[SEED] = true;
}
return oldAtom;
}
if (!sourceAtoms.get(source)) {
sourceAtoms.set(source, new Map([[ROOT, new ObserverSet()]]));
}
const newAtom = createAtom(source, observer);
if (seed) {
newAtom[SEED] = true;
}
observerSourceAtom.get(observer)!.set(source, newAtom);
sourceAtoms.get(source)!.get(ROOT)!.add(newAtom);
return newAtom;
}
return source;
}
function createAtom(source: Source, observer: Observer): Atom {
const keys: Set<any> = new Set();
let seed: boolean = false;
const newAtom: Atom = new Proxy(source as any, {
set(target: any, key: any, value: any): boolean {
if (key === SEED) {
seed = value;
return true;
}
if (!(key in target)) {
target[key] = value;
notify(sourceAtoms.get(source)!.get(ROOT)!);
return true;
}
const current = target[key];
if (current !== value) {
target[key] = value;
const observerSet = sourceAtoms.get(source)!.get(key);
if (observerSet) {
const clean = isTrackable(current);
notify(observerSet, clean);
}
}
return true;
},
deleteProperty(target: any, key: string): boolean {
if (key in target) {
const current = target[key];
delete target[key];
// notify source observers
const clean = isTrackable(current);
notify(sourceAtoms.get(source)!.get(ROOT)!, clean);
const atoms = sourceAtoms.get(source)!;
if (atoms.has(key)) {
// clear source-key observers
for (const atom of atoms.get(key)!) {
atom[KEYS].delete(key);
}
atoms.delete(key);
}
}
return true;
},
get(target: any, key: any, proxy: any): any {
switch (key) {
case OBSERVER:
return observer;
case SOURCE:
return source;
case KEYS:
return keys;
case SEED:
return seed;
default:
const value = target[key];
// register observer to source-key
if (!keys.has(key) && observerSourceAtom.has(observer)) {
const atoms = sourceAtoms.get(source)!;
if (!atoms.has(key)) {
atoms.set(key, new ObserverSet());
}
atoms.get(key)!.add(newAtom);
keys.add(key);
}
//
return _atom(value, observer);
}
},
});
return newAtom;
}
function isTrackable(value: any): boolean {
return ( return (
value !== null &&
typeof value === "object" && typeof value === "object" &&
value !== null &&
!(value instanceof Date) && !(value instanceof Date) &&
!(value instanceof Promise) && !(value instanceof Promise) &&
!(value instanceof String) && !(value instanceof String) &&
@@ -134,144 +30,212 @@ function isTrackable(value: any): boolean {
); );
} }
function registerObserver(observer: Observer) { const targetToKeysToCallbacks = new WeakMap<Target, Map<ObjectKey, Set<Callback>>>();
if (!observerSourceAtom.get(observer)) { /**
observerSourceAtom.set(observer, new Map()); * Observes a given key on a target with an callback. The callback will be
* called when the given key changes on the target.
*
* @param target the target whose key should be observed
* @param key the key to observe (or Symbol(KEYCHANGES) for key creation
* or deletion)
* @param callback the function to call when the key changes
*/
function observeTargetKey(target: Target, key: ObjectKey, callback: Callback): void {
if (!targetToKeysToCallbacks.get(target)) {
targetToKeysToCallbacks.set(target, new Map());
} }
return unregisterObserverAtoms.bind(null, observer, false); const keyToCallbacks = targetToKeysToCallbacks.get(target)!;
if (!keyToCallbacks.get(key)) {
keyToCallbacks.set(key, new Set());
} }
keyToCallbacks.get(key)!.add(callback);
function unregisterObserverAtoms(observer: Observer, keepSeeds: boolean) { if (!callbacksToTargets.has(callback)) {
const observerAtoms = observerSourceAtom.get(observer)!; callbacksToTargets.set(callback, new Set());
for (const [source, atom] of observerAtoms) {
if (keepSeeds && atom[SEED]) {
continue;
} }
observerAtoms.delete(source); callbacksToTargets.get(callback)!.add(target);
const atoms = sourceAtoms.get(source)!;
atoms.get(ROOT)!.delete(atom);
for (const key of atom[KEYS]) {
atoms.get(key)!.delete(atom);
} }
} /**
if (!keepSeeds) { * Notify Reactives that are observing a given target that a key has changed on
observerSourceAtom.delete(observer); * the target.
} *
} * @param target target whose Reactives should be notified that the target was
* changed.
export function useState(state: any): Atom { * @param key the key that changed (or Symbol `KEYCHANGES` if a key was created
const node = getCurrent()!; * or deleted)
const [newAtom, unregisterObserver] = observe(state, node); */
onWillUnmount(() => unregisterObserver()); function notifyReactives(target: Target, key: ObjectKey): void {
return newAtom; const keyToCallbacks = targetToKeysToCallbacks.get(target);
} if (!keyToCallbacks) {
class ObserverSet {
nodeAntichain: Antichain = new Antichain();
callbackSet: Set<Atom> = new Set();
add(atom: Atom) {
if (atom[OBSERVER] instanceof ComponentNode) {
this.nodeAntichain.add(atom);
} else {
this.callbackSet.add(atom);
}
return this;
}
delete(atom: Atom) {
if (atom[OBSERVER] instanceof ComponentNode) {
return this.nodeAntichain.delete(atom);
} else {
return this.callbackSet.delete(atom);
}
}
union(other: ObserverSet) {
for (const atom of other.nodeAntichain) {
this.nodeAntichain.add(atom);
}
for (const callback of other.callbackSet) {
this.callbackSet.add(callback);
}
}
notify() {
for (const atom of this.nodeAntichain) {
// an observer cannot be found twice here: <= in add is based on observers
atom[OBSERVER].render();
}
const called = new Set();
for (const atom of this.callbackSet) {
const observer = atom[OBSERVER];
if (!called.has(observer)) {
observer();
}
called.add(observer);
}
}
*[Symbol.iterator]() {
yield* this.nodeAntichain;
yield* this.callbackSet;
}
}
// Need to optimize this!
function isLessOrEqual(node1: ComponentNode, node2: ComponentNode) {
let current: any = node1;
if (current.level <= node2.level) {
return false;
}
do {
if (current === node2) {
return true;
}
current = current.parent;
} while (current);
return false;
}
// set of atoms linked to observers of type ComponentNode
class Antichain extends Set<Atom> {
level?: number;
add(atom: Atom) {
const node = atom[OBSERVER];
if (this.level === node.level || this.level === undefined) {
super.add(atom);
this.level = node.level;
return this;
}
let willAdd = false;
for (const atom2 of this) {
const node2 = atom2[OBSERVER];
if (!willAdd && isLessOrEqual(node, node2)) {
return this;
} else if (isLessOrEqual(node2, node)) {
super.delete(atom2);
willAdd = true;
}
}
super.add(atom);
this.level = NaN;
return this;
}
}
let toNotify: ObserverSet | null = null;
let toClean: Set<Observer> = new Set();
async function notify(observers: ObserverSet, clean = false) {
if (clean) {
for (const atom of observers) {
toClean.add(atom[OBSERVER]);
}
}
if (toNotify) {
toNotify.union(observers);
return; return;
} }
toNotify = new ObserverSet(); const callbacks = keyToCallbacks.get(key);
toNotify.union(observers); if (!callbacks) {
return;
}
// Loop on copy because clearReactivesForCallback will modify the set in place
for (const callback of [...callbacks]) {
clearReactivesForCallback(callback);
callback();
}
}
const callbacksToTargets = new WeakMap<Callback, Set<Target>>();
/**
* Clears all subscriptions of the Reactives associated with a given callback.
*
* @param callback the callback for which the reactives need to be cleared
*/
function clearReactivesForCallback(callback: Callback): void {
const targetsToClear = callbacksToTargets.get(callback);
if (!targetsToClear) {
return;
}
for (const target of targetsToClear) {
const observedKeys = targetToKeysToCallbacks.get(target);
if (!observedKeys) {
continue;
}
for (const callbacks of observedKeys.values()) {
callbacks.delete(callback);
}
}
targetsToClear.clear();
}
const reactiveCache = new WeakMap<Target, WeakMap<Callback, Reactive>>();
/**
* Creates a reactive proxy for an object. Reading data on the reactive object
* subscribes to changes to the data. Writing data on the object will cause the
* notify callback to be called if there are suscriptions to that data. Nested
* objects and arrays are automatically made reactive as well.
*
* Whenever you are notified of a change, all subscriptions are cleared, and if
* you would like to be notified of any further changes, you should go read
* the underlying data again. We assume that if you don't go read it again after
* being notified, it means that you are no longer interested in that data.
*
* Subscriptions:
* + Reading a property on an object will subscribe you to changes in the value
* of that property.
* + Accessing an object keys (eg with Object.keys or with `for..in`) will
* subscribe you to the creation/deletion of keys. Checking the presence of a
* key on the object with 'in' has the same effect.
* - getOwnPropertyDescriptor does not currently subscribe you to the property.
* This is a choice that was made because changing a key's value will trigger
* this trap and we do not want to subscribe by writes. This also means that
* Object.hasOwnProperty doesn't subscribe as it goes through this trap.
*
* @param target the object for which to create a reactive proxy
* @param callback the function to call when an observed property of the
* reactive has changed
* @returns a proxy that tracks changes to it
*/
export function reactive<T extends Target>(target: T, callback: Callback = () => {}): Reactive<T> {
if (!canBeMadeReactive(target)) {
throw new Error(`Cannot make the given value reactive`);
}
const originalTarget = (target as Reactive)[TARGET];
if (originalTarget) {
return reactive(originalTarget, callback);
}
if (!reactiveCache.has(target)) {
reactiveCache.set(target, new Map());
}
const reactivesForTarget = reactiveCache.get(target)!;
if (!reactivesForTarget.has(callback)) {
const proxy = new Proxy(target, {
get(target: any, key: ObjectKey, proxy: Reactive<T>) {
if (key === TARGET) {
return target;
}
observeTargetKey(target, key, callback);
const value = Reflect.get(target, key, proxy);
if (!canBeMadeReactive(value)) {
return value;
}
return reactive(value, callback);
},
set(target, key, value, proxy) {
const isNewKey = !Object.hasOwnProperty.call(target, key);
const originalValue = Reflect.get(target, key, proxy);
const ret = Reflect.set(target, key, value, proxy);
if (isNewKey) {
notifyReactives(target, KEYCHANGES);
}
// While Array length may trigger the set trap, it's not actually set by this
// method but is updated behind the scenes, and the trap is not called with the
// new value. We disable the "same-value-optimization" for it because of that.
if (originalValue !== value || (Array.isArray(target) && key === "length")) {
notifyReactives(target, key);
}
return ret;
},
deleteProperty(target, key) {
const ret = Reflect.deleteProperty(target, key);
notifyReactives(target, KEYCHANGES);
notifyReactives(target, key);
return ret;
},
ownKeys(target) {
observeTargetKey(target, KEYCHANGES, callback);
return Reflect.ownKeys(target);
},
has(target, key) {
// TODO: this observes all key changes instead of only the presence of the argument key
observeTargetKey(target, KEYCHANGES, callback);
return Reflect.has(target, key);
},
});
reactivesForTarget.set(callback, proxy);
}
return reactivesForTarget.get(callback) as Reactive<T>;
}
/**
* Creates a batched version of a callback so that all calls to it in the same
* microtick will only call the original callback once.
*
* @param callback the callback to batch
* @returns a batched version of the original callback
*/
export function batched(callback: Callback): Callback {
let called = false;
return async () => {
// This await blocks all calls to the callback here, then releases them sequentially
// in the next microtick. This line decides the granularity of the batch.
await Promise.resolve(); await Promise.resolve();
for (const observer of toClean) { if (!called) {
unregisterObserverAtoms(observer, true); called = true;
callback();
// 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
await Promise.resolve();
called = false;
} }
toClean.clear(); };
toNotify.notify(); }
toNotify = null;
const batchedRenderFunctions = new WeakMap<ComponentNode, Callback>();
/**
* Creates a reactive object that will be observed by the current component.
* Reading data from the returned object (eg during rendering) will cause the
* component to subscribe to that data and be rerendered when it changes.
*
* @param state the state to observe
* @returns a reactive object that will cause the component to re-render on
* relevant changes
* @see reactive
*/
export function useState<T extends object>(state: T): Reactive<T> {
const node = getCurrent()!;
if (!batchedRenderFunctions.has(node)) {
batchedRenderFunctions.set(
node,
batched(() => node.render())
);
onWillUnmount(() => clearReactivesForCallback(render));
}
const render = batchedRenderFunctions.get(node)!;
const reactiveState = reactive(state, render);
return reactiveState;
} }
-28
View File
@@ -1,28 +0,0 @@
import { registerSheet } from "./component/style";
import { globalTemplates } from "./app/template_set";
// -----------------------------------------------------------------------------
// Global templates
// -----------------------------------------------------------------------------
export function xml(strings: TemplateStringsArray, ...args: any[]) {
const name = `__template__${xml.nextId++}`;
const value = String.raw(strings, ...args);
globalTemplates[name] = value;
return name;
}
xml.nextId = 1;
// -----------------------------------------------------------------------------
// Global stylesheets
// -----------------------------------------------------------------------------
export function css(strings: TemplateStringsArray, ...args: any[]) {
const name = `__sheet__${css.nextId++}`;
const value = String.raw(strings, ...args);
registerSheet(name, value);
return name;
}
css.nextId = 1;
+137 -108
View File
@@ -1,16 +1,64 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Reactivity: useState destroyed component before being mounted is inactive 1`] = ` exports[`Reactivity: useState concurrent renderings 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<span><block-text-0/></span>\`); let block1 = createBlock(\`<span><block-text-0/><block-text-1/></span>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = ctx['contextObj'].a; let d1 = ctx['context'][ctx['props'].key].n;
return block1([d1]); let d2 = ctx['state'].x;
return block1([d1, d2]);
}
}"
`;
exports[`Reactivity: useState concurrent renderings 2`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<p><block-child-0/></p>\`);
return function template(ctx, node, key = \\"\\") {
let b2 = component(\`ComponentC\`, {key: ctx['props'].key}, key + \`__1\`, node, ctx);
return block1([], [b2]);
}
}"
`;
exports[`Reactivity: useState concurrent renderings 3`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><block-child-0/></div>\`);
return function template(ctx, node, key = \\"\\") {
let b2 = component(\`ComponentB\`, {key: ctx['context'].key}, key + \`__1\`, node, ctx);
return block1([], [b2]);
}
}"
`;
exports[`Reactivity: useState destroyed component before being mounted is inactive 1`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let block1 = createBlock(\`<div><block-child-0/></div>\`);
return function template(ctx, node, key = \\"\\") {
let b2;
if (ctx['state'].flag) {
b2 = component(\`Child\`, {}, key+\`__1\`,null, node, ctx);
}
return block1([], [b2]);
} }
}" }"
`; `;
@@ -18,17 +66,13 @@ exports[`Reactivity: useState destroyed component before being mounted is inacti
exports[`Reactivity: useState destroyed component before being mounted is inactive 2`] = ` exports[`Reactivity: useState destroyed component before being mounted is inactive 2`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><block-child-0/></div>\`); let block1 = createBlock(\`<span><block-text-0/></span>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let b2; let txt1 = ctx['contextObj'].a;
if (ctx['state'].flag) { return block1([txt1]);
b2 = component(\`Child\`, {}, key + \`__1\`, node, ctx);
}
return block1([], [b2]);
} }
}" }"
`; `;
@@ -36,14 +80,16 @@ exports[`Reactivity: useState destroyed component before being mounted is inacti
exports[`Reactivity: useState destroyed component is inactive 1`] = ` exports[`Reactivity: useState destroyed component is inactive 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<span><block-text-0/></span>\`); let block1 = createBlock(\`<div><block-child-0/></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = ctx['contextObj'].a; let b2;
return block1([d1]); if (ctx['state'].flag) {
b2 = component(\`Child\`, {}, key+\`__1\`,null, node, ctx);
}
return block1([], [b2]);
} }
}" }"
`; `;
@@ -51,17 +97,13 @@ exports[`Reactivity: useState destroyed component is inactive 1`] = `
exports[`Reactivity: useState destroyed component is inactive 2`] = ` exports[`Reactivity: useState destroyed component is inactive 2`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><block-child-0/></div>\`); let block1 = createBlock(\`<span><block-text-0/></span>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let b2; let txt1 = ctx['contextObj'].a;
if (ctx['state'].flag) { return block1([txt1]);
b2 = component(\`Child\`, {}, key + \`__1\`, node, ctx);
}
return block1([], [b2]);
} }
}" }"
`; `;
@@ -69,15 +111,14 @@ exports[`Reactivity: useState destroyed component is inactive 2`] = `
exports[`Reactivity: useState one components can subscribe twice to same context 1`] = ` exports[`Reactivity: useState one components can subscribe twice to same context 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><block-text-0/><block-text-1/></div>\`); let block1 = createBlock(\`<div><block-text-0/><block-text-1/></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = ctx['contextObj1'].a; let txt1 = ctx['contextObj1'].a;
let d2 = ctx['contextObj2'].b; let txt2 = ctx['contextObj2'].b;
return block1([d1, d2]); return block1([txt1, txt2]);
} }
}" }"
`; `;
@@ -85,14 +126,14 @@ exports[`Reactivity: useState one components can subscribe twice to same context
exports[`Reactivity: useState parent and children subscribed to same context 1`] = ` exports[`Reactivity: useState parent and children subscribed to same context 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<span><block-text-0/></span>\`); let block1 = createBlock(\`<div><block-child-0/><block-text-0/></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = ctx['contextObj'].a; let b2 = component(\`Child\`, {}, key+\`__1\`,null, node, ctx);
return block1([d1]); let txt1 = ctx['contextObj'].b;
return block1([txt1], [b2]);
} }
}" }"
`; `;
@@ -100,15 +141,13 @@ exports[`Reactivity: useState parent and children subscribed to same context 1`]
exports[`Reactivity: useState parent and children subscribed to same context 2`] = ` exports[`Reactivity: useState parent and children subscribed to same context 2`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><block-child-0/><block-text-0/></div>\`); let block1 = createBlock(\`<span><block-text-0/></span>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let b2 = component(\`Child\`, {}, key + \`__1\`, node, ctx); let txt1 = ctx['contextObj'].a;
let d1 = ctx['contextObj'].b; return block1([txt1]);
return block1([d1], [b2]);
} }
}" }"
`; `;
@@ -179,14 +218,14 @@ exports[`Reactivity: useState several nodes on different level use same context
exports[`Reactivity: useState two components are updated in parallel 1`] = ` exports[`Reactivity: useState two components are updated in parallel 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<span><block-text-0/></span>\`); let block1 = createBlock(\`<div><block-child-0/><block-child-1/></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = ctx['contextObj'].value; let b2 = component(\`Child\`, {}, key+\`__1\`,null, node, ctx);
return block1([d1]); let b3 = component(\`Child\`, {}, key+\`__2\`,null, node, ctx);
return block1([], [b2, b3]);
} }
}" }"
`; `;
@@ -194,15 +233,13 @@ exports[`Reactivity: useState two components are updated in parallel 1`] = `
exports[`Reactivity: useState two components are updated in parallel 2`] = ` exports[`Reactivity: useState two components are updated in parallel 2`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><block-child-0/><block-child-1/></div>\`); let block1 = createBlock(\`<span><block-text-0/></span>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let b2 = component(\`Child\`, {}, key + \`__1\`, node, ctx); let txt1 = ctx['contextObj'].value;
let b3 = component(\`Child\`, {}, key + \`__2\`, node, ctx); return block1([txt1]);
return block1([], [b2, b3]);
} }
}" }"
`; `;
@@ -210,14 +247,14 @@ exports[`Reactivity: useState two components are updated in parallel 2`] = `
exports[`Reactivity: useState two components can subscribe to same context 1`] = ` exports[`Reactivity: useState two components can subscribe to same context 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<span><block-text-0/></span>\`); let block1 = createBlock(\`<div><block-child-0/><block-child-1/></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = ctx['contextObj'].value; let b2 = component(\`Child\`, {}, key+\`__1\`,null, node, ctx);
return block1([d1]); let b3 = component(\`Child\`, {}, key+\`__2\`,null, node, ctx);
return block1([], [b2, b3]);
} }
}" }"
`; `;
@@ -225,15 +262,13 @@ exports[`Reactivity: useState two components can subscribe to same context 1`] =
exports[`Reactivity: useState two components can subscribe to same context 2`] = ` exports[`Reactivity: useState two components can subscribe to same context 2`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><block-child-0/><block-child-1/></div>\`); let block1 = createBlock(\`<span><block-text-0/></span>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let b2 = component(\`Child\`, {}, key + \`__1\`, node, ctx); let txt1 = ctx['contextObj'].value;
let b3 = component(\`Child\`, {}, key + \`__2\`, node, ctx); return block1([txt1]);
return block1([], [b2, b3]);
} }
}" }"
`; `;
@@ -241,14 +276,14 @@ exports[`Reactivity: useState two components can subscribe to same context 2`] =
exports[`Reactivity: useState two independent components on different levels are updated in parallel 1`] = ` exports[`Reactivity: useState two independent components on different levels are updated in parallel 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<span><block-text-0/></span>\`); let block1 = createBlock(\`<div><block-child-0/><block-child-1/></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = ctx['contextObj'].value; let b2 = component(\`Child\`, {}, key+\`__1\`,null, node, ctx);
return block1([d1]); let b3 = component(\`Parent\`, {}, key+\`__2\`,null, node, ctx);
return block1([], [b2, b3]);
} }
}" }"
`; `;
@@ -256,14 +291,13 @@ exports[`Reactivity: useState two independent components on different levels are
exports[`Reactivity: useState two independent components on different levels are updated in parallel 2`] = ` exports[`Reactivity: useState two independent components on different levels are updated in parallel 2`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><block-child-0/></div>\`); let block1 = createBlock(\`<span><block-text-0/></span>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let b2 = component(\`Child\`, {}, key + \`__1\`, node, ctx); let txt1 = ctx['contextObj'].value;
return block1([], [b2]); return block1([txt1]);
} }
}" }"
`; `;
@@ -271,15 +305,13 @@ exports[`Reactivity: useState two independent components on different levels are
exports[`Reactivity: useState two independent components on different levels are updated in parallel 3`] = ` exports[`Reactivity: useState two independent components on different levels are updated in parallel 3`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><block-child-0/><block-child-1/></div>\`); let block1 = createBlock(\`<div><block-child-0/></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let b2 = component(\`Child\`, {}, key + \`__1\`, node, ctx); let b2 = component(\`Child\`, {}, key+\`__1\`,null, node, ctx);
let b3 = component(\`Parent\`, {}, key + \`__2\`, node, ctx); return block1([], [b2]);
return block1([], [b2, b3]);
} }
}" }"
`; `;
@@ -287,14 +319,13 @@ exports[`Reactivity: useState two independent components on different levels are
exports[`Reactivity: useState useContext=useState hook is reactive, for one component 1`] = ` exports[`Reactivity: useState useContext=useState hook is reactive, for one component 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><block-text-0/></div>\`); let block1 = createBlock(\`<div><block-text-0/></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = ctx['contextObj'].value; let txt1 = ctx['contextObj'].value;
return block1([d1]); return block1([txt1]);
} }
}" }"
`; `;
@@ -302,23 +333,8 @@ exports[`Reactivity: useState useContext=useState hook is reactive, for one comp
exports[`Reactivity: useState useless atoms should be deleted 1`] = ` exports[`Reactivity: useState useless atoms should be deleted 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { prepareList, withKey } = helpers;
let block1 = createBlock(\`<div><block-text-0/></div>\`);
return function template(ctx, node, key = \\"\\") {
let d1 = ctx['state'].quantity;
return block1([d1]);
}
}"
`;
exports[`Reactivity: useState useless atoms should be deleted 2`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><block-child-0/> Total: <block-text-0/> Count: <block-text-1/></div>\`); let block1 = createBlock(\`<div><block-child-0/> Total: <block-text-0/> Count: <block-text-1/></div>\`);
@@ -328,13 +344,27 @@ exports[`Reactivity: useState useless atoms should be deleted 2`] = `
for (let i1 = 0; i1 < l_block2; i1++) { for (let i1 = 0; i1 < l_block2; i1++) {
ctx[\`id\`] = v_block2[i1]; ctx[\`id\`] = v_block2[i1];
let key1 = ctx['id']; let key1 = ctx['id'];
c_block2[i1] = withKey(component(\`Quantity\`, {id: ctx['id']}, key + \`__1__\${key1}\`, node, ctx), key1); c_block2[i1] = withKey(component(\`Quantity\`, {id: ctx['id']}, key+\`__1__\${key1}\`,null, node, ctx), key1);
} }
ctx = ctx.__proto__; ctx = ctx.__proto__;
let b2 = list(c_block2); let b2 = list(c_block2);
let d1 = ctx['total']; let txt1 = ctx['total'];
let d2 = Object.keys(ctx['state']).length; let txt2 = Object.keys(ctx['state']).length;
return block1([d1, d2], [b2]); return block1([txt1, txt2], [b2]);
}
}"
`;
exports[`Reactivity: useState useless atoms should be deleted 2`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let block1 = createBlock(\`<div><block-text-0/></div>\`);
return function template(ctx, node, key = \\"\\") {
let txt1 = ctx['state'].quantity;
return block1([txt1]);
} }
}" }"
`; `;
@@ -342,14 +372,13 @@ exports[`Reactivity: useState useless atoms should be deleted 2`] = `
exports[`Reactivity: useState very simple use, with initial value 1`] = ` exports[`Reactivity: useState very simple use, with initial value 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><block-text-0/></div>\`); let block1 = createBlock(\`<div><block-text-0/></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = ctx['contextObj'].value; let txt1 = ctx['contextObj'].value;
return block1([d1]); return block1([txt1]);
} }
}" }"
`; `;
+43
View File
@@ -0,0 +1,43 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`app App supports env with getters/setters 1`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let block1 = createBlock(\`<div><block-text-0/> <block-text-1/></div>\`);
return function template(ctx, node, key = \\"\\") {
let txt1 = ctx['env'].someVal;
let txt2 = Object.keys(ctx['env'].services);
return block1([txt1, txt2]);
}
}"
`;
exports[`app can configure an app with props 1`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let block1 = createBlock(\`<div><block-text-0/></div>\`);
return function template(ctx, node, key = \\"\\") {
let txt1 = ctx['props'].value;
return block1([txt1]);
}
}"
`;
exports[`app destroy remove the widget from the DOM 1`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let block1 = createBlock(\`<div/>\`);
return function template(ctx, node, key = \\"\\") {
return block1();
}
}"
`;
+62
View File
@@ -0,0 +1,62 @@
import { App, Component, xml } from "../../src";
import { status } from "../../src/component/status";
import { makeTestFixture, snapshotEverything, nextTick, elem } from "../helpers";
let fixture: HTMLElement;
snapshotEverything();
beforeEach(() => {
fixture = makeTestFixture();
});
describe("app", () => {
test("destroy remove the widget from the DOM", async () => {
class SomeComponent extends Component {
static template = xml`<div/>`;
}
const app = new App(SomeComponent);
const comp = await app.mount(fixture);
const el = elem(comp);
expect(document.contains(el)).toBe(true);
app.destroy();
expect(document.contains(el)).toBe(false);
expect(status(comp)).toBe("destroyed");
});
test("App supports env with getters/setters", async () => {
let someVal = "maggot";
const services: any = { serv1: "" };
const env = {
get someVal() {
return someVal;
},
services,
};
class SomeComponent extends Component {
static template = xml`<div><t t-esc="env.someVal" /> <t t-esc="Object.keys(env.services)" /></div>`;
}
const app = new App(SomeComponent, { env });
const comp = await app.mount(fixture);
expect(fixture.innerHTML).toBe("<div>maggot serv1</div>");
someVal = "brain";
services.serv2 = "";
comp.render();
await nextTick();
expect(fixture.innerHTML).toBe("<div>brain serv1,serv2</div>");
});
test("can configure an app with props", async () => {
class SomeComponent extends Component {
static template = xml`<div t-esc="props.value"/>`;
}
const app = new App(SomeComponent, { props: { value: 333 } });
await app.mount(fixture);
expect(fixture.innerHTML).toBe("<div>333</div>");
});
});
+32
View File
@@ -227,6 +227,38 @@ describe("misc", () => {
expect(fixture.innerHTML).toBe("<p>() =&gt; 3tostring</p>"); expect(fixture.innerHTML).toBe("<p>() =&gt; 3tostring</p>");
}); });
test("block with 2 subblocks: variation", async () => {
const block = createBlock("<a><b><c><block-child-0/>2</c></b><block-child-1/></a>");
const tree = block([], [text("1"), text("3")]);
mount(tree, fixture);
expect(fixture.innerHTML).toBe("<a><b><c>12</c></b>3</a>");
});
test("block with 2 subblocks: another variation", async () => {
const block = createBlock(
`<a block-attribute-0="hello"><b><c><block-child-0/>2</c></b><block-child-1/></a>`
);
const tree = block(["world"], [text("1"), text("3")]);
mount(tree, fixture);
expect(fixture.innerHTML).toBe(`<a hello="world"><b><c>12</c></b>3</a>`);
});
test("namespace is not propagated to siblings", () => {
const block = createBlock(`<div><svg block-ns="someNameSpace"><g/></svg><div></div></div>`);
const fixture = makeTestFixture();
mount(block(), fixture);
expect(fixture.innerHTML).toBe("<div><svg><g></g></svg><div></div></div>");
expect(fixture.querySelector("svg")!.namespaceURI).toBe("someNameSpace");
expect(fixture.querySelector("g")!.namespaceURI).toBe("someNameSpace");
const allDivs = fixture.querySelectorAll("div");
expect(Array.from(allDivs).map((el) => el.namespaceURI)).toEqual([
"http://www.w3.org/1999/xhtml",
"http://www.w3.org/1999/xhtml",
]);
});
// test.skip("reusing a block skips patching process", async () => { // test.skip("reusing a block skips patching process", async () => {
// const block = createBlock('<div><block-text-0/></div>'); // const block = createBlock('<div><block-text-0/></div>');
// const foo = block(["foo"]); // const foo = block(["foo"]);
+59
View File
@@ -26,6 +26,26 @@ test("simple attribute", async () => {
expect(fixture.innerHTML).toBe(`<div hello="owl"></div>`); expect(fixture.innerHTML).toBe(`<div hello="owl"></div>`);
}); });
test("updating attribute with falsy value", async () => {
const block = createBlock('<div block-attribute-0="hello"></div>');
const tree = block([false]);
mount(tree, fixture);
expect(fixture.innerHTML).toBe(`<div></div>`);
patch(tree, block(["owl"]));
expect(fixture.innerHTML).toBe(`<div hello="owl"></div>`);
patch(tree, block([false]));
expect(fixture.innerHTML).toBe(`<div></div>`);
patch(tree, block(["owl"]));
expect(fixture.innerHTML).toBe(`<div hello="owl"></div>`);
patch(tree, block([undefined]));
expect(fixture.innerHTML).toBe(`<div></div>`);
});
test("dynamic attribute (pair)", async () => { test("dynamic attribute (pair)", async () => {
const block = createBlock('<div block-attributes="0"></div>'); const block = createBlock('<div block-attributes="0"></div>');
const tree = block([["hello", "world"]]); const tree = block([["hello", "world"]]);
@@ -37,6 +57,20 @@ test("dynamic attribute (pair)", async () => {
expect(fixture.innerHTML).toBe(`<div ola="mundo"></div>`); expect(fixture.innerHTML).toBe(`<div ola="mundo"></div>`);
}); });
test("dynamic attribute (pair, with false value)", async () => {
const block = createBlock('<div block-attributes="0"></div>');
const tree = block([["hello", false]]);
mount(tree, fixture);
expect(fixture.innerHTML).toBe(`<div></div>`);
patch(tree, block([["hello", "world"]]));
expect(fixture.innerHTML).toBe(`<div hello="world"></div>`);
patch(tree, block([["hello", false]]));
expect(fixture.innerHTML).toBe(`<div></div>`);
});
test("dynamic attribute (object)", async () => { test("dynamic attribute (object)", async () => {
const block = createBlock('<div block-attributes="0"></div>'); const block = createBlock('<div block-attributes="0"></div>');
const tree = block([{ hello: "world" }]); const tree = block([{ hello: "world" }]);
@@ -48,6 +82,23 @@ test("dynamic attribute (object)", async () => {
expect(fixture.innerHTML).toBe(`<div ola="mundo"></div>`); expect(fixture.innerHTML).toBe(`<div ola="mundo"></div>`);
}); });
test("dynamic attribute (object), with falsy values", async () => {
const block = createBlock('<div block-attributes="0"></div>');
const tree = block([{ hello: "world", blip: false }]);
mount(tree, fixture);
expect(fixture.innerHTML).toBe(`<div hello="world"></div>`);
patch(tree, block([{ ola: "mundo", blip: undefined }]));
expect(fixture.innerHTML).toBe(`<div ola="mundo"></div>`);
patch(tree, block([{ ola: false, blip: 1 }]));
expect(fixture.innerHTML).toBe(`<div blip="1"></div>`);
patch(tree, block([{ ola: undefined, blip: undefined }]));
expect(fixture.innerHTML).toBe(`<div></div>`);
});
test("class attribute", async () => { test("class attribute", async () => {
const block = createBlock('<div block-attribute-0="class"></div>'); const block = createBlock('<div block-attribute-0="class"></div>');
const tree = block(["fire"]); const tree = block(["fire"]);
@@ -65,6 +116,14 @@ test("class attribute", async () => {
expect(fixture.innerHTML).toBe(`<div class="0"></div>`); expect(fixture.innerHTML).toBe(`<div class="0"></div>`);
}); });
test("attribute with undefined value", async () => {
const block = createBlock('<div block-attribute-0="abc"></div>');
const tree = block([undefined]);
mount(tree, fixture);
expect(fixture.innerHTML).toBe(`<div></div>`);
});
test("class attribute with undefined value", async () => { test("class attribute with undefined value", async () => {
const block = createBlock('<div block-attribute-0="class"></div>'); const block = createBlock('<div block-attribute-0="class"></div>');
const tree = block([undefined]); const tree = block([undefined]);
+26
View File
@@ -0,0 +1,26 @@
import { comment, mount } from "../../src/blockdom";
import { makeTestFixture } from "./helpers";
//------------------------------------------------------------------------------
// Setup and helpers
//------------------------------------------------------------------------------
let fixture: HTMLElement;
beforeEach(() => {
fixture = makeTestFixture();
});
afterEach(() => {
fixture.remove();
});
test("simple comment node", async () => {
const tree = comment("foo");
expect(tree.el).toBe(undefined);
mount(tree, fixture);
expect(fixture.innerHTML).toBe("<!--foo-->");
expect(tree.el).not.toBe(undefined);
tree.remove();
expect(fixture.innerHTML).toBe("");
});
+7
View File
@@ -76,4 +76,11 @@ describe("multi blocks", () => {
mount(text(multi([text("a"), text("b")]) as any), fixture); mount(text(multi([text("a"), text("b")]) as any), fixture);
expect(fixture.innerHTML).toBe("ab"); expect(fixture.innerHTML).toBe("ab");
}); });
test("multi inside a block", async () => {
const block = createBlock("<div><block-child-0/></div>");
const tree = block([], [multi([text("foo"), text("bar")])]);
mount(tree, fixture);
expect(fixture.innerHTML).toBe("<div>foobar</div>");
});
}); });
+72
View File
@@ -0,0 +1,72 @@
import { createBlock, mount } from "../../src/blockdom";
import { makeTestFixture } from "./helpers";
//------------------------------------------------------------------------------
// Setup and helpers
//------------------------------------------------------------------------------
const XHTML_URI = "http://www.w3.org/1999/xhtml";
const SVG_URI = "http://www.w3.org/2000/svg";
let fixture: HTMLElement;
beforeEach(() => {
fixture = makeTestFixture();
});
afterEach(() => {
fixture.remove();
});
//------------------------------------------------------------------------------
// Tests
//------------------------------------------------------------------------------
describe("namespace", () => {
test("default namespace is xhtml", () => {
const block = createBlock(`<tag/>`);
const tree = block();
mount(tree, fixture);
expect(fixture.innerHTML).toBe("<tag></tag>");
expect(fixture.firstElementChild!.namespaceURI).toBe(XHTML_URI);
});
test("namespace can be changed with block-ns", () => {
const block = createBlock(`<tag block-ns="${SVG_URI}"/>`);
const tree = block();
mount(tree, fixture);
expect(fixture.innerHTML).toBe("<tag></tag>");
expect(fixture.firstElementChild!.namespaceURI).toBe(SVG_URI);
});
test("namespace is kept for children", () => {
const block = createBlock(
`<parent block-ns="${SVG_URI}"><child><subchild/></child><child/></parent>`
);
const tree = block();
mount(tree, fixture);
expect(fixture.innerHTML).toBe(
"<parent><child><subchild></subchild></child><child></child></parent>"
);
const parent = fixture.firstElementChild!;
const child1 = parent.firstElementChild!;
const subchild = child1.firstElementChild!;
const child2 = child1.nextElementSibling!;
expect(parent.namespaceURI).toBe(SVG_URI);
expect(child1.namespaceURI).toBe(SVG_URI);
expect(child2.namespaceURI).toBe(SVG_URI);
expect(subchild.namespaceURI).toBe(SVG_URI);
});
test("various namespaces in same block", () => {
const block = createBlock(`<none><one block-ns="one"/><two block-ns="two"/></none>`);
const tree = block();
mount(tree, fixture);
expect(fixture.innerHTML).toBe("<none><one></one><two></two></none>");
const none = fixture.firstElementChild!;
const one = none.firstElementChild!;
const two = one.nextElementSibling!;
expect(none.namespaceURI).toBe(XHTML_URI);
expect(one.namespaceURI).toBe("one");
expect(two.namespaceURI).toBe("two");
});
});
@@ -3,14 +3,13 @@
exports[`attributes changing a class with t-att-class (preexisting class 1`] = ` exports[`attributes changing a class with t-att-class (preexisting class 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div class=\\"hoy\\" block-attribute-0=\\"class\\"/>\`); let block1 = createBlock(\`<div class=\\"hoy\\" block-attribute-0=\\"class\\"/>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = ctx['v']; let attr1 = ctx['v'];
return block1([d1]); return block1([attr1]);
} }
}" }"
`; `;
@@ -18,14 +17,13 @@ exports[`attributes changing a class with t-att-class (preexisting class 1`] = `
exports[`attributes changing a class with t-att-class 1`] = ` exports[`attributes changing a class with t-att-class 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div block-attribute-0=\\"class\\"/>\`); let block1 = createBlock(\`<div block-attribute-0=\\"class\\"/>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = ctx['v']; let attr1 = ctx['v'];
return block1([d1]); return block1([attr1]);
} }
}" }"
`; `;
@@ -33,14 +31,13 @@ exports[`attributes changing a class with t-att-class 1`] = `
exports[`attributes changing an attribute with t-att- 1`] = ` exports[`attributes changing an attribute with t-att- 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div block-attribute-0=\\"value\\"/>\`); let block1 = createBlock(\`<div block-attribute-0=\\"value\\"/>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = ctx['v']; let attr1 = ctx['v'];
return block1([d1]); return block1([attr1]);
} }
}" }"
`; `;
@@ -48,14 +45,13 @@ exports[`attributes changing an attribute with t-att- 1`] = `
exports[`attributes class and t-att-class should combine together 1`] = ` exports[`attributes class and t-att-class should combine together 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div block-attribute-0=\\"class\\" class=\\"hello\\"/>\`); let block1 = createBlock(\`<div block-attribute-0=\\"class\\" class=\\"hello\\"/>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = ctx['value']; let attr1 = ctx['value'];
return block1([d1]); return block1([attr1]);
} }
}" }"
`; `;
@@ -63,14 +59,13 @@ exports[`attributes class and t-att-class should combine together 1`] = `
exports[`attributes class and t-attf-class with ternary operation 1`] = ` exports[`attributes class and t-attf-class with ternary operation 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div class=\\"hello\\" block-attribute-0=\\"class\\"/>\`); let block1 = createBlock(\`<div class=\\"hello\\" block-attribute-0=\\"class\\"/>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = (ctx['value']?'world':''); let attr1 = (ctx['value']?'world':'');
return block1([d1]); return block1([attr1]);
} }
}" }"
`; `;
@@ -78,14 +73,13 @@ exports[`attributes class and t-attf-class with ternary operation 1`] = `
exports[`attributes dynamic attribute evaluating to 0 1`] = ` exports[`attributes dynamic attribute evaluating to 0 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div block-attribute-0=\\"foo\\"/>\`); let block1 = createBlock(\`<div block-attribute-0=\\"foo\\"/>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = ctx['value']; let attr1 = ctx['value'];
return block1([d1]); return block1([attr1]);
} }
}" }"
`; `;
@@ -93,14 +87,13 @@ exports[`attributes dynamic attribute evaluating to 0 1`] = `
exports[`attributes dynamic attribute falsy variable 1`] = ` exports[`attributes dynamic attribute falsy variable 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div block-attribute-0=\\"foo\\"/>\`); let block1 = createBlock(\`<div block-attribute-0=\\"foo\\"/>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = ctx['value']; let attr1 = ctx['value'];
return block1([d1]); return block1([attr1]);
} }
}" }"
`; `;
@@ -108,14 +101,13 @@ exports[`attributes dynamic attribute falsy variable 1`] = `
exports[`attributes dynamic attribute with a dash 1`] = ` exports[`attributes dynamic attribute with a dash 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div block-attribute-0=\\"data-action-id\\"/>\`); let block1 = createBlock(\`<div block-attribute-0=\\"data-action-id\\"/>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = ctx['id']; let attr1 = ctx['id'];
return block1([d1]); return block1([attr1]);
} }
}" }"
`; `;
@@ -123,14 +115,13 @@ exports[`attributes dynamic attribute with a dash 1`] = `
exports[`attributes dynamic attributes 1`] = ` exports[`attributes dynamic attributes 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div block-attribute-0=\\"foo\\"/>\`); let block1 = createBlock(\`<div block-attribute-0=\\"foo\\"/>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = 'bar'; let attr1 = 'bar';
return block1([d1]); return block1([attr1]);
} }
}" }"
`; `;
@@ -138,14 +129,13 @@ exports[`attributes dynamic attributes 1`] = `
exports[`attributes dynamic class attribute 1`] = ` exports[`attributes dynamic class attribute 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div block-attribute-0=\\"class\\"/>\`); let block1 = createBlock(\`<div block-attribute-0=\\"class\\"/>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = ctx['c']; let attr1 = ctx['c'];
return block1([d1]); return block1([attr1]);
} }
}" }"
`; `;
@@ -153,14 +143,13 @@ exports[`attributes dynamic class attribute 1`] = `
exports[`attributes dynamic class attribute evaluating to 0 1`] = ` exports[`attributes dynamic class attribute evaluating to 0 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div block-attribute-0=\\"class\\"/>\`); let block1 = createBlock(\`<div block-attribute-0=\\"class\\"/>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = ctx['value']; let attr1 = ctx['value'];
return block1([d1]); return block1([attr1]);
} }
}" }"
`; `;
@@ -168,14 +157,13 @@ exports[`attributes dynamic class attribute evaluating to 0 1`] = `
exports[`attributes dynamic empty class attribute 1`] = ` exports[`attributes dynamic empty class attribute 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div block-attribute-0=\\"class\\"/>\`); let block1 = createBlock(\`<div block-attribute-0=\\"class\\"/>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = ctx['c']; let attr1 = ctx['c'];
return block1([d1]); return block1([attr1]);
} }
}" }"
`; `;
@@ -183,14 +171,41 @@ exports[`attributes dynamic empty class attribute 1`] = `
exports[`attributes dynamic formatted attributes with a dash 1`] = ` exports[`attributes dynamic formatted attributes with a dash 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div block-attribute-0=\\"aria-label\\"/>\`); let block1 = createBlock(\`<div block-attribute-0=\\"aria-label\\"/>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = \`Some text \${ctx['id']}\`; let attr1 = \`Some text \${ctx['id']}\`;
return block1([d1]); return block1([attr1]);
}
}"
`;
exports[`attributes dynamic undefined class attribute 1`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let block1 = createBlock(\`<div block-attribute-0=\\"class\\"/>\`);
return function template(ctx, node, key = \\"\\") {
let attr1 = ctx['c'];
return block1([attr1]);
}
}"
`;
exports[`attributes dynamic undefined generic attribute 1`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let block1 = createBlock(\`<div block-attribute-0=\\"thing\\"/>\`);
return function template(ctx, node, key = \\"\\") {
let attr1 = ctx['c'];
return block1([attr1]);
} }
}" }"
`; `;
@@ -198,14 +213,13 @@ exports[`attributes dynamic formatted attributes with a dash 1`] = `
exports[`attributes fixed variable 1`] = ` exports[`attributes fixed variable 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div block-attribute-0=\\"foo\\"/>\`); let block1 = createBlock(\`<div block-attribute-0=\\"foo\\"/>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = ctx['value']; let attr1 = ctx['value'];
return block1([d1]); return block1([attr1]);
} }
}" }"
`; `;
@@ -213,14 +227,13 @@ exports[`attributes fixed variable 1`] = `
exports[`attributes format expression 1`] = ` exports[`attributes format expression 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div block-attribute-0=\\"foo\\"/>\`); let block1 = createBlock(\`<div block-attribute-0=\\"foo\\"/>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = (ctx['value']+37); let attr1 = (ctx['value']+37);
return block1([d1]); return block1([attr1]);
} }
}" }"
`; `;
@@ -228,14 +241,13 @@ exports[`attributes format expression 1`] = `
exports[`attributes format literal 1`] = ` exports[`attributes format literal 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div block-attribute-0=\\"foo\\"/>\`); let block1 = createBlock(\`<div block-attribute-0=\\"foo\\"/>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = \`bar\`; let attr1 = \`bar\`;
return block1([d1]); return block1([attr1]);
} }
}" }"
`; `;
@@ -243,14 +255,13 @@ exports[`attributes format literal 1`] = `
exports[`attributes format multiple 1`] = ` exports[`attributes format multiple 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div block-attribute-0=\\"foo\\"/>\`); let block1 = createBlock(\`<div block-attribute-0=\\"foo\\"/>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = \`a \${ctx['value1']} is \${ctx['value2']} of \${ctx['value3']} ]\`; let attr1 = \`a \${ctx['value1']} is \${ctx['value2']} of \${ctx['value3']} ]\`;
return block1([d1]); return block1([attr1]);
} }
}" }"
`; `;
@@ -258,14 +269,13 @@ exports[`attributes format multiple 1`] = `
exports[`attributes format value 1`] = ` exports[`attributes format value 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div block-attribute-0=\\"foo\\"/>\`); let block1 = createBlock(\`<div block-attribute-0=\\"foo\\"/>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = \`b\${ctx['value']}r\`; let attr1 = \`b\${ctx['value']}r\`;
return block1([d1]); return block1([attr1]);
} }
}" }"
`; `;
@@ -273,8 +283,8 @@ exports[`attributes format value 1`] = `
exports[`attributes from object variables set previously 1`] = ` exports[`attributes from object variables set previously 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { isBoundary, withDefault, setContextValue } = helpers;
let block1 = createBlock(\`<div><span block-attribute-0=\\"class\\"/></div>\`); let block1 = createBlock(\`<div><span block-attribute-0=\\"class\\"/></div>\`);
@@ -282,8 +292,8 @@ exports[`attributes from object variables set previously 1`] = `
ctx = Object.create(ctx); ctx = Object.create(ctx);
ctx[isBoundary] = 1 ctx[isBoundary] = 1
setContextValue(ctx, \\"o\\", {a:'b'}); setContextValue(ctx, \\"o\\", {a:'b'});
let d1 = ctx['o'].a; let attr1 = ctx['o'].a;
return block1([d1]); return block1([attr1]);
} }
}" }"
`; `;
@@ -291,8 +301,8 @@ exports[`attributes from object variables set previously 1`] = `
exports[`attributes from variables set previously (no external node) 1`] = ` exports[`attributes from variables set previously (no external node) 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { isBoundary, withDefault, setContextValue } = helpers;
let block1 = createBlock(\`<span block-attribute-0=\\"class\\"/>\`); let block1 = createBlock(\`<span block-attribute-0=\\"class\\"/>\`);
@@ -300,8 +310,8 @@ exports[`attributes from variables set previously (no external node) 1`] = `
ctx = Object.create(ctx); ctx = Object.create(ctx);
ctx[isBoundary] = 1 ctx[isBoundary] = 1
setContextValue(ctx, \\"abc\\", 'def'); setContextValue(ctx, \\"abc\\", 'def');
let d1 = ctx['abc']; let attr1 = ctx['abc'];
return block1([d1]); return block1([attr1]);
} }
}" }"
`; `;
@@ -309,8 +319,8 @@ exports[`attributes from variables set previously (no external node) 1`] = `
exports[`attributes from variables set previously 1`] = ` exports[`attributes from variables set previously 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { isBoundary, withDefault, setContextValue } = helpers;
let block1 = createBlock(\`<div><span block-attribute-0=\\"class\\"/></div>\`); let block1 = createBlock(\`<div><span block-attribute-0=\\"class\\"/></div>\`);
@@ -318,8 +328,8 @@ exports[`attributes from variables set previously 1`] = `
ctx = Object.create(ctx); ctx = Object.create(ctx);
ctx[isBoundary] = 1 ctx[isBoundary] = 1
setContextValue(ctx, \\"abc\\", 'def'); setContextValue(ctx, \\"abc\\", 'def');
let d1 = ctx['abc']; let attr1 = ctx['abc'];
return block1([d1]); return block1([attr1]);
} }
}" }"
`; `;
@@ -327,14 +337,13 @@ exports[`attributes from variables set previously 1`] = `
exports[`attributes object 1`] = ` exports[`attributes object 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div block-attributes=\\"0\\"/>\`); let block1 = createBlock(\`<div block-attributes=\\"0\\"/>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = ctx['value']; let attr1 = ctx['value'];
return block1([d1]); return block1([attr1]);
} }
}" }"
`; `;
@@ -342,8 +351,7 @@ exports[`attributes object 1`] = `
exports[`attributes static attributes 1`] = ` exports[`attributes static attributes 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div foo=\\"a\\" bar=\\"b\\" baz=\\"c\\"/>\`); let block1 = createBlock(\`<div foo=\\"a\\" bar=\\"b\\" baz=\\"c\\"/>\`);
@@ -356,8 +364,7 @@ exports[`attributes static attributes 1`] = `
exports[`attributes static attributes on void elements 1`] = ` exports[`attributes static attributes on void elements 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<img src=\\"/test.skip.jpg\\" alt=\\"Test\\"/>\`); let block1 = createBlock(\`<img src=\\"/test.skip.jpg\\" alt=\\"Test\\"/>\`);
@@ -370,8 +377,7 @@ exports[`attributes static attributes on void elements 1`] = `
exports[`attributes static attributes with dashes 1`] = ` exports[`attributes static attributes with dashes 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div aria-label=\\"Close\\"/>\`); let block1 = createBlock(\`<div aria-label=\\"Close\\"/>\`);
@@ -384,14 +390,13 @@ exports[`attributes static attributes with dashes 1`] = `
exports[`attributes t-att-class and class should combine together 1`] = ` exports[`attributes t-att-class and class should combine together 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div class=\\"hello\\" block-attribute-0=\\"class\\"/>\`); let block1 = createBlock(\`<div class=\\"hello\\" block-attribute-0=\\"class\\"/>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = ctx['value']; let attr1 = ctx['value'];
return block1([d1]); return block1([attr1]);
} }
}" }"
`; `;
@@ -399,14 +404,13 @@ exports[`attributes t-att-class and class should combine together 1`] = `
exports[`attributes t-att-class with multiple classes 1`] = ` exports[`attributes t-att-class with multiple classes 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div block-attribute-0=\\"class\\"/>\`); let block1 = createBlock(\`<div block-attribute-0=\\"class\\"/>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = {'a b c':ctx['value']}; let attr1 = {'a b c':ctx['value']};
return block1([d1]); return block1([attr1]);
} }
}" }"
`; `;
@@ -414,14 +418,13 @@ exports[`attributes t-att-class with multiple classes 1`] = `
exports[`attributes t-att-class with multiple classes 2`] = ` exports[`attributes t-att-class with multiple classes 2`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div block-attribute-0=\\"class\\"/>\`); let block1 = createBlock(\`<div block-attribute-0=\\"class\\"/>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = {['a b c']:ctx['value']}; let attr1 = {['a b c']:ctx['value']};
return block1([d1]); return block1([attr1]);
} }
}" }"
`; `;
@@ -429,14 +432,13 @@ exports[`attributes t-att-class with multiple classes 2`] = `
exports[`attributes t-att-class with multiple classes, some of which are duplicate 1`] = ` exports[`attributes t-att-class with multiple classes, some of which are duplicate 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div block-attribute-0=\\"class\\"/>\`); let block1 = createBlock(\`<div block-attribute-0=\\"class\\"/>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = {'a b c':ctx['value'],'a b d':!ctx['value']}; let attr1 = {'a b c':ctx['value'],'a b d':!ctx['value']};
return block1([d1]); return block1([attr1]);
} }
}" }"
`; `;
@@ -444,14 +446,13 @@ exports[`attributes t-att-class with multiple classes, some of which are duplica
exports[`attributes t-att-class with object 1`] = ` exports[`attributes t-att-class with object 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div class=\\"static\\" block-attribute-0=\\"class\\"/>\`); let block1 = createBlock(\`<div class=\\"static\\" block-attribute-0=\\"class\\"/>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = {a:ctx['b'],c:ctx['d'],e:ctx['f']}; let attr1 = {a:ctx['b'],c:ctx['d'],e:ctx['f']};
return block1([d1]); return block1([attr1]);
} }
}" }"
`; `;
@@ -459,14 +460,13 @@ exports[`attributes t-att-class with object 1`] = `
exports[`attributes t-attf-class 1`] = ` exports[`attributes t-attf-class 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div block-attribute-0=\\"class\\"/>\`); let block1 = createBlock(\`<div block-attribute-0=\\"class\\"/>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = \`hello\`; let attr1 = \`hello\`;
return block1([d1]); return block1([attr1]);
} }
}" }"
`; `;
@@ -474,14 +474,13 @@ exports[`attributes t-attf-class 1`] = `
exports[`attributes t-attf-class should combine with class 1`] = ` exports[`attributes t-attf-class should combine with class 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div class=\\"hello\\" block-attribute-0=\\"class\\"/>\`); let block1 = createBlock(\`<div class=\\"hello\\" block-attribute-0=\\"class\\"/>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = \`world\`; let attr1 = \`world\`;
return block1([d1]); return block1([attr1]);
} }
}" }"
`; `;
@@ -489,14 +488,13 @@ exports[`attributes t-attf-class should combine with class 1`] = `
exports[`attributes t-attf-class with multiple classes 1`] = ` exports[`attributes t-attf-class with multiple classes 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div block-attribute-0=\\"class\\"/>\`); let block1 = createBlock(\`<div block-attribute-0=\\"class\\"/>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = \`hello \${ctx['word']}\`; let attr1 = \`hello \${ctx['word']}\`;
return block1([d1]); return block1([attr1]);
} }
}" }"
`; `;
@@ -504,14 +502,13 @@ exports[`attributes t-attf-class with multiple classes 1`] = `
exports[`attributes t-attf-class with multiple classes separated by multiple spaces 1`] = ` exports[`attributes t-attf-class with multiple classes separated by multiple spaces 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div block-attribute-0=\\"class\\"/>\`); let block1 = createBlock(\`<div block-attribute-0=\\"class\\"/>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = \`hello \${ctx['word']}\`; let attr1 = \`hello \${ctx['word']}\`;
return block1([d1]); return block1([attr1]);
} }
}" }"
`; `;
@@ -519,14 +516,13 @@ exports[`attributes t-attf-class with multiple classes separated by multiple spa
exports[`attributes tuple literal 1`] = ` exports[`attributes tuple literal 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div block-attributes=\\"0\\"/>\`); let block1 = createBlock(\`<div block-attributes=\\"0\\"/>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = ['foo','bar']; let attr1 = ['foo','bar'];
return block1([d1]); return block1([attr1]);
} }
}" }"
`; `;
@@ -534,14 +530,13 @@ exports[`attributes tuple literal 1`] = `
exports[`attributes tuple variable 1`] = ` exports[`attributes tuple variable 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div block-attributes=\\"0\\"/>\`); let block1 = createBlock(\`<div block-attributes=\\"0\\"/>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = ctx['value']; let attr1 = ctx['value'];
return block1([d1]); return block1([attr1]);
} }
}" }"
`; `;
@@ -549,8 +544,7 @@ exports[`attributes tuple variable 1`] = `
exports[`attributes two classes 1`] = ` exports[`attributes two classes 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div class=\\"a b\\"/>\`); let block1 = createBlock(\`<div class=\\"a b\\"/>\`);
@@ -563,15 +557,14 @@ exports[`attributes two classes 1`] = `
exports[`attributes two dynamic attributes 1`] = ` exports[`attributes two dynamic attributes 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div block-attribute-0=\\"foo\\" block-attribute-1=\\"bar\\"/>\`); let block1 = createBlock(\`<div block-attribute-0=\\"foo\\" block-attribute-1=\\"bar\\"/>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = 'bar'; let attr1 = 'bar';
let d2 = 'foo'; let attr2 = 'foo';
return block1([d1, d2]); return block1([attr1, attr2]);
} }
}" }"
`; `;
@@ -579,14 +572,13 @@ exports[`attributes two dynamic attributes 1`] = `
exports[`attributes updating classes (with obj notation) 1`] = ` exports[`attributes updating classes (with obj notation) 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div class=\\"hoy\\" block-attribute-0=\\"class\\"/>\`); let block1 = createBlock(\`<div class=\\"hoy\\" block-attribute-0=\\"class\\"/>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = {'a b':ctx['condition']}; let attr1 = {'a b':ctx['condition']};
return block1([d1]); return block1([attr1]);
} }
}" }"
`; `;
@@ -594,16 +586,15 @@ exports[`attributes updating classes (with obj notation) 1`] = `
exports[`attributes various escapes 1`] = ` exports[`attributes various escapes 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div foo=\\"&lt;foo\\" block-attribute-0=\\"bar\\" block-attribute-1=\\"baz\\" block-attributes=\\"2\\"/>\`); let block1 = createBlock(\`<div foo=\\"&lt;foo\\" block-attribute-0=\\"bar\\" block-attribute-1=\\"baz\\" block-attributes=\\"2\\"/>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = ctx['bar']; let attr1 = ctx['bar'];
let d2 = \`<\${ctx['baz']}>\`; let attr2 = \`<\${ctx['baz']}>\`;
let d3 = ctx['qux']; let attr3 = ctx['qux'];
return block1([d1, d2, d3]); return block1([attr1, attr2, attr3]);
} }
}" }"
`; `;
@@ -611,8 +602,7 @@ exports[`attributes various escapes 1`] = `
exports[`attributes various escapes 2 1`] = ` exports[`attributes various escapes 2 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div> &lt; </div>\`); let block1 = createBlock(\`<div> &lt; </div>\`);
@@ -625,14 +615,13 @@ exports[`attributes various escapes 2 1`] = `
exports[`special cases for some specific html attributes/properties input of type checkbox with t-att-indeterminate 1`] = ` exports[`special cases for some specific html attributes/properties input of type checkbox with t-att-indeterminate 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<input type=\\"checkbox\\" block-attribute-0=\\"indeterminate\\"/>\`); let block1 = createBlock(\`<input type=\\"checkbox\\" block-attribute-0=\\"indeterminate\\"/>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = ctx['v']; let attr1 = ctx['v'];
return block1([d1]); return block1([attr1]);
} }
}" }"
`; `;
@@ -640,14 +629,13 @@ exports[`special cases for some specific html attributes/properties input of typ
exports[`special cases for some specific html attributes/properties input type= checkbox, with t-att-checked 1`] = ` exports[`special cases for some specific html attributes/properties input type= checkbox, with t-att-checked 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<input type=\\"checkbox\\" block-attribute-0=\\"checked\\"/>\`); let block1 = createBlock(\`<input type=\\"checkbox\\" block-attribute-0=\\"checked\\"/>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = ctx['flag']; let attr1 = ctx['flag'];
return block1([d1]); return block1([attr1]);
} }
}" }"
`; `;
@@ -655,14 +643,13 @@ exports[`special cases for some specific html attributes/properties input type=
exports[`special cases for some specific html attributes/properties input with t-att-value 1`] = ` exports[`special cases for some specific html attributes/properties input with t-att-value 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<input block-attribute-0=\\"value\\"/>\`); let block1 = createBlock(\`<input block-attribute-0=\\"value\\"/>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = ctx['v']; let attr1 = ctx['v'];
return block1([d1]); return block1([attr1]);
} }
}" }"
`; `;
@@ -670,14 +657,13 @@ exports[`special cases for some specific html attributes/properties input with t
exports[`special cases for some specific html attributes/properties select with t-att-value 1`] = ` exports[`special cases for some specific html attributes/properties select with t-att-value 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<select block-attribute-0=\\"value\\"><option value=\\"potato\\">Potato</option><option value=\\"tomato\\">Tomato</option><option value=\\"onion\\">Onion</option></select>\`); let block1 = createBlock(\`<select block-attribute-0=\\"value\\"><option value=\\"potato\\">Potato</option><option value=\\"tomato\\">Tomato</option><option value=\\"onion\\">Onion</option></select>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = ctx['value']; let attr1 = ctx['value'];
return block1([d1]); return block1([attr1]);
} }
}" }"
`; `;
@@ -685,14 +671,13 @@ exports[`special cases for some specific html attributes/properties select with
exports[`special cases for some specific html attributes/properties textarea with t-att-value 1`] = ` exports[`special cases for some specific html attributes/properties textarea with t-att-value 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<textarea block-attribute-0=\\"value\\"/>\`); let block1 = createBlock(\`<textarea block-attribute-0=\\"value\\"/>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = ctx['v']; let attr1 = ctx['v'];
return block1([d1]); return block1([attr1]);
} }
}" }"
`; `;
@@ -700,8 +685,7 @@ exports[`special cases for some specific html attributes/properties textarea wit
exports[`special cases for some specific html attributes/properties various boolean html attributes 1`] = ` exports[`special cases for some specific html attributes/properties various boolean html attributes 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><input type=\\"checkbox\\" checked=\\"checked\\"/><input checked=\\"checked\\"/><div checked=\\"checked\\"/><div selected=\\"selected\\"/><option selected=\\"selected\\" other=\\"1\\"/><input readonly=\\"readonly\\"/><button disabled=\\"disabled\\"/></div>\`); let block1 = createBlock(\`<div><input type=\\"checkbox\\" checked=\\"checked\\"/><input checked=\\"checked\\"/><div checked=\\"checked\\"/><div selected=\\"selected\\"/><option selected=\\"selected\\" other=\\"1\\"/><input readonly=\\"readonly\\"/><button disabled=\\"disabled\\"/></div>\`);
@@ -3,13 +3,10 @@
exports[`comments only a comment 1`] = ` exports[`comments only a comment 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<!-- comment-->\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return block1(); return comment(\` comment\`);
} }
}" }"
`; `;
@@ -17,8 +14,7 @@ exports[`comments only a comment 1`] = `
exports[`comments properly handle comments 1`] = ` exports[`comments properly handle comments 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div>hello <!-- comment-->owl</div>\`); let block1 = createBlock(\`<div>hello <!-- comment-->owl</div>\`);
@@ -31,8 +27,7 @@ exports[`comments properly handle comments 1`] = `
exports[`comments properly handle comments between t-if/t-else 1`] = ` exports[`comments properly handle comments between t-if/t-else 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><block-child-0/><block-child-1/></div>\`); let block1 = createBlock(\`<div><block-child-0/><block-child-1/></div>\`);
let block2 = createBlock(\`<span>true</span>\`); let block2 = createBlock(\`<span>true</span>\`);
@@ -1,15 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`error handling cannot add twice the same template 1`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div/>\`);
return function template(ctx, node, key = \\"\\") {
return block1();
}
}"
`;
@@ -3,15 +3,13 @@
exports[`t-on can bind event handler 1`] = ` exports[`t-on can bind event handler 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<button block-handler-0=\\"click\\">Click</button>\`); let block1 = createBlock(\`<button block-handler-0=\\"click\\">Click</button>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const v1 = ctx['add']; let hdlr1 = [ctx['add'], ctx];
let d1 = [v1, ctx]; return block1([hdlr1]);
return block1([d1]);
} }
}" }"
`; `;
@@ -19,15 +17,14 @@ exports[`t-on can bind event handler 1`] = `
exports[`t-on can bind handlers with arguments 1`] = ` exports[`t-on can bind handlers with arguments 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<button block-handler-0=\\"click\\">Click</button>\`); let block1 = createBlock(\`<button block-handler-0=\\"click\\">Click</button>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const v1 = ctx['add']; const v1 = ctx['add'];
let d1 = [()=>v1(5), ctx]; let hdlr1 = [()=>v1(5), ctx];
return block1([d1]); return block1([hdlr1]);
} }
}" }"
`; `;
@@ -35,15 +32,14 @@ exports[`t-on can bind handlers with arguments 1`] = `
exports[`t-on can bind handlers with empty object 1`] = ` exports[`t-on can bind handlers with empty object 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<button block-handler-0=\\"click\\">Click</button>\`); let block1 = createBlock(\`<button block-handler-0=\\"click\\">Click</button>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const v1 = ctx['doSomething']; const v1 = ctx['doSomething'];
let d1 = [()=>v1({}), ctx]; let hdlr1 = [()=>v1({}), ctx];
return block1([d1]); return block1([hdlr1]);
} }
}" }"
`; `;
@@ -51,15 +47,14 @@ exports[`t-on can bind handlers with empty object 1`] = `
exports[`t-on can bind handlers with empty object (with non empty inner string) 1`] = ` exports[`t-on can bind handlers with empty object (with non empty inner string) 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<button block-handler-0=\\"click\\">Click</button>\`); let block1 = createBlock(\`<button block-handler-0=\\"click\\">Click</button>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const v1 = ctx['doSomething']; const v1 = ctx['doSomething'];
let d1 = [()=>v1({}), ctx]; let hdlr1 = [()=>v1({}), ctx];
return block1([d1]); return block1([hdlr1]);
} }
}" }"
`; `;
@@ -67,8 +62,8 @@ exports[`t-on can bind handlers with empty object (with non empty inner string)
exports[`t-on can bind handlers with empty object (with non empty inner string) 2`] = ` exports[`t-on can bind handlers with empty object (with non empty inner string) 2`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { prepareList, withKey } = helpers;
let block1 = createBlock(\`<ul><block-child-0/></ul>\`); let block1 = createBlock(\`<ul><block-child-0/></ul>\`);
let block3 = createBlock(\`<li><a block-handler-0=\\"click\\">link</a></li>\`); let block3 = createBlock(\`<li><a block-handler-0=\\"click\\">link</a></li>\`);
@@ -82,8 +77,8 @@ exports[`t-on can bind handlers with empty object (with non empty inner string)
let key1 = ctx['action_index']; let key1 = ctx['action_index'];
const v1 = ctx['activate']; const v1 = ctx['activate'];
const v2 = ctx['action']; const v2 = ctx['action'];
let d1 = [()=>v1(v2), ctx]; let hdlr1 = [()=>v1(v2), ctx];
c_block2[i1] = withKey(block3([d1]), key1); c_block2[i1] = withKey(block3([hdlr1]), key1);
} }
let b2 = list(c_block2); let b2 = list(c_block2);
return block1([], [b2]); return block1([], [b2]);
@@ -94,15 +89,14 @@ exports[`t-on can bind handlers with empty object (with non empty inner string)
exports[`t-on can bind handlers with object arguments 1`] = ` exports[`t-on can bind handlers with object arguments 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<button block-handler-0=\\"click\\">Click</button>\`); let block1 = createBlock(\`<button block-handler-0=\\"click\\">Click</button>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const v1 = ctx['add']; const v1 = ctx['add'];
let d1 = [()=>v1({val:5}), ctx]; let hdlr1 = [()=>v1({val:5}), ctx];
return block1([d1]); return block1([hdlr1]);
} }
}" }"
`; `;
@@ -110,17 +104,14 @@ exports[`t-on can bind handlers with object arguments 1`] = `
exports[`t-on can bind two event handlers 1`] = ` exports[`t-on can bind two event handlers 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<button block-handler-0=\\"click\\" block-handler-1=\\"dblclick\\">Click</button>\`); let block1 = createBlock(\`<button block-handler-0=\\"click\\" block-handler-1=\\"dblclick\\">Click</button>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const v1 = ctx['handleClick']; let hdlr1 = [ctx['handleClick'], ctx];
let d1 = [v1, ctx]; let hdlr2 = [ctx['handleDblClick'], ctx];
const v2 = ctx['handleDblClick']; return block1([hdlr1, hdlr2]);
let d2 = [v2, ctx];
return block1([d1, d2]);
} }
}" }"
`; `;
@@ -128,15 +119,13 @@ exports[`t-on can bind two event handlers 1`] = `
exports[`t-on handler is bound to proper owner 1`] = ` exports[`t-on handler is bound to proper owner 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<button block-handler-0=\\"click\\">Click</button>\`); let block1 = createBlock(\`<button block-handler-0=\\"click\\">Click</button>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const v1 = ctx['add']; let hdlr1 = [ctx['add'], ctx];
let d1 = [v1, ctx]; return block1([hdlr1]);
return block1([d1]);
} }
}" }"
`; `;
@@ -144,8 +133,8 @@ exports[`t-on handler is bound to proper owner 1`] = `
exports[`t-on handler is bound to proper owner, part 2 1`] = ` exports[`t-on handler is bound to proper owner, part 2 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { prepareList, withKey } = helpers;
let block2 = createBlock(\`<button block-handler-0=\\"click\\">Click</button>\`); let block2 = createBlock(\`<button block-handler-0=\\"click\\">Click</button>\`);
@@ -155,9 +144,8 @@ exports[`t-on handler is bound to proper owner, part 2 1`] = `
for (let i1 = 0; i1 < l_block1; i1++) { for (let i1 = 0; i1 < l_block1; i1++) {
ctx[\`value\`] = v_block1[i1]; ctx[\`value\`] = v_block1[i1];
let key1 = ctx['value']; let key1 = ctx['value'];
const v1 = ctx['add']; let hdlr1 = [ctx['add'], ctx];
let d1 = [v1, ctx]; c_block1[i1] = withKey(block2([hdlr1]), key1);
c_block1[i1] = withKey(block2([d1]), key1);
} }
return list(c_block1); return list(c_block1);
} }
@@ -167,15 +155,12 @@ exports[`t-on handler is bound to proper owner, part 2 1`] = `
exports[`t-on handler is bound to proper owner, part 3 1`] = ` exports[`t-on handler is bound to proper owner, part 3 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { getTemplate } = helpers;
const callTemplate_1 = getTemplate(\`sub\`);
let block1 = createBlock(\`<button block-handler-0=\\"click\\">Click</button>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const v1 = ctx['add']; return callTemplate_1.call(this, ctx, node, key + \`__1\`);
let d1 = [v1, ctx];
return block1([d1]);
} }
}" }"
`; `;
@@ -183,12 +168,13 @@ exports[`t-on handler is bound to proper owner, part 3 1`] = `
exports[`t-on handler is bound to proper owner, part 3 2`] = ` exports[`t-on handler is bound to proper owner, part 3 2`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
const callTemplate_2 = getTemplate(\`sub\`); let block1 = createBlock(\`<button block-handler-0=\\"click\\">Click</button>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return callTemplate_2.call(this, ctx, node, key + \`__1\`); let hdlr1 = [ctx['add'], ctx];
return block1([hdlr1]);
} }
}" }"
`; `;
@@ -196,25 +182,9 @@ exports[`t-on handler is bound to proper owner, part 3 2`] = `
exports[`t-on handler is bound to proper owner, part 4 1`] = ` exports[`t-on handler is bound to proper owner, part 4 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { prepareList, getTemplate, withKey } = helpers;
const callTemplate_1 = getTemplate(\`sub\`);
let block1 = createBlock(\`<button block-handler-0=\\"click\\">Click</button>\`);
return function template(ctx, node, key = \\"\\") {
const v1 = ctx['add'];
let d1 = [v1, ctx];
return block1([d1]);
}
}"
`;
exports[`t-on handler is bound to proper owner, part 4 2`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
const callTemplate_2 = getTemplate(\`sub\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
ctx = Object.create(ctx); ctx = Object.create(ctx);
@@ -226,25 +196,37 @@ exports[`t-on handler is bound to proper owner, part 4 2`] = `
ctx[\`value_index\`] = i1; ctx[\`value_index\`] = i1;
ctx[\`value_value\`] = k_block1[i1]; ctx[\`value_value\`] = k_block1[i1];
let key1 = ctx['value']; let key1 = ctx['value'];
c_block1[i1] = withKey(callTemplate_2.call(this, ctx, node, key + \`__1__\${key1}\`), key1); c_block1[i1] = withKey(callTemplate_1.call(this, ctx, node, key + \`__1__\${key1}\`), key1);
} }
return list(c_block1); return list(c_block1);
} }
}" }"
`; `;
exports[`t-on handler is bound to proper owner, part 4 2`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let block1 = createBlock(\`<button block-handler-0=\\"click\\">Click</button>\`);
return function template(ctx, node, key = \\"\\") {
let hdlr1 = [ctx['add'], ctx];
return block1([hdlr1]);
}
}"
`;
exports[`t-on receive event in first argument 1`] = ` exports[`t-on receive event in first argument 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<button block-handler-0=\\"click\\">Click</button>\`); let block1 = createBlock(\`<button block-handler-0=\\"click\\">Click</button>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const v1 = ctx['add']; let hdlr1 = [ctx['add'], ctx];
let d1 = [v1, ctx]; return block1([hdlr1]);
return block1([d1]);
} }
}" }"
`; `;
@@ -252,17 +234,14 @@ exports[`t-on receive event in first argument 1`] = `
exports[`t-on t-on modifiers (native listener) basic support for native listener 1`] = ` exports[`t-on t-on modifiers (native listener) basic support for native listener 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div class=\\"myClass\\" block-handler-0=\\"click\\"><button block-handler-1=\\"click\\">Button</button></div>\`); let block1 = createBlock(\`<div class=\\"myClass\\" block-handler-0=\\"click\\"><button block-handler-1=\\"click\\">Button</button></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const v1 = ctx['divClicked']; let hdlr1 = [ctx['divClicked'], ctx];
let d1 = [v1, ctx]; let hdlr2 = [ctx['btnClicked'], ctx];
const v2 = ctx['btnClicked']; return block1([hdlr1, hdlr2]);
let d2 = [v2, ctx];
return block1([d1, d2]);
} }
}" }"
`; `;
@@ -270,16 +249,14 @@ exports[`t-on t-on modifiers (native listener) basic support for native listener
exports[`t-on t-on modifiers (native listener) t-on combined with t-esc 1`] = ` exports[`t-on t-on modifiers (native listener) t-on combined with t-esc 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><button block-handler-0=\\"click\\"><block-text-1/></button></div>\`); let block1 = createBlock(\`<div><button block-handler-0=\\"click\\"><block-text-1/></button></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const v1 = ctx['onClick']; let hdlr1 = [ctx['onClick'], ctx];
let d1 = [v1, ctx]; let txt1 = ctx['text'];
let d2 = ctx['text']; return block1([hdlr1, txt1]);
return block1([d1, d2]);
} }
}" }"
`; `;
@@ -287,16 +264,15 @@ exports[`t-on t-on modifiers (native listener) t-on combined with t-esc 1`] = `
exports[`t-on t-on modifiers (native listener) t-on combined with t-out 1`] = ` exports[`t-on t-on modifiers (native listener) t-on combined with t-out 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { safeOutput } = helpers;
let block1 = createBlock(\`<div><button block-handler-0=\\"click\\"><block-child-0/></button></div>\`); let block1 = createBlock(\`<div><button block-handler-0=\\"click\\"><block-child-0/></button></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const v1 = ctx['onClick']; let hdlr1 = [ctx['onClick'], ctx];
let d1 = [v1, ctx];
let b2 = safeOutput(ctx['html']); let b2 = safeOutput(ctx['html']);
return block1([d1], [b2]); return block1([hdlr1], [b2]);
} }
}" }"
`; `;
@@ -304,17 +280,14 @@ exports[`t-on t-on modifiers (native listener) t-on combined with t-out 1`] = `
exports[`t-on t-on modifiers (native listener) t-on with .capture modifier 1`] = ` exports[`t-on t-on modifiers (native listener) t-on with .capture modifier 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div block-handler-0=\\"click.capture\\"><button block-handler-1=\\"click\\">Button</button></div>\`); let block1 = createBlock(\`<div block-handler-0=\\"click.capture\\"><button block-handler-1=\\"click\\">Button</button></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const v1 = ctx['onCapture']; let hdlr1 = [\\"capture\\", ctx['onCapture'], ctx];
let d1 = [\\"capture\\", v1, ctx]; let hdlr2 = [ctx['doSomething'], ctx];
const v2 = ctx['doSomething']; return block1([hdlr1, hdlr2]);
let d2 = [v2, ctx];
return block1([d1, d2]);
} }
}" }"
`; `;
@@ -322,14 +295,13 @@ exports[`t-on t-on modifiers (native listener) t-on with .capture modifier 1`] =
exports[`t-on t-on modifiers (native listener) t-on with empty handler (only modifiers) 1`] = ` exports[`t-on t-on modifiers (native listener) t-on with empty handler (only modifiers) 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><button block-handler-0=\\"click.prevent\\">Button</button></div>\`); let block1 = createBlock(\`<div><button block-handler-0=\\"click.prevent\\">Button</button></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = [\\"prevent\\", , ctx]; let hdlr1 = [\\"prevent\\", , ctx];
return block1([d1]); return block1([hdlr1]);
} }
}" }"
`; `;
@@ -337,15 +309,13 @@ exports[`t-on t-on modifiers (native listener) t-on with empty handler (only mod
exports[`t-on t-on modifiers (native listener) t-on with prevent and self modifiers (order matters) 1`] = ` exports[`t-on t-on modifiers (native listener) t-on with prevent and self modifiers (order matters) 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><button block-handler-0=\\"click.prevent.self\\"><span>Button</span></button></div>\`); let block1 = createBlock(\`<div><button block-handler-0=\\"click.prevent.self\\"><span>Button</span></button></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const v1 = ctx['onClick']; let hdlr1 = [\\"prevent\\",\\"self\\", ctx['onClick'], ctx];
let d1 = [\\"prevent\\",\\"self\\", v1, ctx]; return block1([hdlr1]);
return block1([d1]);
} }
}" }"
`; `;
@@ -353,19 +323,15 @@ exports[`t-on t-on modifiers (native listener) t-on with prevent and self modifi
exports[`t-on t-on modifiers (native listener) t-on with prevent and/or stop modifiers 1`] = ` exports[`t-on t-on modifiers (native listener) t-on with prevent and/or stop modifiers 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><button block-handler-0=\\"click.prevent\\">Button 1</button><button block-handler-1=\\"click.stop\\">Button 2</button><button block-handler-2=\\"click.prevent.stop\\">Button 3</button></div>\`); let block1 = createBlock(\`<div><button block-handler-0=\\"click.prevent\\">Button 1</button><button block-handler-1=\\"click.stop\\">Button 2</button><button block-handler-2=\\"click.prevent.stop\\">Button 3</button></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const v1 = ctx['onClickPrevented']; let hdlr1 = [\\"prevent\\", ctx['onClickPrevented'], ctx];
let d1 = [\\"prevent\\", v1, ctx]; let hdlr2 = [\\"stop\\", ctx['onClickStopped'], ctx];
const v2 = ctx['onClickStopped']; let hdlr3 = [\\"prevent\\",\\"stop\\", ctx['onClickPreventedAndStopped'], ctx];
let d2 = [\\"stop\\", v2, ctx]; return block1([hdlr1, hdlr2, hdlr3]);
const v3 = ctx['onClickPreventedAndStopped'];
let d3 = [\\"prevent\\",\\"stop\\", v3, ctx];
return block1([d1, d2, d3]);
} }
}" }"
`; `;
@@ -373,8 +339,8 @@ exports[`t-on t-on modifiers (native listener) t-on with prevent and/or stop mod
exports[`t-on t-on modifiers (native listener) t-on with prevent modifier in t-foreach 1`] = ` exports[`t-on t-on modifiers (native listener) t-on with prevent modifier in t-foreach 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { prepareList, withKey } = helpers;
let block1 = createBlock(\`<div><block-child-0/></div>\`); let block1 = createBlock(\`<div><block-child-0/></div>\`);
let block3 = createBlock(\`<a href=\\"#\\" block-handler-0=\\"click.prevent\\"> Edit <block-text-1/></a>\`); let block3 = createBlock(\`<a href=\\"#\\" block-handler-0=\\"click.prevent\\"> Edit <block-text-1/></a>\`);
@@ -387,9 +353,9 @@ exports[`t-on t-on modifiers (native listener) t-on with prevent modifier in t-f
let key1 = ctx['project']; let key1 = ctx['project'];
const v1 = ctx['onEdit']; const v1 = ctx['onEdit'];
const v2 = ctx['project']; const v2 = ctx['project'];
let d1 = [\\"prevent\\", ev=>v1(v2.id,ev), ctx]; let hdlr1 = [\\"prevent\\", ev=>v1(v2.id,ev), ctx];
let d2 = ctx['project'].name; let txt1 = ctx['project'].name;
c_block2[i1] = withKey(block3([d1, d2]), key1); c_block2[i1] = withKey(block3([hdlr1, txt1]), key1);
} }
let b2 = list(c_block2); let b2 = list(c_block2);
return block1([], [b2]); return block1([], [b2]);
@@ -400,15 +366,13 @@ exports[`t-on t-on modifiers (native listener) t-on with prevent modifier in t-f
exports[`t-on t-on modifiers (native listener) t-on with self and prevent modifiers (order matters) 1`] = ` exports[`t-on t-on modifiers (native listener) t-on with self and prevent modifiers (order matters) 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><button block-handler-0=\\"click.self.prevent\\"><span>Button</span></button></div>\`); let block1 = createBlock(\`<div><button block-handler-0=\\"click.self.prevent\\"><span>Button</span></button></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const v1 = ctx['onClick']; let hdlr1 = [\\"self\\",\\"prevent\\", ctx['onClick'], ctx];
let d1 = [\\"self\\",\\"prevent\\", v1, ctx]; return block1([hdlr1]);
return block1([d1]);
} }
}" }"
`; `;
@@ -416,17 +380,14 @@ exports[`t-on t-on modifiers (native listener) t-on with self and prevent modifi
exports[`t-on t-on modifiers (native listener) t-on with self modifier 1`] = ` exports[`t-on t-on modifiers (native listener) t-on with self modifier 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><button block-handler-0=\\"click\\"><span>Button</span></button><button block-handler-1=\\"click.self\\"><span>Button</span></button></div>\`); let block1 = createBlock(\`<div><button block-handler-0=\\"click\\"><span>Button</span></button><button block-handler-1=\\"click.self\\"><span>Button</span></button></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const v1 = ctx['onClick']; let hdlr1 = [ctx['onClick'], ctx];
let d1 = [v1, ctx]; let hdlr2 = [\\"self\\", ctx['onClickSelf'], ctx];
const v2 = ctx['onClickSelf']; return block1([hdlr1, hdlr2]);
let d2 = [\\"self\\", v2, ctx];
return block1([d1, d2]);
} }
}" }"
`; `;
@@ -434,17 +395,14 @@ exports[`t-on t-on modifiers (native listener) t-on with self modifier 1`] = `
exports[`t-on t-on modifiers (synthetic listener) basic support for synthetic 1`] = ` exports[`t-on t-on modifiers (synthetic listener) basic support for synthetic 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div block-handler-0=\\"click.synthetic\\"><button block-handler-1=\\"click.synthetic\\">Button</button></div>\`); let block1 = createBlock(\`<div block-handler-0=\\"click.synthetic\\"><button block-handler-1=\\"click.synthetic\\">Button</button></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const v1 = ctx['divClicked']; let hdlr1 = [\\"synthetic\\", ctx['divClicked'], ctx];
let d1 = [\\"synthetic\\", v1, ctx]; let hdlr2 = [\\"synthetic\\", ctx['btnClicked'], ctx];
const v2 = ctx['btnClicked']; return block1([hdlr1, hdlr2]);
let d2 = [\\"synthetic\\", v2, ctx];
return block1([d1, d2]);
} }
}" }"
`; `;
@@ -452,15 +410,14 @@ exports[`t-on t-on modifiers (synthetic listener) basic support for synthetic 1`
exports[`t-on t-on with inline statement (function call) 1`] = ` exports[`t-on t-on with inline statement (function call) 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<button block-handler-0=\\"click\\">Click</button>\`); let block1 = createBlock(\`<button block-handler-0=\\"click\\">Click</button>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const v1 = ctx['state']; const v1 = ctx['state'];
let d1 = [()=>v1.incrementCounter(2), ctx]; let hdlr1 = [()=>v1.incrementCounter(2), ctx];
return block1([d1]); return block1([hdlr1]);
} }
}" }"
`; `;
@@ -468,15 +425,14 @@ exports[`t-on t-on with inline statement (function call) 1`] = `
exports[`t-on t-on with inline statement 1`] = ` exports[`t-on t-on with inline statement 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<button block-handler-0=\\"click\\">Click</button>\`); let block1 = createBlock(\`<button block-handler-0=\\"click\\">Click</button>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const v1 = ctx['state']; const v1 = ctx['state'];
let d1 = [()=>v1.counter++, ctx]; let hdlr1 = [()=>v1.counter++, ctx];
return block1([d1]); return block1([hdlr1]);
} }
}" }"
`; `;
@@ -484,15 +440,14 @@ exports[`t-on t-on with inline statement 1`] = `
exports[`t-on t-on with inline statement, part 2 1`] = ` exports[`t-on t-on with inline statement, part 2 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<button block-handler-0=\\"click\\">Toggle</button>\`); let block1 = createBlock(\`<button block-handler-0=\\"click\\">Toggle</button>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const v1 = ctx['state']; const v1 = ctx['state'];
let d1 = [()=>v1.flag=!v1.flag, ctx]; let hdlr1 = [()=>v1.flag=!v1.flag, ctx];
return block1([d1]); return block1([hdlr1]);
} }
}" }"
`; `;
@@ -500,16 +455,15 @@ exports[`t-on t-on with inline statement, part 2 1`] = `
exports[`t-on t-on with inline statement, part 3 1`] = ` exports[`t-on t-on with inline statement, part 3 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<button block-handler-0=\\"click\\">Toggle</button>\`); let block1 = createBlock(\`<button block-handler-0=\\"click\\">Toggle</button>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const v1 = ctx['state']; const v1 = ctx['state'];
const v2 = ctx['someFunction']; const v2 = ctx['someFunction'];
let d1 = [()=>v1.n=v2(3), ctx]; let hdlr1 = [()=>v1.n=v2(3), ctx];
return block1([d1]); return block1([hdlr1]);
} }
}" }"
`; `;
@@ -517,15 +471,15 @@ exports[`t-on t-on with inline statement, part 3 1`] = `
exports[`t-on t-on with t-call 1`] = ` exports[`t-on t-on with t-call 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { getTemplate } = helpers;
const callTemplate_1 = getTemplate(\`sub\`);
let block1 = createBlock(\`<p block-handler-0=\\"click\\">lucas</p>\`); let block1 = createBlock(\`<div><block-child-0/></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const v1 = ctx['update']; let b2 = callTemplate_1.call(this, ctx, node, key + \`__1\`);
let d1 = [v1, ctx]; return block1([], [b2]);
return block1([d1]);
} }
}" }"
`; `;
@@ -533,15 +487,13 @@ exports[`t-on t-on with t-call 1`] = `
exports[`t-on t-on with t-call 2`] = ` exports[`t-on t-on with t-call 2`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
const callTemplate_2 = getTemplate(\`sub\`);
let block1 = createBlock(\`<div><block-child-0/></div>\`); let block1 = createBlock(\`<p block-handler-0=\\"click\\">lucas</p>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let b2 = callTemplate_2.call(this, ctx, node, key + \`__1\`); let hdlr1 = [ctx['update'], ctx];
return block1([], [b2]); return block1([hdlr1]);
} }
}" }"
`; `;
@@ -549,15 +501,15 @@ exports[`t-on t-on with t-call 2`] = `
exports[`t-on t-on, with arguments and t-call 1`] = ` exports[`t-on t-on, with arguments and t-call 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { getTemplate } = helpers;
const callTemplate_1 = getTemplate(\`sub\`);
let block1 = createBlock(\`<p block-handler-0=\\"click\\">lucas</p>\`); let block1 = createBlock(\`<div><block-child-0/></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const v1 = ctx['value']; let b2 = callTemplate_1.call(this, ctx, node, key + \`__1\`);
let d1 = [()=>this.update(v1), ctx]; return block1([], [b2]);
return block1([d1]);
} }
}" }"
`; `;
@@ -565,15 +517,14 @@ exports[`t-on t-on, with arguments and t-call 1`] = `
exports[`t-on t-on, with arguments and t-call 2`] = ` exports[`t-on t-on, with arguments and t-call 2`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
const callTemplate_2 = getTemplate(\`sub\`);
let block1 = createBlock(\`<div><block-child-0/></div>\`); let block1 = createBlock(\`<p block-handler-0=\\"click\\">lucas</p>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let b2 = callTemplate_2.call(this, ctx, node, key + \`__1\`); const v1 = ctx['value'];
return block1([], [b2]); let hdlr1 = [()=>this.update(v1), ctx];
return block1([hdlr1]);
} }
}" }"
`; `;
+123 -135
View File
@@ -3,8 +3,8 @@
exports[`misc complex template 1`] = ` exports[`misc complex template 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { prepareList, withKey } = helpers;
let block1 = createBlock(\`<div block-attribute-0=\\"class\\"><div block-attribute-1=\\"class\\"><div class=\\"batch_header\\"><a block-attribute-2=\\"href\\" block-attribute-3=\\"class\\" title=\\"View Batch\\"><block-text-4/><block-child-0/><i class=\\"arrow fa fa-window-maximize\\"/></a></div><block-child-1/><div class=\\"batch_slots\\"><block-child-2/><block-child-3/></div><div class=\\"batch_commits\\"><block-child-4/></div></div></div>\`); let block1 = createBlock(\`<div block-attribute-0=\\"class\\"><div block-attribute-1=\\"class\\"><div class=\\"batch_header\\"><a block-attribute-2=\\"href\\" block-attribute-3=\\"class\\" title=\\"View Batch\\"><block-text-4/><block-child-0/><i class=\\"arrow fa fa-window-maximize\\"/></a></div><block-child-1/><div class=\\"batch_slots\\"><block-child-2/><block-child-3/></div><div class=\\"batch_commits\\"><block-child-4/></div></div></div>\`);
let block2 = createBlock(\`<i class=\\"fa fa-exclamation-triangle\\"/>\`); let block2 = createBlock(\`<i class=\\"fa fa-exclamation-triangle\\"/>\`);
@@ -18,11 +18,11 @@ exports[`misc complex template 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let b2,b3,b4,b6,b8; let b2,b3,b4,b6,b8;
let d1 = \`batch_tile \${ctx['options'].more?'more':'nomore'}\`; let attr1 = \`batch_tile \${ctx['options'].more?'more':'nomore'}\`;
let d2 = \`card bg-\${ctx['klass']}-light\`; let attr2 = \`card bg-\${ctx['klass']}-light\`;
let d3 = \`/runbot/batch/\${ctx['batch'].id}\`; let attr3 = \`/runbot/batch/\${ctx['batch'].id}\`;
let d4 = \`badge badge-\${ctx['batch'].has_warning?'warning':'light'}\`; let attr4 = \`badge badge-\${ctx['batch'].has_warning?'warning':'light'}\`;
let d5 = ctx['batch'].formated_age; let txt1 = ctx['batch'].formated_age;
if (ctx['batch'].has_warning) { if (ctx['batch'].has_warning) {
b2 = block2(); b2 = block2();
} }
@@ -34,7 +34,7 @@ exports[`misc complex template 1`] = `
for (let i1 = 0; i1 < l_block4; i1++) { for (let i1 = 0; i1 < l_block4; i1++) {
ctx[\`slot\`] = v_block4[i1]; ctx[\`slot\`] = v_block4[i1];
let key1 = ctx['slot'].id; let key1 = ctx['slot'].id;
c_block4[i1] = withKey(component(\`SlotButton\`, {class: ctx['slot_container'],slot: ctx['slot']}, key + \`__1__\${key1}\`, node, ctx), key1); c_block4[i1] = withKey(component(\`SlotButton\`, {class: ctx['slot_container'],slot: ctx['slot']}, key+\`__1__\${key1}\`,null, node, ctx), key1);
} }
ctx = ctx.__proto__; ctx = ctx.__proto__;
b4 = list(c_block4); b4 = list(c_block4);
@@ -53,8 +53,8 @@ exports[`misc complex template 1`] = `
ctx[\`commit_link\`] = v_block8[i1]; ctx[\`commit_link\`] = v_block8[i1];
let key1 = ctx['commit_link'].id; let key1 = ctx['commit_link'].id;
let b10,b11,b12,b13; let b10,b11,b12,b13;
let d6 = \`/runbot/commit/\${ctx['commit_link'].commit_id}\`; let attr5 = \`/runbot/commit/\${ctx['commit_link'].commit_id}\`;
let d7 = \`badge badge-light batch_commit match_type_\${ctx['commit_link'].match_type}\`; let attr6 = \`badge badge-light batch_commit match_type_\${ctx['commit_link'].match_type}\`;
if (ctx['commit_link'].match_type=='new') { if (ctx['commit_link'].match_type=='new') {
b10 = block10(); b10 = block10();
} }
@@ -67,13 +67,13 @@ exports[`misc complex template 1`] = `
if (ctx['commit_link'].match_type=='base_head') { if (ctx['commit_link'].match_type=='base_head') {
b13 = block13(); b13 = block13();
} }
let d8 = ctx['commit_link'].commit_dname; let txt2 = ctx['commit_link'].commit_dname;
let d9 = 'https://%s/commit/%s'%(ctx['commit_link'].commit_remote_url,ctx['commit_link'].commit_name); let attr7 = 'https://%s/commit/%s'%(ctx['commit_link'].commit_remote_url,ctx['commit_link'].commit_name);
let d10 = ctx['commit_link'].commit_subject; let txt3 = ctx['commit_link'].commit_subject;
c_block8[i1] = withKey(block9([d6, d7, d8, d9, d10], [b10, b11, b12, b13]), key1); c_block8[i1] = withKey(block9([attr5, attr6, txt2, attr7, txt3], [b10, b11, b12, b13]), key1);
} }
b8 = list(c_block8); b8 = list(c_block8);
return block1([d1, d2, d3, d4, d5], [b2, b3, b4, b6, b8]); return block1([attr1, attr2, attr3, attr4, txt1], [b2, b3, b4, b6, b8]);
} }
}" }"
`; `;
@@ -81,60 +81,13 @@ exports[`misc complex template 1`] = `
exports[`misc global 1`] = ` exports[`misc global 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { prepareList, isBoundary, withDefault, setContextValue, getTemplate, zero, withKey } = helpers;
const callTemplate_1 = getTemplate(\`_callee-uses-foo\`);
let block1 = createBlock(\`<año block-attribute-0=\\"falló\\"><block-child-0/></año>\`);
return function template(ctx, node, key = \\"\\") {
let d1 = 'agüero';
let b2 = ctx[zero];
return block1([d1], [b2]);
}
}"
`;
exports[`misc global 2`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<span><block-text-0/></span>\`);
return function template(ctx, node, key = \\"\\") {
let d1 = withDefault(ctx['foo'], \`foo default\`);
return block1([d1]);
}
}"
`;
exports[`misc global 3`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><block-child-0/></div>\`);
return function template(ctx, node, key = \\"\\") {
let b3 = text(\`toto default\`);
let b2 = withDefault(safeOutput(ctx['toto']), b3);
return block1([], [b2]);
}
}"
`;
exports[`misc global 4`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
const callTemplate_2 = getTemplate(\`_callee-uses-foo\`); const callTemplate_2 = getTemplate(\`_callee-uses-foo\`);
const callTemplate_4 = getTemplate(\`_callee-uses-foo\`); const callTemplate_3 = getTemplate(\`_callee-uses-foo\`);
const callTemplate_6 = getTemplate(\`_callee-uses-foo\`); const callTemplate_4 = getTemplate(\`_callee-asc\`);
const callTemplate_8 = getTemplate(\`_callee-asc\`); const callTemplate_5 = getTemplate(\`_callee-asc-toto\`);
const callTemplate_10 = getTemplate(\`_callee-asc-toto\`);
let block1 = createBlock(\`<div><block-child-0/><block-child-1/></div>\`); let block1 = createBlock(\`<div><block-child-0/><block-child-1/></div>\`);
let block4 = createBlock(\`<span><block-text-0/></span>\`); let block4 = createBlock(\`<span><block-text-0/></span>\`);
@@ -151,38 +104,85 @@ exports[`misc global 4`] = `
ctx[\`value_index\`] = i1; ctx[\`value_index\`] = i1;
ctx[\`value_value\`] = k_block2[i1]; ctx[\`value_value\`] = k_block2[i1];
let key1 = ctx['value']; let key1 = ctx['value'];
let d1 = ctx['value']; let txt1 = ctx['value'];
let b4 = block4([d1]); let b4 = block4([txt1]);
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;
setContextValue(ctx, \\"foo\\", 'aaa'); setContextValue(ctx, \\"foo\\", 'aaa');
let b6 = callTemplate_2.call(this, ctx, node, key + \`__1__\${key1}\`); let b6 = callTemplate_1.call(this, ctx, node, key + \`__1__\${key1}\`);
ctx = ctx.__proto__; ctx = ctx.__proto__;
let b7 = callTemplate_4.call(this, ctx, node, key + \`__3__\${key1}\`); let b7 = callTemplate_2.call(this, ctx, node, key + \`__2__\${key1}\`);
setContextValue(ctx, \\"foo\\", 'bbb'); setContextValue(ctx, \\"foo\\", 'bbb');
let b8 = callTemplate_6.call(this, ctx, node, key + \`__5__\${key1}\`); let b8 = callTemplate_3.call(this, ctx, node, key + \`__3__\${key1}\`);
let b5 = multi([b6, b7, b8]); let b5 = multi([b6, b7, b8]);
ctx[zero] = b5; ctx[zero] = b5;
let b9 = callTemplate_8.call(this, ctx, node, key + \`__7__\${key1}\`); let b9 = 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, b9]), key1);
} }
ctx = ctx.__proto__; ctx = ctx.__proto__;
let b2 = list(c_block2); let b2 = list(c_block2);
let b10 = callTemplate_10.call(this, ctx, node, key + \`__9\`); let b10 = callTemplate_5.call(this, ctx, node, key + \`__5\`);
return block1([], [b2, b10]); return block1([], [b2, b10]);
} }
}" }"
`; `;
exports[`misc global 2`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault } = helpers;
let block1 = createBlock(\`<span><block-text-0/></span>\`);
return function template(ctx, node, key = \\"\\") {
let txt1 = withDefault(ctx['foo'], \`foo default\`);
return block1([txt1]);
}
}"
`;
exports[`misc global 3`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { zero } = helpers;
let block1 = createBlock(\`<año block-attribute-0=\\"falló\\"><block-child-0/></año>\`);
return function template(ctx, node, key = \\"\\") {
let attr1 = 'agüero';
let b2 = ctx[zero];
return block1([attr1], [b2]);
}
}"
`;
exports[`misc global 4`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { safeOutput, withDefault } = helpers;
let block1 = createBlock(\`<div><block-child-0/></div>\`);
return function template(ctx, node, key = \\"\\") {
let b3 = text(\`toto default\`);
let b2 = withDefault(safeOutput(ctx['toto']), b3);
return block1([], [b2]);
}
}"
`;
exports[`misc other complex template 1`] = ` exports[`misc other complex template 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { prepareList, withKey, getTemplate } = helpers;
const callTemplate_14 = getTemplate(\`LOAD_INFOS_TEMPLATE\`); const callTemplate_1 = getTemplate(\`LOAD_INFOS_TEMPLATE\`);
let block1 = createBlock(\`<div><header><nav class=\\"navbar navbar-expand-md navbar-light bg-light\\"><a block-attribute-0=\\"href\\"><b style=\\"color:#777;\\"><block-text-1/></b></a><button type=\\"button\\" class=\\"navbar-toggler\\" data-toggle=\\"collapse\\" data-target=\\"#top_menu_collapse\\"><span class=\\"navbar-toggler-icon\\"/></button><div class=\\"collapse navbar-collapse\\" id=\\"top_menu_collapse\\" aria-expanded=\\"false\\"><ul class=\\"nav navbar-nav ml-auto text-right\\" id=\\"top_menu\\"><block-child-0/><li class=\\"nav-item divider\\"/><block-child-1/></ul><div><div class=\\"input-group input-group-sm\\"><div class=\\"input-group-prepend input-group-sm\\"><button class=\\"btn btn-default fa fa-cog\\" title=\\"Settings\\" block-handler-2=\\"click\\"/><button class=\\"btn btn-default\\" block-handler-3=\\"click\\"> More </button><block-child-2/></div><input class=\\"form-control\\" type=\\"text\\" placeholder=\\"Search\\" aria-label=\\"Search\\" name=\\"search\\" block-attribute-4=\\"value\\" block-handler-5=\\"keyup\\" block-handler-6=\\"change\\" block-ref=\\"7\\"/><div class=\\"input-group-append\\"><button class=\\"btn btn-default fa fa-eraser\\" block-handler-8=\\"click\\"/></div></div></div></div></nav></header><div class=\\"container-fluid\\" block-ref=\\"9\\"><div class=\\"row\\"><!--div class=\\"form-group col-md-6\\"> let block1 = createBlock(\`<div><header><nav class=\\"navbar navbar-expand-md navbar-light bg-light\\"><a block-attribute-0=\\"href\\"><b style=\\"color:#777;\\"><block-text-1/></b></a><button type=\\"button\\" class=\\"navbar-toggler\\" data-toggle=\\"collapse\\" data-target=\\"#top_menu_collapse\\"><span class=\\"navbar-toggler-icon\\"/></button><div class=\\"collapse navbar-collapse\\" id=\\"top_menu_collapse\\" aria-expanded=\\"false\\"><ul class=\\"nav navbar-nav ml-auto text-right\\" id=\\"top_menu\\"><block-child-0/><li class=\\"nav-item divider\\"/><block-child-1/></ul><div><div class=\\"input-group input-group-sm\\"><div class=\\"input-group-prepend input-group-sm\\"><button class=\\"btn btn-default fa fa-cog\\" title=\\"Settings\\" block-handler-2=\\"click\\"/><button class=\\"btn btn-default\\" block-handler-3=\\"click\\"> More </button><block-child-2/></div><input class=\\"form-control\\" type=\\"text\\" placeholder=\\"Search\\" aria-label=\\"Search\\" name=\\"search\\" block-attribute-4=\\"value\\" block-handler-5=\\"keyup\\" block-handler-6=\\"change\\" block-ref=\\"7\\"/><div class=\\"input-group-append\\"><button class=\\"btn btn-default fa fa-eraser\\" block-handler-8=\\"click\\"/></div></div></div></div></nav></header><div class=\\"container-fluid\\" block-ref=\\"9\\"><div class=\\"row\\"><!--div class=\\"form-group col-md-6\\">
<h5>Search options</h5> <h5>Search options</h5>
@@ -215,33 +215,33 @@ exports[`misc other complex template 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const refs = ctx.__owl__.refs; const refs = ctx.__owl__.refs;
const ref1 = (el) => refs[\`search_input\`] = el;
const ref2 = (el) => refs[\`settings_menu\`] = el;
let b2,b4,b14,b17,b22,b23,b24,b25; let b2,b4,b14,b17,b22,b23,b24,b25;
let d1 = \`/runbot/\${ctx['project'].slug}\`; let attr1 = \`/runbot/\${ctx['project'].slug}\`;
let d2 = ctx['project'].name; let txt1 = ctx['project'].name;
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\`] = v_block2[i1];
let key1 = ctx['project'].id; let key1 = ctx['project'].id;
const v1 = ctx['selectProject']; let hdlr1 = [ctx['selectProject'](ctx['project']), ctx];
const v2 = ctx['project']; let txt2 = ctx['project'].name;
let d3 = [v1(v2), ctx]; c_block2[i1] = withKey(block3([hdlr1, txt2]), key1);
let d4 = ctx['project'].name;
c_block2[i1] = withKey(block3([d3, d4]), key1);
} }
ctx = ctx.__proto__; ctx = ctx.__proto__;
b2 = list(c_block2); b2 = list(c_block2);
if (ctx['user']) { if (ctx['user']) {
let b5,b6; let b5,b6;
if (ctx['user'].public) { if (ctx['user'].public) {
let d5 = \`/web/login?redirect=/\`; let attr2 = \`/web/login?redirect=/\`;
b5 = block5([d5]); b5 = block5([attr2]);
} else { } else {
let b7,b10,b13; let b7,b10,b13;
if (ctx['nb_assigned_errors']&&ctx['nb_assigned_errors']>0) { if (ctx['nb_assigned_errors']&&ctx['nb_assigned_errors']>0) {
let d6 = \`You have \${ctx['nb_assigned_errors']} random bug assigned\`; let attr3 = \`You have \${ctx['nb_assigned_errors']} random bug assigned\`;
let d7 = ctx['nb_assigned_errors']; let txt3 = ctx['nb_assigned_errors'];
let b8 = block8([d6, d7]); let b8 = block8([attr3, txt3]);
let b9 = block9(); let b9 = block9();
b7 = multi([b8, b9]); b7 = multi([b8, b9]);
} else if (ctx['nb_build_errors']&&ctx['nb_build_errors']>0) { } else if (ctx['nb_build_errors']&&ctx['nb_build_errors']>0) {
@@ -249,42 +249,35 @@ exports[`misc other complex template 1`] = `
let b12 = block12(); let b12 = block12();
b10 = multi([b11, b12]); b10 = multi([b11, b12]);
} }
let d8 = ctx['user'].name.length>25?ctx['user'].namesubstring(0,23)+'...':ctx['user'].name; let txt4 = ctx['user'].name.length>25?ctx['user'].namesubstring(0,23)+'...':ctx['user'].name;
let d9 = \`/web/session/logout?redirect=/\`; let attr4 = \`/web/session/logout?redirect=/\`;
let d10 = \`/web\`; let attr5 = \`/web\`;
b13 = block13([d8, d9, d10]); b13 = block13([txt4, attr4, attr5]);
b6 = multi([b7, b10, b13]); b6 = multi([b7, b10, b13]);
} }
b4 = multi([b5, b6]); b4 = multi([b5, b6]);
} }
const v3 = ctx['toggleSettingsMenu']; let hdlr2 = [ctx['toggleSettingsMenu'], ctx];
let d11 = [v3, ctx]; let hdlr3 = [ctx['toggleMore'], ctx];
const v4 = ctx['toggleMore'];
let d12 = [v4, ctx];
if (ctx['categories']&&ctx['categories'].length>1) { if (ctx['categories']&&ctx['categories'].length>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\`] = v_block15[i1];
let key1 = ctx['category'].id; let key1 = ctx['category'].id;
let d13 = ctx['category'].id; let attr6 = ctx['category'].id;
let d14 = ctx['category'].id==ctx['options'].active_category_id; let attr7 = ctx['category'].id==ctx['options'].active_category_id;
let d15 = ctx['category'].name; let txt5 = ctx['category'].name;
c_block15[i1] = withKey(block16([d13, d14, d15]), key1); c_block15[i1] = withKey(block16([attr6, attr7, txt5]), key1);
} }
ctx = ctx.__proto__; ctx = ctx.__proto__;
let b15 = list(c_block15); let b15 = list(c_block15);
b14 = block14([], [b15]); b14 = block14([], [b15]);
} }
let d16 = ctx['search'].value; let attr8 = ctx['search'].value;
const v5 = ctx['updateFilter']; let hdlr4 = [ctx['updateFilter'], ctx];
let d17 = [v5, ctx]; let hdlr5 = [ctx['updateFilter'], ctx];
const v6 = ctx['updateFilter']; let hdlr6 = [ctx['clearSearch'], ctx];
let d18 = [v6, ctx];
let d19 = (el) => refs[\`search_input\`] = el;
const v7 = ctx['clearSearch'];
let d20 = [v7, ctx];
let d21 = (el) => refs[\`settings_menu\`] = el;
if (ctx['triggers']) { if (ctx['triggers']) {
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']);
@@ -293,46 +286,41 @@ exports[`misc other complex template 1`] = `
let key1 = ctx['trigger'].id; let 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) {
let d22 = \`trigger_\${ctx['trigger'].id}\`; let attr9 = \`trigger_\${ctx['trigger'].id}\`;
let d23 = \`trigger_\${ctx['trigger'].id}\`; let attr10 = \`trigger_\${ctx['trigger'].id}\`;
let d24 = ctx['options'].trigger_display[ctx['trigger'].id]; let attr11 = ctx['options'].trigger_display[ctx['trigger'].id];
let d25 = ctx['trigger'].id; let attr12 = ctx['trigger'].id;
const v8 = ctx['updateTriggerDisplay']; let hdlr7 = [ctx['updateTriggerDisplay'], ctx];
let d26 = [v8, ctx]; let attr13 = \`trigger_\${ctx['trigger'].id}\`;
let d27 = \`trigger_\${ctx['trigger'].id}\`; let txt6 = ctx['trigger'].name;
let d28 = ctx['trigger'].name; b20 = block20([attr9, attr10, attr11, attr12, hdlr7, attr13, txt6]);
b20 = block20([d22, d23, d24, d25, d26, d27, d28]);
} }
c_block18[i1] = withKey(multi([b20]), key1); c_block18[i1] = withKey(multi([b20]), key1);
} }
ctx = ctx.__proto__; ctx = ctx.__proto__;
let b18 = list(c_block18); let b18 = list(c_block18);
const v9 = ctx['triggerAll']; let hdlr8 = [ctx['triggerAll'], ctx];
let d29 = [v9, ctx]; let hdlr9 = [ctx['triggerNone'], ctx];
const v10 = ctx['triggerNone']; let hdlr10 = [ctx['triggerDefault'], ctx];
let d30 = [v10, ctx]; let hdlr11 = [ctx['toggleSettingsMenu'], ctx];
const v11 = ctx['triggerDefault']; let b21 = block21([hdlr8, hdlr9, hdlr10, hdlr11]);
let d31 = [v11, ctx];
const v12 = ctx['toggleSettingsMenu'];
let d32 = [v12, ctx];
let b21 = block21([d29, d30, d31, d32]);
b17 = multi([b18, b21]); b17 = multi([b18, b21]);
} }
if (ctx['load_infos']) { if (ctx['load_infos']) {
b22 = callTemplate_14.call(this, ctx, node, key + \`__13\`); b22 = callTemplate_1.call(this, ctx, node, key + \`__1\`);
} }
if (ctx['message']) { if (ctx['message']) {
let d33 = ctx['message']; let txt7 = ctx['message'];
b23 = block23([d33]); b23 = block23([txt7]);
} }
if (!ctx['project']) { if (!ctx['project']) {
b24 = block24(); b24 = block24();
} else { } else {
let b26 = component(\`BundlesList\`, {bundles: ctx['bundles'].sticky,category_custom_views: ctx['category_custom_views'],search: ctx['search']}, key + \`__15\`, node, ctx); let b26 = component(\`BundlesList\`, {bundles: ctx['bundles'].sticky,category_custom_views: ctx['category_custom_views'],search: ctx['search']}, key+\`__2\`,null, node, ctx);
let b27 = component(\`BundlesList\`, {bundles: ctx['bundles'].dev,search: ctx['search']}, key + \`__16\`, node, ctx); let b27 = component(\`BundlesList\`, {bundles: ctx['bundles'].dev,search: ctx['search']}, key+\`__3\`,null, node, ctx);
b25 = block25([], [b26, b27]); b25 = block25([], [b26, b27]);
} }
return block1([d1, d2, d11, d12, d16, d17, d18, d19, d20, d21], [b2, b4, b14, b17, b22, b23, b24, b25]); return block1([attr1, txt1, hdlr2, hdlr3, attr8, hdlr4, hdlr5, ref1, hdlr6, ref2], [b2, b4, b14, b17, b22, b23, b24, b25]);
} }
}" }"
`; `;
@@ -3,8 +3,8 @@
exports[`memory t-foreach does not leak stuff in global scope 1`] = ` exports[`memory t-foreach does not leak stuff in global scope 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { prepareList, withKey } = helpers;
let block1 = createBlock(\`<p><block-child-0/></p>\`); let block1 = createBlock(\`<p><block-child-0/></p>\`);
@@ -3,8 +3,7 @@
exports[`simple templates, mostly static can render a table row 1`] = ` exports[`simple templates, mostly static can render a table row 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<tr><td>cell</td></tr>\`); let block1 = createBlock(\`<tr><td>cell</td></tr>\`);
@@ -17,8 +16,7 @@ exports[`simple templates, mostly static can render a table row 1`] = `
exports[`simple templates, mostly static div with a class attribute 1`] = ` exports[`simple templates, mostly static div with a class attribute 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div class=\\"abc\\">foo</div>\`); let block1 = createBlock(\`<div class=\\"abc\\">foo</div>\`);
@@ -31,8 +29,7 @@ exports[`simple templates, mostly static div with a class attribute 1`] = `
exports[`simple templates, mostly static div with a class attribute with a quote 1`] = ` exports[`simple templates, mostly static div with a class attribute with a quote 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div class=\\"a'bc\\">word</div>\`); let block1 = createBlock(\`<div class=\\"a'bc\\">word</div>\`);
@@ -45,8 +42,7 @@ exports[`simple templates, mostly static div with a class attribute with a quote
exports[`simple templates, mostly static div with a span child node 1`] = ` exports[`simple templates, mostly static div with a span child node 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><span>word</span></div>\`); let block1 = createBlock(\`<div><span>word</span></div>\`);
@@ -59,8 +55,7 @@ exports[`simple templates, mostly static div with a span child node 1`] = `
exports[`simple templates, mostly static div with an arbitrary attribute with a quote 1`] = ` exports[`simple templates, mostly static div with an arbitrary attribute with a quote 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div abc=\\"a'bc\\">word</div>\`); let block1 = createBlock(\`<div abc=\\"a'bc\\">word</div>\`);
@@ -73,8 +68,7 @@ exports[`simple templates, mostly static div with an arbitrary attribute with a
exports[`simple templates, mostly static div with an empty class attribute 1`] = ` exports[`simple templates, mostly static div with an empty class attribute 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div>word</div>\`); let block1 = createBlock(\`<div>word</div>\`);
@@ -87,8 +81,7 @@ exports[`simple templates, mostly static div with an empty class attribute 1`] =
exports[`simple templates, mostly static div with content 1`] = ` exports[`simple templates, mostly static div with content 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div>foo</div>\`); let block1 = createBlock(\`<div>foo</div>\`);
@@ -101,14 +94,13 @@ exports[`simple templates, mostly static div with content 1`] = `
exports[`simple templates, mostly static dom node with t-esc 1`] = ` exports[`simple templates, mostly static dom node with t-esc 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><block-text-0/></div>\`); let block1 = createBlock(\`<div><block-text-0/></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = ctx['text']; let txt1 = ctx['text'];
return block1([d1]); return block1([txt1]);
} }
}" }"
`; `;
@@ -116,14 +108,13 @@ exports[`simple templates, mostly static dom node with t-esc 1`] = `
exports[`simple templates, mostly static dom node with t-esc 2`] = ` exports[`simple templates, mostly static dom node with t-esc 2`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><block-text-0/></div>\`); let block1 = createBlock(\`<div><block-text-0/></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = ctx['text']; let txt1 = ctx['text'];
return block1([d1]); return block1([txt1]);
} }
}" }"
`; `;
@@ -131,8 +122,7 @@ exports[`simple templates, mostly static dom node with t-esc 2`] = `
exports[`simple templates, mostly static dynamic text value 1`] = ` exports[`simple templates, mostly static dynamic text value 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return text(ctx['text']); return text(ctx['text']);
@@ -143,8 +133,7 @@ exports[`simple templates, mostly static dynamic text value 1`] = `
exports[`simple templates, mostly static empty div 1`] = ` exports[`simple templates, mostly static empty div 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div/>\`); let block1 = createBlock(\`<div/>\`);
@@ -157,8 +146,7 @@ exports[`simple templates, mostly static empty div 1`] = `
exports[`simple templates, mostly static empty string 1`] = ` exports[`simple templates, mostly static empty string 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return text(\`\`); return text(\`\`);
@@ -169,8 +157,7 @@ exports[`simple templates, mostly static empty string 1`] = `
exports[`simple templates, mostly static empty string in a template set 1`] = ` exports[`simple templates, mostly static empty string in a template set 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return text(\`\`); return text(\`\`);
@@ -181,8 +168,7 @@ exports[`simple templates, mostly static empty string in a template set 1`] = `
exports[`simple templates, mostly static inline template string in t-esc 1`] = ` exports[`simple templates, mostly static inline template string in t-esc 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return text(\`text\`); return text(\`text\`);
@@ -193,8 +179,8 @@ exports[`simple templates, mostly static inline template string in t-esc 1`] = `
exports[`simple templates, mostly static inline template string with content in t-esc 1`] = ` exports[`simple templates, mostly static inline template string with content in t-esc 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { isBoundary, withDefault, setContextValue } = helpers;
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
ctx = Object.create(ctx); ctx = Object.create(ctx);
@@ -208,8 +194,7 @@ exports[`simple templates, mostly static inline template string with content in
exports[`simple templates, mostly static inline template string with variable in context 1`] = ` exports[`simple templates, mostly static inline template string with variable in context 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return text(\`text \${ctx['v']}\`); return text(\`text \${ctx['v']}\`);
@@ -220,8 +205,7 @@ exports[`simple templates, mostly static inline template string with variable in
exports[`simple templates, mostly static multiple root nodes 1`] = ` exports[`simple templates, mostly static multiple root nodes 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block2 = createBlock(\`<div>foo</div>\`); let block2 = createBlock(\`<div>foo</div>\`);
let block3 = createBlock(\`<span>hey</span>\`); let block3 = createBlock(\`<span>hey</span>\`);
@@ -237,8 +221,7 @@ exports[`simple templates, mostly static multiple root nodes 1`] = `
exports[`simple templates, mostly static simple string 1`] = ` exports[`simple templates, mostly static simple string 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return text(\`hello vdom\`); return text(\`hello vdom\`);
@@ -249,8 +232,7 @@ exports[`simple templates, mostly static simple string 1`] = `
exports[`simple templates, mostly static simple string in t tag 1`] = ` exports[`simple templates, mostly static simple string in t tag 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return text(\`hello vdom\`); return text(\`hello vdom\`);
@@ -261,8 +243,7 @@ exports[`simple templates, mostly static simple string in t tag 1`] = `
exports[`simple templates, mostly static static text and dynamic text (no t tag) 1`] = ` exports[`simple templates, mostly static static text and dynamic text (no t tag) 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let b2 = text(\`hello \`); let b2 = text(\`hello \`);
@@ -275,8 +256,7 @@ exports[`simple templates, mostly static static text and dynamic text (no t tag)
exports[`simple templates, mostly static static text and dynamic text 1`] = ` exports[`simple templates, mostly static static text and dynamic text 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let b2 = text(\`hello \`); let b2 = text(\`hello \`);
@@ -289,14 +269,13 @@ exports[`simple templates, mostly static static text and dynamic text 1`] = `
exports[`simple templates, mostly static t-esc in dom node 1`] = ` exports[`simple templates, mostly static t-esc in dom node 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><block-text-0/></div>\`); let block1 = createBlock(\`<div><block-text-0/></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = ctx['text']; let txt1 = ctx['text'];
return block1([d1]); return block1([txt1]);
} }
}" }"
`; `;
@@ -304,14 +283,13 @@ exports[`simple templates, mostly static t-esc in dom node 1`] = `
exports[`simple templates, mostly static t-esc in dom node, variations 1`] = ` exports[`simple templates, mostly static t-esc in dom node, variations 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div>hello <block-text-0/></div>\`); let block1 = createBlock(\`<div>hello <block-text-0/></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = ctx['text']; let txt1 = ctx['text'];
return block1([d1]); return block1([txt1]);
} }
}" }"
`; `;
@@ -319,14 +297,46 @@ exports[`simple templates, mostly static t-esc in dom node, variations 1`] = `
exports[`simple templates, mostly static t-esc in dom node, variations 2`] = ` exports[`simple templates, mostly static t-esc in dom node, variations 2`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div>hello <block-text-0/> world</div>\`); let block1 = createBlock(\`<div>hello <block-text-0/> world</div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = ctx['text']; let txt1 = ctx['text'];
return block1([d1]); return block1([txt1]);
}
}"
`;
exports[`simple templates, mostly static template with multiple t tag with multiple content 1`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let block1 = createBlock(\`<div><block-text-0/><block-text-1/>Loading<block-text-2/></div>\`);
return function template(ctx, node, key = \\"\\") {
let txt1 = ctx['a'];
let txt2 = ctx['b'];
let txt3 = ctx['c'];
return block1([txt1, txt2, txt3]);
}
}"
`;
exports[`simple templates, mostly static template with t tag with multiple content 1`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let block1 = createBlock(\`<div>Loading<block-child-0/></div>\`);
return function template(ctx, node, key = \\"\\") {
let b2;
if (false) {
b2 = text(\`\`);
}
return block1([], [b2]);
} }
}" }"
`; `;
@@ -334,8 +344,7 @@ exports[`simple templates, mostly static t-esc in dom node, variations 2`] = `
exports[`simple templates, mostly static two t-escs next to each other 1`] = ` exports[`simple templates, mostly static two t-escs next to each other 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let b2 = text(ctx['text1']); let b2 = text(ctx['text1']);
@@ -348,8 +357,7 @@ exports[`simple templates, mostly static two t-escs next to each other 1`] = `
exports[`simple templates, mostly static two t-escs next to each other 2`] = ` exports[`simple templates, mostly static two t-escs next to each other 2`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let b2 = text(ctx['text1']); let b2 = text(ctx['text1']);
@@ -362,15 +370,14 @@ exports[`simple templates, mostly static two t-escs next to each other 2`] = `
exports[`simple templates, mostly static two t-escs next to each other, in a div 1`] = ` exports[`simple templates, mostly static two t-escs next to each other, in a div 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><block-text-0/><block-text-1/></div>\`); let block1 = createBlock(\`<div><block-text-0/><block-text-1/></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = ctx['text1']; let txt1 = ctx['text1'];
let d2 = ctx['text2']; let txt2 = ctx['text2'];
return block1([d1, d2]); return block1([txt1, txt2]);
} }
}" }"
`; `;
@@ -0,0 +1,53 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`properly support svg add proper namespace to g tags 1`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, 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>\`);
return function template(ctx, node, key = \\"\\") {
return block1();
}
}"
`;
exports[`properly support svg add proper namespace to svg 1`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, 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>\`);
return function template(ctx, node, key = \\"\\") {
return block1();
}
}"
`;
exports[`properly support svg namespace to g tags not added if already in svg namespace 1`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let block1 = createBlock(\`<svg block-ns=\\"http://www.w3.org/2000/svg\\"><g/></svg>\`);
return function template(ctx, node, key = \\"\\") {
return block1();
}
}"
`;
exports[`properly support svg namespace to svg tags added even if already in svg namespace 1`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let block1 = createBlock(\`<svg block-ns=\\"http://www.w3.org/2000/svg\\"><svg block-ns=\\"http://www.w3.org/2000/svg\\"/></svg>\`);
return function template(ctx, node, key = \\"\\") {
return block1();
}
}"
`;
File diff suppressed because it is too large Load Diff
@@ -3,8 +3,7 @@
exports[`debugging t-debug 1`] = ` exports[`debugging t-debug 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><block-child-0/></div>\`); let block1 = createBlock(\`<div><block-child-0/></div>\`);
let block2 = createBlock(\`<span>hey</span>\`); let block2 = createBlock(\`<span>hey</span>\`);
@@ -24,8 +23,7 @@ exports[`debugging t-debug 1`] = `
exports[`debugging t-debug on sub template 1`] = ` exports[`debugging t-debug on sub template 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<p>coucou</p>\`); let block1 = createBlock(\`<p>coucou</p>\`);
@@ -39,14 +37,14 @@ exports[`debugging t-debug on sub template 1`] = `
exports[`debugging t-debug on sub template 2`] = ` exports[`debugging t-debug on sub template 2`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { getTemplate } = helpers;
const callTemplate_2 = getTemplate(\`sub\`); const callTemplate_1 = getTemplate(\`sub\`);
let block1 = createBlock(\`<div><block-child-0/></div>\`); let block1 = createBlock(\`<div><block-child-0/></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let b2 = callTemplate_2.call(this, ctx, node, key + \`__1\`); let b2 = callTemplate_1.call(this, ctx, node, key + \`__1\`);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -55,8 +53,8 @@ exports[`debugging t-debug on sub template 2`] = `
exports[`debugging t-log 1`] = ` exports[`debugging t-log 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { isBoundary, withDefault, setContextValue } = helpers;
let block1 = createBlock(\`<div/>\`); let block1 = createBlock(\`<div/>\`);
+59 -63
View File
@@ -3,18 +3,17 @@
exports[`t-esc div with falsy values 1`] = ` exports[`t-esc div with falsy values 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><p><block-text-0/></p><p><block-text-1/></p><p><block-text-2/></p><p><block-text-3/></p><p><block-text-4/></p></div>\`); let block1 = createBlock(\`<div><p><block-text-0/></p><p><block-text-1/></p><p><block-text-2/></p><p><block-text-3/></p><p><block-text-4/></p></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = ctx['v1']; let txt1 = ctx['v1'];
let d2 = ctx['v2']; let txt2 = ctx['v2'];
let d3 = ctx['v3']; let txt3 = ctx['v3'];
let d4 = ctx['v4']; let txt4 = ctx['v4'];
let d5 = ctx['v5']; let txt5 = ctx['v5'];
return block1([d1, d2, d3, d4, d5]); return block1([txt1, txt2, txt3, txt4, txt5]);
} }
}" }"
`; `;
@@ -22,14 +21,13 @@ exports[`t-esc div with falsy values 1`] = `
exports[`t-esc escaping 1`] = ` exports[`t-esc escaping 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<span><block-text-0/></span>\`); let block1 = createBlock(\`<span><block-text-0/></span>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = ctx['var']; let txt1 = ctx['var'];
return block1([d1]); return block1([txt1]);
} }
}" }"
`; `;
@@ -37,14 +35,13 @@ exports[`t-esc escaping 1`] = `
exports[`t-esc escaping on a node 1`] = ` exports[`t-esc escaping on a node 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<span><block-text-0/></span>\`); let block1 = createBlock(\`<span><block-text-0/></span>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = 'ok'; let txt1 = 'ok';
return block1([d1]); return block1([txt1]);
} }
}" }"
`; `;
@@ -52,14 +49,14 @@ exports[`t-esc escaping on a node 1`] = `
exports[`t-esc escaping on a node with a body 1`] = ` exports[`t-esc escaping on a node with a body 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { withDefault } = helpers;
let block1 = createBlock(\`<span><block-text-0/></span>\`); let block1 = createBlock(\`<span><block-text-0/></span>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = withDefault('ok', \`nope\`); let txt1 = withDefault('ok', \`nope\`);
return block1([d1]); return block1([txt1]);
} }
}" }"
`; `;
@@ -67,14 +64,14 @@ exports[`t-esc escaping on a node with a body 1`] = `
exports[`t-esc escaping on a node with a body, as a default 1`] = ` exports[`t-esc escaping on a node with a body, as a default 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { withDefault } = helpers;
let block1 = createBlock(\`<span><block-text-0/></span>\`); let block1 = createBlock(\`<span><block-text-0/></span>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = withDefault(ctx['var'], \`nope\`); let txt1 = withDefault(ctx['var'], \`nope\`);
return block1([d1]); return block1([txt1]);
} }
}" }"
`; `;
@@ -82,8 +79,7 @@ exports[`t-esc escaping on a node with a body, as a default 1`] = `
exports[`t-esc falsy values in text nodes 1`] = ` exports[`t-esc falsy values in text nodes 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let b2 = text(ctx['v1']); let b2 = text(ctx['v1']);
@@ -103,14 +99,13 @@ exports[`t-esc falsy values in text nodes 1`] = `
exports[`t-esc literal 1`] = ` exports[`t-esc literal 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<span><block-text-0/></span>\`); let block1 = createBlock(\`<span><block-text-0/></span>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = 'ok'; let txt1 = 'ok';
return block1([d1]); return block1([txt1]);
} }
}" }"
`; `;
@@ -118,19 +113,22 @@ exports[`t-esc literal 1`] = `
exports[`t-esc t-esc is escaped 1`] = ` exports[`t-esc t-esc is escaped 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { isBoundary, withDefault, LazyValue } = helpers;
let block1 = createBlock(\`<div><block-text-0/></div>\`); let block1 = createBlock(\`<div><block-text-0/></div>\`);
let block2 = createBlock(\`<p>escaped</p>\`); let block2 = createBlock(\`<p>escaped</p>\`);
function value1(ctx, node, key = \\"\\") {
return block2();
}
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
let b2 = block2(); ctx[\`var\`] = new LazyValue(value1, ctx, node);
ctx[\`var\`] = b2; let txt1 = ctx['var'];
let d1 = ctx['var']; return block1([txt1]);
return block1([d1]);
} }
}" }"
`; `;
@@ -138,14 +136,13 @@ exports[`t-esc t-esc is escaped 1`] = `
exports[`t-esc t-esc work with spread operator 1`] = ` exports[`t-esc t-esc work with spread operator 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<span><block-text-0/></span>\`); let block1 = createBlock(\`<span><block-text-0/></span>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = [...ctx['state'].list]; let txt1 = [...ctx['state'].list];
return block1([d1]); return block1([txt1]);
} }
}" }"
`; `;
@@ -153,24 +150,9 @@ exports[`t-esc t-esc work with spread operator 1`] = `
exports[`t-esc t-esc=0 is escaped 1`] = ` exports[`t-esc t-esc=0 is escaped 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { isBoundary, zero, getTemplate } = helpers;
const callTemplate_1 = getTemplate(\`sub\`);
let block1 = createBlock(\`<span><block-text-0/></span>\`);
return function template(ctx, node, key = \\"\\") {
let d1 = ctx[zero];
return block1([d1]);
}
}"
`;
exports[`t-esc t-esc=0 is escaped 2`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
const callTemplate_2 = 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 block2 = createBlock(\`<p>escaped</p>\`);
@@ -180,23 +162,37 @@ exports[`t-esc t-esc=0 is escaped 2`] = `
ctx[isBoundary] = 1; ctx[isBoundary] = 1;
let b2 = block2(); let b2 = block2();
ctx[zero] = b2; ctx[zero] = b2;
let b3 = callTemplate_2.call(this, ctx, node, key + \`__1\`); let b3 = callTemplate_1.call(this, ctx, node, key + \`__1\`);
return block1([], [b3]); return block1([], [b3]);
} }
}" }"
`; `;
exports[`t-esc t-esc=0 is escaped 2`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { zero } = helpers;
let block1 = createBlock(\`<span><block-text-0/></span>\`);
return function template(ctx, node, key = \\"\\") {
let txt1 = ctx[zero];
return block1([txt1]);
}
}"
`;
exports[`t-esc variable 1`] = ` exports[`t-esc variable 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<span><block-text-0/></span>\`); let block1 = createBlock(\`<span><block-text-0/></span>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = ctx['var']; let txt1 = ctx['var'];
return block1([d1]); return block1([txt1]);
} }
}" }"
`; `;
@@ -3,8 +3,8 @@
exports[`t-foreach does not pollute the rendering context 1`] = ` exports[`t-foreach does not pollute the rendering context 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { prepareList, withKey } = helpers;
let block1 = createBlock(\`<div><block-child-0/></div>\`); let block1 = createBlock(\`<div><block-child-0/></div>\`);
@@ -25,8 +25,8 @@ exports[`t-foreach does not pollute the rendering context 1`] = `
exports[`t-foreach iterate on items (on a element node) 1`] = ` exports[`t-foreach iterate on items (on a element node) 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { prepareList, withKey } = helpers;
let block1 = createBlock(\`<div><block-child-0/></div>\`); let block1 = createBlock(\`<div><block-child-0/></div>\`);
let block3 = createBlock(\`<span><block-text-0/></span>\`); let block3 = createBlock(\`<span><block-text-0/></span>\`);
@@ -37,8 +37,8 @@ exports[`t-foreach iterate on items (on a element node) 1`] = `
for (let i1 = 0; i1 < l_block2; i1++) { for (let i1 = 0; i1 < l_block2; i1++) {
ctx[\`item\`] = v_block2[i1]; ctx[\`item\`] = v_block2[i1];
let key1 = ctx['item']; let key1 = ctx['item'];
let d1 = ctx['item']; let txt1 = ctx['item'];
c_block2[i1] = withKey(block3([d1]), key1); c_block2[i1] = withKey(block3([txt1]), key1);
} }
let b2 = list(c_block2); let b2 = list(c_block2);
return block1([], [b2]); return block1([], [b2]);
@@ -49,8 +49,8 @@ exports[`t-foreach iterate on items (on a element node) 1`] = `
exports[`t-foreach iterate on items 1`] = ` exports[`t-foreach iterate on items 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { prepareList, withKey } = helpers;
let block1 = createBlock(\`<div><block-child-0/></div>\`); let block1 = createBlock(\`<div><block-child-0/></div>\`);
@@ -80,8 +80,8 @@ exports[`t-foreach iterate on items 1`] = `
exports[`t-foreach iterate, dict param 1`] = ` exports[`t-foreach iterate, dict param 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { prepareList, withKey } = helpers;
let block1 = createBlock(\`<div><block-child-0/></div>\`); let block1 = createBlock(\`<div><block-child-0/></div>\`);
@@ -111,8 +111,8 @@ exports[`t-foreach iterate, dict param 1`] = `
exports[`t-foreach iterate, position 1`] = ` exports[`t-foreach iterate, position 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { prepareList, withKey } = helpers;
let block1 = createBlock(\`<div><block-child-0/></div>\`); let block1 = createBlock(\`<div><block-child-0/></div>\`);
@@ -147,8 +147,8 @@ exports[`t-foreach iterate, position 1`] = `
exports[`t-foreach simple iteration (in a node) 1`] = ` exports[`t-foreach simple iteration (in a node) 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { prepareList, withKey } = helpers;
let block1 = createBlock(\`<div><block-child-0/></div>\`); let block1 = createBlock(\`<div><block-child-0/></div>\`);
@@ -169,8 +169,8 @@ exports[`t-foreach simple iteration (in a node) 1`] = `
exports[`t-foreach simple iteration 1`] = ` exports[`t-foreach simple iteration 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { prepareList, withKey } = helpers;
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
ctx = Object.create(ctx); ctx = Object.create(ctx);
@@ -188,8 +188,8 @@ exports[`t-foreach simple iteration 1`] = `
exports[`t-foreach simple iteration with two nodes inside 1`] = ` exports[`t-foreach simple iteration with two nodes inside 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { prepareList, withKey } = helpers;
let block3 = createBlock(\`<span>a<block-text-0/></span>\`); let block3 = createBlock(\`<span>a<block-text-0/></span>\`);
let block4 = createBlock(\`<span>b<block-text-0/></span>\`); let block4 = createBlock(\`<span>b<block-text-0/></span>\`);
@@ -200,10 +200,10 @@ exports[`t-foreach simple iteration with two nodes inside 1`] = `
for (let i1 = 0; i1 < l_block1; i1++) { for (let i1 = 0; i1 < l_block1; i1++) {
ctx[\`item\`] = v_block1[i1]; ctx[\`item\`] = v_block1[i1];
let key1 = ctx['item']; let key1 = ctx['item'];
let d1 = ctx['item']; let txt1 = ctx['item'];
let b3 = block3([d1]); let b3 = block3([txt1]);
let d2 = ctx['item']; let txt2 = ctx['item'];
let b4 = block4([d2]); let b4 = block4([txt2]);
c_block1[i1] = withKey(multi([b3, b4]), key1); c_block1[i1] = withKey(multi([b3, b4]), key1);
} }
return list(c_block1); return list(c_block1);
@@ -214,28 +214,9 @@ exports[`t-foreach simple iteration with two nodes inside 1`] = `
exports[`t-foreach t-call with body in t-foreach in t-foreach 1`] = ` exports[`t-foreach t-call with body in t-foreach in t-foreach 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { prepareList, isBoundary, withDefault, setContextValue, getTemplate, withKey } = helpers;
const callTemplate_1 = getTemplate(\`sub\`);
return function template(ctx, node, key = \\"\\") {
let b2 = text(\` [\`);
let b3 = text(ctx['a']);
let b4 = text(\`] [\`);
let b5 = text(ctx['b']);
let b6 = text(\`] [\`);
let b7 = text(ctx['c']);
let b8 = text(\`] \`);
return multi([b2, b3, b4, b5, b6, b7, b8]);
}
}"
`;
exports[`t-foreach t-call with body in t-foreach in t-foreach 2`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
const callTemplate_2 = getTemplate(\`sub\`);
let block1 = createBlock(\`<div><block-child-0/><span>[<block-text-0/>][<block-text-1/>][<block-text-2/>]</span></div>\`); let block1 = createBlock(\`<div><block-child-0/><span>[<block-text-0/>][<block-text-1/>][<block-text-2/>]</span></div>\`);
let block6 = createBlock(\`<span><block-text-0/></span>\`); let block6 = createBlock(\`<span><block-text-0/></span>\`);
@@ -264,35 +245,31 @@ exports[`t-foreach t-call with body in t-foreach in t-foreach 2`] = `
ctx = Object.create(ctx); ctx = Object.create(ctx);
ctx[isBoundary] = 1; ctx[isBoundary] = 1;
setContextValue(ctx, \\"c\\", 'x'+'_'+ctx['a']+'_'+ctx['b']); setContextValue(ctx, \\"c\\", 'x'+'_'+ctx['a']+'_'+ctx['b']);
c_block4[i2] = withKey(callTemplate_2.call(this, ctx, node, key + \`__1__\${key1}__\${key2}\`), key2); c_block4[i2] = withKey(callTemplate_1.call(this, ctx, node, key + \`__1__\${key1}__\${key2}\`), key2);
ctx = ctx.__proto__; ctx = ctx.__proto__;
} }
ctx = ctx.__proto__; ctx = ctx.__proto__;
let b4 = list(c_block4); let b4 = list(c_block4);
let d1 = ctx['c']; let txt1 = ctx['c'];
let b6 = block6([d1]); let b6 = block6([txt1]);
c_block2[i1] = withKey(multi([b4, b6]), key1); c_block2[i1] = withKey(multi([b4, b6]), key1);
} }
ctx = ctx.__proto__; ctx = ctx.__proto__;
let b2 = list(c_block2); let b2 = list(c_block2);
let d2 = ctx['a']; let txt2 = ctx['a'];
let d3 = ctx['b']; let txt3 = ctx['b'];
let d4 = ctx['c']; let txt4 = ctx['c'];
return block1([d2, d3, d4], [b2]); return block1([txt2, txt3, txt4], [b2]);
} }
}" }"
`; `;
exports[`t-foreach t-call without body in t-foreach in t-foreach 1`] = ` exports[`t-foreach t-call with body in t-foreach in t-foreach 2`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
ctx = Object.create(ctx);
ctx[isBoundary] = 1
setContextValue(ctx, \\"c\\", 'x'+'_'+ctx['a']+'_'+ctx['b']);
let b2 = text(\` [\`); let b2 = text(\` [\`);
let b3 = text(ctx['a']); let b3 = text(ctx['a']);
let b4 = text(\`] [\`); let b4 = text(\`] [\`);
@@ -305,12 +282,12 @@ exports[`t-foreach t-call without body in t-foreach in t-foreach 1`] = `
}" }"
`; `;
exports[`t-foreach t-call without body in t-foreach in t-foreach 2`] = ` exports[`t-foreach t-call without body in t-foreach in t-foreach 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { prepareList, getTemplate, withKey } = helpers;
const callTemplate_2 = getTemplate(\`sub\`); const callTemplate_1 = getTemplate(\`sub\`);
let block1 = createBlock(\`<div><block-child-0/><span>[<block-text-0/>][<block-text-1/>][<block-text-2/>]</span></div>\`); let block1 = createBlock(\`<div><block-child-0/><span>[<block-text-0/>][<block-text-1/>][<block-text-2/>]</span></div>\`);
let block6 = createBlock(\`<span><block-text-0/></span>\`); let block6 = createBlock(\`<span><block-text-0/></span>\`);
@@ -334,20 +311,42 @@ exports[`t-foreach t-call without body in t-foreach in t-foreach 2`] = `
ctx[\`b_index\`] = i2; ctx[\`b_index\`] = i2;
ctx[\`b_value\`] = k_block4[i2]; ctx[\`b_value\`] = k_block4[i2];
let key2 = ctx['b']; let key2 = ctx['b'];
c_block4[i2] = withKey(callTemplate_2.call(this, ctx, node, key + \`__1__\${key1}__\${key2}\`), key2); c_block4[i2] = withKey(callTemplate_1.call(this, ctx, node, key + \`__1__\${key1}__\${key2}\`), key2);
} }
ctx = ctx.__proto__; ctx = ctx.__proto__;
let b4 = list(c_block4); let b4 = list(c_block4);
let d1 = ctx['c']; let txt1 = ctx['c'];
let b6 = block6([d1]); let b6 = block6([txt1]);
c_block2[i1] = withKey(multi([b4, b6]), key1); c_block2[i1] = withKey(multi([b4, b6]), key1);
} }
ctx = ctx.__proto__; ctx = ctx.__proto__;
let b2 = list(c_block2); let b2 = list(c_block2);
let d2 = ctx['a']; let txt2 = ctx['a'];
let d3 = ctx['b']; let txt3 = ctx['b'];
let d4 = ctx['c']; let txt4 = ctx['c'];
return block1([d2, d3, d4], [b2]); return block1([txt2, txt3, txt4], [b2]);
}
}"
`;
exports[`t-foreach t-call without body in t-foreach in t-foreach 2`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { isBoundary, withDefault, setContextValue } = helpers;
return function template(ctx, node, key = \\"\\") {
ctx = Object.create(ctx);
ctx[isBoundary] = 1
setContextValue(ctx, \\"c\\", 'x'+'_'+ctx['a']+'_'+ctx['b']);
let b2 = text(\` [\`);
let b3 = text(ctx['a']);
let b4 = text(\`] [\`);
let b5 = text(ctx['b']);
let b6 = text(\`] [\`);
let b7 = text(ctx['c']);
let b8 = text(\`] \`);
return multi([b2, b3, b4, b5, b6, b7, b8]);
} }
}" }"
`; `;
@@ -355,8 +354,8 @@ exports[`t-foreach t-call without body in t-foreach in t-foreach 2`] = `
exports[`t-foreach t-foreach in t-foreach 1`] = ` exports[`t-foreach t-foreach in t-foreach 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { prepareList, withKey } = helpers;
let block1 = createBlock(\`<div><block-child-0/></div>\`); let block1 = createBlock(\`<div><block-child-0/></div>\`);
@@ -389,8 +388,8 @@ exports[`t-foreach t-foreach in t-foreach 1`] = `
exports[`t-foreach t-foreach with t-if inside (no external node) 1`] = ` exports[`t-foreach t-foreach with t-if inside (no external node) 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { prepareList, withKey } = helpers;
let block3 = createBlock(\`<span><block-text-0/></span>\`); let block3 = createBlock(\`<span><block-text-0/></span>\`);
@@ -402,8 +401,8 @@ exports[`t-foreach t-foreach with t-if inside (no external node) 1`] = `
let key1 = ctx['elem'].id; let key1 = ctx['elem'].id;
let b3; let b3;
if (ctx['elem'].id<3) { if (ctx['elem'].id<3) {
let d1 = ctx['elem'].text; let txt1 = ctx['elem'].text;
b3 = block3([d1]); b3 = block3([txt1]);
} }
c_block1[i1] = withKey(multi([b3]), key1); c_block1[i1] = withKey(multi([b3]), key1);
} }
@@ -415,8 +414,8 @@ exports[`t-foreach t-foreach with t-if inside (no external node) 1`] = `
exports[`t-foreach t-foreach with t-if inside 1`] = ` exports[`t-foreach t-foreach with t-if inside 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { prepareList, withKey } = helpers;
let block1 = createBlock(\`<div><block-child-0/></div>\`); let block1 = createBlock(\`<div><block-child-0/></div>\`);
let block4 = createBlock(\`<span><block-text-0/></span>\`); let block4 = createBlock(\`<span><block-text-0/></span>\`);
@@ -429,8 +428,8 @@ exports[`t-foreach t-foreach with t-if inside 1`] = `
let key1 = ctx['elem'].id; let key1 = ctx['elem'].id;
let b4; let b4;
if (ctx['elem'].id<3) { if (ctx['elem'].id<3) {
let d1 = ctx['elem'].text; let txt1 = ctx['elem'].text;
b4 = block4([d1]); b4 = block4([txt1]);
} }
c_block2[i1] = withKey(multi([b4]), key1); c_block2[i1] = withKey(multi([b4]), key1);
} }
@@ -443,8 +442,8 @@ exports[`t-foreach t-foreach with t-if inside 1`] = `
exports[`t-foreach t-key on t-foreach 1`] = ` exports[`t-foreach t-key on t-foreach 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { prepareList, withKey } = helpers;
let block1 = createBlock(\`<div><block-child-0/></div>\`); let block1 = createBlock(\`<div><block-child-0/></div>\`);
let block3 = createBlock(\`<span/>\`); let block3 = createBlock(\`<span/>\`);
@@ -466,8 +465,8 @@ exports[`t-foreach t-key on t-foreach 1`] = `
exports[`t-foreach throws error if invalid loop expression 1`] = ` exports[`t-foreach throws error if invalid loop expression 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { prepareList, withKey } = helpers;
let block1 = createBlock(\`<div><block-child-0/></div>\`); let block1 = createBlock(\`<div><block-child-0/></div>\`);
let block3 = createBlock(\`<span/>\`); let block3 = createBlock(\`<span/>\`);
@@ -491,9 +490,8 @@ exports[`t-foreach throws error if invalid loop expression 1`] = `
exports[`t-foreach with t-memo 1`] = ` exports[`t-foreach with t-memo 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { prepareList, withKey } = helpers;
let assign = Object.assign;
let block1 = createBlock(\`<div><block-child-0/></div>\`); let block1 = createBlock(\`<div><block-child-0/></div>\`);
let block3 = createBlock(\`<p><block-text-0/><block-text-1/></p>\`); let block3 = createBlock(\`<p><block-text-0/><block-text-1/></p>\`);
@@ -515,10 +513,10 @@ exports[`t-foreach with t-memo 1`] = `
continue; continue;
} }
} }
let d1 = ctx['item'].x; let txt1 = ctx['item'].x;
let d2 = ctx['item'].y; let txt2 = ctx['item'].y;
c_block2[i1] = withKey(block3([d1, d2]), key1); c_block2[i1] = withKey(block3([txt1, txt2]), key1);
nextCache[key1] = assign(c_block2[i1], {memo: memo1}); nextCache[key1] = Object.assign(c_block2[i1], {memo: memo1});
} }
let b2 = list(c_block2); let b2 = list(c_block2);
return block1([], [b2]); return block1([], [b2]);
+48 -54
View File
@@ -3,8 +3,7 @@
exports[`t-if a t-if next to a div 1`] = ` exports[`t-if a t-if next to a div 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block2 = createBlock(\`<div>foo</div>\`); let block2 = createBlock(\`<div>foo</div>\`);
@@ -22,8 +21,7 @@ exports[`t-if a t-if next to a div 1`] = `
exports[`t-if a t-if with two inner nodes 1`] = ` exports[`t-if a t-if with two inner nodes 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block3 = createBlock(\`<span>yip</span>\`); let block3 = createBlock(\`<span>yip</span>\`);
let block4 = createBlock(\`<div>yip</div>\`); let block4 = createBlock(\`<div>yip</div>\`);
@@ -43,8 +41,7 @@ exports[`t-if a t-if with two inner nodes 1`] = `
exports[`t-if boolean value condition elif (no outside node) 1`] = ` exports[`t-if boolean value condition elif (no outside node) 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let b2,b3,b4,b5; let b2,b3,b4,b5;
@@ -65,8 +62,7 @@ exports[`t-if boolean value condition elif (no outside node) 1`] = `
exports[`t-if boolean value condition elif 1`] = ` exports[`t-if boolean value condition elif 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><block-child-0/><block-child-1/><block-child-2/><block-child-3/></div>\`); let block1 = createBlock(\`<div><block-child-0/><block-child-1/><block-child-2/><block-child-3/></div>\`);
@@ -89,8 +85,7 @@ exports[`t-if boolean value condition elif 1`] = `
exports[`t-if boolean value condition else 1`] = ` exports[`t-if boolean value condition else 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><span>begin</span><block-child-0/><block-child-1/><span>end</span></div>\`); let block1 = createBlock(\`<div><span>begin</span><block-child-0/><block-child-1/><span>end</span></div>\`);
@@ -109,8 +104,7 @@ exports[`t-if boolean value condition else 1`] = `
exports[`t-if boolean value condition false else 1`] = ` exports[`t-if boolean value condition false else 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><span>begin</span><block-child-0/><block-child-1/><span>end</span></div>\`); let block1 = createBlock(\`<div><span>begin</span><block-child-0/><block-child-1/><span>end</span></div>\`);
@@ -129,8 +123,7 @@ exports[`t-if boolean value condition false else 1`] = `
exports[`t-if boolean value condition missing 1`] = ` exports[`t-if boolean value condition missing 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<span><block-child-0/></span>\`); let block1 = createBlock(\`<span><block-child-0/></span>\`);
@@ -147,8 +140,7 @@ exports[`t-if boolean value condition missing 1`] = `
exports[`t-if can use some boolean operators in expressions 1`] = ` exports[`t-if can use some boolean operators in expressions 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><block-child-0/><block-child-1/><block-child-2/><block-child-3/><block-child-4/><block-child-5/><block-child-6/><block-child-7/></div>\`); let block1 = createBlock(\`<div><block-child-0/><block-child-1/><block-child-2/><block-child-3/><block-child-4/><block-child-5/><block-child-6/><block-child-7/></div>\`);
@@ -186,8 +178,7 @@ exports[`t-if can use some boolean operators in expressions 1`] = `
exports[`t-if div containing a t-if with two inner nodes 1`] = ` exports[`t-if div containing a t-if with two inner nodes 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><block-child-0/></div>\`); let block1 = createBlock(\`<div><block-child-0/></div>\`);
let block3 = createBlock(\`<span>yip</span>\`); let block3 = createBlock(\`<span>yip</span>\`);
@@ -208,8 +199,7 @@ exports[`t-if div containing a t-if with two inner nodes 1`] = `
exports[`t-if dynamic content after t-if with two children nodes 1`] = ` exports[`t-if dynamic content after t-if with two children nodes 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><block-child-0/><block-text-0/></div>\`); let block1 = createBlock(\`<div><block-child-0/><block-text-0/></div>\`);
let block3 = createBlock(\`<p>1</p>\`); let block3 = createBlock(\`<p>1</p>\`);
@@ -222,8 +212,8 @@ exports[`t-if dynamic content after t-if with two children nodes 1`] = `
let b4 = block4(); let b4 = block4();
b2 = multi([b3, b4]); b2 = multi([b3, b4]);
} }
let d1 = ctx['text']; let txt1 = ctx['text'];
return block1([d1], [b2]); return block1([txt1], [b2]);
} }
}" }"
`; `;
@@ -231,8 +221,7 @@ exports[`t-if dynamic content after t-if with two children nodes 1`] = `
exports[`t-if just a t-if 1`] = ` exports[`t-if just a t-if 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let b2; let b2;
@@ -247,8 +236,7 @@ exports[`t-if just a t-if 1`] = `
exports[`t-if simple t-if/t-else 1`] = ` exports[`t-if simple t-if/t-else 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let b2,b3; let b2,b3;
@@ -265,8 +253,7 @@ exports[`t-if simple t-if/t-else 1`] = `
exports[`t-if simple t-if/t-else in a div 1`] = ` exports[`t-if simple t-if/t-else in a div 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><block-child-0/><block-child-1/></div>\`); let block1 = createBlock(\`<div><block-child-0/><block-child-1/></div>\`);
@@ -285,8 +272,7 @@ exports[`t-if simple t-if/t-else in a div 1`] = `
exports[`t-if t-esc with t-elif 1`] = ` exports[`t-if t-esc with t-elif 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><block-child-0/><block-child-1/></div>\`); let block1 = createBlock(\`<div><block-child-0/><block-child-1/></div>\`);
@@ -305,8 +291,7 @@ exports[`t-if t-esc with t-elif 1`] = `
exports[`t-if t-esc with t-if 1`] = ` exports[`t-if t-esc with t-if 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><block-child-0/></div>\`); let block1 = createBlock(\`<div><block-child-0/></div>\`);
@@ -323,8 +308,7 @@ exports[`t-if t-esc with t-if 1`] = `
exports[`t-if t-if and t-else with two nodes 1`] = ` exports[`t-if t-if and t-else with two nodes 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block4 = createBlock(\`<span>a</span>\`); let block4 = createBlock(\`<span>a</span>\`);
let block5 = createBlock(\`<span>b</span>\`); let block5 = createBlock(\`<span>b</span>\`);
@@ -346,8 +330,7 @@ exports[`t-if t-if and t-else with two nodes 1`] = `
exports[`t-if t-if in a div 1`] = ` exports[`t-if t-if in a div 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><block-child-0/></div>\`); let block1 = createBlock(\`<div><block-child-0/></div>\`);
@@ -364,8 +347,7 @@ exports[`t-if t-if in a div 1`] = `
exports[`t-if t-if in a t-if 1`] = ` exports[`t-if t-if in a t-if 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><block-child-0/></div>\`); let block1 = createBlock(\`<div><block-child-0/></div>\`);
let block2 = createBlock(\`<span>1<block-child-0/></span>\`); let block2 = createBlock(\`<span>1<block-child-0/></span>\`);
@@ -384,11 +366,26 @@ exports[`t-if t-if in a t-if 1`] = `
}" }"
`; `;
exports[`t-if t-if with empty content 1`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
return function template(ctx, node, key = \\"\\") {
let b2,b3;
b2 = text(\`hello\`);
if (ctx['condition']) {
b3 = text(\`\`);
}
return multi([b2, b3]);
}
}"
`;
exports[`t-if t-if/t-else with more content 1`] = ` exports[`t-if t-if/t-else with more content 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let b2,b3; let b2,b3;
@@ -407,8 +404,8 @@ exports[`t-if t-if/t-else with more content 1`] = `
exports[`t-if t-set, then t-if 1`] = ` exports[`t-if t-set, then t-if 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { isBoundary, withDefault, setContextValue } = helpers;
let block1 = createBlock(\`<div><block-child-0/></div>\`); let block1 = createBlock(\`<div><block-child-0/></div>\`);
@@ -428,8 +425,8 @@ exports[`t-if t-set, then t-if 1`] = `
exports[`t-if t-set, then t-if, part 2 1`] = ` exports[`t-if t-set, then t-if, part 2 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { isBoundary, withDefault, setContextValue } = helpers;
let block1 = createBlock(\`<div><block-child-0/></div>\`); let block1 = createBlock(\`<div><block-child-0/></div>\`);
let block2 = createBlock(\`<span>COUCOU</span>\`); let block2 = createBlock(\`<span>COUCOU</span>\`);
@@ -451,8 +448,8 @@ exports[`t-if t-set, then t-if, part 2 1`] = `
exports[`t-if t-set, then t-if, part 3 1`] = ` exports[`t-if t-set, then t-if, part 3 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { isBoundary, withDefault, setContextValue } = helpers;
let block1 = createBlock(\`<div><block-child-0/><block-child-1/></div>\`); let block1 = createBlock(\`<div><block-child-0/><block-child-1/></div>\`);
let block2 = createBlock(\`<span>AAA</span>\`); let block2 = createBlock(\`<span>AAA</span>\`);
@@ -477,8 +474,7 @@ exports[`t-if t-set, then t-if, part 3 1`] = `
exports[`t-if two consecutive t-if 1`] = ` exports[`t-if two consecutive t-if 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let b2,b3; let b2,b3;
@@ -496,8 +492,7 @@ exports[`t-if two consecutive t-if 1`] = `
exports[`t-if two consecutive t-if in a div 1`] = ` exports[`t-if two consecutive t-if in a div 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><block-child-0/><block-child-1/></div>\`); let block1 = createBlock(\`<div><block-child-0/><block-child-1/></div>\`);
@@ -517,8 +512,7 @@ exports[`t-if two consecutive t-if in a div 1`] = `
exports[`t-if two t-ifs next to each other 1`] = ` exports[`t-if two t-ifs next to each other 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><block-child-0/><block-child-1/></div>\`); let block1 = createBlock(\`<div><block-child-0/><block-child-1/></div>\`);
let block2 = createBlock(\`<span><block-text-0/></span>\`); let block2 = createBlock(\`<span><block-text-0/></span>\`);
@@ -528,8 +522,8 @@ exports[`t-if two t-ifs next to each other 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let b2,b3; let b2,b3;
if (ctx['condition']) { if (ctx['condition']) {
let d1 = ctx['text']; let txt1 = ctx['text'];
b2 = block2([d1]); b2 = block2([txt1]);
} }
if (ctx['condition']) { if (ctx['condition']) {
let b4 = block4(); let b4 = block4();
+13 -16
View File
@@ -3,15 +3,14 @@
exports[`t-key can use t-key directive on a node 1`] = ` exports[`t-key can use t-key directive on a node 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><block-text-0/></div>\`); let block1 = createBlock(\`<div><block-text-0/></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const tKey_1 = ctx['beer'].id; const tKey_1 = ctx['beer'].id;
let d1 = ctx['beer'].name; let txt1 = ctx['beer'].name;
return toggler(tKey_1, block1([d1])); return toggler(tKey_1, block1([txt1]));
} }
}" }"
`; `;
@@ -19,15 +18,14 @@ exports[`t-key can use t-key directive on a node 1`] = `
exports[`t-key can use t-key directive on a node 2 1`] = ` exports[`t-key can use t-key directive on a node 2 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><block-text-0/></div>\`); let block1 = createBlock(\`<div><block-text-0/></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const tKey_1 = ctx['beer'].id; const tKey_1 = ctx['beer'].id;
let d1 = ctx['beer'].name; let txt1 = ctx['beer'].name;
return toggler(tKey_1, block1([d1])); return toggler(tKey_1, block1([txt1]));
} }
}" }"
`; `;
@@ -35,15 +33,14 @@ exports[`t-key can use t-key directive on a node 2 1`] = `
exports[`t-key can use t-key directive on a node as a function 1`] = ` exports[`t-key can use t-key directive on a node as a function 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><block-text-0/></div>\`); let block1 = createBlock(\`<div><block-text-0/></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const tKey_1 = ctx['getKey'](ctx['beer']); const tKey_1 = ctx['getKey'](ctx['beer']);
let d1 = ctx['beer'].name; let txt1 = ctx['beer'].name;
return toggler(tKey_1, block1([d1])); return toggler(tKey_1, block1([txt1]));
} }
}" }"
`; `;
@@ -51,8 +48,8 @@ exports[`t-key can use t-key directive on a node as a function 1`] = `
exports[`t-key t-key directive in a list 1`] = ` exports[`t-key t-key directive in a list 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { prepareList, withKey } = helpers;
let block1 = createBlock(\`<ul><block-child-0/></ul>\`); let block1 = createBlock(\`<ul><block-child-0/></ul>\`);
let block3 = createBlock(\`<li><block-text-0/></li>\`); let block3 = createBlock(\`<li><block-text-0/></li>\`);
@@ -63,8 +60,8 @@ exports[`t-key t-key directive in a list 1`] = `
for (let i1 = 0; i1 < l_block2; i1++) { for (let i1 = 0; i1 < l_block2; i1++) {
ctx[\`beer\`] = v_block2[i1]; ctx[\`beer\`] = v_block2[i1];
let key1 = ctx['beer'].id; let key1 = ctx['beer'].id;
let d1 = ctx['beer'].name; let txt1 = ctx['beer'].name;
c_block2[i1] = withKey(block3([d1]), key1); c_block2[i1] = withKey(block3([txt1]), key1);
} }
let b2 = list(c_block2); let b2 = list(c_block2);
return block1([], [b2]); return block1([], [b2]);
+102 -96
View File
@@ -3,8 +3,8 @@
exports[`t-out literal 1`] = ` exports[`t-out literal 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { safeOutput } = helpers;
let block1 = createBlock(\`<span><block-child-0/></span>\`); let block1 = createBlock(\`<span><block-child-0/></span>\`);
@@ -18,8 +18,8 @@ exports[`t-out literal 1`] = `
exports[`t-out literal, no outside html element 1`] = ` exports[`t-out literal, no outside html element 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { safeOutput } = helpers;
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return safeOutput('ok'); return safeOutput('ok');
@@ -30,8 +30,29 @@ exports[`t-out literal, no outside html element 1`] = `
exports[`t-out multiple calls to t-out 1`] = ` exports[`t-out multiple calls to t-out 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { isBoundary, zero, getTemplate } = helpers;
const callTemplate_1 = getTemplate(\`sub\`);
let block1 = createBlock(\`<div><block-child-0/></div>\`);
let block2 = createBlock(\`<span>coucou</span>\`);
return function template(ctx, node, key = \\"\\") {
ctx = Object.create(ctx);
ctx[isBoundary] = 1;
let b2 = block2();
ctx[zero] = b2;
let b3 = callTemplate_1.call(this, ctx, node, key + \`__1\`);
return block1([], [b3]);
}
}"
`;
exports[`t-out multiple calls to t-out 2`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { zero } = helpers;
let block1 = createBlock(\`<div><block-child-0/><div>Greeter</div><block-child-1/></div>\`); let block1 = createBlock(\`<div><block-child-0/><div>Greeter</div><block-child-1/></div>\`);
@@ -43,32 +64,11 @@ exports[`t-out multiple calls to t-out 1`] = `
}" }"
`; `;
exports[`t-out multiple calls to t-out 2`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
const callTemplate_2 = getTemplate(\`sub\`);
let block1 = createBlock(\`<div><block-child-0/></div>\`);
let block2 = createBlock(\`<span>coucou</span>\`);
return function template(ctx, node, key = \\"\\") {
ctx = Object.create(ctx);
ctx[isBoundary] = 1;
let b2 = block2();
ctx[zero] = b2;
let b3 = callTemplate_2.call(this, ctx, node, key + \`__1\`);
return block1([], [b3]);
}
}"
`;
exports[`t-out not escaping 1`] = ` exports[`t-out not escaping 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { safeOutput } = helpers;
let block1 = createBlock(\`<div><block-child-0/></div>\`); let block1 = createBlock(\`<div><block-child-0/></div>\`);
@@ -82,8 +82,29 @@ exports[`t-out not escaping 1`] = `
exports[`t-out t-out 0 1`] = ` exports[`t-out t-out 0 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { isBoundary, zero, getTemplate } = helpers;
const callTemplate_1 = getTemplate(\`_basic-callee\`);
let block1 = createBlock(\`<div><block-child-0/></div>\`);
let block2 = createBlock(\`<div>zero</div>\`);
return function template(ctx, node, key = \\"\\") {
ctx = Object.create(ctx);
ctx[isBoundary] = 1;
let b2 = block2();
ctx[zero] = b2;
let b3 = callTemplate_1.call(this, ctx, node, key + \`__1\`);
return block1([], [b3]);
}
}"
`;
exports[`t-out t-out 0 2`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { zero } = helpers;
let block1 = createBlock(\`<div><block-child-0/></div>\`); let block1 = createBlock(\`<div><block-child-0/></div>\`);
@@ -94,32 +115,11 @@ exports[`t-out t-out 0 1`] = `
}" }"
`; `;
exports[`t-out t-out 0 2`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
const callTemplate_2 = getTemplate(\`_basic-callee\`);
let block1 = createBlock(\`<div><block-child-0/></div>\`);
let block2 = createBlock(\`<div>zero</div>\`);
return function template(ctx, node, key = \\"\\") {
ctx = Object.create(ctx);
ctx[isBoundary] = 1;
let b2 = block2();
ctx[zero] = b2;
let b3 = callTemplate_2.call(this, ctx, node, key + \`__1\`);
return block1([], [b3]);
}
}"
`;
exports[`t-out t-out and another sibling node 1`] = ` exports[`t-out t-out and another sibling node 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { safeOutput } = helpers;
let block1 = createBlock(\`<span><span>hello</span><block-child-0/></span>\`); let block1 = createBlock(\`<span><span>hello</span><block-child-0/></span>\`);
@@ -133,17 +133,20 @@ exports[`t-out t-out and another sibling node 1`] = `
exports[`t-out t-out bdom 1`] = ` exports[`t-out t-out bdom 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { isBoundary, withDefault, LazyValue, safeOutput } = helpers;
let block1 = createBlock(\`<div><span><block-child-0/></span></div>\`); let block1 = createBlock(\`<div><span><block-child-0/></span></div>\`);
let block2 = createBlock(\`<ol>set</ol>\`); let block2 = createBlock(\`<ol>set</ol>\`);
function value1(ctx, node, key = \\"\\") {
return block2();
}
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
let b2 = block2(); ctx[\`var\`] = new LazyValue(value1, ctx, node);
ctx[\`var\`] = b2;
let b3 = safeOutput(ctx['var']); let b3 = safeOutput(ctx['var']);
return block1([], [b3]); return block1([], [b3]);
} }
@@ -153,8 +156,8 @@ exports[`t-out t-out bdom 1`] = `
exports[`t-out t-out block 1`] = ` exports[`t-out t-out block 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { safeOutput } = helpers;
let block1 = createBlock(\`<span><block-child-0/></span>\`); let block1 = createBlock(\`<span><block-child-0/></span>\`);
@@ -168,8 +171,8 @@ exports[`t-out t-out block 1`] = `
exports[`t-out t-out escaped 1`] = ` exports[`t-out t-out escaped 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { safeOutput } = helpers;
let block1 = createBlock(\`<span><block-child-0/></span>\`); let block1 = createBlock(\`<span><block-child-0/></span>\`);
@@ -183,8 +186,8 @@ exports[`t-out t-out escaped 1`] = `
exports[`t-out t-out markedup 1`] = ` exports[`t-out t-out markedup 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { safeOutput } = helpers;
let block1 = createBlock(\`<span><block-child-0/></span>\`); let block1 = createBlock(\`<span><block-child-0/></span>\`);
@@ -198,8 +201,8 @@ exports[`t-out t-out markedup 1`] = `
exports[`t-out t-out on a node with a body, as a default 1`] = ` exports[`t-out t-out on a node with a body, as a default 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { safeOutput, withDefault } = helpers;
let block1 = createBlock(\`<span><block-child-0/></span>\`); let block1 = createBlock(\`<span><block-child-0/></span>\`);
@@ -214,8 +217,8 @@ exports[`t-out t-out on a node with a body, as a default 1`] = `
exports[`t-out t-out on a node with a dom node in body, as a default 1`] = ` exports[`t-out t-out on a node with a dom node in body, as a default 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { safeOutput, withDefault } = helpers;
let block1 = createBlock(\`<span><block-child-0/></span>\`); let block1 = createBlock(\`<span><block-child-0/></span>\`);
let block3 = createBlock(\`<div>nope</div>\`); let block3 = createBlock(\`<div>nope</div>\`);
@@ -231,8 +234,8 @@ exports[`t-out t-out on a node with a dom node in body, as a default 1`] = `
exports[`t-out t-out switch escaped 1`] = ` exports[`t-out t-out switch escaped 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { safeOutput } = helpers;
let block1 = createBlock(\`<span><block-child-0/></span>\`); let block1 = createBlock(\`<span><block-child-0/></span>\`);
@@ -246,8 +249,8 @@ exports[`t-out t-out switch escaped 1`] = `
exports[`t-out t-out switch escaped on markup 1`] = ` exports[`t-out t-out switch escaped on markup 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { safeOutput } = helpers;
let block1 = createBlock(\`<span><block-child-0/></span>\`); let block1 = createBlock(\`<span><block-child-0/></span>\`);
@@ -261,8 +264,8 @@ exports[`t-out t-out switch escaped on markup 1`] = `
exports[`t-out t-out switch markup 1`] = ` exports[`t-out t-out switch markup 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { safeOutput } = helpers;
let block1 = createBlock(\`<span><block-child-0/></span>\`); let block1 = createBlock(\`<span><block-child-0/></span>\`);
@@ -276,20 +279,23 @@ exports[`t-out t-out switch markup 1`] = `
exports[`t-out t-out switch markup on bdom 1`] = ` exports[`t-out t-out switch markup on bdom 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { isBoundary, withDefault, LazyValue, safeOutput } = helpers;
let block1 = createBlock(\`<div><block-child-0/><block-child-1/></div>\`); let block1 = createBlock(\`<div><block-child-0/><block-child-1/></div>\`);
let block2 = createBlock(\`<ol>set</ol>\`); let block2 = createBlock(\`<ol>set</ol>\`);
let block3 = createBlock(\`<span><block-child-0/></span>\`); let block3 = createBlock(\`<span><block-child-0/></span>\`);
let block5 = createBlock(\`<span><block-child-0/></span>\`); let block5 = createBlock(\`<span><block-child-0/></span>\`);
function value1(ctx, node, key = \\"\\") {
return block2();
}
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
let b3,b5; let b3,b5;
let b2 = block2(); ctx[\`bdom\`] = new LazyValue(value1, ctx, node);
ctx[\`bdom\`] = b2;
if (ctx['hasBdom']) { if (ctx['hasBdom']) {
let b4 = safeOutput(ctx['bdom']); let b4 = safeOutput(ctx['bdom']);
b3 = block3([], [b4]); b3 = block3([], [b4]);
@@ -305,8 +311,8 @@ exports[`t-out t-out switch markup on bdom 1`] = `
exports[`t-out t-out switch markup on escaped 1`] = ` exports[`t-out t-out switch markup on escaped 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { safeOutput } = helpers;
let block1 = createBlock(\`<span><block-child-0/></span>\`); let block1 = createBlock(\`<span><block-child-0/></span>\`);
@@ -320,8 +326,8 @@ exports[`t-out t-out switch markup on escaped 1`] = `
exports[`t-out t-out with a <t/> in body 1`] = ` exports[`t-out t-out with a <t/> in body 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { safeOutput } = helpers;
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return safeOutput(ctx['var']); return safeOutput(ctx['var']);
@@ -332,8 +338,8 @@ exports[`t-out t-out with a <t/> in body 1`] = `
exports[`t-out t-out with arbitrary object 1`] = ` exports[`t-out t-out with arbitrary object 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { safeOutput } = helpers;
let block1 = createBlock(\`<div><block-child-0/></div>\`); let block1 = createBlock(\`<div><block-child-0/></div>\`);
@@ -347,8 +353,8 @@ exports[`t-out t-out with arbitrary object 1`] = `
exports[`t-out t-out with arbitrary object 2 1`] = ` exports[`t-out t-out with arbitrary object 2 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { safeOutput } = helpers;
let block1 = createBlock(\`<div><block-child-0/></div>\`); let block1 = createBlock(\`<div><block-child-0/></div>\`);
@@ -362,8 +368,8 @@ exports[`t-out t-out with arbitrary object 2 1`] = `
exports[`t-out t-out with comment 1`] = ` exports[`t-out t-out with comment 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { safeOutput } = helpers;
let block1 = createBlock(\`<span><block-child-0/></span>\`); let block1 = createBlock(\`<span><block-child-0/></span>\`);
@@ -377,8 +383,8 @@ exports[`t-out t-out with comment 1`] = `
exports[`t-out t-out with just a t-set t-value in body 1`] = ` exports[`t-out t-out with just a t-set t-value in body 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { safeOutput } = helpers;
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return safeOutput(ctx['var']); return safeOutput(ctx['var']);
@@ -389,8 +395,8 @@ exports[`t-out t-out with just a t-set t-value in body 1`] = `
exports[`t-out variable 1`] = ` exports[`t-out variable 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { safeOutput } = helpers;
let block1 = createBlock(\`<span><block-child-0/></span>\`); let block1 = createBlock(\`<span><block-child-0/></span>\`);
@@ -404,8 +410,8 @@ exports[`t-out variable 1`] = `
exports[`t-raw is deprecated should warn 1`] = ` exports[`t-raw is deprecated should warn 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { safeOutput } = helpers;
let block1 = createBlock(\`<div><block-child-0/></div>\`); let block1 = createBlock(\`<div><block-child-0/></div>\`);
@@ -419,8 +425,8 @@ exports[`t-raw is deprecated should warn 1`] = `
exports[`t-raw is deprecated t-out is actually called in t-raw's place 1`] = ` exports[`t-raw is deprecated t-out is actually called in t-raw's place 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { safeOutput } = helpers;
let block1 = createBlock(\`<div><block-child-0/></div>\`); let block1 = createBlock(\`<div><block-child-0/></div>\`);
+27 -32
View File
@@ -3,16 +3,15 @@
exports[`t-ref can get a dynamic ref on a node 1`] = ` exports[`t-ref can get a dynamic ref on a node 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><span block-ref=\\"0\\"/></div>\`); let block1 = createBlock(\`<div><span block-ref=\\"0\\"/></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const refs = ctx.__owl__.refs; const refs = ctx.__owl__.refs;
const v1 = ctx['id']; const v1 = ctx['id'];
let d1 = (el) => refs[\`myspan\${v1}\`] = el; let ref1 = (el) => refs[\`myspan\${v1}\`] = el;
return block1([d1]); return block1([ref1]);
} }
}" }"
`; `;
@@ -20,15 +19,14 @@ exports[`t-ref can get a dynamic ref on a node 1`] = `
exports[`t-ref can get a ref on a node 1`] = ` exports[`t-ref can get a ref on a node 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><span block-ref=\\"0\\"/></div>\`); let block1 = createBlock(\`<div><span block-ref=\\"0\\"/></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const refs = ctx.__owl__.refs; const refs = ctx.__owl__.refs;
let d1 = (el) => refs[\`myspan\`] = el; const ref1 = (el) => refs[\`myspan\`] = el;
return block1([d1]); return block1([ref1]);
} }
}" }"
`; `;
@@ -36,14 +34,14 @@ exports[`t-ref can get a ref on a node 1`] = `
exports[`t-ref ref in a t-call 1`] = ` exports[`t-ref ref in a t-call 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { getTemplate } = helpers;
const callTemplate_2 = getTemplate(\`sub\`); const callTemplate_1 = getTemplate(\`sub\`);
let block1 = createBlock(\`<div><block-child-0/></div>\`); let block1 = createBlock(\`<div><block-child-0/></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let b2 = callTemplate_2.call(this, ctx, node, key + \`__1\`); let b2 = callTemplate_1.call(this, ctx, node, key + \`__1\`);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -52,15 +50,14 @@ exports[`t-ref ref in a t-call 1`] = `
exports[`t-ref ref in a t-call 2`] = ` exports[`t-ref ref in a t-call 2`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div>1<span block-ref=\\"0\\"/>2</div>\`); let block1 = createBlock(\`<div>1<span block-ref=\\"0\\"/>2</div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const refs = ctx.__owl__.refs; const refs = ctx.__owl__.refs;
let d1 = (el) => refs[\`name\`] = el; const ref1 = (el) => refs[\`name\`] = el;
return block1([d1]); return block1([ref1]);
} }
}" }"
`; `;
@@ -68,18 +65,17 @@ exports[`t-ref ref in a t-call 2`] = `
exports[`t-ref ref in a t-if 1`] = ` exports[`t-ref ref in a t-if 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><block-child-0/></div>\`); let block1 = createBlock(\`<div><block-child-0/></div>\`);
let block2 = createBlock(\`<span block-ref=\\"0\\"/>\`); let block2 = createBlock(\`<span block-ref=\\"0\\"/>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const refs = ctx.__owl__.refs; const refs = ctx.__owl__.refs;
const ref1 = (el) => refs[\`name\`] = el;
let b2; let b2;
if (ctx['condition']) { if (ctx['condition']) {
let d1 = (el) => refs[\`name\`] = el; b2 = block2([ref1]);
b2 = block2([d1]);
} }
return block1([], [b2]); return block1([], [b2]);
} }
@@ -89,8 +85,8 @@ exports[`t-ref ref in a t-if 1`] = `
exports[`t-ref refs in a loop 1`] = ` exports[`t-ref refs in a loop 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { prepareList, withKey } = helpers;
let block1 = createBlock(\`<div><block-child-0/></div>\`); let block1 = createBlock(\`<div><block-child-0/></div>\`);
let block3 = createBlock(\`<div block-ref=\\"0\\"><block-text-1/></div>\`); let block3 = createBlock(\`<div block-ref=\\"0\\"><block-text-1/></div>\`);
@@ -103,10 +99,10 @@ exports[`t-ref refs in a loop 1`] = `
ctx[\`item\`] = v_block2[i1]; ctx[\`item\`] = v_block2[i1];
let key1 = ctx['item']; let key1 = ctx['item'];
const tKey_1 = ctx['item']; const tKey_1 = ctx['item'];
const v2 = ctx['item']; const v1 = ctx['item'];
let d1 = (el) => refs[\`\${v2}\`] = el; let ref1 = (el) => refs[\`\${v1}\`] = el;
let d2 = ctx['item']; let txt1 = ctx['item'];
c_block2[i1] = withKey(block3([d1, d2]), tKey_1 + key1); c_block2[i1] = withKey(block3([ref1, txt1]), tKey_1 + key1);
} }
let b2 = list(c_block2); let b2 = list(c_block2);
return block1([], [b2]); return block1([], [b2]);
@@ -117,21 +113,20 @@ exports[`t-ref refs in a loop 1`] = `
exports[`t-ref two refs, one in a t-if 1`] = ` exports[`t-ref two refs, one in a t-if 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><block-child-0/><p block-ref=\\"0\\"/></div>\`); let block1 = createBlock(\`<div><block-child-0/><p block-ref=\\"0\\"/></div>\`);
let block2 = createBlock(\`<span block-ref=\\"0\\"/>\`); let block2 = createBlock(\`<span block-ref=\\"0\\"/>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const refs = ctx.__owl__.refs; const refs = ctx.__owl__.refs;
const ref1 = (el) => refs[\`name\`] = el;
const ref2 = (el) => refs[\`p\`] = el;
let b2; let b2;
if (ctx['condition']) { if (ctx['condition']) {
let d1 = (el) => refs[\`name\`] = el; b2 = block2([ref1]);
b2 = block2([d1]);
} }
let d2 = (el) => refs[\`p\`] = el; return block1([ref2], [b2]);
return block1([d2], [b2]);
} }
}" }"
`; `;
+166 -148
View File
@@ -3,8 +3,8 @@
exports[`t-set evaluate value expression 1`] = ` exports[`t-set evaluate value expression 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { isBoundary, withDefault, setContextValue } = helpers;
let block1 = createBlock(\`<div><block-text-0/></div>\`); let block1 = createBlock(\`<div><block-text-0/></div>\`);
@@ -12,8 +12,8 @@ exports[`t-set evaluate value expression 1`] = `
ctx = Object.create(ctx); ctx = Object.create(ctx);
ctx[isBoundary] = 1 ctx[isBoundary] = 1
setContextValue(ctx, \\"value\\", 1+2); setContextValue(ctx, \\"value\\", 1+2);
let d1 = ctx['value']; let txt1 = ctx['value'];
return block1([d1]); return block1([txt1]);
} }
}" }"
`; `;
@@ -21,8 +21,8 @@ exports[`t-set evaluate value expression 1`] = `
exports[`t-set evaluate value expression, part 2 1`] = ` exports[`t-set evaluate value expression, part 2 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { isBoundary, withDefault, setContextValue } = helpers;
let block1 = createBlock(\`<div><block-text-0/></div>\`); let block1 = createBlock(\`<div><block-text-0/></div>\`);
@@ -30,8 +30,8 @@ exports[`t-set evaluate value expression, part 2 1`] = `
ctx = Object.create(ctx); ctx = Object.create(ctx);
ctx[isBoundary] = 1 ctx[isBoundary] = 1
setContextValue(ctx, \\"value\\", ctx['somevariable']+2); setContextValue(ctx, \\"value\\", ctx['somevariable']+2);
let d1 = ctx['value']; let txt1 = ctx['value'];
return block1([d1]); return block1([txt1]);
} }
}" }"
`; `;
@@ -39,8 +39,8 @@ exports[`t-set evaluate value expression, part 2 1`] = `
exports[`t-set set from attribute literal (no outside div) 1`] = ` exports[`t-set set from attribute literal (no outside div) 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { isBoundary, withDefault, setContextValue } = helpers;
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
ctx = Object.create(ctx); ctx = Object.create(ctx);
@@ -54,8 +54,8 @@ exports[`t-set set from attribute literal (no outside div) 1`] = `
exports[`t-set set from attribute literal 1`] = ` exports[`t-set set from attribute literal 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { isBoundary, withDefault, setContextValue } = helpers;
let block1 = createBlock(\`<div><block-text-0/></div>\`); let block1 = createBlock(\`<div><block-text-0/></div>\`);
@@ -63,8 +63,8 @@ exports[`t-set set from attribute literal 1`] = `
ctx = Object.create(ctx); ctx = Object.create(ctx);
ctx[isBoundary] = 1 ctx[isBoundary] = 1
setContextValue(ctx, \\"value\\", 'ok'); setContextValue(ctx, \\"value\\", 'ok');
let d1 = ctx['value']; let txt1 = ctx['value'];
return block1([d1]); return block1([txt1]);
} }
}" }"
`; `;
@@ -72,8 +72,8 @@ exports[`t-set set from attribute literal 1`] = `
exports[`t-set set from attribute lookup 1`] = ` exports[`t-set set from attribute lookup 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { isBoundary, withDefault, setContextValue } = helpers;
let block1 = createBlock(\`<div><block-text-0/></div>\`); let block1 = createBlock(\`<div><block-text-0/></div>\`);
@@ -81,8 +81,8 @@ exports[`t-set set from attribute lookup 1`] = `
ctx = Object.create(ctx); ctx = Object.create(ctx);
ctx[isBoundary] = 1 ctx[isBoundary] = 1
setContextValue(ctx, \\"stuff\\", ctx['value']); setContextValue(ctx, \\"stuff\\", ctx['value']);
let d1 = ctx['stuff']; let txt1 = ctx['stuff'];
return block1([d1]); return block1([txt1]);
} }
}" }"
`; `;
@@ -90,8 +90,8 @@ exports[`t-set set from attribute lookup 1`] = `
exports[`t-set set from body literal 1`] = ` exports[`t-set set from body literal 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { isBoundary, withDefault, setContextValue } = helpers;
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
ctx = Object.create(ctx); ctx = Object.create(ctx);
@@ -105,18 +105,21 @@ exports[`t-set set from body literal 1`] = `
exports[`t-set set from body lookup 1`] = ` exports[`t-set set from body lookup 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { isBoundary, withDefault, LazyValue } = helpers;
let block1 = createBlock(\`<div><block-text-0/></div>\`); let block1 = createBlock(\`<div><block-text-0/></div>\`);
function value1(ctx, node, key = \\"\\") {
return text(ctx['value']);
}
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
let b2 = text(ctx['value']); ctx[\`stuff\`] = new LazyValue(value1, ctx, node);
ctx[\`stuff\`] = b2; let txt1 = ctx['stuff'];
let d1 = ctx['stuff']; return block1([txt1]);
return block1([d1]);
} }
}" }"
`; `;
@@ -124,8 +127,8 @@ exports[`t-set set from body lookup 1`] = `
exports[`t-set set from empty body 1`] = ` exports[`t-set set from empty body 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { isBoundary, withDefault, setContextValue } = helpers;
let block1 = createBlock(\`<div><block-text-0/></div>\`); let block1 = createBlock(\`<div><block-text-0/></div>\`);
@@ -133,8 +136,8 @@ exports[`t-set set from empty body 1`] = `
ctx = Object.create(ctx); ctx = Object.create(ctx);
ctx[isBoundary] = 1 ctx[isBoundary] = 1
setContextValue(ctx, \\"stuff\\", null); setContextValue(ctx, \\"stuff\\", null);
let d1 = ctx['stuff']; let txt1 = ctx['stuff'];
return block1([d1]); return block1([txt1]);
} }
}" }"
`; `;
@@ -142,8 +145,8 @@ exports[`t-set set from empty body 1`] = `
exports[`t-set t-set and t-if 1`] = ` exports[`t-set t-set and t-if 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { isBoundary, withDefault, setContextValue } = helpers;
let block1 = createBlock(\`<div><block-child-0/></div>\`); let block1 = createBlock(\`<div><block-child-0/></div>\`);
@@ -163,19 +166,22 @@ exports[`t-set t-set and t-if 1`] = `
exports[`t-set t-set body is evaluated immediately 1`] = ` exports[`t-set t-set body is evaluated immediately 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { isBoundary, withDefault, setContextValue, LazyValue, safeOutput } = helpers;
let block1 = createBlock(\`<div><block-child-0/></div>\`); let block1 = createBlock(\`<div><block-child-0/></div>\`);
let block2 = createBlock(\`<span><block-text-0/></span>\`); let block2 = createBlock(\`<span><block-text-0/></span>\`);
function value1(ctx, node, key = \\"\\") {
let txt1 = ctx['v1'];
return block2([txt1]);
}
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
setContextValue(ctx, \\"v1\\", 'before'); setContextValue(ctx, \\"v1\\", 'before');
let d1 = ctx['v1']; ctx[\`v2\`] = new LazyValue(value1, ctx, node);
let b2 = block2([d1]);
ctx[\`v2\`] = b2;
setContextValue(ctx, \\"v1\\", 'after'); setContextValue(ctx, \\"v1\\", 'after');
let b3 = safeOutput(ctx['v2']); let b3 = safeOutput(ctx['v2']);
return block1([], [b3]); return block1([], [b3]);
@@ -186,18 +192,20 @@ exports[`t-set t-set body is evaluated immediately 1`] = `
exports[`t-set t-set can't alter from within callee 1`] = ` exports[`t-set t-set can't alter from within callee 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { isBoundary, withDefault, setContextValue, getTemplate } = helpers;
const callTemplate_1 = getTemplate(\`sub\`);
let block1 = createBlock(\`<div><block-text-0/><block-text-1/></div>\`); let block1 = createBlock(\`<div><p><block-text-0/></p><block-child-0/><p><block-text-1/></p></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
let d1 = ctx['iter']; setContextValue(ctx, \\"iter\\", 'source');
setContextValue(ctx, \\"iter\\", 'called'); let txt1 = ctx['iter'];
let d2 = ctx['iter']; let b2 = callTemplate_1.call(this, ctx, node, key + \`__1\`);
return block1([d1, d2]); let txt2 = ctx['iter'];
return block1([txt1, txt2], [b2]);
} }
}" }"
`; `;
@@ -205,20 +213,18 @@ exports[`t-set t-set can't alter from within callee 1`] = `
exports[`t-set t-set can't alter from within callee 2`] = ` exports[`t-set t-set can't alter from within callee 2`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { isBoundary, withDefault, setContextValue } = helpers;
const callTemplate_2 = getTemplate(\`sub\`);
let block1 = createBlock(\`<div><p><block-text-0/></p><block-child-0/><p><block-text-1/></p></div>\`); let block1 = createBlock(\`<div><block-text-0/><block-text-1/></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
setContextValue(ctx, \\"iter\\", 'source'); let txt1 = ctx['iter'];
let d1 = ctx['iter']; setContextValue(ctx, \\"iter\\", 'called');
let b2 = callTemplate_2.call(this, ctx, node, key + \`__1\`); let txt2 = ctx['iter'];
let d2 = ctx['iter']; return block1([txt1, txt2]);
return block1([d1, d2], [b2]);
} }
}" }"
`; `;
@@ -226,28 +232,9 @@ exports[`t-set t-set can't alter from within callee 2`] = `
exports[`t-set t-set can't alter in t-call body 1`] = ` exports[`t-set t-set can't alter in t-call body 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { isBoundary, withDefault, setContextValue, getTemplate } = helpers;
const callTemplate_1 = getTemplate(\`sub\`);
let block1 = createBlock(\`<div><block-text-0/><block-text-1/></div>\`);
return function template(ctx, node, key = \\"\\") {
ctx = Object.create(ctx);
ctx[isBoundary] = 1
let d1 = ctx['iter'];
setContextValue(ctx, \\"iter\\", 'called');
let d2 = ctx['iter'];
return block1([d1, d2]);
}
}"
`;
exports[`t-set t-set can't alter in t-call body 2`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
const callTemplate_2 = getTemplate(\`sub\`);
let block1 = createBlock(\`<div><p><block-text-0/></p><block-child-0/><p><block-text-1/></p></div>\`); let block1 = createBlock(\`<div><p><block-text-0/></p><block-child-0/><p><block-text-1/></p></div>\`);
@@ -255,14 +242,33 @@ exports[`t-set t-set can't alter in t-call body 2`] = `
ctx = Object.create(ctx); ctx = Object.create(ctx);
ctx[isBoundary] = 1 ctx[isBoundary] = 1
setContextValue(ctx, \\"iter\\", 'source'); setContextValue(ctx, \\"iter\\", 'source');
let d1 = ctx['iter']; let txt1 = ctx['iter'];
ctx = Object.create(ctx); ctx = Object.create(ctx);
ctx[isBoundary] = 1; ctx[isBoundary] = 1;
setContextValue(ctx, \\"iter\\", 'inCall'); setContextValue(ctx, \\"iter\\", 'inCall');
let b2 = callTemplate_2.call(this, ctx, node, key + \`__1\`); let b2 = callTemplate_1.call(this, ctx, node, key + \`__1\`);
ctx = ctx.__proto__; ctx = ctx.__proto__;
let d2 = ctx['iter']; let txt2 = ctx['iter'];
return block1([d1, d2], [b2]); return block1([txt1, txt2], [b2]);
}
}"
`;
exports[`t-set t-set can't alter in t-call body 2`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { isBoundary, withDefault, setContextValue } = helpers;
let block1 = createBlock(\`<div><block-text-0/><block-text-1/></div>\`);
return function template(ctx, node, key = \\"\\") {
ctx = Object.create(ctx);
ctx[isBoundary] = 1
let txt1 = ctx['iter'];
setContextValue(ctx, \\"iter\\", 'called');
let txt2 = ctx['iter'];
return block1([txt1, txt2]);
} }
}" }"
`; `;
@@ -270,8 +276,8 @@ exports[`t-set t-set can't alter in t-call body 2`] = `
exports[`t-set t-set does not modify render context existing key values 1`] = ` exports[`t-set t-set does not modify render context existing key values 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { isBoundary, withDefault, setContextValue } = helpers;
let block1 = createBlock(\`<div><block-text-0/></div>\`); let block1 = createBlock(\`<div><block-text-0/></div>\`);
@@ -279,8 +285,8 @@ exports[`t-set t-set does not modify render context existing key values 1`] = `
ctx = Object.create(ctx); ctx = Object.create(ctx);
ctx[isBoundary] = 1 ctx[isBoundary] = 1
setContextValue(ctx, \\"value\\", 35); setContextValue(ctx, \\"value\\", 35);
let d1 = ctx['value']; let txt1 = ctx['value'];
return block1([d1]); return block1([txt1]);
} }
}" }"
`; `;
@@ -288,8 +294,8 @@ exports[`t-set t-set does not modify render context existing key values 1`] = `
exports[`t-set t-set evaluates an expression only once 1`] = ` exports[`t-set t-set evaluates an expression only once 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { isBoundary, withDefault, setContextValue } = helpers;
let block1 = createBlock(\`<div><block-text-0/><block-text-1/></div>\`); let block1 = createBlock(\`<div><block-text-0/><block-text-1/></div>\`);
@@ -297,9 +303,9 @@ exports[`t-set t-set evaluates an expression only once 1`] = `
ctx = Object.create(ctx); ctx = Object.create(ctx);
ctx[isBoundary] = 1 ctx[isBoundary] = 1
setContextValue(ctx, \\"v\\", ctx['value']+' artois'); setContextValue(ctx, \\"v\\", ctx['value']+' artois');
let d1 = ctx['v']; let txt1 = ctx['v'];
let d2 = ctx['v']; let txt2 = ctx['v'];
return block1([d1, d2]); return block1([txt1, txt2]);
} }
}" }"
`; `;
@@ -307,8 +313,8 @@ exports[`t-set t-set evaluates an expression only once 1`] = `
exports[`t-set t-set outside modified in t-foreach 1`] = ` exports[`t-set t-set outside modified in t-foreach 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { isBoundary, withDefault, setContextValue, prepareList, withKey } = helpers;
let block1 = createBlock(\`<div><block-child-0/><p>EndLoop: <block-text-0/></p></div>\`); let block1 = createBlock(\`<div><block-child-0/><p>EndLoop: <block-text-0/></p></div>\`);
let block3 = createBlock(\`<p>InLoop: <block-text-0/></p>\`); let block3 = createBlock(\`<p>InLoop: <block-text-0/></p>\`);
@@ -322,14 +328,14 @@ exports[`t-set t-set outside modified in t-foreach 1`] = `
for (let i1 = 0; i1 < l_block2; i1++) { for (let i1 = 0; i1 < l_block2; i1++) {
ctx[\`val\`] = v_block2[i1]; ctx[\`val\`] = v_block2[i1];
let key1 = ctx['val']; let key1 = ctx['val'];
let d1 = ctx['iter']; let txt1 = ctx['iter'];
c_block2[i1] = withKey(block3([d1]), key1); c_block2[i1] = withKey(block3([txt1]), key1);
setContextValue(ctx, \\"iter\\", ctx['iter']+1); setContextValue(ctx, \\"iter\\", ctx['iter']+1);
} }
ctx = ctx.__proto__; ctx = ctx.__proto__;
let b2 = list(c_block2); let b2 = list(c_block2);
let d2 = ctx['iter']; let txt2 = ctx['iter'];
return block1([d2], [b2]); return block1([txt2], [b2]);
} }
}" }"
`; `;
@@ -337,8 +343,8 @@ exports[`t-set t-set outside modified in t-foreach 1`] = `
exports[`t-set t-set outside modified in t-foreach increment-after operator 1`] = ` exports[`t-set t-set outside modified in t-foreach increment-after operator 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { isBoundary, withDefault, setContextValue, prepareList, withKey } = helpers;
let block1 = createBlock(\`<div><block-child-0/><p>EndLoop: <block-text-0/></p></div>\`); let block1 = createBlock(\`<div><block-child-0/><p>EndLoop: <block-text-0/></p></div>\`);
let block3 = createBlock(\`<p>InLoop: <block-text-0/></p>\`); let block3 = createBlock(\`<p>InLoop: <block-text-0/></p>\`);
@@ -352,14 +358,14 @@ exports[`t-set t-set outside modified in t-foreach increment-after operator 1`]
for (let i1 = 0; i1 < l_block2; i1++) { for (let i1 = 0; i1 < l_block2; i1++) {
ctx[\`val\`] = v_block2[i1]; ctx[\`val\`] = v_block2[i1];
let key1 = ctx['val']; let key1 = ctx['val'];
let d1 = ctx['iter']; let txt1 = ctx['iter'];
c_block2[i1] = withKey(block3([d1]), key1); c_block2[i1] = withKey(block3([txt1]), key1);
setContextValue(ctx, \\"iter\\", ctx['iter']++); setContextValue(ctx, \\"iter\\", ctx['iter']++);
} }
ctx = ctx.__proto__; ctx = ctx.__proto__;
let b2 = list(c_block2); let b2 = list(c_block2);
let d2 = ctx['iter']; let txt2 = ctx['iter'];
return block1([d2], [b2]); return block1([txt2], [b2]);
} }
}" }"
`; `;
@@ -367,8 +373,8 @@ exports[`t-set t-set outside modified in t-foreach increment-after operator 1`]
exports[`t-set t-set outside modified in t-foreach increment-before operator 1`] = ` exports[`t-set t-set outside modified in t-foreach increment-before operator 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { isBoundary, withDefault, setContextValue, prepareList, withKey } = helpers;
let block1 = createBlock(\`<div><block-child-0/><p>EndLoop: <block-text-0/></p></div>\`); let block1 = createBlock(\`<div><block-child-0/><p>EndLoop: <block-text-0/></p></div>\`);
let block3 = createBlock(\`<p>InLoop: <block-text-0/></p>\`); let block3 = createBlock(\`<p>InLoop: <block-text-0/></p>\`);
@@ -382,14 +388,14 @@ exports[`t-set t-set outside modified in t-foreach increment-before operator 1`]
for (let i1 = 0; i1 < l_block2; i1++) { for (let i1 = 0; i1 < l_block2; i1++) {
ctx[\`val\`] = v_block2[i1]; ctx[\`val\`] = v_block2[i1];
let key1 = ctx['val']; let key1 = ctx['val'];
let d1 = ctx['iter']; let txt1 = ctx['iter'];
c_block2[i1] = withKey(block3([d1]), key1); c_block2[i1] = withKey(block3([txt1]), key1);
setContextValue(ctx, \\"iter\\", ++ctx['iter']); setContextValue(ctx, \\"iter\\", ++ctx['iter']);
} }
ctx = ctx.__proto__; ctx = ctx.__proto__;
let b2 = list(c_block2); let b2 = list(c_block2);
let d2 = ctx['iter']; let txt2 = ctx['iter'];
return block1([d2], [b2]); return block1([txt2], [b2]);
} }
}" }"
`; `;
@@ -397,8 +403,8 @@ exports[`t-set t-set outside modified in t-foreach increment-before operator 1`]
exports[`t-set t-set should reuse variable if possible 1`] = ` exports[`t-set t-set should reuse variable if possible 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { isBoundary, withDefault, setContextValue, prepareList, withKey } = helpers;
let block1 = createBlock(\`<div><block-child-0/></div>\`); let block1 = createBlock(\`<div><block-child-0/></div>\`);
let block3 = createBlock(\`<div><span>v<block-text-0/></span></div>\`); let block3 = createBlock(\`<div><span>v<block-text-0/></span></div>\`);
@@ -413,9 +419,9 @@ exports[`t-set t-set should reuse variable if possible 1`] = `
ctx[\`elem\`] = v_block2[i1]; ctx[\`elem\`] = v_block2[i1];
ctx[\`elem_index\`] = i1; ctx[\`elem_index\`] = i1;
let key1 = ctx['elem_index']; let key1 = ctx['elem_index'];
let d1 = ctx['v']; let txt1 = ctx['v'];
setContextValue(ctx, \\"v\\", ctx['elem']); setContextValue(ctx, \\"v\\", ctx['elem']);
c_block2[i1] = withKey(block3([d1]), key1); c_block2[i1] = withKey(block3([txt1]), key1);
} }
let b2 = list(c_block2); let b2 = list(c_block2);
return block1([], [b2]); return block1([], [b2]);
@@ -426,20 +432,23 @@ exports[`t-set t-set should reuse variable if possible 1`] = `
exports[`t-set t-set with content and sub t-esc 1`] = ` exports[`t-set t-set with content and sub t-esc 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { isBoundary, withDefault, LazyValue } = helpers;
let block1 = createBlock(\`<div><block-text-0/></div>\`); let block1 = createBlock(\`<div><block-text-0/></div>\`);
function value1(ctx, node, key = \\"\\") {
let b3 = text(ctx['beep']);
let b4 = text(\` boop\`);
return multi([b3, b4]);
}
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
let b3 = text(ctx['beep']); ctx[\`setvar\`] = new LazyValue(value1, ctx, node);
let b4 = text(\` boop\`); let txt1 = ctx['setvar'];
let b2 = multi([b3, b4]); return block1([txt1]);
ctx[\`setvar\`] = b2;
let d1 = ctx['setvar'];
return block1([d1]);
} }
}" }"
`; `;
@@ -447,20 +456,23 @@ exports[`t-set t-set with content and sub t-esc 1`] = `
exports[`t-set t-set with t-value (falsy) and body 1`] = ` exports[`t-set t-set with t-value (falsy) and body 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { isBoundary, withDefault, setContextValue, LazyValue, safeOutput } = helpers;
let block1 = createBlock(\`<div><block-child-0/></div>\`); let block1 = createBlock(\`<div><block-child-0/></div>\`);
let block2 = createBlock(\`<span><block-text-0/></span>\`); let block2 = createBlock(\`<span><block-text-0/></span>\`);
function value1(ctx, node, key = \\"\\") {
let txt1 = ctx['v1'];
return block2([txt1]);
}
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
setContextValue(ctx, \\"v3\\", false); setContextValue(ctx, \\"v3\\", false);
setContextValue(ctx, \\"v1\\", 'before'); setContextValue(ctx, \\"v1\\", 'before');
let d1 = ctx['v1']; ctx[\`v2\`] = withDefault(ctx['v3'], new LazyValue(value1, ctx, node));
let b2 = block2([d1]);
ctx[\`v2\`] = withDefault(ctx['v3'], b2);
setContextValue(ctx, \\"v1\\", 'after'); setContextValue(ctx, \\"v1\\", 'after');
setContextValue(ctx, \\"v3\\", true); setContextValue(ctx, \\"v3\\", true);
let b3 = safeOutput(ctx['v2']); let b3 = safeOutput(ctx['v2']);
@@ -472,20 +484,23 @@ exports[`t-set t-set with t-value (falsy) and body 1`] = `
exports[`t-set t-set with t-value (truthy) and body 1`] = ` exports[`t-set t-set with t-value (truthy) and body 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { isBoundary, withDefault, setContextValue, LazyValue, safeOutput } = helpers;
let block1 = createBlock(\`<div><block-child-0/></div>\`); let block1 = createBlock(\`<div><block-child-0/></div>\`);
let block2 = createBlock(\`<span><block-text-0/></span>\`); let block2 = createBlock(\`<span><block-text-0/></span>\`);
function value1(ctx, node, key = \\"\\") {
let txt1 = ctx['v1'];
return block2([txt1]);
}
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
setContextValue(ctx, \\"v3\\", 'Truthy'); setContextValue(ctx, \\"v3\\", 'Truthy');
setContextValue(ctx, \\"v1\\", 'before'); setContextValue(ctx, \\"v1\\", 'before');
let d1 = ctx['v1']; ctx[\`v2\`] = withDefault(ctx['v3'], new LazyValue(value1, ctx, node));
let b2 = block2([d1]);
ctx[\`v2\`] = withDefault(ctx['v3'], b2);
setContextValue(ctx, \\"v1\\", 'after'); setContextValue(ctx, \\"v1\\", 'after');
setContextValue(ctx, \\"v3\\", false); setContextValue(ctx, \\"v3\\", false);
let b3 = safeOutput(ctx['v2']); let b3 = safeOutput(ctx['v2']);
@@ -497,8 +512,8 @@ exports[`t-set t-set with t-value (truthy) and body 1`] = `
exports[`t-set t-set, t-if, and mix of expression/body lookup, 1 1`] = ` exports[`t-set t-set, t-if, and mix of expression/body lookup, 1 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { isBoundary, withDefault, setContextValue } = helpers;
let block1 = createBlock(\`<div><block-child-0/><block-child-0/><block-text-0/></div>\`); let block1 = createBlock(\`<div><block-child-0/><block-child-0/><block-text-0/></div>\`);
@@ -510,8 +525,8 @@ exports[`t-set t-set, t-if, and mix of expression/body lookup, 1 1`] = `
} else { } else {
setContextValue(ctx, \\"ourvar\\", 0); setContextValue(ctx, \\"ourvar\\", 0);
} }
let d1 = ctx['ourvar']; let txt1 = ctx['ourvar'];
return block1([d1]); return block1([txt1]);
} }
}" }"
`; `;
@@ -519,8 +534,8 @@ exports[`t-set t-set, t-if, and mix of expression/body lookup, 1 1`] = `
exports[`t-set t-set, t-if, and mix of expression/body lookup, 2 1`] = ` exports[`t-set t-set, t-if, and mix of expression/body lookup, 2 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { isBoundary, withDefault, setContextValue } = helpers;
let block1 = createBlock(\`<div><block-child-0/><block-child-0/><block-text-0/></div>\`); let block1 = createBlock(\`<div><block-child-0/><block-child-0/><block-text-0/></div>\`);
@@ -532,8 +547,8 @@ exports[`t-set t-set, t-if, and mix of expression/body lookup, 2 1`] = `
} else { } else {
setContextValue(ctx, \\"ourvar\\", \`0\`); setContextValue(ctx, \\"ourvar\\", \`0\`);
} }
let d1 = ctx['ourvar']; let txt1 = ctx['ourvar'];
return block1([d1]); return block1([txt1]);
} }
}" }"
`; `;
@@ -541,8 +556,8 @@ exports[`t-set t-set, t-if, and mix of expression/body lookup, 2 1`] = `
exports[`t-set t-set, t-if, and mix of expression/body lookup, 3 1`] = ` exports[`t-set t-set, t-if, and mix of expression/body lookup, 3 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { isBoundary, withDefault, setContextValue } = helpers;
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
ctx = Object.create(ctx); ctx = Object.create(ctx);
@@ -562,19 +577,22 @@ exports[`t-set t-set, t-if, and mix of expression/body lookup, 3 1`] = `
exports[`t-set value priority (with non text body 1`] = ` exports[`t-set value priority (with non text body 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { isBoundary, withDefault, LazyValue } = helpers;
let block1 = createBlock(\`<div><block-text-0/></div>\`); let block1 = createBlock(\`<div><block-text-0/></div>\`);
let block2 = createBlock(\`<span>2</span>\`); let block2 = createBlock(\`<span>2</span>\`);
function value1(ctx, node, key = \\"\\") {
return block2();
}
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
let b2 = block2(); ctx[\`value\`] = withDefault(1, new LazyValue(value1, ctx, node));
ctx[\`value\`] = withDefault(1, b2); let txt1 = ctx['value'];
let d1 = ctx['value']; return block1([txt1]);
return block1([d1]);
} }
}" }"
`; `;
@@ -582,8 +600,8 @@ exports[`t-set value priority (with non text body 1`] = `
exports[`t-set value priority 1`] = ` exports[`t-set value priority 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { isBoundary, withDefault, setContextValue } = helpers;
let block1 = createBlock(\`<div><block-text-0/></div>\`); let block1 = createBlock(\`<div><block-text-0/></div>\`);
@@ -591,8 +609,8 @@ exports[`t-set value priority 1`] = `
ctx = Object.create(ctx); ctx = Object.create(ctx);
ctx[isBoundary] = 1 ctx[isBoundary] = 1
setContextValue(ctx, \\"value\\", withDefault(1, \`2\`)); setContextValue(ctx, \\"value\\", withDefault(1, \`2\`));
let d1 = ctx['value']; let txt1 = ctx['value'];
return block1([d1]); return block1([txt1]);
} }
}" }"
`; `;
@@ -3,8 +3,7 @@
exports[`qweb t-tag can fallback if falsy tag 1`] = ` exports[`qweb t-tag can fallback if falsy tag 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = tag => createBlock(\`<\${tag || 'fallback'}/>\`); let block1 = tag => createBlock(\`<\${tag || 'fallback'}/>\`);
@@ -18,8 +17,7 @@ exports[`qweb t-tag can fallback if falsy tag 1`] = `
exports[`qweb t-tag can update 1`] = ` exports[`qweb t-tag can update 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = tag => createBlock(\`<\${tag || 't'}/>\`); let block1 = tag => createBlock(\`<\${tag || 't'}/>\`);
@@ -33,8 +31,7 @@ exports[`qweb t-tag can update 1`] = `
exports[`qweb t-tag simple usecases 1`] = ` exports[`qweb t-tag simple usecases 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = tag => createBlock(\`<\${tag || 't'}/>\`); let block1 = tag => createBlock(\`<\${tag || 't'}/>\`);
@@ -48,8 +45,7 @@ exports[`qweb t-tag simple usecases 1`] = `
exports[`qweb t-tag simple usecases 2`] = ` exports[`qweb t-tag simple usecases 2`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = tag => createBlock(\`<\${tag || 't'}>text</\${tag || 't'}>\`); let block1 = tag => createBlock(\`<\${tag || 't'}>text</\${tag || 't'}>\`);
@@ -63,8 +59,7 @@ exports[`qweb t-tag simple usecases 2`] = `
exports[`qweb t-tag with multiple attributes 1`] = ` exports[`qweb t-tag with multiple attributes 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = tag => createBlock(\`<\${tag || 't'} class=\\"blueberry\\" taste=\\"raspberry\\">gooseberry</\${tag || 't'}>\`); let block1 = tag => createBlock(\`<\${tag || 't'} class=\\"blueberry\\" taste=\\"raspberry\\">gooseberry</\${tag || 't'}>\`);
@@ -78,8 +73,7 @@ exports[`qweb t-tag with multiple attributes 1`] = `
exports[`qweb t-tag with multiple child nodes 1`] = ` exports[`qweb t-tag with multiple child nodes 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = tag => createBlock(\`<\${tag || 't'}> pear <span>apple</span> strawberry </\${tag || 't'}>\`); let block1 = tag => createBlock(\`<\${tag || 't'}> pear <span>apple</span> strawberry </\${tag || 't'}>\`);
@@ -93,8 +87,7 @@ exports[`qweb t-tag with multiple child nodes 1`] = `
exports[`qweb t-tag with multiple t-tag in same template 1`] = ` exports[`qweb t-tag with multiple t-tag in same template 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = tag => createBlock(\`<\${tag || 't'}><block-child-0/></\${tag || 't'}>\`); let block1 = tag => createBlock(\`<\${tag || 't'}><block-child-0/></\${tag || 't'}>\`);
let block2 = tag => createBlock(\`<\${tag || 't'}>baz</\${tag || 't'}>\`); let block2 = tag => createBlock(\`<\${tag || 't'}>baz</\${tag || 't'}>\`);
@@ -111,8 +104,7 @@ exports[`qweb t-tag with multiple t-tag in same template 1`] = `
exports[`qweb t-tag with multiple t-tag in same template, part 2 1`] = ` exports[`qweb t-tag with multiple t-tag in same template, part 2 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block2 = tag => createBlock(\`<\${tag || 't'}>bar</\${tag || 't'}>\`); let block2 = tag => createBlock(\`<\${tag || 't'}>bar</\${tag || 't'}>\`);
let block3 = tag => createBlock(\`<\${tag || 't'}>baz</\${tag || 't'}>\`); let block3 = tag => createBlock(\`<\${tag || 't'}>baz</\${tag || 't'}>\`);
@@ -3,8 +3,7 @@
exports[`loading templates can initialize qweb with a string 1`] = ` exports[`loading templates can initialize qweb with a string 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div>jupiler</div>\`); let block1 = createBlock(\`<div>jupiler</div>\`);
@@ -17,8 +16,7 @@ exports[`loading templates can initialize qweb with a string 1`] = `
exports[`loading templates can initialize qweb with an XMLDocument 1`] = ` exports[`loading templates can initialize qweb with an XMLDocument 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div>jupiler</div>\`); let block1 = createBlock(\`<div>jupiler</div>\`);
@@ -31,16 +29,15 @@ exports[`loading templates can initialize qweb with an XMLDocument 1`] = `
exports[`loading templates can load a few templates from a xml string 1`] = ` exports[`loading templates can load a few templates from a xml string 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { getTemplate } = helpers;
const callTemplate_1 = getTemplate(\`items\`);
let block2 = createBlock(\`<li>ok</li>\`); let block1 = createBlock(\`<ul><block-child-0/></ul>\`);
let block3 = createBlock(\`<li>foo</li>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let b2 = block2(); let b2 = callTemplate_1.call(this, ctx, node, key + \`__1\`);
let b3 = block3(); return block1([], [b2]);
return multi([b2, b3]);
} }
}" }"
`; `;
@@ -48,22 +45,7 @@ exports[`loading templates can load a few templates from a xml string 1`] = `
exports[`loading templates can load a few templates from a xml string 2`] = ` exports[`loading templates can load a few templates from a xml string 2`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<ul/>\`);
return function template(ctx, node, key = \\"\\") {
return block1();
}
}"
`;
exports[`loading templates can load a few templates from an XMLDocument 1`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block2 = createBlock(\`<li>ok</li>\`); let block2 = createBlock(\`<li>ok</li>\`);
let block3 = createBlock(\`<li>foo</li>\`); let block3 = createBlock(\`<li>foo</li>\`);
@@ -76,16 +58,34 @@ exports[`loading templates can load a few templates from an XMLDocument 1`] = `
}" }"
`; `;
exports[`loading templates can load a few templates from an XMLDocument 2`] = ` exports[`loading templates can load a few templates from an XMLDocument 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { getTemplate } = helpers;
const callTemplate_1 = getTemplate(\`items\`);
let block1 = createBlock(\`<ul/>\`); let block1 = createBlock(\`<ul><block-child-0/></ul>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return block1(); let b2 = callTemplate_1.call(this, ctx, node, key + \`__1\`);
return block1([], [b2]);
}
}"
`;
exports[`loading templates can load a few templates from an XMLDocument 2`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let block2 = createBlock(\`<li>ok</li>\`);
let block3 = createBlock(\`<li>foo</li>\`);
return function template(ctx, node, key = \\"\\") {
let b2 = block2();
let b3 = block3();
return multi([b2, b3]);
} }
}" }"
`; `;
@@ -3,8 +3,7 @@
exports[`translation support can set translatable attributes 1`] = ` exports[`translation support can set translatable attributes 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div tomato=\\"word\\" potato=\\"mot\\" title=\\"word\\">text</div>\`); let block1 = createBlock(\`<div tomato=\\"word\\" potato=\\"mot\\" title=\\"word\\">text</div>\`);
@@ -17,8 +16,7 @@ exports[`translation support can set translatable attributes 1`] = `
exports[`translation support can translate node content 1`] = ` exports[`translation support can translate node content 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div>mot</div>\`); let block1 = createBlock(\`<div>mot</div>\`);
@@ -31,8 +29,7 @@ exports[`translation support can translate node content 1`] = `
exports[`translation support does not translate node content if disabled 1`] = ` exports[`translation support does not translate node content if disabled 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><span>mot</span><span>word</span></div>\`); let block1 = createBlock(\`<div><span>mot</span><span>word</span></div>\`);
@@ -45,8 +42,7 @@ exports[`translation support does not translate node content if disabled 1`] = `
exports[`translation support some attributes are translated 1`] = ` exports[`translation support some attributes are translated 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><p label=\\"mot\\">mot</p><p title=\\"mot\\">mot</p><p placeholder=\\"mot\\">mot</p><p alt=\\"mot\\">mot</p><p something=\\"word\\">mot</p></div>\`); let block1 = createBlock(\`<div><p label=\\"mot\\">mot</p><p title=\\"mot\\">mot</p><p placeholder=\\"mot\\">mot</p><p alt=\\"mot\\">mot</p><p something=\\"word\\">mot</p></div>\`);
@@ -59,8 +55,7 @@ exports[`translation support some attributes are translated 1`] = `
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(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div> mot </div>\`); let block1 = createBlock(\`<div> mot </div>\`);
@@ -3,8 +3,7 @@
exports[`white space handling consecutives whitespaces are condensed into a single space 1`] = ` exports[`white space handling consecutives whitespaces are condensed into a single space 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div> abc </div>\`); let block1 = createBlock(\`<div> abc </div>\`);
@@ -17,8 +16,7 @@ exports[`white space handling consecutives whitespaces are condensed into a sing
exports[`white space handling nothing is done in pre tags 1`] = ` exports[`white space handling nothing is done in pre tags 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<pre> </pre>\`); let block1 = createBlock(\`<pre> </pre>\`);
@@ -31,8 +29,7 @@ exports[`white space handling nothing is done in pre tags 1`] = `
exports[`white space handling nothing is done in pre tags 2`] = ` exports[`white space handling nothing is done in pre tags 2`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<pre> let block1 = createBlock(\`<pre>
some text some text
@@ -47,8 +44,7 @@ exports[`white space handling nothing is done in pre tags 2`] = `
exports[`white space handling nothing is done in pre tags 3`] = ` exports[`white space handling nothing is done in pre tags 3`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<pre> let block1 = createBlock(\`<pre>
@@ -60,11 +56,23 @@ exports[`white space handling nothing is done in pre tags 3`] = `
}" }"
`; `;
exports[`white space handling pre inside a div with a new line 1`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let block1 = createBlock(\`<div><pre>SomeText</pre></div>\`);
return function template(ctx, node, key = \\"\\") {
return block1();
}
}"
`;
exports[`white space handling white space only text nodes are condensed into a single space 1`] = ` exports[`white space handling white space only text nodes are condensed into a single space 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div> </div>\`); let block1 = createBlock(\`<div> </div>\`);
@@ -77,8 +85,7 @@ exports[`white space handling white space only text nodes are condensed into a s
exports[`white space handling whitespace only text nodes with newlines are removed 1`] = ` exports[`white space handling whitespace only text nodes with newlines are removed 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><span>abc</span></div>\`); let block1 = createBlock(\`<div><span>abc</span></div>\`);
+15 -5
View File
@@ -1,4 +1,3 @@
import { xml } from "../../src";
import { mount, patch } from "../../src/blockdom"; import { mount, patch } from "../../src/blockdom";
import { makeTestFixture, renderToBdom, renderToString, snapshotEverything } from "../helpers"; import { makeTestFixture, renderToBdom, renderToString, snapshotEverything } from "../helpers";
@@ -52,6 +51,18 @@ describe("attributes", () => {
expect(result).toBe(`<div></div>`); expect(result).toBe(`<div></div>`);
}); });
test("dynamic undefined generic attribute", () => {
const template = `<div t-att-thing="c"/>`;
const result = renderToString(template, { c: undefined });
expect(result).toBe(`<div></div>`);
});
test("dynamic undefined class attribute", () => {
const template = `<div t-att-class="c"/>`;
const result = renderToString(template, { c: undefined });
expect(result).toBe(`<div></div>`);
});
test("dynamic attribute with a dash", () => { test("dynamic attribute with a dash", () => {
const template = `<div t-att-data-action-id="id"/>`; const template = `<div t-att-data-action-id="id"/>`;
const result = renderToString(template, { id: 32 }); const result = renderToString(template, { id: 32 });
@@ -336,9 +347,8 @@ describe("special cases for some specific html attributes/properties", () => {
}); });
test("various boolean html attributes", () => { test("various boolean html attributes", () => {
// the unique assertion here is the code snapshot automatically done by // will cause the template to be snapshotted
// renderToString renderToString(`
xml`
<div> <div>
<input type="checkbox" checked="checked"/> <input type="checkbox" checked="checked"/>
<input checked="checked"/> <input checked="checked"/>
@@ -348,7 +358,7 @@ describe("special cases for some specific html attributes/properties", () => {
<input readonly="readonly"/> <input readonly="readonly"/>
<button disabled="disabled"/> <button disabled="disabled"/>
</div> </div>
`; `);
}); });
test("input with t-att-value", () => { test("input with t-att-value", () => {
+6 -6
View File
@@ -21,12 +21,12 @@ describe("error handling", () => {
expect(() => context.addTemplate("test", "<div/>")).toThrow("already defined"); expect(() => context.addTemplate("test", "<div/>")).toThrow("already defined");
}); });
// test("addTemplates throw if parser error", () => { test("addTemplates throw if parser error", () => {
// const context = new TestContext(); const context = new TestContext();
// expect(() => { expect(() => {
// context.addTemplates("<templates><abc>></templates>"); context.addTemplates("<templates><abc>></templates>");
// }).toThrow("Invalid XML in template"); }).toThrow("Invalid XML in template");
// }); });
test("nice error when t-on is evaluated with a missing event", () => { test("nice error when t-on is evaluated with a missing event", () => {
expect(() => renderToString(`<div t-on="somemethod"></div>`)).toThrow( expect(() => renderToString(`<div t-on="somemethod"></div>`)).toThrow(
+9 -4
View File
@@ -1,5 +1,10 @@
import { xml } from "../../src"; import {
import { renderToString, snapshotEverything, TestContext, trim } from "../helpers"; renderToString,
snapshotEverything,
snapshotTemplate,
TestContext,
trim,
} from "../helpers";
snapshotEverything(); snapshotEverything();
@@ -116,7 +121,7 @@ describe("misc", () => {
}); });
test("other complex template", () => { test("other complex template", () => {
xml` snapshotTemplate(`
<div> <div>
<header> <header>
<nav class="navbar navbar-expand-md navbar-light bg-light"> <nav class="navbar navbar-expand-md navbar-light bg-light">
@@ -257,6 +262,6 @@ describe("misc", () => {
</div> </div>
</div> </div>
</div> </div>
</div>`; </div>`);
}); });
}); });
+327 -14
View File
@@ -46,6 +46,7 @@ describe("qweb parser", () => {
on: {}, on: {},
ref: null, ref: null,
model: null, model: null,
ns: null,
}); });
}); });
@@ -73,6 +74,7 @@ describe("qweb parser", () => {
ref: null, ref: null,
model: null, model: null,
content: [], content: [],
ns: null,
}); });
}); });
@@ -86,6 +88,7 @@ describe("qweb parser", () => {
ref: null, ref: null,
model: null, model: null,
content: [{ type: ASTType.Text, value: "some text" }], content: [{ type: ASTType.Text, value: "some text" }],
ns: null,
}); });
}); });
@@ -98,6 +101,7 @@ describe("qweb parser", () => {
on: {}, on: {},
ref: null, ref: null,
model: null, model: null,
ns: null,
content: [ content: [
{ type: ASTType.Text, value: "some text" }, { type: ASTType.Text, value: "some text" },
{ {
@@ -108,6 +112,7 @@ describe("qweb parser", () => {
on: {}, on: {},
ref: null, ref: null,
model: null, model: null,
ns: null,
content: [{ type: ASTType.Text, value: "inside" }], content: [{ type: ASTType.Text, value: "inside" }],
}, },
], ],
@@ -126,6 +131,7 @@ describe("qweb parser", () => {
on: {}, on: {},
ref: null, ref: null,
model: null, model: null,
ns: null,
content: [], content: [],
}, },
{ {
@@ -136,12 +142,100 @@ describe("qweb parser", () => {
on: {}, on: {},
ref: null, ref: null,
model: null, model: null,
ns: null,
content: [], content: [],
}, },
], ],
}); });
}); });
test("dom node with t multi inside", async () => {
const template = `<div><t>Loading<t t-esc="abc"/></t></div>`;
expect(parse(template)).toEqual({
type: ASTType.DomNode,
tag: "div",
dynamicTag: null,
attrs: {},
on: {},
ref: null,
model: null,
ns: null,
content: [
{ type: ASTType.Text, value: "Loading" },
{ type: ASTType.TEsc, expr: "abc", defaultValue: "" },
],
});
});
test("dom node with multiple t multi inside", async () => {
const template = `
<div>
<t t-esc="a"/>
<t>
<t t-esc="b"/>
<t>Loading<t t-esc="c"/></t>
</t>
</div>`;
expect(parse(template)).toEqual({
type: ASTType.DomNode,
tag: "div",
dynamicTag: null,
attrs: {},
on: {},
ref: null,
model: null,
ns: null,
content: [
{ type: ASTType.TEsc, expr: "a", defaultValue: "" },
{ type: ASTType.TEsc, expr: "b", defaultValue: "" },
{ type: ASTType.Text, value: "Loading" },
{ type: ASTType.TEsc, expr: "c", defaultValue: "" },
],
});
});
test("dom node with t multi inside", async () => {
const template = `<div><t><t>Loading<t t-esc="abc"/></t></t></div>`;
expect(parse(template)).toEqual({
type: ASTType.DomNode,
tag: "div",
dynamicTag: null,
attrs: {},
on: {},
ref: null,
model: null,
ns: null,
content: [
{ type: ASTType.Text, value: "Loading" },
{ type: ASTType.TEsc, expr: "abc", defaultValue: "" },
],
});
});
test("dom node with two t multi inside", async () => {
const template = `
<div>
<t><t t-esc="a"/><t t-esc="b"/></t>
<t><t t-esc="c"/><t t-esc="d"/></t>
</div>`;
expect(parse(template)).toEqual({
type: ASTType.DomNode,
tag: "div",
dynamicTag: null,
attrs: {},
on: {},
ref: null,
model: null,
ns: null,
content: [
{ type: ASTType.TEsc, expr: "a", defaultValue: "" },
{ type: ASTType.TEsc, expr: "b", defaultValue: "" },
{ type: ASTType.TEsc, expr: "c", defaultValue: "" },
{ type: ASTType.TEsc, expr: "d", defaultValue: "" },
],
});
});
test("dom node next to text node", async () => { test("dom node next to text node", async () => {
expect(parse("some text<span></span>")).toEqual({ expect(parse("some text<span></span>")).toEqual({
type: ASTType.Multi, type: ASTType.Multi,
@@ -155,6 +249,7 @@ describe("qweb parser", () => {
on: {}, on: {},
ref: null, ref: null,
model: null, model: null,
ns: null,
content: [], content: [],
}, },
], ],
@@ -170,10 +265,109 @@ describe("qweb parser", () => {
on: {}, on: {},
ref: null, ref: null,
model: null, model: null,
ns: null,
content: [{ type: ASTType.Text, value: "foo" }], content: [{ type: ASTType.Text, value: "foo" }],
}); });
}); });
test("svg dom node", async () => {
expect(
parse(
`<svg width="100px" height="90px"><circle cx="50" cy="50" r="4" stroke="green" stroke-width="1" fill="yellow"/></svg>`
)
).toEqual({
attrs: {
height: "90px",
width: "100px",
},
content: [
{
attrs: {
cx: "50",
cy: "50",
fill: "yellow",
r: "4",
stroke: "green",
"stroke-width": "1",
},
content: [],
dynamicTag: null,
model: null,
ns: null,
on: {},
ref: null,
tag: "circle",
type: 2,
},
],
dynamicTag: null,
model: null,
ns: "http://www.w3.org/2000/svg",
on: {},
ref: null,
tag: "svg",
type: 2,
});
expect(
parse(`<g><circle cx="50" cy="50" r="4" stroke="green" stroke-width="1" fill="yellow"/></g>`)
).toEqual({
attrs: {},
content: [
{
attrs: {
cx: "50",
cy: "50",
fill: "yellow",
r: "4",
stroke: "green",
"stroke-width": "1",
},
content: [],
dynamicTag: null,
model: null,
ns: null,
on: {},
ref: null,
tag: "circle",
type: 2,
},
],
dynamicTag: null,
model: null,
ns: "http://www.w3.org/2000/svg",
on: {},
ref: null,
tag: "g",
type: 2,
});
});
test("pre dom node with new line", async () => {
expect(parse(`<div><pre />\n</div>`)).toEqual({
type: 2,
tag: "div",
dynamicTag: null,
attrs: {},
on: {},
ref: null,
content: [
{
type: 2,
tag: "pre",
dynamicTag: null,
attrs: {},
on: {},
ref: null,
content: [],
model: null,
ns: null,
},
],
model: null,
ns: null,
});
});
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// t-esc // t-esc
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@@ -200,6 +394,7 @@ describe("qweb parser", () => {
on: {}, on: {},
ref: null, ref: null,
model: null, model: null,
ns: null,
content: [{ type: ASTType.TEsc, expr: "text", defaultValue: "" }], content: [{ type: ASTType.TEsc, expr: "text", defaultValue: "" }],
}); });
}); });
@@ -221,6 +416,7 @@ describe("qweb parser", () => {
on: {}, on: {},
ref: null, ref: null,
model: null, model: null,
ns: null,
content: [{ type: ASTType.TEsc, expr: "text", defaultValue: "hey" }], content: [{ type: ASTType.TEsc, expr: "text", defaultValue: "hey" }],
}); });
}); });
@@ -262,6 +458,7 @@ describe("qweb parser", () => {
on: {}, on: {},
ref: null, ref: null,
model: null, model: null,
ns: null,
content: [{ type: ASTType.TOut, expr: "text", body: null }], content: [{ type: ASTType.TOut, expr: "text", body: null }],
}); });
}); });
@@ -275,6 +472,7 @@ describe("qweb parser", () => {
on: {}, on: {},
ref: null, ref: null,
model: null, model: null,
ns: null,
content: [ content: [
{ type: ASTType.TOut, expr: "text", body: [{ type: ASTType.Text, value: "body" }] }, { type: ASTType.TOut, expr: "text", body: [{ type: ASTType.Text, value: "body" }] },
], ],
@@ -294,6 +492,7 @@ describe("qweb parser", () => {
on: {}, on: {},
ref: null, ref: null,
model: null, model: null,
ns: null,
content: [ content: [
{ {
type: ASTType.TIf, type: ASTType.TIf,
@@ -309,6 +508,19 @@ describe("qweb parser", () => {
}); });
}); });
test("t-if with empty content", async () => {
expect(parse(`<t t-if="condition"></t>`)).toEqual({
type: ASTType.TIf,
condition: "condition",
content: {
type: ASTType.Text,
value: "",
},
tElif: null,
tElse: null,
});
});
test("t-if (on dom node", async () => { test("t-if (on dom node", async () => {
expect(parse(`<div t-if="condition">hey</div>`)).toEqual({ expect(parse(`<div t-if="condition">hey</div>`)).toEqual({
type: ASTType.TIf, type: ASTType.TIf,
@@ -321,6 +533,7 @@ describe("qweb parser", () => {
on: {}, on: {},
ref: null, ref: null,
model: null, model: null,
ns: null,
content: [{ type: ASTType.Text, value: "hey" }], content: [{ type: ASTType.Text, value: "hey" }],
}, },
tElif: null, tElif: null,
@@ -397,6 +610,7 @@ describe("qweb parser", () => {
on: {}, on: {},
ref: null, ref: null,
model: null, model: null,
ns: null,
content: [ content: [
{ {
type: ASTType.Text, type: ASTType.Text,
@@ -415,6 +629,7 @@ describe("qweb parser", () => {
on: {}, on: {},
ref: null, ref: null,
model: null, model: null,
ns: null,
content: [{ type: ASTType.Text, value: "elif" }], content: [{ type: ASTType.Text, value: "elif" }],
}, },
}, },
@@ -427,6 +642,7 @@ describe("qweb parser", () => {
on: {}, on: {},
ref: null, ref: null,
model: null, model: null,
ns: null,
content: [ content: [
{ {
type: ASTType.Text, type: ASTType.Text,
@@ -474,6 +690,7 @@ describe("qweb parser", () => {
dynamicTag: null, dynamicTag: null,
ref: null, ref: null,
model: null, model: null,
ns: null,
content: [{ type: ASTType.Text, value: "ok" }], content: [{ type: ASTType.Text, value: "ok" }],
}, },
], ],
@@ -493,6 +710,7 @@ describe("qweb parser", () => {
dynamicTag: null, dynamicTag: null,
ref: null, ref: null,
model: null, model: null,
ns: null,
content: [{ type: ASTType.Text, value: "ok" }], content: [{ type: ASTType.Text, value: "ok" }],
}, },
{ type: ASTType.Text, value: "abc" }, { type: ASTType.Text, value: "abc" },
@@ -527,6 +745,7 @@ describe("qweb parser", () => {
on: {}, on: {},
ref: null, ref: null,
model: null, model: null,
ns: null,
content: [ content: [
{ {
type: ASTType.TIf, type: ASTType.TIf,
@@ -601,6 +820,7 @@ describe("qweb parser", () => {
on: {}, on: {},
ref: null, ref: null,
model: null, model: null,
ns: null,
content: [{ type: ASTType.TEsc, expr: "item", defaultValue: "" }], content: [{ type: ASTType.TEsc, expr: "item", defaultValue: "" }],
}, },
memo: "", memo: "",
@@ -646,6 +866,7 @@ describe("qweb parser", () => {
on: {}, on: {},
ref: null, ref: null,
model: null, model: null,
ns: null,
content: [{ type: ASTType.TEsc, expr: "item", defaultValue: "" }], content: [{ type: ASTType.TEsc, expr: "item", defaultValue: "" }],
}, },
memo: "", memo: "",
@@ -681,6 +902,7 @@ describe("qweb parser", () => {
on: {}, on: {},
ref: null, ref: null,
model: null, model: null,
ns: null,
content: [{ type: ASTType.TEsc, expr: "item", defaultValue: "" }], content: [{ type: ASTType.TEsc, expr: "item", defaultValue: "" }],
}, },
}, },
@@ -715,6 +937,7 @@ describe("qweb parser", () => {
on: {}, on: {},
ref: null, ref: null,
model: null, model: null,
ns: null,
content: [{ type: ASTType.TEsc, expr: "category.name", defaultValue: "" }], content: [{ type: ASTType.TEsc, expr: "category.name", defaultValue: "" }],
}, },
memo: "", memo: "",
@@ -736,6 +959,7 @@ describe("qweb parser", () => {
model: null, model: null,
tag: "div", tag: "div",
dynamicTag: null, dynamicTag: null,
ns: null,
content: [ content: [
{ {
type: ASTType.TForEach, type: ASTType.TForEach,
@@ -781,6 +1005,7 @@ describe("qweb parser", () => {
ref: null, ref: null,
model: null, model: null,
attrs: {}, attrs: {},
ns: null,
content: [{ type: ASTType.TEsc, expr: "item", defaultValue: "" }], content: [{ type: ASTType.TEsc, expr: "item", defaultValue: "" }],
}, },
memo: "", memo: "",
@@ -888,6 +1113,7 @@ describe("qweb parser", () => {
on: {}, on: {},
ref: null, ref: null,
model: null, model: null,
ns: null,
content: [ content: [
{ {
type: ASTType.TCall, type: ASTType.TCall,
@@ -925,6 +1151,7 @@ describe("qweb parser", () => {
on: { click: "add" }, on: { click: "add" },
ref: null, ref: null,
model: null, model: null,
ns: null,
content: [{ type: ASTType.Text, value: "Click" }], content: [{ type: ASTType.Text, value: "Click" }],
}); });
}); });
@@ -968,7 +1195,31 @@ describe("qweb parser", () => {
test("component with event handler", async () => { test("component with event handler", async () => {
expect(() => parse(`<MyComponent t-on-click="someMethod"/>`)).toThrow( expect(() => parse(`<MyComponent t-on-click="someMethod"/>`)).toThrow(
"t-on is no longer supported on Component node. Consider passing a callback in props." "t-on is no longer supported on components. Consider passing a callback in props."
);
});
test("component with t-ref", async () => {
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."
);
});
test("component with t-att", async () => {
expect(() => parse(`<MyComponent t-att="something"/>`)).toThrow(
"t-att makes no sense on component: props are already treated as expressions"
);
});
test("component with t-attf", async () => {
expect(() => parse(`<MyComponent t-attf="something"/>`)).toThrow(
"t-attf is not supported on components: use template strings for string interpolation in props"
);
});
test("component with other unsupported directive", async () => {
expect(() => parse(`<MyComponent t-something="5"/>`)).toThrow(
"unsupported directive on Component: t-something"
); );
}); });
@@ -979,7 +1230,22 @@ describe("qweb parser", () => {
dynamicProps: null, dynamicProps: null,
props: {}, props: {},
isDynamic: false, isDynamic: false,
slots: { default: { type: ASTType.Text, value: "foo" } }, slots: { default: { content: { type: ASTType.Text, value: "foo" } } },
});
});
test("a component with a default slot with attributes", async () => {
expect(
parse(`<MyComponent><t t-set-slot="default" param="param">foo</t></MyComponent>`)
).toEqual({
type: ASTType.TComponent,
name: "MyComponent",
dynamicProps: null,
props: {},
isDynamic: false,
slots: {
default: { content: { type: ASTType.Text, value: "foo" }, attrs: { param: "param" } },
},
}); });
}); });
@@ -992,6 +1258,7 @@ describe("qweb parser", () => {
props: {}, props: {},
slots: { slots: {
default: { default: {
content: {
type: ASTType.Multi, type: ASTType.Multi,
content: [ content: [
{ {
@@ -1003,6 +1270,7 @@ describe("qweb parser", () => {
ref: null, ref: null,
model: null, model: null,
on: {}, on: {},
ns: null,
}, },
{ {
type: ASTType.DomNode, type: ASTType.DomNode,
@@ -1013,10 +1281,12 @@ describe("qweb parser", () => {
ref: null, ref: null,
model: null, model: null,
on: {}, on: {},
ns: null,
}, },
], ],
}, },
}, },
},
}); });
}); });
@@ -1027,10 +1297,27 @@ describe("qweb parser", () => {
isDynamic: false, isDynamic: false,
dynamicProps: null, dynamicProps: null,
props: {}, props: {},
slots: { name: { type: ASTType.Text, value: "foo" } }, slots: { name: { content: { type: ASTType.Text, value: "foo" } } },
}); });
}); });
test("a component with a named slot with attributes", async () => {
expect(parse(`<MyComponent><t t-set-slot="name" param="param">foo</t></MyComponent>`)).toEqual({
type: ASTType.TComponent,
name: "MyComponent",
isDynamic: false,
dynamicProps: null,
props: {},
slots: { name: { content: { type: ASTType.Text, value: "foo" }, attrs: { param: "param" } } },
});
});
test("a component with a named slot with div tag", async () => {
expect(() =>
parse(`<MyComponent><div t-set-slot="name">foo</div></MyComponent>`)
).toThrowError();
});
test("a component with a named slot and some white space", async () => { test("a component with a named slot and some white space", async () => {
expect(parse(`<MyComponent><t t-set-slot="name">foo</t> </MyComponent>`)).toEqual({ expect(parse(`<MyComponent><t t-set-slot="name">foo</t> </MyComponent>`)).toEqual({
type: ASTType.TComponent, type: ASTType.TComponent,
@@ -1039,8 +1326,8 @@ describe("qweb parser", () => {
props: {}, props: {},
isDynamic: false, isDynamic: false,
slots: { slots: {
default: { type: ASTType.Text, value: " " }, default: { content: { type: ASTType.Text, value: " " } },
name: { type: ASTType.Text, value: "foo" }, name: { content: { type: ASTType.Text, value: "foo" } },
}, },
}); });
}); });
@@ -1058,8 +1345,8 @@ describe("qweb parser", () => {
props: {}, props: {},
isDynamic: false, isDynamic: false,
slots: { slots: {
a: { type: ASTType.Text, value: "foo" }, a: { content: { type: ASTType.Text, value: "foo" } },
b: { type: ASTType.Text, value: "bar" }, b: { content: { type: ASTType.Text, value: "bar" } },
}, },
}); });
}); });
@@ -1098,8 +1385,14 @@ describe("qweb parser", () => {
}); });
test("component with t-esc", async () => { test("component with t-esc", async () => {
expect(() => parse(`<MyComponent t-esc="someValue"/>`)).toThrow( expect(parse(`<MyComponent t-esc="someValue"/>`)).toEqual(
"t-esc is not supported on Component nodes" parse(`<MyComponent><t t-esc="someValue"/></MyComponent>`)
);
});
test("component with t-esc and content", async () => {
expect(() => parse(`<MyComponent t-esc="someValue">Some content</MyComponent>`)).toThrow(
"Cannot have t-esc on a component that already has content"
); );
}); });
@@ -1110,7 +1403,7 @@ describe("qweb parser", () => {
dynamicProps: null, dynamicProps: null,
props: {}, props: {},
isDynamic: false, isDynamic: false,
slots: { default: { body: null, name: "subTemplate", type: ASTType.TCall } }, slots: { default: { content: { body: null, name: "subTemplate", type: ASTType.TCall } } },
}); });
}); });
@@ -1130,12 +1423,14 @@ describe("qweb parser", () => {
isDynamic: false, isDynamic: false,
slots: { slots: {
default: { default: {
content: {
type: ASTType.TComponent, type: ASTType.TComponent,
isDynamic: false, isDynamic: false,
name: "Child", name: "Child",
dynamicProps: null, dynamicProps: null,
props: {}, props: {},
slots: { brol: { type: ASTType.Text, value: "coucou" } }, slots: { brol: { content: { type: ASTType.Text, value: "coucou" } } },
},
}, },
}, },
}); });
@@ -1145,7 +1440,7 @@ describe("qweb parser", () => {
const template = ` const template = `
<MyComponent> <MyComponent>
<Child> <Child>
<t><t t-set-slot="brol">coucou</t></t> <t t-set-slot="brol">coucou</t>
</Child> </Child>
</MyComponent> </MyComponent>
`; `;
@@ -1157,12 +1452,14 @@ describe("qweb parser", () => {
isDynamic: false, isDynamic: false,
slots: { slots: {
default: { default: {
content: {
type: ASTType.TComponent, type: ASTType.TComponent,
isDynamic: false, isDynamic: false,
name: "Child", name: "Child",
dynamicProps: null, dynamicProps: null,
props: {}, props: {},
slots: { brol: { type: ASTType.Text, value: "coucou" } }, slots: { brol: { content: { type: ASTType.Text, value: "coucou" } } },
},
}, },
}, },
}); });
@@ -1176,6 +1473,7 @@ describe("qweb parser", () => {
expect(parse(`<t t-slot="default"/>`)).toEqual({ expect(parse(`<t t-slot="default"/>`)).toEqual({
type: ASTType.TSlot, type: ASTType.TSlot,
name: "default", name: "default",
attrs: {},
defaultContent: null, defaultContent: null,
}); });
}); });
@@ -1184,6 +1482,7 @@ describe("qweb parser", () => {
expect(parse(`<t t-slot="header">default content</t>`)).toEqual({ expect(parse(`<t t-slot="header">default content</t>`)).toEqual({
type: ASTType.TSlot, type: ASTType.TSlot,
name: "header", name: "header",
attrs: {},
defaultContent: { type: ASTType.Text, value: "default content" }, defaultContent: { type: ASTType.Text, value: "default content" },
}); });
}); });
@@ -1203,6 +1502,7 @@ describe("qweb parser", () => {
on: {}, on: {},
ref: null, ref: null,
model: null, model: null,
ns: null,
content: [{ type: ASTType.Text, value: "hey" }], content: [{ type: ASTType.Text, value: "hey" }],
}, },
}); });
@@ -1220,6 +1520,7 @@ describe("qweb parser", () => {
on: {}, on: {},
ref: null, ref: null,
model: null, model: null,
ns: null,
content: [{ type: ASTType.Text, value: "hey" }], content: [{ type: ASTType.Text, value: "hey" }],
}, },
}); });
@@ -1238,6 +1539,7 @@ describe("qweb parser", () => {
on: {}, on: {},
ref: "name", ref: "name",
model: null, model: null,
ns: null,
content: [{ type: ASTType.Text, value: "hey" }], content: [{ type: ASTType.Text, value: "hey" }],
}); });
}); });
@@ -1251,6 +1553,7 @@ describe("qweb parser", () => {
on: {}, on: {},
ref: "name", ref: "name",
model: null, model: null,
ns: null,
content: [ content: [
{ type: ASTType.TOut, expr: "text", body: [{ type: ASTType.Text, value: "body" }] }, { type: ASTType.TOut, expr: "text", body: [{ type: ASTType.Text, value: "body" }] },
], ],
@@ -1266,6 +1569,7 @@ describe("qweb parser", () => {
on: {}, on: {},
ref: "name", ref: "name",
model: null, model: null,
ns: null,
content: [{ type: ASTType.TEsc, expr: "text", defaultValue: "body" }], content: [{ type: ASTType.TEsc, expr: "text", defaultValue: "body" }],
}); });
}); });
@@ -1309,7 +1613,8 @@ describe("qweb parser", () => {
model: null, model: null,
tag: "div", tag: "div",
dynamicTag: null, dynamicTag: null,
type: 2, type: ASTType.DomNode,
ns: null,
}, },
type: 16, type: 16,
}, },
@@ -1339,6 +1644,7 @@ describe("qweb parser", () => {
ref: null, ref: null,
tag: "input", tag: "input",
dynamicTag: null, dynamicTag: null,
ns: null,
model: { model: {
baseExpr: "state", baseExpr: "state",
expr: "'stuff'", expr: "'stuff'",
@@ -1357,6 +1663,7 @@ describe("qweb parser", () => {
ref: null, ref: null,
tag: "input", tag: "input",
dynamicTag: null, dynamicTag: null,
ns: null,
model: { model: {
baseExpr: "state", baseExpr: "state",
expr: "'stuff'", expr: "'stuff'",
@@ -1375,6 +1682,7 @@ describe("qweb parser", () => {
ref: null, ref: null,
tag: "input", tag: "input",
dynamicTag: null, dynamicTag: null,
ns: null,
model: { model: {
baseExpr: "state", baseExpr: "state",
expr: "'stuff'", expr: "'stuff'",
@@ -1394,6 +1702,7 @@ describe("qweb parser", () => {
ref: null, ref: null,
tag: "textarea", tag: "textarea",
dynamicTag: null, dynamicTag: null,
ns: null,
model: { model: {
baseExpr: "state", baseExpr: "state",
expr: "'stuff'", expr: "'stuff'",
@@ -1412,6 +1721,7 @@ describe("qweb parser", () => {
ref: null, ref: null,
tag: "input", tag: "input",
dynamicTag: null, dynamicTag: null,
ns: null,
model: { model: {
baseExpr: "state", baseExpr: "state",
expr: "'stuff'", expr: "'stuff'",
@@ -1430,6 +1740,7 @@ describe("qweb parser", () => {
ref: null, ref: null,
tag: "input", tag: "input",
dynamicTag: null, dynamicTag: null,
ns: null,
model: { model: {
baseExpr: "state", baseExpr: "state",
expr: "'stuff'", expr: "'stuff'",
@@ -1448,6 +1759,7 @@ describe("qweb parser", () => {
ref: null, ref: null,
tag: "input", tag: "input",
dynamicTag: null, dynamicTag: null,
ns: null,
model: { model: {
baseExpr: "state", baseExpr: "state",
expr: "'stuff'", expr: "'stuff'",
@@ -1472,6 +1784,7 @@ describe("qweb parser", () => {
tag: "div", tag: "div",
dynamicTag: "theTag", dynamicTag: "theTag",
model: null, model: null,
ns: null,
}); });
}); });
}); });
+17
View File
@@ -137,4 +137,21 @@ describe("simple templates, mostly static", () => {
const template = '<t><t t-esc="`text ${v}`"/></t>'; const template = '<t><t t-esc="`text ${v}`"/></t>';
expect(renderToString(template, { v: "from context" })).toBe("text from context"); expect(renderToString(template, { v: "from context" })).toBe("text from context");
}); });
test("template with t tag with multiple content", () => {
const template = `<div><t>Loading<t t-if="false"/></t></div>`;
expect(renderToString(template)).toBe("<div>Loading</div>");
});
test("template with multiple t tag with multiple content", () => {
const template = `
<div>
<t t-esc="a"/>
<t>
<t t-esc="b"/>
<t>Loading<t t-esc="c"/></t>
</t>
</div>`;
expect(renderToString(template, { a: "a", b: "b", c: "c" })).toBe("<div>abLoadingc</div>");
});
}); });
+25 -17
View File
@@ -1,22 +1,30 @@
import { renderToString, snapshotEverything } from "../helpers";
// NB: check the snapshots to see where the SVG namespaces are added
snapshotEverything();
describe("properly support svg", () => { describe("properly support svg", () => {
test.skip("add proper namespace to svg", () => { test("add proper namespace to svg", () => {
// qweb.addTemplate( const template = `<svg width="100px" height="90px"><circle cx="50" cy="50" r="4" stroke="green" stroke-width="1" fill="yellow"/> </svg>`;
// "test", expect(renderToString(template)).toBe(
// `<svg width="100px" height="90px"><circle cx="50" cy="50" r="4" stroke="green" stroke-width="1" fill="yellow"/> </svg>` `<svg width=\"100px\" height=\"90px\"><circle cx=\"50\" cy=\"50\" r=\"4\" stroke=\"green\" stroke-width=\"1\" fill=\"yellow\"></circle> </svg>`
// ); );
// expect(renderToString(qweb, "test")).toBe(
// `<svg width=\"100px\" height=\"90px\"><circle cx=\"50\" cy=\"50\" r=\"4\" stroke=\"green\" stroke-width=\"1\" fill=\"yellow\"></circle> </svg>`
// );
}); });
test.skip("add proper namespace to g tags", () => { test("add proper namespace to g tags", () => {
// this is necessary if one wants to use components in a svg const template = `<g><circle cx="50" cy="50" r="4" stroke="green" stroke-width="1" fill="yellow"/> </g>`;
// qweb.addTemplate( expect(renderToString(template)).toBe(
// "test", `<g><circle cx=\"50\" cy=\"50\" r=\"4\" stroke=\"green\" stroke-width=\"1\" fill=\"yellow\"></circle> </g>`
// `<g><circle cx="50" cy="50" r="4" stroke="green" stroke-width="1" fill="yellow"/> </g>` );
// ); });
// expect(renderToString(qweb, "test")).toBe(
// `<g><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", () => {
// ); const template = `<svg><g/></svg>`;
expect(renderToString(template)).toBe(`<svg><g></g></svg>`);
});
test("namespace to svg tags added even if already in svg namespace", () => {
const template = `<svg><svg/></svg>`;
expect(renderToString(template)).toBe(`<svg><svg></svg></svg>`);
}); });
}); });
+5 -5
View File
@@ -1,4 +1,4 @@
import { renderToString, snapshotTemplateCode } from "../helpers"; import { renderToString, snapshotTemplate } from "../helpers";
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// debugging // debugging
@@ -9,7 +9,7 @@ describe("debugging", () => {
const consoleLog = console.log; const consoleLog = console.log;
console.log = jest.fn(); console.log = jest.fn();
const template = `<div t-debug=""><t t-if="true"><span t-debug="">hey</span></t></div>`; const template = `<div t-debug=""><t t-if="true"><span t-debug="">hey</span></t></div>`;
snapshotTemplateCode(template); snapshotTemplate(template);
expect(console.log).toHaveBeenCalledTimes(1); expect(console.log).toHaveBeenCalledTimes(1);
console.log = consoleLog; console.log = consoleLog;
}); });
@@ -18,9 +18,9 @@ describe("debugging", () => {
const consoleLog = console.log; const consoleLog = console.log;
console.log = jest.fn(); console.log = jest.fn();
let template = `<p t-debug="">coucou</p>`; let template = `<p t-debug="">coucou</p>`;
snapshotTemplateCode(template); snapshotTemplate(template);
template = `<div><t t-call="sub"/></div>`; template = `<div><t t-call="sub"/></div>`;
snapshotTemplateCode(template); snapshotTemplate(template);
expect(console.log).toHaveBeenCalledTimes(1); expect(console.log).toHaveBeenCalledTimes(1);
console.log = consoleLog; console.log = consoleLog;
}); });
@@ -33,7 +33,7 @@ describe("debugging", () => {
<t t-set="foo" t-value="42"/> <t t-set="foo" t-value="42"/>
<t t-log="foo + 3"/> <t t-log="foo + 3"/>
</div>`; </div>`;
snapshotTemplateCode(template); snapshotTemplate(template);
renderToString(template); renderToString(template);
expect(console.log).toHaveBeenCalledWith(45); expect(console.log).toHaveBeenCalledWith(45);
console.log = consoleLog; console.log = consoleLog;
+6
View File
@@ -16,6 +16,12 @@ describe("t-if", () => {
expect(renderToString(template, {})).toBe("<div></div>"); expect(renderToString(template, {})).toBe("<div></div>");
}); });
test("t-if with empty content", () => {
const template = `hello<t t-if="condition"/>`;
expect(renderToString(template, { condition: true })).toBe("hello");
expect(renderToString(template, { condition: false })).toBe("hello");
});
test("boolean value condition missing", () => { test("boolean value condition missing", () => {
const template = `<span><t t-if="condition">fail</t></span>`; const template = `<span><t t-if="condition">fail</t></span>`;
expect(renderToString(template)).toBe("<span></span>"); expect(renderToString(template)).toBe("<span></span>");
+14 -41
View File
@@ -1,9 +1,10 @@
import { App, Component } from "../../src"; import { Component, mount, xml } from "../../src";
import { makeTestFixture, snapshotApp } from "../helpers"; import { makeTestFixture, snapshotEverything } from "../helpers";
import { xml } from "../../src/tags";
let fixture: HTMLElement; let fixture: HTMLElement;
snapshotEverything();
beforeEach(() => { beforeEach(() => {
fixture = makeTestFixture(); fixture = makeTestFixture();
}); });
@@ -14,16 +15,10 @@ describe("translation support", () => {
static template = xml`<div>word</div>`; static template = xml`<div>word</div>`;
} }
const app = new App(SomeComponent); await mount(SomeComponent, fixture, {
app.configure({
translateFn: (expr: string) => (expr === "word" ? "mot" : expr), translateFn: (expr: string) => (expr === "word" ? "mot" : expr),
}); });
const comp = await app.mount(fixture); expect(fixture.innerHTML).toBe("<div>mot</div>");
const el = comp.el as HTMLElement;
expect(el.outerHTML).toBe("<div>mot</div>");
snapshotApp(app);
}); });
test("does not translate node content if disabled", async () => { test("does not translate node content if disabled", async () => {
@@ -36,16 +31,11 @@ describe("translation support", () => {
`; `;
} }
const app = new App(SomeComponent); await mount(SomeComponent, fixture, {
app.configure({
translateFn: (expr: string) => (expr === "word" ? "mot" : expr), translateFn: (expr: string) => (expr === "word" ? "mot" : expr),
}); });
const comp = await app.mount(fixture);
const el = comp.el as HTMLElement; expect(fixture.innerHTML).toBe("<div><span>mot</span><span>word</span></div>");
expect(el.outerHTML).toBe("<div><span>mot</span><span>word</span></div>");
snapshotApp(app);
}); });
test("some attributes are translated", async () => { test("some attributes are translated", async () => {
@@ -61,18 +51,12 @@ describe("translation support", () => {
`; `;
} }
const app = new App(SomeComponent); await mount(SomeComponent, fixture, {
app.configure({
translateFn: (expr: string) => (expr === "word" ? "mot" : expr), translateFn: (expr: string) => (expr === "word" ? "mot" : expr),
}); });
const comp = await app.mount(fixture); expect(fixture.innerHTML).toBe(
const el = comp.el as HTMLElement;
expect(el.outerHTML).toBe(
'<div><p label="mot">mot</p><p title="mot">mot</p><p placeholder="mot">mot</p><p alt="mot">mot</p><p something="word">mot</p></div>' '<div><p label="mot">mot</p><p title="mot">mot</p><p placeholder="mot">mot</p><p alt="mot">mot</p><p something="word">mot</p></div>'
); );
snapshotApp(app);
}); });
test("can set translatable attributes", async () => { test("can set translatable attributes", async () => {
@@ -82,16 +66,11 @@ describe("translation support", () => {
`; `;
} }
const app = new App(SomeComponent); await mount(SomeComponent, fixture, {
app.configure({
translateFn: (expr: string) => (expr === "word" ? "mot" : expr), translateFn: (expr: string) => (expr === "word" ? "mot" : expr),
translatableAttributes: ["potato"], translatableAttributes: ["potato"],
}); });
const comp = await app.mount(fixture); expect(fixture.innerHTML).toBe('<div tomato="word" potato="mot" title="word">text</div>');
const el = comp.el as HTMLElement;
expect(el.outerHTML).toBe('<div tomato="word" potato="mot" title="word">text</div>');
snapshotApp(app);
}); });
test("translation is done on the trimmed text, with extra spaces readded after", async () => { test("translation is done on the trimmed text, with extra spaces readded after", async () => {
@@ -103,14 +82,8 @@ describe("translation support", () => {
const translateFn = jest.fn((expr: string) => (expr === "word" ? "mot" : expr)); const translateFn = jest.fn((expr: string) => (expr === "word" ? "mot" : expr));
const app = new App(SomeComponent); await mount(SomeComponent, fixture, { translateFn });
app.configure({ translateFn }); expect(fixture.innerHTML).toBe("<div> mot </div>");
const comp = await app.mount(fixture);
const el = comp.el as HTMLElement;
expect(el.outerHTML).toBe("<div> mot </div>");
expect(translateFn).toHaveBeenCalledWith("word"); expect(translateFn).toHaveBeenCalledWith("word");
snapshotApp(app);
}); });
}); });
+2 -2
View File
@@ -1,5 +1,5 @@
import { TemplateSet } from "../../src/app/template_set"; import { TemplateSet } from "../../src/app/template_set";
import { renderToString, TestContext, compile } from "../helpers"; import { renderToString, snapshotTemplate, TestContext } from "../helpers";
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// basic validation // basic validation
@@ -21,7 +21,7 @@ describe("basic validation", () => {
test("invalid xml", () => { test("invalid xml", () => {
const template = "<div>"; const template = "<div>";
expect(() => compile(template)).toThrow("Invalid XML in template"); expect(() => snapshotTemplate(template)).toThrow("Invalid XML in template");
}); });
test("missing template in template set", () => { test("missing template in template set", () => {
+6
View File
@@ -39,4 +39,10 @@ describe("white space handling", () => {
</pre>`; </pre>`;
expect(renderToString(template3)).toBe(template3); expect(renderToString(template3)).toBe(template3);
}); });
test("pre inside a div with a new line", () => {
expect(renderToString(`<div><pre>SomeText</pre>\n</div>`)).toBe(
"<div><pre>SomeText</pre></div>"
);
});
}); });
@@ -1,15 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`app destroy remove the widget from the DOM 1`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div/>\`);
return function template(ctx, node, key = \\"\\") {
return block1();
}
}"
`;
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -3,8 +3,23 @@
exports[`event handling handler receive the event as argument 1`] = ` exports[`event handling handler receive the event as argument 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<span block-handler-0=\\"click\\"><block-child-0/><block-text-1/></span>\`);
return function template(ctx, node, key = \\"\\") {
let hdlr1 = [ctx['inc'], ctx];
let b2 = component(\`Child\`, {}, key+\`__1\`,null, node, ctx);
let txt1 = ctx['state'].value;
return block1([hdlr1, txt1], [b2]);
}
}"
`;
exports[`event handling handler receive the event as argument 2`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let block1 = createBlock(\`<div>simple vnode</div>\`); let block1 = createBlock(\`<div>simple vnode</div>\`);
@@ -14,46 +29,11 @@ exports[`event handling handler receive the event as argument 1`] = `
}" }"
`; `;
exports[`event handling handler receive the event as argument 2`] = ` exports[`event handling objects from scope are properly captured by t-on 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { prepareList, withKey } = helpers;
let block1 = createBlock(\`<span block-handler-0=\\"click\\"><block-child-0/><block-text-1/></span>\`);
return function template(ctx, node, key = \\"\\") {
const v1 = ctx['inc'];
let d1 = [v1, ctx];
let b2 = component(\`Child\`, {}, key + \`__2\`, node, ctx);
let d2 = ctx['state'].value;
return block1([d1, d2], [b2]);
}
}"
`;
exports[`event handling support for callable expression in event handler 1`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><block-text-0/><input type=\\"text\\" block-handler-1=\\"input\\"/></div>\`);
return function template(ctx, node, key = \\"\\") {
let d1 = ctx['state'].value;
const v1 = ctx['obj'];
let d2 = [v1.onInput, ctx];
return block1([d1, d2]);
}
}"
`;
exports[`event handling t-on with handler bound to dynamic argument on a t-foreach 1`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><block-child-0/></div>\`); let block1 = createBlock(\`<div><block-child-0/></div>\`);
let block3 = createBlock(\`<div class=\\"item\\" block-handler-0=\\"click\\"/>\`); let block3 = createBlock(\`<div class=\\"item\\" block-handler-0=\\"click\\"/>\`);
@@ -66,8 +46,49 @@ exports[`event handling t-on with handler bound to dynamic argument on a t-forea
let key1 = ctx['item']; let key1 = ctx['item'];
const v1 = ctx['onClick']; const v1 = ctx['onClick'];
const v2 = ctx['item']; const v2 = ctx['item'];
let d1 = [ev=>v1(v2,ev), ctx]; let hdlr1 = [ev=>v1(v2.val,ev), ctx];
c_block2[i1] = withKey(block3([d1]), key1); c_block2[i1] = withKey(block3([hdlr1]), key1);
}
let b2 = list(c_block2);
return block1([], [b2]);
}
}"
`;
exports[`event handling support for callable expression in event handler 1`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let block1 = createBlock(\`<div><block-text-0/><input type=\\"text\\" block-handler-1=\\"input\\"/></div>\`);
return function template(ctx, node, key = \\"\\") {
let txt1 = ctx['state'].value;
let hdlr1 = [ctx['obj'].onInput, ctx];
return block1([txt1, hdlr1]);
}
}"
`;
exports[`event handling t-on with handler bound to dynamic argument on a t-foreach 1`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { prepareList, withKey } = helpers;
let block1 = createBlock(\`<div><block-child-0/></div>\`);
let block3 = createBlock(\`<div class=\\"item\\" block-handler-0=\\"click\\"/>\`);
return function template(ctx, node, key = \\"\\") {
ctx = Object.create(ctx);
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['items']);
for (let i1 = 0; i1 < l_block2; i1++) {
ctx[\`item\`] = v_block2[i1];
let key1 = ctx['item'];
const v1 = ctx['onClick'];
const v2 = ctx['item'];
let hdlr1 = [ev=>v1(v2,ev), ctx];
c_block2[i1] = withKey(block3([hdlr1]), key1);
} }
let b2 = list(c_block2); let b2 = list(c_block2);
return block1([], [b2]); return block1([], [b2]);
@@ -3,14 +3,10 @@
exports[`basics basic use 1`] = ` exports[`basics basic use 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<span>child<block-text-0/></span>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = ctx['props'].p; return component(\`Child\`, {p: 1}, key+\`__1\`,null, node, ctx);
return block1([d1]);
} }
}" }"
`; `;
@@ -18,11 +14,13 @@ exports[`basics basic use 1`] = `
exports[`basics basic use 2`] = ` exports[`basics basic use 2`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<span>child<block-text-0/></span>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return component(\`Child\`, {p: 1}, key + \`__1\`, node, ctx); let txt1 = ctx['props'].p;
return block1([txt1]);
} }
}" }"
`; `;
@@ -30,13 +28,17 @@ exports[`basics basic use 2`] = `
exports[`basics can select a sub widget 1`] = ` exports[`basics can select a sub widget 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<span>CHILD 1</span>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return block1(); let b2,b3;
if (ctx['env'].options.flag) {
b2 = component(\`Child\`, {}, key+\`__1\`,null, node, ctx);
}
if (!ctx['env'].options.flag) {
b3 = component(\`OtherChild\`, {}, key+\`__2\`,null, node, ctx);
}
return multi([b2, b3]);
} }
}" }"
`; `;
@@ -44,10 +46,9 @@ exports[`basics can select a sub widget 1`] = `
exports[`basics can select a sub widget 2`] = ` exports[`basics can select a sub widget 2`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div>CHILD 2</div>\`); let block1 = createBlock(\`<span>CHILD 1</span>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return block1(); return block1();
@@ -58,29 +59,9 @@ exports[`basics can select a sub widget 2`] = `
exports[`basics can select a sub widget 3`] = ` exports[`basics can select a sub widget 3`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
return function template(ctx, node, key = \\"\\") { let block1 = createBlock(\`<div>CHILD 2</div>\`);
let b2,b3;
if (ctx['env'].options.flag) {
b2 = component(\`Child\`, {}, key + \`__1\`, node, ctx);
}
if (!ctx['env'].options.flag) {
b3 = component(\`OtherChild\`, {}, key + \`__2\`, node, ctx);
}
return multi([b2, b3]);
}
}"
`;
exports[`basics can select a sub widget, part 2 1`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<span>CHILD 1</span>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return block1(); return block1();
@@ -88,13 +69,30 @@ exports[`basics can select a sub widget, part 2 1`] = `
}" }"
`; `;
exports[`basics can select a sub widget, part 2 1`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
return function template(ctx, node, key = \\"\\") {
let b2,b3;
if (ctx['state'].flag) {
b2 = component(\`Child\`, {}, key+\`__1\`,null, node, ctx);
}
if (!ctx['state'].flag) {
b3 = component(\`OtherChild\`, {}, key+\`__2\`,null, node, ctx);
}
return multi([b2, b3]);
}
}"
`;
exports[`basics can select a sub widget, part 2 2`] = ` exports[`basics can select a sub widget, part 2 2`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div>CHILD 2</div>\`); let block1 = createBlock(\`<span>CHILD 1</span>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return block1(); return block1();
@@ -105,18 +103,12 @@ exports[`basics can select a sub widget, part 2 2`] = `
exports[`basics can select a sub widget, part 2 3`] = ` exports[`basics can select a sub widget, part 2 3`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div>CHILD 2</div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let b2,b3; return block1();
if (ctx['state'].flag) {
b2 = component(\`Child\`, {}, key + \`__1\`, node, ctx);
}
if (!ctx['state'].flag) {
b3 = component(\`OtherChild\`, {}, key + \`__2\`, node, ctx);
}
return multi([b2, b3]);
} }
}" }"
`; `;
@@ -124,16 +116,10 @@ exports[`basics can select a sub widget, part 2 3`] = `
exports[`basics sub widget is interactive 1`] = ` exports[`basics sub widget is interactive 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<span><button block-handler-0=\\"click\\">click</button>child<block-text-1/></span>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const v1 = ctx['inc']; return component(\`Child\`, {p: 1}, key+\`__1\`,null, node, ctx);
let d1 = [v1, ctx];
let d2 = ctx['state'].val;
return block1([d1, d2]);
} }
}" }"
`; `;
@@ -141,11 +127,14 @@ exports[`basics sub widget is interactive 1`] = `
exports[`basics sub widget is interactive 2`] = ` exports[`basics sub widget is interactive 2`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<span><button block-handler-0=\\"click\\">click</button>child<block-text-1/></span>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return component(\`Child\`, {p: 1}, key + \`__1\`, node, ctx); let hdlr1 = [ctx['inc'], ctx];
let txt1 = ctx['state'].val;
return block1([hdlr1, txt1]);
} }
}" }"
`; `;
@@ -153,8 +142,32 @@ exports[`basics sub widget is interactive 2`] = `
exports[`basics top level sub widget with a parent 1`] = ` exports[`basics top level sub widget with a parent 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><block-child-0/></div>\`);
return function template(ctx, node, key = \\"\\") {
let b2 = component(\`ComponentB\`, {}, key+\`__1\`,null, node, ctx);
return block1([], [b2]);
}
}"
`;
exports[`basics top level sub widget with a parent 2`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
return function template(ctx, node, key = \\"\\") {
return component(\`ComponentC\`, {}, key+\`__1\`,null, node, ctx);
}
}"
`;
exports[`basics top level sub widget with a parent 3`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let block1 = createBlock(\`<span>Hello</span>\`); let block1 = createBlock(\`<span>Hello</span>\`);
@@ -163,30 +176,3 @@ exports[`basics top level sub widget with a parent 1`] = `
} }
}" }"
`; `;
exports[`basics top level sub widget with a parent 2`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
return function template(ctx, node, key = \\"\\") {
return component(\`ComponentC\`, {}, key + \`__1\`, node, ctx);
}
}"
`;
exports[`basics top level sub widget with a parent 3`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><block-child-0/></div>\`);
return function template(ctx, node, key = \\"\\") {
let b2 = component(\`ComponentB\`, {}, key + \`__1\`, node, ctx);
return block1([], [b2]);
}
}"
`;
+103 -75
View File
@@ -3,21 +3,20 @@
exports[`hooks autofocus hook input in a t-if 1`] = ` exports[`hooks autofocus hook input in a t-if 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><input block-ref=\\"0\\"/><block-child-0/></div>\`); let block1 = createBlock(\`<div><input block-ref=\\"0\\"/><block-child-0/></div>\`);
let block2 = createBlock(\`<input block-ref=\\"0\\"/>\`); let block2 = createBlock(\`<input block-ref=\\"0\\"/>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const refs = ctx.__owl__.refs; const refs = ctx.__owl__.refs;
const ref1 = (el) => refs[\`input1\`] = el;
const ref2 = (el) => refs[\`input2\`] = el;
let b2; let b2;
let d1 = (el) => refs[\`input1\`] = el;
if (ctx['state'].flag) { if (ctx['state'].flag) {
let d2 = (el) => refs[\`input2\`] = el; b2 = block2([ref2]);
b2 = block2([d2]);
} }
return block1([d1], [b2]); return block1([ref1], [b2]);
} }
}" }"
`; `;
@@ -25,16 +24,15 @@ exports[`hooks autofocus hook input in a t-if 1`] = `
exports[`hooks autofocus hook simple input 1`] = ` exports[`hooks autofocus hook simple input 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><input block-ref=\\"0\\"/><input block-ref=\\"1\\"/></div>\`); let block1 = createBlock(\`<div><input block-ref=\\"0\\"/><input block-ref=\\"1\\"/></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const refs = ctx.__owl__.refs; const refs = ctx.__owl__.refs;
let d1 = (el) => refs[\`input1\`] = el; const ref1 = (el) => refs[\`input1\`] = el;
let d2 = (el) => refs[\`input2\`] = el; const ref2 = (el) => refs[\`input2\`] = el;
return block1([d1, d2]); return block1([ref1, ref2]);
} }
}" }"
`; `;
@@ -42,14 +40,10 @@ exports[`hooks autofocus hook simple input 1`] = `
exports[`hooks can use onWillStart, onWillUpdateProps 1`] = ` exports[`hooks can use onWillStart, onWillUpdateProps 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<span><block-text-0/></span>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = ctx['props'].value; return component(\`MyComponent\`, {value: ctx['state'].value}, key+\`__1\`,null, node, ctx);
return block1([d1]);
} }
}" }"
`; `;
@@ -57,11 +51,13 @@ exports[`hooks can use onWillStart, onWillUpdateProps 1`] = `
exports[`hooks can use onWillStart, onWillUpdateProps 2`] = ` exports[`hooks can use onWillStart, onWillUpdateProps 2`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<span><block-text-0/></span>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return component(\`MyComponent\`, {value: ctx['state'].value}, key + \`__1\`, node, ctx); let txt1 = ctx['props'].value;
return block1([txt1]);
} }
}" }"
`; `;
@@ -69,8 +65,7 @@ exports[`hooks can use onWillStart, onWillUpdateProps 2`] = `
exports[`hooks can use useComponent 1`] = ` exports[`hooks can use useComponent 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div/>\`); let block1 = createBlock(\`<div/>\`);
@@ -83,14 +78,13 @@ exports[`hooks can use useComponent 1`] = `
exports[`hooks can use useEnv 1`] = ` exports[`hooks can use useEnv 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><block-text-0/></div>\`); let block1 = createBlock(\`<div><block-text-0/></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = ctx['env'].val; let txt1 = ctx['env'].val;
return block1([d1]); return block1([txt1]);
} }
}" }"
`; `;
@@ -98,14 +92,13 @@ exports[`hooks can use useEnv 1`] = `
exports[`hooks mounted callbacks should be called in reverse order from willUnmount callbacks 1`] = ` exports[`hooks mounted callbacks should be called in reverse order from willUnmount callbacks 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div>hey<block-text-0/></div>\`); let block1 = createBlock(\`<div>hey<block-text-0/></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = ctx['state'].value; let txt1 = ctx['state'].value;
return block1([d1]); return block1([txt1]);
} }
}" }"
`; `;
@@ -113,14 +106,12 @@ exports[`hooks mounted callbacks should be called in reverse order from willUnmo
exports[`hooks parent and child env 1`] = ` exports[`hooks parent and child env 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><block-text-0/></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = ctx['env'].val; let b2 = text(ctx['env'].val);
return block1([d1]); let b3 = component(\`Child\`, {}, key+\`__1\`,null, node, ctx);
return multi([b2, b3]);
} }
}" }"
`; `;
@@ -128,13 +119,13 @@ exports[`hooks parent and child env 1`] = `
exports[`hooks parent and child env 2`] = ` exports[`hooks parent and child env 2`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><block-text-0/></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let b2 = text(ctx['env'].val); let txt1 = ctx['env'].val;
let b3 = component(\`Child\`, {}, key + \`__1\`, node, ctx); return block1([txt1]);
return multi([b2, b3]);
} }
}" }"
`; `;
@@ -142,14 +133,13 @@ exports[`hooks parent and child env 2`] = `
exports[`hooks two different call to willPatch/patched should work 1`] = ` exports[`hooks two different call to willPatch/patched should work 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div>hey<block-text-0/></div>\`); let block1 = createBlock(\`<div>hey<block-text-0/></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = ctx['state'].value; let txt1 = ctx['state'].value;
return block1([d1]); return block1([txt1]);
} }
}" }"
`; `;
@@ -157,14 +147,39 @@ exports[`hooks two different call to willPatch/patched should work 1`] = `
exports[`hooks use sub env does not pollute user env 1`] = ` exports[`hooks use sub env does not pollute user env 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><block-text-0/></div>\`); let block1 = createBlock(\`<div><block-text-0/></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = ctx['env'].val; let txt1 = ctx['env'].val;
return block1([d1]); return block1([txt1]);
}
}"
`;
exports[`hooks use sub env supports arbitrary descriptor 1`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
return function template(ctx, node, key = \\"\\") {
return component(\`Child\`, {}, key+\`__1\`,null, node, ctx);
}
}"
`;
exports[`hooks use sub env supports arbitrary descriptor 2`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let block1 = createBlock(\`<div><block-text-0/> <block-text-1/></div>\`);
return function template(ctx, node, key = \\"\\") {
let txt1 = ctx['env'].someVal;
let txt2 = ctx['env'].someVal2;
return block1([txt1, txt2]);
} }
}" }"
`; `;
@@ -172,8 +187,7 @@ exports[`hooks use sub env does not pollute user env 1`] = `
exports[`hooks useEffect hook dependencies prevent effects from rerunning when unchanged 1`] = ` exports[`hooks useEffect hook dependencies prevent effects from rerunning when unchanged 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div/>\`); let block1 = createBlock(\`<div/>\`);
@@ -183,11 +197,29 @@ exports[`hooks useEffect hook dependencies prevent effects from rerunning when u
}" }"
`; `;
exports[`hooks useEffect hook effect can depend on stuff in dom 1`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let block2 = createBlock(\`<div block-ref=\\"0\\"/>\`);
return function template(ctx, node, key = \\"\\") {
const refs = ctx.__owl__.refs;
const ref1 = (el) => refs[\`div\`] = el;
let b2;
if (ctx['state'].value) {
b2 = block2([ref1]);
}
return multi([b2]);
}
}"
`;
exports[`hooks useEffect hook effect runs on mount, is reapplied on patch, and is cleaned up on unmount and before reapplying 1`] = ` exports[`hooks useEffect hook effect runs on mount, is reapplied on patch, and is cleaned up on unmount and before reapplying 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div/>\`); let block1 = createBlock(\`<div/>\`);
@@ -200,14 +232,13 @@ exports[`hooks useEffect hook effect runs on mount, is reapplied on patch, and i
exports[`hooks useEffect hook effect with empty dependency list never reruns 1`] = ` exports[`hooks useEffect hook effect with empty dependency list never reruns 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><block-text-0/></div>\`); let block1 = createBlock(\`<div><block-text-0/></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = ctx['state'].value; let txt1 = ctx['state'].value;
return block1([d1]); return block1([txt1]);
} }
}" }"
`; `;
@@ -215,14 +246,14 @@ exports[`hooks useEffect hook effect with empty dependency list never reruns 1`]
exports[`hooks useExternalListener 1`] = ` exports[`hooks useExternalListener 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<span><block-text-0/></span>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = ctx['props'].value; let b2;
return block1([d1]); if (ctx['state'].flag) {
b2 = component(\`MyComponent\`, {}, key+\`__1\`,null, node, ctx);
}
return multi([b2]);
} }
}" }"
`; `;
@@ -230,15 +261,13 @@ exports[`hooks useExternalListener 1`] = `
exports[`hooks useExternalListener 2`] = ` exports[`hooks useExternalListener 2`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<span><block-text-0/></span>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let b2; let txt1 = ctx['props'].value;
if (ctx['state'].flag) { return block1([txt1]);
b2 = component(\`MyComponent\`, {}, key + \`__1\`, node, ctx);
}
return multi([b2]);
} }
}" }"
`; `;
@@ -246,16 +275,15 @@ exports[`hooks useExternalListener 2`] = `
exports[`hooks useRef hook: basic use 1`] = ` exports[`hooks useRef hook: basic use 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><button block-ref=\\"0\\"><block-text-1/></button></div>\`); let block1 = createBlock(\`<div><button block-ref=\\"0\\"><block-text-1/></button></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const refs = ctx.__owl__.refs; const refs = ctx.__owl__.refs;
let d1 = (el) => refs[\`button\`] = el; const ref1 = (el) => refs[\`button\`] = el;
let d2 = ctx['value']; let txt1 = ctx['value'];
return block1([d1, d2]); return block1([ref1, txt1]);
} }
}" }"
`; `;
File diff suppressed because it is too large Load Diff
+222 -72
View File
@@ -3,14 +3,13 @@
exports[`basics accept ES6-like syntax for props (with getters) 1`] = ` exports[`basics accept ES6-like syntax for props (with getters) 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<span><block-text-0/></span>\`); let block1 = createBlock(\`<div><block-child-0/></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = ctx['props'].greetings; let b2 = component(\`Child\`, {greetings: ctx['greetings']}, key+\`__1\`,null, node, ctx);
return block1([d1]); return block1([], [b2]);
} }
}" }"
`; `;
@@ -18,14 +17,48 @@ exports[`basics accept ES6-like syntax for props (with getters) 1`] = `
exports[`basics accept ES6-like syntax for props (with getters) 2`] = ` exports[`basics accept ES6-like syntax for props (with getters) 2`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><block-child-0/></div>\`); let block1 = createBlock(\`<span><block-text-0/></span>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let b2 = component(\`Child\`, {greetings: ctx['greetings']}, key + \`__1\`, node, ctx); let txt1 = ctx['props'].greetings;
return block1([], [b2]); return block1([txt1]);
}
}"
`;
exports[`basics arrow functions as prop correctly capture their scope 1`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, 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['items']);
for (let i1 = 0; i1 < l_block1; i1++) {
ctx[\`item\`] = v_block1[i1];
let key1 = ctx['item'].val;
const v1 = ctx['onClick'];
const v2 = ctx['item'];
c_block1[i1] = withKey(component(\`Child\`, {onClick: ev=>v1(v2.val,ev)}, key+\`__1__\${key1}\`,null, node, ctx), key1);
}
return list(c_block1);
}
}"
`;
exports[`basics arrow functions as prop correctly capture their scope 2`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let block1 = createBlock(\`<button block-handler-0=\\"click\\"/>\`);
return function template(ctx, node, key = \\"\\") {
let hdlr1 = [ctx['props'].onClick, ctx];
return block1([hdlr1]);
} }
}" }"
`; `;
@@ -33,14 +66,13 @@ exports[`basics accept ES6-like syntax for props (with getters) 2`] = `
exports[`basics explicit object prop 1`] = ` exports[`basics explicit object prop 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<span><block-text-0/></span>\`); let block1 = createBlock(\`<div><block-child-0/></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = ctx['state'].someval; let b2 = component(\`Child\`, {value: ctx['state'].val}, key+\`__1\`,null, node, ctx);
return block1([d1]); return block1([], [b2]);
} }
}" }"
`; `;
@@ -48,14 +80,63 @@ exports[`basics explicit object prop 1`] = `
exports[`basics explicit object prop 2`] = ` exports[`basics explicit object prop 2`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><block-child-0/></div>\`); let block1 = createBlock(\`<span><block-text-0/></span>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let b2 = component(\`Child\`, {value: ctx['state'].val}, key + \`__1\`, node, ctx); let txt1 = ctx['state'].someval;
return block1([], [b2]); return block1([txt1]);
}
}"
`;
exports[`basics prop names can contain - 1`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
return function template(ctx, node, key = \\"\\") {
return component(\`Child\`, {'prop-name': 7}, key+\`__1\`,null, node, ctx);
}
}"
`;
exports[`basics prop names can contain - 2`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let block1 = createBlock(\`<div><block-text-0/></div>\`);
return function template(ctx, node, key = \\"\\") {
let txt1 = ctx['props']['prop-name'];
return block1([txt1]);
}
}"
`;
exports[`basics support prop names that aren't valid bare object property names 1`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
return function template(ctx, node, key = \\"\\") {
return component(\`Child\`, {'some-dashed-prop': 5,'a.b': 'keyword prop'}, key+\`__1\`,null, node, ctx);
}
}"
`;
exports[`basics support prop names that aren't valid bare object property names 2`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let block1 = createBlock(\`<button block-handler-0=\\"click\\"/>\`);
return function template(ctx, node, key = \\"\\") {
let hdlr1 = [ctx['props'].onClick, ctx];
return block1([hdlr1]);
} }
}" }"
`; `;
@@ -63,15 +144,22 @@ exports[`basics explicit object prop 2`] = `
exports[`basics t-set with a body expression can be passed in props, and then t-out 1`] = ` exports[`basics t-set with a body expression can be passed in props, and then t-out 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { isBoundary, withDefault, LazyValue } = helpers;
let block1 = createBlock(\`<span><block-text-0/><block-child-0/></span>\`); let block1 = createBlock(\`<div><block-child-0/></div>\`);
let block2 = createBlock(\`<p>43</p>\`);
function value1(ctx, node, key = \\"\\") {
return block2();
}
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = ctx['props'].val; ctx = Object.create(ctx);
let b2 = safeOutput(ctx['props'].val); ctx[isBoundary] = 1
return block1([d1], [b2]); ctx[\`abc\`] = new LazyValue(value1, ctx, node);
let b3 = component(\`Child\`, {val: ctx['abc']}, key+\`__1\`,null, node, ctx);
return block1([], [b3]);
} }
}" }"
`; `;
@@ -79,19 +167,15 @@ exports[`basics t-set with a body expression can be passed in props, and then t-
exports[`basics t-set with a body expression can be passed in props, and then t-out 2`] = ` exports[`basics t-set with a body expression can be passed in props, and then t-out 2`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { safeOutput } = helpers;
let block1 = createBlock(\`<div><block-child-0/></div>\`); let block1 = createBlock(\`<span><block-text-0/><block-child-0/></span>\`);
let block2 = createBlock(\`<p>43</p>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
ctx = Object.create(ctx); let txt1 = ctx['props'].val;
ctx[isBoundary] = 1 let b2 = safeOutput(ctx['props'].val);
let b2 = block2(); return block1([txt1], [b2]);
ctx[\`abc\`] = b2;
let b3 = component(\`Child\`, {val: ctx['abc']}, key + \`__1\`, node, ctx);
return block1([], [b3]);
} }
}" }"
`; `;
@@ -99,23 +183,8 @@ exports[`basics t-set with a body expression can be passed in props, and then t-
exports[`basics t-set with a body expression can be used as textual prop 1`] = ` exports[`basics t-set with a body expression can be used as textual prop 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { isBoundary, withDefault, setContextValue } = helpers;
let block1 = createBlock(\`<span><block-text-0/></span>\`);
return function template(ctx, node, key = \\"\\") {
let d1 = ctx['props'].val;
return block1([d1]);
}
}"
`;
exports[`basics t-set with a body expression can be used as textual prop 2`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><block-child-0/></div>\`); let block1 = createBlock(\`<div><block-child-0/></div>\`);
@@ -123,32 +192,31 @@ exports[`basics t-set with a body expression can be used as textual prop 2`] = `
ctx = Object.create(ctx); ctx = Object.create(ctx);
ctx[isBoundary] = 1 ctx[isBoundary] = 1
setContextValue(ctx, \\"abc\\", \`42\`); setContextValue(ctx, \\"abc\\", \`42\`);
let b2 = component(\`Child\`, {val: ctx['abc']}, key + \`__1\`, node, ctx); let b2 = component(\`Child\`, {val: ctx['abc']}, key+\`__1\`,null, node, ctx);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
`; `;
exports[`basics t-set with a body expression can be used as textual prop 2`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let block1 = createBlock(\`<span><block-text-0/></span>\`);
return function template(ctx, node, key = \\"\\") {
let txt1 = ctx['props'].val;
return block1([txt1]);
}
}"
`;
exports[`basics t-set works 1`] = ` exports[`basics t-set works 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { isBoundary, withDefault, setContextValue } = helpers;
let block1 = createBlock(\`<span><block-text-0/></span>\`);
return function template(ctx, node, key = \\"\\") {
let d1 = ctx['props'].val;
return block1([d1]);
}
}"
`;
exports[`basics t-set works 2`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><block-child-0/></div>\`); let block1 = createBlock(\`<div><block-child-0/></div>\`);
@@ -156,8 +224,90 @@ exports[`basics t-set works 2`] = `
ctx = Object.create(ctx); ctx = Object.create(ctx);
ctx[isBoundary] = 1 ctx[isBoundary] = 1
setContextValue(ctx, \\"val\\", 42); setContextValue(ctx, \\"val\\", 42);
let b2 = component(\`Child\`, {val: ctx['val']}, key + \`__1\`, node, ctx); let b2 = component(\`Child\`, {val: ctx['val']}, key+\`__1\`,null, node, ctx);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
`; `;
exports[`basics t-set works 2`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let block1 = createBlock(\`<span><block-text-0/></span>\`);
return function template(ctx, node, key = \\"\\") {
let txt1 = ctx['props'].val;
return block1([txt1]);
}
}"
`;
exports[`basics template string in prop 1`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
return function template(ctx, node, key = \\"\\") {
return component(\`Child\`, {propName: \`1\${ctx['someVal']}3\`}, key+\`__1\`,null, node, ctx);
}
}"
`;
exports[`basics template string in prop 2`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
return function template(ctx, node, key = \\"\\") {
return text(\`\`);
}
}"
`;
exports[`bound functions is referentially equal after update 1`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { bind } = helpers;
return function template(ctx, node, key = \\"\\") {
return component(\`Child\`, {val: ctx['state'].val,fn: bind(ctx, ctx['someFunction'])}, key+\`__1\`,null, node, ctx);
}
}"
`;
exports[`bound functions is referentially equal after update 2`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
return function template(ctx, node, key = \\"\\") {
return text(ctx['props'].val);
}
}"
`;
exports[`can bind function prop with bind suffix 1`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { bind } = helpers;
return function template(ctx, node, key = \\"\\") {
return component(\`Child\`, {doSomething: bind(ctx, ctx['doSomething'])}, key+\`__1\`,null, node, ctx);
}
}"
`;
exports[`can bind function prop with bind suffix 2`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
return function template(ctx, node, key = \\"\\") {
return text(\`child\`);
}
}"
`;
File diff suppressed because it is too large Load Diff
@@ -3,14 +3,13 @@
exports[`reactivity in lifecycle can use a state hook 1`] = ` exports[`reactivity in lifecycle can use a state hook 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><block-text-0/></div>\`); let block1 = createBlock(\`<div><block-text-0/></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = ctx['counter'].value; let txt1 = ctx['counter'].value;
return block1([d1]); return block1([txt1]);
} }
}" }"
`; `;
@@ -18,14 +17,13 @@ exports[`reactivity in lifecycle can use a state hook 1`] = `
exports[`reactivity in lifecycle can use a state hook 2 1`] = ` exports[`reactivity in lifecycle can use a state hook 2 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><block-text-0/></div>\`); let block1 = createBlock(\`<div><block-text-0/></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = ctx['state'].a; let txt1 = ctx['state'].a;
return block1([d1]); return block1([txt1]);
} }
}" }"
`; `;
@@ -33,14 +31,13 @@ exports[`reactivity in lifecycle can use a state hook 2 1`] = `
exports[`reactivity in lifecycle change state while mounting component 1`] = ` exports[`reactivity in lifecycle change state while mounting component 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><block-text-0/></div>\`); let block1 = createBlock(\`<div><block-text-0/></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = ctx['state'].val; let txt1 = ctx['state'].val;
return block1([d1]); return block1([txt1]);
} }
}" }"
`; `;
@@ -48,15 +45,16 @@ exports[`reactivity in lifecycle change state while mounting component 1`] = `
exports[`reactivity in lifecycle state changes in willUnmount do not trigger rerender 1`] = ` exports[`reactivity in lifecycle state changes in willUnmount do not trigger rerender 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<span><block-text-0/><block-text-1/></span>\`); let block1 = createBlock(\`<div><block-child-0/></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = ctx['props'].val; let b2;
let d2 = ctx['state'].n; if (ctx['state'].flag) {
return block1([d1, d2]); b2 = component(\`Child\`, {val: ctx['state'].val}, key+\`__1\`,null, node, ctx);
}
return block1([], [b2]);
} }
}" }"
`; `;
@@ -64,17 +62,14 @@ exports[`reactivity in lifecycle state changes in willUnmount do not trigger rer
exports[`reactivity in lifecycle state changes in willUnmount do not trigger rerender 2`] = ` exports[`reactivity in lifecycle state changes in willUnmount do not trigger rerender 2`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><block-child-0/></div>\`); let block1 = createBlock(\`<span><block-text-0/><block-text-1/></span>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let b2; let txt1 = ctx['props'].val;
if (ctx['state'].flag) { let txt2 = ctx['state'].n;
b2 = component(\`Child\`, {val: ctx['state'].val}, key + \`__1\`, node, ctx); return block1([txt1, txt2]);
}
return block1([], [b2]);
} }
}" }"
`; `;
@@ -3,15 +3,37 @@
exports[`refs basic use 1`] = ` exports[`refs basic use 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div block-ref=\\"0\\"/>\`); let block1 = createBlock(\`<div block-ref=\\"0\\"/>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const refs = ctx.__owl__.refs; const refs = ctx.__owl__.refs;
let d1 = (el) => refs[\`div\`] = el; const ref1 = (el) => refs[\`div\`] = el;
return block1([d1]); return block1([ref1]);
}
}"
`;
exports[`refs can use 2 refs with same name in a t-if/t-else situation 1`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { multiRefSetter } = helpers;
let block2 = createBlock(\`<div block-ref=\\"0\\"/>\`);
let block3 = createBlock(\`<span block-ref=\\"0\\"/>\`);
return function template(ctx, node, key = \\"\\") {
const refs = ctx.__owl__.refs;
const ref1 = multiRefSetter(refs, \`coucou\`);
let b2,b3;
if (ctx['state'].value) {
b2 = block2([ref1]);
} else {
b3 = block3([ref1]);
}
return multi([b2, b3]);
} }
}" }"
`; `;
@@ -19,14 +41,24 @@ exports[`refs basic use 1`] = `
exports[`refs refs are properly bound in slots 1`] = ` exports[`refs refs are properly bound in slots 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { capture } = helpers;
let block1 = createBlock(\`<span><block-child-0/></span>\`); let block1 = createBlock(\`<div><span class=\\"counter\\"><block-text-0/></span><block-child-0/></div>\`);
let block2 = createBlock(\`<button block-handler-0=\\"click\\" block-ref=\\"1\\">do something</button>\`);
function slot1(ctx, node, key = \\"\\") {
const refs = ctx.__owl__.refs;
const ref1 = (el) => refs[\`myButton\`] = el;
let hdlr1 = [ctx['doSomething'], ctx];
return block2([hdlr1, ref1]);
}
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let b2 = callSlot(ctx, node, key, 'footer'); let txt1 = ctx['state'].val;
return block1([], [b2]); const ctx1 = capture(ctx);
let b3 = component(\`Dialog\`, {slots: {'footer': {__render: slot1, __ctx: ctx1}}}, key+\`__1\`,null, node, ctx);
return block1([txt1], [b3]);
} }
}" }"
`; `;
@@ -34,27 +66,33 @@ exports[`refs refs are properly bound in slots 1`] = `
exports[`refs refs are properly bound in slots 2`] = ` exports[`refs refs are properly bound in slots 2`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { callSlot } = helpers;
let assign = Object.assign;
let block1 = createBlock(\`<div><span class=\\"counter\\"><block-text-0/></span><block-child-0/></div>\`); let block1 = createBlock(\`<span><block-child-0/></span>\`);
let block2 = createBlock(\`<button block-handler-0=\\"click\\" block-ref=\\"1\\">do something</button>\`);
const slot3 = ctx => (node, key) => {
const refs = ctx.__owl__.refs
const v4 = ctx['doSomething'];
let d2 = [v4, ctx];
let d3 = (el) => refs[\`myButton\`] = el;
return block2([d2, d3]);
}
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const refs = ctx.__owl__.refs; let b2 = callSlot(ctx, node, key, 'footer', false, {});
let d1 = ctx['state'].val; return block1([], [b2]);
const ctx2 = capture(ctx); }
let b3 = assign(component(\`Dialog\`, {}, key + \`__1\`, node, ctx), {slots: {'footer': slot3(ctx2)}}); }"
return block1([d1], [b3]); `;
exports[`refs throws if there are 2 same refs at the same time 1`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { multiRefSetter } = helpers;
let block2 = createBlock(\`<div block-ref=\\"0\\"/>\`);
let block3 = createBlock(\`<span block-ref=\\"0\\"/>\`);
return function template(ctx, node, key = \\"\\") {
const refs = ctx.__owl__.refs;
const ref1 = multiRefSetter(refs, \`coucou\`);
let b2 = block2([ref1]);
let b3 = block3([ref1]);
return multi([b2, b3]);
} }
}" }"
`; `;
File diff suppressed because it is too large Load Diff
@@ -3,17 +3,10 @@
exports[`style and class handling can set class on multi root component 1`] = ` exports[`style and class handling can set class on multi root component 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block2 = createBlock(\`<div>a</div>\`);
let block3 = createBlock(\`<span block-attribute-0=\\"class\\">b</span>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let b2 = block2(); return component(\`Child\`, {class: 'fromparent'}, key+\`__1\`,null, node, ctx);
let d1 = ctx['props'].class;
let b3 = block3([d1]);
return multi([b2, b3]);
} }
}" }"
`; `;
@@ -21,11 +14,16 @@ exports[`style and class handling can set class on multi root component 1`] = `
exports[`style and class handling can set class on multi root component 2`] = ` exports[`style and class handling can set class on multi root component 2`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block2 = createBlock(\`<div>a</div>\`);
let block3 = createBlock(\`<span block-attribute-0=\\"class\\">b</span>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return component(\`Child\`, {class: 'fromparent'}, key + \`__1\`, node, ctx); let b2 = block2();
let attr1 = ctx['props'].class;
let b3 = block3([attr1]);
return multi([b2, b3]);
} }
}" }"
`; `;
@@ -33,14 +31,10 @@ exports[`style and class handling can set class on multi root component 2`] = `
exports[`style and class handling can set class on sub component, as prop 1`] = ` exports[`style and class handling can set class on sub component, as prop 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div block-attribute-0=\\"class\\">child</div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = ctx['props'].class; return component(\`Child\`, {class: 'some-class'}, key+\`__1\`,null, node, ctx);
return block1([d1]);
} }
}" }"
`; `;
@@ -48,11 +42,13 @@ exports[`style and class handling can set class on sub component, as prop 1`] =
exports[`style and class handling can set class on sub component, as prop 2`] = ` exports[`style and class handling can set class on sub component, as prop 2`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div block-attribute-0=\\"class\\">child</div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return component(\`Child\`, {class: 'some-class'}, key + \`__1\`, node, ctx); let attr1 = ctx['props'].class;
return block1([attr1]);
} }
}" }"
`; `;
@@ -60,14 +56,10 @@ exports[`style and class handling can set class on sub component, as prop 2`] =
exports[`style and class handling can set class on sub sub component 1`] = ` exports[`style and class handling can set class on sub sub component 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div block-attribute-0=\\"class\\">childchild</div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = ctx['props'].class; return component(\`Child\`, {class: 'fromparent'}, key+\`__1\`,null, node, ctx);
return block1([d1]);
} }
}" }"
`; `;
@@ -75,11 +67,10 @@ exports[`style and class handling can set class on sub sub component 1`] = `
exports[`style and class handling can set class on sub sub component 2`] = ` exports[`style and class handling can set class on sub sub component 2`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return component(\`ChildChild\`, {class: (ctx['props'].class||'')+' fromchild'}, key + \`__1\`, node, ctx); return component(\`ChildChild\`, {class: (ctx['props'].class||'')+' fromchild'}, key+\`__1\`,null, node, ctx);
} }
}" }"
`; `;
@@ -87,11 +78,13 @@ exports[`style and class handling can set class on sub sub component 2`] = `
exports[`style and class handling can set class on sub sub component 3`] = ` exports[`style and class handling can set class on sub sub component 3`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div block-attribute-0=\\"class\\">childchild</div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return component(\`Child\`, {class: 'fromparent'}, key + \`__1\`, node, ctx); let attr1 = ctx['props'].class;
return block1([attr1]);
} }
}" }"
`; `;
@@ -99,14 +92,10 @@ exports[`style and class handling can set class on sub sub component 3`] = `
exports[`style and class handling can set more than one class on sub component 1`] = ` exports[`style and class handling can set more than one class on sub component 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div block-attribute-0=\\"class\\">child</div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = ctx['props'].class; return component(\`Child\`, {class: 'a b'}, key+\`__1\`,null, node, ctx);
return block1([d1]);
} }
}" }"
`; `;
@@ -114,11 +103,13 @@ exports[`style and class handling can set more than one class on sub component 1
exports[`style and class handling can set more than one class on sub component 2`] = ` exports[`style and class handling can set more than one class on sub component 2`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div block-attribute-0=\\"class\\">child</div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return component(\`Child\`, {class: 'a b'}, key + \`__1\`, node, ctx); let attr1 = ctx['props'].class;
return block1([attr1]);
} }
}" }"
`; `;
@@ -126,8 +117,7 @@ exports[`style and class handling can set more than one class on sub component 2
exports[`style and class handling can set style and class inside component 1`] = ` exports[`style and class handling can set style and class inside component 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div style=\\"font-weight:bold;\\" class=\\"some-class\\">world</div>\`); let block1 = createBlock(\`<div style=\\"font-weight:bold;\\" class=\\"some-class\\">world</div>\`);
@@ -140,14 +130,13 @@ exports[`style and class handling can set style and class inside component 1`] =
exports[`style and class handling class on components do not interfere with user defined classes 1`] = ` exports[`style and class handling class on components do not interfere with user defined classes 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div block-attribute-0=\\"class\\"/>\`); let block1 = createBlock(\`<div block-attribute-0=\\"class\\"/>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = {c:ctx['state'].c}; let attr1 = {c:ctx['state'].c};
return block1([d1]); return block1([attr1]);
} }
}" }"
`; `;
@@ -155,14 +144,10 @@ exports[`style and class handling class on components do not interfere with user
exports[`style and class handling class on sub component, which is switched to another 1`] = ` exports[`style and class handling class on sub component, which is switched to another 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div block-attribute-0=\\"class\\">a</div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = ctx['props'].class; return component(\`Child\`, {class: 'someclass',child: ctx['state'].child}, key+\`__1\`,null, node, ctx);
return block1([d1]);
} }
}" }"
`; `;
@@ -170,14 +155,16 @@ exports[`style and class handling class on sub component, which is switched to a
exports[`style and class handling class on sub component, which is switched to another 2`] = ` exports[`style and class handling class on sub component, which is switched to another 2`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<span block-attribute-0=\\"class\\">b</span>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = ctx['props'].class; let b2,b3;
return block1([d1]); if (ctx['props'].child==='a') {
b2 = component(\`ChildA\`, {class: ctx['props'].class}, key+\`__1\`,null, node, ctx);
} else {
b3 = component(\`ChildB\`, {class: ctx['props'].class}, key+\`__2\`,null, node, ctx);
}
return multi([b2, b3]);
} }
}" }"
`; `;
@@ -185,17 +172,13 @@ exports[`style and class handling class on sub component, which is switched to a
exports[`style and class handling class on sub component, which is switched to another 3`] = ` exports[`style and class handling class on sub component, which is switched to another 3`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div block-attribute-0=\\"class\\">a</div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let b2,b3; let attr1 = ctx['props'].class;
if (ctx['props'].child==='a') { return block1([attr1]);
b2 = component(\`ChildA\`, {class: ctx['props'].class}, key + \`__1\`, node, ctx);
} else {
b3 = component(\`ChildB\`, {class: ctx['props'].class}, key + \`__2\`, node, ctx);
}
return multi([b2, b3]);
} }
}" }"
`; `;
@@ -203,11 +186,13 @@ exports[`style and class handling class on sub component, which is switched to a
exports[`style and class handling class on sub component, which is switched to another 4`] = ` exports[`style and class handling class on sub component, which is switched to another 4`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<span block-attribute-0=\\"class\\">b</span>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return component(\`Child\`, {class: 'someclass',child: ctx['state'].child}, key + \`__1\`, node, ctx); let attr1 = ctx['props'].class;
return block1([attr1]);
} }
}" }"
`; `;
@@ -215,14 +200,13 @@ exports[`style and class handling class on sub component, which is switched to a
exports[`style and class handling class with extra whitespaces (variation) 1`] = ` exports[`style and class handling class with extra whitespaces (variation) 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div block-attribute-0=\\"class\\"/>\`); let block1 = createBlock(\`<p><block-child-0/></p>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = ctx['props'].class; let b2 = component(\`Child\`, {class: 'a b c d'}, key+\`__1\`,null, node, ctx);
return block1([d1]); return block1([], [b2]);
} }
}" }"
`; `;
@@ -230,14 +214,13 @@ exports[`style and class handling class with extra whitespaces (variation) 1`] =
exports[`style and class handling class with extra whitespaces (variation) 2`] = ` exports[`style and class handling class with extra whitespaces (variation) 2`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<p><block-child-0/></p>\`); let block1 = createBlock(\`<div block-attribute-0=\\"class\\"/>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let b2 = component(\`Child\`, {class: 'a b c d'}, key + \`__1\`, node, ctx); let attr1 = ctx['props'].class;
return block1([], [b2]); return block1([attr1]);
} }
}" }"
`; `;
@@ -245,14 +228,10 @@ exports[`style and class handling class with extra whitespaces (variation) 2`] =
exports[`style and class handling class with extra whitespaces 1`] = ` exports[`style and class handling class with extra whitespaces 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div block-attribute-0=\\"class\\"/>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = ctx['props'].class; return component(\`Child\`, {class: 'a b c d'}, key+\`__1\`,null, node, ctx);
return block1([d1]);
} }
}" }"
`; `;
@@ -260,11 +239,13 @@ exports[`style and class handling class with extra whitespaces 1`] = `
exports[`style and class handling class with extra whitespaces 2`] = ` exports[`style and class handling class with extra whitespaces 2`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div block-attribute-0=\\"class\\"/>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return component(\`Child\`, {class: 'a b c d'}, key + \`__1\`, node, ctx); let attr1 = ctx['props'].class;
return block1([attr1]);
} }
}" }"
`; `;
@@ -272,14 +253,10 @@ exports[`style and class handling class with extra whitespaces 2`] = `
exports[`style and class handling component class and parent class combine together 1`] = ` exports[`style and class handling component class and parent class combine together 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div class=\\"child\\" block-attribute-0=\\"class\\">child</div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = ctx['props'].class; return component(\`Child\`, {class: 'from parent'}, key+\`__1\`,null, node, ctx);
return block1([d1]);
} }
}" }"
`; `;
@@ -287,11 +264,13 @@ exports[`style and class handling component class and parent class combine toget
exports[`style and class handling component class and parent class combine together 2`] = ` exports[`style and class handling component class and parent class combine together 2`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div class=\\"child\\" block-attribute-0=\\"class\\">child</div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return component(\`Child\`, {class: 'from parent'}, key + \`__1\`, node, ctx); let attr1 = ctx['props'].class;
return block1([attr1]);
} }
}" }"
`; `;
@@ -326,14 +305,13 @@ exports[`style and class handling dynamic t-att-style is properly added and upda
exports[`style and class handling empty class attribute is not added on widget root el 1`] = ` exports[`style and class handling empty class attribute is not added on widget root el 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<span block-attribute-0=\\"class\\"/>\`); let block1 = createBlock(\`<div><block-child-0/></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = ctx['props'].class; let b2 = component(\`Child\`, {class: undefined}, key+\`__1\`,null, node, ctx);
return block1([d1]); return block1([], [b2]);
} }
}" }"
`; `;
@@ -341,14 +319,13 @@ exports[`style and class handling empty class attribute is not added on widget r
exports[`style and class handling empty class attribute is not added on widget root el 2`] = ` exports[`style and class handling empty class attribute is not added on widget root el 2`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><block-child-0/></div>\`); let block1 = createBlock(\`<span block-attribute-0=\\"class\\"/>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let b2 = component(\`Child\`, {class: undefined}, key + \`__1\`, node, ctx); let attr1 = ctx['props'].class;
return block1([], [b2]); return block1([attr1]);
} }
}" }"
`; `;
@@ -356,15 +333,10 @@ exports[`style and class handling empty class attribute is not added on widget r
exports[`style and class handling error in subcomponent with class 1`] = ` exports[`style and class handling error in subcomponent with class 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div block-attribute-0=\\"class\\"><block-text-1/></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = ctx['props'].class; return component(\`Child\`, {class: 'a'}, key+\`__1\`,null, node, ctx);
let d2 = this.will.crash;
return block1([d1, d2]);
} }
}" }"
`; `;
@@ -372,11 +344,14 @@ exports[`style and class handling error in subcomponent with class 1`] = `
exports[`style and class handling error in subcomponent with class 2`] = ` exports[`style and class handling error in subcomponent with class 2`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div block-attribute-0=\\"class\\"><block-text-1/></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return component(\`Child\`, {class: 'a'}, key + \`__1\`, node, ctx); let attr1 = ctx['props'].class;
let txt1 = this.will.crash;
return block1([attr1, txt1]);
} }
}" }"
`; `;
@@ -384,8 +359,18 @@ exports[`style and class handling error in subcomponent with class 2`] = `
exports[`style and class handling no class is set is child ignores it 1`] = ` exports[`style and class handling no class is set is child ignores it 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
return function template(ctx, node, key = \\"\\") {
return component(\`Child\`, {class: 'hey'}, key+\`__1\`,null, node, ctx);
}
}"
`;
exports[`style and class handling no class is set is child ignores it 2`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let block1 = createBlock(\`<div>child</div>\`); let block1 = createBlock(\`<div>child</div>\`);
@@ -395,29 +380,13 @@ exports[`style and class handling no class is set is child ignores it 1`] = `
}" }"
`; `;
exports[`style and class handling no class is set is child ignores it 2`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
return function template(ctx, node, key = \\"\\") {
return component(\`Child\`, {class: 'hey'}, key + \`__1\`, node, ctx);
}
}"
`;
exports[`style and class handling no class is set is parent does not give it as prop 1`] = ` exports[`style and class handling no class is set is parent does not give it as prop 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div block-attribute-0=\\"class\\">child</div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = ctx['props'].class; return component(\`Child\`, {}, key+\`__1\`,null, node, ctx);
return block1([d1]);
} }
}" }"
`; `;
@@ -425,11 +394,13 @@ exports[`style and class handling no class is set is parent does not give it as
exports[`style and class handling no class is set is parent does not give it as prop 2`] = ` exports[`style and class handling no class is set is parent does not give it as prop 2`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div block-attribute-0=\\"class\\">child</div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return component(\`Child\`, {}, key + \`__1\`, node, ctx); let attr1 = ctx['props'].class;
return block1([attr1]);
} }
}" }"
`; `;
@@ -437,14 +408,10 @@ exports[`style and class handling no class is set is parent does not give it as
exports[`style and class handling style is properly added on widget root el 1`] = ` exports[`style and class handling style is properly added on widget root el 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div block-attribute-0=\\"style\\"/>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = ctx['props'].style; return component(\`Child\`, {style: 'font-weight: bold;'}, key+\`__1\`,null, node, ctx);
return block1([d1]);
} }
}" }"
`; `;
@@ -452,11 +419,13 @@ exports[`style and class handling style is properly added on widget root el 1`]
exports[`style and class handling style is properly added on widget root el 2`] = ` exports[`style and class handling style is properly added on widget root el 2`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div block-attribute-0=\\"style\\"/>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return component(\`Child\`, {style: 'font-weight: bold;'}, key + \`__1\`, node, ctx); let attr1 = ctx['props'].style;
return block1([attr1]);
} }
}" }"
`; `;
@@ -464,14 +433,13 @@ exports[`style and class handling style is properly added on widget root el 2`]
exports[`style and class handling t-att-class is properly added/removed on widget root el (v2) 1`] = ` exports[`style and class handling t-att-class is properly added/removed on widget root el (v2) 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<span class=\\"c\\" block-attribute-0=\\"class\\"/>\`); let block1 = createBlock(\`<div><block-child-0/></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = {d:ctx['state'].d,...ctx['props'].class}; let b2 = component(\`Child\`, {class: {b:ctx['state'].b}}, key+\`__1\`,null, node, ctx);
return block1([d1]); return block1([], [b2]);
} }
}" }"
`; `;
@@ -479,14 +447,13 @@ exports[`style and class handling t-att-class is properly added/removed on widge
exports[`style and class handling t-att-class is properly added/removed on widget root el (v2) 2`] = ` exports[`style and class handling t-att-class is properly added/removed on widget root el (v2) 2`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><block-child-0/></div>\`); let block1 = createBlock(\`<span class=\\"c\\" block-attribute-0=\\"class\\"/>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let b2 = component(\`Child\`, {class: {b:ctx['state'].b}}, key + \`__1\`, node, ctx); let attr1 = {d:ctx['state'].d,...ctx['props'].class};
return block1([], [b2]); return block1([attr1]);
} }
}" }"
`; `;
@@ -494,14 +461,10 @@ exports[`style and class handling t-att-class is properly added/removed on widge
exports[`style and class handling t-att-class is properly added/removed on widget root el (v3) 1`] = ` exports[`style and class handling t-att-class is properly added/removed on widget root el (v3) 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<span class=\\"c\\" block-attribute-0=\\"class\\"/>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = {d:ctx['state'].d,...ctx['props'].class}; return component(\`Child\`, {class: {a:true,b:ctx['state'].b}}, key+\`__1\`,null, node, ctx);
return block1([d1]);
} }
}" }"
`; `;
@@ -509,11 +472,13 @@ exports[`style and class handling t-att-class is properly added/removed on widge
exports[`style and class handling t-att-class is properly added/removed on widget root el (v3) 2`] = ` exports[`style and class handling t-att-class is properly added/removed on widget root el (v3) 2`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<span class=\\"c\\" block-attribute-0=\\"class\\"/>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return component(\`Child\`, {class: {a:true,b:ctx['state'].b}}, key + \`__1\`, node, ctx); let attr1 = {d:ctx['state'].d,...ctx['props'].class};
return block1([attr1]);
} }
}" }"
`; `;
+187 -129
View File
@@ -3,16 +3,16 @@
exports[`t-call dynamic t-call 1`] = ` exports[`t-call dynamic t-call 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { isBoundary, zero, call } = helpers;
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;
let b1 = text(\` owl \`); let b1 = text(\` owl \`);
ctx[zero] = b1; ctx[zero] = b1;
const template2 = (ctx['current'].template); const template1 = (ctx['current'].template);
return call(template2, ctx, node, key + \`__1\`); return call(this, template1, ctx, node, key + \`__1\`);
} }
}" }"
`; `;
@@ -20,8 +20,7 @@ exports[`t-call dynamic t-call 1`] = `
exports[`t-call dynamic t-call 2`] = ` exports[`t-call dynamic t-call 2`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div>foo</div>\`); let block1 = createBlock(\`<div>foo</div>\`);
@@ -34,8 +33,7 @@ exports[`t-call dynamic t-call 2`] = `
exports[`t-call dynamic t-call 3`] = ` exports[`t-call dynamic t-call 3`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return text(\`bar\`); return text(\`bar\`);
@@ -43,18 +41,90 @@ exports[`t-call dynamic t-call 3`] = `
}" }"
`; `;
exports[`t-call handlers are properly bound through a t-call 1`] = ` exports[`t-call dynamic t-call: key is propagated 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { call } = helpers;
return function template(ctx, node, key = \\"\\") {
let b2 = component(\`Child\`, {}, key+\`__1\`,null, node, ctx);
const template1 = (ctx['sub']);
let b3 = call(this, template1, ctx, node, key + \`__2\`);
return multi([b2, b3]);
}
}"
`;
exports[`t-call dynamic t-call: key is propagated 2`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let block1 = createBlock(\`<div block-attribute-0=\\"id\\"/>\`);
return function template(ctx, node, key = \\"\\") {
let attr1 = ctx['id'];
return block1([attr1]);
}
}"
`;
exports[`t-call dynamic t-call: key is propagated 3`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
return function template(ctx, node, key = \\"\\") {
return component(\`Child\`, {}, key+\`__1\`,null, node, ctx);
}
}"
`;
exports[`t-call handlers are properly bound through a dynamic t-call 1`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { call } = helpers;
let block1 = createBlock(\`<div><block-child-0/><block-text-0/></div>\`);
return function template(ctx, node, key = \\"\\") {
const template1 = ('__template__999');
let b2 = call(this, template1, ctx, node, key + \`__1\`);
let txt1 = ctx['counter'];
return block1([txt1], [b2]);
}
}"
`;
exports[`t-call handlers are properly bound through a dynamic t-call 2`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let block1 = createBlock(\`<p block-handler-0=\\"click\\">lucas</p>\`); let block1 = createBlock(\`<p block-handler-0=\\"click\\">lucas</p>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const v1 = ctx['update']; let hdlr1 = [()=>this.update(), ctx];
let d1 = [v1, ctx]; return block1([hdlr1]);
return block1([d1]); }
}"
`;
exports[`t-call handlers are properly bound through a t-call 1`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { getTemplate } = helpers;
const callTemplate_1 = getTemplate(\`__template__999\`);
let block1 = createBlock(\`<div><block-child-0/><block-text-0/></div>\`);
return function template(ctx, node, key = \\"\\") {
let b2 = callTemplate_1.call(this, ctx, node, key + \`__1\`);
let txt1 = ctx['counter'];
return block1([txt1], [b2]);
} }
}" }"
`; `;
@@ -62,16 +132,13 @@ exports[`t-call handlers are properly bound through a t-call 1`] = `
exports[`t-call handlers are properly bound through a t-call 2`] = ` exports[`t-call handlers are properly bound through a t-call 2`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
const callTemplate_2 = getTemplate(\`__template__9\`);
let block1 = createBlock(\`<div><block-child-0/><block-text-0/></div>\`); let block1 = createBlock(\`<p block-handler-0=\\"click\\">lucas</p>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let b2 = callTemplate_2.call(this, ctx, node, key + \`__1\`); let hdlr1 = [ctx['update'], ctx];
let d1 = ctx['counter']; return block1([hdlr1]);
return block1([d1], [b2]);
} }
}" }"
`; `;
@@ -79,15 +146,15 @@ exports[`t-call handlers are properly bound through a t-call 2`] = `
exports[`t-call handlers with arguments are properly bound through a t-call 1`] = ` exports[`t-call handlers with arguments are properly bound through a t-call 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { getTemplate } = helpers;
const callTemplate_1 = getTemplate(\`__template__999\`);
let block1 = createBlock(\`<p block-handler-0=\\"click\\">lucas</p>\`); let block1 = createBlock(\`<div><block-child-0/></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const v1 = ctx['a']; let b2 = callTemplate_1.call(this, ctx, node, key + \`__1\`);
let d1 = [()=>this.update(v1), ctx]; return block1([], [b2]);
return block1([d1]);
} }
}" }"
`; `;
@@ -95,15 +162,14 @@ exports[`t-call handlers with arguments are properly bound through a t-call 1`]
exports[`t-call handlers with arguments are properly bound through a t-call 2`] = ` exports[`t-call handlers with arguments are properly bound through a t-call 2`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
const callTemplate_2 = getTemplate(\`__template__9\`);
let block1 = createBlock(\`<div><block-child-0/></div>\`); let block1 = createBlock(\`<p block-handler-0=\\"click\\">lucas</p>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let b2 = callTemplate_2.call(this, ctx, node, key + \`__1\`); const v1 = ctx['a'];
return block1([], [b2]); let hdlr1 = [()=>this.update(v1), ctx];
return block1([hdlr1]);
} }
}" }"
`; `;
@@ -111,11 +177,15 @@ exports[`t-call handlers with arguments are properly bound through a t-call 2`]
exports[`t-call parent is set within t-call 1`] = ` exports[`t-call parent is set within t-call 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { getTemplate } = helpers;
const callTemplate_1 = getTemplate(\`__template__999\`);
let block1 = createBlock(\`<div><block-child-0/></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return component(\`Child\`, {}, key + \`__1\`, node, ctx); let b2 = callTemplate_1.call(this, ctx, node, key + \`__1\`);
return block1([], [b2]);
} }
}" }"
`; `;
@@ -123,13 +193,10 @@ exports[`t-call parent is set within t-call 1`] = `
exports[`t-call parent is set within t-call 2`] = ` exports[`t-call parent is set within t-call 2`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<span>lucas</span>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return block1(); return component(\`Child\`, {}, key+\`__1\`,null, node, ctx);
} }
}" }"
`; `;
@@ -137,36 +204,7 @@ exports[`t-call parent is set within t-call 2`] = `
exports[`t-call parent is set within t-call 3`] = ` exports[`t-call parent is set within t-call 3`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
const callTemplate_2 = getTemplate(\`__template__9\`);
let block1 = createBlock(\`<div><block-child-0/></div>\`);
return function template(ctx, node, key = \\"\\") {
let b2 = callTemplate_2.call(this, ctx, node, key + \`__1\`);
return block1([], [b2]);
}
}"
`;
exports[`t-call parent is set within t-call with no parentNode 1`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
return function template(ctx, node, key = \\"\\") {
return component(\`Child\`, {}, key + \`__1\`, node, ctx);
}
}"
`;
exports[`t-call parent is set within t-call with no parentNode 2`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<span>lucas</span>\`); let block1 = createBlock(\`<span>lucas</span>\`);
@@ -176,15 +214,39 @@ exports[`t-call parent is set within t-call with no parentNode 2`] = `
}" }"
`; `;
exports[`t-call parent is set within t-call with no parentNode 1`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { getTemplate } = helpers;
const callTemplate_1 = getTemplate(\`__template__999\`);
return function template(ctx, node, key = \\"\\") {
return callTemplate_1.call(this, ctx, node, key + \`__1\`);
}
}"
`;
exports[`t-call parent is set within t-call with no parentNode 2`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
return function template(ctx, node, key = \\"\\") {
return component(\`Child\`, {}, key+\`__1\`,null, node, ctx);
}
}"
`;
exports[`t-call parent is set within t-call with no parentNode 3`] = ` exports[`t-call parent is set within t-call with no parentNode 3`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
const callTemplate_2 = getTemplate(\`__template__9\`); let block1 = createBlock(\`<span>lucas</span>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return callTemplate_2.call(this, ctx, node, key + \`__1\`); return block1();
} }
}" }"
`; `;
@@ -192,34 +254,19 @@ exports[`t-call parent is set within t-call with no parentNode 3`] = `
exports[`t-call sub components in two t-calls 1`] = ` exports[`t-call sub components in two t-calls 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { getTemplate } = helpers;
const callTemplate_1 = getTemplate(\`sub\`);
let block1 = createBlock(\`<span><block-text-0/></span>\`);
return function template(ctx, node, key = \\"\\") {
let d1 = ctx['props'].val;
return block1([d1]);
}
}"
`;
exports[`t-call sub components in two t-calls 2`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
const callTemplate_2 = getTemplate(\`sub\`); const callTemplate_2 = getTemplate(\`sub\`);
const callTemplate_4 = getTemplate(\`sub\`);
let block3 = createBlock(\`<div><block-child-0/></div>\`); let block3 = createBlock(\`<div><block-child-0/></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let b2,b3; let b2,b3;
if (ctx['state'].val===1) { if (ctx['state'].val===1) {
b2 = callTemplate_2.call(this, ctx, node, key + \`__1\`); b2 = callTemplate_1.call(this, ctx, node, key + \`__1\`);
} else { } else {
let b4 = callTemplate_4.call(this, ctx, node, key + \`__3\`); let b4 = callTemplate_2.call(this, ctx, node, key + \`__2\`);
b3 = block3([], [b4]); b3 = block3([], [b4]);
} }
return multi([b2, b3]); return multi([b2, b3]);
@@ -227,14 +274,27 @@ exports[`t-call sub components in two t-calls 2`] = `
}" }"
`; `;
exports[`t-call sub components in two t-calls 2`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
return function template(ctx, node, key = \\"\\") {
return component(\`Child\`, {val: ctx['state'].val}, key+\`__1\`,null, node, ctx);
}
}"
`;
exports[`t-call sub components in two t-calls 3`] = ` exports[`t-call sub components in two t-calls 3`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<span><block-text-0/></span>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return component(\`Child\`, {val: ctx['state'].val}, key + \`__1\`, node, ctx); let txt1 = ctx['props'].val;
return block1([txt1]);
} }
}" }"
`; `;
@@ -242,36 +302,9 @@ exports[`t-call sub components in two t-calls 3`] = `
exports[`t-call t-call in t-foreach and children component 1`] = ` exports[`t-call t-call in t-foreach and children component 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { prepareList, getTemplate, withKey } = helpers;
const callTemplate_1 = getTemplate(\`__template__999\`);
return function template(ctx, node, key = \\"\\") {
return component(\`Child\`, {val: ctx['val']}, key + \`__1\`, node, ctx);
}
}"
`;
exports[`t-call t-call in t-foreach and children component 2`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<span><block-text-0/></span>\`);
return function template(ctx, node, key = \\"\\") {
let d1 = ctx['props'].val;
return block1([d1]);
}
}"
`;
exports[`t-call t-call in t-foreach and children component 3`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
const callTemplate_2 = getTemplate(\`__template__9\`);
let block1 = createBlock(\`<div><block-child-0/></div>\`); let block1 = createBlock(\`<div><block-child-0/></div>\`);
@@ -285,10 +318,35 @@ exports[`t-call t-call in t-foreach and children component 3`] = `
ctx[\`val_index\`] = i1; ctx[\`val_index\`] = i1;
ctx[\`val_value\`] = k_block2[i1]; ctx[\`val_value\`] = k_block2[i1];
let key1 = ctx['val']; let key1 = ctx['val'];
c_block2[i1] = withKey(callTemplate_2.call(this, ctx, node, key + \`__1__\${key1}\`), key1); c_block2[i1] = withKey(callTemplate_1.call(this, ctx, node, key + \`__1__\${key1}\`), key1);
} }
let b2 = list(c_block2); let b2 = list(c_block2);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
`; `;
exports[`t-call t-call in t-foreach and children component 2`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
return function template(ctx, node, key = \\"\\") {
return component(\`Child\`, {val: ctx['val']}, key+\`__1\`,null, node, ctx);
}
}"
`;
exports[`t-call t-call in t-foreach and children component 3`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let block1 = createBlock(\`<span><block-text-0/></span>\`);
return function template(ctx, node, key = \\"\\") {
let txt1 = ctx['props'].val;
return block1([txt1]);
}
}"
`;
@@ -3,8 +3,7 @@
exports[`t-call-block simple t-call-block with static text 1`] = ` exports[`t-call-block simple t-call-block with static text 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><block-child-0/></div>\`); let block1 = createBlock(\`<div><block-child-0/></div>\`);
@@ -3,13 +3,14 @@
exports[`t-component can switch between dynamic components without the need for a t-key 1`] = ` exports[`t-component can switch between dynamic components without the need for a t-key 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<span>child a</span>\`); let block1 = createBlock(\`<div><block-child-0/></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return block1(); let Comp1 = ctx['constructor'].components[ctx['state'].child];
let b2 = toggler(Comp1, component(Comp1, {}, key+\`__1\`,null, node, ctx));
return block1([], [b2]);
} }
}" }"
`; `;
@@ -17,10 +18,9 @@ exports[`t-component can switch between dynamic components without the need for
exports[`t-component can switch between dynamic components without the need for a t-key 2`] = ` exports[`t-component can switch between dynamic components without the need for a t-key 2`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<span>child b</span>\`); let block1 = createBlock(\`<span>child a</span>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return block1(); return block1();
@@ -31,26 +31,9 @@ exports[`t-component can switch between dynamic components without the need for
exports[`t-component can switch between dynamic components without the need for a t-key 3`] = ` exports[`t-component can switch between dynamic components without the need for a t-key 3`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><block-child-0/></div>\`); let block1 = createBlock(\`<span>child b</span>\`);
return function template(ctx, node, key = \\"\\") {
let Comp2 = ctx['constructor'].components[ctx['state'].child];
let b2 = toggler(Comp2, component(Comp2, {}, key + \`__1\`, node, ctx));
return block1([], [b2]);
}
}"
`;
exports[`t-component can use dynamic components (the class) if given (with different root tagname) 1`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<span>child a</span>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return block1(); return block1();
@@ -58,13 +41,25 @@ exports[`t-component can use dynamic components (the class) if given (with diffe
}" }"
`; `;
exports[`t-component can use dynamic components (the class) if given (with different root tagname) 1`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
return function template(ctx, node, key = \\"\\") {
const tKey_1 = ctx['state'].child;
let Comp1 = ctx['myComponent'];
return toggler(tKey_1, toggler(Comp1, component(Comp1, {}, key+\`__1\`,tKey_1, node, ctx)));
}
}"
`;
exports[`t-component can use dynamic components (the class) if given (with different root tagname) 2`] = ` exports[`t-component can use dynamic components (the class) if given (with different root tagname) 2`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div>child b</div>\`); let block1 = createBlock(\`<span>child a</span>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return block1(); return block1();
@@ -75,24 +70,9 @@ exports[`t-component can use dynamic components (the class) if given (with diffe
exports[`t-component can use dynamic components (the class) if given (with different root tagname) 3`] = ` exports[`t-component can use dynamic components (the class) if given (with different root tagname) 3`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
return function template(ctx, node, key = \\"\\") { let block1 = createBlock(\`<div>child b</div>\`);
const tKey_1 = ctx['state'].child;
let Comp3 = ctx['myComponent'];
return toggler(tKey_1, toggler(Comp3, component(Comp3, {}, tKey_1 + key + \`__2\`, node, ctx)));
}
}"
`;
exports[`t-component can use dynamic components (the class) if given 1`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<span>child a</span>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return block1(); return block1();
@@ -100,13 +80,25 @@ exports[`t-component can use dynamic components (the class) if given 1`] = `
}" }"
`; `;
exports[`t-component can use dynamic components (the class) if given 1`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
return function template(ctx, node, key = \\"\\") {
const tKey_1 = ctx['state'].child;
let Comp1 = ctx['myComponent'];
return toggler(tKey_1, toggler(Comp1, component(Comp1, {}, key+\`__1\`,tKey_1, node, ctx)));
}
}"
`;
exports[`t-component can use dynamic components (the class) if given 2`] = ` exports[`t-component can use dynamic components (the class) if given 2`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<span>child b</span>\`); let block1 = createBlock(\`<span>child a</span>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return block1(); return block1();
@@ -117,13 +109,12 @@ exports[`t-component can use dynamic components (the class) if given 2`] = `
exports[`t-component can use dynamic components (the class) if given 3`] = ` exports[`t-component can use dynamic components (the class) if given 3`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<span>child b</span>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const tKey_1 = ctx['state'].child; return block1();
let Comp3 = ctx['myComponent'];
return toggler(tKey_1, toggler(Comp3, component(Comp3, {}, tKey_1 + key + \`__2\`, node, ctx)));
} }
}" }"
`; `;
@@ -131,16 +122,14 @@ exports[`t-component can use dynamic components (the class) if given 3`] = `
exports[`t-component modifying a sub widget 1`] = ` exports[`t-component modifying a sub widget 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><block-text-0/><button block-handler-1=\\"click\\">Inc</button></div>\`); let block1 = createBlock(\`<div><block-child-0/></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = ctx['state'].counter; let Comp1 = ctx['Counter'];
const v1 = ctx['state']; let b2 = toggler(Comp1, component(Comp1, {}, key+\`__1\`,null, node, ctx));
let d2 = [()=>v1.counter++, ctx]; return block1([], [b2]);
return block1([d1, d2]);
} }
}" }"
`; `;
@@ -148,15 +137,15 @@ exports[`t-component modifying a sub widget 1`] = `
exports[`t-component modifying a sub widget 2`] = ` exports[`t-component modifying a sub widget 2`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><block-child-0/></div>\`); let block1 = createBlock(\`<div><block-text-0/><button block-handler-1=\\"click\\">Inc</button></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let Comp2 = ctx['Counter']; let txt1 = ctx['state'].counter;
let b2 = toggler(Comp2, component(Comp2, {}, key + \`__1\`, node, ctx)); const v1 = ctx['state'];
return block1([], [b2]); let hdlr1 = [()=>v1.counter++, ctx];
return block1([txt1, hdlr1]);
} }
}" }"
`; `;
@@ -164,8 +153,19 @@ exports[`t-component modifying a sub widget 2`] = `
exports[`t-component switching dynamic component 1`] = ` exports[`t-component switching dynamic component 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
return function template(ctx, node, key = \\"\\") {
let Comp1 = ctx['Child'];
return toggler(Comp1, component(Comp1, {}, key+\`__1\`,null, node, ctx));
}
}"
`;
exports[`t-component switching dynamic component 2`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let block1 = createBlock(\`<div>child a</div>\`); let block1 = createBlock(\`<div>child a</div>\`);
@@ -175,11 +175,10 @@ exports[`t-component switching dynamic component 1`] = `
}" }"
`; `;
exports[`t-component switching dynamic component 2`] = ` exports[`t-component switching dynamic component 3`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return text(\`child b\`); return text(\`child b\`);
@@ -187,38 +186,22 @@ exports[`t-component switching dynamic component 2`] = `
}" }"
`; `;
exports[`t-component switching dynamic component 3`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
return function template(ctx, node, key = \\"\\") {
let Comp2 = ctx['Child'];
return toggler(Comp2, component(Comp2, {}, key + \`__1\`, node, ctx));
}
}"
`;
exports[`t-component t-component not on a <t> node 1`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<span>1</span>\`);
return function template(ctx, node, key = \\"\\") {
return block1();
}
}"
`;
exports[`t-component t-component works in simple case 1`] = ` exports[`t-component t-component works in simple case 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
return function template(ctx, node, key = \\"\\") {
let Comp1 = ctx['Child'];
return toggler(Comp1, component(Comp1, {}, key+\`__1\`,null, node, ctx));
}
}"
`;
exports[`t-component t-component works in simple case 2`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let block1 = createBlock(\`<div>child</div>\`); let block1 = createBlock(\`<div>child</div>\`);
@@ -227,16 +210,3 @@ exports[`t-component t-component works in simple case 1`] = `
} }
}" }"
`; `;
exports[`t-component t-component works in simple case 2`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
return function template(ctx, node, key = \\"\\") {
let Comp2 = ctx['Child'];
return toggler(Comp2, component(Comp2, {}, key + \`__1\`, node, ctx));
}
}"
`;
@@ -3,23 +3,8 @@
exports[`list of components components in a node in a t-foreach 1`] = ` exports[`list of components components in a node in a t-foreach 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { prepareList, withKey } = helpers;
let block1 = createBlock(\`<div><block-text-0/></div>\`);
return function template(ctx, node, key = \\"\\") {
let d1 = ctx['props'].item;
return block1([d1]);
}
}"
`;
exports[`list of components components in a node in a t-foreach 2`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><ul><block-child-0/></ul></div>\`); let block1 = createBlock(\`<div><ul><block-child-0/></ul></div>\`);
let block3 = createBlock(\`<li><block-child-0/></li>\`); let block3 = createBlock(\`<li><block-child-0/></li>\`);
@@ -30,7 +15,7 @@ exports[`list of components components in a node in a t-foreach 2`] = `
for (let i1 = 0; i1 < l_block2; i1++) { for (let i1 = 0; i1 < l_block2; i1++) {
ctx[\`item\`] = v_block2[i1]; ctx[\`item\`] = v_block2[i1];
let key1 = 'li_'+ctx['item']; let key1 = 'li_'+ctx['item'];
let b4 = component(\`Child\`, {item: ctx['item']}, key + \`__1__\${key1}\`, node, ctx); let b4 = component(\`Child\`, {item: ctx['item']}, key+\`__1__\${key1}\`,null, node, ctx);
c_block2[i1] = withKey(block3([], [b4]), key1); c_block2[i1] = withKey(block3([], [b4]), key1);
} }
let b2 = list(c_block2); let b2 = list(c_block2);
@@ -39,25 +24,60 @@ exports[`list of components components in a node in a t-foreach 2`] = `
}" }"
`; `;
exports[`list of components list of sub components inside other nodes 1`] = ` exports[`list of components components in a node in a t-foreach 2`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<span>asdf</span>\`); let block1 = createBlock(\`<div><block-text-0/></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return block1(); let txt1 = ctx['props'].item;
return block1([txt1]);
} }
}" }"
`; `;
exports[`list of components list of sub components inside other nodes 2`] = ` exports[`list of components crash on duplicate key in dev mode 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { prepareList, withKey } = helpers;
return function template(ctx, node, key = \\"\\") {
ctx = Object.create(ctx);
const [k_block1, v_block1, l_block1, c_block1] = prepareList([1,2]);
const keys1 = new Set();
for (let i1 = 0; i1 < l_block1; i1++) {
ctx[\`item\`] = v_block1[i1];
let key1 = 'child';
if (keys1.has(key1)) { throw new Error(\`Got duplicate key in t-foreach: \${key1}\`)}
keys1.add(key1);
const props1 = {}
helpers.validateProps(\`Child\`, props1, ctx)
c_block1[i1] = withKey(component(\`Child\`, props1, key+\`__1__\${key1}\`,null, node, ctx), key1);
}
return list(c_block1);
}
}"
`;
exports[`list of components crash on duplicate key in dev mode 2`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
return function template(ctx, node, key = \\"\\") {
return text(\`\`);
}
}"
`;
exports[`list of components list of sub components inside other nodes 1`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { prepareList, withKey } = helpers;
let block1 = createBlock(\`<div><block-child-0/></div>\`); let block1 = createBlock(\`<div><block-child-0/></div>\`);
let block3 = createBlock(\`<div><block-child-0/></div>\`); let block3 = createBlock(\`<div><block-child-0/></div>\`);
@@ -68,7 +88,7 @@ exports[`list of components list of sub components inside other nodes 2`] = `
for (let i1 = 0; i1 < l_block2; i1++) { for (let i1 = 0; i1 < l_block2; i1++) {
ctx[\`blip\`] = v_block2[i1]; ctx[\`blip\`] = v_block2[i1];
let key1 = ctx['blip'].id; let key1 = ctx['blip'].id;
let b4 = component(\`SubComponent\`, {}, key + \`__1__\${key1}\`, node, ctx); let b4 = component(\`SubComponent\`, {}, key+\`__1__\${key1}\`,null, node, ctx);
c_block2[i1] = withKey(block3([], [b4]), key1); c_block2[i1] = withKey(block3([], [b4]), key1);
} }
let b2 = list(c_block2); let b2 = list(c_block2);
@@ -77,26 +97,24 @@ exports[`list of components list of sub components inside other nodes 2`] = `
}" }"
`; `;
exports[`list of components reconciliation alg works for t-foreach in t-foreach 1`] = ` exports[`list of components list of sub components inside other nodes 2`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><block-text-0/></div>\`); let block1 = createBlock(\`<span>asdf</span>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = ctx['props'].blip; return block1();
return block1([d1]);
} }
}" }"
`; `;
exports[`list of components reconciliation alg works for t-foreach in t-foreach 2`] = ` exports[`list of components reconciliation alg works for t-foreach in t-foreach 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { prepareList, withKey } = helpers;
let block1 = createBlock(\`<div><block-child-0/></div>\`); let block1 = createBlock(\`<div><block-child-0/></div>\`);
@@ -113,7 +131,7 @@ exports[`list of components reconciliation alg works for t-foreach in t-foreach
ctx[\`blip\`] = v_block3[i2]; ctx[\`blip\`] = v_block3[i2];
ctx[\`blip_index\`] = i2; ctx[\`blip_index\`] = i2;
let key2 = ctx['blip_index']; let key2 = ctx['blip_index'];
c_block3[i2] = withKey(component(\`Child\`, {blip: ctx['blip']}, key + \`__1__\${key1}__\${key2}\`, node, ctx), key2); c_block3[i2] = withKey(component(\`Child\`, {blip: ctx['blip']}, key+\`__1__\${key1}__\${key2}\`,null, node, ctx), key2);
} }
ctx = ctx.__proto__; ctx = ctx.__proto__;
c_block2[i1] = withKey(list(c_block3), key1); c_block2[i1] = withKey(list(c_block3), key1);
@@ -124,26 +142,25 @@ exports[`list of components reconciliation alg works for t-foreach in t-foreach
}" }"
`; `;
exports[`list of components reconciliation alg works for t-foreach in t-foreach, 2 1`] = ` exports[`list of components reconciliation alg works for t-foreach in t-foreach 2`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><block-text-0/></div>\`); let block1 = createBlock(\`<div><block-text-0/></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = ctx['props'].row+'_'+ctx['props'].col; let txt1 = ctx['props'].blip;
return block1([d1]); return block1([txt1]);
} }
}" }"
`; `;
exports[`list of components reconciliation alg works for t-foreach in t-foreach, 2 2`] = ` exports[`list of components reconciliation alg works for t-foreach in t-foreach, 2 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { prepareList, withKey } = helpers;
let block1 = createBlock(\`<div><block-child-0/></div>\`); let block1 = createBlock(\`<div><block-child-0/></div>\`);
let block3 = createBlock(\`<p><block-child-0/></p>\`); let block3 = createBlock(\`<p><block-child-0/></p>\`);
@@ -160,7 +177,7 @@ exports[`list of components reconciliation alg works for t-foreach in t-foreach,
for (let i2 = 0; i2 < l_block4; i2++) { for (let i2 = 0; i2 < l_block4; i2++) {
ctx[\`col\`] = v_block4[i2]; ctx[\`col\`] = v_block4[i2];
let key2 = ctx['col']; let key2 = ctx['col'];
let b6 = component(\`Child\`, {row: ctx['row'],col: ctx['col']}, key + \`__1__\${key1}__\${key2}\`, node, ctx); let b6 = component(\`Child\`, {row: ctx['row'],col: ctx['col']}, key+\`__1__\${key1}__\${key2}\`,null, node, ctx);
c_block4[i2] = withKey(block5([], [b6]), key2); c_block4[i2] = withKey(block5([], [b6]), key2);
} }
ctx = ctx.__proto__; ctx = ctx.__proto__;
@@ -173,26 +190,25 @@ exports[`list of components reconciliation alg works for t-foreach in t-foreach,
}" }"
`; `;
exports[`list of components simple list 1`] = ` exports[`list of components reconciliation alg works for t-foreach in t-foreach, 2 2`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<span><block-text-0/></span>\`); let block1 = createBlock(\`<div><block-text-0/></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = ctx['props'].value; let txt1 = ctx['props'].row+'_'+ctx['props'].col;
return block1([d1]); return block1([txt1]);
} }
}" }"
`; `;
exports[`list of components simple list 2`] = ` exports[`list of components simple list 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { prepareList, withKey } = helpers;
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
ctx = Object.create(ctx); ctx = Object.create(ctx);
@@ -200,24 +216,45 @@ exports[`list of components simple list 2`] = `
for (let i1 = 0; i1 < l_block1; i1++) { for (let i1 = 0; i1 < l_block1; i1++) {
ctx[\`elem\`] = v_block1[i1]; ctx[\`elem\`] = v_block1[i1];
let key1 = ctx['elem'].id; let key1 = ctx['elem'].id;
c_block1[i1] = withKey(component(\`Child\`, {value: ctx['elem'].value}, key + \`__1__\${key1}\`, node, ctx), key1); c_block1[i1] = withKey(component(\`Child\`, {value: ctx['elem'].value}, key+\`__1__\${key1}\`,null, node, ctx), key1);
} }
return list(c_block1); return list(c_block1);
} }
}" }"
`; `;
exports[`list of components simple list 2`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let block1 = createBlock(\`<span><block-text-0/></span>\`);
return function template(ctx, node, key = \\"\\") {
let txt1 = ctx['props'].value;
return block1([txt1]);
}
}"
`;
exports[`list of components sub components rendered in a loop 1`] = ` exports[`list of components sub components rendered in a loop 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { prepareList, withKey } = helpers;
let block1 = createBlock(\`<p><block-text-0/></p>\`); let block1 = createBlock(\`<div><block-child-0/></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = ctx['props'].n; ctx = Object.create(ctx);
return block1([d1]); const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['state'].numbers);
for (let i1 = 0; i1 < l_block2; i1++) {
ctx[\`number\`] = v_block2[i1];
let key1 = ctx['number'];
c_block2[i1] = withKey(component(\`Child\`, {n: ctx['number']}, key+\`__1__\${key1}\`,null, node, ctx), key1);
}
let b2 = list(c_block2);
return block1([], [b2]);
} }
}" }"
`; `;
@@ -225,21 +262,13 @@ exports[`list of components sub components rendered in a loop 1`] = `
exports[`list of components sub components rendered in a loop 2`] = ` exports[`list of components sub components rendered in a loop 2`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><block-child-0/></div>\`); let block1 = createBlock(\`<p><block-text-0/></p>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
ctx = Object.create(ctx); let txt1 = ctx['props'].n;
const [k_block2, v_block2, l_block2, c_block2] = prepareList(ctx['state'].numbers); return block1([txt1]);
for (let i1 = 0; i1 < l_block2; i1++) {
ctx[\`number\`] = v_block2[i1];
let key1 = ctx['number'];
c_block2[i1] = withKey(component(\`Child\`, {n: ctx['number']}, key + \`__1__\${key1}\`, node, ctx), key1);
}
let b2 = list(c_block2);
return block1([], [b2]);
} }
}" }"
`; `;
@@ -247,23 +276,8 @@ exports[`list of components sub components rendered in a loop 2`] = `
exports[`list of components sub components with some state rendered in a loop 1`] = ` exports[`list of components sub components with some state rendered in a loop 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { prepareList, withKey } = helpers;
let block1 = createBlock(\`<p><block-text-0/></p>\`);
return function template(ctx, node, key = \\"\\") {
let d1 = ctx['state'].n;
return block1([d1]);
}
}"
`;
exports[`list of components sub components with some state rendered in a loop 2`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><block-child-0/></div>\`); let block1 = createBlock(\`<div><block-child-0/></div>\`);
@@ -273,7 +287,7 @@ exports[`list of components sub components with some state rendered in a loop 2`
for (let i1 = 0; i1 < l_block2; i1++) { for (let i1 = 0; i1 < l_block2; i1++) {
ctx[\`number\`] = v_block2[i1]; ctx[\`number\`] = v_block2[i1];
let key1 = ctx['number']; let key1 = ctx['number'];
c_block2[i1] = withKey(component(\`Child\`, {}, key + \`__1__\${key1}\`, node, ctx), key1); c_block2[i1] = withKey(component(\`Child\`, {}, key+\`__1__\${key1}\`,null, node, ctx), key1);
} }
let b2 = list(c_block2); let b2 = list(c_block2);
return block1([], [b2]); return block1([], [b2]);
@@ -281,26 +295,25 @@ exports[`list of components sub components with some state rendered in a loop 2`
}" }"
`; `;
exports[`list of components switch component position 1`] = ` exports[`list of components sub components with some state rendered in a loop 2`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><block-text-0/></div>\`); let block1 = createBlock(\`<p><block-text-0/></p>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = ctx['props'].key; let txt1 = ctx['state'].n;
return block1([d1]); return block1([txt1]);
} }
}" }"
`; `;
exports[`list of components switch component position 2`] = ` exports[`list of components switch component position 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { prepareList, withKey } = helpers;
let block1 = createBlock(\`<span><block-child-0/></span>\`); let block1 = createBlock(\`<span><block-child-0/></span>\`);
@@ -310,7 +323,7 @@ exports[`list of components switch component position 2`] = `
for (let i1 = 0; i1 < l_block2; i1++) { for (let i1 = 0; i1 < l_block2; i1++) {
ctx[\`c\`] = v_block2[i1]; ctx[\`c\`] = v_block2[i1];
let key1 = ctx['c']; let key1 = ctx['c'];
c_block2[i1] = withKey(component(\`Child\`, {key: ctx['c']}, key + \`__1__\${key1}\`, node, ctx), key1); c_block2[i1] = withKey(component(\`Child\`, {key: ctx['c']}, key+\`__1__\${key1}\`,null, node, ctx), key1);
} }
let b2 = list(c_block2); let b2 = list(c_block2);
return block1([], [b2]); return block1([], [b2]);
@@ -318,27 +331,25 @@ exports[`list of components switch component position 2`] = `
}" }"
`; `;
exports[`list of components t-foreach with t-component, and update 1`] = ` exports[`list of components switch component position 2`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<span><block-text-0/><block-text-1/></span>\`); let block1 = createBlock(\`<div><block-text-0/></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = ctx['state'].val; let txt1 = ctx['props'].key;
let d2 = ctx['props'].val; return block1([txt1]);
return block1([d1, d2]);
} }
}" }"
`; `;
exports[`list of components t-foreach with t-component, and update 2`] = ` exports[`list of components t-foreach with t-component, and update 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { prepareList, withKey } = helpers;
let block1 = createBlock(\`<div><block-child-0/></div>\`); let block1 = createBlock(\`<div><block-child-0/></div>\`);
@@ -349,10 +360,25 @@ exports[`list of components t-foreach with t-component, and update 2`] = `
ctx[\`n\`] = v_block2[i1]; ctx[\`n\`] = v_block2[i1];
ctx[\`n_index\`] = i1; ctx[\`n_index\`] = i1;
let key1 = ctx['n_index']; let key1 = ctx['n_index'];
c_block2[i1] = withKey(component(\`Child\`, {val: ctx['n_index']}, key + \`__1__\${key1}\`, node, ctx), key1); c_block2[i1] = withKey(component(\`Child\`, {val: ctx['n_index']}, key+\`__1__\${key1}\`,null, node, ctx), key1);
} }
let b2 = list(c_block2); let b2 = list(c_block2);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
`; `;
exports[`list of components t-foreach with t-component, and update 2`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let block1 = createBlock(\`<span><block-text-0/><block-text-1/></span>\`);
return function template(ctx, node, key = \\"\\") {
let txt1 = ctx['state'].val;
let txt2 = ctx['props'].val;
return block1([txt1, txt2]);
}
}"
`;
+88 -102
View File
@@ -3,23 +3,8 @@
exports[`t-key t-foreach with t-key switch component position 1`] = ` exports[`t-key t-foreach with t-key switch component position 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { prepareList, withKey } = helpers;
let block1 = createBlock(\`<div><block-text-0/></div>\`);
return function template(ctx, node, key = \\"\\") {
let d1 = ctx['props'].key;
return block1([d1]);
}
}"
`;
exports[`t-key t-foreach with t-key switch component position 2`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<span><block-child-0/></span>\`); let block1 = createBlock(\`<span><block-child-0/></span>\`);
@@ -30,7 +15,7 @@ exports[`t-key t-foreach with t-key switch component position 2`] = `
ctx[\`c\`] = v_block2[i1]; ctx[\`c\`] = v_block2[i1];
let key1 = ctx['c']; let key1 = ctx['c'];
const tKey_1 = ctx['key1']; const tKey_1 = ctx['key1'];
c_block2[i1] = withKey(component(\`Child\`, {key: ctx['c']+ctx['key1']}, tKey_1 + key + \`__2__\${key1}\`, node, ctx), tKey_1 + key1); c_block2[i1] = withKey(component(\`Child\`, {key: ctx['c']+ctx['key1']}, key+\`__1__\${key1}\`,tKey_1, node, ctx), tKey_1 + key1);
} }
let b2 = list(c_block2); let b2 = list(c_block2);
return block1([], [b2]); return block1([], [b2]);
@@ -38,17 +23,28 @@ exports[`t-key t-foreach with t-key switch component position 2`] = `
}" }"
`; `;
exports[`t-key t-key on Component 1`] = ` exports[`t-key t-foreach with t-key switch component position 2`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><block-text-0/></div>\`); let block1 = createBlock(\`<div><block-text-0/></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = ctx['props'].key; let txt1 = ctx['props'].key;
return block1([d1]); return block1([txt1]);
}
}"
`;
exports[`t-key t-key on Component 1`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
return function template(ctx, node, key = \\"\\") {
const tKey_1 = ctx['key'];
return toggler(tKey_1, component(\`Child\`, {key: ctx['key']}, key+\`__1\`,tKey_1, node, ctx));
} }
}" }"
`; `;
@@ -56,15 +52,13 @@ exports[`t-key t-key on Component 1`] = `
exports[`t-key t-key on Component 2`] = ` exports[`t-key t-key on Component 2`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<span><block-child-0/></span>\`); let block1 = createBlock(\`<div><block-text-0/></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const tKey_1 = ctx['key']; let txt1 = ctx['props'].key;
let b2 = toggler(tKey_1, component(\`Child\`, {key: ctx['key']}, tKey_1 + key + \`__2\`, node, ctx)); return block1([txt1]);
return block1([], [b2]);
} }
}" }"
`; `;
@@ -72,14 +66,14 @@ exports[`t-key t-key on Component 2`] = `
exports[`t-key t-key on Component as a function 1`] = ` exports[`t-key t-key on Component as a function 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><block-text-0/></div>\`); let block1 = createBlock(\`<span><block-child-0/></span>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = ctx['props'].key; const tKey_1 = ctx['key'];
return block1([d1]); let b2 = toggler(tKey_1, component(\`Child\`, {key: ctx['key']}, key+\`__1\`,tKey_1, node, ctx));
return block1([], [b2]);
} }
}" }"
`; `;
@@ -87,15 +81,13 @@ exports[`t-key t-key on Component as a function 1`] = `
exports[`t-key t-key on Component as a function 2`] = ` exports[`t-key t-key on Component as a function 2`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<span><block-child-0/></span>\`); let block1 = createBlock(\`<div><block-text-0/></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const tKey_1 = ctx['key']; let txt1 = ctx['props'].key;
let b2 = toggler(tKey_1, component(\`Child\`, {key: ctx['key']}, tKey_1 + key + \`__2\`, node, ctx)); return block1([txt1]);
return block1([], [b2]);
} }
}" }"
`; `;
@@ -103,14 +95,16 @@ exports[`t-key t-key on Component as a function 2`] = `
exports[`t-key t-key on multiple Components 1`] = ` exports[`t-key t-key on multiple Components 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><block-text-0/></div>\`); let block1 = createBlock(\`<span><block-child-0/><block-child-1/></span>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = ctx['props'].key; const tKey_1 = ctx['key1'];
return block1([d1]); let b2 = toggler(tKey_1, component(\`Child\`, {key: ctx['key1']}, key+\`__1\`,tKey_1, node, ctx));
const tKey_2 = ctx['key2'];
let b3 = toggler(tKey_2, component(\`Child\`, {key: ctx['key2']}, key+\`__2\`,tKey_2, node, ctx));
return block1([], [b2, b3]);
} }
}" }"
`; `;
@@ -118,17 +112,13 @@ exports[`t-key t-key on multiple Components 1`] = `
exports[`t-key t-key on multiple Components 2`] = ` exports[`t-key t-key on multiple Components 2`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<span><block-child-0/><block-child-1/></span>\`); let block1 = createBlock(\`<div><block-text-0/></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const tKey_1 = ctx['key1']; let txt1 = ctx['props'].key;
let b2 = toggler(tKey_1, component(\`Child\`, {key: ctx['key1']}, tKey_1 + key + \`__2\`, node, ctx)); return block1([txt1]);
const tKey_3 = ctx['key2'];
let b3 = toggler(tKey_3, component(\`Child\`, {key: ctx['key2']}, tKey_3 + key + \`__4\`, node, ctx));
return block1([], [b2, b3]);
} }
}" }"
`; `;
@@ -136,38 +126,10 @@ exports[`t-key t-key on multiple Components 2`] = `
exports[`t-key t-key on multiple Components with t-call 1 1`] = ` exports[`t-key t-key on multiple Components with t-call 1 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { isBoundary, withDefault, setContextValue, getTemplate } = helpers;
const callTemplate_1 = getTemplate(\`calledTemplate\`);
let block1 = createBlock(\`<div><block-text-0/></div>\`);
return function template(ctx, node, key = \\"\\") {
let d1 = ctx['props'].key;
return block1([d1]);
}
}"
`;
exports[`t-key t-key on multiple Components with t-call 1 2`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
return function template(ctx, node, key = \\"\\") {
const tKey_1 = ctx['key'];
return toggler(tKey_1, component(\`Child\`, {key: ctx['key']}, tKey_1 + key + \`__2\`, node, ctx));
}
}"
`;
exports[`t-key t-key on multiple Components with t-call 1 3`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
const callTemplate_2 = getTemplate(\`calledTemplate\`); const callTemplate_2 = getTemplate(\`calledTemplate\`);
const callTemplate_4 = getTemplate(\`calledTemplate\`);
let block1 = createBlock(\`<span><block-child-0/><block-child-1/></span>\`); let block1 = createBlock(\`<span><block-child-0/><block-child-1/></span>\`);
@@ -177,28 +139,55 @@ exports[`t-key t-key on multiple Components with t-call 1 3`] = `
ctx = Object.create(ctx); ctx = Object.create(ctx);
ctx[isBoundary] = 1; ctx[isBoundary] = 1;
setContextValue(ctx, \\"key\\", ctx['key1']); setContextValue(ctx, \\"key\\", ctx['key1']);
let b2 = callTemplate_2.call(this, ctx, node, key + \`__1\`); let b2 = callTemplate_1.call(this, ctx, node, key + \`__1\`);
ctx = ctx.__proto__; ctx = ctx.__proto__;
ctx = Object.create(ctx); ctx = Object.create(ctx);
ctx[isBoundary] = 1; ctx[isBoundary] = 1;
setContextValue(ctx, \\"key\\", ctx['key2']); setContextValue(ctx, \\"key\\", ctx['key2']);
let b3 = callTemplate_4.call(this, ctx, node, key + \`__3\`); let b3 = callTemplate_2.call(this, ctx, node, key + \`__2\`);
return block1([], [b2, b3]); return block1([], [b2, b3]);
} }
}" }"
`; `;
exports[`t-key t-key on multiple Components with t-call 1 2`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
return function template(ctx, node, key = \\"\\") {
const tKey_1 = ctx['key'];
return toggler(tKey_1, component(\`Child\`, {key: ctx['key']}, key+\`__1\`,tKey_1, node, ctx));
}
}"
`;
exports[`t-key t-key on multiple Components with t-call 1 3`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let block1 = createBlock(\`<div><block-text-0/></div>\`);
return function template(ctx, node, key = \\"\\") {
let txt1 = ctx['props'].key;
return block1([txt1]);
}
}"
`;
exports[`t-key t-key on multiple Components with t-call 2 1`] = ` exports[`t-key t-key on multiple Components with t-call 2 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { getTemplate } = helpers;
const callTemplate_1 = getTemplate(\`calledTemplate\`);
let block1 = createBlock(\`<div><block-text-0/></div>\`); let block1 = createBlock(\`<span><block-child-0/></span>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = ctx['props'].key; let b2 = callTemplate_1.call(this, ctx, node, key + \`__1\`);
return block1([d1]); return block1([], [b2]);
} }
}" }"
`; `;
@@ -206,14 +195,13 @@ exports[`t-key t-key on multiple Components with t-call 2 1`] = `
exports[`t-key t-key on multiple Components with t-call 2 2`] = ` exports[`t-key t-key on multiple Components with t-call 2 2`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const tKey_1 = ctx['key1']; const tKey_1 = ctx['key1'];
let b2 = toggler(tKey_1, component(\`Child\`, {key: ctx['key1']}, tKey_1 + key + \`__2\`, node, ctx)); let b2 = toggler(tKey_1, component(\`Child\`, {key: ctx['key1']}, key+\`__1\`,tKey_1, node, ctx));
const tKey_3 = ctx['key2']; const tKey_2 = ctx['key2'];
let b3 = toggler(tKey_3, component(\`Child\`, {key: ctx['key2']}, tKey_3 + key + \`__4\`, node, ctx)); let b3 = toggler(tKey_2, component(\`Child\`, {key: ctx['key2']}, key+\`__2\`,tKey_2, node, ctx));
return multi([b2, b3]); return multi([b2, b3]);
} }
}" }"
@@ -222,15 +210,13 @@ exports[`t-key t-key on multiple Components with t-call 2 2`] = `
exports[`t-key t-key on multiple Components with t-call 2 3`] = ` exports[`t-key t-key on multiple Components with t-call 2 3`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
const callTemplate_2 = getTemplate(\`calledTemplate\`);
let block1 = createBlock(\`<span><block-child-0/></span>\`); let block1 = createBlock(\`<div><block-text-0/></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let b2 = callTemplate_2.call(this, ctx, node, key + \`__1\`); let txt1 = ctx['props'].key;
return block1([], [b2]); return block1([txt1]);
} }
}" }"
`; `;
@@ -3,17 +3,17 @@
exports[`t-model directive .lazy modifier 1`] = ` exports[`t-model directive .lazy modifier 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { toNumber } = helpers;
let block1 = createBlock(\`<div><input block-attribute-0=\\"value\\" block-handler-1=\\"change\\"/><span><block-text-2/></span></div>\`); let block1 = createBlock(\`<div><input block-attribute-0=\\"value\\" block-handler-1=\\"change\\"/><span><block-text-2/></span></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const bExpr1 = ctx['state']; const bExpr1 = ctx['state'];
let d1 = ctx['state']['text']; let attr1 = ctx['state']['text'];
let d2 = [(ev) => { bExpr1['text'] = ev.target.value; }]; let hdlr1 = [(ev) => { bExpr1['text'] = ev.target.value; }];
let d3 = ctx['state'].text; let txt1 = ctx['state'].text;
return block1([d1, d2, d3]); return block1([attr1, hdlr1, txt1]);
} }
}" }"
`; `;
@@ -21,17 +21,17 @@ exports[`t-model directive .lazy modifier 1`] = `
exports[`t-model directive .number modifier 1`] = ` exports[`t-model directive .number modifier 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { toNumber } = helpers;
let block1 = createBlock(\`<div><input block-attribute-0=\\"value\\" block-handler-1=\\"input\\"/><span><block-text-2/></span></div>\`); let block1 = createBlock(\`<div><input block-attribute-0=\\"value\\" block-handler-1=\\"input\\"/><span><block-text-2/></span></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const bExpr1 = ctx['state']; const bExpr1 = ctx['state'];
let d1 = ctx['state']['number']; let attr1 = ctx['state']['number'];
let d2 = [(ev) => { bExpr1['number'] = toNumber(ev.target.value); }]; let hdlr1 = [(ev) => { bExpr1['number'] = toNumber(ev.target.value); }];
let d3 = ctx['state'].number; let txt1 = ctx['state'].number;
return block1([d1, d2, d3]); return block1([attr1, hdlr1, txt1]);
} }
}" }"
`; `;
@@ -39,17 +39,17 @@ exports[`t-model directive .number modifier 1`] = `
exports[`t-model directive .trim modifier 1`] = ` exports[`t-model directive .trim modifier 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { toNumber } = helpers;
let block1 = createBlock(\`<div><input block-attribute-0=\\"value\\" block-handler-1=\\"input\\"/><span><block-text-2/></span></div>\`); let block1 = createBlock(\`<div><input block-attribute-0=\\"value\\" block-handler-1=\\"input\\"/><span><block-text-2/></span></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const bExpr1 = ctx['state']; const bExpr1 = ctx['state'];
let d1 = ctx['state']['text']; let attr1 = ctx['state']['text'];
let d2 = [(ev) => { bExpr1['text'] = ev.target.value.trim(); }]; let hdlr1 = [(ev) => { bExpr1['text'] = ev.target.value.trim(); }];
let d3 = ctx['state'].text; let txt1 = ctx['state'].text;
return block1([d1, d2, d3]); return block1([attr1, hdlr1, txt1]);
} }
}" }"
`; `;
@@ -57,17 +57,17 @@ exports[`t-model directive .trim modifier 1`] = `
exports[`t-model directive basic use, on an input 1`] = ` exports[`t-model directive basic use, on an input 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { toNumber } = helpers;
let block1 = createBlock(\`<div><input block-attribute-0=\\"value\\" block-handler-1=\\"input\\"/><span><block-text-2/></span></div>\`); let block1 = createBlock(\`<div><input block-attribute-0=\\"value\\" block-handler-1=\\"input\\"/><span><block-text-2/></span></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const bExpr1 = ctx['state']; const bExpr1 = ctx['state'];
let d1 = ctx['state']['text']; let attr1 = ctx['state']['text'];
let d2 = [(ev) => { bExpr1['text'] = ev.target.value; }]; let hdlr1 = [(ev) => { bExpr1['text'] = ev.target.value; }];
let d3 = ctx['state'].text; let txt1 = ctx['state'].text;
return block1([d1, d2, d3]); return block1([attr1, hdlr1, txt1]);
} }
}" }"
`; `;
@@ -75,17 +75,17 @@ exports[`t-model directive basic use, on an input 1`] = `
exports[`t-model directive basic use, on an input with bracket expression 1`] = ` exports[`t-model directive basic use, on an input with bracket expression 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { toNumber } = helpers;
let block1 = createBlock(\`<div><input block-attribute-0=\\"value\\" block-handler-1=\\"input\\"/><span><block-text-2/></span></div>\`); let block1 = createBlock(\`<div><input block-attribute-0=\\"value\\" block-handler-1=\\"input\\"/><span><block-text-2/></span></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const bExpr1 = ctx['state']; const bExpr1 = ctx['state'];
let d1 = ctx['state']['text']; let attr1 = ctx['state']['text'];
let d2 = [(ev) => { bExpr1['text'] = ev.target.value; }]; let hdlr1 = [(ev) => { bExpr1['text'] = ev.target.value; }];
let d3 = ctx['state'].text; let txt1 = ctx['state'].text;
return block1([d1, d2, d3]); return block1([attr1, hdlr1, txt1]);
} }
}" }"
`; `;
@@ -93,17 +93,17 @@ exports[`t-model directive basic use, on an input with bracket expression 1`] =
exports[`t-model directive basic use, on another key in component 1`] = ` exports[`t-model directive basic use, on another key in component 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { toNumber } = helpers;
let block1 = createBlock(\`<div><input block-attribute-0=\\"value\\" block-handler-1=\\"input\\"/><span><block-text-2/></span></div>\`); let block1 = createBlock(\`<div><input block-attribute-0=\\"value\\" block-handler-1=\\"input\\"/><span><block-text-2/></span></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const bExpr1 = ctx['some']; const bExpr1 = ctx['some'];
let d1 = ctx['some']['text']; let attr1 = ctx['some']['text'];
let d2 = [(ev) => { bExpr1['text'] = ev.target.value; }]; let hdlr1 = [(ev) => { bExpr1['text'] = ev.target.value; }];
let d3 = ctx['some'].text; let txt1 = ctx['some'].text;
return block1([d1, d2, d3]); return block1([attr1, hdlr1, txt1]);
} }
}" }"
`; `;
@@ -111,18 +111,17 @@ exports[`t-model directive basic use, on another key in component 1`] = `
exports[`t-model directive can also define t-on directive on same event, part 1 1`] = ` exports[`t-model directive can also define t-on directive on same event, part 1 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { toNumber } = helpers;
let block1 = createBlock(\`<div><input block-handler-0=\\"input\\" block-attribute-1=\\"value\\" block-handler-2=\\"input\\"/></div>\`); let block1 = createBlock(\`<div><input block-handler-0=\\"input\\" block-attribute-1=\\"value\\" block-handler-2=\\"input\\"/></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const v1 = ctx['onInput']; let hdlr1 = [ctx['onInput'], ctx];
let d1 = [v1, ctx]; const bExpr1 = ctx['state'];
const bExpr2 = ctx['state']; let attr1 = ctx['state']['text'];
let d2 = ctx['state']['text']; let hdlr2 = [(ev) => { bExpr1['text'] = ev.target.value; }];
let d3 = [(ev) => { bExpr2['text'] = ev.target.value; }]; return block1([hdlr1, attr1, hdlr2]);
return block1([d1, d2, d3]);
} }
}" }"
`; `;
@@ -130,28 +129,25 @@ exports[`t-model directive can also define t-on directive on same event, part 1
exports[`t-model directive can also define t-on directive on same event, part 2 1`] = ` exports[`t-model directive can also define t-on directive on same event, part 2 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { toNumber } = helpers;
let block1 = createBlock(\`<div><input type=\\"radio\\" id=\\"one\\" value=\\"One\\" block-handler-0=\\"click\\" block-attribute-1=\\"checked\\" block-handler-2=\\"click\\"/><input type=\\"radio\\" id=\\"two\\" value=\\"Two\\" block-handler-3=\\"click\\" block-attribute-4=\\"checked\\" block-handler-5=\\"click\\"/><input type=\\"radio\\" id=\\"three\\" value=\\"Three\\" block-handler-6=\\"click\\" block-attribute-7=\\"checked\\" block-handler-8=\\"click\\"/></div>\`); let block1 = createBlock(\`<div><input type=\\"radio\\" id=\\"one\\" value=\\"One\\" block-handler-0=\\"click\\" block-attribute-1=\\"checked\\" block-handler-2=\\"click\\"/><input type=\\"radio\\" id=\\"two\\" value=\\"Two\\" block-handler-3=\\"click\\" block-attribute-4=\\"checked\\" block-handler-5=\\"click\\"/><input type=\\"radio\\" id=\\"three\\" value=\\"Three\\" block-handler-6=\\"click\\" block-attribute-7=\\"checked\\" block-handler-8=\\"click\\"/></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const v1 = ctx['onClick']; let hdlr1 = [ctx['onClick'], ctx];
let d1 = [v1, ctx]; const bExpr1 = ctx['state'];
let attr1 = ctx['state']['choice'] === 'One';
let hdlr2 = [(ev) => { bExpr1['choice'] = ev.target.value; }];
let hdlr3 = [ctx['onClick'], ctx];
const bExpr2 = ctx['state']; const bExpr2 = ctx['state'];
let d2 = ctx['state']['choice'] === 'One'; let attr2 = ctx['state']['choice'] === 'Two';
let d3 = [(ev) => { bExpr2['choice'] = ev.target.value; }]; let hdlr4 = [(ev) => { bExpr2['choice'] = ev.target.value; }];
const v3 = ctx['onClick']; let hdlr5 = [ctx['onClick'], ctx];
let d4 = [v3, ctx]; const bExpr3 = ctx['state'];
const bExpr4 = ctx['state']; let attr3 = ctx['state']['choice'] === 'Three';
let d5 = ctx['state']['choice'] === 'Two'; let hdlr6 = [(ev) => { bExpr3['choice'] = ev.target.value; }];
let d6 = [(ev) => { bExpr4['choice'] = ev.target.value; }]; return block1([hdlr1, attr1, hdlr2, hdlr3, attr2, hdlr4, hdlr5, attr3, hdlr6]);
const v5 = ctx['onClick'];
let d7 = [v5, ctx];
const bExpr6 = ctx['state'];
let d8 = ctx['state']['choice'] === 'Three';
let d9 = [(ev) => { bExpr6['choice'] = ev.target.value; }];
return block1([d1, d2, d3, d4, d5, d6, d7, d8, d9]);
} }
}" }"
`; `;
@@ -159,8 +155,8 @@ exports[`t-model directive can also define t-on directive on same event, part 2
exports[`t-model directive following a scope protecting directive (e.g. t-set) 1`] = ` exports[`t-model directive following a scope protecting directive (e.g. t-set) 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { isBoundary, withDefault, setContextValue, toNumber } = helpers;
let block1 = createBlock(\`<div><input block-attribute-0=\\"value\\" block-handler-1=\\"input\\"/></div>\`); let block1 = createBlock(\`<div><input block-attribute-0=\\"value\\" block-handler-1=\\"input\\"/></div>\`);
@@ -169,9 +165,9 @@ exports[`t-model directive following a scope protecting directive (e.g. t-set) 1
ctx[isBoundary] = 1 ctx[isBoundary] = 1
setContextValue(ctx, \\"admiral\\", 'Bruno'); setContextValue(ctx, \\"admiral\\", 'Bruno');
const bExpr1 = ctx['state']; const bExpr1 = ctx['state'];
let d1 = ctx['state']['text']; let attr1 = ctx['state']['text'];
let d2 = [(ev) => { bExpr1['text'] = ev.target.value; }]; let hdlr1 = [(ev) => { bExpr1['text'] = ev.target.value; }];
return block1([d1, d2]); return block1([attr1, hdlr1]);
} }
}" }"
`; `;
@@ -179,8 +175,8 @@ exports[`t-model directive following a scope protecting directive (e.g. t-set) 1
exports[`t-model directive in a t-foreach 1`] = ` exports[`t-model directive in a t-foreach 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { prepareList, toNumber, withKey } = helpers;
let block1 = createBlock(\`<div><block-child-0/></div>\`); let block1 = createBlock(\`<div><block-child-0/></div>\`);
let block3 = createBlock(\`<input type=\\"checkbox\\" block-attribute-0=\\"checked\\" block-handler-1=\\"input\\"/>\`); let block3 = createBlock(\`<input type=\\"checkbox\\" block-attribute-0=\\"checked\\" block-handler-1=\\"input\\"/>\`);
@@ -192,9 +188,9 @@ exports[`t-model directive in a t-foreach 1`] = `
ctx[\`thing\`] = v_block2[i1]; ctx[\`thing\`] = v_block2[i1];
let key1 = ctx['thing'].id; let key1 = ctx['thing'].id;
const bExpr1 = ctx['thing']; const bExpr1 = ctx['thing'];
let d1 = ctx['thing']['f']; let attr1 = ctx['thing']['f'];
let d2 = [(ev) => { bExpr1['f'] = ev.target.checked; }]; let hdlr1 = [(ev) => { bExpr1['f'] = ev.target.checked; }];
c_block2[i1] = withKey(block3([d1, d2]), key1); c_block2[i1] = withKey(block3([attr1, hdlr1]), key1);
} }
let b2 = list(c_block2); let b2 = list(c_block2);
return block1([], [b2]); return block1([], [b2]);
@@ -205,8 +201,8 @@ exports[`t-model directive in a t-foreach 1`] = `
exports[`t-model directive in a t-foreach, part 2 1`] = ` exports[`t-model directive in a t-foreach, part 2 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { prepareList, toNumber, withKey } = helpers;
let block1 = createBlock(\`<div><block-child-0/></div>\`); let block1 = createBlock(\`<div><block-child-0/></div>\`);
let block3 = createBlock(\`<input block-attribute-0=\\"value\\" block-handler-1=\\"input\\"/>\`); let block3 = createBlock(\`<input block-attribute-0=\\"value\\" block-handler-1=\\"input\\"/>\`);
@@ -219,9 +215,9 @@ exports[`t-model directive in a t-foreach, part 2 1`] = `
ctx[\`thing_index\`] = i1; ctx[\`thing_index\`] = i1;
let key1 = ctx['thing_index']; let key1 = ctx['thing_index'];
const bExpr1 = ctx['state']; const bExpr1 = ctx['state'];
let d1 = ctx['state'][ctx['thing_index']]; let attr1 = ctx['state'][ctx['thing_index']];
let d2 = [(ev) => { bExpr1[ctx['thing_index']] = ev.target.value; }]; let hdlr1 = [(ev) => { bExpr1[ctx['thing_index']] = ev.target.value; }];
c_block2[i1] = withKey(block3([d1, d2]), key1); c_block2[i1] = withKey(block3([attr1, hdlr1]), key1);
} }
let b2 = list(c_block2); let b2 = list(c_block2);
return block1([], [b2]); return block1([], [b2]);
@@ -232,17 +228,17 @@ exports[`t-model directive in a t-foreach, part 2 1`] = `
exports[`t-model directive on a select 1`] = ` exports[`t-model directive on a select 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { toNumber } = helpers;
let block1 = createBlock(\`<div><select block-attribute-0=\\"value\\" block-handler-1=\\"change\\"><option value=\\"\\">Please select one</option><option value=\\"red\\">Red</option><option value=\\"blue\\">Blue</option></select><span>Choice: <block-text-2/></span></div>\`); let block1 = createBlock(\`<div><select block-attribute-0=\\"value\\" block-handler-1=\\"change\\"><option value=\\"\\">Please select one</option><option value=\\"red\\">Red</option><option value=\\"blue\\">Blue</option></select><span>Choice: <block-text-2/></span></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const bExpr1 = ctx['state']; const bExpr1 = ctx['state'];
let d1 = ctx['state']['color']; let attr1 = ctx['state']['color'];
let d2 = [(ev) => { bExpr1['color'] = ev.target.value; }]; let hdlr1 = [(ev) => { bExpr1['color'] = ev.target.value; }];
let d3 = ctx['state'].color; let txt1 = ctx['state'].color;
return block1([d1, d2, d3]); return block1([attr1, hdlr1, txt1]);
} }
}" }"
`; `;
@@ -250,16 +246,16 @@ exports[`t-model directive on a select 1`] = `
exports[`t-model directive on a select, initial state 1`] = ` exports[`t-model directive on a select, initial state 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { toNumber } = helpers;
let block1 = createBlock(\`<div><select block-attribute-0=\\"value\\" block-handler-1=\\"change\\"><option value=\\"\\">Please select one</option><option value=\\"red\\">Red</option><option value=\\"blue\\">Blue</option></select></div>\`); let block1 = createBlock(\`<div><select block-attribute-0=\\"value\\" block-handler-1=\\"change\\"><option value=\\"\\">Please select one</option><option value=\\"red\\">Red</option><option value=\\"blue\\">Blue</option></select></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const bExpr1 = ctx['state']; const bExpr1 = ctx['state'];
let d1 = ctx['state']['color']; let attr1 = ctx['state']['color'];
let d2 = [(ev) => { bExpr1['color'] = ev.target.value; }]; let hdlr1 = [(ev) => { bExpr1['color'] = ev.target.value; }];
return block1([d1, d2]); return block1([attr1, hdlr1]);
} }
}" }"
`; `;
@@ -267,17 +263,17 @@ exports[`t-model directive on a select, initial state 1`] = `
exports[`t-model directive on a sub state key 1`] = ` exports[`t-model directive on a sub state key 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { toNumber } = helpers;
let block1 = createBlock(\`<div><input block-attribute-0=\\"value\\" block-handler-1=\\"input\\"/><span><block-text-2/></span></div>\`); let block1 = createBlock(\`<div><input block-attribute-0=\\"value\\" block-handler-1=\\"input\\"/><span><block-text-2/></span></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const bExpr1 = ctx['state'].something; const bExpr1 = ctx['state'].something;
let d1 = ctx['state'].something['text']; let attr1 = ctx['state'].something['text'];
let d2 = [(ev) => { bExpr1['text'] = ev.target.value; }]; let hdlr1 = [(ev) => { bExpr1['text'] = ev.target.value; }];
let d3 = ctx['state'].something.text; let txt1 = ctx['state'].something.text;
return block1([d1, d2, d3]); return block1([attr1, hdlr1, txt1]);
} }
}" }"
`; `;
@@ -285,20 +281,20 @@ exports[`t-model directive on a sub state key 1`] = `
exports[`t-model directive on an input type=radio 1`] = ` exports[`t-model directive on an input type=radio 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { toNumber } = helpers;
let block1 = createBlock(\`<div><input type=\\"radio\\" id=\\"one\\" value=\\"One\\" block-attribute-0=\\"checked\\" block-handler-1=\\"click\\"/><input type=\\"radio\\" id=\\"two\\" value=\\"Two\\" block-attribute-2=\\"checked\\" block-handler-3=\\"click\\"/><span>Choice: <block-text-4/></span></div>\`); let block1 = createBlock(\`<div><input type=\\"radio\\" id=\\"one\\" value=\\"One\\" block-attribute-0=\\"checked\\" block-handler-1=\\"click\\"/><input type=\\"radio\\" id=\\"two\\" value=\\"Two\\" block-attribute-2=\\"checked\\" block-handler-3=\\"click\\"/><span>Choice: <block-text-4/></span></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const bExpr1 = ctx['state']; const bExpr1 = ctx['state'];
let d1 = ctx['state']['choice'] === 'One'; let attr1 = ctx['state']['choice'] === 'One';
let d2 = [(ev) => { bExpr1['choice'] = ev.target.value; }]; let hdlr1 = [(ev) => { bExpr1['choice'] = ev.target.value; }];
const bExpr2 = ctx['state']; const bExpr2 = ctx['state'];
let d3 = ctx['state']['choice'] === 'Two'; let attr2 = ctx['state']['choice'] === 'Two';
let d4 = [(ev) => { bExpr2['choice'] = ev.target.value; }]; let hdlr2 = [(ev) => { bExpr2['choice'] = ev.target.value; }];
let d5 = ctx['state'].choice; let txt1 = ctx['state'].choice;
return block1([d1, d2, d3, d4, d5]); return block1([attr1, hdlr1, attr2, hdlr2, txt1]);
} }
}" }"
`; `;
@@ -306,19 +302,19 @@ exports[`t-model directive on an input type=radio 1`] = `
exports[`t-model directive on an input type=radio, with initial value 1`] = ` exports[`t-model directive on an input type=radio, with initial value 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { toNumber } = helpers;
let block1 = createBlock(\`<div><input type=\\"radio\\" id=\\"one\\" value=\\"One\\" block-attribute-0=\\"checked\\" block-handler-1=\\"click\\"/><input type=\\"radio\\" id=\\"two\\" value=\\"Two\\" block-attribute-2=\\"checked\\" block-handler-3=\\"click\\"/></div>\`); let block1 = createBlock(\`<div><input type=\\"radio\\" id=\\"one\\" value=\\"One\\" block-attribute-0=\\"checked\\" block-handler-1=\\"click\\"/><input type=\\"radio\\" id=\\"two\\" value=\\"Two\\" block-attribute-2=\\"checked\\" block-handler-3=\\"click\\"/></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const bExpr1 = ctx['state']; const bExpr1 = ctx['state'];
let d1 = ctx['state']['choice'] === 'One'; let attr1 = ctx['state']['choice'] === 'One';
let d2 = [(ev) => { bExpr1['choice'] = ev.target.value; }]; let hdlr1 = [(ev) => { bExpr1['choice'] = ev.target.value; }];
const bExpr2 = ctx['state']; const bExpr2 = ctx['state'];
let d3 = ctx['state']['choice'] === 'Two'; let attr2 = ctx['state']['choice'] === 'Two';
let d4 = [(ev) => { bExpr2['choice'] = ev.target.value; }]; let hdlr2 = [(ev) => { bExpr2['choice'] = ev.target.value; }];
return block1([d1, d2, d3, d4]); return block1([attr1, hdlr1, attr2, hdlr2]);
} }
}" }"
`; `;
@@ -326,22 +322,22 @@ exports[`t-model directive on an input type=radio, with initial value 1`] = `
exports[`t-model directive on an input, type=checkbox 1`] = ` exports[`t-model directive on an input, type=checkbox 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { toNumber } = helpers;
let block1 = createBlock(\`<div><input type=\\"checkbox\\" block-attribute-0=\\"checked\\" block-handler-1=\\"input\\"/><span><block-child-0/><block-child-1/></span></div>\`); let block1 = createBlock(\`<div><input type=\\"checkbox\\" block-attribute-0=\\"checked\\" block-handler-1=\\"input\\"/><span><block-child-0/><block-child-1/></span></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let b2,b3; let b2,b3;
const bExpr1 = ctx['state']; const bExpr1 = ctx['state'];
let d1 = ctx['state']['flag']; let attr1 = ctx['state']['flag'];
let d2 = [(ev) => { bExpr1['flag'] = ev.target.checked; }]; let hdlr1 = [(ev) => { bExpr1['flag'] = ev.target.checked; }];
if (ctx['state'].flag) { if (ctx['state'].flag) {
b2 = text(\`yes\`); b2 = text(\`yes\`);
} else { } else {
b3 = text(\`no\`); b3 = text(\`no\`);
} }
return block1([d1, d2], [b2, b3]); return block1([attr1, hdlr1], [b2, b3]);
} }
}" }"
`; `;
@@ -349,17 +345,17 @@ exports[`t-model directive on an input, type=checkbox 1`] = `
exports[`t-model directive on an textarea 1`] = ` exports[`t-model directive on an textarea 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { toNumber } = helpers;
let block1 = createBlock(\`<div><textarea block-attribute-0=\\"value\\" block-handler-1=\\"input\\"/><span><block-text-2/></span></div>\`); let block1 = createBlock(\`<div><textarea block-attribute-0=\\"value\\" block-handler-1=\\"input\\"/><span><block-text-2/></span></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const bExpr1 = ctx['state']; const bExpr1 = ctx['state'];
let d1 = ctx['state']['text']; let attr1 = ctx['state']['text'];
let d2 = [(ev) => { bExpr1['text'] = ev.target.value; }]; let hdlr1 = [(ev) => { bExpr1['text'] = ev.target.value; }];
let d3 = ctx['state'].text; let txt1 = ctx['state'].text;
return block1([d1, d2, d3]); return block1([attr1, hdlr1, txt1]);
} }
}" }"
`; `;
@@ -367,8 +363,8 @@ exports[`t-model directive on an textarea 1`] = `
exports[`t-model directive two inputs in a div alternating with a t-if 1`] = ` exports[`t-model directive two inputs in a div alternating with a t-if 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { toNumber } = helpers;
let block1 = createBlock(\`<div><block-child-0/><block-child-1/></div>\`); let block1 = createBlock(\`<div><block-child-0/><block-child-1/></div>\`);
let block2 = createBlock(\`<input class=\\"a\\" block-attribute-0=\\"value\\" block-handler-1=\\"input\\"/>\`); let block2 = createBlock(\`<input class=\\"a\\" block-attribute-0=\\"value\\" block-handler-1=\\"input\\"/>\`);
@@ -378,15 +374,15 @@ exports[`t-model directive two inputs in a div alternating with a t-if 1`] = `
let b2,b3; let b2,b3;
if (ctx['state'].flag) { if (ctx['state'].flag) {
const bExpr1 = ctx['state']; const bExpr1 = ctx['state'];
let d1 = ctx['state']['text1']; let attr1 = ctx['state']['text1'];
let d2 = [(ev) => { bExpr1['text1'] = ev.target.value; }]; let hdlr1 = [(ev) => { bExpr1['text1'] = ev.target.value; }];
b2 = block2([d1, d2]); b2 = block2([attr1, hdlr1]);
} }
if (!ctx['state'].flag) { if (!ctx['state'].flag) {
const bExpr2 = ctx['state']; const bExpr2 = ctx['state'];
let d3 = ctx['state']['text2']; let attr2 = ctx['state']['text2'];
let d4 = [(ev) => { bExpr2['text2'] = ev.target.value; }]; let hdlr2 = [(ev) => { bExpr2['text2'] = ev.target.value; }];
b3 = block3([d3, d4]); b3 = block3([attr2, hdlr2]);
} }
return block1([], [b2, b3]); return block1([], [b2, b3]);
} }
@@ -3,8 +3,8 @@
exports[`t-on t-on expression captured in t-foreach 1`] = ` exports[`t-on t-on expression captured in t-foreach 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { isBoundary, withDefault, setContextValue, prepareList, withKey } = helpers;
let block1 = createBlock(\`<div><block-child-0/></div>\`); let block1 = createBlock(\`<div><block-child-0/></div>\`);
let block3 = createBlock(\`<div><button block-handler-0=\\"click\\">expr</button></div>\`); let block3 = createBlock(\`<div><button block-handler-0=\\"click\\">expr</button></div>\`);
@@ -20,9 +20,9 @@ exports[`t-on t-on expression captured in t-foreach 1`] = `
let key1 = ctx['val']; let key1 = ctx['val'];
const v1 = ctx['otherState']; const v1 = ctx['otherState'];
const v2 = ctx['iter']; const v2 = ctx['iter'];
let d1 = [()=>v1.vals.push(v2+'_'+v2), ctx]; let hdlr1 = [()=>v1.vals.push(v2+'_'+v2), ctx];
setContextValue(ctx, \\"iter\\", ctx['iter']+1); setContextValue(ctx, \\"iter\\", ctx['iter']+1);
c_block2[i1] = withKey(block3([d1]), key1); c_block2[i1] = withKey(block3([hdlr1]), key1);
} }
let b2 = list(c_block2); let b2 = list(c_block2);
return block1([], [b2]); return block1([], [b2]);
@@ -33,8 +33,8 @@ exports[`t-on t-on expression captured in t-foreach 1`] = `
exports[`t-on t-on expression in t-foreach 1`] = ` exports[`t-on t-on expression in t-foreach 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { prepareList, withKey } = helpers;
let block1 = createBlock(\`<div><block-child-0/></div>\`); let block1 = createBlock(\`<div><block-child-0/></div>\`);
let block3 = createBlock(\`<div><block-text-0/>: <block-text-1/><button block-handler-2=\\"click\\">Expr</button></div>\`); let block3 = createBlock(\`<div><block-text-0/>: <block-text-1/><button block-handler-2=\\"click\\">Expr</button></div>\`);
@@ -46,12 +46,12 @@ exports[`t-on t-on expression in t-foreach 1`] = `
ctx[\`val\`] = v_block2[i1]; ctx[\`val\`] = v_block2[i1];
ctx[\`val_index\`] = i1; ctx[\`val_index\`] = i1;
let key1 = ctx['val']; let key1 = ctx['val'];
let d1 = ctx['val_index']; let txt1 = ctx['val_index'];
let d2 = ctx['val']+''; let txt2 = ctx['val']+'';
const v1 = ctx['otherState']; const v1 = ctx['otherState'];
const v2 = ctx['val']; const v2 = ctx['val'];
let d3 = [()=>v1.vals.push(v2), ctx]; let hdlr1 = [()=>v1.vals.push(v2), ctx];
c_block2[i1] = withKey(block3([d1, d2, d3]), key1); c_block2[i1] = withKey(block3([txt1, txt2, hdlr1]), key1);
} }
let b2 = list(c_block2); let b2 = list(c_block2);
return block1([], [b2]); return block1([], [b2]);
@@ -62,8 +62,8 @@ exports[`t-on t-on expression in t-foreach 1`] = `
exports[`t-on t-on expression in t-foreach with t-set 1`] = ` exports[`t-on t-on expression in t-foreach with t-set 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { isBoundary, withDefault, setContextValue, prepareList, withKey } = helpers;
let block1 = createBlock(\`<div><block-child-0/></div>\`); let block1 = createBlock(\`<div><block-child-0/></div>\`);
let block3 = createBlock(\`<div><block-text-0/>: <block-text-1/><button block-handler-2=\\"click\\">Expr</button></div>\`); let block3 = createBlock(\`<div><block-text-0/>: <block-text-1/><button block-handler-2=\\"click\\">Expr</button></div>\`);
@@ -79,13 +79,13 @@ exports[`t-on t-on expression in t-foreach with t-set 1`] = `
ctx[\`val_index\`] = i1; ctx[\`val_index\`] = i1;
let key1 = ctx['val']; let key1 = ctx['val'];
setContextValue(ctx, \\"bossa\\", ctx['bossa']+'_'+ctx['val_index']); setContextValue(ctx, \\"bossa\\", ctx['bossa']+'_'+ctx['val_index']);
let d1 = ctx['val_index']; let txt1 = ctx['val_index'];
let d2 = ctx['val']+''; let txt2 = ctx['val']+'';
const v1 = ctx['otherState']; const v1 = ctx['otherState'];
const v2 = ctx['val']; const v2 = ctx['val'];
const v3 = ctx['bossa']; const v3 = ctx['bossa'];
let d3 = [()=>v1.vals.push(v2+'_'+v3), ctx]; let hdlr1 = [()=>v1.vals.push(v2+'_'+v3), ctx];
c_block2[i1] = withKey(block3([d1, d2, d3]), key1); c_block2[i1] = withKey(block3([txt1, txt2, hdlr1]), key1);
} }
let b2 = list(c_block2); let b2 = list(c_block2);
return block1([], [b2]); return block1([], [b2]);
@@ -96,8 +96,8 @@ exports[`t-on t-on expression in t-foreach with t-set 1`] = `
exports[`t-on t-on method call in t-foreach 1`] = ` exports[`t-on t-on method call in t-foreach 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { prepareList, withKey } = helpers;
let block1 = createBlock(\`<div><block-child-0/></div>\`); let block1 = createBlock(\`<div><block-child-0/></div>\`);
let block3 = createBlock(\`<div><block-text-0/>: <block-text-1/><button block-handler-2=\\"click\\">meth call</button></div>\`); let block3 = createBlock(\`<div><block-text-0/>: <block-text-1/><button block-handler-2=\\"click\\">meth call</button></div>\`);
@@ -109,11 +109,11 @@ exports[`t-on t-on method call in t-foreach 1`] = `
ctx[\`val\`] = v_block2[i1]; ctx[\`val\`] = v_block2[i1];
ctx[\`val_index\`] = i1; ctx[\`val_index\`] = i1;
let key1 = ctx['val']; let key1 = ctx['val'];
let d1 = ctx['val_index']; let txt1 = ctx['val_index'];
let d2 = ctx['val']+''; let txt2 = ctx['val']+'';
const v1 = ctx['val']; const v1 = ctx['val'];
let d3 = [()=>this.addVal(v1), ctx]; let hdlr1 = [()=>this.addVal(v1), ctx];
c_block2[i1] = withKey(block3([d1, d2, d3]), key1); c_block2[i1] = withKey(block3([txt1, txt2, hdlr1]), key1);
} }
let b2 = list(c_block2); let b2 = list(c_block2);
return block1([], [b2]); return block1([], [b2]);
@@ -124,15 +124,16 @@ exports[`t-on t-on method call in t-foreach 1`] = `
exports[`t-on t-on on destroyed components 1`] = ` exports[`t-on t-on on destroyed components 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div block-handler-0=\\"click\\"/>\`); let block1 = createBlock(\`<div><block-child-0/></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const v1 = ctx['onClick']; let b2;
let d1 = [v1, ctx]; if (ctx['state'].flag) {
return block1([d1]); b2 = component(\`Child\`, {}, key+\`__1\`,null, node, ctx);
}
return block1([], [b2]);
} }
}" }"
`; `;
@@ -140,17 +141,13 @@ exports[`t-on t-on on destroyed components 1`] = `
exports[`t-on t-on on destroyed components 2`] = ` exports[`t-on t-on on destroyed components 2`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><block-child-0/></div>\`); let block1 = createBlock(\`<div block-handler-0=\\"click\\"/>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let b2; let hdlr1 = [ctx['onClick'], ctx];
if (ctx['state'].flag) { return block1([hdlr1]);
b2 = component(\`Child\`, {}, key + \`__1\`, node, ctx);
}
return block1([], [b2]);
} }
}" }"
`; `;
@@ -3,14 +3,13 @@
exports[`t-props basic use 1`] = ` exports[`t-props basic use 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<span><block-text-0/></span>\`); let block1 = createBlock(\`<div><block-child-0/></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = ctx['props'].a+ctx['props'].b; let b2 = component(\`Child\`, ctx['some'].obj, key+\`__1\`,null, node, ctx);
return block1([d1]); return block1([], [b2]);
} }
}" }"
`; `;
@@ -18,14 +17,13 @@ exports[`t-props basic use 1`] = `
exports[`t-props basic use 2`] = ` exports[`t-props basic use 2`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><block-child-0/></div>\`); let block1 = createBlock(\`<span><block-text-0/></span>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let b2 = component(\`Child\`, ctx['some'].obj, key + \`__1\`, node, ctx); let txt1 = ctx['props'].a+ctx['props'].b;
return block1([], [b2]); return block1([txt1]);
} }
}" }"
`; `;
@@ -33,15 +31,13 @@ exports[`t-props basic use 2`] = `
exports[`t-props t-props and other props 1`] = ` exports[`t-props t-props and other props 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><block-text-0/><block-text-1/></div>\`); let block1 = createBlock(\`<div><div><block-child-0/></div></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = ctx['props'].a; let b2 = component(\`Comp\`, Object.assign({}, ctx['state1'], {a: ctx['a']}), key+\`__1\`,null, node, ctx);
let d2 = ctx['props'].b; return block1([], [b2]);
return block1([d1, d2]);
} }
}" }"
`; `;
@@ -49,14 +45,14 @@ exports[`t-props t-props and other props 1`] = `
exports[`t-props t-props and other props 2`] = ` exports[`t-props t-props and other props 2`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><div><block-child-0/></div></div>\`); let block1 = createBlock(\`<div><block-text-0/><block-text-1/></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let b2 = component(\`Comp\`, Object.assign({}, ctx['state1'], {a: ctx['a']}), key + \`__1\`, node, ctx); let txt1 = ctx['props'].a;
return block1([], [b2]); let txt2 = ctx['props'].b;
return block1([txt1, txt2]);
} }
}" }"
`; `;
@@ -64,14 +60,13 @@ exports[`t-props t-props and other props 2`] = `
exports[`t-props t-props only 1`] = ` exports[`t-props t-props only 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><block-text-0/></div>\`); let block1 = createBlock(\`<div><div><block-child-0/></div></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let d1 = ctx['props'].a; let b2 = component(\`Comp\`, ctx['state'], key+\`__1\`,null, node, ctx);
return block1([d1]); return block1([], [b2]);
} }
}" }"
`; `;
@@ -79,14 +74,13 @@ exports[`t-props t-props only 1`] = `
exports[`t-props t-props only 2`] = ` exports[`t-props t-props only 2`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><div><block-child-0/></div></div>\`); let block1 = createBlock(\`<div><block-text-0/></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let b2 = component(\`Comp\`, ctx['state'], key + \`__1\`, node, ctx); let txt1 = ctx['props'].a;
return block1([], [b2]); return block1([txt1]);
} }
}" }"
`; `;
@@ -94,8 +88,21 @@ exports[`t-props t-props only 2`] = `
exports[`t-props t-props with props 1`] = ` exports[`t-props t-props with props 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><block-child-0/></div>\`);
return function template(ctx, node, key = \\"\\") {
let b2 = component(\`Child\`, Object.assign({}, ctx['props'], {a: 1,b: 2}), key+\`__1\`,null, node, ctx);
return block1([], [b2]);
}
}"
`;
exports[`t-props t-props with props 2`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let block1 = createBlock(\`<div/>\`); let block1 = createBlock(\`<div/>\`);
@@ -104,18 +111,3 @@ exports[`t-props t-props with props 1`] = `
} }
}" }"
`; `;
exports[`t-props t-props with props 2`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><block-child-0/></div>\`);
return function template(ctx, node, key = \\"\\") {
let b2 = component(\`Child\`, Object.assign({}, ctx['props'], {a: 1,b: 2}), key + \`__1\`, node, ctx);
return block1([], [b2]);
}
}"
`;
+266 -64
View File
@@ -3,18 +3,27 @@
exports[`t-set slot setted value (with t-set) not accessible with t-esc 1`] = ` exports[`t-set slot setted value (with t-set) not accessible with t-esc 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { isBoundary, withDefault, setContextValue, capture } = helpers;
let block1 = createBlock(\`<div><block-text-0/><block-text-1/></div>\`); let block1 = createBlock(\`<div><p><block-text-0/></p><block-child-0/><p><block-text-1/></p></div>\`);
function slot1(ctx, node, key = \\"\\") {
ctx = Object.create(ctx);
ctx[isBoundary] = 1
setContextValue(ctx, \\"iter\\", 'inCall');
return text('');
}
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
let d1 = ctx['iter']; setContextValue(ctx, \\"iter\\", 'source');
setContextValue(ctx, \\"iter\\", 'called'); let txt1 = ctx['iter'];
let d2 = ctx['iter']; const ctx1 = capture(ctx);
return block1([d1, d2]); let b2 = component(\`Childcomp\`, {slots: {'default': {__render: slot1, __ctx: ctx1}}}, key+\`__1\`,null, node, ctx);
let txt2 = ctx['iter'];
return block1([txt1, txt2], [b2]);
} }
}" }"
`; `;
@@ -22,25 +31,162 @@ exports[`t-set slot setted value (with t-set) not accessible with t-esc 1`] = `
exports[`t-set slot setted value (with t-set) not accessible with t-esc 2`] = ` exports[`t-set slot setted value (with t-set) not accessible with t-esc 2`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { isBoundary, withDefault, setContextValue } = helpers;
let assign = Object.assign;
let block1 = createBlock(\`<div><p><block-text-0/></p><block-child-0/><p><block-text-1/></p></div>\`); let block1 = createBlock(\`<div><block-text-0/><block-text-1/></div>\`);
const slot3 = ctx => (node, key) => {
setContextValue(ctx, \\"iter\\", 'inCall');
}
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
setContextValue(ctx, \\"iter\\", 'source'); let txt1 = ctx['iter'];
let d1 = ctx['iter']; setContextValue(ctx, \\"iter\\", 'called');
const ctx2 = capture(ctx); let txt2 = ctx['iter'];
let b2 = assign(component(\`Childcomp\`, {}, key + \`__1\`, node, ctx), {slots: {'default': slot3(ctx2)}}); return block1([txt1, txt2]);
let d2 = ctx['iter']; }
return block1([d1, d2], [b2]); }"
`;
exports[`t-set slots with a t-set with a component in body 1`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { capture, isBoundary, withDefault, LazyValue, safeOutput } = helpers;
function slot1(ctx, node, key = \\"\\") {
ctx = Object.create(ctx);
ctx[isBoundary] = 1
ctx[\`v\`] = new LazyValue(value1, ctx, node);
let b3 = text(\` in slot \`);
let b4 = safeOutput(ctx['v']);
return multi([b3, b4]);
}
function value1(ctx, node, key = \\"\\") {
return component(\`C\`, {}, key+\`__1\`,null, node, ctx);
}
return function template(ctx, node, key = \\"\\") {
const ctx1 = capture(ctx);
return component(\`Child\`, {slots: {'default': {__render: slot1, __ctx: ctx1}}}, key+\`__2\`,null, node, ctx);
}
}"
`;
exports[`t-set slots with a t-set with a component in body 2`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { callSlot } = helpers;
return function template(ctx, node, key = \\"\\") {
let b2 = text(\`Child \`);
let b3 = callSlot(ctx, node, key, 'default', false, {});
return multi([b2, b3]);
}
}"
`;
exports[`t-set slots with a t-set with a component in body 3`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
return function template(ctx, node, key = \\"\\") {
return text(\`C\`);
}
}"
`;
exports[`t-set slots with an t-set with a component in body 1`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { capture, isBoundary, withDefault, LazyValue, safeOutput } = helpers;
let block4 = createBlock(\`<div>coffee</div>\`);
function slot1(ctx, node, key = \\"\\") {
ctx = Object.create(ctx);
ctx[isBoundary] = 1
ctx[\`v\`] = new LazyValue(value1, ctx, node);
let b5 = text(\` tea \`);
let b6 = safeOutput(ctx['v']);
return multi([b5, b6]);
}
function value1(ctx, node, key = \\"\\") {
let b3 = component(\`Child\`, {}, key+\`__1\`,null, node, ctx);
let b4 = block4();
return multi([b3, b4]);
}
return function template(ctx, node, key = \\"\\") {
const ctx1 = capture(ctx);
return component(\`Blorg\`, {slots: {'default': {__render: slot1, __ctx: ctx1}}}, key+\`__2\`,null, node, ctx);
}
}"
`;
exports[`t-set slots with an t-set with a component in body 2`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { callSlot } = helpers;
return function template(ctx, node, key = \\"\\") {
let b2 = text(\`Blorg \`);
let b3 = callSlot(ctx, node, key, 'default', false, {});
return multi([b2, b3]);
}
}"
`;
exports[`t-set slots with an t-set with a component in body 3`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
return function template(ctx, node, key = \\"\\") {
return text(\`Child\`);
}
}"
`;
exports[`t-set slots with an unused t-set with a component in body 1`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { capture, isBoundary, withDefault, LazyValue } = helpers;
function slot1(ctx, node, key = \\"\\") {
ctx = Object.create(ctx);
ctx[isBoundary] = 1
ctx[\`v\`] = new LazyValue(value1, ctx, node);
return text(\` in slot \`);
}
function value1(ctx, node, key = \\"\\") {
return component(\`Child\`, {}, key+\`__1\`,null, node, ctx);
}
return function template(ctx, node, key = \\"\\") {
const ctx1 = capture(ctx);
return component(\`Child\`, {slots: {'default': {__render: slot1, __ctx: ctx1}}}, key+\`__2\`,null, node, ctx);
}
}"
`;
exports[`t-set slots with an unused t-set with a component in body 2`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { callSlot } = helpers;
return function template(ctx, node, key = \\"\\") {
let b2 = text(\`Child \`);
let b3 = callSlot(ctx, node, key, 'default', false, {});
return multi([b2, b3]);
} }
}" }"
`; `;
@@ -48,18 +194,18 @@ exports[`t-set slot setted value (with t-set) not accessible with t-esc 2`] = `
exports[`t-set t-set can't alter component even if key in component 1`] = ` exports[`t-set t-set can't alter component even if key in component 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { isBoundary, withDefault, setContextValue } = helpers;
let block1 = createBlock(\`<div><p><block-text-0/></p><p><block-text-1/></p></div>\`); let block1 = createBlock(\`<div><p><block-text-0/></p><p><block-text-1/></p></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
let d1 = ctx['iter']; let txt1 = ctx['iter'];
setContextValue(ctx, \\"iter\\", 5); setContextValue(ctx, \\"iter\\", 5);
let d2 = ctx['iter']; let txt2 = ctx['iter'];
return block1([d1, d2]); return block1([txt1, txt2]);
} }
}" }"
`; `;
@@ -67,18 +213,18 @@ exports[`t-set t-set can't alter component even if key in component 1`] = `
exports[`t-set t-set can't alter component if key not in component 1`] = ` exports[`t-set t-set can't alter component if key not in component 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { isBoundary, withDefault, setContextValue } = helpers;
let block1 = createBlock(\`<div><p><block-text-0/></p><p><block-text-1/></p></div>\`); let block1 = createBlock(\`<div><p><block-text-0/></p><p><block-text-1/></p></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
let d1 = ctx['iter']; let txt1 = ctx['iter'];
setContextValue(ctx, \\"iter\\", 5); setContextValue(ctx, \\"iter\\", 5);
let d2 = ctx['iter']; let txt2 = ctx['iter'];
return block1([d1, d2]); return block1([txt1, txt2]);
} }
}" }"
`; `;
@@ -86,8 +232,8 @@ exports[`t-set t-set can't alter component if key not in component 1`] = `
exports[`t-set t-set in t-if 1`] = ` exports[`t-set t-set in t-if 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { isBoundary, withDefault, setContextValue } = helpers;
let block1 = createBlock(\`<div><block-child-0/><block-child-0/><block-child-0/><p><block-text-0/></p></div>\`); let block1 = createBlock(\`<div><block-child-0/><block-child-0/><block-child-0/><p><block-text-0/></p></div>\`);
@@ -102,8 +248,8 @@ exports[`t-set t-set in t-if 1`] = `
} else { } else {
setContextValue(ctx, \\"iter\\", 4); setContextValue(ctx, \\"iter\\", 4);
} }
let d1 = ctx['iter']; let txt1 = ctx['iter'];
return block1([d1]); return block1([txt1]);
} }
}" }"
`; `;
@@ -111,27 +257,8 @@ exports[`t-set t-set in t-if 1`] = `
exports[`t-set t-set not altered by child comp 1`] = ` exports[`t-set t-set not altered by child comp 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { isBoundary, withDefault, setContextValue } = helpers;
let block1 = createBlock(\`<div><block-text-0/><block-text-1/></div>\`);
return function template(ctx, node, key = \\"\\") {
ctx = Object.create(ctx);
ctx[isBoundary] = 1
let d1 = ctx['iter'];
setContextValue(ctx, \\"iter\\", 'called');
let d2 = ctx['iter'];
return block1([d1, d2]);
}
}"
`;
exports[`t-set t-set not altered by child comp 2`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers;
let block1 = createBlock(\`<div><p><block-text-0/></p><block-child-0/><p><block-text-1/></p></div>\`); let block1 = createBlock(\`<div><p><block-text-0/></p><block-child-0/><p><block-text-1/></p></div>\`);
@@ -139,10 +266,29 @@ exports[`t-set t-set not altered by child comp 2`] = `
ctx = Object.create(ctx); ctx = Object.create(ctx);
ctx[isBoundary] = 1 ctx[isBoundary] = 1
setContextValue(ctx, \\"iter\\", 'source'); setContextValue(ctx, \\"iter\\", 'source');
let d1 = ctx['iter']; let txt1 = ctx['iter'];
let b2 = component(\`Childcomp\`, {}, key + \`__1\`, node, ctx); let b2 = component(\`Childcomp\`, {}, key+\`__1\`,null, node, ctx);
let d2 = ctx['iter']; let txt2 = ctx['iter'];
return block1([d1, d2], [b2]); return block1([txt1, txt2], [b2]);
}
}"
`;
exports[`t-set t-set not altered by child comp 2`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { isBoundary, withDefault, setContextValue } = helpers;
let block1 = createBlock(\`<div><block-text-0/><block-text-1/></div>\`);
return function template(ctx, node, key = \\"\\") {
ctx = Object.create(ctx);
ctx[isBoundary] = 1
let txt1 = ctx['iter'];
setContextValue(ctx, \\"iter\\", 'called');
let txt2 = ctx['iter'];
return block1([txt1, txt2]);
} }
}" }"
`; `;
@@ -150,8 +296,8 @@ exports[`t-set t-set not altered by child comp 2`] = `
exports[`t-set t-set outside modified in t-if 1`] = ` exports[`t-set t-set outside modified in t-if 1`] = `
"function anonymous(bdom, helpers "function anonymous(bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, component } = bdom; let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue, toNumber, safeOutput } = helpers; let { isBoundary, withDefault, setContextValue } = helpers;
let block1 = createBlock(\`<div><block-child-0/><block-child-0/><block-child-0/><p><block-text-0/></p></div>\`); let block1 = createBlock(\`<div><block-child-0/><block-child-0/><block-child-0/><p><block-text-0/></p></div>\`);
@@ -167,8 +313,64 @@ exports[`t-set t-set outside modified in t-if 1`] = `
} else { } else {
setContextValue(ctx, \\"iter\\", 4); setContextValue(ctx, \\"iter\\", 4);
} }
let d1 = ctx['iter']; let txt1 = ctx['iter'];
return block1([d1]); return block1([txt1]);
}
}"
`;
exports[`t-set t-set with a component in body 1`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { isBoundary, withDefault, LazyValue, safeOutput } = helpers;
let block1 = createBlock(\`<div><div><block-child-0/></div></div>\`);
function value1(ctx, node, key = \\"\\") {
return component(\`Child\`, {}, key+\`__1\`,null, node, ctx);
}
return function template(ctx, node, key = \\"\\") {
ctx = Object.create(ctx);
ctx[isBoundary] = 1
ctx[\`v\`] = new LazyValue(value1, ctx, node);
let b3 = safeOutput(ctx['v']);
return block1([], [b3]);
}
}"
`;
exports[`t-set t-set with a component in body 2`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
return function template(ctx, node, key = \\"\\") {
return text(\`Child\`);
}
}"
`;
exports[`t-set t-set with something in body 1`] = `
"function anonymous(bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
let { isBoundary, withDefault, LazyValue, safeOutput } = helpers;
let block1 = createBlock(\`<div><div><block-child-0/></div></div>\`);
let block2 = createBlock(\`<p>coucou</p>\`);
function value1(ctx, node, key = \\"\\") {
return block2();
}
return function template(ctx, node, key = \\"\\") {
ctx = Object.create(ctx);
ctx[isBoundary] = 1
ctx[\`v\`] = new LazyValue(value1, ctx, node);
let b3 = safeOutput(ctx['v']);
return block1([], [b3]);
} }
}" }"
`; `;
-28
View File
@@ -1,28 +0,0 @@
import { App, Component } from "../../src";
import { status } from "../../src/component/status";
import { xml } from "../../src/tags";
import { makeTestFixture, snapshotEverything } from "../helpers";
let fixture: HTMLElement;
snapshotEverything();
beforeEach(() => {
fixture = makeTestFixture();
});
describe("app", () => {
test("destroy remove the widget from the DOM", async () => {
class SomeComponent extends Component {
static template = xml`<div/>`;
}
const app = new App(SomeComponent);
const comp = await app.mount(fixture);
const el = comp.el!;
expect(document.contains(el)).toBe(true);
app.destroy();
expect(document.contains(el)).toBe(false);
expect(status(comp)).toBe("destroyed");
});
});
+47 -48
View File
@@ -1,6 +1,5 @@
import { App, Component, mount, status, useState } from "../../src"; import { App, Component, mount, status, useState, xml } from "../../src";
import { xml } from "../../src/tags"; import { elem, makeTestFixture, nextTick, snapshotEverything } from "../helpers";
import { makeTestFixture, nextTick, snapshotEverything } from "../helpers";
import { markup } from "../../src/utils"; import { markup } from "../../src/utils";
let fixture: HTMLElement; let fixture: HTMLElement;
@@ -20,34 +19,21 @@ describe("basics", () => {
const component = await mount(Test, fixture); const component = await mount(Test, fixture);
expect(fixture.innerHTML).toBe("<span>simple vnode</span>"); expect(fixture.innerHTML).toBe("<span>simple vnode</span>");
expect(component.el).toEqual(fixture.querySelector("span")); expect(elem(component)).toEqual(fixture.querySelector("span"));
});
test("has no el after creation", async () => {
let el: any = null;
class Test extends Component {
static template = xml`<span>simple</span>`;
setup() {
el = this.el;
}
}
await mount(Test, fixture);
expect(el).toBeUndefined();
}); });
test("cannot mount on a documentFragment", async () => { test("cannot mount on a documentFragment", async () => {
class SomeWidget extends Component { class SomeWidget extends Component {
static template = xml`<div>content</div>`; static template = xml`<div>content</div>`;
} }
let error; let error: Error;
try { try {
await mount(SomeWidget, document.createDocumentFragment() as any); await mount(SomeWidget, document.createDocumentFragment() as any);
} catch (e) { } catch (e) {
error = e; error = e as Error;
} }
expect(error).toBeDefined(); expect(error!).toBeDefined();
expect(error.message).toBe("Cannot mount component: the target is not a valid DOM element"); expect(error!.message).toBe("Cannot mount component: the target is not a valid DOM element");
}); });
test("can mount a simple component with props", async () => { test("can mount a simple component with props", async () => {
@@ -55,11 +41,11 @@ describe("basics", () => {
static template = xml`<span><t t-esc="props.value"/></span>`; static template = xml`<span><t t-esc="props.value"/></span>`;
} }
const app = new App(Test, { value: 3 }); const app = new App(Test, { props: { value: 3 } });
const component = await app.mount(fixture); const component = await app.mount(fixture);
expect(fixture.innerHTML).toBe("<span>3</span>"); expect(fixture.innerHTML).toBe("<span>3</span>");
expect(component.el).toEqual(fixture.querySelector("span")); expect(elem(component)).toEqual(fixture.querySelector("span"));
}); });
test("can mount a component with just some text", async () => { test("can mount a component with just some text", async () => {
@@ -70,7 +56,7 @@ describe("basics", () => {
const component = await mount(Test, fixture); const component = await mount(Test, fixture);
expect(fixture.innerHTML).toBe("just text"); expect(fixture.innerHTML).toBe("just text");
expect(component.el).toBeInstanceOf(Text); expect(elem(component)).toBeInstanceOf(Text);
}); });
test("can mount a component with no text", async () => { test("can mount a component with no text", async () => {
@@ -81,7 +67,7 @@ describe("basics", () => {
const component = await mount(Test, fixture); const component = await mount(Test, fixture);
expect(fixture.innerHTML).toBe(""); expect(fixture.innerHTML).toBe("");
expect(component.el).toBeInstanceOf(Text); expect(elem(component)).toBeInstanceOf(Text);
}); });
test("can mount a simple component with multiple roots", async () => { test("can mount a simple component with multiple roots", async () => {
@@ -92,7 +78,7 @@ describe("basics", () => {
const component = await mount(Test, fixture); const component = await mount(Test, fixture);
expect(fixture.innerHTML).toBe("<span></span><div></div>"); expect(fixture.innerHTML).toBe("<span></span><div></div>");
expect((component.el as any).tagName).toBe("SPAN"); expect(elem(component).tagName).toBe("SPAN");
}); });
test("component with dynamic content can be updated", async () => { test("component with dynamic content can be updated", async () => {
@@ -106,7 +92,8 @@ describe("basics", () => {
expect(fixture.innerHTML).toBe("<span>1</span>"); expect(fixture.innerHTML).toBe("<span>1</span>");
component.value = 2; component.value = 2;
await component.render(); component.render();
await nextTick();
expect(fixture.innerHTML).toBe("<span>2</span>"); expect(fixture.innerHTML).toBe("<span>2</span>");
}); });
@@ -123,7 +110,8 @@ describe("basics", () => {
expect(fixture.innerHTML).toBe("onetwothree"); expect(fixture.innerHTML).toBe("onetwothree");
component.items = ["two", "three", "one"]; component.items = ["two", "three", "one"];
await component.render(); component.render();
await nextTick();
expect(fixture.innerHTML).toBe("twothreeone"); expect(fixture.innerHTML).toBe("twothreeone");
}); });
@@ -137,16 +125,15 @@ describe("basics", () => {
} }
} }
const app = new App(Test, p); const app = new App(Test, { props: p });
await app.mount(fixture); await app.mount(fixture);
}); });
test("some simple sanity checks (el/status)", async () => { test("some simple sanity checks (el/status)", async () => {
expect.assertions(4); expect.assertions(3);
class Test extends Component { class Test extends Component {
static template = xml`<span>simple vnode</span>`; static template = xml`<span>simple vnode</span>`;
setup() { setup() {
expect(this.el).toBe(undefined);
expect(status(this)).toBe("new"); expect(status(this)).toBe("new");
} }
} }
@@ -160,28 +147,28 @@ describe("basics", () => {
static template = xml`<span>simple vnode</span>`; static template = xml`<span>simple vnode</span>`;
} }
let error; let error: Error;
try { try {
await mount(Test, null as any); await mount(Test, null as any);
} catch (e) { } catch (e) {
error = e; error = e as Error;
} }
expect(error).toBeDefined(); expect(error!).toBeDefined();
expect(error.message).toBe("Cannot mount component: the target is not a valid DOM element"); expect(error!.message).toBe("Cannot mount component: the target is not a valid DOM element");
}); });
test("a component cannot be mounted in a detached node", async () => { test("a component cannot be mounted in a detached node", async () => {
class Test extends Component { class Test extends Component {
static template = xml`<div/>`; static template = xml`<div/>`;
} }
let error; let error: Error;
try { try {
await mount(Test, document.createElement("div")); await mount(Test, document.createElement("div"));
} catch (e) { } catch (e) {
error = e; error = e as Error;
} }
expect(error).toBeDefined(); expect(error!).toBeDefined();
expect(error.message).toBe("Cannot mount a component on a detached dom node"); expect(error!.message).toBe("Cannot mount a component on a detached dom node");
}); });
test("crashes if it cannot find a template", async () => { test("crashes if it cannot find a template", async () => {
@@ -189,14 +176,14 @@ describe("basics", () => {
static template = "wrongtemplate"; static template = "wrongtemplate";
} }
let error; let error: Error;
try { try {
await mount(Test, fixture); await mount(Test, fixture);
} catch (e) { } catch (e) {
error = e; error = e as Error;
} }
expect(error).toBeDefined(); expect(error!).toBeDefined();
expect(error.message).toBe('Missing template: "wrongtemplate"'); expect(error!.message).toBe('Missing template: "wrongtemplate"');
}); });
test("class component with dynamic text", async () => { test("class component with dynamic text", async () => {
@@ -258,7 +245,8 @@ describe("basics", () => {
const test = await mount(Test, fixture); const test = await mount(Test, fixture);
expect(fixture.innerHTML).toBe("<div>3</div>"); expect(fixture.innerHTML).toBe("<div>3</div>");
test.value = 5; test.value = 5;
await test.render(); test.render();
await nextTick();
expect(fixture.innerHTML).toBe("<div>5</div>"); expect(fixture.innerHTML).toBe("<div>5</div>");
}); });
@@ -377,13 +365,14 @@ describe("basics", () => {
}); });
} }
const counter = await mount(Counter, fixture); await mount(Counter, fixture);
expect(fixture.innerHTML).toBe("<div>0<button>Inc</button></div>"); expect(fixture.innerHTML).toBe("<div>0<button>Inc</button></div>");
const button = (<HTMLElement>counter.el).getElementsByTagName("button")[0]; const button = fixture.getElementsByTagName("button")[0];
button.click(); button.click();
await nextTick(); await nextTick();
expect(fixture.innerHTML).toBe("<div>1<button>Inc</button></div>"); expect(fixture.innerHTML).toBe("<div>1<button>Inc</button></div>");
}); });
// TODO: rename // TODO: rename
test("rerendering a widget with a sub widget", async () => { test("rerendering a widget with a sub widget", async () => {
class Counter extends Component { class Counter extends Component {
@@ -490,7 +479,7 @@ describe("basics", () => {
} }
const widget = await mount(SomeComponent, fixture); const widget = await mount(SomeComponent, fixture);
expect(fixture.innerHTML).toBe(`<div></div>`); expect(fixture.innerHTML).toBe(`<div></div>`);
widget.el!.appendChild(document.createElement("span")); fixture.querySelector("div")!.appendChild(document.createElement("span"));
expect(fixture.innerHTML).toBe(`<div><span></span></div>`); expect(fixture.innerHTML).toBe(`<div><span></span></div>`);
await widget.render(); await widget.render();
expect(fixture.innerHTML).toBe(`<div><span></span></div>`); expect(fixture.innerHTML).toBe(`<div><span></span></div>`);
@@ -503,7 +492,7 @@ describe("basics", () => {
} }
const comp = await mount(SomeComponent, fixture); const comp = await mount(SomeComponent, fixture);
expect(fixture.innerHTML).toBe(`<div><h1>h1</h1><span>1</span></div>`); expect(fixture.innerHTML).toBe(`<div><h1>h1</h1><span>1</span></div>`);
(comp.el! as any).querySelector("h1")!.appendChild(document.createElement("p")); fixture.querySelector("h1")!.appendChild(document.createElement("p"));
expect(fixture.innerHTML).toBe("<div><h1>h1<p></p></h1><span>1</span></div>"); expect(fixture.innerHTML).toBe("<div><h1>h1<p></p></h1><span>1</span></div>");
comp.state.value++; comp.state.value++;
@@ -830,6 +819,16 @@ describe("mount targets", () => {
expect(fixture.innerHTML).toBe("<span></span><div>app</div>"); expect(fixture.innerHTML).toBe("<span></span><div>app</div>");
}); });
test("mount function: can mount a component (with default position='last-child')", async () => {
class Root extends Component {
static template = xml`<div>app</div>`;
}
const span = document.createElement("span");
fixture.appendChild(span);
await mount(Root, fixture, { position: "last-child" });
expect(fixture.innerHTML).toBe("<span></span><div>app</div>");
});
test("default mount option is 'last-child'", async () => { test("default mount option is 'last-child'", async () => {
class Root extends Component { class Root extends Component {
static template = xml`<div>app</div>`; static template = xml`<div>app</div>`;

Some files were not shown because too many files have changed in this diff Show More