Sophie

Sophie

distrib > Mageia > 5 > i586 > media > core-release > by-pkgid > b4603fcd3afb71dfbec25f4867b993f4 > files > 894

js_of_ocaml-doc-2.4.1-2.mga5.noarch.rpm

= The Js_of_ocaml library

== Base types ==

Base values are not represented the same way in OCaml and Javascript.
In particular, OCaml strings are mutable arrays of bytes, while
Javascript strings are constant arrays of UTF-16 code points.  We list
here the correspondance between base types.  Conversion functions are
provided.

|= OCaml values |= Ocaml type of Javascript values |= Actual Javascript type |
| {{{int}}}     | {{{int}}}                        | Number                  |
| {{{float}}}   | {{{float}}} or {{{float Js.t}}}  | Number                  |
| {{{bool}}}    | {{{bool Js.t}}}                  | Boolean                 |
| {{{string}}}  | {{{Js.js_string Js.t}}}          | String                  |
| {{{array}}}   | {{{Js.js_array Js.t}}}           | Array                   |

Integers are implemented as Javascript numbers.  They can thus be
directly passed to and from Javascript.  To allow a possible
compatibility with Obrowser, where floats are boxed, we use to types
for floats.  Numbers of type {{{float}}} can be passed to Javascript
functions.  We rely in implicit coercion to perform unboxing when
needed.  On the other hand, Javascript will return unboxed float, of
type {{{float Js.t}}}.

== Typing Javascript objects ==

Javascript objects are given types of the shape
  {{{<m_1 : t_1; ...; m_n : t_n> Js.t}}},
using a phantom object type.  The methods {{{m_i}}} stands for the
field of the Javascript object.  For instance, a Javascript object of
type:
{{{
   < data : js_string t Js.prop;
     appendData : js_string t -> unit Js.meth> Js.t
}}}
has a property {{{data}}} containing a Javascript string, and a method
{{{appendData}}} taking a Javascript string as argument and returning
no value.

=== Method name and underscore

Some overloading is possible using a syntactic trick: names
{{{_foo}}}, {{{foo_abcd}}} and {{{foo}}} are all mapped to a same
Javascript field name {{{foo}}}: when accessing a field of an object,
the name given in the OCaml code is transformed by removing a leading
underscore and then removing all characters starting from the last
underscore; this yields the corresponding Javascript name.  For
instance, these three types correspond to the same Javascript method
{{{drawImage}}}:
{{{
    drawImage :
        imageElement t -> float -> float -> unit meth
    drawImage_withSize :
        imageElement t -> float -> float -> float -> float -> unit meth
    drawImage_fromCanvas :
        canvasElement t -> float -> float -> unit meth
}}}
This trick can also be used to refer to Javascript fields {{{type}}} or
{{{URL}}}, for instance as {{{_type}}} and {{{_URL}}}.

==== Example

<<code language="ocaml"|
class type .. = object
  (* Referer to [meth] *)
  method meth : ..
  method meth_int : ..
  method _meth_ : ..
  method _meth_aa : ..

  (* Referer to  [meth_a] *)
  method meth_a_int : ..
  method _meth_a_ : ..
  method _meth_a_b : ..

  (* Referer to [Meth] *)
  method _Meth : ..

  (* Referer to [_meth] *)
  method __meth : ..

  (* Referer to [_] *)
  method __ : ..
end
>>

== Syntax extension ==

A syntax extension is available for manipulating object properties,
invoking methods and creating objects.  The syntax and typing rules
are as follows:

        * Getting a property
{{{
            obj : <m : u prop> Js.t
            -----------------------
                 obj##m : u
}}}
        * Setting a property
{{{
            obj : <m : u prop> Js.t
              e : u
            -----------------------
               obj##m <- e : unit
}}}
        * Invoking a method
{{{
            obj : <m : t_1 -> ... -> t_n -> u meth; ..> Js.t
                e_i : t_i               (1 <= i <= n)
            -------------------------------------------------
                      obj##m(e_1, ..., e_n) : u
}}}
        * Creating an object
{{{
            constr : (t_1 -> ... -> t_n -> u Js.t) Js.constr
            e_i : t_i               (1 <= i <= n)
            ------------------------------------------------
                    jsnew constr (e1, ..., en) : u
}}}

== OCaml and Javascript functions ==

OCaml and Javascript do not follow the same calling convention.  In
OCaml, functions can be partially applied, returning a function
closure.  In Javascript, when only some of the parameters are passed,
the others are set to the {{{undefined}}} value.  As a consequence, it
is not possible to call a Javascript function from OCaml as if it was
an OCaml function, and conversely.


=== Calling Javascript functions ===

At the moment, there is no syntactic sugar for calling Javascript
functions.  You should use either {{{Js.Unsafe.call}}} or
{{{Js.Unsafe.fun_call}}}, depending whether you want {{{this}}} to be
bound to some particular object in the function body or not.

You can also refer to a Javascript function using an OCaml external
declaration. Then, you need to write stub functions in C so that the
OCaml compiler accept the external declaration:

{{{
   Ocaml file:
      external foo : t1 -> t2 = "foo"
   C file:
      #include <stdlib.h>
      #define D(f) void f () { exit(1); }
      D(foo)
}}}
You can call this function as if it was an OCaml function, as the
Javascript function is appropriately wrapped by the system.

Refer to <<a_manual chapter="linker" |the linker manual>>
to link your program with javascript stubs.


=== Using OCaml functions from JS  ===

You should use function {{{Js.wrap_callback}}} or function
{{{Js.wrap_meth_callback}}} to wrap an OCaml function so that
it can be called from Javascript.

To call an OCaml function from Javascript, follow this example:
<<code language="ocaml"|

Js.Unsafe.global##plop <- Js.wrap_callback f
>>

Or, to create a JS object with OCaml methods:
<<code language="ocaml"|
Js.Unsafe.global##plop <-
  Js.Unsafe.obj [| ("f", Js.Unsafe.inject (Js.wrap_meth_callback f));
                   ("g", Js.Unsafe.inject (Js.wrap_meth_callback g)) |]
>>

Variant: create an empty JavaScript object (typed or not) and
set its properties afterward

<<code language="ocaml"|

(* Optionnal : type the exported JavaScript object. *)
class type exported = object
  method addFloat : (float -> float -> float) callback writeonly_prop
  method printInt : (int -> unit) callback writeonly_prop
end

let exported : exported Js.t =
  let empty = Js.Unsafe.obj [||] in
  Js.Unsafe.global##exportModuleA <- empty;
  empty

let _ =
  exported##printInt <- Js.wrap_callback (fun i -> print_int i );
  exported##addFloat <- Js.wrap_callback (fun x y -> x +. y)
>>

== IO ==

The <<a_api | module Json >> module allows to marshal and unmarshal the
javascript representation of OCaml values into the corresponding JSON
string. The unmarshaling is unsafe in the same way the OCaml
{{{Marshal.from_string}}} function is.

Type-safe unmarshaling may be achieved with the
{{{deriving}}} library using either the optionnal {{{Json}}}
class or the {{{Pickle}}} class.

* The {{{Json}}} class use a Json as external representation and do
  not preserve potential sharings in the data representation. See
  <<a_api | module Deriving_Json >> for more information.
* The {{{Pickle}}} class use a binary format as external
  representation and preserve sharings in the data representation.

== Events ==

Besides the functions provided by {{{Dom_html}}} to register event handlers
(mainly <<a_api | val Dom_html.addEventListener >>)
using the usual Javascript way, js_of_ocaml provides another module to
program event handlers very easily and concisely, in the module
<<a_api | module Lwt_js_events >>.

This module defines functions you can call on a DOM element to create
an Lwt thread that will return when the event occures.

Example:

<<code language="ocaml"|
Lwt.ignore_result (Lwt_js_events.click target ~>>= handler);
>>

The handler receives the JS event as parameter.

Each of these functions has a version (same name with an ending "s")
that loops when the handler terminates. Example:

<<code language="ocaml"|
Lwt.ignore_result (Lwt_js_events.clicks target handler);
>>

To remove an event handler, cancel the Lwt threads using {{{Lwt.cancel}}}.
It is also possible to use {{{Lwt.pick}}}.
For example the following piece of code waits
for a click on one of t1 or t2:

<<code language="ocaml"|
Lwt.pick [Lwt_js_events.click t1 ~>>= handler1;
          Lwt_js_events.click t2 ~>>= handler2]
>>

Warning: If you are using {{{Lwt.pick}}} and your handlers take time,
be aware that other events listeners will not be cancelled
before the handler has terminated. It is probably a better idea
to return immediately after having launched the long handlers.


Look at the <<a_api text="API documentation" | module Lwt_js_events>>
for more information.