callback.mx raw
1 //:build wasm
2
3 package callback
4
5 // The callback registry maps a host-visible integer id to a Moxie function
6 // value. The host (JS) keeps the id and calls back through the Dispatch*
7 // exports in dispatch.mx.
8 //
9 // Table is a self-mutating type: every registration mutates it through a
10 // method, so the maps and the function values they hold live in the
11 // registry's sovereign arena instead of the frame of whichever wasm export
12 // happened to register the callback. Writes to a package global outside a
13 // method - and the empty interface this registry used to store callbacks
14 // through - are both forbidden in Moxie.
15 type Table struct {
16 nextID int32
17 once map[int32]bool
18 f0 map[int32]func()
19 fS map[int32]func(string)
20 fB map[int32]func(bool)
21 fI map[int32]func(int32)
22 fIS map[int32]func(int32, string)
23 fIIS map[int32]func(int32, int32, string)
24 fSS map[int32]func(string, string)
25 f6I map[int32]func(int32, int32, int32, int32, int32, int32)
26 fII map[int32]func(int32, int32)
27 fIII map[int32]func(int32, int32, int32)
28 fBytes map[int32]func([]byte)
29 }
30
31 var table Table
32
33 // add allocates the next id and records whether it fires once.
34 func (t *Table) add(once bool) (id int32) {
35 if t.once == nil {
36 t.once = map[int32]bool{}
37 }
38 t.nextID++
39 id = t.nextID
40 if once {
41 t.once[id] = true
42 }
43 return
44 }
45
46 // Release drops every entry for id.
47 func (t *Table) Release(id int32) {
48 delete(t.f0, id)
49 delete(t.fS, id)
50 delete(t.fB, id)
51 delete(t.fI, id)
52 delete(t.fIS, id)
53 delete(t.fIIS, id)
54 delete(t.fSS, id)
55 delete(t.f6I, id)
56 delete(t.fII, id)
57 delete(t.fIII, id)
58 delete(t.fBytes, id)
59 delete(t.once, id)
60 }
61
62 func (t *Table) Register0(fn func()) (n int32) {
63 n = t.add(false)
64 if t.f0 == nil {
65 t.f0 = map[int32]func(){}
66 }
67 t.f0[n] = fn
68 return
69 }
70 func (t *Table) Register0Once(fn func()) (n int32) {
71 n = t.add(true)
72 if t.f0 == nil {
73 t.f0 = map[int32]func(){}
74 }
75 t.f0[n] = fn
76 return
77 }
78 func (t *Table) RegisterS(fn func(string)) (n int32) {
79 n = t.add(false)
80 if t.fS == nil {
81 t.fS = map[int32]func(string){}
82 }
83 t.fS[n] = fn
84 return
85 }
86 func (t *Table) RegisterSOnce(fn func(string)) (n int32) {
87 n = t.add(true)
88 if t.fS == nil {
89 t.fS = map[int32]func(string){}
90 }
91 t.fS[n] = fn
92 return
93 }
94 func (t *Table) RegisterB(fn func(bool)) (n int32) {
95 n = t.add(false)
96 if t.fB == nil {
97 t.fB = map[int32]func(bool){}
98 }
99 t.fB[n] = fn
100 return
101 }
102 func (t *Table) RegisterBOnce(fn func(bool)) (n int32) {
103 n = t.add(true)
104 if t.fB == nil {
105 t.fB = map[int32]func(bool){}
106 }
107 t.fB[n] = fn
108 return
109 }
110 func (t *Table) RegisterI(fn func(int32)) (n int32) {
111 n = t.add(false)
112 if t.fI == nil {
113 t.fI = map[int32]func(int32){}
114 }
115 t.fI[n] = fn
116 return
117 }
118 func (t *Table) RegisterIOnce(fn func(int32)) (n int32) {
119 n = t.add(true)
120 if t.fI == nil {
121 t.fI = map[int32]func(int32){}
122 }
123 t.fI[n] = fn
124 return
125 }
126 func (t *Table) RegisterIS(fn func(int32, string)) (n int32) {
127 n = t.add(false)
128 if t.fIS == nil {
129 t.fIS = map[int32]func(int32, string){}
130 }
131 t.fIS[n] = fn
132 return
133 }
134 func (t *Table) RegisterISOnce(fn func(int32, string)) (n int32) {
135 n = t.add(true)
136 if t.fIS == nil {
137 t.fIS = map[int32]func(int32, string){}
138 }
139 t.fIS[n] = fn
140 return
141 }
142 func (t *Table) RegisterIIS(fn func(int32, int32, string)) (n int32) {
143 n = t.add(false)
144 if t.fIIS == nil {
145 t.fIIS = map[int32]func(int32, int32, string){}
146 }
147 t.fIIS[n] = fn
148 return
149 }
150 func (t *Table) RegisterIISOnce(fn func(int32, int32, string)) (n int32) {
151 n = t.add(true)
152 if t.fIIS == nil {
153 t.fIIS = map[int32]func(int32, int32, string){}
154 }
155 t.fIIS[n] = fn
156 return
157 }
158 func (t *Table) RegisterSS(fn func(string, string)) (n int32) {
159 n = t.add(false)
160 if t.fSS == nil {
161 t.fSS = map[int32]func(string, string){}
162 }
163 t.fSS[n] = fn
164 return
165 }
166 func (t *Table) RegisterSSOnce(fn func(string, string)) (n int32) {
167 n = t.add(true)
168 if t.fSS == nil {
169 t.fSS = map[int32]func(string, string){}
170 }
171 t.fSS[n] = fn
172 return
173 }
174 func (t *Table) Register6I(fn func(int32, int32, int32, int32, int32, int32)) (n int32) {
175 n = t.add(false)
176 if t.f6I == nil {
177 t.f6I = map[int32]func(int32, int32, int32, int32, int32, int32){}
178 }
179 t.f6I[n] = fn
180 return
181 }
182 func (t *Table) Register6IOnce(fn func(int32, int32, int32, int32, int32, int32)) (n int32) {
183 n = t.add(true)
184 if t.f6I == nil {
185 t.f6I = map[int32]func(int32, int32, int32, int32, int32, int32){}
186 }
187 t.f6I[n] = fn
188 return
189 }
190 func (t *Table) RegisterII(fn func(int32, int32)) (n int32) {
191 n = t.add(false)
192 if t.fII == nil {
193 t.fII = map[int32]func(int32, int32){}
194 }
195 t.fII[n] = fn
196 return
197 }
198 func (t *Table) RegisterIIOnce(fn func(int32, int32)) (n int32) {
199 n = t.add(true)
200 if t.fII == nil {
201 t.fII = map[int32]func(int32, int32){}
202 }
203 t.fII[n] = fn
204 return
205 }
206 func (t *Table) RegisterIII(fn func(int32, int32, int32)) (n int32) {
207 n = t.add(false)
208 if t.fIII == nil {
209 t.fIII = map[int32]func(int32, int32, int32){}
210 }
211 t.fIII[n] = fn
212 return
213 }
214 func (t *Table) RegisterIIIOnce(fn func(int32, int32, int32)) (n int32) {
215 n = t.add(true)
216 if t.fIII == nil {
217 t.fIII = map[int32]func(int32, int32, int32){}
218 }
219 t.fIII[n] = fn
220 return
221 }
222 func (t *Table) RegisterBytes(fn func([]byte)) (n int32) {
223 n = t.add(false)
224 if t.fBytes == nil {
225 t.fBytes = map[int32]func([]byte){}
226 }
227 t.fBytes[n] = fn
228 return
229 }
230 func (t *Table) RegisterBytesOnce(fn func([]byte)) (n int32) {
231 n = t.add(true)
232 if t.fBytes == nil {
233 t.fBytes = map[int32]func([]byte){}
234 }
235 t.fBytes[n] = fn
236 return
237 }
238
239 // --- typed lookups: one per signature, so the dispatcher calls the callback
240 // directly instead of asserting an interface{} back to a function type.
241
242 func (t *Table) Lookup0(id int32) (fn func(), ok bool) {
243 fn, ok = t.f0[id]
244 if ok && t.once[id] {
245 t.Release(id)
246 }
247 return
248 }
249 func (t *Table) LookupS(id int32) (fn func(string), ok bool) {
250 fn, ok = t.fS[id]
251 if ok && t.once[id] {
252 t.Release(id)
253 }
254 return
255 }
256 func (t *Table) LookupB(id int32) (fn func(bool), ok bool) {
257 fn, ok = t.fB[id]
258 if ok && t.once[id] {
259 t.Release(id)
260 }
261 return
262 }
263 func (t *Table) LookupI(id int32) (fn func(int32), ok bool) {
264 fn, ok = t.fI[id]
265 if ok && t.once[id] {
266 t.Release(id)
267 }
268 return
269 }
270 func (t *Table) LookupIS(id int32) (fn func(int32, string), ok bool) {
271 fn, ok = t.fIS[id]
272 if ok && t.once[id] {
273 t.Release(id)
274 }
275 return
276 }
277 func (t *Table) LookupIIS(id int32) (fn func(int32, int32, string), ok bool) {
278 fn, ok = t.fIIS[id]
279 if ok && t.once[id] {
280 t.Release(id)
281 }
282 return
283 }
284 func (t *Table) LookupSS(id int32) (fn func(string, string), ok bool) {
285 fn, ok = t.fSS[id]
286 if ok && t.once[id] {
287 t.Release(id)
288 }
289 return
290 }
291 func (t *Table) Lookup6I(id int32) (fn func(int32, int32, int32, int32, int32, int32), ok bool) {
292 fn, ok = t.f6I[id]
293 if ok && t.once[id] {
294 t.Release(id)
295 }
296 return
297 }
298 func (t *Table) LookupII(id int32) (fn func(int32, int32), ok bool) {
299 fn, ok = t.fII[id]
300 if ok && t.once[id] {
301 t.Release(id)
302 }
303 return
304 }
305 func (t *Table) LookupIII(id int32) (fn func(int32, int32, int32), ok bool) {
306 fn, ok = t.fIII[id]
307 if ok && t.once[id] {
308 t.Release(id)
309 }
310 return
311 }
312 func (t *Table) LookupBytes(id int32) (fn func([]byte), ok bool) {
313 fn, ok = t.fBytes[id]
314 if ok && t.once[id] {
315 t.Release(id)
316 }
317 return
318 }
319
320 // --- package-level entry points used by the jsbridge packages.
321
322 func Register0(fn func()) (n int32) { return table.Register0(fn) }
323 func Register0Once(fn func()) (n int32) { return table.Register0Once(fn) }
324 func RegisterS(fn func(string)) (n int32) { return table.RegisterS(fn) }
325 func RegisterSOnce(fn func(string)) (n int32) { return table.RegisterSOnce(fn) }
326 func RegisterB(fn func(bool)) (n int32) { return table.RegisterB(fn) }
327 func RegisterBOnce(fn func(bool)) (n int32) { return table.RegisterBOnce(fn) }
328 func RegisterI(fn func(int32)) (n int32) { return table.RegisterI(fn) }
329 func RegisterIOnce(fn func(int32)) (n int32) { return table.RegisterIOnce(fn) }
330 func RegisterIS(fn func(int32, string)) (n int32) { return table.RegisterIS(fn) }
331 func RegisterISOnce(fn func(int32, string)) (n int32) { return table.RegisterISOnce(fn) }
332 func RegisterIIS(fn func(int32, int32, string)) (n int32) { return table.RegisterIIS(fn) }
333 func RegisterIISOnce(fn func(int32, int32, string)) (n int32) { return table.RegisterIISOnce(fn) }
334 func RegisterSS(fn func(string, string)) (n int32) { return table.RegisterSS(fn) }
335 func RegisterSSOnce(fn func(string, string)) (n int32) { return table.RegisterSSOnce(fn) }
336 func Register6I(fn func(int32, int32, int32, int32, int32, int32)) (n int32) {
337 return table.Register6I(fn)
338 }
339 func Register6IOnce(fn func(int32, int32, int32, int32, int32, int32)) (n int32) {
340 return table.Register6IOnce(fn)
341 }
342 func RegisterII(fn func(int32, int32)) (n int32) { return table.RegisterII(fn) }
343 func RegisterIIOnce(fn func(int32, int32)) (n int32) { return table.RegisterIIOnce(fn) }
344 func RegisterIII(fn func(int32, int32, int32)) (n int32) { return table.RegisterIII(fn) }
345 func RegisterIIIOnce(fn func(int32, int32, int32)) (n int32) { return table.RegisterIIIOnce(fn) }
346 func RegisterBytes(fn func([]byte)) (n int32) { return table.RegisterBytes(fn) }
347 func RegisterBytesOnce(fn func([]byte)) (n int32) { return table.RegisterBytesOnce(fn) }
348
349 // Release drops a registration (the host releases ids it no longer needs).
350 func Release(id int32) { table.Release(id) }
351