package eliom

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

Source file eliom_syntax.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
# 1 "src/lib/eliom_syntax.server.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.
 *)

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

(* Global data *)

type compilation_unit_global_data2 =
  { mutable server_section : Eliom_runtime.client_value_datum array list
  ; mutable client_section : Eliom_runtime.injection_datum array list }

let get_global_data, modify_global_data =
  (* We have to classify global data from ocsigen extensions (no site
     available) and eliommodules (site data available).
     Furthermore, the Eliom services must only send global data from
     ocsigen extensions and their own site.  *)
  let global_data = ref Eliom_lib.String_map.empty in
  let site_data =
    Eliom_reference.Volatile.eref ~scope:Eliom_common.site_scope
      Eliom_lib.String_map.empty
  in
  let is_site_available () =
    (* Matches valid states for Eliom_common.get_site_data *)
    Eliom_common.(
      get_sp_option () <> None || Ocsigen_extensions.during_initialisation ())
  in
  let get () =
    if is_site_available ()
    then
      Eliom_lib.String_map.merge
        (fun compilation_unit_id global site ->
           match global, site with
           | None, None -> assert false
           | Some data, None | None, Some data -> Some data
           | Some _, Some site_data ->
               Eliom_lib.Lwt_log.ign_error_f ~section:Eliom_lib.Lwt_log.eliom
                 "Compilation unit %s linked globally AND as Eliom module"
                 compilation_unit_id;
               Some site_data)
        !global_data
        (Eliom_reference.Volatile.get site_data)
    else !global_data
  in
  let modify f =
    if is_site_available ()
    then Eliom_reference.Volatile.modify site_data f
    else global_data := f !global_data
  in
  get, modify

let current_server_section_data = ref []

let get_compilation_unit_global_data compilation_unit_id =
  (if not (Eliom_lib.String_map.mem compilation_unit_id (get_global_data ()))
   then
     let data = {server_section = []; client_section = []} in
     ignore
       (modify_global_data (Eliom_lib.String_map.add compilation_unit_id data)));
  Eliom_lib.String_map.find compilation_unit_id (get_global_data ())

let close_server_section compilation_unit_id =
  let data = get_compilation_unit_global_data compilation_unit_id in
  data.server_section <-
    Array.of_list (List.rev !current_server_section_data) :: data.server_section;
  current_server_section_data := []

let close_client_section compilation_unit_id injection_data =
  close_server_section compilation_unit_id;
  let data = get_compilation_unit_global_data compilation_unit_id in
  let injection_datum (injection_id, injection_value, loc, ident) =
    { Eliom_runtime.injection_id
    ; injection_value
    ; injection_dbg = Some (loc, ident) }
  in
  let injection_data = Array.of_list injection_data in
  data.client_section <-
    Array.map injection_datum injection_data :: data.client_section

let get_global_data () =
  Eliom_lib.String_map.map
    (fun {server_section; client_section} ->
       { Eliom_runtime.server_sections_data =
           Array.of_list (List.rev server_section)
       ; client_sections_data = Array.of_list (List.rev client_section) })
    (get_global_data ())

(* Request data *)

let request_data :
    Eliom_runtime.client_value_datum list Eliom_reference.Volatile.eref
  =
  Eliom_reference.Volatile.eref ~scope:Eliom_common.request_scope []

let get_request_data () =
  Array.of_list (List.rev (Eliom_reference.Volatile.get request_data))

(* Register data *)

let is_global = ref false

let register_client_value_data ~closure_id ~args ~value =
  let client_value_datum = {Eliom_runtime.closure_id; args; value} in
  if !is_global
  then
    if Eliom_common.get_sp_option () = None
    then
      current_server_section_data :=
        client_value_datum :: !current_server_section_data
    else
      raise
        (Eliom_client_value.Client_value_creation_invalid_context closure_id)
  else
    Eliom_reference.Volatile.modify request_data (fun sofar ->
      client_value_datum :: sofar)

(*****************************************************************************)
(* Syntax helpers *)

let escaped_value = Eliom_client_value.escaped_value
let last_id = ref 0

let client_value ?pos closure_id args =
  let instance_id = if !is_global then (incr last_id; !last_id) else 0 in
  let value = Eliom_client_value.create_client_value ~loc:pos ~instance_id in
  register_client_value_data ~closure_id ~args:(Eliom_lib.to_poly args) ~value;
  Eliom_client_value.client_value_from_server_repr value

let set_global b = is_global := b
let global_context () = !is_global
OCaml

Innovation. Community. Security.