{0 Export OCaml code to JavaScript}

This page explains how to make OCaml values (functions, objects, constants)
accessible from JavaScript code.

{1:basic-export Basic export with [Js.export]}

Use {{!Js_of_ocaml.Js.export}Js.export} to export a single named value:

{@ocaml[
open Js_of_ocaml

let () =
  Js.export "myMathLib"
    (object%js
       method add x y = x + y
       method abs x = abs x
       val zero = 0
     end)
]}

From JavaScript:
{@javascript[
myMathLib.add(3, 4);    // 7
myMathLib.abs(-5);      // 5
myMathLib.zero;         // 0
]}

{1:export-all Exporting multiple values with [Js.export_all]}

Use {{!Js_of_ocaml.Js.export_all}Js.export_all} to export all properties of an object as top-level
exports:

{@ocaml[
let () =
  Js.export_all
    (object%js
       method add x y = x + y
       method sub x y = x - y
       val version = Js.string "1.0.0"
     end)
]}

From JavaScript:
{@javascript[
add(3, 4);        // 7 (directly accessible)
sub(5, 2);        // 3
version;          // "1.0.0"
]}

{1:export-functions Exporting individual functions}

You can export plain OCaml functions. They are automatically wrapped for
JavaScript:

{@ocaml[
let greet name =
  "Hello, " ^ name ^ "!"

let factorial n =
  let rec aux acc = function
    | 0 -> acc
    | n -> aux (acc * n) (n - 1)
  in aux 1 n

let () =
  Js.export "greet" greet;
  Js.export "factorial" factorial
]}

From JavaScript:
{@javascript[
greet("World");    // "Hello, World!"
factorial(5);      // 120
]}

{1:type-considerations Type considerations}

Exported functions are automatically wrapped with {{!Js_of_ocaml.Js.wrap_callback}Js.wrap_callback}.
However, you must convert OCaml values to their JavaScript equivalents (strings
with [Js.string], booleans with [Js.bool], etc.). See
{{!page-"javascript-interop".conversions}type conversions}
for the full list.

{1:callbacks Handling callbacks from JavaScript}

When JavaScript passes a callback to your OCaml code, you receive a JavaScript
function. Use {{!Js_of_ocaml.Js.Unsafe.fun_call}Js.Unsafe.fun_call} to invoke it:

{@ocaml[
let () =
  Js.export "utils"
    (object%js
       method forEach arr callback =
         let len = arr##.length in
         for i = 0 to len - 1 do
           let item = Js.array_get arr i in
           Js.Optdef.iter item (fun v ->
             ignore (Js.Unsafe.fun_call callback [| Js.Unsafe.inject v |]))
         done
     end)
]}

From JavaScript:
{@javascript[
utils.forEach([1, 2, 3], function(x) { console.log(x); });
]}

{1:nodejs Using with Node.js}

{{!Js_of_ocaml.Js.export}Js.export} and {{!Js_of_ocaml.Js.export_all}Js.export_all} automatically use [module.exports]
when running in Node.js:

{@ocaml[
(* math.ml *)
open Js_of_ocaml

let () =
  Js.export_all
    (object%js
       method add x y = x + y
       method mul x y = x * y
     end)
]}

Build and use:
{v
$ ocamlfind ocamlc -package js_of_ocaml,js_of_ocaml-ppx \
    -linkpkg math.ml -o math.byte
$ js_of_ocaml math.byte -o math.js
$ node
> var math = require("./math.js");
> math.add(2, 3)
5
> math.mul(4, 5)
20
v}

{1:browsers Using in browsers}

In browsers, exports are added to the global object ([window]):

{@html[
<script src="math.js"></script>
<script>
  console.log(myMathLib.add(2, 3));
</script>
]}

To avoid polluting the global namespace, you can export a single namespace
object:

{@ocaml[
let () =
  Js.export "MyApp"
    (object%js
       val math = object%js
         method add x y = x + y
       end
       val utils = object%js
         method log msg = Console.console##log msg
       end
     end)
]}
