-
Notifications
You must be signed in to change notification settings - Fork 0
3-component re-exporter resource chains: implement shim module approach #92
Description
Context
Epic #69 has been extensively investigated across multiple sessions. 70/73 runtime tests pass. The remaining 3 fixtures (resource_floats, resource_with_lists, resource-import-and-export) are 3-component re-exporter chains that fuse successfully but crash at runtime.
Root cause (proven)
The re-exporter's generated code (wit-bindgen) has conflicting requirements for borrow params:
- Dereference: The code uses the value directly as a raw pointer (
*(value as *const FloatRep)) — needs the REP - Drop: Rust's Drop impl calls
resource.drop(value)— needs a valid wasmtime HANDLE
With shared wasmtime resource types, these are incompatible: REPs are memory addresses (large), handles are sequential integers (small). No adapter-level fix can make one value serve both purposes.
Solution: Re-exporter shim module
Instead of trying to replicate canon lift/lower in the adapter, generate a proper shim module for re-exporter boundaries that preserves the component model's resource table semantics.
The shim module would:
- Export the re-exporter's functions with proper canon lift wrapping
- Handle borrow handle creation/destruction in the re-exporter's resource table
- Convert between the caller's and callee's resource representations
- Be instantiated as a separate core module within the P2 wrapper
This is the approach used by wit-component (the reference implementation) for re-exported resources.
Files to modify
- merger.rs: Export re-exporter's internal functions from the fused module
- resolver.rs: Skip adapter creation for re-exporter-targeted calls, mark them for shim handling
- component_wrap.rs: Generate the shim module with canon lift/lower for re-exporter functions
- lib.rs: Skip
wire_adapter_indicesfor shim-handled calls
Key findings from investigation
resource.repin the re-exporter is identity (the generated code doesn't call wasmtime'sresource.rep)- The re-exporter stores inner handles from
canon lowerinFloatRep.inner— these must be memory addresses (from the re-exporter's resource table), not sequential integers [method]functions extract inner handles via double indirection (struct field access);[static]functions forward reps directly from the stack — different indirection levels through the same 3→0 adapter- The cleanup path (function 417 → 353 → resource.drop) drops values via the imported type's
resource.drop, which must receive valid handles
Related PRs
- fix: reject multiply-instantiated modules in resolver #76-fix: prevent resource map overwrites and remove unsafe graph upgrades #91: Infrastructure improvements (all merged)
- Specifically fix: prevent resource map overwrites and remove unsafe graph upgrades #91: Safe fixes (or_insert + downgrade-only graph override)
Labels
Epic #69, enhancement