Exemple #1
0
        /// <summary>
        /// http://www.ecma-international.org/ecma-262/5.1/#sec-12.14
        /// </summary>
        /// <param name="tryStatement"></param>
        /// <returns></returns>
        public Completion ExecuteTryStatement(TryStatement tryStatement)
        {
            var b = ExecuteStatement(tryStatement.Block);

            if (b.Type == Completion.Throw)
            {
                // execute catch
                if (tryStatement.Handlers.Any())
                {
                    for (int i = 0, len = tryStatement.Handlers.Count; i < len; i++)
                    {
                        var catchClause = tryStatement.Handlers[i];
                        var c           = _engine.GetValue(b);
                        var oldEnv      = _engine.ExecutionContext.LexicalEnvironment;
                        var catchEnv    = LexicalEnvironment.NewDeclarativeEnvironment(_engine, oldEnv);
                        catchEnv.Record.CreateMutableBinding(catchClause.Param.Name);
                        catchEnv.Record.SetMutableBinding(catchClause.Param.Name, c, false);
                        _engine.ExecutionContext.LexicalEnvironment = catchEnv;
                        b = ExecuteStatement(catchClause.Body);
                        _engine.ExecutionContext.LexicalEnvironment = oldEnv;
                    }
                }
            }

            if (tryStatement.Finalizer != null)
            {
                var f = ExecuteStatement(tryStatement.Finalizer);
                if (f.Type == Completion.Normal)
                {
                    return(b);
                }

                return(f);
            }

            return(b);
        }
Exemple #2
0
        public JsValue EvaluateFunctionExpression(FunctionExpression functionExpression)
        {
            var funcEnv = LexicalEnvironment.NewDeclarativeEnvironment(_engine, _engine.ExecutionContext.LexicalEnvironment);
            var envRec  = (DeclarativeEnvironmentRecord)funcEnv.Record;

            if (functionExpression.Id != null && !String.IsNullOrEmpty(functionExpression.Id.Name))
            {
                envRec.CreateMutableBinding(functionExpression.Id.Name);
            }

            var closure = new ScriptFunctionInstance(
                _engine,
                functionExpression,
                funcEnv,
                functionExpression.Strict
                );

            if (functionExpression.Id != null && !String.IsNullOrEmpty(functionExpression.Id.Name))
            {
                envRec.InitializeImmutableBinding(functionExpression.Id.Name, closure);
            }

            return(closure);
        }
Exemple #3
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 = new LexicalEnvironment();
            GlobalEnvironment.Setup(new ObjectEnvironmentRecord(this, Global, false), null);

            // 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);
        }
Exemple #4
0
        public JsValue Call(JsValue thisObject, JsValue[] arguments, bool directCall)
        {
            if (arguments.At(0).Type != Types.String)
            {
                return(arguments.At(0));
            }

            var code = TypeConverter.ToString(arguments.At(0));

            try
            {
                var parser  = new JavaScriptParser(StrictModeScope.IsStrictModeCode);
                var program = parser.Parse(code);
                using (new StrictModeScope(program.Strict))
                {
                    using (new EvalCodeScope())
                    {
                        LexicalEnvironment strictVarEnv = null;

                        try
                        {
                            if (!directCall)
                            {
                                Engine.EnterExecutionContext(Engine.GlobalEnvironment, Engine.GlobalEnvironment, Engine.Global);
                            }

                            if (StrictModeScope.IsStrictModeCode)
                            {
                                strictVarEnv = LexicalEnvironment.NewDeclarativeEnvironment(Engine, Engine.ExecutionContext.LexicalEnvironment);
                                Engine.EnterExecutionContext(strictVarEnv, strictVarEnv, Engine.ExecutionContext.ThisBinding);
                            }

                            Engine.DeclarationBindingInstantiation(DeclarationBindingType.EvalCode, program.FunctionDeclarations, program.VariableDeclarations, this, arguments);

                            var result = _engine.ExecuteStatement(program);

                            if (result.Type == Completion.Throw)
                            {
                                throw result.Exception ?? new JavaScriptException(result.GetValueOrDefault())
                                      .SetCallstack(_engine, result.Location);
                            }
                            else
                            {
                                return(result.GetValueOrDefault());
                            }
                        }
                        finally
                        {
                            if (strictVarEnv != null)
                            {
                                Engine.LeaveExecutionContext();
                            }

                            if (!directCall)
                            {
                                Engine.LeaveExecutionContext();
                            }
                        }
                    }
                }
            }
            catch (ParserException)
            {
                throw new JavaScriptException(Engine.SyntaxError);
            }
        }
        public ObjectInstance Construct(JsValue[] arguments)
        {
            var    argCount = arguments.Length;
            string p        = "";
            string body     = "";

            if (argCount == 1)
            {
                body = TypeConverter.ToString(arguments[0]);
            }
            else if (argCount > 1)
            {
                var firstArg = arguments[0];
                p = TypeConverter.ToString(firstArg);
                for (var k = 1; k < argCount - 1; k++)
                {
                    var nextArg = arguments[k];
                    p += "," + TypeConverter.ToString(nextArg);
                }

                body = TypeConverter.ToString(arguments[argCount - 1]);
            }

            var parameters = this.ParseArgumentNames(p);
            var parser     = new JavaScriptParser();
            FunctionExpression function;

            try
            {
                var functionExpression = "function(" + p + ") { " + body + "}";
                function = parser.ParseFunctionExpression(functionExpression);
            }
            catch (ParserException)
            {
                throw new JavaScriptException(Engine.SyntaxError);
            }

            // todo: check if there is not a way to use the FunctionExpression directly instead of creating a FunctionDeclaration
            var functionObject = new ScriptFunctionInstance(
                Engine,
                new FunctionDeclaration
            {
                Type = SyntaxNodes.FunctionDeclaration,
                Body = new BlockStatement
                {
                    Type = SyntaxNodes.BlockStatement,
                    Body = new [] { function.Body }
                },
                Parameters = parameters.Select(x => new Identifier
                {
                    Type = SyntaxNodes.Identifier,
                    Name = x
                }).ToArray(),
                FunctionDeclarations = function.FunctionDeclarations,
                VariableDeclarations = function.VariableDeclarations
            },
                LexicalEnvironment.NewDeclarativeEnvironment(Engine, Engine.ExecutionContext.LexicalEnvironment),
                function.Strict
                )
            {
                Extensible = true
            };

            return(functionObject);
        }
Exemple #6
0
        /// <summary>
        /// https://tc39.es/ecma262/#sec-runtime-semantics-forin-div-ofbodyevaluation-lhs-stmt-iterator-lhskind-labelset
        /// </summary>
        private Completion BodyEvaluation(
            JintExpression lhs,
            JintStatement stmt,
            IIterator iteratorRecord,
            IterationKind iterationKind,
            LhsKind lhsKind,
            IteratorKind iteratorKind = IteratorKind.Sync)
        {
            var    oldEnv        = _engine.ExecutionContext.LexicalEnvironment;
            var    v             = Undefined.Instance;
            var    destructuring = _destructuring;
            string lhsName       = null;

            var completionType = CompletionType.Normal;
            var close          = false;

            try
            {
                while (true)
                {
                    LexicalEnvironment iterationEnv = null;
                    if (!iteratorRecord.TryIteratorStep(out var nextResult))
                    {
                        close = true;
                        return(new Completion(CompletionType.Normal, v, null, Location));
                    }

                    if (iteratorKind == IteratorKind.Async)
                    {
                        // nextResult = await nextResult;
                    }

                    var nextValue = nextResult.Get(CommonProperties.Value);
                    close = true;

                    Reference lhsRef = null;
                    if (lhsKind != LhsKind.LexicalBinding)
                    {
                        if (!destructuring)
                        {
                            lhsRef = (Reference)lhs.Evaluate();
                        }
                    }
                    else
                    {
                        iterationEnv = LexicalEnvironment.NewDeclarativeEnvironment(_engine, oldEnv);
                        if (_tdzNames != null)
                        {
                            BindingInstantiation(iterationEnv);
                        }
                        _engine.UpdateLexicalEnvironment(iterationEnv);

                        if (!destructuring)
                        {
                            if (lhsName == null)
                            {
                                lhsName = ((Identifier)((VariableDeclaration)_leftNode).Declarations[0].Id).Name;
                            }
                            lhsRef = _engine.ResolveBinding(lhsName);
                        }
                    }

                    if (!destructuring)
                    {
                        // If lhsRef is an abrupt completion, then
                        // Let status be lhsRef.

                        if (lhsKind == LhsKind.LexicalBinding)
                        {
                            lhsRef.InitializeReferencedBinding(nextValue);
                        }
                        else
                        {
                            _engine.PutValue(lhsRef, nextValue);
                        }
                    }
                    else
                    {
                        BindingPatternAssignmentExpression.ProcessPatterns(
                            _engine,
                            _assignmentPattern,
                            nextValue,
                            iterationEnv,
                            checkObjectPatternPropertyReference: _lhsKind != LhsKind.VarBinding);

                        if (lhsKind == LhsKind.Assignment)
                        {
                            // DestructuringAssignmentEvaluation of assignmentPattern using nextValue as the argument.
                        }
                        else if (lhsKind == LhsKind.VarBinding)
                        {
                            // BindingInitialization for lhs passing nextValue and undefined as the arguments.
                        }
                        else
                        {
                            // BindingInitialization for lhs passing nextValue and iterationEnv as arguments
                        }
                    }

                    var result = stmt.Execute();
                    _engine.UpdateLexicalEnvironment(oldEnv);

                    if (!ReferenceEquals(result.Value, null))
                    {
                        v = result.Value;
                    }

                    if (result.Type == CompletionType.Break && (result.Identifier == null || result.Identifier == _statement?.LabelSet?.Name))
                    {
                        return(new Completion(CompletionType.Normal, v, null, Location));
                    }

                    if (result.Type != CompletionType.Continue || (result.Identifier != null && result.Identifier != _statement?.LabelSet?.Name))
                    {
                        if (result.Type != CompletionType.Normal)
                        {
                            return(result);
                        }
                    }
                }
            }
            catch
            {
                completionType = CompletionType.Throw;
                throw;
            }
            finally
            {
                if (close)
                {
                    iteratorRecord.Close(completionType);
                }
                _engine.UpdateLexicalEnvironment(oldEnv);
            }
        }
Exemple #7
0
        /// <summary>
        /// https://tc39.es/ecma262/#sec-performeval
        /// </summary>
        public JsValue Call(JsValue thisObject, JsValue[] arguments, bool direct)
        {
            if (!(arguments.At(0) is JsString x))
            {
                return(arguments.At(0));
            }

            var    parser = new JavaScriptParser(x.ToString(), ParserOptions);
            Script script;

            try
            {
                script = parser.ParseScript(StrictModeScope.IsStrictModeCode);
            }
            catch (ParserException e)
            {
                return(e.Description == Messages.InvalidLHSInAssignment
                    ? ExceptionHelper.ThrowReferenceError <JsValue>(_engine)
                    : ExceptionHelper.ThrowSyntaxError <JsValue>(_engine));
            }

            var body = script.Body;

            if (body.Count == 0)
            {
                return(Undefined);
            }

            var strictEval = script.Strict || _engine._isStrict;
            var ctx        = _engine.ExecutionContext;

            using (new StrictModeScope(strictEval))
            {
                LexicalEnvironment lexEnv;
                LexicalEnvironment varEnv;
                if (direct)
                {
                    lexEnv = LexicalEnvironment.NewDeclarativeEnvironment(_engine, ctx.LexicalEnvironment);
                    varEnv = ctx.VariableEnvironment;
                }
                else
                {
                    lexEnv = LexicalEnvironment.NewDeclarativeEnvironment(_engine, Engine.GlobalEnvironment);
                    varEnv = Engine.GlobalEnvironment;
                }

                if (strictEval)
                {
                    varEnv = lexEnv;
                }

                // If ctx is not already suspended, suspend ctx.

                Engine.EnterExecutionContext(lexEnv, varEnv);

                try
                {
                    Engine.EvalDeclarationInstantiation(script, varEnv, lexEnv, strictEval);

                    var statement = new JintScript(_engine, script);
                    var result    = statement.Execute();
                    var value     = result.GetValueOrDefault();

                    if (result.Type == CompletionType.Throw)
                    {
                        var ex = new JavaScriptException(value).SetCallstack(_engine, result.Location);
                        throw ex;
                    }
                    else
                    {
                        return(value);
                    }
                }
                finally
                {
                    Engine.LeaveExecutionContext();
                }
            }
        }
Exemple #8
0
        public Engine(Action <Options> options)
        {
            _executionContexts = new ExecutionContextStack();

            Global = GlobalObject.CreateGlobalObject(this);

            Object   = ObjectConstructor.CreateObjectConstructor(this);
            Function = FunctionConstructor.CreateFunctionConstructor(this);

            Symbol   = SymbolConstructor.CreateSymbolConstructor(this);
            Array    = ArrayConstructor.CreateArrayConstructor(this);
            Map      = MapConstructor.CreateMapConstructor(this);
            Set      = SetConstructor.CreateSetConstructor(this);
            Iterator = IteratorConstructor.CreateIteratorConstructor(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");

            GlobalSymbolRegistry = new GlobalSymbolRegistry();

            // 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();

            Symbol.Configure();
            Symbol.PrototypeObject.Configure();

            Function.Configure();
            Function.PrototypeObject.Configure();

            Array.Configure();
            Array.PrototypeObject.Configure();

            Map.Configure();
            Map.PrototypeObject.Configure();

            Set.Configure();
            Set.PrototypeObject.Configure();

            Iterator.Configure();
            Iterator.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();

            options?.Invoke(Options);

            // gather some options as fields for faster checks
            _isDebugMode = Options.IsDebugMode;

            if (_isDebugMode)
            {
                MyAPIGateway.Utilities.ShowMessage("SpaceJS", "Debug mode enabled.");
            }

            _isStrict                 = Options.IsStrict;
            _maxStatements            = Options._MaxStatements;
            _referenceResolver        = Options.ReferenceResolver;
            _memoryLimit              = Options._MemoryLimit;
            _runBeforeStatementChecks = (_maxStatements > 0 && _maxStatements < int.MaxValue) ||
                                        Options._TimeoutInterval.Ticks > 0 ||
                                        _memoryLimit > 0 ||
                                        _isDebugMode;

            _referencePool         = new ReferencePool();
            _argumentsInstancePool = new ArgumentsInstancePool(this);
            _jsValueArrayPool      = new JsValueArrayPool();

            Eval = new EvalFunctionInstance(this, System.ArrayExt.Empty <string>(), 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,
             *                  "importNamespace",
             *                  (thisObj, arguments) => new NamespaceReference(this, TypeConverter.ToString(arguments.At(0)))), false, false, false);
             *          }
             */
            //            ClrTypeConverter = new DefaultTypeConverter(this);
        }
        public Completion Execute(JsValue input)
        {
            if (!_initialized)
            {
                Initialize();
                _initialized = true;
            }

            JsValue        v           = Undefined.Instance;
            Location       l           = _engine._lastSyntaxNode.Location;
            JintSwitchCase defaultCase = null;
            bool           hit         = false;

            for (var i = 0; i < (uint)_jintSwitchBlock.Length; i++)
            {
                var clause = _jintSwitchBlock[i];

                LexicalEnvironment oldEnv = null;
                if (clause.LexicalDeclarations != null)
                {
                    oldEnv = _engine.ExecutionContext.LexicalEnvironment;
                    var blockEnv = LexicalEnvironment.NewDeclarativeEnvironment(_engine, oldEnv);
                    JintStatementList.BlockDeclarationInstantiation(blockEnv, clause.LexicalDeclarations);
                    _engine.UpdateLexicalEnvironment(blockEnv);
                }

                if (clause.Test == null)
                {
                    defaultCase = clause;
                }
                else
                {
                    var clauseSelector = clause.Test.GetValue();
                    if (JintBinaryExpression.StrictlyEqual(clauseSelector, input))
                    {
                        hit = true;
                    }
                }

                if (hit && clause.Consequent != null)
                {
                    var r = clause.Consequent.Execute();

                    if (oldEnv != null)
                    {
                        _engine.UpdateLexicalEnvironment(oldEnv);
                    }

                    if (r.Type != CompletionType.Normal)
                    {
                        return(r);
                    }

                    l = r.Location;
                    v = r.Value ?? Undefined.Instance;
                }
            }

            // do we need to execute the default case ?
            if (hit == false && defaultCase != null)
            {
                LexicalEnvironment oldEnv = null;
                if (defaultCase.LexicalDeclarations != null)
                {
                    oldEnv = _engine.ExecutionContext.LexicalEnvironment;
                    var blockEnv = LexicalEnvironment.NewDeclarativeEnvironment(_engine, oldEnv);
                    JintStatementList.BlockDeclarationInstantiation(blockEnv, defaultCase.LexicalDeclarations);
                    _engine.UpdateLexicalEnvironment(blockEnv);
                }

                var r = defaultCase.Consequent.Execute();

                if (oldEnv != null)
                {
                    _engine.UpdateLexicalEnvironment(oldEnv);
                }
                if (r.Type != CompletionType.Normal)
                {
                    return(r);
                }

                l = r.Location;
                v = r.Value ?? Undefined.Instance;
            }

            return(new Completion(CompletionType.Normal, v, null, l));
        }
        /// <summary>
        /// http://www.ecma-international.org/ecma-262/5.1/#sec-12.14
        /// </summary>
        /// <param name="tryStatement"></param>
        /// <returns></returns>
        public void ExecuteTryStatement(RuntimeState state)
        {
            TryStatement             tryStatement = (TryStatement)state.arg;
            ExecuteTryStatementLocal local;

            if (state.local == null)
            {
                state.local = local = new ExecuteTryStatementLocal();
                local.stage = 0;
            }
            else
            {
                local = (ExecuteTryStatementLocal)state.local;
            }

            if (local.stage == 0)
            {
                if (state.calleeReturned)
                {
                    state.calleeReturned = false;
                    local.stage          = 1;
                    local.b = (Completion)state.calleeReturnValue;
                    return;
                }

                Call(_engine.ExecuteStatement, tryStatement.Block);
                return;
            }

            if (local.stage == 1)
            {
                if (state.calleeReturned)
                {
                    state.calleeReturned = false;
                    local.stage          = 2;
                    local.b = (Completion)state.calleeReturnValue;
                    return;
                }

                var catchClause = tryStatement.Handler;
                if (catchClause != null)
                {
                    var c = local.b.Value;
                    local.oldEnv = _engine.ExecutionContext.LexicalEnvironment;
                    var catchEnv = LexicalEnvironment.NewDeclarativeEnvironment(_engine, local.oldEnv);
                    catchEnv._record.CreateMutableBinding(((Identifier)catchClause.Param).Name, c);

                    _engine.UpdateLexicalEnvironment(catchEnv);
                    Call(_engine.ExecuteStatement, catchClause.Body);
                    return;
                }
                local.stage = 2;
            }

            if (local.stage == 2)
            {
                if (state.calleeReturned)
                {
                    var f = (Completion)state.calleeReturnValue;
                    if (f.Type == CompletionType.Normal)
                    {
                        Return(local.b);
                        return;
                    }

                    Return(f);
                    return;
                }

                if (tryStatement.Finalizer != null)
                {
                    Call(_engine.ExecuteStatement, tryStatement.Finalizer);
                    return;
                }

                Return(local.b);
                return;
            }
        }
Exemple #11
0
        /// <summary>
        /// http://www.ecma-international.org/ecma-262/5.1/#sec-13.2.1
        /// </summary>
        /// <param name="thisArg"></param>
        /// <param name="arguments"></param>
        /// <returns></returns>
        public override JsValue Call(JsValue thisArg, JsValue[] arguments)
        {
            var scope = Engine.PoolStrictMode.Get();

            scope.Setup(Strict, true);
            {
                // setup new execution context http://www.ecma-international.org/ecma-262/5.1/#sec-10.4.3
                JsValue thisBinding;
                if (StrictModeScope.IsStrictModeCode)
                {
                    thisBinding = thisArg;
                }
                else if (thisArg == Undefined.Instance || thisArg == Null.Instance)
                {
                    thisBinding = Engine.Global;
                }
                else if (!thisArg.IsObject())
                {
                    thisBinding = TypeConverter.ToObject(Engine, thisArg);
                }
                else
                {
                    thisBinding = thisArg;
                }

                var localEnv = LexicalEnvironment.NewDeclarativeEnvironment(Engine, Scope);

                Engine.EnterExecutionContext(localEnv, localEnv, thisBinding);

                try
                {
                    Engine.DeclarationBindingInstantiation(
                        DeclarationBindingType.FunctionCode,
                        _functionDeclaration.FunctionDeclarations,
                        _functionDeclaration.VariableDeclarations,
                        this,
                        arguments);

                    var result = Engine.ExecuteStatement(_functionDeclaration.Body);

                    if (result.Type == Completion.Throw)
                    {
                        JavaScriptException ex = new JavaScriptException(result.GetValueOrDefault())
                                                 .SetCallstack(Engine, result.Location);
                        throw ex;
                    }

                    if (result.Type == Completion.Return)
                    {
                        scope.Teardown();
                        Engine.PoolStrictMode.Put(scope);

                        return(result.GetValueOrDefault());
                    }
                }
                finally
                {
                    Engine.LeaveExecutionContext();
                }

                scope.Teardown();
                Engine.PoolStrictMode.Put(scope);

                return(Undefined.Instance);
            }
        }
        public void CallState(RuntimeState state)
        {
            CallArgs args    = (CallArgs)state.arg;
            JsValue  thisArg = args.thisObject;

            JsValue[] arguments = args.arguments;

            if (state.calleeReturned)
            {
                try
                {
                    var result = (Completion)state.calleeReturnValue;
                    var value  = result.GetValueOrDefault();
                    var argumentInstanceRented = (bool)state.local;
                    // we can safely release arguments if they don't escape the scope
                    if (argumentInstanceRented &&
                        _engine.ExecutionContext.LexicalEnvironment?._record is DeclarativeEnvironmentRecord &&
                        !(result.Value is ArgumentsInstance))
                    {
                        var der = _engine.ExecutionContext.LexicalEnvironment._record as DeclarativeEnvironmentRecord;
                        der.ReleaseArguments();
                    }

                    if (result.Type == CompletionType.Throw)
                    {
                        var ex = new JavaScriptException(value).SetCallstack(_engine, result.Location);
                        throw ex;
                    }

                    if (result.Type == CompletionType.Return)
                    {
                        _engine.Return((JsValue)(value));
                        return;
                    }
                }
                finally
                {
                    _engine.LeaveExecutionContext();
                }
                _engine.Return((JsValue)(Undefined));
                return;
            }
            else
            {
                // setup new execution context http://www.ecma-international.org/ecma-262/5.1/#sec-10.4.3
                JsValue thisBinding;
                if (StrictModeScope.IsStrictModeCode)
                {
                    thisBinding = thisArg;
                }
                else if (thisArg._type == Types.Undefined || thisArg._type == Types.Null)
                {
                    thisBinding = _engine.Global;
                }
                else if (thisArg._type != Types.Object)
                {
                    thisBinding = TypeConverter.ToObject(_engine, thisArg);
                }
                else
                {
                    thisBinding = thisArg;
                }

                var localEnv = LexicalEnvironment.NewDeclarativeEnvironment(_engine, _scope);

                _engine.EnterExecutionContext(localEnv, localEnv, thisBinding);

                state.local = _engine.DeclarationBindingInstantiation(
                    DeclarationBindingType.FunctionCode,
                    _functionDeclaration.HoistingScope.FunctionDeclarations,
                    _functionDeclaration.HoistingScope.VariableDeclarations,
                    this,
                    arguments);

                _engine.Call(_engine.ExecuteStatement, _functionDeclaration.Body);
                return;
            }
        }