diff --git a/CHANGELOG.md b/CHANGELOG.md index 45559953..9699a3a7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -66,6 +66,8 @@ - Fix formatting of props spread for multiline JSX expression https://github.com/rescript-lang/syntax/pull/736 - Fix issue with JSX V4 and newtype https://github.com/rescript-lang/syntax/pull/737 - Fix issue with JSX V4 when components are nested https://github.com/rescript-lang/syntax/pull/738 +- Improve code generated for default arguments in JSX V4 https://github.com/rescript-lang/syntax/pull/739 +- Fix issue with JSX V4 props of the form `~p as module(...)` https://github.com/rescript-lang/syntax/pull/739 #### :eyeglasses: Spec Compliance diff --git a/cli/JSXV4.md b/cli/JSXV4.md index 91280d3c..5967b75e 100644 --- a/cli/JSXV4.md +++ b/cli/JSXV4.md @@ -18,7 +18,7 @@ To build an entire project in V4 mode, including all its dependencies, use the n ### Dependency-level config 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. -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. +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. 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: @@ -264,7 +264,7 @@ let make = React.forwardRef({ ### Transformation for Component Definition ```rescript -@react.component (~x, ~y=3+x, ?z) => body +@react.component (~x, ~y=3+x, ~z=?) => body ``` is transformed to @@ -272,11 +272,13 @@ is transformed to ```rescript type props<'x, 'y, 'z> = {x: 'x, y?: 'y, z?: 'z} -({x, y, z}: props<_>) => { - let y = switch props.y { +({x, ?y, ?z}: props<_, _, _>) => { + let x = x + let y = switch y { | None => 3 + x | Some(y) => y } + let z = z body } ``` diff --git a/cli/reactjs_jsx_v4.ml b/cli/reactjs_jsx_v4.ml index 65447e85..e2afe36d 100644 --- a/cli/reactjs_jsx_v4.ml +++ b/cli/reactjs_jsx_v4.ml @@ -640,6 +640,7 @@ let rec recursivelyTransformNamedArgsForMake expr args newtypes coreType = in let type_ = match pattern with + | {ppat_desc = Ppat_constraint (_, {ptyp_desc = Ptyp_package _})} -> None | {ppat_desc = Ppat_constraint (_, type_)} -> Some type_ | _ -> None in @@ -843,39 +844,34 @@ let modifiedBinding ~bindingLoc ~bindingPatLoc ~fnName binding = in (wrapExpressionWithBinding wrapExpression, hasForwardRef, expression) -let vbMatch (name, default, _, alias, loc, _) = +let vbMatch ~expr (name, default, _, alias, loc, _) = let label = getLabel name in match default with | Some default -> - Vb.mk - (Pat.var (Location.mkloc alias loc)) - (Exp.match_ - (Exp.field - (Exp.ident {txt = Lident "props"; loc = Location.none}) - (Location.mknoloc @@ Lident label)) - [ - Exp.case - (Pat.construct - (Location.mknoloc @@ Lident "Some") - (Some (Pat.var (Location.mknoloc label)))) - (Exp.ident (Location.mknoloc @@ Lident label)); - Exp.case - (Pat.construct (Location.mknoloc @@ Lident "None") None) - default; - ]) - | None -> - Vb.mk - (Pat.var (Location.mkloc alias loc)) - (Exp.field - (Exp.ident {txt = Lident "props"; loc = Location.none}) - (Location.mknoloc @@ Lident label)) + let value_binding = + Vb.mk + (Pat.var (Location.mkloc alias loc)) + (Exp.match_ + (Exp.ident {txt = Lident alias; loc = Location.none}) + [ + Exp.case + (Pat.construct + (Location.mknoloc @@ Lident "Some") + (Some (Pat.var (Location.mknoloc label)))) + (Exp.ident (Location.mknoloc @@ Lident label)); + Exp.case + (Pat.construct (Location.mknoloc @@ Lident "None") None) + default; + ]) + in + Exp.let_ Nonrecursive [value_binding] expr + | None -> expr let vbMatchExpr namedArgList expr = let rec aux namedArgList = match namedArgList with | [] -> expr - | [namedArg] -> Exp.let_ Nonrecursive [vbMatch namedArg] expr - | namedArg :: rest -> Exp.let_ Nonrecursive [vbMatch namedArg] (aux rest) + | namedArg :: rest -> vbMatch namedArg ~expr:(aux rest) in aux (List.rev namedArgList) @@ -970,11 +966,10 @@ let mapBinding ~config ~emptyLoc ~pstr_loc ~fileName ~recFlag binding = in let rec stripConstraintUnpack ~label pattern = match pattern with + | {ppat_desc = Ppat_constraint (_, {ptyp_desc = Ptyp_package _})} -> + pattern | {ppat_desc = Ppat_constraint (pattern, _)} -> stripConstraintUnpack ~label pattern - | {ppat_desc = Ppat_unpack _; ppat_loc} -> - (* remove unpack e.g. model: module(T) *) - Pat.var ~loc:ppat_loc {txt = label; loc = ppat_loc} | _ -> pattern in let rec returnedExpression patternsWithLabel patternsWithNolabel @@ -1043,11 +1038,6 @@ let mapBinding ~config ~emptyLoc ~pstr_loc ~fileName ~recFlag binding = | [] -> Pat.any () | _ -> Pat.record (List.rev patternsWithLabel) Open in - let recordPattern = - if hasDefaultValue namedArgList then - Pat.var {txt = "props"; loc = emptyLoc} - else recordPattern - in let expression = Exp.fun_ Nolabel None (Pat.constraint_ recordPattern diff --git a/tests/ppx/react/aliasProps.res b/tests/ppx/react/aliasProps.res index c6951703..8c183b94 100644 --- a/tests/ppx/react/aliasProps.res +++ b/tests/ppx/react/aliasProps.res @@ -14,3 +14,30 @@ module C2 = { @react.component let make = (~foo as bar="") => React.string(bar) } + +module C3 = { + @react.component + let make = (~foo as bar="", ~a=bar, ~b) => { + React.string(bar ++ a ++ b) + } +} + +module C4 = { + @react.component + let make = (~a as b, ~x=true) =>