[FIX] qweb: fix issue variables set in body of t-call

The body of a t-call directive may be used to define private variables
to the sub template call.

However, the code that handles t-call worked like this:

- compile sub template if necessary
- then compile body of t-call to extract variables

This means that the variables defined in the t-call body were not yet
processed and available in the context.  Because of that, when the call
to t-esc is done, there is not internal qweb var, and the code simply
outputs a scope['varname'], which is in our case a VDOMArray, so it is
displayed as [object object]

What this fix does is changing the way t-esc works: if we are in the
context of a sub template, then it assumes that any outside variable may
or may not be a VDomArray, so it needs to check and eventually convert
it to a string, if necessary.

closes #719
This commit is contained in:
Géry Debongnie
2020-09-16 09:58:57 +02:00
committed by aab-odoo
parent 2529aa3ef2
commit 3bf91afc3f
5 changed files with 56 additions and 2 deletions
+7 -1
View File
@@ -41,6 +41,12 @@ function compileValueNode(value: any, node: Element, qweb: QWeb, ctx: Compilatio
if (typeof value === "string") {
exprID = `_${ctx.generateID()}`;
ctx.addLine(`let ${exprID} = ${ctx.formatExpression(value)};`);
if (ctx.isSubTemplate) {
ctx.rootContext.shouldDefineUtils = true;
ctx.addLine(
`${exprID} = ${exprID} instanceof utils.VDomArray ? utils.vDomToString(${exprID}) : ${exprID};`
);
}
} else {
exprID = `scope.${value.id}`;
}
@@ -238,7 +244,7 @@ QWeb.addDirective({
if (!subId) {
subId = QWeb.nextId++;
qweb.subTemplates[subTemplate] = subId;
const subTemplateFn = qweb._compile(subTemplate, nodeTemplate.elem, ctx, true);
const subTemplateFn = qweb._compile(subTemplate, nodeTemplate.elem, ctx, true, true);
QWeb.subTemplates[subId] = subTemplateFn;
}
+1
View File
@@ -22,6 +22,7 @@ export class CompilationContext {
shouldDefineUtils: boolean = false;
shouldDefineRefs: boolean = false;
shouldDefineResult: boolean = true;
isSubTemplate: boolean = false;
loopNumber: number = 0;
inPreTag: boolean = false;
templateName: string;
+3 -1
View File
@@ -413,10 +413,12 @@ export class QWeb extends EventBus {
name: string,
elem: Element,
parentContext?: CompilationContext,
defineKey?: boolean
defineKey?: boolean,
isSubTemplate?: boolean
): CompiledTemplate {
const isDebug = elem.attributes.hasOwnProperty("t-debug");
const ctx = new CompilationContext(name);
ctx.isSubTemplate = Boolean(isSubTemplate);
if (elem.tagName !== "t") {
ctx.shouldDefineResult = false;
}
@@ -1502,6 +1502,7 @@ exports[`t-call (template calling recursive template, part 2 2`] = `
let vn3 = h('p', p3, c3);
c2.push(vn3);
let _4 = scope['node'].val;
_4 = _4 instanceof utils.VDomArray ? utils.vDomToString(_4) : _4;
if (_4 != null) {
c3.push({text: _4});
}
@@ -1581,6 +1582,7 @@ exports[`t-call (template calling recursive template, part 3 2`] = `
let vn3 = h('p', p3, c3);
c2.push(vn3);
let _4 = scope['node'].val;
_4 = _4 instanceof utils.VDomArray ? utils.vDomToString(_4) : _4;
if (_4 != null) {
c3.push({text: _4});
}
@@ -1662,6 +1664,7 @@ exports[`t-call (template calling recursive template, part 4: with t-set recursi
let vn3 = h('p', p3, c3);
c2.push(vn3);
let _4 = scope['node'].val;
_4 = _4 instanceof utils.VDomArray ? utils.vDomToString(_4) : _4;
if (_4 != null) {
c3.push({text: _4});
}
@@ -1752,6 +1755,33 @@ exports[`t-call (template calling t-call with t-if 1`] = `
}"
`;
exports[`t-call (template calling t-call with t-set inside and body text content 1`] = `
"function anonymous(context, extra
) {
// Template name: \\"main\\"
let utils = this.constructor.utils;
let scope = Object.create(context);
let h = this.h;
let c1 = [], p1 = {key:1};
let vn1 = h('div', p1, c1);
let _origScope4 = scope;
scope = Object.create(scope);
scope.__access_mode__ = 'ro';
{
{
let c__0 = [];
let c5 = new utils.VDomArray();
c5.push({text: \`yip yip\`});
scope.val = c5
scope[utils.zero] = c__0;
}
this.constructor.subTemplates['1'].call(this, scope, Object.assign({}, extra, {parentNode: c1, parent: utils.getComponent(context), key: '__6__'}));
}
scope = _origScope4;
return vn1;
}"
`;
exports[`t-call (template calling t-call with t-set inside and outside 1`] = `
"function anonymous(context, extra
) {
+15
View File
@@ -1072,6 +1072,21 @@ describe("t-call (template calling", () => {
expect(renderToString(qweb1, "main")).toBe("<div><span>ok</span></div>");
expect(renderToString(qweb2, "main")).toBe("<div><span>ok</span></div>");
});
test("t-call with t-set inside and body text content", () => {
qweb.addTemplate("sub", `<p><t t-esc="val"/></p>`);
qweb.addTemplate(
"main",
`
<div>
<t t-call="sub">
<t t-set="val">yip yip</t>
</t>
</div>`
);
const expected = "<div><p>yip yip</p></div>";
expect(renderToString(qweb, "main")).toBe(expected);
});
});
describe("foreach", () => {