File: library.wiki

package info (click to toggle)
js-of-ocaml 1.2-2
  • links: PTS, VCS
  • area: main
  • in suites: wheezy
  • size: 6,464 kB
  • sloc: ml: 21,533; makefile: 325
file content (149 lines) | stat: -rw-r--r-- 5,715 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
= 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.

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 for 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}}}.


== 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.

=== Passing OCaml function to Javascript function ===

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.

== IO ==

The <<a_api | module Json >> allows to marshall and unmarshall the
javascript representation of OCaml values into the corresponding JSON
string. The unmarshalling is unsafe in the same way the OCaml
{{{Marshall.from_string}}} function is.

Type-safe unmarshalling may be achieved with the
{{{deriving-ocsigen}}} 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.