uce/spikes/wasm-phase3
2026-06-12 19:55:35 +00:00
..
2026-06-12 19:55:35 +00:00
2026-06-12 19:55:35 +00:00
2026-06-12 19:55:35 +00:00
2026-06-12 19:55:35 +00:00
2026-06-12 19:55:35 +00:00
2026-06-12 19:55:35 +00:00
2026-06-12 19:55:35 +00:00
2026-06-12 19:55:35 +00:00

spikes/wasm-phase3 — dynamic loader + workspace scaffold

Phase 3 combines the Phase 0 dynamic PIC-module loader with the Phase 2 UCEB1 request-context membrane. It is still a spike, not the production wasm worker, but it validates the load-bearing pieces together:

  1. build a core WASM reactor that owns memory, allocator, Request, DValue, UCEB1, and output buffering;
  2. build a separate PIC side module with dylink.0 from a generated-shape UCE page C++ file;
  3. parse dylink.0, allocate __memory_base/__table_base, resolve env.*, GOT.mem.*, and GOT.func.* imports against the core/workspace;
  4. instantiate the unit, run relocations/constructors, set its Request pointer, call __uce_render, and read rendered output from core-owned memory.

The fixture intentionally exercises the loader branches that are easiest to accidentally leave dark: non-zero table_size / __table_base, GOT.func resolution (phase3_core_print), and deferred self-resolution of unit-owned GOT.mem entries. The loader output prints those resolutions before the final pass marker. Its generated-shape expressions call html_escape(...) so the side-module import surface includes the first ordinary UCE helper dependency rather than only types.h/DValue.

Run on k-uce:

bash spikes/wasm-phase3/build_modules.sh
bash spikes/wasm-phase3/build_loader.sh
/tmp/uce/wasm-phase3/loader

Expected final line:

PHASE3 EXIT CRITERION: PASS

Files:

  • core.cpp — core/workspace scaffold and UCEB1 membrane decode.
  • page.uce — source page for the generated-shape fixture.
  • generated/page.uce.cpp — checked-in UCE-preprocessor-shaped side-module fixture: uce_lib.h include, __uce_set_current_request, __uce_render, literal markup lowered to print(R"(...)"), expression prints wrapped in html_escape(...), callback/lambda/table exercises, and self-GOT data.
  • loader.cpp — dynamic linker/runner adapted from Phase 0.
  • hostcalls.syms — explicit core hostcall allowlist.

Still deferred to production Phase 3/4 work:

  • running the actual UCE preprocessor inside this build script rather than using a checked-in generated-shape fixture;
  • lazy component/path dispatch for a full site tree;
  • uce-starter end-to-end under a wasm FastCGI worker;
  • productionizing the side-module allocator gate as a real #ifdef in types.h instead of this spike's copied-header text patch;
  • parser hardening beyond the spike's basic magic/version/bounds/alignment checks, including fuzzing malformed wasm/dylink sections before accepting cache or third-party units;
  • import-policy hardening beyond this spike's fail-fast resolver;
  • workspace birth/drop integration with the real server lifecycle, including retaining unaligned allocation pointers needed to unload units or drop a workspace cleanly.