Skip to content

Commit 2aab005

Browse files
committed
Native: keep labeled-arg make, use old-style JSX calls
On native, don't generate the makeProps/wrapper pattern for [@react.component]. Keep make with its original labeled-arg signature for backward compatibility with .rei files, .ml call sites, and first-class modules. Native JSX now generates old-style labeled-arg calls (Component.make ~prop1:v1 ~children:... ()) instead of Component.make(Component.makeProps(~prop1:v1, ...)).
1 parent 7fa29cb commit 2aab005

3 files changed

Lines changed: 24 additions & 36 deletions

File tree

packages/server-reason-react-ppx/server_reason_react_ppx.ml

Lines changed: 22 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,8 @@ let component_make_props_ident tag =
9999

100100
let is_key_arg (label, _) = match label with Optional "key" | Labelled "key" -> true | _ -> false
101101

102-
let rewrite_component ~loc tag args children =
102+
(* JSX rewrite for JS/melange: Component.make(Component.makeProps(~prop1:v1, ...)) *)
103+
let rewrite_component_js ~loc tag args children =
103104
let component = pexp_ident ~loc tag in
104105
let props_args =
105106
match children with
@@ -116,6 +117,22 @@ let rewrite_component ~loc tag args children =
116117
in
117118
pexp_apply ~loc component make_args
118119

120+
(* JSX rewrite for native: Component.make(~prop1:v1, ~children:..., ()) -- old-style labeled args *)
121+
let rewrite_component_native ~loc tag args children =
122+
let component = pexp_ident ~loc tag in
123+
let props_args =
124+
match children with
125+
| None -> args
126+
| Some [ children ] -> (Labelled "children", children) :: args
127+
| Some children -> (Labelled "children", [%expr React.list [%e pexp_list ~loc children]]) :: args
128+
in
129+
pexp_apply ~loc component (props_args @ [ (Nolabel, [%expr ()]) ])
130+
131+
let rewrite_component ~loc tag args children =
132+
match mode.contents with
133+
| Js -> rewrite_component_js ~loc tag args children
134+
| Native -> rewrite_component_native ~loc tag args children
135+
119136
let validate_prop ~loc id name =
120137
match DomProps.findByJsxName ~tag:id name with
121138
| Ok p -> p
@@ -1356,41 +1373,14 @@ let rewrite_structure_item ~nested_module_names structure_item =
13561373
else None
13571374
in
13581375
let rewrites = List.map value_bindings ~f:rewrite_component_binding in
1359-
let make_props_bindings =
1360-
List.filter_map rewrites ~f:(function
1361-
| Some (_, make_props_binding, _) -> Some make_props_binding
1362-
| None -> None)
1363-
in
1364-
let public_bindings =
1365-
List.filter_map rewrites ~f:(function Some (_, _, public_binding) -> Some public_binding | None -> None)
1366-
in
13671376
let internal_bindings =
13681377
List.map2 value_bindings rewrites ~f:(fun vb rewrite ->
13691378
match rewrite with Some (internal_binding, _, _) -> internal_binding | None -> vb)
13701379
in
1371-
match make_props_bindings with
1372-
| [] -> pstr_value ~loc:structure_item.pstr_loc rec_flag internal_bindings
1373-
| _ -> (
1374-
let loc = structure_item.pstr_loc in
1375-
(* Propagate non-react attributes from the original bindings to the
1376-
include struct. This ensures attributes like [@platform js] or
1377-
[@browser_only] are visible to subsequent ppxes (e.g. browser_ppx) so they can drop the entire include when needed. *)
1378-
let propagated_attrs =
1379-
List.concat_map value_bindings ~f:(fun vb ->
1380-
List.filter vb.pvb_attributes ~f:(fun attr -> not (is_react_attr attr)))
1381-
in
1382-
let include_stri =
1383-
[%stri
1384-
include struct
1385-
[%%i pstr_value ~loc:structure_item.pstr_loc Nonrecursive make_props_bindings]
1386-
[%%i pstr_value ~loc:structure_item.pstr_loc rec_flag internal_bindings]
1387-
[%%i pstr_value ~loc:structure_item.pstr_loc Nonrecursive public_bindings]
1388-
end]
1389-
in
1390-
match (propagated_attrs, include_stri.pstr_desc) with
1391-
| _ :: _, Pstr_include incl ->
1392-
{ include_stri with pstr_desc = Pstr_include { incl with pincl_attributes = propagated_attrs } }
1393-
| _ -> include_stri)
1380+
(* On native, keep make with labeled args (no wrapper) for backward
1381+
compatibility with .rei files, .ml call sites, and first-class modules.
1382+
Native JSX uses old-style labeled arg calls, so makeProps/wrapper aren't needed. *)
1383+
pstr_value ~loc:structure_item.pstr_loc rec_flag internal_bindings
13941384
with Error err -> pstr_eval ~loc:structure_item.pstr_loc err [])
13951385
| _ -> structure_item
13961386

tasks/plan-08-action-formdata-protocol-progressive-ench.md

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -111,11 +111,9 @@ React's client-side `encodeFormAction` callback converts a server reference into
111111
- [ ] Replace the `useActionState` stub in `packages/react/src/React.ml:878` with a real implementation that works with the form state protocol.
112112
- [ ] This enables progressive enhancement for stateful form actions (showing optimistic updates, handling errors).
113113

114-
### Phase 6: Bound server references (optional, future)
114+
### Phase 6: Bound server references → moved to plan-12
115115

116-
- [ ] Support `$ACTION_REF_` for bound server references (server functions with pre-filled arguments via `.bind()`).
117-
- [ ] This requires changes to `Runtime.server_function` to carry a `bound` field and to the PPX to support partial application of server functions.
118-
- [ ] The `action_to_json` function in `ReactServerDOM.ml:198` currently always emits `"bound": null`; this would need to emit the bound arguments when present.
116+
Moved to `tasks/plan-12-bound-server-references.md`. Includes `$ACTION_REF_` support, `encode_bound` on `Runtime.server_function`, and PPX changes for partial application.
119117

120118
## Design
121119

File renamed without changes.

0 commit comments

Comments
 (0)