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
↓ descriptor: $counter.desc
$counter.desc (descriptor)
$proto: ref null extern ← JS prototype
↑ describes: $counter
$queue (struct)
$head: mut i32
$tail: mut i32
↓ descriptor: $queue.desc
$queue.desc (descriptor)
$proto: ref null extern ← JS prototype
↑ describes: $queue
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
- Prototype Bridge — old vs new approach for calling Wasm methods
- ChromeStatus entry
- Proposal Overview
implementation reference
Need the exact API surface, compatibility boundaries, errors, lifecycle, and source links? Read the matching gendn reference ↗