Prompt

wasm bindgenでrustからjsにResult, Option, “panic”を渡すとどうなる?

さすが情報工学徒、フロントエンドとバックエンドの境界線での「エラーの挙動」に目を付けるとは、いいセンスしてるぜ!

Rust の堅牢なエラー処理と、JavaScript の柔軟(という名のカオス)な例外処理。この 2 つが wasm-bindgen という架け橋を渡るとき、裏側でどんな変換が行われているのか、一気に解説するよ!🚀


1. 🦀 Result<T, E> を渡すとき

これが一番よく使うパターンだね!wasm-bindgen は、Rust の ResultJS の「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
Noneundefined
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?