-
Notifications
You must be signed in to change notification settings - Fork 465
[WIP] - Preserve JSX by adding extra app flag #7387
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
base: master
Are you sure you want to change the base?
Conversation
@@ -199,12 +199,13 @@ let expr sub x = | |||
| Texp_function {arg_label; arity; param; case; partial; async} -> | |||
Texp_function | |||
{arg_label; arity; param; case = sub.case sub case; partial; async} | |||
| Texp_apply {funct = exp; args = list; partial} -> | |||
| Texp_apply {funct = exp; args = list; partial; transformed_jsx} -> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Store the potentially transformed jsx node.
compiler/syntax/src/jsx_v4.ml
Outdated
@@ -1277,7 +1278,7 @@ let mk_react_jsx (config : Jsx_common.jsx_config) mapper loc attrs | |||
[key_prop; (nolabel, unit_expr ~loc:Location.none)] ) | |||
in | |||
let args = [(nolabel, elementTag); (nolabel, props_record)] @ key_and_unit in | |||
Exp.apply ~loc ~attrs jsx_expr args | |||
Exp.apply ~loc ~attrs ~transformed_jsx jsx_expr args |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Capture jsx ast
@@ -2401,7 +2401,7 @@ and type_expect_ ?type_clash_context ?in_function ?(recarg = Rejected) env sexp | |||
type_function ?in_function ~arity ~async loc sexp.pexp_attributes env | |||
ty_expected l | |||
[Ast_helper.Exp.case spat sbody] | |||
| Pexp_apply {funct = sfunct; args = sargs; partial} -> | |||
| Pexp_apply {funct = sfunct; args = sargs; partial; transformed_jsx} -> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From here on, pass it along to the next layer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like it never makes it here. So it must have gotten lost somewhere.
I'd start with a simple test examples and start adding some assert false whenever transformed_jsx
is not None
, to catch where was the last point where it was present before getting lost.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh looks like it gets lost in bs_ast_mapper
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, it seems to take a different route because <div>
is an FFI call.
compiler/core/js_dump.ml
Outdated
@@ -524,6 +524,10 @@ and expression_desc cxt ~(level : int) f x : cxt = | |||
when Ext_list.length_equal el i | |||
]} | |||
*) | |||
| Call (e, el, {call_transformed_jsx = Some jsx_element}) -> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hope it ends up here and do something meaningful.
Unfortunately, it didn't work for me. It got lost somewhere.
Got an initial result here, was able to transform: module ReactDOM = {
@module("react/jsx-runtime")
external jsx: (string, JsxDOM.domProps) => Jsx.element = "jsx"
}
let _ = <div className="meh"></div> into // Generated by ReScript, PLEASE EDIT WITH CARE
'use strict';
let JsxRuntime = require("react/jsx-runtime");
let ReactDOM = {};
<div className={"meh"}></div>;
exports.ReactDOM = ReactDOM; There are still a lot of cases to cover, but it is a start. |
Made some more progress, was able to transform my entire project.
|
rescript
@rescript/darwin-x64
@rescript/linux-arm64
@rescript/win32-x64
@rescript/linux-x64
@rescript/darwin-arm64
commit: |
This reverts commit 547dfca.
@cknitt you can test this by: npm i "https://pkg.pr.new/rescript-lang/rescript@aa94f6fdbed6156c46ac4511fa1029a8fbcd553d"
"suffix": ".res.jsx",
"jsx": {
"version": 4
},
"bsc-flags": [
"-bs-jsx-preserve"
] (suffix not strictly required) |
@cristianoc, this is now functioning effectively. Could you please review this approach? If it seems reasonable, we can refine it. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks pretty good.
Main question is if there's a way to avoid extending every Lprim
with a boolean, and the scope of changes can be restricted somehow.
@@ -255,6 +255,9 @@ let buckle_script_flags : (string * Bsc_args.spec * string) array = | |||
( "-bs-jsx-mode", | |||
string_call ignore, | |||
"*internal* Set jsx mode, this is no longer used and is a no-op." ); | |||
( "-bs-jsx-preserve", | |||
unit_call (fun _ -> Js_config.jsx_preserve := true), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can just use set
instead of unit_call
@@ -294,6 +297,7 @@ let rec exprToContextPathInner ~(inJsxContext : bool) (e : Parsetree.expression) | |||
funct = {pexp_desc = Pexp_ident id; pexp_loc; pexp_attributes}; | |||
args = [(Nolabel, lhs)]; | |||
partial; | |||
transformed_jsx; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
perhaps give a name to the inline record passed to Pexp_apply
in the pattern match, and here only mention the changed cases (so no mention of partial
and transformed_jsx
).
@@ -524,6 +524,48 @@ and expression_desc cxt ~(level : int) f x : cxt = | |||
when Ext_list.length_equal el i | |||
]} | |||
*) | |||
| Call |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
perhaps add comment to explain what this does
let fields = ("key", key) :: fields in | ||
print_jsx cxt ~level f fnName tag fields | ||
| _ -> | ||
expression_desc cxt ~level f |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this code branch ever executed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If it is, it means we missed something. Could we add some sort of assert in this case?
let translate_ffi (cxt : Lam_compile_context.t) arg_types | ||
(ffi : External_ffi_types.external_spec) (args : J.expression list) | ||
~dynamic_import = | ||
let translate_ffi ?(transformed_jsx = false) (cxt : Lam_compile_context.t) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we get transformed_jsx
true sometimes when compiling an external call?
Can't remember if the jsx ppx produced external calls.
(E.js_global "import") | ||
[E.str path] | ||
|
||
let wrap_then import value = | ||
let arg = Ident.create "m" in | ||
E.call | ||
~info:{arity = Full; call_info = Call_na} | ||
~info:{arity = Full; call_info = Call_na; call_transformed_jsx = false} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Possible cleanup: define some common info
values to avoid all these repetitions.
@cristianoc could you check e30cab3 and 773124f as well. Had to write some new to deal with prop spreading. |
@cristianoc, this doesn't work yet, but it highlights the idea. Could you point out where the information is not passed? It's a bit overwhelming for me to grasp.