package eliom

  1. Overview
  2. Docs
Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source

Source file eliom_runtime.ml

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
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
# 1 "src/lib/eliom_runtime.shared.ml"
(* Ocsigen
 * http://www.ocsigen.org
 * Copyright (C) CNRS Univ Paris Diderot
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, with linking exception;
 * either version 2.1 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *)

(**/**)

open Js_of_ocaml

module Client_value_server_repr = struct
  type u =
    { mutable loc : Eliom_lib_base.pos option
    ; instance_id : int
    ; unwrapper : Eliom_wrap.unwrapper }
  [@@warning "-69"]

  type 'a t = u

  let create ~loc ~instance_id ~unwrapper = {instance_id; loc; unwrapper}
  let instance_id cv = cv.instance_id
  let loc cv = cv.loc
  let clear_loc cv = cv.loc <- None
  let to_poly v = v
end

type escaped_value = Ocsigen_lib_base.poly

module RawXML = struct
  type separator = Space | Comma

  let separator_to_string = function Space -> " " | Comma -> ", "

  [@@@warning "-39"]

  type cookie_info = bool * string list [@@deriving json]

  [@@@warning "+39"]

  type caml_event_handler =
    | CE_registered_closure of
        string * Ocsigen_lib_base.poly (* 'a Js.t -> unit) client_value *)
    | CE_client_closure of (Dom_html.event Js.t -> unit) (* Client side-only *)
    | CE_client_closure_mouse of (Dom_html.mouseEvent Js.t -> unit)
      (* Client side-only *)
    | CE_client_closure_keyboard of (Dom_html.keyboardEvent Js.t -> unit)
      (* Client side-only *)
    | CE_client_closure_touch of (Dom_html.touchEvent Js.t -> unit)
      (* Client side-only *)
    | CE_call_service of
        ([`A | `Form_get | `Form_post]
        * cookie_info option
        * string option
        * Ocsigen_lib_base.poly)
          (* (event -> bool) client_value *)
          option
          Eliom_lazy.request

  type internal_event_handler = Raw of string | Caml of caml_event_handler
  type uri = string Eliom_lazy.request

  let string_of_uri = Eliom_lazy.force
  let uri_of_string = Eliom_lazy.from_val
  let uri_of_fun = Eliom_lazy.from_fun
  let internal_event_handler_of_service info = Caml (CE_call_service info)
  let ce_registered_closure_class = "caml_c" (*"caml_closure"*)
  let ce_registered_attr_class = "caml_attr"
  let ce_call_service_class = "caml_link"
  let process_node_class = "caml_p" (*"caml_process_node"*)
  let request_node_class = "caml_r" (*"caml_request_node"*)
  let ce_call_service_attrib = "data-eliom-cookies-info"
  let ce_template_attrib = "data-eliom-template"
  let node_id_attrib = "data-eliom-id" (*"data-eliom-node-id"*)
  let closure_attr_prefix = "" (*"caml_closure_id"*)
  let closure_name_prefix = "data-eliom-c-"
  (*!!! This prefix has to be different from any other prefix *)

  let client_attr_prefix = "eliom_attrib"
  let client_name_prefix = "data-eliom-"

  type aname = string

  type acontent =
    | AFloat of float
    | AInt of int
    | AStr of string
    | AStrL of separator * string list

  type racontent =
    | RA of acontent
    | RAReact of acontent option React.signal
    | RACamlEventHandler of caml_event_handler
    | RALazyStr of string Eliom_lazy.request
    | RALazyStrL of separator * string Eliom_lazy.request list
    | RAClient of string * attrib option * Ocsigen_lib_base.poly
  (*attrib client_value *)

  and attrib = aname * racontent

  let aname = function
    | name, RACamlEventHandler (CE_registered_closure (_crypto, _)) ->
        closure_name_prefix ^ name
    | _, RAClient (_, Some (name, _), _) | name, RAClient (_, None, _) ->
        client_name_prefix ^ name
    | name, _ -> name

  let acontent = function
    | _, RAReact s -> (
      match React.S.value s with None -> AStr "" | Some x -> x)
    | _, RA a -> a
    | _, RACamlEventHandler (CE_registered_closure (crypto, _)) ->
        AStr (closure_attr_prefix ^ crypto)
    | _, RACamlEventHandler _ -> AStr ""
    | _, RALazyStr str -> AStr (Eliom_lazy.force str)
    | _, RALazyStrL (sep, str) -> AStrL (sep, List.map Eliom_lazy.force str)
    | _, RAClient (crypto, _, _) -> AStr (client_attr_prefix ^ crypto)

  let racontent (_, a) = a

  let react_float_attrib name s =
    name, RAReact (React.S.map (fun f -> Some (AFloat f)) s)

  let react_int_attrib name s =
    name, RAReact (React.S.map (fun f -> Some (AInt f)) s)

  let react_string_attrib name s =
    name, RAReact (React.S.map (fun f -> Some (AStr f)) s)

  let react_space_sep_attrib name s =
    name, RAReact (React.S.map (fun f -> Some (AStrL (Space, f))) s)

  let react_comma_sep_attrib name s =
    name, RAReact (React.S.map (fun f -> Some (AStrL (Comma, f))) s)

  let react_poly_attrib name v s =
    ( name
    , RAReact (React.S.map (function false -> None | true -> Some (AStr v)) s) )

  let float_attrib name value = name, RA (AFloat value)
  let int_attrib name value = name, RA (AInt value)
  let string_attrib name value = name, RA (AStr value)
  let space_sep_attrib name values = name, RA (AStrL (Space, values))
  let comma_sep_attrib name values = name, RA (AStrL (Comma, values))

  let internal_event_handler_attrib name value =
    match value with
    | Raw value -> name, RA (AStr value)
    | Caml v -> name, RACamlEventHandler v

  let uri_attrib name value = name, RALazyStr value
  let uris_attrib name value = name, RALazyStrL (Space, value)

  type ename = string
  type node_id = NoId | ProcessId of string | RequestId of string

  module ClosureMap = Map.Make (struct
      type t = string

      let compare = compare
    end)

  type event_handler_table =
    Ocsigen_lib_base.poly
      (* (biggest_event Js.t -> unit) client_value *)
      ClosureMap.t

  type client_attrib_table =
    Ocsigen_lib_base.poly (* attrib client_value *) ClosureMap.t

  let filter_class_value acc = function
    | AStr v -> v :: acc
    | AStrL (_space, v) -> v @ acc
    | _ -> failwith "attribute class is not a string"

  let filter_class (freepos, acc_class, acc_attr) = function
    | "class", RA value -> freepos, filter_class_value acc_class value, acc_attr
    | (_, RACamlEventHandler (CE_registered_closure _)) as attr ->
        freepos, ce_registered_closure_class :: acc_class, attr :: acc_attr
    | _, RACamlEventHandler (CE_call_service link_info) -> (
      match Eliom_lazy.force link_info with
      | None -> freepos, acc_class, acc_attr
      | Some (_kind, cookie_info, tmpl, _) ->
          let acc_class = ce_call_service_class :: acc_class in
          let acc_attr =
            match cookie_info with
            | None -> acc_attr
            | Some v ->
                (ce_call_service_attrib, RA (AStr ([%json_of: cookie_info] v)))
                :: acc_attr
          in
          let acc_attr =
            match tmpl with
            | None -> acc_attr
            | Some tmpl -> (ce_template_attrib, RA (AStr tmpl)) :: acc_attr
          in
          freepos, acc_class, acc_attr)
    | "", RAClient (crypt, Some ("class", RA v), cv) ->
        let acc_class = filter_class_value acc_class v in
        let acc_class = ce_registered_attr_class :: acc_class
        and acc_attr = ("class", RAClient (crypt, None, cv)) :: acc_attr in
        freepos, acc_class, acc_attr
    | "", RAClient (crypt, init, cv) ->
        let freepos, acc_attr =
          match init with
          | Some ((an, _) as a) ->
              freepos, (an, RAClient (crypt, None, cv)) :: a :: acc_attr
          | None ->
              let name = Printf.sprintf "anonym%d" freepos in
              let freepos = succ freepos in
              freepos, (name, RAClient (crypt, None, cv)) :: acc_attr
        in
        freepos, ce_registered_attr_class :: acc_class, acc_attr
    | _, RAClient _ -> assert false
    | attr -> freepos, acc_class, attr :: acc_attr

  let filter_class_attribs node_id attribs =
    let nid_classes, nid_attribs =
      match node_id with
      | NoId -> [], []
      | ProcessId i -> [process_node_class], [node_id_attrib, RA (AStr i)]
      | RequestId i -> [request_node_class], [node_id_attrib, RA (AStr i)]
    in
    let _, classes, attribs =
      List.fold_left filter_class (0, nid_classes, nid_attribs) attribs
    in
    match classes with
    | [] -> attribs
    | _ -> ("class", RA (AStrL (Space, classes))) :: attribs
end

let tyxml_unwrap_id_int = 1
let client_value_unwrap_id_int = 7

type client_value_datum =
  { closure_id : string
  ; args : Ocsigen_lib_base.poly
  ; value : Ocsigen_lib_base.poly Client_value_server_repr.t }

type injection_datum =
  { injection_dbg : (Eliom_lib_base.pos * string option) option
  ; injection_id : int
  ; injection_value : Ocsigen_lib_base.poly }

type compilation_unit_global_data =
  { server_sections_data : client_value_datum array array
  ; client_sections_data : injection_datum array array }

type global_data = compilation_unit_global_data Eliom_lib.String_map.t
type request_data = client_value_datum array

let global_data_unwrap_id_int = 8

type 'a eliom_caml_service_data =
  {ecs_request_data : request_data; ecs_data : 'a}

(* the data sent on channels *)
type 'a eliom_comet_data_type = 'a Eliom_wrap.wrapped_value
OCaml

Innovation. Community. Security.