public void Visit(FunctionObject node)
        {
            if (node != null)
            {
                // it's a declaration; put the index to -1.
                node.Index = -1;

                // create a function scope, assign it to the function object,
                // and push it on the stack
                var parentScope = CurrentLexicalScope;
                if (node.FunctionType == FunctionType.Expression 
                    && !string.IsNullOrEmpty(node.Name))
                {
                    // function expressions have an intermediate scope between the parent and the
                    // function's scope that contains just the function name so the function can
                    // be self-referencing without the function expression polluting the parent scope.
                    // don't add the function name field yet, because it's not a decl per se.
                    parentScope = new FunctionScope(parentScope, true, m_settings, node)
                    {
                        IsInWithScope = m_withDepth > 0
                    };

                    // add this function object to the list of function objects the variable scope
                    // will need to ghost later
                    CurrentVariableScope.GhostedFunctions.Add(node);
                }

                node.FunctionScope = new FunctionScope(parentScope, node.FunctionType != FunctionType.Declaration, m_settings, node)
                {
                    IsInWithScope = m_withDepth > 0
                };
                m_lexicalStack.Push(node.FunctionScope);
                m_variableStack.Push(node.FunctionScope);

                var savedIndex = m_orderIndex;
                try
                {
                    // recurse into the function to handle it after saving the current index and resetting it
                    if (node.Body != null)
                    {
                        m_orderIndex = 0;
                        node.Body.Accept(this);
                    }
                }
                finally
                {
                    Debug.Assert(CurrentLexicalScope == node.FunctionScope);
                    m_lexicalStack.Pop();
                    m_variableStack.Pop();

                    m_orderIndex = savedIndex;
                }

                // nothing to add to the var-decl list.
                // but add the function name to the current lex-decl list
                // IF it is a declaration and it has a name (and it SHOULD unless there was an error)
                if (node.FunctionType == FunctionType.Declaration && 
                    !string.IsNullOrEmpty(node.Name))
                {
                    var lexicalScope = CurrentLexicalScope;
                    lexicalScope.LexicallyDeclaredNames.Add(node);

                    if (lexicalScope != CurrentVariableScope)
                    {
                        // the current lexical scope is the variable scope.
                        // this is ES6 syntax: a function declaration inside a block scope. Not allowed
                        // in ES5 code, so throw a warning and ghost this function in the outer variable scope 
                        // to make sure that we don't generate any naming collisions.
                        node.NameContext.HandleError(JSError.MisplacedFunctionDeclaration, false);
                        CurrentVariableScope.GhostedFunctions.Add(node);
                    }
                }
            }
        }
Exemplo n.º 2
0
        public void Visit(FunctionObject node)
        {
            if (node != null)
            {
                // it's a declaration; put the index to -1.
                node.Index = -1;

                // create a function scope, assign it to the function object,
                // and push it on the stack
                var parentScope = CurrentLexicalScope;
                if (node.FunctionType == FunctionType.Expression &&
                    !string.IsNullOrEmpty(node.Name))
                {
                    // function expressions have an intermediate scope between the parent and the
                    // function's scope that contains just the function name so the function can
                    // be self-referencing without the function expression polluting the parent scope.
                    // don't add the function name field yet, because it's not a decl per se.
                    parentScope = new FunctionScope(parentScope, true, m_settings, node)
                    {
                        IsInWithScope = m_withDepth > 0
                    };

                    // add this function object to the list of function objects the variable scope
                    // will need to ghost later
                    CurrentVariableScope.GhostedFunctions.Add(node);
                }

                node.FunctionScope = new FunctionScope(parentScope, node.FunctionType != FunctionType.Declaration, m_settings, node)
                {
                    IsInWithScope = m_withDepth > 0
                };
                m_lexicalStack.Push(node.FunctionScope);
                m_variableStack.Push(node.FunctionScope);

                var savedIndex = m_orderIndex;
                try
                {
                    // recurse into the function to handle it after saving the current index and resetting it
                    if (node.Body != null)
                    {
                        m_orderIndex = 0;
                        node.Body.Accept(this);
                    }
                }
                finally
                {
                    Debug.Assert(CurrentLexicalScope == node.FunctionScope);
                    m_lexicalStack.Pop();
                    m_variableStack.Pop();

                    m_orderIndex = savedIndex;
                }

                // nothing to add to the var-decl list.
                // but add the function name to the current lex-decl list
                // IF it is a declaration and it has a name (and it SHOULD unless there was an error)
                if (node.FunctionType == FunctionType.Declaration &&
                    !string.IsNullOrEmpty(node.Name))
                {
                    var lexicalScope = CurrentLexicalScope;
                    lexicalScope.LexicallyDeclaredNames.Add(node);

                    if (lexicalScope != CurrentVariableScope)
                    {
                        // the current lexical scope is the variable scope.
                        // this is ES6 syntax: a function declaration inside a block scope. Not allowed
                        // in ES5 code, so throw a warning and ghost this function in the outer variable scope
                        // to make sure that we don't generate any naming collisions.
                        node.NameContext.HandleError(JSError.MisplacedFunctionDeclaration, false);
                        CurrentVariableScope.GhostedFunctions.Add(node);
                    }
                }
            }
        }