Runtime representation

This page describes how OCaml values are represented at runtime in JavaScript. Understanding this is useful for debugging, writing JavaScript primitives, and understanding compatibility limitations.

Overview

Js_of_ocaml maps OCaml values to JavaScript values as directly as possible for performance. This differs from the standard OCaml runtime representation.

OCaml type

JavaScript representation

int

Number (32-bit)

float

Number (unboxed)

bool

Number (0 or 1)

char

Number (0-255)

string

Special string object (MlBytes) or JavaScript string

bytes

Special bytes object (MlBytes)

array

JavaScript Array with tag

tuple

JavaScript Array with tag 0

record

JavaScript Array with tag 0

variant

Number (constant) or Array (with arguments)

int32

Number (32-bit)

nativeint

Number (32-bit)

int64

MlInt64 object

bigarray

Ml_Bigarray object

exception

Array with exception identity

object

Array with method table and instance variables

Integers

OCaml integers are represented as JavaScript numbers. Unlike native OCaml where integers are 31 or 63 bits (with one bit used for tagging), js_of_ocaml uses the full 32-bit range.

Implications:

Floats

OCaml floats are JavaScript numbers directly.

Implications:

Rounding difference: JavaScript rounds ties away from zero, while native OCaml (libc) rounds ties to even.

Booleans

OCaml booleans are represented as the numbers 0 (false) and 1 (true), not JavaScript's true and false. See type conversions for converting between them.

Bytes

OCaml bytes are always represented as MlBytes objects with:

The contents can be a JavaScript string (more memory efficient) or an array of bytes (for mutation). The runtime converts between these as needed.

Strings

OCaml strings can be represented as:

Important: Even when represented as a JavaScript string, it encodes a sequence of bytes, not UTF-16 text. Each character's code point represents one byte (0-255). Assuming the bytes are UTF-8 encoded text, use Js.string to convert to a native UTF-16 JavaScript string. To convert back, use Js.to_string. See conversions.

Blocks, arrays, records, modules

OCaml heap-allocated values (arrays, tuples, records, variant constructors with arguments) are represented as JavaScript arrays where:

For example, Some 42 becomes [0, 42] (tag 0, one field).

Variants

type t =
  | A        (* 0 *)
  | B        (* 1 *)
  | C of int (* [0, n] — tag 0, since it's the first non-constant *)
  | D of int (* [1, n] — tag 1 *)

Int32 and Nativeint

Int32.t and Nativeint.t are represented directly as JavaScript numbers, like regular int values.

Note that nativeint is 32 bits in js_of_ocaml (matching JavaScript's bitwise operations), not the platform's native word size.

Int64

Int64.t values are represented as MlInt64 objects, which store the value as three numbers: two 24-bit integers (lo, mi) and one 16-bit integer (hi), since JavaScript numbers cannot represent the full 64-bit range precisely.

Bigarray

Bigarrays are represented as Ml_Bigarray objects, which use JavaScript Typed Arrays for storing the underlying data:

OCaml kind

JavaScript Typed Array

Float32

Float32Array

Float64

Float64Array

Int8_signed

Int8Array

Int8_unsigned

Uint8Array

Int16_signed

Int16Array

Int16_unsigned

Uint16Array

Int32

Int32Array

Int64

Int32Array (2 elements per value)

Int

Int32Array

Nativeint

Int32Array

Complex32

Float32Array (2 elements per complex)

Complex64

Float64Array (2 elements per complex)

Char

Uint8Array

Exceptions

OCaml exceptions are represented as:

For example, Not_found is just its identity object, while Failure "oops" becomes [0, <Failure identity>, "oops"] (index 0 is the block tag).

Note: OCaml exceptions are not JavaScript Error objects. When an OCaml exception propagates to JavaScript code, it appears as an array, not an Error. See error handling for how to work with exceptions across the OCaml/JavaScript boundary.

Objects

OCaml objects (from the object-oriented layer) are implemented using JavaScript arrays. They have nothing to do with JavaScript objects. Use the PPX syntax (object%js) to create JavaScript objects.

Compatibility considerations

Due to representation differences, some operations behave differently:

Marshalling (Marshal module):

Polymorphic comparison and hashing:

See also