diff --git a/demos/async.html b/demos/async.html index d166a080..cf1e28a0 100644 --- a/demos/async.html +++ b/demos/async.html @@ -19,8 +19,16 @@ var req = new XMLHttpRequest(); req.open('GET', href, true); req.onreadystatechange = function() { - if (req.readyState == 4 && req.status == 200) { - callback(req.responseText); + if (req.readyState == 4) { + if(req.status == 200) { + callback(req.responseText); + } else { + var error = interpreter.createObject(interpreter.ERROR); + interpreter.setProperty(error, 'message', + req.status + req.statusText, + Interpreter.NONENUMERABLE_DESCRIPTOR); + callback(undefined, error); + } } }; req.send(null); @@ -102,11 +110,20 @@

JS-Interpreter Async Demo

will both do nothing, returning true to indicate that the program still has code to execute.

+

The callback takes one or two arguments. If called with one, the + supplied value is used as the return value of the asynchronous + call. If called with two, the first is ignored and the second is + used as the value of an exception thrown by the call.

+

Click Parse, then either click Step repeatedly, or click Run once. Open your browser's console for errors.


diff --git a/interpreter.js b/interpreter.js index 917f10e1..3115f4da 100644 --- a/interpreter.js +++ b/interpreter.js @@ -3226,8 +3226,13 @@ Interpreter.prototype['stepCallExpression'] = function(stack, state, node) { state.value = func.nativeFunc.apply(state.funcThis_, state.arguments_); } else if (func.asyncFunc) { var thisInterpreter = this; - var callback = function(value) { - state.value = value; + var callback = function(value, exception) { + if (arguments.length <= 1) { + state.value = value; + } else { + thisInterpreter.unwind(Interpreter.Completion.THROW, + exception, undefined); + } thisInterpreter.paused_ = false; }; // Force the argument lengths to match, then append the callback.