参考类型支持
WebAssembly 最近获得了对名为 externref
的新值类型的支持。在 WebAssembly 参考类型存储库中提出的 WebAssembly 的此功能有望实现主机(JS)和 Wasm 模块之间更高效的通信。此功能消除了 wasm-bindgen
生成的大部分 JS 粘合代码的需要,因为它可以使用 JS 值原生调用 API。
例如,这个 Rust 函数
#![allow(unused)] fn main() { #[wasm_bindgen] pub fn takes_js_value(a: &JsValue) { // ... } }
在没有参考类型支持的情况下生成此 JS 粘合代码
const heap = new Array(32).fill(undefined);
heap.push(undefined, null, true, false);
let stack_pointer = 32;
function addBorrowedObject(obj) {
if (stack_pointer == 1) throw new Error('out of js stack');
heap[--stack_pointer] = obj;
return stack_pointer;
}
export function takes_js_value(a) {
try {
wasm.takes_js_value(addBorrowedObject(a));
} finally {
heap[stack_pointer++] = undefined;
}
}
我们可以在这里看到 JS 如何在底层管理一个 JS 值表,这些值被传递给 Wasm 二进制文件,因此 Wasm 实际上只使用索引。但是,如果我们使用 -Ctarget-feature=+reference-types
(自 Rust v1.82 起默认)进行编译,则生成的 JS 如下所示
export function takes_js_value(a) {
wasm.takes_js_value(a);
}
就是这样!WebAssembly 二进制文件直接获取 JS 值并在内部进行管理。
目前,Firefox 79+ 和 Chrome 支持此功能。其他浏览器很可能很快也会支持!在 Node.js 中,此功能位于 --experimental-wasm-anyref
标志之后,尽管截至 14.6.0,该支持当前与上游规范不一致。