spawn_wasm.mx raw

   1  //go:build js && wasm
   2  
   3  package runtime
   4  
   5  import "unsafe"
   6  
   7  // Bridge imports for spawn-boundary SAB channels and domain creation.
   8  // These are provided by wasm-worker-host.mjs in the JS host.
   9  
  10  //go:wasmimport bridge channel_create
  11  func bridgeChannelCreate(slotSize, slotCount int32) int32
  12  
  13  //go:wasmimport bridge channel_send
  14  func bridgeChannelSend(handle int32, srcPtr *byte, srcLen int32)
  15  
  16  //go:wasmimport bridge channel_recv
  17  func bridgeChannelRecv(handle int32, dstPtr *byte, dstCap int32) int32
  18  
  19  //go:wasmimport bridge channel_close
  20  func bridgeChannelClose(handle int32)
  21  
  22  //go:wasmimport bridge spawn_domain
  23  func bridgeSpawnDomain(fnIdx int32, argPtr *byte, argLen int32, chanHandlesPtr *byte, nChans int32)
  24  
  25  //go:wasmimport bridge is_worker_context
  26  func bridgeIsWorkerContext() int32
  27  
  28  // SpawnChannelCreate creates a SAB-backed channel for use across a spawn
  29  // boundary. slotSize and slotCount must both be powers of two; slotSize
  30  // >= 64. Returns an opaque int32 handle stored as a uintptr.
  31  func SpawnChannelCreate(slotSize, slotCount int32) uintptr {
  32  	return uintptr(bridgeChannelCreate(slotSize, slotCount))
  33  }
  34  
  35  // SpawnChannelSend sends bytes to a SAB channel identified by handle.
  36  func SpawnChannelSend(handle uintptr, data unsafe.Pointer, n int32) {
  37  	bridgeChannelSend(int32(handle), (*byte)(data), n)
  38  }
  39  
  40  // SpawnChannelRecv receives into dst from a SAB channel. Returns byte count
  41  // or -1 if the channel is closed.
  42  func SpawnChannelRecv(handle uintptr, dst unsafe.Pointer, cap int32) int32 {
  43  	return bridgeChannelRecv(int32(handle), (*byte)(dst), cap)
  44  }
  45  
  46  // SpawnChannelClose marks a SAB channel as closed.
  47  func SpawnChannelClose(handle uintptr) {
  48  	bridgeChannelClose(int32(handle))
  49  }
  50  
  51  // SpawnDomain creates a new Worker running the spawned function at fnIdx.
  52  // argPtr/argLen carry serialized scalar args; chanHandlesPtr/nChans carry
  53  // int32 SAB handles. Called by compiler-emitted spawn site code.
  54  //
  55  // Panics if not running inside a Web Worker: channel_recv uses Atomics.wait
  56  // which is forbidden on the main browser thread. See moxie/wasm deployment docs.
  57  func SpawnDomain(fnIdx int32, argPtr unsafe.Pointer, argLen int32, chanHandlesPtr unsafe.Pointer, nChans int32) {
  58  	if bridgeIsWorkerContext() == 0 {
  59  		runtimePanic("moxie/spawn: wasm binary must be loaded inside a Web Worker — channel_recv uses Atomics.wait which is blocked on the main thread")
  60  	}
  61  	bridgeSpawnDomain(fnIdx, (*byte)(argPtr), argLen, (*byte)(chanHandlesPtr), nChans)
  62  }
  63