Debugging WASM in Chrome DevTools
Chrome DevTools 中斷點攔截 WASM ref.cast 型別例外實戰
- Chrome DevTools Sources 面板可自動反組譯 WASM 為 WAT 格式並直接設置中斷點,無需額外工具鏈
- 勾選「Pause on exceptions」可在 ref.cast 型別轉換失敗的瞬間凍結執行,同步顯示呼叫堆疊與型別不符細節
- WASM gc 型別例外場景中,DevTools 除錯器的資訊密度顯著優於 printf 日誌法,且無需重新編譯
Chrome DevTools 早已能在 WebAssembly 二進位模組中設置中斷點、逐步執行 WAT 反組譯碼,並在 ref.cast 型別轉換失敗的瞬間凍結程式——不需要插入任何 printf,也不需要重新編譯,一次暫停就能同時拿到完整呼叫堆疊與型別資訊。Eli Bendersky 在為 Scheme 編譯器開發 WASM gc 後端的過程中,親身驗證了這套工作流程的有效性。
環境建置:local HTTP server 是第一關
瀏覽器載入 WASM 除錯符號需要 HTTP 協定;直接以 file:// 路徑開啟無法取得原始碼對應資訊。作者推薦兩種方案:安裝 static-server npm 套件(一行啟動),或直接用 Python 內建指令 python3 -m http.server 8080 在專案根目錄起服務。瀏覽器開啟 http://localhost:8080 後,DevTools 所有 WASM 除錯功能即完整可用。
WAT 反組譯:Sources 面板的隱藏入口
Chrome DevTools 的 Sources › Page › wasm 路徑下,所有已載入的 .wasm 模組都會自動以 WAT(WebAssembly Text Format,WASM 的人類可讀文字表示格式)展開。開發者可直接在 WAT 位址行上點擊設置中斷點,程式執行至該指令時即暫停,左側 Scope 面板同步顯示所有局部變數的當前值——包含 WASM gc 規範新增的引用型別(gc references)。
ref.cast 例外攔截:「Pause on exceptions」核取方塊
ref.cast 是 WASM gc 擴充規範中的引用型別轉換指令,等同靜態語言的強制型別轉型(downcast)。轉換目標型別不符時,執行引擎拋出例外並立即終止模組,若沒有攔截機制,錯誤訊息幾乎毫無診斷線索。
DevTools Sources 面板右側「Breakpoints」區塊內有兩個核取方塊:Pause on caught exceptions 與 Pause on uncaught exceptions。勾選後,任何未捕獲例外(含 ref.cast 失敗)都會在拋出當下凍結執行,Call Stack 顯示完整呼叫路徑,Scope 面板同時呈現失敗轉換的來源型別與目標型別,讓「期望型別 A、實際收到型別 B」的問題一覽無遺。
gc 引用型別的結構化檢視
WASM gc 引用型別在傳統工具中通常只顯示為不透明記憶體位址。Chrome DevTools 對 gc references 的支援已達到結構化展開的程度:Scope 面板中的 gc 引用欄位會列出物件內部欄位,開發者可直接確認值是否符合預期,不再需要透過 memory.copy 搬出原始位元組再手動解析。
printf vs 除錯器:WASM gc 例外的最終答案
傳統 WASM 開發者傾向使用 printf 等價手法(呼叫 JavaScript import 印出日誌)的理由是工具鏈複雜度高。作者的實際體驗給出更新的結論:在 gc 型別例外這個特定場景,中斷點搭配 Pause on exceptions 的資訊密度遠高於 printf——一次暫停同時取得呼叫堆疊、型別資訊與局部變數,而 printf 需要手動插入每個懷疑點、重新編譯後再執行。
Take-home:面對 WASM gc 的
ref.cast型別例外,Chrome DevTools「Pause on exceptions」可在零額外程式碼的情況下精準定位問題;printf 日誌仍適合快速確認執行流程,但一旦涉及型別系統錯誤,應優先開啟除錯器而非盲目插入 log。