diff --git a/src/qweb/base_directives.ts b/src/qweb/base_directives.ts index f8a4623e..45441a09 100644 --- a/src/qweb/base_directives.ts +++ b/src/qweb/base_directives.ts @@ -265,7 +265,7 @@ QWeb.addDirective({ // ------------------------------------------------ const callingScope = hasBody ? "scope" : "Object.assign(Object.create(context), scope)"; const parentComponent = `utils.getComponent(context)`; - const keyCode = ctx.loopNumber ? `, key: ${ctx.generateTemplateKey()}` : ""; + const keyCode = ctx.loopNumber || ctx.hasKey0 ? `, key: ${ctx.generateTemplateKey()}` : ""; const parentNode = ctx.parentNode ? `c${ctx.parentNode}` : "result"; const extra = `Object.assign({}, extra, {parentNode: ${parentNode}, parent: ${parentComponent}${keyCode}})`; if (ctx.parentNode) { @@ -334,6 +334,13 @@ QWeb.addDirective({ `Directive t-foreach should always be used with a t-key! (in template: '${ctx.templateName}')` ); } + if (nodeCopy.hasAttribute("t-key")) { + const expr = ctx.formatExpression(nodeCopy.getAttribute("t-key")!); + ctx.addLine(`let key${ctx.loopNumber} = ${expr};`); + nodeCopy.removeAttribute("t-key"); + } else { + ctx.addLine(`let key${ctx.loopNumber} = i${ctx.loopNumber};`); + } nodeCopy.removeAttribute("t-foreach"); qweb._compileNode(nodeCopy, ctx); diff --git a/src/qweb/compilation_context.ts b/src/qweb/compilation_context.ts index 4c380464..0abceb5e 100644 --- a/src/qweb/compilation_context.ts +++ b/src/qweb/compilation_context.ts @@ -26,7 +26,8 @@ export class CompilationContext { templateName: string; allowMultipleRoots: boolean = false; hasParentWidget: boolean = false; - currentKey: string = ""; + hasKey0: boolean = false; + keyStack: boolean[] = []; constructor(name?: string) { this.rootContext = this; @@ -48,20 +49,15 @@ export class CompilationContext { */ generateTemplateKey(prefix: string = ""): string { const id = this.generateID(); - if (this.loopNumber === 0 && !this.currentKey) { + if (this.loopNumber === 0 && !this.hasKey0) { return `'${prefix}__${id}__'`; } - let locationExpr = `\`${prefix}__${id}__`; - for (let i = 0; i < this.loopNumber - 1; i++) { - locationExpr += `\${i${i + 1}}__`; - } - if (this.currentKey) { - const k = this.currentKey; - this.addLine(`let k${id} = ${locationExpr}\` + ${k};`); - } else { - locationExpr += this.loopNumber ? `\${i${this.loopNumber}}__\`` : "`"; - this.addLine(`let k${id} = ${locationExpr};`); + let key = `\`${prefix}__${id}__`; + let start = this.hasKey0 ? 0 : 1; + for (let i = start; i < this.loopNumber + 1; i++) { + key += `\${key${i}}__`; } + this.addLine(`let k${id} = ${key}\`;`); return `k${id}`; } @@ -116,11 +112,11 @@ export class CompilationContext { } indent() { - this.indentLevel++; + this.rootContext.indentLevel++; } dedent() { - this.indentLevel--; + this.rootContext.indentLevel--; } addLine(line: string): number { diff --git a/src/qweb/extensions.ts b/src/qweb/extensions.ts index 4c5922c6..bd1e8dd3 100644 --- a/src/qweb/extensions.ts +++ b/src/qweb/extensions.ts @@ -303,9 +303,20 @@ QWeb.addDirective({ QWeb.addDirective({ name: "key", priority: 45, - atNodeEncounter({ ctx, value }) { - let id = ctx.generateID(); - ctx.addLine(`const nodeKey${id} = ${ctx.formatExpression(value)};`); - ctx.currentKey = `nodeKey${id}`; + atNodeEncounter({ ctx, value, node }) { + if (ctx.loopNumber === 0) { + ctx.keyStack.push(ctx.rootContext.hasKey0); + ctx.rootContext.hasKey0 = true; + } + ctx.addLine("{"); + ctx.indent(); + ctx.addLine(`let key${ctx.loopNumber} = ${ctx.formatExpression(value)};`); + }, + finalize({ ctx }) { + ctx.dedent(); + ctx.addLine("}"); + if (ctx.loopNumber === 0) { + ctx.rootContext.hasKey0 = ctx.keyStack.pop() as boolean; + } } }); diff --git a/src/qweb/qweb.ts b/src/qweb/qweb.ts index 0bd591cd..f95d1c58 100644 --- a/src/qweb/qweb.ts +++ b/src/qweb/qweb.ts @@ -402,8 +402,8 @@ export class QWeb extends EventBus { ctx.shouldDefineResult = false; ctx.addLine(`let c${ctx.parentNode} = extra.parentNode;`); if (defineKey) { - ctx.currentKey = `key${ctx.generateID()}`; - ctx.addLine(`let ${ctx.currentKey} = extra.key || '';`); + ctx.addLine(`let key0 = extra.key || "";`); + ctx.hasKey0 = true; } } this._compileNode(elem, ctx); @@ -482,9 +482,6 @@ export class QWeb extends EventBus { } return; } - if (ctx !== ctx.rootContext) { - ctx = ctx.subContext("currentKey", ctx.currentKey); - } const firstLetter = node.tagName[0]; if (firstLetter === firstLetter.toUpperCase()) { @@ -759,8 +756,8 @@ export class QWeb extends EventBus { } } let nodeID = ctx.generateID(); - let nodeKey = ctx.currentKey || nodeID; - const parts = [`key:${nodeKey}`]; + let key = ctx.loopNumber || ctx.hasKey0 ? `\`\${key${ctx.loopNumber}}_${nodeID}\`` : nodeID; + const parts = [`key:${key}`]; if (attrs.length + tattrs.length > 0) { parts.push(`attrs:{${attrs.join(",")}}`); } @@ -789,6 +786,9 @@ export class QWeb extends EventBus { ctx.addLine(`let vn${nodeID} = h('${node.nodeName}', p${nodeID}, c${nodeID});`); if (ctx.parentNode) { ctx.addLine(`c${ctx.parentNode}.push(vn${nodeID});`); + } else if (ctx.loopNumber || ctx.hasKey0) { + ctx.rootContext.shouldDefineResult = true; + ctx.addLine(`result = vn${nodeID};`); } return nodeID; diff --git a/tests/component/__snapshots__/component.test.ts.snap b/tests/component/__snapshots__/component.test.ts.snap index f52a855d..78fe841d 100644 --- a/tests/component/__snapshots__/component.test.ts.snap +++ b/tests/component/__snapshots__/component.test.ts.snap @@ -27,6 +27,7 @@ exports[`basic widget properties reconciliation alg works for t-foreach in t-for scope.section_index = i1 scope.section = _3[i1] scope.section_value = _4[i1] + let key1 = i1; let _6 = scope['section'].blips; if (!_6) { throw new Error('QWeb error: Invalid loop expression')} let _7 = _8 = _6; @@ -43,8 +44,9 @@ exports[`basic widget properties reconciliation alg works for t-foreach in t-for scope.blip_index = i2 scope.blip = _7[i2] scope.blip_value = _8[i2] + let key2 = i2; // Component 'Child' - let k11 = \`__11__\${i1}__\${i2}__\`; + let k11 = \`__11__\${key1}__\${key2}__\`; let w10 = k11 in parent.__owl__.cmap ? parent.__owl__.children[parent.__owl__.cmap[k11]] : false; let props10 = {blip:scope['blip']}; if (w10 && w10.__owl__.currentFiber && !w10.__owl__.vnode) { @@ -75,6 +77,81 @@ exports[`basic widget properties reconciliation alg works for t-foreach in t-for }" `; +exports[`basic widget properties same t-keys in two different places 1`] = ` +"function anonymous(context, extra +) { + // Template name: \\"__template__2\\" + let utils = this.constructor.utils; + let QWeb = this.constructor; + let parent = context; + let scope = Object.create(context); + let h = this.h; + let c1 = [], p1 = {key:1}; + let vn1 = h('div', p1, c1); + let c2 = [], p2 = {key:2}; + let vn2 = h('div', p2, c2); + c1.push(vn2); + { + let key0 = 1; + // Component 'Child' + let k4 = \`__4__\${key0}__\`; + let w3 = k4 in parent.__owl__.cmap ? parent.__owl__.children[parent.__owl__.cmap[k4]] : false; + let props3 = {blip:'1'}; + if (w3 && w3.__owl__.currentFiber && !w3.__owl__.vnode) { + w3.destroy(); + w3 = false; + } + if (w3) { + w3.__updateProps(props3, extra.fiber, undefined); + let pvnode = w3.__owl__.pvnode; + c2.push(pvnode); + } else { + let componentKey3 = \`Child\`; + let W3 = context.constructor.components[componentKey3] || QWeb.components[componentKey3]|| scope['Child']; + if (!W3) {throw new Error('Cannot find the definition of component \\"' + componentKey3 + '\\"')} + w3 = new W3(parent, props3); + parent.__owl__.cmap[k4] = w3.__owl__.id; + let fiber = w3.__prepare(extra.fiber, undefined, () => { const vnode = fiber.vnode; pvnode.sel = vnode.sel; }); + let pvnode = h('dummy', {key: k4, hook: {remove() {},destroy(vn) {w3.destroy();}}}); + c2.push(pvnode); + w3.__owl__.pvnode = pvnode; + } + w3.__owl__.parentLastFiberId = extra.fiber.id; + } + let c5 = [], p5 = {key:5}; + let vn5 = h('div', p5, c5); + c1.push(vn5); + { + let key0 = 1; + // Component 'Child' + let k7 = \`__7__\${key0}__\`; + let w6 = k7 in parent.__owl__.cmap ? parent.__owl__.children[parent.__owl__.cmap[k7]] : false; + let props6 = {blip:'2'}; + if (w6 && w6.__owl__.currentFiber && !w6.__owl__.vnode) { + w6.destroy(); + w6 = false; + } + if (w6) { + w6.__updateProps(props6, extra.fiber, undefined); + let pvnode = w6.__owl__.pvnode; + c5.push(pvnode); + } else { + let componentKey6 = \`Child\`; + let W6 = context.constructor.components[componentKey6] || QWeb.components[componentKey6]|| scope['Child']; + if (!W6) {throw new Error('Cannot find the definition of component \\"' + componentKey6 + '\\"')} + w6 = new W6(parent, props6); + parent.__owl__.cmap[k7] = w6.__owl__.id; + let fiber = w6.__prepare(extra.fiber, undefined, () => { const vnode = fiber.vnode; pvnode.sel = vnode.sel; }); + let pvnode = h('dummy', {key: k7, hook: {remove() {},destroy(vn) {w6.destroy();}}}); + c5.push(pvnode); + w6.__owl__.pvnode = pvnode; + } + w6.__owl__.parentLastFiberId = extra.fiber.id; + } + return vn1; +}" +`; + exports[`basic widget properties t-key on a component with t-if, and a sibling component 1`] = ` "function anonymous(context, extra ) { @@ -87,55 +164,57 @@ exports[`basic widget properties t-key on a component with t-if, and a sibling c let c1 = [], p1 = {key:1}; let vn1 = h('div', p1, c1); if (false) { - const nodeKey2 = 'str'; - // Component 'Child' - let k4 = \`__4__\` + nodeKey2; - let w3 = k4 in parent.__owl__.cmap ? parent.__owl__.children[parent.__owl__.cmap[k4]] : false; - let props3 = {}; - if (w3 && w3.__owl__.currentFiber && !w3.__owl__.vnode) { - w3.destroy(); - w3 = false; + { + let key0 = 'str'; + // Component 'Child' + let k3 = \`__3__\${key0}__\`; + 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, undefined); + let pvnode = w2.__owl__.pvnode; + c1.push(pvnode); + } else { + let componentKey2 = \`Child\`; + let W2 = context.constructor.components[componentKey2] || QWeb.components[componentKey2]|| scope['Child']; + if (!W2) {throw new Error('Cannot find the definition of component \\"' + componentKey2 + '\\"')} + w2 = new W2(parent, props2); + parent.__owl__.cmap[k3] = w2.__owl__.id; + let fiber = w2.__prepare(extra.fiber, undefined, () => { 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; } - if (w3) { - w3.__updateProps(props3, extra.fiber, undefined); - let pvnode = w3.__owl__.pvnode; - c1.push(pvnode); - } else { - let componentKey3 = \`Child\`; - let W3 = context.constructor.components[componentKey3] || QWeb.components[componentKey3]|| scope['Child']; - if (!W3) {throw new Error('Cannot find the definition of component \\"' + componentKey3 + '\\"')} - w3 = new W3(parent, props3); - parent.__owl__.cmap[k4] = w3.__owl__.id; - let fiber = w3.__prepare(extra.fiber, undefined, () => { const vnode = fiber.vnode; pvnode.sel = vnode.sel; }); - let pvnode = h('dummy', {key: k4, hook: {remove() {},destroy(vn) {w3.destroy();}}}); - c1.push(pvnode); - w3.__owl__.pvnode = pvnode; - } - w3.__owl__.parentLastFiberId = extra.fiber.id; } // Component 'Child' - let w5 = '__6__' in parent.__owl__.cmap ? parent.__owl__.children[parent.__owl__.cmap['__6__']] : false; - let props5 = {}; - if (w5 && w5.__owl__.currentFiber && !w5.__owl__.vnode) { - w5.destroy(); - w5 = false; + let w4 = '__5__' in parent.__owl__.cmap ? parent.__owl__.children[parent.__owl__.cmap['__5__']] : false; + let props4 = {}; + if (w4 && w4.__owl__.currentFiber && !w4.__owl__.vnode) { + w4.destroy(); + w4 = false; } - if (w5) { - w5.__updateProps(props5, extra.fiber, undefined); - let pvnode = w5.__owl__.pvnode; + if (w4) { + w4.__updateProps(props4, extra.fiber, undefined); + let pvnode = w4.__owl__.pvnode; c1.push(pvnode); } else { - let componentKey5 = \`Child\`; - let W5 = context.constructor.components[componentKey5] || QWeb.components[componentKey5]|| scope['Child']; - if (!W5) {throw new Error('Cannot find the definition of component \\"' + componentKey5 + '\\"')} - w5 = new W5(parent, props5); - parent.__owl__.cmap['__6__'] = w5.__owl__.id; - let fiber = w5.__prepare(extra.fiber, undefined, () => { const vnode = fiber.vnode; pvnode.sel = vnode.sel; }); - let pvnode = h('dummy', {key: '__6__', hook: {remove() {},destroy(vn) {w5.destroy();}}}); + let componentKey4 = \`Child\`; + let W4 = context.constructor.components[componentKey4] || QWeb.components[componentKey4]|| scope['Child']; + if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')} + w4 = new W4(parent, props4); + parent.__owl__.cmap['__5__'] = w4.__owl__.id; + let fiber = w4.__prepare(extra.fiber, undefined, () => { const vnode = fiber.vnode; pvnode.sel = vnode.sel; }); + let pvnode = h('dummy', {key: '__5__', hook: {remove() {},destroy(vn) {w4.destroy();}}}); c1.push(pvnode); - w5.__owl__.pvnode = pvnode; + w4.__owl__.pvnode = pvnode; } - w5.__owl__.parentLastFiberId = extra.fiber.id; + w4.__owl__.parentLastFiberId = extra.fiber.id; return vn1; }" `; @@ -322,31 +401,34 @@ exports[`composition sub components with some state rendered in a loop 1`] = ` scope.number_index = i1 scope.number = _3[i1] scope.number_value = _4[i1] - const nodeKey6 = scope['number']; - // Component 'ChildWidget' - let k8 = \`__8__\` + nodeKey6; - let w7 = k8 in parent.__owl__.cmap ? parent.__owl__.children[parent.__owl__.cmap[k8]] : false; - let props7 = {}; - if (w7 && w7.__owl__.currentFiber && !w7.__owl__.vnode) { - w7.destroy(); - w7 = false; + let key1 = i1; + { + let key1 = scope['number']; + // Component 'ChildWidget' + let k7 = \`__7__\${key1}__\`; + let w6 = k7 in parent.__owl__.cmap ? parent.__owl__.children[parent.__owl__.cmap[k7]] : false; + let props6 = {}; + if (w6 && w6.__owl__.currentFiber && !w6.__owl__.vnode) { + w6.destroy(); + w6 = false; + } + if (w6) { + w6.__updateProps(props6, extra.fiber, undefined); + let pvnode = w6.__owl__.pvnode; + c1.push(pvnode); + } else { + let componentKey6 = \`ChildWidget\`; + let W6 = context.constructor.components[componentKey6] || QWeb.components[componentKey6]|| scope['ChildWidget']; + if (!W6) {throw new Error('Cannot find the definition of component \\"' + componentKey6 + '\\"')} + w6 = new W6(parent, props6); + parent.__owl__.cmap[k7] = w6.__owl__.id; + let fiber = w6.__prepare(extra.fiber, undefined, () => { const vnode = fiber.vnode; pvnode.sel = vnode.sel; }); + let pvnode = h('dummy', {key: k7, hook: {remove() {},destroy(vn) {w6.destroy();}}}); + c1.push(pvnode); + w6.__owl__.pvnode = pvnode; + } + w6.__owl__.parentLastFiberId = extra.fiber.id; } - if (w7) { - w7.__updateProps(props7, extra.fiber, undefined); - let pvnode = w7.__owl__.pvnode; - c1.push(pvnode); - } else { - let componentKey7 = \`ChildWidget\`; - let W7 = context.constructor.components[componentKey7] || QWeb.components[componentKey7]|| scope['ChildWidget']; - if (!W7) {throw new Error('Cannot find the definition of component \\"' + componentKey7 + '\\"')} - w7 = new W7(parent, props7); - parent.__owl__.cmap[k8] = w7.__owl__.id; - let fiber = w7.__prepare(extra.fiber, undefined, () => { const vnode = fiber.vnode; pvnode.sel = vnode.sel; }); - let pvnode = h('dummy', {key: k8, hook: {remove() {},destroy(vn) {w7.destroy();}}}); - c1.push(pvnode); - w7.__owl__.pvnode = pvnode; - } - w7.__owl__.parentLastFiberId = extra.fiber.id; } scope = _origScope5; return vn1; @@ -922,31 +1004,33 @@ exports[`random stuff/miscellaneous snapshotting compiled code 1`] = ` let h = this.h; let c1 = [], p1 = {key:1}; let vn1 = h('div', p1, c1); - const nodeKey2 = 'somestring'; - // Component 'child' - let k4 = \`__4__\` + nodeKey2; - let w3 = k4 in parent.__owl__.cmap ? parent.__owl__.children[parent.__owl__.cmap[k4]] : false; - let props3 = {flag:scope['state'].flag}; - if (w3 && w3.__owl__.currentFiber && !w3.__owl__.vnode) { - w3.destroy(); - w3 = false; + { + let key0 = 'somestring'; + // Component 'child' + let k3 = \`__3__\${key0}__\`; + let w2 = k3 in parent.__owl__.cmap ? parent.__owl__.children[parent.__owl__.cmap[k3]] : false; + let props2 = {flag:scope['state'].flag}; + if (w2 && w2.__owl__.currentFiber && !w2.__owl__.vnode) { + w2.destroy(); + w2 = false; + } + if (w2) { + w2.__updateProps(props2, extra.fiber, undefined); + let pvnode = w2.__owl__.pvnode; + c1.push(pvnode); + } else { + let componentKey2 = \`child\`; + let W2 = context.constructor.components[componentKey2] || QWeb.components[componentKey2]|| scope['child']; + if (!W2) {throw new Error('Cannot find the definition of component \\"' + componentKey2 + '\\"')} + w2 = new W2(parent, props2); + parent.__owl__.cmap[k3] = w2.__owl__.id; + let fiber = w2.__prepare(extra.fiber, undefined, () => { 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; } - if (w3) { - w3.__updateProps(props3, extra.fiber, undefined); - let pvnode = w3.__owl__.pvnode; - c1.push(pvnode); - } else { - let componentKey3 = \`child\`; - let W3 = context.constructor.components[componentKey3] || QWeb.components[componentKey3]|| scope['child']; - if (!W3) {throw new Error('Cannot find the definition of component \\"' + componentKey3 + '\\"')} - w3 = new W3(parent, props3); - parent.__owl__.cmap[k4] = w3.__owl__.id; - let fiber = w3.__prepare(extra.fiber, undefined, () => { const vnode = fiber.vnode; pvnode.sel = vnode.sel; }); - let pvnode = h('dummy', {key: k4, hook: {remove() {},destroy(vn) {w3.destroy();}}}); - c1.push(pvnode); - w3.__owl__.pvnode = pvnode; - } - w3.__owl__.parentLastFiberId = extra.fiber.id; return vn1; }" `; @@ -978,32 +1062,35 @@ exports[`random stuff/miscellaneous t-on with handler bound to dynamic argument scope.item_index = i1 scope.item = _3[i1] scope.item_value = _4[i1] - const nodeKey6 = scope['item']; - // Component 'Child' - let k8 = \`__8__\` + nodeKey6; - let args9 = [scope['item']]; - let w7 = k8 in parent.__owl__.cmap ? parent.__owl__.children[parent.__owl__.cmap[k8]] : false; - let props7 = {}; - if (w7 && w7.__owl__.currentFiber && !w7.__owl__.vnode) { - w7.destroy(); - w7 = false; + let key1 = i1; + { + let key1 = scope['item']; + // Component 'Child' + let k7 = \`__7__\${key1}__\`; + let args8 = [scope['item']]; + let w6 = k7 in parent.__owl__.cmap ? parent.__owl__.children[parent.__owl__.cmap[k7]] : false; + let props6 = {}; + if (w6 && w6.__owl__.currentFiber && !w6.__owl__.vnode) { + w6.destroy(); + w6 = false; + } + if (w6) { + w6.__updateProps(props6, extra.fiber, undefined); + let pvnode = w6.__owl__.pvnode; + c1.push(pvnode); + } else { + let componentKey6 = \`Child\`; + let W6 = context.constructor.components[componentKey6] || QWeb.components[componentKey6]|| scope['Child']; + if (!W6) {throw new Error('Cannot find the definition of component \\"' + componentKey6 + '\\"')} + w6 = new W6(parent, props6); + parent.__owl__.cmap[k7] = w6.__owl__.id; + let fiber = w6.__prepare(extra.fiber, undefined, () => { const vnode = fiber.vnode; pvnode.sel = vnode.sel; vnode.data.hook = {create(_, vn){vn.elm.addEventListener('ev', function (e) {if (!context.__owl__.isMounted){return}utils.getComponent(context)['onEv'](...args8, e);});}};}); + let pvnode = h('dummy', {key: k7, hook: {remove() {},destroy(vn) {w6.destroy();}}}); + c1.push(pvnode); + w6.__owl__.pvnode = pvnode; + } + w6.__owl__.parentLastFiberId = extra.fiber.id; } - if (w7) { - w7.__updateProps(props7, extra.fiber, undefined); - let pvnode = w7.__owl__.pvnode; - c1.push(pvnode); - } else { - let componentKey7 = \`Child\`; - let W7 = context.constructor.components[componentKey7] || QWeb.components[componentKey7]|| scope['Child']; - if (!W7) {throw new Error('Cannot find the definition of component \\"' + componentKey7 + '\\"')} - w7 = new W7(parent, props7); - parent.__owl__.cmap[k8] = w7.__owl__.id; - let fiber = w7.__prepare(extra.fiber, undefined, () => { const vnode = fiber.vnode; pvnode.sel = vnode.sel; vnode.data.hook = {create(_, vn){vn.elm.addEventListener('ev', function (e) {if (!context.__owl__.isMounted){return}utils.getComponent(context)['onEv'](...args9, e);});}};}); - let pvnode = h('dummy', {key: k8, hook: {remove() {},destroy(vn) {w7.destroy();}}}); - c1.push(pvnode); - w7.__owl__.pvnode = pvnode; - } - w7.__owl__.parentLastFiberId = extra.fiber.id; } scope = _origScope5; return vn1; @@ -1017,14 +1104,14 @@ exports[`t-call handlers are properly bound through a t-call 1`] = ` let utils = this.constructor.utils; let h = this.h; let c1 = extra.parentNode; - let key2 = extra.key || ''; - let c3 = [], p3 = {key:key2,on:{}}; - let vn3 = h('p', p3, c3); - c1.push(vn3); - let k4 = \`click__4__\` + key2; - extra.handlers[k4] = extra.handlers[k4] || function (e) {if (!context.__owl__.isMounted){return}utils.getComponent(context)['update'](e);}; - p3.on['click'] = extra.handlers[k4]; - c3.push({text: \`lucas\`}); + let key0 = extra.key || \\"\\"; + let c2 = [], p2 = {key:\`\${key0}_2\`,on:{}}; + let vn2 = h('p', p2, c2); + c1.push(vn2); + let k3 = \`click__3__\${key0}__\`; + extra.handlers[k3] = extra.handlers[k3] || function (e) {if (!context.__owl__.isMounted){return}utils.getComponent(context)['update'](e);}; + p2.on['click'] = extra.handlers[k3]; + c2.push({text: \`lucas\`}); }" `; @@ -1036,13 +1123,13 @@ exports[`t-call handlers with arguments are properly bound through a t-call 1`] let scope = Object.create(context); let h = this.h; let c1 = extra.parentNode; - let key2 = extra.key || ''; - let c3 = [], p3 = {key:key2,on:{}}; - let vn3 = h('p', p3, c3); - c1.push(vn3); - let args4 = [scope['a']]; - p3.on['click'] = function (e) {if (!context.__owl__.isMounted){return}utils.getComponent(context)['update'](...args4, e);}; - c3.push({text: \`lucas\`}); + let key0 = extra.key || \\"\\"; + let c2 = [], p2 = {key:\`\${key0}_2\`,on:{}}; + let vn2 = h('p', p2, c2); + c1.push(vn2); + let args3 = [scope['a']]; + p2.on['click'] = function (e) {if (!context.__owl__.isMounted){return}utils.getComponent(context)['update'](...args3, e);}; + c2.push({text: \`lucas\`}); }" `; @@ -1056,31 +1143,31 @@ exports[`t-call parent is set within t-call 1`] = ` let scope = Object.create(context); let h = this.h; let c1 = extra.parentNode; - let key2 = extra.key || ''; + let key0 = extra.key || \\"\\"; // Component 'Child' - let k4 = \`__4__\` + key2; - let w3 = k4 in parent.__owl__.cmap ? parent.__owl__.children[parent.__owl__.cmap[k4]] : false; - let props3 = {}; - if (w3 && w3.__owl__.currentFiber && !w3.__owl__.vnode) { - w3.destroy(); - w3 = false; + let k3 = \`__3__\${key0}__\`; + 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 (w3) { - w3.__updateProps(props3, extra.fiber, undefined); - let pvnode = w3.__owl__.pvnode; + if (w2) { + w2.__updateProps(props2, extra.fiber, undefined); + let pvnode = w2.__owl__.pvnode; c1.push(pvnode); } else { - let componentKey3 = \`Child\`; - let W3 = context.constructor.components[componentKey3] || QWeb.components[componentKey3]|| scope['Child']; - if (!W3) {throw new Error('Cannot find the definition of component \\"' + componentKey3 + '\\"')} - w3 = new W3(parent, props3); - parent.__owl__.cmap[k4] = w3.__owl__.id; - let fiber = w3.__prepare(extra.fiber, undefined, () => { const vnode = fiber.vnode; pvnode.sel = vnode.sel; }); - let pvnode = h('dummy', {key: k4, hook: {remove() {},destroy(vn) {w3.destroy();}}}); + let componentKey2 = \`Child\`; + let W2 = context.constructor.components[componentKey2] || QWeb.components[componentKey2]|| scope['Child']; + if (!W2) {throw new Error('Cannot find the definition of component \\"' + componentKey2 + '\\"')} + w2 = new W2(parent, props2); + parent.__owl__.cmap[k3] = w2.__owl__.id; + let fiber = w2.__prepare(extra.fiber, undefined, () => { const vnode = fiber.vnode; pvnode.sel = vnode.sel; }); + let pvnode = h('dummy', {key: k3, hook: {remove() {},destroy(vn) {w2.destroy();}}}); c1.push(pvnode); - w3.__owl__.pvnode = pvnode; + w2.__owl__.pvnode = pvnode; } - w3.__owl__.parentLastFiberId = extra.fiber.id; + w2.__owl__.parentLastFiberId = extra.fiber.id; }" `; @@ -1094,31 +1181,31 @@ exports[`t-call parent is set within t-call with no parentNode 1`] = ` let scope = Object.create(context); let h = this.h; let c1 = extra.parentNode; - let key2 = extra.key || ''; + let key0 = extra.key || \\"\\"; // Component 'Child' - let k4 = \`__4__\` + key2; - let w3 = k4 in parent.__owl__.cmap ? parent.__owl__.children[parent.__owl__.cmap[k4]] : false; - let props3 = {}; - if (w3 && w3.__owl__.currentFiber && !w3.__owl__.vnode) { - w3.destroy(); - w3 = false; + let k3 = \`__3__\${key0}__\`; + 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 (w3) { - w3.__updateProps(props3, extra.fiber, undefined); - let pvnode = w3.__owl__.pvnode; + if (w2) { + w2.__updateProps(props2, extra.fiber, undefined); + let pvnode = w2.__owl__.pvnode; c1.push(pvnode); } else { - let componentKey3 = \`Child\`; - let W3 = context.constructor.components[componentKey3] || QWeb.components[componentKey3]|| scope['Child']; - if (!W3) {throw new Error('Cannot find the definition of component \\"' + componentKey3 + '\\"')} - w3 = new W3(parent, props3); - parent.__owl__.cmap[k4] = w3.__owl__.id; - let fiber = w3.__prepare(extra.fiber, undefined, () => { const vnode = fiber.vnode; pvnode.sel = vnode.sel; }); - let pvnode = h('dummy', {key: k4, hook: {remove() {},destroy(vn) {w3.destroy();}}}); + let componentKey2 = \`Child\`; + let W2 = context.constructor.components[componentKey2] || QWeb.components[componentKey2]|| scope['Child']; + if (!W2) {throw new Error('Cannot find the definition of component \\"' + componentKey2 + '\\"')} + w2 = new W2(parent, props2); + parent.__owl__.cmap[k3] = w2.__owl__.id; + let fiber = w2.__prepare(extra.fiber, undefined, () => { const vnode = fiber.vnode; pvnode.sel = vnode.sel; }); + let pvnode = h('dummy', {key: k3, hook: {remove() {},destroy(vn) {w2.destroy();}}}); c1.push(pvnode); - w3.__owl__.pvnode = pvnode; + w2.__owl__.pvnode = pvnode; } - w3.__owl__.parentLastFiberId = extra.fiber.id; + w2.__owl__.parentLastFiberId = extra.fiber.id; }" `; @@ -1224,16 +1311,16 @@ exports[`t-model directive in a t-foreach 1`] = ` scope.thing_index = i1 scope.thing = _3[i1] scope.thing_value = _4[i1] - const nodeKey6 = scope['thing'].id; - let _7 = 'checkbox'; - let c8 = [], p8 = {key:nodeKey6,attrs:{type: _7},on:{}}; - let vn8 = h('input', p8, c8); - c1.push(vn8); - let expr8 = scope['thing']; - let k9 = \`__9__\` + nodeKey6; - p8.props = {checked: expr8.f}; - extra.handlers[k9] = extra.handlers[k9] || ((ev) => {expr8.f = ev.target.checked}); - p8.on['input'] = extra.handlers[k9]; + let key1 = scope['thing'].id; + let _6 = 'checkbox'; + let c7 = [], p7 = {key:\`\${key1}_7\`,attrs:{type: _6},on:{}}; + let vn7 = h('input', p7, c7); + c1.push(vn7); + let expr7 = scope['thing']; + let k8 = \`__8__\${key1}__\`; + p7.props = {checked: expr7.f}; + extra.handlers[k8] = extra.handlers[k8] || ((ev) => {expr7.f = ev.target.checked}); + p7.on['input'] = extra.handlers[k8]; } scope = _origScope5; return vn1; @@ -1382,6 +1469,36 @@ exports[`t-model directive on an input, type=checkbox 1`] = ` }" `; +exports[`t-model directive two inputs in a div with a t-key 1`] = ` +"function anonymous(context, extra +) { + // Template name: \\"__template__1\\" + let scope = Object.create(context); + let result; + let h = this.h; + { + let key0 = 'key'; + let c1 = [], p1 = {key:\`\${key0}_1\`}; + let vn1 = h('div', p1, c1); + result = vn1; + result = vn1; + if (scope['state'].flag) { + let _3 = {'a':true}; + let c4 = [], p4 = {key:\`\${key0}_4\`,class:_3}; + let vn4 = h('input', p4, c4); + c1.push(vn4); + } + if (!scope['state'].flag) { + let _6 = {'b':true}; + let c7 = [], p7 = {key:\`\${key0}_7\`,class:_6}; + let vn7 = h('input', p7, c7); + c1.push(vn7); + } + } + 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 index e07196d2..fe1edc2c 100644 --- a/tests/component/__snapshots__/slots.test.ts.snap +++ b/tests/component/__snapshots__/slots.test.ts.snap @@ -229,14 +229,14 @@ exports[`t-slot directive slots are rendered with proper context, part 2 1`] = ` // Template name: \\"Link\\" let scope = Object.create(context); let h = this.h; - let _12 = scope['props'].to; - let c13 = [], p13 = {key:13,attrs:{href: _12}}; - let 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})); + let _11 = scope['props'].to; + let c12 = [], p12 = {key:12,attrs:{href: _11}}; + let vn12 = h('a', p12, c12); + const slot13 = this.constructor.slots[context.__owl__.slotId + '_' + 'default']; + if (slot13) { + slot13.call(this, context.__owl__.scope, Object.assign({}, extra, {parentNode: c12, parent: extra.parent || context})); } - return vn13; + return vn12; }" `; @@ -270,35 +270,35 @@ exports[`t-slot directive slots are rendered with proper context, part 2 2`] = ` scope.user_index = i1 scope.user = _4[i1] scope.user_value = _5[i1] - const nodeKey7 = scope['user'].id; - let c8 = [], p8 = {key:nodeKey7}; - let vn8 = h('li', p8, c8); - c2.push(vn8); + let key1 = scope['user'].id; + let c7 = [], p7 = {key:\`\${key1}_7\`}; + let vn7 = h('li', p7, c7); + c2.push(vn7); // Component 'Link' - let k10 = \`__10__\` + 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; + let k9 = \`__9__\${key1}__\`; + let w8 = k9 in parent.__owl__.cmap ? parent.__owl__.children[parent.__owl__.cmap[k9]] : false; + let props8 = {to:'/user/'+scope['user'].id}; + if (w8 && w8.__owl__.currentFiber && !w8.__owl__.vnode) { + w8.destroy(); + w8 = false; } - if (w9) { - w9.__updateProps(props9, extra.fiber, Object.assign(Object.create(context), scope)); - let pvnode = w9.__owl__.pvnode; - c8.push(pvnode); + if (w8) { + w8.__updateProps(props8, extra.fiber, Object.assign(Object.create(context), scope)); + let pvnode = w8.__owl__.pvnode; + c7.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; + let componentKey8 = \`Link\`; + let W8 = context.constructor.components[componentKey8] || QWeb.components[componentKey8]|| scope['Link']; + if (!W8) {throw new Error('Cannot find the definition of component \\"' + componentKey8 + '\\"')} + w8 = new W8(parent, props8); + parent.__owl__.cmap[k9] = w8.__owl__.id; + w8.__owl__.slotId = 1; + let fiber = w8.__prepare(extra.fiber, Object.assign(Object.create(context), scope), () => { const vnode = fiber.vnode; pvnode.sel = vnode.sel; }); + let pvnode = h('dummy', {key: k9, hook: {remove() {},destroy(vn) {w8.destroy();}}}); + c7.push(pvnode); + w8.__owl__.pvnode = pvnode; } - w9.__owl__.parentLastFiberId = extra.fiber.id; + w8.__owl__.parentLastFiberId = extra.fiber.id; } scope = _origScope6; return vn1; @@ -311,11 +311,11 @@ exports[`t-slot directive slots are rendered with proper context, part 2 3`] = ` // Template name: \\"slot_default_template\\" let scope = Object.create(context); let h = this.h; - let c8 = extra.parentNode; - c8.push({text: \`User \`}); - let _11 = scope['user'].name; - if (_11 != null) { - c8.push({text: _11}); + let c7 = extra.parentNode; + c7.push({text: \`User \`}); + let _10 = scope['user'].name; + if (_10 != null) { + c7.push({text: _10}); } }" `; @@ -326,14 +326,14 @@ exports[`t-slot directive slots are rendered with proper context, part 3 1`] = ` // Template name: \\"Link\\" let scope = Object.create(context); let h = this.h; - let _11 = scope['props'].to; - let c12 = [], p12 = {key:12,attrs:{href: _11}}; - let vn12 = h('a', p12, c12); - const slot13 = this.constructor.slots[context.__owl__.slotId + '_' + 'default']; - if (slot13) { - slot13.call(this, context.__owl__.scope, Object.assign({}, extra, {parentNode: c12, parent: extra.parent || context})); + let _10 = scope['props'].to; + let c11 = [], p11 = {key:11,attrs:{href: _10}}; + let vn11 = h('a', p11, c11); + const slot12 = this.constructor.slots[context.__owl__.slotId + '_' + 'default']; + if (slot12) { + slot12.call(this, context.__owl__.scope, Object.assign({}, extra, {parentNode: c11, parent: extra.parent || context})); } - return vn12; + return vn11; }" `; @@ -367,36 +367,36 @@ exports[`t-slot directive slots are rendered with proper context, part 3 2`] = ` scope.user_index = i1 scope.user = _4[i1] scope.user_value = _5[i1] - const nodeKey7 = scope['user'].id; - let c8 = [], p8 = {key:nodeKey7}; - let vn8 = h('li', p8, c8); - c2.push(vn8); + let key1 = scope['user'].id; + let c7 = [], p7 = {key:\`\${key1}_7\`}; + let vn7 = h('li', p7, c7); + c2.push(vn7); scope.userdescr = 'User '+scope['user'].name; // Component 'Link' - let k10 = \`__10__\` + 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; + let k9 = \`__9__\${key1}__\`; + let w8 = k9 in parent.__owl__.cmap ? parent.__owl__.children[parent.__owl__.cmap[k9]] : false; + let props8 = {to:'/user/'+scope['user'].id}; + if (w8 && w8.__owl__.currentFiber && !w8.__owl__.vnode) { + w8.destroy(); + w8 = false; } - if (w9) { - w9.__updateProps(props9, extra.fiber, Object.assign(Object.create(context), scope)); - let pvnode = w9.__owl__.pvnode; - c8.push(pvnode); + if (w8) { + w8.__updateProps(props8, extra.fiber, Object.assign(Object.create(context), scope)); + let pvnode = w8.__owl__.pvnode; + c7.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; + let componentKey8 = \`Link\`; + let W8 = context.constructor.components[componentKey8] || QWeb.components[componentKey8]|| scope['Link']; + if (!W8) {throw new Error('Cannot find the definition of component \\"' + componentKey8 + '\\"')} + w8 = new W8(parent, props8); + parent.__owl__.cmap[k9] = w8.__owl__.id; + w8.__owl__.slotId = 1; + let fiber = w8.__prepare(extra.fiber, Object.assign(Object.create(context), scope), () => { const vnode = fiber.vnode; pvnode.sel = vnode.sel; }); + let pvnode = h('dummy', {key: k9, hook: {remove() {},destroy(vn) {w8.destroy();}}}); + c7.push(pvnode); + w8.__owl__.pvnode = pvnode; } - w9.__owl__.parentLastFiberId = extra.fiber.id; + w8.__owl__.parentLastFiberId = extra.fiber.id; } scope = _origScope6; return vn1; @@ -409,9 +409,9 @@ exports[`t-slot directive slots are rendered with proper context, part 3 3`] = ` // Template name: \\"slot_default_template\\" let scope = Object.create(context); let h = this.h; - let c8 = extra.parentNode; + let c7 = extra.parentNode; if (scope.userdescr != null) { - c8.push({text: scope.userdescr}); + c7.push({text: scope.userdescr}); } }" `; diff --git a/tests/component/component.test.ts b/tests/component/component.test.ts index fbf90693..b0edf283 100644 --- a/tests/component/component.test.ts +++ b/tests/component/component.test.ts @@ -322,6 +322,36 @@ describe("basic widget properties", () => { console.warn = warn; }); + test("reconciliation alg works for t-foreach in t-foreach, 2", async () => { + class Child extends Component { + static template = xml`
`; + } + + class Parent extends Component { + static template = xml` +
+

+

+ +

+

+
`; + static components = { Child }; + state = useState({ rows: [1, 2], cols: ["a", "b"] }); + } + + const widget = new Parent(); + await widget.mount(fixture); + expect(fixture.innerHTML).toBe( + "

1_a

1_b

2_a

2_b

" + ); + widget.state.rows = [2, 1]; + await nextTick(); + expect(fixture.innerHTML).toBe( + "

2_a

2_b

1_a

1_b

" + ); + }); + test("same t-keys in two different places", async () => { class Child extends Component { static template = xml``; @@ -339,6 +369,7 @@ describe("basic widget properties", () => { const widget = new Parent(); await widget.mount(fixture); expect(fixture.innerHTML).toBe("
1
2
"); + expect(env.qweb.templates[Parent.template].fn.toString()).toMatchSnapshot(); }); test("t-key on a component with t-if, and a sibling component", async () => { @@ -4418,6 +4449,28 @@ describe("t-model directive", () => { expect(comp.state[2].f).toBe(false); expect(env.qweb.templates[SomeComponent.template].fn.toString()).toMatchSnapshot(); }); + + test("two inputs in a div with a t-key", async () => { + class SomeComponent extends Component { + static template = xml` +
+ + +
+ `; + state = useState({ flag: true }); + } + const comp = new SomeComponent(); + await comp.mount(fixture); + expect(fixture.innerHTML).toBe('
'); + expect(env.qweb.templates[SomeComponent.template].fn.toString()).toMatchSnapshot(); + fixture.querySelector("input")!.value = "asdf"; + expect(fixture.querySelector("input")!.value).toBe("asdf"); + comp.state.flag = false; + await nextTick(); + expect(fixture.innerHTML).toBe('
'); + expect(fixture.querySelector("input")!.value).toBe(""); + }); }); describe("environment and plugins", () => { diff --git a/tests/qweb/__snapshots__/qweb.test.ts.snap b/tests/qweb/__snapshots__/qweb.test.ts.snap index 9a3a50c1..72f84359 100644 --- a/tests/qweb/__snapshots__/qweb.test.ts.snap +++ b/tests/qweb/__snapshots__/qweb.test.ts.snap @@ -428,6 +428,7 @@ exports[`foreach does not pollute the rendering context 1`] = ` scope.item_index = i1 scope.item = _3[i1] scope.item_value = _4[i1] + let key1 = i1; let _6 = scope['item']; if (_6 != null) { c1.push({text: _6}); @@ -462,13 +463,13 @@ exports[`foreach iterate on items (on a element node) 1`] = ` scope.item_index = i1 scope.item = _3[i1] scope.item_value = _4[i1] - const nodeKey6 = scope['item']; - let c7 = [], p7 = {key:nodeKey6}; - let vn7 = h('span', p7, c7); - c1.push(vn7); - let _8 = scope['item']; - if (_8 != null) { - c7.push({text: _8}); + let key1 = scope['item']; + let c6 = [], p6 = {key:\`\${key1}_6\`}; + let vn6 = h('span', p6, c6); + c1.push(vn6); + let _7 = scope['item']; + if (_7 != null) { + c6.push({text: _7}); } } scope = _origScope5; @@ -500,6 +501,7 @@ exports[`foreach iterate on items 1`] = ` scope.item_index = i1 scope.item = _3[i1] scope.item_value = _4[i1] + let key1 = i1; c1.push({text: \` [\`}); let _6 = scope['item_index']; if (_6 != null) { @@ -546,6 +548,7 @@ exports[`foreach iterate, dict param 1`] = ` scope.item_index = i1 scope.item = _3[i1] scope.item_value = _4[i1] + let key1 = i1; c1.push({text: \` [\`}); let _6 = scope['item_index']; if (_6 != null) { @@ -592,6 +595,7 @@ exports[`foreach iterate, position 1`] = ` scope.elem_index = i1 scope.elem = _3[i1] scope.elem_value = _4[i1] + let key1 = i1; c1.push({text: \` -\`}); if (scope['elem_first']) { c1.push({text: \` first\`}); @@ -635,6 +639,7 @@ exports[`foreach t-foreach in t-forach 1`] = ` scope.number_index = i1 scope.number = _3[i1] scope.number_value = _4[i1] + let key1 = i1; let _6 = scope['letters']; if (!_6) { throw new Error('QWeb error: Invalid loop expression')} let _7 = _8 = _6; @@ -651,6 +656,7 @@ exports[`foreach t-foreach in t-forach 1`] = ` scope.letter_index = i2 scope.letter = _7[i2] scope.letter_value = _8[i2] + let key2 = i2; c1.push({text: \` [\`}); let _10 = scope['number']; if (_10 != null) { @@ -693,7 +699,8 @@ exports[`foreach warn if no key in some case 1`] = ` scope.item_index = i1 scope.item = _3[i1] scope.item_value = _4[i1] - let c6 = [], p6 = {key:6}; + let key1 = i1; + let c6 = [], p6 = {key:\`\${key1}_6\`}; let vn6 = h('span', p6, c6); c1.push(vn6); let _7 = scope['item']; @@ -757,7 +764,8 @@ exports[`misc global 1`] = ` scope.value_index = i1 scope.value = _3[i1] scope.value_value = _4[i1] - let c6 = [], p6 = {key:6}; + let key1 = i1; + let c6 = [], p6 = {key:\`\${key1}_6\`}; let vn6 = h('span', p6, c6); c1.push(vn6); let _7 = scope['value']; @@ -765,32 +773,32 @@ exports[`misc global 1`] = ` c6.push({text: _7}); } { - let _origScope11 = scope; + let _origScope10 = scope; scope = Object.assign(Object.create(context), scope); { let c__0 = []; { - let _origScope15 = scope; + let _origScope13 = scope; scope = Object.assign(Object.create(context), scope); { let c__0 = []; scope.foo = 'aaa'; scope[utils.zero] = c__0; } - let k16 = \`__16__\${i1}__\`; - this.subTemplates['_callee-uses-foo'].call(this, scope, Object.assign({}, extra, {parentNode: c__0, parent: utils.getComponent(context), key: k16})); - scope = _origScope15; + let k14 = \`__14__\${key1}__\`; + this.subTemplates['_callee-uses-foo'].call(this, scope, Object.assign({}, extra, {parentNode: c__0, parent: utils.getComponent(context), key: k14})); + scope = _origScope13; } - let k17 = \`__17__\${i1}__\`; - this.subTemplates['_callee-uses-foo'].call(this, Object.assign(Object.create(context), scope), Object.assign({}, extra, {parentNode: c__0, parent: utils.getComponent(context), key: k17})); + let k15 = \`__15__\${key1}__\`; + this.subTemplates['_callee-uses-foo'].call(this, Object.assign(Object.create(context), scope), Object.assign({}, extra, {parentNode: c__0, parent: utils.getComponent(context), key: k15})); scope.foo = 'bbb'; - let k18 = \`__18__\${i1}__\`; - this.subTemplates['_callee-uses-foo'].call(this, Object.assign(Object.create(context), scope), Object.assign({}, extra, {parentNode: c__0, parent: utils.getComponent(context), key: k18})); + let k16 = \`__16__\${key1}__\`; + this.subTemplates['_callee-uses-foo'].call(this, Object.assign(Object.create(context), scope), Object.assign({}, extra, {parentNode: c__0, parent: utils.getComponent(context), key: k16})); scope[utils.zero] = c__0; } - let k19 = \`__19__\${i1}__\`; - this.subTemplates['_callee-asc'].call(this, scope, Object.assign({}, extra, {parentNode: c1, parent: utils.getComponent(context), key: k19})); - scope = _origScope11; + let k17 = \`__17__\${key1}__\`; + this.subTemplates['_callee-asc'].call(this, scope, Object.assign({}, extra, {parentNode: c1, parent: utils.getComponent(context), key: k17})); + scope = _origScope10; } } scope = _origScope5; @@ -1044,11 +1052,11 @@ exports[`t-call (template calling basic caller 2`] = ` // Template name: \\"_basic-callee\\" let h = this.h; let c1 = extra.parentNode; - let key2 = extra.key || ''; - let c3 = [], p3 = {key:key2}; - let vn3 = h('span', p3, c3); - c1.push(vn3); - c3.push({text: \`ok\`}); + let key0 = extra.key || \\"\\"; + let c2 = [], p2 = {key:\`\${key0}_2\`}; + let vn2 = h('span', p2, c2); + c1.push(vn2); + c2.push({text: \`ok\`}); }" `; @@ -1073,11 +1081,11 @@ exports[`t-call (template calling basic caller, no parent node 2`] = ` // Template name: \\"_basic-callee\\" let h = this.h; let c1 = extra.parentNode; - let key2 = extra.key || ''; - let c3 = [], p3 = {key:key2}; - let vn3 = h('div', p3, c3); - c1.push(vn3); - c3.push({text: \`ok\`}); + let key0 = extra.key || \\"\\"; + let c2 = [], p2 = {key:\`\${key0}_2\`}; + let vn2 = h('div', p2, c2); + c1.push(vn2); + c2.push({text: \`ok\`}); }" `; @@ -1091,23 +1099,23 @@ exports[`t-call (template calling call with several sub nodes on same line 1`] = let c1 = [], p1 = {key:1}; let vn1 = h('div', p1, c1); { - let _origScope4 = scope; + let _origScope3 = scope; scope = Object.assign(Object.create(context), scope); { let c__0 = []; + let c4 = [], p4 = {key:4}; + let vn4 = h('span', p4, c4); + c__0.push(vn4); + c4.push({text: \`hey\`}); + c__0.push({text: \` \`}); let c5 = [], p5 = {key:5}; let vn5 = h('span', p5, c5); c__0.push(vn5); - c5.push({text: \`hey\`}); - c__0.push({text: \` \`}); - let c6 = [], p6 = {key:6}; - let vn6 = h('span', p6, c6); - c__0.push(vn6); - c6.push({text: \`yay\`}); + c5.push({text: \`yay\`}); scope[utils.zero] = c__0; } this.subTemplates['SubTemplate'].call(this, scope, Object.assign({}, extra, {parentNode: c1, parent: utils.getComponent(context)})); - scope = _origScope4; + scope = _origScope3; } return vn1; }" @@ -1121,11 +1129,11 @@ exports[`t-call (template calling call with several sub nodes on same line 2`] = let scope = Object.create(context); let h = this.h; let c1 = extra.parentNode; - let key2 = extra.key || ''; - let c3 = [], p3 = {key:key2}; - let vn3 = h('div', p3, c3); - c1.push(vn3); - c3.push(...scope[utils.zero]); + let key0 = extra.key || \\"\\"; + let c2 = [], p2 = {key:\`\${key0}_2\`}; + let vn2 = h('div', p2, c2); + c1.push(vn2); + c2.push(...scope[utils.zero]); }" `; @@ -1139,23 +1147,23 @@ exports[`t-call (template calling cascading t-call t-raw='0' 1`] = ` let c1 = [], p1 = {key:1}; let vn1 = h('div', p1, c1); { - let _origScope13 = scope; + let _origScope12 = scope; scope = Object.assign(Object.create(context), scope); { let c__0 = []; + let c13 = [], p13 = {key:13}; + let vn13 = h('span', p13, c13); + c__0.push(vn13); + c13.push({text: \`hey\`}); + c__0.push({text: \` \`}); let c14 = [], p14 = {key:14}; let vn14 = h('span', p14, c14); c__0.push(vn14); - c14.push({text: \`hey\`}); - c__0.push({text: \` \`}); - let c15 = [], p15 = {key:15}; - let vn15 = h('span', p15, c15); - c__0.push(vn15); - c15.push({text: \`yay\`}); + c14.push({text: \`yay\`}); scope[utils.zero] = c__0; } this.subTemplates['SubTemplate'].call(this, scope, Object.assign({}, extra, {parentNode: c1, parent: utils.getComponent(context)})); - scope = _origScope13; + scope = _origScope12; } return vn1; }" @@ -1204,16 +1212,17 @@ exports[`t-call (template calling recursive template, part 1 2`] = ` let scope = Object.create(context); let h = this.h; let c1 = extra.parentNode; - let key3 = extra.key || ''; - let c4 = [], p4 = {key:key3}; - let vn4 = h('div', p4, c4); - c1.push(vn4); - let c5 = [], p5 = {key:key3}; - let vn5 = h('span', p5, c5); - c4.push(vn5); - c5.push({text: \`hey\`}); + let key0 = extra.key || \\"\\"; + let c3 = [], p3 = {key:\`\${key0}_3\`}; + let vn3 = h('div', p3, c3); + c1.push(vn3); + let c4 = [], p4 = {key:\`\${key0}_4\`}; + let vn4 = h('span', p4, c4); + c3.push(vn4); + c4.push({text: \`hey\`}); if (false) { - this.subTemplates['recursive'].call(this, Object.assign(Object.create(context), scope), Object.assign({}, extra, {parentNode: c4, parent: utils.getComponent(context)})); + let k5 = \`__5__\${key0}__\`; + this.subTemplates['recursive'].call(this, Object.assign(Object.create(context), scope), Object.assign({}, extra, {parentNode: c3, parent: utils.getComponent(context), key: k5})); } }" `; @@ -1228,7 +1237,7 @@ exports[`t-call (template calling recursive template, part 2 1`] = ` let c1 = [], p1 = {key:1}; let vn1 = h('div', p1, c1); { - let _origScope12 = scope; + let _origScope11 = scope; scope = Object.assign(Object.create(context), scope); { let c__0 = []; @@ -1236,7 +1245,7 @@ exports[`t-call (template calling recursive template, part 2 1`] = ` scope[utils.zero] = c__0; } this.subTemplates['nodeTemplate'].call(this, scope, Object.assign({}, extra, {parentNode: c1, parent: utils.getComponent(context)})); - scope = _origScope12; + scope = _origScope11; } return vn1; }" @@ -1250,47 +1259,48 @@ exports[`t-call (template calling recursive template, part 2 2`] = ` let scope = Object.create(context); let h = this.h; let c1 = extra.parentNode; - let key2 = extra.key || ''; - let c3 = [], p3 = {key:key2}; - let vn3 = h('div', p3, c3); - c1.push(vn3); - let c4 = [], p4 = {key:key2}; - let vn4 = h('p', p4, c4); - c3.push(vn4); - let _5 = scope['node'].val; - if (_5 != null) { - c4.push({text: _5}); + let key0 = extra.key || \\"\\"; + let c2 = [], p2 = {key:\`\${key0}_2\`}; + let vn2 = h('div', p2, c2); + c1.push(vn2); + let c3 = [], p3 = {key:\`\${key0}_3\`}; + let vn3 = h('p', p3, c3); + c2.push(vn3); + let _4 = scope['node'].val; + if (_4 != null) { + c3.push({text: _4}); } - let _6 = scope['node'].children||[]; - if (!_6) { throw new Error('QWeb error: Invalid loop expression')} - let _7 = _8 = _6; - if (!(_6 instanceof Array)) { - _7 = Object.keys(_6); - _8 = Object.values(_6); + let _5 = scope['node'].children||[]; + if (!_5) { throw new Error('QWeb error: Invalid loop expression')} + let _6 = _7 = _5; + if (!(_5 instanceof Array)) { + _6 = Object.keys(_5); + _7 = Object.values(_5); } - let _length7 = _7.length; - let _origScope9 = scope; + let _length6 = _6.length; + let _origScope8 = scope; scope = Object.assign(Object.create(context), scope); - for (let i1 = 0; i1 < _length7; i1++) { + for (let i1 = 0; i1 < _length6; i1++) { scope.subtree_first = i1 === 0 - scope.subtree_last = i1 === _length7 - 1 + scope.subtree_last = i1 === _length6 - 1 scope.subtree_index = i1 - scope.subtree = _7[i1] - scope.subtree_value = _8[i1] + scope.subtree = _6[i1] + scope.subtree_value = _7[i1] + let key1 = i1; { - let _origScope10 = scope; + let _origScope9 = scope; scope = Object.assign(Object.create(context), scope); { let c__0 = []; scope.node = scope['subtree']; scope[utils.zero] = c__0; } - let k11 = \`__11__\` + key2; - this.subTemplates['nodeTemplate'].call(this, scope, Object.assign({}, extra, {parentNode: c3, parent: utils.getComponent(context), key: k11})); - scope = _origScope10; + let k10 = \`__10__\${key0}__\${key1}__\`; + this.subTemplates['nodeTemplate'].call(this, scope, Object.assign({}, extra, {parentNode: c2, parent: utils.getComponent(context), key: k10})); + scope = _origScope9; } } - scope = _origScope9; + scope = _origScope8; }" `; @@ -1304,7 +1314,7 @@ exports[`t-call (template calling recursive template, part 3 1`] = ` let c1 = [], p1 = {key:1}; let vn1 = h('div', p1, c1); { - let _origScope12 = scope; + let _origScope11 = scope; scope = Object.assign(Object.create(context), scope); { let c__0 = []; @@ -1312,7 +1322,7 @@ exports[`t-call (template calling recursive template, part 3 1`] = ` scope[utils.zero] = c__0; } this.subTemplates['nodeTemplate'].call(this, scope, Object.assign({}, extra, {parentNode: c1, parent: utils.getComponent(context)})); - scope = _origScope12; + scope = _origScope11; } return vn1; }" @@ -1326,47 +1336,48 @@ exports[`t-call (template calling recursive template, part 3 2`] = ` let scope = Object.create(context); let h = this.h; let c1 = extra.parentNode; - let key2 = extra.key || ''; - let c3 = [], p3 = {key:key2}; - let vn3 = h('div', p3, c3); - c1.push(vn3); - let c4 = [], p4 = {key:key2}; - let vn4 = h('p', p4, c4); - c3.push(vn4); - let _5 = scope['node'].val; - if (_5 != null) { - c4.push({text: _5}); + let key0 = extra.key || \\"\\"; + let c2 = [], p2 = {key:\`\${key0}_2\`}; + let vn2 = h('div', p2, c2); + c1.push(vn2); + let c3 = [], p3 = {key:\`\${key0}_3\`}; + let vn3 = h('p', p3, c3); + c2.push(vn3); + let _4 = scope['node'].val; + if (_4 != null) { + c3.push({text: _4}); } - let _6 = scope['node'].children||[]; - if (!_6) { throw new Error('QWeb error: Invalid loop expression')} - let _7 = _8 = _6; - if (!(_6 instanceof Array)) { - _7 = Object.keys(_6); - _8 = Object.values(_6); + let _5 = scope['node'].children||[]; + if (!_5) { throw new Error('QWeb error: Invalid loop expression')} + let _6 = _7 = _5; + if (!(_5 instanceof Array)) { + _6 = Object.keys(_5); + _7 = Object.values(_5); } - let _length7 = _7.length; - let _origScope9 = scope; + let _length6 = _6.length; + let _origScope8 = scope; scope = Object.assign(Object.create(context), scope); - for (let i1 = 0; i1 < _length7; i1++) { + for (let i1 = 0; i1 < _length6; i1++) { scope.subtree_first = i1 === 0 - scope.subtree_last = i1 === _length7 - 1 + scope.subtree_last = i1 === _length6 - 1 scope.subtree_index = i1 - scope.subtree = _7[i1] - scope.subtree_value = _8[i1] + scope.subtree = _6[i1] + scope.subtree_value = _7[i1] + let key1 = i1; { - let _origScope10 = scope; + let _origScope9 = scope; scope = Object.assign(Object.create(context), scope); { let c__0 = []; scope.node = scope['subtree']; scope[utils.zero] = c__0; } - let k11 = \`__11__\` + key2; - this.subTemplates['nodeTemplate'].call(this, scope, Object.assign({}, extra, {parentNode: c3, parent: utils.getComponent(context), key: k11})); - scope = _origScope10; + let k10 = \`__10__\${key0}__\${key1}__\`; + this.subTemplates['nodeTemplate'].call(this, scope, Object.assign({}, extra, {parentNode: c2, parent: utils.getComponent(context), key: k10})); + scope = _origScope9; } } - scope = _origScope9; + scope = _origScope8; }" `; @@ -1380,7 +1391,7 @@ exports[`t-call (template calling scoped parameters 1`] = ` let c1 = [], p1 = {key:1}; let vn1 = h('div', p1, c1); { - let _origScope3 = scope; + let _origScope2 = scope; scope = Object.assign(Object.create(context), scope); { let c__0 = []; @@ -1388,7 +1399,7 @@ exports[`t-call (template calling scoped parameters 1`] = ` scope[utils.zero] = c__0; } this.subTemplates['_basic-callee'].call(this, scope, Object.assign({}, extra, {parentNode: c1, parent: utils.getComponent(context)})); - scope = _origScope3; + scope = _origScope2; } if (scope.foo != null) { c1.push({text: scope.foo}); @@ -1419,11 +1430,11 @@ exports[`t-call (template calling t-call with t-if 2`] = ` // Template name: \\"sub\\" let h = this.h; let c1 = extra.parentNode; - let key2 = extra.key || ''; - let c3 = [], p3 = {key:key2}; - let vn3 = h('span', p3, c3); - c1.push(vn3); - c3.push({text: \`ok\`}); + let key0 = extra.key || \\"\\"; + let c2 = [], p2 = {key:\`\${key0}_2\`}; + let vn2 = h('span', p2, c2); + c1.push(vn2); + c2.push({text: \`ok\`}); }" `; @@ -1452,18 +1463,19 @@ exports[`t-call (template calling t-call with t-set inside and outside 1`] = ` scope.v_index = i1 scope.v = _3[i1] scope.v_value = _4[i1] + let key1 = i1; scope.val = scope['v'].val; { - let _origScope9 = scope; + let _origScope8 = scope; scope = Object.assign(Object.create(context), scope); { let c__0 = []; scope.val3 = scope.val*3; scope[utils.zero] = c__0; } - let k10 = \`__10__\${i1}__\`; - this.subTemplates['sub'].call(this, scope, Object.assign({}, extra, {parentNode: c1, parent: utils.getComponent(context), key: k10})); - scope = _origScope9; + let k9 = \`__9__\${key1}__\`; + this.subTemplates['sub'].call(this, scope, Object.assign({}, extra, {parentNode: c1, parent: utils.getComponent(context), key: k9})); + scope = _origScope8; } } scope = _origScope5; @@ -1501,7 +1513,7 @@ exports[`t-call (template calling t-call, conditional and t-set in t-call body 1 } else if (scope.v1==='elif') { { - let _origScope7 = scope; + let _origScope5 = scope; scope = Object.assign(Object.create(context), scope); { let c__0 = []; @@ -1509,7 +1521,7 @@ exports[`t-call (template calling t-call, conditional and t-set in t-call body 1 scope[utils.zero] = c__0; } this.subTemplates['callee2'].call(this, scope, Object.assign({}, extra, {parentNode: c1, parent: utils.getComponent(context)})); - scope = _origScope7; + scope = _origScope5; } } return vn1; @@ -1539,7 +1551,7 @@ exports[`t-call (template calling with unused body 1`] = ` let result; let h = this.h; { - let _origScope4 = scope; + let _origScope3 = scope; scope = Object.assign(Object.create(context), scope); { let c__0 = []; @@ -1549,7 +1561,7 @@ exports[`t-call (template calling with unused body 1`] = ` result = [] this.subTemplates['_basic-callee'].call(this, scope, Object.assign({}, extra, {parentNode: result, parent: utils.getComponent(context)})); result = result[0] - scope = _origScope4; + scope = _origScope3; } return result; }" @@ -1564,7 +1576,7 @@ exports[`t-call (template calling with unused setbody 1`] = ` let result; let h = this.h; { - let _origScope4 = scope; + let _origScope3 = scope; scope = Object.assign(Object.create(context), scope); { let c__0 = []; @@ -1574,7 +1586,7 @@ exports[`t-call (template calling with unused setbody 1`] = ` result = [] this.subTemplates['_basic-callee'].call(this, scope, Object.assign({}, extra, {parentNode: result, parent: utils.getComponent(context)})); result = result[0] - scope = _origScope4; + scope = _origScope3; } return result; }" @@ -1589,7 +1601,7 @@ exports[`t-call (template calling with used body 1`] = ` let result; let h = this.h; { - let _origScope4 = scope; + let _origScope3 = scope; scope = Object.assign(Object.create(context), scope); { let c__0 = []; @@ -1599,7 +1611,7 @@ exports[`t-call (template calling with used body 1`] = ` result = [] this.subTemplates['_callee-printsbody'].call(this, scope, Object.assign({}, extra, {parentNode: result, parent: utils.getComponent(context)})); result = result[0] - scope = _origScope4; + scope = _origScope3; } return result; }" @@ -1615,7 +1627,7 @@ exports[`t-call (template calling with used set body 1`] = ` let c1 = [], p1 = {key:1}; let vn1 = h('span', p1, c1); { - let _origScope4 = scope; + let _origScope3 = scope; scope = Object.assign(Object.create(context), scope); { let c__0 = []; @@ -1623,7 +1635,7 @@ exports[`t-call (template calling with used set body 1`] = ` scope[utils.zero] = c__0; } this.subTemplates['_callee-uses-foo'].call(this, scope, Object.assign({}, extra, {parentNode: c1, parent: utils.getComponent(context)})); - scope = _origScope4; + scope = _origScope3; } return vn1; }" @@ -1812,18 +1824,18 @@ exports[`t-esc t-esc=0 is escaped 1`] = ` let c1 = [], p1 = {key:1}; let vn1 = h('div', p1, c1); { - let _origScope4 = scope; + let _origScope3 = scope; scope = Object.assign(Object.create(context), scope); { let c__0 = []; - let c5 = [], p5 = {key:5}; - let vn5 = h('p', p5, c5); - c__0.push(vn5); - c5.push({text: \`escaped\`}); + let c4 = [], p4 = {key:4}; + let vn4 = h('p', p4, c4); + c__0.push(vn4); + c4.push({text: \`escaped\`}); scope[utils.zero] = c__0; } this.subTemplates['test'].call(this, scope, Object.assign({}, extra, {parentNode: c1, parent: utils.getComponent(context)})); - scope = _origScope4; + scope = _origScope3; } return vn1; }" @@ -2110,15 +2122,20 @@ exports[`t-key can use t-key directive on a node 1`] = ` ) { // Template name: \\"test\\" let scope = Object.create(context); + let result; let h = this.h; - const nodeKey1 = scope['beer'].id; - let c2 = [], p2 = {key:nodeKey1}; - let vn2 = h('div', p2, c2); - let _3 = scope['beer'].name; - if (_3 != null) { - c2.push({text: _3}); + { + let key0 = scope['beer'].id; + let c1 = [], p1 = {key:\`\${key0}_1\`}; + let vn1 = h('div', p1, c1); + result = vn1; + result = vn1; + let _2 = scope['beer'].name; + if (_2 != null) { + c1.push({text: _2}); + } } - return vn2; + return result; }" `; @@ -2146,13 +2163,13 @@ exports[`t-key t-key directive in a list 1`] = ` scope.beer_index = i1 scope.beer = _3[i1] scope.beer_value = _4[i1] - const nodeKey6 = scope['beer'].id; - let c7 = [], p7 = {key:nodeKey6}; - let vn7 = h('li', p7, c7); - c1.push(vn7); - let _8 = scope['beer'].name; - if (_8 != null) { - c7.push({text: _8}); + let key1 = scope['beer'].id; + let c6 = [], p6 = {key:\`\${key1}_6\`}; + let vn6 = h('li', p6, c6); + c1.push(vn6); + let _7 = scope['beer'].name; + if (_7 != null) { + c6.push({text: _7}); } } scope = _origScope5; @@ -2250,16 +2267,16 @@ exports[`t-on can bind handlers with loop variable as argument 1`] = ` scope.action_index = i1 scope.action = _3[i1] scope.action_value = _4[i1] - const nodeKey6 = scope['action_index']; - let c7 = [], p7 = {key:nodeKey6}; - let vn7 = h('li', p7, c7); - c1.push(vn7); - let c8 = [], p8 = {key:nodeKey6,on:{}}; - let vn8 = h('a', p8, c8); - c7.push(vn8); - let args9 = [scope['action']]; - p8.on['click'] = function (e) {if (!context.__owl__.isMounted){return}utils.getComponent(context)['activate'](...args9, e);}; - c8.push({text: \`link\`}); + let key1 = scope['action_index']; + let c6 = [], p6 = {key:\`\${key1}_6\`}; + let vn6 = h('li', p6, c6); + c1.push(vn6); + let c7 = [], p7 = {key:\`\${key1}_7\`,on:{}}; + let vn7 = h('a', p7, c7); + c6.push(vn7); + let args8 = [scope['action']]; + p7.on['click'] = function (e) {if (!context.__owl__.isMounted){return}utils.getComponent(context)['activate'](...args8, e);}; + c7.push({text: \`link\`}); } scope = _origScope5; return vn1; @@ -2507,17 +2524,20 @@ exports[`t-on t-on with prevent modifier in t-foreach 1`] = ` scope.project_index = i1 scope.project = _3[i1] scope.project_value = _4[i1] - const nodeKey6 = scope['project']; - let _7 = '#'; - let c8 = [], p8 = {key:nodeKey6,attrs:{href: _7},on:{}}; - let vn8 = h('a', p8, c8); - c1.push(vn8); - let args9 = [scope['project'].id]; - p8.on['click'] = function (e) {if (!context.__owl__.isMounted){return}e.preventDefault();utils.getComponent(context)['onEdit'](...args9, e);}; - c8.push({text: \` Edit \`}); - let _10 = scope['project'].name; - if (_10 != null) { - c8.push({text: _10}); + let key1 = i1; + { + let key1 = scope['project']; + let _6 = '#'; + let c7 = [], p7 = {key:\`\${key1}_7\`,attrs:{href: _6},on:{}}; + let vn7 = h('a', p7, c7); + c1.push(vn7); + let args8 = [scope['project'].id]; + p7.on['click'] = function (e) {if (!context.__owl__.isMounted){return}e.preventDefault();utils.getComponent(context)['onEdit'](...args8, e);}; + c7.push({text: \` Edit \`}); + let _9 = scope['project'].name; + if (_9 != null) { + c7.push({text: _9}); + } } } scope = _origScope5; @@ -2750,22 +2770,25 @@ exports[`t-ref refs in a loop 1`] = ` scope.item_index = i1 scope.item = _3[i1] scope.item_value = _4[i1] - const nodeKey6 = scope['item']; - let c7 = [], p7 = {key:nodeKey6}; - let vn7 = h('div', p7, c7); - c1.push(vn7); - const ref8 = (scope['item']); - p7.hook = { - create: (_, n) => { - context.__owl__.refs[ref8] = n.elm; - }, - destroy: () => { - delete context.__owl__.refs[ref8]; - }, - }; - let _9 = scope['item']; - if (_9 != null) { - c7.push({text: _9}); + let key1 = i1; + { + let key1 = scope['item']; + let c6 = [], p6 = {key:\`\${key1}_6\`}; + let vn6 = h('div', p6, c6); + c1.push(vn6); + const ref7 = (scope['item']); + p6.hook = { + create: (_, n) => { + context.__owl__.refs[ref7] = n.elm; + }, + destroy: () => { + delete context.__owl__.refs[ref7]; + }, + }; + let _8 = scope['item']; + if (_8 != null) { + c6.push({text: _8}); + } } } scope = _origScope5; @@ -2988,16 +3011,16 @@ exports[`t-set t-set should reuse variable if possible 1`] = ` scope.elem_index = i1 scope.elem = _3[i1] scope.elem_value = _4[i1] - const nodeKey6 = scope['elem_index']; - let c7 = [], p7 = {key:nodeKey6}; - let vn7 = h('div', p7, c7); - c1.push(vn7); - let c8 = [], p8 = {key:nodeKey6}; - let vn8 = h('span', p8, c8); - c7.push(vn8); - c8.push({text: \`v\`}); + let key1 = scope['elem_index']; + let c6 = [], p6 = {key:\`\${key1}_6\`}; + let vn6 = h('div', p6, c6); + c1.push(vn6); + let c7 = [], p7 = {key:\`\${key1}_7\`}; + let vn7 = h('span', p7, c7); + c6.push(vn7); + c7.push({text: \`v\`}); if (scope.v != null) { - c8.push({text: scope.v}); + c7.push({text: scope.v}); } scope.v = scope['elem']; } diff --git a/tests/router/__snapshots__/route_component.test.ts.snap b/tests/router/__snapshots__/route_component.test.ts.snap index 6d53833c..b4a33c9a 100644 --- a/tests/router/__snapshots__/route_component.test.ts.snap +++ b/tests/router/__snapshots__/route_component.test.ts.snap @@ -11,33 +11,35 @@ exports[`RouteComponent can render simple cases 1`] = ` let result; let h = this.h; if (scope['routeComponent']) { - const nodeKey4 = scope['env'].router.currentRouteName; - // Component 'routeComponent' - let k6 = \`__6__\` + nodeKey4; - let w5 = k6 in parent.__owl__.cmap ? parent.__owl__.children[parent.__owl__.cmap[k6]] : false; - let vn7 = {}; - result = vn7; - let props5 = Object.assign({}, scope['env'].router.currentParams); - if (w5 && w5.__owl__.currentFiber && !w5.__owl__.vnode) { - w5.destroy(); - w5 = false; + { + let key0 = scope['env'].router.currentRouteName; + // Component 'routeComponent' + let k5 = \`__5__\${key0}__\`; + let w4 = k5 in parent.__owl__.cmap ? parent.__owl__.children[parent.__owl__.cmap[k5]] : false; + let vn6 = {}; + result = vn6; + let props4 = Object.assign({}, scope['env'].router.currentParams); + if (w4 && w4.__owl__.currentFiber && !w4.__owl__.vnode) { + w4.destroy(); + w4 = false; + } + if (w4) { + w4.__updateProps(props4, extra.fiber, undefined); + let pvnode = w4.__owl__.pvnode; + utils.defineProxy(vn6, pvnode); + } else { + let componentKey4 = \`routeComponent\`; + let W4 = context.constructor.components[componentKey4] || QWeb.components[componentKey4]|| scope['routeComponent']; + if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')} + w4 = new W4(parent, props4); + parent.__owl__.cmap[k5] = w4.__owl__.id; + let fiber = w4.__prepare(extra.fiber, undefined, () => { const vnode = fiber.vnode; pvnode.sel = vnode.sel; }); + let pvnode = h('dummy', {key: k5, hook: {remove() {},destroy(vn) {w4.destroy();}}}); + utils.defineProxy(vn6, pvnode); + w4.__owl__.pvnode = pvnode; + } + w4.__owl__.parentLastFiberId = extra.fiber.id; } - if (w5) { - w5.__updateProps(props5, extra.fiber, undefined); - let pvnode = w5.__owl__.pvnode; - utils.defineProxy(vn7, pvnode); - } else { - let componentKey5 = \`routeComponent\`; - let W5 = context.constructor.components[componentKey5] || QWeb.components[componentKey5]|| scope['routeComponent']; - if (!W5) {throw new Error('Cannot find the definition of component \\"' + componentKey5 + '\\"')} - w5 = new W5(parent, props5); - parent.__owl__.cmap[k6] = w5.__owl__.id; - let fiber = w5.__prepare(extra.fiber, undefined, () => { const vnode = fiber.vnode; pvnode.sel = vnode.sel; }); - let pvnode = h('dummy', {key: k6, hook: {remove() {},destroy(vn) {w5.destroy();}}}); - utils.defineProxy(vn7, pvnode); - w5.__owl__.pvnode = pvnode; - } - w5.__owl__.parentLastFiberId = extra.fiber.id; } return result; }"