From 469d74a0a2ec641018af7dc7df4c9468f62e21b3 Mon Sep 17 00:00:00 2001 From: leftibot Date: Wed, 15 Apr 2026 17:26:53 -0600 Subject: [PATCH] Fix #14: Reset playground engine between runs and display errors The ChaiScript WASM engine accumulated state (variables, functions) across script executions, causing confusing errors when editing code. Additionally, if the engine aborted due to an unhandled exception, no meaningful error was shown and subsequent runs silently failed. Each run now reloads the WASM module via resetEngine() to guarantee a clean engine state. An onAbort handler catches WASM crashes and displays the error message. Exception formatting handles string, Error, and unknown throw types. Co-Authored-By: Claude Opus 4.6 (1M context) --- playground.html | 96 ++++++++++++++++++++++++++++++++++++---------- test_playground.sh | 10 ++++- 2 files changed, 85 insertions(+), 21 deletions(-) diff --git a/playground.html b/playground.html index 3d6efdc..9e6cdd4 100644 --- a/playground.html +++ b/playground.html @@ -270,32 +270,85 @@

Interactive Playground Loading&hellip outputEl.scrollTop = outputEl.scrollHeight; } - var Module = { - print: function(text) { - appendOutput(text); - }, - printErr: function(text) { - appendOutput(text, 'chai-output-error'); - }, - onRuntimeInitialized: function() { - statusEl.textContent = 'Ready'; - statusEl.className = 'ready'; - btnRun.disabled = false; - runtimeReady = true; - selectExample(0); + var engineAborted = false; + var engineScript = null; + var pendingCode = null; + var firstLoad = true; + + function setEngineStatus(text, className) { + statusEl.textContent = text; + statusEl.className = className; + } + + function formatError(e) { + if (typeof e === 'string') { return e; } + if (e && e.message) { return e.message; } + try { return String(e); } catch (_) { return 'Unknown error'; } + } + + function executePendingCode() { + if (!pendingCode) { return; } + var code = pendingCode; + pendingCode = null; + try { + Module.eval(code); + } catch (e) { + appendOutput('Error: ' + formatError(e), 'chai-output-error'); + } + } + + function createModuleConfig() { + return { + print: function(text) { + appendOutput(text); + }, + printErr: function(text) { + appendOutput(text, 'chai-output-error'); + }, + onAbort: function(what) { + engineAborted = true; + setEngineStatus('Error \u2014 click Run to retry', 'error'); + appendOutput('Engine error: ' + formatError(what), 'chai-output-error'); + }, + onRuntimeInitialized: function() { + engineAborted = false; + setEngineStatus('Ready', 'ready'); + btnRun.disabled = false; + runtimeReady = true; + if (firstLoad) { + firstLoad = false; + selectExample(0); + } else { + executePendingCode(); + } + } + }; + } + + var Module = createModuleConfig(); + + function resetEngine() { + runtimeReady = false; + btnRun.disabled = true; + setEngineStatus('Resetting\u2026', 'loading'); + if (engineScript) { + engineScript.parentNode.removeChild(engineScript); + engineScript = null; } - }; + Module = createModuleConfig(); + window.Module = Module; + engineScript = document.createElement('script'); + engineScript.src = '/playground/chaiscript.js'; + document.body.appendChild(engineScript); + } function runCode() { var code = inputEl.value; if (!code.trim()) { return; } outputEl.innerHTML = ''; - try { - Module.eval(code); - } catch (e) { - appendOutput('Error: ' + e.message, 'chai-output-error'); - } + pendingCode = code; + resetEngine(); } function scheduleLiveRun() { @@ -331,7 +384,10 @@

Interactive Playground Loading&hellip }); buildSidebar(); + + engineScript = document.createElement('script'); + engineScript.src = '/playground/chaiscript.js'; + document.body.appendChild(engineScript); - diff --git a/test_playground.sh b/test_playground.sh index ebb1d38..6869f0f 100644 --- a/test_playground.sh +++ b/test_playground.sh @@ -64,7 +64,15 @@ assert_file_contains "playground.html" "example-item" assert_file_contains "playground.html" "debounceTimer" assert_file_contains "playground.html" "addEventListener.*input" -# 9. Playground examples cover major ChaiScript features +# 9. Playground engine is reset between runs (issue #14) +assert_file_contains "playground.html" "resetEngine" +assert_file_contains "playground.html" "onAbort" + +# 10. Playground catches and displays exceptions with detail (issue #14) +assert_file_contains "playground.html" "chai-output-error" +assert_file_contains "playground.html" "engineAborted" + +# 11. Playground examples cover major ChaiScript features assert_file_contains "playground.html" "Variables & Types" assert_file_contains "playground.html" "Functions" assert_file_contains "playground.html" "Loops"