5252 * v5: Removed .ml support.
5353 * v6: Added `config.experimental_features` and `config.jsx_preserve_mode` to the BundleConfig.
5454 * v7: Added debug dump output APIs for developer playground tooling.
55+ * v8: Added genType and source map configuration and compilation outputs.
5556 * *)
56- let api_version = " 7 "
57+ let api_version = " 8 "
5758
5859module Js = Js_of_ocaml. Js
5960
@@ -78,6 +79,10 @@ module Bundle_config = struct
7879 mutable open_modules : string list ;
7980 mutable experimental_features : string list ;
8081 mutable jsx_preserve_mode : bool ;
82+ mutable gentype_enabled : bool ;
83+ mutable source_map_mode : Js_config .source_map ;
84+ mutable source_map_sources_content : bool ;
85+ mutable source_map_root : string ;
8186 }
8287
8388 let make () =
@@ -88,6 +93,10 @@ module Bundle_config = struct
8893 open_modules = [] ;
8994 experimental_features = [] ;
9095 jsx_preserve_mode = false ;
96+ gentype_enabled = false ;
97+ source_map_mode = No_source_map ;
98+ source_map_sources_content = false ;
99+ source_map_root = " " ;
91100 }
92101
93102 let default_filename (lang : Lang.t ) = " playground." ^ Lang. to_string lang
@@ -96,6 +105,21 @@ module Bundle_config = struct
96105 match m with
97106 | Ext_module_system. Commonjs -> " commonjs"
98107 | Esmodule -> " esmodule"
108+
109+ let source_map_of_string value =
110+ match String. lowercase_ascii value with
111+ | "linked" -> Some Js_config. Linked
112+ | "inline" -> Some Inline
113+ | "hidden" -> Some Hidden
114+ | "false" | "none" | "disabled" -> Some No_source_map
115+ | _ -> None
116+
117+ let string_of_source_map mode =
118+ match mode with
119+ | Js_config. Linked -> " linked"
120+ | Inline -> " inline"
121+ | Hidden -> " hidden"
122+ | No_source_map -> " false"
99123end
100124
101125type loc_err_info = {
@@ -473,6 +497,127 @@ module Compile = struct
473497 List. iter Iter. iter_structure_item structure.str_items;
474498 Js. array (! acc |> Array. of_list)
475499
500+ let gentype_output ~module_system ~modulename ~sourcefile structure env =
501+ let cmt_annots = Cmt_format. Implementation structure in
502+ let input_cmt =
503+ {
504+ Cmt_format. cmt_modname = modulename;
505+ cmt_annots;
506+ cmt_value_dependencies = [] ;
507+ cmt_comments = [] ;
508+ cmt_args = [||];
509+ cmt_sourcefile = Some sourcefile;
510+ cmt_builddir = Sys. getcwd () ;
511+ cmt_loadpath = ! Config. load_path;
512+ cmt_source_digest = None ;
513+ cmt_initial_env = env;
514+ cmt_imports = [] ;
515+ cmt_interface_digest = None ;
516+ cmt_use_summaries = false ;
517+ cmt_extra_info = {Cmt_utils. deprecated_used = [] };
518+ }
519+ in
520+ let has_gentype_annotations =
521+ Gentype_main. cmt_check_annotations input_cmt
522+ ~check_annotation: (fun ~loc :_ attributes ->
523+ attributes
524+ |> Annotation. get_attribute_payload
525+ Annotation. tag_is_one_of_the_gentype_annotations
526+ <> None )
527+ in
528+ if has_gentype_annotations then
529+ let module_ =
530+ match module_system with
531+ | Ext_module_system. Commonjs -> Gentype_config. CommonJS
532+ | Esmodule -> ESModule
533+ in
534+ let project_root = Sys. getcwd () in
535+ let config =
536+ {
537+ Gentype_config. default with
538+ module_;
539+ platform_lib = " rescript" ;
540+ project_root;
541+ bsb_project_root = project_root;
542+ suffix = Literals. suffix_js;
543+ }
544+ in
545+ let source_file = sourcefile in
546+ let output_file_relative =
547+ source_file |> Paths. get_output_file_relative ~config
548+ in
549+ let file_name =
550+ sourcefile |> Filename. basename |> Filename. remove_extension
551+ |> Module_name. from_string_unsafe
552+ in
553+ let resolver =
554+ Module_resolver. create_lazy_resolver ~config
555+ ~extensions: [" .res" ; " .shim.ts" ] ~exclude_file: (fun _ -> false )
556+ in
557+ let code_text =
558+ input_cmt
559+ |> Gentype_main. translate_cmt ~config ~output_file_relative ~resolver
560+ |> Emit_js. emit_translation_as_string ~config ~file_name
561+ ~output_file_relative ~resolver
562+ ~input_cmt_translate_type_declarations:
563+ Gentype_main. input_cmt_translate_type_declarations
564+ in
565+ Emit_type. file_header ~source_file: (Filename. basename source_file)
566+ ^ " \n " ^ code_text ^ " \n "
567+ else " No @gentype annotations found."
568+
569+ let render_javascript ~module_system ~filename ~source ~source_map_mode
570+ ~source_map_sources_content ~source_map_root lambda_output =
571+ let buffer = Buffer. create 1000 in
572+ let generated_file =
573+ Filename. concat (Sys. getcwd () )
574+ (Filename. remove_extension (Filename. basename filename)
575+ ^ Literals. suffix_js)
576+ in
577+ let source_map_builder =
578+ match source_map_mode with
579+ | Js_config. No_source_map -> None
580+ | Linked | Inline | Hidden ->
581+ Some
582+ (Js_source_map. make ~generated_file ~source_root: source_map_root
583+ ~sources_content: source_map_sources_content)
584+ in
585+ let print_javascript () =
586+ Js_dump_program. pp_deps_program ~output_prefix: " " module_system
587+ lambda_output
588+ (Ext_pp. from_buffer buffer)
589+ in
590+ (match source_map_builder with
591+ | None -> print_javascript ()
592+ | Some builder ->
593+ let source_file =
594+ if Filename. is_relative filename then
595+ Filename. concat (Sys. getcwd () ) filename
596+ else filename
597+ in
598+ let source_dir = Filename. dirname source_file in
599+ Js_of_ocaml.Sys_js. mount ~path: source_dir (fun ~prefix :_ ~path ->
600+ if path = Filename. basename source_file then Some source else None );
601+ Ext_pervasives. finally ()
602+ ~clean: (fun () -> Js_of_ocaml.Sys_js. unmount ~path: source_dir)
603+ (fun () -> Js_source_map. with_builder builder print_javascript));
604+ let source_map =
605+ match source_map_builder with
606+ | None -> None
607+ | Some builder ->
608+ let json = Js_source_map. json builder in
609+ (match source_map_mode with
610+ | Linked ->
611+ Buffer. add_string buffer
612+ (Js_source_map. linked_comment ~map_file: (generated_file ^ " .map" ))
613+ | Inline ->
614+ Buffer. add_string buffer (Js_source_map. inline_comment ~json )
615+ | Hidden -> ()
616+ | No_source_map -> assert false );
617+ Some json
618+ in
619+ (Buffer. contents buffer, source_map)
620+
476621 let implementation ?(include_debug_outputs = false )
477622 ~(config : Bundle_config.t ) ~lang str =
478623 let {
@@ -481,6 +626,10 @@ module Compile = struct
481626 open_modules;
482627 experimental_features;
483628 jsx_preserve_mode;
629+ gentype_enabled;
630+ source_map_mode;
631+ source_map_sources_content;
632+ source_map_root;
484633 } =
485634 config
486635 in
@@ -502,6 +651,9 @@ module Compile = struct
502651 let types_signature = ref [] in
503652 Js_config. jsx_version := Some Js_config. Jsx_v4 ;
504653 Js_config. jsx_preserve := jsx_preserve_mode;
654+ Js_config. source_map := source_map_mode;
655+ Js_config. source_map_sources_content := source_map_sources_content;
656+ Js_config. source_map_root := source_map_root;
505657 experimental_features
506658 |> List. iter Experimental_features. enable_from_string;
507659 (* default *)
@@ -519,27 +671,34 @@ module Compile = struct
519671 let {Translmod. lambda; exports; hoisted_functions} =
520672 Translmod. transl_implementation modulename typed_tree
521673 in
522- let buffer = Buffer. create 1000 in
523- let () =
524- Js_dump_program. pp_deps_program ~output_prefix: " "
525- (* does not matter here *) module_system
526- ( Lam_compile_main. compile " " exports hoisted_functions lambda)
527- ( Ext_pp. from_buffer buffer)
674+ let lambda_output =
675+ Lam_compile_main. compile " " exports hoisted_functions lambda
676+ in
677+ let js_code, source_map =
678+ render_javascript ~module_system ~filename ~source: str ~source_map_mode
679+ ~source_map_sources_content ~source_map_root lambda_output
528680 in
529- let v = Buffer. contents buffer in
530681 let type_hints = collect_type_hints typed_tree in
682+ let source_map_attrs =
683+ match source_map with
684+ | None -> [||]
685+ | Some source_map ->
686+ Js.Unsafe. [|(" source_map" , inject @@ Js. string source_map)|]
687+ in
531688 let attrs =
532- Js.Unsafe.
533- [|
534- (" js_code" , inject @@ Js. string v);
535- ( " warnings" ,
536- inject
537- @@ (! warning_infos
538- |> Array. map Error_ret. make_warning
539- |> Js. array |> inject) );
540- (" type_hints" , inject @@ type_hints);
541- (" type" , inject @@ Js. string " success" );
542- |]
689+ Array. append
690+ Js.Unsafe.
691+ [|
692+ (" js_code" , inject @@ Js. string js_code);
693+ ( " warnings" ,
694+ inject
695+ @@ (! warning_infos
696+ |> Array. map Error_ret. make_warning
697+ |> Js. array |> inject) );
698+ (" type_hints" , inject @@ type_hints);
699+ (" type" , inject @@ Js. string " success" );
700+ |]
701+ source_map_attrs
543702 in
544703 if include_debug_outputs then
545704 let parsetree = Printer. to_string Printast. implementation ast in
@@ -548,6 +707,19 @@ module Compile = struct
548707 in
549708 let lambda_output = Printer. to_string Printlambda. lambda lambda in
550709 let lam = Printlambda. lambda_to_string lambda in
710+ let gentype_attrs =
711+ if gentype_enabled then
712+ let structure, _ = typed_tree in
713+ Js.Unsafe.
714+ [|
715+ ( " gentype" ,
716+ inject
717+ @@ Js. string
718+ (gentype_output ~module_system ~modulename
719+ ~sourcefile: filename structure env) );
720+ |]
721+ else [||]
722+ in
551723 let debug_attrs =
552724 Js.Unsafe.
553725 [|
@@ -557,7 +729,7 @@ module Compile = struct
557729 (" lam" , inject @@ Js. string lam);
558730 |]
559731 in
560- Js.Unsafe. obj (Array. append attrs debug_attrs)
732+ Js.Unsafe. obj (Array. concat [ attrs; debug_attrs; gentype_attrs] )
561733 else Js.Unsafe. obj attrs
562734 with e -> (
563735 match e with
@@ -658,6 +830,25 @@ module Export = struct
658830 config.jsx_preserve_mode < - value;
659831 true
660832 in
833+ let set_gentype_enabled value =
834+ config.gentype_enabled < - value;
835+ true
836+ in
837+ let set_source_map_mode value =
838+ match Bundle_config. source_map_of_string value with
839+ | Some source_map_mode ->
840+ config.source_map_mode < - source_map_mode;
841+ true
842+ | None -> false
843+ in
844+ let set_source_map_sources_content value =
845+ config.source_map_sources_content < - value;
846+ true
847+ in
848+ let set_source_map_root value =
849+ config.source_map_root < - value;
850+ true
851+ in
661852 let convert_syntax ~(from_lang : string ) ~(to_lang : string ) (src : string )
662853 =
663854 let open Lang in
@@ -716,6 +907,22 @@ module Export = struct
716907 inject
717908 @@ Js. wrap_meth_callback (fun _ value ->
718909 Js. bool (set_jsx_preserve_mode (Js. to_bool value))) );
910+ ( " setGentypeEnabled" ,
911+ inject
912+ @@ Js. wrap_meth_callback (fun _ value ->
913+ Js. bool (set_gentype_enabled (Js. to_bool value))) );
914+ ( " setSourceMapMode" ,
915+ inject
916+ @@ Js. wrap_meth_callback (fun _ value ->
917+ Js. bool (set_source_map_mode (Js. to_string value))) );
918+ ( " setSourceMapSourcesContent" ,
919+ inject
920+ @@ Js. wrap_meth_callback (fun _ value ->
921+ Js. bool (set_source_map_sources_content (Js. to_bool value))) );
922+ ( " setSourceMapRoot" ,
923+ inject
924+ @@ Js. wrap_meth_callback (fun _ value ->
925+ Js. bool (set_source_map_root (Js. to_string value))) );
719926 ( " getConfig" ,
720927 inject
721928 @@ Js. wrap_meth_callback (fun _ ->
@@ -730,6 +937,17 @@ module Export = struct
730937 (" warn_flags" , inject @@ Js. string config.warn_flags);
731938 ( " jsx_preserve_mode" ,
732939 inject @@ (config.jsx_preserve_mode |> Js. bool ) );
940+ ( " gentype_enabled" ,
941+ inject @@ (config.gentype_enabled |> Js. bool ) );
942+ ( " source_map_mode" ,
943+ inject
944+ @@ (config.source_map_mode
945+ |> Bundle_config. string_of_source_map |> Js. string ) );
946+ ( " source_map_sources_content" ,
947+ inject @@ (config.source_map_sources_content |> Js. bool )
948+ );
949+ ( " source_map_root" ,
950+ inject @@ Js. string config.source_map_root );
733951 ( " experimental_features" ,
734952 inject
735953 @@ (config.experimental_features |> Array. of_list
0 commit comments