Example #1
0
 public void Visit(ParameterDeclaration node)
 {
     // shoudn't get here
     DebugEx.Fail("shouldn't get here");
 }
 public void Visit(ParameterDeclaration node)
 {
     // we're good
 }
 public void Visit(ParameterDeclaration node)
 {
     // invalid! ignore
     IsValid = false;
 }
Example #4
0
 public void Visit(ParameterDeclaration node)
 {
     // add the names from the binding, but ignore any initializers
     node.IfNotNull(n => n.Binding.IfNotNull(b => b.Accept(this)));
 }
Example #5
0
        public FunctionObject(Lookup identifier, JSParser parser, FunctionType functionType, ParameterDeclaration[] parameterDeclarations, Block bodyBlock, Context functionContext, FunctionScope functionScope)
            : base(functionContext, parser)
        {
            FunctionType = functionType;
            m_functionScope = functionScope;
            if (functionScope != null)
            {
                functionScope.FunctionObject = this;
            }

            m_name = string.Empty;
            Identifier = identifier;
            if (Identifier != null) { Identifier.Parent = this; }

            m_parameterDeclarations = parameterDeclarations;

            Body = bodyBlock;
            if (bodyBlock != null) { bodyBlock.Parent = this; }

            // now we need to make sure that the enclosing scope has the name of this function defined
            // so that any references get properly resolved once we start analyzing the parent scope
            // see if this is not anonymnous AND not a getter/setter
            bool isGetterSetter = (FunctionType == FunctionType.Getter || FunctionType == FunctionType.Setter);
            if (Identifier != null && !isGetterSetter)
            {
                // yes -- add the function name to the current enclosing
                // check whether the function name is in use already
                // shouldn't be any duplicate names
                ActivationObject enclosingScope = m_functionScope.Parent;
                // functions aren't owned by block scopes
                while (enclosingScope is BlockScope)
                {
                    enclosingScope = enclosingScope.Parent;
                }

                // if the enclosing scope already contains this name, then we know we have a dup
                string functionName = Identifier.Name;
                m_variableField = enclosingScope[functionName];
                if (m_variableField != null)
                {
                    // it's pointing to a function
                    m_variableField.IsFunction = true;

                    if (FunctionType == FunctionType.Expression)
                    {
                        // if the containing scope is itself a named function expression, then just
                        // continue on as if everything is fine. It will chain and be good.
                        if (!(m_variableField is JSNamedFunctionExpressionField))
                        {
                            if (m_variableField.NamedFunctionExpression != null)
                            {
                                // we have a second named function expression in the same scope
                                // with the same name. Not an error unless someone actually references
                                // it.

                                // we are now ambiguous.
                                m_variableField.IsAmbiguous = true;

                                // BUT because this field now points to multiple function object, we
                                // need to break the connection. We'll leave the inner NFEs pointing
                                // to this field as the outer field so the names all align, however.
                                DetachFromOuterField(true);

                                // create a new NFE pointing to the existing field as the outer so
                                // the names stay in sync, and with a value of our function object.
                                JSNamedFunctionExpressionField namedExpressionField =
                                    new JSNamedFunctionExpressionField(m_variableField);
                                namedExpressionField.FieldValue = this;
                                m_functionScope.AddField(namedExpressionField);

                                // hook our function object up to the named field
                                m_variableField = namedExpressionField;
                                Identifier.VariableField = namedExpressionField;

                                // we're done; quit.
                                return;
                            }
                            else if (m_variableField.IsAmbiguous)
                            {
                                // we're pointing to a field that is already marked as ambiguous.
                                // just create our own NFE pointing to this one, and hook us up.
                                JSNamedFunctionExpressionField namedExpressionField =
                                    new JSNamedFunctionExpressionField(m_variableField);
                                namedExpressionField.FieldValue = this;
                                m_functionScope.AddField(namedExpressionField);

                                // hook our function object up to the named field
                                m_variableField = namedExpressionField;
                                Identifier.VariableField = namedExpressionField;

                                // we're done; quit.
                                return;
                            }
                            else
                            {
                                // we are a named function expression in a scope that has already
                                // defined a local variable of the same name. Not good. Throw the
                                // error but keep them attached because the names have to be synced
                                // to keep the same meaning in all browsers.
                                Identifier.Context.HandleError(JSError.AmbiguousNamedFunctionExpression, false);

                                // if we are preserving function names, then we need to mark this field
                                // as not crunchable
                                if (Parser.Settings.PreserveFunctionNames)
                                {
                                    m_variableField.CanCrunch = false;
                                }
                            }
                        }
                        /*else
                        {
                            // it's okay; just chain the NFEs as normal and everything will work out
                            // and the names will be properly synced.
                        }*/
                    }
                    else
                    {
                        // function declaration -- duplicate name
                        Identifier.Context.HandleError(JSError.DuplicateName, false);
                    }
                }
                else
                {
                    // doesn't exist -- create it now
                    m_variableField = enclosingScope.DeclareField(functionName, this, 0);

                    // and it's a pointing to a function object
                    m_variableField.IsFunction = true;
                }

                // set the identifier variable field now. We *know* what the field is now, and during
                // Analyze mode we aren't going to recurse into the identifier because that would add
                // a reference to it.
                Identifier.VariableField = m_variableField;

                // if we're here, we have a name. if this is a function expression, then we have
                // a named function expression and we need to do a little more work to prepare for
                // the ambiguities of named function expressions in various browsers.
                if (FunctionType == FunctionType.Expression)
                {
                    // now add a field within the function scope that indicates that it's okay to reference
                    // this named function expression from WITHIN the function itself.
                    // the inner field points to the outer field since we're going to want to catch ambiguous
                    // references in the future
                    JSNamedFunctionExpressionField namedExpressionField = new JSNamedFunctionExpressionField(m_variableField);
                    m_functionScope.AddField(namedExpressionField);
                    m_variableField.NamedFunctionExpression = namedExpressionField;
                }
                else
                {
                    // function declarations are declared by definition
                    m_variableField.IsDeclared = true;
                }
            }
        }