Ejemplo n.º 1
0
        public virtual void AddReference(ActivationObject scope)
        {
            // if we have an outer field, add the reference to it
            if (m_outerField != null)
            {
                m_outerField.AddReference(scope);
            }

            ++m_refCount;
            if (m_value is FunctionObject)
            {
                // add the reference to the scope
                ((FunctionObject)FieldValue).FunctionScope.AddReference(scope);
            }

            // no longer a placeholder if we are referenced
            if (m_isPlaceholder)
            {
                m_isPlaceholder = false;
            }
        }
Ejemplo n.º 2
0
        public VariableDeclaration(Context context, JSParser parser, string identifier, Context idContext, AstNode initializer, FieldAttributes fieldAttributes, bool ignoreDuplicates)
            : base(context, parser)
        {
            // identifier cannot be null
            m_identifier = identifier;

            // initializer may be null
            m_initializer = initializer;
            if (m_initializer != null)
            {
                m_initializer.Parent = this;
            }

            // we'll need to do special stuff if the initializer if a function expression,
            // so try the conversion now
            FunctionObject functionValue = m_initializer as FunctionObject;
            string         name          = m_identifier.ToString();

            ActivationObject currentScope  = ScopeStack.Peek();
            ActivationObject definingScope = currentScope;

            if (definingScope is BlockScope)
            {
                // block scope -- the variable is ACTUALLY defined in the containing function/global scope,
                // so we need to check THERE for duplicate defines.
                do
                {
                    definingScope = definingScope.Parent;
                } while (definingScope is BlockScope);
            }

            JSVariableField field = definingScope[name];

            if (field != null &&
                (functionValue == null || functionValue != field.FieldValue))
            {
                // this is a declaration that already has a field declared.
                // if the field is a named function expression, we want to fire an
                // ambiguous named function expression error -- and we know it's an NFE
                // if the FieldValue is a function object OR if the field
                // has already been marked ambiguous
                if (field.IsAmbiguous || field.FieldValue is FunctionObject)
                {
                    if (idContext != null)
                    {
                        idContext.HandleError(
                            JSError.AmbiguousNamedFunctionExpression,
                            true
                            );
                    }
                    else if (context != null)
                    {
                        // not identifier context???? Try the whole statment context.
                        // if neither context is set, then we don't get an error!
                        context.HandleError(
                            JSError.AmbiguousNamedFunctionExpression,
                            true
                            );
                    }

                    // if we are preserving function names, then we need to mark this field
                    // as not crunchable
                    if (Parser.Settings.PreserveFunctionNames)
                    {
                        field.CanCrunch = false;
                    }
                }
                else if (!ignoreDuplicates)
                {
                    if (idContext != null)
                    {
                        // otherwise just a normal duplicate error
                        idContext.HandleError(
                            JSError.DuplicateName,
                            field.IsLiteral
                            );
                    }
                    else if (context != null)
                    {
                        // otherwise just a normal duplicate error
                        context.HandleError(
                            JSError.DuplicateName,
                            field.IsLiteral
                            );
                    }
                }
            }

            bool isLiteral = ((fieldAttributes & FieldAttributes.Literal) != 0);

            // normally the value will be null.
            // but if there is no initializer, we'll use Missing so we can tell the difference.
            // and if this is a literal, we'll set it to the actual literal astnode
            object val = null;

            if (m_initializer == null)
            {
                val = Missing.Value;
            }
            else if (isLiteral || (functionValue != null))
            {
                val = m_initializer;
            }

            m_field = currentScope.DeclareField(
                m_identifier,
                val,
                fieldAttributes
                );
            m_field.OriginalContext = idContext;

            // we are now declared by a var statement
            m_field.IsDeclared = true;

            // if we are declaring a variable inside a with statement, then we will be declaring
            // a local variable in the enclosing scope if the with object doesn't have a property
            // of that name. But if it does, we won't actually be creating a variable field -- we'll
            // just use the property. So if we use an initializer in this declaration, then we will
            // actually be referencing the value.
            // SO, if this is a with-scope and this variable declaration has an initializer, we're going
            // to go ahead and bump up the reference.
            if (currentScope is WithScope && m_initializer != null)
            {
                m_field.AddReference(currentScope);
            }

            // special case the ambiguous function expression test. If we are var-ing a variable
            // with the same name as the function expression, then it's okay. We won't have an ambiguous
            // reference and it will be okay to use the name to reference the function expression
            if (functionValue != null && string.CompareOrdinal(m_identifier, functionValue.Name) == 0)
            {
                // null out the link to the named function expression
                // and make the function object point to the PROPER variable: the local within its own scope
                // and the inner is not pointing to the outer.
                functionValue.DetachFromOuterField(false);
                m_field.IsFunction = false;
            }
        }