internal override void TranslateToIL(ILGenerator il, Type rtype){
//This assumes that rtype == Void.class.
bool savedInsideProtectedRegion = compilerGlobals.InsideProtectedRegion;
compilerGlobals.InsideProtectedRegion = true;
compilerGlobals.BreakLabelStack.Push(compilerGlobals.BreakLabelStack.Peek(0));
compilerGlobals.ContinueLabelStack.Push(compilerGlobals.ContinueLabelStack.Peek(0));
il.BeginExceptionBlock();
if (this.finally_block != null){
if (this.finallyHasControlFlowOutOfIt)
il.BeginExceptionBlock();
if (this.handler != null)
il.BeginExceptionBlock();
}
this.body.TranslateToIL(il, Typeob.Void);
if (this.tryEndContext != null)
this.tryEndContext.EmitLineInfo(il);
if (this.handler != null){
if (this.type == null){
il.BeginCatchBlock(typeof(Exception));
this.handler.context.EmitLineInfo(il);
this.EmitILToLoadEngine(il);
il.Emit(OpCodes.Call, CompilerGlobals.jScriptExceptionValueMethod);
}else{
Type filterType = this.type.ToType();
if (typeof(Exception).IsAssignableFrom(filterType)){
il.BeginCatchBlock(filterType);
this.handler.context.EmitLineInfo(il);
}
else{
il.BeginExceptFilterBlock();
this.handler.context.EmitLineInfo(il);
this.EmitILToLoadEngine(il);
il.Emit(OpCodes.Call, CompilerGlobals.jScriptExceptionValueMethod);
il.Emit(OpCodes.Isinst, filterType);
il.Emit(OpCodes.Ldnull);
il.Emit(OpCodes.Cgt_Un);
il.BeginCatchBlock(null);
this.EmitILToLoadEngine(il);
il.Emit(OpCodes.Call, CompilerGlobals.jScriptExceptionValueMethod);
Convert.Emit(this, il, Typeob.Object, filterType);
}
}
Object tok = this.field is JSVariableField ? ((JSVariableField)this.field).GetMetaData() : this.field;
if (tok is LocalBuilder)
il.Emit(OpCodes.Stloc, (LocalBuilder)tok);
else if (tok is FieldInfo)
il.Emit(OpCodes.Stsfld, (FieldInfo)tok);
else
Convert.EmitLdarg(il, (short)tok);
if (this.handler_scope != null){
if (!this.handler_scope.isKnownAtCompileTime){ //I.e. eval or nested func
this.EmitILToLoadEngine(il);
il.Emit(OpCodes.Ldstr, this.fieldName);
ConstantWrapper.TranslateToILInt(il, this.handler_scope.scopeId);
il.Emit(OpCodes.Call, typeof(Try).GetMethod("PushHandlerScope"));
Globals.ScopeStack.Push(this.handler_scope);
}
il.BeginScope(); // so that we can emit local scoped information for the handler variable
if (this.context.document.debugOn)
this.handler_scope.EmitLocalInfoForFields(il);
}
this.handler.TranslateToIL(il, Typeob.Void);
if (this.handler_scope != null){
il.EndScope();
if (!this.handler_scope.isKnownAtCompileTime){ //I.e. eval or nested func
this.EmitILToLoadEngine(il);
il.Emit(OpCodes.Call, CompilerGlobals.popScriptObjectMethod);
il.Emit(OpCodes.Pop);
Globals.ScopeStack.Pop();
}
}
il.EndExceptionBlock();
}
if (this.finally_block != null){
bool savedInsideFinally = compilerGlobals.InsideFinally;
int savedFinallyStackTop = compilerGlobals.FinallyStackTop;
compilerGlobals.InsideFinally = true;
compilerGlobals.FinallyStackTop = compilerGlobals.BreakLabelStack.Size();
il.BeginFinallyBlock();
this.finally_block.TranslateToIL(il, Typeob.Void);
il.EndExceptionBlock();
compilerGlobals.InsideFinally = savedInsideFinally;
compilerGlobals.FinallyStackTop = savedFinallyStackTop;
if (this.finallyHasControlFlowOutOfIt){
il.BeginCatchBlock(typeof(BreakOutOfFinally));
il.Emit(OpCodes.Ldfld, typeof(BreakOutOfFinally).GetField("target"));
// don't need to go to 0 in the loop because 0 is the outmost block (i.e. function body)
// and that would generate a JIT assert because the jump is sometimes outside the function
for (int i = compilerGlobals.BreakLabelStack.Size()-1, n = i; i > 0; i--){
il.Emit(OpCodes.Dup);
ConstantWrapper.TranslateToILInt(il, i);
Label lab = il.DefineLabel();
il.Emit(OpCodes.Blt_S, lab);
il.Emit(OpCodes.Pop);
if (savedInsideFinally && i < savedFinallyStackTop)
il.Emit(OpCodes.Rethrow);
else
il.Emit(OpCodes.Leave, (Label)compilerGlobals.BreakLabelStack.Peek(n-i));
il.MarkLabel(lab);
}
il.Emit(OpCodes.Pop);
il.BeginCatchBlock(typeof(ContinueOutOfFinally));
il.Emit(OpCodes.Ldfld, typeof(ContinueOutOfFinally).GetField("target"));
// don't need to go to 0 in the loop because 0 is the outmost block (i.e. function body)
for (int i = compilerGlobals.ContinueLabelStack.Size()-1, n = i; i > 0; i--){
il.Emit(OpCodes.Dup);
ConstantWrapper.TranslateToILInt(il, i);
Label lab = il.DefineLabel();
il.Emit(OpCodes.Blt_S, lab);
il.Emit(OpCodes.Pop);
if (savedInsideFinally && i < savedFinallyStackTop)
il.Emit(OpCodes.Rethrow);
else
il.Emit(OpCodes.Leave, (Label)compilerGlobals.ContinueLabelStack.Peek(n-i));
il.MarkLabel(lab);
}
il.Emit(OpCodes.Pop);
ScriptObject scope = Globals.ScopeStack.Peek();
while (scope != null && !(scope is FunctionScope))
scope = scope.GetParent();
if (scope != null && !savedInsideFinally){
il.BeginCatchBlock(typeof(ReturnOutOfFinally));
il.Emit(OpCodes.Pop);
il.Emit(OpCodes.Leave, ((FunctionScope)scope).owner.returnLabel);
}
il.EndExceptionBlock();
}
}
compilerGlobals.InsideProtectedRegion = savedInsideProtectedRegion;
compilerGlobals.BreakLabelStack.Pop();
compilerGlobals.ContinueLabelStack.Pop();
}