Skip to content

Commit 469d74a

Browse files
leftibotclaude
andcommitted
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) <noreply@anthropic.com>
1 parent ca79701 commit 469d74a

2 files changed

Lines changed: 85 additions & 21 deletions

File tree

playground.html

Lines changed: 76 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -270,32 +270,85 @@ <h3>Interactive Playground <span id="chai-status" class="loading">Loading&hellip
270270
outputEl.scrollTop = outputEl.scrollHeight;
271271
}
272272

273-
var Module = {
274-
print: function(text) {
275-
appendOutput(text);
276-
},
277-
printErr: function(text) {
278-
appendOutput(text, 'chai-output-error');
279-
},
280-
onRuntimeInitialized: function() {
281-
statusEl.textContent = 'Ready';
282-
statusEl.className = 'ready';
283-
btnRun.disabled = false;
284-
runtimeReady = true;
285-
selectExample(0);
273+
var engineAborted = false;
274+
var engineScript = null;
275+
var pendingCode = null;
276+
var firstLoad = true;
277+
278+
function setEngineStatus(text, className) {
279+
statusEl.textContent = text;
280+
statusEl.className = className;
281+
}
282+
283+
function formatError(e) {
284+
if (typeof e === 'string') { return e; }
285+
if (e && e.message) { return e.message; }
286+
try { return String(e); } catch (_) { return 'Unknown error'; }
287+
}
288+
289+
function executePendingCode() {
290+
if (!pendingCode) { return; }
291+
var code = pendingCode;
292+
pendingCode = null;
293+
try {
294+
Module.eval(code);
295+
} catch (e) {
296+
appendOutput('Error: ' + formatError(e), 'chai-output-error');
297+
}
298+
}
299+
300+
function createModuleConfig() {
301+
return {
302+
print: function(text) {
303+
appendOutput(text);
304+
},
305+
printErr: function(text) {
306+
appendOutput(text, 'chai-output-error');
307+
},
308+
onAbort: function(what) {
309+
engineAborted = true;
310+
setEngineStatus('Error \u2014 click Run to retry', 'error');
311+
appendOutput('Engine error: ' + formatError(what), 'chai-output-error');
312+
},
313+
onRuntimeInitialized: function() {
314+
engineAborted = false;
315+
setEngineStatus('Ready', 'ready');
316+
btnRun.disabled = false;
317+
runtimeReady = true;
318+
if (firstLoad) {
319+
firstLoad = false;
320+
selectExample(0);
321+
} else {
322+
executePendingCode();
323+
}
324+
}
325+
};
326+
}
327+
328+
var Module = createModuleConfig();
329+
330+
function resetEngine() {
331+
runtimeReady = false;
332+
btnRun.disabled = true;
333+
setEngineStatus('Resetting\u2026', 'loading');
334+
if (engineScript) {
335+
engineScript.parentNode.removeChild(engineScript);
336+
engineScript = null;
286337
}
287-
};
338+
Module = createModuleConfig();
339+
window.Module = Module;
340+
engineScript = document.createElement('script');
341+
engineScript.src = '/playground/chaiscript.js';
342+
document.body.appendChild(engineScript);
343+
}
288344

289345
function runCode() {
290346
var code = inputEl.value;
291347
if (!code.trim()) { return; }
292348

293349
outputEl.innerHTML = '';
294-
try {
295-
Module.eval(code);
296-
} catch (e) {
297-
appendOutput('Error: ' + e.message, 'chai-output-error');
298-
}
350+
pendingCode = code;
351+
resetEngine();
299352
}
300353

301354
function scheduleLiveRun() {
@@ -331,7 +384,10 @@ <h3>Interactive Playground <span id="chai-status" class="loading">Loading&hellip
331384
});
332385

333386
buildSidebar();
387+
388+
engineScript = document.createElement('script');
389+
engineScript.src = '/playground/chaiscript.js';
390+
document.body.appendChild(engineScript);
334391
</script>
335-
<script src="/playground/chaiscript.js"></script>
336392

337393
</body>

test_playground.sh

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,15 @@ assert_file_contains "playground.html" "example-item"
6464
assert_file_contains "playground.html" "debounceTimer"
6565
assert_file_contains "playground.html" "addEventListener.*input"
6666

67-
# 9. Playground examples cover major ChaiScript features
67+
# 9. Playground engine is reset between runs (issue #14)
68+
assert_file_contains "playground.html" "resetEngine"
69+
assert_file_contains "playground.html" "onAbort"
70+
71+
# 10. Playground catches and displays exceptions with detail (issue #14)
72+
assert_file_contains "playground.html" "chai-output-error"
73+
assert_file_contains "playground.html" "engineAborted"
74+
75+
# 11. Playground examples cover major ChaiScript features
6876
assert_file_contains "playground.html" "Variables &amp; Types"
6977
assert_file_contains "playground.html" "Functions"
7078
assert_file_contains "playground.html" "Loops"

0 commit comments

Comments
 (0)