diff --git a/changes/flat-make-exports.feature.md b/changes/flat-make-exports.feature.md new file mode 100644 index 00000000000..40fee82eedd --- /dev/null +++ b/changes/flat-make-exports.feature.md @@ -0,0 +1 @@ +- Export every nested `make` as a flat value such as `A$B$make` and read it that way from other modules, so nested JSX components work as React Server Components client references. diff --git a/changes/remove-hoisted-function.breaking.md b/changes/remove-hoisted-function.breaking.md new file mode 100644 index 00000000000..87e79c343f0 --- /dev/null +++ b/changes/remove-hoisted-function.breaking.md @@ -0,0 +1 @@ +- Remove `@res.hoistedFunction`, which nested `make` flat exports replace; other nested functions are no longer exported flat. diff --git a/compiler/core/js_cmj_format.ml b/compiler/core/js_cmj_format.ml index 21887c64831..85253182fa2 100644 --- a/compiler/core/js_cmj_format.ml +++ b/compiler/core/js_cmj_format.ml @@ -45,26 +45,14 @@ type keyed_cmj_value = { type keyed_cmj_values = keyed_cmj_value array -type hoisted_export = { - path: string list; (** Exact source-level module path segments. *) - export_name: string; - (** Flattened compiler name for the export, before JS identifier - conversion: the emitted export applies [Ext_ident.convert] to it - (a hoisted [Operator.\"+"] is stored as [Operator$+] and exported - as [Operator$$plus]), and so must any consumer that reconstructs - the JS export name. *) -} - type t = { values: keyed_cmj_values; - hoisted_exports: hoisted_export array; pure: bool; package_spec: Js_packages_info.t; case: Ext_js_file_kind.case; } -let make ~(values : cmj_value Map_string.t) ~hoisted_exports ~effect_ - ~package_spec ~case : t = +let make ~(values : cmj_value Map_string.t) ~effect_ ~package_spec ~case : t = { values = Map_string.bindings values @@ -75,7 +63,6 @@ let make ~(values : cmj_value Map_string.t) ~hoisted_exports ~effect_ persistent_closed_lambda = v.persistent_closed_lambda; }) |> Array.of_list; - hoisted_exports = Array.of_list hoisted_exports; pure = effect_ = None; package_spec; case; @@ -173,13 +160,6 @@ let query_by_name (cmj_table : t) name : keyed_cmj_value = let values = cmj_table.values in binary_search values name -let find_hoisted_export (cmj_table : t) path = - Array.find_map - (fun value -> - if List.equal Ext_string.equal value.path path then Some value.export_name - else None) - cmj_table.hoisted_exports - type path = string type cmj_load_info = { diff --git a/compiler/core/js_cmj_format.mli b/compiler/core/js_cmj_format.mli index 6e584aa772b..937f5257778 100644 --- a/compiler/core/js_cmj_format.mli +++ b/compiler/core/js_cmj_format.mli @@ -61,19 +61,8 @@ type keyed_cmj_value = { persistent_closed_lambda: Lambda.t option; } -type hoisted_export = { - path: string list; (** Exact source-level module path segments. *) - export_name: string; - (** Flattened compiler name for the export, before JS identifier - conversion: the emitted export applies [Ext_ident.convert] to it - (a hoisted [Operator.\"+"] is stored as [Operator$+] and exported - as [Operator$$plus]), and so must any consumer that reconstructs - the JS export name. *) -} - type t = { values: keyed_cmj_value array; - hoisted_exports: hoisted_export array; pure: bool; package_spec: Js_packages_info.t; case: Ext_js_file_kind.case; @@ -81,7 +70,6 @@ type t = { val make : values:cmj_value Map_string.t -> - hoisted_exports:hoisted_export list -> effect_:effect_ -> package_spec:Js_packages_info.t -> case:Ext_js_file_kind.case -> @@ -89,8 +77,6 @@ val make : val query_by_name : t -> string -> keyed_cmj_value -val find_hoisted_export : t -> string list -> string option - val single_na : arity val from_file : string -> t diff --git a/compiler/core/js_implementation.ml b/compiler/core/js_implementation.ml index da0b5d784ed..cde54d0f663 100644 --- a/compiler/core/js_implementation.ml +++ b/compiler/core/js_implementation.ml @@ -129,7 +129,7 @@ let after_parsing_impl ppf outputprefix (ast : Parsetree.structure) = Lam_compile_env.reset (); let env = Res_compmisc.initial_env ~modulename () in Env.set_unit_name modulename; - let typedtree, coercion, _, _ = + let typedtree, coercion, finalenv, signature = Typemod.type_implementation_more ?check_exists: (if !((Js_config.current ()).force_cmi) then None else Some ()) @@ -141,13 +141,14 @@ let after_parsing_impl ppf outputprefix (ast : Parsetree.structure) = Printtyped.implementation_with_coercion typedtree_coercion; (if !((Js_config.current ()).cmi_only) then Warnings.check_fatal () else - let {Translmod.lambda; exports; hoisted_functions} = - Translmod.transl_implementation modulename typedtree_coercion + let implementation = + Translmod.transl_implementation modulename finalenv signature + typedtree_coercion in + print_if ppf (Clflags.current ()).dump_rawlambda Printlambda.lambda + implementation.lambda; let js_program = - print_if_pipe ppf (Clflags.current ()).dump_rawlambda - Printlambda.lambda lambda - |> Lam_compile_main.compile outputprefix exports hoisted_functions + Lam_compile_main.compile outputprefix implementation in if not !((Js_config.current ()).cmj_only) then Lam_compile_main.lambda_as_module js_program outputprefix); diff --git a/compiler/core/lam_compile.ml b/compiler/core/lam_compile.ml index db8d1df05d4..259078004e9 100644 --- a/compiler/core/lam_compile.ml +++ b/compiler/core/lam_compile.ml @@ -255,16 +255,10 @@ let compile output_prefix = Pfield "make" (Pfield "B" (Pfield "A" (Lglobal_module Other))) - Normal compilation does not look up the full path. It only queries the - first field, "A", and then emits the remaining fields as JS property - access: Other.A.B.make. The "A" lookup may include Submodule arity data, - but it does not say whether A.B.make has a separate root-level export. - - Hoisted functions need that extra question. For them, query the separate - hoisted-values table with an unambiguous key for source path A.B.make. If - present, the table returns the root-level JS export name, for example - A$B$make. Normal export metadata still lives in the regular .cmj values - table. *) + Every nested [make] is also exported under a flat name (see + [Translmod.implementation]), so it is read as Other.A$B$make rather + than through the module objects. Other reads query only the first field, + "A", and emit the remaining fields as JS property access. *) let rec extract_field_path segments primitive args = match (primitive, args) with | Lambda.Pfield (_, Fld_module {name}), [Lambda.Lprim {primitive; args; _}] @@ -274,12 +268,11 @@ let compile output_prefix = Some (id, name :: segments) | _ -> None in - let hoisted_external_field_name primitive args = + let flat_make_field_name primitive args = match extract_field_path [] primitive args with - | Some (id, (_ :: _ :: _ as segments)) -> - Lam_compile_env.find_hoisted_external_export id segments - |> Option.map (fun name -> (id, name)) - | Some (_, ([] | [_])) | None -> None + | Some (id, segments) -> + Translmod.flat_make_name segments |> Option.map (fun name -> (id, name)) + | None -> None in let rec compile_external_field (* Like [List.empty]*) (lamba_cxt : Lam_compile_context.t) (id : Ident.t) name : Js_output.t = @@ -1633,11 +1626,11 @@ let compile output_prefix = in match prim_info with | {primitive = Pfield (_, Fld_module _); _} -> ( - match hoisted_external_field_name prim_info.primitive prim_info.args with - | Some (id, hoisted_name) -> + match flat_make_field_name prim_info.primitive prim_info.args with + | Some (id, flat_name) -> Js_output.output_of_expression lambda_cxt.continuation ~no_effects:no_effects_const - (E.ml_var_dot id hoisted_name) + (E.ml_var_dot id flat_name) | None -> ( match prim_info with | {primitive = Pfield (_, fld_info); args = [Lglobal_module id]; _} -> ( diff --git a/compiler/core/lam_compile_env.ml b/compiler/core/lam_compile_env.ml index a2ac9610401..b67e68c38f8 100644 --- a/compiler/core/lam_compile_env.ml +++ b/compiler/core/lam_compile_env.ml @@ -106,11 +106,6 @@ let query_external_id_info ?(dynamic_import = false) (module_id : Ident.t) let cmj_table = cmj_table_of_module_id ~dynamic_import module_id in Js_cmj_format.query_by_name cmj_table name -let find_hoisted_external_export ?(dynamic_import = false) (module_id : Ident.t) - (path : string list) : string option = - let cmj_table = cmj_table_of_module_id ~dynamic_import module_id in - Js_cmj_format.find_hoisted_export cmj_table path - let get_package_path_from_cmj (id : Lam_module_ident.t) : string * Js_packages_info.t * Ext_js_file_kind.case = let cmj_load_info = diff --git a/compiler/core/lam_compile_env.mli b/compiler/core/lam_compile_env.mli index 5fd7558b0d9..5ee697dc442 100644 --- a/compiler/core/lam_compile_env.mli +++ b/compiler/core/lam_compile_env.mli @@ -75,9 +75,6 @@ val query_external_id_info : will raise if not found *) -val find_hoisted_external_export : - ?dynamic_import:bool -> Ident.t -> string list -> string option - val is_pure_module : Lam_module_ident.t -> bool val get_package_path_from_cmj : diff --git a/compiler/core/lam_compile_main.ml b/compiler/core/lam_compile_main.ml index cada1a101d8..e24b24b9cd7 100644 --- a/compiler/core/lam_compile_main.ml +++ b/compiler/core/lam_compile_main.ml @@ -101,12 +101,15 @@ let no_side_effects (rest : Lam_group.t list) : string option = if not @@ Lam_analysis.no_side_effects lam then Some "" else None (* TODO :*)) -(* Materialize JS-hoisted values as root-level aliases and exports. The source - value still lives at its normal module path, but downstream tools can import - the flat name directly when the .cmj metadata marks it as hoisted. *) -let js_hoisted_aliases (export_ids : Ident.t list) - (hoisted : Lambda.hoisted_function list) (groups : Lam_group.t list) = - if hoisted = [] then [] +(* Export every nested [make] of the final signature under its flat name, see + [Translmod.implementation]. When the module field holds a toplevel + binding, the alias names that binding ([let A$B$make = make]), which + bundlers can drop when it is unused; otherwise it reads the value through + the module objects. The paths carry the runtime field positions, which a + coerced module block shares with its signature. *) +let flat_make_aliases (export_ids : Ident.t list) + (paths : Translmod.flat_make_path list) (groups : Lam_group.t list) = + if paths = [] then [] else let group_map = Ext_list.fold_left groups Map_ident.empty (fun group_map group -> @@ -120,118 +123,79 @@ let js_hoisted_aliases (export_ids : Ident.t list) let rec access loc base fields = match fields with | [] -> base - | (pos, name) :: fields -> + | {Translmod.pos; name} :: fields -> access loc (Lambda.prim ~primitive:(Lambda.Pfield (pos, Lambda.Fld_module {name})) ~args:[base] loc) fields in - let rec resolve_binding seen = function - | Lambda.Lvar id as lam -> ( - if Set_ident.mem id seen then (lam, Some id) - else - match Map_ident.find_opt id group_map with - | Some - ((Lambda.Lvar _ | Lambda.Lprim {primitive = Lambda.Pfield _; _}) - as alias) -> - resolve_binding (Set_ident.add id seen) alias - | Some resolved -> (resolved, Some id) - | None -> (lam, Some id)) - | Lambda.Lprim {primitive = Lambda.Pfield (pos, _); args = [base]} as lam - -> ( - match fst (resolve_binding seen base) with - | Lambda.Lprim {primitive = Lambda.Pmakeblock (Blk_module _); args} -> ( - match List.nth_opt args pos with - | Some field -> resolve_binding seen field - | None -> (lam, None)) - | _ -> (lam, None)) - | lam -> (lam, None) + (* The fields of the module block [lam] evaluates to, if it is known. *) + let rec block_fields seen (lam : Lambda.t) = + match lam with + | Lvar id when not (Set_ident.mem id seen) -> ( + match Map_ident.find_opt id group_map with + | Some lam -> block_fields (Set_ident.add id seen) lam + | None -> None) + | Lprim {primitive = Pmakeblock (Blk_module names); args} -> + Some (names, args) + | Lprim {primitive = Pfield (pos, Fld_module {name}); args = [base]} -> ( + match field seen base {Translmod.pos; name} with + | Some lam -> block_fields seen lam + | None -> None) + | _ -> None + and field seen lam {Translmod.pos; name} = + match block_fields seen lam with + | Some (names, args) when List.nth_opt names pos = Some name -> + List.nth_opt args pos + | Some _ | None -> None in - let resolve seen lam = fst (resolve_binding seen lam) in - let rec find_field name pos fields args = - match (fields, args) with - | field :: _, arg :: _ when field = name -> Some (pos, arg) - | _ :: fields, _ :: args -> find_field name (pos + 1) fields args - | [], [] -> None - | _ -> invalid_arg "find_field" - in - let rec find_path lam fields positions = + let rec target lam fields = match fields with - | [] -> - let target, binding_id = resolve_binding Set_ident.empty lam in - Some (List.rev positions, binding_id, target) - | field :: fields -> ( - match resolve Set_ident.empty lam with - | Lambda.Lprim {primitive = Lambda.Pmakeblock (Blk_module names); args} - -> ( - match find_field field 0 names args with - | Some (pos, arg) -> find_path arg fields ((pos, field) :: positions) - | None -> None) - | _ -> None) + | [] -> Some lam + | step :: fields -> ( + match field Set_ident.empty lam step with + | Some lam -> target lam fields + | None -> None) in let exported_modules = Ext_list.fold_left export_ids Map_string.empty (fun modules id -> Map_string.add id.Ident.name id modules) in + (* Only export names can clash: the printer renames other bindings. *) let occupied_names = - Ext_list.fold_left groups Set_string.empty (fun occupied group -> - match group with - | Single (_, id, _) -> - Set_string.add (Ext_ident.convert id.Ident.name) occupied - | Recursive bindings -> - Ext_list.fold_left bindings occupied (fun occupied (id, _) -> - Set_string.add (Ext_ident.convert id.Ident.name) occupied) - | Nop _ -> occupied) + Ext_list.fold_left export_ids Set_string.empty (fun occupied id -> + Set_string.add (Ext_ident.convert id.Ident.name) occupied) in - fst - (Ext_list.fold_left hoisted ([], occupied_names) - (fun ((aliases, occupied_names) as state) hoisted -> - let {Lambda.binding; path; loc} = hoisted in - let missing_path () = - Location.prerr_warning loc - (Warnings.Misplaced_attribute "res.hoistedFunction"); - state - in + let loc = Location.in_file (Location.get_input_name ()) in + List.rev @@ fst + @@ Ext_list.fold_left paths ([], occupied_names) + (fun (aliases, occupied_names) path -> + let names = List.map (fun {Translmod.name} -> name) path in + let name = Translmod.flat_export_name names in + let js_name = Ext_ident.convert name in + if Set_string.mem js_name occupied_names then + Location.raise_errorf ~loc + "Cannot export `%s` as `%s` because that name is already \ + exported." + (String.concat "." names) name; match path with - | top :: fields -> ( + | {name = top} :: fields -> ( match Map_string.find_opt top exported_modules with - | Some top_id -> ( - match Map_ident.find_opt top_id group_map with - | Some lam -> ( - match find_path lam fields [] with - | Some (access_path, Some target_id, target) - when Ident.same binding target_id -> - let name = - path - |> List.map Ext_ident.unwrap_uppercase_exotic - |> String.concat "$" - in - let js_name = Ext_ident.convert name in - if Set_string.mem js_name occupied_names then - let error_loc = - match target with - | Lambda.Lfunction {loc} -> loc - | _ -> loc - in - Location.raise_errorf ~loc:error_loc - "Cannot hoist this function as `%s` because that name \ - is already used by a top-level binding." - name - else - let alias_id = Ident.create name in - let alias = access loc (Lambda.var top_id) access_path in - ( ( Lam_group.Single (Alias, alias_id, alias), - alias_id, - alias, - path, - name ) - :: aliases, - Set_string.add js_name occupied_names ) - | Some _ | None -> missing_path ()) - | None -> missing_path ()) - | None -> missing_path ()) - | [] -> missing_path ())) + | Some top_id -> + let alias = + match target (Lambda.var top_id) fields with + | Some (Lvar id) when Map_ident.mem id group_map -> + Lambda.var id + | Some _ | None -> access loc (Lambda.var top_id) fields + in + ( (Ident.create name, alias) :: aliases, + Set_string.add js_name occupied_names ) + | None -> + Location.raise_errorf ~loc + "Internal error: no export for module `%s` of `%s`." top + (String.concat "." names)) + | [] -> assert false) (* The other compilation units this one refers to. Conversion used to drop [Lglobal_module] references and have module analysis add them back (see @@ -254,7 +218,9 @@ let required_modules (lam : Lambda.t) : unit Lam_module_ident.Hash_set.t = collect lam; required -let compile (output_prefix : string) export_idents hoisted (lam : Lambda.t) = +let compile (output_prefix : string) + ({lambda = lam; exports = export_idents; flat_make_paths} : + Translmod.implementation) = let debug_ir = !((Js_config.current ()).debug_ir) in let diagnostics = if debug_ir then Some (Ir_diagnostics.create ~output_prefix) else None @@ -343,32 +309,24 @@ let compile (output_prefix : string) export_idents hoisted (lam : Lambda.t) = let maybe_pure = no_side_effects groups in (* Add the generated alias groups before JS lowering so regular export printing, tree shaking, and .cmj metadata all see the flat runtime value. *) - let hoisted_aliases = js_hoisted_aliases meta.exports hoisted groups in - let hoisted_groups, hoisted_exports, hoisted_export_map, hoisted_metadata = - Ext_list.fold_left hoisted_aliases ([], [], Map_ident.empty, []) - (fun - (groups, exports, export_map, hoisted_metadata) - (group, id, lam, path, name) - -> - ( group :: groups, - id :: exports, - Map_ident.add id lam export_map, - {Js_cmj_format.path; export_name = name} :: hoisted_metadata )) + let flat_aliases = flat_make_aliases meta.exports flat_make_paths groups in + let flat_exports = List.map fst flat_aliases in + let groups = + groups + @ List.map (fun (id, lam) -> Lam_group.Single (Alias, id, lam)) flat_aliases in - let groups = groups @ List.rev hoisted_groups in let meta = { meta with - exports = meta.exports @ List.rev hoisted_exports; + exports = meta.exports @ flat_exports; export_idents = - Ext_list.fold_left hoisted_exports meta.export_idents (fun acc id -> + Ext_list.fold_left flat_exports meta.export_idents (fun acc id -> Set_ident.add id acc); } in let export_map = - Map_ident.fold - (fun id lam acc -> Map_ident.add id lam acc) - hoisted_export_map coerced_input.export_map + Ext_list.fold_left flat_aliases coerced_input.export_map + (fun acc (id, lam) -> Map_ident.add id lam acc) in let () = if debug_ir then @@ -426,7 +384,7 @@ let compile (output_prefix : string) export_idents hoisted (lam : Lambda.t) = Lam_stats_export.get_dependent_module_effect maybe_pure external_module_ids in let v : Js_cmj_format.t = - Lam_stats_export.export_to_cmj meta effect_ export_map hoisted_metadata + Lam_stats_export.export_to_cmj meta effect_ export_map (Ext_filename.case output_prefix) in if not !((Clflags.current ()).dont_write_files) then diff --git a/compiler/core/lam_compile_main.mli b/compiler/core/lam_compile_main.mli index c62ff0dca4e..29568f5e113 100644 --- a/compiler/core/lam_compile_main.mli +++ b/compiler/core/lam_compile_main.mli @@ -27,12 +27,7 @@ (** Compile and register the hook of function to compile a lambda to JS IR *) -val compile : - string -> - Ident.t list -> - Lambda.hoisted_function list -> - Lambda.t -> - J.deps_program +val compile : string -> Translmod.implementation -> J.deps_program (** For toplevel, [filename] is [""] which is the same as {!Env.get_unit_name ()} *) diff --git a/compiler/core/lam_compile_primitive.ml b/compiler/core/lam_compile_primitive.ml index 13330638622..e0b081d3d66 100644 --- a/compiler/core/lam_compile_primitive.ml +++ b/compiler/core/lam_compile_primitive.ml @@ -120,21 +120,15 @@ let translate output_prefix loc (cxt : Lam_compile_context.t) Lam_compile_env.register_ml_module ~dynamic_import:true module_; let import = import_of_path (import_path oid) in (* the single source of truth for ML export names: a binding named - [case] is exported as [$$case], and a hoisted [Operator.\"+"] whose - cmj metadata stores the raw flattened name [Operator$+] is - exported as [Operator$$plus] *) + [case] is exported as [$$case] *) let ml_export_name = Js_dump_import_export.js_export_name in match path with | [] -> import | [name] -> wrap_then import (ml_export_name name) | _ :: _ :: _ -> ( - (* a nested path is importable when the target is a hoisted - root-level export; the cmj knows *) - match - Lam_compile_env.find_hoisted_external_export ~dynamic_import:true - module_ path - with - | Some hoisted_name -> wrap_then import (ml_export_name hoisted_name) + (* a nested [make] is importable through its flat export *) + match Translmod.flat_make_name path with + | Some name -> wrap_then import (ml_export_name name) | None -> Location.raise_errorf ~loc "Invalid argument: Dynamic import requires a module or module \ diff --git a/compiler/core/lam_stats_export.ml b/compiler/core/lam_stats_export.ml index b47424a0235..e3051f300f8 100644 --- a/compiler/core/lam_stats_export.ml +++ b/compiler/core/lam_stats_export.ml @@ -130,11 +130,11 @@ let get_dependent_module_effect (maybe_pure : string option) ]} TODO: check that we don't do this in browser environment *) -let export_to_cmj (meta : Lam_stats.t) effect_ export_map hoisted_exports case : - Js_cmj_format.t = +let export_to_cmj (meta : Lam_stats.t) effect_ export_map case : Js_cmj_format.t + = let values = values_of_export meta export_map in - Js_cmj_format.make ~values ~hoisted_exports ~effect_ + Js_cmj_format.make ~values ~effect_ ~package_spec:(Js_packages_state.get_packages_info ()) ~case (* FIXME: make sure [-o] would not change its case diff --git a/compiler/core/lam_stats_export.mli b/compiler/core/lam_stats_export.mli index ba0238adb5f..8e42a4c8d30 100644 --- a/compiler/core/lam_stats_export.mli +++ b/compiler/core/lam_stats_export.mli @@ -29,6 +29,5 @@ val export_to_cmj : Lam_stats.t -> Js_cmj_format.effect_ -> Lambda.t Map_ident.t -> - Js_cmj_format.hoisted_export list -> Ext_js_file_kind.case -> Js_cmj_format.t diff --git a/compiler/ext/config.ml b/compiler/ext/config.ml index 8b9658a611b..bc248f43e05 100644 --- a/compiler/ext/config.ml +++ b/compiler/ext/config.ml @@ -1,4 +1,4 @@ -let cmi_magic_number = "Caml1999I038" +let cmi_magic_number = "Caml1999I039" (* Magic numbers for marshaled values of the *current* parsetree, whose layout changes across compiler versions. *) diff --git a/compiler/frontend/bs_builtin_ppx.ml b/compiler/frontend/bs_builtin_ppx.ml index d28fcc51a1b..fbbf47ad832 100644 --- a/compiler/frontend/bs_builtin_ppx.ml +++ b/compiler/frontend/bs_builtin_ppx.ml @@ -60,20 +60,11 @@ type mapper = Ast_mapper.mapper let default_mapper = Ast_mapper.default_mapper -let mark_hoisted_function_attributes (bindings : Parsetree.value_binding list) = - Ext_list.iter bindings (fun {pvb_attributes} -> - Ext_list.iter pvb_attributes (fun (({txt}, _) as attr) -> - if txt = "res.hoistedFunction" then - Used_attributes.mark_used_attribute attr)) - (* [Ast_mapper.default_mapper.expr], with non-recursive binding groups routed through tuple/module-record pattern flattening ([let rec] groups only admit variable patterns, so they map per binding). Every fallback in [expr_mapper] funnels through here, so the flattening applies uniformly. *) let default_expr_mapper (self : mapper) (e : Parsetree.expression) = - (match e.pexp_desc with - | Pexp_let (_, bindings, _) -> mark_hoisted_function_attributes bindings - | _ -> ()); match e.pexp_desc with | Pexp_let (Nonrecursive, vbs, body) -> { @@ -559,9 +550,6 @@ let signature_item_mapper (self : mapper) (sigi : Parsetree.signature_item) : let structure_item_mapper (self : mapper) (str : Parsetree.structure_item) : Parsetree.structure_item = - (match str.pstr_desc with - | Pstr_value (_, bindings) -> mark_hoisted_function_attributes bindings - | _ -> ()); match str.pstr_desc with | Pstr_value (_, vbs) when List.exists diff --git a/compiler/jsoo/jsoo_playground_main.ml b/compiler/jsoo/jsoo_playground_main.ml index f19f783442c..799f36ccb4b 100644 --- a/compiler/jsoo/jsoo_playground_main.ml +++ b/compiler/jsoo/jsoo_playground_main.ml @@ -658,21 +658,16 @@ module Compile = struct (* default *) let ast = impl str in let ast = Ppx_entry.rewrite_implementation ast in - let typed_tree = - let a, b, _, signature = - Typemod.type_implementation_more modulename modulename modulename env - ast - in - (* finalenv := c ; *) - types_signature := signature; - (a, b) - in - let {Translmod.lambda; exports; hoisted_functions} = - Translmod.transl_implementation modulename typed_tree + let structure, coercion, finalenv, signature = + Typemod.type_implementation_more modulename modulename modulename env + ast in - let lambda_output = - Lam_compile_main.compile "" exports hoisted_functions lambda + types_signature := signature; + let typed_tree = (structure, coercion) in + let ({Translmod.lambda} as implementation) = + Translmod.transl_implementation modulename finalenv signature typed_tree in + let lambda_output = Lam_compile_main.compile "" implementation in let js_code, source_map = render_javascript ~module_system ~filename ~source:str ~source_map_mode ~source_map_sources_content ~source_map_root lambda_output diff --git a/compiler/ml/lambda.ml b/compiler/ml/lambda.ml index 57760bdf61f..357e6310e98 100644 --- a/compiler/ml/lambda.ml +++ b/compiler/ml/lambda.ml @@ -13,8 +13,6 @@ (* *) (**************************************************************************) -type hoisted_function = {binding: Ident.t; path: string list; loc: Location.t} - type tag_info = | Blk_constructor of { name: string; diff --git a/compiler/ml/lambda.mli b/compiler/ml/lambda.mli index 571568407e8..1c4d19856c0 100644 --- a/compiler/ml/lambda.mli +++ b/compiler/ml/lambda.mli @@ -17,8 +17,6 @@ open Asttypes -type hoisted_function = {binding: Ident.t; path: string list; loc: Location.t} - type tag_info = | Blk_constructor of { name: string; diff --git a/compiler/ml/translattribute.ml b/compiler/ml/translattribute.ml index ebe68560b9b..bceb8f54b28 100644 --- a/compiler/ml/translattribute.ml +++ b/compiler/ml/translattribute.ml @@ -28,20 +28,6 @@ let find_attribute p (attributes : t list) = Location.prerr_warning loc (Warnings.Duplicated_attribute txt); None -let get_empty_attribute name attributes = - match - find_attribute - (fun (({txt}, _) : Parsetree.attribute) -> txt = name) - attributes - with - | None -> None - | Some ({loc}, Parsetree.PStr []) -> Some loc - | Some ({loc}, _) -> - Location.prerr_warning loc - (Warnings.Attribute_payload - (name, "This attribute does not accept a payload")); - None - let parse_inline_attribute (attr : t option) : Lambda.inline_attribute = match attr with | None -> Default_inline diff --git a/compiler/ml/translattribute.mli b/compiler/ml/translattribute.mli index 0ece4887635..d34101f5ee7 100644 --- a/compiler/ml/translattribute.mli +++ b/compiler/ml/translattribute.mli @@ -22,5 +22,3 @@ val add_inline_attribute : Lambda.t -> Location.t -> Parsetree.attributes -> Lambda.t val get_inline_attribute : Parsetree.attributes -> Lambda.inline_attribute - -val get_empty_attribute : string -> Parsetree.attributes -> Location.t option diff --git a/compiler/ml/translcore.ml b/compiler/ml/translcore.ml index 80618a82a77..2d51884f4b5 100644 --- a/compiler/ml/translcore.ml +++ b/compiler/ml/translcore.ml @@ -949,34 +949,6 @@ let extract_directive_for_fn exp = if txt = "directive" then Ast_payload.semantic_string_of_payload payload else None) -let hoisted_function_attr_name = "res.hoistedFunction" - -let find_js_hoisted_attr attrs = - Translattribute.get_empty_attribute hoisted_function_attr_name attrs - -(* A value binding's source attributes are not carried all the way to JS - emission. Record the binding and its source path here so later compiler - stages can add the flat JS export and matching .cmj metadata. *) -let mark_js_hoisted_pattern ~js_hoist attrs pat lam = - match find_js_hoisted_attr attrs with - | None -> () - | Some loc -> ( - match lam with - | Lfunction _ -> ( - match pat.pat_desc with - | Tpat_var (id, _) | Tpat_alias ({pat_desc = Tpat_any}, id, _) -> ( - match js_hoist with - | Some register -> register id loc - | None -> - Location.prerr_warning loc - (Warnings.Misplaced_attribute hoisted_function_attr_name)) - | _ -> - Location.prerr_warning loc - (Warnings.Misplaced_attribute hoisted_function_attr_name)) - | _ -> - Location.prerr_warning loc - (Warnings.Misplaced_attribute hoisted_function_attr_name)) - (* JSX preserve mode: a call of a JSX external as the JSX PPX produces it, which [transl_jsx_element] turns into [Pjsx]. The JSX module's names ([jsx], [jsxs], [jsxKeyed], [jsxsKeyed], [jsxFragment]) are fixed by the @@ -1196,7 +1168,7 @@ and transl_exp0 (e : Typedtree.expression) : Lambda.t = Transl_path.transl_value_path ~loc:e.exp_loc e.exp_env path | Texp_constant cst -> const (const_of_typed cst) | Texp_let (rec_flag, pat_expr_list, body) -> - transl_let ~js_hoist:None rec_flag pat_expr_list (transl_exp body) + transl_let rec_flag pat_expr_list (transl_exp body) | Texp_function {params = fparams; body; async} -> let directive = extract_directive_for_fn e in let params, lbody, return_unit = transl_function e.exp_loc fparams body in @@ -1629,7 +1601,7 @@ and transl_function loc (params : function_param list) body = fp_partial, return_unit ) -and transl_let ~js_hoist rec_flag pat_expr_list body = +and transl_let rec_flag pat_expr_list body = match rec_flag with | Nonrecursive -> let rec transl = function @@ -1640,7 +1612,6 @@ and transl_let ~js_hoist rec_flag pat_expr_list body = transl_exp expr) in let lam = Translattribute.add_inline_attribute lam vb_loc attr in - mark_js_hoisted_pattern ~js_hoist attr pat lam; Matching.for_let pat.pat_loc lam pat (transl rem) in transl pat_expr_list @@ -1660,7 +1631,6 @@ and transl_let ~js_hoist rec_flag pat_expr_list body = (fun () -> transl_exp expr) in let lam = Translattribute.add_inline_attribute lam vb_loc vb_attributes in - mark_js_hoisted_pattern ~js_hoist vb_attributes pat lam; (id, lam) in Lambda_scc.bind_rec (Ext_list.map pat_expr_list transl_case) body diff --git a/compiler/ml/translcore.mli b/compiler/ml/translcore.mli index 000953852fb..e55ce214a88 100644 --- a/compiler/ml/translcore.mli +++ b/compiler/ml/translcore.mli @@ -19,11 +19,7 @@ val transl_exp : Typedtree.expression -> Lambda.t val transl_let : - js_hoist:(Ident.t -> Location.t -> unit) option -> - Asttypes.rec_flag -> - Typedtree.value_binding list -> - Lambda.t -> - Lambda.t + Asttypes.rec_flag -> Typedtree.value_binding list -> Lambda.t -> Lambda.t val transl_primitive : Location.t -> diff --git a/compiler/ml/translmod.ml b/compiler/ml/translmod.ml index 9bf1b0e0fa7..02d69bf90be 100644 --- a/compiler/ml/translmod.ml +++ b/compiler/ml/translmod.ml @@ -45,18 +45,6 @@ let is_top (rootpath : Path.t option) = | Some (Pident _) -> true | _ -> false -let module_path = function - | Some path -> ( - match Path.flatten path with - | `Ok (_, segments) -> Some segments - | `Contains_apply -> None) - | None -> None - -let exportable_module_path rootpath = - match module_path rootpath with - | Some (_ :: _ as path) -> Some path - | _ -> None - let functor_path path param : Path.t option = match path with | None -> None @@ -228,23 +216,10 @@ let get_functor_params mexp coercion root_path = | _ -> assert false (* Translation can overlap on compiler domains. Each request owns the export - and hoisting accumulators until [transl_implementation] returns them. *) + accumulator until [transl_implementation] returns it. *) let export_identifiers_key = Request_local.new_key (fun () -> ref []) -let js_hoisted_key = Request_local.new_key (fun () -> ref []) let export_identifiers () : Ident.t list ref = Domain.DLS.get export_identifiers_key -let js_hoisted () : Lambda.hoisted_function list ref = - Domain.DLS.get js_hoisted_key - -let js_hoist_handler rootpath = - match exportable_module_path rootpath with - | None -> None - | Some path -> - Some - (fun id loc -> - js_hoisted () := - {Lambda.binding = id; path = path @ [id.Ident.name]; loc} - :: !(js_hoisted ())) let rec compile_functor mexp coercion root_path loc = let functor_param, body, body_path, res_coercion, inline_attribute = @@ -387,10 +362,7 @@ and transl_structure loc fields cc rootpath final_env = function | _ -> if not (Parmatch.irrefutable vb_pat) then raise (Error (vb_pat.pat_loc, Fragile_pattern_in_toplevel))); - ( Translcore.transl_let - ~js_hoist:(js_hoist_handler rootpath) - rec_flag pat_expr_list body, - size ) + (Translcore.transl_let rec_flag pat_expr_list body, size) | Tstr_typext tyext -> let ids = List.map (fun ext -> ext.ext_id) tyext.tyext_constructors in let body, size = @@ -411,10 +383,9 @@ and transl_structure loc fields cc rootpath final_env = function size ) | Tstr_module mb as s -> let id = mb.mb_id in - let hidden = Typemod.rescript_hide s in let body, size = transl_structure loc - (if hidden then fields else id :: fields) + (if Typemod.rescript_hide s then fields else id :: fields) cc rootpath final_env rem in let module_body = @@ -471,23 +442,71 @@ let _ = Translcore.transl_module := transl_module (* Compile an implementation *) +(* Nested [make] values are also exported under a flat name such as + [A$B$make]: React Server Components can only pass a client module's + top-level exports to the client, so [Lib.A.B.make] must not be reached + through the module object. Producer and consumer derive these paths from + the signature alone, so consumers are rebuilt exactly when the set + changes. *) +type flat_make_step = {pos: int; name: string} + +type flat_make_path = flat_make_step list + +let flat_make_paths env (sg : Types.signature) : flat_make_path list = + let rec of_signature env rev_path sg acc = + let env = Env.add_signature sg env in + fst + (List.fold_left + (fun (acc, pos) (item : Types.signature_item) -> + match item with + | Sig_value (_, {val_kind = Val_prim _}) -> (acc, pos) + | Sig_value (id, _) -> + let acc = + if rev_path <> [] && Ident.name id = "make" then + List.rev ({pos; name = "make"} :: rev_path) :: acc + else acc + in + (acc, pos + 1) + | Sig_typext _ -> (acc, pos + 1) + | Sig_module (id, {md_type}, _) -> + let acc = + match Mtype.scrape env md_type with + | Mty_signature sg -> + of_signature env + ({pos; name = Ident.name id} :: rev_path) + sg acc + | Mty_ident _ | Mty_alias _ | Mty_functor _ -> acc + in + (acc, pos + 1) + | Sig_type _ | Sig_modtype _ -> (acc, pos)) + (acc, 0) sg) + in + List.rev (of_signature env [] sg []) + type implementation = { lambda: Lambda.t; exports: Ident.t list; - hoisted_functions: Lambda.hoisted_function list; + flat_make_paths: flat_make_path list; } -let transl_implementation module_name (str, cc) = +let transl_implementation module_name final_env signature (str, cc) = export_identifiers () := []; - js_hoisted () := []; let module_id = Ident.create_persistent module_name in let body, _ = transl_struct Location.none [] cc (global_path module_id) str in { lambda = body; exports = !(export_identifiers ()); - hoisted_functions = !(js_hoisted ()); + flat_make_paths = flat_make_paths final_env signature; } +let flat_export_name path = + path |> List.map Ext_ident.unwrap_uppercase_exotic |> String.concat "$" + +let flat_make_name path = + match path with + | _ :: _ :: _ when Ext_list.last path = "make" -> Some (flat_export_name path) + | _ -> None + (* Build the list of value identifiers defined by a toplevel structure (excluding primitive declarations). *) diff --git a/compiler/ml/translmod.mli b/compiler/ml/translmod.mli index 471a46f4ca8..b2b61ba0295 100644 --- a/compiler/ml/translmod.mli +++ b/compiler/ml/translmod.mli @@ -16,14 +16,33 @@ (* Translation from typed abstract syntax to lambda terms, for the module language *) +type flat_make_step = {pos: int; name: string} +(** A module field on the way to a nested [make]: its runtime position + (counted as in [Env]) and its source name. *) + +type flat_make_path = flat_make_step list + type implementation = { lambda: Lambda.t; exports: Ident.t list; - hoisted_functions: Lambda.hoisted_function list; + flat_make_paths: flat_make_path list; + (** The nested [make] values of the final signature, which are also + exported under [flat_export_name] of their path. *) } val transl_implementation : - string -> Typedtree.structure * Typedtree.module_coercion -> implementation + string -> + Env.t -> + Types.signature -> + Typedtree.structure * Typedtree.module_coercion -> + implementation +(** [transl_implementation module_name final_env signature (str, cc)] *) + +val flat_export_name : string list -> string + +val flat_make_name : string list -> string option +(** The flat export a read of this source path from another module goes + through: [Some "A$B$make"] for [A.B.make], [None] for other paths. *) type error (* exception Error of Location.t * error *) diff --git a/tests/build_tests/react_ppx/src/abstract_component_test.res.js b/tests/build_tests/react_ppx/src/abstract_component_test.res.js index 8863c77600f..b280eb432ac 100644 --- a/tests/build_tests/react_ppx/src/abstract_component_test.res.js +++ b/tests/build_tests/react_ppx/src/abstract_component_test.res.js @@ -24,8 +24,14 @@ let GenericRenderProp = { make: Abstract_component_test$GenericRenderProp }; +let PolyVariantLowerBound$make = Abstract_component_test$PolyVariantLowerBound; + +let GenericRenderProp$make = Abstract_component_test$GenericRenderProp; + export { PolyVariantLowerBound, GenericRenderProp, + PolyVariantLowerBound$make, + GenericRenderProp$make, } /* No side effect */ diff --git a/tests/build_tests/react_ppx/src/gpr_3987_test.res.js b/tests/build_tests/react_ppx/src/gpr_3987_test.res.js index 30bedfb06b7..d2f5ae6b052 100644 --- a/tests/build_tests/react_ppx/src/gpr_3987_test.res.js +++ b/tests/build_tests/react_ppx/src/gpr_3987_test.res.js @@ -55,10 +55,19 @@ JsxRuntime.jsx(Gpr_3987_test$Gpr3987ReproError, { onChange: (param, param$1) => {} }); +let Gpr3987ReproOk$make = Gpr_3987_test$Gpr3987ReproOk; + +let Gpr3987ReproOk2$make = Gpr_3987_test$Gpr3987ReproOk2; + +let Gpr3987ReproError$make = Gpr_3987_test$Gpr3987ReproError; + export { makeContainer, Gpr3987ReproOk, Gpr3987ReproOk2, Gpr3987ReproError, + Gpr3987ReproOk$make, + Gpr3987ReproOk2$make, + Gpr3987ReproError$make, } /* Not a pure module */ diff --git a/tests/build_tests/react_ppx/src/issue_7917_test.res.js b/tests/build_tests/react_ppx/src/issue_7917_test.res.js index 9df85100b95..66e06ff0bf5 100644 --- a/tests/build_tests/react_ppx/src/issue_7917_test.res.js +++ b/tests/build_tests/react_ppx/src/issue_7917_test.res.js @@ -18,8 +18,11 @@ function Issue_7917_test(props) { let make = Issue_7917_test; +let M$make = Issue_7917_test$M; + export { M, make, + M$make, } /* react/jsx-runtime Not a pure module */ diff --git a/tests/build_tests/react_ppx/src/nested_component_consumer.res b/tests/build_tests/react_ppx/src/nested_component_consumer.res new file mode 100644 index 00000000000..4a95dfa77a5 --- /dev/null +++ b/tests/build_tests/react_ppx/src/nested_component_consumer.res @@ -0,0 +1,8 @@ +@react.component +let make = () => + + + {React.null} + {React.null} + + diff --git a/tests/build_tests/react_ppx/src/nested_component_consumer.res.js b/tests/build_tests/react_ppx/src/nested_component_consumer.res.js new file mode 100644 index 00000000000..701cf60f8f7 --- /dev/null +++ b/tests/build_tests/react_ppx/src/nested_component_consumer.res.js @@ -0,0 +1,28 @@ +// Generated by ReScript, PLEASE EDIT WITH CARE + +import * as JsxRuntime from "react/jsx-runtime"; +import * as Nested_component_producer$ReactPpxTests from "./nested_component_producer.res.js"; + +function Nested_component_consumer(props) { + return JsxRuntime.jsxs(Nested_component_producer$ReactPpxTests.Provider$make, { + children: [ + JsxRuntime.jsx(Nested_component_producer$ReactPpxTests.Trigger$make, { + label: "x" + }), + JsxRuntime.jsx(Nested_component_producer$ReactPpxTests.Menu$Item$make, { + children: null + }), + JsxRuntime.jsx(Nested_component_producer$ReactPpxTests.Ext$make, { + children: null + }), + JsxRuntime.jsx(Nested_component_producer$ReactPpxTests.RecA$make, {}) + ] + }); +} + +let make = Nested_component_consumer; + +export { + make, +} +/* react/jsx-runtime Not a pure module */ diff --git a/tests/build_tests/react_ppx/src/nested_component_producer.res b/tests/build_tests/react_ppx/src/nested_component_producer.res new file mode 100644 index 00000000000..bbd5762d0ed --- /dev/null +++ b/tests/build_tests/react_ppx/src/nested_component_producer.res @@ -0,0 +1,44 @@ +module Provider = { + @react.component + let make = (~children: React.element) => children +} + +module Trigger = { + @react.component + let make = (~label: string) => React.string(label) + let make = React.memo(make) +} + +module Menu = { + module Item = { + @react.component + let make = (~children: React.element) => children + } +} + +module Ext = { + @react.component @module("./ext.js") + external make: (~children: React.element) => React.element = "default" +} + +module Hidden = { + @react.component + let make = () => React.null +} + +module rec RecA: { + @react.component + let make: unit => React.element +} = { + @react.component + let make = () => +} +and RecB: { + @react.component + let make: unit => React.element +} = { + @react.component + let make = () => React.null +} + +let hidden = diff --git a/tests/build_tests/react_ppx/src/nested_component_producer.res.js b/tests/build_tests/react_ppx/src/nested_component_producer.res.js new file mode 100644 index 00000000000..8c595a5d313 --- /dev/null +++ b/tests/build_tests/react_ppx/src/nested_component_producer.res.js @@ -0,0 +1,92 @@ +// Generated by ReScript, PLEASE EDIT WITH CARE + +import * as React from "react"; +import ExtJs from "./ext.js"; +import * as JsxRuntime from "react/jsx-runtime"; + +function Nested_component_producer$Provider(props) { + return props.children; +} + +let Provider = { + make: Nested_component_producer$Provider +}; + +function Nested_component_producer$Trigger(props) { + return props.label; +} + +let make = React.memo(Nested_component_producer$Trigger); + +let Trigger = { + make: make +}; + +function Nested_component_producer$Menu$Item(props) { + return props.children; +} + +let Item = { + make: Nested_component_producer$Menu$Item +}; + +let Menu = { + Item: Item +}; + +let make$1 = ExtJs; + +let Ext = { + make: make$1 +}; + +function Nested_component_producer$Hidden(props) { + return null; +} + +function Nested_component_producer$RecB(props) { + return null; +} + +let RecB = { + make: Nested_component_producer$RecB +}; + +function Nested_component_producer$RecA(props) { + return JsxRuntime.jsx(Nested_component_producer$RecB, {}); +} + +let RecA = { + make: Nested_component_producer$RecA +}; + +let hidden = JsxRuntime.jsx(Nested_component_producer$Hidden, {}); + +let Provider$make = Nested_component_producer$Provider; + +let Trigger$make = make; + +let Menu$Item$make = Nested_component_producer$Menu$Item; + +let Ext$make = make$1; + +let RecA$make = Nested_component_producer$RecA; + +let RecB$make = Nested_component_producer$RecB; + +export { + Provider, + Trigger, + Menu, + Ext, + RecA, + RecB, + hidden, + Provider$make, + Trigger$make, + Menu$Item$make, + Ext$make, + RecA$make, + RecB$make, +} +/* make Not a pure module */ diff --git a/tests/build_tests/react_ppx/src/nested_component_producer.resi b/tests/build_tests/react_ppx/src/nested_component_producer.resi new file mode 100644 index 00000000000..75f7daf8c2c --- /dev/null +++ b/tests/build_tests/react_ppx/src/nested_component_producer.resi @@ -0,0 +1,32 @@ +module Provider: { + @react.component + let make: (~children: React.element) => React.element +} + +module Trigger: { + @react.component + let make: (~label: string) => React.element +} + +module Menu: { + module Item: { + @react.component + let make: (~children: React.element) => React.element + } +} + +module Ext: { + @react.component + let make: (~children: React.element) => React.element +} + +module rec RecA: { + @react.component + let make: unit => React.element +} +and RecB: { + @react.component + let make: unit => React.element +} + +let hidden: React.element diff --git a/tests/build_tests/react_ppx/src/recursive_component_test.res.js b/tests/build_tests/react_ppx/src/recursive_component_test.res.js index 8c8e26e1254..bf10018c90c 100644 --- a/tests/build_tests/react_ppx/src/recursive_component_test.res.js +++ b/tests/build_tests/react_ppx/src/recursive_component_test.res.js @@ -20,7 +20,10 @@ let Rec = { make: Recursive_component_test$Rec }; +let Rec$make = Recursive_component_test$Rec; + export { Rec, + Rec$make, } /* No side effect */ diff --git a/tests/build_tests/react_ppx/src/recursive_explicit_component_test.res.js b/tests/build_tests/react_ppx/src/recursive_explicit_component_test.res.js index 9577ffd28ab..8869bf1b8de 100644 --- a/tests/build_tests/react_ppx/src/recursive_explicit_component_test.res.js +++ b/tests/build_tests/react_ppx/src/recursive_explicit_component_test.res.js @@ -49,10 +49,19 @@ let componentWithPropsElement = React.createElement(Recursive_explicit_component foo: 1 }); +let SelfCreateElement$make = Recursive_explicit_component_test$SelfCreateElement; + +let RawSiblingCreateElement$make = Recursive_explicit_component_test$RawSiblingCreateElement; + +let ComponentWithProps$make = Recursive_explicit_component_test$ComponentWithProps; + export { SelfCreateElement, RawSiblingCreateElement, ComponentWithProps, componentWithPropsElement, + SelfCreateElement$make, + RawSiblingCreateElement$make, + ComponentWithProps$make, } /* componentWithPropsElement Not a pure module */ diff --git a/tests/build_tests/super_errors/expected/flat_make_export_collision.res.expected b/tests/build_tests/super_errors/expected/flat_make_export_collision.res.expected new file mode 100644 index 00000000000..5b22daad07c --- /dev/null +++ b/tests/build_tests/super_errors/expected/flat_make_export_collision.res.expected @@ -0,0 +1,5 @@ + + We've found a bug for you! + /.../fixtures/flat_make_export_collision.res + + Cannot export `A.B.make` as `A$B$make` because that name is already exported. \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/hoisted_function_export_collision.res.expected b/tests/build_tests/super_errors/expected/hoisted_function_export_collision.res.expected deleted file mode 100644 index 7969277ca0f..00000000000 --- a/tests/build_tests/super_errors/expected/hoisted_function_export_collision.res.expected +++ /dev/null @@ -1,11 +0,0 @@ - - We've found a bug for you! - /.../fixtures/hoisted_function_export_collision.res:3:14-21 - - 1 │ module One = { - 2 │ @res.hoistedFunction - 3 │ let make = () => () - 4 │ } - 5 │ let \"One$make" = () => () - - Cannot hoist this function as `One$make` because that name is already used by a top-level binding. \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/hoisted_function_hidden_by_signature.res.expected b/tests/build_tests/super_errors/expected/hoisted_function_hidden_by_signature.res.expected deleted file mode 100644 index bbba188005a..00000000000 --- a/tests/build_tests/super_errors/expected/hoisted_function_hidden_by_signature.res.expected +++ /dev/null @@ -1,11 +0,0 @@ - - Warning number 53 - /.../fixtures/hoisted_function_hidden_by_signature.res:4:3-22 - - 2 │ let visible: unit => string - 3 │ } = { - 4 │ @res.hoistedFunction - 5 │ let hidden = () => "hidden" - 6 │ let visible = hidden - - the @res.hoistedFunction attribute cannot appear in this context \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/hoisted_function_invalid_payload.res.expected b/tests/build_tests/super_errors/expected/hoisted_function_invalid_payload.res.expected deleted file mode 100644 index ae6bd4b594a..00000000000 --- a/tests/build_tests/super_errors/expected/hoisted_function_invalid_payload.res.expected +++ /dev/null @@ -1,11 +0,0 @@ - - Warning number 47 - /.../fixtures/hoisted_function_invalid_payload.res:2:3-22 - - 1 │ module Nested = { - 2 │ @res.hoistedFunction("name") - 3 │ let make = () => () - 4 │ } - - illegal payload for attribute @res.hoistedFunction. -This attribute does not accept a payload \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/hoisted_function_not_exportable.res.expected b/tests/build_tests/super_errors/expected/hoisted_function_not_exportable.res.expected deleted file mode 100644 index 9d299b480aa..00000000000 --- a/tests/build_tests/super_errors/expected/hoisted_function_not_exportable.res.expected +++ /dev/null @@ -1,70 +0,0 @@ - - Warning number 32 - /.../fixtures/hoisted_function_not_exportable.res:26:7-10 - - 24 │ module Shadowed = { - 25 │ @res.hoistedFunction - 26 │ let make = () => "first" - 27 │ let make = () => "second" - 28 │ } - - unused value make. - - - Warning number 53 - /.../fixtures/hoisted_function_not_exportable.res:15:3-22 - - 13 │ } - 14 │ module Make = () => { - 15 │ @res.hoistedFunction - 16 │ let make = () => () - 17 │ } - - the @res.hoistedFunction attribute cannot appear in this context - - - Warning number 53 - /.../fixtures/hoisted_function_not_exportable.res:9:5-24 - - 7 │ let localModule = () => { - 8 │ module Local = { - 9 │ @res.hoistedFunction - 10 │ let make = () => () - 11 │ } - - the @res.hoistedFunction attribute cannot appear in this context - - - Warning number 53 - /.../fixtures/hoisted_function_not_exportable.res:2:3-22 - - 1 │ let run = () => { - 2 │ @res.hoistedFunction - 3 │ let local = () => () - 4 │ local() - - the @res.hoistedFunction attribute cannot appear in this context - - - Warning number 53 - /.../fixtures/hoisted_function_not_exportable.res:19:3-22 - - 17 │ } - 18 │ %%private( - 19 │ @res.hoistedFunction - 20 │ let privateMake = () => () - 21 │ ) - - the @res.hoistedFunction attribute cannot appear in this context - - - Warning number 53 - /.../fixtures/hoisted_function_not_exportable.res:25:3-22 - - 23 │ let usePrivate = privateMake() - 24 │ module Shadowed = { - 25 │ @res.hoistedFunction - 26 │ let make = () => "first" - 27 │ let make = () => "second" - - the @res.hoistedFunction attribute cannot appear in this context \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/hoisted_function_path_collision.res.expected b/tests/build_tests/super_errors/expected/hoisted_function_path_collision.res.expected deleted file mode 100644 index 3299c8be04c..00000000000 --- a/tests/build_tests/super_errors/expected/hoisted_function_path_collision.res.expected +++ /dev/null @@ -1,11 +0,0 @@ - - We've found a bug for you! - /.../fixtures/hoisted_function_path_collision.res:7:19-26 - - 5 │ } - 6 │ @res.hoistedFunction - 7 │ let \"B$make" = () => () - 8 │ } - 9 │ let after = () - - Cannot hoist this function as `A$B$make` because that name is already used by a top-level binding. \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/hoisted_function_unsupported_pattern.res.expected b/tests/build_tests/super_errors/expected/hoisted_function_unsupported_pattern.res.expected deleted file mode 100644 index a2e9b9970ea..00000000000 --- a/tests/build_tests/super_errors/expected/hoisted_function_unsupported_pattern.res.expected +++ /dev/null @@ -1,10 +0,0 @@ - - Warning number 53 - /.../fixtures/hoisted_function_unsupported_pattern.res:2:3-22 - - 1 │ module Nested = { - 2 │ @res.hoistedFunction - 3 │ let f as g = () => "ok" - 4 │ } - - the @res.hoistedFunction attribute cannot appear in this context \ No newline at end of file diff --git a/tests/build_tests/super_errors/expected/warning_101_bs_unused_attribute.res.expected b/tests/build_tests/super_errors/expected/warning_101_bs_unused_attribute.res.expected index 7fcb36fc443..f7448f2e635 100644 --- a/tests/build_tests/super_errors/expected/warning_101_bs_unused_attribute.res.expected +++ b/tests/build_tests/super_errors/expected/warning_101_bs_unused_attribute.res.expected @@ -13,28 +13,13 @@ For example, some attributes are only meaningful in externals. Warning number 101 (configured as error) - /.../fixtures/warning_101_bs_unused_attribute.res:4:1-20 + /.../fixtures/warning_101_bs_unused_attribute.res:5:3-22 - 2 │ let x = 1 3 │ - 4 │ @res.hoistedFunction - 5 │ type t = int - 6 │ - - Unused attribute: @res.hoistedFunction -This attribute has no effect here. -For example, some attributes are only meaningful in externals. - - - - Warning number 101 (configured as error) - /.../fixtures/warning_101_bs_unused_attribute.res:8:14-33 - - 6 │ - 7 │ module ExpressionAttribute = { - 8 │ let make = @res.hoistedFunction () => () - 9 │ } - 10 │ + 4 │ module Hoisted = { + 5 │ @res.hoistedFunction + 6 │ let make = () => () + 7 │ } Unused attribute: @res.hoistedFunction This attribute has no effect here. diff --git a/tests/build_tests/super_errors/fixtures/flat_make_export_collision.res b/tests/build_tests/super_errors/fixtures/flat_make_export_collision.res new file mode 100644 index 00000000000..f77cc4419a8 --- /dev/null +++ b/tests/build_tests/super_errors/fixtures/flat_make_export_collision.res @@ -0,0 +1,7 @@ +module A = { + module B = { + let make = () => 1 + } +} + +let \"A$B$make" = 2 diff --git a/tests/build_tests/super_errors/fixtures/hoisted_function_export_collision.res b/tests/build_tests/super_errors/fixtures/hoisted_function_export_collision.res deleted file mode 100644 index ac642bfe4e5..00000000000 --- a/tests/build_tests/super_errors/fixtures/hoisted_function_export_collision.res +++ /dev/null @@ -1,5 +0,0 @@ -module One = { - @res.hoistedFunction - let make = () => () -} -let \"One$make" = () => () diff --git a/tests/build_tests/super_errors/fixtures/hoisted_function_hidden_by_signature.res b/tests/build_tests/super_errors/fixtures/hoisted_function_hidden_by_signature.res deleted file mode 100644 index 7b50cba0d12..00000000000 --- a/tests/build_tests/super_errors/fixtures/hoisted_function_hidden_by_signature.res +++ /dev/null @@ -1,7 +0,0 @@ -module A: { - let visible: unit => string -} = { - @res.hoistedFunction - let hidden = () => "hidden" - let visible = hidden -} diff --git a/tests/build_tests/super_errors/fixtures/hoisted_function_invalid_payload.res b/tests/build_tests/super_errors/fixtures/hoisted_function_invalid_payload.res deleted file mode 100644 index 3f4a9a6b25e..00000000000 --- a/tests/build_tests/super_errors/fixtures/hoisted_function_invalid_payload.res +++ /dev/null @@ -1,4 +0,0 @@ -module Nested = { - @res.hoistedFunction("name") - let make = () => () -} diff --git a/tests/build_tests/super_errors/fixtures/hoisted_function_not_exportable.res b/tests/build_tests/super_errors/fixtures/hoisted_function_not_exportable.res deleted file mode 100644 index a4e0037fd3b..00000000000 --- a/tests/build_tests/super_errors/fixtures/hoisted_function_not_exportable.res +++ /dev/null @@ -1,29 +0,0 @@ -let run = () => { - @res.hoistedFunction - let local = () => () - local() -} - -let localModule = () => { - module Local = { - @res.hoistedFunction - let make = () => () - } - Local.make() -} -module Make = () => { - @res.hoistedFunction - let make = () => () -} -%%private( - @res.hoistedFunction - let privateMake = () => () -) - -let usePrivate = privateMake() -module Shadowed = { - @res.hoistedFunction - let make = () => "first" - let make = () => "second" -} -let after = () diff --git a/tests/build_tests/super_errors/fixtures/hoisted_function_path_collision.res b/tests/build_tests/super_errors/fixtures/hoisted_function_path_collision.res deleted file mode 100644 index c74d5feb43f..00000000000 --- a/tests/build_tests/super_errors/fixtures/hoisted_function_path_collision.res +++ /dev/null @@ -1,9 +0,0 @@ -module A = { - module B = { - @res.hoistedFunction - let make = () => () - } - @res.hoistedFunction - let \"B$make" = () => () -} -let after = () diff --git a/tests/build_tests/super_errors/fixtures/hoisted_function_unsupported_pattern.res b/tests/build_tests/super_errors/fixtures/hoisted_function_unsupported_pattern.res deleted file mode 100644 index 258b059e263..00000000000 --- a/tests/build_tests/super_errors/fixtures/hoisted_function_unsupported_pattern.res +++ /dev/null @@ -1,4 +0,0 @@ -module Nested = { - @res.hoistedFunction - let f as g = () => "ok" -} diff --git a/tests/build_tests/super_errors/fixtures/warning_101_bs_unused_attribute.res b/tests/build_tests/super_errors/fixtures/warning_101_bs_unused_attribute.res index 2206888afd4..e2084a4f0ae 100644 --- a/tests/build_tests/super_errors/fixtures/warning_101_bs_unused_attribute.res +++ b/tests/build_tests/super_errors/fixtures/warning_101_bs_unused_attribute.res @@ -1,9 +1,7 @@ @as("foo") let x = 1 -@res.hoistedFunction -type t = int - -module ExpressionAttribute = { - let make = @res.hoistedFunction () => () +module Hoisted = { + @res.hoistedFunction + let make = () => () } 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 8669c8eafed..2b25ff60b42 100644 --- a/tests/gentype_tests/typescript-react-example/src/Hooks.res.js +++ b/tests/gentype_tests/typescript-react-example/src/Hooks.res.js @@ -204,6 +204,18 @@ let make$1 = Hooks; let $$default = Hooks; +let Inner$make = Hooks$Inner; + +let Inner$Inner2$make = Hooks$Inner$Inner2; + +let NoProps$make = Hooks$NoProps; + +let WithRef$make = make; + +let RenderPropRequiresConversion$make = Hooks$RenderPropRequiresConversion; + +let DD$make = Hooks$DD; + export { make$1 as make, $$default as default, @@ -219,5 +231,11 @@ export { RenderPropRequiresConversion, WithChildren, DD, + Inner$make, + Inner$Inner2$make, + NoProps$make, + WithRef$make, + RenderPropRequiresConversion$make, + DD$make, } /* make Not a pure module */ diff --git a/tests/gentype_tests/typescript-react-example/src/InnerModuleSignature.res.js b/tests/gentype_tests/typescript-react-example/src/InnerModuleSignature.res.js index 047a40e2a9b..bdcb9888769 100644 --- a/tests/gentype_tests/typescript-react-example/src/InnerModuleSignature.res.js +++ b/tests/gentype_tests/typescript-react-example/src/InnerModuleSignature.res.js @@ -9,7 +9,10 @@ let InnerModule = { make: make }; +let InnerModule$make = make; + export { InnerModule, + InnerModule$make, } /* No side effect */ 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 016dda6790c..0fe03d9550e 100644 --- a/tests/gentype_tests/typescript-react-example/src/JSXV4.res.js +++ b/tests/gentype_tests/typescript-react-example/src/JSXV4.res.js @@ -12,8 +12,11 @@ let CompV4 = { let make = JSXV4Gen.make; +let CompV4$make = JSXV4$CompV4; + export { CompV4, make, + CompV4$make, } /* make Not a pure module */ diff --git a/tests/gentype_tests/typescript-react-example/src/References.res.js b/tests/gentype_tests/typescript-react-example/src/References.res.js index ab19e92b230..7bad7d29a73 100644 --- a/tests/gentype_tests/typescript-react-example/src/References.res.js +++ b/tests/gentype_tests/typescript-react-example/src/References.res.js @@ -43,6 +43,8 @@ function preserveRefIdentity(x) { return x; } +let R$make = make; + export { create, access, @@ -53,5 +55,6 @@ export { set, destroysRefIdentity, preserveRefIdentity, + R$make, } /* No side effect */ diff --git a/tests/ounit_tests/ounit_compiler_request_tests.ml b/tests/ounit_tests/ounit_compiler_request_tests.ml index eb7a8156892..169aec490fc 100644 --- a/tests/ounit_tests/ounit_compiler_request_tests.ml +++ b/tests/ounit_tests/ounit_compiler_request_tests.ml @@ -260,9 +260,8 @@ let failed_writing_closes_files_tests _context = let open_files () = Array.length (Sys.readdir "/proc/self/fd") in let before = open_files () in let cmj = - Js_cmj_format.make ~values:Map_string.empty ~hoisted_exports:[] - ~effect_:None ~package_spec:Js_packages_info.empty - ~case:Ext_js_file_kind.Little + Js_cmj_format.make ~values:Map_string.empty ~effect_:None + ~package_spec:Js_packages_info.empty ~case:Ext_js_file_kind.Little in let cmi = { diff --git a/tests/ounit_tests/ounit_lambda_constant_tests.ml b/tests/ounit_tests/ounit_lambda_constant_tests.ml index cbed5fa9a10..b9566f8f9c5 100644 --- a/tests/ounit_tests/ounit_lambda_constant_tests.ml +++ b/tests/ounit_tests/ounit_lambda_constant_tests.ml @@ -294,11 +294,11 @@ let suites = ]; ] in - let typed, _, _ = + let typed, signature, env = Typemod.type_structure (Env.initial_safe_string ()) structure in let implementation = - Translmod.transl_implementation "RegexpTest" + Translmod.transl_implementation "RegexpTest" env signature (typed, Typedtree.Tcoerce_none) in let sources = ref [] in diff --git a/tests/tests/src/Import.mjs b/tests/tests/src/Import.mjs index 1655f29d9cf..29df3041b02 100644 --- a/tests/tests/src/Import.mjs +++ b/tests/tests/src/Import.mjs @@ -134,6 +134,22 @@ let M2; let each2 = O.forEach; +let M$make = M.make; + +let N$N0$make = N0.make; + +let N$N1$O$make = N1.O.make; + +let N$N2$make = N2.make; + +let N$N3$make = N3.make; + +let M0$make = M0.make; + +let M1$make = M1.make; + +let MConstrained$make = MConstrained.make; + export { eachIntAsync, eachIntLazy, @@ -156,5 +172,13 @@ export { f7, f8, f9, + M$make, + N$N0$make, + N$N1$O$make, + N$N2$make, + N$N3$make, + M0$make, + M1$make, + MConstrained$make, } /* Not a pure module */ diff --git a/tests/tests/src/alias_default_value_test.mjs b/tests/tests/src/alias_default_value_test.mjs index 1541a25702d..a708e73cf05 100644 --- a/tests/tests/src/alias_default_value_test.mjs +++ b/tests/tests/src/alias_default_value_test.mjs @@ -91,6 +91,22 @@ let C8 = { make: Alias_default_value_test$C8 }; +let C0$make = Alias_default_value_test$C0; + +let C1$make = Alias_default_value_test$C1; + +let C2$make = Alias_default_value_test$C2; + +let C3$make = Alias_default_value_test$C3; + +let C4$make = Alias_default_value_test$C4; + +let C6$make = Alias_default_value_test$C6; + +let C7$make = Alias_default_value_test$C7; + +let C8$make = Alias_default_value_test$C8; + export { C0, C1, @@ -100,5 +116,13 @@ export { C6, C7, C8, + C0$make, + C1$make, + C2$make, + C3$make, + C4$make, + C6$make, + C7$make, + C8$make, } /* No side effect */ diff --git a/tests/tests/src/async_jsx.mjs b/tests/tests/src/async_jsx.mjs index f02ec3cf205..5ac8684afaa 100644 --- a/tests/tests/src/async_jsx.mjs +++ b/tests/tests/src/async_jsx.mjs @@ -33,9 +33,15 @@ let Bar = { make: Async_jsx$Bar }; +let Foo$make = Async_jsx$Foo; + +let Bar$make = Async_jsx$Bar; + export { getNow, Foo, Bar, + Foo$make, + Bar$make, } /* react/jsx-runtime Not a pure module */ diff --git a/tests/tests/src/exception_alias.mjs b/tests/tests/src/exception_alias.mjs index 7eaa017bd4b..05d5c63f2d8 100644 --- a/tests/tests/src/exception_alias.mjs +++ b/tests/tests/src/exception_alias.mjs @@ -82,6 +82,8 @@ let a4 = a0; let a5 = a0; +let List$make = Stdlib_List.make; + export { a0, a1, @@ -90,5 +92,6 @@ export { a4, a5, List, + List$make, } /* b Not a pure module */ diff --git a/tests/tests/src/hoisted_function_attr.mjs b/tests/tests/src/flat_make_export.mjs similarity index 65% rename from tests/tests/src/hoisted_function_attr.mjs rename to tests/tests/src/flat_make_export.mjs index 9e68ea7f5ed..c873eec95b2 100644 --- a/tests/tests/src/hoisted_function_attr.mjs +++ b/tests/tests/src/flat_make_export.mjs @@ -2,6 +2,10 @@ function make() { + return "top"; +} + +function make$1() { return "one"; } @@ -10,7 +14,7 @@ function keep() { } let One = { - make: make, + make: make$1, keep: keep }; @@ -18,7 +22,7 @@ function keep$1() { return "two-keep"; } -function make$1() { +function make$2() { return "two"; } @@ -27,7 +31,7 @@ function keep$2() { } let Inner = { - make: make$1, + make: make$2, keep: keep$2 }; @@ -40,7 +44,7 @@ function keep$3() { return "three-inner-keep"; } -function make$2() { +function make$3() { return "three"; } @@ -49,7 +53,7 @@ function keep$4() { } let Deep = { - make: make$2, + make: make$3, keep: keep$4 }; @@ -62,37 +66,16 @@ let Three = { Inner: Inner$1 }; -function $$switch() { - return "keyword"; -} - -function $plus() { - return "dollar"; -} - -let Escaped = { - $$switch: $$switch, - $plus: $plus -}; - -function $plus$1() { - return "operator"; -} - -let Operator = { - $plus: $plus$1 -}; - -function make$3() { +function make$4() { return "nested"; } let B = { - make: make$3 + make: make$4 }; function B$make() { - return "exotic"; + return "exotic-value"; } let Ambiguous = { @@ -108,19 +91,11 @@ let RecursiveB = { value: value }; -function make$4() { +function make$5() { return "recursive"; } let RecursiveA = { - make: make$4 -}; - -function make$5() { - return "typed"; -} - -let Typed = { make: make$5 }; @@ -132,55 +107,76 @@ let Coerced = { make: make$6 }; +function make$7() { + return "rebound"; +} + +let Rebound = { + make: make$7 +}; + +function Make(X) { + let make = () => X.value; + return { + make: make + }; +} + +function make$8() { + return "applied"; +} + +let Applied = { + make: make$8 +}; + let Included = { - make: make, + make: make$1, keep: keep }; let Aliased; -let Coerced$make = Coerced.make; +let One$make = make$1; -let Typed$make = Typed.make; +let Two$Inner$make = make$2; -let RecursiveA$make = RecursiveA.make; +let Three$Inner$Deep$make = make$3; -let Ambiguous$B$make = B.make; +let Ambiguous$B$make = make$4; -let Operator$$plus = Operator.$plus; +let RecursiveA$make = make$5; -let Escaped$$plus = $plus; +let Coerced$make = make$6; -let Escaped$switch = $$switch; +let Rebound$make = Rebound.make; -let Three$Inner$Deep$make = Three.Inner.Deep.make; +let Applied$make = make$8; -let Two$Inner$make = Inner.make; - -let One$make = make; +let Included$make = make$1; export { + make, One, Two, Three, - Escaped, - Operator, Ambiguous, RecursiveA, RecursiveB, - Typed, Coerced, + Rebound, + Make, + Applied, Included, Aliased, - Coerced$make, - Typed$make, - RecursiveA$make, - Ambiguous$B$make, - Operator$$plus, - Escaped$$plus, - Escaped$switch, - Three$Inner$Deep$make, - Two$Inner$make, One$make, + Two$Inner$make, + Three$Inner$Deep$make, + Ambiguous$B$make, + RecursiveA$make, + Coerced$make, + Rebound$make, + Applied$make, + Included$make, } /* No side effect */ diff --git a/tests/tests/src/hoisted_function_attr.res b/tests/tests/src/flat_make_export.res similarity index 64% rename from tests/tests/src/hoisted_function_attr.res rename to tests/tests/src/flat_make_export.res index 679b633cf78..d106b1013ea 100644 --- a/tests/tests/src/hoisted_function_attr.res +++ b/tests/tests/src/flat_make_export.res @@ -1,5 +1,6 @@ +let make = () => "top" + module One = { - @res.hoistedFunction let make = () => "one" let keep = () => "one-keep" @@ -9,7 +10,6 @@ module Two = { let keep = () => "two-keep" module Inner = { - @res.hoistedFunction let make = () => "two" let keep = () => "two-inner-keep" @@ -21,7 +21,6 @@ module Three = { let keep = () => "three-inner-keep" module Deep = { - @res.hoistedFunction let make = () => "three" let keep = () => "three-deep-keep" @@ -29,32 +28,17 @@ module Three = { } } -module Escaped = { - @res.hoistedFunction - let \"switch" = () => "keyword" - - @res.hoistedFunction - let $plus = () => "dollar" -} - -module Operator = { - @res.hoistedFunction - let \"+" = () => "operator" -} - module Ambiguous = { module B = { - @res.hoistedFunction let make = () => "nested" } - let \"B$make" = () => "exotic" + let \"B$make" = () => "exotic-value" } module rec RecursiveA: { let make: unit => string } = { - @res.hoistedFunction let make = () => RecursiveB.value() } and RecursiveB: { @@ -63,20 +47,31 @@ and RecursiveB: { let value = () => "recursive" } -module Typed = { - @res.hoistedFunction - let make: unit => string = () => "typed" -} - module Coerced: { let make: unit => string } = { let hidden = () => "coerced" - @res.hoistedFunction let make = () => hidden() } +module Rebound = { + let make = () => "rebound" + let make = Some(make) +} + +module Make = ( + X: { + let value: string + }, +) => { + let make = () => X.value +} + +module Applied = Make({ + let value = "applied" +}) + module Included = { include One } diff --git a/tests/tests/src/flat_make_export_hidden.mjs b/tests/tests/src/flat_make_export_hidden.mjs new file mode 100644 index 00000000000..1e909af4214 --- /dev/null +++ b/tests/tests/src/flat_make_export_hidden.mjs @@ -0,0 +1,35 @@ +// Generated by ReScript, PLEASE EDIT WITH CARE + + +function make() { + return 1; +} + +let B = { + make: make +}; + +let A = { + B: B +}; + +function A$B$make() { + if (Math.random() > 2) { + return 0; + } else { + return 2; + } +} + +function both() { + return 1 + A$B$make() | 0; +} + +let A$B$make$1 = make; + +export { + A, + both, + A$B$make$1 as A$B$make, +} +/* No side effect */ diff --git a/tests/tests/src/flat_make_export_hidden.res b/tests/tests/src/flat_make_export_hidden.res new file mode 100644 index 00000000000..938ff2ee2d7 --- /dev/null +++ b/tests/tests/src/flat_make_export_hidden.res @@ -0,0 +1,10 @@ +module A = { + module B = { + let make = () => 1 + } +} + +// Hidden by the interface, so it does not clash with the flat export. +let \"A$B$make" = () => Math.random() > 2. ? 0 : 2 + +let both = () => A.B.make() + \"A$B$make"() diff --git a/tests/tests/src/flat_make_export_hidden.resi b/tests/tests/src/flat_make_export_hidden.resi new file mode 100644 index 00000000000..84a878b79c9 --- /dev/null +++ b/tests/tests/src/flat_make_export_hidden.resi @@ -0,0 +1,7 @@ +module A: { + module B: { + let make: unit => int + } +} + +let both: unit => int diff --git a/tests/tests/src/flat_make_export_test.mjs b/tests/tests/src/flat_make_export_test.mjs new file mode 100644 index 00000000000..b870d470736 --- /dev/null +++ b/tests/tests/src/flat_make_export_test.mjs @@ -0,0 +1,36 @@ +// Generated by ReScript, PLEASE EDIT WITH CARE + +import * as Mocha from "mocha"; +import * as Test_utils from "./test_utils.mjs"; +import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.mjs"; +import * as Flat_make_export_use from "./flat_make_export_use.mjs"; + +Mocha.describe("Flat_make_export_test", () => { + Mocha.test("nested make values are read through flat exports", () => { + Test_utils.eq("File \"flat_make_export_test.res\", line 6, characters 7-14", Flat_make_export_use.top, "top"); + Test_utils.eq("File \"flat_make_export_test.res\", line 7, characters 7-14", Flat_make_export_use.one, "one"); + Test_utils.eq("File \"flat_make_export_test.res\", line 8, characters 7-14", Flat_make_export_use.two, "two"); + Test_utils.eq("File \"flat_make_export_test.res\", line 9, characters 7-14", Flat_make_export_use.three, "three"); + }); + Mocha.test("other values keep their module path", () => { + Test_utils.eq("File \"flat_make_export_test.res\", line 13, characters 7-14", Flat_make_export_use.oneKeep, "one-keep"); + Test_utils.eq("File \"flat_make_export_test.res\", line 14, characters 7-14", Flat_make_export_use.twoKeep, "two-inner-keep"); + Test_utils.eq("File \"flat_make_export_test.res\", line 15, characters 7-14", Flat_make_export_use.threeKeep, "three-deep-keep"); + Test_utils.eq("File \"flat_make_export_test.res\", line 16, characters 7-14", Flat_make_export_use.exoticValue, "exotic-value"); + }); + Mocha.test("flat names follow the signature, not the implementation", () => { + Test_utils.eq("File \"flat_make_export_test.res\", line 20, characters 7-14", Flat_make_export_use.nested, "nested"); + Test_utils.eq("File \"flat_make_export_test.res\", line 21, characters 7-14", Flat_make_export_use.recursive, "recursive"); + Test_utils.eq("File \"flat_make_export_test.res\", line 22, characters 7-14", Flat_make_export_use.coerced, "coerced"); + Test_utils.eq("File \"flat_make_export_test.res\", line 23, characters 7-14", Stdlib_Option.map(Flat_make_export_use.rebound, f => f()), "rebound"); + Test_utils.eq("File \"flat_make_export_test.res\", line 24, characters 7-14", Flat_make_export_use.applied, "applied"); + Test_utils.eq("File \"flat_make_export_test.res\", line 25, characters 7-14", Flat_make_export_use.included, "one"); + Test_utils.eq("File \"flat_make_export_test.res\", line 26, characters 7-14", Flat_make_export_use.aliased, "one"); + }); + Mocha.test("a binding hidden by the interface does not clash", () => { + Test_utils.eq("File \"flat_make_export_test.res\", line 30, characters 7-14", Flat_make_export_use.hidden, 1); + Test_utils.eq("File \"flat_make_export_test.res\", line 31, characters 7-14", Flat_make_export_use.hiddenBoth, 3); + }); +}); + +/* Not a pure module */ diff --git a/tests/tests/src/flat_make_export_test.res b/tests/tests/src/flat_make_export_test.res new file mode 100644 index 00000000000..83a02908de6 --- /dev/null +++ b/tests/tests/src/flat_make_export_test.res @@ -0,0 +1,33 @@ +open Mocha +open Test_utils + +describe(__MODULE__, () => { + test("nested make values are read through flat exports", () => { + eq(__LOC__, Flat_make_export_use.top, "top") + eq(__LOC__, Flat_make_export_use.one, "one") + eq(__LOC__, Flat_make_export_use.two, "two") + eq(__LOC__, Flat_make_export_use.three, "three") + }) + + test("other values keep their module path", () => { + eq(__LOC__, Flat_make_export_use.oneKeep, "one-keep") + eq(__LOC__, Flat_make_export_use.twoKeep, "two-inner-keep") + eq(__LOC__, Flat_make_export_use.threeKeep, "three-deep-keep") + eq(__LOC__, Flat_make_export_use.exoticValue, "exotic-value") + }) + + test("flat names follow the signature, not the implementation", () => { + eq(__LOC__, Flat_make_export_use.nested, "nested") + eq(__LOC__, Flat_make_export_use.recursive, "recursive") + eq(__LOC__, Flat_make_export_use.coerced, "coerced") + eq(__LOC__, Flat_make_export_use.rebound->Option.map(f => f()), Some("rebound")) + eq(__LOC__, Flat_make_export_use.applied, "applied") + eq(__LOC__, Flat_make_export_use.included, "one") + eq(__LOC__, Flat_make_export_use.aliased, "one") + }) + + test("a binding hidden by the interface does not clash", () => { + eq(__LOC__, Flat_make_export_use.hidden, 1) + eq(__LOC__, Flat_make_export_use.hiddenBoth, 3) + }) +}) diff --git a/tests/tests/src/flat_make_export_use.mjs b/tests/tests/src/flat_make_export_use.mjs new file mode 100644 index 00000000000..7662f33788e --- /dev/null +++ b/tests/tests/src/flat_make_export_use.mjs @@ -0,0 +1,59 @@ +// Generated by ReScript, PLEASE EDIT WITH CARE + +import * as Flat_make_export from "./flat_make_export.mjs"; +import * as Flat_make_export_hidden from "./flat_make_export_hidden.mjs"; + +let top = Flat_make_export.make(); + +let one = Flat_make_export.One$make(); + +let oneKeep = Flat_make_export.One.keep(); + +let two = Flat_make_export.Two$Inner$make(); + +let twoKeep = Flat_make_export.Two.Inner.keep(); + +let three = Flat_make_export.Three$Inner$Deep$make(); + +let threeKeep = Flat_make_export.Three.Inner.Deep.keep(); + +let nested = Flat_make_export.Ambiguous$B$make(); + +let exoticValue = Flat_make_export.Ambiguous.B$make(); + +let recursive = Flat_make_export.RecursiveA$make(); + +let coerced = Flat_make_export.Coerced$make(); + +let rebound = Flat_make_export.Rebound$make; + +let applied = Flat_make_export.Applied$make(); + +let included = Flat_make_export.Included$make(); + +let aliased = Flat_make_export.One$make(); + +let hidden = Flat_make_export_hidden.A$B$make(); + +let hiddenBoth = Flat_make_export_hidden.both(); + +export { + top, + one, + oneKeep, + two, + twoKeep, + three, + threeKeep, + nested, + exoticValue, + recursive, + coerced, + rebound, + applied, + included, + aliased, + hidden, + hiddenBoth, +} +/* top Not a pure module */ diff --git a/tests/tests/src/flat_make_export_use.res b/tests/tests/src/flat_make_export_use.res new file mode 100644 index 00000000000..c055bf2d780 --- /dev/null +++ b/tests/tests/src/flat_make_export_use.res @@ -0,0 +1,21 @@ +let top = Flat_make_export.make() + +let one = Flat_make_export.One.make() +let oneKeep = Flat_make_export.One.keep() + +let two = Flat_make_export.Two.Inner.make() +let twoKeep = Flat_make_export.Two.Inner.keep() + +let three = Flat_make_export.Three.Inner.Deep.make() +let threeKeep = Flat_make_export.Three.Inner.Deep.keep() + +let nested = Flat_make_export.Ambiguous.B.make() +let exoticValue = Flat_make_export.Ambiguous.\"B$make"() +let recursive = Flat_make_export.RecursiveA.make() +let coerced = Flat_make_export.Coerced.make() +let rebound = Flat_make_export.Rebound.make +let applied = Flat_make_export.Applied.make() +let included = Flat_make_export.Included.make() +let aliased = Flat_make_export.Aliased.make() +let hidden = Flat_make_export_hidden.A.B.make() +let hiddenBoth = Flat_make_export_hidden.both() diff --git a/tests/tests/src/gpr_3519_jsx_test.mjs b/tests/tests/src/gpr_3519_jsx_test.mjs index d6404300952..b8b75e73937 100644 --- a/tests/tests/src/gpr_3519_jsx_test.mjs +++ b/tests/tests/src/gpr_3519_jsx_test.mjs @@ -13,8 +13,11 @@ let Foo = { make: make }; +let Foo$make = make; + export { React, Foo, + Foo$make, } /* No side effect */ diff --git a/tests/tests/src/gpr_5071_test.mjs b/tests/tests/src/gpr_5071_test.mjs index 5e390c146ca..11ca4970c4e 100644 --- a/tests/tests/src/gpr_5071_test.mjs +++ b/tests/tests/src/gpr_5071_test.mjs @@ -13,7 +13,10 @@ let H = { make: make }; +let H$make = make; + export { H, + H$make, } /* No side effect */ diff --git a/tests/tests/src/hoisted_function_attr_test.mjs b/tests/tests/src/hoisted_function_attr_test.mjs deleted file mode 100644 index 94f44dc7bef..00000000000 --- a/tests/tests/src/hoisted_function_attr_test.mjs +++ /dev/null @@ -1,31 +0,0 @@ -// Generated by ReScript, PLEASE EDIT WITH CARE - -import * as Mocha from "mocha"; -import * as Test_utils from "./test_utils.mjs"; -import * as Hoisted_function_attr_use from "./hoisted_function_attr_use.mjs"; - -Mocha.describe("Hoisted_function_attr_test", () => { - Mocha.test("flat cross-module exports", () => { - Test_utils.eq("File \"hoisted_function_attr_test.res\", line 6, characters 7-14", Hoisted_function_attr_use.one, "one"); - Test_utils.eq("File \"hoisted_function_attr_test.res\", line 7, characters 7-14", Hoisted_function_attr_use.two, "two"); - Test_utils.eq("File \"hoisted_function_attr_test.res\", line 8, characters 7-14", Hoisted_function_attr_use.three, "three"); - }); - Mocha.test("exotic identifiers", () => { - Test_utils.eq("File \"hoisted_function_attr_test.res\", line 12, characters 7-14", Hoisted_function_attr_use.keyword, "keyword"); - Test_utils.eq("File \"hoisted_function_attr_test.res\", line 13, characters 7-14", Hoisted_function_attr_use.dollar, "dollar"); - Test_utils.eq("File \"hoisted_function_attr_test.res\", line 14, characters 7-14", Hoisted_function_attr_use.operator, "operator"); - }); - Mocha.test("structurally distinct paths", () => { - Test_utils.eq("File \"hoisted_function_attr_test.res\", line 18, characters 7-14", Hoisted_function_attr_use.nested, "nested"); - Test_utils.eq("File \"hoisted_function_attr_test.res\", line 19, characters 7-14", Hoisted_function_attr_use.exoticPath, "exotic"); - }); - Mocha.test("recursive modules", () => Test_utils.eq("File \"hoisted_function_attr_test.res\", line 23, characters 7-14", Hoisted_function_attr_use.recursive, "recursive")); - Mocha.test("explicit function type annotations", () => Test_utils.eq("File \"hoisted_function_attr_test.res\", line 27, characters 7-14", Hoisted_function_attr_use.typed, "typed")); - Mocha.test("signature coercion preserves hoists", () => Test_utils.eq("File \"hoisted_function_attr_test.res\", line 31, characters 7-14", Hoisted_function_attr_use.coerced, "coerced")); - Mocha.test("includes and aliases do not create additional hoists", () => { - Test_utils.eq("File \"hoisted_function_attr_test.res\", line 35, characters 7-14", Hoisted_function_attr_use.included, "one"); - Test_utils.eq("File \"hoisted_function_attr_test.res\", line 36, characters 7-14", Hoisted_function_attr_use.aliased, "one"); - }); -}); - -/* Not a pure module */ diff --git a/tests/tests/src/hoisted_function_attr_test.res b/tests/tests/src/hoisted_function_attr_test.res deleted file mode 100644 index e5e3212bfdb..00000000000 --- a/tests/tests/src/hoisted_function_attr_test.res +++ /dev/null @@ -1,38 +0,0 @@ -open Mocha -open Test_utils - -describe(__MODULE__, () => { - test("flat cross-module exports", () => { - eq(__LOC__, Hoisted_function_attr_use.one, "one") - eq(__LOC__, Hoisted_function_attr_use.two, "two") - eq(__LOC__, Hoisted_function_attr_use.three, "three") - }) - - test("exotic identifiers", () => { - eq(__LOC__, Hoisted_function_attr_use.keyword, "keyword") - eq(__LOC__, Hoisted_function_attr_use.dollar, "dollar") - eq(__LOC__, Hoisted_function_attr_use.operator, "operator") - }) - - test("structurally distinct paths", () => { - eq(__LOC__, Hoisted_function_attr_use.nested, "nested") - eq(__LOC__, Hoisted_function_attr_use.exoticPath, "exotic") - }) - - test("recursive modules", () => { - eq(__LOC__, Hoisted_function_attr_use.recursive, "recursive") - }) - - test("explicit function type annotations", () => { - eq(__LOC__, Hoisted_function_attr_use.typed, "typed") - }) - - test("signature coercion preserves hoists", () => { - eq(__LOC__, Hoisted_function_attr_use.coerced, "coerced") - }) - - test("includes and aliases do not create additional hoists", () => { - eq(__LOC__, Hoisted_function_attr_use.included, "one") - eq(__LOC__, Hoisted_function_attr_use.aliased, "one") - }) -}) diff --git a/tests/tests/src/hoisted_function_attr_use.mjs b/tests/tests/src/hoisted_function_attr_use.mjs deleted file mode 100644 index 979b2062421..00000000000 --- a/tests/tests/src/hoisted_function_attr_use.mjs +++ /dev/null @@ -1,55 +0,0 @@ -// Generated by ReScript, PLEASE EDIT WITH CARE - -import * as Hoisted_function_attr from "./hoisted_function_attr.mjs"; - -let one = Hoisted_function_attr.One$make(); - -let oneKeep = Hoisted_function_attr.One.keep(); - -let two = Hoisted_function_attr.Two$Inner$make(); - -let twoKeep = Hoisted_function_attr.Two.Inner.keep(); - -let three = Hoisted_function_attr.Three$Inner$Deep$make(); - -let threeKeep = Hoisted_function_attr.Three.Inner.Deep.keep(); - -let keyword = Hoisted_function_attr.Escaped$switch(); - -let dollar = Hoisted_function_attr.Escaped$$plus(); - -let operator = Hoisted_function_attr.Operator$$plus(); - -let nested = Hoisted_function_attr.Ambiguous$B$make(); - -let exoticPath = Hoisted_function_attr.Ambiguous.B$make(); - -let recursive = Hoisted_function_attr.RecursiveA$make(); - -let typed = Hoisted_function_attr.Typed$make(); - -let coerced = Hoisted_function_attr.Coerced$make(); - -let included = Hoisted_function_attr.Included.make(); - -let aliased = Hoisted_function_attr.One$make(); - -export { - one, - oneKeep, - two, - twoKeep, - three, - threeKeep, - keyword, - dollar, - operator, - nested, - exoticPath, - recursive, - typed, - coerced, - included, - aliased, -} -/* one Not a pure module */ diff --git a/tests/tests/src/hoisted_function_attr_use.res b/tests/tests/src/hoisted_function_attr_use.res deleted file mode 100644 index 6e2f7643145..00000000000 --- a/tests/tests/src/hoisted_function_attr_use.res +++ /dev/null @@ -1,20 +0,0 @@ -let one = Hoisted_function_attr.One.make() -let oneKeep = Hoisted_function_attr.One.keep() - -let two = Hoisted_function_attr.Two.Inner.make() -let twoKeep = Hoisted_function_attr.Two.Inner.keep() - -let three = Hoisted_function_attr.Three.Inner.Deep.make() -let threeKeep = Hoisted_function_attr.Three.Inner.Deep.keep() - -let keyword = Hoisted_function_attr.Escaped.\"switch"() -let dollar = Hoisted_function_attr.Escaped.$plus() -let operator = Hoisted_function_attr.Operator.\"+"() - -let nested = Hoisted_function_attr.Ambiguous.B.make() -let exoticPath = Hoisted_function_attr.Ambiguous.\"B$make"() -let recursive = Hoisted_function_attr.RecursiveA.make() -let typed = Hoisted_function_attr.Typed.make() -let coerced = Hoisted_function_attr.Coerced.make() -let included = Hoisted_function_attr.Included.make() -let aliased = Hoisted_function_attr.Aliased.make() diff --git a/tests/tests/src/import2.mjs b/tests/tests/src/import2.mjs index bc04c95162a..e86c765f8cb 100644 --- a/tests/tests/src/import2.mjs +++ b/tests/tests/src/import2.mjs @@ -8,7 +8,7 @@ let b = A; let c = import("./export_keyword.mjs").then(m => m.$$case); -let d = import("./hoisted_function_attr.mjs").then(m => m.Operator$$plus); +let d = import("./flat_make_export.mjs").then(m => m.Two$Inner$make); export { a, diff --git a/tests/tests/src/import2.res b/tests/tests/src/import2.res index b9684f60960..c465b59b948 100644 --- a/tests/tests/src/import2.res +++ b/tests/tests/src/import2.res @@ -5,7 +5,5 @@ let b = Import_external.makeA the emitted export (`case` is exported as `$$case`) */ let c = import(Export_keyword.case) -/* hoisted export names also go through JS identifier conversion: - the cmj stores the raw flattened name (Operator$+), the module exports - the converted one (Operator$$plus) */ -let d = import(Hoisted_function_attr.Operator.\"+") +/* a nested make is imported through its flat export */ +let d = import(Flat_make_export.Two.Inner.make) diff --git a/tests/tests/src/jsx_optional_props_test.mjs b/tests/tests/src/jsx_optional_props_test.mjs index 8fab49e1737..3329b8baaab 100644 --- a/tests/tests/src/jsx_optional_props_test.mjs +++ b/tests/tests/src/jsx_optional_props_test.mjs @@ -31,6 +31,8 @@ let _comment_multiple_children = JsxRuntime.jsxs("div", { ] }); +let ComponentWithOptionalProps$make = Jsx_optional_props_test$ComponentWithOptionalProps; + export { ComponentWithOptionalProps, _element, @@ -38,5 +40,6 @@ export { _comment_only_fragment, _comment_single_child, _comment_multiple_children, + ComponentWithOptionalProps$make, } /* _element Not a pure module */ diff --git a/tests/tests/src/jsx_preserve_cases.mjs b/tests/tests/src/jsx_preserve_cases.mjs index 8d413e86aac..1ae13468cc9 100644 --- a/tests/tests/src/jsx_preserve_cases.mjs +++ b/tests/tests/src/jsx_preserve_cases.mjs @@ -109,6 +109,10 @@ let undefinedKey =
; +let AsProp$make = Jsx_preserve_cases$AsProp; + +let Req$make = Jsx_preserve_cases$Req; + export { AsProp, asProp, @@ -131,5 +135,7 @@ export { copySpread, localComp, undefinedKey, + AsProp$make, + Req$make, } /* Not a pure module */ diff --git a/tests/tests/src/jsx_preserve_custom_runtime.mjs b/tests/tests/src/jsx_preserve_custom_runtime.mjs index 6fbd7c56768..15924dbc14c 100644 --- a/tests/tests/src/jsx_preserve_custom_runtime.mjs +++ b/tests/tests/src/jsx_preserve_custom_runtime.mjs @@ -40,6 +40,10 @@ let keyed =
; +let Comp$make = Jsx_preserve_custom_runtime$Comp; + +let TopMemo$make = memoComp; + export { MyJsx, Comp, @@ -48,5 +52,7 @@ export { topMemo, fragment, keyed, + Comp$make, + TopMemo$make, } /* memoComp Not a pure module */ diff --git a/tests/tests/src/jsx_preserve_test.mjs b/tests/tests/src/jsx_preserve_test.mjs index bc66ee92593..69e84c5206c 100644 --- a/tests/tests/src/jsx_preserve_test.mjs +++ b/tests/tests/src/jsx_preserve_test.mjs @@ -308,6 +308,20 @@ let _comment_multiple_children =
let make$2 = Jsx_preserve_test; +let Icon$make = Jsx_preserve_test$Icon; + +let B$make = Jsx_preserve_test$B; + +let MyWeirdComponent$make = Jsx_preserve_test$MyWeirdComponent; + +let ComponentWithOptionalProps$make = Jsx_preserve_test$ComponentWithOptionalProps; + +let X$make = Jsx_preserve_test$X; + +let Y$make = make; + +let ContextProvider$make = make$1; + export { Icon, _single_element_child, @@ -352,5 +366,12 @@ export { _comment_only_fragment, _comment_single_child, _comment_multiple_children, + Icon$make, + B$make, + MyWeirdComponent$make, + ComponentWithOptionalProps$make, + X$make, + Y$make, + ContextProvider$make, } /* _single_element_child Not a pure module */ diff --git a/tests/tests/src/jsxv4_newtype.mjs b/tests/tests/src/jsxv4_newtype.mjs index a6e2b5a2dc7..350f091e21c 100644 --- a/tests/tests/src/jsxv4_newtype.mjs +++ b/tests/tests/src/jsxv4_newtype.mjs @@ -33,10 +33,22 @@ let V4A3 = { make: Jsxv4_newtype$V4A3 }; +let V4A$make = Jsxv4_newtype$V4A; + +let V4A1$make = Jsxv4_newtype$V4A1; + +let V4A2$make = Jsxv4_newtype$V4A2; + +let V4A3$make = Jsxv4_newtype$V4A3; + export { V4A, V4A1, V4A2, V4A3, + V4A$make, + V4A1$make, + V4A2$make, + V4A3$make, } /* No side effect */ diff --git a/tests/tests/src/mario_game.mjs b/tests/tests/src/mario_game.mjs index 1da97ecb645..eca037f2378 100644 --- a/tests/tests/src/mario_game.mjs +++ b/tests/tests/src/mario_game.mjs @@ -3060,6 +3060,12 @@ let Main = { preload: preload }; +let Sprite$make = make; + +let Particle$make = make$1; + +let Viewport$make = make$3; + export { Random, Actors, @@ -3072,5 +3078,8 @@ export { Director, Procedural_generator, Main, + Sprite$make, + Particle$make, + Viewport$make, } /* Not a pure module */ diff --git a/tests/tests/src/module_missing_conversion.mjs b/tests/tests/src/module_missing_conversion.mjs index e45e16d66bc..1410309823a 100644 --- a/tests/tests/src/module_missing_conversion.mjs +++ b/tests/tests/src/module_missing_conversion.mjs @@ -40,9 +40,12 @@ let u = [Stdlib_String]; let hh = "x".length; +let XX$make = Stdlib_Array.make; + export { XX, u, hh, + XX$make, } /* hh Not a pure module */ diff --git a/tests/tests/src/recursive_react_component.mjs b/tests/tests/src/recursive_react_component.mjs index d7c3005004b..d9f5ba54ac0 100644 --- a/tests/tests/src/recursive_react_component.mjs +++ b/tests/tests/src/recursive_react_component.mjs @@ -50,11 +50,23 @@ let ShadowedByNestedParameter = { let make$1 = Recursive_react_component; +let ShadowedSelfReference$make = Recursive_react_component$ShadowedSelfReference; + +let Leaf$make = Recursive_react_component$Leaf; + +let ShadowedByLocalLet$make = Recursive_react_component$ShadowedByLocalLet; + +let ShadowedByNestedParameter$make = Recursive_react_component$ShadowedByNestedParameter; + export { make$1 as make, ShadowedSelfReference, Leaf, ShadowedByLocalLet, ShadowedByNestedParameter, + ShadowedSelfReference$make, + Leaf$make, + ShadowedByLocalLet$make, + ShadowedByNestedParameter$make, } /* react Not a pure module */ diff --git a/tests/tests/src/test_pervasive.mjs b/tests/tests/src/test_pervasive.mjs index 6ed0caf27c8..7181f30f136 100644 --- a/tests/tests/src/test_pervasive.mjs +++ b/tests/tests/src/test_pervasive.mjs @@ -146,6 +146,8 @@ function a18(prim0, prim1) { let f = Stdlib_List.concat; +let Pervasives$make = Stdlib_List.make; + export { Pervasives$1 as Pervasives, f, @@ -168,5 +170,6 @@ export { a16, a17, a18, + Pervasives$make, } /* No side effect */ diff --git a/tests/tests/src/test_pervasives3.mjs b/tests/tests/src/test_pervasives3.mjs index 8eec9e8367b..94b27cd07fa 100644 --- a/tests/tests/src/test_pervasives3.mjs +++ b/tests/tests/src/test_pervasives3.mjs @@ -71,8 +71,11 @@ let Pervasives$1 = { let v = Stdlib_List.concat; +let Pervasives$make = Stdlib_List.make; + export { Pervasives$1 as Pervasives, v, + Pervasives$make, } /* No side effect */