Question 1: Reading through the opam manual, I don’t see any mention of js_of_ocaml, minimal mention of stubs, and the document assumes architectures are ’ typically one of "x86_32" , "x86_64" , "ppc32" , "ppc64" , "arm32" or "arm64" , or the lowercased output of uname -m , or "unknown"'. How does the distribution of js_of_ocaml-specific libraries typically work?
Primitive code must be annotated with the primitive name and primitive requirements. The linker uses these information to only include the primitive actually used in the program and to perform better deadcode elimination.
Quick disclaimer, I haven’t actually released any jsoo bindings to Javascript libraries. But hopefully I can help a bit :))
I think js_of_ocaml support in opam is lacking, I don’t think there is a way to specify that a library should only be used in the context of compiling to javascript. If it is a binding library, it will have a dependency most likely to js_of_ocaml but that’s probably about it. There’s nothing in opam yet that I’m aware of to mark a library as jsoo-compatible (by library here I mean plain OCaml code not a binding to a JS library).
As I see it the current way to do this is just to release the library like any other library. When compiling an actual application with dune using executable and (modes js), it is then up to the user to provide the javascript library which could be:
You could then document how a user should provide the JS library implementation that your library binds.
Alternatively, the library stanza does support the js_of_ocaml field (see Stanza Reference — Dune documentation). I believe this allows you to vendor the Javascript library in your repository and link it to the library so the user wouldn’t have to provide it at all. This allows you to write bindings for a specific version of a library and ensure the user gets the correct JS. See for example the bindings to leaflet here: https://codeberg.org/openEngiadina/geopub/src/branch/main/src/leaflet/dune. I haven’t actually seen anything released like this in practice, but I think it should work.
The difference is you are binding a Javascript library whereas zarith_stubs_js provides Javascript implementations for Zarith’s C functions. For example, the C function ml_z_div and the JS counterpart.
Using a .js file with the joo_global_object approach like you pointed out
I want to make sure I understand the approach you’re taking here. JSOO outputs index.bc.js, which includes require("@codemirror/view"), require("@codemirror/state"), etc. You then rely on Parcel (or Webpack, etc) to link the JS. Does that sound right?
This approach sounds very appealing since it’s simple on the OCaml side. It made your Codemirror bindings possible (which I could never figure out how to do). More generally, it solves the problem of working with JS modules from OCaml. I see two downsides:
It’s an extra step for users
Makes it possible to link an incompatible version of the JS library (as you noted)
Yep exactly, the examples are broken in that code-mirror repository as you pointed out (thanks for the issue), but they should be working in this editor application using npx esbuild in a dune rule.
Thanks for pointing out that jsoo-react issue, I like the comment:
I guess it all comes down to how “close” to JavaScript ecosystem a project is: for projects leveraging a lot of JS related tooling, using Webpack or other bundler is not a pain (actually helps). But for projects leaning more on OCaml side, with very few JavaScript dependencies, adding bundler is actually overkill.