diff --git a/CHANGELOG.md b/CHANGELOG.md
index 624bd355e0..46c3cf44be 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -23,6 +23,7 @@
- Show `Stdlib.TypedArray` completions for typed arrays. https://github.com/rescript-lang/rescript/pull/7827
- Show `Stdlib.Null` and `Stdlib.Nullable` completions for `Stdlib.null<'a>` and `Stdlib.nullable<'a>` types, respectively. https://github.com/rescript-lang/rescript/pull/7826
- Fix generation of interfaces for module types containing multiple type constraints. https://github.com/rescript-lang/rescript/pull/7825
+- JSX preserve mode: fix "make is not a valid component name". https://github.com/rescript-lang/rescript/pull/7831
#### :memo: Documentation
diff --git a/compiler/core/js_pass_flatten_and_mark_dead.ml b/compiler/core/js_pass_flatten_and_mark_dead.ml
index 830f0ddde3..30424e68ab 100644
--- a/compiler/core/js_pass_flatten_and_mark_dead.ml
+++ b/compiler/core/js_pass_flatten_and_mark_dead.ml
@@ -245,6 +245,10 @@ let subst_map (substitution : J.expression Hash_ident.t) =
turn a runtime crash into compile time crash : )
*)
match Ext_list.nth_opt ls (Int32.to_int i) with
+ (* 7432: prevent optimization in JSX preserve mode *)
+ | Some {expression_desc = J.Var (Id {name = "make"})}
+ when !Js_config.jsx_preserve ->
+ super.expression self x
| Some
({expression_desc = J.Var _ | Number _ | Str _ | Undefined _} as
x) ->
diff --git a/compiler/core/lam_pass_remove_alias.ml b/compiler/core/lam_pass_remove_alias.ml
index 6b66d43ea0..fe19cf1961 100644
--- a/compiler/core/lam_pass_remove_alias.ml
+++ b/compiler/core/lam_pass_remove_alias.ml
@@ -45,6 +45,15 @@ let simplify_alias (meta : Lam_stats.t) (lam : Lam.t) : Lam.t =
let rec simpl (lam : Lam.t) : Lam.t =
match lam with
| Lvar _ -> lam
+ (* 7432: prevent optimization in JSX preserve mode *)
+ | Lprim
+ {
+ primitive = Pjs_call {prim_name = "jsx" | "jsxs"} as primitive;
+ args = (Lprim {primitive = Pfield (_, _)} as field_arg) :: rest;
+ loc;
+ }
+ when !Js_config.jsx_preserve ->
+ Lam.prim ~primitive ~args:(field_arg :: Ext_list.map rest simpl) loc
| Lprim {primitive = Pfield (i, info) as primitive; args = [arg]; loc} -> (
(* ATTENTION:
Main use case, we should detect inline all immutable block .. *)
diff --git a/tests/tests/src/async_jsx.mjs b/tests/tests/src/async_jsx.mjs
index 795c65b52c..f02ec3cf20 100644
--- a/tests/tests/src/async_jsx.mjs
+++ b/tests/tests/src/async_jsx.mjs
@@ -25,7 +25,7 @@ let Foo = {
function Async_jsx$Bar(props) {
return
-
+
;
}
diff --git a/tests/tests/src/jsx_preserve_test.mjs b/tests/tests/src/jsx_preserve_test.mjs
index 9933c4f471..e5ced9a3f1 100644
--- a/tests/tests/src/jsx_preserve_test.mjs
+++ b/tests/tests/src/jsx_preserve_test.mjs
@@ -1,5 +1,6 @@
// Generated by ReScript, PLEASE EDIT WITH CARE
+import * as React from "react";
import * as JsxRuntime from "react/jsx-runtime";
function Jsx_preserve_test$Icon(props) {
@@ -20,7 +21,7 @@ let _multiple_element_children =
{"Hello, world!"}
-
+
;
let _single_element_fragment = <>
@@ -141,7 +142,7 @@ let B = {
let _external_component_with_children =
-
+ ;
function Jsx_preserve_test$MyWeirdComponent(props) {
@@ -155,7 +156,7 @@ let MyWeirdComponent = {
make: Jsx_preserve_test$MyWeirdComponent
};
-let _escaped_jsx_prop = ;
@@ -197,7 +198,7 @@ let ComponentWithOptionalProps = {
make: Jsx_preserve_test$ComponentWithOptionalProps
};
-let _optional_props = }
@@ -208,11 +209,9 @@ let _props_with_hyphen = ;
-let React = {};
-
-let _fragment =
+let _fragment = <>
{"Hello, world!"}
-;
+>;
let _youtube_iframe = ;
+function make(_props) {
+ return null;
+}
+
+let X = {
+ make: make
+};
+
+;
+
+function Jsx_preserve_test$Y(props) {
+ return null;
+}
+
+let make$1 = React.memo(Jsx_preserve_test$Y);
+
+let Y = {
+ x: 42,
+ make: make$1
+};
+
+;
+
+let context = React.createContext(0);
+
+let make$2 = context.Provider;
+
+let ContextProvider = {
+ make: make$2
+};
+
+function Jsx_preserve_test(props) {
+ return
+ {props.children}
+ ;
+}
+
+let make$3 = Jsx_preserve_test;
+
export {
Icon,
_single_element_child,
@@ -250,8 +290,12 @@ export {
ComponentWithOptionalProps,
_optional_props,
_props_with_hyphen,
- React,
_fragment,
_youtube_iframe,
+ X,
+ Y,
+ context,
+ ContextProvider,
+ make$3 as make,
}
/* _single_element_child Not a pure module */
diff --git a/tests/tests/src/jsx_preserve_test.res b/tests/tests/src/jsx_preserve_test.res
index ff8635c1f2..8f22846e2b 100644
--- a/tests/tests/src/jsx_preserve_test.res
+++ b/tests/tests/src/jsx_preserve_test.res
@@ -129,17 +129,6 @@ let _optional_props = }
let _props_with_hyphen =
-module React = {
- type component<'props> = Jsx.component<'props>
- type element = Jsx.element
-
- external jsx: (component<'props>, 'props) => element = "jsx"
-
- type fragmentProps = {children?: element}
-
- external jsxFragment: component = "Fragment"
-}
-
let _fragment = <> {Jsx.string("Hello, world!")} >
let _youtube_iframe =
@@ -153,3 +142,32 @@ let _youtube_iframe =
allowFullScreen={true}
>
+
+module X = {
+ type props = {}
+ let make = (_props: props) => React.null
+}
+
+let _ =
+
+module Y = {
+ let x = 42
+
+ @react.component
+ let make = () => React.null
+
+ let make = React.memo(make)
+}
+
+let _ =
+
+let context = React.createContext(0)
+
+module ContextProvider = {
+ let make = React.Context.provider(context)
+}
+
+@react.component
+let make = (~children) => {
+ {children}
+}