diff --git a/CHANGELOG.md b/CHANGELOG.md index 744da2a53e..861c9cb811 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,7 @@ - Fix signature matching for externals when abstract alias hides function arity. https://github.com/rescript-lang/rescript/pull/8045 - Fix arity detection for arrows returning nested generics. https://github.com/rescript-lang/rescript/pull/8064 - Fix error handling when rescript.json parsing fails and improve error message. https://github.com/rescript-lang/rescript/pull/8067 +- Fix invalid JSX being generated for empty fragments. https://github.com/rescript-lang/rescript/pull/8077 #### :memo: Documentation diff --git a/compiler/core/js_dump.ml b/compiler/core/js_dump.ml index ea1c3d5fda..43967a3f1c 100644 --- a/compiler/core/js_dump.ml +++ b/compiler/core/js_dump.ml @@ -1105,6 +1105,14 @@ and print_indented_list (f : P.t) (parent_expr_level : int) (cxt : cxt) and print_jsx cxt ?(spread_props : J.expression option) ?(key : J.expression option) ~(level : int) f (fnName : string) (tag : J.expression) (fields : (string * J.expression) list) : cxt = + (* TODO: make fragment detection respect custom JSX runtime modules instead of + assuming "JsxRuntime". *) + let is_fragment = + match tag.expression_desc with + | J.Var (J.Qualified ({id = {name = "JsxRuntime"}}, Some "Fragment")) -> + true + | _ -> false + in let print_tag cxt = match tag.expression_desc with (* "div" or any other primitive tag *) @@ -1112,7 +1120,7 @@ and print_jsx cxt ?(spread_props : J.expression option) P.string f txt; cxt (* fragment *) - | J.Var (J.Qualified ({id = {name = "JsxRuntime"}}, Some "Fragment")) -> cxt + | _ when is_fragment -> cxt (* A user defined component or external component *) | _ -> expression ~level cxt f tag in @@ -1129,6 +1137,11 @@ and print_jsx cxt ?(spread_props : J.expression option) else Some [e] else None) fields + (* For fragments without children we normalize to an empty list so they + print as <> instead of which is invalid JSX. *) + |> function + | None when is_fragment -> Some [] + | other -> other in let print_props cxt props = (* If a key is present, should be printed before the spread props, @@ -1169,7 +1182,7 @@ and print_jsx cxt ?(spread_props : J.expression option) match children_opt with | Some _ -> cxt | None -> - (* Put a space the tag name and /> *) + (* Put a space between the tag name and /> *) P.space f; cxt) else diff --git a/tests/tests/src/jsx_preserve_test.mjs b/tests/tests/src/jsx_preserve_test.mjs index 3622e7901d..570ca4607c 100644 --- a/tests/tests/src/jsx_preserve_test.mjs +++ b/tests/tests/src/jsx_preserve_test.mjs @@ -192,6 +192,8 @@ let _props_with_hyphen =