mirror of
https://github.com/ChaiScript/ChaiScript.git
synced 2026-06-15 08:26:16 +08:00
Replace the static ChaiScript singleton in the Emscripten wrapper with a handle-based registry symmetric to the existing State registry. JS callers now create an engine with chaiscript_create(), pass the resulting handle to the eval/state helpers, and release it with chaiscript_destroy(). Multiple independent engines are now possible, and a state snapshot can be restored onto any engine. Updated the playground HTML and the three native regression tests to exercise the new API. Requested by @lefticus in PR #699 review. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
77 lines
2.8 KiB
C++
77 lines
2.8 KiB
C++
// Test that validates the save/restore/release state helpers used by the
|
|
// Emscripten wrapper. A handle-based registry is exposed so the JS playground
|
|
// can capture a pristine engine once and restore it between runs without
|
|
// reloading the WASM module.
|
|
|
|
#ifndef CHAISCRIPT_NO_THREADS
|
|
#define CHAISCRIPT_NO_THREADS
|
|
#endif
|
|
|
|
#ifndef CHAISCRIPT_NO_DYNLOAD
|
|
#define CHAISCRIPT_NO_DYNLOAD
|
|
#endif
|
|
|
|
#include "../emscripten/chaiscript_eval.hpp"
|
|
#include <cassert>
|
|
#include <chaiscript/chaiscript.hpp>
|
|
#include <string>
|
|
|
|
int main() {
|
|
const int chai = chaiscript_create();
|
|
assert(chai > 0 && "create must return a positive handle");
|
|
|
|
// Capture a baseline before any user code has been evaluated.
|
|
const int baseline = chaiscript_save_state(chai);
|
|
assert(baseline > 0 && "saveState must return a positive handle");
|
|
|
|
// Distinct calls produce distinct handles.
|
|
const int second = chaiscript_save_state(chai);
|
|
assert(second != baseline && "saveState must mint a fresh handle each call");
|
|
chaiscript_release_state(second);
|
|
|
|
// Define a global that did not exist in the baseline.
|
|
chaiscript_eval(chai, "var post_baseline_marker = 123");
|
|
assert(chaiscript_eval_int(chai, "post_baseline_marker") == 123);
|
|
|
|
// Restoring the baseline must drop the post-baseline definition: evaluating
|
|
// it should now fail with eval_error because the variable is undefined.
|
|
chaiscript_restore_state(chai, baseline);
|
|
|
|
[[maybe_unused]] bool caught = false;
|
|
try {
|
|
chaiscript_eval(chai, "post_baseline_marker");
|
|
} catch (const chaiscript::exception::eval_error &) {
|
|
caught = true;
|
|
}
|
|
assert(caught && "restoreState must drop globals defined after the snapshot");
|
|
|
|
// The engine remains usable after a restore.
|
|
chaiscript_eval(chai, "var after_restore = 7");
|
|
assert(chaiscript_eval_int(chai, "after_restore * 6") == 42);
|
|
|
|
// Releasing the handle is required so the registry does not grow unbounded.
|
|
chaiscript_release_state(baseline);
|
|
|
|
// Releasing a handle that was never minted (or has already been released) is
|
|
// a no-op rather than an error.
|
|
chaiscript_release_state(baseline);
|
|
chaiscript_release_state(99999);
|
|
|
|
// Restoring an unknown handle is a no-op: state must be unchanged.
|
|
chaiscript_restore_state(chai, 99999);
|
|
assert(chaiscript_eval_int(chai, "after_restore") == 7);
|
|
|
|
// A snapshot taken on one engine can be restored onto a different engine,
|
|
// confirming that state is decoupled from any particular instance.
|
|
const int snapshot_with_after_restore = chaiscript_save_state(chai);
|
|
const int chai2 = chaiscript_create();
|
|
chaiscript_restore_state(chai2, snapshot_with_after_restore);
|
|
assert(chaiscript_eval_int(chai2, "after_restore") == 7);
|
|
|
|
chaiscript_release_state(snapshot_with_after_restore);
|
|
chaiscript_destroy(chai2);
|
|
chaiscript_destroy(chai);
|
|
|
|
return 0;
|
|
}
|