參考型別的支援

WebAssembly 最近增加了對稱為 externref 的新值型別的支援。在 WebAssembly 參考型別儲存庫 中提出的 WebAssembly 功能,希望能夠實現主機(JS)和 Wasm 模組之間更有效率的通訊。此功能消除了 wasm-bindgen 產生的大部分 JS 黏合程式碼的需求,因為它可以原生呼叫具有 JS 值的 API。

例如,這個 Rust 函式


# #![allow(unused_variables)]
#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,其支援目前與上游規範不一致。