v149 · WebAssembly
WebAssembly Custom Descriptors
WasmGC structs can now carry a custom descriptor — a companion type whose first field becomes the struct's JavaScript prototype. Call wasmObj.myMethod() directly, with no hand-written wrapper class, and share type metadata across all instances instead of storing it per-object.
concepts
-
Prototype Bridge
Side-by-side comparison: the old pattern (JS wrapper class around raw Wasm exports) versus the new pattern (Wasm struct whose descriptor wires up the prototype automatically). Live code editor lets you call methods on both and see the difference.
-
Type-Safe Objects
Custom descriptors introduce exact types — a Counter descriptor cannot be applied to a Queue struct. Explore how the type boundary is enforced and why it matters for safe multi-type Wasm modules.
-
Method Dispatch Bench
Benchmark three dispatch patterns: JS wrapper class, per-object closures, and shared prototype (simulating custom descriptor). Side-by-side timing shows why the shared-prototype approach wins on both speed and memory — and how the real WasmGC custom descriptor takes it even further.
-
JS Interop Explorer
Live REPL with two sandboxed contexts — the old per-closure
Counterclass and a newCounterProtothat simulates the custom descriptor pattern. Evaluate arbitrary expressions, use preset snippets forinstanceof, prototype chain checks, and method calls, and see the outputs side by side. -
Memory Footprint Demo
Sliders for object count (10–5000) and methods per type (1–20) drive a live memory model comparing three allocation patterns: per-instance closures, JS wrapper class, and custom descriptor. Instance layout visualisation shows exactly which fields each approach stores per object.
-
Descriptor vs Wrapper Comparison
Step through six stages of the object lifecycle — module instantiation, object creation, method call,
instanceofcheck, prototype chain traversal, and memory layout — for both the legacy JS wrapper class and the new custom descriptor pattern. A side-by-side annotated code view and a live simulation that runs both patterns measure creation time and method-call throughput.
why it shipped
WasmGC structs have long been a mismatch with JavaScript's object model: every time you wanted to call a method, you either exported a free function (counter_get(ptr)) or built a hand-written JS proxy class that duplicated the type hierarchy. Custom descriptors let the Wasm module itself declare which JS prototype its struct objects should inherit, eliminating the boilerplate entirely and reducing per-instance memory (the descriptor object is shared at the type level, not copied per instance). The j2cl Java-to-Wasm compiler is the first major toolchain to use this to expose compiled Java classes with natural JS method-call syntax.
references
implementation reference
Need the exact API surface, compatibility boundaries, errors, lifecycle, and source links? Read the matching gendn reference ↗