diff --git a/src/qweb/base_directives.ts b/src/qweb/base_directives.ts
index 463edcaa..b8b10a3c 100644
--- a/src/qweb/base_directives.ts
+++ b/src/qweb/base_directives.ts
@@ -28,9 +28,12 @@ QWeb.utils.getFragment = function(str: string): DocumentFragment {
QWeb.utils.htmlToVDOM = htmlToVDOM;
function compileValueNode(value: any, node: Element, qweb: QWeb, ctx: CompilationContext) {
- if (value === "0" && ctx.caller) {
- qweb._compileNode(ctx.caller, ctx);
- return;
+ if (value === "0") {
+ const caller = ctx.getCaller();
+ if (caller) {
+ qweb._compileNode(caller, ctx.getInliningContext());
+ return;
+ }
}
if (value.xml instanceof NodeList && !value.id) {
diff --git a/src/qweb/compilation_context.ts b/src/qweb/compilation_context.ts
index 45189cc3..6fe8b319 100644
--- a/src/qweb/compilation_context.ts
+++ b/src/qweb/compilation_context.ts
@@ -32,6 +32,8 @@ export class CompilationContext {
scopeVars: any[] = [];
currentKey: string = "";
templates: { [key: string]: boolean } = {};
+ callingLevel: number = 0;
+ inliningLevel: number = 0;
constructor(name?: string) {
this.rootContext = this;
@@ -129,6 +131,10 @@ export class CompilationContext {
subContext(key: keyof CompilationContext, value: any): CompilationContext {
const newContext = Object.create(this);
newContext[key] = value;
+ if (key === 'caller') {
+ newContext.callingLevel++;
+ newContext.inliningLevel++;
+ }
return newContext;
}
@@ -166,6 +172,27 @@ export class CompilationContext {
this.dedent();
this.addLine("}");
}
+ /**
+ * Recursively (inverse) fetches the `caller` of a context
+ * Useful to determine to which t-call a t-raw="0" refers
+ */
+ getCaller(targetLevel?: number): Element | null {
+ if (targetLevel === undefined) {
+ targetLevel = this.inliningLevel;
+ }
+ if (targetLevel === this.callingLevel) {
+ return this.caller || null;
+ }
+ const proto = (this as any).__proto__;
+ return proto ? proto.getCaller(targetLevel) : null;
+ }
+ /**
+ * Marks the context with the current recursive level
+ * in which we are for inlining archs (t-raw="0")
+ */
+ getInliningContext(): CompilationContext {
+ return this.subContext('inliningLevel', this.inliningLevel - 1);
+ }
getValue(val: any): QWebVar | string {
return val in this.variables ? this.getValue(this.variables[val]) : val;
diff --git a/tests/qweb/__snapshots__/qweb.test.ts.snap b/tests/qweb/__snapshots__/qweb.test.ts.snap
index 409cc823..14ac1876 100644
--- a/tests/qweb/__snapshots__/qweb.test.ts.snap
+++ b/tests/qweb/__snapshots__/qweb.test.ts.snap
@@ -910,6 +910,46 @@ exports[`t-call (template calling call with several sub nodes on same line 1`] =
}"
`;
+exports[`t-call (template calling cascading t-call t-raw='0' 1`] = `
+"function anonymous(context,extra
+) {
+ var h = this.h;
+ let c1 = [], p1 = {key:1};
+ var vn1 = h('div', p1, c1);
+ let c5 = [], p5 = {key:5};
+ var vn5 = h('div', p5, c5);
+ c1.push(vn5);
+ let c8 = [], p8 = {key:8};
+ var vn8 = h('div', p8, c8);
+ c5.push(vn8);
+ let c11 = [], p11 = {key:11};
+ var vn11 = h('div', p11, c11);
+ c8.push(vn11);
+ let c12 = [], p12 = {key:12};
+ var vn12 = h('span', p12, c12);
+ c11.push(vn12);
+ c12.push({text: \`cascade 2\`});
+ let c13 = [], p13 = {key:13};
+ var vn13 = h('span', p13, c13);
+ c11.push(vn13);
+ c13.push({text: \`cascade 1\`});
+ let c14 = [], p14 = {key:14};
+ var vn14 = h('span', p14, c14);
+ c11.push(vn14);
+ c14.push({text: \`cascade 0\`});
+ let c15 = [], p15 = {key:15};
+ var vn15 = h('span', p15, c15);
+ c11.push(vn15);
+ c15.push({text: \`hey\`});
+ c11.push({text: \` \`});
+ let c16 = [], p16 = {key:16};
+ var vn16 = h('span', p16, c16);
+ c11.push(vn16);
+ c16.push({text: \`yay\`});
+ return vn1;
+}"
+`;
+
exports[`t-call (template calling inherit context 1`] = `
"function anonymous(context,extra
) {
diff --git a/tests/qweb/qweb.test.ts b/tests/qweb/qweb.test.ts
index d1d85c4b..6a45f66d 100644
--- a/tests/qweb/qweb.test.ts
+++ b/tests/qweb/qweb.test.ts
@@ -673,6 +673,39 @@ describe("t-call (template calling", () => {
expect(renderToString(qweb, "main")).toBe(expected);
});
+ test("cascading t-call t-raw='0'", () => {
+ qweb.addTemplates(`
+