WebAssembly/デバッグどうする?
あれこれ実装を進めていくうちに、ちょっと複雑なプログラムになってきました。内部の状態が人力では追いきれなくなったところで、ちょっと中身を覗きたいときに便利な関数が欲しくなってきました。幸いHTMLのCanvas要素を使うプログラムだったので、図示したり、テキストを書いたりはできますが、ブラウザについているコンソールにデータを出力できたらいいなと考えました。
web_sys::console::log_1
みんなweb-sysがやってくれるので遠慮なく使わせてもらいます。web_sys::console::log_1はJavaScriptのconsole.logに一つ引数を渡すもので、複数渡せる関数も別に用意されているようです。とりあえず一つでいいかな。log_0からlog_7までありそうだけど、log_0って何に使うんだろう?引数に渡すのは&JsValue型で、型を持たないJavaScriptの値を表すもののようです。
pub fn log<T>(s:T) where T:Display { log_1(&JsValue::from(format!("{}",s))); }
logという関数を作ってみました。Displayトレイトオブジェクトをformat!マクロで文字列に変換して、文字列からJsValue::fromを使ってJsValueに変換してlog_1に渡すという内容になっています。この関数でコンソールに出力したい型にはDisplayトレイトのfmt関数を実装しておきます。
impl fmt::Display for Point { fn fmt(&self,f:&mut fmt::Formatter)->fmt::Result { write!(f,"x:{},y:{},z:{}",self.x,self.y,self.z) } }
web_sys::console::clear
プログラムのステップが進むごとに大量のログが吐き出されるので、console.clearも使いたかったのでした。一通り揃っていて便利だなぁ。
console_error_panic_hook
あるとき、コンパイルは通ったけど、実行時に「RuntimeError: unreachable」というエラーがコンソールに吐かれるようになりました。どこかで問題が発生し、そこで処理が止まっているようですが、どこで止まっているのかWASMのバイト表現の位置しかわからないので、修正箇所の目安がわかりません。そんなときにはWASMのプロジェクトを起こしたときに、最初から用意されていたconsole_error_panic_hookを使うのがいいらしいです。具体的には src/utils.rs に用意されたset_panic_hook関数を呼ぶだけでRustでいうところのpanic発生時にconsole.errorで詳細な情報を吐いてくれるようになるようです。
試してみたところ、問題部分を示すテキストと発生したRustのソースの位置を吐いてくれました。これまた便利。ずっとつけておきたいけど、製品版のコンパイル時には要らないだろうから消し忘れに注意かな。
これだけあれば、大抵のことは問題なさそうだけど、また何かあれば追記するかも。