Description
Motivation
The end-goal is drop-in integration with the Explicit Resource Management proposal (at Stage 3), with the nearer term goal of smoothing integration with tools that polyfill that.
The syntax it enables:
const func = () => {
// declare an instance of our wasm-bindgen'd struct, specifying that it should be cleaned up
// at the end of the scope it's declared in.
using foobar = new MyStruct();
// do a bunch of stuff...
}
func();
// When func() (or any other scope that keyword is used in) finishes, MyStruct::free is called
At the moment, Deno, Bun and Typescript >= 5.2 support the above directly; Usage without the above sugar is a little underwhelming, but probably still useful as a standardized target:
class MyStruct {
free() {} // the usual wasm-bindgen methods elided for brevity
[Symbol.dispose]() {
this.free();
}
}
const foo = new MyStruct();
foo[Symbol.dispose]();
// or, more usefully, use a disposable stack (supplied by a polyfill) to orchestrate
// more elaborate resource management
const stack = new DisposableStack();
const bar = stack.use(new MyStruct());
const baz = stack.use(new OtherStruct(bar));
// free the above in reverse order
stack[Symbol.dispose]();
Proposed Solution
Include the [Symbol.dispose]() { this.free() }
pattern on all generated classes, polyfilling via Symbol.dispose ??= Symbol("Symbol.dispose");
.
Async dispose is probably irrelevant
Alternatives
It's not terribly difficult for 3rd party authors to run the generated bindings through code transformation of their own.
Additional Context
The ecmascript proposal, for reference: https://github.com/tc39/proposal-explicit-resource-management