Compare commits

..

41 Commits

Author SHA1 Message Date
Géry Debongnie 64bad25762 [REL] v2.0.0-beta-22
# v2.0.0-beta-22

- fix: t-call: nested t-call with magic variable 0
- fix: prevent crash in case with t-foreach, t-out and components
2022-09-29 09:17:06 +02:00
Géry Debongnie 7ab34c5ca5 [FIX] prevent crash in case with t-foreach and t-out with components
The t-out directive is compiled internally into a LazyValue, which
represents a value that may or may not be created sometimes in the
future.  It can also be reused more than once, and this is where there
may be an issue: if a component is contained in the lazyvalue, it needs
a unique key (coming from the t-foreach) to be properly indexed in the
parent children map.  However, the LazyValue does not keep the key
information, so it is not able to provide it to its content.

The fix is then quite clear: the LazyValue class should store the key
information, and provides it to its content.  This allows the LazyValue
to be used multiple times, in any place in a template.

closes #1270
2022-09-29 08:28:38 +02:00
Géry Debongnie 669fd622ec [FIX] t-call: nested t-call with magic variable 0
Before this commit, the template compiler would guess the next block id
that will be generated when compiling the body of a tcall.  This is
correct IF there are not nested t-call, but otherwise wrong, because the
next block id could be mixed up: the first t-call would save the next
block id (let's say n), then the inner t-call would also save the same
block id (so, n), will then generate its own block (n+1), then the outer
t-call would use the block n index instead of n+1

The best fix, in my opinion, is to make sure we get the next block var
name, so we do not have to guess. To do that, each compile block type
function needs to properly return the information.

closes #1267
2022-09-28 09:31:41 +02:00
Géry Debongnie ab72cdddde [REL] v2.0.0-beta-21
# v2.0.0-beta-21

- fix: prevent side effects at template compilation
- fix: props validation: does not crash with t-call-context
- fix: make t-portal work in all cases
- fix: make props validation work through slots
2022-09-26 15:44:11 +02:00
Géry Debongnie 17fb33475c [FIX] props validation: make it work through slots
A recent commit fixes the props validation code to make it work
regardless of the rendering context (important with the recent
t-call-context directive). Unfortunately, it then breaks props
validation through slots, because it assumed that the parent node in the
virtual node was the parent of the component, but it is not necessarily
true.

To fix this, we can use a simple property of the template functions:
they are bound to the current instance of the component, so we can
simply use "this"
2022-09-26 15:17:58 +02:00
Géry Debongnie ab29b896eb [FIX] portal: make it work in all cases
Before this commit, the portal wouldn't work when its target is created
after the portal content, since it wouldn't be able to mount the dom at
the correct location.

With this commit, we work around the issue by mounting the portal
content at the portal location, then when the Portal component is
mounted, moving it to its correct location.

The big downside with that approach is that the portal content is
(sometimes) rendered and mounted at a location, THEN mounted in another
location. I think that it is most of the time not an issue, but one
could argue that it is inconsistent: some specific code could work at
one point, then fail in a different very similar situation (for example,
iframes don't support very well being moved around).  On the flip side,
having the portal work as expected is very useful, and may be worth the
tradeoff.

closes #1250
2022-09-26 12:01:12 +02:00
Géry Debongnie d5ed25cd19 [FIX] props validation: does not crash with t-call-context
The code for props validation assumed that the rendering context was a
component.  This was actually true when it was written, but is no longer
true since t-call-context was introduced.

Because of that, it would crash when trying to access the internals of
the component, such as the static components object.

The fix is simple: instead of passing the context to the props
validation code, which can now be anything, we pass the component node,
which is guaranteed to give a reference to the component (and also to
the app).  This also make the code slightly simpler.

closes #1261
2022-09-24 08:34:22 +02:00
Géry Debongnie c4f0f17b9b [FIX] blockdom: prevent side effects at block compilation
When creating the template node for a block, we create htmlelements and
set their (static) attributes.  But this can have side effects. For
example, setting the src attribute for an img element will trigger a
request to fetch the image.

We avoid that issue by simply setting the html element template node
inside a <template/> element.

Note that I don't really see how to test this fix in jest: we don't have
a real browser, and no real way to check for this side effect.

closes #1257
2022-09-21 13:59:13 +02:00
Florent Dardenne - dafl@odoo d27455e9f2 [IMP] doc: explicit useEffect first parameter
The `useEffect` has two parameters:
* The `effect` function
* The `computeDependencies` function

The `effect` function always take as parameters the result
 of the `computeDependencies` function.

Expliciting this allows to better understand the `useEffect`
behaviour and the following example in the doc:

```
useEffect(
    (el) => el && el.focus(),
    () => [ref.el]
  );
```
2022-09-09 20:24:56 +02:00
Géry Debongnie 6ef38676c4 [DOC] doc: fix broken link and update roadmap 2022-09-09 09:45:05 +02:00
Géry Debongnie b51756f356 [REL] v2.0.0-beta-20
# v2.0.0-beta-20

- app: properly rethrow unhandled errors
2022-09-09 09:26:12 +02:00
Samuel Degueldre cfdf7caa50 [IMP] app: rethrow errors that were not handled
This commit makes it so that when an error occurs in an owl app and none
of the registered error handlers are able to handle it, we rethrow the
error instead of just logging it to the console and swallowing it. This
allows users of owl to handle errors that happen in owl applications by
using event listeners for error and unhandledrejection events on the
window.
2022-09-09 09:23:32 +02:00
Florent Dardenne - dafl@odoo a5a6a592c1 [FIX] tutorial_todoapp: fix the final code mount issue
In app.js, `mount(Root, document.body, { dev: true, env });`  crash because `body` is not available yet.
Therefore, moving the script into the body fix the issue.
2022-09-08 13:30:38 +02:00
Géry Debongnie d0d7482b0f [REL] v2.0.0-beta-19
# v2.0.0-beta-19

- fix: events: correctly call handlers in iframes
2022-09-06 12:13:25 +02:00
Samuel Degueldre 8fe4c0c76e [FIX] events: correctly call handlers in iframes
Previously, event handlers would not work when an app was mounted in an
iframe, this is caused by a guard in the event handler that checks that
the target element is still in the document, but it doesn't check
against the correct document in the case of an iframe.

This commit changes the check to check against the target's
ownerDocument.
2022-09-06 12:06:59 +02:00
Géry Debongnie c1afaeb92a [REL] v2.0.0-beta-18
# v2.0.0-beta-18

- fix: allow multiple occurrences of same slot in different locations
2022-09-02 14:57:18 +02:00
Géry Debongnie 3883cec079 [FIX] slots: prevent crash when using same slot in different locations
Before this commit, a crash could occur when a component with no props
is defined in a slot, and that slot is conditionally displayed in
multiple locations.

The reason for that is that the key provided to the callSlot function
was identical, so from the perspective of the component function, it was
not possible to make the difference between a component located in
either places.  With this commit, we make sure that a unique key is used
when a slot is reused in a template (or if it is dynamic, because in
that case, we have no idea at compile time if it will be unique or not)

closes #1246
2022-09-02 12:12:00 +02:00
Géry Debongnie 9cb74d619b [REL] v2.0.0-beta-17
# v2.0.0-beta-17

- imp: types: expose ComponentConstructor for typing purpose
- fix: compiler: fix falsy values for properties not keeping input empty
- fix: app: allow mounting owl apps in iframe
2022-09-01 15:41:33 +02:00
Samuel Degueldre a93f015795 [FIX] app: allow mounting owl apps in iframe
Previously, attempting to mount an app in an iframe would crash, saying
that the target is not a valid DOM element, this is because instanceof
checks do not work cross-frame as global objects do not have the same
identity in frames as with the main window. This commit fixes that by
making sure the target is an instance of HTMLElement of the
corresponding window, and checks that the corresponding document body
contains it.
2022-08-17 10:05:46 +02:00
Samuel Degueldre 02a187d80b [FIX] compiler: fix falsy values for properties not keeping input empty
Recently, we made it so that when a component is rendered, it always
updates the property values for computed properties. This was done by
wrapping the value in a String or Boolean object. One issue with this is
that wrapping a falsy value in a String doesn't yield an empty string,
but a string containing the value as text (eg new String(undefined) ->
"undefined"), which causes the value to not remain empty as per the
spec. This commit fixes that by adding a fallback to the empty string
for falsy values before converting to a String object.

closes: #1236
2022-08-05 09:50:38 +02:00
Rémi Rahir d3b0d1971e [IMP] types: expose ComponentConstructor for typing purpose
We have been using this type in o-spreadsheet since https://github.com/odoo/o-spreadsheet/pull/1187
but the new typing file (https://github.com/odoo/owl/pull/1207) does not include it.
It would be useful to allow us to bump or version of owl witouht having to resort
to long aboslute paths (i.e. import from `@odoo/owl`and not
`@odoo/owl/dist/types/runtime/component@ everywhere).
2022-07-25 14:34:14 +02:00
Géry Debongnie b90aa0e23a [REL] v2.0.0-beta-16
# v2.0.0-beta-16

Notes

- fix: components: fix cause left unset when thrown object is not Error
2022-07-22 09:43:43 +02:00
Samuel Degueldre 163366997c [FIX] components: fix cause left unset when thrown object is not Error
Previously, when wrapping errors in wrapError, if the error was not an
actual error object, we wouldn't set the cause property on the wrapping
error correctly. The "instanceof Error" check is simply there so that we
can know whether we can add the original errors message to the wrapping
error, but the line that sets the error's cause was mistakenly moved
into that condition.

This commit also fixes the wrapping error's message in the case of
non-Error objects, to avoid having "the following error occurred in
hookname:" with nothing after the colon which is confusing/misleading.
2022-07-22 09:21:19 +02:00
Géry Debongnie 588b655c11 [REL] v2.0.0-beta-15
# v2.0.0-beta-15

Notes

- fix: lifecyle_hooks: correctly wrap errors in async code
- imp: use a custom error class for all errors thrown by owl
- fix: package.json: remove browser value
- ref: component_node: slightly simplify code
2022-07-20 10:02:24 +02:00
Géry Debongnie f5d5273c25 [REF] component_node: slightly simplify code 2022-07-20 09:57:27 +02:00
Géry Debongnie 9fd662fdce [FIX] package.json: remove browser value
As far as I can tell, the browser value overrides the main value in many
cases.  But then, we don't want to use the iife format, since it don't
work well with bundlers. This commit fixes the issue by simply removing
the key, so the main entry will be used instead.

maybe fixes #1181
2022-07-20 09:56:39 +02:00
Samuel Degueldre 7786077921 [IMP] *: use a custom error class for all errors thrown by owl
This commit makes all errors thrown in owl use a custom error class. The
main point of this is to always wrap user-code errors that happen during
the owl lifecycle so that they can be treated uniformly in onError by
checking the cause property, and also allows user code to differenciate
owl errors from non-owl errors reliably at runtime.
2022-07-18 15:40:14 +02:00
Aaron Bohy 30bc605c84 [FIX] lifecyle_hooks: correctly wrap errors in async code
Before this commit, wrapping an error occurring in async code
would result in an unhandledpromise exception, because we created
another promise, that would be rejected and that we didn't catch.
2022-07-18 15:40:14 +02:00
Géry Debongnie d1118455aa [REL] v2.0.0-beta-14
# v2.0.0-beta-14

Yes, there is no beta-13 release...

## Fixes:

- [FIX] compiler: better handle update of properties with same value
2022-07-08 16:11:45 +02:00
Géry Debongnie f8073cb153 [FIX] compiler: better handle update of properties with same value
Before this commit, owl would incorrectly skip patching html properties
when the new value is the same as the value used in the previous render.
However, this is incorrect, since the user may have changed the value by
clicking on a checkbox, or changing some text in an input.

So, to be more correct, owl has to force the update whenever it
encounters a prop.  This is however hard to do without impacting the
main update loop, so we kind of work around the problem by using String
and Boolean instance, instead of primitive values.
2022-07-08 15:58:49 +02:00
Géry Debongnie 6c72e0a143 [REL] v2.0.0-beta-12
# v2.0.0-beta-12

- fix: compiler: properly handle t-set in t-if with no content
2022-06-29 11:12:59 +02:00
Géry Debongnie 382e3e4010 [FIX] compiler: properly handle t-set in t-if with no content
Before this commit, whenever Owl encounter a t-if, it generates an
anchor (a "hole") in the current block being compiled. However, in some
cases, the content of the t-if may not have any content at all, and the
anchor is then useless. Worse, the code generating the anchor generates
an index based on the number of sub blocks, but if there is no content,
the next anchor being created will have the same index, which then may
cause weird bugs.

A possible way to fix this could be to make sure we increment properly
the anchor index, but we could even do better: not having an anchor at
all.
2022-06-29 11:08:14 +02:00
Géry Debongnie 76c389a7a8 [REL] v2.0.0-beta-11
# v2.0.0-beta-11

Yet another release with some small fixes.

[FIX] fix some issues with t-out with falsy values, and with default values
[REF] app: slightly simplify the create component path
[IMP] compiler: add support for binary operators
[IMP] add support for t-call-context directive
[FIX] properly get component reference instead of context
[FIX] blockdom: fix crash when class object key has leading spaces
2022-06-28 15:28:12 +02:00
Géry Debongnie b9ba0abf41 [FIX] test: run prettier 2022-06-28 15:26:55 +02:00
Géry Debongnie 4ca37be7f3 [FIX] tests: update wrong snapshot
oups
2022-06-28 15:20:53 +02:00
Géry Debongnie d6667ddf2e [FIX] fix some issues with t-out with falsy values, and with default value 2022-06-28 15:10:11 +02:00
Géry Debongnie 6f86beeaf3 [REF] app: slightly simplify the create component path 2022-06-28 13:11:57 +02:00
Géry Debongnie 7f580a4e1d [IMP] compiler: add support for binary operators 2022-06-24 15:39:55 +02:00
Géry Debongnie c7459ef87b [IMP] add support for t-call-context directive 2022-06-22 16:15:54 +02:00
Géry Debongnie 5772b4e9e4 [FIX] properly get component reference instead of context
Before this commit, the generated code for the component directive was
using the current context as the place to look for static informations
(such as the sub components). However, it is not entirely correct, since
the current context may be different than the current component (which
is easily accessed by using the this variable).

Also, while doing this, we fix some issues in the t-set directive, which
as calling lazy values with the wrong this.
2022-06-22 16:15:54 +02:00
Samuel Degueldre e57e2ee378 [FIX] blockdom: fix crash when class object key has leading spaces
Previously, having a leading or trailing space caused
HTMLElement.classList.add to be called with an empty string (because we
are splitting on whitespace), which is not allowed and caused a crash.
This commit fixes that by trimming the keys of the class object in the
same way that we already do it for class strings.
2022-06-22 15:48:45 +02:00
79 changed files with 2919 additions and 1167 deletions
+1 -1
View File
@@ -124,5 +124,5 @@ npm install @odoo/owl
If you want to use a simple `<script>` tag, the last release can be downloaded here: If you want to use a simple `<script>` tag, the last release can be downloaded here:
- [owl-1.4.10](https://github.com/odoo/owl/releases/tag/v1.4.10) - [owl](https://github.com/odoo/owl/releases/latest)
+3 -2
View File
@@ -770,10 +770,11 @@ For reference, here is the final code:
<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>
``` ```
+2 -1
View File
@@ -234,7 +234,8 @@ are defined by a function instead of just the dependencies.
The `useEffect` hook takes two function: the effect function and the dependency The `useEffect` hook takes two function: the effect function and the dependency
function. The effect function perform some task and return (optionally) a cleanup function. The effect function perform some task and return (optionally) a cleanup
function. The dependency function returns a list of dependencies. If any of these function. The dependency function returns a list of dependencies, these dependencies
are passed as parameters in the effect function . If any of these
dependencies changes, then the current effect will be cleaned up and reexecuted. dependencies changes, then the current effect will be cleaned up and reexecuted.
Here is an example without any dependencies: Here is an example without any dependencies:
+9
View File
@@ -540,6 +540,15 @@ This can be used to define variables scoped to a sub template:
<!-- "var" does not exist here --> <!-- "var" does not exist here -->
``` ```
Note: by default, the rendering context for a sub template is simply the current
rendering context (so, the current component). However, it may be useful to be
able to specify a specific object as context. This can be done by using the
`t-call-context` directive:
```xml
<t t-call="other-template" t-call-context="obj"/>
```
### Dynamic sub templates ### Dynamic sub templates
The `t-call` directive can also be used to dynamically call a sub template, The `t-call` directive can also be used to dynamically call a sub template,
+1 -2
View File
@@ -1,9 +1,8 @@
{ {
"name": "@odoo/owl", "name": "@odoo/owl",
"version": "2.0.0-beta-10", "version": "2.0.0-beta-22",
"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",
"module": "dist/owl.es.js", "module": "dist/owl.es.js",
"types": "dist/types/owl.d.ts", "types": "dist/types/owl.d.ts",
"files": [ "files": [
+4 -23
View File
@@ -1,28 +1,9 @@
# 🦉 OWL Roadmap 🦉 # 🦉 OWL Roadmap 🦉
- Current version: 1.4.10 - Current version: 2.X
- Status: stable - Status: stable
This roadmap is only an attempt at predicting Owl's future. Everything may Owl is currently stable. No (large) improvements is expected in the near future.
change!
### 1.x
- add chrome and firefox devtools,
- fix every bugs,
- improve documentation,
- small backward compatible improvements.
### 2.x (2020? 2021? 2022?)
- stop support for `t-set` directive to define the content of a slot
Maybe:
- reimplement vdom to use *block* system, like Vue 3, which should make Owl
much faster
- refactor `QWeb` to use an intermediate representation (some kind of AST) to
allow additional optimisations.
Note that we intend to keep maintaining owl, and as such, improvements and/or
breaking changes may require a version bump in the future.
+16 -8
View File
@@ -6,6 +6,14 @@ import dts from "rollup-plugin-dts";
let input, output; let input, output;
const IIFE_FILENAME = "dist/owl.iife.js";
const CJS_FILENAME = "dist/owl.cjs.js";
const ES_FILENAME = "dist/owl.es.js";
if (pkg.module !== ES_FILENAME || pkg.main !== CJS_FILENAME) {
throw new Error("package.json has been modified. Build script should be updated accordingly");
}
const outro = ` const outro = `
__info__.version = '${pkg.version}'; __info__.version = '${pkg.version}';
__info__.date = '${new Date().toISOString()}'; __info__.date = '${new Date().toISOString()}';
@@ -23,19 +31,19 @@ switch (process.argv[4]) {
case "runtime": case "runtime":
input = "src/runtime/index.ts"; input = "src/runtime/index.ts";
output = [ output = [
getConfigForFormat('esm', addSuffix(pkg.module, 'runtime'), outro), getConfigForFormat('esm', addSuffix(ES_FILENAME, 'runtime'), outro),
getConfigForFormat('cjs', addSuffix(pkg.main, 'runtime'), outro), getConfigForFormat('cjs', addSuffix(CJS_FILENAME, 'runtime'), outro),
getConfigForFormat('iife', addSuffix(pkg.browser, 'runtime'), outro), getConfigForFormat('iife', addSuffix(IIFE_FILENAME, 'runtime'), outro),
getConfigForFormat('iife', addSuffix(pkg.browser, 'runtime'), outro, true), getConfigForFormat('iife', addSuffix(IIFE_FILENAME, 'runtime'), outro, true),
] ]
break; break;
default: default:
input = "src/index.ts", input = "src/index.ts",
output = [ output = [
getConfigForFormat('esm', pkg.module, outro), getConfigForFormat('esm', ES_FILENAME, outro),
getConfigForFormat('cjs', pkg.main, outro), getConfigForFormat('cjs', CJS_FILENAME, outro),
getConfigForFormat('iife', pkg.browser, outro), getConfigForFormat('iife', IIFE_FILENAME, outro),
getConfigForFormat('iife', pkg.browser, outro, true), getConfigForFormat('iife', IIFE_FILENAME, outro, true),
] ]
} }
+166 -125
View File
@@ -1,3 +1,4 @@
import { isProp } from "../runtime/blockdom/attributes";
import { import {
compileExpr, compileExpr,
compileExprToArray, compileExprToArray,
@@ -22,13 +23,14 @@ import {
ASTTif, ASTTif,
ASTTKey, ASTTKey,
ASTTOut, ASTTOut,
ASTTSet,
ASTTranslation,
ASTType,
ASTTPortal, ASTTPortal,
EventHandlers, ASTTranslation,
ASTTSet,
ASTType,
Attrs, Attrs,
EventHandlers,
} from "./parser"; } from "./parser";
import { OwlError } from "../runtime/error_handling";
type BlockType = "block" | "text" | "multi" | "list" | "html" | "comment"; type BlockType = "block" | "text" | "multi" | "list" | "html" | "comment";
@@ -140,9 +142,10 @@ interface Context {
tKeyExpr: string | null; tKeyExpr: string | null;
nameSpace?: string; nameSpace?: string;
tModelSelectedExpr?: string; tModelSelectedExpr?: string;
ctxVar?: string;
} }
function createContext(parentCtx: Context, params?: Partial<Context>) { function createContext(parentCtx: Context, params?: Partial<Context>): Context {
return Object.assign( return Object.assign(
{ {
block: null, block: null,
@@ -211,6 +214,14 @@ class CodeTarget {
result.push(`}`); result.push(`}`);
return result.join("\n "); return result.join("\n ");
} }
currentKey(ctx: Context) {
let key = this.loopLevel ? `key${this.loopLevel}` : "key";
if (ctx.tKeyExpr) {
key = `${ctx.tKeyExpr} + ${key}`;
}
return key;
}
} }
const TRANSLATABLE_ATTRS = ["label", "title", "placeholder", "alt"]; const TRANSLATABLE_ATTRS = ["label", "title", "placeholder", "alt"];
@@ -229,6 +240,7 @@ export class CodeGenerator {
translatableAttributes: string[] = TRANSLATABLE_ATTRS; translatableAttributes: string[] = TRANSLATABLE_ATTRS;
ast: AST; ast: AST;
staticDefs: { id: string; expr: string }[] = []; staticDefs: { id: string; expr: string }[] = [];
slotNames: Set<String> = new Set();
helpers: Set<string> = new Set(); helpers: Set<string> = new Set();
constructor(ast: AST, options: CodeGenOptions) { constructor(ast: AST, options: CodeGenOptions) {
@@ -333,8 +345,8 @@ export class CodeGenerator {
this.addLine(`const ${varName} = ${expr};`); this.addLine(`const ${varName} = ${expr};`);
} }
insertAnchor(block: BlockDescription) { insertAnchor(block: BlockDescription, index: number = block.children.length) {
const tag = `block-child-${block.children.length}`; const tag = `block-child-${index}`;
const anchor = xmlDoc.createElement(tag); const anchor = xmlDoc.createElement(tag);
block.insert(anchor); block.insert(anchor);
} }
@@ -361,19 +373,15 @@ export class CodeGenerator {
insertBlock(expression: string, block: BlockDescription, ctx: Context): void { insertBlock(expression: string, block: BlockDescription, ctx: Context): void {
let blockExpr = block.generateExpr(expression); let blockExpr = block.generateExpr(expression);
const tKeyExpr = ctx.tKeyExpr;
if (block.parentVar) { if (block.parentVar) {
let keyArg = `key${this.target.loopLevel}`; let key = this.target.currentKey(ctx);
if (tKeyExpr) {
keyArg = `${tKeyExpr} + ${keyArg}`;
}
this.helpers.add("withKey"); this.helpers.add("withKey");
this.addLine(`${block.parentVar}[${ctx.index}] = withKey(${blockExpr}, ${keyArg});`); this.addLine(`${block.parentVar}[${ctx.index}] = withKey(${blockExpr}, ${key});`);
return; return;
} }
if (tKeyExpr) { if (ctx.tKeyExpr) {
blockExpr = `toggler(${tKeyExpr}, ${blockExpr})`; blockExpr = `toggler(${ctx.tKeyExpr}, ${blockExpr})`;
} }
if (block.isRoot && !ctx.preventRoot) { if (block.isRoot && !ctx.preventRoot) {
@@ -420,78 +428,66 @@ export class CodeGenerator {
.join(""); .join("");
} }
compileAST(ast: AST, ctx: Context) { /**
* @returns the newly created block name, if any
*/
compileAST(ast: AST, ctx: Context): string | null {
switch (ast.type) { switch (ast.type) {
case ASTType.Comment: case ASTType.Comment:
this.compileComment(ast, ctx); return this.compileComment(ast, ctx);
break;
case ASTType.Text: case ASTType.Text:
this.compileText(ast, ctx); return this.compileText(ast, ctx);
break;
case ASTType.DomNode: case ASTType.DomNode:
this.compileTDomNode(ast, ctx); return this.compileTDomNode(ast, ctx);
break;
case ASTType.TEsc: case ASTType.TEsc:
this.compileTEsc(ast, ctx); return this.compileTEsc(ast, ctx);
break;
case ASTType.TOut: case ASTType.TOut:
this.compileTOut(ast, ctx); return this.compileTOut(ast, ctx);
break;
case ASTType.TIf: case ASTType.TIf:
this.compileTIf(ast, ctx); return this.compileTIf(ast, ctx);
break;
case ASTType.TForEach: case ASTType.TForEach:
this.compileTForeach(ast, ctx); return this.compileTForeach(ast, ctx);
break;
case ASTType.TKey: case ASTType.TKey:
this.compileTKey(ast, ctx); return this.compileTKey(ast, ctx);
break;
case ASTType.Multi: case ASTType.Multi:
this.compileMulti(ast, ctx); return this.compileMulti(ast, ctx);
break;
case ASTType.TCall: case ASTType.TCall:
this.compileTCall(ast, ctx); return this.compileTCall(ast, ctx);
break;
case ASTType.TCallBlock: case ASTType.TCallBlock:
this.compileTCallBlock(ast, ctx); return this.compileTCallBlock(ast, ctx);
break;
case ASTType.TSet: case ASTType.TSet:
this.compileTSet(ast, ctx); return this.compileTSet(ast, ctx);
break;
case ASTType.TComponent: case ASTType.TComponent:
this.compileComponent(ast, ctx); return this.compileComponent(ast, ctx);
break;
case ASTType.TDebug: case ASTType.TDebug:
this.compileDebug(ast, ctx); return this.compileDebug(ast, ctx);
break;
case ASTType.TLog: case ASTType.TLog:
this.compileLog(ast, ctx); return this.compileLog(ast, ctx);
break;
case ASTType.TSlot: case ASTType.TSlot:
this.compileTSlot(ast, ctx); return this.compileTSlot(ast, ctx);
break;
case ASTType.TTranslation: case ASTType.TTranslation:
this.compileTTranslation(ast, ctx); return this.compileTTranslation(ast, ctx);
break;
case ASTType.TPortal: case ASTType.TPortal:
this.compileTPortal(ast, ctx); return this.compileTPortal(ast, ctx);
} }
} }
compileDebug(ast: ASTDebug, ctx: Context) { compileDebug(ast: ASTDebug, ctx: Context): string | null {
this.addLine(`debugger;`); this.addLine(`debugger;`);
if (ast.content) { if (ast.content) {
this.compileAST(ast.content, ctx); return this.compileAST(ast.content, ctx);
} }
return null;
} }
compileLog(ast: ASTLog, ctx: Context) { compileLog(ast: ASTLog, ctx: Context): string | null {
this.addLine(`console.log(${compileExpr(ast.expr)});`); this.addLine(`console.log(${compileExpr(ast.expr)});`);
if (ast.content) { if (ast.content) {
this.compileAST(ast.content, ctx); return this.compileAST(ast.content, ctx);
} }
return null;
} }
compileComment(ast: ASTComment, ctx: Context) { compileComment(ast: ASTComment, ctx: Context): string {
let { block, forceNewBlock } = ctx; let { block, forceNewBlock } = ctx;
const isNewBlock = !block || forceNewBlock; const isNewBlock = !block || forceNewBlock;
if (isNewBlock) { if (isNewBlock) {
@@ -504,9 +500,10 @@ export class CodeGenerator {
const text = xmlDoc.createComment(ast.value); const text = xmlDoc.createComment(ast.value);
block!.insert(text); block!.insert(text);
} }
return block!.varName;
} }
compileText(ast: ASTText, ctx: Context) { compileText(ast: ASTText, ctx: Context): string {
let { block, forceNewBlock } = ctx; let { block, forceNewBlock } = ctx;
let value = ast.value; let value = ast.value;
@@ -525,6 +522,7 @@ export class CodeGenerator {
const createFn = ast.type === ASTType.Text ? xmlDoc.createTextNode : xmlDoc.createComment; const createFn = ast.type === ASTType.Text ? xmlDoc.createTextNode : xmlDoc.createComment;
block.insert(createFn.call(xmlDoc, value)); block.insert(createFn.call(xmlDoc, value));
} }
return block.varName;
} }
generateHandlerCode(rawEvent: string, handler: string): string { generateHandlerCode(rawEvent: string, handler: string): string {
@@ -533,7 +531,7 @@ export class CodeGenerator {
.slice(1) .slice(1)
.map((m) => { .map((m) => {
if (!MODS.has(m)) { if (!MODS.has(m)) {
throw new Error(`Unknown event modifier: '${m}'`); throw new OwlError(`Unknown event modifier: '${m}'`);
} }
return `"${m}"`; return `"${m}"`;
}); });
@@ -544,7 +542,7 @@ export class CodeGenerator {
return `[${modifiersCode}${this.captureExpression(handler)}, ctx]`; return `[${modifiersCode}${this.captureExpression(handler)}, ctx]`;
} }
compileTDomNode(ast: ASTDomNode, ctx: Context) { compileTDomNode(ast: ASTDomNode, ctx: Context): string {
let { block, forceNewBlock } = ctx; let { block, forceNewBlock } = ctx;
const isNewBlock = !block || forceNewBlock || ast.dynamicTag !== null || ast.ns; const isNewBlock = !block || forceNewBlock || ast.dynamicTag !== null || ast.ns;
let codeIdx = this.target.code.length; let codeIdx = this.target.code.length;
@@ -577,13 +575,22 @@ export class CodeGenerator {
attrName = key.slice(7); attrName = key.slice(7);
attrs["block-attribute-" + idx] = attrName; attrs["block-attribute-" + idx] = attrName;
} else if (key.startsWith("t-att")) { } else if (key.startsWith("t-att")) {
attrName = key === "t-att" ? null : key.slice(6);
expr = compileExpr(ast.attrs[key]); expr = compileExpr(ast.attrs[key]);
if (attrName && isProp(ast.tag, attrName)) {
// we force a new string or new boolean to bypass the equality check in blockdom when patching same value
if (attrName === "value") {
// When the expression is falsy, fall back to an empty string
expr = `new String((${expr}) || "")`;
} else {
expr = `new Boolean(${expr})`;
}
}
const idx = block!.insertData(expr, "attr"); 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 {
attrName = key.slice(6); attrs[`block-attribute-${idx}`] = attrName!;
attrs[`block-attribute-${idx}`] = attrName;
} }
} else if (this.translatableAttributes.includes(key)) { } else if (this.translatableAttributes.includes(key)) {
attrs[key] = this.translateFn(ast.attrs[key]); attrs[key] = this.translateFn(ast.attrs[key]);
@@ -691,7 +698,7 @@ export class CodeGenerator {
const children = ast.content; const children = ast.content;
for (let i = 0; i < children.length; i++) { for (let i = 0; i < children.length; i++) {
const child = ast.content[i]; const child = ast.content[i];
const subCtx: Context = createContext(ctx, { const subCtx = createContext(ctx, {
block, block,
index: block!.childNumber, index: block!.childNumber,
forceNewBlock: false, forceNewBlock: false,
@@ -722,9 +729,10 @@ export class CodeGenerator {
this.addLine(`let ${block!.children.map((c) => c.varName)};`, codeIdx); this.addLine(`let ${block!.children.map((c) => c.varName)};`, codeIdx);
} }
} }
return block!.varName;
} }
compileTEsc(ast: ASTTEsc, ctx: Context) { compileTEsc(ast: ASTTEsc, ctx: Context): string {
let { block, forceNewBlock } = ctx; let { block, forceNewBlock } = ctx;
let expr: string; let expr: string;
if (ast.expr === "0") { if (ast.expr === "0") {
@@ -745,29 +753,47 @@ export class CodeGenerator {
const text = xmlDoc.createElement(`block-text-${idx}`); const text = xmlDoc.createElement(`block-text-${idx}`);
block.insert(text); block.insert(text);
} }
return block.varName;
} }
compileTOut(ast: ASTTOut, ctx: Context) { compileTOut(ast: ASTTOut, ctx: Context): string {
let { block } = ctx; let { block } = ctx;
if (block) { if (block) {
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 blockStr;
let expr = ast.expr === "0" ? "ctx[zero]" : `safeOutput(${compileExpr(ast.expr)})`; if (ast.expr === "0") {
if (ast.body) { this.helpers.add("zero");
const nextId = BlockDescription.nextBlockId; blockStr = `ctx[zero]`;
const subCtx: Context = createContext(ctx); } else if (ast.body) {
let bodyValue = null;
bodyValue = BlockDescription.nextBlockId;
const subCtx = createContext(ctx);
this.compileAST({ type: ASTType.Multi, content: ast.body }, subCtx); this.compileAST({ type: ASTType.Multi, content: ast.body }, subCtx);
this.helpers.add("withDefault"); this.helpers.add("safeOutput");
expr = `withDefault(${expr}, b${nextId})`; blockStr = `safeOutput(${compileExpr(ast.expr)}, b${bodyValue})`;
} else {
this.helpers.add("safeOutput");
blockStr = `safeOutput(${compileExpr(ast.expr)})`;
} }
this.insertBlock(`${expr}`, block, ctx); this.insertBlock(blockStr, block, ctx);
return block.varName;
} }
compileTIf(ast: ASTTif, ctx: Context, nextNode?: ASTDomNode) { compileTIfBranch(content: AST, block: BlockDescription, ctx: Context) {
let { block, forceNewBlock, index } = ctx; this.target.indentLevel++;
let currentIndex = index; let childN = block.children.length;
this.compileAST(content, createContext(ctx, { block, index: ctx.index }));
if (block.children.length > childN) {
// we have some content => need to insert an anchor at correct index
this.insertAnchor(block!, childN);
}
this.target.indentLevel--;
}
compileTIf(ast: ASTTif, ctx: Context, nextNode?: ASTDomNode): string {
let { block, forceNewBlock } = ctx;
const codeIdx = this.target.code.length; const codeIdx = this.target.code.length;
const isNewBlock = !block || (block.type !== "multi" && forceNewBlock); const isNewBlock = !block || (block.type !== "multi" && forceNewBlock);
if (block) { if (block) {
@@ -777,28 +803,16 @@ export class CodeGenerator {
block = this.createBlock(block, "multi", ctx); block = this.createBlock(block, "multi", ctx);
} }
this.addLine(`if (${compileExpr(ast.condition)}) {`); this.addLine(`if (${compileExpr(ast.condition)}) {`);
this.target.indentLevel++; this.compileTIfBranch(ast.content, block, ctx);
this.insertAnchor(block!);
const subCtx: Context = createContext(ctx, { block, index: currentIndex });
this.compileAST(ast.content, subCtx);
this.target.indentLevel--;
if (ast.tElif) { if (ast.tElif) {
for (let clause of ast.tElif) { for (let clause of ast.tElif) {
this.addLine(`} else if (${compileExpr(clause.condition)}) {`); this.addLine(`} else if (${compileExpr(clause.condition)}) {`);
this.target.indentLevel++; this.compileTIfBranch(clause.content, block, ctx);
this.insertAnchor(block);
const subCtx: Context = createContext(ctx, { block, index: currentIndex });
this.compileAST(clause.content, subCtx);
this.target.indentLevel--;
} }
} }
if (ast.tElse) { if (ast.tElse) {
this.addLine(`} else {`); this.addLine(`} else {`);
this.target.indentLevel++; this.compileTIfBranch(ast.tElse, block, ctx);
this.insertAnchor(block);
const subCtx: Context = createContext(ctx, { block, index: currentIndex });
this.compileAST(ast.tElse, subCtx);
this.target.indentLevel--;
} }
this.addLine("}"); this.addLine("}");
if (isNewBlock) { if (isNewBlock) {
@@ -821,9 +835,10 @@ export class CodeGenerator {
const args = block!.children.map((c) => c.varName).join(", "); const args = block!.children.map((c) => c.varName).join(", ");
this.insertBlock(`multi([${args}])`, block!, ctx)!; this.insertBlock(`multi([${args}])`, block!, ctx)!;
} }
return block.varName;
} }
compileTForeach(ast: ASTTForEach, ctx: Context) { compileTForeach(ast: ASTTForEach, ctx: Context): string {
let { block } = ctx; let { block } = ctx;
if (block) { if (block) {
this.insertAnchor(block); this.insertAnchor(block);
@@ -860,8 +875,9 @@ export class CodeGenerator {
this.define(`key${this.target.loopLevel}`, ast.key ? compileExpr(ast.key) : loopVar); this.define(`key${this.target.loopLevel}`, ast.key ? compileExpr(ast.key) : loopVar);
if (this.dev) { if (this.dev) {
// Throw error on duplicate keys in dev mode // Throw error on duplicate keys in dev mode
this.helpers.add("OwlError");
this.addLine( this.addLine(
`if (keys${block.id}.has(key${this.target.loopLevel})) { throw new Error(\`Got duplicate key in t-foreach: \${key${this.target.loopLevel}}\`)}` `if (keys${block.id}.has(key${this.target.loopLevel})) { throw new OwlError(\`Got duplicate key in t-foreach: \${key${this.target.loopLevel}}\`)}`
); );
this.addLine(`keys${block.id}.add(key${this.target.loopLevel});`); this.addLine(`keys${block.id}.add(key${this.target.loopLevel});`);
} }
@@ -884,7 +900,7 @@ export class CodeGenerator {
this.addLine("}"); this.addLine("}");
} }
const subCtx: Context = createContext(ctx, { block, index: loopVar }); const subCtx = createContext(ctx, { block, index: loopVar });
this.compileAST(ast.body, subCtx); this.compileAST(ast.body, subCtx);
if (ast.memo) { if (ast.memo) {
this.addLine( this.addLine(
@@ -900,9 +916,10 @@ export class CodeGenerator {
this.addLine(`ctx = ctx.__proto__;`); this.addLine(`ctx = ctx.__proto__;`);
} }
this.insertBlock("l", block, ctx); this.insertBlock("l", block, ctx);
return block.varName;
} }
compileTKey(ast: ASTTKey, ctx: Context) { compileTKey(ast: ASTTKey, ctx: Context): string | null {
const tKeyExpr = generateId("tKey_"); const tKeyExpr = generateId("tKey_");
this.define(tKeyExpr, compileExpr(ast.expr)); this.define(tKeyExpr, compileExpr(ast.expr));
ctx = createContext(ctx, { ctx = createContext(ctx, {
@@ -910,20 +927,22 @@ export class CodeGenerator {
block: ctx.block, block: ctx.block,
index: ctx.index, index: ctx.index,
}); });
this.compileAST(ast.content, ctx); return this.compileAST(ast.content, ctx);
} }
compileMulti(ast: ASTMulti, ctx: Context) { compileMulti(ast: ASTMulti, ctx: Context): string | null {
let { block, forceNewBlock } = ctx; let { block, forceNewBlock } = ctx;
const isNewBlock = !block || forceNewBlock; const isNewBlock = !block || forceNewBlock;
let codeIdx = this.target.code.length; let codeIdx = this.target.code.length;
if (isNewBlock) { if (isNewBlock) {
const n = ast.content.filter((c) => c.type !== ASTType.TSet).length; const n = ast.content.filter((c) => c.type !== ASTType.TSet).length;
let result: string | null = null;
if (n <= 1) { if (n <= 1) {
for (let child of ast.content) { for (let child of ast.content) {
this.compileAST(child, ctx); const blockName = this.compileAST(child, ctx);
result = result || blockName;
} }
return; return result;
} }
block = this.createBlock(block, "multi", ctx); block = this.createBlock(block, "multi", ctx);
} }
@@ -931,7 +950,7 @@ export class CodeGenerator {
for (let i = 0, l = ast.content.length; i < l; i++) { for (let i = 0, l = ast.content.length; i < l; i++) {
const child = ast.content[i]; const child = ast.content[i];
const isTSet = child.type === ASTType.TSet; const isTSet = child.type === ASTType.TSet;
const subCtx: Context = createContext(ctx, { const subCtx = createContext(ctx, {
block, block,
index, index,
forceNewBlock: !isTSet, forceNewBlock: !isTSet,
@@ -963,20 +982,25 @@ export class CodeGenerator {
const args = block!.children.map((c) => c.varName).join(", "); const args = block!.children.map((c) => c.varName).join(", ");
this.insertBlock(`multi([${args}])`, block!, ctx)!; this.insertBlock(`multi([${args}])`, block!, ctx)!;
} }
return block!.varName;
} }
compileTCall(ast: ASTTCall, ctx: Context) { compileTCall(ast: ASTTCall, ctx: Context): string {
let { block, forceNewBlock } = ctx; let { block, forceNewBlock } = ctx;
let ctxVar = ctx.ctxVar || "ctx";
if (ast.context) {
ctxVar = generateId("ctx");
this.addLine(`let ${ctxVar} = ${compileExpr(ast.context)};`);
}
if (ast.body) { if (ast.body) {
this.addLine(`ctx = Object.create(ctx);`); this.addLine(`${ctxVar} = Object.create(${ctxVar});`);
this.addLine(`ctx[isBoundary] = 1;`); this.addLine(`${ctxVar}[isBoundary] = 1;`);
this.helpers.add("isBoundary"); this.helpers.add("isBoundary");
const nextId = BlockDescription.nextBlockId; const subCtx = createContext(ctx, { preventRoot: true, ctxVar });
const subCtx: Context = createContext(ctx, { preventRoot: true }); const bl = this.compileMulti({ type: ASTType.Multi, content: ast.body }, subCtx);
this.compileAST({ type: ASTType.Multi, content: ast.body }, subCtx); if (bl) {
if (nextId !== BlockDescription.nextBlockId) {
this.helpers.add("zero"); this.helpers.add("zero");
this.addLine(`ctx[zero] = b${nextId};`); this.addLine(`${ctxVar}[zero] = ${bl};`);
} }
} }
const isDynamic = INTERP_REGEXP.test(ast.name); const isDynamic = INTERP_REGEXP.test(ast.name);
@@ -994,7 +1018,7 @@ export class CodeGenerator {
} }
this.define(templateVar, subTemplate); this.define(templateVar, subTemplate);
block = this.createBlock(block, "multi", ctx); block = this.createBlock(block, "multi", ctx);
this.insertBlock(`call(this, ${templateVar}, ctx, node, ${key})`, block!, { this.insertBlock(`call(this, ${templateVar}, ${ctxVar}, node, ${key})`, block!, {
...ctx, ...ctx,
forceNewBlock: !block, forceNewBlock: !block,
}); });
@@ -1002,17 +1026,18 @@ export class CodeGenerator {
const id = generateId(`callTemplate_`); const id = generateId(`callTemplate_`);
this.staticDefs.push({ id, expr: `app.getTemplate(${subTemplate})` }); this.staticDefs.push({ id, expr: `app.getTemplate(${subTemplate})` });
block = this.createBlock(block, "multi", ctx); block = this.createBlock(block, "multi", ctx);
this.insertBlock(`${id}.call(this, ctx, node, ${key})`, block!, { this.insertBlock(`${id}.call(this, ${ctxVar}, node, ${key})`, block!, {
...ctx, ...ctx,
forceNewBlock: !block, forceNewBlock: !block,
}); });
} }
if (ast.body && !ctx.isLast) { if (ast.body && !ctx.isLast) {
this.addLine(`ctx = ctx.__proto__;`); this.addLine(`${ctxVar} = ${ctxVar}.__proto__;`);
} }
return block.varName;
} }
compileTCallBlock(ast: ASTTCallBlock, ctx: Context) { compileTCallBlock(ast: ASTTCallBlock, ctx: Context): string {
let { block, forceNewBlock } = ctx; let { block, forceNewBlock } = ctx;
if (block) { if (block) {
if (!forceNewBlock) { if (!forceNewBlock) {
@@ -1021,9 +1046,10 @@ export class CodeGenerator {
} }
block = this.createBlock(block, "multi", ctx); block = this.createBlock(block, "multi", ctx);
this.insertBlock(compileExpr(ast.name), block, { ...ctx, forceNewBlock: !block }); this.insertBlock(compileExpr(ast.name), block, { ...ctx, forceNewBlock: !block });
return block.varName;
} }
compileTSet(ast: ASTTSet, ctx: Context) { compileTSet(ast: ASTTSet, ctx: Context): null {
this.target.shouldProtectScope = true; this.target.shouldProtectScope = true;
this.helpers.add("isBoundary").add("withDefault"); this.helpers.add("isBoundary").add("withDefault");
const expr = ast.value ? compileExpr(ast.value || "") : "null"; const expr = ast.value ? compileExpr(ast.value || "") : "null";
@@ -1031,7 +1057,8 @@ export class CodeGenerator {
this.helpers.add("LazyValue"); this.helpers.add("LazyValue");
const bodyAst: AST = { type: ASTType.Multi, content: ast.body }; const bodyAst: AST = { type: ASTType.Multi, content: ast.body };
const name = this.compileInNewTarget("value", bodyAst, ctx); const name = this.compileInNewTarget("value", bodyAst, ctx);
let value = `new LazyValue(${name}, ctx, node)`; let key = this.target.currentKey(ctx);
let value = `new LazyValue(${name}, ctx, this, node, ${key})`;
value = ast.value ? (value ? `withDefault(${expr}, ${value})` : expr) : value; value = ast.value ? (value ? `withDefault(${expr}, ${value})` : expr) : value;
this.addLine(`ctx[\`${ast.name}\`] = ${value};`); this.addLine(`ctx[\`${ast.name}\`] = ${value};`);
} else { } else {
@@ -1046,8 +1073,9 @@ export class CodeGenerator {
value = expr; value = expr;
} }
this.helpers.add("setContextValue"); this.helpers.add("setContextValue");
this.addLine(`setContextValue(ctx, "${ast.name}", ${value});`); this.addLine(`setContextValue(${ctx.ctxVar || "ctx"}, "${ast.name}", ${value});`);
} }
return null;
} }
generateComponentKey() { generateComponentKey() {
@@ -1078,7 +1106,7 @@ export class CodeGenerator {
name = _name; name = _name;
value = `bind(ctx, ${value || undefined})`; value = `bind(ctx, ${value || undefined})`;
} else { } else {
throw new Error("Invalid prop suffix"); throw new OwlError("Invalid prop suffix");
} }
} }
name = /^[a-z_]+$/i.test(name) ? name : `'${name}'`; name = /^[a-z_]+$/i.test(name) ? name : `'${name}'`;
@@ -1099,7 +1127,7 @@ export class CodeGenerator {
return propString; return propString;
} }
compileComponent(ast: ASTComponent, ctx: Context) { compileComponent(ast: ASTComponent, ctx: Context): string {
let { block } = ctx; let { block } = ctx;
// props // props
const hasSlotsProp = "slots" in (ast.props || {}); const hasSlotsProp = "slots" in (ast.props || {});
@@ -1165,7 +1193,7 @@ export class CodeGenerator {
} }
if (this.dev) { if (this.dev) {
this.addLine(`helpers.validateProps(${expr}, ${propVar!}, ctx);`); this.addLine(`helpers.validateProps(${expr}, ${propVar!}, this);`);
} }
if (block && (ctx.forceNewBlock === false || ctx.tKeyExpr)) { if (block && (ctx.forceNewBlock === false || ctx.tKeyExpr)) {
@@ -1187,7 +1215,7 @@ export class CodeGenerator {
})`, })`,
}); });
let blockExpr = `${id}(${propString}, ${keyArg}, node, ctx, ${ast.isDynamic ? expr : null})`; let blockExpr = `${id}(${propString}, ${keyArg}, node, this, ${ast.isDynamic ? expr : null})`;
if (ast.isDynamic) { if (ast.isDynamic) {
blockExpr = `toggler(${expr}, ${blockExpr})`; blockExpr = `toggler(${expr}, ${blockExpr})`;
} }
@@ -1199,6 +1227,7 @@ export class CodeGenerator {
block = this.createBlock(block, "multi", ctx); block = this.createBlock(block, "multi", ctx);
this.insertBlock(blockExpr, block, ctx); this.insertBlock(blockExpr, block, ctx);
return block.varName;
} }
wrapWithEventCatcher(expr: string, on: EventHandlers): string { wrapWithEventCatcher(expr: string, on: EventHandlers): string {
@@ -1217,34 +1246,43 @@ export class CodeGenerator {
return `${name}(${expr}, [${handlers.join(",")}])`; return `${name}(${expr}, [${handlers.join(",")}])`;
} }
compileTSlot(ast: ASTSlot, ctx: Context) { compileTSlot(ast: ASTSlot, ctx: Context): string {
this.helpers.add("callSlot"); this.helpers.add("callSlot");
let { block } = ctx; let { block } = ctx;
let blockString: string; let blockString: string;
let slotName; let slotName;
let dynamic = false; let dynamic = false;
let isMultiple = false;
if (ast.name.match(INTERP_REGEXP)) { if (ast.name.match(INTERP_REGEXP)) {
dynamic = true; dynamic = true;
isMultiple = true;
slotName = interpolate(ast.name); slotName = interpolate(ast.name);
} else { } else {
slotName = "'" + ast.name + "'"; slotName = "'" + ast.name + "'";
isMultiple = isMultiple || this.slotNames.has(ast.name);
this.slotNames.add(ast.name);
} }
const dynProps = ast.attrs ? ast.attrs["t-props"] : null; const dynProps = ast.attrs ? ast.attrs["t-props"] : null;
if (ast.attrs) { if (ast.attrs) {
delete ast.attrs["t-props"]; delete ast.attrs["t-props"];
} }
let key = this.target.loopLevel ? `key${this.target.loopLevel}` : "key";
if (isMultiple) {
key = `${key} + \`${this.generateComponentKey()}\``;
}
const props = ast.attrs ? this.formatPropObject(ast.attrs) : []; const props = ast.attrs ? this.formatPropObject(ast.attrs) : [];
const scope = this.getPropString(props, dynProps); const scope = this.getPropString(props, dynProps);
if (ast.defaultContent) { if (ast.defaultContent) {
const name = this.compileInNewTarget("defaultContent", ast.defaultContent, ctx); const name = this.compileInNewTarget("defaultContent", ast.defaultContent, ctx);
blockString = `callSlot(ctx, node, key, ${slotName}, ${dynamic}, ${scope}, ${name})`; blockString = `callSlot(ctx, node, ${key}, ${slotName}, ${dynamic}, ${scope}, ${name})`;
} else { } else {
if (dynamic) { if (dynamic) {
let name = generateId("slot"); let name = generateId("slot");
this.define(name, slotName); this.define(name, slotName);
blockString = `toggler(${name}, callSlot(ctx, node, key, ${name}, ${dynamic}, ${scope}))`; blockString = `toggler(${name}, callSlot(ctx, node, ${key}, ${name}, ${dynamic}, ${scope}))`;
} else { } else {
blockString = `callSlot(ctx, node, key, ${slotName}, ${dynamic}, ${scope})`; blockString = `callSlot(ctx, node, ${key}, ${slotName}, ${dynamic}, ${scope})`;
} }
} }
// event handling // event handling
@@ -1257,14 +1295,16 @@ export class CodeGenerator {
} }
block = this.createBlock(block, "multi", ctx); block = this.createBlock(block, "multi", ctx);
this.insertBlock(blockString, block, { ...ctx, forceNewBlock: false }); this.insertBlock(blockString, block, { ...ctx, forceNewBlock: false });
return block.varName;
} }
compileTTranslation(ast: ASTTranslation, ctx: Context) { compileTTranslation(ast: ASTTranslation, ctx: Context): string | null {
if (ast.content) { if (ast.content) {
this.compileAST(ast.content, Object.assign({}, ctx, { translate: false })); return this.compileAST(ast.content, Object.assign({}, ctx, { translate: false }));
} }
return null;
} }
compileTPortal(ast: ASTTPortal, ctx: Context) { compileTPortal(ast: ASTTPortal, ctx: Context): string {
if (!this.staticDefs.find((d) => d.id === "Portal")) { if (!this.staticDefs.find((d) => d.id === "Portal")) {
this.staticDefs.push({ id: "Portal", expr: `app.Portal` }); this.staticDefs.push({ id: "Portal", expr: `app.Portal` });
} }
@@ -1291,5 +1331,6 @@ export class CodeGenerator {
} }
block = this.createBlock(block, "multi", ctx); block = this.createBlock(block, "multi", ctx);
this.insertBlock(blockString, block, { ...ctx, forceNewBlock: false }); this.insertBlock(blockString, block, { ...ctx, forceNewBlock: false });
return block.varName;
} }
} }
+7 -6
View File
@@ -1,3 +1,5 @@
import { OwlError } from "../runtime/error_handling";
/** /**
* Owl QWeb Expression Parser * Owl QWeb Expression Parser
* *
@@ -86,9 +88,8 @@ const STATIC_TOKEN_MAP: { [key: string]: TKind } = Object.assign(Object.create(n
// note that the space after typeof is relevant. It makes sure that the formatted // note that the space after typeof is relevant. It makes sure that the formatted
// expression has a space after typeof. Currently we don't support delete and void // expression has a space after typeof. Currently we don't support delete and void
const OPERATORS = "...,.,===,==,+,!==,!=,!,||,&&,>=,>,<=,<,?,-,*,/,%,typeof ,=>,=,;,in ,new ".split( const OPERATORS =
"," "...,.,===,==,+,!==,!=,!,||,&&,>=,>,<=,<,?,-,*,/,%,typeof ,=>,=,;,in ,new ,|,&,^,~".split(",");
);
type Tokenizer = (expr: string) => Token | false; type Tokenizer = (expr: string) => Token | false;
@@ -107,14 +108,14 @@ let tokenizeString: Tokenizer = function (expr) {
i++; i++;
cur = expr[i]; cur = expr[i];
if (!cur) { if (!cur) {
throw new Error("Invalid expression"); throw new OwlError("Invalid expression");
} }
s += cur; s += cur;
} }
i++; i++;
} }
if (expr[i] !== start) { if (expr[i] !== start) {
throw new Error("Invalid expression"); throw new OwlError("Invalid expression");
} }
s += start; s += start;
if (start === "`") { if (start === "`") {
@@ -224,7 +225,7 @@ export function tokenize(expr: string): Token[] {
error = e; // Silence all errors and throw a generic error below error = e; // Silence all errors and throw a generic error below
} }
if (current.length || error) { if (current.length || error) {
throw new Error(`Tokenizer error: could not tokenize \`${expr}\``); throw new OwlError(`Tokenizer error: could not tokenize \`${expr}\``);
} }
return result; return result;
} }
+29 -19
View File
@@ -1,3 +1,5 @@
import { OwlError } from "../runtime/error_handling";
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// AST Type definition // AST Type definition
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@@ -115,6 +117,7 @@ export interface ASTTCall {
type: ASTType.TCall; type: ASTType.TCall;
name: string; name: string;
body: AST[] | null; body: AST[] | null;
context: string | null;
} }
interface SlotDefinition { interface SlotDefinition {
@@ -318,7 +321,7 @@ function parseDOMNode(node: Element, ctx: ParsingContext): AST | null {
return null; return null;
} }
if (tagName.startsWith("block-")) { if (tagName.startsWith("block-")) {
throw new Error(`Invalid tag name: '${tagName}'`); throw new OwlError(`Invalid tag name: '${tagName}'`);
} }
ctx = Object.assign({}, ctx); ctx = Object.assign({}, ctx);
if (tagName === "pre") { if (tagName === "pre") {
@@ -339,13 +342,15 @@ function parseDOMNode(node: Element, ctx: ParsingContext): AST | null {
const value = node.getAttribute(attr)!; const value = node.getAttribute(attr)!;
if (attr.startsWith("t-on")) { if (attr.startsWith("t-on")) {
if (attr === "t-on") { if (attr === "t-on") {
throw new Error("Missing event name with t-on directive"); throw new OwlError("Missing event name with t-on directive");
} }
on = on || {}; on = on || {};
on[attr.slice(5)] = value; on[attr.slice(5)] = value;
} else if (attr.startsWith("t-model")) { } else if (attr.startsWith("t-model")) {
if (!["input", "select", "textarea"].includes(tagName)) { if (!["input", "select", "textarea"].includes(tagName)) {
throw new Error("The t-model directive only works with <input>, <textarea> and <select>"); throw new OwlError(
"The t-model directive only works with <input>, <textarea> and <select>"
);
} }
let baseExpr, expr; let baseExpr, expr;
@@ -358,7 +363,7 @@ function parseDOMNode(node: Element, ctx: ParsingContext): AST | null {
baseExpr = value.slice(0, index); baseExpr = value.slice(0, index);
expr = value.slice(index + 1, -1); expr = value.slice(index + 1, -1);
} else { } else {
throw new Error(`Invalid t-model expression: "${value}" (it should be assignable)`); throw new OwlError(`Invalid t-model expression: "${value}" (it should be assignable)`);
} }
const typeAttr = node.getAttribute("type"); const typeAttr = node.getAttribute("type");
@@ -389,10 +394,10 @@ function parseDOMNode(node: Element, ctx: ParsingContext): AST | null {
ctx.tModelInfo = model; ctx.tModelInfo = model;
} }
} else if (attr.startsWith("block-")) { } else if (attr.startsWith("block-")) {
throw new Error(`Invalid attribute: '${attr}'`); throw new OwlError(`Invalid attribute: '${attr}'`);
} else if (attr !== "t-name") { } else if (attr !== "t-name") {
if (attr.startsWith("t-") && !attr.startsWith("t-att")) { if (attr.startsWith("t-") && !attr.startsWith("t-att")) {
throw new Error(`Unknown QWeb directive: '${attr}'`); throw new OwlError(`Unknown QWeb directive: '${attr}'`);
} }
const tModel = ctx.tModelInfo; const tModel = ctx.tModelInfo;
if (tModel && ["t-att-value", "t-attf-value"].includes(attr)) { if (tModel && ["t-att-value", "t-attf-value"].includes(attr)) {
@@ -446,7 +451,7 @@ function parseTEscNode(node: Element, ctx: ParsingContext): AST | null {
}; };
} }
if (ast.type === ASTType.TComponent) { if (ast.type === ASTType.TComponent) {
throw new Error("t-esc is not supported on Component nodes"); throw new OwlError("t-esc is not supported on Component nodes");
} }
return tesc; return tesc;
} }
@@ -502,7 +507,7 @@ function parseTForEach(node: Element, ctx: ParsingContext): AST | null {
node.removeAttribute("t-as"); node.removeAttribute("t-as");
const key = node.getAttribute("t-key"); const key = node.getAttribute("t-key");
if (!key) { if (!key) {
throw new Error( throw new OwlError(
`"Directive t-foreach should always be used with a t-key!" (expression: t-foreach="${collection}" t-as="${elem}")` `"Directive t-foreach should always be used with a t-key!" (expression: t-foreach="${collection}" t-as="${elem}")`
); );
} }
@@ -557,11 +562,13 @@ function parseTCall(node: Element, ctx: ParsingContext): AST | null {
return null; return null;
} }
const subTemplate = node.getAttribute("t-call")!; const subTemplate = node.getAttribute("t-call")!;
const context = node.getAttribute("t-call-context");
node.removeAttribute("t-call"); node.removeAttribute("t-call");
node.removeAttribute("t-call-context");
if (node.tagName !== "t") { if (node.tagName !== "t") {
const ast = parseNode(node, ctx); const ast = parseNode(node, ctx);
const tcall: AST = { type: ASTType.TCall, name: subTemplate, body: null }; const tcall: AST = { type: ASTType.TCall, name: subTemplate, body: null, context };
if (ast && ast.type === ASTType.DomNode) { if (ast && ast.type === ASTType.DomNode) {
ast.content = [tcall]; ast.content = [tcall];
return ast; return ast;
@@ -579,6 +586,7 @@ function parseTCall(node: Element, ctx: ParsingContext): AST | null {
type: ASTType.TCall, type: ASTType.TCall,
name: subTemplate, name: subTemplate,
body: body.length ? body : null, body: body.length ? body : null,
context,
}; };
} }
@@ -682,7 +690,9 @@ function parseComponent(node: Element, ctx: ParsingContext): AST | null {
let isDynamic = node.hasAttribute("t-component"); let isDynamic = node.hasAttribute("t-component");
if (isDynamic && name !== "t") { if (isDynamic && name !== "t") {
throw new Error(`Directive 't-component' can only be used on <t> nodes (used on a <${name}>)`); throw new OwlError(
`Directive 't-component' can only be used on <t> nodes (used on a <${name}>)`
);
} }
if (!(firstLetter === firstLetter.toUpperCase() || isDynamic)) { if (!(firstLetter === firstLetter.toUpperCase() || isDynamic)) {
@@ -709,7 +719,7 @@ function parseComponent(node: Element, ctx: ParsingContext): AST | null {
on[name.slice(5)] = value; on[name.slice(5)] = value;
} else { } else {
const message = directiveErrorMap.get(name.split("-").slice(0, 2).join("-")); const message = directiveErrorMap.get(name.split("-").slice(0, 2).join("-"));
throw new Error(message || `unsupported directive on Component: ${name}`); throw new OwlError(message || `unsupported directive on Component: ${name}`);
} }
} else { } else {
props = props || {}; props = props || {};
@@ -725,7 +735,7 @@ function parseComponent(node: Element, ctx: ParsingContext): AST | null {
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") { if (slotNode.tagName !== "t") {
throw new Error( throw new OwlError(
`Directive 't-set-slot' can only be used on <t> nodes (used on a <${slotNode.tagName}>)` `Directive 't-set-slot' can only be used on <t> nodes (used on a <${slotNode.tagName}>)`
); );
} }
@@ -900,7 +910,7 @@ function normalizeTIf(el: Element) {
let nattr = (name: string) => +!!node.getAttribute(name); let nattr = (name: string) => +!!node.getAttribute(name);
if (prevElem && (pattr("t-if") || pattr("t-elif"))) { if (prevElem && (pattr("t-if") || pattr("t-elif"))) {
if (pattr("t-foreach")) { if (pattr("t-foreach")) {
throw new Error( throw new OwlError(
"t-if cannot stay at the same level as t-foreach when using t-elif or t-else" "t-if cannot stay at the same level as t-foreach when using t-elif or t-else"
); );
} }
@@ -909,19 +919,19 @@ function normalizeTIf(el: Element) {
return a + b; return a + b;
}) > 1 }) > 1
) { ) {
throw new Error("Only one conditional branching directive is allowed per node"); throw new OwlError("Only one conditional branching directive is allowed per node");
} }
// All text (with only spaces) and comment nodes (nodeType 8) between // All text (with only spaces) and comment nodes (nodeType 8) between
// branch nodes are removed // branch nodes are removed
let textNode; let textNode;
while ((textNode = node.previousSibling) !== prevElem) { while ((textNode = node.previousSibling) !== prevElem) {
if (textNode!.nodeValue!.trim().length && textNode!.nodeType !== 8) { if (textNode!.nodeValue!.trim().length && textNode!.nodeType !== 8) {
throw new Error("text is not allowed between branching directives"); throw new OwlError("text is not allowed between branching directives");
} }
textNode!.remove(); textNode!.remove();
} }
} else { } else {
throw new Error( throw new OwlError(
"t-elif and t-else directives must be preceded by a t-if or t-elif directive" "t-elif and t-else directives must be preceded by a t-if or t-elif directive"
); );
} }
@@ -942,7 +952,7 @@ function normalizeTEsc(el: Element) {
); );
for (const el of elements) { for (const el of elements) {
if (el.childNodes.length) { if (el.childNodes.length) {
throw new Error("Cannot have t-esc on a component that already has content"); throw new OwlError("Cannot have t-esc on a component that already has content");
} }
const value = el.getAttribute("t-esc"); const value = el.getAttribute("t-esc");
el.removeAttribute("t-esc"); el.removeAttribute("t-esc");
@@ -996,7 +1006,7 @@ function parseXML(xml: string): XMLDocument {
} }
} }
} }
throw new Error(msg); throw new OwlError(msg);
} }
return doc; return doc;
+10 -11
View File
@@ -1,12 +1,12 @@
import { Component, ComponentConstructor, Props } from "./component"; import { Component, ComponentConstructor, Props } from "./component";
import { ComponentNode } from "./component_node"; import { ComponentNode } from "./component_node";
import { nodeErrorHandlers } from "./error_handling"; import { nodeErrorHandlers, OwlError } from "./error_handling";
import { Fiber, MountOptions } from "./fibers"; import { Fiber, MountOptions } from "./fibers";
import { Scheduler } from "./scheduler"; import { Scheduler } from "./scheduler";
import { STATUS } from "./status";
import { validateProps } from "./template_helpers"; import { validateProps } from "./template_helpers";
import { TemplateSet, TemplateSetConfig } from "./template_set"; import { TemplateSet, TemplateSetConfig } from "./template_set";
import { validateTarget } from "./utils"; import { validateTarget } from "./utils";
import { handleError } from "./error_handling";
// reimplement dev mode stuff see last change in 0f7a8289a6fb8387c3c1af41c6664b2a8448758f // reimplement dev mode stuff see last change in 0f7a8289a6fb8387c3c1af41c6664b2a8448758f
@@ -95,9 +95,7 @@ export class App<
nodeErrorHandlers.set(node, handlers); nodeErrorHandlers.set(node, handlers);
} }
handlers.unshift((e) => { handlers.unshift((e) => {
if (isResolved) { if (!isResolved) {
console.error(e);
} else {
reject(e); reject(e);
} }
throw e; throw e;
@@ -141,10 +139,7 @@ export class App<
return (props: P, key: string, ctx: ComponentNode, parent: any, C: any) => { return (props: P, key: string, ctx: ComponentNode, parent: any, C: any) => {
let children = ctx.children; let children = ctx.children;
let node: any = children[key]; let node: any = children[key];
if ( if (isDynamic && node && node.component.constructor !== C) {
node &&
(node.status === STATUS.DESTROYED || (isDynamic && node.component.constructor !== C))
) {
node = undefined; node = undefined;
} }
const parentFiber = ctx.fiber!; const parentFiber = ctx.fiber!;
@@ -158,9 +153,9 @@ export class App<
if (isStatic) { if (isStatic) {
C = parent.constructor.components[name as any]; C = parent.constructor.components[name as any];
if (!C) { if (!C) {
throw new Error(`Cannot find the definition of component "${name}"`); throw new OwlError(`Cannot find the definition of component "${name}"`);
} else if (!(C.prototype instanceof Component)) { } else if (!(C.prototype instanceof Component)) {
throw new Error( throw new OwlError(
`"${name}" is not a Component. It must inherit from the Component class` `"${name}" is not a Component. It must inherit from the Component class`
); );
} }
@@ -173,6 +168,10 @@ export class App<
return node; return node;
}; };
} }
handleError(...args: Parameters<typeof handleError>) {
return handleError(...args);
}
} }
export async function mount< export async function mount<
+5 -1
View File
@@ -93,6 +93,10 @@ function toClassObj(expr: string | number | { [c: string]: any }) {
for (let key in expr as any) { for (let key in expr as any) {
const value = (expr as any)[key]; const value = (expr as any)[key];
if (value) { if (value) {
key = trim.call(key);
if (!key) {
continue;
}
const words = split.call(key, wordRegexp); const words = split.call(key, wordRegexp);
for (let word of words) { for (let word of words) {
result[word] = value; result[word] = value;
@@ -140,7 +144,7 @@ export function updateClass(this: HTMLElement, val: any, oldVal: any) {
export function makePropSetter(name: string): Setter<HTMLElement> { export function makePropSetter(name: string): Setter<HTMLElement> {
return function setProp(this: HTMLElement, value: any) { return function setProp(this: HTMLElement, value: any) {
// support 0, fallback to empty string for other falsy values // support 0, fallback to empty string for other falsy values
(this as any)[name] = value === 0 ? 0 : value || ""; (this as any)[name] = value === 0 ? 0 : value ? value.valueOf() : "";
}; };
} }
+11 -1
View File
@@ -1,3 +1,4 @@
import { OwlError } from "../error_handling";
import { import {
attrsSetter, attrsSetter,
attrsUpdater, attrsUpdater,
@@ -156,6 +157,15 @@ function buildTree(
: document.createElement(tagName); : document.createElement(tagName);
} }
if (el instanceof Element) { if (el instanceof Element) {
if (!domParentTree) {
// some html elements may have side effects when setting their attributes.
// For example, setting the src attribute of an <img/> will trigger a
// request to get the corresponding image. This is something that we
// don't want at compile time. We avoid that by putting the content of
// the block in a <template/> element
const fragment = document.createElement("template").content;
fragment.appendChild(el);
}
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;
@@ -245,7 +255,7 @@ function buildTree(
}; };
} }
} }
throw new Error("boom"); throw new OwlError("boom");
} }
function addRef(tree: IntermediateTree) { function addRef(tree: IntermediateTree) {
+2 -2
View File
@@ -27,8 +27,8 @@ function createElementHandler(evName: string, capture: boolean = false): EventHa
} }
function listener(ev: Event) { function listener(ev: Event) {
const currentTarget = ev.currentTarget; const currentTarget = ev.currentTarget as HTMLElement;
if (!currentTarget || !document.contains(currentTarget as HTMLElement)) return; if (!currentTarget || !currentTarget.ownerDocument.contains(currentTarget)) return;
const data = (currentTarget as any)[eventKey]; const data = (currentTarget as any)[eventKey];
if (!data) return; if (!data) return;
config.mainEventHandler(data, ev, currentTarget); config.mainEventHandler(data, ev, currentTarget);
+4 -6
View File
@@ -1,7 +1,7 @@
import type { App, Env } from "./app"; import type { App, Env } from "./app";
import { BDom, VNode } from "./blockdom"; import { BDom, VNode } from "./blockdom";
import { Component, ComponentConstructor, Props } from "./component"; import { Component, ComponentConstructor, Props } from "./component";
import { fibersInError, handleError } from "./error_handling"; import { fibersInError, OwlError } from "./error_handling";
import { Fiber, makeChildFiber, makeRootFiber, MountFiber, MountOptions } from "./fibers"; import { Fiber, makeChildFiber, makeRootFiber, MountFiber, MountOptions } from "./fibers";
import { import {
clearReactivesForCallback, clearReactivesForCallback,
@@ -18,7 +18,7 @@ let currentNode: ComponentNode | null = null;
export function getCurrent(): ComponentNode { export function getCurrent(): ComponentNode {
if (!currentNode) { if (!currentNode) {
throw new Error("No active component (a hook function should only be called in 'setup')"); throw new OwlError("No active component (a hook function should only be called in 'setup')");
} }
return currentNode; return currentNode;
} }
@@ -83,7 +83,6 @@ export class ComponentNode<P extends Props = any, E = any> implements VNode<Comp
renderFn: Function; renderFn: Function;
parent: ComponentNode | null; parent: ComponentNode | null;
level: number;
childEnv: Env; childEnv: Env;
children: { [key: string]: ComponentNode } = Object.create(null); children: { [key: string]: ComponentNode } = Object.create(null);
refs: any = {}; refs: any = {};
@@ -108,7 +107,6 @@ export class ComponentNode<P extends Props = any, E = any> implements VNode<Comp
this.parent = parent; this.parent = parent;
this.props = props; this.props = props;
this.parentKey = parentKey; this.parentKey = parentKey;
this.level = parent ? parent.level + 1 : 0;
const defaultProps = C.defaultProps; const defaultProps = C.defaultProps;
props = Object.assign({}, props); props = Object.assign({}, props);
if (defaultProps) { if (defaultProps) {
@@ -143,7 +141,7 @@ export class ComponentNode<P extends Props = any, E = any> implements VNode<Comp
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({ node: this, error: e }); this.app.handleError({ node: this, error: e });
return; return;
} }
if (this.status === STATUS.NEW && this.fiber === fiber) { if (this.status === STATUS.NEW && this.fiber === fiber) {
@@ -221,7 +219,7 @@ export class ComponentNode<P extends Props = any, E = any> implements VNode<Comp
cb.call(component); cb.call(component);
} }
} catch (e) { } catch (e) {
handleError({ error: e, node: this }); this.app.handleError({ error: e, node: this });
} }
} }
this.status = STATUS.DESTROYED; this.status = STATUS.DESTROYED;
+14 -1
View File
@@ -1,6 +1,11 @@
import type { ComponentNode } from "./component_node"; import type { ComponentNode } from "./component_node";
import type { Fiber } from "./fibers"; import type { Fiber } from "./fibers";
// Custom error class that wraps error that happen in the owl lifecycle
export class OwlError extends Error {
cause?: any;
}
// Maps fibers to thrown errors // Maps fibers to thrown errors
export const fibersInError: WeakMap<Fiber, any> = new WeakMap(); export const fibersInError: WeakMap<Fiber, any> = new WeakMap();
export const nodeErrorHandlers: WeakMap<ComponentNode, ((error: any) => void)[]> = new WeakMap(); export const nodeErrorHandlers: WeakMap<ComponentNode, ((error: any) => void)[]> = new WeakMap();
@@ -37,7 +42,14 @@ function _handleError(node: ComponentNode | null, error: any): boolean {
type ErrorParams = { error: any } & ({ node: ComponentNode } | { fiber: Fiber }); type ErrorParams = { error: any } & ({ node: ComponentNode } | { fiber: Fiber });
export function handleError(params: ErrorParams) { export function handleError(params: ErrorParams) {
const error = params.error; let { error } = params;
// Wrap error if it wasn't wrapped by wrapError (ie when not in dev mode)
if (!(error instanceof OwlError)) {
error = Object.assign(
new OwlError(`An error occured in the owl lifecycle (see this Error's "cause" property)`),
{ cause: error }
);
}
const node = "node" in params ? params.node : params.fiber.node; const node = "node" in params ? params.node : params.fiber.node;
const fiber = "fiber" in params ? params.fiber : node.fiber!; const fiber = "fiber" in params ? params.fiber : node.fiber!;
@@ -59,5 +71,6 @@ export function handleError(params: ErrorParams) {
} catch (e) { } catch (e) {
console.error(e); console.error(e);
} }
throw error;
} }
} }
+2 -1
View File
@@ -1,5 +1,6 @@
import { filterOutModifiersFromData } from "./blockdom/config"; import { filterOutModifiersFromData } from "./blockdom/config";
import { STATUS } from "./status"; import { STATUS } from "./status";
import { OwlError } from "./error_handling";
export const mainEventHandler = (data: any, ev: Event, currentTarget?: EventTarget | null) => { export const mainEventHandler = (data: any, ev: Event, currentTarget?: EventTarget | null) => {
const { data: _data, modifiers } = filterOutModifiersFromData(data); const { data: _data, modifiers } = filterOutModifiersFromData(data);
@@ -33,7 +34,7 @@ export const mainEventHandler = (data: any, ev: Event, currentTarget?: EventTarg
if (Object.hasOwnProperty.call(data, 0)) { if (Object.hasOwnProperty.call(data, 0)) {
const handler = data[0]; const handler = data[0];
if (typeof handler !== "function") { if (typeof handler !== "function") {
throw new Error(`Invalid handler (expected a function, received: '${handler}')`); throw new OwlError(`Invalid handler (expected a function, received: '${handler}')`);
} }
let node = data[1] ? data[1].__owl__ : null; let node = data[1] ? data[1].__owl__ : null;
if (node ? node.status === STATUS.MOUNTED : true) { if (node ? node.status === STATUS.MOUNTED : true) {
+6 -5
View File
@@ -1,6 +1,6 @@
import { BDom, mount } from "./blockdom"; import { BDom, mount } from "./blockdom";
import type { ComponentNode } from "./component_node"; import type { ComponentNode } from "./component_node";
import { fibersInError, handleError } from "./error_handling"; import { fibersInError, OwlError } from "./error_handling";
import { STATUS } from "./status"; import { STATUS } from "./status";
export function makeChildFiber(node: ComponentNode, parent: Fiber): Fiber { export function makeChildFiber(node: ComponentNode, parent: Fiber): Fiber {
@@ -43,7 +43,7 @@ export function makeRootFiber(node: ComponentNode): Fiber {
} }
function throwOnRender() { function throwOnRender() {
throw new Error("Attempted to render cancelled fiber"); throw new OwlError("Attempted to render cancelled fiber");
} }
/** /**
@@ -56,6 +56,7 @@ function cancelFibers(fibers: Fiber[]): number {
fiber.render = throwOnRender; fiber.render = throwOnRender;
if (node.status === STATUS.NEW) { if (node.status === STATUS.NEW) {
node.destroy(); node.destroy();
delete node.parent!.children[node.parentKey!];
} }
node.fiber = null; node.fiber = null;
if (fiber.bdom) { if (fiber.bdom) {
@@ -129,7 +130,7 @@ export class Fiber {
(this.bdom as any) = true; (this.bdom as any) = true;
this.bdom = node.renderFn(); this.bdom = node.renderFn();
} catch (e) { } catch (e) {
handleError({ node, error: e }); node.app.handleError({ node, error: e });
} }
root.setCounter(root.counter - 1); root.setCounter(root.counter - 1);
} }
@@ -194,7 +195,7 @@ export class RootFiber extends Fiber {
} }
} catch (e) { } catch (e) {
this.locked = false; this.locked = false;
handleError({ fiber: current || this, error: e }); node.app.handleError({ fiber: current || this, error: e });
} }
} }
@@ -258,7 +259,7 @@ export class MountFiber extends RootFiber {
} }
} }
} catch (e) { } catch (e) {
handleError({ fiber: current as Fiber, error: e }); this.node.app.handleError({ fiber: current as Fiber, error: e });
} }
} }
} }
+2
View File
@@ -36,6 +36,7 @@ export const blockDom = {
export { App, mount } from "./app"; export { App, mount } from "./app";
export { xml } from "./template_set"; export { xml } from "./template_set";
export { Component } from "./component"; export { Component } from "./component";
export type { ComponentConstructor } from "./component";
export { useComponent, useState } from "./component_node"; export { useComponent, useState } from "./component_node";
export { status } from "./status"; export { status } from "./status";
export { reactive, markRaw, toRaw } from "./reactivity"; export { reactive, markRaw, toRaw } from "./reactivity";
@@ -54,5 +55,6 @@ export {
onError, onError,
} from "./lifecycle_hooks"; } from "./lifecycle_hooks";
export { validate } from "./validation"; export { validate } from "./validation";
export { OwlError } from "./error_handling";
export const __info__ = {}; export const __info__ = {};
+15 -15
View File
@@ -1,21 +1,30 @@
import { getCurrent } from "./component_node"; import { getCurrent } from "./component_node";
import { nodeErrorHandlers } from "./error_handling"; import { nodeErrorHandlers, OwlError } from "./error_handling";
const TIMEOUT = Symbol("timeout"); const TIMEOUT = Symbol("timeout");
function wrapError(fn: (...args: any[]) => any, hookName: string) { function wrapError(fn: (...args: any[]) => any, hookName: string) {
const error = new Error(`The following error occurred in ${hookName}: `) as Error & { const error = new OwlError(`The following error occurred in ${hookName}: `) as Error & {
cause: any; cause: any;
}; };
const timeoutError = new Error(`${hookName}'s promise hasn't resolved after 3 seconds`); const timeoutError = new OwlError(`${hookName}'s promise hasn't resolved after 3 seconds`);
const node = getCurrent(); const node = getCurrent();
return (...args: any[]) => { return (...args: any[]) => {
const onError = (cause: any) => {
error.cause = cause;
if (cause instanceof Error) {
error.message += `"${cause.message}"`;
} else {
error.message = `Something that is not an Error was thrown in ${hookName} (see this Error's "cause" property)`;
}
throw error;
};
try { try {
const result = fn(...args); const result = fn(...args);
if (result instanceof Promise) { if (result instanceof Promise) {
if (hookName === "onWillStart" || hookName === "onWillUpdateProps") { if (hookName === "onWillStart" || hookName === "onWillUpdateProps") {
const fiber = node.fiber; const fiber = node.fiber;
Promise.race([ Promise.race([
result, result.catch(() => {}),
new Promise((resolve) => setTimeout(() => resolve(TIMEOUT), 3000)), new Promise((resolve) => setTimeout(() => resolve(TIMEOUT), 3000)),
]).then((res) => { ]).then((res) => {
if (res === TIMEOUT && node.fiber === fiber) { if (res === TIMEOUT && node.fiber === fiber) {
@@ -23,20 +32,11 @@ function wrapError(fn: (...args: any[]) => any, hookName: string) {
} }
}); });
} }
return result.catch((cause) => { return result.catch(onError);
error.cause = cause;
if (cause instanceof Error) {
error.message += `"${cause.message}"`;
}
throw error;
});
} }
return result; return result;
} catch (cause) { } catch (cause) {
if (cause instanceof Error) { onError(cause);
error.message += `"${cause.message}"`;
}
throw error;
} }
}; };
} }
+38 -32
View File
@@ -1,64 +1,60 @@
import { onWillUnmount } from "./lifecycle_hooks"; import { onMounted, onWillUnmount } from "./lifecycle_hooks";
import { BDom, text, VNode } from "./blockdom"; import { BDom, text, VNode } from "./blockdom";
import { Component } from "./component"; import { Component } from "./component";
import { OwlError } from "./error_handling";
const VText: any = text("").constructor; const VText: any = text("").constructor;
class VPortal extends VText implements Partial<VNode<VPortal>> { class VPortal extends VText implements Partial<VNode<VPortal>> {
// selector: string; content: BDom | null;
realBDom: BDom | null; selector: string;
target: HTMLElement | null = null; target: HTMLElement | null = null;
constructor(selector: string, realBDom: BDom) { constructor(selector: string, content: BDom) {
super(""); super("");
this.selector = selector; this.selector = selector;
this.realBDom = realBDom; this.content = content;
} }
mount(parent: HTMLElement, anchor: ChildNode) { mount(parent: HTMLElement, anchor: ChildNode) {
super.mount(parent, anchor); super.mount(parent, anchor);
this.target = document.querySelector(this.selector) as any; this.target = document.querySelector(this.selector) as any;
if (!this.target) { if (this.target) {
let el: any = this.el; this.content!.mount(this.target!, null);
while (el && el.parentElement instanceof HTMLElement) { } else {
el = el.parentElement; this.content!.mount(parent, anchor);
}
this.target = el && el.querySelector(this.selector);
if (!this.target) {
throw new Error("invalid portal target");
}
} }
this.realBDom!.mount(this.target!, null);
} }
beforeRemove() { beforeRemove() {
this.realBDom!.beforeRemove(); this.content!.beforeRemove();
} }
remove() { remove() {
if (this.realBDom) { if (this.content) {
super.remove(); super.remove();
this.realBDom!.remove(); this.content!.remove();
this.realBDom = null; this.content = null;
} }
} }
patch(other: VPortal) { patch(other: VPortal) {
super.patch(other); super.patch(other);
if (this.realBDom) { if (this.content) {
this.realBDom.patch(other.realBDom!, true); this.content.patch(other.content!, true);
} else { } else {
this.realBDom = other.realBDom; this.content = other.content;
this.realBDom!.mount(this.target!, null); this.content!.mount(this.target!, null);
} }
} }
} }
/** /**
* <t t-slot="default"/> * kind of similar to <t t-slot="default"/>, but it wraps it around a VPortal
*/ */
export function portalTemplate(app: any, bdom: any, helpers: any) { export function portalTemplate(app: any, bdom: any, helpers: any) {
let { callSlot } = helpers; let { callSlot } = helpers;
return function template(ctx: any, node: any, key = "") { return function template(ctx: any, node: any, key = ""): any {
return callSlot(ctx, node, key, "default", false, null); return new VPortal(ctx.props.target, callSlot(ctx, node, key, "default", false, null));
}; };
} }
@@ -72,13 +68,23 @@ export class Portal extends Component {
}; };
setup() { setup() {
const node = this.__owl__; const node: any = this.__owl__;
const renderFn = node.renderFn;
node.renderFn = () => new VPortal(this.props.target, renderFn()); onMounted(() => {
onWillUnmount(() => { const portal: VPortal = node.bdom;
if (node.bdom) { if (!portal.target) {
node.bdom.remove(); const target: HTMLElement = document.querySelector(this.props.target);
if (target) {
portal.content!.moveBefore(target, null);
} else {
throw new OwlError("invalid portal target");
}
} }
}); });
onWillUnmount(() => {
const portal: VPortal = node.bdom;
portal.remove();
});
} }
} }
+2 -1
View File
@@ -1,4 +1,5 @@
import { Callback } from "./utils"; import { Callback } from "./utils";
import { OwlError } from "./error_handling";
// Allows to get the target of a Reactive (used for making a new Reactive from the underlying object) // Allows to get the target of a Reactive (used for making a new Reactive from the underlying object)
export const TARGET = Symbol("Target"); export const TARGET = Symbol("Target");
@@ -197,7 +198,7 @@ export function reactive<T extends Target>(
callback: Callback = () => {} callback: Callback = () => {}
): Reactive<T> | NonReactive<T> { ): Reactive<T> | NonReactive<T> {
if (!canBeMadeReactive(target)) { if (!canBeMadeReactive(target)) {
throw new Error(`Cannot make the given value reactive`); throw new OwlError(`Cannot make the given value reactive`);
} }
if (SKIP in target) { if (SKIP in target) {
return target as NonReactive<T>; return target as NonReactive<T>;
+21 -12
View File
@@ -4,6 +4,7 @@ import { html } from "./blockdom/index";
import { isOptional, validateSchema } from "./validation"; import { isOptional, validateSchema } from "./validation";
import type { ComponentConstructor } from "./component"; import type { ComponentConstructor } from "./component";
import { markRaw } from "./reactivity"; import { markRaw } from "./reactivity";
import { OwlError } from "./error_handling";
const ObjectCreate = Object.create; const ObjectCreate = Object.create;
/** /**
@@ -70,7 +71,7 @@ function prepareList(collection: any): [any[], any[], number, any[]] {
values = Object.keys(collection); values = Object.keys(collection);
keys = Object.values(collection); keys = Object.values(collection);
} else { } else {
throw new Error("Invalid loop expression"); throw new OwlError("Invalid loop expression");
} }
const n = values.length; const n = values.length;
return [keys, values, n, new Array(n)]; return [keys, values, n, new Array(n)];
@@ -108,15 +109,20 @@ function shallowEqual(l1: any[], l2: any[]): boolean {
class LazyValue { class LazyValue {
fn: any; fn: any;
ctx: any; ctx: any;
component: any;
node: any; node: any;
constructor(fn: any, ctx: any, node: any) { key: any;
constructor(fn: any, ctx: any, component: any, node: any, key: any) {
this.fn = fn; this.fn = fn;
this.ctx = capture(ctx); this.ctx = capture(ctx);
this.component = component;
this.node = node; this.node = node;
this.key = key;
} }
evaluate(): any { evaluate(): any {
return this.fn(this.ctx, this.node); return this.fn.call(this.component, this.ctx, this.node, this.key);
} }
toString() { toString() {
@@ -127,9 +133,9 @@ class LazyValue {
/* /*
* Safely outputs `value` as a block depending on the nature of `value` * Safely outputs `value` as a block depending on the nature of `value`
*/ */
export function safeOutput(value: any): ReturnType<typeof toggler> { export function safeOutput(value: any, defaultValue?: any): ReturnType<typeof toggler> {
if (!value) { if (value === undefined) {
return value; return defaultValue ? toggler("default", defaultValue) : toggler("undefined", text(""));
} }
let safeKey; let safeKey;
let block; let block;
@@ -189,7 +195,7 @@ function multiRefSetter(refs: RefMap, name: string): RefSetter {
if (el) { if (el) {
count++; count++;
if (count > 1) { if (count > 1) {
throw new Error("Cannot have 2 elements with same ref name at the same time"); throw new OwlError("Cannot have 2 elements with same ref name at the same time");
} }
} }
if (count === 0 || el) { if (count === 0 || el) {
@@ -204,11 +210,11 @@ function multiRefSetter(refs: RefMap, name: string): RefSetter {
* 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.
*/ */
export function validateProps<P>(name: string | ComponentConstructor<P>, props: P, parent?: any) { export function validateProps<P>(name: string | ComponentConstructor<P>, props: P, comp?: any) {
const ComponentClass = const ComponentClass =
typeof name !== "string" typeof name !== "string"
? name ? name
: (parent.constructor.components[name] as ComponentConstructor<P> | undefined); : (comp.constructor.components[name] as ComponentConstructor<P> | undefined);
if (!ComponentClass) { if (!ComponentClass) {
// this is an error, wrong component. We silently return here instead so the // this is an error, wrong component. We silently return here instead so the
@@ -218,7 +224,7 @@ export function validateProps<P>(name: string | ComponentConstructor<P>, props:
const schema = ComponentClass.props; const schema = ComponentClass.props;
if (!schema) { if (!schema) {
if (parent.__owl__.app.warnIfNoStaticProps) { if (comp.__owl__.app.warnIfNoStaticProps) {
console.warn(`Component '${ComponentClass.name}' does not have a static props description`); console.warn(`Component '${ComponentClass.name}' does not have a static props description`);
} }
return; return;
@@ -231,7 +237,7 @@ export function validateProps<P>(name: string | ComponentConstructor<P>, props:
: name in schema && !("*" in schema) && !isOptional(schema[name]); : name in schema && !("*" in schema) && !isOptional(schema[name]);
for (let p in defaultProps) { for (let p in defaultProps) {
if (isMandatory(p)) { if (isMandatory(p)) {
throw new Error( throw new OwlError(
`A default value cannot be defined for a mandatory prop (name: '${p}', component: ${ComponentClass.name})` `A default value cannot be defined for a mandatory prop (name: '${p}', component: ${ComponentClass.name})`
); );
} }
@@ -240,7 +246,9 @@ export function validateProps<P>(name: string | ComponentConstructor<P>, props:
const errors = validateSchema(props, schema); const errors = validateSchema(props, schema);
if (errors.length) { if (errors.length) {
throw new Error(`Invalid props for component '${ComponentClass.name}': ` + errors.join(", ")); throw new OwlError(
`Invalid props for component '${ComponentClass.name}': ` + errors.join(", ")
);
} }
} }
@@ -262,4 +270,5 @@ export const helpers = {
bind, bind,
createCatcher, createCatcher,
markRaw, markRaw,
OwlError,
}; };
+5 -4
View File
@@ -3,6 +3,7 @@ import { comment, createBlock, html, list, multi, text, toggler } from "./blockd
import { getCurrent } from "./component_node"; import { getCurrent } from "./component_node";
import { Portal, portalTemplate } from "./portal"; import { Portal, portalTemplate } from "./portal";
import { helpers } from "./template_helpers"; import { helpers } from "./template_helpers";
import { OwlError } from "./error_handling";
const bdom = { text, createBlock, list, multi, html, toggler, comment }; const bdom = { text, createBlock, list, multi, html, toggler, comment };
@@ -31,7 +32,7 @@ function parseXML(xml: string): Document {
} }
} }
} }
throw new Error(msg); throw new OwlError(msg);
} }
return doc; return doc;
} }
@@ -76,7 +77,7 @@ export class TemplateSet {
if (currentAsString === newAsString) { if (currentAsString === newAsString) {
return; return;
} }
throw new Error(`Template ${name} already defined with different content`); throw new OwlError(`Template ${name} already defined with different content`);
} }
this.rawTemplates[name] = template; this.rawTemplates[name] = template;
} }
@@ -102,7 +103,7 @@ export class TemplateSet {
const componentName = getCurrent().component.constructor.name; const componentName = getCurrent().component.constructor.name;
extraInfo = ` (for component "${componentName}")`; extraInfo = ` (for component "${componentName}")`;
} catch {} } catch {}
throw new Error(`Missing template: "${name}"${extraInfo}`); throw new OwlError(`Missing template: "${name}"${extraInfo}`);
} }
const isFn = typeof rawTemplate === "function" && !(rawTemplate instanceof Element); const isFn = typeof rawTemplate === "function" && !(rawTemplate instanceof Element);
const templateFn = isFn ? rawTemplate : this._compileTemplate(name, rawTemplate); const templateFn = isFn ? rawTemplate : this._compileTemplate(name, rawTemplate);
@@ -119,7 +120,7 @@ export class TemplateSet {
} }
_compileTemplate(name: string, template: string | Element): ReturnType<typeof compile> { _compileTemplate(name: string, template: string | Element): ReturnType<typeof compile> {
throw new Error(`Unable to compile a template. Please use owl full build instead`); throw new OwlError(`Unable to compile a template. Please use owl full build instead`);
} }
callTemplate(owner: any, subTemplate: string, ctx: any, parent: any, key: any): any { callTemplate(owner: any, subTemplate: string, ctx: any, parent: any, key: any): any {
+13 -6
View File
@@ -1,3 +1,4 @@
import { OwlError } from "./error_handling";
export type Callback = () => void; export type Callback = () => void;
/** /**
@@ -27,12 +28,18 @@ export function batched(callback: Callback): Callback {
} }
export function validateTarget(target: HTMLElement) { export function validateTarget(target: HTMLElement) {
if (!(target instanceof HTMLElement)) { // Get the document and HTMLElement corresponding to the target to allow mounting in iframes
throw new Error("Cannot mount component: the target is not a valid DOM element"); const document = target && target.ownerDocument;
} if (document) {
if (!document.body.contains(target)) { const HTMLElement = document.defaultView!.HTMLElement;
throw new Error("Cannot mount a component on a detached dom node"); if (target instanceof HTMLElement) {
if (!document.body.contains(target)) {
throw new OwlError("Cannot mount a component on a detached dom node");
}
return;
}
} }
throw new OwlError("Cannot mount component: the target is not a valid DOM element");
} }
export class EventBus extends EventTarget { export class EventBus extends EventTarget {
@@ -54,7 +61,7 @@ export function whenReady(fn?: any): Promise<void> {
export async function loadFile(url: string): Promise<string> { export async function loadFile(url: string): Promise<string> {
const result = await fetch(url); const result = await fetch(url);
if (!result.ok) { if (!result.ok) {
throw new Error("Error while fetching xml templates"); throw new OwlError("Error while fetching xml templates");
} }
return await result.text(); return await result.text();
} }
+3 -1
View File
@@ -1,3 +1,5 @@
import { OwlError } from "./error_handling";
type BaseType = type BaseType =
| typeof String | typeof String
| typeof Boolean | typeof Boolean
@@ -70,7 +72,7 @@ function toSchema(spec: SimplifiedSchema): NormalizedSchema {
export function validate(obj: { [key: string]: any }, spec: Schema) { export function validate(obj: { [key: string]: any }, spec: Schema) {
let errors = validateSchema(obj, spec); let errors = validateSchema(obj, spec);
if (errors.length) { if (errors.length) {
throw new Error("Invalid object: " + errors.join(", ")); throw new OwlError("Invalid object: " + errors.join(", "));
} }
} }
+11 -11
View File
@@ -57,7 +57,7 @@ exports[`Reactivity: useState destroyed component before being mounted is inacti
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let b2; let b2;
if (ctx['state'].flag) { if (ctx['state'].flag) {
b2 = comp1({}, key + \`__1\`, node, ctx, null); b2 = comp1({}, key + \`__1\`, node, this, null);
} }
return block1([], [b2]); return block1([], [b2]);
} }
@@ -89,7 +89,7 @@ exports[`Reactivity: useState destroyed component is inactive 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let b2; let b2;
if (ctx['state'].flag) { if (ctx['state'].flag) {
b2 = comp1({}, key + \`__1\`, node, ctx, null); b2 = comp1({}, key + \`__1\`, node, this, null);
} }
return block1([], [b2]); return block1([], [b2]);
} }
@@ -134,7 +134,7 @@ exports[`Reactivity: useState parent and children subscribed to same context 1`]
let block1 = createBlock(\`<div><block-child-0/><block-text-0/></div>\`); let block1 = createBlock(\`<div><block-child-0/><block-text-0/></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const b2 = comp1({}, key + \`__1\`, node, ctx, null); const b2 = comp1({}, key + \`__1\`, node, this, null);
let txt1 = ctx['contextObj'].b; let txt1 = ctx['contextObj'].b;
return block1([txt1], [b2]); return block1([txt1], [b2]);
} }
@@ -228,8 +228,8 @@ exports[`Reactivity: useState two components are updated in parallel 1`] = `
let block1 = createBlock(\`<div><block-child-0/><block-child-1/></div>\`); let block1 = createBlock(\`<div><block-child-0/><block-child-1/></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const b2 = comp1({}, key + \`__1\`, node, ctx, null); const b2 = comp1({}, key + \`__1\`, node, this, null);
const b3 = comp2({}, key + \`__2\`, node, ctx, null); const b3 = comp2({}, key + \`__2\`, node, this, null);
return block1([], [b2, b3]); return block1([], [b2, b3]);
} }
}" }"
@@ -259,8 +259,8 @@ exports[`Reactivity: useState two components can subscribe to same context 1`] =
let block1 = createBlock(\`<div><block-child-0/><block-child-1/></div>\`); let block1 = createBlock(\`<div><block-child-0/><block-child-1/></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const b2 = comp1({}, key + \`__1\`, node, ctx, null); const b2 = comp1({}, key + \`__1\`, node, this, null);
const b3 = comp2({}, key + \`__2\`, node, ctx, null); const b3 = comp2({}, key + \`__2\`, node, this, null);
return block1([], [b2, b3]); return block1([], [b2, b3]);
} }
}" }"
@@ -290,8 +290,8 @@ exports[`Reactivity: useState two independent components on different levels are
let block1 = createBlock(\`<div><block-child-0/><block-child-1/></div>\`); let block1 = createBlock(\`<div><block-child-0/><block-child-1/></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const b2 = comp1({}, key + \`__1\`, node, ctx, null); const b2 = comp1({}, key + \`__1\`, node, this, null);
const b3 = comp2({}, key + \`__2\`, node, ctx, null); const b3 = comp2({}, key + \`__2\`, node, this, null);
return block1([], [b2, b3]); return block1([], [b2, b3]);
} }
}" }"
@@ -320,7 +320,7 @@ exports[`Reactivity: useState two independent components on different levels are
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 = \\"\\") {
const b2 = comp1({}, key + \`__1\`, node, ctx, null); const b2 = comp1({}, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -355,7 +355,7 @@ exports[`Reactivity: useState useless atoms should be deleted 1`] = `
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];
const key1 = ctx['id']; const key1 = ctx['id'];
c_block2[i1] = withKey(comp1({id: ctx['id']}, key + \`__1__\${key1}\`, node, ctx, null), key1); c_block2[i1] = withKey(comp1({id: ctx['id']}, key + \`__1__\${key1}\`, node, this, null), key1);
} }
ctx = ctx.__proto__; ctx = ctx.__proto__;
const b2 = list(c_block2); const b2 = list(c_block2);
+13
View File
@@ -29,6 +29,19 @@ exports[`app can configure an app with props 1`] = `
}" }"
`; `;
exports[`app can mount app in an iframe 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let block1 = createBlock(\`<div class=\\"my-div\\"/>\`);
return function template(ctx, node, key = \\"\\") {
return block1();
}
}"
`;
exports[`app destroy remove the widget from the DOM 1`] = ` exports[`app destroy remove the widget from the DOM 1`] = `
"function anonymous(app, bdom, helpers "function anonymous(app, bdom, helpers
) { ) {
+18
View File
@@ -76,4 +76,22 @@ describe("app", () => {
"Component 'Root' does not have a static props description" "Component 'Root' does not have a static props description"
); );
}); });
test("can mount app in an iframe", async () => {
class SomeComponent extends Component {
static template = xml`<div class="my-div"/>`;
}
const iframe = document.createElement("iframe");
fixture.appendChild(iframe);
const app = new App(SomeComponent);
const iframeDoc = iframe.contentDocument!;
const comp = await app.mount(iframeDoc.body);
const div = iframeDoc.querySelector(".my-div");
expect(div).not.toBe(null);
expect(iframeDoc.contains(div)).toBe(true);
app.destroy();
expect(iframeDoc.contains(div)).toBe(false);
expect(status(comp)).toBe("destroyed");
});
}); });
@@ -168,6 +168,48 @@ exports[`attributes dynamic class attribute evaluating to 0 1`] = `
}" }"
`; `;
exports[`attributes dynamic class attribute that starts and ends with a space 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, 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 class attribute which is only a space 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, 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 class attribute with multiple consecutive spaces 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, 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 empty class attribute 1`] = ` exports[`attributes dynamic empty class attribute 1`] = `
"function anonymous(app, bdom, helpers "function anonymous(app, bdom, helpers
) { ) {
@@ -470,6 +512,20 @@ exports[`attributes t-att-class with multiple classes 2`] = `
}" }"
`; `;
exports[`attributes t-att-class with multiple classes 3`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let block1 = createBlock(\`<div block-attribute-0=\\"class\\"/>\`);
return function template(ctx, node, key = \\"\\") {
let attr1 = {'a b c':ctx['value']};
return block1([attr1]);
}
}"
`;
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(app, bdom, helpers "function anonymous(app, bdom, helpers
) { ) {
@@ -498,6 +554,34 @@ exports[`attributes t-att-class with object 1`] = `
}" }"
`; `;
exports[`attributes t-att-class with object 2`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let block1 = createBlock(\`<div block-attribute-0=\\"class\\"/>\`);
return function template(ctx, node, key = \\"\\") {
let attr1 = {' a ':ctx['value']};
return block1([attr1]);
}
}"
`;
exports[`attributes t-att-class with object 3`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let block1 = createBlock(\`<div block-attribute-0=\\"class\\"/>\`);
return function template(ctx, node, key = \\"\\") {
let attr1 = {' ':ctx['value']};
return block1([attr1]);
}
}"
`;
exports[`attributes t-attf-class 1`] = ` exports[`attributes t-attf-class 1`] = `
"function anonymous(app, bdom, helpers "function anonymous(app, bdom, helpers
) { ) {
@@ -624,6 +708,20 @@ exports[`attributes updating classes (with obj notation) 1`] = `
}" }"
`; `;
exports[`attributes updating property with falsy value 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let block1 = createBlock(\`<input block-attribute-0=\\"value\\"/>\`);
return function template(ctx, node, key = \\"\\") {
let attr1 = new String((ctx['v']) || \\"\\");
return block1([attr1]);
}
}"
`;
exports[`attributes various escapes 1`] = ` exports[`attributes various escapes 1`] = `
"function anonymous(app, bdom, helpers "function anonymous(app, bdom, helpers
) { ) {
@@ -661,7 +759,7 @@ exports[`special cases for some specific html attributes/properties input of typ
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 attr1 = ctx['v']; let attr1 = new Boolean(ctx['v']);
return block1([attr1]); return block1([attr1]);
} }
}" }"
@@ -675,7 +773,21 @@ exports[`special cases for some specific html attributes/properties input type=
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 attr1 = ctx['flag']; let attr1 = new Boolean(ctx['flag']);
return block1([attr1]);
}
}"
`;
exports[`special cases for some specific html attributes/properties input with t-att-value (patching with same value 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let block1 = createBlock(\`<input block-attribute-0=\\"value\\"/>\`);
return function template(ctx, node, key = \\"\\") {
let attr1 = new String((ctx['v']) || \\"\\");
return block1([attr1]); return block1([attr1]);
} }
}" }"
@@ -689,7 +801,21 @@ exports[`special cases for some specific html attributes/properties input with t
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 attr1 = ctx['v']; let attr1 = new String((ctx['v']) || \\"\\");
return block1([attr1]);
}
}"
`;
exports[`special cases for some specific html attributes/properties input, type checkbox, with t-att-checked (patching with same value 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let block1 = createBlock(\`<input type=\\"checkbox\\" block-attribute-0=\\"checked\\"/>\`);
return function template(ctx, node, key = \\"\\") {
let attr1 = new Boolean(ctx['v']);
return block1([attr1]); return block1([attr1]);
} }
}" }"
@@ -703,7 +829,7 @@ exports[`special cases for some specific html attributes/properties select with
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 attr1 = ctx['value']; let attr1 = new String((ctx['value']) || \\"\\");
return block1([attr1]); return block1([attr1]);
} }
}" }"
@@ -717,7 +843,7 @@ exports[`special cases for some specific html attributes/properties textarea wit
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 attr1 = ctx['v']; let attr1 = new String((ctx['v']) || \\"\\");
return block1([attr1]); return block1([attr1]);
} }
}" }"
@@ -35,7 +35,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];
const key1 = ctx['slot'].id; const key1 = ctx['slot'].id;
c_block4[i1] = withKey(comp1({class: ctx['slot_container'],slot: ctx['slot']}, key + \`__1__\${key1}\`, node, ctx, null), key1); c_block4[i1] = withKey(comp1({class: ctx['slot_container'],slot: ctx['slot']}, key + \`__1__\${key1}\`, node, this, null), key1);
} }
ctx = ctx.__proto__; ctx = ctx.__proto__;
b4 = list(c_block4); b4 = list(c_block4);
@@ -166,13 +166,13 @@ exports[`misc global 4`] = `
"function anonymous(app, bdom, helpers "function anonymous(app, bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom; let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let { safeOutput, withDefault } = helpers; let { safeOutput } = helpers;
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 = \\"\\") {
const b3 = text(\`toto default\`); const b3 = text(\`toto default\`);
const b2 = withDefault(safeOutput(ctx['toto']), b3); const b2 = safeOutput(ctx['toto'], b3);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -269,7 +269,7 @@ exports[`misc other complex template 1`] = `
ctx[\`category\`] = v_block15[i1]; ctx[\`category\`] = v_block15[i1];
const key1 = ctx['category'].id; const key1 = ctx['category'].id;
let attr6 = ctx['category'].id; let attr6 = ctx['category'].id;
let attr7 = ctx['category'].id==ctx['options'].active_category_id; let attr7 = new Boolean(ctx['category'].id==ctx['options'].active_category_id);
let txt5 = ctx['category'].name; let txt5 = ctx['category'].name;
c_block15[i1] = withKey(block16([attr6, attr7, txt5]), key1); c_block15[i1] = withKey(block16([attr6, attr7, txt5]), key1);
} }
@@ -277,7 +277,7 @@ exports[`misc other complex template 1`] = `
const b15 = list(c_block15); const b15 = list(c_block15);
b14 = block14([], [b15]); b14 = block14([], [b15]);
} }
let attr8 = ctx['search'].value; let attr8 = new String((ctx['search'].value) || \\"\\");
let hdlr4 = [ctx['updateFilter'], ctx]; let hdlr4 = [ctx['updateFilter'], ctx];
let hdlr5 = [ctx['updateFilter'], ctx]; let hdlr5 = [ctx['updateFilter'], ctx];
let hdlr6 = [ctx['clearSearch'], ctx]; let hdlr6 = [ctx['clearSearch'], ctx];
@@ -291,7 +291,7 @@ exports[`misc other complex template 1`] = `
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 attr9 = \`trigger_\${ctx['trigger'].id}\`; let attr9 = \`trigger_\${ctx['trigger'].id}\`;
let attr10 = \`trigger_\${ctx['trigger'].id}\`; let attr10 = \`trigger_\${ctx['trigger'].id}\`;
let attr11 = ctx['options'].trigger_display[ctx['trigger'].id]; let attr11 = new Boolean(ctx['options'].trigger_display[ctx['trigger'].id]);
let attr12 = ctx['trigger'].id; let attr12 = ctx['trigger'].id;
let hdlr7 = [ctx['updateTriggerDisplay'], ctx]; let hdlr7 = [ctx['updateTriggerDisplay'], ctx];
let attr13 = \`trigger_\${ctx['trigger'].id}\`; let attr13 = \`trigger_\${ctx['trigger'].id}\`;
@@ -319,8 +319,8 @@ exports[`misc other complex template 1`] = `
if (!ctx['project']) { if (!ctx['project']) {
b24 = block24(); b24 = block24();
} else { } else {
const b26 = comp1({bundles: ctx['bundles'].sticky,category_custom_views: ctx['category_custom_views'],search: ctx['search']}, key + \`__2\`, node, ctx, null); const b26 = comp1({bundles: ctx['bundles'].sticky,category_custom_views: ctx['category_custom_views'],search: ctx['search']}, key + \`__2\`, node, this, null);
const b27 = comp2({bundles: ctx['bundles'].dev,search: ctx['search']}, key + \`__3\`, node, ctx, null); const b27 = comp2({bundles: ctx['bundles'].dev,search: ctx['search']}, key + \`__3\`, node, this, null);
b25 = block25([], [b26, b27]); b25 = block25([], [b26, b27]);
} }
return block1([attr1, txt1, hdlr2, hdlr3, attr8, hdlr4, hdlr5, ref1, hdlr6, ref2], [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]);
@@ -334,6 +334,57 @@ exports[`t-call (template calling) inherit context 2`] = `
}" }"
`; `;
exports[`t-call (template calling) nested t-calls with magic variable 0 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let { isBoundary, zero } = helpers;
const callTemplate_1 = app.getTemplate(\`grandchild\`);
const callTemplate_2 = app.getTemplate(\`child\`);
let block1 = createBlock(\`<p>Some content...</p>\`);
return function template(ctx, node, key = \\"\\") {
ctx = Object.create(ctx);
ctx[isBoundary] = 1;
ctx = Object.create(ctx);
ctx[isBoundary] = 1;
const b1 = block1();
ctx[zero] = b1;
const b2 = callTemplate_1.call(this, ctx, node, key + \`__1\`);
ctx = ctx.__proto__;
ctx[zero] = b2;
return callTemplate_2.call(this, ctx, node, key + \`__2\`);
}
}"
`;
exports[`t-call (template calling) nested t-calls with magic variable 0 2`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let { zero } = helpers;
return function template(ctx, node, key = \\"\\") {
const b2 = text(\`grandchild\`);
const b3 = ctx[zero];
return multi([b2, b3]);
}
}"
`;
exports[`t-call (template calling) nested t-calls with magic variable 0 3`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let { zero } = helpers;
return function template(ctx, node, key = \\"\\") {
return ctx[zero];
}
}"
`;
exports[`t-call (template calling) recursive template, part 1 1`] = ` exports[`t-call (template calling) recursive template, part 1 1`] = `
"function anonymous(app, bdom, helpers "function anonymous(app, bdom, helpers
) { ) {
@@ -617,6 +668,36 @@ exports[`t-call (template calling) t-call allowed on a non t node 2`] = `
}" }"
`; `;
exports[`t-call (template calling) t-call on a div with t-call-context 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
const callTemplate_1 = app.getTemplate(\`sub\`);
let block1 = createBlock(\`<div><block-child-0/></div>\`);
return function template(ctx, node, key = \\"\\") {
let ctx1 = ctx['obj'];
const b2 = callTemplate_1.call(this, ctx1, node, key + \`__1\`);
return block1([], [b2]);
}
}"
`;
exports[`t-call (template calling) t-call on a div with t-call-context 2`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let block1 = createBlock(\`<span><block-text-0/></span>\`);
return function template(ctx, node, key = \\"\\") {
let txt1 = ctx['value'];
return block1([txt1]);
}
}"
`;
exports[`t-call (template calling) t-call with body content as root of a template 1`] = ` exports[`t-call (template calling) t-call with body content as root of a template 1`] = `
"function anonymous(app, bdom, helpers "function anonymous(app, bdom, helpers
) { ) {
@@ -890,6 +971,67 @@ exports[`t-call (template calling) t-call, conditional and t-set in t-call body
}" }"
`; `;
exports[`t-call (template calling) t-call-context 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
const callTemplate_1 = app.getTemplate(\`sub\`);
return function template(ctx, node, key = \\"\\") {
let ctx1 = ctx['obj'];
return callTemplate_1.call(this, ctx1, node, key + \`__1\`);
}
}"
`;
exports[`t-call (template calling) t-call-context 2`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let block1 = createBlock(\`<span><block-text-0/></span>\`);
return function template(ctx, node, key = \\"\\") {
let txt1 = ctx['value'];
return block1([txt1]);
}
}"
`;
exports[`t-call (template calling) t-call-context and value in body 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let { isBoundary, withDefault, setContextValue } = helpers;
const callTemplate_1 = app.getTemplate(\`sub\`);
return function template(ctx, node, key = \\"\\") {
ctx = Object.create(ctx);
ctx[isBoundary] = 1
let ctx1 = ctx['obj'];
ctx1 = Object.create(ctx1);
ctx1[isBoundary] = 1;
setContextValue(ctx1, \\"value2\\", ctx['aaron']);
return callTemplate_1.call(this, ctx1, node, key + \`__1\`);
}
}"
`;
exports[`t-call (template calling) t-call-context and value in body 2`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let block1 = createBlock(\`<span><block-text-0/><block-text-1/></span>\`);
return function template(ctx, node, key = \\"\\") {
let txt1 = ctx['value1'];
let txt2 = ctx['value2'];
return block1([txt1, txt2]);
}
}"
`;
exports[`t-call (template calling) t-esc inside t-call, with t-set outside 1`] = ` exports[`t-call (template calling) t-esc inside t-call, with t-set outside 1`] = `
"function anonymous(app, bdom, helpers "function anonymous(app, bdom, helpers
) { ) {
@@ -126,7 +126,32 @@ exports[`t-esc t-esc is escaped 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
ctx = Object.create(ctx); ctx = Object.create(ctx);
ctx[isBoundary] = 1 ctx[isBoundary] = 1
ctx[\`var\`] = new LazyValue(value1, ctx, node); ctx[\`var\`] = new LazyValue(value1, ctx, this, node, key);
let txt1 = ctx['var'];
return block1([txt1]);
}
}"
`;
exports[`t-esc t-esc with the 0 number 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
return function template(ctx, node, key = \\"\\") {
return text(ctx['var']);
}
}"
`;
exports[`t-esc t-esc with the 0 number, in a p 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let block1 = createBlock(\`<p><block-text-0/></p>\`);
return function template(ctx, node, key = \\"\\") {
let txt1 = ctx['var']; let txt1 = ctx['var'];
return block1([txt1]); return block1([txt1]);
} }
@@ -183,6 +208,17 @@ exports[`t-esc t-esc=0 is escaped 2`] = `
}" }"
`; `;
exports[`t-esc top level t-esc with undefined 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
return function template(ctx, node, key = \\"\\") {
return text(ctx['var']);
}
}"
`;
exports[`t-esc variable 1`] = ` exports[`t-esc variable 1`] = `
"function anonymous(app, bdom, helpers "function anonymous(app, bdom, helpers
) { ) {
@@ -161,7 +161,7 @@ exports[`t-out t-out bdom 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
ctx = Object.create(ctx); ctx = Object.create(ctx);
ctx[isBoundary] = 1 ctx[isBoundary] = 1
ctx[\`var\`] = new LazyValue(value1, ctx, node); ctx[\`var\`] = new LazyValue(value1, ctx, this, node, key);
const b3 = safeOutput(ctx['var']); const b3 = safeOutput(ctx['var']);
return block1([], [b3]); return block1([], [b3]);
} }
@@ -217,13 +217,13 @@ exports[`t-out t-out on a node with a body, as a default 1`] = `
"function anonymous(app, bdom, helpers "function anonymous(app, bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom; let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let { safeOutput, withDefault } = helpers; let { safeOutput } = helpers;
let block1 = createBlock(\`<span><block-child-0/></span>\`); let block1 = createBlock(\`<span><block-child-0/></span>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const b3 = text(\`nope\`); const b3 = text(\`nope\`);
const b2 = withDefault(safeOutput(ctx['var']), b3); const b2 = safeOutput(ctx['var'], b3);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -233,14 +233,14 @@ exports[`t-out t-out on a node with a dom node in body, as a default 1`] = `
"function anonymous(app, bdom, helpers "function anonymous(app, bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom; let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let { safeOutput, withDefault } = helpers; let { safeOutput } = 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>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const b3 = block3(); const b3 = block3();
const b2 = withDefault(safeOutput(ctx['var']), b3); const b2 = safeOutput(ctx['var'], b3);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -310,7 +310,7 @@ exports[`t-out t-out switch markup on bdom 1`] = `
ctx = Object.create(ctx); ctx = Object.create(ctx);
ctx[isBoundary] = 1 ctx[isBoundary] = 1
let b3,b5; let b3,b5;
ctx[\`bdom\`] = new LazyValue(value1, ctx, node); ctx[\`bdom\`] = new LazyValue(value1, ctx, this, node, key);
if (ctx['hasBdom']) { if (ctx['hasBdom']) {
const b4 = safeOutput(ctx['bdom']); const b4 = safeOutput(ctx['bdom']);
b3 = block3([], [b4]); b3 = block3([], [b4]);
@@ -407,6 +407,45 @@ exports[`t-out t-out with just a t-set t-value in body 1`] = `
}" }"
`; `;
exports[`t-out t-out with the 0 number 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let { safeOutput } = helpers;
return function template(ctx, node, key = \\"\\") {
return safeOutput(ctx['var']);
}
}"
`;
exports[`t-out t-out with the 0 number, in a p 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let { safeOutput } = helpers;
let block1 = createBlock(\`<p><block-child-0/></p>\`);
return function template(ctx, node, key = \\"\\") {
const b2 = safeOutput(ctx['var']);
return block1([], [b2]);
}
}"
`;
exports[`t-out top level t-out with undefined 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let { safeOutput } = helpers;
return function template(ctx, node, key = \\"\\") {
return safeOutput(ctx['var']);
}
}"
`;
exports[`t-out variable 1`] = ` exports[`t-out variable 1`] = `
"function anonymous(app, bdom, helpers "function anonymous(app, bdom, helpers
) { ) {
@@ -106,7 +106,7 @@ exports[`t-set set from body literal (with t-if/t-else 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
ctx = Object.create(ctx); ctx = Object.create(ctx);
ctx[isBoundary] = 1 ctx[isBoundary] = 1
ctx[\`value\`] = new LazyValue(value1, ctx, node); ctx[\`value\`] = new LazyValue(value1, ctx, this, node, key);
return text(ctx['value']); return text(ctx['value']);
} }
}" }"
@@ -142,7 +142,7 @@ exports[`t-set set from body lookup 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
ctx = Object.create(ctx); ctx = Object.create(ctx);
ctx[isBoundary] = 1 ctx[isBoundary] = 1
ctx[\`stuff\`] = new LazyValue(value1, ctx, node); ctx[\`stuff\`] = new LazyValue(value1, ctx, this, node, key);
let txt1 = ctx['stuff']; let txt1 = ctx['stuff'];
return block1([txt1]); return block1([txt1]);
} }
@@ -206,7 +206,7 @@ exports[`t-set t-set body is evaluated immediately 1`] = `
ctx = Object.create(ctx); ctx = Object.create(ctx);
ctx[isBoundary] = 1 ctx[isBoundary] = 1
setContextValue(ctx, \\"v1\\", 'before'); setContextValue(ctx, \\"v1\\", 'before');
ctx[\`v2\`] = new LazyValue(value1, ctx, node); ctx[\`v2\`] = new LazyValue(value1, ctx, this, node, key);
setContextValue(ctx, \\"v1\\", 'after'); setContextValue(ctx, \\"v1\\", 'after');
const b3 = safeOutput(ctx['v2']); const b3 = safeOutput(ctx['v2']);
return block1([], [b3]); return block1([], [b3]);
@@ -471,7 +471,7 @@ exports[`t-set t-set with content and sub t-esc 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
ctx = Object.create(ctx); ctx = Object.create(ctx);
ctx[isBoundary] = 1 ctx[isBoundary] = 1
ctx[\`setvar\`] = new LazyValue(value1, ctx, node); ctx[\`setvar\`] = new LazyValue(value1, ctx, this, node, key);
let txt1 = ctx['setvar']; let txt1 = ctx['setvar'];
return block1([txt1]); return block1([txt1]);
} }
@@ -497,7 +497,7 @@ exports[`t-set t-set with t-value (falsy) and body 1`] = `
ctx[isBoundary] = 1 ctx[isBoundary] = 1
setContextValue(ctx, \\"v3\\", false); setContextValue(ctx, \\"v3\\", false);
setContextValue(ctx, \\"v1\\", 'before'); setContextValue(ctx, \\"v1\\", 'before');
ctx[\`v2\`] = withDefault(ctx['v3'], new LazyValue(value1, ctx, node)); ctx[\`v2\`] = withDefault(ctx['v3'], new LazyValue(value1, ctx, this, node, key));
setContextValue(ctx, \\"v1\\", 'after'); setContextValue(ctx, \\"v1\\", 'after');
setContextValue(ctx, \\"v3\\", true); setContextValue(ctx, \\"v3\\", true);
const b3 = safeOutput(ctx['v2']); const b3 = safeOutput(ctx['v2']);
@@ -525,7 +525,7 @@ exports[`t-set t-set with t-value (truthy) and body 1`] = `
ctx[isBoundary] = 1 ctx[isBoundary] = 1
setContextValue(ctx, \\"v3\\", 'Truthy'); setContextValue(ctx, \\"v3\\", 'Truthy');
setContextValue(ctx, \\"v1\\", 'before'); setContextValue(ctx, \\"v1\\", 'before');
ctx[\`v2\`] = withDefault(ctx['v3'], new LazyValue(value1, ctx, node)); ctx[\`v2\`] = withDefault(ctx['v3'], new LazyValue(value1, ctx, this, node, key));
setContextValue(ctx, \\"v1\\", 'after'); setContextValue(ctx, \\"v1\\", 'after');
setContextValue(ctx, \\"v3\\", false); setContextValue(ctx, \\"v3\\", false);
const b3 = safeOutput(ctx['v2']); const b3 = safeOutput(ctx['v2']);
@@ -534,13 +534,36 @@ exports[`t-set t-set with t-value (truthy) and body 1`] = `
}" }"
`; `;
exports[`t-set t-set, multiple t-ifs, and a specific configuration 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let { isBoundary, withDefault, setContextValue } = helpers;
let block1 = createBlock(\`<p><div><span>First div</span></div><div><block-child-0/></div></p>\`);
return function template(ctx, node, key = \\"\\") {
ctx = Object.create(ctx);
ctx[isBoundary] = 1
let b2;
if (ctx['flag']) {
setContextValue(ctx, \\"bouh\\", 2);
}
if (!ctx['flag']) {
b2 = text(\`Second\`);
}
return block1([], [b2]);
}
}"
`;
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(app, bdom, helpers "function anonymous(app, bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom; let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let { isBoundary, withDefault, setContextValue } = 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-text-0/></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
ctx = Object.create(ctx); ctx = Object.create(ctx);
@@ -562,7 +585,7 @@ exports[`t-set t-set, t-if, and mix of expression/body lookup, 2 1`] = `
let { text, createBlock, list, multi, html, toggler, comment } = bdom; let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let { isBoundary, withDefault, setContextValue } = 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-text-0/></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
ctx = Object.create(ctx); ctx = Object.create(ctx);
@@ -615,7 +638,7 @@ exports[`t-set value priority (with non text body 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
ctx = Object.create(ctx); ctx = Object.create(ctx);
ctx[isBoundary] = 1 ctx[isBoundary] = 1
ctx[\`value\`] = withDefault(1, new LazyValue(value1, ctx, node)); ctx[\`value\`] = withDefault(1, new LazyValue(value1, ctx, this, node, key));
let txt1 = ctx['value']; let txt1 = ctx['value'];
return block1([txt1]); return block1([txt1]);
} }
+95
View File
@@ -63,6 +63,24 @@ describe("attributes", () => {
expect(result).toBe(`<div></div>`); expect(result).toBe(`<div></div>`);
}); });
test("dynamic class attribute which is only a space", () => {
const template = `<div t-att-class="c"/>`;
const result = renderToString(template, { c: " " });
expect(result).toBe(`<div></div>`);
});
test("dynamic class attribute with multiple consecutive spaces", () => {
const template = `<div t-att-class="c"/>`;
const result = renderToString(template, { c: "a b" });
expect(result).toBe(`<div class="a b"></div>`);
});
test("dynamic class attribute that starts and ends with a space", () => {
const template = `<div t-att-class="c"/>`;
const result = renderToString(template, { c: " a " });
expect(result).toBe(`<div class="a"></div>`);
});
test("dynamic undefined generic attribute", () => { test("dynamic undefined generic attribute", () => {
const template = `<div t-att-thing="c"/>`; const template = `<div t-att-thing="c"/>`;
const result = renderToString(template, { c: undefined }); const result = renderToString(template, { c: undefined });
@@ -260,6 +278,14 @@ describe("attributes", () => {
const template = `<div class="static" t-att-class="{a: b, c: d, e: f}"/>`; const template = `<div class="static" t-att-class="{a: b, c: d, e: f}"/>`;
const result = renderToString(template, { b: true, d: false, f: true }); const result = renderToString(template, { b: true, d: false, f: true });
expect(result).toBe(`<div class="static a e"></div>`); expect(result).toBe(`<div class="static a e"></div>`);
// leading and trailing space in the key
expect(renderToString(`<div t-att-class="{' a ': value}" />`, { value: true })).toBe(
'<div class="a"></div>'
);
// whitespace only key
expect(renderToString(`<div t-att-class="{' ': value}" />`, { value: true })).toBe(
"<div></div>"
);
}); });
test("t-att-class with multiple classes", () => { test("t-att-class with multiple classes", () => {
@@ -269,6 +295,10 @@ describe("attributes", () => {
expect(renderToString(`<div t-att-class="{['a b c']: value}" />`, { value: true })).toBe( expect(renderToString(`<div t-att-class="{['a b c']: value}" />`, { value: true })).toBe(
'<div class="a b c"></div>' '<div class="a b c"></div>'
); );
// multiple spaces between classes
expect(renderToString(`<div t-att-class="{'a b c': value}" />`, { value: true })).toBe(
'<div class="a b c"></div>'
);
}); });
test("t-att-class with multiple classes, some of which are duplicate", () => { test("t-att-class with multiple classes, some of which are duplicate", () => {
@@ -299,6 +329,35 @@ describe("attributes", () => {
expect(fixture.innerHTML).toBe('<div value=""></div>'); expect(fixture.innerHTML).toBe('<div value=""></div>');
}); });
test("updating property with falsy value", async () => {
// render input with initial value
const template = `<input t-att-value="v"></input>`;
const bnode1 = renderToBdom(template, { v: false });
const fixture = makeTestFixture();
mount(bnode1, fixture);
const input = fixture.querySelector("input")!;
expect(input.value).toBe("");
patch(bnode1, renderToBdom(template, { v: "owl" }));
expect(input.value).toBe("owl");
patch(bnode1, renderToBdom(template, { v: false }));
expect(input.value).toBe("");
patch(bnode1, renderToBdom(template, { v: "owl" }));
expect(input.value).toBe("owl");
patch(bnode1, renderToBdom(template, { v: undefined }));
expect(input.value).toBe("");
patch(bnode1, renderToBdom(template, { v: "owl" }));
expect(input.value).toBe("owl");
patch(bnode1, renderToBdom(template, { v: null }));
expect(input.value).toBe("");
});
test("changing a class with t-att-class", () => { test("changing a class with t-att-class", () => {
// render input with initial value // render input with initial value
const template = `<div t-att-class="v"/>`; const template = `<div t-att-class="v"/>`;
@@ -399,6 +458,42 @@ describe("special cases for some specific html attributes/properties", () => {
expect(input.value).toBe("potato"); expect(input.value).toBe("potato");
}); });
test("input with t-att-value (patching with same value", () => {
// render input with initial value
const template = `<input t-att-value="v"/>`;
const bnode1 = renderToBdom(template, { v: "zucchini" });
const fixture = makeTestFixture();
mount(bnode1, fixture);
const input = fixture.querySelector("input")!;
expect(input.value).toBe("zucchini");
// change value manually in input, to simulate user input
input.value = "tomato";
expect(input.value).toBe("tomato");
const bnode2 = renderToBdom(template, { v: "zucchini" });
patch(bnode1, bnode2);
expect(input.value).toBe("zucchini");
});
test("input, type checkbox, with t-att-checked (patching with same value", () => {
// render input with initial value
const template = `<input type="checkbox" t-att-checked="v"/>`;
const bnode1 = renderToBdom(template, { v: true });
const fixture = makeTestFixture();
mount(bnode1, fixture);
const input = fixture.querySelector("input")!;
expect(input.checked).toBe(true);
// change checked manually in input, to simulate user input
input.checked = false;
expect(input.checked).toBe(false);
const bnode2 = renderToBdom(template, { v: true });
patch(bnode1, bnode2);
expect(input.checked).toBe(true);
});
test("input of type checkbox with t-att-indeterminate", () => { test("input of type checkbox with t-att-indeterminate", () => {
const template = `<input type="checkbox" t-att-indeterminate="v"/>`; const template = `<input type="checkbox" t-att-indeterminate="v"/>`;
const bnode1 = renderToBdom(template, { v: true }); const bnode1 = renderToBdom(template, { v: true });
@@ -221,4 +221,11 @@ describe("expression evaluation", () => {
expect(compileExpr("a.c in b")).toBe("ctx['a'].c in ctx['b']"); expect(compileExpr("a.c in b")).toBe("ctx['a'].c in ctx['b']");
expect(compileExpr("typeof val")).toBe("typeof ctx['val']"); expect(compileExpr("typeof val")).toBe("typeof ctx['val']");
}); });
test("binary operators", () => {
expect(compileExpr("1 | 1")).toBe("1|1");
expect(compileExpr("1 & 1")).toBe("1&1");
expect(compileExpr("1 ^ 1")).toBe("1^1");
expect(compileExpr("~1")).toBe("~1");
});
}); });
+15 -1
View File
@@ -1033,6 +1033,7 @@ describe("qweb parser", () => {
type: ASTType.TCall, type: ASTType.TCall,
name: "blap", name: "blap",
body: null, body: null,
context: null,
}, },
memo: "", memo: "",
hasNoFirst: false, hasNoFirst: false,
@@ -1070,6 +1071,7 @@ describe("qweb parser", () => {
type: ASTType.TCall, type: ASTType.TCall,
name: "blabla", name: "blabla",
body: null, body: null,
context: null,
}); });
}); });
@@ -1077,10 +1079,20 @@ describe("qweb parser", () => {
expect(parse(`<t t-call="sub">ok</t>`)).toEqual({ expect(parse(`<t t-call="sub">ok</t>`)).toEqual({
type: ASTType.TCall, type: ASTType.TCall,
name: "sub", name: "sub",
context: null,
body: [{ type: ASTType.Text, value: "ok" }], body: [{ type: ASTType.Text, value: "ok" }],
}); });
}); });
test("t-call expression with t-call-context", async () => {
expect(parse(`<t t-call="blabla" t-call-context="someContext"/>`)).toEqual({
type: ASTType.TCall,
name: "blabla",
body: null,
context: "someContext",
});
});
test("t-call on a div node", async () => { test("t-call on a div node", async () => {
expect(parse(`<div t-call="blabla" />`)).toEqual({ expect(parse(`<div t-call="blabla" />`)).toEqual({
type: ASTType.DomNode, type: ASTType.DomNode,
@@ -1096,6 +1108,7 @@ describe("qweb parser", () => {
type: ASTType.TCall, type: ASTType.TCall,
name: "blabla", name: "blabla",
body: null, body: null,
context: null,
}, },
], ],
}); });
@@ -1111,6 +1124,7 @@ describe("qweb parser", () => {
type: ASTType.TCall, type: ASTType.TCall,
name: "blabla", name: "blabla",
body: null, body: null,
context: null,
}, },
}); });
}); });
@@ -1547,7 +1561,7 @@ describe("qweb parser", () => {
on: null, on: null,
slots: { slots: {
default: { default: {
content: { body: null, name: "subTemplate", type: ASTType.TCall }, content: { body: null, name: "subTemplate", type: ASTType.TCall, context: null },
attrs: null, attrs: null,
scope: null, scope: null,
on: null, on: null,
+51
View File
@@ -445,4 +445,55 @@ describe("t-call (template calling)", () => {
const expected2 = "<div><bar>quux</bar></div>"; const expected2 = "<div><bar>quux</bar></div>";
expect(context.renderToString("main", { template: "bar", val: "quux" })).toBe(expected2); expect(context.renderToString("main", { template: "bar", val: "quux" })).toBe(expected2);
}); });
test("t-call-context", () => {
const context = new TestContext();
context.addTemplate("sub", `<span><t t-esc="value"/></span>`);
context.addTemplate("main", `<t t-call="sub" t-call-context="obj"/>`);
expect(context.renderToString("main", { obj: { value: 123 } })).toBe("<span>123</span>");
});
test("t-call on a div with t-call-context", () => {
const context = new TestContext();
context.addTemplate("sub", `<span><t t-esc="value"/></span>`);
context.addTemplate("main", `<div t-call="sub" t-call-context="obj"/>`);
expect(context.renderToString("main", { obj: { value: 123 } })).toBe(
"<div><span>123</span></div>"
);
});
test("t-call-context and value in body", () => {
const context = new TestContext();
context.addTemplate("sub", `<span><t t-esc="value1"/><t t-esc="value2"/></span>`);
context.addTemplate(
"main",
`
<t t-call="sub" t-call-context="obj">
<t t-set="value2" t-value="aaron" />
</t>`
);
expect(context.renderToString("main", { obj: { value1: 123 }, aaron: "lucas" })).toBe(
"<span>123lucas</span>"
);
});
test("nested t-calls with magic variable 0", () => {
const context = new TestContext();
context.addTemplate("grandchild", `grandchild<t t-out="0"/>`);
context.addTemplate("child", `<t t-out="0"/>`);
context.addTemplate(
"main",
`
<t t-call="child">
<t t-call="grandchild">
<p>Some content...</p>
</t>
</t>`
);
expect(context.renderToString("main")).toBe("grandchild<p>Some content...</p>");
});
}); });
+15
View File
@@ -67,6 +67,21 @@ describe("t-esc", () => {
); );
}); });
test("t-esc with the 0 number", () => {
const template = `<t t-esc="var"/>`;
expect(renderToString(template, { var: 0 })).toBe("0");
});
test("t-esc with the 0 number, in a p", () => {
const template = `<p><t t-esc="var"/></p>`;
expect(renderToString(template, { var: 0 })).toBe("<p>0</p>");
});
test("top level t-esc with undefined", () => {
const template = `<t t-esc="var"/>`;
expect(renderToString(template, { var: undefined })).toBe("");
});
test("falsy values in text nodes", () => { test("falsy values in text nodes", () => {
const template = ` const template = `
<t t-esc="v1"/>:<t t-esc="v2"/>:<t t-esc="v3"/>:<t t-esc="v4"/>:<t t-esc="v5"/>`; <t t-esc="v1"/>:<t t-esc="v2"/>:<t t-esc="v3"/>:<t t-esc="v4"/>:<t t-esc="v5"/>`;
+15
View File
@@ -47,6 +47,21 @@ describe("t-out", () => {
expect(renderToString(template, { var: new String("ok") })).toBe("<span>ok</span>"); expect(renderToString(template, { var: new String("ok") })).toBe("<span>ok</span>");
}); });
test("t-out with the 0 number", () => {
const template = `<t t-out="var"/>`;
expect(renderToString(template, { var: 0 })).toBe("0");
});
test("t-out with the 0 number, in a p", () => {
const template = `<p><t t-out="var"/></p>`;
expect(renderToString(template, { var: 0 })).toBe("<p>0</p>");
});
test("top level t-out with undefined", () => {
const template = `<t t-out="var"/>`;
expect(renderToString(template, { var: undefined })).toBe("");
});
test("with an extended String class", () => { test("with an extended String class", () => {
class LoveString extends String { class LoveString extends String {
valueOf(): string { valueOf(): string {
+16
View File
@@ -33,6 +33,22 @@ describe("t-set", () => {
expect(renderToString(template, { value: "ok" })).toBe("<div>grimbergen</div>"); expect(renderToString(template, { value: "ok" })).toBe("<div>grimbergen</div>");
}); });
test("t-set, multiple t-ifs, and a specific configuration", () => {
const template = `
<p>
<div>
<t t-if="flag" t-set="bouh" t-value="2"/>
<span>First div</span>
</div>
<div>
<t t-if="!flag">Second</t>
</div>
</p>`;
expect(renderToString(template)).toBe(
"<p><div><span>First div</span></div><div>Second</div></p>"
);
});
test("set from body literal", () => { test("set from body literal", () => {
const template = `<t><t t-set="value">ok</t><t t-esc="value"/></t>`; const template = `<t><t t-set="value">ok</t><t t-esc="value"/></t>`;
expect(renderToString(template)).toBe("ok"); expect(renderToString(template)).toBe("ok");
@@ -8,7 +8,7 @@ exports[`basics GrandChild display is controlled by its GrandParent 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const Comp1 = ctx['myComp']; const Comp1 = ctx['myComp'];
return toggler(Comp1, comp1({displayGrandChild: ctx['displayGrandChild']}, key + \`__1\`, node, ctx, Comp1)); return toggler(Comp1, comp1({displayGrandChild: ctx['displayGrandChild']}, key + \`__1\`, node, this, Comp1));
} }
}" }"
`; `;
@@ -22,7 +22,7 @@ exports[`basics GrandChild display is controlled by its GrandParent 2`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let b2; let b2;
if (ctx['props'].displayGrandChild) { if (ctx['props'].displayGrandChild) {
b2 = comp1({}, key + \`__1\`, node, ctx, null); b2 = comp1({}, key + \`__1\`, node, this, null);
} }
return multi([b2]); return multi([b2]);
} }
@@ -66,7 +66,7 @@ exports[`basics a class component inside a class component, no external dom 1`]
const comp1 = app.createComponent(\`Child\`, true, false, false, true); const comp1 = app.createComponent(\`Child\`, true, false, false, true);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({}, key + \`__1\`, node, ctx, null); return comp1({}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -106,7 +106,7 @@ exports[`basics a component inside a component 1`] = `
let block1 = createBlock(\`<span><block-child-0/></span>\`); let block1 = createBlock(\`<span><block-child-0/></span>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const b2 = comp1({}, key + \`__1\`, node, ctx, null); const b2 = comp1({}, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -150,7 +150,7 @@ exports[`basics can handle empty props 1`] = `
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 = \\"\\") {
const b2 = comp1({val: undefined}, key + \`__1\`, node, ctx, null); const b2 = comp1({val: undefined}, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -268,7 +268,7 @@ exports[`basics child can be updated 1`] = `
const comp1 = app.createComponent(\`Child\`, true, false, false, false); const comp1 = app.createComponent(\`Child\`, true, false, false, false);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({value: ctx['state'].counter}, key + \`__1\`, node, ctx, null); return comp1({value: ctx['state'].counter}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -305,7 +305,7 @@ exports[`basics class parent, class child component with props 1`] = `
const comp1 = app.createComponent(\`Child\`, true, false, false, false); const comp1 = app.createComponent(\`Child\`, true, false, false, false);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({value: 42}, key + \`__1\`, node, ctx, null); return comp1({value: 42}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -333,7 +333,7 @@ exports[`basics component children doesn't leak (if case) 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let b2; let b2;
if (ctx['ifVar']) { if (ctx['ifVar']) {
b2 = comp1({}, key + \`__1\`, node, ctx, null); b2 = comp1({}, key + \`__1\`, node, this, null);
} }
return multi([b2]); return multi([b2]);
} }
@@ -361,7 +361,7 @@ exports[`basics component children doesn't leak (t-key case) 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const tKey_1 = ctx['keyVar']; const tKey_1 = ctx['keyVar'];
return toggler(tKey_1, comp1({}, tKey_1 + key + \`__1\`, node, ctx, null)); return toggler(tKey_1, comp1({}, tKey_1 + key + \`__1\`, node, this, null));
} }
}" }"
`; `;
@@ -427,7 +427,7 @@ exports[`basics higher order components parent and child 1`] = `
const comp1 = app.createComponent(\`Child\`, true, false, false, false); const comp1 = app.createComponent(\`Child\`, true, false, false, false);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({child: ctx['state'].child}, key + \`__1\`, node, ctx, null); return comp1({child: ctx['state'].child}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -442,9 +442,9 @@ exports[`basics higher order components parent and child 2`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let b2,b3; let b2,b3;
if (ctx['props'].child==='a') { if (ctx['props'].child==='a') {
b2 = comp1({}, key + \`__1\`, node, ctx, null); b2 = comp1({}, key + \`__1\`, node, this, null);
} else { } else {
b3 = comp2({}, key + \`__2\`, node, ctx, null); b3 = comp2({}, key + \`__2\`, node, this, null);
} }
return multi([b2, b3]); return multi([b2, b3]);
} }
@@ -494,8 +494,8 @@ exports[`basics list of two sub components inside other nodes 1`] = `
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];
const key1 = ctx['blip'].id; const key1 = ctx['blip'].id;
const b4 = comp1({}, key + \`__1__\${key1}\`, node, ctx, null); const b4 = comp1({}, key + \`__1__\${key1}\`, node, this, null);
const b5 = comp2({}, key + \`__2__\${key1}\`, node, ctx, null); const b5 = comp2({}, key + \`__2__\${key1}\`, node, this, null);
c_block2[i1] = withKey(block3([], [b4, b5]), key1); c_block2[i1] = withKey(block3([], [b4, b5]), key1);
} }
const b2 = list(c_block2); const b2 = list(c_block2);
@@ -524,7 +524,7 @@ exports[`basics parent, child and grandchild 1`] = `
const comp1 = app.createComponent(\`Child\`, true, false, false, true); const comp1 = app.createComponent(\`Child\`, true, false, false, true);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({}, key + \`__1\`, node, ctx, null); return comp1({}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -536,7 +536,7 @@ exports[`basics parent, child and grandchild 2`] = `
const comp1 = app.createComponent(\`GrandChild\`, true, false, false, true); const comp1 = app.createComponent(\`GrandChild\`, true, false, false, true);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({}, key + \`__1\`, node, ctx, null); return comp1({}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -603,9 +603,9 @@ exports[`basics reconciliation alg is not confused in some specific situation 1`
let block1 = createBlock(\`<div><block-child-0/><block-child-1/></div>\`); let block1 = createBlock(\`<div><block-child-0/><block-child-1/></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const b2 = comp1({}, key + \`__1\`, node, ctx, null); const b2 = comp1({}, key + \`__1\`, node, this, null);
const tKey_1 = 4; const tKey_1 = 4;
const b3 = toggler(tKey_1, comp2({}, tKey_1 + key + \`__2\`, node, ctx, null)); const b3 = toggler(tKey_1, comp2({}, tKey_1 + key + \`__2\`, node, this, null));
return block1([], [b2, b3]); return block1([], [b2, b3]);
} }
}" }"
@@ -631,7 +631,7 @@ exports[`basics rerendering a widget with a sub widget 1`] = `
const comp1 = app.createComponent(\`Counter\`, true, false, false, true); const comp1 = app.createComponent(\`Counter\`, true, false, false, true);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({}, key + \`__1\`, node, ctx, null); return comp1({}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -663,9 +663,9 @@ exports[`basics same t-keys in two different places 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const tKey_1 = 1; const tKey_1 = 1;
const b2 = toggler(tKey_1, comp1({blip: '1'}, tKey_1 + key + \`__1\`, node, ctx, null)); const b2 = toggler(tKey_1, comp1({blip: '1'}, tKey_1 + key + \`__1\`, node, this, null));
const tKey_2 = 1; const tKey_2 = 1;
const b3 = toggler(tKey_2, comp2({blip: '2'}, tKey_2 + key + \`__2\`, node, ctx, null)); const b3 = toggler(tKey_2, comp2({blip: '2'}, tKey_2 + key + \`__2\`, node, this, null));
return block1([], [b2, b3]); return block1([], [b2, b3]);
} }
}" }"
@@ -744,7 +744,7 @@ exports[`basics sub components between t-ifs 1`] = `
} else { } else {
b3 = block3(); b3 = block3();
} }
b4 = comp1({}, key + \`__1\`, node, ctx, null); b4 = comp1({}, key + \`__1\`, node, this, null);
if (ctx['state'].flag) { if (ctx['state'].flag) {
b5 = block5(); b5 = block5();
} }
@@ -780,7 +780,7 @@ exports[`basics t-elif works with t-component 1`] = `
if (ctx['state'].flag) { if (ctx['state'].flag) {
b2 = block2(); b2 = block2();
} else if (!ctx['state'].flag) { } else if (!ctx['state'].flag) {
b3 = comp1({}, key + \`__1\`, node, ctx, null); b3 = comp1({}, key + \`__1\`, node, this, null);
} }
return block1([], [b2, b3]); return block1([], [b2, b3]);
} }
@@ -814,7 +814,7 @@ exports[`basics t-else with empty string works with t-component 1`] = `
if (ctx['state'].flag) { if (ctx['state'].flag) {
b2 = block2(); b2 = block2();
} else { } else {
b3 = comp1({}, key + \`__1\`, node, ctx, null); b3 = comp1({}, key + \`__1\`, node, this, null);
} }
return block1([], [b2, b3]); return block1([], [b2, b3]);
} }
@@ -848,7 +848,7 @@ exports[`basics t-else works with t-component 1`] = `
if (ctx['state'].flag) { if (ctx['state'].flag) {
b2 = block2(); b2 = block2();
} else { } else {
b3 = comp1({}, key + \`__1\`, node, ctx, null); b3 = comp1({}, key + \`__1\`, node, this, null);
} }
return block1([], [b2, b3]); return block1([], [b2, b3]);
} }
@@ -879,7 +879,7 @@ exports[`basics t-if works with t-component 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let b2; let b2;
if (ctx['state'].flag) { if (ctx['state'].flag) {
b2 = comp1({}, key + \`__1\`, node, ctx, null); b2 = comp1({}, key + \`__1\`, node, this, null);
} }
return block1([], [b2]); return block1([], [b2]);
} }
@@ -912,9 +912,9 @@ exports[`basics t-key on a component with t-if, and a sibling component 1`] = `
let b2,b3; let b2,b3;
if (false) { if (false) {
const tKey_1 = 'str'; const tKey_1 = 'str';
b2 = toggler(tKey_1, comp1({}, tKey_1 + key + \`__1\`, node, ctx, null)); b2 = toggler(tKey_1, comp1({}, tKey_1 + key + \`__1\`, node, this, null));
} }
b3 = comp2({}, key + \`__2\`, node, ctx, null); b3 = comp2({}, key + \`__2\`, node, this, null);
return block1([], [b2, b3]); return block1([], [b2, b3]);
} }
}" }"
@@ -944,7 +944,7 @@ exports[`basics text after a conditional component 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let b2; let b2;
if (ctx['state'].hasChild) { if (ctx['state'].hasChild) {
b2 = comp1({}, key + \`__1\`, node, ctx, null); b2 = comp1({}, key + \`__1\`, node, this, null);
} }
let txt1 = ctx['state'].text; let txt1 = ctx['state'].text;
return block1([txt1], [b2]); return block1([txt1], [b2]);
@@ -972,7 +972,7 @@ exports[`basics three level of components with collapsing root nodes 1`] = `
const comp1 = app.createComponent(\`Child\`, true, false, false, true); const comp1 = app.createComponent(\`Child\`, true, false, false, true);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({}, key + \`__1\`, node, ctx, null); return comp1({}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -984,7 +984,7 @@ exports[`basics three level of components with collapsing root nodes 2`] = `
const comp1 = app.createComponent(\`GrandChild\`, true, false, false, true); const comp1 = app.createComponent(\`GrandChild\`, true, false, false, true);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({}, key + \`__1\`, node, ctx, null); return comp1({}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -1010,8 +1010,8 @@ exports[`basics two child components 1`] = `
const comp2 = app.createComponent(\`Child\`, true, false, false, true); const comp2 = app.createComponent(\`Child\`, true, false, false, true);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const b2 = comp1({}, key + \`__1\`, node, ctx, null); const b2 = comp1({}, key + \`__1\`, node, this, null);
const b3 = comp2({}, key + \`__2\`, node, ctx, null); const b3 = comp2({}, key + \`__2\`, node, this, null);
return multi([b2, b3]); return multi([b2, b3]);
} }
}" }"
@@ -1040,7 +1040,7 @@ exports[`basics update props of component without concrete own node 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const tKey_1 = ctx['childProps'].key; const tKey_1 = ctx['childProps'].key;
const b2 = toggler(tKey_1, comp1(Object.assign({}, ctx['childProps']), tKey_1 + key + \`__1\`, node, ctx, null)); const b2 = toggler(tKey_1, comp1(Object.assign({}, ctx['childProps']), tKey_1 + key + \`__1\`, node, this, null));
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -1054,7 +1054,7 @@ exports[`basics update props of component without concrete own node 2`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const tKey_1 = ctx['props'].subKey; const tKey_1 = ctx['props'].subKey;
return toggler(tKey_1, comp1({key: ctx['props'].key,subKey: ctx['props'].subKey}, tKey_1 + key + \`__1\`, node, ctx, null)); return toggler(tKey_1, comp1({key: ctx['props'].key,subKey: ctx['props'].subKey}, tKey_1 + key + \`__1\`, node, this, null));
} }
}" }"
`; `;
@@ -1100,7 +1100,7 @@ exports[`basics updating widget immediately 1`] = `
const comp1 = app.createComponent(\`Child\`, true, false, false, false); const comp1 = app.createComponent(\`Child\`, true, false, false, false);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({flag: ctx['state'].flag}, key + \`__1\`, node, ctx, null); return comp1({flag: ctx['state'].flag}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -1142,7 +1142,7 @@ exports[`basics widget after a t-foreach 1`] = `
} }
ctx = ctx.__proto__; ctx = ctx.__proto__;
const b2 = list(c_block2); const b2 = list(c_block2);
const b4 = comp1({}, key + \`__1\`, node, ctx, null); const b4 = comp1({}, key + \`__1\`, node, this, null);
return block1([], [b2, b4]); return block1([], [b2, b4]);
} }
}" }"
@@ -1170,7 +1170,7 @@ exports[`basics zero or one child components 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let b2; let b2;
if (ctx['state'].hasChild) { if (ctx['state'].hasChild) {
b2 = comp1({}, key + \`__1\`, node, ctx, null); b2 = comp1({}, key + \`__1\`, node, this, null);
} }
return multi([b2]); return multi([b2]);
} }
@@ -1251,7 +1251,7 @@ exports[`support svg components add proper namespace to svg 1`] = `
let block1 = createBlock(\`<svg block-ns=\\"http://www.w3.org/2000/svg\\"><block-child-0/></svg>\`); let block1 = createBlock(\`<svg block-ns=\\"http://www.w3.org/2000/svg\\"><block-child-0/></svg>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const b2 = comp1({}, key + \`__1\`, node, ctx, null); const b2 = comp1({}, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -1308,6 +1308,18 @@ exports[`t-out in components can switch the contents of two t-out repeatedly 1`]
}" }"
`; `;
exports[`t-out in components t-out and updating falsy values, 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let { safeOutput } = helpers;
return function template(ctx, node, key = \\"\\") {
return safeOutput(ctx['state'].a);
}
}"
`;
exports[`t-out in components update properly on state changes 1`] = ` exports[`t-out in components update properly on state changes 1`] = `
"function anonymous(app, bdom, helpers "function anonymous(app, bdom, helpers
) { ) {
@@ -8,7 +8,7 @@ exports[`Cascading renders after microtaskTick 1`] = `
const comp1 = app.createComponent(\`Child\`, true, false, false, true); const comp1 = app.createComponent(\`Child\`, true, false, false, true);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const b2 = comp1({}, key + \`__1\`, node, ctx, null); const b2 = comp1({}, key + \`__1\`, node, this, null);
const b3 = text(\` _ \`); const b3 = text(\` _ \`);
ctx = Object.create(ctx); ctx = Object.create(ctx);
const [k_block4, v_block4, l_block4, c_block4] = prepareList(ctx['state']);; const [k_block4, v_block4, l_block4, c_block4] = prepareList(ctx['state']);;
@@ -36,7 +36,7 @@ exports[`Cascading renders after microtaskTick 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];
const key1 = ctx['elem'].id; const key1 = ctx['elem'].id;
c_block1[i1] = withKey(comp1({id: ctx['elem'].id}, key + \`__1__\${key1}\`, node, ctx, null), key1); c_block1[i1] = withKey(comp1({id: ctx['elem'].id}, key + \`__1__\${key1}\`, node, this, null), key1);
} }
return list(c_block1); return list(c_block1);
} }
@@ -64,7 +64,7 @@ exports[`another scenario with delayed rendering 1`] = `
let b2,b3; let b2,b3;
b2 = text(\`A\`); b2 = text(\`A\`);
if (ctx['state'].value<15) { if (ctx['state'].value<15) {
b3 = comp1({value: ctx['state'].value}, key + \`__1\`, node, ctx, null); b3 = comp1({value: ctx['state'].value}, key + \`__1\`, node, this, null);
} }
return multi([b2, b3]); return multi([b2, b3]);
} }
@@ -79,7 +79,7 @@ exports[`another scenario with delayed rendering 2`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const b2 = text(ctx['props'].value); const b2 = text(ctx['props'].value);
const b3 = comp1({}, key + \`__1\`, node, ctx, null); const b3 = comp1({}, key + \`__1\`, node, this, null);
return multi([b2, b3]); return multi([b2, b3]);
} }
}" }"
@@ -121,7 +121,7 @@ exports[`calling render in destroy 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const tKey_1 = ctx['key']; const tKey_1 = ctx['key'];
return toggler(tKey_1, comp1({fromA: ctx['state']}, tKey_1 + key + \`__1\`, node, ctx, null)); return toggler(tKey_1, comp1({fromA: ctx['state']}, tKey_1 + key + \`__1\`, node, this, null));
} }
}" }"
`; `;
@@ -133,7 +133,7 @@ exports[`calling render in destroy 2`] = `
const comp1 = app.createComponent(\`C\`, true, false, false, false); const comp1 = app.createComponent(\`C\`, true, false, false, false);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({fromA: ctx['props'].fromA}, key + \`__1\`, node, ctx, null); return comp1({fromA: ctx['props'].fromA}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -177,7 +177,7 @@ exports[`changing state before first render does not trigger a render (with pare
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let b2; let b2;
if (ctx['state'].flag) { if (ctx['state'].flag) {
b2 = comp1({}, key + \`__1\`, node, ctx, null); b2 = comp1({}, key + \`__1\`, node, this, null);
} }
return block1([], [b2]); return block1([], [b2]);
} }
@@ -221,7 +221,7 @@ exports[`concurrent renderings scenario 1 1`] = `
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 = \\"\\") {
const b2 = comp1({fromA: ctx['state'].fromA}, key + \`__1\`, node, ctx, null); const b2 = comp1({fromA: ctx['state'].fromA}, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -236,7 +236,7 @@ exports[`concurrent renderings scenario 1 2`] = `
let block1 = createBlock(\`<p><block-child-0/></p>\`); let block1 = createBlock(\`<p><block-child-0/></p>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const b2 = comp1({fromA: ctx['props'].fromA,fromB: ctx['state'].fromB}, key + \`__1\`, node, ctx, null); const b2 = comp1({fromA: ctx['props'].fromA,fromB: ctx['state'].fromB}, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -267,7 +267,7 @@ exports[`concurrent renderings scenario 2 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let txt1 = ctx['state'].fromA; let txt1 = ctx['state'].fromA;
const b2 = comp1({fromA: ctx['state'].fromA}, key + \`__1\`, node, ctx, null); const b2 = comp1({fromA: ctx['state'].fromA}, key + \`__1\`, node, this, null);
return block1([txt1], [b2]); return block1([txt1], [b2]);
} }
}" }"
@@ -282,7 +282,7 @@ exports[`concurrent renderings scenario 2 2`] = `
let block1 = createBlock(\`<p><block-child-0/></p>\`); let block1 = createBlock(\`<p><block-child-0/></p>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const b2 = comp1({fromA: ctx['props'].fromA,fromB: ctx['state'].fromB}, key + \`__1\`, node, ctx, null); const b2 = comp1({fromA: ctx['props'].fromA,fromB: ctx['state'].fromB}, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -312,7 +312,7 @@ exports[`concurrent renderings scenario 2bis 1`] = `
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 = \\"\\") {
const b2 = comp1({fromA: ctx['state'].fromA}, key + \`__1\`, node, ctx, null); const b2 = comp1({fromA: ctx['state'].fromA}, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -327,7 +327,7 @@ exports[`concurrent renderings scenario 2bis 2`] = `
let block1 = createBlock(\`<p><block-child-0/></p>\`); let block1 = createBlock(\`<p><block-child-0/></p>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const b2 = comp1({fromA: ctx['props'].fromA,fromB: ctx['state'].fromB}, key + \`__1\`, node, ctx, null); const b2 = comp1({fromA: ctx['props'].fromA,fromB: ctx['state'].fromB}, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -357,7 +357,7 @@ exports[`concurrent renderings scenario 3 1`] = `
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 = \\"\\") {
const b2 = comp1({fromA: ctx['state'].fromA}, key + \`__1\`, node, ctx, null); const b2 = comp1({fromA: ctx['state'].fromA}, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -372,7 +372,7 @@ exports[`concurrent renderings scenario 3 2`] = `
let block1 = createBlock(\`<p><block-child-0/></p>\`); let block1 = createBlock(\`<p><block-child-0/></p>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const b2 = comp1({fromA: ctx['props'].fromA}, key + \`__1\`, node, ctx, null); const b2 = comp1({fromA: ctx['props'].fromA}, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -387,7 +387,7 @@ exports[`concurrent renderings scenario 3 3`] = `
let block1 = createBlock(\`<span><block-child-0/></span>\`); let block1 = createBlock(\`<span><block-child-0/></span>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const b2 = comp1({fromA: ctx['props'].fromA,fromC: ctx['state'].fromC}, key + \`__1\`, node, ctx, null); const b2 = comp1({fromA: ctx['props'].fromA,fromC: ctx['state'].fromC}, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -417,7 +417,7 @@ exports[`concurrent renderings scenario 4 1`] = `
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 = \\"\\") {
const b2 = comp1({fromA: ctx['state'].fromA}, key + \`__1\`, node, ctx, null); const b2 = comp1({fromA: ctx['state'].fromA}, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -432,7 +432,7 @@ exports[`concurrent renderings scenario 4 2`] = `
let block1 = createBlock(\`<p><block-child-0/></p>\`); let block1 = createBlock(\`<p><block-child-0/></p>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const b2 = comp1({fromA: ctx['props'].fromA}, key + \`__1\`, node, ctx, null); const b2 = comp1({fromA: ctx['props'].fromA}, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -447,7 +447,7 @@ exports[`concurrent renderings scenario 4 3`] = `
let block1 = createBlock(\`<span><block-child-0/></span>\`); let block1 = createBlock(\`<span><block-child-0/></span>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const b2 = comp1({fromA: ctx['props'].fromA,fromC: ctx['state'].fromC}, key + \`__1\`, node, ctx, null); const b2 = comp1({fromA: ctx['props'].fromA,fromC: ctx['state'].fromC}, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -477,7 +477,7 @@ exports[`concurrent renderings scenario 5 1`] = `
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 = \\"\\") {
const b2 = comp1({fromA: ctx['state'].fromA}, key + \`__1\`, node, ctx, null); const b2 = comp1({fromA: ctx['state'].fromA}, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -506,7 +506,7 @@ exports[`concurrent renderings scenario 6 1`] = `
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 = \\"\\") {
const b2 = comp1({fromA: ctx['state'].fromA}, key + \`__1\`, node, ctx, null); const b2 = comp1({fromA: ctx['state'].fromA}, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -535,7 +535,7 @@ exports[`concurrent renderings scenario 7 1`] = `
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 = \\"\\") {
const b2 = comp1({fromA: ctx['state'].fromA}, key + \`__1\`, node, ctx, null); const b2 = comp1({fromA: ctx['state'].fromA}, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -565,7 +565,7 @@ exports[`concurrent renderings scenario 8 1`] = `
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 = \\"\\") {
const b2 = comp1({fromA: ctx['state'].fromA}, key + \`__1\`, node, ctx, null); const b2 = comp1({fromA: ctx['state'].fromA}, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -597,8 +597,8 @@ exports[`concurrent renderings scenario 9 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let txt1 = ctx['state'].fromA; let txt1 = ctx['state'].fromA;
const b2 = comp1({fromA: ctx['state'].fromA}, key + \`__1\`, node, ctx, null); const b2 = comp1({fromA: ctx['state'].fromA}, key + \`__1\`, node, this, null);
const b3 = comp2({fromA: ctx['state'].fromA}, key + \`__2\`, node, ctx, null); const b3 = comp2({fromA: ctx['state'].fromA}, key + \`__2\`, node, this, null);
return block1([txt1], [b2, b3]); return block1([txt1], [b2, b3]);
} }
}" }"
@@ -627,7 +627,7 @@ exports[`concurrent renderings scenario 9 3`] = `
let block1 = createBlock(\`<p><block-child-0/></p>\`); let block1 = createBlock(\`<p><block-child-0/></p>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const b2 = comp1({fromA: ctx['props'].fromA,fromC: ctx['state'].fromC}, key + \`__1\`, node, ctx, null); const b2 = comp1({fromA: ctx['props'].fromA,fromC: ctx['state'].fromC}, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -657,7 +657,7 @@ exports[`concurrent renderings scenario 10 1`] = `
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 = \\"\\") {
const b2 = comp1({value: ctx['state'].value}, key + \`__1\`, node, ctx, null); const b2 = comp1({value: ctx['state'].value}, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -674,7 +674,7 @@ exports[`concurrent renderings scenario 10 2`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let b2; let b2;
if (ctx['state'].hasChild) { if (ctx['state'].hasChild) {
b2 = comp1({value: ctx['props'].value}, key + \`__1\`, node, ctx, null); b2 = comp1({value: ctx['props'].value}, key + \`__1\`, node, this, null);
} }
return block1([], [b2]); return block1([], [b2]);
} }
@@ -704,7 +704,7 @@ exports[`concurrent renderings scenario 11 1`] = `
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 = \\"\\") {
const b2 = comp1({val: ctx['state'].valA}, key + \`__1\`, node, ctx, null); const b2 = comp1({val: ctx['state'].valA}, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -734,7 +734,7 @@ exports[`concurrent renderings scenario 12 1`] = `
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 = \\"\\") {
const b2 = comp1({val: ctx['val']}, key + \`__1\`, node, ctx, null); const b2 = comp1({val: ctx['val']}, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -765,9 +765,9 @@ exports[`concurrent renderings scenario 13 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let b2,b3; let b2,b3;
b2 = comp1({}, key + \`__1\`, node, ctx, null); b2 = comp1({}, key + \`__1\`, node, this, null);
if (ctx['state'].bool) { if (ctx['state'].bool) {
b3 = comp2({}, key + \`__2\`, node, ctx, null); b3 = comp2({}, key + \`__2\`, node, this, null);
} }
return block1([], [b2, b3]); return block1([], [b2, b3]);
} }
@@ -797,7 +797,7 @@ exports[`concurrent renderings scenario 14 1`] = `
let block1 = createBlock(\`<p><block-child-0/></p>\`); let block1 = createBlock(\`<p><block-child-0/></p>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const b2 = comp1({fromA: ctx['state'].fromA}, key + \`__1\`, node, ctx, null); const b2 = comp1({fromA: ctx['state'].fromA}, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -812,7 +812,7 @@ exports[`concurrent renderings scenario 14 2`] = `
let block1 = createBlock(\`<p><block-child-0/></p>\`); let block1 = createBlock(\`<p><block-child-0/></p>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const b2 = comp1({fromB: ctx['state'].fromB,fromA: ctx['props'].fromA}, key + \`__1\`, node, ctx, null); const b2 = comp1({fromB: ctx['state'].fromB,fromA: ctx['props'].fromA}, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -843,7 +843,7 @@ exports[`concurrent renderings scenario 15 1`] = `
let block1 = createBlock(\`<p><block-child-0/></p>\`); let block1 = createBlock(\`<p><block-child-0/></p>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const b2 = comp1({fromA: ctx['state'].fromA}, key + \`__1\`, node, ctx, null); const b2 = comp1({fromA: ctx['state'].fromA}, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -858,7 +858,7 @@ exports[`concurrent renderings scenario 15 2`] = `
let block1 = createBlock(\`<p><block-child-0/></p>\`); let block1 = createBlock(\`<p><block-child-0/></p>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const b2 = comp1({fromB: ctx['state'].fromB,fromA: ctx['props'].fromA}, key + \`__1\`, node, ctx, null); const b2 = comp1({fromB: ctx['state'].fromB,fromA: ctx['props'].fromA}, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -887,7 +887,7 @@ exports[`concurrent renderings scenario 16 1`] = `
const comp1 = app.createComponent(\`B\`, true, false, false, false); const comp1 = app.createComponent(\`B\`, true, false, false, false);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({fromA: ctx['state'].fromA}, key + \`__1\`, node, ctx, null); return comp1({fromA: ctx['state'].fromA}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -899,7 +899,7 @@ exports[`concurrent renderings scenario 16 2`] = `
const comp1 = app.createComponent(\`C\`, true, false, false, false); const comp1 = app.createComponent(\`C\`, true, false, false, false);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({fromB: ctx['state'].fromB,fromA: ctx['props'].fromA}, key + \`__1\`, node, ctx, null); return comp1({fromB: ctx['state'].fromB,fromA: ctx['props'].fromA}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -919,7 +919,7 @@ exports[`concurrent renderings scenario 16 3`] = `
b6 = text(ctx['state'].fromC); b6 = text(ctx['state'].fromC);
b7 = text(\`: \`); b7 = text(\`: \`);
if (ctx['state'].fromC===13) { if (ctx['state'].fromC===13) {
b8 = comp1({}, key + \`__1\`, node, ctx, null); b8 = comp1({}, key + \`__1\`, node, this, null);
} }
return multi([b2, b3, b4, b5, b6, b7, b8]); return multi([b2, b3, b4, b5, b6, b7, b8]);
} }
@@ -947,10 +947,10 @@ exports[`creating two async components, scenario 1 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let b2,b3; let b2,b3;
if (ctx['state'].flagA) { if (ctx['state'].flagA) {
b2 = comp1({}, key + \`__1\`, node, ctx, null); b2 = comp1({}, key + \`__1\`, node, this, null);
} }
if (ctx['state'].flagB) { if (ctx['state'].flagB) {
b3 = comp2({}, key + \`__2\`, node, ctx, null); b3 = comp2({}, key + \`__2\`, node, this, null);
} }
return multi([b2, b3]); return multi([b2, b3]);
} }
@@ -995,9 +995,9 @@ exports[`creating two async components, scenario 2 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let b2,b3; let b2,b3;
b2 = comp1({val: ctx['state'].valA}, key + \`__1\`, node, ctx, null); b2 = comp1({val: ctx['state'].valA}, key + \`__1\`, node, this, null);
if (ctx['state'].flagB) { if (ctx['state'].flagB) {
b3 = comp2({val: ctx['state'].valB}, key + \`__2\`, node, ctx, null); b3 = comp2({val: ctx['state'].valB}, key + \`__2\`, node, this, null);
} }
return block1([], [b2, b3]); return block1([], [b2, b3]);
} }
@@ -1043,9 +1043,9 @@ exports[`creating two async components, scenario 3 (patching in the same frame)
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let b2,b3; let b2,b3;
b2 = comp1({val: ctx['state'].valA}, key + \`__1\`, node, ctx, null); b2 = comp1({val: ctx['state'].valA}, key + \`__1\`, node, this, null);
if (ctx['state'].flagB) { if (ctx['state'].flagB) {
b3 = comp2({val: ctx['state'].valB}, key + \`__2\`, node, ctx, null); b3 = comp2({val: ctx['state'].valB}, key + \`__2\`, node, this, null);
} }
return block1([], [b2, b3]); return block1([], [b2, b3]);
} }
@@ -1087,7 +1087,7 @@ exports[`delay willUpdateProps 1`] = `
const comp1 = app.createComponent(\`Child\`, true, false, false, false); const comp1 = app.createComponent(\`Child\`, true, false, false, false);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({value: ctx['state'].value}, key + \`__1\`, node, ctx, null); return comp1({value: ctx['state'].value}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -1113,7 +1113,7 @@ exports[`delay willUpdateProps with rendering grandchild 1`] = `
const comp1 = app.createComponent(\`Parent\`, true, false, false, false); const comp1 = app.createComponent(\`Parent\`, true, false, false, false);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({state: ctx['state']}, key + \`__1\`, node, ctx, null); return comp1({state: ctx['state']}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -1126,8 +1126,8 @@ exports[`delay willUpdateProps with rendering grandchild 2`] = `
const comp2 = app.createComponent(\`ReactiveChild\`, true, false, false, true); const comp2 = app.createComponent(\`ReactiveChild\`, true, false, false, true);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const b2 = comp1({value: ctx['props'].state.value}, key + \`__1\`, node, ctx, null); const b2 = comp1({value: ctx['props'].state.value}, key + \`__1\`, node, this, null);
const b3 = comp2({}, key + \`__2\`, node, ctx, null); const b3 = comp2({}, key + \`__2\`, node, this, null);
return multi([b2, b3]); return multi([b2, b3]);
} }
}" }"
@@ -1168,7 +1168,7 @@ exports[`delayed fiber does not get rendered if it was cancelled 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const b2 = text(\`A\`); const b2 = text(\`A\`);
const b3 = comp1({}, key + \`__1\`, node, ctx, null); const b3 = comp1({}, key + \`__1\`, node, this, null);
return multi([b2, b3]); return multi([b2, b3]);
} }
}" }"
@@ -1182,7 +1182,7 @@ exports[`delayed fiber does not get rendered if it was cancelled 2`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const b2 = text(\`B\`); const b2 = text(\`B\`);
const b3 = comp1({}, key + \`__1\`, node, ctx, null); const b3 = comp1({}, key + \`__1\`, node, this, null);
return multi([b2, b3]); return multi([b2, b3]);
} }
}" }"
@@ -1196,7 +1196,7 @@ exports[`delayed fiber does not get rendered if it was cancelled 3`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const b2 = text(\`C\`); const b2 = text(\`C\`);
const b3 = comp1({}, key + \`__1\`, node, ctx, null); const b3 = comp1({}, key + \`__1\`, node, this, null);
return multi([b2, b3]); return multi([b2, b3]);
} }
}" }"
@@ -1220,7 +1220,7 @@ exports[`delayed rendering, but then initial rendering is cancelled by yet anoth
const comp1 = app.createComponent(\`B\`, true, false, false, false); const comp1 = app.createComponent(\`B\`, true, false, false, false);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({value: ctx['state'].value}, key + \`__1\`, node, ctx, null); return comp1({value: ctx['state'].value}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -1232,7 +1232,7 @@ exports[`delayed rendering, but then initial rendering is cancelled by yet anoth
const comp1 = app.createComponent(\`C\`, true, false, false, false); const comp1 = app.createComponent(\`C\`, true, false, false, false);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({value: ctx['state'].someValue+ctx['props'].value}, key + \`__1\`, node, ctx, null); return comp1({value: ctx['state'].someValue+ctx['props'].value}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -1246,7 +1246,7 @@ exports[`delayed rendering, but then initial rendering is cancelled by yet anoth
let block3 = createBlock(\`<p><block-text-0/></p>\`); let block3 = createBlock(\`<p><block-text-0/></p>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const b2 = comp1({}, key + \`__1\`, node, ctx, null); const b2 = comp1({}, key + \`__1\`, node, this, null);
let txt1 = ctx['props'].value; let txt1 = ctx['props'].value;
const b3 = block3([txt1]); const b3 = block3([txt1]);
return multi([b2, b3]); return multi([b2, b3]);
@@ -1277,7 +1277,7 @@ exports[`delayed rendering, destruction, stuff happens 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const b2 = text(\`A\`); const b2 = text(\`A\`);
const b3 = comp1({value: ctx['state'].value}, key + \`__1\`, node, ctx, null); const b3 = comp1({value: ctx['state'].value}, key + \`__1\`, node, this, null);
return multi([b2, b3]); return multi([b2, b3]);
} }
}" }"
@@ -1293,7 +1293,7 @@ exports[`delayed rendering, destruction, stuff happens 2`] = `
let b2,b3; let b2,b3;
b2 = text(\`B\`); b2 = text(\`B\`);
if (ctx['state'].hasChild) { if (ctx['state'].hasChild) {
b3 = comp1({value: ctx['state'].someValue+ctx['props'].value}, key + \`__1\`, node, ctx, null); b3 = comp1({value: ctx['state'].someValue+ctx['props'].value}, key + \`__1\`, node, this, null);
} }
return multi([b2, b3]); return multi([b2, b3]);
} }
@@ -1310,7 +1310,7 @@ exports[`delayed rendering, destruction, stuff happens 3`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const b2 = text(\`C\`); const b2 = text(\`C\`);
const b3 = comp1({}, key + \`__1\`, node, ctx, null); const b3 = comp1({}, key + \`__1\`, node, this, null);
let txt1 = ctx['props'].value; let txt1 = ctx['props'].value;
const b4 = block4([txt1]); const b4 = block4([txt1]);
return multi([b2, b3, b4]); return multi([b2, b3, b4]);
@@ -1342,7 +1342,7 @@ exports[`delayed rendering, reusing fiber and stuff 1`] = `
const comp1 = app.createComponent(\`B\`, true, false, false, false); const comp1 = app.createComponent(\`B\`, true, false, false, false);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({value: ctx['state'].value}, key + \`__1\`, node, ctx, null); return comp1({value: ctx['state'].value}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -1355,7 +1355,7 @@ exports[`delayed rendering, reusing fiber and stuff 2`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const b2 = text(ctx['props'].value); const b2 = text(ctx['props'].value);
const b3 = comp1({}, key + \`__1\`, node, ctx, null); const b3 = comp1({}, key + \`__1\`, node, this, null);
return multi([b2, b3]); return multi([b2, b3]);
} }
}" }"
@@ -1386,7 +1386,7 @@ exports[`delayed rendering, reusing fiber then component is destroyed and stuff
let b2,b3; let b2,b3;
b2 = text(\`A\`); b2 = text(\`A\`);
if (ctx['state'].value<15) { if (ctx['state'].value<15) {
b3 = comp1({value: ctx['state'].value}, key + \`__1\`, node, ctx, null); b3 = comp1({value: ctx['state'].value}, key + \`__1\`, node, this, null);
} }
return multi([b2, b3]); return multi([b2, b3]);
} }
@@ -1401,7 +1401,7 @@ exports[`delayed rendering, reusing fiber then component is destroyed and stuff
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const b2 = text(ctx['props'].value); const b2 = text(ctx['props'].value);
const b3 = comp1({}, key + \`__1\`, node, ctx, null); const b3 = comp1({}, key + \`__1\`, node, this, null);
return multi([b2, b3]); return multi([b2, b3]);
} }
}" }"
@@ -1429,7 +1429,7 @@ exports[`delayed rendering, then component is destroyed and stuff 1`] = `
const comp1 = app.createComponent(\`B\`, true, false, false, false); const comp1 = app.createComponent(\`B\`, true, false, false, false);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({value: ctx['state'].value}, key + \`__1\`, node, ctx, null); return comp1({value: ctx['state'].value}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -1444,7 +1444,7 @@ exports[`delayed rendering, then component is destroyed and stuff 2`] = `
let b2,b3; let b2,b3;
b2 = text(ctx['props'].value); b2 = text(ctx['props'].value);
if (ctx['props'].value<10) { if (ctx['props'].value<10) {
b3 = comp1({}, key + \`__1\`, node, ctx, null); b3 = comp1({}, key + \`__1\`, node, this, null);
} }
return multi([b2, b3]); return multi([b2, b3]);
} }
@@ -1477,8 +1477,8 @@ exports[`destroyed component causes other soon to be destroyed component to rere
let b2,b3; let b2,b3;
b2 = text(\` A \`); b2 = text(\` A \`);
if (ctx['state'].flag) { if (ctx['state'].flag) {
const b4 = comp1({value: ctx['state'].valueB}, key + \`__1\`, node, ctx, null); const b4 = comp1({value: ctx['state'].valueB}, key + \`__1\`, node, this, null);
const b5 = comp2({value: ctx['state'].valueC}, key + \`__2\`, node, ctx, null); const b5 = comp2({value: ctx['state'].valueC}, key + \`__2\`, node, this, null);
b3 = multi([b4, b5]); b3 = multi([b4, b5]);
} }
return multi([b2, b3]); return multi([b2, b3]);
@@ -1518,7 +1518,7 @@ exports[`destroying/recreating a subcomponent, other scenario 1`] = `
let b2,b3; let b2,b3;
b2 = text(\`parent\`); b2 = text(\`parent\`);
if (ctx['state'].hasChild) { if (ctx['state'].hasChild) {
b3 = comp1({}, key + \`__1\`, node, ctx, null); b3 = comp1({}, key + \`__1\`, node, this, null);
} }
return multi([b2, b3]); return multi([b2, b3]);
} }
@@ -1547,7 +1547,7 @@ exports[`destroying/recreating a subwidget with different props (if start is not
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let b2; let b2;
if (ctx['state'].val>1) { if (ctx['state'].val>1) {
b2 = comp1({val: ctx['state'].val}, key + \`__1\`, node, ctx, null); b2 = comp1({val: ctx['state'].val}, key + \`__1\`, node, this, null);
} }
return block1([], [b2]); return block1([], [b2]);
} }
@@ -1575,7 +1575,7 @@ exports[`parent and child rendered at exact same time 1`] = `
const comp1 = app.createComponent(\`Child\`, true, false, false, false); const comp1 = app.createComponent(\`Child\`, true, false, false, false);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({value: ctx['state'].value}, key + \`__1\`, node, ctx, null); return comp1({value: ctx['state'].value}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -1602,7 +1602,7 @@ exports[`properly behave when destroyed/unmounted while rendering 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let b2; let b2;
if (ctx['state'].flag) { if (ctx['state'].flag) {
b2 = comp1({val: ctx['state'].val}, key + \`__1\`, node, ctx, null); b2 = comp1({val: ctx['state'].val}, key + \`__1\`, node, this, null);
} }
return block1([], [b2]); return block1([], [b2]);
} }
@@ -1618,7 +1618,7 @@ exports[`properly behave when destroyed/unmounted while rendering 2`] = `
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 = \\"\\") {
const b2 = comp1({val: ctx['props'].val}, key + \`__1\`, node, ctx, null); const b2 = comp1({val: ctx['props'].val}, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -1649,7 +1649,7 @@ exports[`rendering component again in next microtick 1`] = `
let b2; let b2;
let hdlr1 = [ctx['onClick'], ctx]; let hdlr1 = [ctx['onClick'], ctx];
if (ctx['env'].config.flag) { if (ctx['env'].config.flag) {
b2 = comp1({}, key + \`__1\`, node, ctx, null); b2 = comp1({}, key + \`__1\`, node, this, null);
} }
return block1([hdlr1], [b2]); return block1([hdlr1], [b2]);
} }
@@ -1676,7 +1676,7 @@ exports[`rendering parent twice, with different props on child and stuff 1`] = `
const comp1 = app.createComponent(\`Child\`, true, false, false, false); const comp1 = app.createComponent(\`Child\`, true, false, false, false);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({value: ctx['state'].value}, key + \`__1\`, node, ctx, null); return comp1({value: ctx['state'].value}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -1701,8 +1701,8 @@ exports[`renderings, destruction, patch, stuff, ... yet another variation 1`] =
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const b2 = text(\`A\`); const b2 = text(\`A\`);
const b3 = comp1({value: ctx['state'].value}, key + \`__1\`, node, ctx, null); const b3 = comp1({value: ctx['state'].value}, key + \`__1\`, node, this, null);
const b4 = comp2({}, key + \`__2\`, node, ctx, null); const b4 = comp2({}, key + \`__2\`, node, this, null);
return multi([b2, b3, b4]); return multi([b2, b3, b4]);
} }
}" }"
@@ -1718,7 +1718,7 @@ exports[`renderings, destruction, patch, stuff, ... yet another variation 2`] =
let b2,b3; let b2,b3;
b2 = text(\`B\`); b2 = text(\`B\`);
if (ctx['props'].value===33) { if (ctx['props'].value===33) {
b3 = comp1({}, key + \`__1\`, node, ctx, null); b3 = comp1({}, key + \`__1\`, node, this, null);
} }
return multi([b2, b3]); return multi([b2, b3]);
} }
@@ -1776,7 +1776,7 @@ exports[`t-foreach with dynamic async component 1`] = `
let b3; let b3;
if (ctx['arr']) { if (ctx['arr']) {
const Comp1 = ctx['myComp']; const Comp1 = ctx['myComp'];
b3 = toggler(Comp1, comp1({key: ctx['arr'][0]}, key + \`__1__\${key1}\`, node, ctx, Comp1)); b3 = toggler(Comp1, comp1({key: ctx['arr'][0]}, key + \`__1__\${key1}\`, node, this, Comp1));
} }
c_block1[i1] = withKey(multi([b3]), key1); c_block1[i1] = withKey(multi([b3]), key1);
} }
@@ -1810,7 +1810,7 @@ exports[`t-key on dom node having a component 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const tKey_1 = ctx['key']; const tKey_1 = ctx['key'];
const Comp1 = ctx['myComp']; const Comp1 = ctx['myComp'];
const b2 = toggler(tKey_1, toggler(Comp1, comp1({key: ctx['key']}, tKey_1 + key + \`__1\`, node, ctx, Comp1))); const b2 = toggler(tKey_1, toggler(Comp1, comp1({key: ctx['key']}, tKey_1 + key + \`__1\`, node, this, Comp1)));
return toggler(tKey_1, block1([], [b2])); return toggler(tKey_1, block1([], [b2]));
} }
}" }"
@@ -1836,7 +1836,7 @@ exports[`t-key on dynamic async component (toggler is never patched) 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const tKey_1 = ctx['key']; const tKey_1 = ctx['key'];
const Comp1 = ctx['myComp']; const Comp1 = ctx['myComp'];
return toggler(tKey_1, toggler(Comp1, comp1({key: ctx['key']}, tKey_1 + key + \`__1\`, node, ctx, Comp1))); return toggler(tKey_1, toggler(Comp1, comp1({key: ctx['key']}, tKey_1 + key + \`__1\`, node, this, Comp1)));
} }
}" }"
`; `;
@@ -1867,7 +1867,7 @@ exports[`two renderings initiated between willPatch and patched 1`] = `
let b2; let b2;
if (ctx['state'].flag) { if (ctx['state'].flag) {
const tKey_1 = 'panel_'+ctx['state'].panel; const tKey_1 = 'panel_'+ctx['state'].panel;
b2 = toggler(tKey_1, comp1({val: ctx['state'].panel}, tKey_1 + key + \`__1\`, node, ctx, null)); b2 = toggler(tKey_1, comp1({val: ctx['state'].panel}, tKey_1 + key + \`__1\`, node, this, null));
} }
return block1([], [b2]); return block1([], [b2]);
} }
@@ -1896,7 +1896,7 @@ exports[`two sequential renderings before an animation frame 1`] = `
const comp1 = app.createComponent(\`Child\`, true, false, false, false); const comp1 = app.createComponent(\`Child\`, true, false, false, false);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({value: ctx['state'].value}, key + \`__1\`, node, ctx, null); return comp1({value: ctx['state'].value}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -1921,7 +1921,7 @@ exports[`update a sub-component twice in the same frame 1`] = `
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 = \\"\\") {
const b2 = comp1({val: ctx['state'].valA}, key + \`__1\`, node, ctx, null); const b2 = comp1({val: ctx['state'].valA}, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -1950,7 +1950,7 @@ exports[`update a sub-component twice in the same frame, 2 1`] = `
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 = \\"\\") {
const b2 = comp1({val: ctx['state'].valA}, key + \`__1\`, node, ctx, null); const b2 = comp1({val: ctx['state'].valA}, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -7,7 +7,7 @@ exports[`basics display a nice error if a component is not a component 1`] = `
const comp1 = app.createComponent(\`SomeComponent\`, true, false, false, true); const comp1 = app.createComponent(\`SomeComponent\`, true, false, false, true);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({}, key + \`__1\`, node, ctx, null); return comp1({}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -20,8 +20,8 @@ exports[`basics display a nice error if it cannot find component (in dev mode) 1
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {}; const props1 = {};
helpers.validateProps(\`SomeMispelledComponent\`, props1, ctx); helpers.validateProps(\`SomeMispelledComponent\`, props1, this);
return comp1(props1, key + \`__1\`, node, ctx, null); return comp1(props1, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -33,7 +33,7 @@ exports[`basics display a nice error if it cannot find component 1`] = `
const comp1 = app.createComponent(\`SomeMispelledComponent\`, true, false, false, true); const comp1 = app.createComponent(\`SomeMispelledComponent\`, true, false, false, true);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({}, key + \`__1\`, node, ctx, null); return comp1({}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -47,7 +47,7 @@ exports[`basics no component catching error lead to full app destruction 1`] = `
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 = \\"\\") {
const b2 = comp1({flag: ctx['state'].flag}, key + \`__1\`, node, ctx, null); const b2 = comp1({flag: ctx['state'].flag}, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -80,7 +80,7 @@ exports[`basics simple catchError 1`] = `
if (ctx['error']) { if (ctx['error']) {
b2 = text(\`Error\`); b2 = text(\`Error\`);
} else { } else {
b3 = comp1({}, key + \`__1\`, node, ctx, null); b3 = comp1({}, key + \`__1\`, node, this, null);
} }
return block1([], [b2, b3]); return block1([], [b2, b3]);
} }
@@ -101,6 +101,72 @@ exports[`basics simple catchError 2`] = `
}" }"
`; `;
exports[`can catch errors Errors have the right cause 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
return function template(ctx, node, key = \\"\\") {
return text(ctx['state'].value);
}
}"
`;
exports[`can catch errors Errors in owl lifecycle are wrapped in dev mode: async hook 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
return function template(ctx, node, key = \\"\\") {
return text(ctx['state'].value);
}
}"
`;
exports[`can catch errors Errors in owl lifecycle are wrapped out of dev mode: async hook 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
return function template(ctx, node, key = \\"\\") {
return text(ctx['state'].value);
}
}"
`;
exports[`can catch errors Errors in owl lifecycle are wrapped outside dev mode: sync hook 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
return function template(ctx, node, key = \\"\\") {
return text(ctx['state'].value);
}
}"
`;
exports[`can catch errors Thrown values that are not errors are wrapped in dev mode 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
return function template(ctx, node, key = \\"\\") {
return text(ctx['state'].value);
}
}"
`;
exports[`can catch errors Thrown values that are not errors are wrapped outside dev mode 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
return function template(ctx, node, key = \\"\\") {
return text(ctx['state'].value);
}
}"
`;
exports[`can catch errors an error in onWillDestroy 1`] = ` exports[`can catch errors an error in onWillDestroy 1`] = `
"function anonymous(app, bdom, helpers "function anonymous(app, bdom, helpers
) { ) {
@@ -111,7 +177,7 @@ exports[`can catch errors an error in onWillDestroy 1`] = `
let b2,b3; let b2,b3;
b2 = text(ctx['state'].value); b2 = text(ctx['state'].value);
if (ctx['state'].hasChild) { if (ctx['state'].hasChild) {
b3 = comp1({}, key + \`__1\`, node, ctx, null); b3 = comp1({}, key + \`__1\`, node, this, null);
} }
return multi([b2, b3]); return multi([b2, b3]);
} }
@@ -141,7 +207,7 @@ exports[`can catch errors an error in onWillDestroy, variation 1`] = `
let b2,b3; let b2,b3;
b2 = text(ctx['state'].value); b2 = text(ctx['state'].value);
if (ctx['state'].hasChild) { if (ctx['state'].hasChild) {
b3 = comp1({}, key + \`__1\`, node, ctx, null); b3 = comp1({}, key + \`__1\`, node, this, null);
} }
return multi([b2, b3]); return multi([b2, b3]);
} }
@@ -183,11 +249,11 @@ exports[`can catch errors can catch an error in a component render function 1`]
let block1 = createBlock(\`<div><block-child-0/></div>\`); let block1 = createBlock(\`<div><block-child-0/></div>\`);
function slot1(ctx, node, key = \\"\\") { function slot1(ctx, node, key = \\"\\") {
return comp1({flag: ctx['state'].flag}, key + \`__1\`, node, ctx, null); return comp1({flag: ctx['state'].flag}, key + \`__1\`, node, this, null);
} }
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const b3 = comp2({slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__2\`, node, ctx, null); const b3 = comp2({slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__2\`, node, this, null);
return block1([], [b3]); return block1([], [b3]);
} }
}" }"
@@ -238,11 +304,11 @@ exports[`can catch errors can catch an error in the constructor call of a compon
let block1 = createBlock(\`<div><block-child-0/></div>\`); let block1 = createBlock(\`<div><block-child-0/></div>\`);
function slot1(ctx, node, key = \\"\\") { function slot1(ctx, node, key = \\"\\") {
return comp1({}, key + \`__1\`, node, ctx, null); return comp1({}, key + \`__1\`, node, this, null);
} }
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const b3 = comp2({slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__2\`, node, ctx, null); const b3 = comp2({slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__2\`, node, this, null);
return block1([], [b3]); return block1([], [b3]);
} }
}" }"
@@ -280,13 +346,13 @@ exports[`can catch errors can catch an error in the constructor call of a compon
let block1 = createBlock(\`<div><block-child-0/></div>\`); let block1 = createBlock(\`<div><block-child-0/></div>\`);
function slot1(ctx, node, key = \\"\\") { function slot1(ctx, node, key = \\"\\") {
const b3 = comp1({}, key + \`__1\`, node, ctx, null); const b3 = comp1({}, key + \`__1\`, node, this, null);
const b4 = comp2({}, key + \`__2\`, node, ctx, null); const b4 = comp2({}, key + \`__2\`, node, this, null);
return multi([b3, b4]); return multi([b3, b4]);
} }
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const b5 = comp3({slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__3\`, node, ctx, null); const b5 = comp3({slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__3\`, node, this, null);
return block1([], [b5]); return block1([], [b5]);
} }
}" }"
@@ -362,11 +428,11 @@ exports[`can catch errors can catch an error in the initial call of a component
let block1 = createBlock(\`<div><block-child-0/></div>\`); let block1 = createBlock(\`<div><block-child-0/></div>\`);
function slot1(ctx, node, key = \\"\\") { function slot1(ctx, node, key = \\"\\") {
return comp1({}, key + \`__1\`, node, ctx, null); return comp1({}, key + \`__1\`, node, this, null);
} }
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const b3 = comp2({slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__2\`, node, ctx, null); const b3 = comp2({slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__2\`, node, this, null);
return block1([], [b3]); return block1([], [b3]);
} }
}" }"
@@ -417,13 +483,13 @@ exports[`can catch errors can catch an error in the initial call of a component
let block1 = createBlock(\`<div><block-child-0/></div>\`); let block1 = createBlock(\`<div><block-child-0/></div>\`);
function slot1(ctx, node, key = \\"\\") { function slot1(ctx, node, key = \\"\\") {
return comp1({}, key + \`__1\`, node, ctx, null); return comp1({}, key + \`__1\`, node, this, null);
} }
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let b3; let b3;
if (ctx['state'].flag) { if (ctx['state'].flag) {
b3 = comp2({slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__2\`, node, ctx, null); b3 = comp2({slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__2\`, node, this, null);
} }
return block1([], [b3]); return block1([], [b3]);
} }
@@ -471,7 +537,7 @@ exports[`can catch errors can catch an error in the mounted call (in child of ch
const comp1 = app.createComponent(\`B\`, true, false, false, true); const comp1 = app.createComponent(\`B\`, true, false, false, true);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({}, key + \`__1\`, node, ctx, null); return comp1({}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -485,7 +551,7 @@ exports[`can catch errors can catch an error in the mounted call (in child of ch
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 = \\"\\") {
const b2 = comp1({}, key + \`__1\`, node, ctx, null); const b2 = comp1({}, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -504,7 +570,7 @@ exports[`can catch errors can catch an error in the mounted call (in child of ch
if (ctx['state'].error) { if (ctx['state'].error) {
b2 = text(\`Error handled\`); b2 = text(\`Error handled\`);
} else { } else {
b3 = comp1({}, key + \`__1\`, node, ctx, null); b3 = comp1({}, key + \`__1\`, node, this, null);
} }
return block1([], [b2, b3]); return block1([], [b2, b3]);
} }
@@ -537,7 +603,7 @@ exports[`can catch errors can catch an error in the mounted call (in root compon
if (ctx['state'].error) { if (ctx['state'].error) {
b2 = text(\`Error handled\`); b2 = text(\`Error handled\`);
} else { } else {
b3 = comp1({}, key + \`__1\`, node, ctx, null); b3 = comp1({}, key + \`__1\`, node, this, null);
} }
return block1([], [b2, b3]); return block1([], [b2, b3]);
} }
@@ -568,11 +634,11 @@ exports[`can catch errors can catch an error in the mounted call 1`] = `
let block1 = createBlock(\`<div><block-child-0/></div>\`); let block1 = createBlock(\`<div><block-child-0/></div>\`);
function slot1(ctx, node, key = \\"\\") { function slot1(ctx, node, key = \\"\\") {
return comp1({}, key + \`__1\`, node, ctx, null); return comp1({}, key + \`__1\`, node, this, null);
} }
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const b3 = comp2({slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__2\`, node, ctx, null); const b3 = comp2({slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__2\`, node, this, null);
return block1([], [b3]); return block1([], [b3]);
} }
}" }"
@@ -622,12 +688,12 @@ exports[`can catch errors can catch an error in the willPatch call 1`] = `
let block1 = createBlock(\`<div><span><block-text-0/></span><block-child-0/></div>\`); let block1 = createBlock(\`<div><span><block-text-0/></span><block-child-0/></div>\`);
function slot1(ctx, node, key = \\"\\") { function slot1(ctx, node, key = \\"\\") {
return comp1({message: ctx['state'].message}, key + \`__1\`, node, ctx, null); return comp1({message: ctx['state'].message}, key + \`__1\`, node, this, null);
} }
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let txt1 = ctx['state'].message; let txt1 = ctx['state'].message;
const b3 = comp2({slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__2\`, node, ctx, null); const b3 = comp2({slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__2\`, node, this, null);
return block1([txt1], [b3]); return block1([txt1], [b3]);
} }
}" }"
@@ -678,11 +744,11 @@ exports[`can catch errors can catch an error in the willStart call 1`] = `
let block1 = createBlock(\`<div><block-child-0/></div>\`); let block1 = createBlock(\`<div><block-child-0/></div>\`);
function slot1(ctx, node, key = \\"\\") { function slot1(ctx, node, key = \\"\\") {
return comp1({}, key + \`__1\`, node, ctx, null); return comp1({}, key + \`__1\`, node, this, null);
} }
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const b3 = comp2({slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__2\`, node, ctx, null); const b3 = comp2({slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__2\`, node, this, null);
return block1([], [b3]); return block1([], [b3]);
} }
}" }"
@@ -733,13 +799,13 @@ exports[`can catch errors can catch an error origination from a child's willStar
let block1 = createBlock(\`<div><block-child-0/></div>\`); let block1 = createBlock(\`<div><block-child-0/></div>\`);
function slot1(ctx, node, key = \\"\\") { function slot1(ctx, node, key = \\"\\") {
const b3 = comp1({}, key + \`__1\`, node, ctx, null); const b3 = comp1({}, key + \`__1\`, node, this, null);
const b4 = comp2({}, key + \`__2\`, node, ctx, null); const b4 = comp2({}, key + \`__2\`, node, this, null);
return multi([b3, b4]); return multi([b3, b4]);
} }
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const b5 = comp3({slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__3\`, node, ctx, null); const b5 = comp3({slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__3\`, node, this, null);
return block1([], [b5]); return block1([], [b5]);
} }
}" }"
@@ -804,7 +870,7 @@ exports[`can catch errors catchError in catchError 1`] = `
if (ctx['error']) { if (ctx['error']) {
b2 = text(\`Error\`); b2 = text(\`Error\`);
} else { } else {
b3 = comp1({}, key + \`__1\`, node, ctx, null); b3 = comp1({}, key + \`__1\`, node, this, null);
} }
return block1([], [b2, b3]); return block1([], [b2, b3]);
} }
@@ -820,7 +886,7 @@ exports[`can catch errors catchError in catchError 2`] = `
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 = \\"\\") {
const b2 = comp1({}, key + \`__1\`, node, ctx, null); const b2 = comp1({}, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -850,7 +916,7 @@ exports[`can catch errors catching error, rethrow, render parent -- a main comp
function slot1(ctx, node, key = \\"\\") { function slot1(ctx, node, key = \\"\\") {
const Comp1 = ctx['cp'].Comp; const Comp1 = ctx['cp'].Comp;
return toggler(Comp1, comp1({}, key + \`__1\`, node, ctx, Comp1)); return toggler(Comp1, comp1({}, key + \`__1\`, node, this, Comp1));
} }
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
@@ -861,7 +927,7 @@ exports[`can catch errors catching error, rethrow, render parent -- a main comp
const key1 = ctx['cp'].id; const key1 = ctx['cp'].id;
const v1 = ctx['cp']; const v1 = ctx['cp'];
const ctx1 = capture(ctx); const ctx1 = capture(ctx);
c_block1[i1] = withKey(comp2({onError: ()=>this.cleanUp(v1.id),slots: markRaw({'default': {__render: slot1, __ctx: ctx1}})}, key + \`__2__\${key1}\`, node, ctx, null), key1); c_block1[i1] = withKey(comp2({onError: ()=>this.cleanUp(v1.id),slots: markRaw({'default': {__render: slot1, __ctx: ctx1}})}, key + \`__2__\${key1}\`, node, this, null), key1);
} }
return list(c_block1); return list(c_block1);
} }
@@ -887,7 +953,7 @@ exports[`can catch errors catching error, rethrow, render parent -- a main comp
const comp1 = app.createComponent(\`ErrorComponent\`, true, false, false, true); const comp1 = app.createComponent(\`ErrorComponent\`, true, false, false, true);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({}, key + \`__1\`, node, ctx, null); return comp1({}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -928,7 +994,7 @@ exports[`can catch errors catching in child makes parent render 1`] = `
function slot1(ctx, node, key = \\"\\") { function slot1(ctx, node, key = \\"\\") {
const Comp1 = ctx['elem'][1]; const Comp1 = ctx['elem'][1];
return toggler(Comp1, comp1({id: ctx['elem'][0]}, key + \`__1\`, node, ctx, Comp1)); return toggler(Comp1, comp1({id: ctx['elem'][0]}, key + \`__1\`, node, this, Comp1));
} }
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
@@ -939,7 +1005,7 @@ exports[`can catch errors catching in child makes parent render 1`] = `
const key1 = ctx['elem'][0]; const key1 = ctx['elem'][0];
const v1 = ctx['elem']; const v1 = ctx['elem'];
const ctx1 = capture(ctx); const ctx1 = capture(ctx);
c_block1[i1] = withKey(comp2({onError: (_error)=>this.onError(v1[0],_error),slots: markRaw({'default': {__render: slot1, __ctx: ctx1}})}, key + \`__2__\${key1}\`, node, ctx, null), key1); c_block1[i1] = withKey(comp2({onError: (_error)=>this.onError(v1[0],_error),slots: markRaw({'default': {__render: slot1, __ctx: ctx1}})}, key + \`__2__\${key1}\`, node, this, null), key1);
} }
return list(c_block1); return list(c_block1);
} }
@@ -997,12 +1063,12 @@ exports[`can catch errors error in mounted on a component with a sibling (proper
let block1 = createBlock(\`<div><block-child-0/><block-child-1/></div>\`); let block1 = createBlock(\`<div><block-child-0/><block-child-1/></div>\`);
function slot1(ctx, node, key = \\"\\") { function slot1(ctx, node, key = \\"\\") {
return comp2({}, key + \`__2\`, node, ctx, null); return comp2({}, key + \`__2\`, node, this, null);
} }
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const b2 = comp1({}, key + \`__1\`, node, ctx, null); const b2 = comp1({}, key + \`__1\`, node, this, null);
const b4 = comp3({slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__3\`, node, ctx, null); const b4 = comp3({slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__3\`, node, this, null);
return block1([], [b2, b4]); return block1([], [b2, b4]);
} }
}" }"
@@ -1059,7 +1125,7 @@ exports[`can catch errors onError in class inheritance is called if rethrown 1`]
const comp1 = app.createComponent(\`Concrete\`, true, false, false, true); const comp1 = app.createComponent(\`Concrete\`, true, false, false, true);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({}, key + \`__1\`, node, ctx, null); return comp1({}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -1090,7 +1156,7 @@ exports[`can catch errors onError in class inheritance is not called if no rethr
const comp1 = app.createComponent(\`Concrete\`, true, false, false, true); const comp1 = app.createComponent(\`Concrete\`, true, false, false, true);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({}, key + \`__1\`, node, ctx, null); return comp1({}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -1123,7 +1189,7 @@ exports[`errors and promises a rendering error in a sub component will reject th
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 = \\"\\") {
const b2 = comp1({}, key + \`__1\`, node, ctx, null); const b2 = comp1({}, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -1166,7 +1232,7 @@ exports[`errors and promises a rendering error will reject the render promise (w
let block1 = createBlock(\`<div><block-child-0/><block-text-0/></div>\`); let block1 = createBlock(\`<div><block-child-0/><block-text-0/></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const b2 = comp1({}, key + \`__1\`, node, ctx, null); const b2 = comp1({}, key + \`__1\`, node, this, null);
let txt1 = ctx['x'].y; let txt1 = ctx['x'].y;
return block1([txt1], [b2]); return block1([txt1], [b2]);
} }
@@ -1296,3 +1362,16 @@ exports[`errors and promises errors in rerender 1`] = `
} }
}" }"
`; `;
exports[`errors and promises wrapped errors in async code are correctly caught 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let block1 = createBlock(\`<div>abc</div>\`);
return function template(ctx, node, key = \\"\\") {
return block1();
}
}"
`;
@@ -38,7 +38,7 @@ exports[`event handling handler receive the event as argument 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let hdlr1 = [ctx['inc'], ctx]; let hdlr1 = [ctx['inc'], ctx];
const b2 = comp1({}, key + \`__1\`, node, ctx, null); const b2 = comp1({}, key + \`__1\`, node, this, null);
let txt1 = ctx['state'].value; let txt1 = ctx['state'].value;
return block1([hdlr1, txt1], [b2]); return block1([hdlr1, txt1], [b2]);
} }
@@ -58,6 +58,20 @@ exports[`event handling handler receive the event as argument 2`] = `
}" }"
`; `;
exports[`event handling handler works when app is mounted in an iframe 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let block1 = createBlock(\`<span block-handler-0=\\"click\\">click me</span>\`);
return function template(ctx, node, key = \\"\\") {
let hdlr1 = [ctx['inc'], ctx];
return block1([hdlr1]);
}
}"
`;
exports[`event handling input blur event is not called if component is destroyed 1`] = ` exports[`event handling input blur event is not called if component is destroyed 1`] = `
"function anonymous(app, bdom, helpers "function anonymous(app, bdom, helpers
) { ) {
@@ -69,7 +83,7 @@ exports[`event handling input blur event is not called if component is destroyed
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let b2; let b2;
if (ctx['state'].cond) { if (ctx['state'].cond) {
b2 = comp1({}, key + \`__1\`, node, ctx, null); b2 = comp1({}, key + \`__1\`, node, this, null);
} }
return block1([], [b2]); return block1([], [b2]);
} }
@@ -7,7 +7,7 @@ exports[`basics basic use 1`] = `
const comp1 = app.createComponent(\`Child\`, true, false, false, false); const comp1 = app.createComponent(\`Child\`, true, false, false, false);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({p: 1}, key + \`__1\`, node, ctx, null); return comp1({p: 1}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -36,10 +36,10 @@ exports[`basics can select a sub widget 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let b2,b3; let b2,b3;
if (ctx['env'].options.flag) { if (ctx['env'].options.flag) {
b2 = comp1({}, key + \`__1\`, node, ctx, null); b2 = comp1({}, key + \`__1\`, node, this, null);
} }
if (!ctx['env'].options.flag) { if (!ctx['env'].options.flag) {
b3 = comp2({}, key + \`__2\`, node, ctx, null); b3 = comp2({}, key + \`__2\`, node, this, null);
} }
return multi([b2, b3]); return multi([b2, b3]);
} }
@@ -82,10 +82,10 @@ exports[`basics can select a sub widget, part 2 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let b2,b3; let b2,b3;
if (ctx['state'].flag) { if (ctx['state'].flag) {
b2 = comp1({}, key + \`__1\`, node, ctx, null); b2 = comp1({}, key + \`__1\`, node, this, null);
} }
if (!ctx['state'].flag) { if (!ctx['state'].flag) {
b3 = comp2({}, key + \`__2\`, node, ctx, null); b3 = comp2({}, key + \`__2\`, node, this, null);
} }
return multi([b2, b3]); return multi([b2, b3]);
} }
@@ -125,7 +125,7 @@ exports[`basics sub widget is interactive 1`] = `
const comp1 = app.createComponent(\`Child\`, true, false, false, false); const comp1 = app.createComponent(\`Child\`, true, false, false, false);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({p: 1}, key + \`__1\`, node, ctx, null); return comp1({p: 1}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -154,7 +154,7 @@ exports[`basics top level sub widget with a parent 1`] = `
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 = \\"\\") {
const b2 = comp1({}, key + \`__1\`, node, ctx, null); const b2 = comp1({}, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -167,7 +167,7 @@ exports[`basics top level sub widget with a parent 2`] = `
const comp1 = app.createComponent(\`ComponentC\`, true, false, false, true); const comp1 = app.createComponent(\`ComponentC\`, true, false, false, true);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({}, key + \`__1\`, node, ctx, null); return comp1({}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -44,7 +44,7 @@ exports[`hooks can use onWillStart, onWillUpdateProps 1`] = `
const comp1 = app.createComponent(\`MyComponent\`, true, false, false, false); const comp1 = app.createComponent(\`MyComponent\`, true, false, false, false);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({value: ctx['state'].value}, key + \`__1\`, node, ctx, null); return comp1({value: ctx['state'].value}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -112,7 +112,7 @@ exports[`hooks parent and child env (with useChildSubEnv then useSubEnv) 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const b2 = text(ctx['env'].val); const b2 = text(ctx['env'].val);
const b3 = comp1({}, key + \`__1\`, node, ctx, null); const b3 = comp1({}, key + \`__1\`, node, this, null);
return multi([b2, b3]); return multi([b2, b3]);
} }
}" }"
@@ -144,7 +144,7 @@ exports[`hooks parent and child env (with useChildSubEnv) 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const b2 = text(ctx['env'].val); const b2 = text(ctx['env'].val);
const b3 = comp1({}, key + \`__1\`, node, ctx, null); const b3 = comp1({}, key + \`__1\`, node, this, null);
return multi([b2, b3]); return multi([b2, b3]);
} }
}" }"
@@ -172,7 +172,7 @@ exports[`hooks parent and child env (with useSubEnv) 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const b2 = text(ctx['env'].val); const b2 = text(ctx['env'].val);
const b3 = comp1({}, key + \`__1\`, node, ctx, null); const b3 = comp1({}, key + \`__1\`, node, this, null);
return multi([b2, b3]); return multi([b2, b3]);
} }
}" }"
@@ -227,7 +227,7 @@ exports[`hooks useChildSubEnv supports arbitrary descriptor 1`] = `
const comp1 = app.createComponent(\`Child\`, true, false, false, true); const comp1 = app.createComponent(\`Child\`, true, false, false, true);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({}, key + \`__1\`, node, ctx, null); return comp1({}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -328,7 +328,7 @@ exports[`hooks useExternalListener 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let b2; let b2;
if (ctx['state'].flag) { if (ctx['state'].flag) {
b2 = comp1({}, key + \`__1\`, node, ctx, null); b2 = comp1({}, key + \`__1\`, node, this, null);
} }
return multi([b2]); return multi([b2]);
} }
@@ -386,7 +386,7 @@ exports[`hooks useSubEnv supports arbitrary descriptor 1`] = `
const comp1 = app.createComponent(\`Child\`, true, false, false, true); const comp1 = app.createComponent(\`Child\`, true, false, false, true);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({}, key + \`__1\`, node, ctx, null); return comp1({}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -23,8 +23,8 @@ exports[`lifecycle hooks component semantics 1`] = `
let block1 = createBlock(\`<div>A<block-child-0/><block-child-1/></div>\`); let block1 = createBlock(\`<div>A<block-child-0/><block-child-1/></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const b2 = comp1({}, key + \`__1\`, node, ctx, null); const b2 = comp1({}, key + \`__1\`, node, this, null);
const b3 = comp2({}, key + \`__2\`, node, ctx, null); const b3 = comp2({}, key + \`__2\`, node, this, null);
return block1([], [b2, b3]); return block1([], [b2, b3]);
} }
}" }"
@@ -55,11 +55,11 @@ exports[`lifecycle hooks component semantics 3`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let b2,b3,b4; let b2,b3,b4;
b2 = comp1({}, key + \`__1\`, node, ctx, null); b2 = comp1({}, key + \`__1\`, node, this, null);
if (ctx['state'].flag) { if (ctx['state'].flag) {
b3 = comp2({}, key + \`__2\`, node, ctx, null); b3 = comp2({}, key + \`__2\`, node, this, null);
} else { } else {
b4 = comp3({}, key + \`__3\`, node, ctx, null); b4 = comp3({}, key + \`__3\`, node, this, null);
} }
return block1([], [b2, b3, b4]); return block1([], [b2, b3, b4]);
} }
@@ -116,7 +116,7 @@ exports[`lifecycle hooks components are unmounted and destroyed if no longer in
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let b2; let b2;
if (ctx['state'].flag) { if (ctx['state'].flag) {
const b3 = comp1({n: ctx['state'].n}, key + \`__1\`, node, ctx, null); const b3 = comp1({n: ctx['state'].n}, key + \`__1\`, node, this, null);
b2 = block2([], [b3]); b2 = block2([], [b3]);
} }
return multi([b2]); return multi([b2]);
@@ -147,7 +147,7 @@ exports[`lifecycle hooks components are unmounted destroyed if no longer in DOM
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let b2; let b2;
if (ctx['state'].ok) { if (ctx['state'].ok) {
b2 = comp1({}, key + \`__1\`, node, ctx, null); b2 = comp1({}, key + \`__1\`, node, this, null);
} }
return multi([b2]); return multi([b2]);
} }
@@ -177,7 +177,7 @@ exports[`lifecycle hooks destroy new children before being mountged 1`] = `
let b2,b3,b4; let b2,b3,b4;
b2 = text(\`before\`); b2 = text(\`before\`);
if (ctx['state'].flag) { if (ctx['state'].flag) {
b3 = comp1({}, key + \`__1\`, node, ctx, null); b3 = comp1({}, key + \`__1\`, node, this, null);
} }
b4 = text(\`after\`); b4 = text(\`after\`);
return multi([b2, b3, b4]); return multi([b2, b3, b4]);
@@ -205,7 +205,7 @@ exports[`lifecycle hooks hooks are called in proper order in widget creation/des
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 = \\"\\") {
const b2 = comp1({}, key + \`__1\`, node, ctx, null); const b2 = comp1({}, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -231,7 +231,7 @@ exports[`lifecycle hooks lifecycle callbacks are bound to component 1`] = `
const comp1 = app.createComponent(\`Test\`, true, false, false, false); const comp1 = app.createComponent(\`Test\`, true, false, false, false);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({rev: ctx['rev']}, key + \`__1\`, node, ctx, null); return comp1({rev: ctx['rev']}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -256,7 +256,7 @@ exports[`lifecycle hooks lifecycle semantics 1`] = `
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 = \\"\\") {
const b2 = comp1({a: ctx['state'].a}, key + \`__1\`, node, ctx, null); const b2 = comp1({a: ctx['state'].a}, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -284,7 +284,7 @@ exports[`lifecycle hooks lifecycle semantics, part 2 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let b2; let b2;
if (ctx['state'].hasChild) { if (ctx['state'].hasChild) {
b2 = comp1({}, key + \`__1\`, node, ctx, null); b2 = comp1({}, key + \`__1\`, node, this, null);
} }
return multi([b2]); return multi([b2]);
} }
@@ -298,7 +298,7 @@ exports[`lifecycle hooks lifecycle semantics, part 2 2`] = `
const comp1 = app.createComponent(\`GrandChild\`, true, false, false, true); const comp1 = app.createComponent(\`GrandChild\`, true, false, false, true);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({}, key + \`__1\`, node, ctx, null); return comp1({}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -325,7 +325,7 @@ exports[`lifecycle hooks lifecycle semantics, part 3 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let b2; let b2;
if (ctx['state'].hasChild) { if (ctx['state'].hasChild) {
b2 = comp1({}, key + \`__1\`, node, ctx, null); b2 = comp1({}, key + \`__1\`, node, this, null);
} }
return multi([b2]); return multi([b2]);
} }
@@ -341,7 +341,7 @@ exports[`lifecycle hooks lifecycle semantics, part 4 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let b2; let b2;
if (ctx['state'].hasChild) { if (ctx['state'].hasChild) {
b2 = comp1({}, key + \`__1\`, node, ctx, null); b2 = comp1({}, key + \`__1\`, node, this, null);
} }
return multi([b2]); return multi([b2]);
} }
@@ -355,7 +355,7 @@ exports[`lifecycle hooks lifecycle semantics, part 4 2`] = `
const comp1 = app.createComponent(\`GrandChild\`, true, false, false, true); const comp1 = app.createComponent(\`GrandChild\`, true, false, false, true);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({}, key + \`__1\`, node, ctx, null); return comp1({}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -382,7 +382,7 @@ exports[`lifecycle hooks lifecycle semantics, part 5 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let b2; let b2;
if (ctx['state'].hasChild) { if (ctx['state'].hasChild) {
b2 = comp1({}, key + \`__1\`, node, ctx, null); b2 = comp1({}, key + \`__1\`, node, this, null);
} }
return multi([b2]); return multi([b2]);
} }
@@ -409,7 +409,7 @@ exports[`lifecycle hooks lifecycle semantics, part 6 1`] = `
const comp1 = app.createComponent(\`Child\`, true, false, false, false); const comp1 = app.createComponent(\`Child\`, true, false, false, false);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({value: ctx['state'].value}, key + \`__1\`, node, ctx, null); return comp1({value: ctx['state'].value}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -449,7 +449,7 @@ exports[`lifecycle hooks mounted hook is called on every mount, not just the fir
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let b2; let b2;
if (ctx['state'].hasChild) { if (ctx['state'].hasChild) {
b2 = comp1({}, key + \`__1\`, node, ctx, null); b2 = comp1({}, key + \`__1\`, node, this, null);
} }
return multi([b2]); return multi([b2]);
} }
@@ -478,7 +478,7 @@ exports[`lifecycle hooks mounted hook is called on subcomponents, in proper orde
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 = \\"\\") {
const b2 = comp1({}, key + \`__1\`, node, ctx, null); const b2 = comp1({}, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -508,7 +508,7 @@ exports[`lifecycle hooks mounted hook is called on subsubcomponents, in proper o
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let b2; let b2;
if (ctx['state'].flag) { if (ctx['state'].flag) {
b2 = comp1({}, key + \`__1\`, node, ctx, null); b2 = comp1({}, key + \`__1\`, node, this, null);
} }
return block1([], [b2]); return block1([], [b2]);
} }
@@ -524,7 +524,7 @@ exports[`lifecycle hooks mounted hook is called on subsubcomponents, in proper o
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 = \\"\\") {
const b2 = comp1({}, key + \`__1\`, node, ctx, null); const b2 = comp1({}, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -550,7 +550,7 @@ exports[`lifecycle hooks onWillRender 1`] = `
const comp1 = app.createComponent(\`Child\`, true, false, false, false); const comp1 = app.createComponent(\`Child\`, true, false, false, false);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({someValue: ctx['state'].value}, key + \`__1\`, node, ctx, null); return comp1({someValue: ctx['state'].value}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -579,7 +579,7 @@ exports[`lifecycle hooks patched hook is called after updateProps 1`] = `
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 = \\"\\") {
const b2 = comp1({a: ctx['state'].a}, key + \`__1\`, node, ctx, null); const b2 = comp1({a: ctx['state'].a}, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -663,7 +663,7 @@ exports[`lifecycle hooks sub widget (inside sub node): hooks are correctly calle
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let b2; let b2;
if (ctx['state'].flag) { if (ctx['state'].flag) {
b2 = comp1({}, key + \`__1\`, node, ctx, null); b2 = comp1({}, key + \`__1\`, node, this, null);
} }
return multi([b2]); return multi([b2]);
} }
@@ -704,8 +704,8 @@ exports[`lifecycle hooks timeout in onWillUpdateProps emits a warning 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {prop: ctx['state'].prop}; const props1 = {prop: ctx['state'].prop};
helpers.validateProps(\`Child\`, props1, ctx); helpers.validateProps(\`Child\`, props1, this);
return comp1(props1, key + \`__1\`, node, ctx, null); return comp1(props1, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -730,7 +730,7 @@ exports[`lifecycle hooks willPatch, patched hook are called on subsubcomponents,
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 = \\"\\") {
const b2 = comp1({n: ctx['state'].n}, key + \`__1\`, node, ctx, null); const b2 = comp1({n: ctx['state'].n}, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -745,7 +745,7 @@ exports[`lifecycle hooks willPatch, patched hook are called on subsubcomponents,
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 = \\"\\") {
const b2 = comp1({n: ctx['props'].n}, key + \`__1\`, node, ctx, null); const b2 = comp1({n: ctx['props'].n}, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -772,7 +772,7 @@ exports[`lifecycle hooks willStart hook is called on sub component 1`] = `
const comp1 = app.createComponent(\`Child\`, true, false, false, true); const comp1 = app.createComponent(\`Child\`, true, false, false, true);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({}, key + \`__1\`, node, ctx, null); return comp1({}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -828,7 +828,7 @@ exports[`lifecycle hooks willStart, mounted on subwidget rendered after main is
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let b2,b3; let b2,b3;
if (ctx['state'].ok) { if (ctx['state'].ok) {
b2 = comp1({}, key + \`__1\`, node, ctx, null); b2 = comp1({}, key + \`__1\`, node, this, null);
} else { } else {
b3 = block3(); b3 = block3();
} }
@@ -857,7 +857,7 @@ exports[`lifecycle hooks willUpdateProps hook is called 1`] = `
const comp1 = app.createComponent(\`Child\`, true, false, false, false); const comp1 = app.createComponent(\`Child\`, true, false, false, false);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({n: ctx['state'].n}, key + \`__1\`, node, ctx, null); return comp1({n: ctx['state'].n}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -9,7 +9,7 @@ exports[`basics accept ES6-like syntax for props (with getters) 1`] = `
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 = \\"\\") {
const b2 = comp1({greetings: ctx['greetings']}, key + \`__1\`, node, ctx, null); const b2 = comp1({greetings: ctx['greetings']}, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -44,7 +44,7 @@ exports[`basics arrow functions as prop correctly capture their scope 1`] = `
const key1 = ctx['item'].val; const key1 = ctx['item'].val;
const v1 = ctx['onClick']; const v1 = ctx['onClick'];
const v2 = ctx['item']; const v2 = ctx['item'];
c_block1[i1] = withKey(comp1({onClick: _ev=>v1(v2.val,_ev)}, key + \`__1__\${key1}\`, node, ctx, null), key1); c_block1[i1] = withKey(comp1({onClick: _ev=>v1(v2.val,_ev)}, key + \`__1__\${key1}\`, node, this, null), key1);
} }
return list(c_block1); return list(c_block1);
} }
@@ -74,7 +74,7 @@ exports[`basics explicit object prop 1`] = `
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 = \\"\\") {
const b2 = comp1({value: ctx['state'].val}, key + \`__1\`, node, ctx, null); const b2 = comp1({value: ctx['state'].val}, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -101,7 +101,7 @@ exports[`basics prop names can contain - 1`] = `
const comp1 = app.createComponent(\`Child\`, true, false, false, false); const comp1 = app.createComponent(\`Child\`, true, false, false, false);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({'prop-name': 7}, key + \`__1\`, node, ctx, null); return comp1({'prop-name': 7}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -127,7 +127,7 @@ exports[`basics support prop names that aren't valid bare object property names
const comp1 = app.createComponent(\`Child\`, true, false, false, false); const comp1 = app.createComponent(\`Child\`, true, false, false, false);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({'some-dashed-prop': 5}, key + \`__1\`, node, ctx, null); return comp1({'some-dashed-prop': 5}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -163,8 +163,8 @@ exports[`basics t-set with a body expression can be passed in props, and then t-
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
ctx = Object.create(ctx); ctx = Object.create(ctx);
ctx[isBoundary] = 1 ctx[isBoundary] = 1
ctx[\`abc\`] = new LazyValue(value1, ctx, node); ctx[\`abc\`] = new LazyValue(value1, ctx, this, node, key);
const b3 = comp1({val: ctx['abc']}, key + \`__1\`, node, ctx, null); const b3 = comp1({val: ctx['abc']}, key + \`__1\`, node, this, null);
return block1([], [b3]); return block1([], [b3]);
} }
}" }"
@@ -199,7 +199,7 @@ exports[`basics t-set with a body expression can be used as textual prop 1`] = `
ctx = Object.create(ctx); ctx = Object.create(ctx);
ctx[isBoundary] = 1 ctx[isBoundary] = 1
setContextValue(ctx, \\"abc\\", \`42\`); setContextValue(ctx, \\"abc\\", \`42\`);
const b2 = comp1({val: ctx['abc']}, key + \`__1\`, node, ctx, null); const b2 = comp1({val: ctx['abc']}, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -232,7 +232,7 @@ exports[`basics t-set works 1`] = `
ctx = Object.create(ctx); ctx = Object.create(ctx);
ctx[isBoundary] = 1 ctx[isBoundary] = 1
setContextValue(ctx, \\"val\\", 42); setContextValue(ctx, \\"val\\", 42);
const b2 = comp1({val: ctx['val']}, key + \`__1\`, node, ctx, null); const b2 = comp1({val: ctx['val']}, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -259,7 +259,7 @@ exports[`basics template string in prop 1`] = `
const comp1 = app.createComponent(\`Child\`, true, false, false, false); const comp1 = app.createComponent(\`Child\`, true, false, false, false);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({propName: \`1\${ctx['someVal']}3\`}, key + \`__1\`, node, ctx, null); return comp1({propName: \`1\${ctx['someVal']}3\`}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -283,7 +283,7 @@ exports[`bound functions is referentially equal after update 1`] = `
const comp1 = app.createComponent(\`Child\`, true, false, false, false); const comp1 = app.createComponent(\`Child\`, true, false, false, false);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({val: ctx['state'].val,fn: bind(ctx, ctx['someFunction'])}, key + \`__1\`, node, ctx, null); return comp1({val: ctx['state'].val,fn: bind(ctx, ctx['someFunction'])}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -307,7 +307,7 @@ exports[`can bind function prop with bind suffix 1`] = `
const comp1 = app.createComponent(\`Child\`, true, false, false, false); const comp1 = app.createComponent(\`Child\`, true, false, false, false);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({doSomething: bind(ctx, ctx['doSomething'])}, key + \`__1\`, node, ctx, null); return comp1({doSomething: bind(ctx, ctx['doSomething'])}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -8,8 +8,8 @@ exports[`default props a default prop cannot be defined on a mandatory prop 1`]
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {}; const props1 = {};
helpers.validateProps(\`Child\`, props1, ctx); helpers.validateProps(\`Child\`, props1, this);
return comp1(props1, key + \`__1\`, node, ctx, null); return comp1(props1, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -24,8 +24,8 @@ exports[`default props can set default boolean values 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {}; const props1 = {};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, this);
const b2 = comp1(props1, key + \`__1\`, node, ctx, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -61,8 +61,8 @@ exports[`default props can set default values 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {}; const props1 = {};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, this);
const b2 = comp1(props1, key + \`__1\`, node, ctx, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -92,8 +92,8 @@ exports[`default props default values are also set whenever component is updated
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['state'].p}; const props1 = {p: ctx['state'].p};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, this);
const b2 = comp1(props1, key + \`__1\`, node, ctx, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -121,8 +121,8 @@ exports[`props validation can specify that additional props are allowed (array)
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {message: 'm',otherProp: 'o'}; const props1 = {message: 'm',otherProp: 'o'};
helpers.validateProps(\`Child\`, props1, ctx); helpers.validateProps(\`Child\`, props1, this);
return comp1(props1, key + \`__1\`, node, ctx, null); return comp1(props1, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -148,8 +148,8 @@ exports[`props validation can specify that additional props are allowed (object)
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {message: 'm',otherProp: 'o'}; const props1 = {message: 'm',otherProp: 'o'};
helpers.validateProps(\`Child\`, props1, ctx); helpers.validateProps(\`Child\`, props1, this);
return comp1(props1, key + \`__1\`, node, ctx, null); return comp1(props1, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -177,8 +177,8 @@ exports[`props validation can validate a prop with multiple types 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, this);
const b2 = comp1(props1, key + \`__1\`, node, ctx, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -207,8 +207,8 @@ exports[`props validation can validate a prop with multiple types 3`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, this);
const b2 = comp1(props1, key + \`__1\`, node, ctx, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -237,8 +237,8 @@ exports[`props validation can validate a prop with multiple types 5`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, this);
const b2 = comp1(props1, key + \`__1\`, node, ctx, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -254,8 +254,8 @@ exports[`props validation can validate an array with given primitive type 1`] =
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, this);
const b2 = comp1(props1, key + \`__1\`, node, ctx, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -284,8 +284,8 @@ exports[`props validation can validate an array with given primitive type 3`] =
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, this);
const b2 = comp1(props1, key + \`__1\`, node, ctx, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -314,8 +314,8 @@ exports[`props validation can validate an array with given primitive type 5`] =
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, this);
const b2 = comp1(props1, key + \`__1\`, node, ctx, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -331,8 +331,8 @@ exports[`props validation can validate an array with given primitive type 6`] =
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, this);
const b2 = comp1(props1, key + \`__1\`, node, ctx, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -348,8 +348,8 @@ exports[`props validation can validate an array with multiple sub element types
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, this);
const b2 = comp1(props1, key + \`__1\`, node, ctx, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -378,8 +378,8 @@ exports[`props validation can validate an array with multiple sub element types
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, this);
const b2 = comp1(props1, key + \`__1\`, node, ctx, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -408,8 +408,8 @@ exports[`props validation can validate an array with multiple sub element types
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, this);
const b2 = comp1(props1, key + \`__1\`, node, ctx, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -438,8 +438,8 @@ exports[`props validation can validate an array with multiple sub element types
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, this);
const b2 = comp1(props1, key + \`__1\`, node, ctx, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -455,8 +455,8 @@ exports[`props validation can validate an object with simple shape 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, this);
const b2 = comp1(props1, key + \`__1\`, node, ctx, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -485,8 +485,8 @@ exports[`props validation can validate an object with simple shape 3`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, this);
const b2 = comp1(props1, key + \`__1\`, node, ctx, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -502,8 +502,8 @@ exports[`props validation can validate an object with simple shape 4`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, this);
const b2 = comp1(props1, key + \`__1\`, node, ctx, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -519,8 +519,8 @@ exports[`props validation can validate an object with simple shape 5`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, this);
const b2 = comp1(props1, key + \`__1\`, node, ctx, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -536,8 +536,8 @@ exports[`props validation can validate an optional props 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, this);
const b2 = comp1(props1, key + \`__1\`, node, ctx, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -566,8 +566,8 @@ exports[`props validation can validate an optional props 3`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, this);
const b2 = comp1(props1, key + \`__1\`, node, ctx, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -596,8 +596,8 @@ exports[`props validation can validate an optional props 5`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, this);
const b2 = comp1(props1, key + \`__1\`, node, ctx, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -613,8 +613,8 @@ exports[`props validation can validate recursively complicated prop def 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, this);
const b2 = comp1(props1, key + \`__1\`, node, ctx, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -643,8 +643,8 @@ exports[`props validation can validate recursively complicated prop def 3`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, this);
const b2 = comp1(props1, key + \`__1\`, node, ctx, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -673,13 +673,47 @@ exports[`props validation can validate recursively complicated prop def 5`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, this);
const b2 = comp1(props1, key + \`__1\`, node, ctx, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
`; `;
exports[`props validation can validate through slots 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let { markRaw } = helpers;
const comp1 = app.createComponent(\`Child\`, true, false, false, true);
const comp2 = app.createComponent(\`Wrapper\`, true, true, false, true);
function slot1(ctx, node, key = \\"\\") {
const props1 = {};
helpers.validateProps(\`Child\`, props1, this);
return comp1(props1, key + \`__1\`, node, this, null);
}
return function template(ctx, node, key = \\"\\") {
const props2 = {slots: markRaw({'default': {__render: slot1, __ctx: ctx}})};
helpers.validateProps(\`Wrapper\`, props2, this);
return comp2(props2, key + \`__2\`, node, this, null);
}
}"
`;
exports[`props validation can validate through slots 2`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let { callSlot } = helpers;
return function template(ctx, node, key = \\"\\") {
return callSlot(ctx, node, key, 'default', false, {});
}
}"
`;
exports[`props validation default values are applied before validating props at update 1`] = ` exports[`props validation default values are applied before validating props at update 1`] = `
"function anonymous(app, bdom, helpers "function anonymous(app, bdom, helpers
) { ) {
@@ -690,8 +724,8 @@ exports[`props validation default values are applied before validating props at
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['state'].p}; const props1 = {p: ctx['state'].p};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, this);
const b2 = comp1(props1, key + \`__1\`, node, ctx, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -721,8 +755,8 @@ exports[`props validation missing required boolean prop causes an error 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {}; const props1 = {};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, this);
const b2 = comp1(props1, key + \`__1\`, node, ctx, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -738,8 +772,8 @@ exports[`props validation mix of optional and mandatory 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {}; const props1 = {};
helpers.validateProps(\`Child\`, props1, ctx); helpers.validateProps(\`Child\`, props1, this);
const b2 = comp1(props1, key + \`__1\`, node, ctx, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -755,8 +789,8 @@ exports[`props validation props are validated in dev mode (code snapshot) 1`] =
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {message: 1}; const props1 = {message: 1};
helpers.validateProps(\`Child\`, props1, ctx); helpers.validateProps(\`Child\`, props1, this);
const b2 = comp1(props1, key + \`__1\`, node, ctx, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -786,8 +820,8 @@ exports[`props validation props are validated whenever component is updated 1`]
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['state'].p}; const props1 = {p: ctx['state'].p};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, this);
const b2 = comp1(props1, key + \`__1\`, node, ctx, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -817,8 +851,8 @@ exports[`props validation props: list of strings 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {}; const props1 = {};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, this);
const b2 = comp1(props1, key + \`__1\`, node, ctx, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -834,8 +868,8 @@ exports[`props validation validate simple types 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, this);
const b2 = comp1(props1, key + \`__1\`, node, ctx, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -851,8 +885,8 @@ exports[`props validation validate simple types 2`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, this);
const b2 = comp1(props1, key + \`__1\`, node, ctx, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -881,8 +915,8 @@ exports[`props validation validate simple types 4`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, this);
const b2 = comp1(props1, key + \`__1\`, node, ctx, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -898,8 +932,8 @@ exports[`props validation validate simple types 5`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, this);
const b2 = comp1(props1, key + \`__1\`, node, ctx, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -915,8 +949,8 @@ exports[`props validation validate simple types 6`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, this);
const b2 = comp1(props1, key + \`__1\`, node, ctx, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -945,8 +979,8 @@ exports[`props validation validate simple types 8`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, this);
const b2 = comp1(props1, key + \`__1\`, node, ctx, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -962,8 +996,8 @@ exports[`props validation validate simple types 9`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, this);
const b2 = comp1(props1, key + \`__1\`, node, ctx, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -979,8 +1013,8 @@ exports[`props validation validate simple types 10`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, this);
const b2 = comp1(props1, key + \`__1\`, node, ctx, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -1009,8 +1043,8 @@ exports[`props validation validate simple types 12`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, this);
const b2 = comp1(props1, key + \`__1\`, node, ctx, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -1026,8 +1060,8 @@ exports[`props validation validate simple types 13`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, this);
const b2 = comp1(props1, key + \`__1\`, node, ctx, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -1043,8 +1077,8 @@ exports[`props validation validate simple types 14`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, this);
const b2 = comp1(props1, key + \`__1\`, node, ctx, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -1073,8 +1107,8 @@ exports[`props validation validate simple types 16`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, this);
const b2 = comp1(props1, key + \`__1\`, node, ctx, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -1090,8 +1124,8 @@ exports[`props validation validate simple types 17`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, this);
const b2 = comp1(props1, key + \`__1\`, node, ctx, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -1107,8 +1141,8 @@ exports[`props validation validate simple types 18`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, this);
const b2 = comp1(props1, key + \`__1\`, node, ctx, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -1137,8 +1171,8 @@ exports[`props validation validate simple types 20`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, this);
const b2 = comp1(props1, key + \`__1\`, node, ctx, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -1154,8 +1188,8 @@ exports[`props validation validate simple types 21`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, this);
const b2 = comp1(props1, key + \`__1\`, node, ctx, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -1171,8 +1205,8 @@ exports[`props validation validate simple types 22`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, this);
const b2 = comp1(props1, key + \`__1\`, node, ctx, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -1201,8 +1235,8 @@ exports[`props validation validate simple types 24`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, this);
const b2 = comp1(props1, key + \`__1\`, node, ctx, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -1218,8 +1252,8 @@ exports[`props validation validate simple types, alternate form 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, this);
const b2 = comp1(props1, key + \`__1\`, node, ctx, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -1235,8 +1269,8 @@ exports[`props validation validate simple types, alternate form 2`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, this);
const b2 = comp1(props1, key + \`__1\`, node, ctx, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -1265,8 +1299,8 @@ exports[`props validation validate simple types, alternate form 4`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, this);
const b2 = comp1(props1, key + \`__1\`, node, ctx, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -1282,8 +1316,8 @@ exports[`props validation validate simple types, alternate form 5`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, this);
const b2 = comp1(props1, key + \`__1\`, node, ctx, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -1299,8 +1333,8 @@ exports[`props validation validate simple types, alternate form 6`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, this);
const b2 = comp1(props1, key + \`__1\`, node, ctx, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -1329,8 +1363,8 @@ exports[`props validation validate simple types, alternate form 8`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, this);
const b2 = comp1(props1, key + \`__1\`, node, ctx, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -1346,8 +1380,8 @@ exports[`props validation validate simple types, alternate form 9`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, this);
const b2 = comp1(props1, key + \`__1\`, node, ctx, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -1363,8 +1397,8 @@ exports[`props validation validate simple types, alternate form 10`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, this);
const b2 = comp1(props1, key + \`__1\`, node, ctx, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -1393,8 +1427,8 @@ exports[`props validation validate simple types, alternate form 12`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, this);
const b2 = comp1(props1, key + \`__1\`, node, ctx, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -1410,8 +1444,8 @@ exports[`props validation validate simple types, alternate form 13`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, this);
const b2 = comp1(props1, key + \`__1\`, node, ctx, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -1427,8 +1461,8 @@ exports[`props validation validate simple types, alternate form 14`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, this);
const b2 = comp1(props1, key + \`__1\`, node, ctx, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -1457,8 +1491,8 @@ exports[`props validation validate simple types, alternate form 16`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, this);
const b2 = comp1(props1, key + \`__1\`, node, ctx, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -1474,8 +1508,8 @@ exports[`props validation validate simple types, alternate form 17`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, this);
const b2 = comp1(props1, key + \`__1\`, node, ctx, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -1491,8 +1525,8 @@ exports[`props validation validate simple types, alternate form 18`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, this);
const b2 = comp1(props1, key + \`__1\`, node, ctx, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -1521,8 +1555,8 @@ exports[`props validation validate simple types, alternate form 20`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, this);
const b2 = comp1(props1, key + \`__1\`, node, ctx, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -1538,8 +1572,8 @@ exports[`props validation validate simple types, alternate form 21`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, this);
const b2 = comp1(props1, key + \`__1\`, node, ctx, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -1555,8 +1589,8 @@ exports[`props validation validate simple types, alternate form 22`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, this);
const b2 = comp1(props1, key + \`__1\`, node, ctx, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -1585,8 +1619,8 @@ exports[`props validation validate simple types, alternate form 24`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {p: ctx['p']}; const props1 = {p: ctx['p']};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, this);
const b2 = comp1(props1, key + \`__1\`, node, ctx, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -1602,8 +1636,8 @@ exports[`props validation validation is only done in dev mode 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const props1 = {}; const props1 = {};
helpers.validateProps(\`SubComp\`, props1, ctx); helpers.validateProps(\`SubComp\`, props1, this);
const b2 = comp1(props1, key + \`__1\`, node, ctx, null); const b2 = comp1(props1, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -1618,7 +1652,7 @@ exports[`props validation validation is only done in dev mode 2`] = `
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 = \\"\\") {
const b2 = comp1({}, key + \`__1\`, node, ctx, null); const b2 = comp1({}, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -9,7 +9,7 @@ exports[`reactivity in lifecycle Child component doesn't render when state they
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let b2; let b2;
if (ctx['state'].renderChild) { if (ctx['state'].renderChild) {
b2 = comp1({state: ctx['state']}, key + \`__1\`, node, ctx, null); b2 = comp1({state: ctx['state']}, key + \`__1\`, node, this, null);
} }
return multi([b2]); return multi([b2]);
} }
@@ -34,7 +34,7 @@ exports[`reactivity in lifecycle Component is automatically subscribed to reacti
const comp1 = app.createComponent(\`Child\`, true, false, false, false); const comp1 = app.createComponent(\`Child\`, true, false, false, false);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({obj: ctx['obj'],reactiveObj: ctx['reactiveObj']}, key + \`__1\`, node, ctx, null); return comp1({obj: ctx['obj'],reactiveObj: ctx['reactiveObj']}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -119,7 +119,7 @@ exports[`reactivity in lifecycle state changes in willUnmount do not trigger rer
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let b2; let b2;
if (ctx['state'].flag) { if (ctx['state'].flag) {
b2 = comp1({val: ctx['state'].val}, key + \`__1\`, node, ctx, null); b2 = comp1({val: ctx['state'].val}, key + \`__1\`, node, this, null);
} }
return block1([], [b2]); return block1([], [b2]);
} }
@@ -52,7 +52,7 @@ exports[`refs refs and recursive templates 1`] = `
let b2; let b2;
let txt1 = ctx['props'].tree.value; let txt1 = ctx['props'].tree.value;
if (ctx['props'].tree.child) { if (ctx['props'].tree.child) {
b2 = comp1({tree: ctx['props'].tree.child}, key + \`__1\`, node, ctx, null); b2 = comp1({tree: ctx['props'].tree.child}, key + \`__1\`, node, this, null);
} }
return block1([ref1, txt1], [b2]); return block1([ref1, txt1], [b2]);
} }
@@ -79,7 +79,7 @@ exports[`refs refs are properly bound in slots 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let txt1 = ctx['state'].val; let txt1 = ctx['state'].val;
const ctx1 = capture(ctx); const ctx1 = capture(ctx);
const b3 = comp1({slots: markRaw({'footer': {__render: slot1, __ctx: ctx1}})}, key + \`__1\`, node, ctx, null); const b3 = comp1({slots: markRaw({'footer': {__render: slot1, __ctx: ctx1}})}, key + \`__1\`, node, this, null);
return block1([txt1], [b3]); return block1([txt1], [b3]);
} }
}" }"
@@ -8,7 +8,7 @@ exports[`children, default props and renderings 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const b2 = text(ctx['state'].value); const b2 = text(ctx['state'].value);
const b3 = comp1({}, key + \`__1\`, node, ctx, null); const b3 = comp1({}, key + \`__1\`, node, this, null);
return multi([b2, b3]); return multi([b2, b3]);
} }
}" }"
@@ -32,7 +32,7 @@ exports[`force render in case of existing render 1`] = `
const comp1 = app.createComponent(\`B\`, true, false, false, false); const comp1 = app.createComponent(\`B\`, true, false, false, false);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({val: ctx['state'].val}, key + \`__1\`, node, ctx, null); return comp1({val: ctx['state'].val}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -44,7 +44,7 @@ exports[`force render in case of existing render 2`] = `
const comp1 = app.createComponent(\`C\`, true, false, false, true); const comp1 = app.createComponent(\`C\`, true, false, false, true);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const b2 = comp1({}, key + \`__1\`, node, ctx, null); const b2 = comp1({}, key + \`__1\`, node, this, null);
const b3 = text(ctx['props'].val); const b3 = text(ctx['props'].val);
return multi([b2, b3]); return multi([b2, b3]);
} }
@@ -70,7 +70,7 @@ exports[`rendering semantics can force a render to update sub tree 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const b2 = text(ctx['state'].value); const b2 = text(ctx['state'].value);
const b3 = comp1({}, key + \`__1\`, node, ctx, null); const b3 = comp1({}, key + \`__1\`, node, this, null);
return multi([b2, b3]); return multi([b2, b3]);
} }
}" }"
@@ -95,7 +95,7 @@ exports[`rendering semantics can render a parent without rendering child 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const b2 = text(ctx['state'].value); const b2 = text(ctx['state'].value);
const b3 = comp1({}, key + \`__1\`, node, ctx, null); const b3 = comp1({}, key + \`__1\`, node, this, null);
return multi([b2, b3]); return multi([b2, b3]);
} }
}" }"
@@ -119,7 +119,7 @@ exports[`rendering semantics props are reactive (nested prop) 1`] = `
const comp1 = app.createComponent(\`Child\`, true, false, false, false); const comp1 = app.createComponent(\`Child\`, true, false, false, false);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({a: ctx['state']}, key + \`__1\`, node, ctx, null); return comp1({a: ctx['state']}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -142,7 +142,7 @@ exports[`rendering semantics props are reactive 1`] = `
const comp1 = app.createComponent(\`Child\`, true, false, false, false); const comp1 = app.createComponent(\`Child\`, true, false, false, false);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({a: ctx['state']}, key + \`__1\`, node, ctx, null); return comp1({a: ctx['state']}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -166,7 +166,7 @@ exports[`rendering semantics render need a boolean = true to be 'deep' 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const b2 = text(ctx['state'].value); const b2 = text(ctx['state'].value);
const b3 = comp1({}, key + \`__1\`, node, ctx, null); const b3 = comp1({}, key + \`__1\`, node, this, null);
return multi([b2, b3]); return multi([b2, b3]);
} }
}" }"
@@ -192,7 +192,7 @@ exports[`rendering semantics render with deep=true followed by render with deep=
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const b2 = text(\`parent\`); const b2 = text(\`parent\`);
const b3 = text(ctx['state'].value); const b3 = text(ctx['state'].value);
const b4 = comp1({}, key + \`__1\`, node, ctx, null); const b4 = comp1({}, key + \`__1\`, node, this, null);
return multi([b2, b3, b4]); return multi([b2, b3, b4]);
} }
}" }"
@@ -219,7 +219,7 @@ exports[`rendering semantics rendering is atomic (for one subtree) 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const b2 = text(ctx['state'].obj.val); const b2 = text(ctx['state'].obj.val);
const b3 = comp1({obj: ctx['state'].obj}, key + \`__1\`, node, ctx, null); const b3 = comp1({obj: ctx['state'].obj}, key + \`__1\`, node, this, null);
return multi([b2, b3]); return multi([b2, b3]);
} }
}" }"
@@ -232,7 +232,7 @@ exports[`rendering semantics rendering is atomic (for one subtree) 2`] = `
const comp1 = app.createComponent(\`C\`, true, false, false, false); const comp1 = app.createComponent(\`C\`, true, false, false, false);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({obj: ctx['props'].obj}, key + \`__1\`, node, ctx, null); return comp1({obj: ctx['props'].obj}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -255,7 +255,7 @@ exports[`rendering semantics works as expected for dynamic number of props 1`] =
const comp1 = app.createComponent(\`Child\`, true, false, true, false); const comp1 = app.createComponent(\`Child\`, true, false, true, false);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1(Object.assign({}, ctx['state']), key + \`__1\`, node, ctx, null); return comp1(Object.assign({}, ctx['state']), key + \`__1\`, node, this, null);
} }
}" }"
`; `;
+270 -100
View File
@@ -9,7 +9,7 @@ exports[`slots can define a default content 1`] = `
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 = \\"\\") {
const b2 = comp1({}, key + \`__1\`, node, ctx, null); const b2 = comp1({}, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -55,7 +55,7 @@ exports[`slots can define and call slots 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const ctx1 = capture(ctx); const ctx1 = capture(ctx);
const b4 = comp1({slots: markRaw({'header': {__render: slot1, __ctx: ctx1}, 'footer': {__render: slot2, __ctx: ctx1}})}, key + \`__1\`, node, ctx, null); const b4 = comp1({slots: markRaw({'header': {__render: slot1, __ctx: ctx1}, 'footer': {__render: slot2, __ctx: ctx1}})}, key + \`__1\`, node, this, null);
return block1([], [b4]); return block1([], [b4]);
} }
}" }"
@@ -90,7 +90,7 @@ exports[`slots can define and call slots with bound params 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const ctx1 = capture(ctx); const ctx1 = capture(ctx);
return comp1({slots: markRaw({'abc': {__render: slot1, __ctx: ctx1, getValue: bind(ctx, ctx['getValue'])}})}, key + \`__1\`, node, ctx, null); return comp1({slots: markRaw({'abc': {__render: slot1, __ctx: ctx1, getValue: bind(ctx, ctx['getValue'])}})}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -130,7 +130,7 @@ exports[`slots can define and call slots with params 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const ctx1 = capture(ctx); const ctx1 = capture(ctx);
const b4 = comp1({slots: markRaw({'header': {__render: slot1, __ctx: ctx1, param: ctx['var']}, 'footer': {__render: slot2, __ctx: ctx1, param: '5'}})}, key + \`__1\`, node, ctx, null); const b4 = comp1({slots: markRaw({'header': {__render: slot1, __ctx: ctx1, param: ctx['var']}, 'footer': {__render: slot2, __ctx: ctx1, param: '5'}})}, key + \`__1\`, node, this, null);
return block1([], [b4]); return block1([], [b4]);
} }
}" }"
@@ -168,12 +168,12 @@ exports[`slots can render node with t-ref and Component in same slot 1`] = `
const refs = ctx.__owl__.refs; const refs = ctx.__owl__.refs;
const ref1 = (el) => refs[\`div\`] = el; const ref1 = (el) => refs[\`div\`] = el;
const b2 = block2([ref1]); const b2 = block2([ref1]);
const b3 = comp1({}, key + \`__1\`, node, ctx, null); const b3 = comp1({}, key + \`__1\`, node, this, null);
return multi([b2, b3]); return multi([b2, b3]);
} }
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp2({slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__2\`, node, ctx, null); return comp2({slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__2\`, node, this, null);
} }
}" }"
`; `;
@@ -209,7 +209,7 @@ exports[`slots can use component in default-content of t-slot 1`] = `
const comp1 = app.createComponent(\`Child\`, true, false, false, true); const comp1 = app.createComponent(\`Child\`, true, false, false, true);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({}, key + \`__1\`, node, ctx, null); return comp1({}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -222,7 +222,7 @@ exports[`slots can use component in default-content of t-slot 2`] = `
const comp1 = app.createComponent(\`GrandChild\`, true, false, false, true); const comp1 = app.createComponent(\`GrandChild\`, true, false, false, true);
function defaultContent1(ctx, node, key = \\"\\") { function defaultContent1(ctx, node, key = \\"\\") {
return comp1({}, key + \`__1\`, node, ctx, null); return comp1({}, key + \`__1\`, node, this, null);
} }
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
@@ -249,7 +249,7 @@ exports[`slots can use t-call in default-content of t-slot 1`] = `
const comp1 = app.createComponent(\`Child\`, true, false, false, true); const comp1 = app.createComponent(\`Child\`, true, false, false, true);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({}, key + \`__1\`, node, ctx, null); return comp1({}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -296,7 +296,7 @@ exports[`slots content is the default slot (variation) 1`] = `
} }
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__1\`, node, ctx, null); return comp1({slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -328,7 +328,7 @@ exports[`slots content is the default slot 1`] = `
} }
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const b3 = comp1({slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__1\`, node, ctx, null); const b3 = comp1({slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__1\`, node, this, null);
return block1([], [b3]); return block1([], [b3]);
} }
}" }"
@@ -364,7 +364,7 @@ exports[`slots default content is not rendered if named slot is provided 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const ctx1 = capture(ctx); const ctx1 = capture(ctx);
const b3 = comp1({slots: markRaw({'header': {__render: slot1, __ctx: ctx1}})}, key + \`__1\`, node, ctx, null); const b3 = comp1({slots: markRaw({'header': {__render: slot1, __ctx: ctx1}})}, key + \`__1\`, node, this, null);
return block1([], [b3]); return block1([], [b3]);
} }
}" }"
@@ -403,7 +403,7 @@ exports[`slots default content is not rendered if slot is provided 1`] = `
} }
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const b3 = comp1({slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__1\`, node, ctx, null); const b3 = comp1({slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__1\`, node, this, null);
return block1([], [b3]); return block1([], [b3]);
} }
}" }"
@@ -443,7 +443,7 @@ exports[`slots default slot next to named slot, with default content 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const ctx1 = capture(ctx); const ctx1 = capture(ctx);
const b3 = comp1({slots: markRaw({'footer': {__render: slot1, __ctx: ctx1}})}, key + \`__1\`, node, ctx, null); const b3 = comp1({slots: markRaw({'footer': {__render: slot1, __ctx: ctx1}})}, key + \`__1\`, node, this, null);
return block1([], [b3]); return block1([], [b3]);
} }
}" }"
@@ -485,7 +485,7 @@ exports[`slots default slot with params with - in it 1`] = `
} }
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({slots: markRaw({'default': {__render: slot1, __ctx: ctx, __scope: \\"slotScope\\"}})}, key + \`__1\`, node, ctx, null); return comp1({slots: markRaw({'default': {__render: slot1, __ctx: ctx, __scope: \\"slotScope\\"}})}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -520,7 +520,7 @@ exports[`slots default slot with slot scope: shorthand syntax 1`] = `
} }
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({slots: markRaw({'default': {__render: slot1, __ctx: ctx, __scope: \\"slotScope\\"}})}, key + \`__1\`, node, ctx, null); return comp1({slots: markRaw({'default': {__render: slot1, __ctx: ctx, __scope: \\"slotScope\\"}})}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -552,7 +552,7 @@ exports[`slots default slot work with text nodes (variation) 1`] = `
} }
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__1\`, node, ctx, null); return comp1({slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -583,7 +583,7 @@ exports[`slots default slot work with text nodes 1`] = `
} }
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const b3 = comp1({slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__1\`, node, ctx, null); const b3 = comp1({slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__1\`, node, this, null);
return block1([], [b3]); return block1([], [b3]);
} }
}" }"
@@ -604,6 +604,64 @@ exports[`slots default slot work with text nodes 2`] = `
}" }"
`; `;
exports[`slots dynamic slot in multiple locations 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let { capture, markRaw } = helpers;
const comp1 = app.createComponent(\`Child\`, true, false, false, true);
const comp2 = app.createComponent(\`Slotter\`, true, true, false, false);
function slot1(ctx, node, key = \\"\\") {
const b2 = text(\`hello \`);
const b3 = comp1({}, key + \`__1\`, node, this, null);
return multi([b2, b3]);
}
return function template(ctx, node, key = \\"\\") {
const ctx1 = capture(ctx);
return comp2({location: ctx['state'].location,slots: markRaw({'coffee': {__render: slot1, __ctx: ctx1}})}, key + \`__2\`, node, this, null);
}
}"
`;
exports[`slots dynamic slot in multiple locations 2`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let { callSlot } = helpers;
let block2 = createBlock(\`<p><block-child-0/></p>\`);
return function template(ctx, node, key = \\"\\") {
let b2,b4;
if (ctx['props'].location===1) {
const slot1 = ('coffee');
const b3 = toggler(slot1, callSlot(ctx, node, key + \`__1\`, slot1, true, {}));
b2 = block2([], [b3]);
}
if (ctx['props'].location===2) {
const slot2 = ('coffee');
b4 = toggler(slot2, callSlot(ctx, node, key + \`__2\`, slot2, true, {}));
}
return multi([b2, b4]);
}
}"
`;
exports[`slots dynamic slot in multiple locations 3`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let block1 = createBlock(\`<div>child</div>\`);
return function template(ctx, node, key = \\"\\") {
return block1();
}
}"
`;
exports[`slots dynamic t-slot call 1`] = ` exports[`slots dynamic t-slot call 1`] = `
"function anonymous(app, bdom, helpers "function anonymous(app, bdom, helpers
) { ) {
@@ -628,7 +686,7 @@ exports[`slots dynamic t-slot call 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const ctx1 = capture(ctx); const ctx1 = capture(ctx);
const b6 = comp1({slots: markRaw({'slot1': {__render: slot1, __ctx: ctx1}, 'slot2': {__render: slot2, __ctx: ctx1}})}, key + \`__1\`, node, ctx, null); const b6 = comp1({slots: markRaw({'slot1': {__render: slot1, __ctx: ctx1}, 'slot2': {__render: slot2, __ctx: ctx1}})}, key + \`__1\`, node, this, null);
return block1([], [b6]); return block1([], [b6]);
} }
}" }"
@@ -645,7 +703,7 @@ exports[`slots dynamic t-slot call 2`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let hdlr1 = [ctx['toggle'], ctx]; let hdlr1 = [ctx['toggle'], ctx];
const slot1 = (ctx['current'].slot); const slot1 = (ctx['current'].slot);
const b2 = toggler(slot1, callSlot(ctx, node, key, slot1, true, {})); const b2 = toggler(slot1, callSlot(ctx, node, key + \`__1\`, slot1, true, {}));
return block1([hdlr1], [b2]); return block1([hdlr1], [b2]);
} }
}" }"
@@ -675,7 +733,7 @@ exports[`slots dynamic t-slot call with default 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const ctx1 = capture(ctx); const ctx1 = capture(ctx);
const b6 = comp1({slots: markRaw({'slot1': {__render: slot1, __ctx: ctx1}, 'slot2': {__render: slot2, __ctx: ctx1}})}, key + \`__1\`, node, ctx, null); const b6 = comp1({slots: markRaw({'slot1': {__render: slot1, __ctx: ctx1}, 'slot2': {__render: slot2, __ctx: ctx1}})}, key + \`__1\`, node, this, null);
return block1([], [b6]); return block1([], [b6]);
} }
}" }"
@@ -695,7 +753,7 @@ exports[`slots dynamic t-slot call with default 2`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let hdlr1 = [ctx['toggle'], ctx]; let hdlr1 = [ctx['toggle'], ctx];
const b3 = callSlot(ctx, node, key, (ctx['current'].slot), true, {}, defaultContent1); const b3 = callSlot(ctx, node, key + \`__1\`, (ctx['current'].slot), true, {}, defaultContent1);
return block1([hdlr1], [b3]); return block1([hdlr1], [b3]);
} }
}" }"
@@ -713,7 +771,7 @@ exports[`slots fun: two calls to the same slot 1`] = `
} }
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__1\`, node, ctx, null); return comp1({slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -726,7 +784,7 @@ exports[`slots fun: two calls to the same slot 2`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const b2 = callSlot(ctx, node, key, 'default', false, {}); const b2 = callSlot(ctx, node, key, 'default', false, {});
const b3 = callSlot(ctx, node, key, 'default', false, {}); const b3 = callSlot(ctx, node, key + \`__1\`, 'default', false, {});
return multi([b2, b3]); return multi([b2, b3]);
} }
}" }"
@@ -741,7 +799,7 @@ exports[`slots missing slots are ignored 1`] = `
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 = \\"\\") {
const b2 = comp1({}, key + \`__1\`, node, ctx, null); const b2 = comp1({}, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -770,7 +828,7 @@ exports[`slots mix of slots, t-call, t-call with body, and giving own props chil
const comp1 = app.createComponent(\`P\`, true, false, false, true); const comp1 = app.createComponent(\`P\`, true, false, false, true);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({}, key + \`__1\`, node, ctx, null); return comp1({}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -786,7 +844,7 @@ exports[`slots mix of slots, t-call, t-call with body, and giving own props chil
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let hdlr1 = [ctx['inc'], ctx]; let hdlr1 = [ctx['inc'], ctx];
const b2 = block2([hdlr1]); const b2 = block2([hdlr1]);
const b3 = comp1({number: ctx['state'].number}, key + \`__1\`, node, ctx, null); const b3 = comp1({number: ctx['state'].number}, key + \`__1\`, node, this, null);
return multi([b2, b3]); return multi([b2, b3]);
} }
}" }"
@@ -808,7 +866,7 @@ exports[`slots mix of slots, t-call, t-call with body, and giving own props chil
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const ctx1 = capture(ctx); const ctx1 = capture(ctx);
return comp1({slots: markRaw({'default': {__render: slot1, __ctx: ctx1}})}, key + \`__2\`, node, ctx, null); return comp1({slots: markRaw({'default': {__render: slot1, __ctx: ctx1}})}, key + \`__2\`, node, this, null);
} }
}" }"
`; `;
@@ -856,7 +914,7 @@ exports[`slots mix of slots, t-call, t-call with body, and giving own props chil
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const b2 = text(\`[B]\`); const b2 = text(\`[B]\`);
const b3 = comp1({slots: ctx['props'].slots}, key + \`__1\`, node, ctx, null); const b3 = comp1({slots: ctx['props'].slots}, key + \`__1\`, node, this, null);
return multi([b2, b3]); return multi([b2, b3]);
} }
}" }"
@@ -894,7 +952,7 @@ exports[`slots multiple roots are allowed in a default slot 1`] = `
} }
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const b5 = comp1({slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__1\`, node, ctx, null); const b5 = comp1({slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__1\`, node, this, null);
return block1([], [b5]); return block1([], [b5]);
} }
}" }"
@@ -934,7 +992,7 @@ exports[`slots multiple roots are allowed in a named slot 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const ctx1 = capture(ctx); const ctx1 = capture(ctx);
const b5 = comp1({slots: markRaw({'content': {__render: slot1, __ctx: ctx1}})}, key + \`__1\`, node, ctx, null); const b5 = comp1({slots: markRaw({'content': {__render: slot1, __ctx: ctx1}})}, key + \`__1\`, node, this, null);
return block1([], [b5]); return block1([], [b5]);
} }
}" }"
@@ -965,16 +1023,16 @@ exports[`slots multiple slots containing components 1`] = `
const comp3 = app.createComponent(\`B\`, true, true, false, true); const comp3 = app.createComponent(\`B\`, true, true, false, true);
function slot1(ctx, node, key = \\"\\") { function slot1(ctx, node, key = \\"\\") {
return comp1({val: 1}, key + \`__1\`, node, ctx, null); return comp1({val: 1}, key + \`__1\`, node, this, null);
} }
function slot2(ctx, node, key = \\"\\") { function slot2(ctx, node, key = \\"\\") {
return comp2({val: 2}, key + \`__2\`, node, ctx, null); return comp2({val: 2}, key + \`__2\`, node, this, null);
} }
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const ctx1 = capture(ctx); const ctx1 = capture(ctx);
return comp3({slots: markRaw({'s1': {__render: slot1, __ctx: ctx1}, 's2': {__render: slot2, __ctx: ctx1}})}, key + \`__3\`, node, ctx, null); return comp3({slots: markRaw({'s1': {__render: slot1, __ctx: ctx1}, 's2': {__render: slot2, __ctx: ctx1}})}, key + \`__3\`, node, this, null);
} }
}" }"
`; `;
@@ -1028,7 +1086,7 @@ exports[`slots named slot inside slot 1`] = `
function slot2(ctx, node, key = \\"\\") { function slot2(ctx, node, key = \\"\\") {
const ctx2 = capture(ctx); const ctx2 = capture(ctx);
return comp1({slots: markRaw({'brol': {__render: slot3, __ctx: ctx2}})}, key + \`__1\`, node, ctx, null); return comp1({slots: markRaw({'brol': {__render: slot3, __ctx: ctx2}})}, key + \`__1\`, node, this, null);
} }
function slot3(ctx, node, key = \\"\\") { function slot3(ctx, node, key = \\"\\") {
@@ -1038,7 +1096,7 @@ exports[`slots named slot inside slot 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const ctx1 = capture(ctx); const ctx1 = capture(ctx);
const b5 = comp2({slots: markRaw({'brol': {__render: slot1, __ctx: ctx1}, 'default': {__render: slot2, __ctx: ctx1}})}, key + \`__2\`, node, ctx, null); const b5 = comp2({slots: markRaw({'brol': {__render: slot1, __ctx: ctx1}, 'default': {__render: slot2, __ctx: ctx1}})}, key + \`__2\`, node, this, null);
return block1([], [b5]); return block1([], [b5]);
} }
}" }"
@@ -1079,7 +1137,7 @@ exports[`slots named slot inside slot, part 3 1`] = `
function slot2(ctx, node, key = \\"\\") { function slot2(ctx, node, key = \\"\\") {
const ctx2 = capture(ctx); const ctx2 = capture(ctx);
return comp1({slots: markRaw({'brol': {__render: slot3, __ctx: ctx2}})}, key + \`__1\`, node, ctx, null); return comp1({slots: markRaw({'brol': {__render: slot3, __ctx: ctx2}})}, key + \`__1\`, node, this, null);
} }
function slot3(ctx, node, key = \\"\\") { function slot3(ctx, node, key = \\"\\") {
@@ -1089,7 +1147,7 @@ exports[`slots named slot inside slot, part 3 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const ctx1 = capture(ctx); const ctx1 = capture(ctx);
const b5 = comp2({slots: markRaw({'brol': {__render: slot1, __ctx: ctx1}, 'default': {__render: slot2, __ctx: ctx1}})}, key + \`__2\`, node, ctx, null); const b5 = comp2({slots: markRaw({'brol': {__render: slot1, __ctx: ctx1}, 'default': {__render: slot2, __ctx: ctx1}})}, key + \`__2\`, node, this, null);
return block1([], [b5]); return block1([], [b5]);
} }
}" }"
@@ -1120,7 +1178,7 @@ exports[`slots named slots can define a default content 1`] = `
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 = \\"\\") {
const b2 = comp1({}, key + \`__1\`, node, ctx, null); const b2 = comp1({}, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -1164,7 +1222,7 @@ exports[`slots named slots inside slot, again 1`] = `
function slot2(ctx, node, key = \\"\\") { function slot2(ctx, node, key = \\"\\") {
const ctx2 = capture(ctx); const ctx2 = capture(ctx);
return comp1({slots: markRaw({'brol2': {__render: slot3, __ctx: ctx2}})}, key + \`__1\`, node, ctx, null); return comp1({slots: markRaw({'brol2': {__render: slot3, __ctx: ctx2}})}, key + \`__1\`, node, this, null);
} }
function slot3(ctx, node, key = \\"\\") { function slot3(ctx, node, key = \\"\\") {
@@ -1174,7 +1232,7 @@ exports[`slots named slots inside slot, again 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const ctx1 = capture(ctx); const ctx1 = capture(ctx);
const b5 = comp2({slots: markRaw({'brol1': {__render: slot1, __ctx: ctx1}, 'default': {__render: slot2, __ctx: ctx1}})}, key + \`__2\`, node, ctx, null); const b5 = comp2({slots: markRaw({'brol1': {__render: slot1, __ctx: ctx1}, 'default': {__render: slot2, __ctx: ctx1}})}, key + \`__2\`, node, this, null);
return block1([], [b5]); return block1([], [b5]);
} }
}" }"
@@ -1217,15 +1275,15 @@ exports[`slots nested slots in same template 1`] = `
let block1 = createBlock(\`<span id=\\"parent\\"><block-child-0/></span>\`); let block1 = createBlock(\`<span id=\\"parent\\"><block-child-0/></span>\`);
function slot1(ctx, node, key = \\"\\") { function slot1(ctx, node, key = \\"\\") {
return comp2({slots: markRaw({'default': {__render: slot2, __ctx: ctx}})}, key + \`__2\`, node, ctx, null); return comp2({slots: markRaw({'default': {__render: slot2, __ctx: ctx}})}, key + \`__2\`, node, this, null);
} }
function slot2(ctx, node, key = \\"\\") { function slot2(ctx, node, key = \\"\\") {
return comp1({}, key + \`__1\`, node, ctx, null); return comp1({}, key + \`__1\`, node, this, null);
} }
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const b4 = comp3({slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__3\`, node, ctx, null); const b4 = comp3({slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__3\`, node, this, null);
return block1([], [b4]); return block1([], [b4]);
} }
}" }"
@@ -1283,11 +1341,11 @@ exports[`slots nested slots: evaluation context and parented relationship 1`] =
const comp2 = app.createComponent(\`Child\`, true, true, false, true); const comp2 = app.createComponent(\`Child\`, true, true, false, true);
function slot1(ctx, node, key = \\"\\") { function slot1(ctx, node, key = \\"\\") {
return comp1({val: ctx['state'].val}, key + \`__1\`, node, ctx, null); return comp1({val: ctx['state'].val}, key + \`__1\`, node, this, null);
} }
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp2({slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__2\`, node, ctx, null); return comp2({slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__2\`, node, this, null);
} }
}" }"
`; `;
@@ -1304,7 +1362,7 @@ exports[`slots nested slots: evaluation context and parented relationship 2`] =
} }
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__1\`, node, ctx, null); return comp1({slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -1345,7 +1403,7 @@ exports[`slots no named slot content => just no children 1`] = `
const comp1 = app.createComponent(\`Dialog\`, true, false, false, true); const comp1 = app.createComponent(\`Dialog\`, true, false, false, true);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({}, key + \`__1\`, node, ctx, null); return comp1({}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -1377,7 +1435,7 @@ exports[`slots simple default slot 1`] = `
} }
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__1\`, node, ctx, null); return comp1({slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -1415,7 +1473,7 @@ exports[`slots simple default slot with params 1`] = `
} }
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__1\`, node, ctx, null); return comp1({slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -1447,7 +1505,7 @@ exports[`slots simple default slot with params and bound function 1`] = `
} }
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({slots: markRaw({'default': {__render: slot1, __ctx: ctx, __scope: \\"slotScope\\"}})}, key + \`__1\`, node, ctx, null); return comp1({slots: markRaw({'default': {__render: slot1, __ctx: ctx, __scope: \\"slotScope\\"}})}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -1476,7 +1534,7 @@ exports[`slots simple default slot, variation 1`] = `
} }
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__1\`, node, ctx, null); return comp1({slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -1512,7 +1570,7 @@ exports[`slots simple dynamic slot with slot scope 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const ctx1 = capture(ctx); const ctx1 = capture(ctx);
return comp1({slots: markRaw({'slotName': {__render: slot1, __ctx: ctx1, __scope: \\"slotScope\\"}})}, key + \`__1\`, node, ctx, null); return comp1({slots: markRaw({'slotName': {__render: slot1, __ctx: ctx1, __scope: \\"slotScope\\"}})}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -1527,7 +1585,7 @@ exports[`slots simple dynamic slot with slot scope 2`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const slot1 = ('slotName'); const slot1 = ('slotName');
const b2 = toggler(slot1, callSlot(ctx, node, key, slot1, true, {bool: ctx['state'].bool})); const b2 = toggler(slot1, callSlot(ctx, node, key + \`__1\`, slot1, true, {bool: ctx['state'].bool}));
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -1542,7 +1600,7 @@ exports[`slots simple named and empty slot -- 2 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const ctx1 = capture(ctx); const ctx1 = capture(ctx);
return comp1({slots: markRaw({'myEmptySlot': {myProp: 'myProp text'}})}, key + \`__1\`, node, ctx, null); return comp1({slots: markRaw({'myEmptySlot': {myProp: 'myProp text'}})}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -1579,7 +1637,7 @@ exports[`slots simple named and empty slot 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const ctx1 = capture(ctx); const ctx1 = capture(ctx);
return comp1({slots: markRaw({'myEmptySlot': {}, 'default': {__render: slot1, __ctx: ctx1}})}, key + \`__1\`, node, ctx, null); return comp1({slots: markRaw({'myEmptySlot': {}, 'default': {__render: slot1, __ctx: ctx1}})}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -1619,7 +1677,7 @@ exports[`slots simple slot with slot scope 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const ctx1 = capture(ctx); const ctx1 = capture(ctx);
return comp1({slots: markRaw({'slotName': {__render: slot1, __ctx: ctx1, __scope: \\"slotScope\\"}})}, key + \`__1\`, node, ctx, null); return comp1({slots: markRaw({'slotName': {__render: slot1, __ctx: ctx1, __scope: \\"slotScope\\"}})}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -1655,7 +1713,7 @@ exports[`slots slot and (inline) t-call 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const ctx1 = capture(ctx); const ctx1 = capture(ctx);
const b3 = comp1({slots: markRaw({'default': {__render: slot1, __ctx: ctx1}})}, key + \`__2\`, node, ctx, null); const b3 = comp1({slots: markRaw({'default': {__render: slot1, __ctx: ctx1}})}, key + \`__2\`, node, this, null);
return block1([], [b3]); return block1([], [b3]);
} }
}" }"
@@ -1705,7 +1763,7 @@ exports[`slots slot and t-call 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const ctx1 = capture(ctx); const ctx1 = capture(ctx);
const b3 = comp1({slots: markRaw({'default': {__render: slot1, __ctx: ctx1}})}, key + \`__2\`, node, ctx, null); const b3 = comp1({slots: markRaw({'default': {__render: slot1, __ctx: ctx1}})}, key + \`__2\`, node, this, null);
return block1([], [b3]); return block1([], [b3]);
} }
}" }"
@@ -1753,7 +1811,7 @@ exports[`slots slot and t-esc 1`] = `
} }
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const b3 = comp1({slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__1\`, node, ctx, null); const b3 = comp1({slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__1\`, node, this, null);
return block1([], [b3]); return block1([], [b3]);
} }
}" }"
@@ -1785,13 +1843,13 @@ exports[`slots slot are properly rendered if inner props are changed 1`] = `
let block1 = createBlock(\`<div><button block-handler-0=\\"click\\">Inc[<block-text-1/>]</button><block-child-0/></div>\`); let block1 = createBlock(\`<div><button block-handler-0=\\"click\\">Inc[<block-text-1/>]</button><block-child-0/></div>\`);
function slot1(ctx, node, key = \\"\\") { function slot1(ctx, node, key = \\"\\") {
return comp1({val: ctx['state'].val}, key + \`__1\`, node, ctx, null); return comp1({val: ctx['state'].val}, key + \`__1\`, node, this, null);
} }
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let hdlr1 = [ctx['inc'], ctx]; let hdlr1 = [ctx['inc'], ctx];
let txt1 = ctx['state'].val; let txt1 = ctx['state'].val;
const b3 = comp2({slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__2\`, node, ctx, null); const b3 = comp2({slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__2\`, node, this, null);
return block1([hdlr1, txt1], [b3]); return block1([hdlr1, txt1], [b3]);
} }
}" }"
@@ -1835,11 +1893,11 @@ exports[`slots slot content has different key from other content -- dynamic slot
const comp2 = app.createComponent(\`SlotDisplay\`, true, true, false, true); const comp2 = app.createComponent(\`SlotDisplay\`, true, true, false, true);
function slot1(ctx, node, key = \\"\\") { function slot1(ctx, node, key = \\"\\") {
return comp1({parent: 'Parent'}, key + \`__1\`, node, ctx, null); return comp1({parent: 'Parent'}, key + \`__1\`, node, this, null);
} }
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp2({slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__2\`, node, ctx, null); return comp2({slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__2\`, node, this, null);
} }
}" }"
`; `;
@@ -1852,9 +1910,9 @@ exports[`slots slot content has different key from other content -- dynamic slot
const comp1 = app.createComponent(\`Child\`, true, false, false, false); const comp1 = app.createComponent(\`Child\`, true, false, false, false);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const b2 = comp1({parent: 'SlotDisplay'}, key + \`__1\`, node, ctx, null); const b2 = comp1({parent: 'SlotDisplay'}, key + \`__1\`, node, this, null);
const slot1 = (ctx['slotName']); const slot1 = (ctx['slotName']);
const b3 = toggler(slot1, callSlot(ctx, node, key, slot1, true, {})); const b3 = toggler(slot1, callSlot(ctx, node, key + \`__2\`, slot1, true, {}));
return multi([b2, b3]); return multi([b2, b3]);
} }
}" }"
@@ -1883,11 +1941,11 @@ exports[`slots slot content has different key from other content -- static slot
const comp2 = app.createComponent(\`SlotDisplay\`, true, true, false, true); const comp2 = app.createComponent(\`SlotDisplay\`, true, true, false, true);
function slot1(ctx, node, key = \\"\\") { function slot1(ctx, node, key = \\"\\") {
return comp1({parent: 'Parent'}, key + \`__1\`, node, ctx, null); return comp1({parent: 'Parent'}, key + \`__1\`, node, this, null);
} }
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp2({slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__2\`, node, ctx, null); return comp2({slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__2\`, node, this, null);
} }
}" }"
`; `;
@@ -1900,7 +1958,7 @@ exports[`slots slot content has different key from other content -- static slot
const comp1 = app.createComponent(\`Child\`, true, false, false, false); const comp1 = app.createComponent(\`Child\`, true, false, false, false);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const b2 = comp1({parent: 'SlotDisplay'}, key + \`__1\`, node, ctx, null); const b2 = comp1({parent: 'SlotDisplay'}, key + \`__1\`, node, this, null);
const b3 = callSlot(ctx, node, key, 'default', false, {}); const b3 = callSlot(ctx, node, key, 'default', false, {});
return multi([b2, b3]); return multi([b2, b3]);
} }
@@ -1940,7 +1998,7 @@ exports[`slots slot content is bound to caller (variation) 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const ctx1 = capture(ctx); const ctx1 = capture(ctx);
return comp1({slots: markRaw({'default': {__render: slot1, __ctx: ctx1}})}, key + \`__1\`, node, ctx, null); return comp1({slots: markRaw({'default': {__render: slot1, __ctx: ctx1}})}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -1975,7 +2033,7 @@ exports[`slots slot content is bound to caller 1`] = `
} }
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__1\`, node, ctx, null); return comp1({slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -1995,6 +2053,118 @@ exports[`slots slot content is bound to caller 2`] = `
}" }"
`; `;
exports[`slots slot in multiple locations 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let { markRaw } = helpers;
const comp1 = app.createComponent(\`Child\`, true, false, false, true);
const comp2 = app.createComponent(\`Slotter\`, true, true, false, false);
function slot1(ctx, node, key = \\"\\") {
const b2 = text(\` hello \`);
const b3 = comp1({}, key + \`__1\`, node, this, null);
return multi([b2, b3]);
}
return function template(ctx, node, key = \\"\\") {
return comp2({location: ctx['state'].location,slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__2\`, node, this, null);
}
}"
`;
exports[`slots slot in multiple locations 2`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let { callSlot } = helpers;
let block2 = createBlock(\`<p><block-child-0/></p>\`);
return function template(ctx, node, key = \\"\\") {
let b2,b4;
if (ctx['props'].location===1) {
const b3 = callSlot(ctx, node, key, 'default', false, {});
b2 = block2([], [b3]);
}
if (ctx['props'].location===2) {
b4 = callSlot(ctx, node, key + \`__1\`, 'default', false, {});
}
return multi([b2, b4]);
}
}"
`;
exports[`slots slot in multiple locations 3`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let block1 = createBlock(\`<div>child</div>\`);
return function template(ctx, node, key = \\"\\") {
return block1();
}
}"
`;
exports[`slots slot in t-foreach locations 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let { markRaw } = helpers;
const comp1 = app.createComponent(\`Child\`, true, false, false, true);
const comp2 = app.createComponent(\`Slotter\`, true, true, false, false);
function slot1(ctx, node, key = \\"\\") {
const b2 = text(\` hello \`);
const b3 = comp1({}, key + \`__1\`, node, this, null);
return multi([b2, b3]);
}
return function template(ctx, node, key = \\"\\") {
return comp2({list: ctx['state'].list,slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__2\`, node, this, null);
}
}"
`;
exports[`slots slot in t-foreach locations 2`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let { prepareList, callSlot, withKey } = helpers;
let block2 = createBlock(\`<p><block-text-0/><block-child-0/></p>\`);
return function template(ctx, node, key = \\"\\") {
ctx = Object.create(ctx);
const [k_block1, v_block1, l_block1, c_block1] = prepareList(ctx['props'].list);;
for (let i1 = 0; i1 < l_block1; i1++) {
ctx[\`elem\`] = v_block1[i1];
ctx[\`elem_index\`] = i1;
const key1 = ctx['elem_index'];
let txt1 = ctx['elem'];
const b3 = callSlot(ctx, node, key1, 'default', false, {});
c_block1[i1] = withKey(block2([txt1], [b3]), key1);
}
return list(c_block1);
}
}"
`;
exports[`slots slot in t-foreach locations 3`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let block1 = createBlock(\`<div>child</div>\`);
return function template(ctx, node, key = \\"\\") {
return block1();
}
}"
`;
exports[`slots slot preserves properly parented relationship 1`] = ` exports[`slots slot preserves properly parented relationship 1`] = `
"function anonymous(app, bdom, helpers "function anonymous(app, bdom, helpers
) { ) {
@@ -2006,11 +2176,11 @@ exports[`slots slot preserves properly parented relationship 1`] = `
let block1 = createBlock(\`<div><block-child-0/></div>\`); let block1 = createBlock(\`<div><block-child-0/></div>\`);
function slot1(ctx, node, key = \\"\\") { function slot1(ctx, node, key = \\"\\") {
return comp1({}, key + \`__1\`, node, ctx, null); return comp1({}, key + \`__1\`, node, this, null);
} }
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const b3 = comp2({slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__2\`, node, ctx, null); const b3 = comp2({slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__2\`, node, this, null);
return block1([], [b3]); return block1([], [b3]);
} }
}" }"
@@ -2055,7 +2225,7 @@ exports[`slots slot preserves properly parented relationship, even through t-cal
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const ctx1 = capture(ctx); const ctx1 = capture(ctx);
const b3 = comp1({slots: markRaw({'default': {__render: slot1, __ctx: ctx1}})}, key + \`__2\`, node, ctx, null); const b3 = comp1({slots: markRaw({'default': {__render: slot1, __ctx: ctx1}})}, key + \`__2\`, node, this, null);
return block1([], [b3]); return block1([], [b3]);
} }
}" }"
@@ -2068,7 +2238,7 @@ exports[`slots slot preserves properly parented relationship, even through t-cal
const comp1 = app.createComponent(\`GrandChild\`, true, false, false, true); const comp1 = app.createComponent(\`GrandChild\`, true, false, false, true);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({}, key + \`__1\`, node, ctx, null); return comp1({}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -2116,7 +2286,7 @@ exports[`slots slot with slot scope and t-props 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const ctx1 = capture(ctx); const ctx1 = capture(ctx);
return comp1({slots: markRaw({'slotName': {__render: slot1, __ctx: ctx1, __scope: \\"info\\"}})}, key + \`__1\`, node, ctx, null); return comp1({slots: markRaw({'slotName': {__render: slot1, __ctx: ctx1, __scope: \\"info\\"}})}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -2145,7 +2315,7 @@ exports[`slots slots and wrapper components 1`] = `
} }
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__1\`, node, ctx, null); return comp1({slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -2172,7 +2342,7 @@ exports[`slots slots are properly bound to correct component 1`] = `
const comp1 = app.createComponent(\`Child\`, true, false, false, true); const comp1 = app.createComponent(\`Child\`, true, false, false, true);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({}, key + \`__1\`, node, ctx, null); return comp1({}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -2218,7 +2388,7 @@ exports[`slots slots are rendered with proper context 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let txt1 = ctx['state'].val; let txt1 = ctx['state'].val;
const ctx1 = capture(ctx); const ctx1 = capture(ctx);
const b3 = comp1({slots: markRaw({'footer': {__render: slot1, __ctx: ctx1}})}, key + \`__1\`, node, ctx, null); const b3 = comp1({slots: markRaw({'footer': {__render: slot1, __ctx: ctx1}})}, key + \`__1\`, node, this, null);
return block1([txt1], [b3]); return block1([txt1], [b3]);
} }
}" }"
@@ -2262,7 +2432,7 @@ exports[`slots slots are rendered with proper context, part 2 1`] = `
ctx[\`user\`] = v_block2[i1]; ctx[\`user\`] = v_block2[i1];
const key1 = ctx['user'].id; const key1 = ctx['user'].id;
const ctx1 = capture(ctx); const ctx1 = capture(ctx);
const b7 = comp1({to: '/user/'+ctx['user'].id,slots: markRaw({'default': {__render: slot1, __ctx: ctx1}})}, key + \`__1__\${key1}\`, node, ctx, null); const b7 = comp1({to: '/user/'+ctx['user'].id,slots: markRaw({'default': {__render: slot1, __ctx: ctx1}})}, key + \`__1__\${key1}\`, node, this, null);
c_block2[i1] = withKey(block3([], [b7]), key1); c_block2[i1] = withKey(block3([], [b7]), key1);
} }
const b2 = list(c_block2); const b2 = list(c_block2);
@@ -2311,7 +2481,7 @@ exports[`slots slots are rendered with proper context, part 3 1`] = `
const key1 = ctx['user'].id; const key1 = ctx['user'].id;
setContextValue(ctx, \\"userdescr\\", 'User '+ctx['user'].name); setContextValue(ctx, \\"userdescr\\", 'User '+ctx['user'].name);
const ctx1 = capture(ctx); const ctx1 = capture(ctx);
const b5 = comp1({to: '/user/'+ctx['user'].id,slots: markRaw({'default': {__render: slot1, __ctx: ctx1}})}, key + \`__1__\${key1}\`, node, ctx, null); const b5 = comp1({to: '/user/'+ctx['user'].id,slots: markRaw({'default': {__render: slot1, __ctx: ctx1}})}, key + \`__1__\${key1}\`, node, this, null);
c_block2[i1] = withKey(block3([], [b5]), key1); c_block2[i1] = withKey(block3([], [b5]), key1);
} }
const b2 = list(c_block2); const b2 = list(c_block2);
@@ -2354,7 +2524,7 @@ exports[`slots slots are rendered with proper context, part 4 1`] = `
ctx[isBoundary] = 1 ctx[isBoundary] = 1
setContextValue(ctx, \\"userdescr\\", 'User '+ctx['state'].user.name); setContextValue(ctx, \\"userdescr\\", 'User '+ctx['state'].user.name);
const ctx1 = capture(ctx); const ctx1 = capture(ctx);
const b3 = comp1({to: '/user/'+ctx['state'].user.id,slots: markRaw({'default': {__render: slot1, __ctx: ctx1}})}, key + \`__1\`, node, ctx, null); const b3 = comp1({to: '/user/'+ctx['state'].user.id,slots: markRaw({'default': {__render: slot1, __ctx: ctx1}})}, key + \`__1\`, node, this, null);
return block1([], [b3]); return block1([], [b3]);
} }
}" }"
@@ -2396,7 +2566,7 @@ exports[`slots slots in slots, with vars 1`] = `
ctx[isBoundary] = 1 ctx[isBoundary] = 1
setContextValue(ctx, \\"test\\", ctx['state'].name); setContextValue(ctx, \\"test\\", ctx['state'].name);
const ctx1 = capture(ctx); const ctx1 = capture(ctx);
const b3 = comp1({slots: markRaw({'default': {__render: slot1, __ctx: ctx1}})}, key + \`__1\`, node, ctx, null); const b3 = comp1({slots: markRaw({'default': {__render: slot1, __ctx: ctx1}})}, key + \`__1\`, node, this, null);
return block1([], [b3]); return block1([], [b3]);
} }
}" }"
@@ -2416,7 +2586,7 @@ exports[`slots slots in slots, with vars 2`] = `
} }
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const b3 = comp1({slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__1\`, node, ctx, null); const b3 = comp1({slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__1\`, node, this, null);
return block1([], [b3]); return block1([], [b3]);
} }
}" }"
@@ -2458,7 +2628,7 @@ exports[`slots slots in t-foreach and re-rendering 1`] = `
ctx[\`n_index\`] = i1; ctx[\`n_index\`] = i1;
const key1 = ctx['n_index']; const key1 = ctx['n_index'];
const ctx1 = capture(ctx); const ctx1 = capture(ctx);
c_block2[i1] = withKey(comp1({slots: markRaw({'default': {__render: slot1, __ctx: ctx1}})}, key + \`__1__\${key1}\`, node, ctx, null), key1); c_block2[i1] = withKey(comp1({slots: markRaw({'default': {__render: slot1, __ctx: ctx1}})}, key + \`__1__\${key1}\`, node, this, null), key1);
} }
const b2 = list(c_block2); const b2 = list(c_block2);
return block1([], [b2]); return block1([], [b2]);
@@ -2513,7 +2683,7 @@ exports[`slots slots in t-foreach in t-foreach 1`] = `
ctx[\`node2\`] = v_block6[i2]; ctx[\`node2\`] = v_block6[i2];
const key2 = ctx['node2'].key; const key2 = ctx['node2'].key;
const ctx1 = capture(ctx); const ctx1 = capture(ctx);
c_block6[i2] = withKey(comp1({slots: markRaw({'default': {__render: slot1, __ctx: ctx1}})}, key + \`__1__\${key1}__\${key2}\`, node, ctx, null), key2); c_block6[i2] = withKey(comp1({slots: markRaw({'default': {__render: slot1, __ctx: ctx1}})}, key + \`__1__\${key1}__\${key2}\`, node, this, null), key2);
} }
ctx = ctx.__proto__; ctx = ctx.__proto__;
const b6 = list(c_block6); const b6 = list(c_block6);
@@ -2565,7 +2735,7 @@ exports[`slots slots in t-foreach with t-set and re-rendering 1`] = `
const key1 = ctx['n_index']; const key1 = ctx['n_index'];
setContextValue(ctx, \\"dummy\\", ctx['n_index']); setContextValue(ctx, \\"dummy\\", ctx['n_index']);
const ctx1 = capture(ctx); const ctx1 = capture(ctx);
c_block2[i1] = withKey(comp1({slots: markRaw({'default': {__render: slot1, __ctx: ctx1}})}, key + \`__1__\${key1}\`, node, ctx, null), key1); c_block2[i1] = withKey(comp1({slots: markRaw({'default': {__render: slot1, __ctx: ctx1}})}, key + \`__1__\${key1}\`, node, this, null), key1);
} }
const b2 = list(c_block2); const b2 = list(c_block2);
return block1([], [b2]); return block1([], [b2]);
@@ -2605,7 +2775,7 @@ exports[`slots t-debug on a t-set-slot (defining a slot) 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const ctx1 = capture(ctx); const ctx1 = capture(ctx);
const b3 = comp1({slots: markRaw({'content': {__render: slot1, __ctx: ctx1}})}, key + \`__1\`, node, ctx, null); const b3 = comp1({slots: markRaw({'content': {__render: slot1, __ctx: ctx1}})}, key + \`__1\`, node, this, null);
return block1([], [b3]); return block1([], [b3]);
} }
}" }"
@@ -2644,7 +2814,7 @@ exports[`slots t-set t-value in a slot 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const ctx1 = capture(ctx); const ctx1 = capture(ctx);
const b3 = comp1({slots: markRaw({'default': {__render: slot1, __ctx: ctx1}})}, key + \`__1\`, node, ctx, null); const b3 = comp1({slots: markRaw({'default': {__render: slot1, __ctx: ctx1}})}, key + \`__1\`, node, this, null);
return block1([], [b3]); return block1([], [b3]);
} }
}" }"
@@ -2706,7 +2876,7 @@ exports[`slots t-slot in recursive templates 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const ctx1 = capture(ctx); const ctx1 = capture(ctx);
return comp1({slots: markRaw({'default': {__render: slot1, __ctx: ctx1}})}, key + \`__2\`, node, ctx, null); return comp1({slots: markRaw({'default': {__render: slot1, __ctx: ctx1}})}, key + \`__2\`, node, this, null);
} }
}" }"
`; `;
@@ -2737,11 +2907,11 @@ exports[`slots t-slot nested within another slot 1`] = `
let block1 = createBlock(\`<span id=\\"c1\\"><block-child-0/></span>\`); let block1 = createBlock(\`<span id=\\"c1\\"><block-child-0/></span>\`);
function slot1(ctx, node, key = \\"\\") { function slot1(ctx, node, key = \\"\\") {
return comp1({}, key + \`__1\`, node, ctx, null); return comp1({}, key + \`__1\`, node, this, null);
} }
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const b3 = comp2({slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__2\`, node, ctx, null); const b3 = comp2({slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__2\`, node, this, null);
return block1([], [b3]); return block1([], [b3]);
} }
}" }"
@@ -2758,7 +2928,7 @@ exports[`slots t-slot nested within another slot 2`] = `
let block1 = createBlock(\`<span id=\\"c2\\"><block-child-0/></span>\`); let block1 = createBlock(\`<span id=\\"c2\\"><block-child-0/></span>\`);
function slot1(ctx, node, key = \\"\\") { function slot1(ctx, node, key = \\"\\") {
return comp1({slots: markRaw({'default': {__render: slot2, __ctx: ctx}})}, key + \`__1\`, node, ctx, null); return comp1({slots: markRaw({'default': {__render: slot2, __ctx: ctx}})}, key + \`__1\`, node, this, null);
} }
function slot2(ctx, node, key = \\"\\") { function slot2(ctx, node, key = \\"\\") {
@@ -2766,7 +2936,7 @@ exports[`slots t-slot nested within another slot 2`] = `
} }
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const b4 = comp2({slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__2\`, node, ctx, null); const b4 = comp2({slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__2\`, node, this, null);
return block1([], [b4]); return block1([], [b4]);
} }
}" }"
@@ -2829,7 +2999,7 @@ exports[`slots t-slot scope context 1`] = `
} }
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__1\`, node, ctx, null); return comp1({slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -2850,7 +3020,7 @@ exports[`slots t-slot scope context 2`] = `
} }
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__1\`, node, ctx, null); return comp1({slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -2884,7 +3054,7 @@ exports[`slots t-slot within dynamic t-call 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const ctx1 = capture(ctx); const ctx1 = capture(ctx);
const b3 = comp1({slots: markRaw({'default': {__render: slot1, __ctx: ctx1}})}, key + \`__2\`, node, ctx, null); const b3 = comp1({slots: markRaw({'default': {__render: slot1, __ctx: ctx1}})}, key + \`__2\`, node, this, null);
return block1([], [b3]); return block1([], [b3]);
} }
}" }"
@@ -2914,7 +3084,7 @@ exports[`slots t-slot within dynamic t-call 3`] = `
let block1 = createBlock(\`<div class=\\"slot\\"><block-child-0/></div>\`); let block1 = createBlock(\`<div class=\\"slot\\"><block-child-0/></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const b2 = comp1({}, key + \`__1\`, node, ctx, null); const b2 = comp1({}, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -2944,11 +3114,11 @@ exports[`slots template can just return a slot 1`] = `
let block1 = createBlock(\`<div><block-child-0/></div>\`); let block1 = createBlock(\`<div><block-child-0/></div>\`);
function slot1(ctx, node, key = \\"\\") { function slot1(ctx, node, key = \\"\\") {
return comp1({value: ctx['state'].value}, key + \`__1\`, node, ctx, null); return comp1({value: ctx['state'].value}, key + \`__1\`, node, this, null);
} }
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const b3 = comp2({slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__2\`, node, ctx, null); const b3 = comp2({slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__2\`, node, this, null);
return block1([], [b3]); return block1([], [b3]);
} }
}" }"
@@ -7,7 +7,7 @@ exports[`style and class handling can set class on multi root component 1`] = `
const comp1 = app.createComponent(\`Child\`, true, false, false, false); const comp1 = app.createComponent(\`Child\`, true, false, false, false);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({class: 'fromparent'}, key + \`__1\`, node, ctx, null); return comp1({class: 'fromparent'}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -36,7 +36,7 @@ exports[`style and class handling can set class on sub component, as prop 1`] =
const comp1 = app.createComponent(\`Child\`, true, false, false, false); const comp1 = app.createComponent(\`Child\`, true, false, false, false);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({class: 'some-class'}, key + \`__1\`, node, ctx, null); return comp1({class: 'some-class'}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -62,7 +62,7 @@ exports[`style and class handling can set class on sub sub component 1`] = `
const comp1 = app.createComponent(\`Child\`, true, false, false, false); const comp1 = app.createComponent(\`Child\`, true, false, false, false);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({class: 'fromparent'}, key + \`__1\`, node, ctx, null); return comp1({class: 'fromparent'}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -74,7 +74,7 @@ exports[`style and class handling can set class on sub sub component 2`] = `
const comp1 = app.createComponent(\`ChildChild\`, true, false, false, false); const comp1 = app.createComponent(\`ChildChild\`, true, false, false, false);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({class: (ctx['props'].class||'')+' fromchild'}, key + \`__1\`, node, ctx, null); return comp1({class: (ctx['props'].class||'')+' fromchild'}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -100,7 +100,7 @@ exports[`style and class handling can set more than one class on sub component 1
const comp1 = app.createComponent(\`Child\`, true, false, false, false); const comp1 = app.createComponent(\`Child\`, true, false, false, false);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({class: 'a b'}, key + \`__1\`, node, ctx, null); return comp1({class: 'a b'}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -153,7 +153,7 @@ exports[`style and class handling class on sub component, which is switched to a
const comp1 = app.createComponent(\`Child\`, true, false, false, false); const comp1 = app.createComponent(\`Child\`, true, false, false, false);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({class: 'someclass',child: ctx['state'].child}, key + \`__1\`, node, ctx, null); return comp1({class: 'someclass',child: ctx['state'].child}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -168,9 +168,9 @@ exports[`style and class handling class on sub component, which is switched to a
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let b2,b3; let b2,b3;
if (ctx['props'].child==='a') { if (ctx['props'].child==='a') {
b2 = comp1({class: ctx['props'].class}, key + \`__1\`, node, ctx, null); b2 = comp1({class: ctx['props'].class}, key + \`__1\`, node, this, null);
} else { } else {
b3 = comp2({class: ctx['props'].class}, key + \`__2\`, node, ctx, null); b3 = comp2({class: ctx['props'].class}, key + \`__2\`, node, this, null);
} }
return multi([b2, b3]); return multi([b2, b3]);
} }
@@ -214,7 +214,7 @@ exports[`style and class handling class with extra whitespaces (variation) 1`] =
let block1 = createBlock(\`<p><block-child-0/></p>\`); let block1 = createBlock(\`<p><block-child-0/></p>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const b2 = comp1({class: 'a b c d'}, key + \`__1\`, node, ctx, null); const b2 = comp1({class: 'a b c d'}, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -241,7 +241,7 @@ exports[`style and class handling class with extra whitespaces 1`] = `
const comp1 = app.createComponent(\`Child\`, true, false, false, false); const comp1 = app.createComponent(\`Child\`, true, false, false, false);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({class: 'a b c d'}, key + \`__1\`, node, ctx, null); return comp1({class: 'a b c d'}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -267,7 +267,7 @@ exports[`style and class handling component class and parent class combine toget
const comp1 = app.createComponent(\`Child\`, true, false, false, false); const comp1 = app.createComponent(\`Child\`, true, false, false, false);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({class: 'from parent'}, key + \`__1\`, node, ctx, null); return comp1({class: 'from parent'}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -322,7 +322,7 @@ exports[`style and class handling empty class attribute is not added on widget r
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 = \\"\\") {
const b2 = comp1({class: undefined}, key + \`__1\`, node, ctx, null); const b2 = comp1({class: undefined}, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -349,7 +349,7 @@ exports[`style and class handling error in subcomponent with class 1`] = `
const comp1 = app.createComponent(\`Child\`, true, false, false, false); const comp1 = app.createComponent(\`Child\`, true, false, false, false);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({class: 'a'}, key + \`__1\`, node, ctx, null); return comp1({class: 'a'}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -376,7 +376,7 @@ exports[`style and class handling no class is set is child ignores it 1`] = `
const comp1 = app.createComponent(\`Child\`, true, false, false, false); const comp1 = app.createComponent(\`Child\`, true, false, false, false);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({class: 'hey'}, key + \`__1\`, node, ctx, null); return comp1({class: 'hey'}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -401,7 +401,7 @@ exports[`style and class handling no class is set is parent does not give it as
const comp1 = app.createComponent(\`Child\`, true, false, false, true); const comp1 = app.createComponent(\`Child\`, true, false, false, true);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({}, key + \`__1\`, node, ctx, null); return comp1({}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -427,7 +427,7 @@ exports[`style and class handling style is properly added on widget root el 1`]
const comp1 = app.createComponent(\`Child\`, true, false, false, false); const comp1 = app.createComponent(\`Child\`, true, false, false, false);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({style: 'font-weight: bold;'}, key + \`__1\`, node, ctx, null); return comp1({style: 'font-weight: bold;'}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -455,7 +455,7 @@ exports[`style and class handling t-att-class is properly added/removed on widge
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 = \\"\\") {
const b2 = comp1({class: {b:ctx['state'].b}}, key + \`__1\`, node, ctx, null); const b2 = comp1({class: {b:ctx['state'].b}}, key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -482,7 +482,7 @@ exports[`style and class handling t-att-class is properly added/removed on widge
const comp1 = app.createComponent(\`Child\`, true, false, false, false); const comp1 = app.createComponent(\`Child\`, true, false, false, false);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({class: {a:true,b:ctx['state'].b}}, key + \`__1\`, node, ctx, null); return comp1({class: {a:true,b:ctx['state'].b}}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -50,7 +50,7 @@ exports[`t-call dynamic t-call: key is propagated 1`] = `
const call = app.callTemplate.bind(app); const call = app.callTemplate.bind(app);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const b2 = comp1({}, key + \`__1\`, node, ctx, null); const b2 = comp1({}, key + \`__1\`, node, this, null);
const template1 = (ctx['sub']); const template1 = (ctx['sub']);
const b3 = call(this, template1, ctx, node, key + \`__2\`); const b3 = call(this, template1, ctx, node, key + \`__2\`);
return multi([b2, b3]); return multi([b2, b3]);
@@ -79,7 +79,7 @@ exports[`t-call dynamic t-call: key is propagated 3`] = `
const comp1 = app.createComponent(\`Child\`, true, false, false, true); const comp1 = app.createComponent(\`Child\`, true, false, false, true);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({}, key + \`__1\`, node, ctx, null); return comp1({}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -197,7 +197,7 @@ exports[`t-call parent is set within t-call 2`] = `
const comp1 = app.createComponent(\`Child\`, true, false, false, true); const comp1 = app.createComponent(\`Child\`, true, false, false, true);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({}, key + \`__1\`, node, ctx, null); return comp1({}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -234,7 +234,7 @@ exports[`t-call parent is set within t-call with no parentNode 2`] = `
const comp1 = app.createComponent(\`Child\`, true, false, false, true); const comp1 = app.createComponent(\`Child\`, true, false, false, true);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({}, key + \`__1\`, node, ctx, null); return comp1({}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -331,7 +331,7 @@ exports[`t-call sub components in two t-calls 2`] = `
const comp1 = app.createComponent(\`Child\`, true, false, false, false); const comp1 = app.createComponent(\`Child\`, true, false, false, false);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({val: ctx['state'].val}, key + \`__1\`, node, ctx, null); return comp1({val: ctx['state'].val}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -384,7 +384,7 @@ exports[`t-call t-call in t-foreach and children component 2`] = `
const comp1 = app.createComponent(\`Child\`, true, false, false, false); const comp1 = app.createComponent(\`Child\`, true, false, false, false);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({val: ctx['val']}, key + \`__1\`, node, ctx, null); return comp1({val: ctx['val']}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -402,3 +402,115 @@ exports[`t-call t-call in t-foreach and children component 3`] = `
} }
}" }"
`; `;
exports[`t-call t-call with t-call-context and subcomponent 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
const callTemplate_1 = app.getTemplate(\`someTemplate\`);
return function template(ctx, node, key = \\"\\") {
let ctx1 = ctx['subctx'];
return callTemplate_1.call(this, ctx1, node, key + \`__1\`);
}
}"
`;
exports[`t-call t-call with t-call-context and subcomponent 2`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
const comp1 = app.createComponent(\`Child\`, true, false, false, false);
const comp2 = app.createComponent(\`Child\`, true, false, false, false);
return function template(ctx, node, key = \\"\\") {
const b2 = comp1({name: ctx['aab']}, key + \`__1\`, node, this, null);
const b3 = comp2({name: ctx['lpe']}, key + \`__2\`, node, this, null);
return multi([b2, b3]);
}
}"
`;
exports[`t-call t-call with t-call-context and subcomponent 3`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
return function template(ctx, node, key = \\"\\") {
const b2 = text(\`child\`);
const b3 = text(ctx['props'].name);
return multi([b2, b3]);
}
}"
`;
exports[`t-call t-call with t-call-context and subcomponent, in dev mode 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
const callTemplate_1 = app.getTemplate(\`someTemplate\`);
return function template(ctx, node, key = \\"\\") {
let ctx1 = ctx['subctx'];
return callTemplate_1.call(this, ctx1, node, key + \`__1\`);
}
}"
`;
exports[`t-call t-call with t-call-context and subcomponent, in dev mode 2`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
const comp1 = app.createComponent(\`Child\`, true, false, false, false);
const comp2 = app.createComponent(\`Child\`, true, false, false, false);
return function template(ctx, node, key = \\"\\") {
const props1 = {name: ctx['aab']};
helpers.validateProps(\`Child\`, props1, this);
const b2 = comp1(props1, key + \`__1\`, node, this, null);
const props2 = {name: ctx['lpe']};
helpers.validateProps(\`Child\`, props2, this);
const b3 = comp2(props2, key + \`__2\`, node, this, null);
return multi([b2, b3]);
}
}"
`;
exports[`t-call t-call with t-call-context and subcomponent, in dev mode 3`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
return function template(ctx, node, key = \\"\\") {
const b2 = text(\`child\`);
const b3 = text(ctx['props'].name);
return multi([b2, b3]);
}
}"
`;
exports[`t-call t-call with t-call-context, simple use 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
const callTemplate_1 = app.getTemplate(\`someTemplate\`);
return function template(ctx, node, key = \\"\\") {
let ctx1 = ctx['subctx'];
return callTemplate_1.call(this, ctx1, node, key + \`__1\`);
}
}"
`;
exports[`t-call t-call with t-call-context, simple use 2`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
return function template(ctx, node, key = \\"\\") {
const b2 = text(ctx['aab']);
const b3 = text(ctx['lpe']);
return multi([b2, b3]);
}
}"
`;
@@ -10,7 +10,7 @@ exports[`t-component can switch between dynamic components without the need for
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const Comp1 = ctx['constructor'].components[ctx['state'].child]; const Comp1 = ctx['constructor'].components[ctx['state'].child];
const b2 = toggler(Comp1, comp1({}, key + \`__1\`, node, ctx, Comp1)); const b2 = toggler(Comp1, comp1({}, key + \`__1\`, node, this, Comp1));
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -51,7 +51,7 @@ exports[`t-component can use dynamic components (the class) if given (with diffe
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const tKey_1 = ctx['state'].child; const tKey_1 = ctx['state'].child;
const Comp1 = ctx['myComponent']; const Comp1 = ctx['myComponent'];
return toggler(tKey_1, toggler(Comp1, comp1({}, tKey_1 + key + \`__1\`, node, ctx, Comp1))); return toggler(tKey_1, toggler(Comp1, comp1({}, tKey_1 + key + \`__1\`, node, this, Comp1)));
} }
}" }"
`; `;
@@ -91,7 +91,7 @@ exports[`t-component can use dynamic components (the class) if given 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const tKey_1 = ctx['state'].child; const tKey_1 = ctx['state'].child;
const Comp1 = ctx['myComponent']; const Comp1 = ctx['myComponent'];
return toggler(tKey_1, toggler(Comp1, comp1({}, tKey_1 + key + \`__1\`, node, ctx, Comp1))); return toggler(tKey_1, toggler(Comp1, comp1({}, tKey_1 + key + \`__1\`, node, this, Comp1)));
} }
}" }"
`; `;
@@ -132,7 +132,7 @@ exports[`t-component modifying a sub widget 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const Comp1 = ctx['Counter']; const Comp1 = ctx['Counter'];
const b2 = toggler(Comp1, comp1({}, key + \`__1\`, node, ctx, Comp1)); const b2 = toggler(Comp1, comp1({}, key + \`__1\`, node, this, Comp1));
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -162,7 +162,7 @@ exports[`t-component switching dynamic component 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const Comp1 = ctx['Child']; const Comp1 = ctx['Child'];
return toggler(Comp1, comp1({}, key + \`__1\`, node, ctx, Comp1)); return toggler(Comp1, comp1({}, key + \`__1\`, node, this, Comp1));
} }
}" }"
`; `;
@@ -199,7 +199,7 @@ exports[`t-component t-component works in simple case 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const Comp1 = ctx['Child']; const Comp1 = ctx['Child'];
return toggler(Comp1, comp1({}, key + \`__1\`, node, ctx, Comp1)); return toggler(Comp1, comp1({}, key + \`__1\`, node, this, Comp1));
} }
}" }"
`; `;
@@ -16,7 +16,7 @@ exports[`list of components components in a node in a t-foreach 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];
const key1 = 'li_'+ctx['item']; const key1 = 'li_'+ctx['item'];
const b4 = comp1({item: ctx['item']}, key + \`__1__\${key1}\`, node, ctx, null); const b4 = comp1({item: ctx['item']}, key + \`__1__\${key1}\`, node, this, null);
c_block2[i1] = withKey(block3([], [b4]), key1); c_block2[i1] = withKey(block3([], [b4]), key1);
} }
const b2 = list(c_block2); const b2 = list(c_block2);
@@ -43,7 +43,7 @@ exports[`list of components crash on duplicate key in dev mode 1`] = `
"function anonymous(app, bdom, helpers "function anonymous(app, bdom, helpers
) { ) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom; let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let { prepareList, withKey } = helpers; let { prepareList, OwlError, withKey } = helpers;
const comp1 = app.createComponent(\`Child\`, true, false, false, true); const comp1 = app.createComponent(\`Child\`, true, false, false, true);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
@@ -53,11 +53,11 @@ exports[`list of components crash on duplicate key in dev mode 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];
const key1 = 'child'; const key1 = 'child';
if (keys1.has(key1)) { throw new Error(\`Got duplicate key in t-foreach: \${key1}\`)} if (keys1.has(key1)) { throw new OwlError(\`Got duplicate key in t-foreach: \${key1}\`)}
keys1.add(key1); keys1.add(key1);
const props1 = {}; const props1 = {};
helpers.validateProps(\`Child\`, props1, ctx); helpers.validateProps(\`Child\`, props1, this);
c_block1[i1] = withKey(comp1(props1, key + \`__1__\${key1}\`, node, ctx, null), key1); c_block1[i1] = withKey(comp1(props1, key + \`__1__\${key1}\`, node, this, null), key1);
} }
return list(c_block1); return list(c_block1);
} }
@@ -91,7 +91,7 @@ exports[`list of components list of sub components inside other nodes 1`] = `
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];
const key1 = ctx['blip'].id; const key1 = ctx['blip'].id;
const b4 = comp1({}, key + \`__1__\${key1}\`, node, ctx, null); const b4 = comp1({}, key + \`__1__\${key1}\`, node, this, null);
c_block2[i1] = withKey(block3([], [b4]), key1); c_block2[i1] = withKey(block3([], [b4]), key1);
} }
const b2 = list(c_block2); const b2 = list(c_block2);
@@ -135,7 +135,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;
const key2 = ctx['blip_index']; const key2 = ctx['blip_index'];
c_block3[i2] = withKey(comp1({blip: ctx['blip']}, key + \`__1__\${key1}__\${key2}\`, node, ctx, null), key2); c_block3[i2] = withKey(comp1({blip: ctx['blip']}, key + \`__1__\${key1}__\${key2}\`, node, this, null), key2);
} }
ctx = ctx.__proto__; ctx = ctx.__proto__;
c_block2[i1] = withKey(list(c_block3), key1); c_block2[i1] = withKey(list(c_block3), key1);
@@ -182,7 +182,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];
const key2 = ctx['col']; const key2 = ctx['col'];
const b6 = comp1({row: ctx['row'],col: ctx['col']}, key + \`__1__\${key1}__\${key2}\`, node, ctx, null); const b6 = comp1({row: ctx['row'],col: ctx['col']}, key + \`__1__\${key1}__\${key2}\`, node, this, null);
c_block4[i2] = withKey(block5([], [b6]), key2); c_block4[i2] = withKey(block5([], [b6]), key2);
} }
ctx = ctx.__proto__; ctx = ctx.__proto__;
@@ -222,7 +222,7 @@ exports[`list of components simple list 1`] = `
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];
const key1 = ctx['elem'].id; const key1 = ctx['elem'].id;
c_block1[i1] = withKey(comp1({value: ctx['elem'].value}, key + \`__1__\${key1}\`, node, ctx, null), key1); c_block1[i1] = withKey(comp1({value: ctx['elem'].value}, key + \`__1__\${key1}\`, node, this, null), key1);
} }
return list(c_block1); return list(c_block1);
} }
@@ -258,7 +258,7 @@ exports[`list of components sub components rendered in a loop 1`] = `
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];
const key1 = ctx['number']; const key1 = ctx['number'];
c_block2[i1] = withKey(comp1({n: ctx['number']}, key + \`__1__\${key1}\`, node, ctx, null), key1); c_block2[i1] = withKey(comp1({n: ctx['number']}, key + \`__1__\${key1}\`, node, this, null), key1);
} }
const b2 = list(c_block2); const b2 = list(c_block2);
return block1([], [b2]); return block1([], [b2]);
@@ -295,7 +295,7 @@ exports[`list of components sub components with some state rendered in a loop 1`
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];
const key1 = ctx['number']; const key1 = ctx['number'];
c_block2[i1] = withKey(comp1({}, key + \`__1__\${key1}\`, node, ctx, null), key1); c_block2[i1] = withKey(comp1({}, key + \`__1__\${key1}\`, node, this, null), key1);
} }
const b2 = list(c_block2); const b2 = list(c_block2);
return block1([], [b2]); return block1([], [b2]);
@@ -332,7 +332,7 @@ exports[`list of components switch component position 1`] = `
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];
const key1 = ctx['c']; const key1 = ctx['c'];
c_block2[i1] = withKey(comp1({key: ctx['c']}, key + \`__1__\${key1}\`, node, ctx, null), key1); c_block2[i1] = withKey(comp1({key: ctx['c']}, key + \`__1__\${key1}\`, node, this, null), key1);
} }
const b2 = list(c_block2); const b2 = list(c_block2);
return block1([], [b2]); return block1([], [b2]);
@@ -370,7 +370,7 @@ exports[`list of components t-foreach with t-component, and update 1`] = `
ctx[\`n\`] = v_block2[i1]; ctx[\`n\`] = v_block2[i1];
ctx[\`n_index\`] = i1; ctx[\`n_index\`] = i1;
const key1 = ctx['n_index']; const key1 = ctx['n_index'];
c_block2[i1] = withKey(comp1({val: ctx['n_index']}, key + \`__1__\${key1}\`, node, ctx, null), key1); c_block2[i1] = withKey(comp1({val: ctx['n_index']}, key + \`__1__\${key1}\`, node, this, null), key1);
} }
const b2 = list(c_block2); const b2 = list(c_block2);
return block1([], [b2]); return block1([], [b2]);
@@ -16,7 +16,7 @@ exports[`t-key t-foreach with t-key switch component position 1`] = `
ctx[\`c\`] = v_block2[i1]; ctx[\`c\`] = v_block2[i1];
const key1 = ctx['c']; const key1 = ctx['c'];
const tKey_1 = ctx['key1']; const tKey_1 = ctx['key1'];
c_block2[i1] = withKey(comp1({key: ctx['c']+ctx['key1']}, tKey_1 + key + \`__1__\${key1}\`, node, ctx, null), tKey_1 + key1); c_block2[i1] = withKey(comp1({key: ctx['c']+ctx['key1']}, tKey_1 + key + \`__1__\${key1}\`, node, this, null), tKey_1 + key1);
} }
const b2 = list(c_block2); const b2 = list(c_block2);
return block1([], [b2]); return block1([], [b2]);
@@ -46,7 +46,7 @@ exports[`t-key t-key on Component 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const tKey_1 = ctx['key']; const tKey_1 = ctx['key'];
return toggler(tKey_1, comp1({key: ctx['key']}, tKey_1 + key + \`__1\`, node, ctx, null)); return toggler(tKey_1, comp1({key: ctx['key']}, tKey_1 + key + \`__1\`, node, this, null));
} }
}" }"
`; `;
@@ -75,7 +75,7 @@ exports[`t-key t-key on Component as a function 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const tKey_1 = ctx['key']; const tKey_1 = ctx['key'];
const b2 = toggler(tKey_1, comp1({key: ctx['key']}, tKey_1 + key + \`__1\`, node, ctx, null)); const b2 = toggler(tKey_1, comp1({key: ctx['key']}, tKey_1 + key + \`__1\`, node, this, null));
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -106,9 +106,9 @@ exports[`t-key t-key on multiple Components 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const tKey_1 = ctx['key1']; const tKey_1 = ctx['key1'];
const b2 = toggler(tKey_1, comp1({key: ctx['key1']}, tKey_1 + key + \`__1\`, node, ctx, null)); const b2 = toggler(tKey_1, comp1({key: ctx['key1']}, tKey_1 + key + \`__1\`, node, this, null));
const tKey_2 = ctx['key2']; const tKey_2 = ctx['key2'];
const b3 = toggler(tKey_2, comp2({key: ctx['key2']}, tKey_2 + key + \`__2\`, node, ctx, null)); const b3 = toggler(tKey_2, comp2({key: ctx['key2']}, tKey_2 + key + \`__2\`, node, this, null));
return block1([], [b2, b3]); return block1([], [b2, b3]);
} }
}" }"
@@ -163,7 +163,7 @@ exports[`t-key t-key on multiple Components with t-call 1 2`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const tKey_1 = ctx['key']; const tKey_1 = ctx['key'];
return toggler(tKey_1, comp1({key: ctx['key']}, tKey_1 + key + \`__1\`, node, ctx, null)); return toggler(tKey_1, comp1({key: ctx['key']}, tKey_1 + key + \`__1\`, node, this, null));
} }
}" }"
`; `;
@@ -206,9 +206,9 @@ exports[`t-key t-key on multiple Components with t-call 2 2`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const tKey_1 = ctx['key1']; const tKey_1 = ctx['key1'];
const b2 = toggler(tKey_1, comp1({key: ctx['key1']}, tKey_1 + key + \`__1\`, node, ctx, null)); const b2 = toggler(tKey_1, comp1({key: ctx['key1']}, tKey_1 + key + \`__1\`, node, this, null));
const tKey_2 = ctx['key2']; const tKey_2 = ctx['key2'];
const b3 = toggler(tKey_2, comp2({key: ctx['key2']}, tKey_2 + key + \`__2\`, node, ctx, null)); const b3 = toggler(tKey_2, comp2({key: ctx['key2']}, tKey_2 + key + \`__2\`, node, this, null));
return multi([b2, b3]); return multi([b2, b3]);
} }
}" }"
@@ -133,7 +133,7 @@ exports[`t-on t-on on component next to t-on on div 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const hdlr1 = [ctx['increment'], ctx]; const hdlr1 = [ctx['increment'], ctx];
const b2 = catcher1(comp1({value: ctx['state'].value}, key + \`__1\`, node, ctx, null), [hdlr1]); const b2 = catcher1(comp1({value: ctx['state'].value}, key + \`__1\`, node, this, null), [hdlr1]);
let hdlr2 = [ctx['decrement'], ctx]; let hdlr2 = [ctx['decrement'], ctx];
return block1([hdlr2], [b2]); return block1([hdlr2], [b2]);
} }
@@ -164,7 +164,7 @@ exports[`t-on t-on on components 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const hdlr1 = [ctx['increment'], ctx]; const hdlr1 = [ctx['increment'], ctx];
return catcher1(comp1({value: ctx['state'].value}, key + \`__1\`, node, ctx, null), [hdlr1]); return catcher1(comp1({value: ctx['state'].value}, key + \`__1\`, node, this, null), [hdlr1]);
} }
}" }"
`; `;
@@ -199,7 +199,7 @@ exports[`t-on t-on on components and t-foreach 1`] = `
const key1 = ctx['name']; const key1 = ctx['name'];
const v1 = ctx['name']; const v1 = ctx['name'];
const hdlr1 = [()=>this.log(v1), ctx]; const hdlr1 = [()=>this.log(v1), ctx];
c_block1[i1] = withKey(catcher1(comp1({value: ctx['name']}, key + \`__1__\${key1}\`, node, ctx, null), [hdlr1]), key1); c_block1[i1] = withKey(catcher1(comp1({value: ctx['name']}, key + \`__1__\${key1}\`, node, this, null), [hdlr1]), key1);
} }
return list(c_block1); return list(c_block1);
} }
@@ -232,7 +232,7 @@ exports[`t-on t-on on components, variation 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const hdlr1 = [ctx['increment'], ctx]; const hdlr1 = [ctx['increment'], ctx];
const b2 = catcher1(comp1({value: ctx['state'].value}, key + \`__1\`, node, ctx, null), [hdlr1]); const b2 = catcher1(comp1({value: ctx['state'].value}, key + \`__1\`, node, this, null), [hdlr1]);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -262,7 +262,7 @@ exports[`t-on t-on on components, with 'prevent' modifier 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const hdlr1 = [\\"prevent\\", ctx['increment'], ctx]; const hdlr1 = [\\"prevent\\", ctx['increment'], ctx];
return catcher1(comp1({value: ctx['state'].value}, key + \`__1\`, node, ctx, null), [hdlr1]); return catcher1(comp1({value: ctx['state'].value}, key + \`__1\`, node, this, null), [hdlr1]);
} }
}" }"
`; `;
@@ -295,7 +295,7 @@ exports[`t-on t-on on components, with a handler update 1`] = `
setContextValue(ctx, \\"name\\", ctx['state'].name); setContextValue(ctx, \\"name\\", ctx['state'].name);
const v1 = ctx['name']; const v1 = ctx['name'];
const hdlr1 = [()=>this.log(v1), ctx]; const hdlr1 = [()=>this.log(v1), ctx];
return catcher1(comp1({value: ctx['name']}, key + \`__1\`, node, ctx, null), [hdlr1]); return catcher1(comp1({value: ctx['name']}, key + \`__1\`, node, this, null), [hdlr1]);
} }
}" }"
`; `;
@@ -325,7 +325,7 @@ exports[`t-on t-on on destroyed components 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let b2; let b2;
if (ctx['state'].flag) { if (ctx['state'].flag) {
b2 = comp1({}, key + \`__1\`, node, ctx, null); b2 = comp1({}, key + \`__1\`, node, this, null);
} }
return block1([], [b2]); return block1([], [b2]);
} }
@@ -360,7 +360,7 @@ exports[`t-on t-on on slot, with 'prevent' modifier 1`] = `
} }
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__1\`, node, ctx, null); return comp1({slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -402,7 +402,7 @@ exports[`t-on t-on on t-set-slots 1`] = `
const b3 = text(ctx['state'].count); const b3 = text(ctx['state'].count);
const b4 = text(\`] \`); const b4 = text(\`] \`);
const ctx1 = capture(ctx); const ctx1 = capture(ctx);
const b8 = comp1({slots: markRaw({'myslot': {__render: slot1, __ctx: ctx1}})}, key + \`__1\`, node, ctx, null); const b8 = comp1({slots: markRaw({'myslot': {__render: slot1, __ctx: ctx1}})}, key + \`__1\`, node, this, null);
return multi([b2, b3, b4, b8]); return multi([b2, b3, b4, b8]);
} }
}" }"
@@ -434,7 +434,7 @@ exports[`t-on t-on on t-slots 1`] = `
} }
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1({slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__1\`, node, ctx, null); return comp1({slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -0,0 +1,39 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`components in t-out simple list 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let { prepareList, isBoundary, withDefault, LazyValue, safeOutput, withKey } = helpers;
const comp1 = app.createComponent(\`Child\`, true, false, false, true);
function value1(ctx, node, key = \\"\\") {
return comp1({}, key + \`__1\`, node, this, null);
}
return function template(ctx, node, key = \\"\\") {
ctx = Object.create(ctx);
ctx[isBoundary] = 1
ctx = Object.create(ctx);
const [k_block1, v_block1, l_block1, c_block1] = prepareList([1,2]);;
for (let i1 = 0; i1 < l_block1; i1++) {
ctx[\`n\`] = v_block1[i1];
const key1 = ctx['n'];
ctx[\`blabla\`] = new LazyValue(value1, ctx, this, node, key1);
c_block1[i1] = withKey(safeOutput(ctx['blabla']), key1);
}
return list(c_block1);
}
}"
`;
exports[`components in t-out simple list 2`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
return function template(ctx, node, key = \\"\\") {
return text(\`child\`);
}
}"
`;
@@ -9,7 +9,7 @@ exports[`t-props basic use 1`] = `
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 = \\"\\") {
const b2 = comp1(Object.assign({}, ctx['some'].obj), key + \`__1\`, node, ctx, null); const b2 = comp1(Object.assign({}, ctx['some'].obj), key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -36,7 +36,7 @@ exports[`t-props child receives a copy of the t-props object, not the original 1
const comp1 = app.createComponent(\`Child\`, true, false, true, false); const comp1 = app.createComponent(\`Child\`, true, false, true, false);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
return comp1(Object.assign({}, ctx['childProps']), key + \`__1\`, node, ctx, null); return comp1(Object.assign({}, ctx['childProps']), key + \`__1\`, node, this, null);
} }
}" }"
`; `;
@@ -63,7 +63,7 @@ exports[`t-props t-props and other props 1`] = `
let block1 = createBlock(\`<div><div><block-child-0/></div></div>\`); let block1 = createBlock(\`<div><div><block-child-0/></div></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const b2 = comp1(Object.assign({}, ctx['state1'], {a: ctx['a']}), key + \`__1\`, node, ctx, null); const b2 = comp1(Object.assign({}, ctx['state1'], {a: ctx['a']}), key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -93,7 +93,7 @@ exports[`t-props t-props only 1`] = `
let block1 = createBlock(\`<div><div><block-child-0/></div></div>\`); let block1 = createBlock(\`<div><div><block-child-0/></div></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const b2 = comp1(Object.assign({}, ctx['state']), key + \`__1\`, node, ctx, null); const b2 = comp1(Object.assign({}, ctx['state']), key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -122,7 +122,7 @@ exports[`t-props t-props with props 1`] = `
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 = \\"\\") {
const b2 = comp1(Object.assign({}, ctx['childProps'], {a: 1,b: 2}), key + \`__1\`, node, ctx, null); const b2 = comp1(Object.assign({}, ctx['childProps'], {a: 1,b: 2}), key + \`__1\`, node, this, null);
return block1([], [b2]); return block1([], [b2]);
} }
}" }"
@@ -22,7 +22,7 @@ exports[`t-set slot setted value (with t-set) not accessible with t-esc 1`] = `
setContextValue(ctx, \\"iter\\", 'source'); setContextValue(ctx, \\"iter\\", 'source');
let txt1 = ctx['iter']; let txt1 = ctx['iter'];
const ctx1 = capture(ctx); const ctx1 = capture(ctx);
const b2 = comp1({slots: markRaw({'default': {__render: slot1, __ctx: ctx1}})}, key + \`__1\`, node, ctx, null); const b2 = comp1({slots: markRaw({'default': {__render: slot1, __ctx: ctx1}})}, key + \`__1\`, node, this, null);
let txt2 = ctx['iter']; let txt2 = ctx['iter'];
return block1([txt1, txt2], [b2]); return block1([txt1, txt2], [b2]);
} }
@@ -59,19 +59,19 @@ exports[`t-set slots with a t-set with a component in body 1`] = `
function slot1(ctx, node, key = \\"\\") { function slot1(ctx, node, key = \\"\\") {
ctx = Object.create(ctx); ctx = Object.create(ctx);
ctx[isBoundary] = 1 ctx[isBoundary] = 1
ctx[\`v\`] = new LazyValue(value1, ctx, node); ctx[\`v\`] = new LazyValue(value1, ctx, this, node, key);
const b3 = text(\` in slot \`); const b3 = text(\` in slot \`);
const b4 = safeOutput(ctx['v']); const b4 = safeOutput(ctx['v']);
return multi([b3, b4]); return multi([b3, b4]);
} }
function value1(ctx, node, key = \\"\\") { function value1(ctx, node, key = \\"\\") {
return comp1({}, key + \`__1\`, node, ctx, null); return comp1({}, key + \`__1\`, node, this, null);
} }
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const ctx1 = capture(ctx); const ctx1 = capture(ctx);
return comp2({slots: markRaw({'default': {__render: slot1, __ctx: ctx1}})}, key + \`__2\`, node, ctx, null); return comp2({slots: markRaw({'default': {__render: slot1, __ctx: ctx1}})}, key + \`__2\`, node, this, null);
} }
}" }"
`; `;
@@ -114,21 +114,21 @@ exports[`t-set slots with an t-set with a component in body 1`] = `
function slot1(ctx, node, key = \\"\\") { function slot1(ctx, node, key = \\"\\") {
ctx = Object.create(ctx); ctx = Object.create(ctx);
ctx[isBoundary] = 1 ctx[isBoundary] = 1
ctx[\`v\`] = new LazyValue(value1, ctx, node); ctx[\`v\`] = new LazyValue(value1, ctx, this, node, key);
const b5 = text(\` tea \`); const b5 = text(\` tea \`);
const b6 = safeOutput(ctx['v']); const b6 = safeOutput(ctx['v']);
return multi([b5, b6]); return multi([b5, b6]);
} }
function value1(ctx, node, key = \\"\\") { function value1(ctx, node, key = \\"\\") {
const b3 = comp1({}, key + \`__1\`, node, ctx, null); const b3 = comp1({}, key + \`__1\`, node, this, null);
const b4 = block4(); const b4 = block4();
return multi([b3, b4]); return multi([b3, b4]);
} }
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const ctx1 = capture(ctx); const ctx1 = capture(ctx);
return comp2({slots: markRaw({'default': {__render: slot1, __ctx: ctx1}})}, key + \`__2\`, node, ctx, null); return comp2({slots: markRaw({'default': {__render: slot1, __ctx: ctx1}})}, key + \`__2\`, node, this, null);
} }
}" }"
`; `;
@@ -169,17 +169,17 @@ exports[`t-set slots with an unused t-set with a component in body 1`] = `
function slot1(ctx, node, key = \\"\\") { function slot1(ctx, node, key = \\"\\") {
ctx = Object.create(ctx); ctx = Object.create(ctx);
ctx[isBoundary] = 1 ctx[isBoundary] = 1
ctx[\`v\`] = new LazyValue(value1, ctx, node); ctx[\`v\`] = new LazyValue(value1, ctx, this, node, key);
return text(\` in slot \`); return text(\` in slot \`);
} }
function value1(ctx, node, key = \\"\\") { function value1(ctx, node, key = \\"\\") {
return comp1({}, key + \`__1\`, node, ctx, null); return comp1({}, key + \`__1\`, node, this, null);
} }
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const ctx1 = capture(ctx); const ctx1 = capture(ctx);
return comp2({slots: markRaw({'default': {__render: slot1, __ctx: ctx1}})}, key + \`__2\`, node, ctx, null); return comp2({slots: markRaw({'default': {__render: slot1, __ctx: ctx1}})}, key + \`__2\`, node, this, null);
} }
}" }"
`; `;
@@ -242,7 +242,7 @@ exports[`t-set t-set in t-if 1`] = `
let { text, createBlock, list, multi, html, toggler, comment } = bdom; let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let { isBoundary, withDefault, setContextValue } = 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><p><block-text-0/></p></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
ctx = Object.create(ctx); ctx = Object.create(ctx);
@@ -275,7 +275,7 @@ exports[`t-set t-set not altered by child comp 1`] = `
ctx[isBoundary] = 1 ctx[isBoundary] = 1
setContextValue(ctx, \\"iter\\", 'source'); setContextValue(ctx, \\"iter\\", 'source');
let txt1 = ctx['iter']; let txt1 = ctx['iter'];
const b2 = comp1({}, key + \`__1\`, node, ctx, null); const b2 = comp1({}, key + \`__1\`, node, this, null);
let txt2 = ctx['iter']; let txt2 = ctx['iter'];
return block1([txt1, txt2], [b2]); return block1([txt1, txt2], [b2]);
} }
@@ -307,7 +307,7 @@ exports[`t-set t-set outside modified in t-if 1`] = `
let { text, createBlock, list, multi, html, toggler, comment } = bdom; let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let { isBoundary, withDefault, setContextValue } = 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><p><block-text-0/></p></div>\`);
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
ctx = Object.create(ctx); ctx = Object.create(ctx);
@@ -337,13 +337,13 @@ exports[`t-set t-set with a component in body 1`] = `
let block1 = createBlock(\`<div><div><block-child-0/></div></div>\`); let block1 = createBlock(\`<div><div><block-child-0/></div></div>\`);
function value1(ctx, node, key = \\"\\") { function value1(ctx, node, key = \\"\\") {
return comp1({}, key + \`__1\`, node, ctx, null); return comp1({}, key + \`__1\`, node, this, null);
} }
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
ctx = Object.create(ctx); ctx = Object.create(ctx);
ctx[isBoundary] = 1 ctx[isBoundary] = 1
ctx[\`v\`] = new LazyValue(value1, ctx, node); ctx[\`v\`] = new LazyValue(value1, ctx, this, node, key);
const b3 = safeOutput(ctx['v']); const b3 = safeOutput(ctx['v']);
return block1([], [b3]); return block1([], [b3]);
} }
@@ -377,7 +377,7 @@ exports[`t-set t-set with something in body 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
ctx = Object.create(ctx); ctx = Object.create(ctx);
ctx[isBoundary] = 1 ctx[isBoundary] = 1
ctx[\`v\`] = new LazyValue(value1, ctx, node); ctx[\`v\`] = new LazyValue(value1, ctx, this, node, key);
const b3 = safeOutput(ctx['v']); const b3 = safeOutput(ctx['v']);
return block1([], [b3]); return block1([], [b3]);
} }
+35 -7
View File
@@ -1,5 +1,12 @@
import { App, Component, mount, status, toRaw, useState, xml } from "../../src"; import { App, Component, mount, status, toRaw, useState, xml } from "../../src";
import { elem, makeTestFixture, nextTick, snapshotEverything, useLogLifecycle } from "../helpers"; import {
elem,
makeTestFixture,
nextAppError,
nextTick,
snapshotEverything,
useLogLifecycle,
} from "../helpers";
import { markup } from "../../src/runtime/utils"; import { markup } from "../../src/runtime/utils";
let fixture: HTMLElement; let fixture: HTMLElement;
@@ -208,14 +215,14 @@ describe("basics", () => {
static template = xml`<div/>`; static template = xml`<div/>`;
} }
let error: Error; let error: Error;
const prom = mount(Test, fixture); const app = new App(Test);
const prom = app.mount(fixture);
await Promise.resolve(); await Promise.resolve();
fixture.remove(); fixture.remove();
try { prom.catch((e: Error) => (error = e));
await prom; await expect(nextAppError(app)).resolves.toThrow(
} catch (e) { "Cannot mount a component on a detached dom node"
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");
expect(console.warn).toBeCalledTimes(1); expect(console.warn).toBeCalledTimes(1);
@@ -1084,4 +1091,25 @@ describe("t-out in components", () => {
await nextTick(); await nextTick();
expect(fixture.innerHTML).toBe("<div>1</div><div>2</div>"); expect(fixture.innerHTML).toBe("<div>1</div><div>2</div>");
}); });
test("t-out and updating falsy values, ", async () => {
class Test extends Component {
static template = xml`<t t-out="state.a"/>`;
state: any = useState({ a: 0 });
}
const comp = await mount(Test, fixture);
expect(fixture.innerHTML).toBe("0");
comp.state.a = undefined;
await nextTick();
expect(fixture.innerHTML).toBe("");
comp.state.a = "hello";
await nextTick();
expect(fixture.innerHTML).toBe("hello");
comp.state.a = false;
await nextTick();
expect(fixture.innerHTML).toBe("false");
});
}); });
+243 -84
View File
@@ -1,4 +1,4 @@
import { Component, mount, onWillDestroy } from "../../src"; import { App, Component, mount, onWillDestroy } from "../../src";
import { import {
onError, onError,
onMounted, onMounted,
@@ -18,7 +18,9 @@ import {
nextMicroTick, nextMicroTick,
snapshotEverything, snapshotEverything,
useLogLifecycle, useLogLifecycle,
nextAppError,
} from "../helpers"; } from "../helpers";
import { OwlError } from "../../src/runtime/error_handling";
let fixture: HTMLElement; let fixture: HTMLElement;
@@ -58,9 +60,10 @@ describe("basics", () => {
parent.state.flag = true; parent.state.flag = true;
parent.render(); parent.render();
await nextTick(); await expect(nextAppError(parent.__owl__.app)).resolves.toThrow(
"An error occured in the owl lifecycle"
);
expect(fixture.innerHTML).toBe(""); expect(fixture.innerHTML).toBe("");
expect(mockConsoleError).toBeCalledTimes(1);
expect(mockConsoleWarn).toBeCalledTimes(1); expect(mockConsoleWarn).toBeCalledTimes(1);
}); });
@@ -70,12 +73,13 @@ describe("basics", () => {
static template = xml`<SomeMispelledComponent />`; static template = xml`<SomeMispelledComponent />`;
static components = { SomeComponent }; static components = { SomeComponent };
} }
const app = new App(Parent);
let error: Error; let error: Error;
try { const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
await mount(Parent, fixture); await expect(nextAppError(app)).resolves.toThrow(
} catch (e) { 'Cannot find the definition of component "SomeMispelledComponent"'
error = e as Error; );
} await mountProm;
expect(error!).toBeDefined(); expect(error!).toBeDefined();
expect(error!.message).toBe('Cannot find the definition of component "SomeMispelledComponent"'); expect(error!.message).toBe('Cannot find the definition of component "SomeMispelledComponent"');
expect(console.error).toBeCalledTimes(0); expect(console.error).toBeCalledTimes(0);
@@ -89,12 +93,13 @@ describe("basics", () => {
static template = xml`<SomeMispelledComponent />`; static template = xml`<SomeMispelledComponent />`;
static components = { SomeComponent }; static components = { SomeComponent };
} }
const app = new App(Parent, { test: true });
let error: Error; let error: Error;
try { const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
await mount(Parent, fixture, { test: true }); await expect(nextAppError(app)).resolves.toThrow(
} catch (e) { 'Cannot find the definition of component "SomeMispelledComponent"'
error = e as Error; );
} await mountProm;
expect(error!).toBeDefined(); expect(error!).toBeDefined();
expect(error!.message).toBe('Cannot find the definition of component "SomeMispelledComponent"'); expect(error!.message).toBe('Cannot find the definition of component "SomeMispelledComponent"');
expect(console.error).toBeCalledTimes(0); expect(console.error).toBeCalledTimes(0);
@@ -108,13 +113,13 @@ describe("basics", () => {
static template = xml`<SomeComponent />`; static template = xml`<SomeComponent />`;
static components = { SomeComponent: notAComponentConstructor }; static components = { SomeComponent: notAComponentConstructor };
} }
const app = new App(Parent as typeof Component);
let error: Error; let error: Error;
try { const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
// @ts-expect-error await expect(nextAppError(app)).resolves.toThrow(
await mount(Parent, fixture); '"SomeComponent" is not a Component. It must inherit from the Component class'
} catch (e) { );
error = e as Error; await mountProm;
}
expect(error!).toBeDefined(); expect(error!).toBeDefined();
expect(error!.message).toBe( expect(error!.message).toBe(
'"SomeComponent" is not a Component. It must inherit from the Component class' '"SomeComponent" is not a Component. It must inherit from the Component class'
@@ -155,26 +160,26 @@ describe("basics", () => {
describe("errors and promises", () => { describe("errors and promises", () => {
test("a rendering error will reject the mount promise", async () => { test("a rendering error will reject the mount promise", async () => {
// we do not catch error in willPatch anymore // we do not catch error in willPatch anymore
class App extends Component { class Root extends Component {
static template = xml`<div><t t-esc="this.will.crash"/></div>`; static template = xml`<div><t t-esc="this.will.crash"/></div>`;
} }
let error: Error; const app = new App(Root);
try { let error: OwlError;
await mount(App, fixture); const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
} catch (e) { await expect(nextAppError(app)).resolves.toThrow("error occured in the owl lifecycle");
error = e as Error; await mountProm;
}
expect(error!).toBeDefined(); expect(error!).toBeDefined();
expect(error!.cause).toBeDefined();
const regexp = const regexp =
/Cannot read properties of undefined \(reading 'crash'\)|Cannot read property 'crash' of undefined/g; /Cannot read properties of undefined \(reading 'crash'\)|Cannot read property 'crash' of undefined/g;
expect(error!.message).toMatch(regexp); expect(error!.cause.message).toMatch(regexp);
expect(mockConsoleError).toBeCalledTimes(0); expect(mockConsoleError).toBeCalledTimes(0);
expect(mockConsoleError).toBeCalledTimes(0); expect(mockConsoleError).toBeCalledTimes(0);
}); });
test("an error in mounted call will reject the mount promise", async () => { test("an error in mounted call will reject the mount promise", async () => {
class App extends Component { class Root extends Component {
static template = xml`<div>abc</div>`; static template = xml`<div>abc</div>`;
setup() { setup() {
onMounted(() => { onMounted(() => {
@@ -183,21 +188,21 @@ describe("errors and promises", () => {
} }
} }
let error: Error; const app = new App(Root);
try { let error: OwlError;
await mount(App, fixture); const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
} catch (e) { await expect(nextAppError(app)).resolves.toThrow("error occured in the owl lifecycle");
error = e as Error; await mountProm;
}
expect(error!).toBeDefined(); expect(error!).toBeDefined();
expect(error!.message).toBe("boom"); expect(error!.cause).toBeDefined();
expect(error!.cause.message).toBe("boom");
expect(fixture.innerHTML).toBe(""); expect(fixture.innerHTML).toBe("");
expect(mockConsoleError).toBeCalledTimes(0); expect(mockConsoleError).toBeCalledTimes(0);
expect(mockConsoleWarn).toBeCalledTimes(1); expect(mockConsoleWarn).toBeCalledTimes(1);
}); });
test("an error in onMounted callback will have the component's setup in its stack trace", async () => { test("an error in onMounted callback will have the component's setup in its stack trace", async () => {
class App extends Component { class Root extends Component {
static template = xml`<div>abc</div>`; static template = xml`<div>abc</div>`;
setup() { setup() {
onMounted(() => { onMounted(() => {
@@ -206,14 +211,13 @@ describe("errors and promises", () => {
} }
} }
let error: Error; const app = new App(Root, { test: true });
try { let error: OwlError;
await mount(App, fixture, { test: true }); const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
} catch (e) { await expect(nextAppError(app)).resolves.toThrow("error occurred in onMounted");
error = e as Error; await mountProm;
}
expect(error!).toBeDefined(); expect(error!).toBeDefined();
expect(error!.stack).toContain("App.setup"); expect(error!.stack).toContain("Root.setup");
expect(error!.stack).toContain("error_handling.test.ts"); expect(error!.stack).toContain("error_handling.test.ts");
expect(fixture.innerHTML).toBe(""); expect(fixture.innerHTML).toBe("");
expect(mockConsoleError).toBeCalledTimes(0); expect(mockConsoleError).toBeCalledTimes(0);
@@ -221,7 +225,7 @@ describe("errors and promises", () => {
}); });
test("errors in onWillRender/onRender aren't wrapped more than once", async () => { test("errors in onWillRender/onRender aren't wrapped more than once", async () => {
class App extends Component { class Root extends Component {
static template = xml`<div>abc</div>`; static template = xml`<div>abc</div>`;
setup() { setup() {
onWillRender(() => { onWillRender(() => {
@@ -233,12 +237,11 @@ describe("errors and promises", () => {
} }
} }
let error: Error; const app = new App(Root, { test: true });
try { let error: OwlError;
await mount(App, fixture, { test: true }); const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
} catch (e) { await expect(nextAppError(app)).resolves.toThrow("error occurred in onWillRender");
error = e as Error; await mountProm;
}
expect(error!).toBeDefined(); expect(error!).toBeDefined();
expect(error!.message).toBe( expect(error!.message).toBe(
`The following error occurred in onWillRender: "boom in onWillRender"` `The following error occurred in onWillRender: "boom in onWillRender"`
@@ -264,6 +267,29 @@ describe("errors and promises", () => {
expect(error!.message).toBe("Tokenizer error: could not tokenize `{ 'invalid: 5 }`"); expect(error!.message).toBe("Tokenizer error: could not tokenize `{ 'invalid: 5 }`");
}); });
test("wrapped errors in async code are correctly caught", async () => {
class Root extends Component {
static template = xml`<div>abc</div>`;
setup() {
onWillStart(async () => {
await Promise.resolve();
throw new Error("boom in onWillStart");
});
}
}
const app = new App(Root, { test: true });
let error: OwlError;
const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
await expect(nextAppError(app)).resolves.toThrow("error occurred in onWillStart");
await mountProm;
expect(error!).toBeDefined();
expect(error!.message).toBe(
`The following error occurred in onWillStart: "boom in onWillStart"`
);
await new Promise((r) => setTimeout(r, 0)); // wait for the rejection event to bubble
});
test("an error in willPatch call will reject the render promise", async () => { test("an error in willPatch call will reject the render promise", async () => {
class Root extends Component { class Root extends Component {
static template = xml`<div><t t-esc="val"/></div>`; static template = xml`<div><t t-esc="val"/></div>`;
@@ -315,21 +341,21 @@ describe("errors and promises", () => {
class Child extends Component { class Child extends Component {
static template = xml`<div><t t-esc="this.will.crash"/></div>`; static template = xml`<div><t t-esc="this.will.crash"/></div>`;
} }
class App extends Component { class Parent extends Component {
static template = xml`<div><Child/></div>`; static template = xml`<div><Child/></div>`;
static components = { Child }; static components = { Child };
} }
let error: Error; const app = new App(Parent);
try { let error: OwlError;
await mount(App, fixture); const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
} catch (e) { await expect(nextAppError(app)).resolves.toThrow("error occured in the owl lifecycle");
error = e as Error; await mountProm;
}
expect(error!).toBeDefined(); expect(error!).toBeDefined();
expect(error!.cause).toBeDefined();
const regexp = const regexp =
/Cannot read properties of undefined \(reading 'crash'\)|Cannot read property 'crash' of undefined/g; /Cannot read properties of undefined \(reading 'crash'\)|Cannot read property 'crash' of undefined/g;
expect(error!.message).toMatch(regexp); expect(error!.cause.message).toMatch(regexp);
expect(mockConsoleError).toBeCalledTimes(0); expect(mockConsoleError).toBeCalledTimes(0);
expect(mockConsoleWarn).toBeCalledTimes(1); expect(mockConsoleWarn).toBeCalledTimes(1);
}); });
@@ -339,7 +365,7 @@ describe("errors and promises", () => {
static template = xml`<div><t t-if="flag" t-esc="this.will.crash"/></div>`; static template = xml`<div><t t-if="flag" t-esc="this.will.crash"/></div>`;
flag = false; flag = false;
setup() { setup() {
onError((e) => (error = e)); onError(({ cause }) => (error = cause));
} }
} }
@@ -366,16 +392,16 @@ describe("errors and promises", () => {
static components = { Child }; static components = { Child };
} }
let error: Error; const app = new App(Parent);
try { let error: OwlError;
await mount(Parent, fixture); const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
} catch (e) { await expect(nextAppError(app)).resolves.toThrow("error occured in the owl lifecycle");
error = e as Error; await mountProm;
}
expect(error!).toBeDefined(); expect(error!).toBeDefined();
expect(error!.cause).toBeDefined();
const regexp = const regexp =
/Cannot read properties of undefined \(reading 'y'\)|Cannot read property 'y' of undefined/g; /Cannot read properties of undefined \(reading 'y'\)|Cannot read property 'y' of undefined/g;
expect(error!.message).toMatch(regexp); expect(error!.cause.message).toMatch(regexp);
expect(mockConsoleError).toBeCalledTimes(0); expect(mockConsoleError).toBeCalledTimes(0);
expect(mockConsoleWarn).toBeCalledTimes(1); expect(mockConsoleWarn).toBeCalledTimes(1);
}); });
@@ -396,13 +422,12 @@ describe("errors and promises", () => {
} }
} }
try { const app = new App(Example, { test: true });
await mount(Example, fixture, { test: true }); let error: OwlError;
} catch (e) { const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
expect((e as Error).message).toBe( await expect(nextAppError(app)).resolves.toThrow("error occurred in onMounted");
`The following error occurred in onMounted: "Error in mounted"` await mountProm;
); expect(error!.message).toBe(`The following error occurred in onMounted: "Error in mounted"`);
}
// 1 additional error is logged because the destruction of the app causes // 1 additional error is logged because the destruction of the app causes
// the onWillUnmount hook to be called and to fail // the onWillUnmount hook to be called and to fail
expect(mockConsoleError).toBeCalledTimes(1); expect(mockConsoleError).toBeCalledTimes(1);
@@ -419,9 +444,10 @@ describe("errors and promises", () => {
root.state = "boom"; root.state = "boom";
root.render(); root.render();
await nextTick(); await expect(nextAppError(root.__owl__.app)).resolves.toThrow(
"error occured in the owl lifecycle"
);
expect(fixture.innerHTML).toBe(""); expect(fixture.innerHTML).toBe("");
expect(mockConsoleError).toBeCalledTimes(1);
expect(mockConsoleWarn).toBeCalledTimes(1); expect(mockConsoleWarn).toBeCalledTimes(1);
}); });
}); });
@@ -471,17 +497,150 @@ describe("can catch errors", () => {
}); });
} }
} }
let e: Error; const app = new App(Root, { test: true });
try { let error: OwlError;
await mount(Root, fixture, { test: true }); const crashProm = expect(nextAppError(app)).resolves.toThrow("error occurred in onWillStart");
} catch (error) { await app.mount(fixture).catch((e: Error) => (error = e));
e = error as Error; await crashProm;
} expect(error!.message).toBe(
expect(e!.message).toBe(
`The following error occurred in onWillStart: "No active component (a hook function should only be called in 'setup')"` `The following error occurred in onWillStart: "No active component (a hook function should only be called in 'setup')"`
); );
}); });
test("Errors have the right cause", async () => {
const err = new Error("test error");
class Root extends Component {
static template = xml`<t t-esc="state.value"/>`;
state = useState({ value: 1 });
setup() {
onMounted(() => {
throw err;
});
}
}
const app = new App(Root, { test: true });
let error: OwlError;
const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
await expect(nextAppError(app)).resolves.toThrow("error occurred in onMounted");
await mountProm;
expect(error!.message).toBe(`The following error occurred in onMounted: "test error"`);
expect(error!.cause).toBe(err);
});
test("Errors in owl lifecycle are wrapped in dev mode: async hook", async () => {
const err = new Error("test error");
class Root extends Component {
static template = xml`<t t-esc="state.value"/>`;
state = useState({ value: 1 });
setup() {
onWillStart(async () => {
await nextMicroTick();
throw err;
});
}
}
const app = new App(Root, { test: true });
let error: OwlError;
const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
await expect(nextAppError(app)).resolves.toThrow("error occurred in onWillStart");
await mountProm;
expect(error!.message).toBe(`The following error occurred in onWillStart: "test error"`);
expect(error!.cause).toBe(err);
});
test("Errors in owl lifecycle are wrapped outside dev mode: sync hook", async () => {
const err = new Error("test error");
class Root extends Component {
static template = xml`<t t-esc="state.value"/>`;
state = useState({ value: 1 });
setup() {
onMounted(() => {
throw err;
});
}
}
const app = new App(Root);
let error: OwlError;
const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
await expect(nextAppError(app)).resolves.toThrow("error occured in the owl lifecycle");
await mountProm;
expect(error!.message).toBe(
`An error occured in the owl lifecycle (see this Error's "cause" property)`
);
expect(error!.cause).toBe(err);
});
test("Errors in owl lifecycle are wrapped out of dev mode: async hook", async () => {
const err = new Error("test error");
class Root extends Component {
static template = xml`<t t-esc="state.value"/>`;
state = useState({ value: 1 });
setup() {
onWillStart(async () => {
await nextMicroTick();
throw err;
});
}
}
const app = new App(Root);
let error: OwlError;
const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
await expect(nextAppError(app)).resolves.toThrow("error occured in the owl lifecycle");
await mountProm;
expect(error!.message).toBe(
`An error occured in the owl lifecycle (see this Error's "cause" property)`
);
expect(error!.cause).toBe(err);
});
test("Thrown values that are not errors are wrapped in dev mode", async () => {
class Root extends Component {
static template = xml`<t t-esc="state.value"/>`;
state = useState({ value: 1 });
setup() {
onMounted(() => {
throw "This is not an error";
});
}
}
const app = new App(Root, { test: true });
let error: OwlError;
const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
await expect(nextAppError(app)).resolves.toThrow("not an Error was thrown in onMounted");
await mountProm;
expect(error!.message).toBe(
`Something that is not an Error was thrown in onMounted (see this Error's "cause" property)`
);
expect(error!.cause).toBe("This is not an error");
});
test("Thrown values that are not errors are wrapped outside dev mode", async () => {
class Root extends Component {
static template = xml`<t t-esc="state.value"/>`;
state = useState({ value: 1 });
setup() {
onMounted(() => {
throw "This is not an error";
});
}
}
const app = new App(Root);
let error: OwlError;
const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
await expect(nextAppError(app)).resolves.toThrow("error occured in the owl lifecycle");
await mountProm;
expect(error!.message).toBe(
`An error occured in the owl lifecycle (see this Error's "cause" property)`
);
expect(error!.cause).toBe("This is not an error");
});
test("can catch an error in the initial call of a component render function (parent mounted)", async () => { test("can catch an error in the initial call of a component render function (parent mounted)", async () => {
class ErrorComponent extends Component { class ErrorComponent extends Component {
static template = xml`<div>hey<t t-esc="state.this.will.crash"/></div>`; static template = xml`<div>hey<t t-esc="state.this.will.crash"/></div>`;
@@ -1180,8 +1339,8 @@ describe("can catch errors", () => {
class Catch extends Component { class Catch extends Component {
static template = xml`<t t-slot="default" />`; static template = xml`<t t-slot="default" />`;
setup() { setup() {
onError((error) => { onError(({ cause }) => {
this.props.onError(error); this.props.onError(cause);
}); });
} }
} }
+18
View File
@@ -171,4 +171,22 @@ describe("event handling", () => {
// input is removed when component is destroyed => nothing should happen // input is removed when component is destroyed => nothing should happen
expect([]).toBeLogged(); expect([]).toBeLogged();
}); });
test("handler works when app is mounted in an iframe", async () => {
let clickCount = 0;
class Parent extends Component {
static template = xml`<span t-on-click="inc">click me</span>`;
inc() {
clickCount++;
}
}
const iframe = document.createElement("iframe");
fixture.appendChild(iframe);
const iframeDoc = iframe.contentDocument!;
await mount(Parent, iframeDoc.body);
expect(clickCount).toBe(0);
iframeDoc.querySelector("span")!.click();
expect(clickCount).toBe(1);
});
}); });
+15 -6
View File
@@ -17,8 +17,16 @@ import {
useChildSubEnv, useChildSubEnv,
useSubEnv, useSubEnv,
xml, xml,
OwlError,
} from "../../src/index"; } from "../../src/index";
import { elem, logStep, makeTestFixture, nextTick, snapshotEverything } from "../helpers"; import {
elem,
logStep,
makeTestFixture,
nextAppError,
nextTick,
snapshotEverything,
} from "../helpers";
let fixture: HTMLElement; let fixture: HTMLElement;
@@ -650,11 +658,12 @@ describe("hooks", () => {
} }
} }
try { let error: OwlError;
await mount(MyComponent, fixture); const app = new App(MyComponent);
} catch (e: any) { const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
expect(e.message).toBe("Intentional error"); await expect(nextAppError(app)).resolves.toThrow("error occured in the owl lifecycle");
} await mountProm;
expect(error!.cause.message).toBe("Intentional error");
// no console.error because the error has been caught in this test // no console.error because the error has been caught in this test
expect(console.error).toHaveBeenCalledTimes(0); expect(console.error).toHaveBeenCalledTimes(0);
console.error = originalconsoleError; console.error = originalconsoleError;
+124 -111
View File
@@ -1,6 +1,6 @@
import { makeTestFixture, nextTick, snapshotEverything } from "../helpers"; import { makeTestFixture, nextAppError, nextTick, snapshotEverything } from "../helpers";
import { Component, onError, xml, mount } from "../../src"; import { Component, onError, xml, mount, OwlError } from "../../src";
import { DEV_MSG } from "../../src/runtime/app"; import { App, DEV_MSG } from "../../src/runtime/app";
import { validateProps } from "../../src/runtime/template_helpers"; import { validateProps } from "../../src/runtime/template_helpers";
import { Schema } from "../../src/runtime/validation"; import { Schema } from "../../src/runtime/validation";
@@ -48,13 +48,14 @@ describe("props validation", () => {
static components = { SubComp }; static components = { SubComp };
static template = xml`<div><SubComp /></div>`; static template = xml`<div><SubComp /></div>`;
} }
let error: Error | undefined;
try { const app = new App(Parent, { test: true });
await mount(Parent, fixture, { dev: true }); let error: OwlError | undefined;
} catch (e) { const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
error = e as Error; await expect(nextAppError(app)).resolves.toThrow(
} "Invalid props for component 'SubComp': 'message' is missing"
);
await mountProm;
expect(error!).toBeDefined(); expect(error!).toBeDefined();
expect(error!.message).toBe("Invalid props for component 'SubComp': 'message' is missing"); expect(error!.message).toBe("Invalid props for component 'SubComp': 'message' is missing");
error = undefined; error = undefined;
@@ -77,12 +78,13 @@ describe("props validation", () => {
static template = xml`<div><SubComp /></div>`; static template = xml`<div><SubComp /></div>`;
} }
let error: Error; const app = new App(Parent, { test: true });
try { let error: OwlError | undefined;
await mount(Parent, fixture, { dev: true }); const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
} catch (e) { await expect(nextAppError(app)).resolves.toThrow(
error = e as Error; "Invalid props for component 'SubComp': 'message' is missing"
} );
await mountProm;
expect(error!).toBeDefined(); expect(error!).toBeDefined();
expect(error!.message).toBe("Invalid props for component 'SubComp': 'message' is missing"); expect(error!.message).toBe("Invalid props for component 'SubComp': 'message' is missing");
}); });
@@ -126,14 +128,12 @@ describe("props validation", () => {
}; };
(Parent as any).components = { SubComp }; (Parent as any).components = { SubComp };
let error: Error | undefined;
props = {}; props = {};
let app = new App(Parent, { test: true });
try { let error: OwlError | undefined;
await mount(Parent, fixture, { dev: true }); let mountProm = app.mount(fixture).catch((e: Error) => (error = e));
} catch (e) { await expect(nextAppError(app)).resolves.toThrow("Invalid props for component '_a'");
error = e as Error; await mountProm;
}
expect(error!).toBeDefined(); expect(error!).toBeDefined();
expect(error!.message).toBe( expect(error!.message).toBe(
`Invalid props for component '_a': 'p' is undefined (should be a ${test.type.name.toLowerCase()})` `Invalid props for component '_a': 'p' is undefined (should be a ${test.type.name.toLowerCase()})`
@@ -147,11 +147,10 @@ describe("props validation", () => {
} }
expect(error!).toBeUndefined(); expect(error!).toBeUndefined();
props = { p: test.ko }; props = { p: test.ko };
try { app = new App(Parent, { test: true });
await mount(Parent, fixture, { dev: true }); mountProm = app.mount(fixture).catch((e: Error) => (error = e));
} catch (e) { await expect(nextAppError(app)).resolves.toThrow("Invalid props for component '_a'");
error = e as Error; await mountProm;
}
expect(error!).toBeDefined(); expect(error!).toBeDefined();
expect(error!.message).toBe( expect(error!.message).toBe(
`Invalid props for component '_a': 'p' is not a ${test.type.name.toLowerCase()}` `Invalid props for component '_a': 'p' is not a ${test.type.name.toLowerCase()}`
@@ -181,13 +180,12 @@ describe("props validation", () => {
static template = xml`<div>hey</div>`; static template = xml`<div>hey</div>`;
}; };
(Parent as any).components = { SubComp }; (Parent as any).components = { SubComp };
let error: Error | undefined;
props = {}; props = {};
try { let app = new App(Parent, { test: true });
await mount(Parent, fixture, { dev: true }); let error: OwlError | undefined;
} catch (e) { let mountProm = app.mount(fixture).catch((e: Error) => (error = e));
error = e as Error; await expect(nextAppError(app)).resolves.toThrow("Invalid props for component '_a'");
} await mountProm;
expect(error!).toBeDefined(); expect(error!).toBeDefined();
expect(error!.message).toBe( expect(error!.message).toBe(
`Invalid props for component '_a': 'p' is undefined (should be a ${test.type.name.toLowerCase()})` `Invalid props for component '_a': 'p' is undefined (should be a ${test.type.name.toLowerCase()})`
@@ -201,11 +199,10 @@ describe("props validation", () => {
} }
expect(error!).toBeUndefined(); expect(error!).toBeUndefined();
props = { p: test.ko }; props = { p: test.ko };
try { app = new App(Parent, { test: true });
await mount(Parent, fixture, { dev: true }); mountProm = app.mount(fixture).catch((e: Error) => (error = e));
} catch (e) { await expect(nextAppError(app)).resolves.toThrow("Invalid props for component '_a'");
error = e as Error; await mountProm;
}
expect(error!).toBeDefined(); expect(error!).toBeDefined();
expect(error!.message).toBe( expect(error!.message).toBe(
`Invalid props for component '_a': 'p' is not a ${test.type.name.toLowerCase()}` `Invalid props for component '_a': 'p' is not a ${test.type.name.toLowerCase()}`
@@ -227,26 +224,25 @@ describe("props validation", () => {
} }
let error: Error; let error: Error;
let props: { p?: any }; let props: { p?: any };
props = { p: "string" };
try { try {
props = { p: "string" };
await mount(Parent, fixture, { dev: true }); await mount(Parent, fixture, { dev: true });
} catch (e) { } catch (e) {
error = e as Error; error = e as Error;
} }
expect(error!).toBeUndefined(); expect(error!).toBeUndefined();
props = { p: true };
try { try {
props = { p: true };
await mount(Parent, fixture, { dev: true }); await mount(Parent, fixture, { dev: true });
} catch (e) { } catch (e) {
error = e as Error; error = e as Error;
} }
expect(error!).toBeUndefined(); expect(error!).toBeUndefined();
try { props = { p: 1 };
props = { p: 1 }; const app = new App(Parent, { test: true });
await mount(Parent, fixture, { dev: true }); const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
} catch (e) { await expect(nextAppError(app)).resolves.toThrow("Invalid props for component 'SubComp'");
error = e as Error; await mountProm;
}
expect(error!).toBeDefined(); expect(error!).toBeDefined();
expect(error!.message).toBe( expect(error!.message).toBe(
"Invalid props for component 'SubComp': 'p' is not a string or boolean" "Invalid props for component 'SubComp': 'p' is not a string or boolean"
@@ -267,26 +263,25 @@ describe("props validation", () => {
} }
let error: Error; let error: Error;
let props: { p?: any }; let props: { p?: any };
props = { p: "key" };
try { try {
props = { p: "key" };
await mount(Parent, fixture, { dev: true }); await mount(Parent, fixture, { dev: true });
} catch (e) { } catch (e) {
error = e as Error; error = e as Error;
} }
expect(error!).toBeUndefined(); expect(error!).toBeUndefined();
props = {};
try { try {
props = {};
await mount(Parent, fixture, { dev: true }); await mount(Parent, fixture, { dev: true });
} catch (e) { } catch (e) {
error = e as Error; error = e as Error;
} }
expect(error!).toBeUndefined(); expect(error!).toBeUndefined();
try { props = { p: 1 };
props = { p: 1 }; const app = new App(Parent, { test: true });
await mount(Parent, fixture, { dev: true }); const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
} catch (e) { await expect(nextAppError(app)).resolves.toThrow("Invalid props for component 'SubComp'");
error = e as Error; await mountProm;
}
expect(error!).toBeDefined(); expect(error!).toBeDefined();
expect(error!.message).toBe("Invalid props for component 'SubComp': 'p' is not a string"); expect(error!.message).toBe("Invalid props for component 'SubComp': 'p' is not a string");
}); });
@@ -319,20 +314,18 @@ describe("props validation", () => {
error = e as Error; error = e as Error;
} }
expect(error!).toBeUndefined(); expect(error!).toBeUndefined();
try { props = { p: [1] };
props = { p: [1] }; let app = new App(Parent, { test: true });
await mount(Parent, fixture, { dev: true }); let mountProm = app.mount(fixture).catch((e: Error) => (error = e));
} catch (e) { await expect(nextAppError(app)).resolves.toThrow("Invalid props for component 'SubComp'");
error = e as Error; await mountProm;
}
expect(error!).toBeDefined(); expect(error!).toBeDefined();
error = undefined; error = undefined;
try { app = new App(Parent, { test: true });
props = { p: ["string", 1] }; mountProm = app.mount(fixture).catch((e: Error) => (error = e));
await mount(Parent, fixture, { dev: true }); await expect(nextAppError(app)).resolves.toThrow("Invalid props for component 'SubComp'");
} catch (e) { await mountProm;
error = e as Error; expect(error!).toBeDefined();
}
}); });
test("can validate an array with multiple sub element types", async () => { test("can validate an array with multiple sub element types", async () => {
@@ -370,12 +363,11 @@ describe("props validation", () => {
error = e as Error; error = e as Error;
} }
expect(error!).toBeUndefined(); expect(error!).toBeUndefined();
try { props = { p: [true, 1] };
props = { p: [true, 1] }; const app = new App(Parent, { test: true });
await mount(Parent, fixture, { dev: true }); const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
} catch (e) { await expect(nextAppError(app)).resolves.toThrow("Invalid props for component 'SubComp'");
error = e as Error; await mountProm;
}
expect(error!).toBeDefined(); expect(error!).toBeDefined();
expect(error!.message).toBe( expect(error!.message).toBe(
"Invalid props for component 'SubComp': 'p[1]' is not a string or boolean" "Invalid props for component 'SubComp': 'p[1]' is not a string or boolean"
@@ -405,33 +397,30 @@ describe("props validation", () => {
error = e as Error; error = e as Error;
} }
expect(error!).toBeUndefined(); expect(error!).toBeUndefined();
try { props = { p: { id: 1, url: "url", extra: true } };
props = { p: { id: 1, url: "url", extra: true } }; let app = new App(Parent, { test: true });
await mount(Parent, fixture, { dev: true }); let mountProm = app.mount(fixture).catch((e: Error) => (error = e));
} catch (e) { await expect(nextAppError(app)).resolves.toThrow("Invalid props for component 'SubComp'");
error = e as Error; await mountProm;
}
expect(error!).toBeDefined(); expect(error!).toBeDefined();
expect(error!.message).toBe( expect(error!.message).toBe(
"Invalid props for component 'SubComp': 'p' has not the correct shape (unknown key 'extra')" "Invalid props for component 'SubComp': 'p' has not the correct shape (unknown key 'extra')"
); );
try { props = { p: { id: "1", url: "url" } };
props = { p: { id: "1", url: "url" } }; app = new App(Parent, { test: true });
await mount(Parent, fixture, { dev: true }); mountProm = app.mount(fixture).catch((e: Error) => (error = e));
} catch (e) { await expect(nextAppError(app)).resolves.toThrow("Invalid props for component 'SubComp'");
error = e as Error; await mountProm;
}
expect(error!).toBeDefined(); expect(error!).toBeDefined();
expect(error!.message).toBe( expect(error!.message).toBe(
"Invalid props for component 'SubComp': 'p' has not the correct shape ('id' is not a number)" "Invalid props for component 'SubComp': 'p' has not the correct shape ('id' is not a number)"
); );
error = undefined; error = undefined;
try { props = { p: { id: 1 } };
props = { p: { id: 1 } }; app = new App(Parent, { test: true });
await mount(Parent, fixture, { dev: true }); mountProm = app.mount(fixture).catch((e: Error) => (error = e));
} catch (e) { await expect(nextAppError(app)).resolves.toThrow("Invalid props for component 'SubComp'");
error = e as Error; await mountProm;
}
expect(error!).toBeDefined(); expect(error!).toBeDefined();
expect(error!.message).toBe( expect(error!.message).toBe(
"Invalid props for component 'SubComp': 'p' has not the correct shape ('url' is missing (should be a string))" "Invalid props for component 'SubComp': 'p' has not the correct shape ('url' is missing (should be a string))"
@@ -474,12 +463,11 @@ describe("props validation", () => {
error = e as Error; error = e as Error;
} }
expect(error!).toBeUndefined(); expect(error!).toBeUndefined();
try { props = { p: { id: 1, url: [12, true] } };
props = { p: { id: 1, url: [12, true] } }; const app = new App(Parent, { test: true });
await mount(Parent, fixture, { dev: true }); const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
} catch (e) { await expect(nextAppError(app)).resolves.toThrow("Invalid props for component 'SubComp'");
error = e as Error; await mountProm;
}
expect(error!).toBeDefined(); expect(error!).toBeDefined();
expect(error!.message).toBe( expect(error!.message).toBe(
"Invalid props for component 'SubComp': 'p' has not the correct shape ('url' is not a boolean or list of numbers)" "Invalid props for component 'SubComp': 'p' has not the correct shape ('url' is not a boolean or list of numbers)"
@@ -686,11 +674,10 @@ describe("props validation", () => {
static components = { SubComp }; static components = { SubComp };
} }
let error: Error; let error: Error;
try { const app = new App(Parent, { test: true });
await mount(Parent, fixture, { dev: true }); const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
} catch (e) { await expect(nextAppError(app)).resolves.toThrow("Invalid props for component 'SubComp'");
error = e as Error; await mountProm;
}
expect(error!).toBeDefined(); expect(error!).toBeDefined();
expect(error!.message).toBe("Invalid props for component 'SubComp': 'p' is missing"); expect(error!.message).toBe("Invalid props for component 'SubComp': 'p' is missing");
}); });
@@ -754,11 +741,10 @@ describe("props validation", () => {
static template = xml`<div><Child/></div>`; static template = xml`<div><Child/></div>`;
} }
let error: Error; let error: Error;
try { const app = new App(Parent, { test: true });
await mount(Parent, fixture, { dev: true }); const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
} catch (e) { await expect(nextAppError(app)).resolves.toThrow("Invalid props for component 'Child'");
error = e as Error; await mountProm;
}
expect(error!).toBeDefined(); expect(error!).toBeDefined();
expect(error!.message).toBe( expect(error!.message).toBe(
"Invalid props for component 'Child': 'mandatory' is missing (should be a number)" "Invalid props for component 'Child': 'mandatory' is missing (should be a number)"
@@ -794,6 +780,32 @@ describe("props validation", () => {
// we just check that it doesn't throw // we just check that it doesn't throw
await expect(mount(Parent, fixture, { dev: true })).resolves.toEqual(expect.anything()); await expect(mount(Parent, fixture, { dev: true })).resolves.toEqual(expect.anything());
}); });
test("can validate through slots", async () => {
class Child extends Component {
static props = ["message"];
static template = xml`<div>hey</div>`;
}
class Wrapper extends Component {
static template = xml`<t t-slot="default"/>`;
}
class Parent extends Component {
static components = { Child, Wrapper };
static template = xml`<Wrapper><Child /></Wrapper>`;
}
const app = new App(Parent, { test: true });
let error: OwlError | undefined;
const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
await expect(nextAppError(app)).resolves.toThrow(
"Invalid props for component 'Child': 'message' is missing"
);
await mountProm;
expect(error!).toBeDefined();
expect(error!.message).toBe("Invalid props for component 'Child': 'message' is missing");
});
}); });
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@@ -859,11 +871,12 @@ describe("default props", () => {
static template = xml`<Child/>`; static template = xml`<Child/>`;
} }
let error: Error; let error: Error;
try { const app = new App(Parent, { test: true });
await mount(Parent, fixture, { dev: true }); const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
} catch (e) { await expect(nextAppError(app)).resolves.toThrow(
error = e as Error; "default value cannot be defined for a mandatory prop"
} );
await mountProm;
expect(error!).toBeDefined(); expect(error!).toBeDefined();
expect(error!.message).toBe( expect(error!.message).toBe(
"A default value cannot be defined for a mandatory prop (name: 'mandatory', component: Child)" "A default value cannot be defined for a mandatory prop (name: 'mandatory', component: Child)"
+10 -5
View File
@@ -1,5 +1,5 @@
import { Component, mount, onMounted, useRef, useState } from "../../src/index"; import { App, Component, mount, onMounted, useRef, useState } from "../../src/index";
import { logStep, makeTestFixture, nextTick, snapshotEverything } from "../helpers"; import { logStep, makeTestFixture, nextAppError, nextTick, snapshotEverything } from "../helpers";
import { xml } from "../../src/index"; import { xml } from "../../src/index";
snapshotEverything(); snapshotEverything();
@@ -94,9 +94,14 @@ describe("refs", () => {
ref = useRef("coucou"); ref = useRef("coucou");
} }
await expect(async () => { const app = new App(Test, { test: true });
await mount(Test, fixture); const mountProm = expect(app.mount(fixture)).rejects.toThrowError(
}).rejects.toThrowError("Cannot have 2 elements with same ref name at the same time"); "Cannot have 2 elements with same ref name at the same time"
);
await expect(nextAppError(app)).resolves.toThrow(
"Cannot have 2 elements with same ref name at the same time"
);
await mountProm;
expect(console.warn).toBeCalledTimes(1); expect(console.warn).toBeCalledTimes(1);
console.warn = consoleWarn; console.warn = consoleWarn;
}); });
+105 -8
View File
@@ -1,5 +1,5 @@
import { App, Component, mount, onMounted, useState, xml } from "../../src/index"; import { App, Component, mount, onMounted, useState, xml } from "../../src/index";
import { children, makeTestFixture, nextTick, snapshotEverything } from "../helpers"; import { children, makeTestFixture, nextAppError, nextTick, snapshotEverything } from "../helpers";
snapshotEverything(); snapshotEverything();
let originalconsoleWarn = console.warn; let originalconsoleWarn = console.warn;
@@ -204,13 +204,12 @@ describe("slots", () => {
static components = { Child }; static components = { Child };
} }
let error = null; let error: Error;
try { const app = new App(Parent);
await mount(Parent, fixture); const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
} catch (e) { await expect(nextAppError(app)).resolves.toThrow("error occured in the owl lifecycle");
error = e; await mountProm;
} expect(error!).not.toBeNull();
expect(error).not.toBeNull();
expect(mockConsoleWarn).toBeCalledTimes(1); expect(mockConsoleWarn).toBeCalledTimes(1);
}); });
@@ -1819,4 +1818,102 @@ describe("slots", () => {
await nextTick(); await nextTick();
expect(fixture.innerHTML).toBe("<button>inc</button>[B][C][A][sub1] [sub2334]"); expect(fixture.innerHTML).toBe("<button>inc</button>[B][C][A][sub1] [sub2334]");
}); });
test("slot in multiple locations", async () => {
class Child extends Component {
static template = xml`<div>child</div>`;
}
class Slotter extends Component {
static components = { Child };
static template = xml`
<t t-if="props.location === 1">
<p><t t-slot="default"/></p>
</t>
<t t-if="props.location === 2">
<t t-slot="default"/>
</t>
`;
}
class Parent extends Component {
static components = { Child, Slotter };
static template = xml`
<Slotter location="state.location">
hello <Child/>
</Slotter>`;
state = useState({ location: 1 });
}
const parent = await mount(Parent, fixture);
expect(fixture.innerHTML).toBe("<p> hello <div>child</div></p>");
parent.state.location = 2;
await nextTick();
expect(fixture.innerHTML).toBe(" hello <div>child</div>");
});
test("dynamic slot in multiple locations", async () => {
class Child extends Component {
static template = xml`<div>child</div>`;
}
class Slotter extends Component {
static components = { Child };
static template = xml`
<t t-if="props.location === 1">
<p><t t-slot="{{'coffee'}}"/></p>
</t>
<t t-if="props.location === 2">
<t t-slot="{{'coffee'}}"/>
</t>
`;
}
class Parent extends Component {
static components = { Child, Slotter };
static template = xml`
<Slotter location="state.location">
<t t-set-slot="coffee">hello <Child/></t>
</Slotter>`;
state = useState({ location: 1 });
}
const parent = await mount(Parent, fixture);
expect(fixture.innerHTML).toBe("<p>hello <div>child</div></p>");
parent.state.location = 2;
await nextTick();
expect(fixture.innerHTML).toBe("hello <div>child</div>");
});
test("slot in t-foreach locations", async () => {
class Child extends Component {
static template = xml`<div>child</div>`;
}
class Slotter extends Component {
static components = { Child };
static template = xml`
<t t-foreach="props.list" t-as="elem" t-key="elem_index">
<p><t t-esc="elem"/><t t-slot="default"/></p>
</t>
`;
}
class Parent extends Component {
static components = { Child, Slotter };
static template = xml`
<Slotter list="state.list">
hello <Child/>
</Slotter>`;
state = useState({ list: [1] });
}
const parent = await mount(Parent, fixture);
expect(fixture.innerHTML).toBe("<p>1 hello <div>child</div></p>");
parent.state.list.push(2);
await nextTick();
expect(fixture.innerHTML).toBe(
"<p>1 hello <div>child</div></p><p>2 hello <div>child</div></p>"
);
});
}); });
+11 -10
View File
@@ -1,5 +1,6 @@
import { Component, mount, onMounted, useState, xml } from "../../src"; import { OwlError } from "../../src/runtime/error_handling";
import { makeTestFixture, nextTick, snapshotEverything } from "../helpers"; import { App, Component, mount, onMounted, useState, xml } from "../../src";
import { makeTestFixture, nextAppError, nextTick, snapshotEverything } from "../helpers";
snapshotEverything(); snapshotEverything();
let fixture: HTMLElement; let fixture: HTMLElement;
@@ -342,20 +343,20 @@ describe("style and class handling", () => {
class Child extends Component { class Child extends Component {
static template = xml`<div t-att-class="props.class" t-esc="this.will.crash"/>`; static template = xml`<div t-att-class="props.class" t-esc="this.will.crash"/>`;
} }
class ParentWidget extends Component { class Parent extends Component {
static template = xml`<Child class="'a'"/>`; static template = xml`<Child class="'a'"/>`;
static components = { Child }; static components = { Child };
} }
let error: Error; let error: OwlError;
try { const app = new App(Parent);
await mount(ParentWidget, fixture); const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
} catch (e) { await expect(nextAppError(app)).resolves.toThrow("error occured in the owl lifecycle");
error = e as Error; await mountProm;
}
expect(error!).toBeDefined(); expect(error!).toBeDefined();
expect(error!.cause).toBeDefined();
const regexp = const regexp =
/Cannot read properties of undefined \(reading 'crash'\)|Cannot read property 'crash' of undefined/g; /Cannot read properties of undefined \(reading 'crash'\)|Cannot read property 'crash' of undefined/g;
expect(error!.message).toMatch(regexp); expect(error!.cause.message).toMatch(regexp);
expect(fixture.innerHTML).toBe(""); expect(fixture.innerHTML).toBe("");
expect(mockConsoleWarn).toBeCalledTimes(1); expect(mockConsoleWarn).toBeCalledTimes(1);
}); });
+71
View File
@@ -244,4 +244,75 @@ describe("t-call", () => {
} }
expect(clickCount).toBe(2); expect(clickCount).toBe(2);
}); });
test("t-call with t-call-context, simple use", async () => {
class Root extends Component {
static template = xml`
<t t-call="someTemplate" t-call-context="subctx"/>`;
subctx = { aab: "aaron", lpe: "lucas" };
}
await mount(Root, fixture, {
templates: `
<templates>
<t t-name="someTemplate"><t t-esc="aab"/><t t-esc="lpe"/></t>
</templates>`,
});
expect(fixture.innerHTML).toBe("aaronlucas");
});
test("t-call with t-call-context and subcomponent", async () => {
class Child extends Component {
static template = xml`child<t t-esc="props.name"/>`;
}
class Root extends Component {
static template = xml`
<t t-call="someTemplate" t-call-context="subctx"/>`;
static components = { Child };
subctx = { aab: "aaron", lpe: "lucas" };
}
await mount(Root, fixture, {
templates: `
<templates>
<t t-name="someTemplate">
<Child name="aab"/>
<Child name="lpe"/>
</t>
</templates>`,
});
expect(fixture.innerHTML).toBe("childaaronchildlucas");
});
test("t-call with t-call-context and subcomponent, in dev mode", async () => {
class Child extends Component {
static template = xml`child<t t-esc="props.name"/>`;
static props = ["name"];
}
class Root extends Component {
static template = xml`
<t t-call="someTemplate" t-call-context="subctx"/>`;
static components = { Child };
subctx = { aab: "aaron", lpe: "lucas" };
}
await mount(Root, fixture, {
dev: true,
templates: `
<templates>
<t t-name="someTemplate">
<Child name="aab"/>
<Child name="lpe"/>
</t>
</templates>`,
});
expect(fixture.innerHTML).toBe("childaaronchildlucas");
});
}); });
+15 -5
View File
@@ -1,5 +1,11 @@
import { Component, mount, onMounted, useState, xml } from "../../src/index"; import { App, Component, mount, onMounted, useState, xml } from "../../src/index";
import { makeTestFixture, nextTick, snapshotEverything, useLogLifecycle } from "../helpers"; import {
makeTestFixture,
nextAppError,
nextTick,
snapshotEverything,
useLogLifecycle,
} from "../helpers";
snapshotEverything(); snapshotEverything();
@@ -315,9 +321,13 @@ describe("list of components", () => {
`; `;
static components = { Child }; static components = { Child };
} }
await expect(async () => {
await mount(Parent, fixture, { dev: true }); const app = new App(Parent, { test: true });
}).rejects.toThrowError("Got duplicate key in t-foreach: child"); const mountProm = expect(app.mount(fixture)).rejects.toThrow(
"Got duplicate key in t-foreach: child"
);
await expect(nextAppError(app)).resolves.toThrow("Got duplicate key in t-foreach: child");
await mountProm;
console.info = consoleInfo; console.info = consoleInfo;
expect(mockConsoleWarn).toBeCalledTimes(1); expect(mockConsoleWarn).toBeCalledTimes(1);
}); });
+36
View File
@@ -0,0 +1,36 @@
import { Component, mount, xml } from "../../src/index";
import { makeTestFixture, snapshotEverything } from "../helpers";
snapshotEverything();
// -----------------------------------------------------------------------------
// t-out
// -----------------------------------------------------------------------------
describe("components in t-out", () => {
let fixture: HTMLElement;
beforeEach(() => {
fixture = makeTestFixture();
});
test("simple list", async () => {
class Child extends Component {
static template = xml`child`;
}
class Parent extends Component {
static template = xml`
<t t-foreach="[1,2]" t-as="n" t-key="n">
<t t-set="blabla">
<Child />
</t>
<t t-out="blabla"/>
</t>`;
static components = { Child };
}
await mount(Parent, fixture);
expect(fixture.innerHTML).toBe("childchild");
});
});
+16 -1
View File
@@ -19,6 +19,7 @@ import { helpers } from "../src/runtime/template_helpers";
import { TemplateSet, globalTemplates } from "../src/runtime/template_set"; import { TemplateSet, globalTemplates } from "../src/runtime/template_set";
import { BDom } from "../src/runtime/blockdom"; import { BDom } from "../src/runtime/blockdom";
import { compile } from "../src/compiler"; import { compile } from "../src/compiler";
import { OwlError } from "../src/runtime/error_handling";
const mount = blockDom.mount; const mount = blockDom.mount;
@@ -221,7 +222,7 @@ export async function editInput(input: HTMLInputElement | HTMLTextAreaElement, v
afterEach(() => { afterEach(() => {
if (steps.length) { if (steps.length) {
steps.splice(0); steps.splice(0);
throw new Error("Remaining steps! Should be checked by a .toBeLogged() assertion!"); throw new OwlError("Remaining steps! Should be checked by a .toBeLogged() assertion!");
} }
}); });
@@ -260,6 +261,20 @@ expect.extend({
}, },
}); });
export function nextAppError(app: any) {
const { handleError } = app;
return new Promise((resolve) => {
app.handleError = (...args: Parameters<typeof handleError>) => {
try {
handleError.call(app, ...args);
} catch (e: any) {
app.handleError = handleError;
resolve(e);
}
};
});
}
declare global { declare global {
namespace jest { namespace jest {
interface Matchers<R> { interface Matchers<R> {
+87 -11
View File
@@ -155,6 +155,44 @@ exports[`Portal Add and remove portals with t-foreach inside div 1`] = `
}" }"
`; `;
exports[`Portal Child and Portal 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
const comp1 = app.createComponent(\`Child\`, true, false, false, true);
let block3 = createBlock(\`<div class=\\"portal\\"/>\`);
return function template(ctx, node, key = \\"\\") {
const b2 = comp1({}, key + \`__1\`, node, this, null);
const b3 = block3();
return multi([b2, b3]);
}
}"
`;
exports[`Portal Child and Portal 2`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
const Portal = app.Portal;
const comp1 = app.createComponent(null, false, true, false, false);
let block2 = createBlock(\`<span>child</span>\`);
let block3 = createBlock(\`<span>portal</span>\`);
function slot1(ctx, node, key = \\"\\") {
return block3();
}
return function template(ctx, node, key = \\"\\") {
const b2 = block2();
const b4 = comp1({target: '.portal',slots: {'default': {__render: slot1, __ctx: ctx}}}, key + \`__1\`, node, ctx, Portal);
return multi([b2, b4]);
}
}"
`;
exports[`Portal Portal composed with t-slot 1`] = ` exports[`Portal Portal composed with t-slot 1`] = `
"function anonymous(app, bdom, helpers "function anonymous(app, bdom, helpers
) { ) {
@@ -166,11 +204,11 @@ exports[`Portal Portal composed with t-slot 1`] = `
let block1 = createBlock(\`<div><block-child-0/></div>\`); let block1 = createBlock(\`<div><block-child-0/></div>\`);
function slot1(ctx, node, key = \\"\\") { function slot1(ctx, node, key = \\"\\") {
return comp1({customHandler: ctx['_handled']}, key + \`__1\`, node, ctx, null); return comp1({customHandler: ctx['_handled']}, key + \`__1\`, node, this, null);
} }
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
const b3 = comp2({slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__2\`, node, ctx, null); const b3 = comp2({slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__2\`, node, this, null);
return block1([], [b3]); return block1([], [b3]);
} }
}" }"
@@ -303,7 +341,7 @@ exports[`Portal conditional use of Portal (with sub Component) 1`] = `
let block2 = createBlock(\`<span>1</span>\`); let block2 = createBlock(\`<span>1</span>\`);
function slot1(ctx, node, key = \\"\\") { function slot1(ctx, node, key = \\"\\") {
return comp1({val: ctx['state'].val}, key + \`__1\`, node, ctx, null); return comp1({val: ctx['state'].val}, key + \`__1\`, node, this, null);
} }
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
@@ -365,7 +403,7 @@ exports[`Portal conditional use of Portal with child and div 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let b2; let b2;
if (ctx['state'].hasPortal) { if (ctx['state'].hasPortal) {
b2 = comp1({}, key + \`__1\`, node, ctx, null); b2 = comp1({}, key + \`__1\`, node, this, null);
} }
return multi([b2]); return multi([b2]);
} }
@@ -413,7 +451,7 @@ exports[`Portal conditional use of Portal with child and div, variation 1`] = `
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
let b2; let b2;
if (ctx['state'].hasPortal) { if (ctx['state'].hasPortal) {
const b3 = comp1({}, key + \`__1\`, node, ctx, null); const b3 = comp1({}, key + \`__1\`, node, this, null);
b2 = block2([], [b3]); b2 = block2([], [b3]);
} }
return multi([b2]); return multi([b2]);
@@ -488,7 +526,7 @@ exports[`Portal lifecycle hooks of portal sub component are properly called 1`]
let block1 = createBlock(\`<div><block-child-0/><block-child-0/></div>\`); let block1 = createBlock(\`<div><block-child-0/><block-child-0/></div>\`);
function slot1(ctx, node, key = \\"\\") { function slot1(ctx, node, key = \\"\\") {
return comp1({val: ctx['state'].val}, key + \`__1\`, node, ctx, null); return comp1({val: ctx['state'].val}, key + \`__1\`, node, this, null);
} }
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
@@ -515,6 +553,44 @@ exports[`Portal lifecycle hooks of portal sub component are properly called 2`]
}" }"
`; `;
exports[`Portal portal and Child 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
const comp1 = app.createComponent(\`Child\`, true, false, false, true);
let block2 = createBlock(\`<div class=\\"portal\\"/>\`);
return function template(ctx, node, key = \\"\\") {
const b2 = block2();
const b3 = comp1({}, key + \`__1\`, node, this, null);
return multi([b2, b3]);
}
}"
`;
exports[`Portal portal and Child 2`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
const Portal = app.Portal;
const comp1 = app.createComponent(null, false, true, false, false);
let block2 = createBlock(\`<span>child</span>\`);
let block3 = createBlock(\`<span>portal</span>\`);
function slot1(ctx, node, key = \\"\\") {
return block3();
}
return function template(ctx, node, key = \\"\\") {
const b2 = block2();
const b4 = comp1({target: '.portal',slots: {'default': {__render: slot1, __ctx: ctx}}}, key + \`__1\`, node, ctx, Portal);
return multi([b2, b4]);
}
}"
`;
exports[`Portal portal could have dynamically no content 1`] = ` exports[`Portal portal could have dynamically no content 1`] = `
"function anonymous(app, bdom, helpers "function anonymous(app, bdom, helpers
) { ) {
@@ -552,7 +628,7 @@ exports[`Portal portal destroys on crash 1`] = `
let block1 = createBlock(\`<div><block-child-0/></div>\`); let block1 = createBlock(\`<div><block-child-0/></div>\`);
function slot1(ctx, node, key = \\"\\") { function slot1(ctx, node, key = \\"\\") {
return comp1({error: ctx['state'].error}, key + \`__1\`, node, ctx, null); return comp1({error: ctx['state'].error}, key + \`__1\`, node, this, null);
} }
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
@@ -587,7 +663,7 @@ exports[`Portal portal with child and props 1`] = `
let block1 = createBlock(\`<div><block-child-0/></div>\`); let block1 = createBlock(\`<div><block-child-0/></div>\`);
function slot1(ctx, node, key = \\"\\") { function slot1(ctx, node, key = \\"\\") {
return comp1({val: ctx['state'].val}, key + \`__1\`, node, ctx, null); return comp1({val: ctx['state'].val}, key + \`__1\`, node, this, null);
} }
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
@@ -740,7 +816,7 @@ exports[`Portal portal's parent's env is not polluted 1`] = `
let block1 = createBlock(\`<div><block-child-0/></div>\`); let block1 = createBlock(\`<div><block-child-0/></div>\`);
function slot1(ctx, node, key = \\"\\") { function slot1(ctx, node, key = \\"\\") {
return comp1({}, key + \`__1\`, node, ctx, null); return comp1({}, key + \`__1\`, node, this, null);
} }
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
@@ -776,7 +852,7 @@ exports[`Portal simple catchError with portal 1`] = `
if (ctx['error']) { if (ctx['error']) {
b2 = text(\`Error\`); b2 = text(\`Error\`);
} else { } else {
b3 = comp1({}, key + \`__1\`, node, ctx, null); b3 = comp1({}, key + \`__1\`, node, this, null);
} }
return block1([], [b2, b3]); return block1([], [b2, b3]);
} }
@@ -900,7 +976,7 @@ exports[`Portal: UI/UX focus is kept across re-renders 1`] = `
let block1 = createBlock(\`<div><block-child-0/></div>\`); let block1 = createBlock(\`<div><block-child-0/></div>\`);
function slot1(ctx, node, key = \\"\\") { function slot1(ctx, node, key = \\"\\") {
return comp1({val: ctx['state'].val}, key + \`__1\`, node, ctx, null); return comp1({val: ctx['state'].val}, key + \`__1\`, node, this, null);
} }
return function template(ctx, node, key = \\"\\") { return function template(ctx, node, key = \\"\\") {
+61 -20
View File
@@ -1,3 +1,4 @@
import { OwlError } from "../../src/runtime/error_handling";
import { import {
App, App,
Component, Component,
@@ -11,7 +12,7 @@ import {
} from "../../src"; } from "../../src";
import { xml } from "../../src/"; import { xml } from "../../src/";
import { DEV_MSG } from "../../src/runtime/app"; import { DEV_MSG } from "../../src/runtime/app";
import { elem, makeTestFixture, nextTick, snapshotEverything } from "../helpers"; import { elem, makeTestFixture, nextAppError, nextTick, snapshotEverything } from "../helpers";
let fixture: HTMLElement; let fixture: HTMLElement;
let originalconsoleWarn = console.warn; let originalconsoleWarn = console.warn;
@@ -268,15 +269,14 @@ describe("Portal", () => {
} }
let error: Error; let error: Error;
try { const app = new App(Parent);
await mount(Parent, fixture); const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
} catch (e) { await expect(nextAppError(app)).resolves.toThrow("invalid portal target");
error = e as Error; await mountProm;
}
expect(error!).toBeDefined(); expect(error!).toBeDefined();
expect(error!.message).toBe("invalid portal target"); expect(error!.message).toBe("invalid portal target");
expect(fixture.innerHTML).toBe(`<div></div>`); expect(fixture.innerHTML).toBe(``);
expect(mockConsoleWarn).toBeCalledTimes(1); expect(mockConsoleWarn).toBeCalledTimes(1);
}); });
@@ -499,7 +499,7 @@ describe("Portal", () => {
</div>`; </div>`;
state = { error: false }; state = { error: false };
setup() { setup() {
onError((e) => (error = e)); onError(({ cause }) => (error = cause));
} }
} }
addOutsideDiv(fixture); addOutsideDiv(fixture);
@@ -874,6 +874,48 @@ describe("Portal", () => {
await nextTick(); await nextTick();
expect(fixture.innerHTML).toBe('<div id="outside"></div><div></div>'); expect(fixture.innerHTML).toBe('<div id="outside"></div><div></div>');
}); });
test("Child and Portal", async () => {
class Child extends Component {
static template = xml`
<span>child</span>
<t t-portal="'.portal'"><span>portal</span></t>`;
}
class Parent extends Component {
static template = xml`
<t>
<Child/>
<div class="portal"></div>
</t>`;
static components = { Child };
}
await mount(Parent, fixture);
expect(fixture.innerHTML).toBe(
'<span>child</span><div class="portal"></div><span>portal</span>'
);
});
test("portal and Child", async () => {
class Child extends Component {
static template = xml`
<span>child</span>
<t t-portal="'.portal'"><span>portal</span></t>`;
}
class Parent extends Component {
static template = xml`
<t>
<div class="portal"></div>
<Child/>
</t>`;
static components = { Child };
}
await mount(Parent, fixture);
expect(fixture.innerHTML).toBe(
'<div class="portal"><span>portal</span></div><span>child</span>'
);
});
}); });
describe("Portal: UI/UX", () => { describe("Portal: UI/UX", () => {
@@ -958,14 +1000,14 @@ describe("Portal: Props validation", () => {
</t> </t>
</div>`; </div>`;
} }
let error: Error; let error: OwlError;
try { const app = new App(Parent);
await mount(Parent, fixture, { dev: true }); const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
} catch (e) { await expect(nextAppError(app)).resolves.toThrow("error occured in the owl lifecycle");
error = e as Error; await mountProm;
}
expect(error!).toBeDefined(); expect(error!).toBeDefined();
expect(error!.message).toBe(`' ' is not a valid selector`); expect(error!.cause).toBeDefined();
expect(error!.cause.message).toBe(`' ' is not a valid selector`);
}); });
test("target must be a valid selector 2", async () => { test("target must be a valid selector 2", async () => {
@@ -978,11 +1020,10 @@ describe("Portal: Props validation", () => {
</div>`; </div>`;
} }
let error: Error; let error: Error;
try { const app = new App(Parent);
await mount(Parent, fixture, { dev: true }); const mountProm = app.mount(fixture).catch((e: Error) => (error = e));
} catch (e) { await expect(nextAppError(app)).resolves.toThrow("invalid portal target");
error = e as Error; await mountProm;
}
expect(error!).toBeDefined(); expect(error!).toBeDefined();
expect(error!.message).toBe(`invalid portal target`); expect(error!.message).toBe(`invalid portal target`);
}); });
+1 -3
View File
@@ -72,10 +72,8 @@ async function startRelease() {
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
log(`Step 3/${STEPS}: updating package.json, readme.md and roadmap.md...`); log(`Step 3/${STEPS}: updating package.json...`);
await replaceInFile("./package.json", current, next); await replaceInFile("./package.json", current, next);
await replaceInFile("./README.md", current, next);
await replaceInFile("./roadmap.md", current, next);
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
log(`Step 4/${STEPS}: creating git commit...`); log(`Step 4/${STEPS}: creating git commit...`);