调试 Rust 生成的WebAssembly
本节包含 Rust 调试生成的 WebAssembly 的提示。
带调试符号的构建
⚡ 调试时,请务必确保,是使用调试符号构建的!
如果没有启用调试符号,那么自定义 "name"
部分不会出现在已编译二进制 .wasm
文件中,还有堆栈跟踪的是像 wasm-function[42]
这样的函数名称,而不是函数的 Rust 名称,如 wasm_game_of_life::Universe::live_neighbor_count
。
使用调试版本时(就是 wasm-pack build --debug
或 cargo build
),当然默认情况下启用调试符号。
对于 “release” 构建,默认情况下不启用调试符号。
要启用调试符号,请确保在 Cargo.toml
的 [profile.release]
部分中 debug=true
:
[profile.release]
debug = true
使用 console
API 记录日志
日志记录是我们拥有的最有效的工具之一,可以用来证明和反驳关于为什么我们的程序有缺陷的假设。 在 Web 上,console.log函数 用于将消息记录到浏览器的开发人员工具控制台。
我们可以使用 web-sys
crate 获取 console.log
函数。
extern crate web_sys;
web_sys::console::log_1(&"Hello, world!".into());
或者,函数 console.error 与 console.log 具有相同的签名,不同的是,使用 console.error 在日志消息旁边会捕获和显示堆栈跟踪。
参考
- 使用
web-sys
crate 的console.log
: - 使用
web-sys
crate 的console.error
: - MDN 的
console
对象 - Firefox 开发工具 — Web Console
- Microsoft Edge 开发工具 — Console
- 入门 Chrome DevTools Console
记录 Panics
console_error_panic_hook
crate 会将控制台意外的 panics 记录到 console.error
。
而不是变得晦涩难懂,难以调试的 RuntimeError: unreachable executed
错误消息,这会给你 Rust 格式化的 panic 消息。
你只需要在初始化函数或公共代码路径中通过调用 console_error_panic_hook::set_once()
:
#[wasm_bindgen]
pub fn init_panic_hook() {
console_error_panic_hook::set_once();
}
使用调试器
不幸的是,WebAssembly的调试还不成熟。在大多数 Unix 系统上 DWARF 用于对调试器提供运行程序的源代码级检查所需的信息进行编码。 在 Windows 上有一种编码类似信息的替代格式。 目前,WebAssembly 的类似的东西。 因此,调试器目前提供的实用程序有限,我们最终将逐步执行编译器发出的原始 WebAssembly 指令,而不是编写的源代码文本。
有一个用于调试 W3C Webassembly 组的子章节 ,所以希望这个在将来得到改进!
尽管如此,调试器对于检查与我们的 WebAssembly 交互的 JavaScript 和检查原始 wasm 状态仍然很有用。
参考
- 调试器 - Firefox 开发者工具 | MDN
- Microsoft Edge Developer Tools — Debugger
- Get Started with Debugging JavaScript in Chrome DevTools
首先避免调试WebAssembly
如果该错误来自与 JavaScript 或 Web API 的交互,那么先用 wasm-bindgen-test
写测试吧。
如果 bug 不涉及与 JavaScript 或 webapi 的交互,那么尝试将其复制为一个普通的 Rust #[test]
函数,在调试时可以利用本地成熟的工具。
使用像 quickcheck
这样的测试 crate 和它的测试用例 shrinkers 来机械地减少测试用例。
最终,如果你可以将 bug 隔离在一个不需要与 JavaScript 交互的较小的测试用例中,那么你将更容易找到和修复 bug。
请注意,为了在没有编译器和链接器错误的情况下运行本机 #[test]
,你需要确保 Cargo.toml
文件的 [lib.cratet type]
数组中包含 “rlib”
。
[lib]
crate-type ["cdylib", "rlib"]