Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
- Add builtin abstract types for File and Blob APIs. https://github.com/rescript-lang/rescript-compiler/pull/6383
- Untagged variants: Support `promise`, RegExes, Dates, File and Blob. https://github.com/rescript-lang/rescript-compiler/pull/6383
- Support aliased types as payloads to untagged variants. https://github.com/rescript-lang/rescript-compiler/pull/6394
- Support the async component for React Server Component in JSX V4. https://github.com/rescript-lang/rescript-compiler/pull/6399

#### :nail_care: Polish

Expand Down
File renamed without changes.
File renamed without changes.
2 changes: 2 additions & 0 deletions jscomp/others/jsxPPXReactSupportC.res
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,5 @@ let createElementWithKey = (~key=?, component, props) =>

let createElementVariadicWithKey = (~key=?, component, props, elements) =>
createElementVariadic(component, addKeyProp(~key?, props), elements)

external asyncComponent: promise<Jsx.element> => Jsx.element = "%identity"
2 changes: 2 additions & 0 deletions jscomp/others/jsxPPXReactSupportU.res
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,5 @@ let createElementWithKey = (~key=?, component, props) =>

let createElementVariadicWithKey = (~key=?, component, props, elements) =>
createElementVariadic(component, addKeyProp(~key?, props), elements)

external asyncComponent: promise<Jsx.element> => Jsx.element = "%identity"
15 changes: 15 additions & 0 deletions jscomp/syntax/src/react_jsx_common.ml
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,18 @@ let removeArity binding =
| _ -> expr
in
{binding with pvb_expr = removeArityRecord binding.pvb_expr}

let is_async : Parsetree.attribute -> bool =
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would you move this function too?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does it look? 9d283ba
I moved is_async and is_await to ast_async and ast_await instead of moving ast_attributes.ml to ml. If we are going to move ast_attributes.ml, then other modules need to be moved too such as external_arg_spec.ml, bs_syntaxerr.ml. I think that is a bit too much.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great.
Good to merge

fun ({txt}, _) -> txt = "async" || txt = "res.async"

let async_component ~async expr =
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should not move as it's specific to the ppx

if async then
let open Ast_helper in
Exp.apply
(Exp.ident
{
loc = Location.none;
txt = Ldot (Lident "JsxPPXReactSupport", "asyncComponent");
})
[(Nolabel, expr)]
else expr
9 changes: 9 additions & 0 deletions jscomp/syntax/src/reactjs_jsx_v4.ml
Original file line number Diff line number Diff line change
Expand Up @@ -909,6 +909,11 @@ let mapBinding ~config ~emptyLoc ~pstr_loc ~fileName ~recFlag binding =
let bindingWrapper, hasForwardRef, expression =
modifiedBinding ~bindingLoc ~bindingPatLoc ~fnName binding
in
let isAsync =
Ext_list.find_first binding.pvb_expr.pexp_attributes
React_jsx_common.is_async
|> Option.is_some
in
(* do stuff here! *)
let namedArgList, newtypes, _typeConstraints =
recursivelyTransformNamedArgsForMake
Expand Down Expand Up @@ -942,6 +947,9 @@ let mapBinding ~config ~emptyLoc ~pstr_loc ~fileName ~recFlag binding =
(Pat.var @@ Location.mknoloc "props")
(Typ.constr (Location.mknoloc @@ Lident "props") [Typ.any ()])
in
let innerExpression =
React_jsx_common.async_component ~async:isAsync innerExpression
in
let fullExpression =
(* React component name should start with uppercase letter *)
(* let make = { let \"App" = props => make(props); \"App" } *)
Expand Down Expand Up @@ -1083,6 +1091,7 @@ let mapBinding ~config ~emptyLoc ~pstr_loc ~fileName ~recFlag binding =
| _ -> [Typ.any ()]))))
expression
in
let expression = Ast_async.add_async_attribute ~async:isAsync expression in
let expression =
(* Add new tupes (type a,b,c) to make's definition *)
newtypes
Expand Down
19 changes: 19 additions & 0 deletions jscomp/syntax/tests/ppx/react/asyncAwait.res
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
let f = a => Js.Promise.resolve(a + a)

module C0 = {
@react.component
let make = async (~a) => {
let a = await f(a)
<div> {React.int(a)} </div>
}
}

module C1 = {
@react.component
let make = async (~status) => {
switch status {
| #on => React.string("on")
| #off => React.string("off")
}
}
}
31 changes: 31 additions & 0 deletions jscomp/syntax/tests/ppx/react/expected/asyncAwait.res.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
let f = a => Js.Promise.resolve(a + a)

module C0 = {
type props<'a> = {a: 'a}

let make = async ({a, _}: props<_>) => {
let a = await f(a)
ReactDOM.jsx("div", {children: ?ReactDOM.someElement({React.int(a)})})
}
let make = {
let \"AsyncAwait$C0" = (props: props<_>) => JsxPPXReactSupport.asyncComponent(make(props))

\"AsyncAwait$C0"
}
}

module C1 = {
type props<'status> = {status: 'status}

let make = async ({status, _}: props<_>) => {
switch status {
| #on => React.string("on")
| #off => React.string("off")
}
}
let make = {
let \"AsyncAwait$C1" = (props: props<_>) => JsxPPXReactSupport.asyncComponent(make(props))

\"AsyncAwait$C1"
}
}