this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

wip - findlibish

+344 -51
+12
example/dune
··· 32 32 33 33 (executable 34 34 (name unix_client) 35 + (public_name unix_client) 36 + (package js_top_worker-unix) 35 37 (modules unix_client) 36 38 (libraries js_top_worker_client rpclib.cmdliner)) 37 39 ··· 42 44 (system "mkdir -p cmis; cp %{ocaml_where}/*.cmi cmis"))) 43 45 44 46 (rule 47 + (targets 48 + (dir lib)) 49 + (deps mklib.sh) 50 + (action 51 + (system "./mklib.sh"))) 52 + 53 + (rule 45 54 (targets worker.js) 46 55 (deps stubs.js) 47 56 (action ··· 50 59 --toplevel 51 60 ; --pretty 52 61 --no-cmis 62 + --effects=cps 53 63 +toplevel.js 54 64 +dynlink.js 65 + +bigstringaf/runtime.js 55 66 stubs.js 56 67 %{dep:worker.bc} 57 68 -o ··· 66 77 --toplevel 67 78 ; --pretty 68 79 --no-cmis 80 + --effects=cps 69 81 +toplevel.js 70 82 +dynlink.js 71 83 stubs.js
+4 -1
example/example.ml
··· 15 15 path = "/static/cmis"; 16 16 cmas = []; 17 17 cmis = { dynamic_cmis = []; static_cmis = [] }; 18 + stdlib_dcs = "/lib/ocaml/dynamic_cmis.json"; 19 + findlib_metas = ["/lib/astring/META"]; 20 + findlib_requires = ["astring"]; 18 21 } 19 22 in 20 23 Lwt.return (Ok rpc) ··· 42 45 let* rpc = initialise "worker.js" (fun _ -> log "Timeout") in 43 46 let* o = W.setup rpc () in 44 47 log_output o; 45 - let* o = W.exec rpc "2*2;;" in 48 + let* o = W.exec rpc "Astring.String.fields \"foo bar baz\";;" in 46 49 log_output o; 47 50 Lwt.return (Ok ())
+3
example/example2.ml
··· 19 19 path = "/static/cmis"; 20 20 cmas = []; 21 21 cmis = { dynamic_cmis = [dcs]; static_cmis = [] }; 22 + stdlib_dcs = "/lib/ocaml/dynamic_cmis.json"; 23 + findlib_metas = []; 24 + findlib_requires = []; 22 25 } 23 26 in 24 27 Lwt.return (Ok rpc)
+26
example/mklib.sh
··· 1 + #!/bin/bash 2 + 3 + mkdir -p lib/ocaml 4 + cp $OPAM_SWITCH_PREFIX/lib/ocaml/*.cmi lib/ocaml/ 5 + mkdir -p lib/astring 6 + cp $OPAM_SWITCH_PREFIX/lib/astring/META lib/astring 7 + cp $OPAM_SWITCH_PREFIX/lib/astring/*.cmi lib/astring 8 + 9 + js_of_ocaml $OPAM_SWITCH_PREFIX/lib/astring/astring.cma -o lib/astring/astring.cma.js --effects=cps 10 + 11 + cat > lib/ocaml/dynamic_cmis.json << EOF 12 + { 13 + dcs_url: "/lib/ocaml/", 14 + dcs_toplevel_modules: ["CamlinternalOO","Stdlib","CamlinternalFormat","Std_exit","CamlinternalMod","CamlinternalFormatBasics","CamlinternalLazy"], 15 + dcs_file_prefixes : ["stdlib__"] 16 + } 17 + EOF 18 + 19 + cat > lib/astring/dynamic_cmis.json << EOF 20 + { 21 + dcs_url: "/lib/astring/", 22 + dcs_toplevel_modules: ["Astring"], 23 + dcs_file_prefixes : [] 24 + } 25 + EOF 26 +
+27 -2
example/unix_worker.ml
··· 92 92 binary_handler rpcfn this_connection |> M.run) 93 93 done 94 94 95 + let handle_findlib_error = function 96 + | Failure msg -> 97 + Printf.fprintf stderr "%s" msg 98 + | Fl_package_base.No_such_package(pkg, reason) -> 99 + Printf.fprintf stderr "No such package: %s%s\n" pkg (if reason <> "" then " - " ^ reason else "") 100 + | Fl_package_base.Package_loop pkg -> 101 + Printf.fprintf stderr "Package requires itself: %s\n" pkg 102 + | exn -> 103 + raise exn 104 + 95 105 module Server = Js_top_worker_rpc.Toplevel_api_gen.Make (Impl.IdlM.GenServer ()) 96 106 97 107 module S : Impl.S = struct 108 + type findlib_t = unit 109 + 98 110 let capture = capture 99 111 let sync_get _ = None 100 112 let create_file ~name:_ ~content:_ = failwith "Not implemented" ··· 102 114 let import_scripts urls = if List.length urls > 0 then failwith "Not implemented" else () 103 115 104 116 let init_function _ () = failwith "Not implemented" 117 + 118 + let findlib_init _ = () 119 + 120 + let get_stdlib_dcs _uri = 121 + [] 122 + 123 + let require () packages = 124 + try 125 + let eff_packages = Findlib.package_deep_ancestors !Topfind.predicates packages in 126 + Topfind.load eff_packages; [] 127 + with exn -> 128 + handle_findlib_error exn; [] 105 129 end 106 130 107 131 module U = Impl.Make (S) ··· 110 134 let open U in 111 135 Logs.set_reporter (Logs_fmt.reporter ()); 112 136 Logs.set_level (Some Logs.Info); 113 - let pid = Unix.getpid () in 137 + (* let pid = Unix.getpid () in *) 114 138 Server.exec execute; 115 139 Server.setup setup; 116 140 Server.init init; ··· 119 143 Server.query_errors query_errors; 120 144 Server.type_enclosing type_enclosing; 121 145 Server.compile_js compile_js; 146 + Server.exec_toplevel exec_toplevel; 122 147 let rpc_fn = IdlM.server Server.implementation in 123 148 let process x = 124 149 let open M in ··· 126 151 >>= fun response -> Jsonrpc.string_of_response response |> return 127 152 in 128 153 serve_requests process 129 - (Js_top_worker_rpc.Toplevel_api_gen.sockpath ^ string_of_int pid) 154 + (Js_top_worker_rpc.Toplevel_api_gen.sockpath) 130 155 131 156 let _ = start_server ()
+1 -1
idl/toplevel_api.ml
··· 179 179 } 180 180 [@@deriving rpcty] 181 181 182 - type init_libs = { path : string; cmis : cmis; cmas : cma list } [@@deriving rpcty] 182 + type init_libs = { path : string; cmis : cmis; cmas : cma list; findlib_metas : string list; findlib_requires : string list; stdlib_dcs : string } [@@deriving rpcty] 183 183 type err = InternalError of string [@@deriving rpcty] 184 184 185 185 type opt_id = string option [@@deriving rpcty]
+83 -17
idl/toplevel_api_gen.ml
··· 1948 1948 and _ = typ_of_cma 1949 1949 and _ = cma 1950 1950 end[@@ocaml.doc "@inline"][@@merlin.hide ] 1951 - type init_libs = { 1951 + type init_libs = 1952 + { 1952 1953 path: string ; 1953 1954 cmis: cmis ; 1954 - cmas: cma list }[@@deriving rpcty] 1955 + cmas: cma list ; 1956 + findlib_metas: string list ; 1957 + findlib_requires: string list ; 1958 + stdlib_dcs: string }[@@deriving rpcty] 1955 1959 include 1956 1960 struct 1957 1961 let _ = fun (_ : init_libs) -> () ··· 1985 1989 Rpc.Types.fget = (fun _r -> _r.cmas); 1986 1990 Rpc.Types.fset = (fun v -> fun _s -> { _s with cmas = v }) 1987 1991 } 1992 + and init_libs_findlib_metas : (_, init_libs) Rpc.Types.field = 1993 + { 1994 + Rpc.Types.fname = "findlib_metas"; 1995 + Rpc.Types.field = 1996 + (Rpc.Types.List (let open Rpc.Types in Basic String)); 1997 + Rpc.Types.fdefault = None; 1998 + Rpc.Types.fdescription = []; 1999 + Rpc.Types.fversion = None; 2000 + Rpc.Types.fget = (fun _r -> _r.findlib_metas); 2001 + Rpc.Types.fset = (fun v -> fun _s -> { _s with findlib_metas = v }) 2002 + } 2003 + and init_libs_findlib_requires : (_, init_libs) Rpc.Types.field = 2004 + { 2005 + Rpc.Types.fname = "findlib_requires"; 2006 + Rpc.Types.field = 2007 + (Rpc.Types.List (let open Rpc.Types in Basic String)); 2008 + Rpc.Types.fdefault = None; 2009 + Rpc.Types.fdescription = []; 2010 + Rpc.Types.fversion = None; 2011 + Rpc.Types.fget = (fun _r -> _r.findlib_requires); 2012 + Rpc.Types.fset = 2013 + (fun v -> fun _s -> { _s with findlib_requires = v }) 2014 + } 2015 + and init_libs_stdlib_dcs : (_, init_libs) Rpc.Types.field = 2016 + { 2017 + Rpc.Types.fname = "stdlib_dcs"; 2018 + Rpc.Types.field = (let open Rpc.Types in Basic String); 2019 + Rpc.Types.fdefault = None; 2020 + Rpc.Types.fdescription = []; 2021 + Rpc.Types.fversion = None; 2022 + Rpc.Types.fget = (fun _r -> _r.stdlib_dcs); 2023 + Rpc.Types.fset = (fun v -> fun _s -> { _s with stdlib_dcs = v }) 2024 + } 1988 2025 and typ_of_init_libs = 1989 2026 Rpc.Types.Struct 1990 2027 ({ 1991 2028 Rpc.Types.fields = 1992 2029 [Rpc.Types.BoxedField init_libs_path; 1993 2030 Rpc.Types.BoxedField init_libs_cmis; 1994 - Rpc.Types.BoxedField init_libs_cmas]; 2031 + Rpc.Types.BoxedField init_libs_cmas; 2032 + Rpc.Types.BoxedField init_libs_findlib_metas; 2033 + Rpc.Types.BoxedField init_libs_findlib_requires; 2034 + Rpc.Types.BoxedField init_libs_stdlib_dcs]; 1995 2035 Rpc.Types.sname = "init_libs"; 1996 2036 Rpc.Types.version = None; 1997 2037 Rpc.Types.constructor = 1998 2038 (fun getter -> 1999 2039 let open Rresult.R in 2000 - (getter.Rpc.Types.field_get "cmas" 2001 - (Rpc.Types.List typ_of_cma)) 2040 + (getter.Rpc.Types.field_get "stdlib_dcs" 2041 + (let open Rpc.Types in Basic String)) 2002 2042 >>= 2003 - (fun init_libs_cmas -> 2004 - (getter.Rpc.Types.field_get "cmis" typ_of_cmis) >>= 2005 - (fun init_libs_cmis -> 2006 - (getter.Rpc.Types.field_get "path" 2007 - (let open Rpc.Types in Basic String)) 2043 + (fun init_libs_stdlib_dcs -> 2044 + (getter.Rpc.Types.field_get "findlib_requires" 2045 + (Rpc.Types.List 2046 + (let open Rpc.Types in Basic String))) 2047 + >>= 2048 + (fun init_libs_findlib_requires -> 2049 + (getter.Rpc.Types.field_get "findlib_metas" 2050 + (Rpc.Types.List 2051 + (let open Rpc.Types in Basic String))) 2008 2052 >>= 2009 - (fun init_libs_path -> 2010 - return 2011 - { 2012 - path = init_libs_path; 2013 - cmis = init_libs_cmis; 2014 - cmas = init_libs_cmas 2015 - })))) 2053 + (fun init_libs_findlib_metas -> 2054 + (getter.Rpc.Types.field_get "cmas" 2055 + (Rpc.Types.List typ_of_cma)) 2056 + >>= 2057 + (fun init_libs_cmas -> 2058 + (getter.Rpc.Types.field_get "cmis" 2059 + typ_of_cmis) 2060 + >>= 2061 + (fun init_libs_cmis -> 2062 + (getter.Rpc.Types.field_get "path" 2063 + (let open Rpc.Types in 2064 + Basic String)) 2065 + >>= 2066 + (fun init_libs_path -> 2067 + return 2068 + { 2069 + path = init_libs_path; 2070 + cmis = init_libs_cmis; 2071 + cmas = init_libs_cmas; 2072 + findlib_metas = 2073 + init_libs_findlib_metas; 2074 + findlib_requires = 2075 + init_libs_findlib_requires; 2076 + stdlib_dcs = 2077 + init_libs_stdlib_dcs 2078 + }))))))) 2016 2079 } : init_libs Rpc.Types.structure) 2017 2080 and init_libs = 2018 2081 { ··· 2023 2086 let _ = init_libs_path 2024 2087 and _ = init_libs_cmis 2025 2088 and _ = init_libs_cmas 2089 + and _ = init_libs_findlib_metas 2090 + and _ = init_libs_findlib_requires 2091 + and _ = init_libs_stdlib_dcs 2026 2092 and _ = typ_of_init_libs 2027 2093 and _ = init_libs 2028 2094 end[@@ocaml.doc "@inline"][@@merlin.hide ]
+3 -2
lib/dune
··· 8 8 js_top_worker-rpc 9 9 js_of_ocaml-compiler 10 10 js_of_ocaml-ppx 11 + js_of_ocaml 11 12 astring 12 13 mime_printer 13 14 compiler-libs.common ··· 31 32 (library 32 33 (public_name js_top_worker-web) 33 34 (name js_top_worker_web) 34 - (modules worker) 35 + (modules worker findlibish jslib) 35 36 (preprocess 36 37 (pps js_of_ocaml-ppx)) 37 - (libraries js_top_worker js_of_ocaml-toplevel logs.browser)) 38 + (libraries js_top_worker js_of_ocaml-toplevel logs.browser uri angstrom findlib fpath)) 38 39 39 40 (ocamllex uTop_lexer)
+127
lib/findlibish.ml
··· 1 + (* Kinda findlib, sorta *) 2 + 3 + 4 + type library = { 5 + name : string; 6 + meta_uri : Uri.t; 7 + archive_name : string option; 8 + dir : string option; 9 + deps : string list; 10 + mutable loaded : bool; 11 + } 12 + 13 + let read_libraries_from_pkg_defs ~library_name meta_uri pkg_defs = 14 + try 15 + let archive_filename = 16 + try Some (Fl_metascanner.lookup "archive" [ "byte" ] pkg_defs) 17 + with _ -> ( 18 + try Some (Fl_metascanner.lookup "archive" [ "native" ] pkg_defs) 19 + with _ -> None) 20 + in 21 + 22 + let deps_str = Fl_metascanner.lookup "requires" [] pkg_defs in 23 + let deps = Astring.String.fields ~empty:false deps_str in 24 + let dir = 25 + List.find_opt (fun d -> d.Fl_metascanner.def_var = "directory") pkg_defs 26 + in 27 + let dir = Option.map (fun d -> d.Fl_metascanner.def_value) dir in 28 + let archive_name = 29 + Option.bind archive_filename (fun a -> 30 + let file_name_len = String.length a in 31 + if file_name_len > 0 then Some (Filename.chop_extension a) else None) 32 + in 33 + [ { name = library_name; archive_name; dir; deps; meta_uri; loaded=false } ] 34 + with Not_found -> [] 35 + 36 + 37 + type t = library list 38 + 39 + let dcs_filename = "dynamic_cmis.json" 40 + 41 + let fetch_dynamic_cmis url = 42 + match Jslib.sync_get url with 43 + | None -> Error (`Msg "Failed to fetch dynamic cmis") 44 + | Some json -> 45 + let rpc = Jsonrpc.of_string json in 46 + Rpcmarshal.unmarshal Js_top_worker_rpc.Toplevel_api_gen.typ_of_dynamic_cmis rpc 47 + 48 + let init findlib_metas : t = 49 + let metas = List.filter_map (fun x -> 50 + match Jslib.sync_get x with 51 + | Some meta -> Some (x, meta) 52 + | None -> None) findlib_metas in 53 + List.flatten @@ List.filter_map (fun (x, meta) -> 54 + match Angstrom.parse_string ~consume:All Uri.Parser.uri_reference x with 55 + | Ok uri -> ( 56 + Jslib.log "Parsed uri: %s" (Uri.path uri); 57 + let path = Uri.path uri in 58 + let file = Fpath.v path in 59 + let base_library_name = 60 + if Fpath.basename file = "META" then Fpath.parent file |> Fpath.basename 61 + else Fpath.get_ext file 62 + in 63 + 64 + let lexing = Lexing.from_string meta in 65 + try 66 + let meta = Fl_metascanner.parse_lexing lexing in 67 + let rec extract_name_and_archive ~prefix 68 + ((name, pkg_expr) : string * Fl_metascanner.pkg_expr) = 69 + let library_name = prefix ^ "." ^ name in 70 + let libraries = 71 + read_libraries_from_pkg_defs ~library_name uri pkg_expr.pkg_defs 72 + in 73 + let child_libraries = 74 + pkg_expr.pkg_children 75 + |> List.map (extract_name_and_archive ~prefix:library_name) 76 + |> List.flatten 77 + in 78 + libraries @ child_libraries 79 + in 80 + let libraries = 81 + read_libraries_from_pkg_defs ~library_name:base_library_name uri meta.pkg_defs 82 + in 83 + let libraries = 84 + libraries 85 + @ (meta.pkg_children 86 + |> List.map (extract_name_and_archive ~prefix:base_library_name) 87 + |> List.flatten) in 88 + Some libraries 89 + with _ -> 90 + Jslib.log "Failed to parse meta: %s" (Uri.path uri); 91 + None) 92 + | Error m -> 93 + Jslib.log "Failed to parse uri: %s" m; None) metas 94 + 95 + 96 + let require v packages = 97 + let rec require dcss package : Js_top_worker_rpc.Toplevel_api_gen.dynamic_cmis list = 98 + match List.find (fun lib -> lib.name = package) v with 99 + | exception Not_found -> 100 + Jslib.log "Package %s not found" package; 101 + dcss 102 + | lib -> 103 + if lib.loaded 104 + then dcss 105 + else begin 106 + let dep_dcs = List.fold_left require dcss lib.deps in 107 + let path = Uri.path lib.meta_uri in 108 + let dir = Fpath.v path |> Fpath.parent in 109 + let dcs = Fpath.(dir / dcs_filename |> to_string) in 110 + let uri = Uri.with_path lib.meta_uri dcs in 111 + match fetch_dynamic_cmis (Uri.to_string uri) with 112 + | Ok dcs -> 113 + let () = match lib.archive_name with 114 + | None -> () 115 + | Some archive -> 116 + let dir = match lib.dir with None -> dir | Some d -> Fpath.append dir (Fpath.v d) in 117 + let archive_js = Fpath.(dir / (archive ^ ".cma.js") |> to_string) in 118 + Js_of_ocaml.Worker.import_scripts [(Uri.with_path uri archive_js |> Uri.to_string)]; 119 + lib.loaded <- true 120 + in 121 + dcs :: dep_dcs 122 + | Error (`Msg m) -> 123 + Jslib.log "Failed to unmarshal dynamic_cms from url %s: %s" (Uri.to_string uri) m; 124 + dcss 125 + end 126 + in 127 + List.fold_left require [] packages
+23 -1
lib/impl.ml
··· 34 34 35 35 end 36 36 module type S = sig 37 + type findlib_t 37 38 val capture : (unit -> 'a) -> unit -> captured * 'a 38 39 val create_file : name:string -> content:string -> unit 39 40 val sync_get : string -> string option 40 41 41 42 val import_scripts : string list -> unit 42 43 val init_function : string -> (unit -> unit ) 44 + 45 + val get_stdlib_dcs : string -> Toplevel_api_gen.dynamic_cmis list 46 + 47 + val findlib_init : string list -> findlib_t 48 + 49 + val require : findlib_t -> string list -> Toplevel_api_gen.dynamic_cmis list 43 50 end 44 51 45 52 module Make (S : S) = struct 46 53 let functions : (unit -> unit) list option ref = ref None 54 + let requires : string list ref = ref [] 47 55 let path : string option ref = ref None 56 + let findlib_v : S.findlib_t option ref = ref None 48 57 49 58 let refill_lexbuf s p ppf buffer len = 50 59 if !p = String.length s then 0 ··· 278 287 Logs.info (fun m -> m "init()"); 279 288 path := Some init_libs.path; 280 289 290 + findlib_v := Some (S.findlib_init init_libs.findlib_metas); 291 + 292 + (match S.get_stdlib_dcs init_libs.stdlib_dcs with 293 + |[dcs] -> add_dynamic_cmis dcs 294 + | _ -> ()); 281 295 Clflags.no_check_prims := true; 282 296 List.iter 283 297 (fun { Toplevel_api_gen.sc_name; sc_content } -> ··· 291 305 292 306 S.import_scripts 293 307 (List.map (fun cma -> cma.Toplevel_api_gen.url) init_libs.cmas); 308 + 309 + requires := init_libs.findlib_requires; 294 310 functions := 295 311 Some 296 312 (List.map ··· 328 344 let err = Format.asprintf "%a" Env.report_error e in 329 345 failwith ("Error: " ^ err)) 330 346 in 331 - 347 + 348 + let dcs = (match !findlib_v with 349 + | Some v -> 350 + S.require v !requires 351 + | None -> []) in 352 + List.iter add_dynamic_cmis dcs; 353 + 332 354 Logs.info (fun m -> m "setup() finished"); 333 355 334 356 IdlM.ErrM.return
+21
lib/jslib.ml
··· 1 + let log fmt = 2 + Format.kasprintf 3 + (fun s -> Js_of_ocaml.(Console.console##log (Js.string s))) 4 + fmt 5 + 6 + let sync_get url = 7 + let open Js_of_ocaml in 8 + let x = XmlHttpRequest.create () in 9 + x##.responseType := Js.string "arraybuffer"; 10 + x##_open (Js.string "GET") (Js.string url) Js._false; 11 + x##send Js.null; 12 + match x##.status with 13 + | 200 -> 14 + Js.Opt.case 15 + (File.CoerceTo.arrayBuffer x##.response) 16 + (fun () -> 17 + Console.console##log (Js.string "Failed to receive file"); 18 + None) 19 + (fun b -> Some (Typed_array.String.of_arrayBuffer b)) 20 + | _ -> None 21 +
+14 -27
lib/worker.ml
··· 1 1 open Js_top_worker_rpc 2 2 open Js_top_worker 3 3 4 - let optbind : 'a option -> ('a -> 'b option) -> 'b option = 5 - fun x fn -> match x with None -> None | Some a -> fn a 6 - 7 - let log fmt = 8 - Format.kasprintf 9 - (fun s -> Js_of_ocaml.(Console.console##log (Js.string s))) 10 - fmt 11 - 12 - let sync_get url = 13 - let open Js_of_ocaml in 14 - let x = XmlHttpRequest.create () in 15 - x##.responseType := Js.string "arraybuffer"; 16 - x##_open (Js.string "GET") (Js.string url) Js._false; 17 - x##send Js.null; 18 - match x##.status with 19 - | 200 -> 20 - Js.Opt.case 21 - (File.CoerceTo.arrayBuffer x##.response) 22 - (fun () -> 23 - Console.console##log (Js.string "Failed to receive file"); 24 - None) 25 - (fun b -> Some (Typed_array.String.of_arrayBuffer b)) 26 - | _ -> None 27 - 28 4 module Server = Toplevel_api_gen.Make (Impl.IdlM.GenServer ()) 29 5 30 6 (* OCamlorg toplevel in a web worker ··· 34 10 thread" keeping the page responsive. *) 35 11 36 12 let server process e = 37 - log "Worker received: %s" e; 13 + Jslib.log "Worker received: %s" e; 38 14 let _, id, call = Jsonrpc.version_id_and_call_of_string e in 39 15 Impl.M.bind (process call) (fun response -> 40 16 let rtxt = Jsonrpc.string_of_response ~id response in 41 - log "Worker sending: %s" rtxt; 17 + Jslib.log "Worker sending: %s" rtxt; 42 18 Js_of_ocaml.Worker.post_message rtxt; 43 19 Impl.M.return ()) 44 20 ··· 57 33 | _ -> None 58 34 59 35 module S : Impl.S = struct 36 + type findlib_t = Findlibish.t 37 + 60 38 let capture : (unit -> 'a) -> unit -> Impl.captured * 'a = 61 39 fun f () -> 62 40 let stdout_buff = Buffer.create 1024 in ··· 74 52 in 75 53 (captured, x) 76 54 77 - let sync_get = sync_get 55 + let sync_get = Jslib.sync_get 78 56 let create_file = Js_of_ocaml.Sys_js.create_file 79 57 58 + let get_stdlib_dcs uri = 59 + Findlibish.fetch_dynamic_cmis uri |> Result.to_list 60 + 80 61 let import_scripts = Js_of_ocaml.Worker.import_scripts 62 + 63 + let findlib_init = Findlibish.init 64 + 65 + let require v = function 66 + | [] -> [] 67 + | packages -> Findlibish.require v packages 81 68 82 69 let init_function func_name = 83 70 let open Js_of_ocaml in