[FIX] qweb: t-set expressions are evaluated only once

closes #23
This commit is contained in:
Géry Debongnie
2019-04-15 13:50:28 +02:00
parent 3d18359dd8
commit 85eb30626d
3 changed files with 263 additions and 173 deletions
+51 -14
View File
@@ -43,6 +43,7 @@ export class Context {
nextID: number = 1; nextID: number = 1;
code: string[] = []; code: string[] = [];
variables: { [key: string]: any } = {}; variables: { [key: string]: any } = {};
definedVariables: { [key: string]: string } = {};
escaping: boolean = false; escaping: boolean = false;
parentNode: number | null = null; parentNode: number | null = null;
rootNode: number | null = null; rootNode: number | null = null;
@@ -157,11 +158,13 @@ export class Context {
} else if (c.match(/\W/) && invar.length) { } else if (c.match(/\W/) && invar.length) {
// TODO: Should check for possible spaces before dot // TODO: Should check for possible spaces before dot
if (chars[invarPos - 1] !== "." && RESERVED_WORDS.indexOf(invar) < 0) { if (chars[invarPos - 1] !== "." && RESERVED_WORDS.indexOf(invar) < 0) {
invar = if (!(invar in this.definedVariables)) {
WORD_REPLACEMENT[invar] || invar =
(invar in this.variables && WORD_REPLACEMENT[invar] ||
this.formatExpression(this.variables[invar])) || (invar in this.variables &&
"context['" + invar + "']"; this.formatExpression(this.variables[invar])) ||
"context['" + invar + "']";
}
} }
r += invar; r += invar;
invar = ""; invar = "";
@@ -700,19 +703,20 @@ function compileValueNode(value: any, node: Element, qweb: QWeb, ctx: Context) {
} }
if (typeof value === "string") { if (typeof value === "string") {
const exprID = ctx.generateID(); let exprID = value;
ctx.addLine(`var e${exprID} = ${ctx.formatExpression(value)};`); if (!(value in ctx.definedVariables)) {
ctx.addIf(`e${exprID} || e${exprID} === 0`); exprID = `_${ctx.generateID()}`;
let text = `e${exprID}`; ctx.addLine(`var ${exprID} = ${ctx.formatExpression(value)};`);
}
ctx.addIf(`${exprID} || ${exprID} === 0`);
if (!ctx.parentNode) { if (!ctx.parentNode) {
throw new Error("Should not have a text node without a parent"); throw new Error("Should not have a text node without a parent");
} }
if (ctx.escaping) { if (ctx.escaping) {
ctx.addLine(`c${ctx.parentNode}.push({text: ${text}});`); ctx.addLine(`c${ctx.parentNode}.push({text: ${exprID}});`);
} else { } else {
let fragID = ctx.generateID(); let fragID = ctx.generateID();
ctx.addLine(`var frag${fragID} = this.utils.getFragment(e${exprID})`); ctx.addLine(`var frag${fragID} = this.utils.getFragment(${exprID})`);
let tempNodeID = ctx.generateID(); let tempNodeID = ctx.generateID();
ctx.addLine(`var p${tempNodeID} = {hook: {`); ctx.addLine(`var p${tempNodeID} = {hook: {`);
ctx.addLine( ctx.addLine(
@@ -771,7 +775,11 @@ const setDirective: Directive = {
const variable = node.getAttribute("t-set")!; const variable = node.getAttribute("t-set")!;
let value = node.getAttribute("t-value")!; let value = node.getAttribute("t-value")!;
if (value) { if (value) {
ctx.variables[variable] = value; const varName = `_${ctx.generateID()}`;
const formattedValue = ctx.formatExpression(value);
ctx.addLine(`var ${varName} = ${formattedValue}`);
ctx.definedVariables[varName] = formattedValue;
ctx.variables[variable] = varName;
} else { } else {
ctx.variables[variable] = node.childNodes; ctx.variables[variable] = node.childNodes;
} }
@@ -836,13 +844,42 @@ const callDirective: Directive = {
// extract variables from nodecopy // extract variables from nodecopy
const tempCtx = new Context(); const tempCtx = new Context();
tempCtx.nextID = ctx.rootContext.nextID;
qweb._compileNode(nodeCopy, tempCtx); qweb._compileNode(nodeCopy, tempCtx);
const vars = Object.assign({}, ctx.variables, tempCtx.variables); const vars = Object.assign({}, ctx.variables, tempCtx.variables);
var definedVariables = Object.assign(
{},
ctx.definedVariables,
tempCtx.definedVariables
);
ctx.rootContext.nextID = tempCtx.nextID;
// open new scope, if necessary
const hasNewVariables = Object.keys(definedVariables).length > 0;
if (hasNewVariables) {
ctx.addLine("{");
ctx.indent();
}
// add new variables, if any
for (let key in definedVariables) {
ctx.addLine(`let ${key} = ${definedVariables[key]}`);
}
// compile sub template
const subCtx = ctx const subCtx = ctx
.subContext("caller", nodeCopy) .subContext("caller", nodeCopy)
.subContext("variables", Object.create(vars)); .subContext("variables", Object.create(vars))
.subContext("definedVariables", Object.create(definedVariables));
qweb._compileNode(nodeTemplate, subCtx); qweb._compileNode(nodeTemplate, subCtx);
// close new scope
if (hasNewVariables) {
ctx.dedent();
ctx.addLine("}");
}
return true; return true;
} }
}; };
+198 -159
View File
@@ -105,10 +105,11 @@ exports[`attributes from object variables set previously 1`] = `
var h = this.utils.h; var h = this.utils.h;
var c1 = [], p1 = {key:1}; var c1 = [], p1 = {key:1};
var vn1 = h('div', p1, c1); var vn1 = h('div', p1, c1);
var _2 = {a: 'b'}.a; var _2 = {a: 'b'}
var c3 = [], p3 = {key:3,attrs:{class: _2}}; var _3 = _2.a;
var vn3 = h('span', p3, c3); var c4 = [], p4 = {key:4,attrs:{class: _3}};
c1.push(vn3); var vn4 = h('span', p4, c4);
c1.push(vn4);
return vn1; return vn1;
}" }"
`; `;
@@ -119,10 +120,11 @@ exports[`attributes from variables set previously 1`] = `
var h = this.utils.h; var h = this.utils.h;
var c1 = [], p1 = {key:1}; var c1 = [], p1 = {key:1};
var vn1 = h('div', p1, c1); var vn1 = h('div', p1, c1);
var _2 = 'def'; var _2 = 'def'
var c3 = [], p3 = {key:3,attrs:{class: _2}}; var _3 = _2;
var vn3 = h('span', p3, c3); var c4 = [], p4 = {key:4,attrs:{class: _3}};
c1.push(vn3); var vn4 = h('span', p4, c4);
c1.push(vn4);
return vn1; return vn1;
}" }"
`; `;
@@ -273,9 +275,9 @@ exports[`foreach does not pollute the rendering context 1`] = `
context.item_index = i; context.item_index = i;
context.item = _3[i]; context.item = _3[i];
context.item_value = _4[i]; context.item_value = _4[i];
var e5 = context['item']; var _5 = context['item'];
if (e5 || e5 === 0) { if (_5 || _5 === 0) {
c1.push({text: e5}); c1.push({text: _5});
} }
} }
return vn1; return vn1;
@@ -304,9 +306,9 @@ exports[`foreach iterate on items (on a element node) 1`] = `
var c5 = [], p5 = {key:5}; var c5 = [], p5 = {key:5};
var vn5 = h('span', p5, c5); var vn5 = h('span', p5, c5);
c1.push(vn5); c1.push(vn5);
var e6 = context['item']; var _6 = context['item'];
if (e6 || e6 === 0) { if (_6 || _6 === 0) {
c5.push({text: e6}); c5.push({text: _6});
} }
} }
return vn1; return vn1;
@@ -333,19 +335,19 @@ exports[`foreach iterate on items 1`] = `
context.item = _3[i]; context.item = _3[i];
context.item_value = _4[i]; context.item_value = _4[i];
c1.push({text: \` [\`}); c1.push({text: \` [\`});
var e5 = context['item_index']; var _5 = context['item_index'];
if (e5 || e5 === 0) { if (_5 || _5 === 0) {
c1.push({text: e5}); c1.push({text: _5});
} }
c1.push({text: \`: \`}); c1.push({text: \`: \`});
var e6 = context['item']; var _6 = context['item'];
if (e6 || e6 === 0) { if (_6 || _6 === 0) {
c1.push({text: e6}); c1.push({text: _6});
} }
c1.push({text: \` \`}); c1.push({text: \` \`});
var e7 = context['item_value']; var _7 = context['item_value'];
if (e7 || e7 === 0) { if (_7 || _7 === 0) {
c1.push({text: e7}); c1.push({text: _7});
} }
c1.push({text: \`] \`}); c1.push({text: \`] \`});
} }
@@ -373,24 +375,24 @@ exports[`foreach iterate, dict param 1`] = `
context.item = _3[i]; context.item = _3[i];
context.item_value = _4[i]; context.item_value = _4[i];
c1.push({text: \` [\`}); c1.push({text: \` [\`});
var e5 = context['item_index']; var _5 = context['item_index'];
if (e5 || e5 === 0) { if (_5 || _5 === 0) {
c1.push({text: e5}); c1.push({text: _5});
} }
c1.push({text: \`: \`}); c1.push({text: \`: \`});
var e6 = context['item']; var _6 = context['item'];
if (e6 || e6 === 0) { if (_6 || _6 === 0) {
c1.push({text: e6}); c1.push({text: _6});
} }
c1.push({text: \` \`}); c1.push({text: \` \`});
var e7 = context['item_value']; var _7 = context['item_value'];
if (e7 || e7 === 0) { if (_7 || _7 === 0) {
c1.push({text: e7}); c1.push({text: _7});
} }
c1.push({text: \` - \`}); c1.push({text: \` - \`});
var e8 = context['item_parity']; var _8 = context['item_parity'];
if (e8 || e8 === 0) { if (_8 || _8 === 0) {
c1.push({text: e8}); c1.push({text: _8});
} }
c1.push({text: \`] \`}); c1.push({text: \`] \`});
} }
@@ -418,19 +420,19 @@ exports[`foreach iterate, integer param 1`] = `
context.item = _3[i]; context.item = _3[i];
context.item_value = _4[i]; context.item_value = _4[i];
c1.push({text: \` [\`}); c1.push({text: \` [\`});
var e5 = context['item_index']; var _5 = context['item_index'];
if (e5 || e5 === 0) { if (_5 || _5 === 0) {
c1.push({text: e5}); c1.push({text: _5});
} }
c1.push({text: \`: \`}); c1.push({text: \`: \`});
var e6 = context['item']; var _6 = context['item'];
if (e6 || e6 === 0) { if (_6 || _6 === 0) {
c1.push({text: e6}); c1.push({text: _6});
} }
c1.push({text: \` \`}); c1.push({text: \` \`});
var e7 = context['item_value']; var _7 = context['item_value'];
if (e7 || e7 === 0) { if (_7 || _7 === 0) {
c1.push({text: e7}); c1.push({text: _7});
} }
c1.push({text: \`] \`}); c1.push({text: \`] \`});
} }
@@ -465,9 +467,9 @@ exports[`foreach iterate, position 1`] = `
c1.push({text: \` last\`}); c1.push({text: \` last\`});
} }
c1.push({text: \` (\`}); c1.push({text: \` (\`});
var e5 = context['elem_parity']; var _5 = context['elem_parity'];
if (e5 || e5 === 0) { if (_5 || _5 === 0) {
c1.push({text: e5}); c1.push({text: _5});
} }
c1.push({text: \`) \`}); c1.push({text: \`) \`});
} }
@@ -526,55 +528,63 @@ exports[`misc global 1`] = `
var c5 = [], p5 = {key:5,on:{}}; var c5 = [], p5 = {key:5,on:{}};
var vn5 = h('span', p5, c5); var vn5 = h('span', p5, c5);
c1.push(vn5); c1.push(vn5);
var e6 = context['value']; var _6 = context['value'];
if (e6 || e6 === 0) { if (_6 || _6 === 0) {
c5.push({text: e6}); c5.push({text: _6});
} }
var _7 = 'agüero'; {
var c8 = [], p8 = {key:8,attrs:{\\"falló\\": _7},on:{}}; let _11 = 'bbb'
var vn8 = h('Año', p8, c8); var _13 = 'agüero';
c1.push(vn8); var c14 = [], p14 = {key:14,attrs:{\\"falló\\": _13},on:{}};
var c9 = [], p9 = {key:9,on:{}}; var vn14 = h('Año', p14, c14);
var vn9 = h('span', p9, c9); c1.push(vn14);
c8.push(vn9); {
var e10 = 'aaa'; let _15 = 'aaa'
if (e10 || e10 === 0) { var c16 = [], p16 = {key:16,on:{}};
c9.push({text: e10}); var vn16 = h('span', p16, c16);
} else { c14.push(vn16);
c9.push({text: \`foo default\`}); if (_15 || _15 === 0) {
} c16.push({text: _15});
var c11 = [], p11 = {key:11,on:{}}; } else {
var vn11 = h('span', p11, c11); c16.push({text: \`foo default\`});
c8.push(vn11); }
var e12 = context['foo']; }
if (e12 || e12 === 0) { var c17 = [], p17 = {key:17,on:{}};
c11.push({text: e12}); var vn17 = h('span', p17, c17);
} else { c14.push(vn17);
c11.push({text: \`foo default\`}); var _18 = context['foo'];
} if (_18 || _18 === 0) {
var c13 = [], p13 = {key:13,on:{}}; c17.push({text: _18});
var vn13 = h('span', p13, c13); } else {
c8.push(vn13); c17.push({text: \`foo default\`});
var e14 = 'bbb'; }
if (e14 || e14 === 0) { var _19 = 'bbb'
c13.push({text: e14}); {
} else { let _19 = 'bbb'
c13.push({text: \`foo default\`}); var c20 = [], p20 = {key:20,on:{}};
var vn20 = h('span', p20, c20);
c14.push(vn20);
if (_19 || _19 === 0) {
c20.push({text: _19});
} else {
c20.push({text: \`foo default\`});
}
}
} }
} }
var c15 = [], p15 = {key:15,on:{}}; var c21 = [], p21 = {key:21,on:{}};
var vn15 = h('div', p15, c15); var vn21 = h('div', p21, c21);
c1.push(vn15); c1.push(vn21);
var e16 = context['toto']; var _22 = context['toto'];
if (e16 || e16 === 0) { if (_22 || _22 === 0) {
var frag17 = this.utils.getFragment(e16) var frag23 = this.utils.getFragment(_22)
var p18 = {hook: { var p24 = {hook: {
insert: n => n.elm.parentNode.replaceChild(frag17, n.elm), insert: n => n.elm.parentNode.replaceChild(frag23, n.elm),
}}; }};
var vn18 = h('div', p18) var vn24 = h('div', p24)
c15.push(vn18); c21.push(vn24);
} else { } else {
c15.push({text: \`toto default\`}); c21.push({text: \`toto default\`});
} }
return vn1; return vn1;
}" }"
@@ -693,9 +703,12 @@ exports[`t-call (template calling inherit context 1`] = `
var h = this.utils.h; var h = this.utils.h;
var c1 = [], p1 = {key:1}; var c1 = [], p1 = {key:1};
var vn1 = h('div', p1, c1); var vn1 = h('div', p1, c1);
var e2 = 1; var _2 = 1
if (e2 || e2 === 0) { {
c1.push({text: e2}); let _2 = 1
if (_2 || _2 === 0) {
c1.push({text: _2});
}
} }
return vn1; return vn1;
}" }"
@@ -707,10 +720,13 @@ exports[`t-call (template calling scoped parameters 1`] = `
var h = this.utils.h; var h = this.utils.h;
var c1 = [], p1 = {key:1}; var c1 = [], p1 = {key:1};
var vn1 = h('div', p1, c1); var vn1 = h('div', p1, c1);
c1.push({text: \`ok\`}); {
var e2 = context['foo']; let _2 = 42
if (e2 || e2 === 0) { c1.push({text: \`ok\`});
c1.push({text: e2}); }
var _3 = context['foo'];
if (_3 || _3 === 0) {
c1.push({text: _3});
} }
return vn1; return vn1;
}" }"
@@ -720,10 +736,10 @@ exports[`t-call (template calling with unused body 1`] = `
"function anonymous(context,extra "function anonymous(context,extra
) { ) {
var h = this.utils.h; var h = this.utils.h;
var c1 = [], p1 = {key:1}; var c2 = [], p2 = {key:2};
var vn1 = h('div', p1, c1); var vn2 = h('div', p2, c2);
c1.push({text: \`ok\`}); c2.push({text: \`ok\`});
return vn1; return vn2;
}" }"
`; `;
@@ -731,10 +747,13 @@ exports[`t-call (template calling with unused setbody 1`] = `
"function anonymous(context,extra "function anonymous(context,extra
) { ) {
var h = this.utils.h; var h = this.utils.h;
var c1 = [], p1 = {key:1}; {
var vn1 = h('div', p1, c1); let _1 = 3
c1.push({text: \`ok\`}); var c2 = [], p2 = {key:2};
return vn1; var vn2 = h('div', p2, c2);
c2.push({text: \`ok\`});
}
return vn2;
}" }"
`; `;
@@ -742,10 +761,10 @@ exports[`t-call (template calling with used body 1`] = `
"function anonymous(context,extra "function anonymous(context,extra
) { ) {
var h = this.utils.h; var h = this.utils.h;
var c1 = [], p1 = {key:1}; var c2 = [], p2 = {key:2};
var vn1 = h('h1', p1, c1); var vn2 = h('h1', p2, c2);
c1.push({text: \`ok\`}); c2.push({text: \`ok\`});
return vn1; return vn2;
}" }"
`; `;
@@ -755,9 +774,11 @@ exports[`t-call (template calling with used set body 1`] = `
var h = this.utils.h; var h = this.utils.h;
var c1 = [], p1 = {key:1}; var c1 = [], p1 = {key:1};
var vn1 = h('span', p1, c1); var vn1 = h('span', p1, c1);
var e2 = 'ok'; {
if (e2 || e2 === 0) { let _2 = 'ok'
c1.push({text: e2}); if (_2 || _2 === 0) {
c1.push({text: _2});
}
} }
return vn1; return vn1;
}" }"
@@ -769,9 +790,9 @@ exports[`t-esc escaping on a node 1`] = `
var h = this.utils.h; var h = this.utils.h;
var c1 = [], p1 = {key:1,on:{}}; var c1 = [], p1 = {key:1,on:{}};
var vn1 = h('span', p1, c1); var vn1 = h('span', p1, c1);
var e2 = 'ok'; var _2 = 'ok';
if (e2 || e2 === 0) { if (_2 || _2 === 0) {
c1.push({text: e2}); c1.push({text: _2});
} }
return vn1; return vn1;
}" }"
@@ -783,9 +804,9 @@ exports[`t-esc escaping on a node with a body 1`] = `
var h = this.utils.h; var h = this.utils.h;
var c1 = [], p1 = {key:1,on:{}}; var c1 = [], p1 = {key:1,on:{}};
var vn1 = h('span', p1, c1); var vn1 = h('span', p1, c1);
var e2 = 'ok'; var _2 = 'ok';
if (e2 || e2 === 0) { if (_2 || _2 === 0) {
c1.push({text: e2}); c1.push({text: _2});
} else { } else {
c1.push({text: \`nope\`}); c1.push({text: \`nope\`});
} }
@@ -799,9 +820,9 @@ exports[`t-esc escaping on a node with a body, as a default 1`] = `
var h = this.utils.h; var h = this.utils.h;
var c1 = [], p1 = {key:1,on:{}}; var c1 = [], p1 = {key:1,on:{}};
var vn1 = h('span', p1, c1); var vn1 = h('span', p1, c1);
var e2 = context['var']; var _2 = context['var'];
if (e2 || e2 === 0) { if (_2 || _2 === 0) {
c1.push({text: e2}); c1.push({text: _2});
} else { } else {
c1.push({text: \`nope\`}); c1.push({text: \`nope\`});
} }
@@ -815,9 +836,9 @@ exports[`t-esc literal 1`] = `
var h = this.utils.h; var h = this.utils.h;
var c1 = [], p1 = {key:1}; var c1 = [], p1 = {key:1};
var vn1 = h('span', p1, c1); var vn1 = h('span', p1, c1);
var e2 = 'ok'; var _2 = 'ok';
if (e2 || e2 === 0) { if (_2 || _2 === 0) {
c1.push({text: e2}); c1.push({text: _2});
} }
return vn1; return vn1;
}" }"
@@ -829,9 +850,9 @@ exports[`t-esc variable 1`] = `
var h = this.utils.h; var h = this.utils.h;
var c1 = [], p1 = {key:1}; var c1 = [], p1 = {key:1};
var vn1 = h('span', p1, c1); var vn1 = h('span', p1, c1);
var e2 = context['var']; var _2 = context['var'];
if (e2 || e2 === 0) { if (_2 || _2 === 0) {
c1.push({text: e2}); c1.push({text: _2});
} }
return vn1; return vn1;
}" }"
@@ -1115,9 +1136,9 @@ exports[`t-raw literal 1`] = `
var h = this.utils.h; var h = this.utils.h;
var c1 = [], p1 = {key:1}; var c1 = [], p1 = {key:1};
var vn1 = h('span', p1, c1); var vn1 = h('span', p1, c1);
var e2 = 'ok'; var _2 = 'ok';
if (e2 || e2 === 0) { if (_2 || _2 === 0) {
var frag3 = this.utils.getFragment(e2) var frag3 = this.utils.getFragment(_2)
var p4 = {hook: { var p4 = {hook: {
insert: n => n.elm.parentNode.replaceChild(frag3, n.elm), insert: n => n.elm.parentNode.replaceChild(frag3, n.elm),
}}; }};
@@ -1134,9 +1155,9 @@ exports[`t-raw not escaping 1`] = `
var h = this.utils.h; var h = this.utils.h;
var c1 = [], p1 = {key:1}; var c1 = [], p1 = {key:1};
var vn1 = h('div', p1, c1); var vn1 = h('div', p1, c1);
var e2 = context['var']; var _2 = context['var'];
if (e2 || e2 === 0) { if (_2 || _2 === 0) {
var frag3 = this.utils.getFragment(e2) var frag3 = this.utils.getFragment(_2)
var p4 = {hook: { var p4 = {hook: {
insert: n => n.elm.parentNode.replaceChild(frag3, n.elm), insert: n => n.elm.parentNode.replaceChild(frag3, n.elm),
}}; }};
@@ -1157,9 +1178,9 @@ exports[`t-raw t-raw and another sibling node 1`] = `
var vn2 = h('span', p2, c2); var vn2 = h('span', p2, c2);
c1.push(vn2); c1.push(vn2);
c2.push({text: \`hello\`}); c2.push({text: \`hello\`});
var e3 = context['var']; var _3 = context['var'];
if (e3 || e3 === 0) { if (_3 || _3 === 0) {
var frag4 = this.utils.getFragment(e3) var frag4 = this.utils.getFragment(_3)
var p5 = {hook: { var p5 = {hook: {
insert: n => n.elm.parentNode.replaceChild(frag4, n.elm), insert: n => n.elm.parentNode.replaceChild(frag4, n.elm),
}}; }};
@@ -1176,9 +1197,9 @@ exports[`t-raw variable 1`] = `
var h = this.utils.h; var h = this.utils.h;
var c1 = [], p1 = {key:1}; var c1 = [], p1 = {key:1};
var vn1 = h('span', p1, c1); var vn1 = h('span', p1, c1);
var e2 = context['var']; var _2 = context['var'];
if (e2 || e2 === 0) { if (_2 || _2 === 0) {
var frag3 = this.utils.getFragment(e2) var frag3 = this.utils.getFragment(_2)
var p4 = {hook: { var p4 = {hook: {
insert: n => n.elm.parentNode.replaceChild(frag3, n.elm), insert: n => n.elm.parentNode.replaceChild(frag3, n.elm),
}}; }};
@@ -1227,9 +1248,9 @@ exports[`t-set evaluate value expression 1`] = `
var h = this.utils.h; var h = this.utils.h;
var c1 = [], p1 = {key:1}; var c1 = [], p1 = {key:1};
var vn1 = h('div', p1, c1); var vn1 = h('div', p1, c1);
var e2 = 1 + 2; var _2 = 1 + 2
if (e2 || e2 === 0) { if (_2 || _2 === 0) {
c1.push({text: e2}); c1.push({text: _2});
} }
return vn1; return vn1;
}" }"
@@ -1241,9 +1262,9 @@ exports[`t-set evaluate value expression, part 2 1`] = `
var h = this.utils.h; var h = this.utils.h;
var c1 = [], p1 = {key:1}; var c1 = [], p1 = {key:1};
var vn1 = h('div', p1, c1); var vn1 = h('div', p1, c1);
var e2 = context['somevariable'] + 2; var _2 = context['somevariable'] + 2
if (e2 || e2 === 0) { if (_2 || _2 === 0) {
c1.push({text: e2}); c1.push({text: _2});
} }
return vn1; return vn1;
}" }"
@@ -1255,9 +1276,9 @@ exports[`t-set set from attribute literal 1`] = `
var h = this.utils.h; var h = this.utils.h;
var c1 = [], p1 = {key:1}; var c1 = [], p1 = {key:1};
var vn1 = h('div', p1, c1); var vn1 = h('div', p1, c1);
var e2 = 'ok'; var _2 = 'ok'
if (e2 || e2 === 0) { if (_2 || _2 === 0) {
c1.push({text: e2}); c1.push({text: _2});
} }
return vn1; return vn1;
}" }"
@@ -1269,9 +1290,9 @@ exports[`t-set set from attribute lookup 1`] = `
var h = this.utils.h; var h = this.utils.h;
var c1 = [], p1 = {key:1}; var c1 = [], p1 = {key:1};
var vn1 = h('div', p1, c1); var vn1 = h('div', p1, c1);
var e2 = context['value']; var _2 = context['value']
if (e2 || e2 === 0) { if (_2 || _2 === 0) {
c1.push({text: e2}); c1.push({text: _2});
} }
return vn1; return vn1;
}" }"
@@ -1292,9 +1313,9 @@ exports[`t-set set from body lookup 1`] = `
var h = this.utils.h; var h = this.utils.h;
var c1 = [], p1 = {key:1}; var c1 = [], p1 = {key:1};
var vn1 = h('div', p1, c1); var vn1 = h('div', p1, c1);
var e2 = context['value']; var _2 = context['value'];
if (e2 || e2 === 0) { if (_2 || _2 === 0) {
c1.push({text: e2}); c1.push({text: _2});
} }
return vn1; return vn1;
}" }"
@@ -1316,22 +1337,40 @@ exports[`t-set t-set and t-if 1`] = `
var h = this.utils.h; var h = this.utils.h;
var c1 = [], p1 = {key:1}; var c1 = [], p1 = {key:1};
var vn1 = h('div', p1, c1); var vn1 = h('div', p1, c1);
if (context['value'] === 'ok') { var _2 = context['value']
if (_2 === 'ok') {
c1.push({text: \`grimbergen\`}); c1.push({text: \`grimbergen\`});
} }
return vn1; return vn1;
}" }"
`; `;
exports[`t-set t-set evaluates an expression only once 1`] = `
"function anonymous(context,extra
) {
var h = this.utils.h;
var c1 = [], p1 = {key:1};
var vn1 = h('div', p1, c1);
var _2 = context['value'] + ' artois'
if (_2 || _2 === 0) {
c1.push({text: _2});
}
if (_2 || _2 === 0) {
c1.push({text: _2});
}
return vn1;
}"
`;
exports[`t-set value priority 1`] = ` exports[`t-set value priority 1`] = `
"function anonymous(context,extra "function anonymous(context,extra
) { ) {
var h = this.utils.h; var h = this.utils.h;
var c1 = [], p1 = {key:1}; var c1 = [], p1 = {key:1};
var vn1 = h('div', p1, c1); var vn1 = h('div', p1, c1);
var e2 = 1; var _2 = 1
if (e2 || e2 === 0) { if (_2 || _2 === 0) {
c1.push({text: e2}); c1.push({text: _2});
} }
return vn1; return vn1;
}" }"
+14
View File
@@ -234,6 +234,20 @@ describe("t-set", () => {
expect(renderToString(qweb, "test", { value: "ok" })).toBe("<div>ok</div>"); expect(renderToString(qweb, "test", { value: "ok" })).toBe("<div>ok</div>");
}); });
test("t-set evaluates an expression only once", () => {
qweb.addTemplate(
"test",
`<div >
<t t-set="v" t-value="value + ' artois'"/>
<t t-esc="v"/>
<t t-esc="v"/>
</div>`
);
expect(renderToString(qweb, "test", { value: "stella" })).toBe(
"<div>stella artoisstella artois</div>"
);
});
test("set from body lookup", () => { test("set from body lookup", () => {
qweb.addTemplate( qweb.addTemplate(
"test", "test",