WARNING: THIS SITE IS A MIRROR OF GITHUB.COM / IT CANNOT LOGIN OR REGISTER ACCOUNTS / THE CONTENTS ARE PROVIDED AS-IS / THIS SITE ASSUMES NO RESPONSIBILITY FOR ANY DISPLAYED CONTENT OR LINKS / IF YOU FOUND SOMETHING MAY NOT GOOD FOR EVERYONE, CONTACT ADMIN AT ilovescratch@foxmail.com
Skip to content

Commit 034e254

Browse files
authored
Fix invalid JSX being generated for empty fragments (#8077)
* Fix invalid JSX being generated for empty fragments * Reduce code duplication * Added TODO * CHANGELOG
1 parent 0c49e79 commit 034e254

File tree

4 files changed

+21
-2
lines changed

4 files changed

+21
-2
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
- Fix signature matching for externals when abstract alias hides function arity. https://github.com/rescript-lang/rescript/pull/8045
2727
- Fix arity detection for arrows returning nested generics. https://github.com/rescript-lang/rescript/pull/8064
2828
- Fix error handling when rescript.json parsing fails and improve error message. https://github.com/rescript-lang/rescript/pull/8067
29+
- Fix invalid JSX being generated for empty fragments. https://github.com/rescript-lang/rescript/pull/8077
2930

3031
#### :memo: Documentation
3132

compiler/core/js_dump.ml

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1105,14 +1105,22 @@ and print_indented_list (f : P.t) (parent_expr_level : int) (cxt : cxt)
11051105
and print_jsx cxt ?(spread_props : J.expression option)
11061106
?(key : J.expression option) ~(level : int) f (fnName : string)
11071107
(tag : J.expression) (fields : (string * J.expression) list) : cxt =
1108+
(* TODO: make fragment detection respect custom JSX runtime modules instead of
1109+
assuming "JsxRuntime". *)
1110+
let is_fragment =
1111+
match tag.expression_desc with
1112+
| J.Var (J.Qualified ({id = {name = "JsxRuntime"}}, Some "Fragment")) ->
1113+
true
1114+
| _ -> false
1115+
in
11081116
let print_tag cxt =
11091117
match tag.expression_desc with
11101118
(* "div" or any other primitive tag *)
11111119
| J.Str {txt} ->
11121120
P.string f txt;
11131121
cxt
11141122
(* fragment *)
1115-
| J.Var (J.Qualified ({id = {name = "JsxRuntime"}}, Some "Fragment")) -> cxt
1123+
| _ when is_fragment -> cxt
11161124
(* A user defined component or external component *)
11171125
| _ -> expression ~level cxt f tag
11181126
in
@@ -1129,6 +1137,11 @@ and print_jsx cxt ?(spread_props : J.expression option)
11291137
else Some [e]
11301138
else None)
11311139
fields
1140+
(* For fragments without children we normalize to an empty list so they
1141+
print as <></> instead of </> which is invalid JSX. *)
1142+
|> function
1143+
| None when is_fragment -> Some []
1144+
| other -> other
11321145
in
11331146
let print_props cxt props =
11341147
(* 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)
11691182
match children_opt with
11701183
| Some _ -> cxt
11711184
| None ->
1172-
(* Put a space the tag name and /> *)
1185+
(* Put a space between the tag name and /> *)
11731186
P.space f;
11741187
cxt)
11751188
else

tests/tests/src/jsx_preserve_test.mjs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,8 @@ let _props_with_hyphen = <label
192192
data-testid={"test"}
193193
/>;
194194

195+
let _empty_fragment = <></>;
196+
195197
let _fragment = <>
196198
{"Hello, world!"}
197199
</>;
@@ -271,6 +273,7 @@ export {
271273
ComponentWithOptionalProps,
272274
_optional_props,
273275
_props_with_hyphen,
276+
_empty_fragment,
274277
_fragment,
275278
_youtube_iframe,
276279
X,

tests/tests/src/jsx_preserve_test.res

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,8 @@ let _optional_props = <ComponentWithOptionalProps i=1 s="test" element={<div />}
124124

125125
let _props_with_hyphen = <label ariaLabel={"close sidebar"} dataTestId="test" />
126126

127+
let _empty_fragment = <> </>
128+
127129
let _fragment = <> {Jsx.string("Hello, world!")} </>
128130

129131
let _youtube_iframe =

0 commit comments

Comments
 (0)