diff --git a/compiler/packages/babel-plugin-react-forget/src/ReactiveScopes/CodegenReactiveFunction.ts b/compiler/packages/babel-plugin-react-forget/src/ReactiveScopes/CodegenReactiveFunction.ts index d3f83236fc..67cc064a67 100644 --- a/compiler/packages/babel-plugin-react-forget/src/ReactiveScopes/CodegenReactiveFunction.ts +++ b/compiler/packages/babel-plugin-react-forget/src/ReactiveScopes/CodegenReactiveFunction.ts @@ -1280,12 +1280,15 @@ function codegenJsxAttribute( let value; switch (innerValue.type) { case "StringLiteral": - case "JSXElement": - case "JSXFragment": { + case "JSXElement": { value = innerValue; break; } default: { + // NOTE JSXFragment is technically allowed as an attribute value per the spec + // but many tools do not support this case. We emit fragments wrapped in an + // expression container for compatibility purposes. + // spec: https://github.com/facebook/jsx/blob/main/AST.md#jsx-attributes value = createJsxExpressionContainer(attribute.place.loc, innerValue); break; } diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/jsx-attribute-with-jsx-fragment-value.flow.expect.md b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/jsx-attribute-with-jsx-fragment-value.flow.expect.md new file mode 100644 index 0000000000..e6c996a4f4 --- /dev/null +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/jsx-attribute-with-jsx-fragment-value.flow.expect.md @@ -0,0 +1,80 @@ + +## Input + +```javascript +// @flow +function Component({items}) { + // Per the spec, {...} /> is valid. + // But many tools don't allow fragments as jsx attribute values, + // so we ensure not to emit them wrapped in an expression container + return items.length > 0 + ? ( + {items.map(item => )} + }> + ) + : null; +} + +function Foo({item}) { + return
{item.name}
; +} + +export const FIXTURE_ENTRYPOINT = { + fn: Component, + params: [{items: [{id: 1, name: 'One!'}]}], +}; +``` + +## Code + +```javascript +import { unstable_useMemoCache as useMemoCache } from "react"; +function Component(t26) { + const $ = useMemoCache(2); + const { items } = t26; + const c_0 = $[0] !== items; + let t0; + if (c_0) { + t0 = + items.length > 0 ? ( + + {items.map((item) => ( + + ))} + + } + /> + ) : null; + $[0] = items; + $[1] = t0; + } else { + t0 = $[1]; + } + return t0; +} + +function Foo(t7) { + const $ = useMemoCache(2); + const { item } = t7; + const c_0 = $[0] !== item.name; + let t0; + if (c_0) { + t0 =
{item.name}
; + $[0] = item.name; + $[1] = t0; + } else { + t0 = $[1]; + } + return t0; +} + +export const FIXTURE_ENTRYPOINT = { + fn: Component, + params: [{ items: [{ id: 1, name: "One!" }] }], +}; + +``` + \ No newline at end of file diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/jsx-attribute-with-jsx-fragment-value.flow.js b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/jsx-attribute-with-jsx-fragment-value.flow.js new file mode 100644 index 0000000000..f9d6aa2c61 --- /dev/null +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/jsx-attribute-with-jsx-fragment-value.flow.js @@ -0,0 +1,22 @@ +// @flow +function Component({items}) { + // Per the spec, {...} /> is valid. + // But many tools don't allow fragments as jsx attribute values, + // so we ensure not to emit them wrapped in an expression container + return items.length > 0 + ? ( + {items.map(item => )} + }> + ) + : null; +} + +function Foo({item}) { + return
{item.name}
; +} + +export const FIXTURE_ENTRYPOINT = { + fn: Component, + params: [{items: [{id: 1, name: 'One!'}]}], +}; \ No newline at end of file