// Package wasmguest is the guest half of the BlockNinja wasm plugin ABI: // the go:wasmexport entry points (bn_alloc / bn_invoke / bn_free), guest // memory pinning, the generic host-call import, and the dispatch table that // adapts an unmodified plugin.PluginRegistration to ABI hook calls. // // The wire contract lives in core/docs/wasm-abi.md; the messages in // git.dev.alexdunmow.com/block/pluginsdk/abi/v1. // // # Plugin boilerplate // // A plugin becomes a wasm plugin by adding one main file next to its // Registration: // // //go:build wasip1 // // package main // // import "git.dev.alexdunmow.com/block/pluginsdk/plugin/wasmguest" // // func init() { wasmguest.Serve(Registration) } // func main() {} // never called — reactor mode // // and compiling in REACTOR mode (Go >= 1.24 toolchain; this repo's floor is // higher): // // GOOS=wasip1 GOARCH=wasm go build -buildmode=c-shared -o plugin.wasm . // // Reactor modules export `_initialize` instead of `_start`: the host runs // `_initialize` once per instance — which runs the init func above, hence // Serve — before any bn_invoke. Serve is non-blocking: it stores the // registration, runs the Register pass against capture registries, and // returns; all work then arrives through bn_invoke. // // Command mode (plain `go build`) does NOT work and must not be used: its // `_start` runs main synchronously, so a blocking main deadlocks the Go // runtime ("all goroutines are asleep") and a returning main exits and // closes the module — either way the exports are never callable // (empirically verified against wazero v1.12.0; see wasm-abi.md). // // # Build shape // // Dispatch, describe, capture-registry, and context-reconstruction logic is // plain Go and builds on every GOOS so it stays natively testable. Only // exports.go (go:wasmexport, memory pinning) and hostcalls.go // (go:wasmimport blockninja host_call) carry the wasip1 build tag. package wasmguest