`wasm-bindgen` 的設計
本節旨在深入探討 `wasm-bindgen` 目前在 Rust 中的內部運作方式。如果您在遙遠的未來閱讀此內容,它可能不再是最新的,但請隨時開啟一個問題,我們可以嘗試回答問題和/或更新此內容!
基礎:ES 模組
關於 `wasm-bindgen`,首先要了解的是,它基本上建立在 ES 模組的概念之上。換句話說,這個工具採取一個明確的立場,認為 Wasm 檔案應被視為 ES 模組。這表示您可以從 Wasm 檔案 `import`,使用其 `export` 的功能等等,從一般的 JS 檔案中進行。
現在不幸的是,在撰寫本文時,Wasm 互操作的介面不是很豐富。Wasm 模組只能呼叫函式或匯出函式,這些函式僅處理 `i32`、`i64`、`f32` 和 `f64`。真可惜!
這就是這個專案的用武之地。`wasm-bindgen` 的目標是使用更豐富的型別(如類別、JS 物件、Rust 結構、字串等)來增強 Wasm 模組的「ABI」。但請記住,一切都基於 ES 模組!這表示編譯器實際上正在產生某種「損壞」的 Wasm 檔案。例如,rustc 發出的 wasm 檔案不具有我們希望擁有的介面。相反,它需要 `wasm-bindgen` 工具來後處理檔案,產生 `foo.js` 和 `foo_bg.wasm` 檔案。`foo.js` 檔案是使用 JS 表示的所需介面(類別、型別、字串等),而 `foo_bg.wasm` 模組僅用作實作細節(它與原始的 `foo.wasm` 檔案略有修改)。
隨著 WebAssembly 中隨著時間的推移穩定更多功能(例如元件模型),預計 JS 檔案會變得越來越小。它不太可能永遠消失,但 `wasm-bindgen` 旨在密切遵循 WebAssembly 規範和提案,以盡可能地優化 JS/Rust。
基礎 #2:在 Rust 中不具侵入性
在更像 Rust 的方面,`wasm-bindgen` crate 的設計理想情況下是對 Rust crate 的影響盡可能小。理想情況下,在關鍵位置註解幾個 `#[wasm_bindgen]` 屬性,否則您就可以開始了。該屬性力求既不發明新的語法,又能與現有的慣用語法一起使用。
例如,一個函式庫可能會在正常的 Rust 中公開一個如下的函式
#![allow(unused)] fn main() { pub fn greet(name: &str) -> String { // ... } }
使用 `#[wasm_bindgen]`,您需要做的就是將其導出到 JS
#![allow(unused)] fn main() { #[wasm_bindgen] pub fn greet(name: &str) -> String { // ... } }
此外,這裡在 Rust 中進行最小干預的設計應允許我們輕鬆利用即將推出的元件模型提案。理想情況下,您只需升級 `wasm-bindgen` 的 crate 以及您的工具鏈,就可以立即取得對元件模型的原始存取權! (但這仍然需要一段時間...)