Example #1
0
 public JintForInForOfStatement(ForOfStatement statement) : base(statement)
 {
     _leftNode        = statement.Left;
     _rightExpression = statement.Right;
     _forBody         = statement.Body;
     _iterationKind   = IterationKind.Iterate;
 }
Example #2
0
 public JintForInForOfStatement(
     Engine engine,
     ForOfStatement statement) : base(engine, statement)
 {
     _initialized     = false;
     _leftNode        = statement.Left;
     _rightExpression = statement.Right;
     _forBody         = statement.Body;
     _iterationKind   = IterationKind.Iterate;
 }
Example #3
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);
            }
        }
        protected Completion ForInOfBodyEvaluation(IForInOfInitializer lhs, Statement stmt, IteratorRecord iteratorRecord, IterationKind iterationKind, LHSKind lhsKind, List <string> labelSet, IteratorKind?iteratorKindNullable = null)
        {
            var    iteratorKind = iteratorKindNullable.GetValueOrDefault(IteratorKind.Sync);
            var    oldEnv       = Interpreter.Instance().RunningExecutionContext().LexicalEnvironment;
            IValue V            = UndefinedValue.Instance;
            // TODO assuming destructuring is false
            bool destructuring = false;

            while (true)
            {
                var nextResultComp = iteratorRecord.NextMethod.Call(iteratorRecord.Iterator);
                if (nextResultComp.IsAbrupt())
                {
                    return(nextResultComp);
                }
                var nextResult = nextResultComp.value;
                if (iteratorKind == IteratorKind.Async)
                {
                    throw new NotImplementedException("async");
                }
                if (!(nextResult is Object nextResultObject))
                {
                    return(Completion.ThrowTypeError("iterator next did not return an object."));
                }
                var doneComp = IteratorRecord.IteratorComplete(nextResultObject);
                if (doneComp.IsAbrupt())
                {
                    return(doneComp);
                }
                var done = (doneComp.value as BooleanValue) !.boolean;
                if (done)
                {
                    return(Completion.NormalCompletion(V));
                }
                var nextValueComp = IteratorRecord.IteratorValue(nextResultObject);
                if (nextValueComp.IsAbrupt())
                {
                    return(nextValueComp);
                }
                var        nextValue = nextValueComp.value !;
                Completion lhsRef    = Completion.NormalCompletion();
                if (lhsKind == LHSKind.Assignment || lhsKind == LHSKind.VarBinding)
                {
                    if (!destructuring)
                    {
                        lhsRef = lhs.Evaluate(Interpreter.Instance());
                    }
                }
                else
                {
                    if (lhsKind != LHSKind.LexicalBinding)
                    {
                        throw new InvalidOperationException("Spec 13.7.5.13 step 6hi");
                    }
                    if (!(lhs is ForDeclaration forDeclaration))
                    {
                        throw new InvalidOperationException("Spec 13.7.5.13 step 6hii");
                    }
                    var iterationEnv = oldEnv.NewDeclarativeEnvironment();
                    forDeclaration.BindingInstantiation(iterationEnv);
                    Interpreter.Instance().RunningExecutionContext().LexicalEnvironment = iterationEnv;
                    if (!destructuring)
                    {
                        lhsRef = Interpreter.Instance().ResolveBinding(forDeclaration.name, IsStrictMode);
                    }
                }
                Completion status;
                if (!destructuring)
                {
                    if (lhsRef.IsAbrupt())
                    {
                        status = lhsRef;
                    }
                    else if (lhsKind == LHSKind.LexicalBinding)
                    {
                        status = (lhsRef.value as ReferenceValue) !.InitializeReferencedBinding(nextValue);
                    }
                    else
                    {
                        status = (lhsRef.value as ReferenceValue) !.PutValue(nextValue);
                    }
                }
                else
                {
                    throw new NotImplementedException("destructuring");
                }
                if (status.IsAbrupt())
                {
                    Interpreter.Instance().RunningExecutionContext().LexicalEnvironment = oldEnv;
                    if (iteratorKind == IteratorKind.Async)
                    {
                        throw new NotImplementedException("async");
                    }
                    if (iterationKind == IterationKind.Enumerate)
                    {
                        return(status);
                    }
                    else
                    {
                        return(iteratorRecord.IteratorClose(status));
                    }
                }
                var result = stmt.Evaluate(Interpreter.Instance());
                Interpreter.Instance().RunningExecutionContext().LexicalEnvironment = oldEnv;
                if (!LoopContinues(result, labelSet))
                {
                    if (iterationKind == IterationKind.Enumerate)
                    {
                        return(result.UpdateEmpty(V));
                    }
                    else
                    {
                        status = result.UpdateEmpty(V);
                        if (iteratorKind == IteratorKind.Async)
                        {
                            throw new NotImplementedException("async");
                        }
                        return(iteratorRecord.IteratorClose(status));
                    }
                }
                if (result.value != null)
                {
                    V = result.value;
                }
            }
        }
        protected static CompletionOr <IteratorRecord?> ForInOfHeadEvaluation(IEnumerable <string> TDZNames, AbstractExpression expr, IterationKind iterationKind)
        {
            var oldEnv = Interpreter.Instance().RunningExecutionContext().LexicalEnvironment;

            if (TDZNames.Any())
            {
                if (TDZNames.Distinct().Count() < TDZNames.Count())
                {
                    throw new InvalidOperationException("Spec 13.7.5.12 step 2a");
                }
                var TDZ       = oldEnv.NewDeclarativeEnvironment();
                var TDZEnvRec = TDZ.EnvironmentRecord;
                foreach (var name in TDZNames)
                {
                    TDZEnvRec.CreateMutableBinding(name, false);
                }
                Interpreter.Instance().RunningExecutionContext().LexicalEnvironment = TDZ;
            }
            var exprRef = expr.Evaluate(Interpreter.Instance());

            Interpreter.Instance().RunningExecutionContext().LexicalEnvironment = oldEnv;
            var exprValue = exprRef.GetValue();

            if (exprValue.IsAbrupt())
            {
                return(exprValue.WithEmpty <IteratorRecord?>());
            }
            if (iterationKind == IterationKind.Enumerate)
            {
                if (exprValue.value == UndefinedValue.Instance || exprValue.value == NullValue.Instance)
                {
                    return(new Completion(CompletionType.Break, null, null).WithEmpty <IteratorRecord?>());
                }
                var obj = exprValue.value !.ToObject().value as Object;
                return(obj !.EnumerateObjectProperties());
            }
            else
            {
                return((exprValue.value !.ToObject().value as Object) !.GetIterator());
            }
        }
Example #6
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);
            }
        }