skulpt with timeout
by sc549
HTML
<script src="https://cdn.jsdelivr.net/gh/skulpt/skulpt-dist/skulpt.js"></script>
<script src="https://cdn.jsdelivr.net/gh/skulpt/skulpt-dist/skulpt-stdlib.js"></script>
<textarea id="code" rows="24" cols="80">
from time import sleep
print('Ready')
sleep(.5)
print('Set')
sleep(.2)
i = 0
while True:
sleep(.2)
print(i, end=", ")
i += 1
</textarea><br>
<button id="run" onclick="runit()" type="button">Run</button>
<button onclick="stopit()" type="button">Stop</button>
<pre id="output"></pre>
CSS
#code {
max-height: 50vh;
max-width: 60vw;
}
JavaScript
var StopExecution = false;
function outf(text) {
const output = document.getElementById("output");
text = text.replace(/</g, "<");
output.innerHTML += text;
}
function stopit() {
StopExecution = true;
}
Sk.configure({
output: outf,
// here are some other related configurations for limits
// yieldLimit: 100,
// execLimit: 5000,
// timeoutMsg: "your program timed out"
killableWhile: true,
// killableFor: true,
inputTakesPrompt: true,
// you can customise the input function - this can return a promise - the default is just to use window.prompt
inputfun(args) {
return new Promise((resolve, reject) => {
setTimeout(function() {
resolve(window.prompt(args))
}, 250)
})
},
__future__: Sk.python3
});
function runit() {
StopExecution = false;
const prog = document.getElementById("code").value;
const output = document.getElementById("output");
const run = document.getElementById("run");
output.innerHTML = "";
run.disabled = true;
Sk.misceval.asyncToPromise(() =>
Sk.importMainWithBody("<stdin>", false, prog, true), {
// handle a suspension of the executing code
// "*" says handle all types of suspensions
"*": () => {
if (StopExecution) throw "Execution interrupted"
}
},
).catch(err => {
outf("\n" + err.toString());
}).finally(() => {
run.disabled = false;
})
}