From 164489fbb2a5e84498b55e39f84c23cbbbda2f03 Mon Sep 17 00:00:00 2001 From: Matthew Phillips Date: Fri, 23 Jul 2021 13:00:49 -0400 Subject: [PATCH] Correctly serialize falsey values at top-level of components (#834) * Correctly serialize falsey values at top-level of components * Adding a changeset --- .changeset/healthy-pants-rule.md | 5 +++ packages/astro/src/internal/h.ts | 36 ++++++++++--------- packages/astro/test/astro-expr.test.js | 6 ++++ .../astro-expr/src/components/falsy.astro | 23 ++++++++++++ .../fixtures/astro-expr/src/pages/falsy.astro | 7 ++++ 5 files changed, 61 insertions(+), 16 deletions(-) create mode 100644 .changeset/healthy-pants-rule.md create mode 100644 packages/astro/test/fixtures/astro-expr/src/components/falsy.astro diff --git a/.changeset/healthy-pants-rule.md b/.changeset/healthy-pants-rule.md new file mode 100644 index 000000000..d265f96f7 --- /dev/null +++ b/.changeset/healthy-pants-rule.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +Fix for `false` being rendered in conditionals diff --git a/packages/astro/src/internal/h.ts b/packages/astro/src/internal/h.ts index 470597999..411b743fd 100644 --- a/packages/astro/src/internal/h.ts +++ b/packages/astro/src/internal/h.ts @@ -5,6 +5,23 @@ export type HTag = string | AstroComponent; const voidTags = new Set(['area', 'base', 'br', 'col', 'command', 'embed', 'hr', 'img', 'input', 'keygen', 'link', 'meta', 'param', 'source', 'track', 'wbr']); +function* _children(children: Array) { + for (let child of children) { + // Special: If a child is a function, call it automatically. + // This lets you do {() => ...} without the extra boilerplate + // of wrapping it in a function and calling it. + if (typeof child === 'function') { + yield child(); + } else if (typeof child === 'string') { + yield child; + } else if (!child && child !== 0) { + // do nothing, safe to ignore falsey values. + } else { + yield child; + } + } +} + /** Generator for primary h() function */ function* _h(tag: string, attrs: HProps, children: Array) { if (tag.toLowerCase() === '!doctype') { @@ -32,20 +49,7 @@ function* _h(tag: string, attrs: HProps, children: Array) { return; } - for (let child of children) { - // Special: If a child is a function, call it automatically. - // This lets you do {() => ...} without the extra boilerplate - // of wrapping it in a function and calling it. - if (typeof child === 'function') { - yield child(); - } else if (typeof child === 'string') { - yield child; - } else if (!child && child !== 0) { - // do nothing, safe to ignore falsey values. - } else { - yield child; - } - } + yield * _children(children); yield ``; } @@ -62,6 +66,6 @@ export async function h(tag: HTag, attrs: HProps, ...pChildren: Array) { - return children.join(''); +export function Fragment(_: HProps, ...children: Array) { + return Array.from(_children(children)).join(''); } diff --git a/packages/astro/test/astro-expr.test.js b/packages/astro/test/astro-expr.test.js index 10d1909a4..87764b4e4 100644 --- a/packages/astro/test/astro-expr.test.js +++ b/packages/astro/test/astro-expr.test.js @@ -80,6 +80,12 @@ Expressions('Does not render falsy values using &&', async ({ runtime }) => { assert.equal($('#false').length, 0, `Expected {false && } not to render`); assert.equal($('#null').length, 0, `Expected {null && } not to render`); assert.equal($('#undefined').length, 0, `Expected {undefined && } not to render`); + + // Inside of a component + assert.equal($('#frag-true').length, 1, `Expected {true && } to render`); + assert.equal($('#frag-false').length, 0, `Expected {false && } not to render`); + assert.equal($('#frag-null').length, 0, `Expected {null && } not to render`); + assert.equal($('#frag-undefined').length, 0, `Expected {undefined && } not to render`); }); Expressions.run(); diff --git a/packages/astro/test/fixtures/astro-expr/src/components/falsy.astro b/packages/astro/test/fixtures/astro-expr/src/components/falsy.astro new file mode 100644 index 000000000..544deaf7b --- /dev/null +++ b/packages/astro/test/fixtures/astro-expr/src/components/falsy.astro @@ -0,0 +1,23 @@ +--- +const { items, emptyItems } = Astro.props; + +const internal = []; +--- + + +{false && ( + +)} + + +{null && ( + +)} + + +{true && ( + +)} + + +{false && ()} \ No newline at end of file diff --git a/packages/astro/test/fixtures/astro-expr/src/pages/falsy.astro b/packages/astro/test/fixtures/astro-expr/src/pages/falsy.astro index 294f71684..39c56e252 100644 --- a/packages/astro/test/fixtures/astro-expr/src/pages/falsy.astro +++ b/packages/astro/test/fixtures/astro-expr/src/pages/falsy.astro @@ -1,3 +1,6 @@ +--- +import Falsey from '../components/falsy.astro'; +--- My site @@ -8,5 +11,9 @@ {undefined && } {true && } {0 && "VALUE"} + +
+ +