Compare commits

..

1 Commits

Author SHA1 Message Date
Lucas Perais b1d95eae11 [FIX] runtime/fibers: render a parent when self is in error
Have a Component A which instantiate another one (B) which also have some Children (C).
Have B be the one to handle the errors from the Children via the onError hook.
This hook should call a props coming from A. The real error handler is on A then, passed to B via props.

This handler naturally sets a flag on A, and triggers a render.

Before this commit, the mounting of A never resolved as the fiber that was recycled in A
was still part of a root one which was flagged as being in error.

After this commit, the A component mounts correctly.

Closes #1298
2022-12-08 10:49:06 +01:00
38 changed files with 476 additions and 6190 deletions
-47
View File
@@ -1,47 +0,0 @@
{
"env": {
"browser": true,
"node": true,
"es2022": true
},
"parser": "@typescript-eslint/parser",
"plugins": ["@typescript-eslint"],
"parserOptions": {
"sourceType": "module"
},
"root": true,
"rules": {
"no-restricted-globals": ["error", "event", "self"],
"no-const-assign": ["error"],
"no-debugger": ["error"],
"no-dupe-class-members": ["error"],
"no-dupe-keys": ["error"],
"no-dupe-args": ["error"],
"no-dupe-else-if": ["error"],
"no-unsafe-negation": ["error"],
"no-duplicate-imports": ["error"],
"valid-typeof": ["error"],
"@typescript-eslint/no-unused-vars": ["error", { "vars": "all", "args": "none", "ignoreRestSiblings": false, "caughtErrors": "all" }],
"no-restricted-syntax": [
"error",
{
"selector": "MemberExpression[object.name='test'][property.name='only']",
"message": "test.only(...) is forbidden",
},
{
"selector": "MemberExpression[object.name='describe'][property.name='only']",
"message": "describe.only(...) is forbidden",
}
],
},
"globals": {
"describe": true,
"expect": true,
"test": true,
"beforeEach": true,
"beforeAll": true,
"afterEach": true,
"afterAll": true,
"jest": true,
},
}
+1 -2
View File
@@ -22,8 +22,7 @@ jobs:
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- run: npm ci
- run: npm install
- run: npm run test
- run: npm run check-formatting
- run: npm run lint
- run: npm run build
+3
View File
@@ -14,6 +14,9 @@ npm-debug.log*
yarn-debug.log*
yarn-error.log*
package-lock.json
yarn.lock
#ide's
.vscode
.idea
+3 -3
View File
@@ -174,9 +174,9 @@ class Root extends Component {
```
The template contains a [`t-foreach`](../reference/templates.md#loops) loop to iterate
through the tasks. It can find the `tasks` list from the component, since the rendering
context contains the properties of the component. Note that we use the `id` of each task
as a `t-key`, which is very common. There are two css classes: `task-list` and `task`,
through the tasks. It can find the `tasks` list from the component, since the
component is the rendering context. Note that we use the `id` of each task as a
`t-key`, which is very common. There are two css classes: `task-list` and `task`,
that we will use in the next section.
Finally, notice the use of the `t-att-checked` attribute:
+4 -3
View File
@@ -115,7 +115,7 @@ It is useful to explain the various rules that apply on these expressions:
<div><p t-if="console.log(1)">NOT valid</p></div>
```
2. it can use anything in the rendering context (which typically contains the properties of the component):
2. it can use anything in the rendering context (typically, the component):
```xml
<p t-if="user.birthday === today()">Happy bithday!</p>
@@ -541,8 +541,9 @@ This can be used to define variables scoped to a sub template:
```
Note: by default, the rendering context for a sub template is simply the current
rendering context. 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:
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"/>
-5711
View File
File diff suppressed because it is too large Load Diff
+6 -6
View File
@@ -1,6 +1,6 @@
{
"name": "@odoo/owl",
"version": "2.0.3",
"version": "2.0.2",
"description": "Odoo Web Library (OWL)",
"main": "dist/owl.cjs.js",
"module": "dist/owl.es.js",
@@ -25,7 +25,6 @@
"playground:watch": "npm-run-all --parallel playground:serve \"build:* -- --watch\"",
"prettier": "prettier {src/*.ts,src/**/*.ts,tests/*.ts,tests/**/*.ts,doc/*.md,doc/**/*.md} --write",
"check-formatting": "prettier {src/*.ts,src/**/*.ts,tests/*.ts,tests/**/*.ts,doc/*.md,doc/**/*.md} --check",
"lint": "eslint src/**/*.ts tests/**/*.ts",
"publish": "npm run build && npm publish",
"release": "node tools/release.js",
"compile_templates": "node tools/compile_xml.js"
@@ -43,25 +42,26 @@
"devDependencies": {
"@types/jest": "^27.0.1",
"@types/node": "^14.11.8",
"@typescript-eslint/eslint-plugin": "5.48.1",
"@typescript-eslint/parser": "5.48.1",
"chalk": "^3.0.0",
"cpx": "^1.5.0",
"current-git-branch": "^1.1.0",
"eslint": "8.31.0",
"git-rev-sync": "^1.12.0",
"github-api": "^3.3.0",
"jest": "^27.1.0",
"jest-diff": "^27.3.1",
"jest-environment-jsdom": "^27.1.0",
"live-server": "^1.2.1",
"npm-run-all": "^4.1.5",
"prettier": "2.4.1",
"rollup": "^2.56.3",
"rollup-plugin-dts": "^4.2.2",
"rollup-plugin-terser": "^7.0.2",
"rollup-plugin-typescript2": "^0.31.1",
"sass": "^1.16.1",
"source-map-support": "^0.5.10",
"ts-jest": "^27.0.5",
"typescript": "4.5.2"
"typescript": "4.5.2",
"uglify-es": "^3.3.9"
},
"jest": {
"testEnvironment": "jsdom",
+3 -3
View File
@@ -539,7 +539,7 @@ export class CodeGenerator {
if (modifiers.length) {
modifiersCode = `${modifiers.join(",")}, `;
}
return `[${modifiersCode}${this.captureExpression(handler)}, this]`;
return `[${modifiersCode}${this.captureExpression(handler)}, ctx]`;
}
compileTDomNode(ast: ASTDomNode, ctx: Context): string {
@@ -1140,7 +1140,7 @@ export class CodeGenerator {
if (this.target.loopLevel || !this.hasSafeContext) {
ctxStr = generateId("ctx");
this.helpers.add("capture");
this.define(ctxStr, `capture(ctx)`);
this.define(ctxStr, `capture(ctx, this)`);
}
let slotStr: string[] = [];
for (let slotName in ast.slots) {
@@ -1316,7 +1316,7 @@ export class CodeGenerator {
if (this.target.loopLevel || !this.hasSafeContext) {
ctxStr = generateId("ctx");
this.helpers.add("capture");
this.define(ctxStr, `capture(ctx)`);
this.define(ctxStr, `capture(ctx, this)`);
}
let id = generateId("comp");
this.staticDefs.push({
+1 -1
View File
@@ -28,7 +28,7 @@ import { OwlError } from "../runtime/error_handling";
//------------------------------------------------------------------------------
const RESERVED_WORDS =
"true,false,NaN,null,undefined,debugger,console,window,in,instanceof,new,function,return,eval,void,Math,RegExp,Array,Object,Date".split(
"true,false,NaN,null,undefined,debugger,console,window,in,instanceof,new,function,return,this,eval,void,Math,RegExp,Array,Object,Date".split(
","
);
+2 -1
View File
@@ -1,11 +1,12 @@
import { Component, ComponentConstructor, Props } from "./component";
import { ComponentNode } from "./component_node";
import { nodeErrorHandlers, OwlError, handleError } from "./error_handling";
import { nodeErrorHandlers, OwlError } from "./error_handling";
import { Fiber, MountOptions } from "./fibers";
import { Scheduler } from "./scheduler";
import { validateProps } from "./template_helpers";
import { TemplateSet, TemplateSetConfig } from "./template_set";
import { validateTarget } from "./utils";
import { handleError } from "./error_handling";
// reimplement dev mode stuff see last change in 0f7a8289a6fb8387c3c1af41c6664b2a8448758f
+1 -3
View File
@@ -114,8 +114,7 @@ export class ComponentNode<P extends Props = any, E = any> implements VNode<Comp
}
}
this.component = new C(props, env, this);
const ctx = Object.assign(Object.create(this.component), { this: this.component });
this.renderFn = app.getTemplate(C.template).bind(this.component, ctx, this);
this.renderFn = app.getTemplate(C.template).bind(this.component, this.component, this);
this.component.setup();
currentNode = null;
}
@@ -318,7 +317,6 @@ export class ComponentNode<P extends Props = any, E = any> implements VNode<Comp
}
_patch() {
let hasChildren = false;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
for (let _k in this.children) {
hasChildren = true;
break;
+1 -1
View File
@@ -25,7 +25,7 @@ export function makeRootFiber(node: ComponentNode): Fiber {
current.children = [];
current.childrenMap = {};
current.bdom = null;
if (fibersInError.has(current)) {
if (fibersInError.has(root)) {
fibersInError.delete(current);
fibersInError.delete(root);
current.appliedToDom = false;
+1 -1
View File
@@ -28,7 +28,7 @@ const COLLECTION_RAWTYPES = new Set(["Set", "Map", "WeakMap"]);
* @returns the raw type of the object
*/
function rawType(obj: any) {
return objectToString.call(toRaw(obj)).slice(8, -1);
return objectToString.call(obj).slice(8, -1);
}
/**
* Checks whether a given value can be made into a reactive object.
+3 -3
View File
@@ -46,8 +46,8 @@ function callSlot(
return slotBDom || text("");
}
function capture(ctx: any): any {
const result = ObjectCreate(ctx);
function capture(ctx: any, component: any): any {
const result = ObjectCreate(component);
for (let k in ctx) {
result[k] = ctx[k];
}
@@ -114,7 +114,7 @@ class LazyValue {
constructor(fn: any, ctx: any, component: any, node: any, key: any) {
this.fn = fn;
this.ctx = capture(ctx);
this.ctx = capture(ctx, component);
this.component = component;
this.node = node;
this.key = key;
@@ -8,7 +8,7 @@ exports[`t-on can bind event handler 1`] = `
let block1 = createBlock(\`<button block-handler-0=\\"click\\">Click</button>\`);
return function template(ctx, node, key = \\"\\") {
let hdlr1 = [ctx['add'], this];
let hdlr1 = [ctx['add'], ctx];
return block1([hdlr1]);
}
}"
@@ -23,7 +23,7 @@ exports[`t-on can bind handlers with arguments 1`] = `
return function template(ctx, node, key = \\"\\") {
const v1 = ctx['add'];
let hdlr1 = [()=>v1(5), this];
let hdlr1 = [()=>v1(5), ctx];
return block1([hdlr1]);
}
}"
@@ -38,7 +38,7 @@ exports[`t-on can bind handlers with empty object 1`] = `
return function template(ctx, node, key = \\"\\") {
const v1 = ctx['doSomething'];
let hdlr1 = [()=>v1({}), this];
let hdlr1 = [()=>v1({}), ctx];
return block1([hdlr1]);
}
}"
@@ -53,7 +53,7 @@ exports[`t-on can bind handlers with empty object (with non empty inner string)
return function template(ctx, node, key = \\"\\") {
const v1 = ctx['doSomething'];
let hdlr1 = [()=>v1({}), this];
let hdlr1 = [()=>v1({}), ctx];
return block1([hdlr1]);
}
}"
@@ -77,7 +77,7 @@ exports[`t-on can bind handlers with empty object (with non empty inner string)
const key1 = ctx['action_index'];
const v1 = ctx['activate'];
const v2 = ctx['action'];
let hdlr1 = [()=>v1(v2), this];
let hdlr1 = [()=>v1(v2), ctx];
c_block2[i1] = withKey(block3([hdlr1]), key1);
}
const b2 = list(c_block2);
@@ -95,7 +95,7 @@ exports[`t-on can bind handlers with object arguments 1`] = `
return function template(ctx, node, key = \\"\\") {
const v1 = ctx['add'];
let hdlr1 = [()=>v1({val:5}), this];
let hdlr1 = [()=>v1({val:5}), ctx];
return block1([hdlr1]);
}
}"
@@ -109,8 +109,8 @@ exports[`t-on can bind two event handlers 1`] = `
let block1 = createBlock(\`<button block-handler-0=\\"click\\" block-handler-1=\\"dblclick\\">Click</button>\`);
return function template(ctx, node, key = \\"\\") {
let hdlr1 = [ctx['handleClick'], this];
let hdlr2 = [ctx['handleDblClick'], this];
let hdlr1 = [ctx['handleClick'], ctx];
let hdlr2 = [ctx['handleDblClick'], ctx];
return block1([hdlr1, hdlr2]);
}
}"
@@ -124,7 +124,7 @@ exports[`t-on handler is bound to proper owner 1`] = `
let block1 = createBlock(\`<button block-handler-0=\\"click\\">Click</button>\`);
return function template(ctx, node, key = \\"\\") {
let hdlr1 = [ctx['add'], this];
let hdlr1 = [ctx['add'], ctx];
return block1([hdlr1]);
}
}"
@@ -144,7 +144,7 @@ exports[`t-on handler is bound to proper owner, part 2 1`] = `
for (let i1 = 0; i1 < l_block1; i1++) {
ctx[\`value\`] = v_block1[i1];
const key1 = ctx['value'];
let hdlr1 = [ctx['add'], this];
let hdlr1 = [ctx['add'], ctx];
c_block1[i1] = withKey(block2([hdlr1]), key1);
}
return list(c_block1);
@@ -172,7 +172,7 @@ exports[`t-on handler is bound to proper owner, part 3 2`] = `
let block1 = createBlock(\`<button block-handler-0=\\"click\\">Click</button>\`);
return function template(ctx, node, key = \\"\\") {
let hdlr1 = [ctx['add'], this];
let hdlr1 = [ctx['add'], ctx];
return block1([hdlr1]);
}
}"
@@ -210,7 +210,7 @@ exports[`t-on handler is bound to proper owner, part 4 2`] = `
let block1 = createBlock(\`<button block-handler-0=\\"click\\">Click</button>\`);
return function template(ctx, node, key = \\"\\") {
let hdlr1 = [ctx['add'], this];
let hdlr1 = [ctx['add'], ctx];
return block1([hdlr1]);
}
}"
@@ -224,7 +224,7 @@ exports[`t-on receive event in first argument 1`] = `
let block1 = createBlock(\`<button block-handler-0=\\"click\\">Click</button>\`);
return function template(ctx, node, key = \\"\\") {
let hdlr1 = [ctx['add'], this];
let hdlr1 = [ctx['add'], ctx];
return block1([hdlr1]);
}
}"
@@ -238,8 +238,8 @@ exports[`t-on t-on modifiers (native listener) basic support for native listener
let block1 = createBlock(\`<div class=\\"myClass\\" block-handler-0=\\"click\\"><button block-handler-1=\\"click\\">Button</button></div>\`);
return function template(ctx, node, key = \\"\\") {
let hdlr1 = [ctx['divClicked'], this];
let hdlr2 = [ctx['btnClicked'], this];
let hdlr1 = [ctx['divClicked'], ctx];
let hdlr2 = [ctx['btnClicked'], ctx];
return block1([hdlr1, hdlr2]);
}
}"
@@ -253,7 +253,7 @@ exports[`t-on t-on modifiers (native listener) t-on combined with t-esc 1`] = `
let block1 = createBlock(\`<div><button block-handler-0=\\"click\\"><block-text-1/></button></div>\`);
return function template(ctx, node, key = \\"\\") {
let hdlr1 = [ctx['onClick'], this];
let hdlr1 = [ctx['onClick'], ctx];
let txt1 = ctx['text'];
return block1([hdlr1, txt1]);
}
@@ -269,7 +269,7 @@ exports[`t-on t-on modifiers (native listener) t-on combined with t-out 1`] = `
let block1 = createBlock(\`<div><button block-handler-0=\\"click\\"><block-child-0/></button></div>\`);
return function template(ctx, node, key = \\"\\") {
let hdlr1 = [ctx['onClick'], this];
let hdlr1 = [ctx['onClick'], ctx];
const b2 = safeOutput(ctx['html']);
return block1([hdlr1], [b2]);
}
@@ -284,8 +284,8 @@ exports[`t-on t-on modifiers (native listener) t-on with .capture modifier 1`] =
let block1 = createBlock(\`<div block-handler-0=\\"click.capture\\"><button block-handler-1=\\"click\\">Button</button></div>\`);
return function template(ctx, node, key = \\"\\") {
let hdlr1 = [\\"capture\\", ctx['onCapture'], this];
let hdlr2 = [ctx['doSomething'], this];
let hdlr1 = [\\"capture\\", ctx['onCapture'], ctx];
let hdlr2 = [ctx['doSomething'], ctx];
return block1([hdlr1, hdlr2]);
}
}"
@@ -299,7 +299,7 @@ exports[`t-on t-on modifiers (native listener) t-on with empty handler (only mod
let block1 = createBlock(\`<div><button block-handler-0=\\"click.prevent\\">Button</button></div>\`);
return function template(ctx, node, key = \\"\\") {
let hdlr1 = [\\"prevent\\", , this];
let hdlr1 = [\\"prevent\\", , ctx];
return block1([hdlr1]);
}
}"
@@ -313,7 +313,7 @@ exports[`t-on t-on modifiers (native listener) t-on with prevent and self modifi
let block1 = createBlock(\`<div><button block-handler-0=\\"click.prevent.self\\"><span>Button</span></button></div>\`);
return function template(ctx, node, key = \\"\\") {
let hdlr1 = [\\"prevent\\",\\"self\\", ctx['onClick'], this];
let hdlr1 = [\\"prevent\\",\\"self\\", ctx['onClick'], ctx];
return block1([hdlr1]);
}
}"
@@ -327,9 +327,9 @@ exports[`t-on t-on modifiers (native listener) t-on with prevent and/or stop mod
let block1 = createBlock(\`<div><button block-handler-0=\\"click.prevent\\">Button 1</button><button block-handler-1=\\"click.stop\\">Button 2</button><button block-handler-2=\\"click.prevent.stop\\">Button 3</button></div>\`);
return function template(ctx, node, key = \\"\\") {
let hdlr1 = [\\"prevent\\", ctx['onClickPrevented'], this];
let hdlr2 = [\\"stop\\", ctx['onClickStopped'], this];
let hdlr3 = [\\"prevent\\",\\"stop\\", ctx['onClickPreventedAndStopped'], this];
let hdlr1 = [\\"prevent\\", ctx['onClickPrevented'], ctx];
let hdlr2 = [\\"stop\\", ctx['onClickStopped'], ctx];
let hdlr3 = [\\"prevent\\",\\"stop\\", ctx['onClickPreventedAndStopped'], ctx];
return block1([hdlr1, hdlr2, hdlr3]);
}
}"
@@ -352,7 +352,7 @@ exports[`t-on t-on modifiers (native listener) t-on with prevent modifier in t-f
const key1 = ctx['project'];
const v1 = ctx['onEdit'];
const v2 = ctx['project'];
let hdlr1 = [\\"prevent\\", _ev=>v1(v2.id,_ev), this];
let hdlr1 = [\\"prevent\\", _ev=>v1(v2.id,_ev), ctx];
let txt1 = ctx['project'].name;
c_block2[i1] = withKey(block3([hdlr1, txt1]), key1);
}
@@ -370,7 +370,7 @@ exports[`t-on t-on modifiers (native listener) t-on with self and prevent modifi
let block1 = createBlock(\`<div><button block-handler-0=\\"click.self.prevent\\"><span>Button</span></button></div>\`);
return function template(ctx, node, key = \\"\\") {
let hdlr1 = [\\"self\\",\\"prevent\\", ctx['onClick'], this];
let hdlr1 = [\\"self\\",\\"prevent\\", ctx['onClick'], ctx];
return block1([hdlr1]);
}
}"
@@ -384,8 +384,8 @@ exports[`t-on t-on modifiers (native listener) t-on with self modifier 1`] = `
let block1 = createBlock(\`<div><button block-handler-0=\\"click\\"><span>Button</span></button><button block-handler-1=\\"click.self\\"><span>Button</span></button></div>\`);
return function template(ctx, node, key = \\"\\") {
let hdlr1 = [ctx['onClick'], this];
let hdlr2 = [\\"self\\", ctx['onClickSelf'], this];
let hdlr1 = [ctx['onClick'], ctx];
let hdlr2 = [\\"self\\", ctx['onClickSelf'], ctx];
return block1([hdlr1, hdlr2]);
}
}"
@@ -399,8 +399,8 @@ exports[`t-on t-on modifiers (synthetic listener) basic support for synthetic 1`
let block1 = createBlock(\`<div block-handler-0=\\"click.synthetic\\"><button block-handler-1=\\"click.synthetic\\">Button</button></div>\`);
return function template(ctx, node, key = \\"\\") {
let hdlr1 = [\\"synthetic\\", ctx['divClicked'], this];
let hdlr2 = [\\"synthetic\\", ctx['btnClicked'], this];
let hdlr1 = [\\"synthetic\\", ctx['divClicked'], ctx];
let hdlr2 = [\\"synthetic\\", ctx['btnClicked'], ctx];
return block1([hdlr1, hdlr2]);
}
}"
@@ -415,7 +415,7 @@ exports[`t-on t-on with inline statement (function call) 1`] = `
return function template(ctx, node, key = \\"\\") {
const v1 = ctx['state'];
let hdlr1 = [()=>v1.incrementCounter(2), this];
let hdlr1 = [()=>v1.incrementCounter(2), ctx];
return block1([hdlr1]);
}
}"
@@ -430,7 +430,7 @@ exports[`t-on t-on with inline statement 1`] = `
return function template(ctx, node, key = \\"\\") {
const v1 = ctx['state'];
let hdlr1 = [()=>v1.counter++, this];
let hdlr1 = [()=>v1.counter++, ctx];
return block1([hdlr1]);
}
}"
@@ -445,7 +445,7 @@ exports[`t-on t-on with inline statement, part 2 1`] = `
return function template(ctx, node, key = \\"\\") {
const v1 = ctx['state'];
let hdlr1 = [()=>v1.flag=!v1.flag, this];
let hdlr1 = [()=>v1.flag=!v1.flag, ctx];
return block1([hdlr1]);
}
}"
@@ -461,7 +461,7 @@ exports[`t-on t-on with inline statement, part 3 1`] = `
return function template(ctx, node, key = \\"\\") {
const v1 = ctx['state'];
const v2 = ctx['someFunction'];
let hdlr1 = [()=>v1.n=v2(3), this];
let hdlr1 = [()=>v1.n=v2(3), ctx];
return block1([hdlr1]);
}
}"
@@ -490,7 +490,7 @@ exports[`t-on t-on with t-call 2`] = `
let block1 = createBlock(\`<p block-handler-0=\\"click\\">lucas</p>\`);
return function template(ctx, node, key = \\"\\") {
let hdlr1 = [ctx['update'], this];
let hdlr1 = [ctx['update'], ctx];
return block1([hdlr1]);
}
}"
@@ -519,9 +519,8 @@ exports[`t-on t-on, with arguments and t-call 2`] = `
let block1 = createBlock(\`<p block-handler-0=\\"click\\">lucas</p>\`);
return function template(ctx, node, key = \\"\\") {
const v1 = ctx['this'];
const v2 = ctx['value'];
let hdlr1 = [()=>v1.update(v2), this];
const v1 = ctx['value'];
let hdlr1 = [()=>this.update(v1), ctx];
return block1([hdlr1]);
}
}"
+11 -11
View File
@@ -228,7 +228,7 @@ exports[`misc other complex template 1`] = `
for (let i1 = 0; i1 < l_block2; i1++) {
ctx[\`project\`] = v_block2[i1];
const key1 = ctx['project'].id;
let hdlr1 = [ctx['selectProject'](ctx['project']), this];
let hdlr1 = [ctx['selectProject'](ctx['project']), ctx];
let txt2 = ctx['project'].name;
c_block2[i1] = withKey(block3([hdlr1, txt2]), key1);
}
@@ -260,8 +260,8 @@ exports[`misc other complex template 1`] = `
}
b4 = multi([b5, b6]);
}
let hdlr2 = [ctx['toggleSettingsMenu'], this];
let hdlr3 = [ctx['toggleMore'], this];
let hdlr2 = [ctx['toggleSettingsMenu'], ctx];
let hdlr3 = [ctx['toggleMore'], ctx];
if (ctx['categories']&&ctx['categories'].length>1) {
ctx = Object.create(ctx);
const [k_block15, v_block15, l_block15, c_block15] = prepareList(ctx['categories']);;
@@ -278,9 +278,9 @@ exports[`misc other complex template 1`] = `
b14 = block14([], [b15]);
}
let attr8 = new String((ctx['search'].value) || \\"\\");
let hdlr4 = [ctx['updateFilter'], this];
let hdlr5 = [ctx['updateFilter'], this];
let hdlr6 = [ctx['clearSearch'], this];
let hdlr4 = [ctx['updateFilter'], ctx];
let hdlr5 = [ctx['updateFilter'], ctx];
let hdlr6 = [ctx['clearSearch'], ctx];
if (ctx['triggers']) {
ctx = Object.create(ctx);
const [k_block18, v_block18, l_block18, c_block18] = prepareList(ctx['triggers']);;
@@ -293,7 +293,7 @@ exports[`misc other complex template 1`] = `
let attr10 = \`trigger_\${ctx['trigger'].id}\`;
let attr11 = new Boolean(ctx['options'].trigger_display[ctx['trigger'].id]);
let attr12 = ctx['trigger'].id;
let hdlr7 = [ctx['updateTriggerDisplay'], this];
let hdlr7 = [ctx['updateTriggerDisplay'], ctx];
let attr13 = \`trigger_\${ctx['trigger'].id}\`;
let txt6 = ctx['trigger'].name;
b20 = block20([attr9, attr10, attr11, attr12, hdlr7, attr13, txt6]);
@@ -302,10 +302,10 @@ exports[`misc other complex template 1`] = `
}
ctx = ctx.__proto__;
const b18 = list(c_block18);
let hdlr8 = [ctx['triggerAll'], this];
let hdlr9 = [ctx['triggerNone'], this];
let hdlr10 = [ctx['triggerDefault'], this];
let hdlr11 = [ctx['toggleSettingsMenu'], this];
let hdlr8 = [ctx['triggerAll'], ctx];
let hdlr9 = [ctx['triggerNone'], ctx];
let hdlr10 = [ctx['triggerDefault'], ctx];
let hdlr11 = [ctx['toggleSettingsMenu'], ctx];
const b21 = block21([hdlr8, hdlr9, hdlr10, hdlr11]);
b17 = multi([b18, b21]);
}
+3 -12
View File
@@ -161,9 +161,7 @@ describe("t-on", () => {
owner.__owl__ = node;
const fixture = makeTestFixture();
const render = context.getTemplate("main");
const ctx = Object.create(owner);
ctx.this = owner;
const bdom = render.call(owner, ctx, node);
const bdom = render(owner, node);
mount(bdom, fixture);
fixture.querySelector("button")!.click();
});
@@ -188,9 +186,7 @@ describe("t-on", () => {
owner.__owl__ = node;
const fixture = makeTestFixture();
const render = context.getTemplate("main");
const ctx = Object.create(owner);
ctx.this = owner;
const bdom = render.call(owner, ctx, node);
const bdom = render(owner, node);
mount(bdom, fixture);
fixture.querySelector("button")!.click();
});
@@ -270,9 +266,7 @@ describe("t-on", () => {
const fixture = makeTestFixture();
const render = app.getTemplate("main");
const ctx = Object.create(owner);
ctx.this = owner;
const bdom = render.call(owner, ctx, node);
const bdom = render(owner, node);
mount(bdom, fixture);
fixture.querySelector("p")!.click();
});
@@ -290,9 +284,6 @@ describe("t-on", () => {
expect(this).toBe(owner);
expect(val).toBe(444);
},
get this() {
return owner;
},
value: 444,
};
@@ -135,7 +135,7 @@ exports[`basics can be clicked on and updated 1`] = `
return function template(ctx, node, key = \\"\\") {
let txt1 = ctx['state'].counter;
const v1 = ctx['state'];
let hdlr1 = [()=>v1.counter++, this];
let hdlr1 = [()=>v1.counter++, ctx];
return block1([txt1, hdlr1]);
}
}"
@@ -646,7 +646,7 @@ exports[`basics rerendering a widget with a sub widget 2`] = `
return function template(ctx, node, key = \\"\\") {
let txt1 = ctx['state'].counter;
const v1 = ctx['state'];
let hdlr1 = [()=>v1.counter++, this];
let hdlr1 = [()=>v1.counter++, ctx];
return block1([txt1, hdlr1]);
}
}"
@@ -93,7 +93,7 @@ exports[`another scenario with delayed rendering 3`] = `
let block1 = createBlock(\`<button block-handler-0=\\"click\\"><block-text-1/></button>\`);
return function template(ctx, node, key = \\"\\") {
let hdlr1 = [ctx['increment'], this];
let hdlr1 = [ctx['increment'], ctx];
let txt1 = ctx['state'].val;
return block1([hdlr1, txt1]);
}
@@ -1262,7 +1262,7 @@ exports[`delayed rendering, but then initial rendering is cancelled by yet anoth
let block1 = createBlock(\`<button block-handler-0=\\"click\\"><block-text-1/></button>\`);
return function template(ctx, node, key = \\"\\") {
let hdlr1 = [ctx['increment'], this];
let hdlr1 = [ctx['increment'], ctx];
let txt1 = ctx['state'].val;
return block1([hdlr1, txt1]);
}
@@ -1327,7 +1327,7 @@ exports[`delayed rendering, destruction, stuff happens 4`] = `
return function template(ctx, node, key = \\"\\") {
const b2 = text(\`D\`);
let hdlr1 = [ctx['increment'], this];
let hdlr1 = [ctx['increment'], ctx];
let txt1 = ctx['state'].val;
const b3 = block3([hdlr1, txt1]);
return multi([b2, b3]);
@@ -1369,7 +1369,7 @@ exports[`delayed rendering, reusing fiber and stuff 3`] = `
let block1 = createBlock(\`<button block-handler-0=\\"click\\"><block-text-1/></button>\`);
return function template(ctx, node, key = \\"\\") {
let hdlr1 = [ctx['increment'], this];
let hdlr1 = [ctx['increment'], ctx];
let txt1 = ctx['state'].val;
return block1([hdlr1, txt1]);
}
@@ -1415,7 +1415,7 @@ exports[`delayed rendering, reusing fiber then component is destroyed and stuff
let block1 = createBlock(\`<button block-handler-0=\\"click\\"><block-text-1/></button>\`);
return function template(ctx, node, key = \\"\\") {
let hdlr1 = [ctx['increment'], this];
let hdlr1 = [ctx['increment'], ctx];
let txt1 = ctx['state'].val;
return block1([hdlr1, txt1]);
}
@@ -1459,7 +1459,7 @@ exports[`delayed rendering, then component is destroyed and stuff 3`] = `
let block1 = createBlock(\`<button block-handler-0=\\"click\\"><block-text-1/></button>\`);
return function template(ctx, node, key = \\"\\") {
let hdlr1 = [ctx['increment'], this];
let hdlr1 = [ctx['increment'], ctx];
let txt1 = ctx['state'].val;
return block1([hdlr1, txt1]);
}
@@ -1647,7 +1647,7 @@ exports[`rendering component again in next microtick 1`] = `
return function template(ctx, node, key = \\"\\") {
let b2;
let hdlr1 = [ctx['onClick'], this];
let hdlr1 = [ctx['onClick'], ctx];
if (ctx['env'].config.flag) {
b2 = comp1({}, key + \`__1\`, node, this, null);
}
@@ -1734,7 +1734,7 @@ exports[`renderings, destruction, patch, stuff, ... yet another variation 3`] =
return function template(ctx, node, key = \\"\\") {
const b2 = text(\`D\`);
let hdlr1 = [ctx['increment'], this];
let hdlr1 = [ctx['increment'], ctx];
let txt1 = ctx['state'].val;
const b3 = block3([hdlr1, txt1]);
return multi([b2, b3]);
@@ -1751,7 +1751,7 @@ exports[`renderings, destruction, patch, stuff, ... yet another variation 4`] =
return function template(ctx, node, key = \\"\\") {
const b2 = text(\`C\`);
let hdlr1 = [ctx['increment'], this];
let hdlr1 = [ctx['increment'], ctx];
let txt1 = ctx['state'].val;
const b3 = block3([hdlr1, txt1]);
return multi([b2, b3]);
@@ -940,10 +940,9 @@ exports[`can catch errors catching error, rethrow, render parent -- a main comp
for (let i1 = 0; i1 < l_block1; i1++) {
ctx[\`cp\`] = v_block1[i1];
const key1 = ctx['cp'].id;
const v1 = ctx['this'];
const v2 = ctx['cp'];
const ctx1 = capture(ctx);
c_block1[i1] = withKey(comp2({onError: ()=>v1.cleanUp(v2.id),slots: markRaw({'default': {__render: slot1.bind(this), __ctx: ctx1}})}, key + \`__2__\${key1}\`, node, this, null), key1);
const v1 = ctx['cp'];
const ctx1 = capture(ctx, this);
c_block1[i1] = withKey(comp2({onError: ()=>this.cleanUp(v1.id),slots: markRaw({'default': {__render: slot1.bind(this), __ctx: ctx1}})}, key + \`__2__\${key1}\`, node, this, null), key1);
}
return list(c_block1);
}
@@ -1015,14 +1014,13 @@ exports[`can catch errors catching in child makes parent render 1`] = `
return function template(ctx, node, key = \\"\\") {
ctx = Object.create(ctx);
const [k_block1, v_block1, l_block1, c_block1] = prepareList(Object.entries(ctx['this'].elements));;
const [k_block1, v_block1, l_block1, c_block1] = prepareList(Object.entries(this.elements));;
for (let i1 = 0; i1 < l_block1; i1++) {
ctx[\`elem\`] = v_block1[i1];
const key1 = ctx['elem'][0];
const v1 = ctx['this'];
const v2 = ctx['elem'];
const ctx1 = capture(ctx);
c_block1[i1] = withKey(comp2({onError: (_error)=>v1.onError(v2[0],_error),slots: markRaw({'default': {__render: slot1.bind(this), __ctx: ctx1}})}, key + \`__2__\${key1}\`, node, this, null), key1);
const v1 = ctx['elem'];
const ctx1 = capture(ctx, this);
c_block1[i1] = withKey(comp2({onError: (_error)=>this.onError(v1[0],_error),slots: markRaw({'default': {__render: slot1.bind(this), __ctx: ctx1}})}, key + \`__2__\${key1}\`, node, this, null), key1);
}
return list(c_block1);
}
@@ -1157,7 +1155,7 @@ exports[`can catch errors onError in class inheritance is called if rethrown 2`]
return function template(ctx, node, key = \\"\\") {
let b2,b3;
if (!ctx['state'].error) {
b2 = text(ctx['this'].will.crash);
b2 = text(this.will.crash);
} else {
b3 = text(ctx['state'].error);
}
@@ -1188,7 +1186,7 @@ exports[`can catch errors onError in class inheritance is not called if no rethr
return function template(ctx, node, key = \\"\\") {
let b2,b3;
if (!ctx['state'].error) {
b2 = text(ctx['this'].will.crash);
b2 = text(this.will.crash);
} else {
b3 = text(ctx['state'].error);
}
@@ -1197,6 +1195,131 @@ exports[`can catch errors onError in class inheritance is not called if no rethr
}"
`;
exports[`can catch errors re-render parent when self is in error - 2 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
const comp1 = app.createComponent(\`Classic\`, true, false, false, false);
const comp2 = app.createComponent(\`Classic\`, true, false, false, false);
return function template(ctx, node, key = \\"\\") {
const b2 = comp1({hasBoom: true,state: ctx['reactive']}, key + \`__1\`, node, this, null);
const b3 = comp2({hasBoom: false,state: ctx['reactive']}, key + \`__2\`, node, this, null);
return multi([b2, b3]);
}
}"
`;
exports[`can catch errors re-render parent when self is in error - 2 2`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
const comp1 = app.createComponent(\`BoomWrapper\`, true, false, false, false);
let block3 = createBlock(\`<div><block-text-0/></div>\`);
return function template(ctx, node, key = \\"\\") {
let b2,b3;
if (ctx['props'].hasBoom) {
b2 = comp1({state: ctx['props'].state}, key + \`__1\`, node, this, null);
} else {
let txt1 = ctx['props'].state.safeTree;
b3 = block3([txt1]);
}
return multi([b2, b3]);
}
}"
`;
exports[`can catch errors re-render parent when self is in error - 2 3`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
const comp1 = app.createComponent(\`Boom\`, true, false, false, true);
return function template(ctx, node, key = \\"\\") {
let b2,b3;
if (ctx['state'].errorTree==='error') {
b2 = comp1({}, key + \`__1\`, node, this, null);
} else {
b3 = text(ctx['state'].errorTree);
}
return multi([b2, b3]);
}
}"
`;
exports[`can catch errors re-render parent when self is in error - 2 4`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let block1 = createBlock(\`<div/>\`);
return function template(ctx, node, key = \\"\\") {
return block1();
}
}"
`;
exports[`can catch errors re-render parent when self is in error 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
const comp1 = app.createComponent(\`Classic\`, true, false, false, true);
return function template(ctx, node, key = \\"\\") {
return comp1({}, key + \`__1\`, node, this, null);
}
}"
`;
exports[`can catch errors re-render parent when self is in error 2`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let { bind } = helpers;
const comp1 = app.createComponent(\`BoomWrapper\`, true, false, false, false);
let block3 = createBlock(\`<div/>\`);
return function template(ctx, node, key = \\"\\") {
let b2,b3;
if (!ctx['inError']) {
b2 = comp1({onError: bind(this, ctx['onErrorAsProps'])}, key + \`__1\`, node, this, null);
} else {
b3 = block3();
}
return multi([b2, b3]);
}
}"
`;
exports[`can catch errors re-render parent when self is in error 3`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
const comp1 = app.createComponent(\`Boom\`, true, false, false, true);
return function template(ctx, node, key = \\"\\") {
return comp1({}, key + \`__1\`, node, this, null);
}
}"
`;
exports[`can catch errors re-render parent when self is in error 4`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let block1 = createBlock(\`<div/>\`);
return function template(ctx, node, key = \\"\\") {
return block1();
}
}"
`;
exports[`errors and promises a rendering error in a sub component will reject the mount promise 1`] = `
"function anonymous(app, bdom, helpers
) {
@@ -1220,7 +1343,7 @@ exports[`errors and promises a rendering error in a sub component will reject th
let block1 = createBlock(\`<div><block-text-0/></div>\`);
return function template(ctx, node, key = \\"\\") {
let txt1 = ctx['this'].will.crash;
let txt1 = this.will.crash;
return block1([txt1]);
}
}"
@@ -1234,7 +1357,7 @@ exports[`errors and promises a rendering error will reject the mount promise 1`]
let block1 = createBlock(\`<div><block-text-0/></div>\`);
return function template(ctx, node, key = \\"\\") {
let txt1 = ctx['this'].will.crash;
let txt1 = this.will.crash;
return block1([txt1]);
}
}"
@@ -1279,7 +1402,7 @@ exports[`errors and promises a rendering error will reject the render promise 1`
return function template(ctx, node, key = \\"\\") {
let b2;
if (ctx['flag']) {
b2 = text(ctx['this'].will.crash);
b2 = text(this.will.crash);
}
return block1([], [b2]);
}
@@ -8,7 +8,7 @@ exports[`event handling Invalid handler throws an error 1`] = `
let block1 = createBlock(\`<button block-handler-0=\\"click\\">click</button>\`);
return function template(ctx, node, key = \\"\\") {
let hdlr1 = [ctx['dosomething'], this];
let hdlr1 = [ctx['dosomething'], ctx];
return block1([hdlr1]);
}
}"
@@ -22,7 +22,7 @@ exports[`event handling handler is not called if component is destroyed 1`] = `
let block1 = createBlock(\`<span block-handler-0=\\"click\\"/>\`);
return function template(ctx, node, key = \\"\\") {
let hdlr1 = [ctx['click'], this];
let hdlr1 = [ctx['click'], ctx];
return block1([hdlr1]);
}
}"
@@ -37,7 +37,7 @@ exports[`event handling handler receive the event as argument 1`] = `
let block1 = createBlock(\`<span block-handler-0=\\"click\\"><block-child-0/><block-text-1/></span>\`);
return function template(ctx, node, key = \\"\\") {
let hdlr1 = [ctx['inc'], this];
let hdlr1 = [ctx['inc'], ctx];
const b2 = comp1({}, key + \`__1\`, node, this, null);
let txt1 = ctx['state'].value;
return block1([hdlr1, txt1], [b2]);
@@ -66,7 +66,7 @@ exports[`event handling handler works when app is mounted in an iframe 1`] = `
let block1 = createBlock(\`<span block-handler-0=\\"click\\">click me</span>\`);
return function template(ctx, node, key = \\"\\") {
let hdlr1 = [ctx['inc'], this];
let hdlr1 = [ctx['inc'], ctx];
return block1([hdlr1]);
}
}"
@@ -98,7 +98,7 @@ exports[`event handling input blur event is not called if component is destroyed
let block1 = createBlock(\`<input block-handler-0=\\"blur\\"/>\`);
return function template(ctx, node, key = \\"\\") {
let hdlr1 = [ctx['blur'], this];
let hdlr1 = [ctx['blur'], ctx];
return block1([hdlr1]);
}
}"
@@ -121,7 +121,7 @@ exports[`event handling objects from scope are properly captured by t-on 1`] = `
const key1 = ctx['item'];
const v1 = ctx['onClick'];
const v2 = ctx['item'];
let hdlr1 = [_ev=>v1(v2.val,_ev), this];
let hdlr1 = [_ev=>v1(v2.val,_ev), ctx];
c_block2[i1] = withKey(block3([hdlr1]), key1);
}
const b2 = list(c_block2);
@@ -139,7 +139,7 @@ exports[`event handling support for callable expression in event handler 1`] = `
return function template(ctx, node, key = \\"\\") {
let txt1 = ctx['state'].value;
let hdlr1 = [ctx['obj'].onInput, this];
let hdlr1 = [ctx['obj'].onInput, ctx];
return block1([txt1, hdlr1]);
}
}"
@@ -162,7 +162,7 @@ exports[`event handling t-on with handler bound to dynamic argument on a t-forea
const key1 = ctx['item'];
const v1 = ctx['onClick'];
const v2 = ctx['item'];
let hdlr1 = [_ev=>v1(v2,_ev), this];
let hdlr1 = [_ev=>v1(v2,_ev), ctx];
c_block2[i1] = withKey(block3([hdlr1]), key1);
}
const b2 = list(c_block2);
@@ -138,7 +138,7 @@ exports[`basics sub widget is interactive 2`] = `
let block1 = createBlock(\`<span><button block-handler-0=\\"click\\">click</button>child<block-text-1/></span>\`);
return function template(ctx, node, key = \\"\\") {
let hdlr1 = [ctx['inc'], this];
let hdlr1 = [ctx['inc'], ctx];
let txt1 = ctx['state'].val;
return block1([hdlr1, txt1]);
}
@@ -563,7 +563,7 @@ exports[`lifecycle hooks onWillRender 2`] = `
let block1 = createBlock(\`<button block-handler-0=\\"click\\"><block-text-1/></button>\`);
return function template(ctx, node, key = \\"\\") {
let hdlr1 = [ctx['increment'], this];
let hdlr1 = [ctx['increment'], ctx];
let txt1 = ctx['state'].value;
return block1([hdlr1, txt1]);
}
@@ -59,7 +59,7 @@ exports[`basics arrow functions as prop correctly capture their scope 2`] = `
let block1 = createBlock(\`<button block-handler-0=\\"click\\"/>\`);
return function template(ctx, node, key = \\"\\") {
let hdlr1 = [ctx['props'].onClick, this];
let hdlr1 = [ctx['props'].onClick, ctx];
return block1([hdlr1]);
}
}"
@@ -140,7 +140,7 @@ exports[`basics support prop names that aren't valid bare object property names
let block1 = createBlock(\`<button block-handler-0=\\"click\\"/>\`);
return function template(ctx, node, key = \\"\\") {
let hdlr1 = [ctx['props'].onClick, this];
let hdlr1 = [ctx['props'].onClick, ctx];
return block1([hdlr1]);
}
}"
@@ -72,13 +72,13 @@ exports[`refs refs are properly bound in slots 1`] = `
function slot1(ctx, node, key = \\"\\") {
const refs = this.__owl__.refs;
const ref1 = (el) => refs[\`myButton\`] = el;
let hdlr1 = [ctx['doSomething'], this];
let hdlr1 = [ctx['doSomething'], ctx];
return block2([hdlr1, ref1]);
}
return function template(ctx, node, key = \\"\\") {
let txt1 = ctx['state'].val;
const ctx1 = capture(ctx);
const ctx1 = capture(ctx, this);
const b3 = comp1({slots: markRaw({'footer': {__render: slot1.bind(this), __ctx: ctx1}})}, key + \`__1\`, node, this, null);
return block1([txt1], [b3]);
}
@@ -54,7 +54,7 @@ exports[`slots can define and call slots 1`] = `
}
return function template(ctx, node, key = \\"\\") {
const ctx1 = capture(ctx);
const ctx1 = capture(ctx, this);
const b4 = comp1({slots: markRaw({'header': {__render: slot1.bind(this), __ctx: ctx1}, 'footer': {__render: slot2.bind(this), __ctx: ctx1}})}, key + \`__1\`, node, this, null);
return block1([], [b4]);
}
@@ -89,7 +89,7 @@ exports[`slots can define and call slots with bound params 1`] = `
}
return function template(ctx, node, key = \\"\\") {
const ctx1 = capture(ctx);
const ctx1 = capture(ctx, this);
return comp1({slots: markRaw({'abc': {__render: slot1.bind(this), __ctx: ctx1, getValue: bind(this, ctx['getValue'])}})}, key + \`__1\`, node, this, null);
}
}"
@@ -129,7 +129,7 @@ exports[`slots can define and call slots with params 1`] = `
}
return function template(ctx, node, key = \\"\\") {
const ctx1 = capture(ctx);
const ctx1 = capture(ctx, this);
const b4 = comp1({slots: markRaw({'header': {__render: slot1.bind(this), __ctx: ctx1, param: ctx['var']}, 'footer': {__render: slot2.bind(this), __ctx: ctx1, param: '5'}})}, key + \`__1\`, node, this, null);
return block1([], [b4]);
}
@@ -363,7 +363,7 @@ exports[`slots default content is not rendered if named slot is provided 1`] = `
}
return function template(ctx, node, key = \\"\\") {
const ctx1 = capture(ctx);
const ctx1 = capture(ctx, this);
const b3 = comp1({slots: markRaw({'header': {__render: slot1.bind(this), __ctx: ctx1}})}, key + \`__1\`, node, this, null);
return block1([], [b3]);
}
@@ -442,7 +442,7 @@ exports[`slots default slot next to named slot, with default content 1`] = `
}
return function template(ctx, node, key = \\"\\") {
const ctx1 = capture(ctx);
const ctx1 = capture(ctx, this);
const b3 = comp1({slots: markRaw({'footer': {__render: slot1.bind(this), __ctx: ctx1}})}, key + \`__1\`, node, this, null);
return block1([], [b3]);
}
@@ -619,7 +619,7 @@ exports[`slots dynamic slot in multiple locations 1`] = `
}
return function template(ctx, node, key = \\"\\") {
const ctx1 = capture(ctx);
const ctx1 = capture(ctx, this);
return comp2({location: ctx['state'].location,slots: markRaw({'coffee': {__render: slot1.bind(this), __ctx: ctx1}})}, key + \`__2\`, node, this, null);
}
}"
@@ -685,7 +685,7 @@ exports[`slots dynamic t-slot call 1`] = `
}
return function template(ctx, node, key = \\"\\") {
const ctx1 = capture(ctx);
const ctx1 = capture(ctx, this);
const b6 = comp1({slots: markRaw({'slot1': {__render: slot1.bind(this), __ctx: ctx1}, 'slot2': {__render: slot2.bind(this), __ctx: ctx1}})}, key + \`__1\`, node, this, null);
return block1([], [b6]);
}
@@ -701,7 +701,7 @@ exports[`slots dynamic t-slot call 2`] = `
let block1 = createBlock(\`<button block-handler-0=\\"click\\"><block-child-0/></button>\`);
return function template(ctx, node, key = \\"\\") {
let hdlr1 = [ctx['toggle'], this];
let hdlr1 = [ctx['toggle'], ctx];
const slot1 = (ctx['current'].slot);
const b2 = toggler(slot1, callSlot(ctx, node, key + \`__1\`, slot1, true, {}));
return block1([hdlr1], [b2]);
@@ -732,7 +732,7 @@ exports[`slots dynamic t-slot call with default 1`] = `
}
return function template(ctx, node, key = \\"\\") {
const ctx1 = capture(ctx);
const ctx1 = capture(ctx, this);
const b6 = comp1({slots: markRaw({'slot1': {__render: slot1.bind(this), __ctx: ctx1}, 'slot2': {__render: slot2.bind(this), __ctx: ctx1}})}, key + \`__1\`, node, this, null);
return block1([], [b6]);
}
@@ -752,7 +752,7 @@ exports[`slots dynamic t-slot call with default 2`] = `
}
return function template(ctx, node, key = \\"\\") {
let hdlr1 = [ctx['toggle'], this];
let hdlr1 = [ctx['toggle'], ctx];
const b3 = callSlot(ctx, node, key + \`__1\`, (ctx['current'].slot), true, {}, defaultContent1.bind(this));
return block1([hdlr1], [b3]);
}
@@ -842,7 +842,7 @@ exports[`slots mix of slots, t-call, t-call with body, and giving own props chil
let block2 = createBlock(\`<button block-handler-0=\\"click\\">inc</button>\`);
return function template(ctx, node, key = \\"\\") {
let hdlr1 = [ctx['inc'], this];
let hdlr1 = [ctx['inc'], ctx];
const b2 = block2([hdlr1]);
const b3 = comp1({number: ctx['state'].number}, key + \`__1\`, node, this, null);
return multi([b2, b3]);
@@ -865,7 +865,7 @@ exports[`slots mix of slots, t-call, t-call with body, and giving own props chil
}
return function template(ctx, node, key = \\"\\") {
const ctx1 = capture(ctx);
const ctx1 = capture(ctx, this);
return comp1({slots: markRaw({'default': {__render: slot1.bind(this), __ctx: ctx1}})}, key + \`__2\`, node, this, null);
}
}"
@@ -991,7 +991,7 @@ exports[`slots multiple roots are allowed in a named slot 1`] = `
}
return function template(ctx, node, key = \\"\\") {
const ctx1 = capture(ctx);
const ctx1 = capture(ctx, this);
const b5 = comp1({slots: markRaw({'content': {__render: slot1.bind(this), __ctx: ctx1}})}, key + \`__1\`, node, this, null);
return block1([], [b5]);
}
@@ -1031,7 +1031,7 @@ exports[`slots multiple slots containing components 1`] = `
}
return function template(ctx, node, key = \\"\\") {
const ctx1 = capture(ctx);
const ctx1 = capture(ctx, this);
return comp3({slots: markRaw({'s1': {__render: slot1.bind(this), __ctx: ctx1}, 's2': {__render: slot2.bind(this), __ctx: ctx1}})}, key + \`__3\`, node, this, null);
}
}"
@@ -1085,7 +1085,7 @@ exports[`slots named slot inside slot 1`] = `
}
function slot2(ctx, node, key = \\"\\") {
const ctx2 = capture(ctx);
const ctx2 = capture(ctx, this);
return comp1({slots: markRaw({'brol': {__render: slot3.bind(this), __ctx: ctx2}})}, key + \`__1\`, node, this, null);
}
@@ -1095,7 +1095,7 @@ exports[`slots named slot inside slot 1`] = `
}
return function template(ctx, node, key = \\"\\") {
const ctx1 = capture(ctx);
const ctx1 = capture(ctx, this);
const b5 = comp2({slots: markRaw({'brol': {__render: slot1.bind(this), __ctx: ctx1}, 'default': {__render: slot2.bind(this), __ctx: ctx1}})}, key + \`__2\`, node, this, null);
return block1([], [b5]);
}
@@ -1136,7 +1136,7 @@ exports[`slots named slot inside slot, part 3 1`] = `
}
function slot2(ctx, node, key = \\"\\") {
const ctx2 = capture(ctx);
const ctx2 = capture(ctx, this);
return comp1({slots: markRaw({'brol': {__render: slot3.bind(this), __ctx: ctx2}})}, key + \`__1\`, node, this, null);
}
@@ -1146,7 +1146,7 @@ exports[`slots named slot inside slot, part 3 1`] = `
}
return function template(ctx, node, key = \\"\\") {
const ctx1 = capture(ctx);
const ctx1 = capture(ctx, this);
const b5 = comp2({slots: markRaw({'brol': {__render: slot1.bind(this), __ctx: ctx1}, 'default': {__render: slot2.bind(this), __ctx: ctx1}})}, key + \`__2\`, node, this, null);
return block1([], [b5]);
}
@@ -1221,7 +1221,7 @@ exports[`slots named slots inside slot, again 1`] = `
}
function slot2(ctx, node, key = \\"\\") {
const ctx2 = capture(ctx);
const ctx2 = capture(ctx, this);
return comp1({slots: markRaw({'brol2': {__render: slot3.bind(this), __ctx: ctx2}})}, key + \`__1\`, node, this, null);
}
@@ -1231,7 +1231,7 @@ exports[`slots named slots inside slot, again 1`] = `
}
return function template(ctx, node, key = \\"\\") {
const ctx1 = capture(ctx);
const ctx1 = capture(ctx, this);
const b5 = comp2({slots: markRaw({'brol1': {__render: slot1.bind(this), __ctx: ctx1}, 'default': {__render: slot2.bind(this), __ctx: ctx1}})}, key + \`__2\`, node, this, null);
return block1([], [b5]);
}
@@ -1569,7 +1569,7 @@ exports[`slots simple dynamic slot with slot scope 1`] = `
}
return function template(ctx, node, key = \\"\\") {
const ctx1 = capture(ctx);
const ctx1 = capture(ctx, this);
return comp1({slots: markRaw({'slotName': {__render: slot1.bind(this), __ctx: ctx1, __scope: \\"slotScope\\"}})}, key + \`__1\`, node, this, null);
}
}"
@@ -1599,7 +1599,7 @@ exports[`slots simple named and empty slot -- 2 1`] = `
const comp1 = app.createComponent(\`Child\`, true, true, false, true);
return function template(ctx, node, key = \\"\\") {
const ctx1 = capture(ctx);
const ctx1 = capture(ctx, this);
return comp1({slots: markRaw({'myEmptySlot': {myProp: 'myProp text'}})}, key + \`__1\`, node, this, null);
}
}"
@@ -1636,7 +1636,7 @@ exports[`slots simple named and empty slot 1`] = `
}
return function template(ctx, node, key = \\"\\") {
const ctx1 = capture(ctx);
const ctx1 = capture(ctx, this);
return comp1({slots: markRaw({'myEmptySlot': {}, 'default': {__render: slot1.bind(this), __ctx: ctx1}})}, key + \`__1\`, node, this, null);
}
}"
@@ -1676,7 +1676,7 @@ exports[`slots simple slot with slot scope 1`] = `
}
return function template(ctx, node, key = \\"\\") {
const ctx1 = capture(ctx);
const ctx1 = capture(ctx, this);
return comp1({slots: markRaw({'slotName': {__render: slot1.bind(this), __ctx: ctx1, __scope: \\"slotScope\\"}})}, key + \`__1\`, node, this, null);
}
}"
@@ -1712,7 +1712,7 @@ exports[`slots slot and (inline) t-call 1`] = `
}
return function template(ctx, node, key = \\"\\") {
const ctx1 = capture(ctx);
const ctx1 = capture(ctx, this);
const b3 = comp1({slots: markRaw({'default': {__render: slot1.bind(this), __ctx: ctx1}})}, key + \`__2\`, node, this, null);
return block1([], [b3]);
}
@@ -1762,7 +1762,7 @@ exports[`slots slot and t-call 1`] = `
}
return function template(ctx, node, key = \\"\\") {
const ctx1 = capture(ctx);
const ctx1 = capture(ctx, this);
const b3 = comp1({slots: markRaw({'default': {__render: slot1.bind(this), __ctx: ctx1}})}, key + \`__2\`, node, this, null);
return block1([], [b3]);
}
@@ -1847,7 +1847,7 @@ exports[`slots slot are properly rendered if inner props are changed 1`] = `
}
return function template(ctx, node, key = \\"\\") {
let hdlr1 = [ctx['inc'], this];
let hdlr1 = [ctx['inc'], ctx];
let txt1 = ctx['state'].val;
const b3 = comp2({slots: markRaw({'default': {__render: slot1.bind(this), __ctx: ctx}})}, key + \`__2\`, node, this, null);
return block1([hdlr1, txt1], [b3]);
@@ -1992,13 +1992,12 @@ exports[`slots slot content is bound to caller (variation) 1`] = `
ctx = Object.create(ctx);
ctx[isBoundary] = 1
setContextValue(ctx, \\"var\\", 1);
const v1 = ctx['this'];
let hdlr1 = [()=>v1.inc(), this];
let hdlr1 = [()=>this.inc(), ctx];
return block1([hdlr1]);
}
return function template(ctx, node, key = \\"\\") {
const ctx1 = capture(ctx);
const ctx1 = capture(ctx, this);
return comp1({slots: markRaw({'default': {__render: slot1.bind(this), __ctx: ctx1}})}, key + \`__1\`, node, this, null);
}
}"
@@ -2029,7 +2028,7 @@ exports[`slots slot content is bound to caller 1`] = `
let block1 = createBlock(\`<button block-handler-0=\\"click\\">some text</button>\`);
function slot1(ctx, node, key = \\"\\") {
let hdlr1 = [ctx['inc'], this];
let hdlr1 = [ctx['inc'], ctx];
return block1([hdlr1]);
}
@@ -2225,7 +2224,7 @@ exports[`slots slot preserves properly parented relationship, even through t-cal
}
return function template(ctx, node, key = \\"\\") {
const ctx1 = capture(ctx);
const ctx1 = capture(ctx, this);
const b3 = comp1({slots: markRaw({'default': {__render: slot1.bind(this), __ctx: ctx1}})}, key + \`__2\`, node, this, null);
return block1([], [b3]);
}
@@ -2286,7 +2285,7 @@ exports[`slots slot with slot scope and t-props 1`] = `
}
return function template(ctx, node, key = \\"\\") {
const ctx1 = capture(ctx);
const ctx1 = capture(ctx, this);
return comp1({slots: markRaw({'slotName': {__render: slot1.bind(this), __ctx: ctx1, __scope: \\"info\\"}})}, key + \`__1\`, node, this, null);
}
}"
@@ -2360,8 +2359,7 @@ exports[`slots slots are properly bound to correct component 2`] = `
ctx = Object.create(ctx);
ctx[isBoundary] = 1
setContextValue(ctx, \\"var\\", 1);
const v1 = ctx['this'];
let hdlr1 = [()=>v1.increment(), this];
let hdlr1 = [()=>this.increment(), ctx];
let txt1 = ctx['state'].value;
return block1([hdlr1, txt1]);
}
@@ -2383,13 +2381,13 @@ exports[`slots slots are rendered with proper context 1`] = `
let block2 = createBlock(\`<button block-handler-0=\\"click\\">do something</button>\`);
function slot1(ctx, node, key = \\"\\") {
let hdlr1 = [ctx['doSomething'], this];
let hdlr1 = [ctx['doSomething'], ctx];
return block2([hdlr1]);
}
return function template(ctx, node, key = \\"\\") {
let txt1 = ctx['state'].val;
const ctx1 = capture(ctx);
const ctx1 = capture(ctx, this);
const b3 = comp1({slots: markRaw({'footer': {__render: slot1.bind(this), __ctx: ctx1}})}, key + \`__1\`, node, this, null);
return block1([txt1], [b3]);
}
@@ -2433,7 +2431,7 @@ exports[`slots slots are rendered with proper context, part 2 1`] = `
for (let i1 = 0; i1 < l_block2; i1++) {
ctx[\`user\`] = v_block2[i1];
const key1 = ctx['user'].id;
const ctx1 = capture(ctx);
const ctx1 = capture(ctx, this);
const b7 = comp1({to: '/user/'+ctx['user'].id,slots: markRaw({'default': {__render: slot1.bind(this), __ctx: ctx1}})}, key + \`__1__\${key1}\`, node, this, null);
c_block2[i1] = withKey(block3([], [b7]), key1);
}
@@ -2482,7 +2480,7 @@ exports[`slots slots are rendered with proper context, part 3 1`] = `
ctx[\`user\`] = v_block2[i1];
const key1 = ctx['user'].id;
setContextValue(ctx, \\"userdescr\\", 'User '+ctx['user'].name);
const ctx1 = capture(ctx);
const ctx1 = capture(ctx, this);
const b5 = comp1({to: '/user/'+ctx['user'].id,slots: markRaw({'default': {__render: slot1.bind(this), __ctx: ctx1}})}, key + \`__1__\${key1}\`, node, this, null);
c_block2[i1] = withKey(block3([], [b5]), key1);
}
@@ -2525,7 +2523,7 @@ exports[`slots slots are rendered with proper context, part 4 1`] = `
ctx = Object.create(ctx);
ctx[isBoundary] = 1
setContextValue(ctx, \\"userdescr\\", 'User '+ctx['state'].user.name);
const ctx1 = capture(ctx);
const ctx1 = capture(ctx, this);
const b3 = comp1({to: '/user/'+ctx['state'].user.id,slots: markRaw({'default': {__render: slot1.bind(this), __ctx: ctx1}})}, key + \`__1\`, node, this, null);
return block1([], [b3]);
}
@@ -2567,7 +2565,7 @@ exports[`slots slots in slots, with vars 1`] = `
ctx = Object.create(ctx);
ctx[isBoundary] = 1
setContextValue(ctx, \\"test\\", ctx['state'].name);
const ctx1 = capture(ctx);
const ctx1 = capture(ctx, this);
const b3 = comp1({slots: markRaw({'default': {__render: slot1.bind(this), __ctx: ctx1}})}, key + \`__1\`, node, this, null);
return block1([], [b3]);
}
@@ -2629,7 +2627,7 @@ exports[`slots slots in t-foreach and re-rendering 1`] = `
ctx[\`n\`] = v_block2[i1];
ctx[\`n_index\`] = i1;
const key1 = ctx['n_index'];
const ctx1 = capture(ctx);
const ctx1 = capture(ctx, this);
c_block2[i1] = withKey(comp1({slots: markRaw({'default': {__render: slot1.bind(this), __ctx: ctx1}})}, key + \`__1__\${key1}\`, node, this, null), key1);
}
const b2 = list(c_block2);
@@ -2684,7 +2682,7 @@ exports[`slots slots in t-foreach in t-foreach 1`] = `
for (let i2 = 0; i2 < l_block6; i2++) {
ctx[\`node2\`] = v_block6[i2];
const key2 = ctx['node2'].key;
const ctx1 = capture(ctx);
const ctx1 = capture(ctx, this);
c_block6[i2] = withKey(comp1({slots: markRaw({'default': {__render: slot1.bind(this), __ctx: ctx1}})}, key + \`__1__\${key1}__\${key2}\`, node, this, null), key2);
}
ctx = ctx.__proto__;
@@ -2736,7 +2734,7 @@ exports[`slots slots in t-foreach with t-set and re-rendering 1`] = `
ctx[\`n_index\`] = i1;
const key1 = ctx['n_index'];
setContextValue(ctx, \\"dummy\\", ctx['n_index']);
const ctx1 = capture(ctx);
const ctx1 = capture(ctx, this);
c_block2[i1] = withKey(comp1({slots: markRaw({'default': {__render: slot1.bind(this), __ctx: ctx1}})}, key + \`__1__\${key1}\`, node, this, null), key1);
}
const b2 = list(c_block2);
@@ -2776,7 +2774,7 @@ exports[`slots t-debug on a t-set-slot (defining a slot) 1`] = `
}
return function template(ctx, node, key = \\"\\") {
const ctx1 = capture(ctx);
const ctx1 = capture(ctx, this);
const b3 = comp1({slots: markRaw({'content': {__render: slot1.bind(this), __ctx: ctx1}})}, key + \`__1\`, node, this, null);
return block1([], [b3]);
}
@@ -2815,7 +2813,7 @@ exports[`slots t-set t-value in a slot 1`] = `
}
return function template(ctx, node, key = \\"\\") {
const ctx1 = capture(ctx);
const ctx1 = capture(ctx, this);
const b3 = comp1({slots: markRaw({'default': {__render: slot1.bind(this), __ctx: ctx1}})}, key + \`__1\`, node, this, null);
return block1([], [b3]);
}
@@ -2849,7 +2847,7 @@ exports[`slots t-set-slot=default has priority over rest of the content 1`] = `
}
return function template(ctx, node, key = \\"\\") {
const ctx1 = capture(ctx);
const ctx1 = capture(ctx, this);
return comp1({slots: markRaw({'default': {__render: slot1.bind(this), __ctx: ctx1}})}, key + \`__1\`, node, this, null);
}
}"
@@ -2907,7 +2905,7 @@ exports[`slots t-slot in recursive templates 1`] = `
}
return function template(ctx, node, key = \\"\\") {
const ctx1 = capture(ctx);
const ctx1 = capture(ctx, this);
return comp1({slots: markRaw({'default': {__render: slot1.bind(this), __ctx: ctx1}})}, key + \`__2\`, node, this, null);
}
}"
@@ -3046,7 +3044,7 @@ exports[`slots t-slot scope context 2`] = `
let block1 = createBlock(\`<div block-handler-0=\\"click\\"><block-child-0/></div>\`);
function slot1(ctx, node, key = \\"\\") {
let hdlr1 = [ctx['onClick'], this];
let hdlr1 = [ctx['onClick'], ctx];
const b2 = callSlot(ctx, node, key, 'default', false, {});
return block1([hdlr1], [b2]);
}
@@ -3085,7 +3083,7 @@ exports[`slots t-slot within dynamic t-call 1`] = `
}
return function template(ctx, node, key = \\"\\") {
const ctx1 = capture(ctx);
const ctx1 = capture(ctx, this);
const b3 = comp1({slots: markRaw({'default': {__render: slot1.bind(this), __ctx: ctx1}})}, key + \`__2\`, node, this, null);
return block1([], [b3]);
}
@@ -363,7 +363,7 @@ exports[`style and class handling error in subcomponent with class 2`] = `
return function template(ctx, node, key = \\"\\") {
let attr1 = ctx['props'].class;
let txt1 = ctx['this'].will.crash;
let txt1 = this.will.crash;
return block1([attr1, txt1]);
}
}"
@@ -109,8 +109,7 @@ exports[`t-call handlers are properly bound through a dynamic t-call 2`] = `
let block1 = createBlock(\`<p block-handler-0=\\"click\\">lucas</p>\`);
return function template(ctx, node, key = \\"\\") {
const v1 = ctx['this'];
let hdlr1 = [()=>v1.update(), this];
let hdlr1 = [()=>this.update(), ctx];
return block1([hdlr1]);
}
}"
@@ -140,7 +139,7 @@ exports[`t-call handlers are properly bound through a t-call 2`] = `
let block1 = createBlock(\`<p block-handler-0=\\"click\\">lucas</p>\`);
return function template(ctx, node, key = \\"\\") {
let hdlr1 = [ctx['update'], this];
let hdlr1 = [ctx['update'], ctx];
return block1([hdlr1]);
}
}"
@@ -169,9 +168,8 @@ exports[`t-call handlers with arguments are properly bound through a t-call 2`]
let block1 = createBlock(\`<p block-handler-0=\\"click\\">lucas</p>\`);
return function template(ctx, node, key = \\"\\") {
const v1 = ctx['this'];
const v2 = ctx['a'];
let hdlr1 = [()=>v1.update(v2), this];
const v1 = ctx['a'];
let hdlr1 = [()=>this.update(v1), ctx];
return block1([hdlr1]);
}
}"
@@ -289,7 +287,7 @@ exports[`t-call recursive t-call binding this -- static t-call 2`] = `
ctx[isBoundary] = 1
let b2;
if (ctx['level']<2) {
let hdlr1 = [\\"stop\\", ctx['onClicked'].bind(ctx['this']), this];
let hdlr1 = [\\"stop\\", ctx['onClicked'].bind(this), ctx];
let txt1 = ctx['level'];
const b3 = block3([hdlr1, txt1]);
ctx = Object.create(ctx);
@@ -540,6 +538,7 @@ exports[`t-call t-call-context: ComponentNode is not looked up in the context 2`
let block2 = createBlock(\`<div block-ref=\\"0\\">outside slot</div>\`);
let block4 = createBlock(\`<div block-ref=\\"0\\">I'm the default slot</div>\`);
let block5 = createBlock(\`<div><block-text-0/></div>\`);
let block6 = createBlock(\`<div><block-text-0/></div>\`);
function slot1(ctx, node, key = \\"\\") {
const refs = this.__owl__.refs;
@@ -548,18 +547,20 @@ exports[`t-call t-call-context: ComponentNode is not looked up in the context 2`
ctx[isBoundary] = 1
const b4 = block4([ref2]);
setContextValue(ctx, \\"test\\", 3);
let txt1 = ctx['test'];
let txt1 = this.__owl__.name;
const b5 = block5([txt1]);
return multi([b4, b5]);
let txt2 = ctx['test'];
const b6 = block6([txt2]);
return multi([b4, b5, b6]);
}
return function template(ctx, node, key = \\"\\") {
const refs = this.__owl__.refs;
const ref1 = (el) => refs[\`myRef\`] = el;
const b2 = block2([ref1]);
const ctx1 = capture(ctx);
const b6 = comp1({prop: bind(this, ctx['method']),slots: markRaw({'default': {__render: slot1.bind(this), __ctx: ctx1}})}, key + \`__1\`, node, this, null);
return multi([b2, b6]);
const ctx1 = capture(ctx, this);
const b7 = comp1({prop: bind(this, ctx['method']),slots: markRaw({'default': {__render: slot1.bind(this), __ctx: ctx1}})}, key + \`__1\`, node, this, null);
return multi([b2, b7]);
}
}"
`;
@@ -575,102 +576,3 @@ exports[`t-call t-call-context: ComponentNode is not looked up in the context 3`
}
}"
`;
exports[`t-call t-call-context: handlers have the correct this 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 = {handler:ctx['handler']};
return callTemplate_1.call(this, ctx1, node, key + \`__1\`);
}
}"
`;
exports[`t-call t-call-context: handlers have the correct this 2`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let block1 = createBlock(\`<div class=\\"click_me\\" block-handler-0=\\"click\\"/>\`);
return function template(ctx, node, key = \\"\\") {
let hdlr1 = [ctx['handler'], this];
return block1([hdlr1]);
}
}"
`;
exports[`t-call t-call-context: slots don't make component available again when context is captured 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
const callTemplate_1 = app.getTemplate(\`template\`);
return function template(ctx, node, key = \\"\\") {
let ctx1 = {};
return callTemplate_1.call(this, ctx1, node, key + \`__1\`);
}
}"
`;
exports[`t-call t-call-context: slots don't make component available again when context is captured 2`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let { isBoundary, withDefault, setContextValue, capture, markRaw } = helpers;
const comp1 = app.createComponent(\`Child\`, true, true, false, true);
function slot1(ctx, node, key = \\"\\") {
return text(ctx['someValue']);
}
return function template(ctx, node, key = \\"\\") {
ctx = Object.create(ctx);
ctx[isBoundary] = 1
setContextValue(ctx, \\"dummy\\", 0);
const ctx1 = capture(ctx);
const props1 = {slots: markRaw({'default': {__render: slot1.bind(this), __ctx: ctx1}})};
helpers.validateProps(\`Child\`, props1, this);
return comp1(props1, key + \`__1\`, node, this, null);
}
}"
`;
exports[`t-call t-call-context: slots don't make component available again when context is captured 3`] = `
"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[`t-call t-call-context: this is not available inside t-call-context 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 = {};
return callTemplate_1.call(this, ctx1, node, key + \`__1\`);
}
}"
`;
exports[`t-call t-call-context: this is not available inside t-call-context 2`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
return function template(ctx, node, key = \\"\\") {
return text(ctx['this']);
}
}"
`;
@@ -148,7 +148,7 @@ exports[`t-component modifying a sub widget 2`] = `
return function template(ctx, node, key = \\"\\") {
let txt1 = ctx['state'].counter;
const v1 = ctx['state'];
let hdlr1 = [()=>v1.counter++, this];
let hdlr1 = [()=>v1.counter++, ctx];
return block1([txt1, hdlr1]);
}
}"
@@ -175,7 +175,7 @@ exports[`list of components order is correct when slots are not of same type 1`]
}
return function template(ctx, node, key = \\"\\") {
const ctx1 = capture(ctx);
const ctx1 = capture(ctx, this);
return comp1({slots: markRaw({'a': {__render: slot1.bind(this), __ctx: ctx1, active: !ctx['state'].active}, 'b': {__render: slot2.bind(this), __ctx: ctx1, active: true}, 'c': {__render: slot3.bind(this), __ctx: ctx1, active: ctx['state'].active}})}, key + \`__1\`, node, this, null);
}
}"
@@ -127,7 +127,7 @@ exports[`t-model directive can also define t-on directive on same event, part 1
const expr1 = 'text';
let attr1 = bExpr1[expr1];
let hdlr1 = [(ev) => { bExpr1[expr1] = ev.target.value; }];
let hdlr2 = [ctx['onInput'], this];
let hdlr2 = [ctx['onInput'], ctx];
return block1([attr1, hdlr1, hdlr2]);
}
}"
@@ -146,17 +146,17 @@ exports[`t-model directive can also define t-on directive on same event, part 2
const expr1 = 'choice';
let attr1 = bExpr1[expr1] === 'One';
let hdlr1 = [(ev) => { bExpr1[expr1] = ev.target.value; }];
let hdlr2 = [ctx['onClick'], this];
let hdlr2 = [ctx['onClick'], ctx];
const bExpr2 = ctx['state'];
const expr2 = 'choice';
let attr2 = bExpr2[expr2] === 'Two';
let hdlr3 = [(ev) => { bExpr2[expr2] = ev.target.value; }];
let hdlr4 = [ctx['onClick'], this];
let hdlr4 = [ctx['onClick'], ctx];
const bExpr3 = ctx['state'];
const expr3 = 'choice';
let attr3 = bExpr3[expr3] === 'Three';
let hdlr5 = [(ev) => { bExpr3[expr3] = ev.target.value; }];
let hdlr6 = [ctx['onClick'], this];
let hdlr6 = [ctx['onClick'], ctx];
return block1([attr1, hdlr1, hdlr2, attr2, hdlr3, hdlr4, attr3, hdlr5, hdlr6]);
}
}"
@@ -423,7 +423,7 @@ exports[`t-model directive t-model is applied before t-on-input 1`] = `
const expr1 = 'text';
let attr1 = bExpr1[expr1];
let hdlr1 = [(ev) => { bExpr1[expr1] = ev.target.value; }];
let hdlr2 = [ctx['onInput'], this];
let hdlr2 = [ctx['onInput'], ctx];
return block1([attr1, hdlr1, hdlr2]);
}
}"
@@ -20,7 +20,7 @@ exports[`t-on t-on expression captured in t-foreach 1`] = `
const key1 = ctx['val'];
const v1 = ctx['otherState'];
const v2 = ctx['iter'];
let hdlr1 = [()=>v1.vals.push(v2+'_'+v2), this];
let hdlr1 = [()=>v1.vals.push(v2+'_'+v2), ctx];
setContextValue(ctx, \\"iter\\", ctx['iter']+1);
c_block2[i1] = withKey(block3([hdlr1]), key1);
}
@@ -50,7 +50,7 @@ exports[`t-on t-on expression in t-foreach 1`] = `
let txt2 = ctx['val']+'';
const v1 = ctx['otherState'];
const v2 = ctx['val'];
let hdlr1 = [()=>v1.vals.push(v2), this];
let hdlr1 = [()=>v1.vals.push(v2), ctx];
c_block2[i1] = withKey(block3([txt1, txt2, hdlr1]), key1);
}
const b2 = list(c_block2);
@@ -84,7 +84,7 @@ exports[`t-on t-on expression in t-foreach with t-set 1`] = `
const v1 = ctx['otherState'];
const v2 = ctx['val'];
const v3 = ctx['bossa'];
let hdlr1 = [()=>v1.vals.push(v2+'_'+v3), this];
let hdlr1 = [()=>v1.vals.push(v2+'_'+v3), ctx];
c_block2[i1] = withKey(block3([txt1, txt2, hdlr1]), key1);
}
const b2 = list(c_block2);
@@ -111,9 +111,8 @@ exports[`t-on t-on method call in t-foreach 1`] = `
const key1 = ctx['val'];
let txt1 = ctx['val_index'];
let txt2 = ctx['val']+'';
const v1 = ctx['this'];
const v2 = ctx['val'];
let hdlr1 = [()=>v1.addVal(v2), this];
const v1 = ctx['val'];
let hdlr1 = [()=>this.addVal(v1), ctx];
c_block2[i1] = withKey(block3([txt1, txt2, hdlr1]), key1);
}
const b2 = list(c_block2);
@@ -133,9 +132,9 @@ exports[`t-on t-on on component next to t-on on div 1`] = `
let block1 = createBlock(\`<div><block-child-0/><p block-handler-0=\\"click\\">dec</p></div>\`);
return function template(ctx, node, key = \\"\\") {
const hdlr1 = [ctx['increment'], this];
const hdlr1 = [ctx['increment'], ctx];
const b2 = catcher1(comp1({value: ctx['state'].value}, key + \`__1\`, node, this, null), [hdlr1]);
let hdlr2 = [ctx['decrement'], this];
let hdlr2 = [ctx['decrement'], ctx];
return block1([hdlr2], [b2]);
}
}"
@@ -164,7 +163,7 @@ exports[`t-on t-on on components 1`] = `
const catcher1 = createCatcher({\\"click\\":0});
return function template(ctx, node, key = \\"\\") {
const hdlr1 = [ctx['increment'], this];
const hdlr1 = [ctx['increment'], ctx];
return catcher1(comp1({value: ctx['state'].value}, key + \`__1\`, node, this, null), [hdlr1]);
}
}"
@@ -198,9 +197,8 @@ exports[`t-on t-on on components and t-foreach 1`] = `
for (let i1 = 0; i1 < l_block1; i1++) {
ctx[\`name\`] = v_block1[i1];
const key1 = ctx['name'];
const v1 = ctx['this'];
const v2 = ctx['name'];
const hdlr1 = [()=>v1.log(v2), this];
const v1 = ctx['name'];
const hdlr1 = [()=>this.log(v1), ctx];
c_block1[i1] = withKey(catcher1(comp1({value: ctx['name']}, key + \`__1__\${key1}\`, node, this, null), [hdlr1]), key1);
}
return list(c_block1);
@@ -233,7 +231,7 @@ exports[`t-on t-on on components, variation 1`] = `
let block1 = createBlock(\`<div><span/><block-child-0/><p/></div>\`);
return function template(ctx, node, key = \\"\\") {
const hdlr1 = [ctx['increment'], this];
const hdlr1 = [ctx['increment'], ctx];
const b2 = catcher1(comp1({value: ctx['state'].value}, key + \`__1\`, node, this, null), [hdlr1]);
return block1([], [b2]);
}
@@ -263,7 +261,7 @@ exports[`t-on t-on on components, with 'prevent' modifier 1`] = `
const catcher1 = createCatcher({\\"click.prevent\\":0});
return function template(ctx, node, key = \\"\\") {
const hdlr1 = [\\"prevent\\", ctx['increment'], this];
const hdlr1 = [\\"prevent\\", ctx['increment'], ctx];
return catcher1(comp1({value: ctx['state'].value}, key + \`__1\`, node, this, null), [hdlr1]);
}
}"
@@ -295,9 +293,8 @@ exports[`t-on t-on on components, with a handler update 1`] = `
ctx = Object.create(ctx);
ctx[isBoundary] = 1
setContextValue(ctx, \\"name\\", ctx['state'].name);
const v1 = ctx['this'];
const v2 = ctx['name'];
const hdlr1 = [()=>v1.log(v2), this];
const v1 = ctx['name'];
const hdlr1 = [()=>this.log(v1), ctx];
return catcher1(comp1({value: ctx['name']}, key + \`__1\`, node, this, null), [hdlr1]);
}
}"
@@ -343,7 +340,7 @@ exports[`t-on t-on on destroyed components 2`] = `
let block1 = createBlock(\`<div block-handler-0=\\"click\\"/>\`);
return function template(ctx, node, key = \\"\\") {
let hdlr1 = [ctx['onClick'], this];
let hdlr1 = [ctx['onClick'], ctx];
return block1([hdlr1]);
}
}"
@@ -376,7 +373,7 @@ exports[`t-on t-on on slot, with 'prevent' modifier 2`] = `
const catcher1 = createCatcher({\\"click.prevent\\":0});
return function template(ctx, node, key = \\"\\") {
const hdlr1 = [\\"prevent\\", ctx['doSomething'], this];
const hdlr1 = [\\"prevent\\", ctx['doSomething'], ctx];
return catcher1(callSlot(ctx, node, key, 'default', false, {}), [hdlr1]);
}
}"
@@ -396,8 +393,7 @@ exports[`t-on t-on on t-set-slots 1`] = `
function slot1(ctx, node, key = \\"\\") {
const b6 = block6();
const b7 = block7();
const v1 = ctx['this'];
const hdlr1 = [()=>v1.state.count++, this];
const hdlr1 = [()=>this.state.count++, ctx];
return catcher1(multi([b6, b7]), [hdlr1]);
}
@@ -405,7 +401,7 @@ exports[`t-on t-on on t-set-slots 1`] = `
const b2 = text(\` [\`);
const b3 = text(ctx['state'].count);
const b4 = text(\`] \`);
const ctx1 = capture(ctx);
const ctx1 = capture(ctx, this);
const b8 = comp1({slots: markRaw({'myslot': {__render: slot1.bind(this), __ctx: ctx1}})}, key + \`__1\`, node, this, null);
return multi([b2, b3, b4, b8]);
}
@@ -454,8 +450,7 @@ exports[`t-on t-on on t-slots 2`] = `
const b2 = text(\` [\`);
const b3 = text(ctx['state'].count);
const b4 = text(\`] \`);
const v1 = ctx['this'];
const hdlr1 = [()=>v1.state.count++, this];
const hdlr1 = [()=>this.state.count++, ctx];
const b5 = catcher1(callSlot(ctx, node, key, 'default', false, {}), [hdlr1]);
return multi([b2, b3, b4, b5]);
}
@@ -473,8 +468,8 @@ exports[`t-on t-on when first component child is an empty component 1`] = `
let block1 = createBlock(\`<div block-handler-0=\\"click\\"><block-child-0/></div>\`);
return function template(ctx, node, key = \\"\\") {
let hdlr1 = [ctx['push'], this];
const hdlr2 = [()=>{}, this];
let hdlr1 = [ctx['push'], ctx];
const hdlr2 = [()=>{}, ctx];
const b2 = catcher1(comp1({list: ctx['list']}, key + \`__1\`, node, this, null), [hdlr2]);
return block1([hdlr1], [b2]);
}
@@ -21,7 +21,7 @@ exports[`t-set slot setted value (with t-set) not accessible with t-esc 1`] = `
ctx[isBoundary] = 1
setContextValue(ctx, \\"iter\\", 'source');
let txt1 = ctx['iter'];
const ctx1 = capture(ctx);
const ctx1 = capture(ctx, this);
const b2 = comp1({slots: markRaw({'default': {__render: slot1.bind(this), __ctx: ctx1}})}, key + \`__1\`, node, this, null);
let txt2 = ctx['iter'];
return block1([txt1, txt2], [b2]);
@@ -70,7 +70,7 @@ exports[`t-set slots with a t-set with a component in body 1`] = `
}
return function template(ctx, node, key = \\"\\") {
const ctx1 = capture(ctx);
const ctx1 = capture(ctx, this);
return comp2({slots: markRaw({'default': {__render: slot1.bind(this), __ctx: ctx1}})}, key + \`__2\`, node, this, null);
}
}"
@@ -127,7 +127,7 @@ exports[`t-set slots with an t-set with a component in body 1`] = `
}
return function template(ctx, node, key = \\"\\") {
const ctx1 = capture(ctx);
const ctx1 = capture(ctx, this);
return comp2({slots: markRaw({'default': {__render: slot1.bind(this), __ctx: ctx1}})}, key + \`__2\`, node, this, null);
}
}"
@@ -178,7 +178,7 @@ exports[`t-set slots with an unused t-set with a component in body 1`] = `
}
return function template(ctx, node, key = \\"\\") {
const ctx1 = capture(ctx);
const ctx1 = capture(ctx, this);
return comp2({slots: markRaw({'default': {__render: slot1.bind(this), __ctx: ctx1}})}, key + \`__2\`, node, this, null);
}
}"
+126
View File
@@ -9,6 +9,7 @@ import {
onRendered,
onWillUnmount,
useState,
reactive,
xml,
} from "../../src/index";
import {
@@ -785,6 +786,131 @@ describe("can catch errors", () => {
expect(mockConsoleWarn).toBeCalledTimes(0);
});
test("re-render parent when self is in error", async () => {
class Boom extends Component {
static template = xml`<div />`;
setup() {
onWillStart(() => {
throw new Error("Boom Error");
});
}
}
const steps: string[] = [];
class BoomWrapper extends Component {
static template = xml`<Boom />`;
static components = { Boom };
setup() {
onError(() => {
steps.push("onError in child");
this.props.onError();
});
}
}
class Classic extends Component {
static template = xml`<BoomWrapper t-if="!inError" onError.bind="onErrorAsProps"/><div t-else="" />`;
static components = { BoomWrapper };
inError: Boolean = false;
setup() {
onMounted(() => {
steps.push("mounted");
});
}
onErrorAsProps() {
this.inError = true;
this.render(true);
}
}
class App extends Component {
static template = xml`<Classic />`;
static components = { Classic };
}
await mount(App, fixture);
expect(steps).toEqual(["onError in child", "mounted"]);
});
test("re-render parent when self is in error - 2", async () => {
class Boom extends Component {
static template = xml`<div />`;
setup() {
onWillStart(() => {
throw new Error("Boom Error");
});
}
}
const steps: string[] = [];
class BoomWrapper extends Component {
static template = xml`<Boom t-if="state.errorTree === 'error'" /><t t-else="" t-esc="state.errorTree" />`;
static components = { Boom };
state: any;
setup() {
this.state = useState(this.props.state);
onError(() => {
steps.push("onError");
this.state.onError();
});
onWillRender(() => {
steps.push(`BoomWrapper willRender`);
});
}
}
let classicId = 0;
class Classic extends Component {
static template = xml`
<BoomWrapper t-if="props.hasBoom" state="props.state"/>
<div t-else="" t-esc="props.state.safeTree" />
`;
static components = { BoomWrapper };
id: Number = 0;
state: any;
inError: Boolean = false;
setup() {
this.id = classicId++;
onMounted(() => {
steps.push(`mounted ${this.id}`);
});
onWillRender(() => {
steps.push(`Classic willRender ${this.id}`);
});
}
}
class App extends Component {
reactive: any;
setup() {
this.reactive = reactive({
errorTree: "error",
safeTree: "safe",
onError() {
this.safeTree = "safe2";
this.errorTree = "errorHandled";
},
});
}
static template = xml`<Classic hasBoom="true" state="reactive" /><Classic hasBoom="false" state="reactive"/>`;
static components = { Classic };
}
await mount(App, fixture);
expect(steps).toEqual([
"Classic willRender 0",
"Classic willRender 1",
"BoomWrapper willRender",
"onError",
"Classic willRender 1",
"BoomWrapper willRender",
"mounted 1",
"mounted 0",
]);
expect(fixture.innerHTML).toBe("errorHandled<div>safe2</div>");
});
test("can catch an error in the willStart call", async () => {
class ErrorComponent extends Component {
static template = xml`<div>Some text</div>`;
+2 -1
View File
@@ -1,5 +1,6 @@
import { App, Component, mount, onMounted, useRef, useState, xml } from "../../src/index";
import { App, Component, mount, onMounted, useRef, useState } from "../../src/index";
import { logStep, makeTestFixture, nextAppError, nextTick, snapshotEverything } from "../helpers";
import { xml } from "../../src/index";
snapshotEverything();
let fixture: HTMLElement;
+2 -69
View File
@@ -345,83 +345,16 @@ describe("t-call", () => {
<Child prop.bind="method">
<div t-ref="myRef2">I'm the default slot</div>
<t t-set="test" t-value="3"/>
<div t-esc="this.__owl__.name"/>
<div t-esc="test"/>
</Child>
</t>
</templates>`,
});
expect(fixture.innerHTML).toBe(
"<div>outside slot</div><div>I'm the default slot</div><div>3</div>"
"<div>outside slot</div><div>I'm the default slot</div><div>Root</div><div>3</div>"
);
expect(Object.keys(child.__owl__.refs)).toEqual([]);
expect(Object.keys(root.__owl__.refs)).toEqual(["myRef", "myRef2"]);
});
test("t-call-context: slots don't make component available again when context is captured", async () => {
class Child extends Component {
static template = xml`<t t-slot="default"/>`;
}
class Root extends Component {
static template = xml`<t t-call="template" t-call-context="{}"/>`;
static components = { Child };
someValue = "Hello";
}
await mount(Root, fixture, {
test: true,
templates: `
<templates>
<t t-name="template">
<t t-set="dummy" t-value="0"/>
<Child>
<t t-esc="someValue"/>
</Child>
</t>
</templates>`,
});
expect(fixture.innerHTML).toBe("");
});
test("t-call-context: this is not available inside t-call-context", async () => {
class Root extends Component {
static template = xml`<t t-call="someTemplate" t-call-context="{}"/>`;
}
await mount(Root, fixture, {
templates: `
<templates>
<t t-name="someTemplate">
<t t-esc="this"/>
</t>
</templates>`,
});
expect(fixture.innerHTML).toBe("");
});
test("t-call-context: handlers have the correct this", async () => {
class Root extends Component {
static template = xml`<t t-call="someTemplate" t-call-context="{ handler: handler }"/>`;
setup() {
root = this;
}
handler() {
handlerThis = this;
}
}
let root: Root | null = null;
let handlerThis: Root | null = null;
await mount(Root, fixture, {
templates: `
<templates>
<t t-name="someTemplate">
<div class="click_me" t-on-click="handler"/>
</t>
</templates>`,
});
const toClick: HTMLDivElement = fixture.querySelector(".click_me")!;
toClick.click();
expect(handlerThis).toBe(root);
});
});
+9 -9
View File
@@ -20,7 +20,7 @@ exports[`Portal Add and remove portals 1`] = `
for (let i1 = 0; i1 < l_block1; i1++) {
ctx[\`portalId\`] = v_block1[i1];
const key1 = ctx['portalId'];
const ctx1 = capture(ctx);
const ctx1 = capture(ctx, this);
c_block1[i1] = withKey(comp1({target: '#outside',slots: {'default': {__render: slot1.bind(this), __ctx: ctx1}}}, key + \`__1__\${key1}\`, node, ctx, Portal), key1);
}
return list(c_block1);
@@ -49,7 +49,7 @@ exports[`Portal Add and remove portals on div 1`] = `
for (let i1 = 0; i1 < l_block1; i1++) {
ctx[\`portalId\`] = v_block1[i1];
const key1 = ctx['portalId'];
const ctx1 = capture(ctx);
const ctx1 = capture(ctx, this);
c_block1[i1] = withKey(comp1({target: '#outside',slots: {'default': {__render: slot1.bind(this), __ctx: ctx1}}}, key + \`__1__\${key1}\`, node, ctx, Portal), key1);
}
return list(c_block1);
@@ -80,7 +80,7 @@ exports[`Portal Add and remove portals with t-foreach 1`] = `
ctx[\`portalId\`] = v_block1[i1];
const key1 = ctx['portalId'];
let txt1 = ctx['portalId'];
const ctx1 = capture(ctx);
const ctx1 = capture(ctx, this);
const b6 = comp1({target: '#outside',slots: {'default': {__render: slot1.bind(this), __ctx: ctx1}}}, key + \`__1__\${key1}\`, node, ctx, Portal);
c_block1[i1] = withKey(block2([txt1], [b6]), key1);
}
@@ -112,7 +112,7 @@ exports[`Portal Add and remove portals with t-foreach and destroy 1`] = `
ctx[\`portalId\`] = v_block1[i1];
const key1 = ctx['portalId'];
let txt1 = ctx['portalId'];
const ctx1 = capture(ctx);
const ctx1 = capture(ctx, this);
const b6 = comp1({target: '#outside',slots: {'default': {__render: slot1.bind(this), __ctx: ctx1}}}, key + \`__1__\${key1}\`, node, ctx, Portal);
c_block1[i1] = withKey(block2([txt1], [b6]), key1);
}
@@ -145,7 +145,7 @@ exports[`Portal Add and remove portals with t-foreach inside div 1`] = `
ctx[\`portalId\`] = v_block2[i1];
const key1 = ctx['portalId'];
let txt1 = ctx['portalId'];
const ctx1 = capture(ctx);
const ctx1 = capture(ctx, this);
const b7 = comp1({target: '#outside',slots: {'default': {__render: slot1.bind(this), __ctx: ctx1}}}, key + \`__1__\${key1}\`, node, ctx, Portal);
c_block2[i1] = withKey(block3([txt1], [b7]), key1);
}
@@ -240,7 +240,7 @@ exports[`Portal Portal composed with t-slot 3`] = `
let block1 = createBlock(\`<div block-handler-0=\\"custom\\"><span id=\\"childSpan\\">child2</span></div>\`);
return function template(ctx, node, key = \\"\\") {
let hdlr1 = [ctx['onCustom'], this];
let hdlr1 = [ctx['onCustom'], ctx];
return block1([hdlr1]);
}
}"
@@ -431,7 +431,7 @@ exports[`Portal conditional use of Portal with child and div 2`] = `
for (let i1 = 0; i1 < l_block2; i1++) {
ctx[\`elem\`] = v_block2[i1];
const key1 = ctx['elem'];
const ctx1 = capture(ctx);
const ctx1 = capture(ctx, this);
c_block2[i1] = withKey(comp1({target: '#outside',slots: {'default': {__render: slot1.bind(this), __ctx: ctx1}}}, key + \`__1__\${key1}\`, node, ctx, Portal), key1);
}
const b2 = list(c_block2);
@@ -481,7 +481,7 @@ exports[`Portal conditional use of Portal with child and div, variation 2`] = `
for (let i1 = 0; i1 < l_block3; i1++) {
ctx[\`elem\`] = v_block3[i1];
const key1 = ctx['elem'];
const ctx1 = capture(ctx);
const ctx1 = capture(ctx, this);
c_block3[i1] = withKey(comp1({target: '#outside',slots: {'default': {__render: slot1.bind(this), __ctx: ctx1}}}, key + \`__1__\${key1}\`, node, ctx, Portal), key1);
}
const b3 = list(c_block3);
@@ -646,7 +646,7 @@ exports[`Portal portal destroys on crash 2`] = `
let block1 = createBlock(\`<span><block-text-0/></span>\`);
return function template(ctx, node, key = \\"\\") {
let txt1 = ctx['props'].error&&ctx['this'].will.crash;
let txt1 = ctx['props'].error&&this.will.crash;
return block1([txt1]);
}
}"
+1 -27
View File
@@ -9,7 +9,7 @@ import {
markRaw,
toRaw,
} from "../src";
import { reactive, getSubscriptions } from "../src/runtime/reactivity";
import { reactive } from "../src/runtime/reactivity";
import { batched } from "../src/runtime/utils";
import {
makeDeferred,
@@ -1020,32 +1020,6 @@ describe("Reactivity", () => {
expect(n3).toBe(2);
});
test("reactive inside other: reading the inner reactive from outer doesn't affect the inner's subscriptions", async () => {
const getObservedKeys = (obj: any) => getSubscriptions(obj).flatMap(({ keys }) => keys);
let n1 = 0;
let n2 = 0;
const innerCb = () => n1++;
const outerCb = () => n2++;
const inner = createReactive({ a: 1 }, innerCb);
const outer = createReactive({ b: inner }, outerCb);
expect(n1).toBe(0);
expect(n2).toBe(0);
expect(getObservedKeys(innerCb)).toEqual([]);
expect(getObservedKeys(outerCb)).toEqual([]);
outer.b.a;
expect(getObservedKeys(innerCb)).toEqual([]);
expect(getObservedKeys(outerCb)).toEqual(["b", "a"]);
expect(n1).toBe(0);
expect(n2).toBe(0);
outer.b.a = 2;
expect(getObservedKeys(innerCb)).toEqual([]);
expect(getObservedKeys(outerCb)).toEqual([]);
expect(n1).toBe(0);
expect(n2).toBe(1);
});
// test("notification is not done after unregistration", async () => {
// let n = 0;
// const observer = () => n++;