diff --git a/tests/component/__snapshots__/component.test.ts.snap b/tests/component/__snapshots__/component.test.ts.snap
index 859fb0e5..1060aa71 100644
--- a/tests/component/__snapshots__/component.test.ts.snap
+++ b/tests/component/__snapshots__/component.test.ts.snap
@@ -1291,493 +1291,6 @@ exports[`t-model directive on an input, type=checkbox 1`] = `
}"
`;
-exports[`t-slot directive can define and call slots 1`] = `
-"function anonymous(context, extra
-) {
- // Template name: \\"Parent\\"
- let utils = this.constructor.utils;
- let QWeb = this.constructor;
- let parent = context;
- let scope = Object.create(context);
- var h = this.h;
- let c1 = [], p1 = {key:1};
- var vn1 = h('div', p1, c1);
- //COMPONENT
- let k3 = \`__4__\`;
- let w2 = k3 in parent.__owl__.cmap ? parent.__owl__.children[parent.__owl__.cmap[k3]] : false;
- let props2 = {};
- if (w2 && w2.__owl__.currentFiber && !w2.__owl__.vnode) {
- w2.destroy();
- w2 = false;
- }
- if (w2) {
- w2.__updateProps(props2, extra.fiber, Object.assign(Object.create(context), scope));
- let pvnode = w2.__owl__.pvnode;
- c1.push(pvnode);
- } else {
- let componentKey2 = \`Dialog\`;
- let W2 = context.constructor.components[componentKey2] || QWeb.components[componentKey2]|| scope['Dialog'];
- if (!W2) {throw new Error('Cannot find the definition of component \\"' + componentKey2 + '\\"')}
- w2 = new W2(parent, props2);
- parent.__owl__.cmap[k3] = w2.__owl__.id;
- w2.__owl__.slotId = 1;
- let fiber = w2.__prepare(extra.fiber, Object.assign(Object.create(context), scope), () => { const vnode = fiber.vnode; pvnode.sel = vnode.sel; });
- let pvnode = h('dummy', {key: k3, hook: {remove() {},destroy(vn) {w2.destroy();}}});
- c1.push(pvnode);
- w2.__owl__.pvnode = pvnode;
- }
- w2.__owl__.parentLastFiberId = extra.fiber.id;
- return vn1;
-}"
-`;
-
-exports[`t-slot directive can define and call slots 2`] = `
-"function anonymous(context, extra
-) {
- // Template name: \\"Dialog\\"
- var h = this.h;
- let c7 = [], p7 = {key:7};
- var vn7 = h('div', p7, c7);
- let c8 = [], p8 = {key:8};
- var vn8 = h('div', p8, c8);
- c7.push(vn8);
- const slot9 = this.constructor.slots[context.__owl__.slotId + '_' + 'header'];
- if (slot9) {
- slot9.call(this, context.__owl__.scope, Object.assign({}, extra, {parentNode: c8, parent: extra.parent || context}));
- }
- let c10 = [], p10 = {key:10};
- var vn10 = h('div', p10, c10);
- c7.push(vn10);
- const slot11 = this.constructor.slots[context.__owl__.slotId + '_' + 'footer'];
- if (slot11) {
- slot11.call(this, context.__owl__.scope, Object.assign({}, extra, {parentNode: c10, parent: extra.parent || context}));
- }
- return vn7;
-}"
-`;
-
-exports[`t-slot directive can define and call slots 3`] = `
-"function anonymous(context, extra
-) {
- // Template name: \\"slot_header_template\\"
- var h = this.h;
- let c1 = extra.parentNode;
- let c5 = [], p5 = {key:5};
- var vn5 = h('span', p5, c5);
- c1.push(vn5);
- c5.push({text: \`header\`});
-}"
-`;
-
-exports[`t-slot directive can define and call slots 4`] = `
-"function anonymous(context, extra
-) {
- // Template name: \\"slot_footer_template\\"
- var h = this.h;
- let c1 = extra.parentNode;
- let c6 = [], p6 = {key:6};
- var vn6 = h('span', p6, c6);
- c1.push(vn6);
- c6.push({text: \`footer\`});
-}"
-`;
-
-exports[`t-slot directive content is the default slot 1`] = `
-"function anonymous(context, extra
-) {
- // Template name: \\"slot_default_template\\"
- var h = this.h;
- let c1 = extra.parentNode;
- let c5 = [], p5 = {key:5};
- var vn5 = h('span', p5, c5);
- c1.push(vn5);
- c5.push({text: \`sts rocks\`});
-}"
-`;
-
-exports[`t-slot directive dafault slots can define a default content 1`] = `
-"function anonymous(context, extra
-) {
- // Template name: \\"__template__1\\"
- var h = this.h;
- let c5 = [], p5 = {key:5};
- var vn5 = h('span', p5, c5);
- const slot6 = this.constructor.slots[context.__owl__.slotId + '_' + 'default'];
- if (slot6) {
- slot6.call(this, context.__owl__.scope, Object.assign({}, extra, {parentNode: c5, parent: extra.parent || context}));
- } else {
- c5.push({text: \`default content\`});
- }
- return vn5;
-}"
-`;
-
-exports[`t-slot directive default slot work with text nodes 1`] = `
-"function anonymous(context, extra
-) {
- // Template name: \\"slot_default_template\\"
- var h = this.h;
- let c1 = extra.parentNode;
- c1.push({text: \`sts rocks\`});
-}"
-`;
-
-exports[`t-slot directive multiple roots are allowed in a default slot 1`] = `
-"function anonymous(context, extra
-) {
- // Template name: \\"slot_default_template\\"
- var h = this.h;
- let c1 = extra.parentNode;
- let c5 = [], p5 = {key:5};
- var vn5 = h('span', p5, c5);
- c1.push(vn5);
- c5.push({text: \`sts\`});
- let c6 = [], p6 = {key:6};
- var vn6 = h('span', p6, c6);
- c1.push(vn6);
- c6.push({text: \`rocks\`});
-}"
-`;
-
-exports[`t-slot directive multiple roots are allowed in a named slot 1`] = `
-"function anonymous(context, extra
-) {
- // Template name: \\"slot_content_template\\"
- var h = this.h;
- let c1 = extra.parentNode;
- let c5 = [], p5 = {key:5};
- var vn5 = h('span', p5, c5);
- c1.push(vn5);
- c5.push({text: \`sts\`});
- let c6 = [], p6 = {key:6};
- var vn6 = h('span', p6, c6);
- c1.push(vn6);
- c6.push({text: \`rocks\`});
-}"
-`;
-
-exports[`t-slot directive named slots can define a default content 1`] = `
-"function anonymous(context, extra
-) {
- // Template name: \\"__template__1\\"
- var h = this.h;
- let c5 = [], p5 = {key:5};
- var vn5 = h('span', p5, c5);
- const slot6 = this.constructor.slots[context.__owl__.slotId + '_' + 'header'];
- if (slot6) {
- slot6.call(this, context.__owl__.scope, Object.assign({}, extra, {parentNode: c5, parent: extra.parent || context}));
- } else {
- c5.push({text: \`default content\`});
- }
- return vn5;
-}"
-`;
-
-exports[`t-slot directive refs are properly bound in slots 1`] = `
-"function anonymous(context, extra
-) {
- // Template name: \\"slot_footer_template\\"
- context.__owl__.refs = context.__owl__.refs || {};
- var h = this.h;
- let c1 = extra.parentNode;
- let c9 = [], p9 = {key:9,on:{}};
- var vn9 = h('button', p9, c9);
- c1.push(vn9);
- extra.handlers['click' + 9] = extra.handlers['click' + 9] || function (e) {if (!context.__owl__.isMounted){return}const fn = context['doSomething'];if (fn) { fn.call(context, e); } else { context.doSomething; }};
- p9.on['click'] = extra.handlers['click' + 9];
- const ref10 = \`myButton\`;
- p9.hook = {
- create: (_, n) => {
- context.__owl__.refs[ref10] = n.elm;
- },
- destroy: () => {
- delete context.__owl__.refs[ref10];
- },
- };
- c9.push({text: \`do something\`});
-}"
-`;
-
-exports[`t-slot directive slots are rendered with proper context 1`] = `
-"function anonymous(context, extra
-) {
- // Template name: \\"slot_footer_template\\"
- var h = this.h;
- let c1 = extra.parentNode;
- let c9 = [], p9 = {key:9,on:{}};
- var vn9 = h('button', p9, c9);
- c1.push(vn9);
- extra.handlers['click' + 9] = extra.handlers['click' + 9] || function (e) {if (!context.__owl__.isMounted){return}const fn = context['doSomething'];if (fn) { fn.call(context, e); } else { context.doSomething; }};
- p9.on['click'] = extra.handlers['click' + 9];
- c9.push({text: \`do something\`});
-}"
-`;
-
-exports[`t-slot directive slots are rendered with proper context, part 2 1`] = `
-"function anonymous(context, extra
-) {
- // Template name: \\"Link\\"
- let scope = Object.create(context);
- var h = this.h;
- var _13 = scope['props'].to;
- let c14 = [], p14 = {key:14,attrs:{href: _13}};
- var vn14 = h('a', p14, c14);
- const slot15 = this.constructor.slots[context.__owl__.slotId + '_' + 'default'];
- if (slot15) {
- slot15.call(this, context.__owl__.scope, Object.assign({}, extra, {parentNode: c14, parent: extra.parent || context}));
- }
- return vn14;
-}"
-`;
-
-exports[`t-slot directive slots are rendered with proper context, part 2 2`] = `
-"function anonymous(context, extra
-) {
- // Template name: \\"App\\"
- let utils = this.constructor.utils;
- let QWeb = this.constructor;
- let parent = context;
- let scope = Object.create(context);
- var h = this.h;
- let c1 = [], p1 = {key:1};
- var vn1 = h('div', p1, c1);
- let c2 = [], p2 = {key:2};
- var vn2 = h('u', p2, c2);
- c1.push(vn2);
- var _3 = scope['state'].users;
- if (!_3) { throw new Error('QWeb error: Invalid loop expression')}
- var _4 = _5 = _3;
- if (!(_3 instanceof Array)) {
- _4 = Object.keys(_3);
- _5 = Object.values(_3);
- }
- var _length4 = _4.length;
- const _origScope6 = scope;
- scope = Object.assign(Object.create(context), scope);
- for (let i1 = 0; i1 < _length4; i1++) {
- scope.user_first = i1 === 0
- scope.user_last = i1 === _length4 - 1
- scope.user_index = i1
- scope.user = _4[i1]
- scope.user_value = _5[i1]
- const nodeKey7 = scope['user'].id;
- let c8 = [], p8 = {key:nodeKey7};
- var vn8 = h('li', p8, c8);
- c2.push(vn8);
- //COMPONENT
- let k10 = \`__11__\` + nodeKey7;
- let w9 = k10 in parent.__owl__.cmap ? parent.__owl__.children[parent.__owl__.cmap[k10]] : false;
- let props9 = {to:'/user/'+scope['user'].id};
- if (w9 && w9.__owl__.currentFiber && !w9.__owl__.vnode) {
- w9.destroy();
- w9 = false;
- }
- if (w9) {
- w9.__updateProps(props9, extra.fiber, Object.assign(Object.create(context), scope));
- let pvnode = w9.__owl__.pvnode;
- c8.push(pvnode);
- } else {
- let componentKey9 = \`Link\`;
- let W9 = context.constructor.components[componentKey9] || QWeb.components[componentKey9]|| scope['Link'];
- if (!W9) {throw new Error('Cannot find the definition of component \\"' + componentKey9 + '\\"')}
- w9 = new W9(parent, props9);
- parent.__owl__.cmap[k10] = w9.__owl__.id;
- w9.__owl__.slotId = 1;
- let fiber = w9.__prepare(extra.fiber, Object.assign(Object.create(context), scope), () => { const vnode = fiber.vnode; pvnode.sel = vnode.sel; });
- let pvnode = h('dummy', {key: k10, hook: {remove() {},destroy(vn) {w9.destroy();}}});
- c8.push(pvnode);
- w9.__owl__.pvnode = pvnode;
- }
- w9.__owl__.parentLastFiberId = extra.fiber.id;
- }
- scope = _origScope6;
- return vn1;
-}"
-`;
-
-exports[`t-slot directive slots are rendered with proper context, part 2 3`] = `
-"function anonymous(context, extra
-) {
- // Template name: \\"slot_default_template\\"
- let scope = Object.create(context);
- var h = this.h;
- let c8 = extra.parentNode;
- c8.push({text: \`User \`});
- var _12 = scope['user'].name;
- if (_12 || _12 === 0) {
- c8.push({text: _12});
- }
-}"
-`;
-
-exports[`t-slot directive slots are rendered with proper context, part 3 1`] = `
-"function anonymous(context, extra
-) {
- // Template name: \\"Link\\"
- let scope = Object.create(context);
- var h = this.h;
- var _12 = scope['props'].to;
- let c13 = [], p13 = {key:13,attrs:{href: _12}};
- var vn13 = h('a', p13, c13);
- const slot14 = this.constructor.slots[context.__owl__.slotId + '_' + 'default'];
- if (slot14) {
- slot14.call(this, context.__owl__.scope, Object.assign({}, extra, {parentNode: c13, parent: extra.parent || context}));
- }
- return vn13;
-}"
-`;
-
-exports[`t-slot directive slots are rendered with proper context, part 3 2`] = `
-"function anonymous(context, extra
-) {
- // Template name: \\"App\\"
- let utils = this.constructor.utils;
- let QWeb = this.constructor;
- let parent = context;
- let scope = Object.create(context);
- var h = this.h;
- let c1 = [], p1 = {key:1};
- var vn1 = h('div', p1, c1);
- let c2 = [], p2 = {key:2};
- var vn2 = h('u', p2, c2);
- c1.push(vn2);
- var _3 = scope['state'].users;
- if (!_3) { throw new Error('QWeb error: Invalid loop expression')}
- var _4 = _5 = _3;
- if (!(_3 instanceof Array)) {
- _4 = Object.keys(_3);
- _5 = Object.values(_3);
- }
- var _length4 = _4.length;
- const _origScope6 = scope;
- scope = Object.assign(Object.create(context), scope);
- for (let i1 = 0; i1 < _length4; i1++) {
- scope.user_first = i1 === 0
- scope.user_last = i1 === _length4 - 1
- scope.user_index = i1
- scope.user = _4[i1]
- scope.user_value = _5[i1]
- const nodeKey7 = scope['user'].id;
- let c8 = [], p8 = {key:nodeKey7};
- var vn8 = h('li', p8, c8);
- c2.push(vn8);
- scope.userdescr = 'User '+scope['user'].name;
- //COMPONENT
- let k10 = \`__11__\` + nodeKey7;
- let w9 = k10 in parent.__owl__.cmap ? parent.__owl__.children[parent.__owl__.cmap[k10]] : false;
- let props9 = {to:'/user/'+scope['user'].id};
- if (w9 && w9.__owl__.currentFiber && !w9.__owl__.vnode) {
- w9.destroy();
- w9 = false;
- }
- if (w9) {
- w9.__updateProps(props9, extra.fiber, Object.assign(Object.create(context), scope));
- let pvnode = w9.__owl__.pvnode;
- c8.push(pvnode);
- } else {
- let componentKey9 = \`Link\`;
- let W9 = context.constructor.components[componentKey9] || QWeb.components[componentKey9]|| scope['Link'];
- if (!W9) {throw new Error('Cannot find the definition of component \\"' + componentKey9 + '\\"')}
- w9 = new W9(parent, props9);
- parent.__owl__.cmap[k10] = w9.__owl__.id;
- w9.__owl__.slotId = 1;
- let fiber = w9.__prepare(extra.fiber, Object.assign(Object.create(context), scope), () => { const vnode = fiber.vnode; pvnode.sel = vnode.sel; });
- let pvnode = h('dummy', {key: k10, hook: {remove() {},destroy(vn) {w9.destroy();}}});
- c8.push(pvnode);
- w9.__owl__.pvnode = pvnode;
- }
- w9.__owl__.parentLastFiberId = extra.fiber.id;
- }
- scope = _origScope6;
- return vn1;
-}"
-`;
-
-exports[`t-slot directive slots are rendered with proper context, part 3 3`] = `
-"function anonymous(context, extra
-) {
- // Template name: \\"slot_default_template\\"
- let scope = Object.create(context);
- var h = this.h;
- let c8 = extra.parentNode;
- if (scope.userdescr || scope.userdescr === 0) {
- c8.push({text: scope.userdescr});
- }
-}"
-`;
-
-exports[`t-slot directive slots are rendered with proper context, part 4 1`] = `
-"function anonymous(context, extra
-) {
- // Template name: \\"App\\"
- let utils = this.constructor.utils;
- let QWeb = this.constructor;
- let parent = context;
- let scope = Object.create(context);
- var h = this.h;
- let c1 = [], p1 = {key:1};
- var vn1 = h('div', p1, c1);
- scope.userdescr = 'User '+scope['state'].user.name;
- //COMPONENT
- let k3 = \`__4__\`;
- let w2 = k3 in parent.__owl__.cmap ? parent.__owl__.children[parent.__owl__.cmap[k3]] : false;
- let props2 = {to:'/user/'+scope['state'].user.id};
- if (w2 && w2.__owl__.currentFiber && !w2.__owl__.vnode) {
- w2.destroy();
- w2 = false;
- }
- if (w2) {
- w2.__updateProps(props2, extra.fiber, Object.assign(Object.create(context), scope));
- let pvnode = w2.__owl__.pvnode;
- c1.push(pvnode);
- } else {
- let componentKey2 = \`Link\`;
- let W2 = context.constructor.components[componentKey2] || QWeb.components[componentKey2]|| scope['Link'];
- if (!W2) {throw new Error('Cannot find the definition of component \\"' + componentKey2 + '\\"')}
- w2 = new W2(parent, props2);
- parent.__owl__.cmap[k3] = w2.__owl__.id;
- w2.__owl__.slotId = 1;
- let fiber = w2.__prepare(extra.fiber, Object.assign(Object.create(context), scope), () => { const vnode = fiber.vnode; pvnode.sel = vnode.sel; });
- let pvnode = h('dummy', {key: k3, hook: {remove() {},destroy(vn) {w2.destroy();}}});
- c1.push(pvnode);
- w2.__owl__.pvnode = pvnode;
- }
- w2.__owl__.parentLastFiberId = extra.fiber.id;
- return vn1;
-}"
-`;
-
-exports[`t-slot directive slots are rendered with proper context, part 4 2`] = `
-"function anonymous(context, extra
-) {
- // Template name: \\"slot_default_template\\"
- let scope = Object.create(context);
- var h = this.h;
- let c1 = extra.parentNode;
- if (scope.userdescr || scope.userdescr === 0) {
- c1.push({text: scope.userdescr});
- }
-}"
-`;
-
-exports[`t-slot directive template can just return a slot 1`] = `
-"function anonymous(context, extra
-) {
- // Template name: \\"__template__2\\"
- let utils = this.constructor.utils;
- let result;
- var h = this.h;
- const slot8 = this.constructor.slots[context.__owl__.slotId + '_' + 'default'];
- if (slot8) {
- let children9= []
- result = {}
- slot8.call(this, context.__owl__.scope, Object.assign({}, extra, {parentNode: children9, parent: extra.parent || context}));
- utils.defineProxy(result, children9[0]);
- }
- return result;
-}"
-`;
-
exports[`top level sub widgets basic use 1`] = `
"function anonymous(context, extra
) {
diff --git a/tests/component/__snapshots__/slots.test.ts.snap b/tests/component/__snapshots__/slots.test.ts.snap
new file mode 100644
index 00000000..8a14014d
--- /dev/null
+++ b/tests/component/__snapshots__/slots.test.ts.snap
@@ -0,0 +1,488 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`t-slot directive can define and call slots 1`] = `
+"function anonymous(context, extra
+) {
+ // Template name: \\"Parent\\"
+ let utils = this.constructor.utils;
+ let QWeb = this.constructor;
+ let parent = context;
+ let scope = Object.create(context);
+ var h = this.h;
+ let c1 = [], p1 = {key:1};
+ var vn1 = h('div', p1, c1);
+ //COMPONENT
+ let k3 = \`__4__\`;
+ let w2 = k3 in parent.__owl__.cmap ? parent.__owl__.children[parent.__owl__.cmap[k3]] : false;
+ let props2 = {};
+ if (w2 && w2.__owl__.currentFiber && !w2.__owl__.vnode) {
+ w2.destroy();
+ w2 = false;
+ }
+ if (w2) {
+ w2.__updateProps(props2, extra.fiber, Object.assign(Object.create(context), scope));
+ let pvnode = w2.__owl__.pvnode;
+ c1.push(pvnode);
+ } else {
+ let componentKey2 = \`Dialog\`;
+ let W2 = context.constructor.components[componentKey2] || QWeb.components[componentKey2]|| scope['Dialog'];
+ if (!W2) {throw new Error('Cannot find the definition of component \\"' + componentKey2 + '\\"')}
+ w2 = new W2(parent, props2);
+ parent.__owl__.cmap[k3] = w2.__owl__.id;
+ w2.__owl__.slotId = 1;
+ let fiber = w2.__prepare(extra.fiber, Object.assign(Object.create(context), scope), () => { const vnode = fiber.vnode; pvnode.sel = vnode.sel; });
+ let pvnode = h('dummy', {key: k3, hook: {remove() {},destroy(vn) {w2.destroy();}}});
+ c1.push(pvnode);
+ w2.__owl__.pvnode = pvnode;
+ }
+ w2.__owl__.parentLastFiberId = extra.fiber.id;
+ return vn1;
+}"
+`;
+
+exports[`t-slot directive can define and call slots 2`] = `
+"function anonymous(context, extra
+) {
+ // Template name: \\"Dialog\\"
+ var h = this.h;
+ let c7 = [], p7 = {key:7};
+ var vn7 = h('div', p7, c7);
+ let c8 = [], p8 = {key:8};
+ var vn8 = h('div', p8, c8);
+ c7.push(vn8);
+ const slot9 = this.constructor.slots[context.__owl__.slotId + '_' + 'header'];
+ if (slot9) {
+ slot9.call(this, context.__owl__.scope, Object.assign({}, extra, {parentNode: c8, parent: extra.parent || context}));
+ }
+ let c10 = [], p10 = {key:10};
+ var vn10 = h('div', p10, c10);
+ c7.push(vn10);
+ const slot11 = this.constructor.slots[context.__owl__.slotId + '_' + 'footer'];
+ if (slot11) {
+ slot11.call(this, context.__owl__.scope, Object.assign({}, extra, {parentNode: c10, parent: extra.parent || context}));
+ }
+ return vn7;
+}"
+`;
+
+exports[`t-slot directive can define and call slots 3`] = `
+"function anonymous(context, extra
+) {
+ // Template name: \\"slot_header_template\\"
+ var h = this.h;
+ let c1 = extra.parentNode;
+ let c5 = [], p5 = {key:5};
+ var vn5 = h('span', p5, c5);
+ c1.push(vn5);
+ c5.push({text: \`header\`});
+}"
+`;
+
+exports[`t-slot directive can define and call slots 4`] = `
+"function anonymous(context, extra
+) {
+ // Template name: \\"slot_footer_template\\"
+ var h = this.h;
+ let c1 = extra.parentNode;
+ let c6 = [], p6 = {key:6};
+ var vn6 = h('span', p6, c6);
+ c1.push(vn6);
+ c6.push({text: \`footer\`});
+}"
+`;
+
+exports[`t-slot directive content is the default slot 1`] = `
+"function anonymous(context, extra
+) {
+ // Template name: \\"slot_default_template\\"
+ var h = this.h;
+ let c1 = extra.parentNode;
+ let c5 = [], p5 = {key:5};
+ var vn5 = h('span', p5, c5);
+ c1.push(vn5);
+ c5.push({text: \`sts rocks\`});
+}"
+`;
+
+exports[`t-slot directive dafault slots can define a default content 1`] = `
+"function anonymous(context, extra
+) {
+ // Template name: \\"__template__1\\"
+ var h = this.h;
+ let c5 = [], p5 = {key:5};
+ var vn5 = h('span', p5, c5);
+ const slot6 = this.constructor.slots[context.__owl__.slotId + '_' + 'default'];
+ if (slot6) {
+ slot6.call(this, context.__owl__.scope, Object.assign({}, extra, {parentNode: c5, parent: extra.parent || context}));
+ } else {
+ c5.push({text: \`default content\`});
+ }
+ return vn5;
+}"
+`;
+
+exports[`t-slot directive default slot work with text nodes 1`] = `
+"function anonymous(context, extra
+) {
+ // Template name: \\"slot_default_template\\"
+ var h = this.h;
+ let c1 = extra.parentNode;
+ c1.push({text: \`sts rocks\`});
+}"
+`;
+
+exports[`t-slot directive multiple roots are allowed in a default slot 1`] = `
+"function anonymous(context, extra
+) {
+ // Template name: \\"slot_default_template\\"
+ var h = this.h;
+ let c1 = extra.parentNode;
+ let c5 = [], p5 = {key:5};
+ var vn5 = h('span', p5, c5);
+ c1.push(vn5);
+ c5.push({text: \`sts\`});
+ let c6 = [], p6 = {key:6};
+ var vn6 = h('span', p6, c6);
+ c1.push(vn6);
+ c6.push({text: \`rocks\`});
+}"
+`;
+
+exports[`t-slot directive multiple roots are allowed in a named slot 1`] = `
+"function anonymous(context, extra
+) {
+ // Template name: \\"slot_content_template\\"
+ var h = this.h;
+ let c1 = extra.parentNode;
+ let c5 = [], p5 = {key:5};
+ var vn5 = h('span', p5, c5);
+ c1.push(vn5);
+ c5.push({text: \`sts\`});
+ let c6 = [], p6 = {key:6};
+ var vn6 = h('span', p6, c6);
+ c1.push(vn6);
+ c6.push({text: \`rocks\`});
+}"
+`;
+
+exports[`t-slot directive named slots can define a default content 1`] = `
+"function anonymous(context, extra
+) {
+ // Template name: \\"__template__1\\"
+ var h = this.h;
+ let c5 = [], p5 = {key:5};
+ var vn5 = h('span', p5, c5);
+ const slot6 = this.constructor.slots[context.__owl__.slotId + '_' + 'header'];
+ if (slot6) {
+ slot6.call(this, context.__owl__.scope, Object.assign({}, extra, {parentNode: c5, parent: extra.parent || context}));
+ } else {
+ c5.push({text: \`default content\`});
+ }
+ return vn5;
+}"
+`;
+
+exports[`t-slot directive refs are properly bound in slots 1`] = `
+"function anonymous(context, extra
+) {
+ // Template name: \\"slot_footer_template\\"
+ context.__owl__.refs = context.__owl__.refs || {};
+ var h = this.h;
+ let c1 = extra.parentNode;
+ let c9 = [], p9 = {key:9,on:{}};
+ var vn9 = h('button', p9, c9);
+ c1.push(vn9);
+ extra.handlers['click' + 9] = extra.handlers['click' + 9] || function (e) {if (!context.__owl__.isMounted){return}const fn = context['doSomething'];if (fn) { fn.call(context, e); } else { context.doSomething; }};
+ p9.on['click'] = extra.handlers['click' + 9];
+ const ref10 = \`myButton\`;
+ p9.hook = {
+ create: (_, n) => {
+ context.__owl__.refs[ref10] = n.elm;
+ },
+ destroy: () => {
+ delete context.__owl__.refs[ref10];
+ },
+ };
+ c9.push({text: \`do something\`});
+}"
+`;
+
+exports[`t-slot directive slots are rendered with proper context 1`] = `
+"function anonymous(context, extra
+) {
+ // Template name: \\"slot_footer_template\\"
+ var h = this.h;
+ let c1 = extra.parentNode;
+ let c9 = [], p9 = {key:9,on:{}};
+ var vn9 = h('button', p9, c9);
+ c1.push(vn9);
+ extra.handlers['click' + 9] = extra.handlers['click' + 9] || function (e) {if (!context.__owl__.isMounted){return}const fn = context['doSomething'];if (fn) { fn.call(context, e); } else { context.doSomething; }};
+ p9.on['click'] = extra.handlers['click' + 9];
+ c9.push({text: \`do something\`});
+}"
+`;
+
+exports[`t-slot directive slots are rendered with proper context, part 2 1`] = `
+"function anonymous(context, extra
+) {
+ // Template name: \\"Link\\"
+ let scope = Object.create(context);
+ var h = this.h;
+ var _13 = scope['props'].to;
+ let c14 = [], p14 = {key:14,attrs:{href: _13}};
+ var vn14 = h('a', p14, c14);
+ const slot15 = this.constructor.slots[context.__owl__.slotId + '_' + 'default'];
+ if (slot15) {
+ slot15.call(this, context.__owl__.scope, Object.assign({}, extra, {parentNode: c14, parent: extra.parent || context}));
+ }
+ return vn14;
+}"
+`;
+
+exports[`t-slot directive slots are rendered with proper context, part 2 2`] = `
+"function anonymous(context, extra
+) {
+ // Template name: \\"App\\"
+ let utils = this.constructor.utils;
+ let QWeb = this.constructor;
+ let parent = context;
+ let scope = Object.create(context);
+ var h = this.h;
+ let c1 = [], p1 = {key:1};
+ var vn1 = h('div', p1, c1);
+ let c2 = [], p2 = {key:2};
+ var vn2 = h('u', p2, c2);
+ c1.push(vn2);
+ var _3 = scope['state'].users;
+ if (!_3) { throw new Error('QWeb error: Invalid loop expression')}
+ var _4 = _5 = _3;
+ if (!(_3 instanceof Array)) {
+ _4 = Object.keys(_3);
+ _5 = Object.values(_3);
+ }
+ var _length4 = _4.length;
+ const _origScope6 = scope;
+ scope = Object.assign(Object.create(context), scope);
+ for (let i1 = 0; i1 < _length4; i1++) {
+ scope.user_first = i1 === 0
+ scope.user_last = i1 === _length4 - 1
+ scope.user_index = i1
+ scope.user = _4[i1]
+ scope.user_value = _5[i1]
+ const nodeKey7 = scope['user'].id;
+ let c8 = [], p8 = {key:nodeKey7};
+ var vn8 = h('li', p8, c8);
+ c2.push(vn8);
+ //COMPONENT
+ let k10 = \`__11__\` + nodeKey7;
+ let w9 = k10 in parent.__owl__.cmap ? parent.__owl__.children[parent.__owl__.cmap[k10]] : false;
+ let props9 = {to:'/user/'+scope['user'].id};
+ if (w9 && w9.__owl__.currentFiber && !w9.__owl__.vnode) {
+ w9.destroy();
+ w9 = false;
+ }
+ if (w9) {
+ w9.__updateProps(props9, extra.fiber, Object.assign(Object.create(context), scope));
+ let pvnode = w9.__owl__.pvnode;
+ c8.push(pvnode);
+ } else {
+ let componentKey9 = \`Link\`;
+ let W9 = context.constructor.components[componentKey9] || QWeb.components[componentKey9]|| scope['Link'];
+ if (!W9) {throw new Error('Cannot find the definition of component \\"' + componentKey9 + '\\"')}
+ w9 = new W9(parent, props9);
+ parent.__owl__.cmap[k10] = w9.__owl__.id;
+ w9.__owl__.slotId = 1;
+ let fiber = w9.__prepare(extra.fiber, Object.assign(Object.create(context), scope), () => { const vnode = fiber.vnode; pvnode.sel = vnode.sel; });
+ let pvnode = h('dummy', {key: k10, hook: {remove() {},destroy(vn) {w9.destroy();}}});
+ c8.push(pvnode);
+ w9.__owl__.pvnode = pvnode;
+ }
+ w9.__owl__.parentLastFiberId = extra.fiber.id;
+ }
+ scope = _origScope6;
+ return vn1;
+}"
+`;
+
+exports[`t-slot directive slots are rendered with proper context, part 2 3`] = `
+"function anonymous(context, extra
+) {
+ // Template name: \\"slot_default_template\\"
+ let scope = Object.create(context);
+ var h = this.h;
+ let c8 = extra.parentNode;
+ c8.push({text: \`User \`});
+ var _12 = scope['user'].name;
+ if (_12 || _12 === 0) {
+ c8.push({text: _12});
+ }
+}"
+`;
+
+exports[`t-slot directive slots are rendered with proper context, part 3 1`] = `
+"function anonymous(context, extra
+) {
+ // Template name: \\"Link\\"
+ let scope = Object.create(context);
+ var h = this.h;
+ var _12 = scope['props'].to;
+ let c13 = [], p13 = {key:13,attrs:{href: _12}};
+ var vn13 = h('a', p13, c13);
+ const slot14 = this.constructor.slots[context.__owl__.slotId + '_' + 'default'];
+ if (slot14) {
+ slot14.call(this, context.__owl__.scope, Object.assign({}, extra, {parentNode: c13, parent: extra.parent || context}));
+ }
+ return vn13;
+}"
+`;
+
+exports[`t-slot directive slots are rendered with proper context, part 3 2`] = `
+"function anonymous(context, extra
+) {
+ // Template name: \\"App\\"
+ let utils = this.constructor.utils;
+ let QWeb = this.constructor;
+ let parent = context;
+ let scope = Object.create(context);
+ var h = this.h;
+ let c1 = [], p1 = {key:1};
+ var vn1 = h('div', p1, c1);
+ let c2 = [], p2 = {key:2};
+ var vn2 = h('u', p2, c2);
+ c1.push(vn2);
+ var _3 = scope['state'].users;
+ if (!_3) { throw new Error('QWeb error: Invalid loop expression')}
+ var _4 = _5 = _3;
+ if (!(_3 instanceof Array)) {
+ _4 = Object.keys(_3);
+ _5 = Object.values(_3);
+ }
+ var _length4 = _4.length;
+ const _origScope6 = scope;
+ scope = Object.assign(Object.create(context), scope);
+ for (let i1 = 0; i1 < _length4; i1++) {
+ scope.user_first = i1 === 0
+ scope.user_last = i1 === _length4 - 1
+ scope.user_index = i1
+ scope.user = _4[i1]
+ scope.user_value = _5[i1]
+ const nodeKey7 = scope['user'].id;
+ let c8 = [], p8 = {key:nodeKey7};
+ var vn8 = h('li', p8, c8);
+ c2.push(vn8);
+ scope.userdescr = 'User '+scope['user'].name;
+ //COMPONENT
+ let k10 = \`__11__\` + nodeKey7;
+ let w9 = k10 in parent.__owl__.cmap ? parent.__owl__.children[parent.__owl__.cmap[k10]] : false;
+ let props9 = {to:'/user/'+scope['user'].id};
+ if (w9 && w9.__owl__.currentFiber && !w9.__owl__.vnode) {
+ w9.destroy();
+ w9 = false;
+ }
+ if (w9) {
+ w9.__updateProps(props9, extra.fiber, Object.assign(Object.create(context), scope));
+ let pvnode = w9.__owl__.pvnode;
+ c8.push(pvnode);
+ } else {
+ let componentKey9 = \`Link\`;
+ let W9 = context.constructor.components[componentKey9] || QWeb.components[componentKey9]|| scope['Link'];
+ if (!W9) {throw new Error('Cannot find the definition of component \\"' + componentKey9 + '\\"')}
+ w9 = new W9(parent, props9);
+ parent.__owl__.cmap[k10] = w9.__owl__.id;
+ w9.__owl__.slotId = 1;
+ let fiber = w9.__prepare(extra.fiber, Object.assign(Object.create(context), scope), () => { const vnode = fiber.vnode; pvnode.sel = vnode.sel; });
+ let pvnode = h('dummy', {key: k10, hook: {remove() {},destroy(vn) {w9.destroy();}}});
+ c8.push(pvnode);
+ w9.__owl__.pvnode = pvnode;
+ }
+ w9.__owl__.parentLastFiberId = extra.fiber.id;
+ }
+ scope = _origScope6;
+ return vn1;
+}"
+`;
+
+exports[`t-slot directive slots are rendered with proper context, part 3 3`] = `
+"function anonymous(context, extra
+) {
+ // Template name: \\"slot_default_template\\"
+ let scope = Object.create(context);
+ var h = this.h;
+ let c8 = extra.parentNode;
+ if (scope.userdescr || scope.userdescr === 0) {
+ c8.push({text: scope.userdescr});
+ }
+}"
+`;
+
+exports[`t-slot directive slots are rendered with proper context, part 4 1`] = `
+"function anonymous(context, extra
+) {
+ // Template name: \\"App\\"
+ let utils = this.constructor.utils;
+ let QWeb = this.constructor;
+ let parent = context;
+ let scope = Object.create(context);
+ var h = this.h;
+ let c1 = [], p1 = {key:1};
+ var vn1 = h('div', p1, c1);
+ scope.userdescr = 'User '+scope['state'].user.name;
+ //COMPONENT
+ let k3 = \`__4__\`;
+ let w2 = k3 in parent.__owl__.cmap ? parent.__owl__.children[parent.__owl__.cmap[k3]] : false;
+ let props2 = {to:'/user/'+scope['state'].user.id};
+ if (w2 && w2.__owl__.currentFiber && !w2.__owl__.vnode) {
+ w2.destroy();
+ w2 = false;
+ }
+ if (w2) {
+ w2.__updateProps(props2, extra.fiber, Object.assign(Object.create(context), scope));
+ let pvnode = w2.__owl__.pvnode;
+ c1.push(pvnode);
+ } else {
+ let componentKey2 = \`Link\`;
+ let W2 = context.constructor.components[componentKey2] || QWeb.components[componentKey2]|| scope['Link'];
+ if (!W2) {throw new Error('Cannot find the definition of component \\"' + componentKey2 + '\\"')}
+ w2 = new W2(parent, props2);
+ parent.__owl__.cmap[k3] = w2.__owl__.id;
+ w2.__owl__.slotId = 1;
+ let fiber = w2.__prepare(extra.fiber, Object.assign(Object.create(context), scope), () => { const vnode = fiber.vnode; pvnode.sel = vnode.sel; });
+ let pvnode = h('dummy', {key: k3, hook: {remove() {},destroy(vn) {w2.destroy();}}});
+ c1.push(pvnode);
+ w2.__owl__.pvnode = pvnode;
+ }
+ w2.__owl__.parentLastFiberId = extra.fiber.id;
+ return vn1;
+}"
+`;
+
+exports[`t-slot directive slots are rendered with proper context, part 4 2`] = `
+"function anonymous(context, extra
+) {
+ // Template name: \\"slot_default_template\\"
+ let scope = Object.create(context);
+ var h = this.h;
+ let c1 = extra.parentNode;
+ if (scope.userdescr || scope.userdescr === 0) {
+ c1.push({text: scope.userdescr});
+ }
+}"
+`;
+
+exports[`t-slot directive template can just return a slot 1`] = `
+"function anonymous(context, extra
+) {
+ // Template name: \\"__template__2\\"
+ let utils = this.constructor.utils;
+ let result;
+ var h = this.h;
+ const slot8 = this.constructor.slots[context.__owl__.slotId + '_' + 'default'];
+ if (slot8) {
+ let children9= []
+ result = {}
+ slot8.call(this, context.__owl__.scope, Object.assign({}, extra, {parentNode: children9, parent: extra.parent || context}));
+ utils.defineProxy(result, children9[0]);
+ }
+ return result;
+}"
+`;
diff --git a/tests/component/component.test.ts b/tests/component/component.test.ts
index 66c8423f..f6df45ce 100644
--- a/tests/component/component.test.ts
+++ b/tests/component/component.test.ts
@@ -4000,845 +4000,6 @@ describe("can deduce template from name", () => {
});
});
-describe("t-slot directive", () => {
- test("can define and call slots", async () => {
- env.qweb.addTemplates(`
-
hey
heyaaron
hey
heyaaron