Skip to content

Commit e3ad8b0

Browse files
committed
fix export of JSX components inside module with regular functions
1 parent 18c14c7 commit e3ad8b0

File tree

11 files changed

+99
-5
lines changed

11 files changed

+99
-5
lines changed

compiler/syntax/src/jsx_common.ml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@ type jsx_config = {
77
mutable nested_modules: string list;
88
mutable has_component: bool;
99
mutable hoisted_structure_items: structure_item list;
10+
(* Nesting depth of [structure] calls while rewriting one implementation.
11+
Used so we only clear/append hoisted items at the true file root — not for
12+
nested [Pmod_structure] reached from expression traversal (e.g. via
13+
[module_expr]), which would otherwise see [nested_modules = []] and wipe
14+
hoisted bindings added for earlier structure items. *)
15+
mutable structure_depth: int;
1016
}
1117

1218
(* Helper method to look up the [@react.component] attribute *)

compiler/syntax/src/jsx_ppx.ml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,8 @@ let get_mapper ~config =
117117
in
118118
let structure mapper items =
119119
let old_config = save_config () in
120-
let is_top_level = config.nested_modules = [] in
120+
let is_top_level = config.structure_depth = 0 in
121+
config.structure_depth <- config.structure_depth + 1;
121122
config.has_component <- false;
122123
if is_top_level then config.hoisted_structure_items <- [];
123124
let result =
@@ -136,6 +137,7 @@ let get_mapper ~config =
136137
result @ List.rev config.hoisted_structure_items
137138
else result
138139
in
140+
config.structure_depth <- config.structure_depth - 1;
139141
restore_config old_config;
140142
result
141143
in
@@ -151,6 +153,7 @@ let rewrite_implementation ~jsx_version ~jsx_module (code : Parsetree.structure)
151153
nested_modules = [];
152154
has_component = false;
153155
hoisted_structure_items = [];
156+
structure_depth = 0;
154157
}
155158
in
156159
let mapper = get_mapper ~config in
@@ -165,6 +168,7 @@ let rewrite_signature ~jsx_version ~jsx_module (code : Parsetree.signature) :
165168
nested_modules = [];
166169
has_component = false;
167170
hoisted_structure_items = [];
171+
structure_depth = 0;
168172
}
169173
in
170174
let mapper = get_mapper ~config in

tests/build_tests/react_ppx/src/gpr_3695_test.res.js

Lines changed: 7 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/build_tests/react_ppx/src/gpr_3987_test.res.js

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/build_tests/react_ppx/src/issue_7917_test.res.js

Lines changed: 4 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/build_tests/rsc_nested_jsx_deep/input.js

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,27 @@ assert.match(
3131
);
3232

3333
const brandIcons = await import("./src/BrandIcons.res.js");
34-
assert.match(Object.keys(brandIcons).join(", "), /ReScript, BrandIcons\$ReScript, BrandIcons\$ReScript\$jsx, getIconForLanguageExtension/);
34+
assert.deepStrictEqual(
35+
new Set(Object.keys(brandIcons)),
36+
new Set([
37+
"ReScript",
38+
"BrandIcons$ReScript",
39+
"BrandIcons$ReScript$jsx",
40+
"getIconForLanguageExtension",
41+
]),
42+
);
43+
44+
const multipleNested = await import("./src/MultipleNested.res.js");
45+
assert.deepStrictEqual(
46+
new Set(Object.keys(multipleNested)),
47+
new Set([
48+
"Group",
49+
"MultipleNested$Group",
50+
"MultipleNested$Group$jsx",
51+
"Other",
52+
"MultipleNested$Other",
53+
"MultipleNested$Other$jsx",
54+
]),
55+
);
3556

3657
await execClean();

tests/build_tests/rsc_nested_jsx_deep/src/BrandIcons.res

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,9 @@ module ReScript = {
33
let make = () => React.null
44
}
55

6-
76
let getIconForLanguageExtension = (language: string) => {
87
switch language {
9-
| "res" | "rescript" => <ReScript />
8+
| "res" | "rescript" => <ReScript />
109
| _ => React.null
1110
}
1211
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
module Group = {
2+
@react.component
3+
let make = (~children) => {
4+
children
5+
}
6+
}
7+
8+
module Other = {
9+
@react.component
10+
let make = (~children) => {
11+
children
12+
}
13+
}

tests/syntax_tests/data/ppx/react/expected/newtype.res.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,4 +99,8 @@ module Uncurried = {
9999
\"Newtype$Uncurried"
100100
}
101101
}
102+
let \"Newtype$V4A" = V4A.make and \"Newtype$V4A$jsx" = true
103+
let \"Newtype$V4A1" = V4A1.make and \"Newtype$V4A1$jsx" = true
104+
let \"Newtype$V4A2" = V4A2.make and \"Newtype$V4A2$jsx" = true
105+
let \"Newtype$V4A3" = V4A3.make and \"Newtype$V4A3$jsx" = true
102106
let \"Newtype$Uncurried" = Uncurried.make and \"Newtype$Uncurried$jsx" = true

tests/syntax_tests/data/ppx/react/expected/v4.res.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ module Rec2 = {
116116
}
117117
and mm = x => make(x)
118118
}
119+
let \"V4$Uncurried" = Uncurried.make and \"V4$Uncurried$jsx" = true
119120
let \"V4$E" = E.make and \"V4$E$jsx" = true
120121
let \"V4$EUncurried" = EUncurried.make and \"V4$EUncurried$jsx" = true
121122
let \"V4$Rec" = Rec.make and \"V4$Rec$jsx" = true

0 commit comments

Comments
 (0)