Skip to content

Generic JSX transform fixes #6606

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Feb 2, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@
#### :bug: Bug Fix

- Fix issue with async and newtype in uncurried mode. https://github.com/rescript-lang/rescript-compiler/pull/6601
- Generic JSX transform: Rename expected module name for lowercase JSX to `Elements` from `DOM`. https://github.com/rescript-lang/rescript-compiler/pull/6606
- Generic JSX transform: Set default config params for `jsxConfig`. https://github.com/rescript-lang/rescript-compiler/pull/6606
- Generic JSX transform: Handle namespaced names. https://github.com/rescript-lang/rescript-compiler/pull/6606

#### :house: Internal

Expand Down
9 changes: 8 additions & 1 deletion jscomp/bsc/rescript_compiler_main.ml
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,14 @@ let buckle_script_flags : (string * Bsc_args.spec * string) array =
"*internal* Set jsx version";

"-bs-jsx-module", string_call (fun i ->
Js_config.jsx_module := Js_config.jsx_module_of_string i),
let isGeneric = match i |> String.lowercase_ascii with
| "react" -> false
| _ -> true in
Js_config.jsx_module := Js_config.jsx_module_of_string i;
if isGeneric then (
Js_config.jsx_mode := Automatic;
Js_config.jsx_version := Some Jsx_v4
)),
"*internal* Set jsx module";

"-bs-jsx-mode", string_call (fun i ->
Expand Down
22 changes: 15 additions & 7 deletions jscomp/syntax/src/jsx_ppx.ml
Original file line number Diff line number Diff line change
Expand Up @@ -48,15 +48,23 @@ let getString ~key fields = fields |> getJsxConfigByKey ~key ~type_:String

let updateConfig config payload =
let fields = getPayloadFields payload in
(match getInt ~key:"version" fields with
| None -> ()
| Some i -> config.Jsx_common.version <- i);
(match getString ~key:"module_" fields with
let moduleRaw = getString ~key:"module_" fields in
let isGeneric =
match moduleRaw |> Option.map (fun m -> String.lowercase_ascii m) with
| Some "react" | None -> false
| Some _ -> true
in
(match (isGeneric, getInt ~key:"version" fields) with
| true, _ -> config.Jsx_common.version <- 4
| false, Some i -> config.Jsx_common.version <- i
| _ -> ());
(match moduleRaw with
| None -> ()
| Some s -> config.module_ <- s);
match getString ~key:"mode" fields with
| None -> ()
| Some s -> config.mode <- s
match (isGeneric, getString ~key:"mode" fields) with
| true, _ -> config.mode <- "automatic"
| false, Some s -> config.mode <- s
| _ -> ()

let isJsxConfigAttr ((loc, _) : attribute) = loc.txt = "jsxConfig"

Expand Down
67 changes: 18 additions & 49 deletions jscomp/syntax/src/jsx_v4.ml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ open Asttypes
open Parsetree
open Longident

let moduleAccessName config = String.capitalize_ascii config.Jsx_common.module_
let moduleAccessName config value =
String.capitalize_ascii config.Jsx_common.module_ ^ "." ^ value
|> Longident.parse

let nolabel = Nolabel

Expand Down Expand Up @@ -384,10 +386,7 @@ let transformUppercaseCall3 ~config modulePath mapper jsxExprLoc callExprLoc
( labelled "children",
Exp.apply
(Exp.ident
{
txt = Ldot (Lident (moduleAccessName config), "array");
loc = Location.none;
})
{txt = moduleAccessName config "array"; loc = Location.none})
[(Nolabel, expression)] );
]
| _ ->
Expand Down Expand Up @@ -431,31 +430,17 @@ let transformUppercaseCall3 ~config modulePath mapper jsxExprLoc callExprLoc
match (!childrenArg, keyProp) with
| None, key :: _ ->
( Exp.ident
{
loc = Location.none;
txt = Ldot (Lident (moduleAccessName config), "jsxKeyed");
},
{loc = Location.none; txt = moduleAccessName config "jsxKeyed"},
[key; (nolabel, unitExpr ~loc:Location.none)] )
| None, [] ->
( Exp.ident
{
loc = Location.none;
txt = Ldot (Lident (moduleAccessName config), "jsx");
},
( Exp.ident {loc = Location.none; txt = moduleAccessName config "jsx"},
[] )
| Some _, key :: _ ->
( Exp.ident
{
loc = Location.none;
txt = Ldot (Lident (moduleAccessName config), "jsxsKeyed");
},
{loc = Location.none; txt = moduleAccessName config "jsxsKeyed"},
[key; (nolabel, unitExpr ~loc:Location.none)] )
| Some _, [] ->
( Exp.ident
{
loc = Location.none;
txt = Ldot (Lident (moduleAccessName config), "jsxs");
},
( Exp.ident {loc = Location.none; txt = moduleAccessName config "jsxs"},
[] )
in
Exp.apply ~loc:jsxExprLoc ~attrs jsxExpr
Expand Down Expand Up @@ -500,9 +485,9 @@ let transformLowercaseCall3 ~config mapper jsxExprLoc callExprLoc attrs
(* the new jsx transform *)
| "automatic" ->
let elementBinding =
match moduleAccessName config with
| "React" -> Lident "ReactDOM"
| generic -> Ldot (Lident generic, "DOM")
match config.module_ |> String.lowercase_ascii with
| "react" -> Lident "ReactDOM"
| _generic -> moduleAccessName config "Elements"
in

let children, nonChildrenProps =
Expand Down Expand Up @@ -539,10 +524,7 @@ let transformLowercaseCall3 ~config mapper jsxExprLoc callExprLoc attrs
( labelled "children",
Exp.apply
(Exp.ident
{
txt = Ldot (Lident (moduleAccessName config), "array");
loc = Location.none;
})
{txt = moduleAccessName config "array"; loc = Location.none})
[(Nolabel, expression)] );
]
in
Expand Down Expand Up @@ -1203,10 +1185,7 @@ let transformStructureItem ~config item =
(* can't be an arrow because it will defensively uncurry *)
let newExternalType =
Ptyp_constr
( {
loc = pstr_loc;
txt = Ldot (Lident (moduleAccessName config), "componentLike");
},
( {loc = pstr_loc; txt = moduleAccessName config "componentLike"},
[retPropsType; innerType] )
in
let newStructure =
Expand Down Expand Up @@ -1321,10 +1300,7 @@ let transformSignatureItem ~config item =
(* can't be an arrow because it will defensively uncurry *)
let newExternalType =
Ptyp_constr
( {
loc = psig_loc;
txt = Ldot (Lident (moduleAccessName config), "componentLike");
},
( {loc = psig_loc; txt = moduleAccessName config "componentLike"},
[retPropsType; innerType] )
in
let newStructure =
Expand Down Expand Up @@ -1419,8 +1395,7 @@ let expr ~config mapper expression =
let fragment =
match config.mode with
| "automatic" ->
Exp.ident ~loc
{loc; txt = Ldot (Lident (moduleAccessName config), "jsxFragment")}
Exp.ident ~loc {loc; txt = moduleAccessName config "jsxFragment"}
| "classic" | _ ->
Exp.ident ~loc {loc; txt = Ldot (Lident "React", "fragment")}
in
Expand All @@ -1431,10 +1406,7 @@ let expr ~config mapper expression =
let applyJsxArray expr =
Exp.apply
(Exp.ident
{
txt = Ldot (Lident (moduleAccessName config), "array");
loc = Location.none;
})
{txt = moduleAccessName config "array"; loc = Location.none})
[(Nolabel, expr)]
in
let countOfChildren = function
Expand Down Expand Up @@ -1472,11 +1444,8 @@ let expr ~config mapper expression =
(match config.mode with
| "automatic" ->
if countOfChildren childrenExpr > 1 then
Exp.ident ~loc
{loc; txt = Ldot (Lident (moduleAccessName config), "jsxs")}
else
Exp.ident ~loc
{loc; txt = Ldot (Lident (moduleAccessName config), "jsx")}
Exp.ident ~loc {loc; txt = moduleAccessName config "jsxs"}
else Exp.ident ~loc {loc; txt = moduleAccessName config "jsx"}
| "classic" | _ ->
if countOfChildren childrenExpr > 1 then
Exp.ident ~loc
Expand Down