## Overview

The js_of_ocaml compiler accepts JavaScript files on the command-line. The main purpose is to provide (external) primitives needed by the bytecode program.

Most primitives from the standard library are already implemented and loaded by default.

## Passing JavaScript files

Pass JavaScript files (must have ".js" extension) directly:

    js_of_ocaml myruntime.js program.byte

## Finding runtime files

OCaml libraries often require JavaScript runtime files. The js_of_ocaml compiler does not automatically locate these files - They must be passed explicitly on the command line.

Runtime files are discovered using Findlib's `jsoo_runtime` variable.

### List required runtime files

To list all JavaScript runtime files for a set of libraries:

    ocamlfind query -format "%+(jsoo_runtime)" -r LIB1 LIB2 ... | grep -v "^$"

Example for base and time_now:

    $ ocamlfind query -format "%+(jsoo_runtime)" -r base time_now | grep -v "^$"
    ~/.opam/4.14.0/lib/base/base_internalhash_types/runtime.js
    ~/.opam/4.14.0/lib/base/runtime.js
    ~/.opam/4.14.0/lib/time_now/runtime.js

### Complete manual compilation example

    $ export LIBS=base,time_now
    $ ocamlfind ocamlc -package $LIBS -linkpkg main.ml -o main.byte
    $ js_of_ocaml $(ocamlfind query -format "%+(jsoo_runtime)" -r $LIBS | grep -v "^$") main.byte

With dune, this is handled automatically.

## Writing JavaScript primitives

User-defined primitives need to be implemented in a separate JavaScript file. See runtime representation for how OCaml values are represented in JavaScript. Primitives should be annotated with additional information.

### Annotation syntax

Annotations are single line comments with the following syntax

    //Provides: primitive_name [const|mutable]
    //Requires: other_primitive[,another_primitive]*
    //Version: version_constraint[,version_constraint]*

    function primitive_name(arg1, arg2) {
      // JavaScript implementation
    }

### Annotations explained

`//Provides: name [modifier]` - Declares a primitive:

- `const` - No side effects (pure function)
- `mutable` - No side effects, but return value may be affected by other primitives
- `mutator` (or empty) - May have side effects

`//Requires: name1, name2` - Lists primitives that must be loaded first

`//Version: < 4.12.0` - OCaml version constraint

`//Alias: other_name` - Makes this primitive an alias for another

`//Weakdef` - Allows this primitive to be overridden by another definition

`//Always` - Always include this code, even if not referenced

`//If: flag` - Only include if flag is enabled (e.g., `//If: effects`)

`//If: !flag` - Only include if flag is disabled

`//Deprecated: message` - Mark primitive as deprecated

All JavaScript code after a `//Provides` annotation belongs to that primitive, until the next `//Provides`.

### Example: custom primitive

    //Provides: my_log_primitive
    //Requires: caml_jsstring_of_string
    function my_log_primitive(msg) {
      console.log(caml_jsstring_of_string(msg));
      return 0;  // Return unit
    }

OCaml side:

    external my_log : string -> unit = "my_log_primitive"

    let () = my_log "Hello from OCaml!"

## Declaring runtime files in packages

### Using jsoo_runtime

In your package's META file, use the `jsoo_runtime` variable:

    # mypackage/META
    package "sublib" (
      directory = "subdir"
      jsoo_runtime = "runtime.js"
    )

Files should be comma-separated and relative to the package directory. By convention, use runtime.js for single files.

### Dune integration

Dune automatically handles `jsoo_runtime` declarations. In your dune file:

    (library
     (name mylib)
     (js_of_ocaml
      (javascript_files runtime.js)))

## Deprecated: linkopts(javascript)

Before dune's native js_of_ocaml support, the standard approach was to use `linkopts(javascript)` in META files:

    # Old approach - deprecated
    package "sublib" (
      directory = "subdir"
      linkopts(javascript) = "+mypackage/sublib/runtime.js"
    )

To list linkopts for libraries:

    ocamlfind query -o-format -r -predicates javascript LIB1 LIB2 ...

### Findlib path syntax (deprecated)

When using linkopts, special path syntax is supported:

- `+package/file.js` - Resolves to `${LIBDIR}/package/file.js`
- `+file.js` - Resolves to js_of_ocaml-compiler's lib directory

Note: Dune generates META files compatible with both approaches but only uses `jsoo_runtime` internally.

## See also

- Compilation modes
- Command-line options