/// <summary> /// http://www.ecma-international.org/ecma-262/5.1/#sec-12.11 /// </summary> /// <param name="switchStatement"></param> /// <returns></returns> public void ExecuteSwitchStatement(RuntimeState state) { SwitchStatement switchStatement = (SwitchStatement)state.arg; if (state.stage == 0) { if (state.calleeReturned) { state.calleeReturned = false; state.stage = 1; var jsValue = _engine.GetValue(state.calleeReturnValue, true); ExecuteSwitchBlockArgs args = new ExecuteSwitchBlockArgs(); args.switchBlock = switchStatement.Cases; args.input = jsValue; Call(ExecuteSwitchBlock, args); return; } else { Call(_engine.EvaluateExpression, switchStatement.Discriminant); return; } } // Stage 1 if (state.calleeReturned) { Completion r = (Completion)state.calleeReturnValue; if (r.Type == CompletionType.Break && r.Identifier == switchStatement.LabelSet?.Name) { Return(new Completion(CompletionType.Normal, r.Value, null)); return; } Return(r); return; } }
public void ExecuteSwitchBlock(RuntimeState state) { ExecuteSwitchBlockArgs args = (ExecuteSwitchBlockArgs)state.arg; List <SwitchCase> switchBlock = args.switchBlock; JsValue input = args.input; ExecuteSwitchBlockLocal local; if (state.local == null) { state.local = local = new ExecuteSwitchBlockLocal(); local.v = Undefined.Instance; local.defaultCase = null; local.hit = false; local.switchBlockCount = switchBlock.Count; local.i = 0; local.stage = 0; } else { local = (ExecuteSwitchBlockLocal)state.local; } if (local.stage == 0) // for loop { if (local.i < local.switchBlockCount) { local.stage = 1; } else { local.stage = 2; } } if (local.stage == 1) // inside for loop { if (state.calleeReturned && state.stage != 10) { Completion r = (Completion)state.calleeReturnValue; if (r.Type != CompletionType.Normal) { Return(r); return; } local.v = r.Value ?? Undefined.Instance; } var clause = switchBlock[local.i]; if (clause.Test == null) { local.defaultCase = clause; } else { if (state.calleeReturned) { state.calleeReturned = false; state.stage = 0; var clauseSelector = _engine.GetValue(state.calleeReturnValue, true); if (ExpressionInterpreter.StrictlyEqual(clauseSelector, input)) { local.hit = true; } } else { state.stage = 10; Call(_engine.EvaluateExpression, clause.Test); return; } } if (local.hit && clause.Consequent != null) { Call(ExecuteStatementList, clause.Consequent); return; } local.i++; local.stage = 0; return; } if (local.stage == 2) { if (state.calleeReturned) { Completion r = (Completion)state.calleeReturnValue; if (r.Type != CompletionType.Normal) { Return(r); return; } local.v = r.Value ?? Undefined.Instance; } // do we need to execute the default case ? if (local.hit == false && local.defaultCase != null) { Call(ExecuteStatementList, local.defaultCase.Consequent); return; } Return(new Completion(CompletionType.Normal, local.v, null)); return; } }