|
1 | | -# Wasm_of_ocaml |
2 | | - |
3 | | -Wasm_of_ocaml is a fork of Js_of_ocaml which compiles OCaml bytecode to WebAssembly. |
4 | | - |
5 | | -## Supported engines |
6 | | - |
7 | | -The generated code works with Chrome 11.9, Node.js 22 and Firefox 122 (or more recent versions of these applications). |
8 | | - |
9 | | -In particular, the output code requires the following [Wasm extensions](https://webassembly.org/roadmap/) to run: |
10 | | -- [the GC extension](https://github.com/WebAssembly/gc), including functional references and 31-bit integers |
11 | | -- [the tail-call extension](https://github.com/WebAssembly/tail-call/blob/main/proposals/tail-call/Overview.md) |
12 | | -- [the exception handling extension](https://github.com/WebAssembly/exception-handling/blob/master/proposals/exception-handling/Exceptions.md) |
13 | | - |
14 | | -OCaml 5.x code using effect handlers can be compiled in two different ways: |
15 | | -One can enable the CPS transformation from `js_of_ocaml` by passing the |
16 | | -`--enable=effects` flag. Without the flag `wasm_of_ocaml` will instead emit code |
17 | | -utilizing |
18 | | -- [the JavaScript-Promise Integration extension](https://github.com/WebAssembly/js-promise-integration/blob/main/proposals/js-promise-integration/Overview.md) |
19 | | - |
| 1 | +# Js_of_ocaml (jsoo) |
| 2 | + |
| 3 | +[](https://github.com/ocsigen/js_of_ocaml/actions) |
| 4 | +[](https://github.com/ocsigen/js_of_ocaml/actions/workflows/siteupdate.yml) |
| 5 | +[](https://github.com/ocsigen/js_of_ocaml/actions/workflows/pages/pages-build-deployment) |
| 6 | + |
| 7 | +Js_of_ocaml is a compiler from OCaml bytecode to JavaScript. It makes it |
| 8 | +possible to run pure OCaml programs in JavaScript environment like browsers and |
| 9 | +Node.js. |
| 10 | + |
| 11 | +- It is easy to install and use as it works with an existing installation of |
| 12 | + OCaml, with no need to recompile any library. |
| 13 | +- It comes with bindings for a large part of the browser APIs. |
| 14 | +- According to our benchmarks, the generated programs runs typically faster than |
| 15 | + with the OCaml bytecode interpreter. |
| 16 | +- We believe this compiler will prove much easier to maintain than a retargeted |
| 17 | + OCaml compiler, as the bytecode provides a very stable API. |
| 18 | + |
| 19 | +Js_of_ocaml is composed of multiple packages: |
| 20 | +- js_of_ocaml-compiler, the compiler. |
| 21 | +- js_of_ocaml-ppx, a ppx syntax extension. |
| 22 | +- js_of_ocaml, the base library. |
| 23 | +- js_of_ocaml-ppx_deriving_json |
| 24 | +- js_of_ocaml-lwt, lwt support. |
| 25 | +- js_of_ocaml-tyxml, tyxml support. |
| 26 | +- js_of_ocaml-toplevel, lib and tools to build an ocaml toplevel to |
| 27 | + javascript. |
| 28 | + |
| 29 | +## Requirements |
| 30 | + |
| 31 | +See |
| 32 | +[opam](https://github.com/ocsigen/js_of_ocaml/blob/master/js_of_ocaml-compiler.opam) |
| 33 | +file for version constraints. |
| 34 | + |
| 35 | +### Toplevel requirements |
| 36 | + |
| 37 | +- tyxml, reactiveData |
| 38 | +- ocp-indent: needed to support indentation in the toplevel |
| 39 | +- higlo: needed to support Syntax highlighting in the toplevel |
| 40 | +- cohttp: needed to build the toplevel webserver |
20 | 41 |
|
21 | 42 | ## Installation |
22 | 43 |
|
23 | | -The following commands will perform a minimal installation: |
24 | | -``` |
25 | | -git clone https://github.com/ocaml-wasm/wasm_of_ocaml |
26 | | -cd wasm_of_ocaml |
27 | | -opam pin add -n --with-version 6.0.0 . |
28 | | -opam install dune.3.17.0 wasm_of_ocaml-compiler |
29 | | -``` |
30 | | -You may want to install additional packages. For instance: |
| 44 | +### Opam |
31 | 45 |
|
32 | 46 | ``` |
33 | | -opam install js_of_ocaml-ppx js_of_ocaml-lwt |
| 47 | +opam install js_of_ocaml js_of_ocaml-compiler js_of_ocaml-ppx |
34 | 48 | ``` |
35 | 49 |
|
36 | 50 | ## Usage |
37 | 51 |
|
38 | | -You can try compiling the program in `examples/cubes`. Your program must first be compiled using the OCaml bytecode compiler `ocamlc`. JavaScript bindings are provided by the `js_of_ocaml` package. The syntax extension is provided by `js_of_ocaml-ppx` package. Package `js_of_ocaml-lwt` provides Javascript specific Lwt functions. |
39 | | - |
40 | | -``` |
41 | | -ocamlfind ocamlc -package js_of_ocaml,js_of_ocaml-ppx,js_of_ocaml-lwt -linkpkg -o cubes.byte cubes.mli cubes.ml |
42 | | -``` |
43 | | - |
44 | | -Then, run the `wasm_of_ocaml` compiler to produce WebAssembly code: |
| 52 | +Your program must first be compiled using the OCaml bytecode compiler `ocamlc`. |
| 53 | +JavaScript bindings are provided by the `js_of_ocaml` package. The syntax |
| 54 | +extension is provided by `js_of_ocaml-ppx` package. |
45 | 55 |
|
46 | 56 | ``` |
47 | | -wasm_of_ocaml cubes.byte |
| 57 | +ocamlfind ocamlc -package js_of_ocaml -package js_of_ocaml-ppx -linkpkg -o cubes.byte cubes.ml |
48 | 58 | ``` |
49 | 59 |
|
50 | | -This outputs a file `cubes.js` which loads the WebAssembly code from file `cube.wasm`. For debugging, we currently also output the generated WebAssembly code in text file to `cube.wat`. Since Chrome does not allow loading from the filesystem, you need to serve the files using some Web server. For instance: |
51 | | -``` |
52 | | -python3 -m http.server 8000 --directory . |
53 | | -``` |
| 60 | +Then, run the `js_of_ocaml` compiler to produce JavaScript code: |
54 | 61 |
|
55 | | -As a larger example, you can try [CAMLBOY](https://github.com/linoscope/CAMLBOY). You need to install a forked version of [Brr](https://github.com/ocaml-wasm/brr/tree/wasm). Once the Js_of_ocaml UI is compiled (with `dune build --profile release`), you can generate WebAssembly code instead with the following command: |
56 | 62 | ``` |
57 | | -wasm_of_ocaml _build/default/bin/web/index.bc-for-jsoo |
| 63 | +js_of_ocaml cubes.byte |
58 | 64 | ``` |
59 | 65 |
|
60 | | -## Implementation status |
61 | | - |
62 | | -A large part of the runtime is [implemented](https://github.com/ocaml-wasm/wasm_of_ocaml/issues/5). File-related functions and dynamic linking are not supported yet. |
63 | | - |
64 | | -## Compatibility with Js_of_ocaml |
65 | | - |
66 | | -Since the value representation is different, some adaptations are necessary. |
67 | | - |
68 | | -The most notable change is that, except for integers, OCaml numbers are no longer mapped to JavaScript numbers. So, explicit conversions `Js.to_float` and `Js.float` are now necessary to convert between OCaml floats and JavaScript numbers. The typing of JavaScript Typed Arrays has also been changed to deal with this. |
| 66 | +## Features |
| 67 | + |
| 68 | +Most of the OCaml standard library is supported. However, |
| 69 | + |
| 70 | +- Most of the Sys module is not supported. |
| 71 | + |
| 72 | +Extra libraries distributed with OCaml (such as Thread) are not supported in |
| 73 | +general. However, |
| 74 | + |
| 75 | +- Bigarray: bigarrays are supported using Typed Arrays |
| 76 | +- Num: supported |
| 77 | +- Str: supported |
| 78 | +- Graphics: partially supported using canvas (see js_of_ocaml-lwt.graphics) |
| 79 | +- Unix: time related functions are supported |
| 80 | + |
| 81 | +Tail call is not optimized in general. However, mutually recursive functions are |
| 82 | +optimized: |
| 83 | + |
| 84 | +- self recursive functions (when the tail calls are the function itself) are |
| 85 | + compiled using a loop. |
| 86 | +- trampolines are used otherwise. |
| 87 | + [More](http://ocsigen.org/js_of_ocaml/dev/manual/tailcall) about tail call |
| 88 | + optimization. |
| 89 | + |
| 90 | +Effect handlers are supported with the `--enable=effects` flag. |
| 91 | + |
| 92 | +## Data representation |
| 93 | + |
| 94 | +Data representation differs from the usual one. Most notably, integers are 32 |
| 95 | +bits (rather than 31 bits or 63 bits), which is their natural size in |
| 96 | +JavaScript, and floats are not boxed. As a consequence, marshalling, polymorphic |
| 97 | +comparison, and hashing functions can yield results different from usual: |
| 98 | + |
| 99 | +- marshalling floats might generate different output. Such output should not be |
| 100 | + unmarshalled using the standard ocaml runtime (native or bytecode). |
| 101 | +- the polymorphic hash function will not give the same results on datastructures |
| 102 | + containing floats; |
| 103 | +- these functions may be more prone to stack overflow. |
| 104 | + |
| 105 | +| OCaml | javascript | |
| 106 | +| ------------- | ------------- | |
| 107 | +| int | number (32bit int) | |
| 108 | +| int32 | number (32bit int) | |
| 109 | +| nativeint | number (32bit int) | |
| 110 | +| int64 | Object (MlInt64) | |
| 111 | +| float | number | |
| 112 | +| string | string or object (MlBytes) | |
| 113 | +| bytes | object (MlBytes) | |
| 114 | +| "immediate" (e.g. true, false, None, ()) | number (32bit int) | |
| 115 | +| "block" | array with tag as first element (e.g. `C(1,2) => [tag,1,2]`) | |
| 116 | +| array | block with tag 0 (e.g. `[\|1;2\|] => [0,1,2]`) | |
| 117 | +| tuple | block with tag 0 (e.g. `(1,2) => [0,1,2]`) | |
| 118 | +| record | block (e.g. `{x=1;y=2} => [0,1,2]`) | |
| 119 | +| constructor with arguments | block (e.g. `C (1, 2) => [tag,1,2]`) | |
| 120 | +| module | block | |
| 121 | +| exception and extensible variant | block or immediate | |
| 122 | +| function | function | |
| 123 | + |
| 124 | + |
| 125 | + |
| 126 | +## Toplevel |
| 127 | + |
| 128 | +- [OCaml 4.04.0+BER](http://ocsigen.github.io/js_of_ocaml/toplevel/#version=4.04.0+BER) |
| 129 | + see http://okmij.org/ftp/ML/MetaOCaml.html |
| 130 | +- [OCaml 4.06.0](http://ocsigen.github.io/js_of_ocaml/toplevel/#version=4.06.0) |
| 131 | + includes Base, Core_kernel, Async_kernel, Async_js |
| 132 | + |
| 133 | +## Contents of the distribution |
| 134 | + |
| 135 | +| Filename | Description | |
| 136 | +| ----------- | -------------------------------------------- | |
| 137 | +| LICENSE | license and copyright notice | |
| 138 | +| README | this file | |
| 139 | +| compiler/ | compiler | |
| 140 | +| examples/ | small examples | |
| 141 | +| lib/ | library for interfacing with JavaScript APIs | |
| 142 | +| ppx/ | ppx syntax extensions | |
| 143 | +| runtime/ | runtime system | |
| 144 | +| toplevel/ | web-based OCaml toplevel | |
0 commit comments