concept · WebAssembly

Type-Safe Objects

Custom descriptors introduce exact types — a Counter's descriptor cannot be placed on a Queue struct, and vice versa. This makes type mismatches a Wasm trap rather than a silent runtime bug. Try mixing types below to see the enforcement.

the type hierarchy

A module that exposes two WasmGC types with custom descriptors pairs each struct with a dedicated descriptor type:

$counter (struct)
$val: mut i32
$counter.desc (descriptor)
$proto: ref null extern ← JS prototype
$queue (struct)
$head: mut i32
$tail: mut i32
$queue.desc (descriptor)
$proto: ref null extern ← JS prototype

allocation with a descriptor

;; struct.new_desc takes the descriptor instance as the final operand (func $counter.new (param $initial i32) (result (ref $counter)) (struct.new_desc $counter (local.get $initial) ;; field $val (global.get $counter.vtable) ;; descriptor instance (shared) ) ) ;; Using the wrong descriptor → Wasm trap at allocation time ;; (exact types enforce that $counter.desc ≠ $queue.desc)
Live experiment — type enforcement

Create Counter and Queue objects, then try calling methods across types. With custom descriptors the prototype chain is distinct per type.

Click a button to start…
Exact types: The proposal introduces an exact type modifier. An exact Counter type is a subtype of the plain Counter heap type but not a supertype of Counter's subtypes. This prevents descriptor mixing — you cannot allocate a Counter struct using a Queue descriptor even if both are structurally similar. The Wasm engine enforces this at allocation time, turning a class of bugs that previously surfaced as memory corruption into clean traps.

see also

implementation reference

Need the exact API surface, compatibility boundaries, errors, lifecycle, and source links? Read the matching gendn reference ↗