這是 Rust 與 WebAssembly 使用教學的未發布文件,已發布的文件可從 Rust 和 WebAssembly 文件網站的主要部分 取得。這裡的文件功能可能在 Rust 和 WebAssembly 工具釋出的版本中並不支援。

偵錯 Rust 生成的 WebAssembly

本節包含 Rust 生成的 WebAssembly 偵錯秘訣。

用偵錯符號建置

⚡ 在進行除錯時,務必先用偵錯符號建置!

如果您未啟用偵錯符號,則已編譯的 .wasm binary 檔中將不會出現 "name" 自訂區段,堆疊追蹤將會顯示像 wasm-function[42] 等的函式名稱,而不是函式的 Rust 名稱,例如 wasm_game_of_life::Universe::live_neighbor_count

在使用「偵錯」建置 (又稱 wasm-pack build --debugcargo build) 時,會預設啟用偵錯符號。

在「版本」建置中不會預設啟用偵錯符號。若要啟用偵錯符號,請確保在 Cargo.toml[profile.release] 區段中將 debug = true

[profile.release]
debug = true

使用 console API 進行記錄

記錄是我們進行假設驗證和反證,以找出程式錯誤原因的有效工具之一。在網路上,console.log 函式是將訊息記錄到瀏覽器開發者工具主控台的方式。

我們可以使用 web-sys 封裝 來取得對 console 紀錄功能的存取


# #![allow(unused_variables)]
#fn main() {
extern crate web_sys;

web_sys::console::log_1(&"Hello, world!".into());
#}

另外, console.error 函式 具有與 console.log 相同的簽章,但開發人員工具會傾向於在使用 console.error 時捕捉和顯示堆疊追蹤以及已記錄的訊息。

參考文獻

記錄驚恐

console_error_panic_hook 封裝會透過 console.error 記錄意外的驚恐至開發人員主控台。這會提供 Rust 格式化的驚恐訊息,而不是取得難以除錯,又難以解讀的 RuntimeError: unreachable executed 錯誤訊息。

你只需要在初始化函式或共用程式碼路徑中呼叫 console_error_panic_hook::set_once() 來安裝掛鉤


# #![allow(unused_variables)]
#fn main() {
#[wasm_bindgen]
pub fn init_panic_hook() {
    console_error_panic_hook::set_once();
}
#}

使用除錯器

不幸的是,WebAssembly 的除錯說明仍並不成熟。在大部分 Unix 系統上,DWARF 用於編碼除錯器提供執行中程式碼原始碼層級檢查所需的資訊。有一個替用格式會在 Windows 上編碼類似的資訊。目前,並沒有 WebAssembly 的等效格式。因此,除錯器目前提供有限的效用,而且最後我們會逐步執行編譯器所產生的原始 WebAssembly 指令,而不是我們編寫的 Rust 原始碼文字。

W3C WebAssembly 小組有一個 關於除錯的子憲章,所以預期這項說明會在未來改進!

儘管如此,除錯器對於檢查與 WebAssembly 互動的 JavaScript,以及檢查原始 wasm 狀態仍然很有用。

參考文獻

避免一開始就除錯 WebAssembly

如果錯誤是 JavaScript 或網路 API 互動所專屬,那麼 使用 wasm-bindgen-test 撰寫測試。

如果錯誤不會涉及 JavaScript 或 Web API 的互動,那麼請嘗試以一般的 Rust #[test] 函數複製這個錯誤,在偵錯時你可以利用作業系統成熟的原生工具。使用像 quickcheck 這種測試函式庫,以及它的測試案例收縮器,來機械化地縮減測試案例。如果你能夠將錯誤孤立在較小的測試案例中,並且不需要與 JavaScript 互動,你將可以更快找到並修正錯誤。

請注意,為了在沒有編譯器和連結器錯誤情況下執行原生 #[test],你需要確保 "rlib" 已包含在 Cargo.toml 檔案中的 [lib.crate-type] 陣列中。

[lib]
crate-type ["cdylib", "rlib"]