From d6667ddf2e6e4eeda2335737f697034c175b5043 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A9ry=20Debongnie?= Date: Tue, 28 Jun 2022 13:21:01 +0200 Subject: [PATCH] [FIX] fix some issues with t-out with falsy values, and with default value --- src/compiler/code_generator.ts | 20 +++++--- src/runtime/template_helpers.ts | 6 +-- .../compiler/__snapshots__/t_esc.test.ts.snap | 36 ++++++++++++++ .../compiler/__snapshots__/t_out.test.ts.snap | 47 +++++++++++++++++-- tests/compiler/t_esc.test.ts | 15 ++++++ tests/compiler/t_out.test.ts | 15 ++++++ .../__snapshots__/basics.test.ts.snap | 12 +++++ tests/components/basics.test.ts | 21 +++++++++ 8 files changed, 158 insertions(+), 14 deletions(-) diff --git a/src/compiler/code_generator.ts b/src/compiler/code_generator.ts index 6bb513ff..fd3b6d6d 100644 --- a/src/compiler/code_generator.ts +++ b/src/compiler/code_generator.ts @@ -754,16 +754,22 @@ export class CodeGenerator { this.insertAnchor(block); } block = this.createBlock(block, "html", ctx); - this.helpers.add(ast.expr === "0" ? "zero" : "safeOutput"); - let expr = ast.expr === "0" ? "ctx[zero]" : `safeOutput(${compileExpr(ast.expr)})`; - if (ast.body) { - const nextId = BlockDescription.nextBlockId; + let blockStr; + if (ast.expr === "0") { + this.helpers.add("zero"); + blockStr = `ctx[zero]`; + } else if (ast.body) { + let bodyValue = null; + bodyValue = BlockDescription.nextBlockId; const subCtx: Context = createContext(ctx); this.compileAST({ type: ASTType.Multi, content: ast.body }, subCtx); - this.helpers.add("withDefault"); - expr = `withDefault(${expr}, b${nextId})`; + this.helpers.add("safeOutput"); + blockStr = `safeOutput(${compileExpr(ast.expr)}, b${bodyValue})`; + } else { + this.helpers.add("safeOutput"); + blockStr = `safeOutput(${compileExpr(ast.expr)})`; } - this.insertBlock(`${expr}`, block, ctx); + this.insertBlock(blockStr, block, ctx); } compileTIf(ast: ASTTif, ctx: Context, nextNode?: ASTDomNode) { diff --git a/src/runtime/template_helpers.ts b/src/runtime/template_helpers.ts index 0e7e5e2c..4164d26a 100644 --- a/src/runtime/template_helpers.ts +++ b/src/runtime/template_helpers.ts @@ -129,9 +129,9 @@ class LazyValue { /* * Safely outputs `value` as a block depending on the nature of `value` */ -export function safeOutput(value: any): ReturnType { - if (!value) { - return value; +export function safeOutput(value: any, defaultValue?: any): ReturnType { + if (value === undefined) { + return defaultValue ? toggler("default", defaultValue) : toggler("undefined", text("")); } let safeKey; let block; diff --git a/tests/compiler/__snapshots__/t_esc.test.ts.snap b/tests/compiler/__snapshots__/t_esc.test.ts.snap index b0263bd7..b264b276 100644 --- a/tests/compiler/__snapshots__/t_esc.test.ts.snap +++ b/tests/compiler/__snapshots__/t_esc.test.ts.snap @@ -133,6 +133,31 @@ exports[`t-esc t-esc is escaped 1`] = ` }" `; +exports[`t-esc t-esc with the 0 number 1`] = ` +"function anonymous(app, bdom, helpers +) { + let { text, createBlock, list, multi, html, toggler, comment } = bdom; + + return function template(ctx, node, key = \\"\\") { + return text(ctx['var']); + } +}" +`; + +exports[`t-esc t-esc with the 0 number, in a p 1`] = ` +"function anonymous(app, bdom, helpers +) { + let { text, createBlock, list, multi, html, toggler, comment } = bdom; + + let block1 = createBlock(\`

\`); + + return function template(ctx, node, key = \\"\\") { + let txt1 = ctx['var']; + return block1([txt1]); + } +}" +`; + exports[`t-esc t-esc work with spread operator 1`] = ` "function anonymous(app, bdom, helpers ) { @@ -183,6 +208,17 @@ exports[`t-esc t-esc=0 is escaped 2`] = ` }" `; +exports[`t-esc top level t-esc with undefined 1`] = ` +"function anonymous(app, bdom, helpers +) { + let { text, createBlock, list, multi, html, toggler, comment } = bdom; + + return function template(ctx, node, key = \\"\\") { + return text(ctx['var']); + } +}" +`; + exports[`t-esc variable 1`] = ` "function anonymous(app, bdom, helpers ) { diff --git a/tests/compiler/__snapshots__/t_out.test.ts.snap b/tests/compiler/__snapshots__/t_out.test.ts.snap index 61fa4789..097889fb 100644 --- a/tests/compiler/__snapshots__/t_out.test.ts.snap +++ b/tests/compiler/__snapshots__/t_out.test.ts.snap @@ -217,13 +217,13 @@ exports[`t-out t-out on a node with a body, as a default 1`] = ` "function anonymous(app, bdom, helpers ) { let { text, createBlock, list, multi, html, toggler, comment } = bdom; - let { safeOutput, withDefault } = helpers; + let { safeOutput } = helpers; let block1 = createBlock(\`\`); return function template(ctx, node, key = \\"\\") { const b3 = text(\`nope\`); - const b2 = withDefault(safeOutput(ctx['var']), b3); + const b2 = safeOutput(ctx['var'], b3); return block1([], [b2]); } }" @@ -233,14 +233,14 @@ exports[`t-out t-out on a node with a dom node in body, as a default 1`] = ` "function anonymous(app, bdom, helpers ) { let { text, createBlock, list, multi, html, toggler, comment } = bdom; - let { safeOutput, withDefault } = helpers; + let { safeOutput } = helpers; let block1 = createBlock(\`\`); let block3 = createBlock(\`
nope
\`); return function template(ctx, node, key = \\"\\") { const b3 = block3(); - const b2 = withDefault(safeOutput(ctx['var']), b3); + const b2 = safeOutput(ctx['var'], b3); return block1([], [b2]); } }" @@ -407,6 +407,45 @@ exports[`t-out t-out with just a t-set t-value in body 1`] = ` }" `; +exports[`t-out t-out with the 0 number 1`] = ` +"function anonymous(app, bdom, helpers +) { + let { text, createBlock, list, multi, html, toggler, comment } = bdom; + let { safeOutput } = helpers; + + return function template(ctx, node, key = \\"\\") { + return safeOutput(ctx['var']); + } +}" +`; + +exports[`t-out t-out with the 0 number, in a p 1`] = ` +"function anonymous(app, bdom, helpers +) { + let { text, createBlock, list, multi, html, toggler, comment } = bdom; + let { safeOutput } = helpers; + + let block1 = createBlock(\`

\`); + + return function template(ctx, node, key = \\"\\") { + const b2 = safeOutput(ctx['var']); + return block1([], [b2]); + } +}" +`; + +exports[`t-out top level t-out with undefined 1`] = ` +"function anonymous(app, bdom, helpers +) { + let { text, createBlock, list, multi, html, toggler, comment } = bdom; + let { safeOutput } = helpers; + + return function template(ctx, node, key = \\"\\") { + return safeOutput(ctx['var']); + } +}" +`; + exports[`t-out variable 1`] = ` "function anonymous(app, bdom, helpers ) { diff --git a/tests/compiler/t_esc.test.ts b/tests/compiler/t_esc.test.ts index 0f076fed..ba9003fc 100644 --- a/tests/compiler/t_esc.test.ts +++ b/tests/compiler/t_esc.test.ts @@ -67,6 +67,21 @@ describe("t-esc", () => { ); }); + test("t-esc with the 0 number", () => { + const template = ``; + expect(renderToString(template, { var: 0 })).toBe("0"); + }); + + test("t-esc with the 0 number, in a p", () => { + const template = `

`; + expect(renderToString(template, { var: 0 })).toBe("

0

"); + }); + + test("top level t-esc with undefined", () => { + const template = ``; + expect(renderToString(template, { var: undefined })).toBe(""); + }); + test("falsy values in text nodes", () => { const template = ` ::::`; diff --git a/tests/compiler/t_out.test.ts b/tests/compiler/t_out.test.ts index ad0e086c..3718dae7 100644 --- a/tests/compiler/t_out.test.ts +++ b/tests/compiler/t_out.test.ts @@ -47,6 +47,21 @@ describe("t-out", () => { expect(renderToString(template, { var: new String("ok") })).toBe("ok"); }); + test("t-out with the 0 number", () => { + const template = ``; + expect(renderToString(template, { var: 0 })).toBe("0"); + }); + + test("t-out with the 0 number, in a p", () => { + const template = `

`; + expect(renderToString(template, { var: 0 })).toBe("

0

"); + }); + + test("top level t-out with undefined", () => { + const template = ``; + expect(renderToString(template, { var: undefined })).toBe(""); + }); + test("with an extended String class", () => { class LoveString extends String { valueOf(): string { diff --git a/tests/components/__snapshots__/basics.test.ts.snap b/tests/components/__snapshots__/basics.test.ts.snap index c0adbd3f..2a75d381 100644 --- a/tests/components/__snapshots__/basics.test.ts.snap +++ b/tests/components/__snapshots__/basics.test.ts.snap @@ -1308,6 +1308,18 @@ exports[`t-out in components can switch the contents of two t-out repeatedly 1`] }" `; +exports[`t-out in components t-out and updating falsy values, 1`] = ` +"function anonymous(app, bdom, helpers +) { + let { text, createBlock, list, multi, html, toggler, comment } = bdom; + let { safeOutput } = helpers; + + return function template(ctx, node, key = \\"\\") { + return safeOutput(ctx['state'].a); + } +}" +`; + exports[`t-out in components update properly on state changes 1`] = ` "function anonymous(app, bdom, helpers ) { diff --git a/tests/components/basics.test.ts b/tests/components/basics.test.ts index 66e72d14..d8d9daa5 100644 --- a/tests/components/basics.test.ts +++ b/tests/components/basics.test.ts @@ -1084,4 +1084,25 @@ describe("t-out in components", () => { await nextTick(); expect(fixture.innerHTML).toBe("
1
2
"); }); + + test("t-out and updating falsy values, ", async () => { + class Test extends Component { + static template = xml``; + state: any = useState({ a: 0 }); + } + + const comp = await mount(Test, fixture); + expect(fixture.innerHTML).toBe("0"); + comp.state.a = undefined; + await nextTick(); + expect(fixture.innerHTML).toBe(""); + + comp.state.a = "hello" + await nextTick(); + expect(fixture.innerHTML).toBe("hello"); + + comp.state.a = false; + await nextTick(); + expect(fixture.innerHTML).toBe("false"); + }); });