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; } }
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; } }