using Esprima.Ast;
using Jint.Runtime.Environments;
namespace Jint.Runtime.Interpreter.Statements
{
///
/// http://www.ecma-international.org/ecma-262/5.1/#sec-12.14
///
internal sealed class JintTryStatement : JintStatement
{
private readonly JintStatement _block;
private readonly JintStatement _catch;
private readonly Key _catchParamName;
private readonly JintStatement _finalizer;
public JintTryStatement(Engine engine, TryStatement statement) : base(engine, statement)
{
_block = Build(engine, statement.Block);
if (_statement.Handler != null)
{
_catch = Build(engine, _statement.Handler.Body);
_catchParamName = ((Identifier) _statement.Handler.Param).Name;
}
if (statement.Finalizer != null)
{
_finalizer = Build(engine, _statement.Finalizer);
}
}
protected override Completion ExecuteInternal()
{
var b = _block.Execute();
if (b.Type == CompletionType.Throw)
{
// execute catch
if (_catch != null)
{
var c = b.Value;
var oldEnv = _engine.ExecutionContext.LexicalEnvironment;
var catchEnv = LexicalEnvironment.NewDeclarativeEnvironment(_engine, oldEnv);
var catchEnvRecord = (DeclarativeEnvironmentRecord) catchEnv._record;
catchEnvRecord.CreateMutableBindingAndInitialize(_catchParamName, canBeDeleted: false, c);
_engine.UpdateLexicalEnvironment(catchEnv);
b = _catch.Execute();
_engine.UpdateLexicalEnvironment(oldEnv);
}
}
if (_finalizer != null)
{
var f = _finalizer.Execute();
if (f.Type == CompletionType.Normal)
{
return b;
}
return f;
}
return b;
}
}
}