eliom
eliom copied to clipboard
Client closure XXX not found
My compilation instructions:
js_of_eliom -rectypes -ppx -o local/var/www/twittex/eliom/twittex.js -package lwt.ppx -package js_of_ocaml.ppx -package js_of_ocaml.deriving.ppx -package ocsature.client -package markiz \
_client/twittex.cmo
eliomc -rectypes -ppx -a -o local/lib/twittex/twittex.cma \
_server/twittex.cmo
This code:
let btn label t =
button ~a:[ (* a_onclick [%client fun _ -> *)
(* let e = Eliom_content.Html.To_dom.of_textarea ~%editor in *)
(* let b = e##.value##substring 0 e##.selectionStart in *)
(* let s = e##.value##substring e##.selectionStart e##.selectionEnd in *)
(* let a = e##.value##substring e##.selectionEnd e##.value##.length in *)
(* e##.value := *)
(* b##concat_4 (Js.string @@ "{" ^ ~%t ^ " ") s (Js.string " }") a *)
(* ] *)]
[ pcdata label ]
in
Result in an error if I uncomment the commented section:
[eliom:client] Client closure 0gsFm82 not found (is the module linked on the client?)
Uncaught (3) [0, Array(3), bC]
NB: In the same code, I use a a_oninput attribute that works just fine.
It really make no sens to me. And it obviously also make my website impossible to run. Is there any missing flag to my compilation ? (no package is pinned, I only have a "eliom" {>= "6.2"} constraint)
Your compilation instructions look OK, but they are not complete, so I can't tell if anything is missing. How have the _client/twittex.cmo and _server/twitter.cmo been produced? Are you using the standard makefile that we distribute via eliom-distillery?
Where do you call btn?
The full compilation process (after a make clean)
ju:~/workspace/twittex$ make
eliomc -rectypes -ppx -infer -package lwt.ppx -package js_of_ocaml.deriving.ppx -package ocsature.server -package markiz twittex.eliom
js_of_eliom -rectypes -ppx -c -package lwt.ppx -package js_of_ocaml.ppx -package js_of_ocaml.deriving.ppx -package ocsature.client -package markiz twittex.eliom
js_of_eliom -rectypes -ppx -o local/var/www/twittex/eliom/twittex.js -package lwt.ppx -package js_of_ocaml.ppx -package js_of_ocaml.deriving.ppx -package ocsature.client -package markiz \
_client/twittex.cmo
There are some missing primitives
Dummy implementations (raising 'Failure' exception) will be used if they are not available at runtime.
You can prevent the generation of dummy implementations with the commandline option '--disable genprim'
Missing primitives:
caml_channel_descriptor
re_search_forward
unix_close
unix_connect
unix_geteuid
unix_gethostbyname
unix_gethostname
unix_getpid
unix_getppid
unix_getpwuid
unix_lockf
unix_set_close_on_exec
unix_socket
unix_string_of_inet_addr
unix_times
eliomc -rectypes -ppx -c -package lwt.ppx -package js_of_ocaml.deriving.ppx -package ocsature.server -package markiz twittex.eliom
eliomc -rectypes -ppx -a -o local/lib/twittex/twittex.cma \
_server/twittex.cmo
eliomopt -rectypes -ppx -c -package lwt.ppx -package js_of_ocaml.deriving.ppx -package ocsature.server -package markiz twittex.eliom
eliomopt -rectypes -ppx -a -o local/lib/twittex/twittex.cmxa \
_server/twittex.cmx
eliomopt -rectypes -ppx -shared -linkall -o local/lib/twittex/twittex.cmxs local/lib/twittex/twittex.cmxa
ju:~/workspace/twittex$
And the code of the whole app:
open%shared Eliom_content.Html.D
module Twittex_app =
Eliom_registration.App
(struct
let application_name = "twittex"
let global_data_path = None
end)
let main_service =
Eliom_service.create
~path:(Eliom_service.Path [])
~meth:(Eliom_service.Get Eliom_parameter.unit)
()
let%client rec render_document doc =
let out = Buffer.create 1024 in
List.iter (block out) doc ;
Buffer.contents out
and block out = function
| `H (i, content) ->
Buffer.add_string out ("<h" ^ (string_of_int i) ^ ">") ;
inlines out content ;
Buffer.add_string out ("</h" ^ (string_of_int i) ^ ">")
| `P content ->
Buffer.add_string out "<p>" ; inlines out content
| `UL list ->
Buffer.add_string out "<ul>" ; list_item_list out list
| `OL list ->
Buffer.add_string out "<ol>" ; list_item_list out list
and inlines out content : unit = List.iter (inline out) content
and list_item_list out =
List.iter @@ fun (`LI (content, children) ) ->
Buffer.add_string out "<li>" ;
inlines out content ;
match children with
| None -> ()
| Some children -> block out (children :> Markiz.block)
and inline out = function
| `IMG url ->
Buffer.add_string out @@
"<img src=\"" ^ url ^ "\" alt=\"" ^ url ^"\"/>"
| `TEXT txt ->
Buffer.add_string out txt
| `TAG (t, content) ->
Buffer.add_string out ("<"^t^">") ;
inlines out content ;
Buffer.add_string out ("</"^t^">")
| `LINK (uri, content)
->
Buffer.add_string out ("<a href=\""^uri^"\">") ;
inlines out content ;
Buffer.add_string out "</a>"
(* https://www.w3.org/TR/html5/syntax.html#optional-tags *)
let%client render s =
let doc = Markiz.parse (Stream.of_bytes s) in
(render_document doc)
let editor =
let renderer = div
~a:[ a_style
"float:left;border:1px solid red;width:400px;height:600px"] [] in
let editor =
textarea ~a:[ a_style
"float:left;border:1px solid black;width:400px;height:600px"
; a_oninput [%client fun ev ->
let input = (Obj.magic ev##.target)##.value in
let rendered = Js.string (try render (Js.to_string input)
with _ -> "") in
(Eliom_content.Html.To_dom.of_div ~%renderer)##.innerHTML
:= rendered ] ]
(pcdata "")
in
let btn label t =
button ~a:[ (* a_onclick [%client fun _ -> *)
(* let e = Eliom_content.Html.To_dom.of_textarea ~%editor in *)
(* let b = e##.value##substring 0 e##.selectionStart in *)
(* let s = e##.value##substring e##.selectionStart e##.selectionEnd in *)
(* let a = e##.value##substring e##.selectionEnd e##.value##.length in *)
(* e##.value := *)
(* b##concat_4 (Js.string @@ "{" ^ ~%t ^ " ") s (Js.string " }") a *)
(* ] *)]
[ pcdata label ]
in
div [ div [ div [ btn "Bold" "b"
; btn "Italic" "i"
; btn "Underline" "u" ]
; editor ]
; div [ renderer ] ]
let () =
Twittex_app.register ~service:main_service @@ fun () () ->
let head = head (title @@ pcdata "twittex") [] in
let body = body [ h1 [ pcdata "Welcome to \"Ocsature.\" template!" ]
; editor ] in
Lwt.return @@ html head body
Makefile is from https://github.com/sagotch/ocsature project template, which is a simpler version of ocsigen-start template.
Try with let editor () = ....
Oh come on... That's the same problem as the last time, how couldn't I see it...
It still is very strange regarding what causes the app to work or not.
Anyway, thanks for the tip!
Note: related to https://github.com/ocsigen/eliom/issues/506
Certain operations need to happen while serving a request. These are frequently implicit and not at all evident from the source code. We need to formalize and document what can only be done while serving a request (not trivial). But as a rough guideline, producing part of your tree as a global value (like editor) is not guaranteed to work.