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