Summary
In vera/browser/runtime.mjs, the State<T> host bindings (~lines 1347-1383) pick the initial state-cell default with key.includes('Float') ? 0.0 : BigInt(0), where key is the mangled type-arg suffix captured from the import name (state_get_<suffix>). After #914, composite State type arguments compile — e.g. State<Tuple<Float64, Int>> mangles to state_get_Tuple_LFloat64_C_Int_R. Such a composite/ADT state is represented as an i32 heap pointer, so its default cell value must be BigInt(0) (integer 0 / null pointer), not 0.0. But key.includes('Float') matches the substring "Float64" inside the mangled composite name and wrongly seeds the cell with the JS float 0.0.
Scope / reachability
Fix direction
Base the browser default on the actual WASM value type of the import, not a substring match on the mangled name:
- (a) read the scalar-vs-pointer (
f64 vs i32/i64) distinction from the import's declared param/result type via WebAssembly.Module.imports metadata if available, or
- (b) tighten the heuristic so ONLY a bare primitive
Float64 suffix (exact match, not a substring inside a composite name) is treated as float; any composite/ADT suffix takes the integer/pointer default.
Add a Node-vs-Python browser parity test in tests/test_browser.py for a State<Tuple<Float64, Int>> (or State<Option<Float64>>) read-before-put program; mutation-validate. Update doc counts + regenerate site assets.
Summary
In
vera/browser/runtime.mjs, theState<T>host bindings (~lines 1347-1383) pick the initial state-cell default withkey.includes('Float') ? 0.0 : BigInt(0), wherekeyis the mangled type-arg suffix captured from the import name (state_get_<suffix>). After #914, compositeStatetype arguments compile — e.g.State<Tuple<Float64, Int>>mangles tostate_get_Tuple_LFloat64_C_Int_R. Such a composite/ADT state is represented as an i32 heap pointer, so its default cell value must beBigInt(0)(integer 0 / null pointer), not0.0. Butkey.includes('Float')matches the substring"Float64"inside the mangled composite name and wrongly seeds the cell with the JS float0.0.Scope / reachability
vera/runtime/state.py) correctly uses the actualwasm_tfor the default, so nativevera runis unaffected.Stateis read (get) before anyput. Thehandle[State<...>](@T = init)init clause and anyputbeforegetmask it.Fix direction
Base the browser default on the actual WASM value type of the import, not a substring match on the mangled name:
f64vsi32/i64) distinction from the import's declared param/result type viaWebAssembly.Module.importsmetadata if available, orFloat64suffix (exact match, not a substring inside a composite name) is treated as float; any composite/ADT suffix takes the integer/pointer default.Add a Node-vs-Python browser parity test in
tests/test_browser.pyfor aState<Tuple<Float64, Int>>(orState<Option<Float64>>) read-before-putprogram; mutation-validate. Update doc counts + regenerate site assets.