demo · v141
WASM Type Explorer
Parse WAT-like type definitions, visualise the memory layout of GC structs, and see how custom descriptors let you attach a JS prototype to each type — turning opaque WASM references into first-class JS objects your devtools can inspect.
Experimental flag
Full Custom Descriptor support requires
chrome://flags/#enable-experimental-webassembly-features. The type parser, layout visualiser, and prototype-bridge demo below work without the flag — only the live WebAssembly.Module.customDescriptors() call requires it.
probing WebAssembly GC + Custom Descriptors…
WAT type DSL — edit and click Parse
type tree
Click Parse to inspect types.
memory layout
Click Parse to see field offsets.
before vs after custom descriptors
pre-141 / no descriptor
WASM object is opaque to JS
// JS side const pt = module.makePoint(3, 4); // pt is an opaque externref — // no prototype, no property access // Must call module functions const d = module.distance(pt); // Cannot inspect pt in DevTools
Chrome 141 + descriptors
WASM object has JS prototype
// JS side — custom descriptor
// attached $pointDesc prototype
const pt = module.makePoint(3, 4);
// pt now has JS prototype with methods
pt.distance(); // calls WASM func
pt.x; pt.y; // field accessors
// DevTools shows: Point { x:3, y:4 }
use case: image processing library
Without custom descriptors, a WASM pixel-manipulation library must route all operations through module-level functions. With descriptors, each Pixel struct gains a prototype with methods — pixel.toHex(), pixel.luminance() — callable directly from JS. DevTools can inspect the struct's fields. JSON serialisation works via the prototype's toJSON(). The WASM ↔ JS boundary disappears from the consumer's perspective.
the WAT descriptor syntax
;; Custom Descriptors proposal (WAT notation — illustrative)
(module
;; Define descriptor type that carries the JS prototype
(type $pointDesc (descriptor
(struct (field $proto externref))
))
;; Struct type with an associated custom descriptor
(type $Point (descriptor $pointDesc
(struct
(field $x f64)
(field $y f64)
)
))
;; Factory: creates a Point struct with host prototype wired in
(func (export "makePoint") (param $x f64) (param $y f64) (result (ref $Point))
(struct.new $Point (local.get $x) (local.get $y)))
;; Method: accessible as pt.distance() via prototype chain
(func (export "distance") (param $p (ref $Point)) (result f64)
(f64.sqrt (f64.add
(f64.mul (struct.get $Point $x (local.get $p)) (struct.get $Point $x (local.get $p)))
(f64.mul (struct.get $Point $y (local.get $p)) (struct.get $Point $y (local.get $p))))))
)
see also
- WebAssembly Custom Descriptors — feature index
- ChromeStatus entry
- Proposal overview