Beispiel #1
0
        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));
        }
Beispiel #2
0
        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;
            }
        }