···79798080let make_worker url =
8181 let worker = make_worker @@ Webworker.create @@ Jstr.of_string url in
8282+ let ready, set_ready = Fut.create () in
8283 let on_message m =
8384 let m = Brr.Ev.as_type m in
8485 let data_marshaled = Brr_io.Message.Ev.data m |> Js_of_ocaml.Js.to_bytestring in
8586 let data : Protocol.answer = Marshal.from_string data_marshaled 0 in
8686- on_message worker data
8787+ match data with
8888+ | Protocol.Ready -> set_ready ()
8989+ | _ -> on_message worker data
8790 in
8891 let _listen =
8992 Brr.Ev.listen Brr_io.Message.Ev.message on_message
9093 @@ Webworker.as_target worker.worker
9194 in
9292- worker
9595+ worker, ready
+10-2
src/extension/merlin_codemirror.ml
···1414 let linter worker = fun view ->
1515 let open Fut.Syntax in
1616 let doc = Utils.get_full_doc @@ Editor.View.state view in
1717+ let* worker = worker in
1718 let+ result = Merlin_client.query_errors worker doc in
1819 List.map (fun Protocol.{ kind; loc; main; sub = _; source } ->
1920 let from = loc.loc_start.pos_cnum in
···4748 let source = Utils.get_full_doc @@ Autocomplete.Context.state ctx in
4849 let pos = Autocomplete.Context.pos ctx in
4950 let+ { from; to_; entries } =
5151+ let* worker = worker in
5052 Merlin_client.query_completions worker source (`Offset pos)
5153 in
5254 let options =
···7274 let open Fut.Syntax in
7375 let doc = Utils.get_full_doc @@ Editor.View.state view in
7476 let pos = `Offset pos in
7777+ let* worker = worker in
7578 let+ result = Merlin_client.query_type worker doc pos in
7679 match result with
7780 | (loc, `String type_, _)::_ ->
···100103101104module Make (Config : Config) = struct
102105 let worker =
103103- let worker = Merlin_client.make_worker Config.worker_url in
104104- let _ = Merlin_client.add_cmis worker Config.cmis in
106106+ let open Fut.Syntax in
107107+ let worker, ready = Merlin_client.make_worker Config.worker_url in
108108+ let* () = ready in
109109+ (* Initial Cmi loading should be the first request. Todo: make it clearer in
110110+ the protocol that this is a mandatory initial exchange: Start worker ->
111111+ worker sends Ready -> client sends Add_cmis *)
112112+ let+ () = Merlin_client.add_cmis worker Config.cmis in
105113 worker
106114107115 open Extensions (Merlin_client.Webworker)
+4-4
src/extension/merlin_codemirror.mli
···37373838 type worker = Merlin_client.Make(Worker).worker
39394040- val autocomplete : worker -> Code_mirror.Extension.t
4040+ val autocomplete : worker Fut.t -> Code_mirror.Extension.t
4141 (** An extension providing completions when typing *)
42424343- val tooltip_on_hover : worker -> Code_mirror.Extension.t
4343+ val tooltip_on_hover : worker Fut.t -> Code_mirror.Extension.t
4444 (** An extension providing type-information when hovering code *)
45454646- val linter : worker -> Code_mirror.Extension.t
4646+ val linter : worker Fut.t -> Code_mirror.Extension.t
4747 (** An extension that highlights errors and warnings in the code *)
48484949- val all_extensions : worker -> Code_mirror.Extension.t array
4949+ val all_extensions : worker Fut.t -> Code_mirror.Extension.t array
5050 (** All the Merlin-specific extensions (does not include [ocaml]) *)
51515252end
+14
src/protocol/protocol.ml
···4646 | All_errors of source
4747 | Add_cmis of cmis
48484949+let action_to_string = function
5050+| Complete_prefix _ -> "Complete_prefix"
5151+| Type_enclosing _ -> "Type_enclosing"
5252+| All_errors _ -> "All_errors"
5353+| Add_cmis _ -> "Add_cmis"
5454+4955type error = {
5056 kind : Location.report_kind;
5157 loc: Location.t;
···65716672(* type errors = { from: int; to_: int; entries: error list } *)
6773type answer =
7474+ | Ready
6875 | Errors of error list
6976 | Completions of completions
7077 | Typed_enclosings of
7178 (Location.t * [ `Index of int | `String of string ] * is_tail_position) list
7279 | Added_cmis
8080+8181+let answer_to_string = function
8282+ | Ready -> "Ready"
8383+ | Errors _ -> "Errors"
8484+ | Completions _ -> "Completions"
8585+ | Typed_enclosings _ -> "Type_enclosings"
8686+ | Added_cmis -> "Added_cmis"
73877488let report_source_to_string = function
7589 | Location.Lexer -> "lexer"
+18-8
src/worker/worker.ml
···55module Location = Ocaml_parsing.Location
6677let stdlib_path = "/static/cmis"
88+let log s = Console.console##log (Js.string s)
89910let sync_get url =
1011 let x = XmlHttpRequest.create () in
···251252 | Add_cmis cmis ->
252253 add_cmis cmis
253254255255+let post res =
256256+ Marshal.to_string res []
257257+ |> Js.bytestring
258258+ |> Worker.post_message
259259+254260let run () =
255261 Console.console##log (Js.string "Worker running");
256256- Worker.set_onmessage @@ fun marshaled_message ->
257257- Console.console##log (Js.string "Received message");
258258- let action : Protocol.action =
259259- let str = Js.to_bytestring marshaled_message in
260260- Marshal.from_string str 0 in
261261- let res = on_message action in
262262- let res = Marshal.to_string res [] |> Js.bytestring in
263263- Worker.post_message res
262262+ Worker.set_onmessage (fun marshaled_message ->
263263+ let action : Protocol.action =
264264+ let str = Js.to_bytestring marshaled_message in
265265+ Marshal.from_string str 0
266266+ in
267267+ log @@ Printf.sprintf "Received message with action %S"
268268+ (Protocol.action_to_string action);
269269+ let res = on_message action in
270270+ log @@ Printf.sprintf "Sending message with answer %S"
271271+ (Protocol.answer_to_string res);
272272+ post res);
273273+ post Protocol.Ready