mirror of
https://github.com/odoo/owl.git
synced 2025-10-06 19:59:41 +07:00
[FIX] t-call: nested t-call with magic variable 0
Before this commit, the template compiler would guess the next block id that will be generated when compiling the body of a tcall. This is correct IF there are not nested t-call, but otherwise wrong, because the next block id could be mixed up: the first t-call would save the next block id (let's say n), then the inner t-call would also save the same block id (so, n), will then generate its own block (n+1), then the outer t-call would use the block n index instead of n+1 The best fix, in my opinion, is to make sure we get the next block var name, so we do not have to guess. To do that, each compile block type function needs to properly return the information. closes #1267
This commit is contained in:
committed by
Sam Degueldre
parent
ab72cdddde
commit
669fd622ec
@@ -424,78 +424,66 @@ export class CodeGenerator {
|
|||||||
.join("");
|
.join("");
|
||||||
}
|
}
|
||||||
|
|
||||||
compileAST(ast: AST, ctx: Context) {
|
/**
|
||||||
|
* @returns the newly created block name, if any
|
||||||
|
*/
|
||||||
|
compileAST(ast: AST, ctx: Context): string | null {
|
||||||
switch (ast.type) {
|
switch (ast.type) {
|
||||||
case ASTType.Comment:
|
case ASTType.Comment:
|
||||||
this.compileComment(ast, ctx);
|
return this.compileComment(ast, ctx);
|
||||||
break;
|
|
||||||
case ASTType.Text:
|
case ASTType.Text:
|
||||||
this.compileText(ast, ctx);
|
return this.compileText(ast, ctx);
|
||||||
break;
|
|
||||||
case ASTType.DomNode:
|
case ASTType.DomNode:
|
||||||
this.compileTDomNode(ast, ctx);
|
return this.compileTDomNode(ast, ctx);
|
||||||
break;
|
|
||||||
case ASTType.TEsc:
|
case ASTType.TEsc:
|
||||||
this.compileTEsc(ast, ctx);
|
return this.compileTEsc(ast, ctx);
|
||||||
break;
|
|
||||||
case ASTType.TOut:
|
case ASTType.TOut:
|
||||||
this.compileTOut(ast, ctx);
|
return this.compileTOut(ast, ctx);
|
||||||
break;
|
|
||||||
case ASTType.TIf:
|
case ASTType.TIf:
|
||||||
this.compileTIf(ast, ctx);
|
return this.compileTIf(ast, ctx);
|
||||||
break;
|
|
||||||
case ASTType.TForEach:
|
case ASTType.TForEach:
|
||||||
this.compileTForeach(ast, ctx);
|
return this.compileTForeach(ast, ctx);
|
||||||
break;
|
|
||||||
case ASTType.TKey:
|
case ASTType.TKey:
|
||||||
this.compileTKey(ast, ctx);
|
return this.compileTKey(ast, ctx);
|
||||||
break;
|
|
||||||
case ASTType.Multi:
|
case ASTType.Multi:
|
||||||
this.compileMulti(ast, ctx);
|
return this.compileMulti(ast, ctx);
|
||||||
break;
|
|
||||||
case ASTType.TCall:
|
case ASTType.TCall:
|
||||||
this.compileTCall(ast, ctx);
|
return this.compileTCall(ast, ctx);
|
||||||
break;
|
|
||||||
case ASTType.TCallBlock:
|
case ASTType.TCallBlock:
|
||||||
this.compileTCallBlock(ast, ctx);
|
return this.compileTCallBlock(ast, ctx);
|
||||||
break;
|
|
||||||
case ASTType.TSet:
|
case ASTType.TSet:
|
||||||
this.compileTSet(ast, ctx);
|
return this.compileTSet(ast, ctx);
|
||||||
break;
|
|
||||||
case ASTType.TComponent:
|
case ASTType.TComponent:
|
||||||
this.compileComponent(ast, ctx);
|
return this.compileComponent(ast, ctx);
|
||||||
break;
|
|
||||||
case ASTType.TDebug:
|
case ASTType.TDebug:
|
||||||
this.compileDebug(ast, ctx);
|
return this.compileDebug(ast, ctx);
|
||||||
break;
|
|
||||||
case ASTType.TLog:
|
case ASTType.TLog:
|
||||||
this.compileLog(ast, ctx);
|
return this.compileLog(ast, ctx);
|
||||||
break;
|
|
||||||
case ASTType.TSlot:
|
case ASTType.TSlot:
|
||||||
this.compileTSlot(ast, ctx);
|
return this.compileTSlot(ast, ctx);
|
||||||
break;
|
|
||||||
case ASTType.TTranslation:
|
case ASTType.TTranslation:
|
||||||
this.compileTTranslation(ast, ctx);
|
return this.compileTTranslation(ast, ctx);
|
||||||
break;
|
|
||||||
case ASTType.TPortal:
|
case ASTType.TPortal:
|
||||||
this.compileTPortal(ast, ctx);
|
return this.compileTPortal(ast, ctx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
compileDebug(ast: ASTDebug, ctx: Context) {
|
compileDebug(ast: ASTDebug, ctx: Context): string | null {
|
||||||
this.addLine(`debugger;`);
|
this.addLine(`debugger;`);
|
||||||
if (ast.content) {
|
if (ast.content) {
|
||||||
this.compileAST(ast.content, ctx);
|
return this.compileAST(ast.content, ctx);
|
||||||
}
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
compileLog(ast: ASTLog, ctx: Context) {
|
compileLog(ast: ASTLog, ctx: Context): string | null {
|
||||||
this.addLine(`console.log(${compileExpr(ast.expr)});`);
|
this.addLine(`console.log(${compileExpr(ast.expr)});`);
|
||||||
if (ast.content) {
|
if (ast.content) {
|
||||||
this.compileAST(ast.content, ctx);
|
return this.compileAST(ast.content, ctx);
|
||||||
}
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
compileComment(ast: ASTComment, ctx: Context) {
|
compileComment(ast: ASTComment, ctx: Context): string {
|
||||||
let { block, forceNewBlock } = ctx;
|
let { block, forceNewBlock } = ctx;
|
||||||
const isNewBlock = !block || forceNewBlock;
|
const isNewBlock = !block || forceNewBlock;
|
||||||
if (isNewBlock) {
|
if (isNewBlock) {
|
||||||
@@ -508,9 +496,10 @@ export class CodeGenerator {
|
|||||||
const text = xmlDoc.createComment(ast.value);
|
const text = xmlDoc.createComment(ast.value);
|
||||||
block!.insert(text);
|
block!.insert(text);
|
||||||
}
|
}
|
||||||
|
return block!.varName;
|
||||||
}
|
}
|
||||||
|
|
||||||
compileText(ast: ASTText, ctx: Context) {
|
compileText(ast: ASTText, ctx: Context): string {
|
||||||
let { block, forceNewBlock } = ctx;
|
let { block, forceNewBlock } = ctx;
|
||||||
|
|
||||||
let value = ast.value;
|
let value = ast.value;
|
||||||
@@ -529,6 +518,7 @@ export class CodeGenerator {
|
|||||||
const createFn = ast.type === ASTType.Text ? xmlDoc.createTextNode : xmlDoc.createComment;
|
const createFn = ast.type === ASTType.Text ? xmlDoc.createTextNode : xmlDoc.createComment;
|
||||||
block.insert(createFn.call(xmlDoc, value));
|
block.insert(createFn.call(xmlDoc, value));
|
||||||
}
|
}
|
||||||
|
return block.varName;
|
||||||
}
|
}
|
||||||
|
|
||||||
generateHandlerCode(rawEvent: string, handler: string): string {
|
generateHandlerCode(rawEvent: string, handler: string): string {
|
||||||
@@ -548,7 +538,7 @@ export class CodeGenerator {
|
|||||||
return `[${modifiersCode}${this.captureExpression(handler)}, ctx]`;
|
return `[${modifiersCode}${this.captureExpression(handler)}, ctx]`;
|
||||||
}
|
}
|
||||||
|
|
||||||
compileTDomNode(ast: ASTDomNode, ctx: Context) {
|
compileTDomNode(ast: ASTDomNode, ctx: Context): string {
|
||||||
let { block, forceNewBlock } = ctx;
|
let { block, forceNewBlock } = ctx;
|
||||||
const isNewBlock = !block || forceNewBlock || ast.dynamicTag !== null || ast.ns;
|
const isNewBlock = !block || forceNewBlock || ast.dynamicTag !== null || ast.ns;
|
||||||
let codeIdx = this.target.code.length;
|
let codeIdx = this.target.code.length;
|
||||||
@@ -735,9 +725,10 @@ export class CodeGenerator {
|
|||||||
this.addLine(`let ${block!.children.map((c) => c.varName)};`, codeIdx);
|
this.addLine(`let ${block!.children.map((c) => c.varName)};`, codeIdx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return block!.varName;
|
||||||
}
|
}
|
||||||
|
|
||||||
compileTEsc(ast: ASTTEsc, ctx: Context) {
|
compileTEsc(ast: ASTTEsc, ctx: Context): string {
|
||||||
let { block, forceNewBlock } = ctx;
|
let { block, forceNewBlock } = ctx;
|
||||||
let expr: string;
|
let expr: string;
|
||||||
if (ast.expr === "0") {
|
if (ast.expr === "0") {
|
||||||
@@ -758,9 +749,10 @@ export class CodeGenerator {
|
|||||||
const text = xmlDoc.createElement(`block-text-${idx}`);
|
const text = xmlDoc.createElement(`block-text-${idx}`);
|
||||||
block.insert(text);
|
block.insert(text);
|
||||||
}
|
}
|
||||||
|
return block.varName;
|
||||||
}
|
}
|
||||||
|
|
||||||
compileTOut(ast: ASTTOut, ctx: Context) {
|
compileTOut(ast: ASTTOut, ctx: Context): string {
|
||||||
let { block } = ctx;
|
let { block } = ctx;
|
||||||
if (block) {
|
if (block) {
|
||||||
this.insertAnchor(block);
|
this.insertAnchor(block);
|
||||||
@@ -782,6 +774,7 @@ export class CodeGenerator {
|
|||||||
blockStr = `safeOutput(${compileExpr(ast.expr)})`;
|
blockStr = `safeOutput(${compileExpr(ast.expr)})`;
|
||||||
}
|
}
|
||||||
this.insertBlock(blockStr, block, ctx);
|
this.insertBlock(blockStr, block, ctx);
|
||||||
|
return block.varName;
|
||||||
}
|
}
|
||||||
|
|
||||||
compileTIfBranch(content: AST, block: BlockDescription, ctx: Context) {
|
compileTIfBranch(content: AST, block: BlockDescription, ctx: Context) {
|
||||||
@@ -795,7 +788,7 @@ export class CodeGenerator {
|
|||||||
this.target.indentLevel--;
|
this.target.indentLevel--;
|
||||||
}
|
}
|
||||||
|
|
||||||
compileTIf(ast: ASTTif, ctx: Context, nextNode?: ASTDomNode) {
|
compileTIf(ast: ASTTif, ctx: Context, nextNode?: ASTDomNode): string {
|
||||||
let { block, forceNewBlock } = ctx;
|
let { block, forceNewBlock } = ctx;
|
||||||
const codeIdx = this.target.code.length;
|
const codeIdx = this.target.code.length;
|
||||||
const isNewBlock = !block || (block.type !== "multi" && forceNewBlock);
|
const isNewBlock = !block || (block.type !== "multi" && forceNewBlock);
|
||||||
@@ -838,9 +831,10 @@ export class CodeGenerator {
|
|||||||
const args = block!.children.map((c) => c.varName).join(", ");
|
const args = block!.children.map((c) => c.varName).join(", ");
|
||||||
this.insertBlock(`multi([${args}])`, block!, ctx)!;
|
this.insertBlock(`multi([${args}])`, block!, ctx)!;
|
||||||
}
|
}
|
||||||
|
return block.varName;
|
||||||
}
|
}
|
||||||
|
|
||||||
compileTForeach(ast: ASTTForEach, ctx: Context) {
|
compileTForeach(ast: ASTTForEach, ctx: Context): string {
|
||||||
let { block } = ctx;
|
let { block } = ctx;
|
||||||
if (block) {
|
if (block) {
|
||||||
this.insertAnchor(block);
|
this.insertAnchor(block);
|
||||||
@@ -918,9 +912,10 @@ export class CodeGenerator {
|
|||||||
this.addLine(`ctx = ctx.__proto__;`);
|
this.addLine(`ctx = ctx.__proto__;`);
|
||||||
}
|
}
|
||||||
this.insertBlock("l", block, ctx);
|
this.insertBlock("l", block, ctx);
|
||||||
|
return block.varName;
|
||||||
}
|
}
|
||||||
|
|
||||||
compileTKey(ast: ASTTKey, ctx: Context) {
|
compileTKey(ast: ASTTKey, ctx: Context): string | null {
|
||||||
const tKeyExpr = generateId("tKey_");
|
const tKeyExpr = generateId("tKey_");
|
||||||
this.define(tKeyExpr, compileExpr(ast.expr));
|
this.define(tKeyExpr, compileExpr(ast.expr));
|
||||||
ctx = createContext(ctx, {
|
ctx = createContext(ctx, {
|
||||||
@@ -928,20 +923,22 @@ export class CodeGenerator {
|
|||||||
block: ctx.block,
|
block: ctx.block,
|
||||||
index: ctx.index,
|
index: ctx.index,
|
||||||
});
|
});
|
||||||
this.compileAST(ast.content, ctx);
|
return this.compileAST(ast.content, ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
compileMulti(ast: ASTMulti, ctx: Context) {
|
compileMulti(ast: ASTMulti, ctx: Context): string | null {
|
||||||
let { block, forceNewBlock } = ctx;
|
let { block, forceNewBlock } = ctx;
|
||||||
const isNewBlock = !block || forceNewBlock;
|
const isNewBlock = !block || forceNewBlock;
|
||||||
let codeIdx = this.target.code.length;
|
let codeIdx = this.target.code.length;
|
||||||
if (isNewBlock) {
|
if (isNewBlock) {
|
||||||
const n = ast.content.filter((c) => c.type !== ASTType.TSet).length;
|
const n = ast.content.filter((c) => c.type !== ASTType.TSet).length;
|
||||||
|
let result: string | null = null;
|
||||||
if (n <= 1) {
|
if (n <= 1) {
|
||||||
for (let child of ast.content) {
|
for (let child of ast.content) {
|
||||||
this.compileAST(child, ctx);
|
const blockName = this.compileAST(child, ctx);
|
||||||
|
result = result || blockName;
|
||||||
}
|
}
|
||||||
return;
|
return result;
|
||||||
}
|
}
|
||||||
block = this.createBlock(block, "multi", ctx);
|
block = this.createBlock(block, "multi", ctx);
|
||||||
}
|
}
|
||||||
@@ -981,9 +978,10 @@ export class CodeGenerator {
|
|||||||
const args = block!.children.map((c) => c.varName).join(", ");
|
const args = block!.children.map((c) => c.varName).join(", ");
|
||||||
this.insertBlock(`multi([${args}])`, block!, ctx)!;
|
this.insertBlock(`multi([${args}])`, block!, ctx)!;
|
||||||
}
|
}
|
||||||
|
return block!.varName;
|
||||||
}
|
}
|
||||||
|
|
||||||
compileTCall(ast: ASTTCall, ctx: Context) {
|
compileTCall(ast: ASTTCall, ctx: Context): string {
|
||||||
let { block, forceNewBlock } = ctx;
|
let { block, forceNewBlock } = ctx;
|
||||||
let ctxVar = ctx.ctxVar || "ctx";
|
let ctxVar = ctx.ctxVar || "ctx";
|
||||||
if (ast.context) {
|
if (ast.context) {
|
||||||
@@ -994,12 +992,11 @@ export class CodeGenerator {
|
|||||||
this.addLine(`${ctxVar} = Object.create(${ctxVar});`);
|
this.addLine(`${ctxVar} = Object.create(${ctxVar});`);
|
||||||
this.addLine(`${ctxVar}[isBoundary] = 1;`);
|
this.addLine(`${ctxVar}[isBoundary] = 1;`);
|
||||||
this.helpers.add("isBoundary");
|
this.helpers.add("isBoundary");
|
||||||
const nextId = BlockDescription.nextBlockId;
|
|
||||||
const subCtx = createContext(ctx, { preventRoot: true, ctxVar });
|
const subCtx = createContext(ctx, { preventRoot: true, ctxVar });
|
||||||
this.compileAST({ type: ASTType.Multi, content: ast.body }, subCtx);
|
const bl = this.compileMulti({ type: ASTType.Multi, content: ast.body }, subCtx);
|
||||||
if (nextId !== BlockDescription.nextBlockId) {
|
if (bl) {
|
||||||
this.helpers.add("zero");
|
this.helpers.add("zero");
|
||||||
this.addLine(`${ctxVar}[zero] = b${nextId};`);
|
this.addLine(`${ctxVar}[zero] = ${bl};`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const isDynamic = INTERP_REGEXP.test(ast.name);
|
const isDynamic = INTERP_REGEXP.test(ast.name);
|
||||||
@@ -1033,9 +1030,10 @@ export class CodeGenerator {
|
|||||||
if (ast.body && !ctx.isLast) {
|
if (ast.body && !ctx.isLast) {
|
||||||
this.addLine(`${ctxVar} = ${ctxVar}.__proto__;`);
|
this.addLine(`${ctxVar} = ${ctxVar}.__proto__;`);
|
||||||
}
|
}
|
||||||
|
return block.varName;
|
||||||
}
|
}
|
||||||
|
|
||||||
compileTCallBlock(ast: ASTTCallBlock, ctx: Context) {
|
compileTCallBlock(ast: ASTTCallBlock, ctx: Context): string {
|
||||||
let { block, forceNewBlock } = ctx;
|
let { block, forceNewBlock } = ctx;
|
||||||
if (block) {
|
if (block) {
|
||||||
if (!forceNewBlock) {
|
if (!forceNewBlock) {
|
||||||
@@ -1044,9 +1042,10 @@ export class CodeGenerator {
|
|||||||
}
|
}
|
||||||
block = this.createBlock(block, "multi", ctx);
|
block = this.createBlock(block, "multi", ctx);
|
||||||
this.insertBlock(compileExpr(ast.name), block, { ...ctx, forceNewBlock: !block });
|
this.insertBlock(compileExpr(ast.name), block, { ...ctx, forceNewBlock: !block });
|
||||||
|
return block.varName;
|
||||||
}
|
}
|
||||||
|
|
||||||
compileTSet(ast: ASTTSet, ctx: Context) {
|
compileTSet(ast: ASTTSet, ctx: Context): null {
|
||||||
this.target.shouldProtectScope = true;
|
this.target.shouldProtectScope = true;
|
||||||
this.helpers.add("isBoundary").add("withDefault");
|
this.helpers.add("isBoundary").add("withDefault");
|
||||||
const expr = ast.value ? compileExpr(ast.value || "") : "null";
|
const expr = ast.value ? compileExpr(ast.value || "") : "null";
|
||||||
@@ -1071,6 +1070,7 @@ export class CodeGenerator {
|
|||||||
this.helpers.add("setContextValue");
|
this.helpers.add("setContextValue");
|
||||||
this.addLine(`setContextValue(${ctx.ctxVar || "ctx"}, "${ast.name}", ${value});`);
|
this.addLine(`setContextValue(${ctx.ctxVar || "ctx"}, "${ast.name}", ${value});`);
|
||||||
}
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
generateComponentKey() {
|
generateComponentKey() {
|
||||||
@@ -1122,7 +1122,7 @@ export class CodeGenerator {
|
|||||||
return propString;
|
return propString;
|
||||||
}
|
}
|
||||||
|
|
||||||
compileComponent(ast: ASTComponent, ctx: Context) {
|
compileComponent(ast: ASTComponent, ctx: Context): string {
|
||||||
let { block } = ctx;
|
let { block } = ctx;
|
||||||
// props
|
// props
|
||||||
const hasSlotsProp = "slots" in (ast.props || {});
|
const hasSlotsProp = "slots" in (ast.props || {});
|
||||||
@@ -1222,6 +1222,7 @@ export class CodeGenerator {
|
|||||||
|
|
||||||
block = this.createBlock(block, "multi", ctx);
|
block = this.createBlock(block, "multi", ctx);
|
||||||
this.insertBlock(blockExpr, block, ctx);
|
this.insertBlock(blockExpr, block, ctx);
|
||||||
|
return block.varName;
|
||||||
}
|
}
|
||||||
|
|
||||||
wrapWithEventCatcher(expr: string, on: EventHandlers): string {
|
wrapWithEventCatcher(expr: string, on: EventHandlers): string {
|
||||||
@@ -1240,7 +1241,7 @@ export class CodeGenerator {
|
|||||||
return `${name}(${expr}, [${handlers.join(",")}])`;
|
return `${name}(${expr}, [${handlers.join(",")}])`;
|
||||||
}
|
}
|
||||||
|
|
||||||
compileTSlot(ast: ASTSlot, ctx: Context) {
|
compileTSlot(ast: ASTSlot, ctx: Context): string {
|
||||||
this.helpers.add("callSlot");
|
this.helpers.add("callSlot");
|
||||||
let { block } = ctx;
|
let { block } = ctx;
|
||||||
let blockString: string;
|
let blockString: string;
|
||||||
@@ -1289,14 +1290,16 @@ export class CodeGenerator {
|
|||||||
}
|
}
|
||||||
block = this.createBlock(block, "multi", ctx);
|
block = this.createBlock(block, "multi", ctx);
|
||||||
this.insertBlock(blockString, block, { ...ctx, forceNewBlock: false });
|
this.insertBlock(blockString, block, { ...ctx, forceNewBlock: false });
|
||||||
|
return block.varName;
|
||||||
}
|
}
|
||||||
|
|
||||||
compileTTranslation(ast: ASTTranslation, ctx: Context) {
|
compileTTranslation(ast: ASTTranslation, ctx: Context): string | null {
|
||||||
if (ast.content) {
|
if (ast.content) {
|
||||||
this.compileAST(ast.content, Object.assign({}, ctx, { translate: false }));
|
return this.compileAST(ast.content, Object.assign({}, ctx, { translate: false }));
|
||||||
}
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
compileTPortal(ast: ASTTPortal, ctx: Context) {
|
compileTPortal(ast: ASTTPortal, ctx: Context): string {
|
||||||
if (!this.staticDefs.find((d) => d.id === "Portal")) {
|
if (!this.staticDefs.find((d) => d.id === "Portal")) {
|
||||||
this.staticDefs.push({ id: "Portal", expr: `app.Portal` });
|
this.staticDefs.push({ id: "Portal", expr: `app.Portal` });
|
||||||
}
|
}
|
||||||
@@ -1323,5 +1326,6 @@ export class CodeGenerator {
|
|||||||
}
|
}
|
||||||
block = this.createBlock(block, "multi", ctx);
|
block = this.createBlock(block, "multi", ctx);
|
||||||
this.insertBlock(blockString, block, { ...ctx, forceNewBlock: false });
|
this.insertBlock(blockString, block, { ...ctx, forceNewBlock: false });
|
||||||
|
return block.varName;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -334,6 +334,57 @@ exports[`t-call (template calling) inherit context 2`] = `
|
|||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`t-call (template calling) nested t-calls with magic variable 0 1`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
let { isBoundary, zero } = helpers;
|
||||||
|
const callTemplate_1 = app.getTemplate(\`grandchild\`);
|
||||||
|
const callTemplate_2 = app.getTemplate(\`child\`);
|
||||||
|
|
||||||
|
let block1 = createBlock(\`<p>Some content...</p>\`);
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
ctx = Object.create(ctx);
|
||||||
|
ctx[isBoundary] = 1;
|
||||||
|
ctx = Object.create(ctx);
|
||||||
|
ctx[isBoundary] = 1;
|
||||||
|
const b1 = block1();
|
||||||
|
ctx[zero] = b1;
|
||||||
|
const b2 = callTemplate_1.call(this, ctx, node, key + \`__1\`);
|
||||||
|
ctx = ctx.__proto__;
|
||||||
|
ctx[zero] = b2;
|
||||||
|
return callTemplate_2.call(this, ctx, node, key + \`__2\`);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`t-call (template calling) nested t-calls with magic variable 0 2`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
let { zero } = helpers;
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
const b2 = text(\`grandchild\`);
|
||||||
|
const b3 = ctx[zero];
|
||||||
|
return multi([b2, b3]);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`t-call (template calling) nested t-calls with magic variable 0 3`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
let { zero } = helpers;
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
return ctx[zero];
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`t-call (template calling) recursive template, part 1 1`] = `
|
exports[`t-call (template calling) recursive template, part 1 1`] = `
|
||||||
"function anonymous(app, bdom, helpers
|
"function anonymous(app, bdom, helpers
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -479,4 +479,21 @@ describe("t-call (template calling)", () => {
|
|||||||
"<span>123lucas</span>"
|
"<span>123lucas</span>"
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("nested t-calls with magic variable 0", () => {
|
||||||
|
const context = new TestContext();
|
||||||
|
context.addTemplate("grandchild", `grandchild<t t-out="0"/>`);
|
||||||
|
context.addTemplate("child", `<t t-out="0"/>`);
|
||||||
|
context.addTemplate(
|
||||||
|
"main",
|
||||||
|
`
|
||||||
|
<t t-call="child">
|
||||||
|
<t t-call="grandchild">
|
||||||
|
<p>Some content...</p>
|
||||||
|
</t>
|
||||||
|
</t>`
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(context.renderToString("main")).toBe("grandchild<p>Some content...</p>");
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user