Skip to content
This repository was archived by the owner on Jun 15, 2023. It is now read-only.

Commit b725fb2

Browse files
committed
1 parent 21591c3 commit b725fb2

9 files changed

+152
-58
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@
6666
- Fix formatting of props spread for multiline JSX expression https://github.com/rescript-lang/syntax/pull/736
6767
- Fix issue with JSX V4 and newtype https://github.com/rescript-lang/syntax/pull/737
6868
- Fix issue with JSX V4 when components are nested https://github.com/rescript-lang/syntax/pull/738
69+
- Improve code generated for default arguments in JSX V4 https://github.com/rescript-lang/syntax/pull/739
70+
- Fix issue with JSX V4 props of the form `~p as module(...)` https://github.com/rescript-lang/syntax/pull/739
6971

7072
#### :eyeglasses: Spec Compliance
7173

cli/JSXV4.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ To build an entire project in V4 mode, including all its dependencies, use the n
1818
### Dependency-level config
1919

2020
Dependencies inherit the `jsx` configuration of the root project. So if the root project uses V4 then the dependencies are built using V4, and the same for V3.
21-
To build certain dependencies in V3 compatibility mode, whatever the version used in the root project, use `"v3-dependencies"`: the listed dependencies will be built in V3 mode, and in addition `-open ReatcV3` is added to the compiler options.
21+
To build certain dependencies in V3 compatibility mode, whatever the version used in the root project, use `"v3-dependencies"`: the listed dependencies will be built in V3 mode, and in addition `-open ReactV3` is added to the compiler options.
2222

2323
For example, suppose a V3 project uses rescript-react 0.11, which requires compatibility mode if compiled with V3, and that 2 dependencies `"rescript-react-native", "rescript-react-navigation"` only build with compatibility mode. Then the setting will be:
2424

@@ -264,19 +264,21 @@ let make = React.forwardRef({
264264
### Transformation for Component Definition
265265

266266
```rescript
267-
@react.component (~x, ~y=3+x, ?z) => body
267+
@react.component (~x, ~y=3+x, ~z=?) => body
268268
```
269269

270270
is transformed to
271271

272272
```rescript
273273
type props<'x, 'y, 'z> = {x: 'x, y?: 'y, z?: 'z}
274274
275-
({x, y, z}: props<_>) => {
276-
let y = switch props.y {
275+
({x, ?y, ?z}: props<_, _, _>) => {
276+
let x = x
277+
let y = switch y {
277278
| None => 3 + x
278279
| Some(y) => y
279280
}
281+
let z = z
280282
body
281283
}
282284
```

cli/reactjs_jsx_v4.ml

Lines changed: 23 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -640,6 +640,7 @@ let rec recursivelyTransformNamedArgsForMake expr args newtypes coreType =
640640
in
641641
let type_ =
642642
match pattern with
643+
| {ppat_desc = Ppat_constraint (_, {ptyp_desc = Ptyp_package _})} -> None
643644
| {ppat_desc = Ppat_constraint (_, type_)} -> Some type_
644645
| _ -> None
645646
in
@@ -843,39 +844,34 @@ let modifiedBinding ~bindingLoc ~bindingPatLoc ~fnName binding =
843844
in
844845
(wrapExpressionWithBinding wrapExpression, hasForwardRef, expression)
845846

846-
let vbMatch (name, default, _, alias, loc, _) =
847+
let vbMatch ~expr (name, default, _, alias, loc, _) =
847848
let label = getLabel name in
848849
match default with
849850
| Some default ->
850-
Vb.mk
851-
(Pat.var (Location.mkloc alias loc))
852-
(Exp.match_
853-
(Exp.field
854-
(Exp.ident {txt = Lident "props"; loc = Location.none})
855-
(Location.mknoloc @@ Lident label))
856-
[
857-
Exp.case
858-
(Pat.construct
859-
(Location.mknoloc @@ Lident "Some")
860-
(Some (Pat.var (Location.mknoloc label))))
861-
(Exp.ident (Location.mknoloc @@ Lident label));
862-
Exp.case
863-
(Pat.construct (Location.mknoloc @@ Lident "None") None)
864-
default;
865-
])
866-
| None ->
867-
Vb.mk
868-
(Pat.var (Location.mkloc alias loc))
869-
(Exp.field
870-
(Exp.ident {txt = Lident "props"; loc = Location.none})
871-
(Location.mknoloc @@ Lident label))
851+
let value_binding =
852+
Vb.mk
853+
(Pat.var (Location.mkloc alias loc))
854+
(Exp.match_
855+
(Exp.ident {txt = Lident alias; loc = Location.none})
856+
[
857+
Exp.case
858+
(Pat.construct
859+
(Location.mknoloc @@ Lident "Some")
860+
(Some (Pat.var (Location.mknoloc label))))
861+
(Exp.ident (Location.mknoloc @@ Lident label));
862+
Exp.case
863+
(Pat.construct (Location.mknoloc @@ Lident "None") None)
864+
default;
865+
])
866+
in
867+
Exp.let_ Nonrecursive [value_binding] expr
868+
| None -> expr
872869

873870
let vbMatchExpr namedArgList expr =
874871
let rec aux namedArgList =
875872
match namedArgList with
876873
| [] -> expr
877-
| [namedArg] -> Exp.let_ Nonrecursive [vbMatch namedArg] expr
878-
| namedArg :: rest -> Exp.let_ Nonrecursive [vbMatch namedArg] (aux rest)
874+
| namedArg :: rest -> vbMatch namedArg ~expr:(aux rest)
879875
in
880876
aux (List.rev namedArgList)
881877

@@ -970,11 +966,10 @@ let mapBinding ~config ~emptyLoc ~pstr_loc ~fileName ~recFlag binding =
970966
in
971967
let rec stripConstraintUnpack ~label pattern =
972968
match pattern with
969+
| {ppat_desc = Ppat_constraint (_, {ptyp_desc = Ptyp_package _})} ->
970+
pattern
973971
| {ppat_desc = Ppat_constraint (pattern, _)} ->
974972
stripConstraintUnpack ~label pattern
975-
| {ppat_desc = Ppat_unpack _; ppat_loc} ->
976-
(* remove unpack e.g. model: module(T) *)
977-
Pat.var ~loc:ppat_loc {txt = label; loc = ppat_loc}
978973
| _ -> pattern
979974
in
980975
let rec returnedExpression patternsWithLabel patternsWithNolabel
@@ -1043,11 +1038,6 @@ let mapBinding ~config ~emptyLoc ~pstr_loc ~fileName ~recFlag binding =
10431038
| [] -> Pat.any ()
10441039
| _ -> Pat.record (List.rev patternsWithLabel) Open
10451040
in
1046-
let recordPattern =
1047-
if hasDefaultValue namedArgList then
1048-
Pat.var {txt = "props"; loc = emptyLoc}
1049-
else recordPattern
1050-
in
10511041
let expression =
10521042
Exp.fun_ Nolabel None
10531043
(Pat.constraint_ recordPattern

tests/ppx/react/aliasProps.res

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,30 @@ module C2 = {
1414
@react.component
1515
let make = (~foo as bar="") => React.string(bar)
1616
}
17+
18+
module C3 = {
19+
@react.component
20+
let make = (~foo as bar="", ~a=bar, ~b) => {
21+
React.string(bar ++ a ++ b)
22+
}
23+
}
24+
25+
module C4 = {
26+
@react.component
27+
let make = (~a as b, ~x=true) => <div> b </div>
28+
}
29+
30+
module C5 = {
31+
@react.component
32+
let make = (~a as (x, y), ~z=3) => x + y + z
33+
}
34+
35+
module C6 = {
36+
module type Comp = {
37+
@react.component
38+
let make: unit => React.element
39+
}
40+
41+
@react.component
42+
let make = (~comp as module(Comp: Comp), ~x as (a, b)) => <Comp />
43+
}

tests/ppx/react/expected/aliasProps.res.txt

Lines changed: 82 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,8 @@
33
module C0 = {
44
type props<'priority, 'text> = {priority: 'priority, text?: 'text}
55

6-
let make = (props: props<_, _>) => {
7-
let _ = props.priority
8-
let text = switch props.text {
6+
let make = ({priority: _, ?text, _}: props<_, _>) => {
7+
let text = switch text {
98
| Some(text) => text
109
| None => "Test"
1110
}
@@ -22,9 +21,8 @@ module C0 = {
2221
module C1 = {
2322
type props<'priority, 'text> = {priority: 'priority, text?: 'text}
2423

25-
let make = (props: props<_, _>) => {
26-
let p = props.priority
27-
let text = switch props.text {
24+
let make = ({priority: p, ?text, _}: props<_, _>) => {
25+
let text = switch text {
2826
| Some(text) => text
2927
| None => "Test"
3028
}
@@ -41,8 +39,8 @@ module C1 = {
4139
module C2 = {
4240
type props<'foo> = {foo?: 'foo}
4341

44-
let make = (props: props<_>) => {
45-
let bar = switch props.foo {
42+
let make = ({foo: ?bar, _}: props<_>) => {
43+
let bar = switch bar {
4644
| Some(foo) => foo
4745
| None => ""
4846
}
@@ -55,3 +53,79 @@ module C2 = {
5553
\"AliasProps$C2"
5654
}
5755
}
56+
57+
module C3 = {
58+
type props<'foo, 'a, 'b> = {foo?: 'foo, a?: 'a, b: 'b}
59+
60+
let make = ({foo: ?bar, ?a, b, _}: props<_, _, _>) => {
61+
let bar = switch bar {
62+
| Some(foo) => foo
63+
| None => ""
64+
}
65+
let a = switch a {
66+
| Some(a) => a
67+
| None => bar
68+
}
69+
70+
{
71+
React.string(bar ++ a ++ b)
72+
}
73+
}
74+
let make = {
75+
let \"AliasProps$C3" = (props: props<_>) => make(props)
76+
77+
\"AliasProps$C3"
78+
}
79+
}
80+
81+
module C4 = {
82+
type props<'a, 'x> = {a: 'a, x?: 'x}
83+
84+
let make = ({a: b, ?x, _}: props<_, _>) => {
85+
let x = switch x {
86+
| Some(x) => x
87+
| None => true
88+
}
89+
90+
ReactDOM.jsx("div", {children: ?ReactDOM.someElement(b)})
91+
}
92+
let make = {
93+
let \"AliasProps$C4" = (props: props<_>) => make(props)
94+
95+
\"AliasProps$C4"
96+
}
97+
}
98+
99+
module C5 = {
100+
type props<'a, 'z> = {a: 'a, z?: 'z}
101+
102+
let make = ({a: (x, y), ?z, _}: props<_, _>) => {
103+
let z = switch z {
104+
| Some(z) => z
105+
| None => 3
106+
}
107+
108+
x + y + z
109+
}
110+
let make = {
111+
let \"AliasProps$C5" = (props: props<_>) => make(props)
112+
113+
\"AliasProps$C5"
114+
}
115+
}
116+
117+
module C6 = {
118+
module type Comp = {
119+
type props = {}
120+
121+
let make: React.componentLike<props, React.element>
122+
}
123+
type props<'comp, 'x> = {comp: 'comp, x: 'x}
124+
125+
let make = ({comp: module(Comp: Comp), x: (a, b), _}: props<_, _>) => React.jsx(Comp.make, {})
126+
let make = {
127+
let \"AliasProps$C6" = (props: props<_>) => make(props)
128+
129+
\"AliasProps$C6"
130+
}
131+
}

tests/ppx/react/expected/defaultValueProp.res.txt

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
module C0 = {
22
type props<'a, 'b> = {a?: 'a, b?: 'b}
3-
let make = (props: props<_, _>) => {
4-
let a = switch props.a {
3+
let make = ({?a, ?b, _}: props<_, _>) => {
4+
let a = switch a {
55
| Some(a) => a
66
| None => 2
77
}
8-
let b = switch props.b {
8+
let b = switch b {
99
| Some(b) => b
1010
| None => a * 2
1111
}
@@ -21,12 +21,11 @@ module C0 = {
2121
module C1 = {
2222
type props<'a, 'b> = {a?: 'a, b: 'b}
2323

24-
let make = (props: props<_, _>) => {
25-
let a = switch props.a {
24+
let make = ({?a, b, _}: props<_, _>) => {
25+
let a = switch a {
2626
| Some(a) => a
2727
| None => 2
2828
}
29-
let b = props.b
3029

3130
React.int(a + b)
3231
}

tests/ppx/react/expected/firstClassModules.res.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,8 @@ module Select = {
6666

6767
let make = (
6868
type a key,
69-
{model, selected, onChange, items, _}: props<
70-
module(T with type t = a and type key = key),
69+
{model: module(T: T with type t = a and type key = key), selected, onChange, items, _}: props<
70+
_,
7171
option<key>,
7272
option<key> => unit,
7373
array<a>,

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ module type T = {
6767
module V4A2 = {
6868
type props<'foo> = {foo: 'foo}
6969

70-
let make = (type a, {foo, _}: props<module(T with type t = a)>) => {
70+
let make = (type a, {foo: (foo: module(T with type t = a)), _}: props<_>) => {
7171
module T = unpack(foo)
7272
ReactDOM.jsx("div", {})
7373
}

tests/ppx/react/expected/uncurriedProps.res.txt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
@@jsxConfig({version: 4})
22
type props<'a> = {a?: 'a}
33

4-
let make = (props: props<(. unit) => unit>) => {
5-
let a = switch props.a {
4+
let make = ({?a, _}: props<(. unit) => unit>) => {
5+
let a = switch a {
66
| Some(a) => a
77
| None => (. ()) => ()
88
}
@@ -28,8 +28,8 @@ func(~callback=(. str, a, b) => {
2828
module Foo = {
2929
type props<'callback> = {callback?: 'callback}
3030

31-
let make = (props: props<(. string, bool, bool) => unit>) => {
32-
let callback = switch props.callback {
31+
let make = ({?callback, _}: props<(. string, bool, bool) => unit>) => {
32+
let callback = switch callback {
3333
| Some(callback) => callback
3434
| None => (. _, _, _) => ()
3535
}

0 commit comments

Comments
 (0)