From a1cd72842968fd97f12fa24aee9cf6f8541cda86 Mon Sep 17 00:00:00 2001 From: mununki Date: Fri, 4 Oct 2024 16:13:44 +0900 Subject: [PATCH 1/7] remove jsx v3 --- docs/docson/build-schema.json | 19 +- jscomp/bsb/bsb_build_schemas.ml | 1 - jscomp/bsb/bsb_config_parse.ml | 31 - jscomp/bsb/bsb_config_types.ml | 3 - jscomp/bsb/bsb_jsx.ml | 17 +- jscomp/bsb/bsb_ninja_gen.ml | 5 +- jscomp/bsb/bsb_ninja_rule.ml | 9 +- jscomp/bsb/bsb_ninja_rule.mli | 1 - jscomp/common/js_config.ml | 4 +- jscomp/common/js_config.mli | 2 +- jscomp/gentype/TranslateTypeExprFromTypes.ml | 19 +- jscomp/syntax/src/jsx_ppx.ml | 16 +- jscomp/syntax/src/reactjs_jsx_v3.ml | 1222 ----------------- .../expected/externalWithCustomName.res.txt | 12 - .../react/expected/externalWithRef.res.txt | 17 - .../externalWithTypeVariables.res.txt | 15 - .../react/expected/fileLevelConfig.res.txt | 17 - .../react/expected/firstClassModules.res.txt | 52 - .../react/expected/firstClassModules.resi.txt | 33 - .../ppx/react/expected/forwardRef.res.txt | 67 - .../ppx/react/expected/forwardRef.resi.txt | 40 - .../ppx/react/expected/mangleKeyword.res.txt | 36 - .../tests/ppx/react/expected/newtype.res.txt | 23 - .../react/expected/optionalKeyType.res.txt | 28 - .../tests/ppx/react/expected/topLevel.res.txt | 21 - .../ppx/react/expected/typeConstraint.res.txt | 15 - .../ppx/react/externalWithCustomName.res | 9 - .../tests/ppx/react/externalWithRef.res | 10 - .../ppx/react/externalWithTypeVariables.res | 10 - .../tests/ppx/react/fileLevelConfig.res | 9 - .../tests/ppx/react/firstClassModules.res | 21 - .../tests/ppx/react/firstClassModules.resi | 17 - jscomp/syntax/tests/ppx/react/forwardRef.res | 27 - jscomp/syntax/tests/ppx/react/forwardRef.resi | 18 - jscomp/syntax/tests/ppx/react/innerModule.res | 13 - .../syntax/tests/ppx/react/mangleKeyword.res | 16 - jscomp/syntax/tests/ppx/react/newtype.res | 7 - .../tests/ppx/react/optionalKeyType.res | 12 - jscomp/syntax/tests/ppx/react/topLevel.res | 10 - .../syntax/tests/ppx/react/typeConstraint.res | 9 - tests/build_tests/react_ppx/rescript.json | 4 +- tests/build_tests/react_ppx/src/React.res | 45 +- .../react_ppx/src/gpr_3695_test.res | 2 +- .../react_ppx/src/gpr_3987_test.bs.js | 23 +- .../react_ppx/src/gpr_3987_test.res | 5 +- .../src/recursive_component_test.bs.js | 17 +- .../src/recursive_component_test.res | 5 - .../package-lock.json | 8 +- .../typescript-react-example/package.json | 4 +- .../typescript-react-example/rescript.json | 4 +- .../src/DynamicallyLoadedComponent.res.js | 4 +- .../src/ExportWithRename.gen.tsx | 4 +- .../src/ExportWithRename.res.js | 4 +- .../src/Hooks.gen.tsx | 106 +- .../typescript-react-example/src/Hooks.res.js | 164 ++- .../src/ImportHookDefault.gen.tsx | 12 + .../src/ImportHooks.gen.tsx | 7 + .../src/ImportIndex.gen.tsx | 2 + .../src/JSXV4.gen.tsx | 12 +- .../typescript-react-example/src/JSXV4.res | 18 +- .../typescript-react-example/src/JSXV4.res.js | 9 - .../src/MyInput.gen.tsx | 2 + .../src/OnClick2.gen.tsx | 10 +- .../src/OnClick2.res.js | 11 +- .../src/V3Compatibility.gen.tsx | 6 - .../src/V3Compatibility.res | 4 - .../src/V3Compatibility.res.js | 2 - .../src/shims/Jsx.shim.ts | 3 + .../src/shims/JsxEvent.shim.ts | 3 + 69 files changed, 265 insertions(+), 2148 deletions(-) delete mode 100644 jscomp/syntax/src/reactjs_jsx_v3.ml delete mode 100644 jscomp/syntax/tests/ppx/react/innerModule.res delete mode 100644 tests/gentype_tests/typescript-react-example/src/V3Compatibility.gen.tsx delete mode 100644 tests/gentype_tests/typescript-react-example/src/V3Compatibility.res delete mode 100644 tests/gentype_tests/typescript-react-example/src/V3Compatibility.res.js create mode 100644 tests/gentype_tests/typescript-react-example/src/shims/Jsx.shim.ts create mode 100644 tests/gentype_tests/typescript-react-example/src/shims/JsxEvent.shim.ts diff --git a/docs/docson/build-schema.json b/docs/docson/build-schema.json index 82d5e24dc0..7dba11054f 100644 --- a/docs/docson/build-schema.json +++ b/docs/docson/build-schema.json @@ -304,15 +304,6 @@ }, "description": "path to gentype, path resolution is similar to ReScript" }, - "reason-specs": { - "type": "object", - "properties": { - "react-jsx": { - "$ref": "#/definitions/react-jsx-version", - "description": "Whether to apply the [RescriptReact](https://github.com/rescript-lang/rescript-react)-specific JSX PPX transformation." - } - } - }, "jsx-specs": { "type": "object", "properties": { @@ -329,10 +320,6 @@ "type": "string", "enum": ["classic", "automatic"], "description": "JSX transformation mode" - }, - "v3-dependencies": { - "$ref": "#/definitions/dependencies", - "description": "Build the given dependencies in JSX V3 compatibility mode." } }, "additionalProperties": false @@ -422,10 +409,6 @@ "type": "boolean", "description": "Configuration for the uncurried mode." }, - "reason": { - "$ref": "#/definitions/reason-specs", - "description": "ReScript comes with [Reason](http://reasonml.github.io/) by default. Specific configurations here." - }, "gentypeconfig": { "$ref": "#/definitions/gentype-specs", "description": "gentype config, see cristianoc/genType for more details" @@ -458,7 +441,7 @@ }, "ppx-flags": { "$ref": "#/definitions/ppx-specs", - "description": "PPX macros to pass to compiler. The syntax is package_name/binary, for example: `reason/reactjs_jsx_ppx_3.native`. Currenly searches in `node_modules`" + "description": "PPX macros to pass to compiler. The syntax is package_name/binary, for example: `rescript-relay/ppx`. Currenly searches in `node_modules`" }, "pp-flags": { "$ref": "#/definitions/pp-specs", diff --git a/jscomp/bsb/bsb_build_schemas.ml b/jscomp/bsb/bsb_build_schemas.ml index 4d6949dc3b..1a9b85be4b 100644 --- a/jscomp/bsb/bsb_build_schemas.ml +++ b/jscomp/bsb/bsb_build_schemas.ml @@ -52,7 +52,6 @@ let jsx = "jsx" let jsx_version = "version" let jsx_module = "module" let jsx_mode = "mode" -let jsx_v3_dependencies = "v3-dependencies" let cut_generators = "cut-generators" let generators = "generators" let command = "command" diff --git a/jscomp/bsb/bsb_config_parse.ml b/jscomp/bsb/bsb_config_parse.ml index 7200d5191a..bb5848a6b9 100644 --- a/jscomp/bsb/bsb_config_parse.ml +++ b/jscomp/bsb/bsb_config_parse.ml @@ -103,26 +103,6 @@ let extract_boolean (map : json_map) (field : string) (default : bool) : bool = | Some config -> Bsb_exception.config_error config (field ^ " expect a boolean") -let extract_reason_react_jsx (map : json_map) = - let default : Bsb_config_types.reason_react_jsx option ref = ref None in - map - |? ( Bsb_build_schemas.reason, - `Obj - (fun m -> - match m.?(Bsb_build_schemas.react_jsx) with - | Some (Flo { loc; flo }) -> ( - match flo with - | "3" -> default := Some Jsx_v3 - | _ -> Bsb_exception.errorf ~loc "Unsupported jsx version %s" flo - ) - | Some x -> - Bsb_exception.config_error x - "Unexpected input (expect a version number) for jsx, note \ - boolean is no longer allowed" - | None -> ()) ) - |> ignore; - !default - let extract_warning (map : json_map) = match map.?(Bsb_build_schemas.warnings) with | None -> Bsb_warning.use_default @@ -262,7 +242,6 @@ let interpret_json ~desc:Bsb_build_schemas.pp_flags p) .path) in - let reason_react_jsx = extract_reason_react_jsx map in let bs_dependencies = extract_dependencies map per_proj_dir Bsb_build_schemas.bs_dependencies in @@ -287,15 +266,6 @@ let interpret_json in let bsc_flags = extract_string_list map Bsb_build_schemas.bsc_flags in let jsx = Bsb_jsx.from_map map in - let jsx, bsc_flags = - match package_kind with - | Pinned_dependency x | Dependency x -> - if List.mem package_name x.jsx.v3_dependencies then - ( { jsx with version = Some Jsx_v3 }, - "-open ReactV3" :: bsc_flags ) - else (x.jsx, bsc_flags) - | _ -> (jsx, bsc_flags) - in { pinned_dependencies; gentype_config; @@ -326,7 +296,6 @@ let interpret_json | Pinned_dependency x | Dependency x -> x.package_specs); file_groups = groups; files_to_install = Queue.create (); - reason_react_jsx; jsx; generators = extract_generators map; cut_generators; diff --git a/jscomp/bsb/bsb_config_types.ml b/jscomp/bsb/bsb_config_types.ml index 88ac34e2df..6088383560 100644 --- a/jscomp/bsb/bsb_config_types.ml +++ b/jscomp/bsb/bsb_config_types.ml @@ -28,8 +28,6 @@ type dependency = { } type dependencies = dependency list -type reason_react_jsx = Jsx_v3 -(* string option *) type gentype_config = bool type command = string @@ -56,7 +54,6 @@ type t = { package_specs : Bsb_package_specs.t; file_groups : Bsb_file_groups.t; files_to_install : Bsb_db.module_info Queue.t; - reason_react_jsx : reason_react_jsx option; jsx: Bsb_jsx.t; (* whether apply PPX transform or not*) generators : command Map_string.t; diff --git a/jscomp/bsb/bsb_jsx.ml b/jscomp/bsb/bsb_jsx.ml index b9fbd08661..9f68549863 100644 --- a/jscomp/bsb/bsb_jsx.ml +++ b/jscomp/bsb/bsb_jsx.ml @@ -1,4 +1,4 @@ -type version = Jsx_v3 | Jsx_v4 +type version = Jsx_v4 type module_ = React | Generic of {moduleName: string} type mode = Classic | Automatic type dependencies = string list @@ -7,13 +7,11 @@ type t = { version : version option; module_ : module_ option; mode : mode option; - v3_dependencies : dependencies; } let encode_no_nl jsx = (match jsx.version with | None -> "" - | Some Jsx_v3 -> "3" | Some Jsx_v4 -> "4") ^ (match jsx.module_ with None -> "" | Some React -> "React" | Some Generic {moduleName} -> moduleName) ^ @@ -35,7 +33,6 @@ let from_map map = let version : version option ref = ref None in let module_ : module_ option ref = ref None in let mode : mode option ref = ref None in - let v3_dependencies : dependencies ref = ref [] in map |? ( Bsb_build_schemas.jsx, `Obj @@ -43,7 +40,6 @@ let from_map map = match m.?(Bsb_build_schemas.jsx_version) with | Some (Flo { loc; flo }) -> ( match flo with - | "3" -> version := Some Jsx_v3 | "4" -> version := Some Jsx_v4 | _ -> Bsb_exception.errorf ~loc "Unsupported jsx version %s" flo ) @@ -76,20 +72,9 @@ let from_map map = Bsb_exception.config_error x "Unexpected input (expect classic or automatic) for jsx mode" | None -> ()) ) - |? ( Bsb_build_schemas.jsx, - `Obj - (fun m -> - match m.?(Bsb_build_schemas.jsx_v3_dependencies) with - | Some (Arr { content }) -> - v3_dependencies := get_list_string content - | Some x -> - Bsb_exception.config_error x - "Unexpected input for jsx v3-dependencies" - | None -> ()) ) |> ignore; { version = !version; module_ = !module_; mode = !mode; - v3_dependencies = !v3_dependencies; } diff --git a/jscomp/bsb/bsb_ninja_gen.ml b/jscomp/bsb/bsb_ninja_gen.ml index 9cb10bb11d..762329a7d1 100644 --- a/jscomp/bsb/bsb_ninja_gen.ml +++ b/jscomp/bsb/bsb_ninja_gen.ml @@ -148,7 +148,6 @@ let output_ninja_and_namespace_map ~per_proj_dir ~package_kind package_specs; file_groups = { files = bs_file_groups }; files_to_install; - reason_react_jsx; jsx; generators; namespace; @@ -195,8 +194,8 @@ let output_ninja_and_namespace_map ~per_proj_dir ~package_kind in let rules : Bsb_ninja_rule.builtin = Bsb_ninja_rule.make_custom_rules ~gentype_config - ~has_postbuild:js_post_build_cmd ~pp_file - ~reason_react_jsx ~jsx ~package_specs ~namespace ~digest ~package_name + ~has_postbuild:js_post_build_cmd ~pp_file ~jsx + ~package_specs ~namespace ~digest ~package_name ~warnings ~ppx_files ~bsc_flags ~dpkg_incls (* dev dependencies *) ~lib_incls (* its own libs *) ~dev_incls (* its own devs *) diff --git a/jscomp/bsb/bsb_ninja_rule.ml b/jscomp/bsb/bsb_ninja_rule.ml index f3a2f2eab4..2c4810d4fd 100644 --- a/jscomp/bsb/bsb_ninja_rule.ml +++ b/jscomp/bsb/bsb_ninja_rule.ml @@ -88,7 +88,6 @@ type builtin = { let make_custom_rules ~(gentype_config : Bsb_config_types.gentype_config) ~(has_postbuild : string option) ~(pp_file : string option) - ~(reason_react_jsx : Bsb_config_types.reason_react_jsx option) ~(jsx : Bsb_jsx.t) ~(digest : string) ~(package_specs : Bsb_package_specs.t) ~(namespace : string option) ~package_name ~warnings ~(ppx_files : Bsb_config_types.ppx list) ~bsc_flags ~(dpkg_incls : string) @@ -156,11 +155,9 @@ let make_custom_rules ~(gentype_config : Bsb_config_types.gentype_config) | None -> () | Some flag -> Ext_buffer.add_char_string buf ' ' (Bsb_build_util.pp_flag flag)); - (match (reason_react_jsx, jsx.version) with - | _, Some Jsx_v3 -> Ext_buffer.add_string buf " -bs-jsx 3" - | _, Some Jsx_v4 -> Ext_buffer.add_string buf " -bs-jsx 4" - | Some Jsx_v3, None -> Ext_buffer.add_string buf " -bs-jsx 3" - | None, None -> ()); + (match (jsx.version) with + | Some Jsx_v4 -> Ext_buffer.add_string buf " -bs-jsx 4" + | None -> ()); (match jsx.module_ with | None -> () | Some React -> Ext_buffer.add_string buf " -bs-jsx-module react" diff --git a/jscomp/bsb/bsb_ninja_rule.mli b/jscomp/bsb/bsb_ninja_rule.mli index e8d25c2a92..b6ce806ab9 100644 --- a/jscomp/bsb/bsb_ninja_rule.mli +++ b/jscomp/bsb/bsb_ninja_rule.mli @@ -68,7 +68,6 @@ val make_custom_rules : gentype_config:Bsb_config_types.gentype_config -> has_postbuild:string option -> pp_file:string option -> - reason_react_jsx:Bsb_config_types.reason_react_jsx option -> jsx:Bsb_jsx.t -> digest:string -> package_specs:Bsb_package_specs.t -> diff --git a/jscomp/common/js_config.ml b/jscomp/common/js_config.ml index 84f4e22f68..6629a1278b 100644 --- a/jscomp/common/js_config.ml +++ b/jscomp/common/js_config.ml @@ -24,7 +24,7 @@ (** Browser is not set via command line only for internal use *) -type jsx_version = Jsx_v3 | Jsx_v4 +type jsx_version = Jsx_v4 type jsx_module = React | Generic of {module_name: string} type jsx_mode = Classic | Automatic @@ -59,7 +59,6 @@ let no_export = ref false let as_ppx = ref false let int_of_jsx_version = function - | Jsx_v3 -> 3 | Jsx_v4 -> 4 let string_of_jsx_module = function @@ -71,7 +70,6 @@ let string_of_jsx_mode = function | Automatic -> "automatic" let jsx_version_of_int = function - | 3 -> Some Jsx_v3 | 4 -> Some Jsx_v4 | _ -> None diff --git a/jscomp/common/js_config.mli b/jscomp/common/js_config.mli index 31855eaca7..ed0984624f 100644 --- a/jscomp/common/js_config.mli +++ b/jscomp/common/js_config.mli @@ -22,7 +22,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) -type jsx_version = Jsx_v3 | Jsx_v4 +type jsx_version = Jsx_v4 type jsx_module = React | Generic of {module_name: string} type jsx_mode = Classic | Automatic diff --git a/jscomp/gentype/TranslateTypeExprFromTypes.ml b/jscomp/gentype/TranslateTypeExprFromTypes.ml index ab51dcdce4..f7e949a95a 100644 --- a/jscomp/gentype/TranslateTypeExprFromTypes.ml +++ b/jscomp/gentype/TranslateTypeExprFromTypes.ml @@ -151,8 +151,7 @@ let translate_constr ~config ~params_translation ~(path : Path.t) ~type_env = param_translation1.dependencies @ param_translation2.dependencies; type_ = variant; } - | ( (["React"; "callback"] | ["ReactV3"; "React"; "callback"]), - [from_translation; to_translation] ) -> + | ["React"; "callback"], [from_translation; to_translation] -> { dependencies = from_translation.dependencies @ to_translation.dependencies; type_ = @@ -163,8 +162,7 @@ let translate_constr ~config ~params_translation ~(path : Path.t) ~type_env = type_vars = []; }; } - | ( (["React"; "componentLike"] | ["ReactV3"; "React"; "componentLike"]), - [props_translation; ret_translation] ) -> + | ["React"; "componentLike"], [props_translation; ret_translation] -> { dependencies = props_translation.dependencies @ ret_translation.dependencies; @@ -176,8 +174,7 @@ let translate_constr ~config ~params_translation ~(path : Path.t) ~type_env = type_vars = []; }; } - | ( (["React"; "component"] | ["ReactV3"; "React"; "component"]), - [props_translation] ) -> + | ["React"; "component"], [props_translation] -> { dependencies = props_translation.dependencies; type_ = @@ -188,17 +185,12 @@ let translate_constr ~config ~params_translation ~(path : Path.t) ~type_env = type_vars = []; }; } - | ( (["React"; "Context"; "t"] | ["ReactV3"; "React"; "Context"; "t"]), - [param_translation] ) -> + | ["React"; "Context"; "t"], [param_translation] -> { dependencies = param_translation.dependencies; type_ = EmitType.type_react_context ~type_:param_translation.type_; } - | ( ( ["React"; "Ref"; "t"] - | ["React"; "ref"] - | ["ReactV3"; "React"; "Ref"; "t"] - | ["ReactV3"; "React"; "ref"] ), - [param_translation] ) -> + | (["React"; "Ref"; "t"] | ["React"; "ref"]), [param_translation] -> { dependencies = param_translation.dependencies; type_ = EmitType.type_react_ref ~type_:param_translation.type_; @@ -214,7 +206,6 @@ let translate_constr ~config ~params_translation ~(path : Path.t) ~type_env = | ["ReactEvent"; "Mouse"; "t"], [] -> {dependencies = []; type_ = EmitType.type_react_event_mouse_t} | ( ( ["React"; "element"] - | ["ReactV3"; "React"; "element"] | ["ReasonReact"; "reactElement"] | ["Pervasives"; "Jsx"; "element"] ), [] ) -> diff --git a/jscomp/syntax/src/jsx_ppx.ml b/jscomp/syntax/src/jsx_ppx.ml index baf3da5448..a9a4894de8 100644 --- a/jscomp/syntax/src/jsx_ppx.ml +++ b/jscomp/syntax/src/jsx_ppx.ml @@ -72,12 +72,6 @@ let process_config_attribute attribute config = if is_jsx_config_attr attribute then update_config config (snd attribute) let get_mapper ~config = - let ( expr3, - module_binding3, - transform_signature_item3, - transform_structure_item3 ) = - Reactjs_jsx_v3.jsx_mapper ~config - in let ( expr4, module_binding4, transform_signature_item4, @@ -87,13 +81,11 @@ let get_mapper ~config = let expr mapper e = match config.version with - | 3 -> expr3 mapper e | 4 -> expr4 mapper e | _ -> default_mapper.expr mapper e in let module_binding mapper mb = match config.version with - | 3 -> module_binding3 mapper mb | 4 -> module_binding4 mapper mb | _ -> default_mapper.module_binding mapper mb in @@ -122,9 +114,7 @@ let get_mapper ~config = | Psig_attribute attr -> process_config_attribute attr config | _ -> ()); let item = default_mapper.signature_item mapper item in - if config.version = 3 then transform_signature_item3 item - else if config.version = 4 then transform_signature_item4 item - else [item]) + if config.version = 4 then transform_signature_item4 item else [item]) items |> List.flatten in @@ -141,9 +131,7 @@ let get_mapper ~config = | Pstr_attribute attr -> process_config_attribute attr config | _ -> ()); let item = default_mapper.structure_item mapper item in - if config.version = 3 then transform_structure_item3 item - else if config.version = 4 then transform_structure_item4 item - else [item]) + if config.version = 4 then transform_structure_item4 item else [item]) items |> List.flatten in diff --git a/jscomp/syntax/src/reactjs_jsx_v3.ml b/jscomp/syntax/src/reactjs_jsx_v3.ml deleted file mode 100644 index 64658b6feb..0000000000 --- a/jscomp/syntax/src/reactjs_jsx_v3.ml +++ /dev/null @@ -1,1222 +0,0 @@ -open Ast_helper -open Ast_mapper -open Asttypes -open Parsetree -open Longident - -let nolabel = Nolabel - -let labelled str = Labelled str - -let optional str = Optional str - -let is_optional str = - match str with - | Optional _ -> true - | _ -> false - -let is_labelled str = - match str with - | Labelled _ -> true - | _ -> false - -let get_label str = - match str with - | Optional str | Labelled str -> str - | Nolabel -> "" - -let option_ident = Lident "option" - -let constant_string ~loc str = - Ast_helper.Exp.constant ~loc (Pconst_string (str, None)) - -let safe_type_from_value value_str = - let value_str = get_label value_str in - if value_str = "" || (value_str.[0] [@doesNotRaise]) <> '_' then value_str - else "T" ^ value_str - -let key_type loc = - Typ.constr ~loc {loc; txt = option_ident} - [Typ.constr ~loc {loc; txt = Lident "string"} []] - -type 'a children = ListLiteral of 'a | Exact of 'a - -type component_config = {props_name: string} - -(* if children is a list, convert it to an array while mapping each element. If not, just map over it, as usual *) -let transform_children_if_list_upper ~loc ~mapper the_list = - let rec transformChildren_ the_list accum = - (* not in the sense of converting a list to an array; convert the AST - reprensentation of a list to the AST reprensentation of an array *) - match the_list with - | {pexp_desc = Pexp_construct ({txt = Lident "[]"}, None)} -> ( - match accum with - | [single_element] -> Exact single_element - | accum -> ListLiteral (Exp.array ~loc (List.rev accum))) - | { - pexp_desc = - Pexp_construct - ({txt = Lident "::"}, Some {pexp_desc = Pexp_tuple [v; acc]}); - } -> - transformChildren_ acc (mapper.expr mapper v :: accum) - | not_a_list -> Exact (mapper.expr mapper not_a_list) - in - transformChildren_ the_list [] - -let transform_children_if_list ~loc ~mapper the_list = - let rec transformChildren_ the_list accum = - (* not in the sense of converting a list to an array; convert the AST - reprensentation of a list to the AST reprensentation of an array *) - match the_list with - | {pexp_desc = Pexp_construct ({txt = Lident "[]"}, None)} -> - Exp.array ~loc (List.rev accum) - | { - pexp_desc = - Pexp_construct - ({txt = Lident "::"}, Some {pexp_desc = Pexp_tuple [v; acc]}); - } -> - transformChildren_ acc (mapper.expr mapper v :: accum) - | not_a_list -> mapper.expr mapper not_a_list - in - transformChildren_ the_list [] - -let extract_children ?(remove_last_position_unit = false) ~loc - props_and_children = - let rec allButLast_ lst acc = - match lst with - | [] -> [] - | [(Nolabel, {pexp_desc = Pexp_construct ({txt = Lident "()"}, None)})] -> - acc - | (Nolabel, {pexp_loc}) :: _rest -> - Jsx_common.raise_error ~loc:pexp_loc - "JSX: found non-labelled argument before the last position" - | arg :: rest -> allButLast_ rest (arg :: acc) - in - let all_but_last lst = allButLast_ lst [] |> List.rev in - match - List.partition - (fun (label, _) -> label = labelled "children") - props_and_children - with - | [], props -> - (* no children provided? Place a placeholder list *) - ( Exp.construct ~loc {loc; txt = Lident "[]"} None, - if remove_last_position_unit then all_but_last props else props ) - | [(_, children_expr)], props -> - ( children_expr, - if remove_last_position_unit then all_but_last props else props ) - | _ -> - Jsx_common.raise_error ~loc - "JSX: somehow there's more than one `children` label" - -let unerasable_ignore loc = - ( {loc; txt = "warning"}, - PStr [Str.eval (Exp.constant (Pconst_string ("-16", None)))] ) - -let merlin_focus = ({loc = Location.none; txt = "merlin.focus"}, PStr []) - -(* Helper method to filter out any attribute that isn't [@react.component] *) -let other_attrs_pure (loc, _) = loc.txt <> "react.component" - -(* Finds the name of the variable the binding is assigned to, otherwise raises Invalid_argument *) -let rec get_fn_name binding = - match binding with - | {ppat_desc = Ppat_var {txt}} -> txt - | {ppat_desc = Ppat_constraint (pat, _)} -> get_fn_name pat - | {ppat_loc} -> - Jsx_common.raise_error ~loc:ppat_loc - "react.component calls cannot be destructured." - -let make_new_binding binding expression new_name = - match binding with - | {pvb_pat = {ppat_desc = Ppat_var ppat_var} as pvb_pat} -> - { - binding with - pvb_pat = - {pvb_pat with ppat_desc = Ppat_var {ppat_var with txt = new_name}}; - pvb_expr = expression; - pvb_attributes = [merlin_focus]; - } - | {pvb_loc} -> - Jsx_common.raise_error ~loc:pvb_loc - "react.component calls cannot be destructured." - -(* Lookup the value of `props` otherwise raise Invalid_argument error *) -let get_props_name_value _acc (loc, exp) = - match (loc, exp) with - | {txt = Lident "props"}, {pexp_desc = Pexp_ident {txt = Lident str}} -> - {props_name = str} - | {txt; loc}, _ -> - Jsx_common.raise_error ~loc - "react.component only accepts props as an option, given: { %s }" - (Longident.last txt) - -(* Lookup the `props` record or string as part of [@react.component] and store the name for use when rewriting *) -let get_props_attr payload = - let default_props = {props_name = "Props"} in - match payload with - | Some - (PStr - ({ - pstr_desc = - Pstr_eval ({pexp_desc = Pexp_record (record_fields, None)}, _); - } - :: _rest)) -> - List.fold_left get_props_name_value default_props record_fields - | Some - (PStr - ({ - pstr_desc = - Pstr_eval ({pexp_desc = Pexp_ident {txt = Lident "props"}}, _); - } - :: _rest)) -> - {props_name = "props"} - | Some (PStr ({pstr_desc = Pstr_eval (_, _); pstr_loc} :: _rest)) -> - Jsx_common.raise_error ~loc:pstr_loc - "react.component accepts a record config with props as an options." - | _ -> default_props - -(* Plucks the label, loc, and type_ from an AST node *) -let pluck_label_default_loc_type (label, default, _, _, loc, type_) = - (label, default, loc, type_) - -(* Lookup the filename from the location information on the AST node and turn it into a valid module identifier *) -let filename_from_loc (pstr_loc : Location.t) = - let file_name = - match pstr_loc.loc_start.pos_fname with - | "" -> !Location.input_name - | file_name -> file_name - in - let file_name = - try Filename.chop_extension (Filename.basename file_name) - with Invalid_argument _ -> file_name - in - let file_name = String.capitalize_ascii file_name in - file_name - -(* Build a string representation of a module name with segments separated by $ *) -let make_module_name file_name nested_modules fn_name = - let full_module_name = - match (file_name, nested_modules, fn_name) with - (* TODO: is this even reachable? It seems like the fileName always exists *) - | "", nested_modules, "make" -> nested_modules - | "", nested_modules, fn_name -> List.rev (fn_name :: nested_modules) - | file_name, nested_modules, "make" -> file_name :: List.rev nested_modules - | file_name, nested_modules, fn_name -> - file_name :: List.rev (fn_name :: nested_modules) - in - let full_module_name = String.concat "$" full_module_name in - full_module_name - -(* - AST node builders - These functions help us build AST nodes that are needed when transforming a [@react.component] into a - constructor and a props external -*) - -(* Build an AST node representing all named args for the `external` definition for a component's props *) -let rec recursively_make_named_args_for_external list args = - match list with - | (label, default, loc, interior_type) :: tl -> - recursively_make_named_args_for_external tl - (Typ.arrow ~loc label - (match (label, interior_type, default) with - (* ~foo=1 *) - | label, None, Some _ -> - { - ptyp_desc = Ptyp_var (safe_type_from_value label); - ptyp_loc = loc; - ptyp_attributes = []; - } - (* ~foo: int=1 *) - | _label, Some type_, Some _ -> type_ - (* ~foo: option=? *) - | ( label, - Some {ptyp_desc = Ptyp_constr ({txt = Lident "option"}, [type_])}, - _ ) - | ( label, - Some - { - ptyp_desc = - Ptyp_constr - ({txt = Ldot (Lident "*predef*", "option")}, [type_]); - }, - _ ) - (* ~foo: int=? - note this isnt valid. but we want to get a type error *) - | label, Some type_, _ - when is_optional label -> - type_ - (* ~foo=? *) - | label, None, _ when is_optional label -> - { - ptyp_desc = Ptyp_var (safe_type_from_value label); - ptyp_loc = loc; - ptyp_attributes = []; - } - (* ~foo *) - | label, None, _ -> - { - ptyp_desc = Ptyp_var (safe_type_from_value label); - ptyp_loc = loc; - ptyp_attributes = []; - } - | _label, Some type_, _ -> type_) - args) - | [] -> args - -(* Build an AST node for the [@obj] representing props for a component *) -let make_props_value fn_name loc named_arg_list_with_key_and_ref props_type = - let props_name = fn_name ^ "Props" in - { - pval_name = {txt = props_name; loc}; - pval_type = - recursively_make_named_args_for_external named_arg_list_with_key_and_ref - (Typ.arrow nolabel - { - ptyp_desc = Ptyp_constr ({txt = Lident "unit"; loc}, []); - ptyp_loc = loc; - ptyp_attributes = []; - } - props_type); - pval_prim = [""]; - pval_attributes = [({txt = "obj"; loc}, PStr [])]; - pval_loc = loc; - } - -(* Build an AST node representing an `external` with the definition of the [@obj] *) -let make_props_external fn_name loc named_arg_list_with_key_and_ref props_type = - { - pstr_loc = loc; - pstr_desc = - Pstr_primitive - (make_props_value fn_name loc named_arg_list_with_key_and_ref props_type); - } - -(* Build an AST node for the signature of the `external` definition *) -let make_props_external_sig fn_name loc named_arg_list_with_key_and_ref - props_type = - { - psig_loc = loc; - psig_desc = - Psig_value - (make_props_value fn_name loc named_arg_list_with_key_and_ref props_type); - } - -(* Build an AST node for the props name when converted to an object inside the function signature *) -let make_props_name ~loc name = - {ppat_desc = Ppat_var {txt = name; loc}; ppat_loc = loc; ppat_attributes = []} - -let make_object_field loc (str, attrs, type_) = - Otag ({loc; txt = str}, attrs, type_) - -(* Build an AST node representing a "closed" object representing a component's props *) -let make_props_type ~loc named_type_list = - Typ.mk ~loc - (Ptyp_object (List.map (make_object_field loc) named_type_list, Closed)) - -(* Builds an AST node for the entire `external` definition of props *) -let make_external_decl fn_name loc named_arg_list_with_key_and_ref - named_type_list = - make_props_external fn_name loc - (List.map pluck_label_default_loc_type named_arg_list_with_key_and_ref) - (make_props_type ~loc named_type_list) - -let newtype_to_var newtype type_ = - let var_desc = Ptyp_var ("type-" ^ newtype) in - let typ (mapper : Ast_mapper.mapper) typ = - match typ.ptyp_desc with - | Ptyp_constr ({txt = Lident name}, _) when name = newtype -> - {typ with ptyp_desc = var_desc} - | _ -> Ast_mapper.default_mapper.typ mapper typ - in - let mapper = {Ast_mapper.default_mapper with typ} in - mapper.typ mapper type_ - -(* TODO: some line number might still be wrong *) -let jsx_mapper ~config = - let transform_uppercase_call3 module_path mapper loc attrs _ call_arguments = - let children, args_with_labels = - extract_children ~loc ~remove_last_position_unit:true call_arguments - in - let args_for_make = args_with_labels in - let children_expr = - transform_children_if_list_upper ~loc ~mapper children - in - let recursively_transformed_args_for_make = - args_for_make - |> List.map (fun (label, expression) -> - (label, mapper.expr mapper expression)) - in - let children_arg = ref None in - let args = - recursively_transformed_args_for_make - @ (match children_expr with - | Exact children -> [(labelled "children", children)] - | ListLiteral {pexp_desc = Pexp_array list} when list = [] -> [] - | ListLiteral expression -> - (* this is a hack to support react components that introspect into their children *) - children_arg := Some expression; - [ - ( labelled "children", - Exp.ident ~loc {loc; txt = Ldot (Lident "React", "null")} ); - ]) - @ [(nolabel, Exp.construct ~loc {loc; txt = Lident "()"} None)] - in - let is_cap str = String.capitalize_ascii str = str in - let ident = - match module_path with - | Lident _ -> Ldot (module_path, "make") - | Ldot (_modulePath, value) as full_path when is_cap value -> - Ldot (full_path, "make") - | module_path -> module_path - in - let props_ident = - match ident with - | Lident path -> Lident (path ^ "Props") - | Ldot (ident, path) -> Ldot (ident, path ^ "Props") - | _ -> - Jsx_common.raise_error ~loc - "JSX name can't be the result of function applications" - in - let props = - Exp.apply ~attrs ~loc (Exp.ident ~loc {loc; txt = props_ident}) args - in - (* handle key, ref, children *) - (* React.createElement(Component.make, props, ...children) *) - match !children_arg with - | None -> - Exp.apply ~loc ~attrs - (Exp.ident ~loc {loc; txt = Ldot (Lident "React", "createElement")}) - [(nolabel, Exp.ident ~loc {txt = ident; loc}); (nolabel, props)] - | Some children -> - Exp.apply ~loc ~attrs - (Exp.ident ~loc - {loc; txt = Ldot (Lident "React", "createElementVariadic")}) - [ - (nolabel, Exp.ident ~loc {txt = ident; loc}); - (nolabel, props); - (nolabel, children); - ] - in - - let transform_lowercase_call3 mapper loc attrs call_arguments id = - let children, non_children_props = extract_children ~loc call_arguments in - let component_name_expr = constant_string ~loc id in - let children_expr = transform_children_if_list ~loc ~mapper children in - let create_element_call = - match children with - (* [@JSX] div(~children=[a]), coming from
a
*) - | { - pexp_desc = - ( Pexp_construct ({txt = Lident "::"}, Some {pexp_desc = Pexp_tuple _}) - | Pexp_construct ({txt = Lident "[]"}, None) ); - } -> - "createDOMElementVariadic" - (* [@JSX] div(~children= value), coming from
...(value)
*) - | {pexp_loc} -> - Jsx_common.raise_error ~loc:pexp_loc - "A spread as a DOM element's children don't make sense written \ - together. You can simply remove the spread." - in - let args = - match non_children_props with - | [_justTheUnitArgumentAtEnd] -> - [ - (* "div" *) - (nolabel, component_name_expr); - (* [|moreCreateElementCallsHere|] *) - (nolabel, children_expr); - ] - | non_empty_props -> - let props_call = - Exp.apply ~loc - (Exp.ident ~loc {loc; txt = Ldot (Lident "ReactDOMRe", "domProps")}) - (non_empty_props - |> List.map (fun (label, expression) -> - (label, mapper.expr mapper expression))) - in - [ - (* "div" *) - (nolabel, component_name_expr); - (* ReactDOMRe.props(~className=blabla, ~foo=bar, ()) *) - (labelled "props", props_call); - (* [|moreCreateElementCallsHere|] *) - (nolabel, children_expr); - ] - in - Exp.apply - ~loc (* throw away the [@JSX] attribute and keep the others, if any *) - ~attrs - (* ReactDOMRe.createElement *) - (Exp.ident ~loc - {loc; txt = Ldot (Lident "ReactDOMRe", create_element_call)}) - args - in - - let rec recursively_transform_named_args_for_make expr args newtypes = - match expr.pexp_desc with - (* TODO: make this show up with a loc. *) - | Pexp_fun (Labelled "key", _, _, _) | Pexp_fun (Optional "key", _, _, _) -> - Jsx_common.raise_error ~loc:expr.pexp_loc - "Key cannot be accessed inside of a component. Don't worry - you can \ - always key a component from its parent!" - | Pexp_fun (Labelled "ref", _, _, _) | Pexp_fun (Optional "ref", _, _, _) -> - Jsx_common.raise_error ~loc:expr.pexp_loc - "Ref cannot be passed as a normal prop. Either give the prop a \ - different name or use the `forwardRef` API instead." - | Pexp_fun (arg, default, pattern, expression) - when is_optional arg || is_labelled arg -> - let () = - match (is_optional arg, pattern, default) with - | true, {ppat_desc = Ppat_constraint (_, {ptyp_desc})}, None -> ( - match ptyp_desc with - | Ptyp_constr ({txt = Lident "option"}, [_]) -> () - | _ -> - let current_type = - match ptyp_desc with - | Ptyp_constr ({txt}, []) -> - String.concat "." (Longident.flatten txt) - | Ptyp_constr ({txt}, _innerTypeArgs) -> - String.concat "." (Longident.flatten txt) ^ "(...)" - | _ -> "..." - in - Location.prerr_warning pattern.ppat_loc - (Preprocessor - (Printf.sprintf - "React: optional argument annotations must have explicit \ - `option`. Did you mean `option<%s>=?`?" - current_type))) - | _ -> () - in - let alias = - match pattern with - | {ppat_desc = Ppat_alias (_, {txt}) | Ppat_var {txt}} -> txt - | {ppat_desc = Ppat_any} -> "_" - | _ -> get_label arg - in - let type_ = - match pattern with - | {ppat_desc = Ppat_constraint (_, type_)} -> Some type_ - | _ -> None - in - - recursively_transform_named_args_for_make expression - ((arg, default, pattern, alias, pattern.ppat_loc, type_) :: args) - newtypes - | Pexp_fun - ( Nolabel, - _, - {ppat_desc = Ppat_construct ({txt = Lident "()"}, _) | Ppat_any}, - _expression ) -> - (args, newtypes, None) - | Pexp_fun - ( Nolabel, - _, - { - ppat_desc = - Ppat_var {txt} | Ppat_constraint ({ppat_desc = Ppat_var {txt}}, _); - }, - _expression ) -> - (args, newtypes, Some txt) - | Pexp_fun (Nolabel, _, pattern, _expression) -> - Location.raise_errorf ~loc:pattern.ppat_loc - "React: react.component refs only support plain arguments and type \ - annotations." - | Pexp_newtype (label, expression) -> - recursively_transform_named_args_for_make expression args - (label :: newtypes) - | Pexp_constraint (expression, _typ) -> - recursively_transform_named_args_for_make expression args newtypes - | _ -> (args, newtypes, None) - in - - let arg_to_type types (name, default, _noLabelName, _alias, loc, type_) = - match (type_, name, default) with - | Some {ptyp_desc = Ptyp_constr ({txt = Lident "option"}, [type_])}, name, _ - when is_optional name -> - ( get_label name, - [], - { - type_ with - ptyp_desc = - Ptyp_constr ({loc = type_.ptyp_loc; txt = option_ident}, [type_]); - } ) - :: types - | Some type_, name, Some _default -> - ( get_label name, - [], - { - ptyp_desc = Ptyp_constr ({loc; txt = option_ident}, [type_]); - ptyp_loc = loc; - ptyp_attributes = []; - } ) - :: types - | Some type_, name, _ -> (get_label name, [], type_) :: types - | None, name, _ when is_optional name -> - ( get_label name, - [], - { - ptyp_desc = - Ptyp_constr - ( {loc; txt = option_ident}, - [ - { - ptyp_desc = Ptyp_var (safe_type_from_value name); - ptyp_loc = loc; - ptyp_attributes = []; - }; - ] ); - ptyp_loc = loc; - ptyp_attributes = []; - } ) - :: types - | None, name, _ when is_labelled name -> - ( get_label name, - [], - { - ptyp_desc = Ptyp_var (safe_type_from_value name); - ptyp_loc = loc; - ptyp_attributes = []; - } ) - :: types - | _ -> types - in - - let arg_to_concrete_type types (name, loc, type_) = - match name with - | name when is_labelled name -> (get_label name, [], type_) :: types - | name when is_optional name -> - (get_label name, [], Typ.constr ~loc {loc; txt = option_ident} [type_]) - :: types - | _ -> types - in - - let nested_modules = ref [] in - let transform_structure_item item = - match item with - (* external *) - | { - pstr_loc; - pstr_desc = - Pstr_primitive - ({pval_name = {txt = fn_name}; pval_attributes; pval_type} as - value_description); - } as pstr -> ( - match List.filter Jsx_common.has_attr pval_attributes with - | [] -> [item] - | [_] -> - let pval_type = Jsx_common.extract_uncurried pval_type in - let rec get_prop_types types ({ptyp_loc; ptyp_desc} as full_type) = - match ptyp_desc with - | Ptyp_arrow (name, type_, ({ptyp_desc = Ptyp_arrow _} as rest)) - when is_labelled name || is_optional name -> - get_prop_types ((name, ptyp_loc, type_) :: types) rest - | Ptyp_arrow (Nolabel, _type, rest) -> get_prop_types types rest - | Ptyp_arrow (name, type_, return_value) - when is_labelled name || is_optional name -> - (return_value, (name, return_value.ptyp_loc, type_) :: types) - | _ -> (full_type, types) - in - let inner_type, prop_types = get_prop_types [] pval_type in - let named_type_list = - List.fold_left arg_to_concrete_type [] prop_types - in - let pluck_label_and_loc (label, loc, type_) = - (label, None (* default *), loc, Some type_) - in - let ret_props_type = make_props_type ~loc:pstr_loc named_type_list in - let external_props_decl = - make_props_external fn_name pstr_loc - ((optional "key", None, pstr_loc, Some (key_type pstr_loc)) - :: List.map pluck_label_and_loc prop_types) - ret_props_type - in - (* can't be an arrow because it will defensively uncurry *) - let new_external_type = - Ptyp_constr - ( {loc = pstr_loc; txt = Ldot (Lident "React", "componentLike")}, - [ret_props_type; inner_type] ) - in - let new_structure = - { - pstr with - pstr_desc = - Pstr_primitive - { - value_description with - pval_type = {pval_type with ptyp_desc = new_external_type}; - pval_attributes = List.filter other_attrs_pure pval_attributes; - }; - } - in - [external_props_decl; new_structure] - | _ -> - Jsx_common.raise_error ~loc:pstr_loc - "Only one react.component call can exist on a component at one time") - (* let component = ... *) - | {pstr_loc; pstr_desc = Pstr_value (rec_flag, value_bindings)} -> ( - let file_name = filename_from_loc pstr_loc in - let empty_loc = Location.in_file file_name in - let map_binding binding = - if Jsx_common.has_attr_on_binding binding then - let binding = Jsx_common.remove_arity binding in - let binding_loc = binding.pvb_loc in - let binding_pat_loc = binding.pvb_pat.ppat_loc in - let binding = - { - binding with - pvb_pat = {binding.pvb_pat with ppat_loc = empty_loc}; - pvb_loc = empty_loc; - } - in - let fn_name = get_fn_name binding.pvb_pat in - let internal_fn_name = fn_name ^ "$Internal" in - let full_module_name = - make_module_name file_name !nested_modules fn_name - in - let modified_binding_old binding = - let expression = binding.pvb_expr in - (* TODO: there is a long-tail of unsupported features inside of blocks - Pexp_letmodule , Pexp_letexception , Pexp_ifthenelse *) - let rec spelunk_for_fun_expression expression = - match expression with - (* let make = (~prop) => ... *) - | {pexp_desc = Pexp_fun _} | {pexp_desc = Pexp_newtype _} -> - expression - (* let make = {let foo = bar in (~prop) => ...} *) - | {pexp_desc = Pexp_let (_recursive, _vbs, return_expression)} -> - (* here's where we spelunk! *) - spelunk_for_fun_expression return_expression - (* let make = React.forwardRef((~prop) => ...) *) - | { - pexp_desc = - Pexp_apply - (_wrapperExpression, [(Nolabel, inner_function_expression)]); - } -> - spelunk_for_fun_expression inner_function_expression - | { - pexp_desc = - Pexp_sequence (_wrapperExpression, inner_function_expression); - } -> - spelunk_for_fun_expression inner_function_expression - | {pexp_desc = Pexp_constraint (inner_function_expression, _typ)} - -> - spelunk_for_fun_expression inner_function_expression - | {pexp_loc} -> - Jsx_common.raise_error ~loc:pexp_loc - "react.component calls can only be on function definitions \ - or component wrappers (forwardRef, memo)." - in - spelunk_for_fun_expression expression - in - let modified_binding binding = - let has_application = ref false in - let wrap_expression_with_binding expression_fn expression = - Vb.mk ~loc:binding_loc - ~attrs:(List.filter other_attrs_pure binding.pvb_attributes) - (Pat.var ~loc:binding_pat_loc - {loc = binding_pat_loc; txt = fn_name}) - (expression_fn expression) - in - let expression = binding.pvb_expr in - let unerasable_ignore_exp exp = - { - exp with - pexp_attributes = - unerasable_ignore empty_loc :: exp.pexp_attributes; - } - in - (* TODO: there is a long-tail of unsupported features inside of blocks - Pexp_letmodule , Pexp_letexception , Pexp_ifthenelse *) - let rec spelunk_for_fun_expression expression = - match expression with - (* let make = (~prop) => ... with no final unit *) - | { - pexp_desc = - Pexp_fun - ( ((Labelled _ | Optional _) as label), - default, - pattern, - ({pexp_desc = Pexp_fun _} as internal_expression) ); - } -> - let wrap, has_unit, exp = - spelunk_for_fun_expression internal_expression - in - ( wrap, - has_unit, - unerasable_ignore_exp - { - expression with - pexp_desc = Pexp_fun (label, default, pattern, exp); - } ) - (* let make = (()) => ... *) - (* let make = (_) => ... *) - | { - pexp_desc = - Pexp_fun - ( Nolabel, - _default, - { - ppat_desc = - Ppat_construct ({txt = Lident "()"}, _) | Ppat_any; - }, - _internalExpression ); - } -> - ((fun a -> a), true, expression) - (* let make = (~prop) => ... *) - | { - pexp_desc = - Pexp_fun - ( (Labelled _ | Optional _), - _default, - _pattern, - _internalExpression ); - } -> - ((fun a -> a), false, unerasable_ignore_exp expression) - (* let make = (prop) => ... *) - | { - pexp_desc = - Pexp_fun (_nolabel, _default, pattern, _internalExpression); - } -> - if has_application.contents then - ((fun a -> a), false, unerasable_ignore_exp expression) - else - Location.raise_errorf ~loc:pattern.ppat_loc - "React: props need to be labelled arguments.\n\ - \ If you are working with refs be sure to wrap with \ - React.forwardRef.\n\ - \ If your component doesn't have any props use () or _ \ - instead of a name." - (* let make = {let foo = bar in (~prop) => ...} *) - | {pexp_desc = Pexp_let (recursive, vbs, internal_expression)} -> - (* here's where we spelunk! *) - let wrap, has_unit, exp = - spelunk_for_fun_expression internal_expression - in - ( wrap, - has_unit, - {expression with pexp_desc = Pexp_let (recursive, vbs, exp)} - ) - (* let make = React.forwardRef((~prop) => ...) *) - | { - pexp_desc = - Pexp_apply - (wrapper_expression, [(Nolabel, internal_expression)]); - } -> - let () = has_application := true in - let _, has_unit, exp = - spelunk_for_fun_expression internal_expression - in - ( (fun exp -> Exp.apply wrapper_expression [(nolabel, exp)]), - has_unit, - exp ) - | { - pexp_desc = - Pexp_sequence (wrapper_expression, internal_expression); - } -> - let wrap, has_unit, exp = - spelunk_for_fun_expression internal_expression - in - ( wrap, - has_unit, - { - expression with - pexp_desc = Pexp_sequence (wrapper_expression, exp); - } ) - | e -> ((fun a -> a), false, e) - in - let wrap_expression, has_unit, expression = - spelunk_for_fun_expression expression - in - (wrap_expression_with_binding wrap_expression, has_unit, expression) - in - let binding_wrapper, has_unit, expression = - modified_binding binding - in - let react_component_attribute = - try Some (List.find Jsx_common.has_attr binding.pvb_attributes) - with Not_found -> None - in - let _attr_loc, payload = - match react_component_attribute with - | Some (loc, payload) -> (loc.loc, Some payload) - | None -> (empty_loc, None) - in - let props = get_props_attr payload in - (* do stuff here! *) - let named_arg_list, newtypes, forward_ref = - recursively_transform_named_args_for_make - (modified_binding_old binding) - [] [] - in - let named_arg_list_with_key_and_ref = - ( optional "key", - None, - Pat.var {txt = "key"; loc = empty_loc}, - "key", - empty_loc, - Some (key_type empty_loc) ) - :: named_arg_list - in - let named_arg_list_with_key_and_ref = - match forward_ref with - | Some _ -> - ( optional "ref", - None, - Pat.var {txt = "key"; loc = empty_loc}, - "ref", - empty_loc, - None ) - :: named_arg_list_with_key_and_ref - | None -> named_arg_list_with_key_and_ref - in - let named_arg_list_with_key_and_ref_for_new = - match forward_ref with - | Some txt -> - named_arg_list - @ [ - ( nolabel, - None, - Pat.var {txt; loc = empty_loc}, - txt, - empty_loc, - None ); - ] - | None -> named_arg_list - in - let pluck_arg (label, _, _, alias, loc, _) = - let label_string = - match label with - | label when is_optional label || is_labelled label -> - get_label label - | _ -> "" - in - ( label, - match label_string with - | "" -> Exp.ident ~loc {txt = Lident alias; loc} - | label_string -> - Exp.apply ~loc - (Exp.ident ~loc {txt = Lident "##"; loc}) - [ - ( nolabel, - Exp.ident ~loc {txt = Lident props.props_name; loc} ); - (nolabel, Exp.ident ~loc {txt = Lident label_string; loc}); - ] ) - in - let named_type_list = List.fold_left arg_to_type [] named_arg_list in - let loc = empty_loc in - let external_args = - (* translate newtypes to type variables *) - List.fold_left - (fun args newtype -> - List.map - (fun (a, b, c, d, e, maybe_typ) -> - match maybe_typ with - | Some typ -> - (a, b, c, d, e, Some (newtype_to_var newtype.txt typ)) - | None -> (a, b, c, d, e, None)) - args) - named_arg_list_with_key_and_ref newtypes - in - let external_types = - (* translate newtypes to type variables *) - List.fold_left - (fun args newtype -> - List.map - (fun (a, b, typ) -> (a, b, newtype_to_var newtype.txt typ)) - args) - named_type_list newtypes - in - let external_decl = - make_external_decl fn_name loc external_args external_types - in - let inner_expression_args = - List.map pluck_arg named_arg_list_with_key_and_ref_for_new - @ - if has_unit then - [(Nolabel, Exp.construct {loc; txt = Lident "()"} None)] - else [] - in - let inner_expression = - Exp.apply - (Exp.ident - { - loc; - txt = - Lident - (match rec_flag with - | Recursive -> internal_fn_name - | Nonrecursive -> fn_name); - }) - inner_expression_args - in - let inner_expression_with_ref = - match forward_ref with - | Some txt -> - { - inner_expression with - pexp_desc = - Pexp_fun - ( nolabel, - None, - { - ppat_desc = Ppat_var {txt; loc = empty_loc}; - ppat_loc = empty_loc; - ppat_attributes = []; - }, - inner_expression ); - } - | None -> inner_expression - in - let full_expression = - Exp.fun_ nolabel None - { - ppat_desc = - Ppat_constraint - ( make_props_name ~loc:empty_loc props.props_name, - make_props_type ~loc:empty_loc external_types ); - ppat_loc = empty_loc; - ppat_attributes = []; - } - inner_expression_with_ref - in - let full_expression = - full_expression - |> Ast_uncurried.uncurried_fun ~loc:full_expression.pexp_loc - ~arity:1 - in - let full_expression = - match full_module_name with - | "" -> full_expression - | txt -> - Exp.let_ Nonrecursive - [ - Vb.mk ~loc:empty_loc - (Pat.var ~loc:empty_loc {loc = empty_loc; txt}) - full_expression; - ] - (Exp.ident ~loc:empty_loc {loc = empty_loc; txt = Lident txt}) - in - let bindings, new_binding = - match rec_flag with - | Recursive -> - ( [ - binding_wrapper - (Exp.let_ ~loc:empty_loc Recursive - [ - make_new_binding binding expression internal_fn_name; - Vb.mk - (Pat.var {loc = empty_loc; txt = fn_name}) - full_expression; - ] - (Exp.ident {loc = empty_loc; txt = Lident fn_name})); - ], - None ) - | Nonrecursive -> - ( [{binding with pvb_expr = expression}], - Some (binding_wrapper full_expression) ) - in - (Some external_decl, bindings, new_binding) - else (None, [binding], None) - in - let structures_and_binding = List.map map_binding value_bindings in - let other_structures (extern, binding, new_binding) - (externs, bindings, new_bindings) = - let externs = - match extern with - | Some extern -> extern :: externs - | None -> externs - in - let new_bindings = - match new_binding with - | Some new_binding -> new_binding :: new_bindings - | None -> new_bindings - in - (externs, binding @ bindings, new_bindings) - in - let externs, bindings, new_bindings = - List.fold_right other_structures structures_and_binding ([], [], []) - in - externs - @ [{pstr_loc; pstr_desc = Pstr_value (rec_flag, bindings)}] - @ - match new_bindings with - | [] -> [] - | new_bindings -> - [ - {pstr_loc = empty_loc; pstr_desc = Pstr_value (rec_flag, new_bindings)}; - ]) - | _ -> [item] - in - - let transform_signature_item item = - match item with - | { - psig_loc; - psig_desc = - Psig_value - ({pval_name = {txt = fn_name}; pval_attributes; pval_type} as - psig_desc); - } as psig -> ( - match List.filter Jsx_common.has_attr pval_attributes with - | [] -> [item] - | [_] -> - let pval_type = Jsx_common.extract_uncurried pval_type in - let rec get_prop_types types ({ptyp_loc; ptyp_desc} as full_type) = - match ptyp_desc with - | Ptyp_arrow (name, type_, ({ptyp_desc = Ptyp_arrow _} as rest)) - when is_optional name || is_labelled name -> - get_prop_types ((name, ptyp_loc, type_) :: types) rest - | Ptyp_arrow (Nolabel, _type, rest) -> get_prop_types types rest - | Ptyp_arrow (name, type_, return_value) - when is_optional name || is_labelled name -> - (return_value, (name, return_value.ptyp_loc, type_) :: types) - | _ -> (full_type, types) - in - let inner_type, prop_types = get_prop_types [] pval_type in - let named_type_list = - List.fold_left arg_to_concrete_type [] prop_types - in - let pluck_label_and_loc (label, loc, type_) = - (label, None, loc, Some type_) - in - let ret_props_type = make_props_type ~loc:psig_loc named_type_list in - let external_props_decl = - make_props_external_sig fn_name psig_loc - ((optional "key", None, psig_loc, Some (key_type psig_loc)) - :: List.map pluck_label_and_loc prop_types) - ret_props_type - in - (* can't be an arrow because it will defensively uncurry *) - let new_external_type = - Ptyp_constr - ( {loc = psig_loc; txt = Ldot (Lident "React", "componentLike")}, - [ret_props_type; inner_type] ) - in - let new_structure = - { - psig with - psig_desc = - Psig_value - { - psig_desc with - pval_type = {pval_type with ptyp_desc = new_external_type}; - pval_attributes = List.filter other_attrs_pure pval_attributes; - }; - } - in - [external_props_decl; new_structure] - | _ -> - Jsx_common.raise_error ~loc:psig_loc - "Only one react.component call can exist on a component at one time") - | _ -> [item] - in - - let transform_jsx_call mapper call_expression call_arguments attrs = - match call_expression.pexp_desc with - | Pexp_ident caller -> ( - match caller with - | {txt = Lident "createElement"; loc} -> - Jsx_common.raise_error ~loc - "JSX: `createElement` should be preceeded by a module name." - (* Foo.createElement(~prop1=foo, ~prop2=bar, ~children=[], ()) *) - | {loc; txt = Ldot (module_path, ("createElement" | "make"))} -> ( - match config.Jsx_common.version with - | 3 -> - transform_uppercase_call3 module_path mapper loc attrs call_expression - call_arguments - | _ -> Jsx_common.raise_error ~loc "JSX: the JSX version must be 3") - (* div(~prop1=foo, ~prop2=bar, ~children=[bla], ()) *) - (* turn that into - ReactDOMRe.createElement(~props=ReactDOMRe.props(~props1=foo, ~props2=bar, ()), [|bla|]) *) - | {loc; txt = Lident id} -> ( - match config.version with - | 3 -> transform_lowercase_call3 mapper loc attrs call_arguments id - | _ -> Jsx_common.raise_error ~loc "JSX: the JSX version must be 3") - | {txt = Ldot (_, anything_not_create_element_or_make); loc} -> - Jsx_common.raise_error ~loc - "JSX: the JSX attribute should be attached to a \ - `YourModuleName.createElement` or `YourModuleName.make` call. We \ - saw `%s` instead" - anything_not_create_element_or_make - | {txt = Lapply _; loc} -> - (* don't think there's ever a case where this is reached *) - Jsx_common.raise_error ~loc - "JSX: encountered a weird case while processing the code. Please \ - report this!") - | _ -> - Jsx_common.raise_error ~loc:call_expression.pexp_loc - "JSX: `createElement` should be preceeded by a simple, direct module \ - name." - in - - let expr mapper expression = - match expression with - (* Does the function application have the @JSX attribute? *) - | { - pexp_desc = Pexp_apply (call_expression, call_arguments); - pexp_attributes; - } -> ( - let jsx_attribute, non_jsx_attributes = - List.partition - (fun (attribute, _) -> attribute.txt = "JSX") - pexp_attributes - in - match (jsx_attribute, non_jsx_attributes) with - (* no JSX attribute *) - | [], _ -> default_mapper.expr mapper expression - | _, non_jsx_attributes -> - transform_jsx_call mapper call_expression call_arguments - non_jsx_attributes) - (* is it a list with jsx attribute? Reason <>foo desugars to [@JSX][foo]*) - | { - pexp_desc = - ( Pexp_construct - ({txt = Lident "::"; loc}, Some {pexp_desc = Pexp_tuple _}) - | Pexp_construct ({txt = Lident "[]"; loc}, None) ); - pexp_attributes; - } as list_items -> ( - let jsx_attribute, non_jsx_attributes = - List.partition - (fun (attribute, _) -> attribute.txt = "JSX") - pexp_attributes - in - match (jsx_attribute, non_jsx_attributes) with - (* no JSX attribute *) - | [], _ -> default_mapper.expr mapper expression - | _, non_jsx_attributes -> - let loc = {loc with loc_ghost = true} in - let fragment = - Exp.ident ~loc {loc; txt = Ldot (Lident "ReasonReact", "fragment")} - in - let children_expr = - transform_children_if_list ~loc ~mapper list_items - in - let args = - [ - (* "div" *) - (nolabel, fragment); - (* [|moreCreateElementCallsHere|] *) - (nolabel, children_expr); - ] - in - Exp.apply - ~loc (* throw away the [@JSX] attribute and keep the others, if any *) - ~attrs:non_jsx_attributes - (* ReactDOMRe.createElement *) - (Exp.ident ~loc - {loc; txt = Ldot (Lident "ReactDOMRe", "createElement")}) - args) - (* Delegate to the default mapper, a deep identity traversal *) - | e -> default_mapper.expr mapper e - in - - let module_binding mapper module_binding = - let _ = nested_modules := module_binding.pmb_name.txt :: !nested_modules in - let mapped = default_mapper.module_binding mapper module_binding in - let () = - match !nested_modules with - | _ :: rest -> nested_modules := rest - | [] -> () - in - mapped - in - (expr, module_binding, transform_signature_item, transform_structure_item) diff --git a/jscomp/syntax/tests/ppx/react/expected/externalWithCustomName.res.txt b/jscomp/syntax/tests/ppx/react/expected/externalWithCustomName.res.txt index 92e89a9738..93680d0ead 100644 --- a/jscomp/syntax/tests/ppx/react/expected/externalWithCustomName.res.txt +++ b/jscomp/syntax/tests/ppx/react/expected/externalWithCustomName.res.txt @@ -1,15 +1,3 @@ -@@jsxConfig({version: 3}) - -module Foo = { - @obj - external componentProps: (~a: int, ~b: string, ~key: string=?, unit) => {"a": int, "b": string} = - "" - @module("Foo") - external component: React.componentLike<{"a": int, "b": string}, React.element> = "component" -} - -let t = React.createElement(Foo.component, Foo.componentProps(~a=1, ~b={"1"}, ())) - @@jsxConfig({version: 4, mode: "classic"}) module Foo = { diff --git a/jscomp/syntax/tests/ppx/react/expected/externalWithRef.res.txt b/jscomp/syntax/tests/ppx/react/expected/externalWithRef.res.txt index 41f643cecb..8ae1b0b9d3 100644 --- a/jscomp/syntax/tests/ppx/react/expected/externalWithRef.res.txt +++ b/jscomp/syntax/tests/ppx/react/expected/externalWithRef.res.txt @@ -1,20 +1,3 @@ -@@jsxConfig({version: 3}) - -module V3 = { - @obj - external makeProps: ( - ~x: string, - ~ref: ReactDOM.Ref.currentDomRef=?, - ~key: string=?, - unit, - ) => {"x": string, "ref": option} = "" - @module("componentForwardRef") - external make: React.componentLike< - {"x": string, "ref": option}, - React.element, - > = "component" -} - @@jsxConfig({version: 4, mode: "classic"}) module V4C = { diff --git a/jscomp/syntax/tests/ppx/react/expected/externalWithTypeVariables.res.txt b/jscomp/syntax/tests/ppx/react/expected/externalWithTypeVariables.res.txt index 454aba7f5a..be16a6c22d 100644 --- a/jscomp/syntax/tests/ppx/react/expected/externalWithTypeVariables.res.txt +++ b/jscomp/syntax/tests/ppx/react/expected/externalWithTypeVariables.res.txt @@ -1,18 +1,3 @@ -@@jsxConfig({version: 3}) - -module V3 = { - @obj - external makeProps: ( - ~x: t<'a>, - ~children: React.element, - ~key: string=?, - unit, - ) => {"x": t<'a>, "children": React.element} = "" - @module("c") - external make: React.componentLike<{"x": t<'a>, "children": React.element}, React.element> = - "component" -} - @@jsxConfig({version: 4, mode: "classic"}) module V4C = { diff --git a/jscomp/syntax/tests/ppx/react/expected/fileLevelConfig.res.txt b/jscomp/syntax/tests/ppx/react/expected/fileLevelConfig.res.txt index a6423491db..a69192fa65 100644 --- a/jscomp/syntax/tests/ppx/react/expected/fileLevelConfig.res.txt +++ b/jscomp/syntax/tests/ppx/react/expected/fileLevelConfig.res.txt @@ -1,20 +1,3 @@ -@@jsxConfig({version: 3}) - -module V3 = { - @obj external makeProps: (~msg: 'msg, ~key: string=?, unit) => {"msg": 'msg} = "" - - @react.component - let make = - @warning("-16") - (~msg) => { - ReactDOMRe.createDOMElementVariadic("div", [{msg->React.string}]) - } - let make = { - let \"FileLevelConfig$V3" = (\"Props": {"msg": 'msg}) => make(~msg=\"Props"["msg"]) - \"FileLevelConfig$V3" - } -} - @@jsxConfig({version: 4, mode: "classic"}) module V4C = { diff --git a/jscomp/syntax/tests/ppx/react/expected/firstClassModules.res.txt b/jscomp/syntax/tests/ppx/react/expected/firstClassModules.res.txt index 7e330ec780..934880c83a 100644 --- a/jscomp/syntax/tests/ppx/react/expected/firstClassModules.res.txt +++ b/jscomp/syntax/tests/ppx/react/expected/firstClassModules.res.txt @@ -1,55 +1,3 @@ -@@jsxConfig({version: 3}) - -module Select = { - module type T = { - type key - type t - } - @obj - external makeProps: ( - ~model: module(T with type t = '\"type-a" and type key = '\"type-key"), - ~selected: option<'\"type-key">, - ~onChange: option<'\"type-key"> => unit, - ~items: array<'\"type-a">, - ~key: string=?, - unit, - ) => { - "model": module(T with type t = '\"type-a" and type key = '\"type-key"), - "selected": option<'\"type-key">, - "onChange": option<'\"type-key"> => unit, - "items": array<'\"type-a">, - } = "" - - @react.component - let make = ( - type a key, - ~model as module(T: T with type t = a and type key = key), - ~selected: option, - ~onChange: option => unit, - ~items: array, - ) => { - let _ = (model, selected, onChange, items) - ReactDOMRe.createDOMElementVariadic("div", []) - } - let make = { - let \"FirstClassModules$Select" = ( - \"Props": { - "model": module(T with type t = '\"type-a" and type key = '\"type-key"), - "selected": option<'\"type-key">, - "onChange": option<'\"type-key"> => unit, - "items": array<'\"type-a">, - }, - ) => - make( - ~items=\"Props"["items"], - ~onChange=\"Props"["onChange"], - ~selected=\"Props"["selected"], - ~model=\"Props"["model"], - ) - \"FirstClassModules$Select" - } -} - @@jsxConfig({version: 4, mode: "classic"}) module Select = { diff --git a/jscomp/syntax/tests/ppx/react/expected/firstClassModules.resi.txt b/jscomp/syntax/tests/ppx/react/expected/firstClassModules.resi.txt index 3a0e98b433..556f6b9f0e 100644 --- a/jscomp/syntax/tests/ppx/react/expected/firstClassModules.resi.txt +++ b/jscomp/syntax/tests/ppx/react/expected/firstClassModules.resi.txt @@ -1,36 +1,3 @@ -@@jsxConfig({version: 3}) - -module Select: { - module type T = { - type key - type t - } - - @obj - external makeProps: ( - ~model: module(T with type t = 'a and type key = 'key), - ~selected: option<'key>, - ~onChange: option<'key> => unit, - ~items: array<'a>, - ~key: string=?, - unit, - ) => { - "model": module(T with type t = 'a and type key = 'key), - "selected": option<'key>, - "onChange": option<'key> => unit, - "items": array<'a>, - } = "" - let make: React.componentLike< - { - "model": module(T with type t = 'a and type key = 'key), - "selected": option<'key>, - "onChange": option<'key> => unit, - "items": array<'a>, - }, - React.element, - > -} - @@jsxConfig({version: 4, mode: "classic"}) module Select: { diff --git a/jscomp/syntax/tests/ppx/react/expected/forwardRef.res.txt b/jscomp/syntax/tests/ppx/react/expected/forwardRef.res.txt index 59ac6dbb17..4ea9cba48c 100644 --- a/jscomp/syntax/tests/ppx/react/expected/forwardRef.res.txt +++ b/jscomp/syntax/tests/ppx/react/expected/forwardRef.res.txt @@ -1,70 +1,3 @@ -@@jsxConfig({version: 3}) - -module V3 = { - module FancyInput = { - @obj - external makeProps: ( - ~className: 'className=?, - ~children: 'children, - ~key: string=?, - ~ref: 'ref=?, - unit, - ) => {"className": option<'className>, "children": 'children} = "" - - @react.component - let make = - @warning("-16") - (~className=?) => - @warning("-16") - (~children) => - @warning("-16") - ref => - ReactDOMRe.createDOMElementVariadic( - "div", - [ - ReactDOMRe.createDOMElementVariadic( - "input", - ~props=ReactDOMRe.domProps( - ~type_="text", - ~className?, - ~ref=?{Js.Nullable.toOption(ref)->Belt.Option.map(ReactDOM.Ref.domRef)}, - (), - ), - [], - ), - children, - ], - ) - let make = React.forwardRef({ - let \"ForwardRef$V3$FancyInput" = ( - \"Props": {"className": option<'className>, "children": 'children}, - ref, - ) => make(~children=\"Props"["children"], ~className=?\"Props"["className"], ref) - \"ForwardRef$V3$FancyInput" - }) - } - @obj external makeProps: (~key: string=?, unit) => {.} = "" - - @react.component - let make = () => { - let input = React.useRef(Js.Nullable.null) - - ReactDOMRe.createDOMElementVariadic( - "div", - [ - React.createElement( - FancyInput.make, - FancyInput.makeProps(~ref=input, ~children={React.string("Click to focus")}, ()), - ), - ], - ) - } - let make = { - let \"ForwardRef$V3" = (\"Props": {.}) => make() - \"ForwardRef$V3" - } -} - @@jsxConfig({version: 4, mode: "classic"}) module V4C = { diff --git a/jscomp/syntax/tests/ppx/react/expected/forwardRef.resi.txt b/jscomp/syntax/tests/ppx/react/expected/forwardRef.resi.txt index 0c8c8d69dc..e0a81497aa 100644 --- a/jscomp/syntax/tests/ppx/react/expected/forwardRef.resi.txt +++ b/jscomp/syntax/tests/ppx/react/expected/forwardRef.resi.txt @@ -1,43 +1,3 @@ -@@jsxConfig({version: 3}) - -module V3: { - module FancyInput: { - @obj - external makeProps: ( - ~className: string=?, - ~children: React.element, - ~ref: ReactDOM.Ref.currentDomRef=?, - ~key: string=?, - unit, - ) => { - "className": option, - "children": React.element, - "ref": option, - } = "" - let make: React.componentLike< - { - "className": option, - "children": React.element, - "ref": option, - }, - React.element, - > - } - - module ForwardRef: { - @obj - external makeProps: ( - ~ref: React.ref>=?, - ~key: string=?, - unit, - ) => {"ref": option>>} = "" - let make: React.componentLike< - {"ref": option>>}, - React.element, - > - } -} - @@jsxConfig({version: 4, mode: "classic"}) module V4C: { diff --git a/jscomp/syntax/tests/ppx/react/expected/mangleKeyword.res.txt b/jscomp/syntax/tests/ppx/react/expected/mangleKeyword.res.txt index 673d055399..9c42648632 100644 --- a/jscomp/syntax/tests/ppx/react/expected/mangleKeyword.res.txt +++ b/jscomp/syntax/tests/ppx/react/expected/mangleKeyword.res.txt @@ -1,39 +1,3 @@ -@@jsxConfig({version: 3}) - -module C3A0 = { - @obj - external makeProps: ( - ~_open: 'T_open, - ~_type: string, - ~key: string=?, - unit, - ) => {"_open": 'T_open, "_type": string} = "" - - @react.component - let make = - @warning("-16") - (@as("open") ~_open) => @warning("-16") (@as("type") ~_type: string) => React.string(_open) - let make = { - let \"MangleKeyword$C3A0" = (\"Props": {"_open": 'T_open, "_type": string}) => - make(~_type=\"Props"["_type"], ~_open=\"Props"["_open"]) - \"MangleKeyword$C3A0" - } -} -module C3A1 = { - @obj - external makeProps: ( - ~_open: string, - ~_type: string, - ~key: string=?, - unit, - ) => {"_open": string, "_type": string} = "" - external make: @as("open") - React.componentLike<{"_open": string, "_type": string}, React.element> = "default" -} - -let c3a0 = React.createElement(C3A0.make, C3A0.makeProps(~_open="x", ~_type="t", ())) -let c3a1 = React.createElement(C3A1.make, C3A1.makeProps(~_open="x", ~_type="t", ())) - @@jsxConfig({version: 4, mode: "classic"}) module C4C0 = { diff --git a/jscomp/syntax/tests/ppx/react/expected/newtype.res.txt b/jscomp/syntax/tests/ppx/react/expected/newtype.res.txt index 240548e08e..afc0ad4f8d 100644 --- a/jscomp/syntax/tests/ppx/react/expected/newtype.res.txt +++ b/jscomp/syntax/tests/ppx/react/expected/newtype.res.txt @@ -1,26 +1,3 @@ -@@jsxConfig({version: 3}) - -module V3 = { - @obj - external makeProps: ( - ~a: '\"type-a", - ~b: array>, - ~c: 'a, - ~key: string=?, - unit, - ) => {"a": '\"type-a", "b": array>, "c": 'a} = "" - - @react.component - let make = (type a, ~a: a, ~b: array>, ~c: 'a, _) => - ReactDOMRe.createDOMElementVariadic("div", []) - let make = { - let \"Newtype$V3" = ( - \"Props": {"a": '\"type-a", "b": array>, "c": 'a}, - ) => make(~c=\"Props"["c"], ~b=\"Props"["b"], ~a=\"Props"["a"]) - \"Newtype$V3" - } -} - @@jsxConfig({version: 4, mode: "classic"}) module V4C = { diff --git a/jscomp/syntax/tests/ppx/react/expected/optionalKeyType.res.txt b/jscomp/syntax/tests/ppx/react/expected/optionalKeyType.res.txt index 6e15939ed2..dca95b859d 100644 --- a/jscomp/syntax/tests/ppx/react/expected/optionalKeyType.res.txt +++ b/jscomp/syntax/tests/ppx/react/expected/optionalKeyType.res.txt @@ -1,33 +1,5 @@ let key = None -@@jsxConfig({version: 3}) - -let _ = React.createElement(C.make, C.makeProps(~key="k", ())) -let _ = React.createElement(C.make, C.makeProps(~key=?Some("k"), ())) -let _ = React.createElement(C.make, C.makeProps(~key?, ())) -let _ = ReactDOMRe.createDOMElementVariadic("div", ~props=ReactDOMRe.domProps(~key="k", ()), []) -let _ = ReactDOMRe.createDOMElementVariadic( - "div", - ~props=ReactDOMRe.domProps(~key=?Some("k"), ()), - [], -) -let _ = ReactDOMRe.createDOMElementVariadic("div", ~props=ReactDOMRe.domProps(~key?, ()), []) -let _ = ReactDOMRe.createDOMElementVariadic( - "div", - ~props=ReactDOMRe.domProps(~key="k", ()), - [ReactDOMRe.createDOMElementVariadic("br", []), ReactDOMRe.createDOMElementVariadic("br", [])], -) -let _ = ReactDOMRe.createDOMElementVariadic( - "div", - ~props=ReactDOMRe.domProps(~key=?Some("k"), ()), - [ReactDOMRe.createDOMElementVariadic("br", []), ReactDOMRe.createDOMElementVariadic("br", [])], -) -let _ = ReactDOMRe.createDOMElementVariadic( - "div", - ~props=ReactDOMRe.domProps(~key?, ()), - [ReactDOMRe.createDOMElementVariadic("br", []), ReactDOMRe.createDOMElementVariadic("br", [])], -) - @@jsxConfig({version: 4, mode: "classic"}) let _ = JsxPPXReactSupport.createElementWithKey(~key="k", C.make, {}) diff --git a/jscomp/syntax/tests/ppx/react/expected/topLevel.res.txt b/jscomp/syntax/tests/ppx/react/expected/topLevel.res.txt index 7bcd208661..8e50d91632 100644 --- a/jscomp/syntax/tests/ppx/react/expected/topLevel.res.txt +++ b/jscomp/syntax/tests/ppx/react/expected/topLevel.res.txt @@ -1,24 +1,3 @@ -@@jsxConfig({version: 3}) - -module V3 = { - @obj external makeProps: (~a: 'a, ~b: 'b, ~key: string=?, unit) => {"a": 'a, "b": 'b} = "" - - @react.component - let make = - @warning("-16") - (~a) => - @warning("-16") - (~b, _) => { - Js.log("This function should be named 'TopLevel.react'") - ReactDOMRe.createDOMElementVariadic("div", []) - } - let make = { - let \"TopLevel$V3" = (\"Props": {"a": 'a, "b": 'b}) => - make(~b=\"Props"["b"], ~a=\"Props"["a"], ()) - \"TopLevel$V3" - } -} - @@jsxConfig({version: 4, mode: "classic"}) module V4C = { diff --git a/jscomp/syntax/tests/ppx/react/expected/typeConstraint.res.txt b/jscomp/syntax/tests/ppx/react/expected/typeConstraint.res.txt index d2e8f62c0c..4e32edbfe0 100644 --- a/jscomp/syntax/tests/ppx/react/expected/typeConstraint.res.txt +++ b/jscomp/syntax/tests/ppx/react/expected/typeConstraint.res.txt @@ -1,18 +1,3 @@ -@@jsxConfig({version: 3}) - -module V3 = { - @obj external makeProps: (~key: string=?, unit) => {.} = "" - - @react.component - let make: - type a. (~a: a, ~b: a, a) => React.element = - (~a, ~b, _) => ReactDOMRe.createDOMElementVariadic("div", []) - let make = { - let \"TypeConstraint$V3" = (\"Props": {.}) => make() - \"TypeConstraint$V3" - } -} - @@jsxConfig({version: 4, mode: "classic"}) module V4C = { diff --git a/jscomp/syntax/tests/ppx/react/externalWithCustomName.res b/jscomp/syntax/tests/ppx/react/externalWithCustomName.res index fc3602fb93..adcbe8f70d 100644 --- a/jscomp/syntax/tests/ppx/react/externalWithCustomName.res +++ b/jscomp/syntax/tests/ppx/react/externalWithCustomName.res @@ -1,12 +1,3 @@ -@@jsxConfig({version: 3}) - -module Foo = { - @react.component @module("Foo") - external component: (~a: int, ~b: string, _) => React.element = "component" -} - -let t = - @@jsxConfig({version: 4, mode: "classic"}) module Foo = { diff --git a/jscomp/syntax/tests/ppx/react/externalWithRef.res b/jscomp/syntax/tests/ppx/react/externalWithRef.res index 9fa0c3b012..258f7f8043 100644 --- a/jscomp/syntax/tests/ppx/react/externalWithRef.res +++ b/jscomp/syntax/tests/ppx/react/externalWithRef.res @@ -1,13 +1,3 @@ -@@jsxConfig({version: 3}) - -module V3 = { - @module("componentForwardRef") @react.component - external make: ( - ~x: string, - ~ref: ReactDOM.Ref.currentDomRef=?, - ) => React.element = "component" -} - @@jsxConfig({version: 4, mode: "classic"}) module V4C = { diff --git a/jscomp/syntax/tests/ppx/react/externalWithTypeVariables.res b/jscomp/syntax/tests/ppx/react/externalWithTypeVariables.res index 9672252f02..402590cf59 100644 --- a/jscomp/syntax/tests/ppx/react/externalWithTypeVariables.res +++ b/jscomp/syntax/tests/ppx/react/externalWithTypeVariables.res @@ -1,13 +1,3 @@ -@@jsxConfig({version: 3}) - -module V3 = { - @module("c") @react.component - external make: ( - ~x: t<'a>, - ~children: React.element, - ) => React.element = "component" -} - @@jsxConfig({version: 4, mode: "classic"}) module V4C = { diff --git a/jscomp/syntax/tests/ppx/react/fileLevelConfig.res b/jscomp/syntax/tests/ppx/react/fileLevelConfig.res index b4e2459caa..b629e50e2c 100644 --- a/jscomp/syntax/tests/ppx/react/fileLevelConfig.res +++ b/jscomp/syntax/tests/ppx/react/fileLevelConfig.res @@ -1,12 +1,3 @@ -@@jsxConfig({version: 3}) - -module V3 = { - @react.component - let make = (~msg) => { -
{msg->React.string}
- } -} - @@jsxConfig({version: 4, mode: "classic"}) module V4C = { diff --git a/jscomp/syntax/tests/ppx/react/firstClassModules.res b/jscomp/syntax/tests/ppx/react/firstClassModules.res index 9567f435c9..e1c98d8ca1 100644 --- a/jscomp/syntax/tests/ppx/react/firstClassModules.res +++ b/jscomp/syntax/tests/ppx/react/firstClassModules.res @@ -1,24 +1,3 @@ -@@jsxConfig({version: 3}) - -module Select = { - module type T = { - type key - type t - } - - @react.component - let make = ( - type a key, - ~model as module(T: T with type t = a and type key = key), - ~selected: option, - ~onChange: option => unit, - ~items: array
, - ) => { - let _ = (model, selected, onChange, items) -
- } -} - @@jsxConfig({version: 4, mode: "classic"}) module Select = { diff --git a/jscomp/syntax/tests/ppx/react/firstClassModules.resi b/jscomp/syntax/tests/ppx/react/firstClassModules.resi index 9f601b3a0f..7305b3ea98 100644 --- a/jscomp/syntax/tests/ppx/react/firstClassModules.resi +++ b/jscomp/syntax/tests/ppx/react/firstClassModules.resi @@ -1,20 +1,3 @@ -@@jsxConfig({version: 3}) - -module Select: { - module type T = { - type key - type t - } - - @react.component - let make: ( - ~model: module(T with type t = 'a and type key = 'key), - ~selected: option<'key>, - ~onChange: option<'key> => unit, - ~items: array<'a>, - ) => React.element -} - @@jsxConfig({version: 4, mode: "classic"}) module Select: { diff --git a/jscomp/syntax/tests/ppx/react/forwardRef.res b/jscomp/syntax/tests/ppx/react/forwardRef.res index b814e14476..12abf4e537 100644 --- a/jscomp/syntax/tests/ppx/react/forwardRef.res +++ b/jscomp/syntax/tests/ppx/react/forwardRef.res @@ -1,30 +1,3 @@ -@@jsxConfig({version: 3}) - -module V3 = { - module FancyInput = { - @react.component - let make = React.forwardRef((~className=?, ~children, ref) => -
- Belt.Option.map(ReactDOM.Ref.domRef)} - /> - children -
- ) - } - - @react.component - let make = () => { - let input = React.useRef(Js.Nullable.null) - -
- {React.string("Click to focus")} -
- } -} - @@jsxConfig({version: 4, mode: "classic"}) module V4C = { diff --git a/jscomp/syntax/tests/ppx/react/forwardRef.resi b/jscomp/syntax/tests/ppx/react/forwardRef.resi index 5dba51695e..e2d44987f8 100644 --- a/jscomp/syntax/tests/ppx/react/forwardRef.resi +++ b/jscomp/syntax/tests/ppx/react/forwardRef.resi @@ -1,21 +1,3 @@ -@@jsxConfig({version: 3}) - -module V3: { - module FancyInput: { - @react.component - let make: ( - ~className: string=?, - ~children: React.element, - ~ref: ReactDOM.Ref.currentDomRef=?, - ) => React.element - } - - module ForwardRef: { - @react.component - let make: (~ref: React.ref>=?) => React.element - } -} - @@jsxConfig({version: 4, mode: "classic"}) module V4C: { diff --git a/jscomp/syntax/tests/ppx/react/innerModule.res b/jscomp/syntax/tests/ppx/react/innerModule.res deleted file mode 100644 index 742f8a65b4..0000000000 --- a/jscomp/syntax/tests/ppx/react/innerModule.res +++ /dev/null @@ -1,13 +0,0 @@ -@@jsxConfig({version: 3}) -module Bar = { - @react.component - let make = (~a, ~b, _) => { - Js.log("This function should be named `InnerModule.react$Bar`") -
- } - @react.component - let component = (~a, ~b, _) => { - Js.log("This function should be named `InnerModule.react$Bar$component`") -
- } -} diff --git a/jscomp/syntax/tests/ppx/react/mangleKeyword.res b/jscomp/syntax/tests/ppx/react/mangleKeyword.res index 94dad3c2c0..f1a5304cc9 100644 --- a/jscomp/syntax/tests/ppx/react/mangleKeyword.res +++ b/jscomp/syntax/tests/ppx/react/mangleKeyword.res @@ -1,19 +1,3 @@ -@@jsxConfig({version: 3}) - -module C3A0 = { - @react.component - let make = - (@as("open") ~_open, @as("type") ~_type: string) => React.string(_open) -} -module C3A1 = { - @react.component - external make: (@as("open") ~_open: string, @as("type") ~_type: string) => React.element = - "default" -} - -let c3a0 = -let c3a1 = - @@jsxConfig({version: 4, mode: "classic"}) module C4C0 = { diff --git a/jscomp/syntax/tests/ppx/react/newtype.res b/jscomp/syntax/tests/ppx/react/newtype.res index e1d859a8d4..688341e9d5 100644 --- a/jscomp/syntax/tests/ppx/react/newtype.res +++ b/jscomp/syntax/tests/ppx/react/newtype.res @@ -1,10 +1,3 @@ -@@jsxConfig({version: 3}) - -module V3 = { - @react.component - let make = (type a, ~a: a, ~b: array>, ~c: 'a, _) =>
-} - @@jsxConfig({version: 4, mode: "classic"}) module V4C = { diff --git a/jscomp/syntax/tests/ppx/react/optionalKeyType.res b/jscomp/syntax/tests/ppx/react/optionalKeyType.res index bec2add5d6..f887eacd6d 100644 --- a/jscomp/syntax/tests/ppx/react/optionalKeyType.res +++ b/jscomp/syntax/tests/ppx/react/optionalKeyType.res @@ -1,17 +1,5 @@ let key = None -@@jsxConfig({version:3}) - -let _ = -let _ = -let _ = -let _ =
-let _ =
-let _ =
-let _ =


-let _ =


-let _ =


- @@jsxConfig({version:4, mode: "classic"}) let _ = diff --git a/jscomp/syntax/tests/ppx/react/topLevel.res b/jscomp/syntax/tests/ppx/react/topLevel.res index 6d7a7eb9b4..54283638e2 100644 --- a/jscomp/syntax/tests/ppx/react/topLevel.res +++ b/jscomp/syntax/tests/ppx/react/topLevel.res @@ -1,13 +1,3 @@ -@@jsxConfig({version: 3}) - -module V3 = { - @react.component - let make = (~a, ~b, _) => { - Js.log("This function should be named 'TopLevel.react'") -
- } -} - @@jsxConfig({version: 4, mode: "classic"}) module V4C = { diff --git a/jscomp/syntax/tests/ppx/react/typeConstraint.res b/jscomp/syntax/tests/ppx/react/typeConstraint.res index 9e1fdc14d7..614094e82e 100644 --- a/jscomp/syntax/tests/ppx/react/typeConstraint.res +++ b/jscomp/syntax/tests/ppx/react/typeConstraint.res @@ -1,12 +1,3 @@ -@@jsxConfig({version: 3}) - -module V3 = { - @react.component - let make: - type a. (~a: a, ~b: a, a) => React.element = - (~a, ~b, _) =>
-} - @@jsxConfig({version: 4, mode: "classic"}) module V4C = { diff --git a/tests/build_tests/react_ppx/rescript.json b/tests/build_tests/react_ppx/rescript.json index 1b1e7ab67b..62d4a8e2fb 100644 --- a/tests/build_tests/react_ppx/rescript.json +++ b/tests/build_tests/react_ppx/rescript.json @@ -1,7 +1,7 @@ { "name": "react-ppx-tests", - "reason": { - "react-jsx": 3 + "jsx": { + "version": 4 }, "sources": { "dir": "src", diff --git a/tests/build_tests/react_ppx/src/React.res b/tests/build_tests/react_ppx/src/React.res index 4854360423..82309ae10c 100644 --- a/tests/build_tests/react_ppx/src/React.res +++ b/tests/build_tests/react_ppx/src/React.res @@ -20,6 +20,18 @@ external cloneElement: (component<'props>, 'props) => element = "cloneElement" external createElementVariadic: (component<'props>, 'props, array) => element = "createElement" +@module("react/jsx-runtime") +external jsx: (component<'props>, 'props) => element = "jsx" + +@module("react/jsx-runtime") +external jsxKeyed: (component<'props>, 'props, ~key: string=?, @ignore unit) => element = "jsx" + +@module("react/jsx-runtime") +external jsxs: (component<'props>, 'props) => element = "jsxs" + +@module("react/jsx-runtime") +external jsxsKeyed: (component<'props>, 'props, ~key: string=?, @ignore unit) => element = "jsxs" + module Ref = { type t<'value> @@ -44,10 +56,15 @@ module Children = { } module Context = { - type t<'props> + type t<'context> + + type props<'context> = { + value: 'context, + children: element, + } @get - external provider: t<'props> => component<{"value": 'props, "children": element}> = "Provider" + external provider: t<'context> => component> = "Provider" } @module("react") @@ -67,29 +84,17 @@ external memoCustomCompareProps: ( ) => component<'props> = "memo" module Fragment = { - @obj - external makeProps: (~children: element, ~key: 'key=?, unit) => {"children": element} = "" + type props = {key?: string, children: element} + @module("react") - external make: component<{ - "children": element, - }> = "Fragment" + external make: component = "Fragment" } module Suspense = { - @obj - external makeProps: ( - ~children: element=?, - ~fallback: element=?, - ~maxDuration: int=?, - ~key: 'key=?, - unit, - ) => {"children": option, "fallback": option, "maxDuration": option} = "" + type props = {key?: string, children?: element, fallback?: element} + @module("react") - external make: component<{ - "children": option, - "fallback": option, - "maxDuration": option, - }> = "Suspense" + external make: component = "Suspense" } /* HOOKS */ diff --git a/tests/build_tests/react_ppx/src/gpr_3695_test.res b/tests/build_tests/react_ppx/src/gpr_3695_test.res index 8549013b7d..e190a47690 100644 --- a/tests/build_tests/react_ppx/src/gpr_3695_test.res +++ b/tests/build_tests/react_ppx/src/gpr_3695_test.res @@ -8,4 +8,4 @@ module Test = { external make: (~className: string=?) => React.element = "Foo" } -let test = (~className) => Test.make(Test.makeProps(~className, ())) +let test = (~className) => Test.make({className}) diff --git a/tests/build_tests/react_ppx/src/gpr_3987_test.bs.js b/tests/build_tests/react_ppx/src/gpr_3987_test.bs.js index 29777b2f91..a8451b2174 100644 --- a/tests/build_tests/react_ppx/src/gpr_3987_test.bs.js +++ b/tests/build_tests/react_ppx/src/gpr_3987_test.bs.js @@ -1,7 +1,7 @@ // Generated by ReScript, PLEASE EDIT WITH CARE 'use strict'; -let React = require("react"); +let JsxRuntime = require("react/jsx-runtime"); function makeContainer(text) { let container = document.createElement("div"); @@ -17,25 +17,20 @@ function makeContainer(text) { return content; } -function makeProps(value, onChange, param) { - return { - value: value, - onChange: onChange - }; -} - function make(_props) { return null; } let Gpr3987ReproOk = { - makeProps: makeProps, make: make }; -React.createElement(make, makeProps("test", (param, param$1) => {}, undefined)); +JsxRuntime.jsx(make, { + value: "test", + onChange: (param, param$1) => {} +}); -function Gpr_3987_test$Gpr3987ReproOk2(Props) { +function Gpr_3987_test$Gpr3987ReproOk2(props) { return null; } @@ -43,12 +38,12 @@ let Gpr3987ReproOk2 = { make: Gpr_3987_test$Gpr3987ReproOk2 }; -React.createElement(Gpr_3987_test$Gpr3987ReproOk2, { +JsxRuntime.jsx(Gpr_3987_test$Gpr3987ReproOk2, { value: "test", onChange: (param, param$1) => {} }); -function Gpr_3987_test$Gpr3987ReproError(Props) { +function Gpr_3987_test$Gpr3987ReproError(props) { return null; } @@ -56,7 +51,7 @@ let Gpr3987ReproError = { make: Gpr_3987_test$Gpr3987ReproError }; -React.createElement(Gpr_3987_test$Gpr3987ReproError, { +JsxRuntime.jsx(Gpr_3987_test$Gpr3987ReproError, { value: "test", onChange: (param, param$1) => {} }); diff --git a/tests/build_tests/react_ppx/src/gpr_3987_test.res b/tests/build_tests/react_ppx/src/gpr_3987_test.res index de195e3596..9adb8c3186 100644 --- a/tests/build_tests/react_ppx/src/gpr_3987_test.res +++ b/tests/build_tests/react_ppx/src/gpr_3987_test.res @@ -24,10 +24,9 @@ let makeContainer = text => { /* This uncurried prop definition compiles */ module Gpr3987ReproOk = { - let makeProps = (~value: string, ~onChange: (. string, int) => unit, ()) => - {"value": value, "onChange": onChange} + type props = {value: string, onChange: (. string, int) => unit} - let make = (_props: {"value": string, "onChange": (. string, int) => unit}) => React.null + let make = (_props: props) => React.null } let _ = ()} /> diff --git a/tests/build_tests/react_ppx/src/recursive_component_test.bs.js b/tests/build_tests/react_ppx/src/recursive_component_test.bs.js index ed067ae1a8..c24783b0fa 100644 --- a/tests/build_tests/react_ppx/src/recursive_component_test.bs.js +++ b/tests/build_tests/react_ppx/src/recursive_component_test.bs.js @@ -1,32 +1,23 @@ // Generated by ReScript, PLEASE EDIT WITH CARE 'use strict'; -let React = require("react"); - -function make(Props) { - let foo = Props.foo; - return React.createElement(make, { - foo: foo - }); -} function mm(x) { - return make$1({ + return make({ b: !x.b }); } -function make$1(props) { +function make(props) { return mm({ b: props.b }); } let Rec = { - make: make$1, + make: make, mm: mm }; -exports.make = make; exports.Rec = Rec; -/* react Not a pure module */ +/* No side effect */ diff --git a/tests/build_tests/react_ppx/src/recursive_component_test.res b/tests/build_tests/react_ppx/src/recursive_component_test.res index 70682b0c69..90eeffe167 100644 --- a/tests/build_tests/react_ppx/src/recursive_component_test.res +++ b/tests/build_tests/react_ppx/src/recursive_component_test.res @@ -5,11 +5,6 @@ flags : [|"-dsource"|] }]; */ -@react.component -let rec make = (~foo, ()) => React.createElement(make, makeProps(~foo, ())) - -@@jsxConfig({version:4}) - module Rec = { @react.component let rec make = (~b) => { diff --git a/tests/gentype_tests/typescript-react-example/package-lock.json b/tests/gentype_tests/typescript-react-example/package-lock.json index be9ccf6fe0..a1bad95d54 100644 --- a/tests/gentype_tests/typescript-react-example/package-lock.json +++ b/tests/gentype_tests/typescript-react-example/package-lock.json @@ -8,7 +8,7 @@ "name": "typescript-react-example", "version": "0.1.0", "dependencies": { - "@rescript/react": "^0.12.2", + "@rescript/react": "^0.13.0", "react": "^18.2.0", "react-dom": "^18.2.0" }, @@ -206,9 +206,9 @@ } }, "node_modules/@rescript/react": { - "version": "0.12.2", - "resolved": "https://registry.npmjs.org/@rescript/react/-/react-0.12.2.tgz", - "integrity": "sha512-EOF19dLTG4Y9K59JqMjG5yfvIsrMZqfxGC2J/oe9gGgrMiUrzZh3KH9khTcR1Z3Ih0lRViSh0/iYnJz20gGoag==", + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@rescript/react/-/react-0.13.0.tgz", + "integrity": "sha512-YSIWIyMlyF9ZaP6Q3hScl1h3wRbdIP4+Cb7PlDt7Y1PG8M8VWYhLoIgLb78mbBHcwFbZu0d5zAt1LSX5ilOiWQ==", "peerDependencies": { "react": ">=18.0.0", "react-dom": ">=18.0.0" diff --git a/tests/gentype_tests/typescript-react-example/package.json b/tests/gentype_tests/typescript-react-example/package.json index 2e24046cf4..379c73f4ec 100644 --- a/tests/gentype_tests/typescript-react-example/package.json +++ b/tests/gentype_tests/typescript-react-example/package.json @@ -10,7 +10,7 @@ "lint": "biome check src" }, "dependencies": { - "@rescript/react": "^0.12.2", + "@rescript/react": "^0.13.0", "react": "^18.2.0", "react-dom": "^18.2.0" }, @@ -21,4 +21,4 @@ "rescript": "file:../../..", "typescript": "^5.2.2" } -} +} \ No newline at end of file diff --git a/tests/gentype_tests/typescript-react-example/rescript.json b/tests/gentype_tests/typescript-react-example/rescript.json index bcee761acf..5df00aebde 100644 --- a/tests/gentype_tests/typescript-react-example/rescript.json +++ b/tests/gentype_tests/typescript-react-example/rescript.json @@ -5,6 +5,8 @@ "importPath": "relative", "shims": { "Js": "Js", + "Jsx": "Jsx", + "JsxEvent": "JsxEvent", "Belt": "Belt", "ReactEvent": "ReactEvent", "RescriptPervasives": "RescriptPervasives", @@ -17,7 +19,7 @@ }, "name": "sample-typescript-app", "bsc-flags": [], - "jsx": { "version": 3 }, + "jsx": { "version": 4 }, "bs-dependencies": ["@rescript/react"], "sources": [ { diff --git a/tests/gentype_tests/typescript-react-example/src/DynamicallyLoadedComponent.res.js b/tests/gentype_tests/typescript-react-example/src/DynamicallyLoadedComponent.res.js index 2c1b3e2173..80bc599ff9 100644 --- a/tests/gentype_tests/typescript-react-example/src/DynamicallyLoadedComponent.res.js +++ b/tests/gentype_tests/typescript-react-example/src/DynamicallyLoadedComponent.res.js @@ -1,8 +1,8 @@ // Generated by ReScript, PLEASE EDIT WITH CARE -function DynamicallyLoadedComponent(Props) { - return Props.s; +function DynamicallyLoadedComponent(props) { + return props.s; } let make = DynamicallyLoadedComponent; diff --git a/tests/gentype_tests/typescript-react-example/src/ExportWithRename.gen.tsx b/tests/gentype_tests/typescript-react-example/src/ExportWithRename.gen.tsx index 78737da02d..6e8cb207cc 100644 --- a/tests/gentype_tests/typescript-react-example/src/ExportWithRename.gen.tsx +++ b/tests/gentype_tests/typescript-react-example/src/ExportWithRename.gen.tsx @@ -3,10 +3,8 @@ /* eslint-disable */ /* tslint:disable */ -import * as React from 'react'; - import * as ExportWithRenameJS from './ExportWithRename.res.js'; -export type Props = { readonly s: string }; +export type props = { readonly s: s }; export const Renamed: React.ComponentType<{ readonly s: string }> = ExportWithRenameJS.make as any; diff --git a/tests/gentype_tests/typescript-react-example/src/ExportWithRename.res.js b/tests/gentype_tests/typescript-react-example/src/ExportWithRename.res.js index 27c42e8666..3d13c84a2f 100644 --- a/tests/gentype_tests/typescript-react-example/src/ExportWithRename.res.js +++ b/tests/gentype_tests/typescript-react-example/src/ExportWithRename.res.js @@ -1,8 +1,8 @@ // Generated by ReScript, PLEASE EDIT WITH CARE -function ExportWithRename(Props) { - return Props.s; +function ExportWithRename(props) { + return props.s; } let make = ExportWithRename; diff --git a/tests/gentype_tests/typescript-react-example/src/Hooks.gen.tsx b/tests/gentype_tests/typescript-react-example/src/Hooks.gen.tsx index fbcc6f2105..f0d4e76bd2 100644 --- a/tests/gentype_tests/typescript-react-example/src/Hooks.gen.tsx +++ b/tests/gentype_tests/typescript-react-example/src/Hooks.gen.tsx @@ -3,16 +3,38 @@ /* eslint-disable */ /* tslint:disable */ -import * as React from 'react'; - import * as HooksJS from './Hooks.res.js'; import type {TypedArray2_Uint8Array_t as Js_TypedArray2_Uint8Array_t} from '../src/shims/Js.shim'; +import type {element as Jsx_element} from '../src/shims/Jsx.shim'; + export type vehicle = { readonly name: string }; +export type props = { readonly vehicle: vehicle }; + +export type Another_props = { readonly vehicle: vehicle; readonly callback: callback }; + +export type Inner_props = { readonly vehicle: vehicle }; + +export type Inner_Another_props = { readonly vehicle: vehicle }; + +export type Inner_Inner2_props = { readonly vehicle: vehicle }; + +export type Inner_Inner2_Another_props = { readonly vehicle: vehicle }; + +export type NoProps_props = {}; + export type cb = (_to:vehicle) => void; +export type WithRename_props = { + readonly _to: T_to; + readonly _Type: T_Type; + readonly cb: cb +}; + +export type WithRef_props = { readonly vehicle: vehicle }; + export type r = { readonly x: string }; export type callback = (_1:input) => output; @@ -25,106 +47,76 @@ export type testDomRef = React.Ref; export type testDomRef2 = React.Ref; -export type Props = { readonly vehicle: vehicle }; - -export const $$default: React.ComponentType<{ readonly vehicle: vehicle }> = HooksJS.default as any; - -export default $$default; +export type Poly_props

= { readonly p: p }; -export type Another_anotherComponent_Props = { readonly callback: () => void; readonly vehicle: vehicle }; +export type Fun_props = { readonly name: name }; -export const Another_anotherComponent: React.ComponentType<{ readonly callback: () => void; readonly vehicle: vehicle }> = HooksJS.Another.anotherComponent as any; +export type RenderPropRequiresConversion_props = { readonly renderVehicle: renderVehicle }; -export type Inner_make_Props = { readonly vehicle: vehicle }; +export type WithChildren_props = { readonly vehicle: vehicle; readonly children: children }; -export const Inner_make: React.ComponentType<{ readonly vehicle: vehicle }> = HooksJS.Inner.make as any; +export type DD_props = { readonly array: array; readonly name: name }; -export type Inner_Another_anotherComponent_Props = { readonly vehicle: vehicle }; +export const $$default: (_1:props) => Jsx_element = HooksJS.default as any; -export const Inner_Another_anotherComponent: React.ComponentType<{ readonly vehicle: vehicle }> = HooksJS.Inner.Another.anotherComponent as any; +export default $$default; -export type Inner_Inner2_make_Props = { readonly vehicle: vehicle }; +export const Another_anotherComponent: (_1:Another_props void)>) => Jsx_element = HooksJS.Another.anotherComponent as any; -export const Inner_Inner2_make: React.ComponentType<{ readonly vehicle: vehicle }> = HooksJS.Inner.Inner2.make as any; +export const Inner_make: (_1:Inner_props) => Jsx_element = HooksJS.Inner.make as any; -export type Inner_Inner2_Another_anotherComponent_Props = { readonly vehicle: vehicle }; +export const Inner_Another_anotherComponent: (_1:Inner_Another_props) => Jsx_element = HooksJS.Inner.Another.anotherComponent as any; -export const Inner_Inner2_Another_anotherComponent: React.ComponentType<{ readonly vehicle: vehicle }> = HooksJS.Inner.Inner2.Another.anotherComponent as any; +export const Inner_Inner2_make: (_1:Inner_Inner2_props) => Jsx_element = HooksJS.Inner.Inner2.make as any; -export type NoProps_make_Props = {}; +export const Inner_Inner2_Another_anotherComponent: (_1:Inner_Inner2_Another_props) => Jsx_element = HooksJS.Inner.Inner2.Another.anotherComponent as any; -export const NoProps_make: React.ComponentType<{}> = HooksJS.NoProps.make as any; +export const NoProps_make: (_1:NoProps_props) => Jsx_element = HooksJS.NoProps.make as any; export const functionWithRenamedArgs: (_to:vehicle, _Type:vehicle, cb:cb) => string = HooksJS.functionWithRenamedArgs as any; -export type WithRename_componentWithRenamedArgs_Props = { - readonly _Type: vehicle; - readonly _to: vehicle; - readonly cb: cb -}; - export const WithRename_componentWithRenamedArgs: React.ComponentType<{ - readonly _Type: vehicle; readonly _to: vehicle; + readonly _Type: vehicle; readonly cb: cb }> = HooksJS.WithRename.componentWithRenamedArgs as any; -export const WithRef_makeWithRef: (_1:{ readonly vehicle: vehicle }) => (_1:(null | undefined | any)) => JSX.Element = HooksJS.WithRef.makeWithRef as any; - -export type testForwardRef_Props = { readonly vehicle: vehicle }; +export const WithRef_makeWithRef: (_1:WithRef_props) => (_1:(null | undefined | any)) => JSX.Element = HooksJS.WithRef.makeWithRef as any; export const testForwardRef: React.ComponentType<{ readonly vehicle: vehicle }> = HooksJS.testForwardRef as any; export const ForwardRef_input: (_1:r) => JSX.Element = HooksJS.ForwardRef.input as any; -export type Poly_polymorphicComponent_Props = { readonly p: [vehicle, T1] }; - export const Poly_polymorphicComponent: React.ComponentType<{ readonly p: [vehicle, any] }> = HooksJS.Poly.polymorphicComponent as any; -export type Fun_functionReturningReactElement_Props = { readonly name: string }; - export const Fun_functionReturningReactElement: React.ComponentType<{ readonly name: string }> = HooksJS.Fun.functionReturningReactElement as any; -export type RenderPropRequiresConversion_make_Props = { readonly renderVehicle: React.ComponentType<{ readonly number: number; readonly vehicle: vehicle }> }; - export const RenderPropRequiresConversion_make: React.ComponentType<{ readonly renderVehicle: React.ComponentType<{ readonly number: number; readonly vehicle: vehicle }> }> = HooksJS.RenderPropRequiresConversion.make as any; -export type WithChildren_aComponentWithChildren_Props = { readonly children: React.ReactNode; readonly vehicle: vehicle }; - -export const WithChildren_aComponentWithChildren: React.ComponentType<{ readonly children: React.ReactNode; readonly vehicle: vehicle }> = HooksJS.WithChildren.aComponentWithChildren as any; - -export type DD_make_Props = { readonly array: Js_TypedArray2_Uint8Array_t; readonly name: string }; +export const WithChildren_aComponentWithChildren: (_1:WithChildren_props) => Jsx_element = HooksJS.WithChildren.aComponentWithChildren as any; export const DD_make: React.ComponentType<{ readonly array: Js_TypedArray2_Uint8Array_t; readonly name: string }> = HooksJS.DD.make as any; -export const NoProps: { make: React.ComponentType<{}> } = HooksJS.NoProps as any; +export const NoProps: { make: (_1:NoProps_props) => Jsx_element } = HooksJS.NoProps as any; export const Inner: { Inner2: { Another: { - anotherComponent: React.ComponentType<{ - readonly vehicle: vehicle - }> + anotherComponent: (_1:Inner_Inner2_Another_props) => Jsx_element }; - make: React.ComponentType<{ - readonly vehicle: vehicle - }> + make: (_1:Inner_Inner2_props) => Jsx_element }; Another: { - anotherComponent: React.ComponentType<{ - readonly vehicle: vehicle - }> + anotherComponent: (_1:Inner_Another_props) => Jsx_element }; - make: React.ComponentType<{ - readonly vehicle: vehicle - }> + make: (_1:Inner_props) => Jsx_element } = HooksJS.Inner as any; export const RenderPropRequiresConversion: { make: React.ComponentType<{ readonly renderVehicle: React.ComponentType<{ readonly number: number; readonly vehicle: vehicle }> }> } = HooksJS.RenderPropRequiresConversion as any; export const WithRename: { componentWithRenamedArgs: React.ComponentType<{ - readonly _Type: vehicle; readonly _to: vehicle; + readonly _Type: vehicle; readonly cb: cb }> } = HooksJS.WithRename as any; @@ -132,12 +124,12 @@ export const ForwardRef: { input: (_1:r) => JSX.Element } = HooksJS.ForwardRef a export const Fun: { functionReturningReactElement: React.ComponentType<{ readonly name: string }> } = HooksJS.Fun as any; -export const WithRef: { makeWithRef: (_1:{ readonly vehicle: vehicle }) => (_1:(null | undefined | any)) => JSX.Element } = HooksJS.WithRef as any; +export const WithRef: { makeWithRef: (_1:WithRef_props) => (_1:(null | undefined | any)) => JSX.Element } = HooksJS.WithRef as any; -export const WithChildren: { aComponentWithChildren: React.ComponentType<{ readonly children: React.ReactNode; readonly vehicle: vehicle }> } = HooksJS.WithChildren as any; +export const WithChildren: { aComponentWithChildren: (_1:WithChildren_props) => Jsx_element } = HooksJS.WithChildren as any; export const DD: { make: React.ComponentType<{ readonly array: Js_TypedArray2_Uint8Array_t; readonly name: string }> } = HooksJS.DD as any; -export const Another: { anotherComponent: React.ComponentType<{ readonly callback: () => void; readonly vehicle: vehicle }> } = HooksJS.Another as any; +export const Another: { anotherComponent: (_1:Another_props void)>) => Jsx_element } = HooksJS.Another as any; export const Poly: { polymorphicComponent: React.ComponentType<{ readonly p: [vehicle, any] }> } = HooksJS.Poly as any; diff --git a/tests/gentype_tests/typescript-react-example/src/Hooks.res.js b/tests/gentype_tests/typescript-react-example/src/Hooks.res.js index 4a35b38c0f..d4e7549a27 100644 --- a/tests/gentype_tests/typescript-react-example/src/Hooks.res.js +++ b/tests/gentype_tests/typescript-react-example/src/Hooks.res.js @@ -3,65 +3,86 @@ import * as Obj from "rescript/lib/es6/obj.js"; import * as React from "react"; import * as ImportHooks from "./ImportHooks.res.js"; +import * as Primitive_option from "rescript/lib/es6/primitive_option.js"; import * as ImportHookDefault from "./ImportHookDefault.res.js"; +import * as JsxRuntime from "react/jsx-runtime"; -function Hooks(Props) { - let vehicle = Props.vehicle; +function Hooks(props) { let match = React.useState(() => 0); let setCount = match[1]; let count = match[0]; - return React.createElement("div", undefined, React.createElement("p", undefined, "Hooks example " + (vehicle.name + (" clicked " + (String(count) + " times")))), React.createElement("button", { - onClick: param => setCount(param => count + 1 | 0) - }, "Click me"), React.createElement(ImportHooks.make, { - person: { - name: "Mary", - age: 71 - }, - children: null, - renderMe: x => x.randomString - }, "child1", "child2"), React.createElement(ImportHookDefault.make, { - person: { - name: "DefaultImport", - age: 42 - }, - children: null, - renderMe: x => x.randomString - }, "child1", "child2")); + return JsxRuntime.jsxs("div", { + children: [ + JsxRuntime.jsx("p", { + children: "Hooks example " + (props.vehicle.name + (" clicked " + (String(count) + " times"))) + }), + JsxRuntime.jsx("button", { + children: "Click me", + onClick: param => setCount(param => count + 1 | 0) + }), + JsxRuntime.jsxs(ImportHooks.make, { + person: { + name: "Mary", + age: 71 + }, + children: [ + "child1", + "child2" + ], + renderMe: x => x.randomString + }), + JsxRuntime.jsxs(ImportHookDefault.make, { + person: { + name: "DefaultImport", + age: 42 + }, + children: [ + "child1", + "child2" + ], + renderMe: x => x.randomString + }) + ] + }); } -function Hooks$Another$anotherComponent(Props) { - let vehicle = Props.vehicle; - let callback = Props.callback; - callback(); - return React.createElement("div", undefined, "Another Hook " + vehicle.name); +function Hooks$Another$anotherComponent(props) { + props.callback(); + return JsxRuntime.jsx("div", { + children: "Another Hook " + props.vehicle.name + }); } let Another = { anotherComponent: Hooks$Another$anotherComponent }; -function Hooks$Inner(Props) { - let vehicle = Props.vehicle; - return React.createElement("div", undefined, "Another Hook " + vehicle.name); +function Hooks$Inner(props) { + return JsxRuntime.jsx("div", { + children: "Another Hook " + props.vehicle.name + }); } -function Hooks$Inner$Another$anotherComponent(Props) { - let vehicle = Props.vehicle; - return React.createElement("div", undefined, "Another Hook " + vehicle.name); +function Hooks$Inner$Another$anotherComponent(props) { + return JsxRuntime.jsx("div", { + children: "Another Hook " + props.vehicle.name + }); } let Another$1 = { anotherComponent: Hooks$Inner$Another$anotherComponent }; -function Hooks$Inner$Inner2(Props) { - let vehicle = Props.vehicle; - return React.createElement("div", undefined, "Another Hook " + vehicle.name); +function Hooks$Inner$Inner2(props) { + return JsxRuntime.jsx("div", { + children: "Another Hook " + props.vehicle.name + }); } -function Hooks$Inner$Inner2$Another$anotherComponent(Props) { - let vehicle = Props.vehicle; - return React.createElement("div", undefined, "Another Hook " + vehicle.name); +function Hooks$Inner$Inner2$Another$anotherComponent(props) { + return JsxRuntime.jsx("div", { + children: "Another Hook " + props.vehicle.name + }); } let Another$2 = { @@ -79,8 +100,10 @@ let Inner = { Inner2: Inner2 }; -function Hooks$NoProps(Props) { - return React.createElement("div", undefined, null); +function Hooks$NoProps(props) { + return JsxRuntime.jsx("div", { + children: null + }); } let NoProps = { @@ -92,68 +115,65 @@ function functionWithRenamedArgs(_to, _Type, cb) { return _to.name + _Type.name; } -function Hooks$WithRename$componentWithRenamedArgs(Props) { - let _to = Props._to; - let _Type = Props._Type; - let cb = Props.cb; - cb(_to); - return _to.name + _Type.name; +function Hooks$WithRename$componentWithRenamedArgs(props) { + let _to = props._to; + props.cb(_to); + return _to.name + props._Type.name; } let WithRename = { componentWithRenamedArgs: Hooks$WithRename$componentWithRenamedArgs }; -function makeWithRef(vehicle) { +function makeWithRef(param) { + let vehicle = param.vehicle; return ref => { if (ref == null) { return null; } else { - return React.createElement("button", { - ref: ref - }, vehicle.name); + return JsxRuntime.jsx("button", { + children: vehicle.name, + ref: Primitive_option.some(ref) + }); } }; } -function Hooks$WithRef$makeWithRef(Props) { - return makeWithRef(Props.vehicle); -} +let Hooks$WithRef$makeWithRef = makeWithRef; let WithRef = { makeWithRef: Hooks$WithRef$makeWithRef }; -let testForwardRef = React.forwardRef((x, y) => makeWithRef(x.vehicle)(y)); +let testForwardRef = React.forwardRef((x, y) => makeWithRef(x)(y)); -let input = React.forwardRef((r, ref) => React.createElement("div", { - ref: Obj.magic(ref) -}, r.x)); +let input = React.forwardRef((r, ref) => JsxRuntime.jsx("div", { + children: r.x, + ref: Primitive_option.some(Obj.magic(ref)) +})); let ForwardRef = { input: input }; -function Hooks$Poly$polymorphicComponent(Props) { - let param = Props.p; - return param[0].name; +function Hooks$Poly$polymorphicComponent(props) { + return props.p[0].name; } let Poly = { polymorphicComponent: Hooks$Poly$polymorphicComponent }; -function Hooks$Fun$functionReturningReactElement(Props) { - return Props.name; +function Hooks$Fun$functionReturningReactElement(props) { + return props.name; } let Fun = { functionReturningReactElement: Hooks$Fun$functionReturningReactElement }; -function Hooks$RenderPropRequiresConversion(Props) { - let renderVehicle = Props.renderVehicle; - return renderVehicle({ +function Hooks$RenderPropRequiresConversion(props) { + return props.renderVehicle({ vehicle: { name: "Car" }, @@ -165,19 +185,23 @@ let RenderPropRequiresConversion = { make: Hooks$RenderPropRequiresConversion }; -function Hooks$WithChildren$aComponentWithChildren(Props) { - let vehicle = Props.vehicle; - let children = Props.children; - return React.createElement("div", undefined, "Another Hook " + vehicle.name, React.createElement("div", undefined, children)); +function Hooks$WithChildren$aComponentWithChildren(props) { + return JsxRuntime.jsxs("div", { + children: [ + "Another Hook " + props.vehicle.name, + JsxRuntime.jsx("div", { + children: props.children + }) + ] + }); } let WithChildren = { aComponentWithChildren: Hooks$WithChildren$aComponentWithChildren }; -function Hooks$DD(Props) { - let name = Props.name; - return name; +function Hooks$DD(props) { + return props.name; } let DD = { diff --git a/tests/gentype_tests/typescript-react-example/src/ImportHookDefault.gen.tsx b/tests/gentype_tests/typescript-react-example/src/ImportHookDefault.gen.tsx index e478b2fd07..8552188b0e 100644 --- a/tests/gentype_tests/typescript-react-example/src/ImportHookDefault.gen.tsx +++ b/tests/gentype_tests/typescript-react-example/src/ImportHookDefault.gen.tsx @@ -39,4 +39,16 @@ import type {renderMe as ImportHooks_renderMe} from './ImportHooks.gen'; export type person = { readonly name: string; readonly age: number }; +export type props = { + readonly person: person; + readonly children: children; + readonly renderMe: renderMe +}; + +export type MM_props = { + readonly person: person; + readonly children: children; + readonly renderMe: renderMe +}; + export default $$default; diff --git a/tests/gentype_tests/typescript-react-example/src/ImportHooks.gen.tsx b/tests/gentype_tests/typescript-react-example/src/ImportHooks.gen.tsx index f05bfbbd57..fc7dd23a2e 100644 --- a/tests/gentype_tests/typescript-react-example/src/ImportHooks.gen.tsx +++ b/tests/gentype_tests/typescript-react-example/src/ImportHooks.gen.tsx @@ -32,3 +32,10 @@ export const foo: unknown = fooTypeChecked as (person:person) => string as any; export type person = { readonly name: string; readonly age: number }; export type renderMe = React.ComponentType<{ readonly randomString: string; readonly poly: a }>; + +export type props = { + readonly actions?: actions; + readonly person: person; + readonly children: children; + readonly renderMe: renderMe +}; diff --git a/tests/gentype_tests/typescript-react-example/src/ImportIndex.gen.tsx b/tests/gentype_tests/typescript-react-example/src/ImportIndex.gen.tsx index d55ef23ca6..31f142f075 100644 --- a/tests/gentype_tests/typescript-react-example/src/ImportIndex.gen.tsx +++ b/tests/gentype_tests/typescript-react-example/src/ImportIndex.gen.tsx @@ -11,4 +11,6 @@ export const defaultTypeChecked: React.ComponentType<{ readonly method?: "push" // Export '$$default' early to allow circular import from the '.bs.js' file. export const $$default: unknown = defaultTypeChecked as React.ComponentType<{ readonly method?: "push" | "replace" }> as any; +export type props = { readonly method?: method }; + export default $$default; diff --git a/tests/gentype_tests/typescript-react-example/src/JSXV4.gen.tsx b/tests/gentype_tests/typescript-react-example/src/JSXV4.gen.tsx index 1d627f900d..5d138887bf 100644 --- a/tests/gentype_tests/typescript-react-example/src/JSXV4.gen.tsx +++ b/tests/gentype_tests/typescript-react-example/src/JSXV4.gen.tsx @@ -5,8 +5,6 @@ import {make as makeNotChecked} from './hookExample'; -import * as React from 'react'; - // In case of type error, check the type of 'make' in 'JSXV4.res' and './hookExample'. export const makeTypeChecked: React.ComponentType<{ readonly actions?: JSX.Element; @@ -29,7 +27,9 @@ export type CompV4_props = { readonly x: x; readonly y: y }; export type person = { readonly name: string; readonly age: number }; -export type renderMe = React.ComponentType<{ readonly randomString: string; readonly poly: a }>; +export type props2 = { readonly randomString: string; readonly poly: a }; + +export type renderMe = (_1:props2) => JSX.Element; export type props = { readonly actions?: actions; @@ -40,10 +40,4 @@ export type props = { export const CompV4_make: React.ComponentType<{ readonly x: string; readonly y: string }> = JSXV4JS.CompV4.make as any; -export type Props = { readonly x: string; readonly y: string }; - -export const CompV3_make: React.ComponentType<{ readonly x: string; readonly y: string }> = JSXV4JS.CompV3.make as any; - -export const CompV3: { make: React.ComponentType<{ readonly x: string; readonly y: string }> } = JSXV4JS.CompV3 as any; - export const CompV4: { make: React.ComponentType<{ readonly x: string; readonly y: string }> } = JSXV4JS.CompV4 as any; diff --git a/tests/gentype_tests/typescript-react-example/src/JSXV4.res b/tests/gentype_tests/typescript-react-example/src/JSXV4.res index fc4ed11c96..fcbdf09f75 100644 --- a/tests/gentype_tests/typescript-react-example/src/JSXV4.res +++ b/tests/gentype_tests/typescript-react-example/src/JSXV4.res @@ -1,28 +1,22 @@ -@@jsxConfig({version: 4}) - @genType module CompV4 = { @react.component let make = (~x, ~y) => React.string(x ++ y) } -@@jsxConfig({version: 3}) - -@genType -module CompV3 = { - @react.component - let make = (~x, ~y) => React.string(x ++ y) -} - @genType type person = { name: string, age: int, } -@genType type renderMe<'a> = React.component<{"randomString": string, "poly": 'a}> +@genType +type props2<'a> = { + randomString: string, + poly: 'a, +} -@@jsxConfig({version: 4}) +@genType type renderMe<'a> = React.component> @genType.import("./hookExample") @react.component external make: ( diff --git a/tests/gentype_tests/typescript-react-example/src/JSXV4.res.js b/tests/gentype_tests/typescript-react-example/src/JSXV4.res.js index bd037b53c3..016dda6790 100644 --- a/tests/gentype_tests/typescript-react-example/src/JSXV4.res.js +++ b/tests/gentype_tests/typescript-react-example/src/JSXV4.res.js @@ -10,19 +10,10 @@ let CompV4 = { make: JSXV4$CompV4 }; -function JSXV4$CompV3(Props) { - return Props.x + Props.y; -} - -let CompV3 = { - make: JSXV4$CompV3 -}; - let make = JSXV4Gen.make; export { CompV4, - CompV3, make, } /* make Not a pure module */ diff --git a/tests/gentype_tests/typescript-react-example/src/MyInput.gen.tsx b/tests/gentype_tests/typescript-react-example/src/MyInput.gen.tsx index ad85bb45cf..5180a79ce0 100644 --- a/tests/gentype_tests/typescript-react-example/src/MyInput.gen.tsx +++ b/tests/gentype_tests/typescript-react-example/src/MyInput.gen.tsx @@ -15,4 +15,6 @@ import type {inputFocusEvent as $$inputFocusEvent} from './shims/ReactEvent.shim export type inputFocusEvent = $$inputFocusEvent; +export type props = { readonly onFocus?: onFocus }; + export default $$default; diff --git a/tests/gentype_tests/typescript-react-example/src/OnClick2.gen.tsx b/tests/gentype_tests/typescript-react-example/src/OnClick2.gen.tsx index 16b6cf3536..211c80ee99 100644 --- a/tests/gentype_tests/typescript-react-example/src/OnClick2.gen.tsx +++ b/tests/gentype_tests/typescript-react-example/src/OnClick2.gen.tsx @@ -3,10 +3,12 @@ /* eslint-disable */ /* tslint:disable */ -import * as React from 'react'; - import * as OnClick2JS from './OnClick2.res.js'; -export type Props = { readonly onClick: (_1:MouseEvent) => void }; +import type {Mouse_t as JsxEvent_Mouse_t} from '../src/shims/JsxEvent.shim'; + +import type {element as Jsx_element} from '../src/shims/Jsx.shim'; + +export type props = { readonly onClick: onClick }; -export const make: React.ComponentType<{ readonly onClick: (_1:MouseEvent) => void }> = OnClick2JS.make as any; +export const make: (_1:props<((_1:JsxEvent_Mouse_t) => void)>) => Jsx_element = OnClick2JS.make as any; diff --git a/tests/gentype_tests/typescript-react-example/src/OnClick2.res.js b/tests/gentype_tests/typescript-react-example/src/OnClick2.res.js index ebe3a61f47..1106cd2f83 100644 --- a/tests/gentype_tests/typescript-react-example/src/OnClick2.res.js +++ b/tests/gentype_tests/typescript-react-example/src/OnClick2.res.js @@ -1,11 +1,10 @@ // Generated by ReScript, PLEASE EDIT WITH CARE -import * as React from "react"; +import * as JsxRuntime from "react/jsx-runtime"; -function OnClick2(Props) { - let onClick = Props.onClick; - return React.createElement("div", { - onClick: onClick +function OnClick2(props) { + return JsxRuntime.jsx("div", { + onClick: props.onClick }); } @@ -14,4 +13,4 @@ let make = OnClick2; export { make, } -/* react Not a pure module */ +/* react/jsx-runtime Not a pure module */ diff --git a/tests/gentype_tests/typescript-react-example/src/V3Compatibility.gen.tsx b/tests/gentype_tests/typescript-react-example/src/V3Compatibility.gen.tsx deleted file mode 100644 index 2b55a93c66..0000000000 --- a/tests/gentype_tests/typescript-react-example/src/V3Compatibility.gen.tsx +++ /dev/null @@ -1,6 +0,0 @@ -/* TypeScript file generated from V3Compatibility.res by genType. */ - -/* eslint-disable */ -/* tslint:disable */ - -export type cb = (_1:number) => string; diff --git a/tests/gentype_tests/typescript-react-example/src/V3Compatibility.res b/tests/gentype_tests/typescript-react-example/src/V3Compatibility.res deleted file mode 100644 index c706483c60..0000000000 --- a/tests/gentype_tests/typescript-react-example/src/V3Compatibility.res +++ /dev/null @@ -1,4 +0,0 @@ -open ReactV3 - -@genType -type cb = int => string diff --git a/tests/gentype_tests/typescript-react-example/src/V3Compatibility.res.js b/tests/gentype_tests/typescript-react-example/src/V3Compatibility.res.js deleted file mode 100644 index d856702bfe..0000000000 --- a/tests/gentype_tests/typescript-react-example/src/V3Compatibility.res.js +++ /dev/null @@ -1,2 +0,0 @@ -// Generated by ReScript, PLEASE EDIT WITH CARE -/* This output is empty. Its source's type definitions, externals and/or unused code got optimized away. */ diff --git a/tests/gentype_tests/typescript-react-example/src/shims/Jsx.shim.ts b/tests/gentype_tests/typescript-react-example/src/shims/Jsx.shim.ts new file mode 100644 index 0000000000..236aca55af --- /dev/null +++ b/tests/gentype_tests/typescript-react-example/src/shims/Jsx.shim.ts @@ -0,0 +1,3 @@ +import type { ReactElement } from "react"; + +export type element = ReactElement; diff --git a/tests/gentype_tests/typescript-react-example/src/shims/JsxEvent.shim.ts b/tests/gentype_tests/typescript-react-example/src/shims/JsxEvent.shim.ts new file mode 100644 index 0000000000..6765b9e859 --- /dev/null +++ b/tests/gentype_tests/typescript-react-example/src/shims/JsxEvent.shim.ts @@ -0,0 +1,3 @@ +export abstract class Mouse_t { + protected opaque: unknown; +} From 9b3c390b2ac7fd306da9d918d5bb14ac9e64a163 Mon Sep 17 00:00:00 2001 From: mununki Date: Fri, 4 Oct 2024 16:25:00 +0900 Subject: [PATCH 2/7] fix genType tests --- .../typescript-react-example/rescript.json | 4 +- .../src/MyInput.gen.tsx | 2 +- .../typescript-react-example/src/MyInput.res | 2 +- .../src/shims/JsxEvent.shim.ts | 58 +++++++++++++++++++ .../src/shims/ReactEvent.shim.ts | 57 ------------------ 5 files changed, 61 insertions(+), 62 deletions(-) delete mode 100644 tests/gentype_tests/typescript-react-example/src/shims/ReactEvent.shim.ts diff --git a/tests/gentype_tests/typescript-react-example/rescript.json b/tests/gentype_tests/typescript-react-example/rescript.json index 5df00aebde..ff2951419f 100644 --- a/tests/gentype_tests/typescript-react-example/rescript.json +++ b/tests/gentype_tests/typescript-react-example/rescript.json @@ -8,9 +8,7 @@ "Jsx": "Jsx", "JsxEvent": "JsxEvent", "Belt": "Belt", - "ReactEvent": "ReactEvent", - "RescriptPervasives": "RescriptPervasives", - "ReasonReact": "ReactShim" + "RescriptPervasives": "RescriptPervasives" }, "debug": { "all": false diff --git a/tests/gentype_tests/typescript-react-example/src/MyInput.gen.tsx b/tests/gentype_tests/typescript-react-example/src/MyInput.gen.tsx index 5180a79ce0..9e9e897357 100644 --- a/tests/gentype_tests/typescript-react-example/src/MyInput.gen.tsx +++ b/tests/gentype_tests/typescript-react-example/src/MyInput.gen.tsx @@ -11,7 +11,7 @@ export const defaultTypeChecked: React.ComponentType<{ readonly onFocus?: (_1:in // Export '$$default' early to allow circular import from the '.bs.js' file. export const $$default: unknown = defaultTypeChecked as React.ComponentType<{ readonly onFocus?: (_1:inputFocusEvent) => void }> as any; -import type {inputFocusEvent as $$inputFocusEvent} from './shims/ReactEvent.shim'; +import type {inputFocusEvent as $$inputFocusEvent} from './shims/JsxEvent.shim'; export type inputFocusEvent = $$inputFocusEvent; diff --git a/tests/gentype_tests/typescript-react-example/src/MyInput.res b/tests/gentype_tests/typescript-react-example/src/MyInput.res index 6415dc127a..a0a7f025d0 100644 --- a/tests/gentype_tests/typescript-react-example/src/MyInput.res +++ b/tests/gentype_tests/typescript-react-example/src/MyInput.res @@ -1,4 +1,4 @@ -@genType.import("./shims/ReactEvent.shim") +@genType.import("./shims/JsxEvent.shim") type inputFocusEvent = ReactEvent.Focus.t @genType.import("./MyInput") @react.component diff --git a/tests/gentype_tests/typescript-react-example/src/shims/JsxEvent.shim.ts b/tests/gentype_tests/typescript-react-example/src/shims/JsxEvent.shim.ts index 6765b9e859..c3b44ff021 100644 --- a/tests/gentype_tests/typescript-react-example/src/shims/JsxEvent.shim.ts +++ b/tests/gentype_tests/typescript-react-example/src/shims/JsxEvent.shim.ts @@ -1,3 +1,61 @@ +export abstract class Animation_t { + protected opaque: unknown; +} + +export abstract class Clipboard_t { + protected opaque: unknown; +} + +export abstract class Composition_t { + protected opaque: unknown; +} + +export abstract class Focus_t { + protected opaque: unknown; +} + +export abstract class Form_t { + protected opaque: unknown; +} + +export abstract class Keyboard_t { + protected opaque: unknown; +} + +export abstract class Image_t { + protected opaque: unknown; +} + +export abstract class Media_t { + protected opaque: unknown; +} + +export abstract class Selection_t { + protected opaque: unknown; +} + +export abstract class Synthetic_t { + protected opaque: unknown; +} + +export abstract class Touch_t { + protected opaque: unknown; +} + +export abstract class Transition_t { + protected opaque: unknown; +} + +export abstract class UI_t { + protected opaque: unknown; +} + +export abstract class Wheel_t { + protected opaque: unknown; +} + +export type inputFocusEvent = React.FocusEvent; + export abstract class Mouse_t { protected opaque: unknown; } diff --git a/tests/gentype_tests/typescript-react-example/src/shims/ReactEvent.shim.ts b/tests/gentype_tests/typescript-react-example/src/shims/ReactEvent.shim.ts deleted file mode 100644 index fc4035f844..0000000000 --- a/tests/gentype_tests/typescript-react-example/src/shims/ReactEvent.shim.ts +++ /dev/null @@ -1,57 +0,0 @@ -export abstract class Animation_t { - protected opaque: unknown; -} - -export abstract class Clipboard_t { - protected opaque: unknown; -} - -export abstract class Composition_t { - protected opaque: unknown; -} - -export abstract class Focus_t { - protected opaque: unknown; -} - -export abstract class Form_t { - protected opaque: unknown; -} - -export abstract class Keyboard_t { - protected opaque: unknown; -} - -export abstract class Image_t { - protected opaque: unknown; -} - -export abstract class Media_t { - protected opaque: unknown; -} - -export abstract class Selection_t { - protected opaque: unknown; -} - -export abstract class Synthetic_t { - protected opaque: unknown; -} - -export abstract class Touch_t { - protected opaque: unknown; -} - -export abstract class Transition_t { - protected opaque: unknown; -} - -export abstract class UI_t { - protected opaque: unknown; -} - -export abstract class Wheel_t { - protected opaque: unknown; -} - -export type inputFocusEvent = React.FocusEvent; From ac209583a961b3af3d77a82c23974e53eab68878 Mon Sep 17 00:00:00 2001 From: mununki Date: Fri, 4 Oct 2024 16:34:54 +0900 Subject: [PATCH 3/7] fix test --- tests/tests/src/recursive_react_component.js | 5 ++--- tests/tests/src/recursive_react_component.res | 4 ++-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/tests/tests/src/recursive_react_component.js b/tests/tests/src/recursive_react_component.js index 4753217ff2..b90857cf2b 100644 --- a/tests/tests/src/recursive_react_component.js +++ b/tests/tests/src/recursive_react_component.js @@ -3,10 +3,9 @@ let React = require("react"); -function make(Props) { - let foo = Props.foo; +function make(props) { return React.createElement(make, { - foo: foo + foo: props.foo }); } diff --git a/tests/tests/src/recursive_react_component.res b/tests/tests/src/recursive_react_component.res index 8e2756aa79..e2d7e3cdf0 100644 --- a/tests/tests/src/recursive_react_component.res +++ b/tests/tests/src/recursive_react_component.res @@ -1,11 +1,11 @@ @@config({ flags: [ "-bs-jsx", - "3", // "-dsource", + "4", // "-dsource", // "-w","A", // "-warn-error", "a" ], }) @react.component -let rec make = (~foo, ()) => React.createElement(make, makeProps(~foo, ())) +let rec make = (~foo, ()) => React.createElement(make, {foo: foo}) From 98b40aeff49135142bc7f99718c2736729e25d22 Mon Sep 17 00:00:00 2001 From: mununki Date: Fri, 4 Oct 2024 18:14:32 +0900 Subject: [PATCH 4/7] changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5574b75c31..d3b4a9819e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ #### :boom: Breaking Change - OCaml compatibility in the stdlib and primitives are dropped/deprecated. https://github.com/rescript-lang/rescript-compiler/pull/6984 +- Remove the JSX v3. https://github.com/rescript-lang/rescript-compiler/pull/7072 #### :rocket: New Feature From 803b9cc513936a3ffd06647c7a728aa8f9d724d0 Mon Sep 17 00:00:00 2001 From: mununki Date: Fri, 4 Oct 2024 18:49:10 +0900 Subject: [PATCH 5/7] remove syntax test expected --- .../ppx/react/expected/innerModule.res.txt | 35 ------------------- 1 file changed, 35 deletions(-) delete mode 100644 jscomp/syntax/tests/ppx/react/expected/innerModule.res.txt diff --git a/jscomp/syntax/tests/ppx/react/expected/innerModule.res.txt b/jscomp/syntax/tests/ppx/react/expected/innerModule.res.txt deleted file mode 100644 index 2a0a1cbf67..0000000000 --- a/jscomp/syntax/tests/ppx/react/expected/innerModule.res.txt +++ /dev/null @@ -1,35 +0,0 @@ -@@jsxConfig({version: 3}) -module Bar = { - @obj external makeProps: (~a: 'a, ~b: 'b, ~key: string=?, unit) => {"a": 'a, "b": 'b} = "" - - @react.component - let make = - @warning("-16") - (~a) => - @warning("-16") - (~b, _) => { - Js.log("This function should be named `InnerModule.react$Bar`") - ReactDOMRe.createDOMElementVariadic("div", []) - } - let make = { - let \"InnerModule$Bar" = (\"Props": {"a": 'a, "b": 'b}) => - make(~b=\"Props"["b"], ~a=\"Props"["a"], ()) - \"InnerModule$Bar" - } - @obj external componentProps: (~a: 'a, ~b: 'b, ~key: string=?, unit) => {"a": 'a, "b": 'b} = "" - - @react.component - let component = - @warning("-16") - (~a) => - @warning("-16") - (~b, _) => { - Js.log("This function should be named `InnerModule.react$Bar$component`") - ReactDOMRe.createDOMElementVariadic("div", []) - } - let component = { - let \"InnerModule$Bar$component" = (\"Props": {"a": 'a, "b": 'b}) => - component(~b=\"Props"["b"], ~a=\"Props"["a"], ()) - \"InnerModule$Bar$component" - } -} From 2f913280a9b80b7a9c5a50fe4c257151c0242556 Mon Sep 17 00:00:00 2001 From: mununki Date: Fri, 4 Oct 2024 18:49:22 +0900 Subject: [PATCH 6/7] remove v3 from build-schema --- docs/docson/build-schema.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docson/build-schema.json b/docs/docson/build-schema.json index 7dba11054f..d06504e5f3 100644 --- a/docs/docson/build-schema.json +++ b/docs/docson/build-schema.json @@ -309,7 +309,7 @@ "properties": { "version": { "type": "number", - "enum": [3, 4], + "enum": [4], "description": "Whether to apply the specific version of JSX PPX transformation" }, "module": { From 4147e42d60503fae7bb5f00b2bc48fb0ce1a3993 Mon Sep 17 00:00:00 2001 From: mununki Date: Fri, 4 Oct 2024 18:49:55 +0900 Subject: [PATCH 7/7] remove makeProps from tests --- .../tests/idempotency/nook-exchange/App.res | 5 - .../idempotency/reason-react/src/React.res | 58 +++++---- .../idempotency/reasonml.org/common/App.res | 18 +-- .../reductive/reductiveContext.res | 9 -- .../reductive/reductiveContext.resi | 16 +-- .../wildcards-world-ui/LazyThreeBoxUpdate.res | 2 +- .../wildcards-world-ui/ReactTranslate.res | 6 - .../wildcards-world-ui/RootProvider.res | 7 - .../wildcards-world-ui/UsdPriceProvider.res | 7 - tests/build_tests/react_ppx/src/React.res | 2 + tests/tests/src/gpr_3519_test.js | 8 +- tests/tests/src/gpr_3519_test.res | 6 - tests/tests/src/gpr_5071_test.js | 18 --- tests/tests/src/gpr_5071_test.res | 14 -- tests/tests/src/react.js | 6 - tests/tests/src/react.res | 123 ++++++------------ 16 files changed, 92 insertions(+), 213 deletions(-) diff --git a/jscomp/syntax/tests/idempotency/nook-exchange/App.res b/jscomp/syntax/tests/idempotency/nook-exchange/App.res index a00808a9de..f67ce62754 100644 --- a/jscomp/syntax/tests/idempotency/nook-exchange/App.res +++ b/jscomp/syntax/tests/idempotency/nook-exchange/App.res @@ -26,11 +26,6 @@ external gtag: option<(. string, string, {"page_path": string}) => unit> = "gtag module TooltipConfigContextProvider = { type tooltipModifiers = array<{"name": string, "options": {"offset": array}}> - let makeProps = (~value, ~children, ()) => - { - "value": value, - "children": children, - } let make = React.Context.provider( ( ReactAtmosphere.Tooltip.configContext: React.Context.t< diff --git a/jscomp/syntax/tests/idempotency/reason-react/src/React.res b/jscomp/syntax/tests/idempotency/reason-react/src/React.res index 74bb44a359..320b51805c 100644 --- a/jscomp/syntax/tests/idempotency/reason-react/src/React.res +++ b/jscomp/syntax/tests/idempotency/reason-react/src/React.res @@ -2,6 +2,8 @@ type element @val external null: element = "null" +external float: float => element = "%identity" +external int: int => element = "%identity" external string: string => element = "%identity" external array: array => element = "%identity" @@ -20,6 +22,20 @@ external cloneElement: (component<'props>, 'props) => element = "cloneElement" external createElementVariadic: (component<'props>, 'props, array) => element = "createElement" +@module("react/jsx-runtime") +external jsx: (component<'props>, 'props) => element = "jsx" + +@module("react/jsx-runtime") +external jsxKeyed: (component<'props>, 'props, ~key: string=?, @ignore unit) => element = "jsx" + +@module("react/jsx-runtime") +external jsxs: (component<'props>, 'props) => element = "jsxs" + +@module("react/jsx-runtime") +external jsxsKeyed: (component<'props>, 'props, ~key: string=?, @ignore unit) => element = "jsxs" + +type ref<'value> = {mutable current: 'value} + module Ref = { type t<'value> @@ -27,7 +43,8 @@ module Ref = { @set external setCurrent: (t<'value>, 'value) => unit = "current" } -@module("react") external createRef: unit => Ref.t> = "createRef" +@module("react") +external createRef: unit => Ref.t> = "createRef" module Children = { @module("react") @scope("Children") @val @@ -43,13 +60,19 @@ module Children = { } module Context = { - type t<'props> + type t<'context> + + type props<'context> = { + value: 'context, + children: element, + } @get - external provider: t<'props> => component<{"value": 'props, "children": element}> = "Provider" + external provider: t<'context> => component> = "Provider" } -@module("react") external createContext: 'a => Context.t<'a> = "createContext" +@module("react") +external createContext: 'a => Context.t<'a> = "createContext" @module("react") external forwardRef: (('props, Js.Nullable.t>) => element) => component<'props> = @@ -65,29 +88,17 @@ external memoCustomCompareProps: ( ) => component<'props> = "memo" module Fragment = { - @obj - external makeProps: (~children: element, ~key: 'key=?, unit) => {"children": element} = "" + type props = {key?: string, children: element} + @module("react") - external make: component<{ - "children": element, - }> = "Fragment" + external make: component = "Fragment" } module Suspense = { - @obj - external makeProps: ( - ~children: element=?, - ~fallback: element=?, - ~maxDuration: int=?, - ~key: 'key=?, - unit, - ) => {"children": option, "fallback": option, "maxDuration": option} = "" + type props = {key?: string, children?: element, fallback?: element} + @module("react") - external make: component<{ - "children": option, - "fallback": option, - "maxDuration": option, - }> = "Suspense" + external make: component = "Suspense" } /* HOOKS */ @@ -228,7 +239,8 @@ external useCallback7: ( ('a, 'b, 'c, 'd, 'e, 'f, 'g), ) => callback<'input, 'output> = "useCallback" -@module("react") external useContext: Context.t<'any> => 'any = "useContext" +@module("react") +external useContext: Context.t<'any> => 'any = "useContext" @module("react") external useRef: 'value => Ref.t<'value> = "useRef" diff --git a/jscomp/syntax/tests/idempotency/reasonml.org/common/App.res b/jscomp/syntax/tests/idempotency/reasonml.org/common/App.res index c035c8524e..9854e1fd64 100644 --- a/jscomp/syntax/tests/idempotency/reasonml.org/common/App.res +++ b/jscomp/syntax/tests/idempotency/reasonml.org/common/App.res @@ -27,10 +27,10 @@ hljs.registerLanguage('text', text); `) -type pageComponent = React.component<{.}> -type pageProps = {.} +type pageProps = {} +type pageComponent = React.component -type props = {"Component": pageComponent, "pageProps": pageProps} +type props = {@as("Component") component: pageComponent, pageProps: pageProps} module Url = { type version = @@ -116,17 +116,9 @@ module Url = { } } -@obj -external makeProps: ( - ~component: pageComponent, - ~pageProps: pageProps, - ~key: string=?, - unit, -) => props = "" - let make = (props: props): React.element => { - let component = props["Component"] - let pageProps = props["pageProps"] + let component = props.component + let pageProps = props.pageProps let router = Next.Router.useRouter() diff --git a/jscomp/syntax/tests/idempotency/reductive/reductiveContext.res b/jscomp/syntax/tests/idempotency/reductive/reductiveContext.res index 4faa0e5add..87ecaa9214 100644 --- a/jscomp/syntax/tests/idempotency/reductive/reductiveContext.res +++ b/jscomp/syntax/tests/idempotency/reductive/reductiveContext.res @@ -10,15 +10,6 @@ module Make = (Config: Config) => { module ContextProvider = { let make = React.Context.provider(storeContext) - let makeProps = ( - ~value: option>, - ~children, - (), - ) => - { - "value": value, - "children": children, - } } module Provider = { diff --git a/jscomp/syntax/tests/idempotency/reductive/reductiveContext.resi b/jscomp/syntax/tests/idempotency/reductive/reductiveContext.resi index e3193a87e5..bf253ff0ef 100644 --- a/jscomp/syntax/tests/idempotency/reductive/reductiveContext.resi +++ b/jscomp/syntax/tests/idempotency/reductive/reductiveContext.resi @@ -5,17 +5,11 @@ module type Config = { module Make: (Config: Config) => { module Provider: { - @obj - external makeProps: ( - ~children: 'children, - ~store: Reductive.Store.t, - ~key: string=?, - unit, - ) => {"children": 'children, "store": Reductive.Store.t} = "" - let make: { - "children": React.element, - "store": Reductive.Store.t, - } => React.element + @react.component + let make: ( + ~children: React.element, + ~store: Reductive.Store.t + ) => React.element } let useSelector: (Config.state => 'selectedState) => 'selectedState let useDispatch: (unit, Config.action) => unit diff --git a/jscomp/syntax/tests/idempotency/wildcards-world-ui/LazyThreeBoxUpdate.res b/jscomp/syntax/tests/idempotency/wildcards-world-ui/LazyThreeBoxUpdate.res index 937e9731e4..55e5f0281c 100644 --- a/jscomp/syntax/tests/idempotency/wildcards-world-ui/LazyThreeBoxUpdate.res +++ b/jscomp/syntax/tests/idempotency/wildcards-world-ui/LazyThreeBoxUpdate.res @@ -8,7 +8,7 @@ let unsafePlaceholder: module(T) = %raw(`{}`) module UnsafePlaceholder = unpack(unsafePlaceholder) -let makeProps = UnsafePlaceholder.makeProps +type props = UnsafePlaceholder.props let make = ReLoadable.lazy_(() => ReLoadable.\"import"(UnsafePlaceholder.make, "./ThreeBoxUpdate.bs.js") diff --git a/jscomp/syntax/tests/idempotency/wildcards-world-ui/ReactTranslate.res b/jscomp/syntax/tests/idempotency/wildcards-world-ui/ReactTranslate.res index 2927a6d14c..155b0e2f59 100644 --- a/jscomp/syntax/tests/idempotency/wildcards-world-ui/ReactTranslate.res +++ b/jscomp/syntax/tests/idempotency/wildcards-world-ui/ReactTranslate.res @@ -49,12 +49,6 @@ module TranslationContext = { setTranslationModeCrypto: _ => (), }) - let makeProps = (~value, ~children, ()) => - { - "value": value, - "children": children, - } - let make = React.Context.provider(translationContext) } let useTranslationModeContext = () => React.useContext(TranslationContext.translationContext) diff --git a/jscomp/syntax/tests/idempotency/wildcards-world-ui/RootProvider.res b/jscomp/syntax/tests/idempotency/wildcards-world-ui/RootProvider.res index e0b2d0e98a..b0da2aae91 100644 --- a/jscomp/syntax/tests/idempotency/wildcards-world-ui/RootProvider.res +++ b/jscomp/syntax/tests/idempotency/wildcards-world-ui/RootProvider.res @@ -101,13 +101,6 @@ module RootContext = { let context = React.createContext((initialState, _ => ())) // Create a provider component let make = React.Context.provider(context) - - // Tell bucklescript how to translate props into JS - let makeProps = (~value, ~children, ()) => - { - "value": value, - "children": children, - } } module RootWithWeb3 = { diff --git a/jscomp/syntax/tests/idempotency/wildcards-world-ui/UsdPriceProvider.res b/jscomp/syntax/tests/idempotency/wildcards-world-ui/UsdPriceProvider.res index 87a7025c48..1c7f2baf47 100644 --- a/jscomp/syntax/tests/idempotency/wildcards-world-ui/UsdPriceProvider.res +++ b/jscomp/syntax/tests/idempotency/wildcards-world-ui/UsdPriceProvider.res @@ -8,13 +8,6 @@ let initialState = {usdPrice: None} module PriceProvider = { let context: React.Context.t> = React.createContext(None) let make = React.Context.provider(context) - - @ocaml.doc(" Tell bucklescript how to translate props into JS ") - let makeProps = (~value, ~children, ()) => - { - "value": value, - "children": children, - } } @decco @deriving(accessors) diff --git a/tests/build_tests/react_ppx/src/React.res b/tests/build_tests/react_ppx/src/React.res index 82309ae10c..ba3c322069 100644 --- a/tests/build_tests/react_ppx/src/React.res +++ b/tests/build_tests/react_ppx/src/React.res @@ -32,6 +32,8 @@ external jsxs: (component<'props>, 'props) => element = "jsxs" @module("react/jsx-runtime") external jsxsKeyed: (component<'props>, 'props, ~key: string=?, @ignore unit) => element = "jsxs" +type ref<'value> = {mutable current: 'value} + module Ref = { type t<'value> diff --git a/tests/tests/src/gpr_3519_test.js b/tests/tests/src/gpr_3519_test.js index a56ca06670..d856702bfe 100644 --- a/tests/tests/src/gpr_3519_test.js +++ b/tests/tests/src/gpr_3519_test.js @@ -1,8 +1,2 @@ // Generated by ReScript, PLEASE EDIT WITH CARE -'use strict'; - - -let Foo = {}; - -exports.Foo = Foo; -/* No side effect */ +/* This output is empty. Its source's type definitions, externals and/or unused code got optimized away. */ diff --git a/tests/tests/src/gpr_3519_test.res b/tests/tests/src/gpr_3519_test.res index 5b52ac5b0b..805ae0c0dd 100644 --- a/tests/tests/src/gpr_3519_test.res +++ b/tests/tests/src/gpr_3519_test.res @@ -1,9 +1,3 @@ -module Foo: { - @obj external makeProps: (~bar: array=?) => string = "" -} = { - @obj external makeProps: (~bar: 'bar=?) => string = "" -} - type arra<'a> = array<'a> @send @variadic external f0: (int, int, int, array) => unit = "f0" diff --git a/tests/tests/src/gpr_5071_test.js b/tests/tests/src/gpr_5071_test.js index 999c63139b..b0236606ef 100644 --- a/tests/tests/src/gpr_5071_test.js +++ b/tests/tests/src/gpr_5071_test.js @@ -2,21 +2,6 @@ 'use strict'; -let Test = {}; - -let u = { - s: "hello" -}; - -function f(s, y) { - let tmp = {}; - if (s !== undefined) { - tmp.s = s; - } - console.log(tmp); - console.log(y); -} - function make(s) { if (s !== undefined) { return s; @@ -29,8 +14,5 @@ let H = { make: make }; -exports.Test = Test; -exports.u = u; -exports.f = f; exports.H = H; /* No side effect */ diff --git a/tests/tests/src/gpr_5071_test.res b/tests/tests/src/gpr_5071_test.res index d7003d2df5..31f118dd45 100644 --- a/tests/tests/src/gpr_5071_test.res +++ b/tests/tests/src/gpr_5071_test.res @@ -1,20 +1,6 @@ @@config({ flags: ["-w", "-16"], }) -module Test: { - @obj - external makeProps: (~s: string=?, unit) => {"s": string} = "" -} = { - @obj - external makeProps: (~s: 's=?, unit) => {"s": 's} = "" -} - -let u = Test.makeProps(~s="hello", ()) - -let f = (~s=?, y) => { - Test.makeProps(~s?, ())->Js.log - Js.log(y) -} module H: { @react.component diff --git a/tests/tests/src/react.js b/tests/tests/src/react.js index cfc2f2da1d..05c8865770 100644 --- a/tests/tests/src/react.js +++ b/tests/tests/src/react.js @@ -10,17 +10,11 @@ let Context = {}; let Fragment = {}; -let StrictMode = {}; - let Suspense = {}; -let SuspenseList = {}; - exports.Ref = Ref; exports.Children = Children; exports.Context = Context; exports.Fragment = Fragment; -exports.StrictMode = StrictMode; exports.Suspense = Suspense; -exports.SuspenseList = SuspenseList; /* No side effect */ diff --git a/tests/tests/src/react.res b/tests/tests/src/react.res index 41145195a0..4a6500180b 100644 --- a/tests/tests/src/react.res +++ b/tests/tests/src/react.res @@ -16,38 +16,42 @@ type component<'props> = componentLike<'props, element> external createElement: (component<'props>, 'props) => element = "createElement" @module("react") -external cloneElement: (element, 'props) => element = "cloneElement" +external cloneElement: (component<'props>, 'props) => element = "cloneElement" @variadic @module("react") external createElementVariadic: (component<'props>, 'props, array) => element = "createElement" +@module("react/jsx-runtime") +external jsx: (component<'props>, 'props) => element = "jsx" + +@module("react/jsx-runtime") +external jsxKeyed: (component<'props>, 'props, ~key: string=?, @ignore unit) => element = "jsx" + +@module("react/jsx-runtime") +external jsxs: (component<'props>, 'props) => element = "jsxs" + +@module("react/jsx-runtime") +external jsxsKeyed: (component<'props>, 'props, ~key: string=?, @ignore unit) => element = "jsxs" + type ref<'value> = {mutable current: 'value} module Ref = { - @deprecated("Please use the type React.ref instead") - type t<'value> = ref<'value> - - @deprecated("Please directly read from ref.current instead") @get - external current: ref<'value> => 'value = "current" + type t<'value> - @deprecated("Please directly assign to ref.current instead") @set - external setCurrent: (ref<'value>, 'value) => unit = "current" + @get external current: t<'value> => 'value = "current" + @set external setCurrent: (t<'value>, 'value) => unit = "current" } @module("react") -external createRef: unit => ref> = "createRef" +external createRef: unit => Ref.t> = "createRef" module Children = { @module("react") @scope("Children") @val external map: (element, element => element) => element = "map" @module("react") @scope("Children") @val - external mapWithIndex: (element, (element, int) => element) => element = "map" - @module("react") @scope("Children") @val external forEach: (element, element => unit) => unit = "forEach" @module("react") @scope("Children") @val - external forEachWithIndex: (element, (element, int) => unit) => unit = "forEach" - @module("react") @scope("Children") @val external count: element => int = "count" @module("react") @scope("Children") @val external only: element => element = "only" @@ -56,17 +60,22 @@ module Children = { } module Context = { - type t<'props> + type t<'context> + + type props<'context> = { + value: 'context, + children: element, + } @get - external provider: t<'props> => component<{"value": 'props, "children": element}> = "Provider" + external provider: t<'context> => component> = "Provider" } @module("react") external createContext: 'a => Context.t<'a> = "createContext" @module("react") -external forwardRef: (('props, Js.Nullable.t>) => element) => component<'props> = +external forwardRef: (('props, Js.Nullable.t>) => element) => component<'props> = "forwardRef" @module("react") @@ -79,57 +88,19 @@ external memoCustomCompareProps: ( ) => component<'props> = "memo" module Fragment = { - @obj - external makeProps: (~children: element, ~key: 'key=?, unit) => {"children": element} = "" - @module("react") - external make: component<{ - "children": element, - }> = "Fragment" -} + type props = {key?: string, children: element} -module StrictMode = { - @obj - external makeProps: (~children: element, ~key: 'key=?, unit) => {"children": element} = "" @module("react") - external make: component<{ - "children": element, - }> = "StrictMode" + external make: component = "Fragment" } module Suspense = { - @obj - external makeProps: ( - ~children: element=?, - ~fallback: element=?, - ~key: 'key=?, - unit, - ) => {"children": option, "fallback": option} = "" - @module("react") - external make: component<{ - "children": option, - "fallback": option, - }> = "Suspense" -} - -/* Experimental React.SuspenseList */ -module SuspenseList = { - type revealOrder - type tail - @obj - external makeProps: ( - ~children: element=?, - ~revealOrder: [#forwards | #backwards | #together]=?, - ~tail: [#collapsed | #hidden]=?, - unit, - ) => {"children": option, "revealOrder": option, "tail": option} = "" + type props = {key?: string, children?: element, fallback?: element} @module("react") - external make: component<{ - "children": option, - "revealOrder": option, - "tail": option, - }> = "SuspenseList" + external make: component = "Suspense" } + /* HOOKS */ /* @@ -248,65 +219,57 @@ external useCallback7: ( @module("react") external useContext: Context.t<'any> => 'any = "useContext" -@module("react") external useRef: 'value => ref<'value> = "useRef" +@module("react") external useRef: 'value => Ref.t<'value> = "useRef" @module("react") external useImperativeHandle0: ( - Js.Nullable.t>, + Js.Nullable.t>, unit => 'value, @as(json`[]`) _, ) => unit = "useImperativeHandle" @module("react") -external useImperativeHandle1: (Js.Nullable.t>, unit => 'value, array<'a>) => unit = +external useImperativeHandle1: (Js.Nullable.t>, unit => 'value, array<'a>) => unit = "useImperativeHandle" @module("react") -external useImperativeHandle2: (Js.Nullable.t>, unit => 'value, ('a, 'b)) => unit = +external useImperativeHandle2: (Js.Nullable.t>, unit => 'value, ('a, 'b)) => unit = "useImperativeHandle" @module("react") -external useImperativeHandle3: (Js.Nullable.t>, unit => 'value, ('a, 'b, 'c)) => unit = - "useImperativeHandle" +external useImperativeHandle3: ( + Js.Nullable.t>, + unit => 'value, + ('a, 'b, 'c), +) => unit = "useImperativeHandle" @module("react") external useImperativeHandle4: ( - Js.Nullable.t>, + Js.Nullable.t>, unit => 'value, ('a, 'b, 'c, 'd), ) => unit = "useImperativeHandle" @module("react") external useImperativeHandle5: ( - Js.Nullable.t>, + Js.Nullable.t>, unit => 'value, ('a, 'b, 'c, 'd, 'e), ) => unit = "useImperativeHandle" @module("react") external useImperativeHandle6: ( - Js.Nullable.t>, + Js.Nullable.t>, unit => 'value, ('a, 'b, 'c, 'd, 'e, 'f), ) => unit = "useImperativeHandle" @module("react") external useImperativeHandle7: ( - Js.Nullable.t>, + Js.Nullable.t>, unit => 'value, ('a, 'b, 'c, 'd, 'e, 'f, 'g), ) => unit = "useImperativeHandle" -type transitionConfig = {timeoutMs: int} - -@module("react") -external useTransition: ( - ~config: transitionConfig=?, - unit, -) => (callback, unit>, bool) = "useTransition" - @set external setDisplayName: (component<'props>, string) => unit = "displayName" - -@get @return(nullable) -external displayName: component<'props> => option = "displayName"