From 34a95a28a06d1d4791a5b3737d5b4b5367150e8f Mon Sep 17 00:00:00 2001 From: leftibot Date: Thu, 30 Apr 2026 17:03:00 -0600 Subject: [PATCH] Address review: snapshot top-level locals alongside engine state ChaiScript::State captures globals, functions, and types but not the top-level scripting locals created by `var x = ...`. The previous restoreState therefore left such variables behind, breaking the playground reset use case and tripping the new test's assertion in Debug builds (where assert is enabled). Pair get_state with get_locals in the snapshot so a restore brings back a clean baseline. Requested by @lefticus in PR #699 review. Co-Authored-By: Claude Opus 4.7 (1M context) --- emscripten/chaiscript_eval.hpp | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/emscripten/chaiscript_eval.hpp b/emscripten/chaiscript_eval.hpp index 70c861e6..02aca25c 100644 --- a/emscripten/chaiscript_eval.hpp +++ b/emscripten/chaiscript_eval.hpp @@ -12,6 +12,7 @@ #define CHAISCRIPT_EMSCRIPTEN_EVAL_HPP_ #include +#include #include #include @@ -21,8 +22,17 @@ namespace detail { return chai; } - inline std::unordered_map &state_registry() { - static std::unordered_map registry; + // ChaiScript::State captures globals/functions/types but not the top-level + // scripting locals (variables created by `var x = ...` at the script's + // outermost scope). The playground's reset-between-runs use case needs both, + // so the snapshot pairs the engine state with the locals map. + struct Snapshot { + chaiscript::ChaiScript::State engine_state; + std::map locals; + }; + + inline std::unordered_map &state_registry() { + static std::unordered_map registry; return registry; } @@ -61,7 +71,8 @@ inline double chaiscript_eval_double(const std::string &input) { // no longer needed. inline int chaiscript_save_state() { const int handle = detail::next_state_handle(); - detail::state_registry().emplace(handle, detail::get_chai_instance().get_state()); + auto &chai = detail::get_chai_instance(); + detail::state_registry().emplace(handle, detail::Snapshot{chai.get_state(), chai.get_locals()}); return handle; } @@ -70,7 +81,9 @@ inline int chaiscript_save_state() { inline void chaiscript_restore_state(const int handle) { const auto it = detail::state_registry().find(handle); if (it != detail::state_registry().end()) { - detail::get_chai_instance().set_state(it->second); + auto &chai = detail::get_chai_instance(); + chai.set_state(it->second.engine_state); + chai.set_locals(it->second.locals); } }