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:
- build a core WASM reactor that owns memory, allocator,
Request,DValue, UCEB1, and output buffering; - build a separate PIC side module with
dylink.0from a generated-shape UCE page C++ file; - parse
dylink.0, allocate__memory_base/__table_base, resolveenv.*,GOT.mem.*, andGOT.func.*imports against the core/workspace; - 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.hinclude,__uce_set_current_request,__uce_render, literal markup lowered toprint(R"(...)"), expression prints wrapped inhtml_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
#ifdefintypes.hinstead 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.