Js_of_ocaml ppx object%js slicing off last _?

Context: I’m trying to export some functions from OCaml/jsoo to Rust/wasm32. I don’t think Js.export / Js.export_all works in this case because:

  1. Chrome loads Jsoo/OCaml code
  2. Jsoo/OCaml code loads *.wasm, then runs *.wasm

Here, OCaml “loads” Rust, which makes the “Rust load some module” approaches not work well.

Anyway, so now my goal is to setup some global variables, i.e.

global.my_ocaml_ffi = { bindings }

Actual Problem

Here is the code I am trying:

let hello_world () = Brr.Console.log [ "hello world from OCaml ffi" ]

let _ =
  Jv.set Jv.global "my_ocaml_ffi" @@ Jv.Id.to_jv
       method hello_world () = hello_world ()
       method add x y = x +. y
       method abs x = x * 2
       val start_worker_jv = start_worker_jv_wrapper

No, here is the weird part, when I type “my_ocaml_ffi” in the JS console, I get back:

> my_ocaml_ffi

{hello: ƒ, add: ƒ, abs: ƒ, start_worker: ƒ}
ƒ ()
ƒ ()
ƒ ()
ƒ z(Br)

Now, there is one more particular thing,

> my_ocaml_ffi.hello
ƒ (){var r=arguments.length,e=new Array(r+1);e[0]=this;for(var t=0;t<r;t++)e[t+1]=arguments[t];var a=caml_callback(n,e);return a instanceof Function?caml_js_wrap_callback(a):a}

> my_ocaml_ffi.hello()
ƒ (){var r=arguments.length;if(r>0)for(var e=new Array(r),t=0;t<r;t++)e[t]=arguments[t];else e=[void 0];var a=caml_callback(n,e);return a instanceof Function?caml_js_wrap_callback(a):a}

> my_ocaml_ffi.hello()()
Win_Gfx.bc.js:2 hello world from OCaml ffi

Two questions:

  1. why did hello_world become hello

  2. why do I have to call it as hello()() instead of hello() ?

Dropping method name suffixes is documented behaviour, as previously answered on this forum: Snake case and js_of_ocaml - #3 by haochenx.


For the second, I haven’t used jsoo, but note that methods are different than regular functions:

let a = object method foo = "bar" end;;
val a : < foo : string > = <obj>
- : string = "bar"

Dropping the unit argument will likely give you what you expect.