Ejemplo n.º 1
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);
                    }
                }
            }
        }
Ejemplo n.º 2
0
 internal FunctionScope(ActivationObject parent, bool isExpression, JSParser parser)
     : base(parent, parser)
 {
     if (isExpression)
     {
         // parent scopes automatically reference enclosed function expressions
         AddReference(Parent);
     }
 }
Ejemplo n.º 3
0
 internal FunctionScope(ActivationObject parent, bool isExpression, JSParser parser)
     : base(parent, parser)
 {
     if (isExpression)
     {
         // parent scopes automatically reference enclosed function expressions
         AddReference(Parent);
     }
 }
Ejemplo n.º 4
0
        public ModuleScope(ModuleDeclaration module, ActivationObject parent, CodeSettings settings)
            : base(parent, settings)
        {
            Owner     = module;
            UseStrict = true;
            ScopeType = ScopeType.Module;

            m_knownExports = new Dictionary <string, JSVariableField>();
        }
Ejemplo n.º 5
0
        internal CatchScope(ActivationObject parent, Context argContext, JSParser parser)
            : base(parent, argContext, parser)
        {
            // get the name of the catch variable
            m_name = Context.Code;

            // add it to the catch-scope's name table
            JSVariableField field = new JSArgumentField(m_name, null);

            NameTable[m_name] = field;
            FieldTable.Add(field);
        }
Ejemplo n.º 6
0
        internal override void HyperCrunch()
        {
            // the block scope is used for catch blocks.
            // we don't want to introduce possible cross-browser problems, so
            // we need to make sure we don't rename our catch parameter to anything
            // already existing in our parent function scope.
            //
            // so walk through the parents (up to the first function or the global scope)
            // and add all existing crunched variable names to our verboten list.
            ActivationObject parentScope = Parent;

            while (parentScope != null)
            {
                // take all the variable names (crunched if they're crunched)
                // and add them to this block's verboten list if they aren't already.
                if (parentScope.NameTable.Count > 0)
                {
                    foreach (var variableField in parentScope.NameTable.Values)
                    {
                        // add it to our verboten list
                        if (!Verboten.ContainsKey(variableField))
                        {
                            Verboten.Add(variableField, variableField);
                        }
                    }
                }

                // also add everything in the parent's verboten list
                if (parentScope.Verboten.Count > 0)
                {
                    foreach (var variableField in parentScope.Verboten.Keys)
                    {
                        // add it to our verboten list
                        if (!Verboten.ContainsKey(variableField))
                        {
                            Verboten.Add(variableField, variableField);
                        }
                    }
                }

                // stop as soon as we've processed a funciton or global scope
                if (!(parentScope is BlockScope))
                {
                    break;
                }
                // next parent
                parentScope = parentScope.Parent;
            }

            // then just perform as usual
            base.HyperCrunch();
        }
Ejemplo n.º 7
0
        internal override void AnalyzeNode()
        {
            // check to see if this node is an argument to a RegExp constructor.
            // if it is, we'll want to not use certain string escapes
            AstNode previousNode = null;
            AstNode parentNode   = Parent;

            while (parentNode != null)
            {
                // is this a call node and he previous node was one of the parameters?
                CallNode callNode = parentNode as CallNode;
                if (callNode != null && previousNode == callNode.Arguments)
                {
                    // are we calling a simple lookup for "RegExp"?
                    Lookup lookup = callNode.Function as Lookup;
                    if (lookup != null && lookup.Name == "RegExp")
                    {
                        // we are -- so all string literals passed within this constructor should not use
                        // standard string escape sequences
                        m_isParameterToRegExp = true;
                        // we can stop looking
                        break;
                    }
                }

                // next up the chain, keeping track of this current node as next iteration's "previous" node
                previousNode = parentNode;
                parentNode   = parentNode.Parent;
            }

            // we only need to process the literals IF we are actually going to do
            // anything with them (combine duplicates). So if we aren't, don't call
            // AddLiteral because it hugely inflates the processing time of the application.
            if (Parser.Settings.CombineDuplicateLiterals)
            {
                // add this literal to the scope's literal collection.
                // HOWEVER, we do NOT want to add it for consideration of literal combination
                // if any scope above us is a with-scope -- otherwise the
                // variable we use to combine the literals might be confused with a
                // property on the with-object.
                // AND we don't want to do it if the scope is unknown, for the same reason.
                // we won't really know if the variable we create will interfere with the
                // scope resolution of any variables that me in the eval string.
                ActivationObject thisScope = Parser.ScopeStack.Peek();
                if (thisScope.IsKnownAtCompileTime && !thisScope.IsInWithScope)
                {
                    thisScope.AddLiteral(this, thisScope);
                }
            }

            // this node has no children, so don't bother calling the base
        }
Ejemplo n.º 8
0
        internal FunctionScope(ActivationObject parent, bool isExpression, CodeSettings settings, FunctionObject funcObj)
            : base(parent, settings)
        {
            ScopeType   = ScopeType.Function;
            m_refScopes = new HashSet <ActivationObject>();
            if (isExpression)
            {
                // parent scopes automatically reference enclosed function expressions
                AddReference(Parent);
            }

            Owner = funcObj;
        }
Ejemplo n.º 9
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
                                  ));
            }
        }
Ejemplo n.º 10
0
            public LiteralReference(ConstantWrapper constantWrapper, ActivationObject childScope, List <ConstantWrapper> sharedList)
            {
                m_count      = 1;
                m_childScope = childScope;

                // use the shared list passed to us, or create a new one
                m_constantWrappers = sharedList ?? new List <ConstantWrapper>();

                // only add the constant wrapper passed to us IF it isn't ALREADY in the list
                // (will only happen with a shared list)
                if (!m_constantWrappers.Contains(constantWrapper))
                {
                    m_constantWrappers.Add(constantWrapper);
                }
            }
Ejemplo n.º 11
0
        internal void AddReference(ActivationObject scope)
        {
            // we don't want to include block scopes or with scopes -- they are really
            // contained within their parents
            while (scope != null && scope is BlockScope)
            {
                scope = scope.Parent;
            }

            if (scope != null)
            {
                // add the scope to the hash
                m_refScopes.Add(scope);
            }
        }
Ejemplo n.º 12
0
 private void AddScopes(List <ActivationObject> list, ActivationObject parentScope)
 {
     // for each child scope...
     foreach (ActivationObject scope in parentScope.ChildScopes)
     {
         // add the scope to the list if it's not a globalscopes
         // which leaves function scopes and block scopes (from catch blocks)
         if (!(scope is GlobalScope))
         {
             list.Add(scope);
         }
         // recurse...
         AddScopes(list, scope);
     }
 }
Ejemplo n.º 13
0
        private void AddScopes(List <ActivationObject> list, ActivationObject parentScope)
        {
            // for each child scope...
            foreach (ActivationObject scope in parentScope.ChildScopes)
            {
                // add the scope to the list if it's not a globalscopes
                if (!(scope is GlobalScope))
                {
                    list.Add(scope);
                }

                // recurse...
                AddScopes(list, scope);
            }
        }
Ejemplo n.º 14
0
        private void WriteScopeReport(FunctionObject funcObj, ActivationObject scope)
        {
            // output the function header
            if (scope is GlobalScope)
            {
                WriteProgress(StringMgr.GetString("GlobalObjectsHeader"));
            }
            else
            {
                FunctionScope functionScope = scope as FunctionScope;
                if (functionScope != null && funcObj != null)
                {
                    WriteFunctionHeader(funcObj, scope.IsKnownAtCompileTime);
                }
                else
                {
                    BlockScope blockScope = scope as BlockScope;
                    if (blockScope is CatchScope)
                    {
                        WriteBlockHeader(blockScope, StringMgr.GetString("BlockTypeCatch"));
                    }
                    else if (blockScope is WithScope)
                    {
                        WriteBlockHeader(blockScope, StringMgr.GetString("BlockTypeWith"));
                    }
                    else
                    {
                        WriteProgress();
                        WriteProgress(StringMgr.GetString("UnknownScopeType", scope.GetType().ToString()));
                    }
                }
            }

            // get all the fields in the scope
            JSVariableField[] scopeFields = scope.GetFields();
            // sort the fields
            Array.Sort(scopeFields, FieldComparer.Instance);

            // iterate over all the fields
            foreach (JSVariableField variableField in scopeFields)
            {
                // don't report placeholder fields
                if (!variableField.IsPlaceholder)
                {
                    WriteMemberReport(variableField, scope);
                }
            }
        }
Ejemplo n.º 15
0
 internal override void AnalyzeNode()
 {
     // if the developer hasn't explicitly flagged eval statements as safe...
     if (Parser.Settings.EvalTreatment != EvalTreatment.Ignore)
     {
         // mark this scope as unknown so we don't
         // crunch out locals we might reference in the eval at runtime
         ActivationObject enclosingScope = ScopeStack.Peek();
         if (enclosingScope != null)
         {
             enclosingScope.IsKnownAtCompileTime = false;
         }
     }
     // then just do the default analysis
     base.AnalyzeNode();
 }
Ejemplo n.º 16
0
        protected ActivationObject(ActivationObject parent, JSParser parser)
        {
            m_parent               = parent;
            m_nameTable            = new Dictionary <string, JSVariableField>();
            m_fieldTable           = new List <JSVariableField>();
            m_childScopes          = new List <ActivationObject>();
            Verboten               = new Dictionary <JSVariableField, JSVariableField>(32);
            m_isKnownAtCompileTime = true;
            m_parser               = parser;

            // if our parent is a scope....
            if (parent != null)
            {
                // add us to the parent's list of child scopes
                parent.m_childScopes.Add(this);
            }
        }
Ejemplo n.º 17
0
        internal override void AnalyzeNode()
        {
            // first we want to make sure that we are indeed within a function scope.
            // it makes no sense to have a return outside of a function
            ActivationObject scope = ScopeStack.Peek();

            while (scope != null && !(scope is FunctionScope))
            {
                scope = scope.Parent;
            }
            if (scope == null)
            {
                Context.HandleError(JSError.BadReturn);
            }

            // now just do the default analyze
            base.AnalyzeNode();
        }
Ejemplo n.º 18
0
        public override JSVariableField DeclareField(string name, object value, FieldAttributes attributes)
        {
            JSVariableField variableField;

            if (!NameTable.TryGetValue(name, out variableField))
            {
                // find the owning scope where variables are defined
                ActivationObject owningScope = Parent;
                while (owningScope is BlockScope)
                {
                    owningScope = owningScope.Parent;
                }
                // create the variable in that scope
                variableField = owningScope.DeclareField(name, value, attributes);
                // and create an inner-reference in our scope
                variableField = CreateInnerField(variableField);
            }
            return(variableField);
        }
Ejemplo n.º 19
0
 internal void AddReference(ActivationObject scope)
 {
     // make sure the hash is created
     if (m_refScopes == null)
     {
         m_refScopes = new Dictionary <ActivationObject, ActivationObject>();
     }
     // we don't want to include block scopes or with scopes -- they are really
     // contained within their parents
     while (scope != null && scope is BlockScope)
     {
         scope = scope.Parent;
     }
     if (scope != null && !m_refScopes.ContainsKey(scope))
     {
         // add the scope to the hash
         m_refScopes.Add(scope, scope);
     }
 }
Ejemplo n.º 20
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();
        }
Ejemplo n.º 21
0
        private bool m_useStrict; //= false;

        #endregion Fields

        #region Constructors

        protected ActivationObject(ActivationObject parent, JSParser parser)
        {
            m_parent = parent;
            m_nameTable = new Dictionary<string, JSVariableField>();
            m_fieldTable = new List<JSVariableField>();
            m_childScopes = new List<ActivationObject>();
            Verboten = new Dictionary<JSVariableField, JSVariableField>(32);
            m_isKnownAtCompileTime = true;
            m_parser = parser;

            // if our parent is a scope....
            if (parent != null)
            {
                // add us to the parent's list of child scopes
                parent.m_childScopes.Add(this);

                // if the parent is strict, so are we
                UseStrict = parent.UseStrict;
            }
        }
Ejemplo n.º 22
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.º 23
0
        // called during ConstantWrapper.AnalyzeNode
        internal virtual List <ConstantWrapper> AddLiteral(ConstantWrapper constantWrapper, ActivationObject refScope)
        {
            List <ConstantWrapper> nodeList = null;

            // numeric constants that are NaN or Infinity need not apply
            if (!constantWrapper.IsSpecialNumeric)
            {
                // if the constant is only one character long, it's never a good idea to
                // try and replace it
                string constantValue = constantWrapper.ToCode();
                if (constantValue.Length > 1)
                {
                    // go up the chain recursively. return the highest shared
                    // constant node list so we can share it if we need to
                    nodeList = ((ActivationObject)Parent).AddLiteral(constantWrapper, this);

                    // if we haven't created our literal map yet, do so now
                    if (m_literalMap == null)
                    {
                        m_literalMap = new Dictionary <string, LiteralReference>();
                    }

                    // now handle our scope
                    LiteralReference literalReference;
                    // see if this constant is in our map
                    if (m_literalMap.ContainsKey(constantValue))
                    {
                        literalReference = m_literalMap[constantValue];
                        // increment the counter
                        literalReference.Increment();
                        // add this constant wrapper to the list
                        if (!literalReference.ConstantWrapperList.Contains(constantWrapper))
                        {
                            literalReference.ConstantWrapperList.Add(constantWrapper);
                        }

                        // if this is the ref scope, or if the ref scope is not the child scope,
                        // set the child scope to null
                        if (literalReference.ChildScope != null &&
                            (refScope == this || refScope != literalReference.ChildScope))
                        {
                            literalReference.ChildScope = null;
                        }
                    }
                    else
                    {
                        // add to the table with count = 1 and our given constant wrapper
                        // if this is the ref scope, child scope is null; otherwise use refScope
                        // if nodelist is null, create a new list; otherwise use the shared list
                        literalReference = new LiteralReference(
                            constantWrapper,
                            (refScope != this ? refScope : null),
                            nodeList
                            );
                        m_literalMap.Add(constantValue, literalReference);
                    }

                    // return whatever list it is we used for our node.
                    // it might be shared, or it might be new if we didn't find a shared list
                    nodeList = literalReference.ConstantWrapperList;
                }
            }

            return(nodeList);
        }
Ejemplo n.º 24
0
        protected virtual void CreateLiteralShortcuts()
        {
            if (m_literalMap != null)
            {
                // get a reference to the first function scope in the chain
                // might be this, might be a parent
                FunctionScope    functionScope = null;
                ActivationObject scope         = this;
                while (scope != null && (functionScope = scope as FunctionScope) == null)
                {
                    scope = scope.Parent;
                }

                // if we didn't find a parent function scope, then don't do any combining
                // because the literals are globals
                if (functionScope != null)
                {
                    // for each value in our literal map
                    foreach (string constantString in m_literalMap.Keys)
                    {
                        LiteralReference literalReference = m_literalMap[constantString];

                        // if the child scope isn't null, then we don't reference the literal
                        // and only one of our child scopes does, so we don't want to add the
                        // shortcut here.
                        // OR if there are no constant wrappers left in the list, then we've already
                        // replaced them all and there's nothing left to do.
                        // BUT if the child scope is null, either we reference it, or more than
                        // one child references it. So if there are any constant wrappers in the list,
                        // then we want to add the shortcut and replace all the constants
                        if (literalReference.ChildScope == null && literalReference.ConstantWrapperList.Count > 0)
                        {
                            // AND we only want to do it if it will be worthwhile.
                            // (and a constant of length 1 is never worthwhile)
                            int constantLength = constantString.Length;
                            if (constantLength > 1)
                            {
                                int minCount = (constantLength + 7) / (constantLength - 1);
                                if (literalReference.Count > minCount)
                                {
                                    // create a special name that won't collide with any other variable names
                                    string specialName = string.Format(CultureInfo.InvariantCulture, "[literal:{0}]", ++s_literalCounter);

                                    // add a generated var statement at the top of the function block that
                                    // is equal to the literal value (just use the first constant wrapper as a model)
                                    ConstantWrapper modelConstant = literalReference.ConstantWrapperList[0];

                                    // by default we will use the value of the first instance as the generated variable's value
                                    object generatedValue = modelConstant.Value;

                                    // BUT....
                                    // if this is a numeric value, then we need to determine whether we should use a
                                    // positive or negative version of this value to minimize the number of minus operators in the results
                                    if (modelConstant.IsNumericLiteral)
                                    {
                                        // first we need to go through the existing references and count how many negative values there are
                                        var numberOfNegatives = 0;
                                        foreach (ConstantWrapper constantWrapper in literalReference.ConstantWrapperList)
                                        {
                                            // since the model us numeric, we shouldn't have any problems calling the
                                            // ToNumber method on the others (which should all also be numeric)
                                            if (constantWrapper.ToNumber() < 0)
                                            {
                                                ++numberOfNegatives;
                                            }
                                        }

                                        // now if more than half of the references are negative, we will want the generated value
                                        // to also be negative! Otherwise we want to force it to Positive.
                                        var absoluteValue = Math.Abs((double)generatedValue);
                                        if (numberOfNegatives > literalReference.ConstantWrapperList.Count / 2)
                                        {
                                            // force it to negative
                                            generatedValue = -absoluteValue;
                                        }
                                        else
                                        {
                                            // force it to positive
                                            generatedValue = absoluteValue;
                                        }
                                    }

                                    // add the generated variable to the function scope
                                    functionScope.FunctionObject.AddGeneratedVar(
                                        specialName,
                                        new ConstantWrapper(
                                            generatedValue,
                                            modelConstant.PrimitiveType,
                                            modelConstant.Context,
                                            Parser),
                                        true);

                                    // walk the list of constant wrappers backwards (because we'll be removing them
                                    // as we go along) and replace each one with a lookup for the generated variable.
                                    // Don't forget to analyze the lookup.
                                    for (int ndx = literalReference.ConstantWrapperList.Count - 1; ndx >= 0; --ndx)
                                    {
                                        ConstantWrapper constantWrapper = literalReference.ConstantWrapperList[ndx];

                                        // create the lookup based on the thisliteral context
                                        Lookup lookup = new Lookup(specialName, constantWrapper.Context, Parser);
                                        // indicate this is generated by our code, not the user
                                        lookup.IsGenerated = true;

                                        // by default, we're just going to replace the constant with the lookup
                                        AstNode replacement = lookup;

                                        // if the constant wrapper is a numeric value that is the NEGATIVE of the
                                        // combined numeric value (which would happen if the literal was subsequently
                                        // combined with a unary minus operator), then we need to change this to a unary-minus
                                        // operator on the lookup, not just the lookup.
                                        if (constantWrapper.IsNumericLiteral)
                                        {
                                            // since the constant wrapper is numeric, we shouldn't have any problems
                                            // calling ToNumber
                                            if ((double)generatedValue == -constantWrapper.ToNumber())
                                            {
                                                // it has been negated! Change the replacement to a unary minus operator
                                                // with the lookup as its operand
                                                replacement = new NumericUnary(
                                                    constantWrapper.Context,
                                                    Parser,
                                                    lookup,
                                                    JSToken.Minus);
                                            }
                                        }

                                        // replace the this literal with the appropriate node
                                        constantWrapper.Parent.ReplaceChild(constantWrapper, replacement);

                                        // set up the lookup's outer local field using the scope of the
                                        // original constant wrapper
                                        lookup.SetOuterLocalField(constantWrapper.EnclosingScope);

                                        // and remove it from the list. This is so child scopes don't also try to
                                        // add a shortcut -- the list will be empty.
                                        literalReference.ConstantWrapperList.RemoveAt(ndx);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
Ejemplo n.º 25
0
        internal virtual void ReserveFields()
        {
            // traverse through our children first to get depth-first
            foreach (ActivationObject scope in m_childScopes)
            {
                scope.ReserveFields();
            }

            // then reserve all our fields that need reserving
            // check for unused local fields or arguments
            foreach (JSVariableField variableField in m_nameTable.Values)
            {
                JSLocalField localField = variableField as JSLocalField;
                if (localField != null)
                {
                    // if this is a named-function-expression name, then we want to use the name of the
                    // outer field so we don't collide in IE
                    JSNamedFunctionExpressionField namedExprField = localField as JSNamedFunctionExpressionField;
                    if (namedExprField != null)
                    {
                        // make sure the field is in this scope's verboten list so we don't accidentally reuse
                        // an outer scope variable name
                        if (!Verboten.ContainsKey(localField))
                        {
                            Verboten.Add(localField, localField);
                        }

                        // we don't need to reserve up the scope because the named function expression's
                        // "outer" field is always in the very next scope
                    }
                    else if (localField.OuterField != null)
                    {
                        // if the outer field is not null, then this field (not the name) needs to be
                        // reserved up the scope chain until the scope where it's defined.
                        // make sure the field is in this scope's verboten list so we don't accidentally reuse
                        // the outer scope's variable name
                        if (!Verboten.ContainsKey(localField))
                        {
                            Verboten.Add(localField, localField);
                        }

                        for (ActivationObject scope = this; scope != null; scope = scope.Parent)
                        {
                            // get the local field by this name (if any)
                            JSLocalField scopeField = scope.GetLocalField(variableField.Name);
                            if (scopeField == null)
                            {
                                // it's not referenced in this scope -- if the field isn't in the verboten
                                // list, add it now
                                if (!scope.Verboten.ContainsKey(localField))
                                {
                                    scope.Verboten.Add(localField, localField);
                                }
                            }
                            else if (scopeField.OuterField == null)
                            {
                                // found the original field -- stop looking
                                break;
                            }
                        }
                    }
                    else if (m_parser.Settings.LocalRenaming == LocalRenaming.KeepLocalizationVars &&
                             localField.Name.StartsWith("L_", StringComparison.Ordinal))
                    {
                        // localization variable. don't crunch it.
                        // add it to this scope's verboten list in the extremely off-hand chance
                        // that a crunched variable might be the same pattern
                        if (!Verboten.ContainsKey(localField))
                        {
                            Verboten.Add(localField, localField);
                        }
                    }
                    else if (!localField.CanCrunch)
                    {
                        // this local field cannot be crunched for whatever reason
                        // (we probably already have a name picked out for it that we want to keep).
                        // add it to the verboten list, too.
                        if (!Verboten.ContainsKey(localField))
                        {
                            Verboten.Add(localField, localField);
                        }
                    }
                }
                else
                {
                    // must be a global of some sort
                    // reserve the name in this scope and all the way up the chain
                    for (ActivationObject scope = this; scope != null; scope = scope.Parent)
                    {
                        if (!scope.Verboten.ContainsKey(variableField))
                        {
                            scope.Verboten.Add(variableField, variableField);
                        }
                    }
                }
            }

            // finally, if this scope is not known at compile time,
            // AND we know we want to make all affected scopes safe
            // for the eval statement
            // AND we are actually referenced by the enclosing scope,
            // then our parent scope is also not known at compile time
            if (!m_isKnownAtCompileTime &&
                Parser.Settings.EvalTreatment == EvalTreatment.MakeAllSafe)
            {
                ActivationObject parentScope = (ActivationObject)Parent;
                FunctionScope    funcScope   = this as FunctionScope;
                if (funcScope == null)
                {
                    // we're not a function -- parent is unknown too
                    parentScope.IsKnownAtCompileTime = false;
                }
                else
                {
                    JSLocalField localField = parentScope.GetLocalField(funcScope.FunctionObject.Name);
                    if (localField == null || localField.IsReferenced)
                    {
                        parentScope.IsKnownAtCompileTime = false;
                    }
                }
            }
        }
Ejemplo n.º 26
0
        internal virtual void AnalyzeScope()
        {
            // check for unused local fields or arguments
            foreach (JSVariableField variableField in m_nameTable.Values)
            {
                JSLocalField locField = variableField as JSLocalField;
                if (locField != null && !locField.IsReferenced && locField.OriginalContext != null)
                {
                    if (locField.FieldValue is FunctionObject)
                    {
                        Context ctx = ((FunctionObject)locField.FieldValue).IdContext;
                        if (ctx == null)
                        {
                            ctx = locField.OriginalContext;
                        }
                        ctx.HandleError(JSError.FunctionNotReferenced, false);
                    }
                    else if (!locField.IsGenerated)
                    {
                        JSArgumentField argumentField = locField as JSArgumentField;
                        if (argumentField != null)
                        {
                            // we only want to throw this error if it's possible to remove it
                            // from the argument list. And that will only happen if there are
                            // no REFERENCED arguments after this one in the formal parameter list.
                            // Assertion: because this is a JSArgumentField, this should be a function scope,
                            // let's walk up to the first function scope we find, just in case.
                            FunctionScope functionScope = this as FunctionScope;
                            if (functionScope == null)
                            {
                                ActivationObject scope = this.Parent;
                                while (scope != null)
                                {
                                    functionScope = scope as FunctionScope;
                                    if (scope != null)
                                    {
                                        break;
                                    }
                                }
                            }
                            if (functionScope == null || functionScope.IsArgumentTrimmable(argumentField))
                            {
                                locField.OriginalContext.HandleError(
                                    JSError.ArgumentNotReferenced,
                                    false
                                    );
                            }
                        }
                        else if (locField.OuterField == null || !locField.OuterField.IsReferenced)
                        {
                            locField.OriginalContext.HandleError(
                                JSError.VariableDefinedNotReferenced,
                                false
                                );
                        }
                    }
                }
            }

            // rename fields if we need to
            RenameFields();

            // recurse
            foreach (ActivationObject activationObject in m_childScopes)
            {
                try
                {
                    Parser.ScopeStack.Push(activationObject);
                    activationObject.AnalyzeScope();
                }
                finally
                {
                    Parser.ScopeStack.Pop();
                }
            }
        }
Ejemplo n.º 27
0
        // called during AnalyzeNodeVisitor(ConstantWrapper)
        internal virtual List<ConstantWrapper> AddLiteral(ConstantWrapper constantWrapper, ActivationObject refScope)
        {
            List<ConstantWrapper> nodeList = null;

            // numeric constants that are NaN or Infinity need not apply
            if (!constantWrapper.IsSpecialNumeric)
            {
                // if the constant is only one character long, it's never a good idea to
                // try and replace it
                string constantValue = constantWrapper.ToCode();
                if (constantValue.Length > 1)
                {
                    // go up the chain recursively. return the highest shared
                    // constant node list so we can share it if we need to
                    nodeList = ((ActivationObject)Parent).AddLiteral(constantWrapper, this);

                    // if we haven't created our literal map yet, do so now
                    if (m_literalMap == null)
                    {
                        m_literalMap = new Dictionary<string, LiteralReference>();
                    }

                    // now handle our scope
                    LiteralReference literalReference;
                    // see if this constant is in our map
                    if (m_literalMap.ContainsKey(constantValue))
                    {
                        literalReference = m_literalMap[constantValue];
                        // increment the counter
                        literalReference.Increment();
                        // add this constant wrapper to the list
                        if (!literalReference.ConstantWrapperList.Contains(constantWrapper))
                        {
                            literalReference.ConstantWrapperList.Add(constantWrapper);
                        }

                        // if this is the ref scope, or if the ref scope is not the child scope,
                        // set the child scope to null
                        if (literalReference.ChildScope != null
                          && (refScope == this || refScope != literalReference.ChildScope))
                        {
                            literalReference.ChildScope = null;
                        }
                    }
                    else
                    {
                        // add to the table with count = 1 and our given constant wrapper
                        // if this is the ref scope, child scope is null; otherwise use refScope
                        // if nodelist is null, create a new list; otherwise use the shared list
                        literalReference = new LiteralReference(
                          constantWrapper,
                          (refScope != this ? refScope : null),
                          nodeList
                          );
                        m_literalMap.Add(constantValue, literalReference);
                    }

                    // return whatever list it is we used for our node.
                    // it might be shared, or it might be new if we didn't find a shared list
                    nodeList = literalReference.ConstantWrapperList;
                }
            }

            return nodeList;
        }
Ejemplo n.º 28
0
 public WithScope(ActivationObject parent, Context context, JSParser parser)
     : base(parent, context, parser)
 {
     // with statements are unknown by default
     //IsKnownAtCompileTime = false;
 }
Ejemplo n.º 29
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.º 30
0
            public LiteralReference(ConstantWrapper constantWrapper, ActivationObject childScope, List<ConstantWrapper> sharedList)
            {
                m_count = 1;
                m_childScope = childScope;

                // use the shared list passed to us, or create a new one
                m_constantWrappers = sharedList ?? new List<ConstantWrapper>();

                // only add the constant wrapper passed to us IF it isn't ALREADY in the list
                // (will only happen with a shared list)
                if (!m_constantWrappers.Contains(constantWrapper))
                {
                    m_constantWrappers.Add(constantWrapper);
                }
            }
Ejemplo n.º 31
0
 // not instantiated directly, only through derived classes
 protected BlockScope(ActivationObject parent, Context context, JSParser parser)
     : base(parent, parser)
 {
     m_context = (context == null ? new Context(parser) : context.Clone());
 }
Ejemplo n.º 32
0
        private void ProcessFields(ActivationObject scope)
        {
            // split fields into defined and referenced lists
            var definedFields    = new List <JSVariableField>();
            var referencedFields = new List <JSVariableField>();

            foreach (var field in scope.NameTable.Values)
            {
                // if the field has no outer field reference, it is defined in this scope.
                // otherwise we're just referencing a field defined elsewhere
                if (!field.IsOuterReference)
                {
                    switch (field.FieldType)
                    {
                    case FieldType.Global:
                        if (scope is GlobalScope)
                        {
                            definedFields.Add(field);
                        }
                        else
                        {
                            referencedFields.Add(field);
                        }
                        break;

                    case FieldType.Local:
                        // defined within this scope
                        definedFields.Add(field);
                        break;

                    case FieldType.Argument:
                        // ignore the scope's arguments because we handle them separately
                        break;

                    case FieldType.CatchError:
                        // ignore the catch-scope's error parameter because we handle it separately
                        break;

                    case FieldType.Arguments:
                        if (field.RefCount > 0)
                        {
                            referencedFields.Add(field);
                        }
                        break;

                    case FieldType.Super:
                        referencedFields.Add(field);
                        break;

                    case FieldType.UndefinedGlobal:
                    case FieldType.Predefined:
                    case FieldType.WithField:
                        referencedFields.Add(field);
                        break;

                    case FieldType.GhostFunction:
                    case FieldType.GhostCatch:
                        // ignore the ghost fields when reporting
                        break;
                    }
                }
                else if (!field.IsPlaceholder)
                {
                    // we are an outer reference and we are not a placeholder,
                    // so this scope actually references the outer field.
                    referencedFields.Add(field);
                }
            }

            if (definedFields.Count > 0)
            {
                m_writer.WriteStartElement("defines");
                foreach (var field in definedFields)
                {
                    ProcessField(field, true);
                }

                m_writer.WriteEndElement();
            }

            if (referencedFields.Count > 0)
            {
                m_writer.WriteStartElement("references");
                foreach (var field in referencedFields)
                {
                    ProcessField(field, false);
                }

                m_writer.WriteEndElement();
            }
        }
Ejemplo n.º 33
0
 // the global scope does nothing when told to add literals -- just returns null
 internal override List<ConstantWrapper> AddLiteral(ConstantWrapper constantWrapper, ActivationObject refScope)
 {
     return null;
 }
Ejemplo n.º 34
0
 internal CatchScope(ActivationObject parent, CodeSettings settings)
     : base(parent, settings, ScopeType.Catch)
 {
 }
Ejemplo n.º 35
0
        private Context m_context; // = null;

        #endregion Fields

        #region Constructors

        // not instantiated directly, only through derived classes
        protected BlockScope(ActivationObject parent, Context context, JSParser parser)
            : base(parent, parser)
        {
            m_context = (context == null ? new Context(parser) : context.Clone());
        }
Ejemplo n.º 36
0
 internal void AddReference(ActivationObject scope)
 {
     // make sure the hash is created
     if (m_refScopes == null)
     {
         m_refScopes = new Dictionary<ActivationObject, ActivationObject>();
     }
     // we don't want to include block scopes or with scopes -- they are really
     // contained within their parents
     while (scope != null && scope is BlockScope)
     {
         scope = scope.Parent;
     }
     if (scope != null && !m_refScopes.ContainsKey(scope))
     {
         // add the scope to the hash
         m_refScopes.Add(scope, scope);
     }
 }
Ejemplo n.º 37
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;
                }
            }
        }
Ejemplo n.º 38
0
        private void ProcessScope(ActivationObject scope)
        {
            switch (scope.ScopeType)
            {
            case ScopeType.Block:
            case ScopeType.Lexical:
            case ScopeType.None:
                // must be generic block scope
                m_writer.WriteStartElement("block");
                if (scope.UseStrict)
                {
                    m_writer.WriteAttributeString("strict", "true");
                }
                break;

            case ScopeType.Class:
                m_writer.WriteStartElement("class");
                if (!scope.ScopeName.IsNullOrWhiteSpace())
                {
                    m_writer.WriteAttributeString("src", scope.ScopeName);
                }

                if (scope.UseStrict)
                {
                    m_writer.WriteAttributeString("strict", "true");
                }
                break;

            case ScopeType.Catch:
                var catchScope = (CatchScope)scope;
                m_writer.WriteStartElement("catch");
                if (scope.UseStrict)
                {
                    m_writer.WriteAttributeString("strict", "true");
                }

                foreach (var bindingIdentifier in BindingsVisitor.Bindings(catchScope.CatchParameter))
                {
                    m_writer.WriteStartElement("catchvar");
                    m_writer.WriteAttributeString("src", bindingIdentifier.Name);

                    OutputContextPosition(bindingIdentifier.Context);

                    var catchVariable = bindingIdentifier.VariableField;
                    if (catchVariable != null)
                    {
                        if (catchVariable.CrunchedName != null)
                        {
                            m_writer.WriteAttributeString("min", catchVariable.CrunchedName);
                        }

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

                    m_writer.WriteEndElement();
                }
                break;

            case ScopeType.Module:
                m_writer.WriteStartElement("module");
                if (!scope.ScopeName.IsNullOrWhiteSpace())
                {
                    m_writer.WriteAttributeString("name", scope.ScopeName);
                }

                if (scope.UseStrict)
                {
                    m_writer.WriteAttributeString("strict", "true");
                }

                (scope as ModuleScope).IfNotNull(m =>
                {
                    m_writer.WriteAttributeString("default", m.HasDefaultExport ? "true" : "false");
                    if (m.IsNotComplete)
                    {
                        m_writer.WriteAttributeString("incomplete", "true");
                    }
                });
                break;

            case ScopeType.Function:
                var functionScope = (FunctionScope)scope;
                m_writer.WriteStartElement("function");

                // for source name, use the scope name
                if (!scope.ScopeName.IsNullOrWhiteSpace())
                {
                    m_writer.WriteAttributeString("src", scope.ScopeName);
                }

                var functionObject = functionScope.Owner as FunctionObject;
                if (functionObject != null)
                {
                    if (functionObject.Binding == null || functionObject.Binding.Name.IsNullOrWhiteSpace())
                    {
                        if (!functionObject.NameGuess.IsNullOrWhiteSpace())
                        {
                            // strip enclosing quotes
                            m_writer.WriteAttributeString("guess", functionObject.NameGuess.Trim('\"'));
                        }
                    }
                    else
                    {
                        if (functionObject.Binding.VariableField != null &&
                            functionObject.Binding.VariableField.CrunchedName != null)
                        {
                            m_writer.WriteAttributeString("min", functionObject.Binding.VariableField.CrunchedName);
                        }
                    }

                    m_writer.WriteAttributeString("type", functionObject.FunctionType.ToString().ToLowerInvariant());
                    OutputContextPosition(functionObject.Context);

                    if (m_useReferenceCounts &&
                        functionObject.Binding != null &&
                        functionObject.Binding.VariableField != null)
                    {
                        var refCount = functionObject.Binding.VariableField.RefCount;
                        m_writer.WriteAttributeString("refcount", refCount.ToStringInvariant());

                        if (refCount == 0 &&
                            functionObject.FunctionType == FunctionType.Declaration &&
                            functionObject.Binding.VariableField.FieldType == FieldType.Local)
                        {
                            // local function declaration with zero references? unreachable code!
                            m_writer.WriteAttributeString("unreachable", "true");
                        }
                    }

                    if (scope.UseStrict)
                    {
                        m_writer.WriteAttributeString("strict", "true");
                    }

                    // add the arguments
                    m_writer.WriteStartElement("arguments");
                    if (functionObject.ParameterDeclarations != null)
                    {
                        foreach (var bindingIdentifier in BindingsVisitor.Bindings(functionObject.ParameterDeclarations))
                        {
                            m_writer.WriteStartElement("argument");

                            m_writer.WriteAttributeString("src", bindingIdentifier.Name);
                            if (bindingIdentifier.VariableField.IfNotNull(v => v.CrunchedName != null))
                            {
                                m_writer.WriteAttributeString("min", bindingIdentifier.VariableField.CrunchedName);
                            }

                            OutputContextPosition(bindingIdentifier.Context);
                            if (m_useReferenceCounts)
                            {
                                bindingIdentifier.VariableField.IfNotNull(v => m_writer.WriteAttributeString("refcount", v.RefCount.ToStringInvariant()));
                            }

                            m_writer.WriteEndElement();
                        }
                    }

                    m_writer.WriteEndElement();
                }
                break;

            case ScopeType.Global:
                Debug.Assert(scope is GlobalScope);
                Debug.Fail("shouldn't get here!");
                m_writer.WriteStartElement("global");
                break;

            case ScopeType.With:
                Debug.Assert(scope is WithScope);
                m_writer.WriteStartElement("with");

                // with-scopes should never be strict because the with-statement is not allowed in strict code
                if (scope.UseStrict)
                {
                    m_writer.WriteAttributeString("strict", "true");
                }
                break;
            }

            // process the defined and referenced fields
            ProcessFields(scope);

            // recursively process each child scope
            foreach (var childScope in scope.ChildScopes)
            {
                ProcessScope(childScope);
            }

            // close the element
            m_writer.WriteEndElement();
        }