sw_wasm.mx raw

   1  //go:build wasm
   2  //:build wasm
   3  
   4  package sw
   5  
   6  import (
   7  	"git.smesh.lol/smesh/web/common/jsbridge/callback"
   8  	"unsafe"
   9  )
  10  
  11  // --- Lifecycle ---
  12  
  13  //:wasmimport bridge sw_on_install
  14  func wasmOnInstall(cbID int32)
  15  
  16  //:wasmimport bridge sw_on_activate
  17  func wasmOnActivate(cbID int32)
  18  
  19  //:wasmimport bridge sw_on_fetch
  20  func wasmOnFetch(cbID int32)
  21  
  22  //:wasmimport bridge sw_on_message
  23  func wasmOnMessage(cbID int32)
  24  
  25  func OnInstall(fn func(Event))  { wasmOnInstall(callback.RegisterI(func(e int32) { fn(Event(e)) })) }
  26  func OnActivate(fn func(Event)) { wasmOnActivate(callback.RegisterI(func(e int32) { fn(Event(e)) })) }
  27  func OnFetch(fn func(Event))    { wasmOnFetch(callback.RegisterI(func(e int32) { fn(Event(e)) })) }
  28  func OnMessage(fn func(Event))  { wasmOnMessage(callback.RegisterI(func(e int32) { fn(Event(e)) })) }
  29  
  30  // --- Event methods ---
  31  
  32  //:wasmimport bridge sw_wait_until
  33  func wasmWaitUntil(event int32, cbID int32)
  34  
  35  //:wasmimport bridge sw_respond_with
  36  func wasmRespondWith(event int32, resp int32)
  37  
  38  //:wasmimport bridge sw_respond_with_network
  39  func wasmRespondWithNetwork(event int32)
  40  
  41  //:wasmimport bridge sw_respond_with_cache_first
  42  func wasmRespondWithCacheFirst(event int32)
  43  
  44  //:wasmimport bridge sw_respond_with_network_first
  45  func wasmRespondWithNetworkFirst(event int32)
  46  
  47  //:wasmimport bridge sw_respond_with_proxy_cache
  48  func wasmRespondWithProxyCache(event int32)
  49  
  50  //:wasmimport bridge sw_prune_proxy_cache
  51  func wasmPruneProxyCache(maxAgeMs int64, cbID int32)
  52  
  53  //:wasmimport bridge sw_get_request_url
  54  func wasmGetRequestURL(event int32, outPtr *int32, outLen *int32)
  55  
  56  //:wasmimport bridge sw_get_request_path
  57  func wasmGetRequestPath(event int32, outPtr *int32, outLen *int32)
  58  
  59  //:wasmimport bridge sw_get_message_data
  60  func wasmGetMessageData(event int32, outPtr *int32, outLen *int32)
  61  
  62  //:wasmimport bridge sw_get_message_client_id
  63  func wasmGetMessageClientID(event int32, outPtr *int32, outLen *int32)
  64  
  65  func WaitUntil(event Event, fn func(done func())) {
  66  	doneID := callback.Register0Once(func() {})
  67  	wasmWaitUntil(int32(event), doneID)
  68  	fn(func() {
  69  		callback.Release(doneID)
  70  	})
  71  }
  72  
  73  func RespondWith(event Event, resp Response)    { wasmRespondWith(int32(event), int32(resp)) }
  74  func RespondWithNetwork(event Event)            { wasmRespondWithNetwork(int32(event)) }
  75  func RespondWithCacheFirst(event Event)         { wasmRespondWithCacheFirst(int32(event)) }
  76  func RespondWithNetworkFirst(event Event)       { wasmRespondWithNetworkFirst(int32(event)) }
  77  func RespondWithProxyCache(event Event)         { wasmRespondWithProxyCache(int32(event)) }
  78  
  79  func PruneProxyCache(maxAgeMs int64, fn func()) {
  80  	wasmPruneProxyCache(maxAgeMs, callback.Register0Once(fn))
  81  }
  82  
  83  func GetRequestURL(event Event) (s string) {
  84  	var rPtr, rLen int32
  85  	wasmGetRequestURL(int32(event), &rPtr, &rLen)
  86  	return ptrToString(rPtr, rLen)
  87  }
  88  
  89  func GetRequestPath(event Event) (s string) {
  90  	var rPtr, rLen int32
  91  	wasmGetRequestPath(int32(event), &rPtr, &rLen)
  92  	return ptrToString(rPtr, rLen)
  93  }
  94  
  95  func GetMessageData(event Event) (s string) {
  96  	var rPtr, rLen int32
  97  	wasmGetMessageData(int32(event), &rPtr, &rLen)
  98  	return ptrToString(rPtr, rLen)
  99  }
 100  
 101  func GetMessageClientID(event Event) (s string) {
 102  	var rPtr, rLen int32
 103  	wasmGetMessageClientID(int32(event), &rPtr, &rLen)
 104  	return ptrToString(rPtr, rLen)
 105  }
 106  
 107  // --- SW globals ---
 108  
 109  //:wasmimport bridge sw_origin
 110  func wasmOrigin(outPtr *int32, outLen *int32)
 111  
 112  //:wasmimport bridge sw_skip_waiting
 113  func wasmSkipWaiting()
 114  
 115  //:wasmimport bridge sw_claim_clients
 116  func wasmClaimClients(cbID int32)
 117  
 118  //:wasmimport bridge sw_match_clients
 119  func wasmMatchClients(cbID int32)
 120  
 121  //:wasmimport bridge sw_post_message
 122  func wasmPostMessage(client int32, ptr *byte, len int32, cap int32)
 123  
 124  //:wasmimport bridge sw_post_message_json
 125  func wasmPostMessageJSON(client int32, ptr *byte, len int32, cap int32)
 126  
 127  //:wasmimport bridge sw_get_client_by_id
 128  func wasmGetClientByID(ptr *byte, len int32, cap int32, cbID int32)
 129  
 130  //:wasmimport bridge sw_navigate
 131  func wasmNavigate(client int32, ptr *byte, len int32, cap int32)
 132  
 133  func Origin() (s string) {
 134  	var rPtr, rLen int32
 135  	wasmOrigin(&rPtr, &rLen)
 136  	return ptrToString(rPtr, rLen)
 137  }
 138  
 139  func SkipWaiting() { wasmSkipWaiting() }
 140  
 141  func ClaimClients(done func()) {
 142  	wasmClaimClients(callback.Register0Once(done))
 143  }
 144  
 145  func MatchClients(fn func(Client)) {
 146  	wasmMatchClients(callback.RegisterI(func(c int32) { fn(Client(c)) }))
 147  }
 148  
 149  func PostMessage(client Client, msg string) {
 150  	wasmPostMessage(int32(client), unsafe.StringData(msg), int32(len(msg)), int32(len(msg)))
 151  }
 152  
 153  func PostMessageJSON(client Client, json string) {
 154  	wasmPostMessageJSON(int32(client), unsafe.StringData(json), int32(len(json)), int32(len(json)))
 155  }
 156  
 157  func GetClientByID(id string, fn func(Client, bool)) {
 158  	cbID := callback.RegisterIIOnce(func(c int32, found int32) {
 159  		fn(Client(c), found != 0)
 160  	})
 161  	wasmGetClientByID(unsafe.StringData(id), int32(len(id)), int32(len(id)), cbID)
 162  }
 163  
 164  func Navigate(client Client, url string) {
 165  	wasmNavigate(int32(client), unsafe.StringData(url), int32(len(url)), int32(len(url)))
 166  }
 167  
 168  // --- Cache ---
 169  
 170  //:wasmimport bridge sw_cache_open
 171  func wasmCacheOpen(ptr *byte, len int32, cap int32, cbID int32)
 172  
 173  //:wasmimport bridge sw_cache_add_all
 174  func wasmCacheAddAll(cache int32, urlsPtr *byte, urlsLen int32, urlsCap int32, count int32, cbID int32)
 175  
 176  //:wasmimport bridge sw_cache_from_manifests
 177  func wasmCacheFromManifests(cache int32, filesPtr *byte, filesLen int32, filesCap int32, count int32, cbID int32)
 178  
 179  //:wasmimport bridge sw_cache_put
 180  func wasmCachePut(cache int32, urlPtr *byte, urlLen int32, urlCap int32, resp int32, cbID int32)
 181  
 182  //:wasmimport bridge sw_cache_match
 183  func wasmCacheMatch(ptr *byte, len int32, cap int32, cbID int32)
 184  
 185  //:wasmimport bridge sw_cache_delete
 186  func wasmCacheDelete(ptr *byte, len int32, cap int32, cbID int32)
 187  
 188  func CacheOpen(name string, fn func(Cache)) {
 189  	wasmCacheOpen(unsafe.StringData(name), int32(len(name)), int32(len(name)),
 190  		callback.RegisterIOnce(func(c int32) { fn(Cache(c)) }))
 191  }
 192  
 193  func CacheAddAll(cache Cache, urls []string, done func()) {
 194  	joined, count := joinNullSep(urls)
 195  	wasmCacheAddAll(int32(cache),
 196  		unsafe.StringData(joined), int32(len(joined)), int32(len(joined)),
 197  		count, callback.Register0Once(done))
 198  }
 199  
 200  func CacheFromManifests(cache Cache, staticFiles []string, done func()) {
 201  	joined, count := joinNullSep(staticFiles)
 202  	wasmCacheFromManifests(int32(cache),
 203  		unsafe.StringData(joined), int32(len(joined)), int32(len(joined)),
 204  		count, callback.Register0Once(done))
 205  }
 206  
 207  func CachePut(cache Cache, url string, resp Response, done func()) {
 208  	wasmCachePut(int32(cache), unsafe.StringData(url), int32(len(url)), int32(len(url)),
 209  		int32(resp), callback.Register0Once(done))
 210  }
 211  
 212  func CacheMatch(url string, fn func(Response)) {
 213  	wasmCacheMatch(unsafe.StringData(url), int32(len(url)), int32(len(url)),
 214  		callback.RegisterIOnce(func(r int32) { fn(Response(r)) }))
 215  }
 216  
 217  func CacheDelete(name string, done func()) {
 218  	wasmCacheDelete(unsafe.StringData(name), int32(len(name)), int32(len(name)),
 219  		callback.Register0Once(done))
 220  }
 221  
 222  // --- Fetch ---
 223  
 224  //:wasmimport bridge sw_fetch
 225  func wasmFetch(ptr *byte, len int32, cap int32, cbID int32)
 226  
 227  //:wasmimport bridge sw_fetch_all
 228  func wasmFetchAll(urlsPtr *byte, urlsLen int32, urlsCap int32, count int32, onEachID int32, onDoneID int32)
 229  
 230  //:wasmimport bridge sw_response_ok
 231  func wasmResponseOK(resp int32) (n int32)
 232  
 233  func Fetch(url string, fn func(Response, bool)) {
 234  	cbID := callback.RegisterIIOnce(func(r int32, ok int32) {
 235  		fn(Response(r), ok != 0)
 236  	})
 237  	wasmFetch(unsafe.StringData(url), int32(len(url)), int32(len(url)), cbID)
 238  }
 239  
 240  func FetchAll(urls []string, onEach func(int32, Response, bool), onDone func()) {
 241  	eachID := callback.RegisterIII(func(idx, resp, ok int32) {
 242  		onEach(idx, Response(resp), ok != 0)
 243  	})
 244  	doneID := callback.Register0Once(func() {
 245  		callback.Release(eachID)
 246  		onDone()
 247  	})
 248  	joined, count := joinNullSep(urls)
 249  	wasmFetchAll(unsafe.StringData(joined), int32(len(joined)), int32(len(joined)),
 250  		count, eachID, doneID)
 251  }
 252  
 253  func ResponseOK(resp Response) (ok bool) {
 254  	return wasmResponseOK(int32(resp)) != 0
 255  }
 256  
 257  // --- SSE ---
 258  
 259  //:wasmimport bridge sw_sse_connect
 260  func wasmSSEConnect(ptr *byte, len int32, cap int32, cbID int32) (n int32)
 261  
 262  //:wasmimport bridge sw_sse_close
 263  func wasmSSEClose(id int32)
 264  
 265  func SSEConnect(url string, onMessage func(string)) (s SSE) {
 266  	cbID := callback.RegisterS(onMessage)
 267  	return SSE(wasmSSEConnect(unsafe.StringData(url), int32(len(url)), int32(len(url)), cbID))
 268  }
 269  
 270  func SSEClose(id SSE) { wasmSSEClose(int32(id)) }
 271  
 272  // --- Timers ---
 273  
 274  //:wasmimport bridge sw_set_timeout
 275  func wasmSetTimeout(ms int32, cbID int32) (n int32)
 276  
 277  //:wasmimport bridge sw_clear_timeout
 278  func wasmClearTimeout(t int32)
 279  
 280  func SetTimeout(ms int32, fn func()) (t Timer) {
 281  	return Timer(wasmSetTimeout(ms, callback.Register0Once(fn)))
 282  }
 283  
 284  func ClearTimeout(t Timer) { wasmClearTimeout(int32(t)) }
 285  
 286  // --- Time ---
 287  
 288  //:wasmimport bridge sw_now_seconds
 289  func wasmNowSeconds() (n int64)
 290  
 291  //:wasmimport bridge sw_now_millis
 292  func wasmNowMillis() (n int64)
 293  
 294  func NowSeconds() (n int64) { return wasmNowSeconds() }
 295  func NowMillis() (n int64) { return wasmNowMillis() }
 296  
 297  // --- Logging ---
 298  
 299  //:wasmimport bridge sw_log
 300  func wasmLog(ptr *byte, len int32, cap int32)
 301  
 302  func Log(msg string) {
 303  	wasmLog(unsafe.StringData(msg), int32(len(msg)), int32(len(msg)))
 304  }
 305  
 306  // joinNullSep joins strings with null byte separator for passing []string to JS.
 307  func joinNullSep(ss []string) ([]byte, int32) {
 308  	if len(ss) == 0 {
 309  		return nil, 0
 310  	}
 311  	total := 0
 312  	for _, s := range ss {
 313  		total += len(s) + 1
 314  	}
 315  	buf := []byte{:0:total}
 316  	for i, s := range ss {
 317  		buf = buf | s
 318  		if i < len(ss)-1 {
 319  			buf = append(buf, 0)
 320  		}
 321  	}
 322  	return buf, int32(len(ss))
 323  }
 324  
 325  func ptrToString(ptr int32, length int32) (s string) {
 326  	if length <= 0 {
 327  		return ""
 328  	}
 329  	return unsafe.String((*byte)(unsafe.Pointer(uintptr(ptr))), length)
 330  }
 331