package eliom

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

Source file eliom_lib.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
# 1 "src/lib/eliom_lib.client.ml"
(* Ocsigen
 * Copyright (C) 2005-2008 Vincent Balat, Stéphane Glondu
 *
 * 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
include Ocsigen_lib_base

include (
  Eliom_lib_base :
    module type of Eliom_lib_base
    with type 'a Int64_map.t = 'a Eliom_lib_base.Int64_map.t
    with type 'a String_map.t = 'a Eliom_lib_base.String_map.t
    with type 'a Int_map.t = 'a Eliom_lib_base.Int_map.t)

(*****************************************************************************)

module Url = struct
  include Url
  include Url_base

  let decode = Url.urldecode
  let encode ?plus s = Url.urlencode ?with_plus:plus s
  let make_encoded_parameters = Url.encode_arguments
  let split_path = Url.path_of_path_string
  let ssl_re = Regexp.regexp "^(https?):\\/\\/"

  let get_ssl s =
    Option.map
      (fun r -> Regexp.matched_group r 1 = Some "https")
      (Regexp.string_match ssl_re s 0)

  let resolve s =
    let a = Dom_html.createA Dom_html.document in
    a##.href := Js.string s;
    Js.to_string a##.href

  let has_get_args url =
    try
      ignore (String.index url '?');
      true
    with Not_found -> false

  let add_get_args url get_args =
    if get_args = []
    then url
    else
      url ^ (if has_get_args url then "&" else "?") ^ encode_arguments get_args

  let string_of_url_path ~encode l =
    if encode
    then print_endline "Warning: Eliom_lib.string_of_url_path ignores ~encode";
    String.concat "/" l

  let path_of_url = function
    | Url.Http {Url.hu_path = path; _}
    | Url.Https {Url.hu_path = path; _}
    | Url.File {Url.fu_path = path; _} ->
        path

  let path_of_url_string s =
    match Url.url_of_string s with
    | Some path -> path_of_url path
    | _ ->
        (* assuming relative URL and improvising *)
        split_path (try String.(sub s 0 (index s '?')) with Not_found -> s)
end

module Lwt_log = struct
  include Lwt_log_js

  let raise_error ?inspect ?exn ?section ?location ?logger msg =
    Lwt.ignore_result
      (log ?inspect ?exn ?section ?location ?logger ~level:Error msg);
    match exn with Some exn -> raise exn | None -> failwith msg

  let raise_error_f ?inspect ?exn ?section ?location ?logger fmt =
    Printf.ksprintf (raise_error ?inspect ?exn ?section ?location ?logger) fmt

  let eliom = Section.make "eliom"
end

let _ =
  Lwt_log.default := Lwt_log.console;
  Lwt.async_exception_hook :=
    fun exn ->
      Firebug.console##error_3 (Js.string "Lwt.async:")
        (Js.string (Printexc.to_string exn))
        exn

(* Deprecated ON *)
let debug_exn fmt exn = Lwt_log.ign_info_f ~exn fmt
let debug fmt = Lwt_log.ign_info_f fmt
let error fmt = Lwt_log.raise_error_f fmt
let error_any any fmt = Lwt_log.raise_error_f ~inspect:any fmt
let jsdebug a = Lwt_log.ign_info ~inspect:a "Jsdebug"
(* Deprecated OFF *)

let trace fmt =
  if Eliom_config.get_tracing ()
  then Lwt_log.ign_info_f (">> " ^^ fmt)
  else Printf.ksprintf ignore fmt

let lwt_ignore ?(message = "") t =
  Lwt.on_failure t (fun exn -> Lwt_log.ign_info_f ~exn "%s" message)

(* Debbuging *)
let jsalert a = Dom_html.window ## (alert a)
let alert fmt = Printf.ksprintf (fun s -> jsalert (Js.string s)) fmt

let confirm =
  let f s =
    let s = Js.string s in
    Dom_html.window ## (confirm s) |> Js.to_bool
  in
  fun fmt -> Printf.ksprintf f fmt

let debug_var s v = Js.Unsafe.set Dom_html.window (Js.string s) v

module String = struct
  include String_base

  let eol_re = Regexp.regexp "[\r\n]"
  let remove_eols s = Regexp.global_replace eol_re s ""
end

(*****************************************************************************)

(* let () =
  (Js.Unsafe.coerce Dom_html.window)##set_tracing <-
    Js.wrap_callback (fun v -> set_tracing (Js.to_bool v)) *)

(* We do not use the deriving (un)marshaling even if typ is available
   because direct jsn (un)marshaling is very fast client side
*)
let to_json ?typ s =
  match Sys.backend_type with
  | Other "js_of_ocaml" -> Js.to_string (Json.output s)
  | _ -> (
    match typ with
    | Some typ -> Deriving_Json.to_string typ s
    | None -> Js.to_string (Json.output s))

let of_json ?typ v =
  match Sys.backend_type with
  | Other "js_of_ocaml" -> Json.unsafe_input (Js.string v)
  | _ -> (
    match typ with
    | Some typ -> Deriving_Json.from_string typ v
    | None -> assert false)

(* Url.urlencode ~with_plus:true (Marshal.to_string x [])
    (* I encode the data because it seems that multipart does not
       like \0 character ... *)
*)
let encode_header_value ~typ x =
  (* We remove end of lines *)
  String.remove_eols (to_json ~typ x)

let unmarshal_js var = Marshal.from_string (Js.to_bytestring var) 0

type file_info = File.file Js.t

let make_cryptographic_safe_string ?len:_ () =
  failwith "make_cryptographic_safe_string not implemented client-side"

module Dom_reference = struct
  class type ['a, 'b] map = object
    method set : 'a -> 'b -> unit Js.meth
    method get : 'a -> 'b Js.Optdef.t Js.meth
    method delete : 'a -> unit Js.meth
  end

  let create_map () : (_, _) map Js.t =
    let map = Js.Unsafe.global##._Map in
    new%js map

  let create_weak_map () : (_, _) map Js.t =
    let weakMap = Js.Unsafe.global##._WeakMap in
    new%js weakMap

  type key = unit ref

  let retain_map : (Obj.t, (key, Obj.t) map Js.t) map Js.t = create_weak_map ()
  let new_key () = ref ()

  let retain ?(key = new_key ()) node ~keep =
    let node = Obj.repr node in
    let m =
      Js.Optdef.get
        (retain_map##get node)
        (fun () ->
           let m = create_map () in
           retain_map##set node m;
           m)
    in
    m##set key (Obj.repr keep)

  let retain_generic = retain

  let release ~key node =
    let node = Obj.repr node in
    Js.Optdef.iter (retain_map##get node) (fun m -> m##delete key)

  let transfer ~key ~src ~dst =
    let src = Obj.repr src in
    Js.Optdef.iter
      (retain_map##get src)
      (fun m ->
         Js.Optdef.iter (m##get key) (fun keep -> retain dst ~key ~keep);
         m##delete key)
end
OCaml

Innovation. Community. Security.