diff --git a/src/compiler/code_generator.ts b/src/compiler/code_generator.ts index ec76367e..37051bea 100644 --- a/src/compiler/code_generator.ts +++ b/src/compiler/code_generator.ts @@ -160,7 +160,6 @@ interface Context { block: BlockDescription | null; index: number | string; forceNewBlock: boolean; - preventRoot?: boolean; isLast?: boolean; translate: boolean; tKeyExpr: string | null; @@ -377,7 +376,7 @@ export class CodeGenerator { ): BlockDescription { const hasRoot = this.target.hasRoot; const block = new BlockDescription(this.target, type); - if (!hasRoot && !ctx.preventRoot) { + if (!hasRoot) { this.target.hasRoot = true; block.isRoot = true; } @@ -403,7 +402,7 @@ export class CodeGenerator { blockExpr = `toggler(${ctx.tKeyExpr}, ${blockExpr})`; } - if (block.isRoot && !ctx.preventRoot) { + if (block.isRoot) { if (this.target.on) { blockExpr = this.wrapWithEventCatcher(blockExpr, this.target.on); } @@ -989,7 +988,6 @@ export class CodeGenerator { block, index, forceNewBlock: !isTSet, - preventRoot: ctx.preventRoot, isLast: ctx.isLast && i === l - 1, }); this.compileAST(child, subCtx); @@ -1025,24 +1023,24 @@ export class CodeGenerator { ctxVar = generateId("ctx"); this.addLine(`let ${ctxVar} = ${compileExpr(ast.context)};`); } + const isDynamic = INTERP_REGEXP.test(ast.name); + const subTemplate = isDynamic ? interpolate(ast.name) : "`" + ast.name + "`"; + if (block && !forceNewBlock) { + this.insertAnchor(block); + } + block = this.createBlock(block, "multi", ctx); if (ast.body) { this.addLine(`${ctxVar} = Object.create(${ctxVar});`); this.addLine(`${ctxVar}[isBoundary] = 1;`); this.helpers.add("isBoundary"); - const subCtx = createContext(ctx, { preventRoot: true, ctxVar }); + const subCtx = createContext(ctx, { ctxVar }); const bl = this.compileMulti({ type: ASTType.Multi, content: ast.body }, subCtx); if (bl) { this.helpers.add("zero"); this.addLine(`${ctxVar}[zero] = ${bl};`); } } - const isDynamic = INTERP_REGEXP.test(ast.name); - const subTemplate = isDynamic ? interpolate(ast.name) : "`" + ast.name + "`"; - if (block) { - if (!forceNewBlock) { - this.insertAnchor(block); - } - } + const key = `key + \`${this.generateComponentKey()}\``; if (isDynamic) { const templateVar = generateId("template"); @@ -1050,7 +1048,6 @@ export class CodeGenerator { this.staticDefs.push({ id: "call", expr: `app.callTemplate.bind(app)` }); } this.define(templateVar, subTemplate); - block = this.createBlock(block, "multi", ctx); this.insertBlock(`call(this, ${templateVar}, ${ctxVar}, node, ${key})`, block!, { ...ctx, forceNewBlock: !block, @@ -1058,7 +1055,6 @@ export class CodeGenerator { } else { const id = generateId(`callTemplate_`); this.staticDefs.push({ id, expr: `app.getTemplate(${subTemplate})` }); - block = this.createBlock(block, "multi", ctx); this.insertBlock(`${id}.call(this, ${ctxVar}, node, ${key})`, block!, { ...ctx, forceNewBlock: !block, diff --git a/tests/compiler/__snapshots__/misc.test.ts.snap b/tests/compiler/__snapshots__/misc.test.ts.snap index acca63db..2e4969c0 100644 --- a/tests/compiler/__snapshots__/misc.test.ts.snap +++ b/tests/compiler/__snapshots__/misc.test.ts.snap @@ -112,16 +112,16 @@ exports[`misc global 1`] = ` ctx = Object.create(ctx); ctx[isBoundary] = 1; setContextValue(ctx, \\"foo\\", 'aaa'); - const b6 = callTemplate_1.call(this, ctx, node, key + \`__1__\${key1}\`); + const b7 = callTemplate_1.call(this, ctx, node, key + \`__1__\${key1}\`); ctx = ctx.__proto__; - const b7 = callTemplate_2.call(this, ctx, node, key + \`__2__\${key1}\`); + const b8 = callTemplate_2.call(this, ctx, node, key + \`__2__\${key1}\`); setContextValue(ctx, \\"foo\\", 'bbb'); - const b8 = callTemplate_3.call(this, ctx, node, key + \`__3__\${key1}\`); - const b5 = multi([b6, b7, b8]); - ctx[zero] = b5; - const b9 = callTemplate_4.call(this, ctx, node, key + \`__4__\${key1}\`); + const b9 = callTemplate_3.call(this, ctx, node, key + \`__3__\${key1}\`); + const b6 = multi([b7, b8, b9]); + ctx[zero] = b6; + const b5 = callTemplate_4.call(this, ctx, node, key + \`__4__\${key1}\`); ctx = ctx.__proto__; - c_block2[i1] = withKey(multi([b4, b9]), key1); + c_block2[i1] = withKey(multi([b4, b5]), key1); } ctx = ctx.__proto__; const b2 = list(c_block2); diff --git a/tests/compiler/__snapshots__/t_call.test.ts.snap b/tests/compiler/__snapshots__/t_call.test.ts.snap index dd3fd2b3..1d2fbefc 100644 --- a/tests/compiler/__snapshots__/t_call.test.ts.snap +++ b/tests/compiler/__snapshots__/t_call.test.ts.snap @@ -61,19 +61,19 @@ exports[`t-call (template calling) call with several sub nodes on same line 1`] const callTemplate_1 = app.getTemplate(\`sub\`); let block1 = createBlock(\`
\`); - let block3 = createBlock(\`hey\`); - let block5 = createBlock(\`yay\`); + let block4 = createBlock(\`hey\`); + let block6 = createBlock(\`yay\`); return function template(ctx, node, key = \\"\\") { ctx = Object.create(ctx); ctx[isBoundary] = 1; - const b3 = block3(); - const b4 = text(\` \`); - const b5 = block5(); - const b2 = multi([b3, b4, b5]); - ctx[zero] = b2; - const b6 = callTemplate_1.call(this, ctx, node, key + \`__1\`); - return block1([], [b6]); + const b4 = block4(); + const b5 = text(\` \`); + const b6 = block6(); + const b3 = multi([b4, b5, b6]); + ctx[zero] = b3; + const b2 = callTemplate_1.call(this, ctx, node, key + \`__1\`); + return block1([], [b2]); } }" `; @@ -101,19 +101,19 @@ exports[`t-call (template calling) cascading t-call t-out='0' 1`] = ` const callTemplate_1 = app.getTemplate(\`subTemplate\`); let block1 = createBlock(\`
\`); - let block3 = createBlock(\`hey\`); - let block5 = createBlock(\`yay\`); + let block4 = createBlock(\`hey\`); + let block6 = createBlock(\`yay\`); return function template(ctx, node, key = \\"\\") { ctx = Object.create(ctx); ctx[isBoundary] = 1; - const b3 = block3(); - const b4 = text(\` \`); - const b5 = block5(); - const b2 = multi([b3, b4, b5]); - ctx[zero] = b2; - const b6 = callTemplate_1.call(this, ctx, node, key + \`__1\`); - return block1([], [b6]); + const b4 = block4(); + const b5 = text(\` \`); + const b6 = block6(); + const b3 = multi([b4, b5, b6]); + ctx[zero] = b3; + const b2 = callTemplate_1.call(this, ctx, node, key + \`__1\`); + return block1([], [b2]); } }" `; @@ -126,17 +126,17 @@ exports[`t-call (template calling) cascading t-call t-out='0' 2`] = ` const callTemplate_1 = app.getTemplate(\`subSubTemplate\`); let block1 = createBlock(\`
\`); - let block3 = createBlock(\`cascade 0\`); + let block4 = createBlock(\`cascade 0\`); return function template(ctx, node, key = \\"\\") { ctx = Object.create(ctx); ctx[isBoundary] = 1; - const b3 = block3(); - const b4 = ctx[zero]; - const b2 = multi([b3, b4]); - ctx[zero] = b2; - const b5 = callTemplate_1.call(this, ctx, node, key + \`__1\`); - return block1([], [b5]); + const b4 = block4(); + const b5 = ctx[zero]; + const b3 = multi([b4, b5]); + ctx[zero] = b3; + const b2 = callTemplate_1.call(this, ctx, node, key + \`__1\`); + return block1([], [b2]); } }" `; @@ -149,17 +149,17 @@ exports[`t-call (template calling) cascading t-call t-out='0' 3`] = ` const callTemplate_1 = app.getTemplate(\`finalTemplate\`); let block1 = createBlock(\`
\`); - let block3 = createBlock(\`cascade 1\`); + let block4 = createBlock(\`cascade 1\`); return function template(ctx, node, key = \\"\\") { ctx = Object.create(ctx); ctx[isBoundary] = 1; - const b3 = block3(); - const b4 = ctx[zero]; - const b2 = multi([b3, b4]); - ctx[zero] = b2; - const b5 = callTemplate_1.call(this, ctx, node, key + \`__1\`); - return block1([], [b5]); + const b4 = block4(); + const b5 = ctx[zero]; + const b3 = multi([b4, b5]); + ctx[zero] = b3; + const b2 = callTemplate_1.call(this, ctx, node, key + \`__1\`); + return block1([], [b2]); } }" `; @@ -186,17 +186,17 @@ exports[`t-call (template calling) cascading t-call t-out='0', without external let { isBoundary, zero } = helpers; const callTemplate_1 = app.getTemplate(\`subTemplate\`); - let block2 = createBlock(\`hey\`); - let block4 = createBlock(\`yay\`); + let block3 = createBlock(\`hey\`); + let block5 = createBlock(\`yay\`); return function template(ctx, node, key = \\"\\") { ctx = Object.create(ctx); ctx[isBoundary] = 1; - const b2 = block2(); - const b3 = text(\` \`); - const b4 = block4(); - const b1 = multi([b2, b3, b4]); - ctx[zero] = b1; + const b3 = block3(); + const b4 = text(\` \`); + const b5 = block5(); + const b2 = multi([b3, b4, b5]); + ctx[zero] = b2; return callTemplate_1.call(this, ctx, node, key + \`__1\`); } }" @@ -209,15 +209,15 @@ exports[`t-call (template calling) cascading t-call t-out='0', without external let { isBoundary, zero } = helpers; const callTemplate_1 = app.getTemplate(\`subSubTemplate\`); - let block2 = createBlock(\`cascade 0\`); + let block3 = createBlock(\`cascade 0\`); return function template(ctx, node, key = \\"\\") { ctx = Object.create(ctx); ctx[isBoundary] = 1; - const b2 = block2(); - const b3 = ctx[zero]; - const b1 = multi([b2, b3]); - ctx[zero] = b1; + const b3 = block3(); + const b4 = ctx[zero]; + const b2 = multi([b3, b4]); + ctx[zero] = b2; return callTemplate_1.call(this, ctx, node, key + \`__1\`); } }" @@ -230,15 +230,15 @@ exports[`t-call (template calling) cascading t-call t-out='0', without external let { isBoundary, zero } = helpers; const callTemplate_1 = app.getTemplate(\`finalTemplate\`); - let block2 = createBlock(\`cascade 1\`); + let block3 = createBlock(\`cascade 1\`); return function template(ctx, node, key = \\"\\") { ctx = Object.create(ctx); ctx[isBoundary] = 1; - const b2 = block2(); - const b3 = ctx[zero]; - const b1 = multi([b2, b3]); - ctx[zero] = b1; + const b3 = block3(); + const b4 = ctx[zero]; + const b2 = multi([b3, b4]); + ctx[zero] = b2; return callTemplate_1.call(this, ctx, node, key + \`__1\`); } }" @@ -342,15 +342,15 @@ exports[`t-call (template calling) nested t-calls with magic variable 0 1`] = ` const callTemplate_1 = app.getTemplate(\`grandchild\`); const callTemplate_2 = app.getTemplate(\`child\`); - let block1 = createBlock(\`

Some content...

\`); + let block3 = createBlock(\`

Some content...

\`); 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 b3 = block3(); + ctx[zero] = b3; const b2 = callTemplate_1.call(this, ctx, node, key + \`__1\`); ctx = ctx.__proto__; ctx[zero] = b2; @@ -571,6 +571,134 @@ exports[`t-call (template calling) recursive template, part 4: with t-set recurs }" `; +exports[`t-call (template calling) root t-call with body: t-foreach 1`] = ` +"function anonymous(app, bdom, helpers +) { + let { text, createBlock, list, multi, html, toggler, comment } = bdom; + let { isBoundary, prepareList, withKey, zero } = helpers; + const callTemplate_1 = app.getTemplate(\`subTemplate\`); + + return function template(ctx, node, key = \\"\\") { + ctx = Object.create(ctx); + ctx[isBoundary] = 1; + ctx = Object.create(ctx); + const [k_block2, v_block2, l_block2, c_block2] = prepareList([1]);; + for (let i1 = 0; i1 < l_block2; i1++) { + ctx[\`i\`] = k_block2[i1]; + const key1 = ctx['i']; + c_block2[i1] = withKey(text(\`1\`), key1); + } + ctx = ctx.__proto__; + const b2 = list(c_block2); + ctx[zero] = b2; + return callTemplate_1.call(this, ctx, node, key + \`__1\`); + } +}" +`; + +exports[`t-call (template calling) root t-call with body: t-foreach 2`] = ` +"function anonymous(app, bdom, helpers +) { + let { text, createBlock, list, multi, html, toggler, comment } = bdom; + + return function template(ctx, node, key = \\"\\") { + return text(\`sub\`); + } +}" +`; + +exports[`t-call (template calling) root t-call with body: t-if false 1`] = ` +"function anonymous(app, bdom, helpers +) { + let { text, createBlock, list, multi, html, toggler, comment } = bdom; + let { isBoundary, zero } = helpers; + const callTemplate_1 = app.getTemplate(\`subTemplate\`); + + return function template(ctx, node, key = \\"\\") { + ctx = Object.create(ctx); + ctx[isBoundary] = 1; + let b3; + if (false) { + b3 = text(\`zero\`); + } + const b2 = multi([b3]); + ctx[zero] = b2; + return callTemplate_1.call(this, ctx, node, key + \`__1\`); + } +}" +`; + +exports[`t-call (template calling) root t-call with body: t-if false 2`] = ` +"function anonymous(app, bdom, helpers +) { + let { text, createBlock, list, multi, html, toggler, comment } = bdom; + + return function template(ctx, node, key = \\"\\") { + return text(\`sub\`); + } +}" +`; + +exports[`t-call (template calling) root t-call with body: t-if true 1`] = ` +"function anonymous(app, bdom, helpers +) { + let { text, createBlock, list, multi, html, toggler, comment } = bdom; + let { isBoundary, zero } = helpers; + const callTemplate_1 = app.getTemplate(\`subTemplate\`); + + return function template(ctx, node, key = \\"\\") { + ctx = Object.create(ctx); + ctx[isBoundary] = 1; + let b3; + if (true) { + b3 = text(\`zero\`); + } + const b2 = multi([b3]); + ctx[zero] = b2; + return callTemplate_1.call(this, ctx, node, key + \`__1\`); + } +}" +`; + +exports[`t-call (template calling) root t-call with body: t-if true 2`] = ` +"function anonymous(app, bdom, helpers +) { + let { text, createBlock, list, multi, html, toggler, comment } = bdom; + + return function template(ctx, node, key = \\"\\") { + return text(\`sub\`); + } +}" +`; + +exports[`t-call (template calling) root t-call with body: t-out with default 1`] = ` +"function anonymous(app, bdom, helpers +) { + let { text, createBlock, list, multi, html, toggler, comment } = bdom; + let { isBoundary, safeOutput, zero } = helpers; + const callTemplate_1 = app.getTemplate(\`subTemplate\`); + + return function template(ctx, node, key = \\"\\") { + ctx = Object.create(ctx); + ctx[isBoundary] = 1; + const b2 = safeOutput(ctx['nothing']); + ctx[zero] = b2; + return callTemplate_1.call(this, ctx, node, key + \`__1\`); + } +}" +`; + +exports[`t-call (template calling) root t-call with body: t-out with default 2`] = ` +"function anonymous(app, bdom, helpers +) { + let { text, createBlock, list, multi, html, toggler, comment } = bdom; + + return function template(ctx, node, key = \\"\\") { + return text(\`sub\`); + } +}" +`; + exports[`t-call (template calling) scoped parameters 1`] = ` "function anonymous(app, bdom, helpers ) { @@ -705,13 +833,13 @@ exports[`t-call (template calling) t-call with body content as root of a templat let { isBoundary, zero } = helpers; const callTemplate_1 = app.getTemplate(\`antony\`); - let block1 = createBlock(\`

antony

\`); + let block2 = createBlock(\`

antony

\`); return function template(ctx, node, key = \\"\\") { ctx = Object.create(ctx); ctx[isBoundary] = 1; - const b1 = block1(); - ctx[zero] = b1; + const b2 = block2(); + ctx[zero] = b2; return callTemplate_1.call(this, ctx, node, key + \`__1\`); } }" @@ -1075,8 +1203,8 @@ exports[`t-call (template calling) with unused body 1`] = ` return function template(ctx, node, key = \\"\\") { ctx = Object.create(ctx); ctx[isBoundary] = 1; - const b1 = text(\`WHEEE\`); - ctx[zero] = b1; + const b2 = text(\`WHEEE\`); + ctx[zero] = b2; return callTemplate_1.call(this, ctx, node, key + \`__1\`); } }" @@ -1136,8 +1264,8 @@ exports[`t-call (template calling) with used body 1`] = ` return function template(ctx, node, key = \\"\\") { ctx = Object.create(ctx); ctx[isBoundary] = 1; - const b1 = text(\`ok\`); - ctx[zero] = b1; + const b2 = text(\`ok\`); + ctx[zero] = b2; return callTemplate_1.call(this, ctx, node, key + \`__1\`); } }" diff --git a/tests/compiler/__snapshots__/t_esc.test.ts.snap b/tests/compiler/__snapshots__/t_esc.test.ts.snap index 290cc58c..e5a165ba 100644 --- a/tests/compiler/__snapshots__/t_esc.test.ts.snap +++ b/tests/compiler/__snapshots__/t_esc.test.ts.snap @@ -180,15 +180,15 @@ exports[`t-esc t-esc=0 is escaped 1`] = ` const callTemplate_1 = app.getTemplate(\`sub\`); let block1 = createBlock(\`
\`); - let block2 = createBlock(\`

escaped

\`); + let block3 = createBlock(\`

escaped

\`); return function template(ctx, node, key = \\"\\") { ctx = Object.create(ctx); ctx[isBoundary] = 1; - const b2 = block2(); - ctx[zero] = b2; - const b3 = callTemplate_1.call(this, ctx, node, key + \`__1\`); - return block1([], [b3]); + const b3 = block3(); + ctx[zero] = b3; + const b2 = callTemplate_1.call(this, ctx, node, key + \`__1\`); + return block1([], [b2]); } }" `; diff --git a/tests/compiler/__snapshots__/t_out.test.ts.snap b/tests/compiler/__snapshots__/t_out.test.ts.snap index 49ec6d67..12e07734 100644 --- a/tests/compiler/__snapshots__/t_out.test.ts.snap +++ b/tests/compiler/__snapshots__/t_out.test.ts.snap @@ -35,15 +35,15 @@ exports[`t-out multiple calls to t-out 1`] = ` const callTemplate_1 = app.getTemplate(\`sub\`); let block1 = createBlock(\`
\`); - let block2 = createBlock(\`coucou\`); + let block3 = createBlock(\`coucou\`); return function template(ctx, node, key = \\"\\") { ctx = Object.create(ctx); ctx[isBoundary] = 1; - const b2 = block2(); - ctx[zero] = b2; - const b3 = callTemplate_1.call(this, ctx, node, key + \`__1\`); - return block1([], [b3]); + const b3 = block3(); + ctx[zero] = b3; + const b2 = callTemplate_1.call(this, ctx, node, key + \`__1\`); + return block1([], [b2]); } }" `; @@ -102,15 +102,15 @@ exports[`t-out t-out 0 1`] = ` const callTemplate_1 = app.getTemplate(\`_basic-callee\`); let block1 = createBlock(\`
\`); - let block2 = createBlock(\`
zero
\`); + let block3 = createBlock(\`
zero
\`); return function template(ctx, node, key = \\"\\") { ctx = Object.create(ctx); ctx[isBoundary] = 1; - const b2 = block2(); - ctx[zero] = b2; - const b3 = callTemplate_1.call(this, ctx, node, key + \`__1\`); - return block1([], [b3]); + const b3 = block3(); + ctx[zero] = b3; + const b2 = callTemplate_1.call(this, ctx, node, key + \`__1\`); + return block1([], [b2]); } }" `; diff --git a/tests/compiler/t_call.test.ts b/tests/compiler/t_call.test.ts index b0ac1571..227cfb8c 100644 --- a/tests/compiler/t_call.test.ts +++ b/tests/compiler/t_call.test.ts @@ -430,6 +430,48 @@ describe("t-call (template calling)", () => { expect(context.renderToString("main")).toBe(expected); }); + test("root t-call with body: t-if true", () => { + const context = new TestContext(); + const subTemplate = `sub`; + const main = `zero`; + context.addTemplate("subTemplate", subTemplate); + context.addTemplate("main", main); + const expected = "sub"; + expect(context.renderToString("main")).toBe(expected); + }); + + test("root t-call with body: t-if false", () => { + const context = new TestContext(); + const subTemplate = `sub`; + const main = `zero`; + context.addTemplate("subTemplate", subTemplate); + context.addTemplate("main", main); + const expected = "sub"; + expect(context.renderToString("main")).toBe(expected); + }); + + test("root t-call with body: t-out with default", () => { + const context = new TestContext(); + const subTemplate = `sub`; + const main = `default`; + context.addTemplate("subTemplate", subTemplate); + context.addTemplate("main", main); + const expected = "sub"; + expect(context.renderToString("main")).toBe(expected); + }); + + test("root t-call with body: t-foreach", () => { + const context = new TestContext(); + const subTemplate = `sub`; + const main = ` + 1 + `; + context.addTemplate("subTemplate", subTemplate); + context.addTemplate("main", main); + const expected = "sub"; + expect(context.renderToString("main")).toBe(expected); + }); + test("dynamic t-call", () => { const context = new TestContext(); const foo = ``; diff --git a/tests/components/__snapshots__/t_call.test.ts.snap b/tests/components/__snapshots__/t_call.test.ts.snap index ee43b15c..5eb05c16 100644 --- a/tests/components/__snapshots__/t_call.test.ts.snap +++ b/tests/components/__snapshots__/t_call.test.ts.snap @@ -10,8 +10,8 @@ exports[`t-call dynamic t-call 1`] = ` return function template(ctx, node, key = \\"\\") { ctx = Object.create(ctx); ctx[isBoundary] = 1; - const b1 = text(\` owl \`); - ctx[zero] = b1; + const b2 = text(\` owl \`); + ctx[zero] = b2; const template1 = (ctx['current'].template); return call(this, template1, ctx, node, key + \`__1\`); }