Prompt
wasm bindgenでrustからjsにResult, Option, “panic”を渡すとどうなる?
さすが情報工学徒、フロントエンドとバックエンドの境界線での「エラーの挙動」に目を付けるとは、いいセンスしてるぜ!
Rust の堅牢なエラー処理と、JavaScript の柔軟(という名のカオス)な例外処理。この 2 つが wasm-bindgen という架け橋を渡るとき、裏側でどんな変換が行われているのか、一気に解説するよ!🚀
1. 🦀 Result<T, E> を渡すとき
これが一番よく使うパターンだね!wasm-bindgen は、Rust の Result を JS の「Promise の拒否 (Reject)」または「例外 (Exception)」 に変換してくれるんだ。
挙動
-
Ok(value): 普通に JS の値として返る。 -
Err(error): JS 側でthrowされた例外 として扱われる。
Rust
#[wasm_bindgen]
pub fn risky_function(val: i32) -> Result<i32, JsValue> {
if val > 0 {
Ok(val * 2)
} else {
Err(JsValue::from_str("0以下はダメだぜ!"))
}
}
JS 側での受け取り方
JavaScript
try {
const res = risky_function(-1);
} catch (e) {
console.error(e); // "0以下はダメだぜ!" が表示される
}
⚠️ 落とし穴:
Result<T, E>のE(エラー型)は、JsValueか、それに変換可能な型である必要があるんだ。自作のstruct MyErrorをそのまま返そうとするとコンパイルエラーになるから注意だぜ!
2. ❓ Option<T> を渡すとき
これは非常に直感的だ!
-
Some(value): JS の値としてそのまま渡る。 -
None: JS のundefinedに変換される。
Rust
#[wasm_bindgen]
pub fn find_user(id: i32) -> Option<String> {
if id == 1 { Some("Ferris".into()) } else { None }
}
JS 側では if (user === undefined) でチェックすれば OK。シンプルで使いやすいよね。
3. 💥 “panic!” が起きたとき(最重要!)
ここが一番「おもしろい(恐ろしい)」ポイントだ。
Rust 側で panic! が発生すると、デフォルトでは WebAssembly の実行が即座に停止する。
デフォルトの挙動
-
JS 側には
RuntimeError: unreachableという不親切なエラーが飛んでくる。 -
Rust 側のパニックメッセージ(「〇〇行目で失敗した」とか)は、JS のコンソールには表示されないんだ。これだとデバッグが地獄だよね。
💡 解決策:console_error_panic_hook
これを導入するのが Wasm 開発の鉄則だぜ!
Rust
// プログラムの開始時に一度呼んでおく
console_error_panic_hook::set_once();
これを入れると、Rust のパニックメッセージとバックトレース(関数の呼び出し履歴)が、JS の console.error に綺麗に出力されるようになる。君が Windows 11 で開発していても Ubuntu で開発していても、ブラウザのデバッガが最強の味方になるわけだ。
🧐 見落とされがちな視点:メモリリーク
もし panic! が起きて Wasm が停止しても、JS のエンジン(V8 など)自体は生き残る。
ただし、パニックした Wasm インスタンスのメモリ状態は不定になるから、基本的にはそのページをリロードするか、インスタンスを破棄して作り直すのが安全だね。
🏁 まとめ
| Rust の型 | JavaScript での姿 |
|---|---|
Ok(T) | 値 T |
Err(E) | throw (例外) |
Some(T) | 値 T |
None | undefined |
panic! | unreachable エラー (停止) |
次は、この Result を使って「Rust で計算して、エラーなら JS のアラートを出す」みたいな連携を作ってみる?それとも、Wasm のメモリを JS から直接覗き見する変態的な(?)テクニックを攻めてみる?😊✨
Would you like me to show you how to set up console_error_panic_hook in a typical wasm-pack project?