public void Visit(ForIn node)
        {
            if (node != null)
            {
                node.Index = NextOrderIndex;

                if (node.Collection != null)
                {
                    node.Collection.Accept(this);
                }

                if (node.Variable != null)
                {
                    // if the variable portion of the for-in statement is a lexical
                    // declaration, then we will create the block node for its body right now
                    // and add the declaration. This will prevent the body from deleting
                    // an empty lexical scope.
                    var lexDeclaration = node.Variable as LexicalDeclaration;
                    if (lexDeclaration != null)
                    {
                        // create the scope on the block
                        node.BlockScope = new BlockScope(CurrentLexicalScope, node.Context, m_settings)
                        {
                            IsInWithScope = m_withDepth > 0
                        };
                        m_lexicalStack.Push(node.BlockScope);
                    }
                }

                try
                {
                    if (node.Variable != null)
                    {
                        node.Variable.Accept(this);
                    }

                    if (node.Body != null)
                    {
                        node.Body.Accept(this);
                    }
                }
                finally
                {
                    if (node.BlockScope != null)
                    {
                        Debug.Assert(CurrentLexicalScope == node.BlockScope);
                        m_lexicalStack.Pop();
                    }
                }
            }
        }
Exemple #2
0
 public void Visit(ForIn node)
 {
     // invalid! ignore
     IsValid = false;
 }
 public void Visit(ForIn node)
 {
     // invalid! ignore
     IsValid = false;
 }
 public void Visit(ForIn node)
 {
     Debug.Fail("shouldn't get here");
 }
Exemple #5
0
 public void Visit(ForIn node)
 {
     // not applicable; terminate
 }
        public void Visit(ForIn node)
        {
            if (node != null)
            {
                node.Index = NextOrderIndex;

                if (node.Collection != null)
                {
                    node.Collection.Accept(this);
                }

                if (node.Variable != null)
                {
                    // if the variable portion of the for-in statement is a lexical
                    // declaration, then we will create the block node for its body right now
                    // and add the declaration. This will prevent the body from deleting
                    // an empty lexical scope.
                    var lexDeclaration = node.Variable as LexicalDeclaration;
                    if (lexDeclaration != null)
                    {
                        // create the scope on the block
                        node.BlockScope = new BlockScope(CurrentLexicalScope, node.Context, m_settings)
                        {
                            IsInWithScope = m_withDepth > 0
                        };
                        m_lexicalStack.Push(node.BlockScope);
                    }
                }

                try
                {
                    if (node.Variable != null)
                    {
                        node.Variable.Accept(this);
                    }

                    if (node.Body != null)
                    {
                        node.Body.Accept(this);
                    }
                }
                finally
                {
                    if (node.BlockScope != null)
                    {
                        Debug.Assert(CurrentLexicalScope == node.BlockScope);
                        m_lexicalStack.Pop();
                    }
                }
            }
        }
 public void Visit(ForIn node)
 {
     Debug.Fail("shouldn't get here");
 }
        private AstNode ParseForStatement()
        {
            m_blockType.Add(BlockType.Loop);
            AstNode forNode = null;
            try
            {
                Context forCtx = m_currentToken.Clone();
                GetNextToken();
                if (JSToken.LeftParenthesis != m_currentToken.Token)
                {
                    ReportError(JSError.NoLeftParenthesis);
                }

                GetNextToken();
                bool isForIn = false, recoveryInForIn = false;
                AstNode lhs = null, initializer = null, condOrColl = null, increment = null;
                Context operatorContext = null;
                Context separator1Context = null;
                Context separator2Context = null;

                try
                {
                    if (JSToken.Var == m_currentToken.Token
                        || JSToken.Let == m_currentToken.Token
                        || JSToken.Const == m_currentToken.Token)
                    {
                        isForIn = true;
                        Declaration declaration;
                        if (m_currentToken.Token == JSToken.Var)
                        {
                            declaration = new Var(m_currentToken.Clone(), this);
                        }
                        else
                        {
                            declaration = new LexicalDeclaration(m_currentToken.Clone(), this)
                                {
                                    StatementToken = m_currentToken.Token
                                };
                        }
 
                        declaration.Append(ParseIdentifierInitializer(JSToken.In));

                        // a list of variable initializers is allowed only in a for(;;)
                        while (JSToken.Comma == m_currentToken.Token)
                        {
                            isForIn = false;
                            declaration.Append(ParseIdentifierInitializer(JSToken.In));
                            //initializer = new Comma(initializer.context.CombineWith(var.context), initializer, var);
                        }

                        initializer = declaration;

                        // if it could still be a for..in, now it's time to get the 'in'
                        // TODO: for ES6 might be 'of'
                        if (isForIn)
                        {
                            if (JSToken.In == m_currentToken.Token
                                || (m_currentToken.Token == JSToken.Identifier && string.CompareOrdinal(m_currentToken.Code, "of") == 0))
                            {
                                operatorContext = m_currentToken.Clone();
                                GetNextToken();
                                condOrColl = ParseExpression();
                            }
                            else
                            {
                                isForIn = false;
                            }
                        }
                    }
                    else
                    {
                        if (JSToken.Semicolon != m_currentToken.Token)
                        {
                            bool isLHS;
                            initializer = ParseUnaryExpression(out isLHS, false);
                            if (isLHS && (JSToken.In == m_currentToken.Token
                                || (m_currentToken.Token == JSToken.Identifier && string.CompareOrdinal(m_currentToken.Code, "of") == 0)))
                            {
                                isForIn = true;
                                operatorContext = m_currentToken.Clone();

                                lhs = initializer;
                                initializer = null;
                                GetNextToken();
                                m_noSkipTokenSet.Add(NoSkipTokenSet.s_BlockConditionNoSkipTokenSet);
                                try
                                {
                                    condOrColl = ParseExpression();
                                }
                                catch (RecoveryTokenException exc)
                                {
                                    if (IndexOfToken(NoSkipTokenSet.s_BlockConditionNoSkipTokenSet, exc) == -1)
                                    {
                                        exc._partiallyComputedNode = null;
                                        throw;
                                    }
                                    else
                                    {
                                        if (exc._partiallyComputedNode == null)
                                            condOrColl = new ConstantWrapper(true, PrimitiveType.Boolean, CurrentPositionContext(), this); // what could we put here?
                                        else
                                            condOrColl = exc._partiallyComputedNode;
                                    }
                                    if (exc._token == JSToken.RightParenthesis)
                                    {
                                        GetNextToken();
                                        recoveryInForIn = true;
                                    }
                                }
                                finally
                                {
                                    m_noSkipTokenSet.Remove(NoSkipTokenSet.s_BlockConditionNoSkipTokenSet);
                                }
                            }
                            else
                            {
                                initializer = ParseExpression(initializer, false, isLHS, JSToken.In);
                            }
                        }
                    }
                }
                catch (RecoveryTokenException exc)
                {
                    // error is too early abort for
                    exc._partiallyComputedNode = null;
                    throw;
                }

                // at this point we know whether or not is a for..in
                if (isForIn)
                {
                    if (!recoveryInForIn)
                    {
                        if (JSToken.RightParenthesis != m_currentToken.Token)
                            ReportError(JSError.NoRightParenthesis);
                        forCtx.UpdateWith(m_currentToken);
                        GetNextToken();
                    }

                    AstNode body = null;
                    // if the statements aren't withing curly-braces, throw a possible error
                    if (JSToken.LeftCurly != m_currentToken.Token)
                    {
                        ReportError(JSError.StatementBlockExpected, CurrentPositionContext(), true);
                    }
                    try
                    {
                        // parse a Statement, not a SourceElement
                        body = ParseStatement(false);
                    }
                    catch (RecoveryTokenException exc)
                    {
                        if (exc._partiallyComputedNode == null)
                            body = new Block(CurrentPositionContext(), this);
                        else
                            body = exc._partiallyComputedNode;
                        exc._partiallyComputedNode = new ForIn(forCtx, this)
                            {
                                Variable = (lhs != null ? lhs : initializer),
                                OperatorContext = operatorContext,
                                Collection = condOrColl,
                                Body = AstNode.ForceToBlock(body),
                            };
                        throw;
                    }

                    // for (a in b)
                    //      lhs = a, initializer = null
                    // for (var a in b)
                    //      lhs = null, initializer = var a
                    forNode = new ForIn(forCtx, this)
                        {
                            Variable = (lhs != null ? lhs : initializer),
                            OperatorContext = operatorContext,
                            Collection = condOrColl,
                            Body = AstNode.ForceToBlock(body),
                        };
                }
                else
                {
                    m_noSkipTokenSet.Add(NoSkipTokenSet.s_BlockConditionNoSkipTokenSet);
                    try
                    {
                        if (JSToken.Semicolon == m_currentToken.Token)
                        {
                            separator1Context = m_currentToken.Clone();
                        }
                        else
                        {
                            ReportError(JSError.NoSemicolon);
                            if (JSToken.Colon == m_currentToken.Token)
                            {
                                m_noSkipTokenSet.Add(NoSkipTokenSet.s_VariableDeclNoSkipTokenSet);
                                try
                                {
                                    SkipTokensAndThrow();
                                }
                                catch (RecoveryTokenException)
                                {
                                    if (JSToken.Semicolon == m_currentToken.Token)
                                    {
                                        m_useCurrentForNext = false;
                                    }
                                    else
                                    {
                                        throw;
                                    }
                                }
                                finally
                                {
                                    m_noSkipTokenSet.Remove(NoSkipTokenSet.s_VariableDeclNoSkipTokenSet);
                                }
                            }
                        }

                        GetNextToken();
                        if (JSToken.Semicolon != m_currentToken.Token)
                        {
                            condOrColl = ParseExpression();
                            if (JSToken.Semicolon != m_currentToken.Token)
                            {
                                ReportError(JSError.NoSemicolon);
                            }
                        }

                        separator2Context = m_currentToken.Clone();
                        GetNextToken();

                        if (JSToken.RightParenthesis != m_currentToken.Token)
                        {
                            increment = ParseExpression();
                        }

                        if (JSToken.RightParenthesis != m_currentToken.Token)
                        {
                            ReportError(JSError.NoRightParenthesis);
                        }

                        forCtx.UpdateWith(m_currentToken);
                        GetNextToken();
                    }
                    catch (RecoveryTokenException exc)
                    {
                        if (IndexOfToken(NoSkipTokenSet.s_BlockConditionNoSkipTokenSet, exc) == -1)
                        {
                            exc._partiallyComputedNode = null;
                            throw;
                        }
                        else
                        {
                            // discard any partial info, just genrate empty condition and increment and keep going
                            exc._partiallyComputedNode = null;
                            if (condOrColl == null)
                                condOrColl = new ConstantWrapper(true, PrimitiveType.Boolean, CurrentPositionContext(), this);
                        }
                        if (exc._token == JSToken.RightParenthesis)
                        {
                            GetNextToken();
                        }
                    }
                    finally
                    {
                        m_noSkipTokenSet.Remove(NoSkipTokenSet.s_BlockConditionNoSkipTokenSet);
                    }

                    // if this is an assignment, throw a warning in case the developer
                    // meant to use == instead of =
                    // but no warning if the condition is wrapped in parens.
                    var binOp = condOrColl as BinaryOperator;
                    if (binOp != null && binOp.OperatorToken == JSToken.Assign)
                    {
                        condOrColl.Context.HandleError(JSError.SuspectAssignment);
                    }

                    AstNode body = null;
                    // if the statements aren't withing curly-braces, throw a possible error
                    if (JSToken.LeftCurly != m_currentToken.Token)
                    {
                        ReportError(JSError.StatementBlockExpected, CurrentPositionContext(), true);
                    }
                    try
                    {
                        // parse a Statement, not a SourceElement
                        body = ParseStatement(false);
                    }
                    catch (RecoveryTokenException exc)
                    {
                        if (exc._partiallyComputedNode == null)
                            body = new Block(CurrentPositionContext(), this);
                        else
                            body = exc._partiallyComputedNode;
                        exc._partiallyComputedNode = new ForNode(forCtx, this)
                            {
                                Initializer = initializer,
                                Separator1Context = separator1Context,
                                Condition = condOrColl,
                                Separator2Context = separator2Context,
                                Incrementer = increment,
                                Body = AstNode.ForceToBlock(body)
                            };
                        throw;
                    }
                    forNode = new ForNode(forCtx, this)
                        {
                            Initializer = initializer,
                            Separator1Context = separator1Context,
                            Condition = condOrColl,
                            Separator2Context = separator2Context,
                            Incrementer = increment,
                            Body = AstNode.ForceToBlock(body)
                        };
                }
            }
            finally
            {
                m_blockType.RemoveAt(m_blockType.Count - 1);
            }

            return forNode;
        }
 public void Visit(ForIn node)
 {
     // not applicable; terminate
 }
        public override void Visit(ForIn node)
        {
            if (node != null)
            {
                // if this forIn-statement has it's own lexical scope, then it's an error
                // if the any of the field names declared in this scope is also defined inside the body.
                if (node.BlockScope != null)
                {
                    foreach (var field in node.BlockScope.LexicallyDeclaredNames)
                    {
                        // if the block has a lexical scope, check it for conflicts
                        if (node.Body != null && node.Body.BlockScope != null)
                        {
                            var lexDecl = node.Body.BlockScope.LexicallyDeclaredName(field.Name);
                            if (lexDecl != null)
                            {
                                // report the error (lex/const/funcdecl collision)
                                lexDecl.NameContext.HandleError(JSError.DuplicateLexicalDeclaration, true);

                                // link the inner one to the outer one so any renaming stays in sync.
                                if (lexDecl.VariableField != null)
                                {
                                    lexDecl.VariableField.OuterField = field.VariableField;
                                    if (field.VariableField != null && !lexDecl.VariableField.CanCrunch)
                                    {
                                        field.VariableField.CanCrunch = false;
                                    }
                                }
                            }
                        }

                        // check to make sure there are no var-decl'd names with the same name. Those will
                        // get carried up to this scope so we don't need to check the block scope (if any)
                        var varDecl = node.BlockScope.VarDeclaredName(field.Name);
                        if (varDecl != null)
                        {
                            // report the error (lex/const collides with var) or warning (funcdecl collides with var)
                            varDecl.NameContext.HandleError(JSError.DuplicateLexicalDeclaration, field is LexicalDeclaration);

                            // and mark them both as no-rename
                            varDecl.VariableField.IfNotNull(v => v.CanCrunch = false);
                            field.VariableField.IfNotNull(v => v.CanCrunch = false);
                        }
                    }
                }

                // if we are stripping debugger statements and the body is
                // just a debugger statement, replace it with a null
                // (but only if the body doesn't have its own lexical scope)
                if (m_parser.Settings.StripDebugStatements
                     && m_parser.Settings.IsModificationAllowed(TreeModifications.StripDebugStatements)
                     && node.Body != null
                     && node.Body.BlockScope == null
                     && node.Body.IsDebuggerStatement)
                {
                    node.Body = null;
                }

                // recurse
                base.Visit(node);

                // if the body is now empty (and doesn't have its own lexical scope), make it null
                if (node.Body != null && node.Body.Count == 0 && node.Body.BlockScope == null)
                {
                    node.Body = null;
                }
            }
        }