Skip to content

Commit e8d2f97

Browse files
authored
Fix dropping attributes of props in JSX v4 (#5905)
1 parent 4b269fb commit e8d2f97

File tree

4 files changed

+157
-19
lines changed

4 files changed

+157
-19
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,11 @@ These are only breaking changes for unformatted code.
6262

6363
# 10.1.1
6464

65+
#### :boom: Breaking Change
66+
67+
- The prop names duplicated to keyword are not mangled automatically in JSX v4.
68+
- Use `@as` instead
69+
6570
#### :rocket: New Feature
6671

6772
- Add support for empty inlined record literal `{}` for inlined records where all fields are optional https://github.com/rescript-lang/rescript-compiler/pull/5900
@@ -71,6 +76,7 @@ These are only breaking changes for unformatted code.
7176
- Prevent inlining of async functions in additional cases https://github.com/rescript-lang/rescript-compiler/issues/5860
7277
- Fix build error where aliasing arguments to `_` in the make function with JSX V4. https://github.com/rescript-lang/rescript-compiler/pull/5881
7378
- Fix parsing of spread props as an expression in JSX V4 https://github.com/rescript-lang/rescript-compiler/pull/5885
79+
- Fix dropping attributes from props in make function in JSX V4 https://github.com/rescript-lang/rescript-compiler/pull/5905
7480

7581
# 10.1.0
7682

res_syntax/src/reactjs_jsx_v4.ml

Lines changed: 30 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -289,14 +289,15 @@ let makePropsTypeParams ?(stripExplicitOption = false)
289289

290290
let makeLabelDecls ~loc namedTypeList =
291291
namedTypeList
292-
|> List.map (fun (isOptional, label, _, interiorType) ->
292+
|> List.map (fun (isOptional, label, attrs, interiorType) ->
293293
if label = "key" then
294-
Type.field ~loc ~attrs:optionalAttrs {txt = label; loc} interiorType
294+
Type.field ~loc ~attrs:(optionalAttrs @ attrs) {txt = label; loc}
295+
interiorType
295296
else if isOptional then
296-
Type.field ~loc ~attrs:optionalAttrs {txt = label; loc}
297+
Type.field ~loc ~attrs:(optionalAttrs @ attrs) {txt = label; loc}
297298
(Typ.var @@ safeTypeFromValue @@ Labelled label)
298299
else
299-
Type.field ~loc {txt = label; loc}
300+
Type.field ~loc ~attrs {txt = label; loc}
300301
(Typ.var @@ safeTypeFromValue @@ Labelled label))
301302

302303
let makeTypeDecls propsName loc namedTypeList =
@@ -681,7 +682,9 @@ let newtypeToVar newtype type_ =
681682
mapper.typ mapper type_
682683

683684
let argToType ~newtypes ~(typeConstraints : core_type option) types
684-
(name, default, _noLabelName, _alias, loc, type_) =
685+
((name, default, {ppat_attributes = attrs}, _alias, loc, type_) :
686+
arg_label * expression option * pattern * label * 'loc * core_type option)
687+
=
685688
let rec getType name coreType =
686689
match coreType with
687690
| {ptyp_desc = Ptyp_arrow (arg, c1, c2)} ->
@@ -699,28 +702,29 @@ let argToType ~newtypes ~(typeConstraints : core_type option) types
699702
in
700703
match (type_, name, default) with
701704
| Some type_, name, _ when isOptional name ->
702-
(true, getLabel name, [], {type_ with ptyp_attributes = optionalAttrs})
705+
(true, getLabel name, attrs, {type_ with ptyp_attributes = optionalAttrs})
703706
:: types
704-
| Some type_, name, _ -> (false, getLabel name, [], type_) :: types
707+
| Some type_, name, _ -> (false, getLabel name, attrs, type_) :: types
705708
| None, name, _ when isOptional name ->
706709
( true,
707710
getLabel name,
708-
[],
711+
attrs,
709712
Typ.var ~loc ~attrs:optionalAttrs (safeTypeFromValue name) )
710713
:: types
711714
| None, name, _ when isLabelled name ->
712-
(false, getLabel name, [], Typ.var ~loc (safeTypeFromValue name)) :: types
715+
(false, getLabel name, attrs, Typ.var ~loc (safeTypeFromValue name))
716+
:: types
713717
| _ -> types
714718

715719
let argWithDefaultValue (name, default, _, _, _, _) =
716720
match default with
717721
| Some default when isOptional name -> Some (getLabel name, default)
718722
| _ -> None
719723

720-
let argToConcreteType types (name, _loc, type_) =
724+
let argToConcreteType types (name, attrs, _loc, type_) =
721725
match name with
722-
| name when isLabelled name -> (false, getLabel name, [], type_) :: types
723-
| name when isOptional name -> (true, getLabel name, [], type_) :: types
726+
| name when isLabelled name -> (false, getLabel name, attrs, type_) :: types
727+
| name when isOptional name -> (true, getLabel name, attrs, type_) :: types
724728
| _ -> types
725729

726730
let check_string_int_attribute_iter =
@@ -763,15 +767,19 @@ let transformStructureItem ~config mapper item =
763767
|> Option.map React_jsx_common.typVarsOfCoreType
764768
|> Option.value ~default:[]
765769
in
766-
let rec getPropTypes types ({ptyp_loc; ptyp_desc} as fullType) =
770+
let rec getPropTypes types
771+
({ptyp_loc; ptyp_desc; ptyp_attributes} as fullType) =
767772
match ptyp_desc with
768773
| Ptyp_arrow (name, type_, ({ptyp_desc = Ptyp_arrow _} as rest))
769774
when isLabelled name || isOptional name ->
770-
getPropTypes ((name, ptyp_loc, type_) :: types) rest
775+
getPropTypes
776+
((name, ptyp_attributes, ptyp_loc, type_) :: types)
777+
rest
771778
| Ptyp_arrow (Nolabel, _type, rest) -> getPropTypes types rest
772779
| Ptyp_arrow (name, type_, returnValue)
773780
when isLabelled name || isOptional name ->
774-
(returnValue, (name, returnValue.ptyp_loc, type_) :: types)
781+
( returnValue,
782+
(name, ptyp_attributes, returnValue.ptyp_loc, type_) :: types )
775783
| _ -> (fullType, types)
776784
in
777785
let innerType, propTypes = getPropTypes [] pval_type in
@@ -1264,19 +1272,22 @@ let transformSignatureItem ~config _mapper item =
12641272
in
12651273
let rec getPropTypes types ({ptyp_loc; ptyp_desc} as fullType) =
12661274
match ptyp_desc with
1267-
| Ptyp_arrow (name, type_, ({ptyp_desc = Ptyp_arrow _} as rest))
1275+
| Ptyp_arrow
1276+
( name,
1277+
({ptyp_attributes = attrs} as type_),
1278+
({ptyp_desc = Ptyp_arrow _} as rest) )
12681279
when isOptional name || isLabelled name ->
1269-
getPropTypes ((name, ptyp_loc, type_) :: types) rest
1280+
getPropTypes ((name, attrs, ptyp_loc, type_) :: types) rest
12701281
| Ptyp_arrow
12711282
(Nolabel, {ptyp_desc = Ptyp_constr ({txt = Lident "unit"}, _)}, rest)
12721283
->
12731284
getPropTypes types rest
12741285
| Ptyp_arrow (Nolabel, _type, rest) ->
12751286
hasForwardRef := true;
12761287
getPropTypes types rest
1277-
| Ptyp_arrow (name, type_, returnValue)
1288+
| Ptyp_arrow (name, ({ptyp_attributes = attrs} as type_), returnValue)
12781289
when isOptional name || isLabelled name ->
1279-
(returnValue, (name, returnValue.ptyp_loc, type_) :: types)
1290+
(returnValue, (name, attrs, returnValue.ptyp_loc, type_) :: types)
12801291
| _ -> (fullType, types)
12811292
in
12821293
let innerType, propTypes = getPropTypes [] pval_type in
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
@@jsxConfig({version: 3})
2+
3+
module C30 = {
4+
@obj external makeProps: (~_open: 'T_open, ~key: string=?, unit) => {"_open": 'T_open} = ""
5+
6+
@react.component let make = @warning("-16") (~_open) => React.string(_open)
7+
let make = {
8+
let \"MangleKeyword$C30" = (\"Props": {"_open": 'T_open}) => make(~_open=\"Props"["_open"])
9+
\"MangleKeyword$C30"
10+
}
11+
}
12+
module C31 = {
13+
@obj external makeProps: (~_open: string, ~key: string=?, unit) => {"_open": string} = ""
14+
external make: React.componentLike<{"_open": string}, React.element> = "default"
15+
}
16+
17+
let c30 = React.createElement(C30.make, C30.makeProps(~_open="x", ()))
18+
let c31 = React.createElement(C31.make, C31.makeProps(~_open="x", ()))
19+
20+
@@jsxConfig({version: 4, mode: "classic"})
21+
22+
module C4C0 = {
23+
type props<'T_open, 'T_type> = {
24+
@as("open") _open: 'T_open,
25+
@as("type") _type: 'T_type,
26+
}
27+
28+
@react.component
29+
let make = ({@as("open") _open, @as("type") _type, _}: props<'T_open, string>) =>
30+
React.string(_open)
31+
let make = {
32+
let \"MangleKeyword$C4C0" = (props: props<_>) => make(props)
33+
34+
\"MangleKeyword$C4C0"
35+
}
36+
}
37+
module C4C1 = {
38+
type props<'T_open, 'T_type> = {
39+
@as("open") _open: 'T_open,
40+
@as("type") _type: 'T_type,
41+
}
42+
43+
external make: @as("open") React.componentLike<props<string, string>, React.element> = "default"
44+
}
45+
46+
let c4c0 = React.createElement(C4C0.make, {_open: "x", _type: "t"})
47+
let c4c1 = React.createElement(C4C1.make, {_open: "x", _type: "t"})
48+
49+
@@jsxConfig({version: 4, mode: "automatic"})
50+
51+
module C4A0 = {
52+
type props<'T_open, 'T_type> = {
53+
@as("open") _open: 'T_open,
54+
@as("type") _type: 'T_type,
55+
}
56+
57+
@react.component
58+
let make = ({@as("open") _open, @as("type") _type, _}: props<'T_open, string>) =>
59+
React.string(_open)
60+
let make = {
61+
let \"MangleKeyword$C4A0" = (props: props<_>) => make(props)
62+
63+
\"MangleKeyword$C4A0"
64+
}
65+
}
66+
module C4A1 = {
67+
type props<'T_open, 'T_type> = {
68+
@as("open") _open: 'T_open,
69+
@as("type") _type: 'T_type,
70+
}
71+
72+
external make: @as("open") React.componentLike<props<string, string>, React.element> = "default"
73+
}
74+
75+
let c4a0 = React.jsx(C4A0.make, {_open: "x", _type: "t"})
76+
let c4a1 = React.jsx(C4A1.make, {_open: "x", _type: "t"})
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
@@jsxConfig({version: 3})
2+
3+
module C30 = {
4+
@react.component
5+
let make = (~_open) => React.string(_open)
6+
}
7+
module C31 = {
8+
@react.component
9+
external make: (~_open: string) => React.element = "default"
10+
}
11+
12+
let c30 = <C30 _open="x" />
13+
let c31 = <C31 _open="x" />
14+
15+
@@jsxConfig({version: 4, mode: "classic"})
16+
17+
module C4C0 = {
18+
@react.component
19+
let make =
20+
(@as("open") ~_open, @as("type") ~_type: string) => React.string(_open)
21+
}
22+
module C4C1 = {
23+
@react.component
24+
external make: (@as("open") ~_open: string, @as("type") ~_type: string) => React.element =
25+
"default"
26+
}
27+
28+
let c4c0 = <C4C0 _open="x" _type="t" />
29+
let c4c1 = <C4C1 _open="x" _type="t" />
30+
31+
@@jsxConfig({version: 4, mode: "automatic"})
32+
33+
module C4A0 = {
34+
@react.component
35+
let make =
36+
(@as("open") ~_open, @as("type") ~_type: string) => React.string(_open)
37+
}
38+
module C4A1 = {
39+
@react.component
40+
external make: (@as("open") ~_open: string, @as("type") ~_type: string) => React.element =
41+
"default"
42+
}
43+
44+
let c4a0 = <C4A0 _open="x" _type="t" />
45+
let c4a1 = <C4A1 _open="x" _type="t" />

0 commit comments

Comments
 (0)