protected override Completion ExecuteInternal()
        {
            var b = _block.Execute();

            if (b.Type == CompletionType.Throw)
            {
                // execute catch
                if (_catch != null)
                {
                    var c              = b.Value;
                    var oldEnv         = _engine.ExecutionContext.LexicalEnvironment;
                    var catchEnv       = LexicalEnvironment.NewDeclarativeEnvironment(_engine, oldEnv);
                    var catchEnvRecord = (DeclarativeEnvironmentRecord)catchEnv._record;
                    catchEnvRecord.CreateMutableBindingAndInitialize(_catchParamName, canBeDeleted: false, c);

                    _engine.UpdateLexicalEnvironment(catchEnv);
                    b = _catch.Execute();
                    _engine.UpdateLexicalEnvironment(oldEnv);
                }
            }

            if (_finalizer != null)
            {
                var f = _finalizer.Execute();
                if (f.Type == CompletionType.Normal)
                {
                    return(b);
                }

                return(f);
            }

            return(b);
        }
Beispiel #2
0
        protected override Completion ExecuteInternal(EvaluationContext context)
        {
            var jsValue = _object.GetValue(context).Value;
            var engine  = context.Engine;
            var obj     = TypeConverter.ToObject(engine.Realm, jsValue);
            var oldEnv  = engine.ExecutionContext.LexicalEnvironment;
            var newEnv  = JintEnvironment.NewObjectEnvironment(engine, obj, oldEnv, provideThis: true, withEnvironment: true);

            engine.UpdateLexicalEnvironment(newEnv);

            Completion c;

            try
            {
                c = _body.Execute(context);
            }
            catch (JavaScriptException e)
            {
                c = new Completion(CompletionType.Throw, e.Error, _statement.Location);
            }
            finally
            {
                engine.UpdateLexicalEnvironment(oldEnv);
            }

            return(c);
        }
Beispiel #3
0
        protected override Completion ExecuteInternal()
        {
            JsValue v = Undefined.Instance;
            bool    iterating;

            do
            {
                var completion = _body.Execute();
                if (!ReferenceEquals(completion.Value, null))
                {
                    v = completion.Value;
                }

                if (completion.Type != CompletionType.Continue || completion.Identifier != _labelSetName)
                {
                    if (completion.Type == CompletionType.Break && (completion.Identifier == null || completion.Identifier == _labelSetName))
                    {
                        return(new Completion(CompletionType.Normal, v, null, Location));
                    }

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

                iterating = TypeConverter.ToBoolean(_test.GetValue());
            } while (iterating);

            return(new Completion(CompletionType.Normal, v, null, Location));
        }
Beispiel #4
0
        /// <summary>
        /// https://tc39.es/ecma262/#sec-forbodyevaluation
        /// </summary>
        private Completion ForBodyEvaluation(EvaluationContext context)
        {
            var v = Undefined.Instance;

            if (_shouldCreatePerIterationEnvironment)
            {
                CreatePerIterationEnvironment(context);
            }

            while (true)
            {
                if (_test != null)
                {
                    if (context.DebugMode)
                    {
                        context.Engine.DebugHandler.OnStep(_test._expression);
                    }

                    if (!TypeConverter.ToBoolean(_test.GetValue(context).Value))
                    {
                        return(NormalCompletion(v));
                    }
                }

                var result = _body.Execute(context);
                if (!ReferenceEquals(result.Value, null))
                {
                    v = result.Value;
                }

                if (result.Type == CompletionType.Break && (result.Target == null || result.Target == _statement?.LabelSet?.Name))
                {
                    return(NormalCompletion(result.Value));
                }

                if (result.Type != CompletionType.Continue || (result.Target != null && result.Target != _statement?.LabelSet?.Name))
                {
                    if (result.Type != CompletionType.Normal)
                    {
                        return(result);
                    }
                }

                if (_shouldCreatePerIterationEnvironment)
                {
                    CreatePerIterationEnvironment(context);
                }

                if (_increment != null)
                {
                    if (context.DebugMode)
                    {
                        context.Engine.DebugHandler.OnStep(_increment._expression);
                    }

                    _increment.GetValue(context);
                }
            }
        }
Beispiel #5
0
        protected override Completion ExecuteInternal()
        {
            // TODO: Esprima added Statement.Label, maybe not necessary as this line is finding the
            // containing label and could keep a table per program with all the labels
            // labeledStatement.Body.LabelSet = labeledStatement.Label;
            var result = _body.Execute();

            if (result.Type == CompletionType.Break && result.Identifier == _labelName)
            {
                var value = result.Value;
                return(new Completion(CompletionType.Normal, value, null, Location));
            }

            return(result);
        }
        /// <summary>
        /// https://tc39.es/ecma262/#sec-forbodyevaluation
        /// </summary>
        private Completion ForBodyEvaluation()
        {
            var v = Undefined.Instance;

            if (_shouldCreatePerIterationEnvironment)
            {
                CreatePerIterationEnvironment();
            }

            while (true)
            {
                if (_test != null)
                {
                    if (!TypeConverter.ToBoolean(_test.GetValue()))
                    {
                        return(new Completion(CompletionType.Normal, v, null, Location));
                    }
                }

                var result = _body.Execute();
                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, result.Value, null, Location));
                }

                if (result.Type != CompletionType.Continue || (result.Identifier != null && result.Identifier != _statement?.LabelSet?.Name))
                {
                    if (result.Type != CompletionType.Normal)
                    {
                        return(result);
                    }
                }

                if (_shouldCreatePerIterationEnvironment)
                {
                    CreatePerIterationEnvironment();
                }

                _increment?.GetValue();
            }
        }
Beispiel #7
0
        protected override Completion ExecuteInternal(EvaluationContext context)
        {
            Completion result;

            if (TypeConverter.ToBoolean(_test.GetValue(context).Value))
            {
                result = _statementConsequent.Execute(context);
            }
            else if (_alternate != null)
            {
                result = _alternate.Execute(context);
            }
            else
            {
                return(new Completion(CompletionType.Normal, null, Location));
            }

            return(result);
        }
Beispiel #8
0
        protected override Completion ExecuteInternal(EvaluationContext context)
        {
            var v = Undefined.Instance;

            while (true)
            {
                if (context.DebugMode)
                {
                    context.Engine.DebugHandler.OnStep(_test._expression);
                }

                var jsValue = _test.GetValue(context).Value;
                if (!TypeConverter.ToBoolean(jsValue))
                {
                    return(new Completion(CompletionType.Normal, v, null, Location));
                }

                var completion = _body.Execute(context);

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

                if (completion.Type != CompletionType.Continue || completion.Target != _labelSetName)
                {
                    if (completion.Type == CompletionType.Break && (completion.Target == null || completion.Target == _labelSetName))
                    {
                        return(new Completion(CompletionType.Normal, v, null, Location));
                    }

                    if (completion.Type != CompletionType.Normal)
                    {
                        return(completion);
                    }
                }
            }
        }
Beispiel #9
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);
            }
        }
Beispiel #10
0
        /// <summary>
        /// https://tc39.es/ecma262/#sec-runtime-semantics-forin-div-ofbodyevaluation-lhs-stmt-iterator-lhskind-labelset
        /// </summary>
        private Completion BodyEvaluation(
            EvaluationContext context,
            JintExpression lhs,
            JintStatement stmt,
            IteratorInstance iteratorRecord,
            IterationKind iterationKind,
            LhsKind lhsKind,
            IteratorKind iteratorKind = IteratorKind.Sync)
        {
            var    engine        = context.Engine;
            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)
                {
                    EnvironmentRecord 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;
                        ExceptionHelper.ThrowNotImplementedException("await");
                    }

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

                    var lhsRef = new ExpressionResult();
                    if (lhsKind != LhsKind.LexicalBinding)
                    {
                        if (!destructuring)
                        {
                            lhsRef = lhs.Evaluate(context);
                        }
                    }
                    else
                    {
                        iterationEnv = JintEnvironment.NewDeclarativeEnvironment(engine, oldEnv);
                        if (_tdzNames != null)
                        {
                            BindingInstantiation(iterationEnv);
                        }
                        engine.UpdateLexicalEnvironment(iterationEnv);

                        if (!destructuring)
                        {
                            var identifier = (Identifier)((VariableDeclaration)_leftNode).Declarations[0].Id;
                            lhsName ??= identifier.Name;
                            lhsRef = new ExpressionResult(ExpressionCompletionType.Normal, engine.ResolveBinding(lhsName), identifier.Location);
                        }
                    }

                    if (context.DebugMode)
                    {
                        context.Engine.DebugHandler.OnStep(_leftNode);
                    }

                    var status = new Completion();
                    if (!destructuring)
                    {
                        if (lhsRef.IsAbrupt())
                        {
                            close  = true;
                            status = new Completion(lhsRef);
                        }
                        else if (lhsKind == LhsKind.LexicalBinding)
                        {
                            ((Reference)lhsRef.Value).InitializeReferencedBinding(nextValue);
                        }
                        else
                        {
                            engine.PutValue((Reference)lhsRef.Value, nextValue);
                        }
                    }
                    else
                    {
                        status = BindingPatternAssignmentExpression.ProcessPatterns(
                            context,
                            _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
                        }
                    }

                    if (status.IsAbrupt())
                    {
                        engine.UpdateLexicalEnvironment(oldEnv);
                        if (_iterationKind == IterationKind.AsyncIterate)
                        {
                            iteratorRecord.Close(status.Type);
                            return(status);
                        }

                        if (iterationKind == IterationKind.Enumerate)
                        {
                            return(status);
                        }

                        iteratorRecord.Close(status.Type);
                        return(status);
                    }

                    var result = stmt.Execute(context);
                    engine.UpdateLexicalEnvironment(oldEnv);

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

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

                    if (result.Type != CompletionType.Continue || (result.Target != null && result.Target != _statement?.LabelSet?.Name))
                    {
                        completionType = result.Type;
                        if (result.IsAbrupt())
                        {
                            close = true;
                            return(result);
                        }
                    }
                }
            }
            catch
            {
                completionType = CompletionType.Throw;
                throw;
            }
            finally
            {
                if (close)
                {
                    try
                    {
                        iteratorRecord.Close(completionType);
                    }
                    catch
                    {
                        // if we already have and exception, use it
                        if (completionType != CompletionType.Throw)
                        {
                            throw;
                        }
                    }
                }
                engine.UpdateLexicalEnvironment(oldEnv);
            }
        }
Beispiel #11
0
        protected override Completion ExecuteInternal(EvaluationContext context)
        {
            var engine = context.Engine;
            int callStackSizeBeforeExecution = engine.CallStack.Count;

            var b = _block.Execute(context);

            if (b.Type == CompletionType.Throw)
            {
                // initialize lazily
                if (_statement.Handler is not null && _catch is null)
                {
                    _catch = Build(_statement.Handler.Body);
                }

                // execute catch
                if (_statement.Handler is not null)
                {
                    // Quick-patch for call stack not being unwinded when an exception is caught.
                    // Ideally, this should instead be solved by always popping the stack when returning
                    // from a call, regardless of whether it throws (i.e. CallStack.Pop() in finally clause
                    // in Engine.Call/Engine.Construct - however, that method currently breaks stack traces
                    // in error messages.
                    while (callStackSizeBeforeExecution < engine.CallStack.Count)
                    {
                        engine.CallStack.Pop();
                    }

                    // https://tc39.es/ecma262/#sec-runtime-semantics-catchclauseevaluation

                    var thrownValue = b.Value;
                    var oldEnv      = engine.ExecutionContext.LexicalEnvironment;
                    var catchEnv    = JintEnvironment.NewDeclarativeEnvironment(engine, oldEnv, catchEnvironment: true);

                    var boundNames = new List <string>();
                    _statement.Handler.Param.GetBoundNames(boundNames);

                    foreach (var argName in boundNames)
                    {
                        catchEnv.CreateMutableBinding(argName, false);
                    }

                    engine.UpdateLexicalEnvironment(catchEnv);

                    var catchParam = _statement.Handler?.Param;
                    catchParam.BindingInitialization(context, thrownValue, catchEnv);

                    b = _catch.Execute(context);

                    engine.UpdateLexicalEnvironment(oldEnv);
                }
            }

            if (_finalizer != null)
            {
                var f = _finalizer.Execute(context);
                if (f.Type == CompletionType.Normal)
                {
                    return(b);
                }

                return(f.UpdateEmpty(Undefined.Instance));
            }

            return(b.UpdateEmpty(Undefined.Instance));
        }