TryStatement :
try Block catch
try Block Finally
try Block Catch Finally
Catch :
catch ( Identifier ) Block
Finally :
finally Block
The try-catch Statements allow you to trap any errors or throw Statements. Whenever code within a try block throws an error, the code in catch will be executed, rather than exiting the program right there and then.
Whenever a catch clause catches an exception, its Identifier (the argument to catch) is said to be bound to that exception.
Note that catch creates a new scope, like function does. Probably because the catch Identifier needed to be bound.
function evaluate(try Block Catch) {
var B = evaluate(Block);
if (B.type != 'throw') return B;
return evaluate(Catch, B); // B is param
}
function evaluate(try Block Finally) {
var B = evaluate(Block);
var F = evaluate(Finally);
// if the finally block threw no error, return whatever the result of the try was
if (F.type == 'normal') return B;
// otherwise return the result of evaluating F
return F;
}
function evaluate(try Block Catch Finally) {
var B = evaluate(Block);
if (B.type == 'throw') var C = evaluate(Catch, B);
else var C = B;
var F = evaluate(Finally);
// if the finally block threw no error, return whatever the result of the try was
if (F.type == 'normal') return C;
// otherwise return the result of evaluating F
return F;
}
The next function is called with parameter C (result of calling the try Block).
function evaluate(catch ( Identifier ) Block, C) {
var rec = global.arrRunningExecutionContexts[global.arrRunningExecutionContexts.length-1];
var oldEnv = rec.LexicalEnvironment;
var catchEnv = NewDeclarativeEnvironment(oldEnv);
catchEnv.CreateMutableBinding(Identifier);
catchEnv.SetMutableBinding(Identifier, C, false); // "strict argument is immaterial"
rec.LexicalEnvironment = catchEnv;
var B = evaluate(Block);
rec.LexicalEnvironment = oldEnv;
return B;
}
function evaluate(finally Block) {
return evaluate(Block);
}