public Completion ExecuteSwitchBlock(List <SwitchCase> switchBlock, JsValue input) { JsValue v = Undefined.Instance; SwitchCase defaultCase = null; bool hit = false; for (int i = 0, len = switchBlock.Count; i < len; i++) { var clause = switchBlock[i]; if (clause.Test == null) { defaultCase = clause; } else { var clauseSelector = _engine.GetValue(_engine.EvaluateExpression(clause.Test)); if (ExpressionInterpreter.StrictlyEqual(clauseSelector, input)) { hit = true; } } if (hit && clause.Consequent != null) { var r = ExecuteStatementList(clause.Consequent); if (r.Type != Completion.Normal) { return(r); } v = r.Value != null ? r.Value : Undefined.Instance; } } // do we need to execute the default case ? if (hit == false && defaultCase != null) { var r = ExecuteStatementList(defaultCase.Consequent); if (r.Type != Completion.Normal) { return(r); } v = r.Value != null ? r.Value : Undefined.Instance; } return(new Completion(Completion.Normal, v, null)); }
public Engine(Action<Options> options) { _executionContexts = new Stack<ExecutionContext>(); Global = GlobalObject.CreateGlobalObject(this); Object = ObjectConstructor.CreateObjectConstructor(this); Function = FunctionConstructor.CreateFunctionConstructor(this); Array = ArrayConstructor.CreateArrayConstructor(this); String = StringConstructor.CreateStringConstructor(this); RegExp = RegExpConstructor.CreateRegExpConstructor(this); Number = NumberConstructor.CreateNumberConstructor(this); Boolean = BooleanConstructor.CreateBooleanConstructor(this); Date = DateConstructor.CreateDateConstructor(this); Math = MathInstance.CreateMathObject(this); Json = JsonInstance.CreateJsonObject(this); Error = ErrorConstructor.CreateErrorConstructor(this, "Error"); EvalError = ErrorConstructor.CreateErrorConstructor(this, "EvalError"); RangeError = ErrorConstructor.CreateErrorConstructor(this, "RangeError"); ReferenceError = ErrorConstructor.CreateErrorConstructor(this, "ReferenceError"); SyntaxError = ErrorConstructor.CreateErrorConstructor(this, "SyntaxError"); TypeError = ErrorConstructor.CreateErrorConstructor(this, "TypeError"); UriError = ErrorConstructor.CreateErrorConstructor(this, "URIError"); // Because the properties might need some of the built-in object // their configuration is delayed to a later step Global.Configure(); Object.Configure(); Object.PrototypeObject.Configure(); Function.Configure(); Function.PrototypeObject.Configure(); Array.Configure(); Array.PrototypeObject.Configure(); String.Configure(); String.PrototypeObject.Configure(); RegExp.Configure(); RegExp.PrototypeObject.Configure(); Number.Configure(); Number.PrototypeObject.Configure(); Boolean.Configure(); Boolean.PrototypeObject.Configure(); Date.Configure(); Date.PrototypeObject.Configure(); Math.Configure(); Json.Configure(); Error.Configure(); Error.PrototypeObject.Configure(); // create the global environment http://www.ecma-international.org/ecma-262/5.1/#sec-10.2.3 GlobalEnvironment = LexicalEnvironment.NewObjectEnvironment(this, Global, null, false); // create the global execution context http://www.ecma-international.org/ecma-262/5.1/#sec-10.4.1.1 EnterExecutionContext(GlobalEnvironment, GlobalEnvironment, Global); Options = new Options(); if (options != null) { options(Options); } Eval = new EvalFunctionInstance(this, new string[0], LexicalEnvironment.NewDeclarativeEnvironment(this, ExecutionContext.LexicalEnvironment), StrictModeScope.IsStrictModeCode); Global.FastAddProperty("eval", Eval, true, false, true); _statements = new StatementInterpreter(this); _expressions = new ExpressionInterpreter(this); if (Options.IsClrAllowed()) { Global.FastAddProperty("System", new NamespaceReference(this, "System"), false, false, false); Global.FastAddProperty("importNamespace", new ClrFunctionInstance(this, (thisObj, arguments) => { return new NamespaceReference(this, TypeConverter.ToString(arguments.At(0))); }), false, false, false); } ClrTypeConverter = new DefaultTypeConverter(this); BreakPoints = new List<BreakPoint>(); DebugHandler = new DebugHandler(this); }
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; } }