From 7fc98f8801db99f5c734519d14691482e9bd6825 Mon Sep 17 00:00:00 2001 From: funman300 Date: Sun, 17 May 2026 20:48:30 -0700 Subject: [PATCH] fix(wasm): state() and step() return Result so errors throw JS exceptions (CR-6) Previously both ReplayPlayer::state() and ::step() returned JsValue::NULL for both the expected "replay exhausted" case and the unexpected "serialisation failed" case. JavaScript callers could not distinguish the two. Now both methods return Result: - step() returns Ok(null) when the replay is finished (expected sentinel) - step() and state() Err(string) when serde_wasm_bindgen fails (throws JS exception) Same fix applied to SolitaireGame::state(). Co-Authored-By: Claude Sonnet 4.6 --- solitaire_wasm/src/lib.rs | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/solitaire_wasm/src/lib.rs b/solitaire_wasm/src/lib.rs index 71b6e7d..673dc5b 100644 --- a/solitaire_wasm/src/lib.rs +++ b/solitaire_wasm/src/lib.rs @@ -193,16 +193,24 @@ impl ReplayPlayer { } /// Snapshot the current `GameState` as a JS object (see `StateSnapshot`). - pub fn state(&self) -> JsValue { - serde_wasm_bindgen::to_value(&self.snapshot()).unwrap_or(JsValue::NULL) + /// + /// Throws a JS string exception on serialisation failure (should never + /// occur in practice — `StateSnapshot` contains only primitive types). + pub fn state(&self) -> Result { + serde_wasm_bindgen::to_value(&self.snapshot()) + .map_err(|e| JsValue::from_str(&e.to_string())) } /// Apply the next move; returns the post-step snapshot, or `null` /// once the move list is exhausted. - pub fn step(&mut self) -> JsValue { + /// + /// Returns `null` (not an exception) when the replay is finished. + /// Throws a JS string exception on serialisation failure. + pub fn step(&mut self) -> Result { match self.step_native() { - Some(snap) => serde_wasm_bindgen::to_value(&snap).unwrap_or(JsValue::NULL), - None => JsValue::NULL, + Some(snap) => serde_wasm_bindgen::to_value(&snap) + .map_err(|e| JsValue::from_str(&e.to_string())), + None => Ok(JsValue::NULL), } } @@ -364,8 +372,11 @@ impl SolitaireGame { } /// Full pile snapshot as a JS object. - pub fn state(&self) -> JsValue { - serde_wasm_bindgen::to_value(&self.snap()).unwrap_or(JsValue::NULL) + /// + /// Throws a JS string exception on serialisation failure. + pub fn state(&self) -> Result { + serde_wasm_bindgen::to_value(&self.snap()) + .map_err(|e| JsValue::from_str(&e.to_string())) } /// The seed used to deal this game.