Skip to content

Commit aa94f6f

Browse files
committed
Add new -bs-jsx-preserve flag
1 parent 8e4811b commit aa94f6f

File tree

11 files changed

+133
-12
lines changed

11 files changed

+133
-12
lines changed

compiler/bsc/rescript_compiler_main.ml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,9 @@ let buckle_script_flags : (string * Bsc_args.spec * string) array =
255255
( "-bs-jsx-mode",
256256
string_call ignore,
257257
"*internal* Set jsx mode, this is no longer used and is a no-op." );
258+
( "-bs-jsx-preserve",
259+
unit_call (fun _ -> Js_config.jsx_preserve := true),
260+
"*internal* Preserve jsx" );
258261
( "-bs-package-output",
259262
string_call Js_packages_state.update_npm_package_path,
260263
"*internal* Set npm-output-path: [opt_module]:path, for example: \

compiler/common/js_config.ml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ let force_cmi = ref false
5050
let force_cmj = ref false
5151
let jsx_version = ref None
5252
let jsx_module = ref React
53+
let jsx_preserve = ref false
5354
let js_stdout = ref true
5455
let all_module_aliases = ref false
5556
let no_stdlib = ref false

compiler/common/js_config.mli

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,8 @@ val jsx_version : jsx_version option ref
8080

8181
val jsx_module : jsx_module ref
8282

83+
val jsx_preserve : bool ref
84+
8385
val js_stdout : bool ref
8486

8587
val all_module_aliases : bool ref

compiler/frontend/ppx_entry.ml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@ let rewrite_signature (ast : Parsetree.signature) : Parsetree.signature =
3434
let open Js_config in
3535
let jsx_version = int_of_jsx_version jsx_version_ in
3636
let jsx_module = string_of_jsx_module !jsx_module in
37-
Jsx_ppx.rewrite_signature ~jsx_version ~jsx_module ast
37+
let jsx_preserve = !jsx_preserve in
38+
Jsx_ppx.rewrite_signature ~jsx_version ~jsx_module ~jsx_preserve ast
3839
in
3940
if !Js_config.no_builtin_ppx then ast
4041
else
@@ -53,7 +54,8 @@ let rewrite_implementation (ast : Parsetree.structure) : Parsetree.structure =
5354
let open Js_config in
5455
let jsx_version = int_of_jsx_version jsx_version_ in
5556
let jsx_module = string_of_jsx_module !jsx_module in
56-
Jsx_ppx.rewrite_implementation ~jsx_version ~jsx_module ast
57+
let jsx_preserve = !jsx_preserve in
58+
Jsx_ppx.rewrite_implementation ~jsx_version ~jsx_module ~jsx_preserve ast
5759
in
5860
if !Js_config.no_builtin_ppx then ast
5961
else

compiler/syntax/cli/res_cli.ml

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@ module ResClflags : sig
163163
val interface : bool ref
164164
val jsx_version : int ref
165165
val jsx_module : string ref
166+
val jsx_preserve : bool ref
166167
val typechecker : bool ref
167168
val test_ast_conversion : bool ref
168169

@@ -175,6 +176,7 @@ end = struct
175176
let interface = ref false
176177
let jsx_version = ref (-1)
177178
let jsx_module = ref "react"
179+
let jsx_preserve = ref false
178180
let file = ref ""
179181
let typechecker = ref false
180182
let test_ast_conversion = ref false
@@ -225,7 +227,7 @@ module CliArgProcessor = struct
225227
[@@unboxed]
226228

227229
let process_file ~is_interface ~width ~recover ~target ~jsx_version
228-
~jsx_module ~typechecker ~test_ast_conversion filename =
230+
~jsx_module ~jsx_preserve ~typechecker ~test_ast_conversion filename =
229231
let len = String.length filename in
230232
let process_interface =
231233
is_interface
@@ -277,7 +279,8 @@ module CliArgProcessor = struct
277279
Ast_mapper_from0.default_mapper tree0
278280
in
279281
let parsetree =
280-
Jsx_ppx.rewrite_signature ~jsx_version ~jsx_module parsetree
282+
Jsx_ppx.rewrite_signature ~jsx_version ~jsx_module ~jsx_preserve
283+
parsetree
281284
in
282285
print_engine.print_interface ~width ~filename
283286
~comments:parse_result.comments parsetree
@@ -302,7 +305,8 @@ module CliArgProcessor = struct
302305
Ast_mapper_from0.default_mapper tree0
303306
in
304307
let parsetree =
305-
Jsx_ppx.rewrite_implementation ~jsx_version ~jsx_module parsetree
308+
Jsx_ppx.rewrite_implementation ~jsx_version ~jsx_module ~jsx_preserve
309+
parsetree
306310
in
307311
print_engine.print_implementation ~width ~filename
308312
~comments:parse_result.comments parsetree
@@ -315,7 +319,7 @@ let () =
315319
CliArgProcessor.process_file ~is_interface:!ResClflags.interface
316320
~width:!ResClflags.width ~recover:!ResClflags.recover
317321
~target:!ResClflags.print ~jsx_version:!ResClflags.jsx_version
318-
~jsx_module:!ResClflags.jsx_module ~typechecker:!ResClflags.typechecker
319-
!ResClflags.file
322+
~jsx_module:!ResClflags.jsx_module ~jsx_preserve:!ResClflags.jsx_preserve
323+
~typechecker:!ResClflags.typechecker !ResClflags.file
320324
~test_ast_conversion:!ResClflags.test_ast_conversion)
321325
[@@raises exit]

compiler/syntax/src/jsx_common.ml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ type jsx_config = {
66
mutable module_: string;
77
mutable nested_modules: string list;
88
mutable has_component: bool;
9+
mutable preserve: bool;
910
}
1011

1112
(* Helper method to look up the [@react.component] attribute *)

compiler/syntax/src/jsx_ppx.ml

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -135,27 +135,29 @@ let get_mapper ~config =
135135

136136
{default_mapper with expr; module_binding; signature; structure}
137137

138-
let rewrite_implementation ~jsx_version ~jsx_module (code : Parsetree.structure)
139-
: Parsetree.structure =
138+
let rewrite_implementation ~jsx_version ~jsx_module ~jsx_preserve
139+
(code : Parsetree.structure) : Parsetree.structure =
140140
let config =
141141
{
142142
Jsx_common.version = jsx_version;
143143
module_ = jsx_module;
144144
nested_modules = [];
145145
has_component = false;
146+
preserve = jsx_preserve;
146147
}
147148
in
148149
let mapper = get_mapper ~config in
149150
mapper.structure mapper code
150151

151-
let rewrite_signature ~jsx_version ~jsx_module (code : Parsetree.signature) :
152-
Parsetree.signature =
152+
let rewrite_signature ~jsx_version ~jsx_module ~jsx_preserve
153+
(code : Parsetree.signature) : Parsetree.signature =
153154
let config =
154155
{
155156
Jsx_common.version = jsx_version;
156157
module_ = jsx_module;
157158
nested_modules = [];
158159
has_component = false;
160+
preserve = jsx_preserve;
159161
}
160162
in
161163
let mapper = get_mapper ~config in

compiler/syntax/src/jsx_ppx.mli

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,13 @@
1111
val rewrite_implementation :
1212
jsx_version:int ->
1313
jsx_module:string ->
14+
jsx_preserve:bool ->
1415
Parsetree.structure ->
1516
Parsetree.structure
1617

1718
val rewrite_signature :
1819
jsx_version:int ->
1920
jsx_module:string ->
21+
jsx_preserve:bool ->
2022
Parsetree.signature ->
2123
Parsetree.signature

compiler/syntax/src/jsx_v4.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1277,7 +1277,7 @@ let mk_react_jsx (config : Jsx_common.jsx_config) mapper loc attrs
12771277
[key_prop; (nolabel, unit_expr ~loc:Location.none)] )
12781278
in
12791279
let args = [(nolabel, elementTag); (nolabel, props_record)] @ key_and_unit in
1280-
Exp.apply ~loc ~attrs ~transformed_jsx:true jsx_expr args
1280+
Exp.apply ~loc ~attrs ~transformed_jsx:config.preserve jsx_expr args
12811281

12821282
(* In most situations, the component name is the make function from a module.
12831283
However, if the name contains a lowercase letter, it means it probably an external component.

tests/tests/src/nojaf.mjs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Generated by ReScript, PLEASE EDIT WITH CARE
2+
3+
import * as JsxRuntime from "react/jsx-runtime";
4+
5+
let React = {};
6+
7+
let ReactDOM = {};
8+
9+
function Nojaf$Icon(props) {
10+
return <strong/>;
11+
}
12+
13+
let Icon = {
14+
make: Nojaf$Icon
15+
};
16+
17+
<div><h1>{"Hello, world!"}</h1><Nojaf$Icon/></div>;
18+
19+
export {
20+
React,
21+
ReactDOM,
22+
Icon,
23+
}
24+
/* Not a pure module */

tests/tests/src/nojaf.res

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
@@config({
2+
flags: ["-bs-jsx", "4", "-bs-jsx-preserve"],
3+
})
4+
5+
module React = {
6+
type element = Jsx.element
7+
8+
@val external null: element = "null"
9+
10+
external float: float => element = "%identity"
11+
external int: int => element = "%identity"
12+
external string: string => element = "%identity"
13+
14+
external array: array<element> => element = "%identity"
15+
16+
type componentLike<'props, 'return> = Jsx.componentLike<'props, 'return>
17+
18+
type component<'props> = Jsx.component<'props>
19+
20+
external component: componentLike<'props, element> => component<'props> = "%identity"
21+
22+
@module("react")
23+
external createElement: (component<'props>, 'props) => element = "createElement"
24+
25+
@module("react")
26+
external cloneElement: (element, 'props) => element = "cloneElement"
27+
28+
@module("react")
29+
external isValidElement: 'a => bool = "isValidElement"
30+
31+
@variadic @module("react")
32+
external createElementVariadic: (component<'props>, 'props, array<element>) => element =
33+
"createElement"
34+
35+
@module("react/jsx-runtime")
36+
external jsx: (component<'props>, 'props) => element = "jsx"
37+
38+
@module("react/jsx-runtime")
39+
external jsxKeyed: (component<'props>, 'props, ~key: string=?, @ignore unit) => element = "jsx"
40+
41+
@module("react/jsx-runtime")
42+
external jsxs: (component<'props>, 'props) => element = "jsxs"
43+
44+
@module("react/jsx-runtime")
45+
external jsxsKeyed: (component<'props>, 'props, ~key: string=?, @ignore unit) => element = "jsxs"
46+
47+
type fragmentProps = {children?: element}
48+
49+
@module("react/jsx-runtime") external jsxFragment: component<fragmentProps> = "Fragment"
50+
}
51+
52+
module ReactDOM = {
53+
external someElement: React.element => option<React.element> = "%identity"
54+
55+
@module("react/jsx-runtime")
56+
external jsx: (string, JsxDOM.domProps) => Jsx.element = "jsx"
57+
58+
@module("react/jsx-runtime")
59+
external jsxKeyed: (string, JsxDOM.domProps, ~key: string=?, @ignore unit) => Jsx.element = "jsx"
60+
61+
@module("react/jsx-runtime")
62+
external jsxs: (string, JsxDOM.domProps) => Jsx.element = "jsxs"
63+
64+
@module("react/jsx-runtime")
65+
external jsxsKeyed: (string, JsxDOM.domProps, ~key: string=?, @ignore unit) => Jsx.element =
66+
"jsxs"
67+
}
68+
69+
module Icon = {
70+
@react.component
71+
let make = () => {
72+
<strong />
73+
}
74+
}
75+
76+
let _ =
77+
<div>
78+
<h1> {React.string("Hello, world!")} </h1>
79+
<Icon />
80+
</div>

0 commit comments

Comments
 (0)