Example #1
0
 internal JSWithField(JSVariableField outerField)
     : base(outerField)
 {
     // with-fields cannot be crunced because they might
     // need to reference a property on the with object
     CanCrunch = false;
 }
        private void DefineParameters()
        {
            var functionObject = (FunctionObject)Owner;

            if (functionObject.ParameterDeclarations != null)
            {
                // for each parameter...
                foreach (ParameterDeclaration parameter in functionObject.ParameterDeclarations)
                {
                    foreach (var nameDeclaration in BindingsVisitor.Bindings(parameter.Binding))
                    {
                        // see if it's already defined
                        var argumentField = this[nameDeclaration.Name];
                        if (argumentField == null)
                        {
                            // not already defined -- create a field now
                            argumentField = new JSVariableField(FieldType.Argument, nameDeclaration.Name, 0, null)
                            {
                                Position        = parameter.Position,
                                OriginalContext = parameter.Context,
                                CanCrunch       = !nameDeclaration.RenameNotAllowed
                            };

                            this.AddField(argumentField);
                        }

                        // make the parameter reference the field and the field reference
                        // the parameter as its declaration
                        nameDeclaration.VariableField = argumentField;
                        argumentField.Declarations.Add(nameDeclaration);
                    }
                }
            }
        }
Example #3
0
 public override JSVariableField this[string name]
 {
     get
     {
         // check the name table
         JSVariableField variableField = base[name];
         if (variableField == null)
         {
             // not found so far, check the window object
             variableField = m_windowObject.GetField(name);
         }
         if (variableField == null)
         {
             // not found so far, check the global object
             variableField = m_globalObject.GetField(name);
         }
         if (variableField == null)
         {
             // see if this value is provided in our "assumed" global list specified on the command line
             if (m_assumedGlobals != null && m_assumedGlobals.Count > 0)
             {
                 foreach (string globalName in m_assumedGlobals)
                 {
                     if (string.Compare(name, globalName.Trim(), StringComparison.Ordinal) == 0)
                     {
                         variableField = CreateField(name, null, 0);
                         break;
                     }
                 }
             }
         }
         return(variableField);
     }
 }
Example #4
0
 internal JSWithField(JSVariableField outerField)
     : base(outerField)
 {
     // with-fields cannot be crunced because they might
     // need to reference a property on the with object
     CanCrunch = false;
 }
Example #5
0
        public void DetachFromOuterField(bool leaveInnerPointingToOuter)
        {
            // we're going to change the reference from the outer variable to the inner variable
            // save the inner variable field
            JSNamedFunctionExpressionField nfeField = m_variableField.NamedFunctionExpression;

            // break the connection from the outer to the inner
            m_variableField.NamedFunctionExpression = null;

            if (!leaveInnerPointingToOuter)
            {
                // detach the inner from the outer
                nfeField.Detach();
            }

            // the outer field no longer points to the function object
            m_variableField.FieldValue = null;
            // but the inner field should
            nfeField.FieldValue = this;

            // our variable field is now the inner field
            m_variableField = nfeField;

            // and so is out identifier
            m_identifier.VariableField = nfeField;
        }
Example #6
0
        internal void SetOuterLocalField(ActivationObject parentScope)
        {
            // if we're trying to set the outer local field using a global scope,
            // then ignore this request. This should only do something for scopes with
            // local variables
            if (!(parentScope is GlobalScope))
            {
                // get the field reference for this lookup value
                JSVariableField variableField = parentScope.FindReference(m_name);
                if (variableField != null)
                {
                    // see if this scope already points to this name
                    if (parentScope[m_name] == null)
                    {
                        // create an inner reference so we don't keep walking up the scope chain for this name
                        variableField = parentScope.CreateInnerField(variableField);
                    }

                    // save the local field
                    VariableField = variableField as JSLocalField;
                    // add a reference
                    if (VariableField != null)
                    {
                        VariableField.AddReference(parentScope);
                    }
                }
            }
        }
Example #7
0
        public override JSVariableField CreateInnerField(JSVariableField outerField)
        {
            return(outerField.IfNotNull(o =>
            {
                // blindly create an inner reference field for with scopes, no matter what it
                // is. globals and predefined values can be hijacked by object properties in
                // this scope.
                var withField = AddField(CreateField(outerField));

                // and we need to make sure that any field that may be referenced from inside
                // a with-statement does not get automatically renamed
                outerField.CanCrunch = false;

                // if the outer field is an undefined global, then we want to flag it with a
                // special attribute that tells us that it might not actually be an undefined global,
                // because it might just be a property reference on the with-object.
                if (outerField.FieldType == FieldType.UndefinedGlobal)
                {
                    do
                    {
                        outerField.Attributes |= FieldAttributes.RTSpecialName;
                    } while ((outerField = outerField.OuterField) != null);
                }

                return withField;
            }));
        }
Example #8
0
        /// <summary>
        /// returns true if the fields point to the same ultimate reference object.
        /// Needs to walk up the outer-reference chain for each field in order to
        /// find the ultimate reference
        /// </summary>
        /// <param name="otherField"></param>
        /// <returns></returns>
        public bool IsSameField(JSVariableField otherField)
        {
            // shortcuts -- if they are already the same object, we're done;
            // and if the other field is null, then we are NOT the same object.
            if (this == otherField)
            {
                return(true);
            }
            else if (otherField == null)
            {
                return(false);
            }

            // get the ultimate field for this field
            var thisOuter = OuterField != null ? OuterField : this;

            while (thisOuter.OuterField != null)
            {
                thisOuter = thisOuter.OuterField;
            }

            // get the ultimate field for the other field
            var otherOuter = otherField.OuterField != null ? otherField.OuterField : otherField;

            while (otherOuter.OuterField != null)
            {
                otherOuter = otherOuter.OuterField;
            }

            // now that we have the same outer fields, check to see if they are the same
            return(thisOuter == otherOuter);
        }
Example #9
0
        /*public override BlockScope Clone()
         * {
         *  return new WithScope(Parser.ScopeStack.Peek(), Context, Parser);
         * }*/

        public override JSVariableField FindReference(string name)
        {
            // call the base class, which will walk up the chain to find wherever the name lives
            JSVariableField variableField = base.FindReference(name);

            if (variableField != null)
            {
                // it exists, but is it in our with scope?
                if (this[name] == null)
                {
                    // it's not. We need to create an inner field pointing to this outer
                    // field so we can make sure the name doesn't get crunched
                    variableField = CreateInnerField(variableField);
                }
            }
            else
            {
                // because this is a with scope, if something isn't defined anywhere, we
                // don't want to throw an error because we very well may be referencing
                // a property on the object of the with scope.
                // So add a global field to our scope and return that instead, and use the
                // RTSpecialName flag to indicate that we don't really know what this thing could be.
                JSVariableField globalField = Parser.GlobalScope.AddField(
                    new JSGlobalField(name, null, FieldAttributes.RTSpecialName)
                    );
                variableField = CreateInnerField(globalField);
            }
            return(variableField);
        }
Example #10
0
        public override JSVariableField CreateInnerField(JSVariableField outerField)
        {
            // blindly create an inner reference field for with scopes, no matter what it
            // is. globals and predefined values can be hijacked by object properties in
            // this scope.
            JSVariableField innerField = CreateField(outerField);

            AddField(innerField);
            return(innerField);
        }
Example #11
0
 internal JSLocalField(JSVariableField outerField)
     : base(outerField)
 {
     JSLocalField outerLocalField = outerField as JSLocalField;
     if (outerLocalField != null)
     {
         // copy some properties
         m_isDefined = outerLocalField.m_isDefined;
         m_isGenerated = outerLocalField.m_isGenerated;
     }
 }
Example #12
0
        private JSVariableField ResolveFromCollection(string name, HashSet <string> collection, FieldType fieldType, bool isFunction)
        {
            if (collection.Contains(name))
            {
                var variableField = new JSVariableField(fieldType, name, 0, null);
                variableField.IsFunction = isFunction;
                return(AddField(variableField));
            }

            return(null);
        }
Example #13
0
        internal JSLocalField(JSVariableField outerField)
            : base(outerField)
        {
            JSLocalField outerLocalField = outerField as JSLocalField;

            if (outerLocalField != null)
            {
                // copy some properties
                m_isDefined   = outerLocalField.m_isDefined;
                m_isGenerated = outerLocalField.m_isGenerated;
            }
        }
Example #14
0
        public virtual JSVariableField FindReference(string name)
        {
            // see if we have it
            JSVariableField variableField = this[name];

            // if we didn't find anything and this scope has a parent
            if (variableField == null && Parent != null)
            {
                // recursively go up the scope chain
                variableField = Parent.FindReference(name);
            }
            return(variableField);
        }
Example #15
0
        //public abstract BlockScope Clone();

        public override JSVariableField this[string name]
        {
            get
            {
                // check this name table
                JSVariableField variableField = base[name];
                if (variableField == null)
                {
                    // we need to keep checking until we hit a non-block scope?
                }
                return(variableField);
            }
        }
Example #16
0
        // NAME [SCOPE TYPE] [crunched to CRUNCH]
        //
        // SCOPE: global, local, outer, ''
        // TYPE: var, function, argument, arguments array, possibly undefined
        private void WriteMemberReport(JSVariableField variableField, ActivationObject immediateScope)
        {
            // skip any *unreferenced* named-function-expression fields
            JSNamedFunctionExpressionField namedFuncExpr = variableField as JSNamedFunctionExpressionField;

            if (namedFuncExpr == null || namedFuncExpr.RefCount > 0 || !m_removeFunctionExpressionNames)
            {
                string scope    = string.Empty;
                string type     = string.Empty;
                string crunched = string.Empty;
                string name     = variableField.Name;
                if (variableField.IsLiteral)
                {
                    name = variableField.FieldValue.ToString();
                }

                // calculate the crunched label
                JSLocalField localField = variableField as JSLocalField;
                if (localField != null)
                {
                    if (localField.CrunchedName != null)
                    {
                        crunched = StringMgr.GetString("CrunchedTo", localField.CrunchedName, localField.RefCount);
                    }
                }

                // get the field's default scope and type
                GetFieldScopeType(variableField, immediateScope, out scope, out type);
                if (variableField is JSWithField)
                {
                    // if the field is a with field, we won't be using the crunched field (since
                    // those fields can't be crunched), so let's overload it with what the field
                    // could POSSIBLY be if the with object doesn't have a property of that name
                    string outerScope;
                    string outerType;
                    GetFieldScopeType(variableField.OuterField, immediateScope, out outerScope, out outerType);
                    crunched = StringMgr.GetString("MemberInfoWithPossibly", outerScope, outerType);
                }

                // format the entire string
                WriteProgress(StringMgr.GetString(
                                  "MemberInfoFormat",
                                  name,
                                  scope,
                                  type,
                                  crunched
                                  ));
            }
        }
Example #17
0
        internal override void AnalyzeScope()
        {
            if (Context != null)
            {
                // get the parent global/function scope where variables defined within our
                // scope are REALLY defined
                ActivationObject definingScope = this;
                do
                {
                    definingScope = definingScope.Parent;
                } while (definingScope is BlockScope);

                // see if there is a variable already defined in that scope with the same name
                JSVariableField outerField = definingScope[m_name];
                if (outerField != null)
                {
                    // there is one defined already!!!
                    // but if it isn't referenced, it's safe to just use it
                    // as the outer field for our catch variable so our names
                    // stay in sync when we rename stuff
                    if (outerField.IsReferenced)
                    {
                        // but the outer field IS referenced somewhere! We have a possible ambiguous
                        // catch variable problem that behaves differently in IE and non-IE browsers.
                        Context.HandleError(JSError.AmbiguousCatchVar);
                    }
                }
                else
                {
                    // there isn't one defined -- add one and hook it to our argument
                    // field as the outer reference so the name doesn't collide with any
                    // other fields in that scope if we are renaming fields
                    outerField = definingScope.CreateField(m_name, null, 0);
                    outerField.IsPlaceholder = true;
                    definingScope.AddField(outerField);
                }

                // point our inner catch variable to the outer variable
                this[m_name].OuterField = outerField;
            }
            base.AnalyzeScope();
        }
Example #18
0
        public virtual JSVariableField CreateInnerField(JSVariableField outerField)
        {
            JSVariableField innerField;

            if (outerField is JSGlobalField || outerField is JSPredefinedField)
            {
                // if this is a global or predefined field, then just add the field itself
                // to the local scope. We don't want to create a local reference.
                innerField = outerField;
            }
            else
            {
                // create a new inner field to be added to our scope
                innerField = CreateField(outerField);
            }

            // add the field to our scope and return it
            AddField(innerField);
            return(innerField);
        }
Example #19
0
        internal JSVariableField(FieldType fieldType, JSVariableField outerField)
        {
            if (outerField == null)
            {
                throw new ArgumentNullException("outerField");
            }

            m_referenceTable   = new HashSet <INameReference>();
            m_declarationTable = new HashSet <INameDeclaration>();

            // set values based on the outer field
            OuterField = outerField;

            Name        = outerField.Name;
            Attributes  = outerField.Attributes;
            FieldValue  = outerField.FieldValue;
            IsGenerated = outerField.IsGenerated;

            // and set some other fields on our object based on the type we are
            SetFieldsBasedOnType(fieldType);
        }
Example #20
0
        public override JSVariableField FindReference(string name)
        {
            JSVariableField variableField = this[name];

            if (variableField == null)
            {
                // didn't find a field in this scope.
                // special to function scopes: check to see if this is the arguments object
                if (string.Compare(name, "arguments", StringComparison.Ordinal) == 0)
                {
                    // this is a reference to the arguments object, so add the
                    // arguments field to the scope and return it
                    variableField = AddArgumentsField();
                }
                else
                {
                    // recurse up the parent chain
                    variableField = Parent.FindReference(name);
                }
            }
            return(variableField);
        }
Example #21
0
        public override JSVariableField this[string name]
        {
            get
            {
                // check the name table
                JSVariableField variableField = base[name];

                // not found so far, check the global properties
                if (variableField == null)
                {
                    variableField = ResolveFromCollection(name, m_globalProperties, FieldType.Predefined, false);
                }

                // not found so far, check the global properties
                if (variableField == null)
                {
                    variableField = ResolveFromCollection(name, m_globalFunctions, FieldType.Predefined, true);
                }

                // if not found so far, check to see if this value is provided in our "assumed"
                // global list specified on the command line
                if (variableField == null)
                {
                    variableField = ResolveFromCollection(name, m_assumedGlobals, FieldType.Global, false);
                }

                // if it's not something explicitly defined so far, check to see if it
                // matches the browser-specific pattern (prefixes followed by Pascal-cased identifiers).
                // Plus, most browsers expose dozens of DOM elements prefixed by "HTML"
                // (eg: HTMLAnchorElement and HTMLTableColElement).
                if (variableField == null && s_blanketPrefixes.IsMatch(name))
                {
                    variableField = new JSVariableField(FieldType.Predefined, name, 0, null);
                    AddField(variableField);
                }

                return(variableField);
            }
        }
Example #22
0
        private static Context GetFirstDeclaration(JSVariableField variableField)
        {
            // only local fields that actually correspond to a declaration get the declaration
            // added to the declarations collection -- inner references don't get the declaration,
            // and neither do ghosted variables. So starting from this variable, walk up the
            // outer-reference chain until we find on with at least one declaration. If we don't
            // find one, that's fine -- there probably isn't a declaration for it (predefined, for example).
            while (variableField != null && variableField.Declarations.Count == 0)
            {
                variableField = variableField.OuterField;
            }

            if (variableField != null)
            {
                foreach (var declaration in variableField.Declarations)
                {
                    // we only care about the FIRST declaration, so return the context of the name
                    return(declaration.Context);
                }
            }

            // if we get here, there were no declarations
            return(null);
        }
Example #23
0
        internal override void AnalyzeNode()
        {
            // get the field -- it should have been generated when the scope was analyzed
            if (CatchBlock != null && !string.IsNullOrEmpty(m_catchVarName))
            {
                m_catchVariable = CatchBlock.BlockScope[m_catchVarName];
            }

            // anaylze the blocks
            base.AnalyzeNode();

            // if the try block is empty, then set it to null
            if (TryBlock != null && TryBlock.Count == 0)
            {
                TryBlock = null;
            }

            // eliminate an empty finally block UNLESS there is no catch block.
            if (FinallyBlock != null && FinallyBlock.Count == 0 && CatchBlock != null &&
                Parser.Settings.IsModificationAllowed(TreeModifications.RemoveEmptyFinally))
            {
                FinallyBlock = null;
            }
        }
Example #24
0
 internal JSVariableField AddField(JSVariableField variableField)
 {
     m_nameTable[variableField.Name] = variableField;
     m_fieldTable.Add(variableField);
     return variableField;
 }
Example #25
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;
            m_identifier = identifier;
            if (m_identifier != null)
            {
                m_identifier.Parent = this;
            }

            // make sure the parameter array is never null so we don't have to keep checking it
            m_parameterDeclarations = parameterDeclarations ?? new ParameterDeclaration[0];

            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 (m_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 = m_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;
                                m_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;
                                m_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.
                                m_identifier.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)
                                {
                                    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
                        m_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.
                m_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;
                }
            }
        }
Example #26
0
 internal JSVariableField AddField(JSVariableField variableField)
 {
     m_nameTable[variableField.Name] = variableField;
     m_fieldTable.Add(variableField);
     return(variableField);
 }
Example #27
0
 public override JSVariableField CreateField(JSVariableField outerField)
 {
     return new JSLocalField(outerField);
 }
Example #28
0
 public abstract JSVariableField CreateField(JSVariableField outerField);
Example #29
0
 internal JSVariableField(JSVariableField outerField)
     : this(outerField.Name, outerField.Attributes, outerField.FieldValue)
 {
     m_outerField = outerField;
 }
Example #30
0
 public abstract JSVariableField CreateField(JSVariableField outerField);
Example #31
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;
                }
            }
        }
Example #32
0
        /*public override BlockScope Clone()
         * {
         *  return new CatchScope(Parser.ScopeStack.Peek(), Context, Parser);
         * }*/

        public override JSVariableField CreateField(JSVariableField outerField)
        {
            return(new JSLocalField(outerField));
        }
Example #33
0
        private static void GetFieldScopeType(JSVariableField variableField, ActivationObject immediateScope, out string scope, out string type)
        {
            JSLocalField      localField                 = variableField as JSLocalField;
            JSPredefinedField predefinedField            = variableField as JSPredefinedField;
            JSNamedFunctionExpressionField namedFuncExpr = variableField as JSNamedFunctionExpressionField;

            // default scope is blank
            scope = string.Empty;

            if (variableField is JSArgumentField)
            {
                type = StringMgr.GetString("MemberInfoTypeArgument");
            }
            else if (variableField is JSArgumentsField)
            {
                type = StringMgr.GetString("MemberInfoTypeArguments");
            }
            else if (predefinedField != null)
            {
                switch (predefinedField.GlobalObject)
                {
                case GlobalObjectInstance.GlobalObject:
                    scope = StringMgr.GetString("MemberInfoScopeGlobalObject");
                    break;

                case GlobalObjectInstance.WindowObject:
                    scope = StringMgr.GetString("MemberInfoScopeWindowObject");
                    break;

                case GlobalObjectInstance.Other:
                    scope = StringMgr.GetString("MemberInfoScopeOtherObject");
                    break;
                }
                switch (predefinedField.MemberType)
                {
                case MemberTypes.Method:
                    type = StringMgr.GetString("MemberInfoBuiltInMethod");
                    break;

                case MemberTypes.Property:
                    type = StringMgr.GetString("MemberInfoBuiltInProperty");
                    break;

                default:
                    type = StringMgr.GetString("MemberInfoBuiltInObject");
                    break;
                }
            }
            else if (variableField is JSGlobalField)
            {
                if ((variableField.Attributes & FieldAttributes.RTSpecialName) == FieldAttributes.RTSpecialName)
                {
                    // this is a special "global." It might not be a global, but something referenced
                    // in a with scope somewhere down the line.
                    type = StringMgr.GetString("MemberInfoPossiblyUndefined");
                }
                else if (variableField.FieldValue is FunctionObject)
                {
                    if (variableField.NamedFunctionExpression == null)
                    {
                        type = StringMgr.GetString("MemberInfoGlobalFunction");
                    }
                    else
                    {
                        type = StringMgr.GetString("MemberInfoFunctionExpression");
                    }
                }
                else
                {
                    type = StringMgr.GetString("MemberInfoGlobalVar");
                }
            }
            else if (variableField is JSWithField)
            {
                type = StringMgr.GetString("MemberInfoWithField");
            }
            else if (namedFuncExpr != null)
            {
                type = StringMgr.GetString("MemberInfoSelfFuncExpr");
            }
            else if (localField != null)
            {
                // type string
                if (localField.FieldValue is FunctionObject)
                {
                    if (localField.NamedFunctionExpression == null)
                    {
                        type = StringMgr.GetString("MemberInfoLocalFunction");
                    }
                    else
                    {
                        type = StringMgr.GetString("MemberInfoFunctionExpression");
                    }
                }
                else if (localField.IsLiteral)
                {
                    type = StringMgr.GetString("MemberInfoLocalLiteral");
                }
                else
                {
                    type = StringMgr.GetString("MemberInfoLocalVar");
                }

                // scope string
                // this is a local variable, so there MUST be a non-null function scope passed
                // to us. That function scope will be the scope we are expecting local variables
                // to be defined in. If the field is defined in that scope, it's local -- otherwise
                // it must be an outer variable.
                JSVariableField scopeField = immediateScope[variableField.Name];
                if (scopeField == null || scopeField.OuterField != null)
                {
                    scope = StringMgr.GetString("MemberInfoScopeOuter");
                }
                else
                {
                    scope = StringMgr.GetString("MemberInfoScopeLocal");
                }
            }
            else
            {
                type = StringMgr.GetString("MemberInfoBuiltInObject");
            }
        }
Example #34
0
 public void SetCatchVariable(JSVariableField field)
 {
     m_catchVariable = field;
 }
Example #35
0
 public JSVariableField(JSVariableField outerField)
     : this(outerField.Name, outerField.Attributes, outerField.FieldValue)
 {
     m_outerField = outerField;
 }
Example #36
0
 public override JSVariableField CreateField(JSVariableField outerField)
 {
     // should NEVER try to create an inner field in a global scope
     throw new NotImplementedException();
 }
Example #37
0
        private void ProcessField(JSVariableField field, bool isDefined)
        {
            // save THIS field's refcount value because we will
            // be adjusting hte field pointer to be the outermost field
            // and we want to report THIS field's refcount, not the overall.
            var refCount = field.RefCount;
            var isGhost  = false;

            // make sure we're at the outer-most field
            var isOuter = false;

            if (!isDefined)
            {
                while (field.OuterField != null)
                {
                    isOuter = true;
                    field   = field.OuterField;
                }
            }

            m_writer.WriteStartElement("field");

            if (field.IsExported)
            {
                m_writer.WriteAttributeString("exported", "true");
            }

            var typeValue = field.FieldType.ToString();

            switch (field.FieldType)
            {
            case FieldType.Argument:
            case FieldType.CatchError:
            case FieldType.WithField:
                if (isOuter)
                {
                    typeValue = "Outer " + typeValue;
                }
                break;

            case FieldType.Local:
                if (isOuter)
                {
                    typeValue = "Outer ";
                }
                else
                {
                    typeValue = string.Empty;
                    if (field.IsPlaceholder || !field.IsDeclared)
                    {
                        isGhost = true;
                    }
                }

                if (field.IsFunction)
                {
                    typeValue += "Function";
                }
                else
                {
                    typeValue += "Variable";
                }
                break;

            case FieldType.Arguments:
            case FieldType.Global:
            case FieldType.UndefinedGlobal:
            case FieldType.GhostCatch:
            case FieldType.GhostFunction:
            case FieldType.Predefined:
            case FieldType.Super:
                break;
            }

            m_writer.WriteAttributeString("type", typeValue.ToLowerInvariant());
            m_writer.WriteAttributeString("src", field.Name);
            if (field.CrunchedName != null)
            {
                m_writer.WriteAttributeString("min", field.CrunchedName);
            }

            OutputContextPosition(field.OriginalContext);

            if (m_useReferenceCounts)
            {
                m_writer.WriteAttributeString("refcount", refCount.ToStringInvariant());
            }

            if (field.IsAmbiguous)
            {
                m_writer.WriteAttributeString("ambiguous", "true");
            }

            if (field.IsGenerated)
            {
                m_writer.WriteAttributeString("generated", "true");
            }

            if (isGhost)
            {
                m_writer.WriteAttributeString("ghost", "true");
            }

            m_writer.WriteEndElement();
        }
Example #38
0
        public void DetachFromOuterField(bool leaveInnerPointingToOuter)
        {
            // we're going to change the reference from the outer variable to the inner variable
            // save the inner variable field
            JSNamedFunctionExpressionField nfeField = m_variableField.NamedFunctionExpression;
            // break the connection from the outer to the inner
            m_variableField.NamedFunctionExpression = null;

            if (!leaveInnerPointingToOuter)
            {
                // detach the inner from the outer
                nfeField.Detach();
            }

            // the outer field no longer points to the function object
            m_variableField.FieldValue = null;
            // but the inner field should
            nfeField.FieldValue = this;

            // our variable field is now the inner field
            m_variableField = nfeField;

            // and so is out identifier
            Identifier.VariableField = nfeField;
        }
Example #39
0
        public virtual JSVariableField CreateInnerField(JSVariableField outerField)
        {
            JSVariableField innerField;
            if (outerField is JSGlobalField || outerField is JSPredefinedField)
            {
                // if this is a global or predefined field, then just add the field itself
                // to the local scope. We don't want to create a local reference.
                innerField = outerField;
            }
            else
            {
                // create a new inner field to be added to our scope
                innerField = CreateField(outerField);
            }

            // add the field to our scope and return it
            AddField(innerField);
            return innerField;
        }
Example #40
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;
            }
        }
Example #41
0
 public override JSVariableField CreateField(JSVariableField outerField)
 {
     // should NEVER try to create an inner field in a global scope
     throw new NotImplementedException();
 }
Example #42
0
        /// <summary>
        /// returns true if the fields point to the same ultimate reference object.
        /// Needs to walk up the outer-reference chain for each field in order to
        /// find the ultimate reference
        /// </summary>
        /// <param name="otherField"></param>
        /// <returns></returns>
        public bool IsSameField(JSVariableField otherField)
        {
            // shortcuts -- if they are already the same object, we're done;
            // and if the other field is null, then we are NOT the same object.
            if (this == otherField)
            {
                return true;
            }
            else if (otherField == null)
            {
                return false;
            }

            // get the ultimate field for this field
            var thisOuter = OuterField != null ? OuterField : this;
            while (thisOuter.OuterField != null)
            {
                thisOuter = thisOuter.OuterField;
            }

            // get the ultimate field for the other field
            var otherOuter = otherField.OuterField != null ? otherField.OuterField : otherField;
            while (otherOuter.OuterField != null)
            {
                otherOuter = otherOuter.OuterField;
            }

            // now that we have the same outer fields, check to see if they are the same
            return thisOuter == otherOuter;
        }