Skip to content

[#446 Tier 1 #5] WASM-exports calling pattern (recommended kickoff) #455

Closed

Description

@hyperpolymath

Part of #446 — Tier 1 item 5. Recommended kickoff per roadmap memory.

Goal

Ship the WASM-exports calling pattern as the first concrete binding from the top-50 roadmap. Lowest scope, highest leverage:

  • ~30 extern fns OR one generic wasm_export_call (design decision)
  • < 1 day estimated
  • Unlocks idaptik vm/wasm AND every future WASM-host integration

Background

stdlib/Deno.affine has WasmExports type + wasmInstance. What it lacks is the calling pattern for the exports of a loaded wasm instance — i.e., once you've loaded mywasm.wasm, how do you call mywasm.exports.add(1, 2) from AffineScript?

Two design options:

Option A: extern fns per type signature

Generate ~30 extern fns covering common signatures:

  • wasm_call_0args_returns_i32
  • wasm_call_1arg_i32_returns_i32
  • wasm_call_2args_i32_i32_returns_i32
  • ... etc.

Pros: type-safe; AS typechecker knows what's allowed.
Cons: bloats Deno.affine; doesn't cover unusual signatures.

Option B: single generic wasm_export_call

extern fn wasm_export_call(
  exports: WasmExports,
  name: String,
  args: Array<WasmValue>
): WasmValue

Where WasmValue is a sum of I32 | I64 | F32 | F64.

Pros: single binding; covers any signature.
Cons: weaker type-safety at the AS call-site (user must marshal manually).

Owner decision needed in PR review — recommendation: ship Option B first (smaller, covers everything), then add Option A overloads as Deno.affine mature.

Acceptance

  • Deno.affine exports a wasm_export_call (or per-signature variants)
  • Idris2 ABI pattern documented (per estate convention: Zig=APIs/FFIs, Idris2=ABIs)
  • Zig FFI implementation lives in affinescript-stdlib/ffi/zig/ (or wherever current pattern dictates)
  • At least one consumer-side example: e.g., examples/wasm-exports-demo.affine that loads a tiny wasm and invokes an export

Test plan

  • Build green: dune build (or whatever the AS build command is — confirm at start)
  • Example runs end-to-end with deno run -A examples/wasm-exports-demo.ts (or AS equivalent)
  • Idaptik vm/wasm consumer team verifies the binding shape works for their use case

Sequencing

  • BLOCKED ON: nothing — this is the kickoff.
  • BLOCKS: every future Tier 1 item that needs to interact with loaded wasm modules (idaptik vm/wasm, Phoenix WebSocket framing if it composes a wasm marshalling step, etc.)

Cross-references

Activity

  1. added
    majorMajor issue — significant scope, broader impact than a feature/bug
    bindingsABI, FFI, WASM, and cross-language interop surfaces
    tier-1AS bindings top-50 Tier 1 (idaptik blockers)
    on May 30, 2026
  2. hyperpolymath commented on May 30, 2026

    @hyperpolymath
    OwnerAuthor

    Decision: Option B — single generic wasm_export_call(exports, name, args: Array<WasmValue>): WasmValue.

    Why B

    • Future-proof — covers any wasm signature including i64, multi-value returns, future spec additions; no binding change required as wasm evolves.
    • Tiny addition to Deno.affine (one extern fn + one sum type) vs ~30 near-identical declarations.
    • Doesn't preclude Option A — typed wrappers can be layered on top of wasm_export_call later as ergonomic helpers. Picking A would delay the generic; picking B doesn't delay typed wrappers (they sit on top).
    • Mirrors the well-trodden "ship generic first, type on top" pattern (JSON.parse → Zod; HTTP → typed clients).

    Acknowledged trade-off

    Weaker static safety at the call site — user marshals manually to WasmValue (I32 | I64 | F32 | F64). Errors deferred to runtime. Acceptable for the kickoff binding; typed wrappers will land as a follow-up sub-issue once usage patterns crystallise.

    Implementation scope

    • Deno.affine: add WasmValue sum type + wasm_export_call extern declaration
    • Zig FFI: implement the call dispatch (marshal args, find export by name, call, marshal return)
    • Idris2 ABI: pattern doc per estate convention (Zig=APIs/FFIs, Idris2=ABIs)
    • Example: examples/wasm-exports-demo.affine loading a tiny wasm + invoking an export end-to-end
    • Test: smoke-test through the Zig FFI

    Ready for a dedicated implementation session.

  3. added 5 commits that reference this issue on May 30, 2026
    9074c20
    fd3b409
    b407f43
    fb7e855
    7ada658
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bindingsABI, FFI, WASM, and cross-language interop surfacesmajorMajor issue — significant scope, broader impact than a feature/bugtier-1AS bindings top-50 Tier 1 (idaptik blockers)

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions