From b9e8fe4bf1c2712afeeb9e4edef5abdd189b89fc Mon Sep 17 00:00:00 2001 From: Alex Dunmow Date: Fri, 3 Jul 2026 21:35:16 +0800 Subject: [PATCH] =?UTF-8?q?feat(wasmguest):=20HostServices()=20=E2=80=94?= =?UTF-8?q?=20per-instance=20CoreServices=20accessor?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Block/template render funcs receive only ctx+content over the ABI, no services. Load runs on a single pooled instance, so a DB-backed block on any other pooled instance had a nil pool. HostServices() exposes the CoreServices bound at _initialize on every instance (live db.* Pool + capability stubs) so render funcs resolve their pool per-instance. Zero value in native builds (Serve never called); callers nil-check Pool. Enables the symposium wasm port (WO-WZ-012). Co-Authored-By: Claude Fable 5 --- plugin/wasmguest/dispatch.go | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/plugin/wasmguest/dispatch.go b/plugin/wasmguest/dispatch.go index 8366344..43f4276 100644 --- a/plugin/wasmguest/dispatch.go +++ b/plugin/wasmguest/dispatch.go @@ -36,6 +36,26 @@ func Serve(reg plugin.PluginRegistration) { current = newGuest(reg) } +// HostServices returns the CoreServices bound to THIS guest instance. Unlike +// the deps handed to Load/HTTPHandler/JobHandlers — which the host delivers on +// only one pooled instance (Load) or lazily on first use — these services are +// bound at `_initialize` on EVERY pooled instance (newGuest). The interface +// fields are host_call-backed capability stubs and Pool is a live db.* bridge. +// +// This is the escape hatch for entry points the ABI does not hand deps to — +// most importantly block/template render funcs (HOOK_RENDER_BLOCK gives the +// closure only ctx+content, no services). A DB-backed block reads its pool from +// HostServices().Pool so it works on any pooled instance, not just the one that +// happened to run Load. In a native build (Serve never called — no wasip1 +// _initialize) current is nil and this returns the zero CoreServices, so guest +// code must nil-check Pool (native tests inject a real pool by other means). +func HostServices() plugin.CoreServices { + if current == nil { + return plugin.CoreServices{} + } + return current.services +} + // guest adapts a plugin.PluginRegistration to ABI hook calls. type guest struct { reg plugin.PluginRegistration