diff --git a/src/qweb/base_directives.ts b/src/qweb/base_directives.ts index 044a6667..f791a116 100644 --- a/src/qweb/base_directives.ts +++ b/src/qweb/base_directives.ts @@ -1,5 +1,4 @@ import { CompilationContext } from "./compilation_context"; -import { QWebExprVar } from "./expression_parser"; import { QWeb } from "./qweb"; import { htmlToVDOM } from "../vdom/html_to_vdom"; @@ -34,7 +33,7 @@ function compileValueNode(value: any, node: Element, qweb: QWeb, ctx: Compilatio return; } - if (value.xml instanceof NodeList) { + if (value.xml instanceof NodeList && !value.id) { for (let node of Array.from(value.xml)) { qweb._compileNode(node, ctx); } @@ -71,6 +70,12 @@ function compileValueNode(value: any, node: Element, qweb: QWeb, ctx: Compilatio qweb._compileChildren(node, ctx); } + if (value.xml instanceof NodeList && value.id) { + ctx.addElse(); + for (let node of Array.from(value.xml)) { + qweb._compileNode(node, ctx); + } + } ctx.closeIf(); } @@ -104,22 +109,21 @@ QWeb.addDirective({ atNodeEncounter({ node, ctx }): boolean { const variable = node.getAttribute("t-set")!; let value = node.getAttribute("t-value")!; + ctx.variables[variable] = ctx.variables[variable] || {}; + let qwebvar = ctx.variables[variable]; + if (value) { const formattedValue = ctx.formatExpression(value); - if (ctx.variables.hasOwnProperty(variable)) { - ctx.addLine(`${(ctx.variables[variable]).id} = ${formattedValue}`); + if (ctx.variables.hasOwnProperty(variable) && qwebvar.id) { + ctx.addLine(`${qwebvar.id} = ${formattedValue}`); } else { const varName = `_${ctx.generateID()}`; ctx.addLine(`var ${varName} = ${formattedValue};`); - ctx.variables[variable] = { - id: varName, - expr: formattedValue - }; + qwebvar.id = varName; + qwebvar.expr = formattedValue; } } else { - ctx.variables[variable] = { - xml: node.childNodes - }; + qwebvar.xml = node.childNodes; } return true; } @@ -133,7 +137,7 @@ QWeb.addDirective({ priority: 20, atNodeEncounter({ node, ctx }): boolean { let cond = ctx.getValue(node.getAttribute("t-if")!); - ctx.addIf(typeof cond === "string" ? ctx.formatExpression(cond) : cond.id); + ctx.addIf(typeof cond === "string" ? ctx.formatExpression(cond) : cond.id!); return false; }, finalize({ ctx }) { @@ -244,8 +248,8 @@ QWeb.addDirective({ // add new variables, if any for (let key in tempCtx.variables) { const v = tempCtx.variables[key]; - if ((v).expr) { - ctx.addLine(`let ${(v).id} = ${(v).expr};`); + if (v.expr) { + ctx.addLine(`let ${v.id} = ${v.expr};`); } // todo: handle XML variables... } diff --git a/src/qweb/compilation_context.ts b/src/qweb/compilation_context.ts index 67ab6371..6869032c 100644 --- a/src/qweb/compilation_context.ts +++ b/src/qweb/compilation_context.ts @@ -1,4 +1,4 @@ -import { compileExpr, QWebVar, QWebExprVar } from "./expression_parser"; +import { compileExpr, QWebVar } from "./expression_parser"; export const INTERP_REGEXP = /\{\{.*?\}\}/g; //------------------------------------------------------------------------------ @@ -149,7 +149,7 @@ export class CompilationContext { this.addLine("}"); } - getValue(val: any): QWebExprVar | string { + getValue(val: any): QWebVar | string { return val in this.variables ? this.getValue(this.variables[val]) : val; } diff --git a/src/qweb/expression_parser.ts b/src/qweb/expression_parser.ts index eeab886e..e5d2fee2 100644 --- a/src/qweb/expression_parser.ts +++ b/src/qweb/expression_parser.ts @@ -38,17 +38,12 @@ const WORD_REPLACEMENT = { lte: "<=" }; -export interface QWebExprVar { - id: string; - expr: string; +export interface QWebVar { + id?: string; + expr?: string; + xml?: NodeList; } -export interface QWebXMLVar { - xml: NodeList; -} - -export type QWebVar = QWebExprVar | QWebXMLVar; - //------------------------------------------------------------------------------ // Tokenizer //------------------------------------------------------------------------------ @@ -252,7 +247,7 @@ export function compileExpr(expr: string, vars: { [key: string]: QWebVar }): str } if (isVar) { if (token.value in vars && "id" in vars[token.value]) { - token.value = (vars[token.value]).id; + token.value = vars[token.value].id!; } else { token.value = `context['${token.value}']`; } diff --git a/tests/qweb/__snapshots__/qweb.test.ts.snap b/tests/qweb/__snapshots__/qweb.test.ts.snap index d5437dac..ee914c4a 100644 --- a/tests/qweb/__snapshots__/qweb.test.ts.snap +++ b/tests/qweb/__snapshots__/qweb.test.ts.snap @@ -699,25 +699,25 @@ exports[`misc global 1`] = ` } else { c17.push({text: \`foo default\`}); } - var _19 = 'bbb'; - let c20 = [], p20 = {key:20}; - var vn20 = h('span', p20, c20); - c14.push(vn20); - if (_19 || _19 === 0) { - c20.push({text: _19}); + _11 = 'bbb' + let c19 = [], p19 = {key:19}; + var vn19 = h('span', p19, c19); + c14.push(vn19); + if (_11 || _11 === 0) { + c19.push({text: _11}); } else { - c20.push({text: \`foo default\`}); + c19.push({text: \`foo default\`}); } } } - let c21 = [], p21 = {key:21}; - var vn21 = h('div', p21, c21); - c1.push(vn21); - var _22 = context['toto']; - if (_22 || _22 === 0) { - c21.push(...utils.htmlToVDOM(_22)); + let c20 = [], p20 = {key:20}; + var vn20 = h('div', p20, c20); + c1.push(vn20); + var _21 = context['toto']; + if (_21 || _21 === 0) { + c20.push(...utils.htmlToVDOM(_21)); } else { - c21.push({text: \`toto default\`}); + c20.push({text: \`toto default\`}); } return vn1; }" @@ -2400,6 +2400,90 @@ exports[`t-set t-set should reuse variable if possible 1`] = ` }" `; +exports[`t-set t-set, t-if, and mix of expression/body lookup, 1 1`] = ` +"function anonymous(context,extra +) { + let sibling = null; + var h = this.h; + let c1 = [], p1 = {key:1}; + var vn1 = h('div', p1, c1); + if (context['flag']) { + } + else { + var _2 = 0; + } + if (_2 || _2 === 0) { + c1.push({text: _2}); + } else { + c1.push({text: \`1\`}); + } + return vn1; +}" +`; + +exports[`t-set t-set, t-if, and mix of expression/body lookup, 1 2`] = ` +"function anonymous(context,extra +) { + let sibling = null; + var h = this.h; + let c1 = [], p1 = {key:1}; + var vn1 = h('div', p1, c1); + if (context['flag']) { + } + else { + var _2 = 0; + } + if (_2 || _2 === 0) { + c1.push({text: _2}); + } else { + c1.push({text: \`1\`}); + } + return vn1; +}" +`; + +exports[`t-set t-set, t-if, and mix of expression/body lookup, 2 1`] = ` +"function anonymous(context,extra +) { + let sibling = null; + var h = this.h; + let c1 = [], p1 = {key:1}; + var vn1 = h('div', p1, c1); + if (context['flag']) { + var _2 = 1; + } + else { + } + if (_2 || _2 === 0) { + c1.push({text: _2}); + } else { + c1.push({text: \`0\`}); + } + return vn1; +}" +`; + +exports[`t-set t-set, t-if, and mix of expression/body lookup, 2 2`] = ` +"function anonymous(context,extra +) { + let sibling = null; + var h = this.h; + let c1 = [], p1 = {key:1}; + var vn1 = h('div', p1, c1); + if (context['flag']) { + var _2 = 1; + } + else { + } + if (_2 || _2 === 0) { + c1.push({text: _2}); + } else { + c1.push({text: \`0\`}); + } + return vn1; +}" +`; + exports[`t-set value priority 1`] = ` "function anonymous(context,extra ) { diff --git a/tests/qweb/qweb.test.ts b/tests/qweb/qweb.test.ts index 4e4cd847..d384778c 100644 --- a/tests/qweb/qweb.test.ts +++ b/tests/qweb/qweb.test.ts @@ -242,6 +242,32 @@ describe("t-set", () => { ); expect(renderToString(qweb, "test", { somevariable: 43 })).toBe("
45
"); }); + + test("t-set, t-if, and mix of expression/body lookup, 1", () => { + qweb.addTemplate( + "test", + `
+ 1 + + +
` + ); + expect(renderToString(qweb, "test", { flag: true })).toBe("
1
"); + expect(renderToString(qweb, "test", { flag: false })).toBe("
0
"); + }); + + test("t-set, t-if, and mix of expression/body lookup, 2", () => { + qweb.addTemplate( + "test", + `
+ + 0 + +
` + ); + expect(renderToString(qweb, "test", { flag: true })).toBe("
1
"); + expect(renderToString(qweb, "test", { flag: false })).toBe("
0
"); + }); }); describe("t-if", () => {