Esempio n. 1
0
 public void Visit(FunctionObject node)
 {
     // recurse the function binding
     if (node != null && node.Binding != null)
     {
         node.Binding.Accept(this);
     }
 }
Esempio n. 2
0
 public void Visit(FunctionObject node)
 {
     // if this is an arrow function, then we're good to go. Otherwise
     // this shouldn't be called for anything but a function expression,
     // which is definitely NOT safe to start a statement off because it would
     // then be interpreted as a function *declaration*.
     m_isSafe = node.IfNotNull(n => n.FunctionType == FunctionType.ArrowFunction);
 }
        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;
        }
        public override void Visit(FunctionObject node)
        {
            if (node != null)
            {
                // if we are reordering ANYTHING, then we need to do the reordering on a scope level.
                // so if that's the case, we need to create a list of all the child functions and NOT
                // recurse at this point. Then we'll reorder, then we'll use the lists to recurse.
                // BUT if we are not reordering anything, no sense making the lists and recursing later.
                // if that's the case, we can just recurse now and not have to worry about anything later.
                if (m_moveVarStatements || m_moveFunctionDecls)
                {
                    // add the node to the appropriate list: either function expression or function declaration.
                    // assume if it's not a function declaration, it must be an expression since the other types
                    // are not declaration (getter, setter) and we want to treat declarations special.
                    // if the conditional comment level isn't zero, then something funky is going on with
                    // the conditional-compilation statements, and we don't want to move the declarations, so
                    // don't add them to the declaration list. But we still want to recurse them, so add them
                    // to the expression list (which get recursed but not moved).
                    if (node.FunctionType == FunctionType.Declaration && m_conditionalCommentLevel == 0)
                    {
                        if (m_functionDeclarations == null)
                        {
                            m_functionDeclarations = new List <FunctionObject>();
                        }

                        m_functionDeclarations.Add(node);
                    }
                    else
                    {
                        if (m_functionExpressions == null)
                        {
                            m_functionExpressions = new List <FunctionObject>();
                        }

                        m_functionExpressions.Add(node);
                    }

                    // BUT DO NOT RECURSE!!!!
                    // we only want the functions and variables in THIS scope, not child function scopes.
                    //base.Visit(node);
                }
                else
                {
                    // we're not reordering, so just recurse now to save the hassle
                    base.Visit(node);
                }
            }
        }
Esempio n. 5
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);
                }
            }
        }
Esempio n. 6
0
 public void Visit(FunctionObject node)
 {
     if (node != null)
     {
         // if this is an arrow function with a single statement in the block that isn't a return statement,
         // then we need to ask the block statement if it requires a separator.
         if (node.FunctionType == FunctionType.ArrowFunction
             && node.Body.IfNotNull(b => b.Count == 1 && !(b[0] is ReturnNode)))
         {
             node.Body[0].Accept(this);
         }
         else
         {
             DoesRequire = false;
         }
     }
 }
 public void Visit(FunctionObject node)
 {
     // we're good
 }
Esempio n. 8
0
        private static int RelocateFunction(Block block, int insertAt, FunctionObject funcDecl)
        {
            if (block[insertAt] != funcDecl)
            {
                // technically function declarations can only be direct children of the program or a function block.
                // and since we are passing in such a block, the parent of the function declaration better be that
                // block. If it isn't, we don't want to move it because it's not in an allowed place, and different
                // browsers treat that situation differently. Some browsers would process such funcdecls as if
                // they were a direct child of the main block. Others will treat it like a function expression with
                // an external name, and only assign the function to the name if that line of code is actually
                // executed. So since there's a difference, just leave them as-is and only move valid funcdecls.
                if (funcDecl.Parent == block && !InsideConditionalComment(funcDecl))
                {
                    // remove the function from it's parent, which will take it away from where it is right now.
                    funcDecl.Parent.ReplaceChild(funcDecl, null);

                    // now insert it into the block at the new location, incrementing the location so the next function
                    // will be inserted after it. It is important that they be in the same order as the source, or the semantics
                    // will change when there are functions with the same name.
                    block.Insert(insertAt++, funcDecl);
                }
            }
            else
            {
                // we're already in the right place. Just increment the pointer to move to the next position
                // for next time
                ++insertAt;
            }

            // return the new position
            return insertAt;
        }
Esempio n. 9
0
        public override void Visit(FunctionObject node)
        {
            if (node != null)
            {
                // if we are reordering ANYTHING, then we need to do the reordering on a scope level.
                // so if that's the case, we need to create a list of all the child functions and NOT
                // recurse at this point. Then we'll reorder, then we'll use the lists to recurse.
                // BUT if we are not reordering anything, no sense making the lists and recursing later.
                // if that's the case, we can just recurse now and not have to worry about anything later.
                if (m_moveVarStatements || m_moveFunctionDecls)
                {
                    // add the node to the appropriate list: either function expression or function declaration.
                    // assume if it's not a function declaration, it must be an expression since the other types
                    // are not declaration (getter, setter) and we want to treat declarations special.
                    if (node.FunctionType == FunctionType.Declaration)
                    {
                        if (m_functionDeclarations == null)
                        {
                            m_functionDeclarations = new List<FunctionObject>();
                        }

                        m_functionDeclarations.Add(node);
                    }
                    else
                    {
                        if (m_functionExpressions == null)
                        {
                            m_functionExpressions = new List<FunctionObject>();
                        }

                        m_functionExpressions.Add(node);
                    }

                    // BUT DO NOT RECURSE!!!!
                    // we only want the functions and variables in THIS scope, not child function scopes.
                    //base.Visit(node);
                }
                else
                {
                    // we're not reordering, so just recurse now to save the hassle
                    base.Visit(node);
                }
            }
        }
Esempio n. 10
0
 private static string GetPropertyType(FunctionObject funcObj)
 {
     // should never be a function declaration....
     return funcObj == null || funcObj.FunctionType == FunctionType.Expression
         ? "data"
         : funcObj.FunctionType == FunctionType.Getter ? "get" : "set";
 }
Esempio n. 11
0
        public override void Visit(FunctionObject node)
        {
            if (node != null)
            {
                // get the name of this function, calculate something if it's anonymous
                if (node.Identifier == null)
                {
                    node.Name = GuessAtName(node);
                }

                // don't analyze the identifier or we'll add an extra reference to it.
                // and we don't need to analyze the parameters because they were fielded-up
                // back when the function object was created, too

                if (ScopeStack.Peek().UseStrict)
                {
                    // we need to make sure the function isn't named "eval" or "arguments"
                    if (string.CompareOrdinal(node.Name, "eval") == 0
                        || string.CompareOrdinal(node.Name, "arguments") == 0)
                    {
                        if (node.IdContext != null)
                        {
                            node.IdContext.HandleError(JSError.StrictModeFunctionName, true);
                        }
                        else if (node.Context != null)
                        {
                            node.Context.HandleError(JSError.StrictModeFunctionName, true);
                        }
                    }

                    // we need to make sure:
                    //  1. there are no duplicate argument names, and
                    //  2. none of them are named "eval" or "arguments"
                    // create map that we'll use to determine if there are any dups
                    if (node.ParameterDeclarations != null
                        && node.ParameterDeclarations.Count > 0)
                    {
                        var parameterMap = new Dictionary<string, string>(node.ParameterDeclarations.Count);
                        foreach (var parameter in node.ParameterDeclarations)
                        {
                            // if it already exists in the map, then it's a dup
                            if (parameterMap.ContainsKey(parameter.Name))
                            {
                                // already exists -- throw an error
                                parameter.Context.HandleError(JSError.StrictModeDuplicateArgument, true);
                            }
                            else
                            {
                                // not in there, add it now
                                parameterMap.Add(parameter.Name, parameter.Name);

                                // now check to see if it's one of the two forbidden names
                                if (string.CompareOrdinal(parameter.Name, "eval") == 0
                                    || string.CompareOrdinal(parameter.Name, "arguments") == 0)
                                {
                                    parameter.Context.HandleError(JSError.StrictModeArgumentName, true);
                                }
                            }
                        }
                    }
                }
                else if (node.ParameterDeclarations != null
                    && node.ParameterDeclarations.Count > 0)
                {
                    // not strict
                    // if there are duplicate parameter names, throw a warning
                    var parameterMap = new Dictionary<string, string>(node.ParameterDeclarations.Count);
                    foreach (var parameter in node.ParameterDeclarations)
                    {
                        // if it already exists in the map, then it's a dup
                        if (parameterMap.ContainsKey(parameter.Name))
                        {
                            // already exists -- throw an error
                            parameter.Context.HandleError(JSError.DuplicateName, false);
                        }
                        else
                        {
                            // not in there, add it now
                            parameterMap.Add(parameter.Name, parameter.Name);
                        }
                    }
                }

                // push the stack and analyze the body
                ScopeStack.Push(node.FunctionScope);
                try
                {
                    // recurse the body
                    node.Body.Accept(this);
                }
                finally
                {
                    ScopeStack.Pop();
                }
            }
        }
Esempio n. 12
0
        //TYPE "NAME" - Starts at line LINE, col COLUMN STATUS [crunched to CRUNCH]
        //
        //TYPE: Function, Function getter, Function setter
        //STATUS: '', Unknown, Unreachable
        private void WriteFunctionHeader(FunctionObject funcObj, bool isKnown)
        {
            // get the crunched value (if any)
            string       crunched   = string.Empty;
            JSLocalField localField = funcObj.LocalField as JSLocalField;

            if (localField != null && localField.CrunchedName != null)
            {
                crunched = StringMgr.GetString("CrunchedTo", localField.CrunchedName, localField.RefCount);
            }

            // get the status if the function
            StringBuilder statusBuilder = new StringBuilder();

            if (!isKnown)
            {
                statusBuilder.Append('[');
                statusBuilder.Append(StringMgr.GetString("NotKnown"));
            }
            if (funcObj.FunctionScope.Parent is GlobalScope)
            {
                // global function.
                // if this is a named function expression, we still want to know if it's
                // referenced by anyone
                if (funcObj.FunctionType == FunctionType.Expression &&
                    !string.IsNullOrEmpty(funcObj.Name))
                {
                    // output a comma separator if not the first item, otherwise
                    // open the square bracket
                    if (statusBuilder.Length > 0)
                    {
                        statusBuilder.Append(", ");
                    }
                    else
                    {
                        statusBuilder.Append('[');
                    }
                    statusBuilder.Append(StringMgr.GetString(
                                             "FunctionInfoReferences",
                                             funcObj.RefCount
                                             ));
                }
            }
            else if (!funcObj.FunctionScope.IsReferenced(null))
            {
                // local function that isn't referenced -- unreachable!
                // output a comma separator if not the first item, otherwise
                // open the square bracket
                if (statusBuilder.Length > 0)
                {
                    statusBuilder.Append(", ");
                }
                else
                {
                    statusBuilder.Append('[');
                }
                statusBuilder.Append(StringMgr.GetString("Unreachable"));
            }
            if (statusBuilder.Length > 0)
            {
                statusBuilder.Append(']');
            }
            string status = statusBuilder.ToString();

            string functionType;

            switch (funcObj.FunctionType)
            {
            case FunctionType.Getter:
                functionType = "FunctionTypePropGet";
                break;

            case FunctionType.Setter:
                functionType = "FunctionTypePropSet";
                break;

            case FunctionType.Expression:
                functionType = "FunctionTypeExpression";
                break;

            default:
                functionType = "FunctionTypeFunction";
                break;
            }

            // output
            WriteProgress();
            WriteProgress(StringMgr.GetString(
                              "FunctionHeader",
                              StringMgr.GetString(functionType),
                              funcObj.Name,
                              funcObj.Context.StartLineNumber,
                              funcObj.Context.StartColumn,
                              status,
                              crunched
                              ));
        }
 public void Visit(FunctionObject node)
 {
     // invalid! ignore
     IsValid = false;
 }
Esempio n. 14
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;
            }
        }
Esempio n. 15
0
        //TYPE "NAME" - Starts at line LINE, col COLUMN STATUS [crunched to CRUNCH]
        //
        //TYPE: Function, Function getter, Function setter
        //STATUS: '', Unknown, Unreachable
        private void WriteFunctionHeader(FunctionObject funcObj, bool isKnown, bool useStrict)
        {
            // get the crunched value (if any)
            string crunched      = string.Empty;
            var    functionField = funcObj.Binding.IfNotNull(b => b.VariableField);

            if (functionField != null && functionField.CrunchedName != null)
            {
                crunched = AjaxMin.CrunchedTo.FormatInvariant(functionField.CrunchedName, functionField.RefCount);
            }

            // get the status if the function
            string status        = null;
            var    statusBuilder = StringBuilderPool.Acquire();

            try
            {
                if (!isKnown)
                {
                    statusBuilder.Append('[');
                    statusBuilder.Append(AjaxMin.NotKnown);
                }
                if (funcObj.EnclosingScope.Parent is GlobalScope)
                {
                    // global function.
                    // if this is a named function expression, we still want to know if it's
                    // referenced by anyone
                    if (funcObj.FunctionType == FunctionType.Expression &&
                        funcObj.Binding != null &&
                        !funcObj.Binding.Name.IsNullOrWhiteSpace())
                    {
                        // output a comma separator if not the first item, otherwise
                        // open the square bracket
                        if (statusBuilder.Length > 0)
                        {
                            statusBuilder.Append(", ");
                        }
                        else
                        {
                            statusBuilder.Append('[');
                        }
                        statusBuilder.Append(AjaxMin.FunctionInfoReferences.FormatInvariant(
                                                 funcObj.Binding.VariableField.IfNotNull(v => v.RefCount)
                                                 ));
                    }
                }
                else if (!funcObj.IsReferenced && m_useReferenceCounts)
                {
                    // local function that isn't referenced -- unreachable!
                    // output a comma separator if not the first item, otherwise
                    // open the square bracket
                    if (statusBuilder.Length > 0)
                    {
                        statusBuilder.Append(", ");
                    }
                    else
                    {
                        statusBuilder.Append('[');
                    }

                    statusBuilder.Append(AjaxMin.Unreachable);
                }

                if (statusBuilder.Length > 0)
                {
                    statusBuilder.Append(']');
                }

                if (useStrict)
                {
                    statusBuilder.Append(AjaxMin.ScopeIsStrictFlag);
                }

                status = statusBuilder.ToString();
            }
            finally
            {
                statusBuilder.Release();
            }

            string functionType;

            switch (funcObj.FunctionType)
            {
            case FunctionType.Getter:
                functionType = AjaxMin.FunctionTypePropGet;
                break;

            case FunctionType.Setter:
                functionType = AjaxMin.FunctionTypePropSet;
                break;

            case FunctionType.Expression:
                functionType = AjaxMin.FunctionTypeExpression;
                break;

            case FunctionType.ArrowFunction:
                functionType = AjaxMin.FunctionTypeArrow;
                break;

            case FunctionType.Method:
                functionType = AjaxMin.FunctionTypeMethod;
                break;

            default:
                functionType = AjaxMin.FunctionTypeFunction;
                break;
            }

            var functionName = funcObj.Binding.IfNotNull(b => b.Name);

            if (functionName.IsNullOrWhiteSpace())
            {
                functionName = !funcObj.NameGuess.IsNullOrWhiteSpace()
                    ? '"' + funcObj.NameGuess + '"'
                    : AjaxMin.AnonymousName;
            }

            // output
            WriteProgress();
            WriteProgress(AjaxMin.FunctionHeader.FormatInvariant(
                              functionType,
                              functionName,
                              funcObj.Context.StartLineNumber,
                              funcObj.Context.StartColumn + 1,
                              status,
                              crunched,
                              funcObj.IsGenerator ? AjaxMin.FunctionTypeGenerator : string.Empty));
        }