public override bool Walk(FunctionObject node) {
     // FunctionExpressions contain FunctionObjects.
     // Therefore we only need to handle FunctionObjects to handle both.
     if (node.Body.Braces != BraceState.StartAndEnd) {
         return false;
     }
     TagSpan span = GetFunctionSpan(_ast, _snapshot, node);
     OutliningTagSpans.Add(span);
     return base.Walk(node);
 }
Example #2
0
        internal FunctionScope(Statement node, ActivationObject parent, bool isExpression, FunctionObject funcObj, ErrorSink errorSink)
            : base(node, parent, errorSink)
        {
            m_refScopes = new HashSet<ActivationObject>();
            if (isExpression)
            {
                // parent scopes automatically reference enclosed function expressions
                AddReference(Parent);
            }

            FunctionObject = funcObj;
        }
        private bool WalkFunction(FunctionObject node, bool isExpression) {
            var functionAnalysis = AddFunction(node, _curUnit, isExpression);
            if (functionAnalysis != null) {
                _analysisStack.Push(_curUnit);
                _curUnit = functionAnalysis;
                Debug.Assert(_scope.EnumerateTowardsGlobal.Contains(functionAnalysis.Environment.Parent));
                _scope = functionAnalysis.Environment;
                return true;
            }

            return false;
        }
Example #4
0
        internal FunctionScope(Statement node, ActivationObject parent, bool isExpression, FunctionObject funcObj, ErrorSink errorSink)
            : base(node, parent, errorSink)
        {
            m_refScopes = new HashSet <ActivationObject>();
            if (isExpression)
            {
                // parent scopes automatically reference enclosed function expressions
                AddReference(Parent);
            }

            FunctionObject = funcObj;
        }
Example #5
0
        private void ResolveGhostedFunctions(ActivationObject scope, FunctionObject funcObject)
        {
            var functionField = funcObject.VariableField;

            // let's check on ghosted names in the outer variable scope
            var ghostField = scope[funcObject.Name];

            if (ghostField == null)
            {
                // nothing; good to go. Add a ghosted field to keep track of it.
                ghostField = new JSVariableField(FieldType.GhostFunction, funcObject.Name);

                scope.AddField(ghostField);
            }
            else if (ghostField.FieldType == FieldType.GhostFunction)
            {
                // there is, but it's another ghosted function expression.
                // what if a lookup is resolved to this field later? We probably still need to
                // at least flag it as ambiguous. We will only need to throw an error, though,
                // if someone actually references the outer ghost variable.
            }
            else
            {
                // something already exists. Could be a naming collision for IE or at least a
                // a cross-browser behavior difference if it's not coded properly.
                // mark this field as a function, even if it wasn't before

                if (ghostField.OuterField != null)
                {
                    // if the pre-existing field we are ghosting is a reference to
                    // an OUTER field, then we actually have a problem that creates a BIG
                    // difference between older IE browsers and everything else.
                    // modern browsers will have the link to the outer field, but older
                    // IE browsers will link to this function expression!
                    // fire a cross-browser error warning
                    _errorSink.HandleError(
                        JSError.AmbiguousNamedFunctionExpression,
                        funcObject.GetNameSpan(_locationResolver),
                        _locationResolver
                        );
                }
            }

            // link them so they all keep the same name going forward
            // (since they are named the same in the sources)
            functionField.OuterField = ghostField;
        }
        internal FunctionAnalysisUnit AddFunction(FunctionObject node, AnalysisUnit outerUnit, bool isExpression = false) {
            EnvironmentRecord scope;
            if (!_scope.GlobalEnvironment.TryGetNodeEnvironment(node, out scope)) {
                if (node.Body == null) {
                    return null;
                }

                IAnalysisSet functionObj;
                UserFunctionValue func = null;
                if (!_scope.GlobalEnvironment.TryGetNodeValue(NodeEnvironmentKind.UserFunctionValue, node, out functionObj)) {
                    func = CreateUserFunction(node, outerUnit);
                } else {
                    func = (UserFunctionValue)functionObj;
                }

                var funcScope = GetFunctionEnvironment(func);
                scope = funcScope;

                VariableDef[] parameters = new VariableDef[node.ParameterDeclarations != null ? node.ParameterDeclarations.Length : 0];
                for (int i = 0; i < parameters.Length; i++) {
                    parameters[i] = funcScope.AddLocatedVariable(
                        node.ParameterDeclarations[i].Name,
                        node.ParameterDeclarations[i],
                        _curUnit.ProjectEntry
                    );
                }

                _scope.Children.Add(scope);
                _scope.GlobalEnvironment.AddNodeEnvironment(node, scope);

                if (!isExpression && node.Name != null) {
                    // lambdas don't have their names published
                    var funcVar = _scope.AddLocatedVariable(node.Name, node, funcScope.AnalysisUnit);
                    funcVar.AddTypes(funcScope.AnalysisUnit, func.SelfSet);
                }

                funcScope.AnalysisUnit.Enqueue();
            }

            return ((FunctionEnvironmentRecord)scope).AnalysisUnit;
        }
 public override void PostWalk(FunctionObject node) {
     if (node.Body != null) {
         Debug.Assert(_scope is DeclarativeEnvironmentRecord && ((DeclarativeEnvironmentRecord)_scope).Node == node);
         Debug.Assert(!(_scope.Parent is DeclarativeEnvironmentRecord) || ((DeclarativeEnvironmentRecord)_scope.Parent).Node != node);
         _scope = _scope.Parent;
         _curUnit = _analysisStack.Pop();
         Debug.Assert(_scope.EnumerateTowardsGlobal.Contains(_curUnit.Environment));
     }
 }
            public override bool Walk(FunctionObject node) {
                IAnalysisSet value;
                EnvironmentRecord record;
                if (_scope.GlobalEnvironment.TryGetNodeEnvironment(node, out record) && 
                    _scope.GlobalEnvironment.TryGetNodeValue(NodeEnvironmentKind.UserFunctionValue, node, out value) &&
                    node.Name != null) {
                    if (node.IsExpression) {
                        // Only assign if the variable wasn't defined explicitly in the
                        // functions scope.
                        var varDef = record.GetVariable(node.Name);
                        if (varDef != null && varDef is LocatedVariableDef &&
                            ((LocatedVariableDef)varDef).Node == node) {
                            varDef.AddTypes(
                                _projectEntry,
                                value,
                                false
                            );
                        }
                    } else {
                        Debug.Assert(record.Parent.ContainsVariable(node.Name));
                        record.Parent.GetVariable(node.Name).AddTypes(
                            _projectEntry,
                            value,
                            false
                        );
                    }
                }

                return true;
            }
 public override bool IsMatch(FunctionObject node) {
     if (node.ParameterDeclarations != null &&
         node.ParameterDeclarations.Length >= 1) {
         var visitor = new CloneVisitor(node.ParameterDeclarations[0].VariableField);
         node.Walk(visitor);
         return visitor.ReturnsClonedVar;
     }
     return false;
 }
            public override bool IsMatch(FunctionObject node) {
                MatchState state = new MatchState(node);

                return Body.IsMatch(state, node.Body);
            }
 public MatchState(FunctionObject curFunction) {
     CurrentFunction = curFunction;
 }
 public SpecializedUserFunctionValue(CallDelegate call, FunctionObject node, AnalysisUnit declUnit, EnvironmentRecord declScope, bool callBase) :
     base(node, declUnit, declScope) {
     _call = call;
     _callBase = callBase;
 }
Example #13
0
 public override bool Walk(FunctionObject node) { AddNode(node, node.GetNameSpan(_tree.LocationResolver).Start, node.ParameterStart, node.ParameterEnd); return true; }
Example #14
0
        public override bool Walk(FunctionObject node)
        {
            if (node != null)
            {
                // create a function scope, assign it to the function object,
                // and push it on the stack
                var parentScope = CurrentLexicalScope;
                if (node.FunctionType == FunctionType.Expression &&
                    !string.IsNullOrEmpty(node.Name))
                {
                    // add this function object to the list of function objects the variable scope
                    // will need to ghost later
                    CurrentVariableScope.GhostedFunctions.Add(node);
                }

                SetScope(
                    node,
                    new FunctionScope(node, parentScope, node.FunctionType != FunctionType.Declaration, node, _errorSink)
                {
                    IsInWithScope = m_withDepth > 0
                }
                    );
                m_lexicalStack.Push(GetScope(node));
                m_variableStack.Push(GetScope(node));

                try
                {
                    // recurse into the function to handle it after saving the current index and resetting it
                    if (node.Body != null)
                    {
                        node.Body.Walk(this);
                    }
                }
                finally
                {
                    Debug.Assert(CurrentLexicalScope == GetScope(node));
                    m_lexicalStack.Pop();
                    m_variableStack.Pop();
                }

                // nothing to add to the var-decl list.
                // but add the function name to the current lex-decl list
                // IF it is a declaration and it has a name (and it SHOULD unless there was an error)
                if (node.FunctionType == FunctionType.Declaration &&
                    !string.IsNullOrEmpty(node.Name))
                {
                    var lexicalScope = CurrentLexicalScope;
                    lexicalScope.LexicallyDeclaredNames.Add(node);

                    if (lexicalScope != CurrentVariableScope)
                    {
                        // the current lexical scope is the variable scope.
                        // this is ES6 syntax: a function declaration inside a block scope. Not allowed
                        // in ES5 code, so throw a warning and ghost this function in the outer variable scope
                        // to make sure that we don't generate any naming collisions.
                        _errorSink.HandleError(JSError.MisplacedFunctionDeclaration, node.GetNameSpan(_locationResolver), _locationResolver);
                        CurrentVariableScope.GhostedFunctions.Add(node);
                    }
                }
            }
            return(false);
        }
        public override bool Walk(FunctionObject node)
        {
            if (node != null)
            {

                // create a function scope, assign it to the function object,
                // and push it on the stack
                var parentScope = CurrentLexicalScope;
                if (node.FunctionType == FunctionType.Expression 
                    && !string.IsNullOrEmpty(node.Name))
                {                    
                    // add this function object to the list of function objects the variable scope
                    // will need to ghost later
                    CurrentVariableScope.GhostedFunctions.Add(node);
                }

                SetScope(
                    node,
                    new FunctionScope(node, parentScope, node.FunctionType != FunctionType.Declaration, node, _errorSink)
                    {
                        IsInWithScope = m_withDepth > 0
                    }
                );
                m_lexicalStack.Push(GetScope(node));
                m_variableStack.Push(GetScope(node));

                try
                {
                    // recurse into the function to handle it after saving the current index and resetting it
                    if (node.Body != null)
                    {
                        node.Body.Walk(this);
                    }
                }
                finally
                {
                    Debug.Assert(CurrentLexicalScope == GetScope(node));
                    m_lexicalStack.Pop();
                    m_variableStack.Pop();
                }

                // nothing to add to the var-decl list.
                // but add the function name to the current lex-decl list
                // IF it is a declaration and it has a name (and it SHOULD unless there was an error)
                if (node.FunctionType == FunctionType.Declaration && 
                    !string.IsNullOrEmpty(node.Name))
                {
                    var lexicalScope = CurrentLexicalScope;
                    lexicalScope.LexicallyDeclaredNames.Add(node);

                    if (lexicalScope != CurrentVariableScope)
                    {
                        // the current lexical scope is the variable scope.
                        // this is ES6 syntax: a function declaration inside a block scope. Not allowed
                        // in ES5 code, so throw a warning and ghost this function in the outer variable scope 
                        // to make sure that we don't generate any naming collisions.
                        _errorSink.HandleError(JSError.MisplacedFunctionDeclaration, node.GetNameSpan(_locationResolver), _locationResolver);
                        CurrentVariableScope.GhostedFunctions.Add(node);
                    }
                }
            }
            return false;
        }
        private void ResolveGhostedFunctions(ActivationObject scope, FunctionObject funcObject)
        {
            var functionField = funcObject.VariableField;

            // let's check on ghosted names in the outer variable scope
            var ghostField = scope[funcObject.Name];
            if (ghostField == null)
            {
                // nothing; good to go. Add a ghosted field to keep track of it.
                ghostField = new JSVariableField(FieldType.GhostFunction, funcObject.Name);

                scope.AddField(ghostField);
            }
            else if (ghostField.FieldType == FieldType.GhostFunction)
            {
                // there is, but it's another ghosted function expression.
                // what if a lookup is resolved to this field later? We probably still need to
                // at least flag it as ambiguous. We will only need to throw an error, though,
                // if someone actually references the outer ghost variable. 
            }
            else
            {
                // something already exists. Could be a naming collision for IE or at least a
                // a cross-browser behavior difference if it's not coded properly.
                // mark this field as a function, even if it wasn't before

                if (ghostField.OuterField != null)
                {
                    // if the pre-existing field we are ghosting is a reference to
                    // an OUTER field, then we actually have a problem that creates a BIG
                    // difference between older IE browsers and everything else.
                    // modern browsers will have the link to the outer field, but older
                    // IE browsers will link to this function expression!
                    // fire a cross-browser error warning
                    _errorSink.HandleError(
                        JSError.AmbiguousNamedFunctionExpression,
                        funcObject.GetNameSpan(_locationResolver), 
                        _locationResolver
                    );
                }
            }

            // link them so they all keep the same name going forward
            // (since they are named the same in the sources)
            functionField.OuterField = ghostField;
        }
        private UserFunctionValue CreateUserFunction(FunctionObject node, AnalysisUnit outerUnit) {
            UserFunctionValue func = null;
            BaseSpecialization[] specializations;
            var funcName = node.Name ?? node.NameGuess;
            if (funcName != null &&
                _specializations.TryGetValue(funcName, out specializations)) {
                foreach (var specialization in specializations) {
                    if (specialization.IsMatch(node)) {
                        func = new SpecializedUserFunctionValue(
                            specialization.Specialization,
                            node,
                            outerUnit,
                            _scope,
                            specialization.CallBase
                        );
                        break;
                    }
                }
            }

            if (func == null) {
                func = new UserFunctionValue(node, outerUnit, _scope, _isNested);
            }

            _scope.GlobalEnvironment.AddNodeValue(NodeEnvironmentKind.UserFunctionValue, node, func.Proxy);
            return func;
        }
Example #18
0
        public override bool Walk(FunctionObject node) {
            if (node.IsGenerator) {
                ReplaceFollowingWhiteSpace(
                    node.GetStartIndex(_tree.LocationResolver) + "function".Length,
                    ""
                );
                if (node.Name != null) {
                    ReplaceFollowingWhiteSpace(
                        node.GeneratorIndex + "*".Length,
                        " "
                    );
                }
            } else if (node.Name == null) {
                ReplaceFollowingWhiteSpace(
                    node.GetStartIndex(_tree.LocationResolver) + "function".Length,
                    _options.SpaceAfterFunctionInAnonymousFunctions ? " " : ""
                );
            } else {
                ReplaceFollowingWhiteSpace(
                    node.GetNameSpan(_tree.LocationResolver).End,
                    ""
                );
            }

            if (node.ParameterDeclarations != null && node.ParameterDeclarations.Length > 0) {
                ReplaceFollowingWhiteSpace(
                    node.ParameterStart + 1,
                    _options.SpaceAfterOpeningAndBeforeClosingNonEmptyParenthesis ? " " : ""
                );

                for (int i = 1; i < node.ParameterDeclarations.Length; i++) {
                    ReplacePreceedingWhiteSpace(node.ParameterDeclarations[i].GetStartIndex(_tree.LocationResolver), _options.SpaceAfterComma ? " " : "", _comma);
                }

                ReplacePreceedingWhiteSpace(
                    node.ParameterEnd - 1,
                    _options.SpaceAfterOpeningAndBeforeClosingNonEmptyParenthesis ? " " : ""
                );
            } else {
                ReplaceFollowingWhiteSpace(
                    node.ParameterStart + 1,
                    ""
                );
            }

            if (!_onEnter) {
                ReplacePreceedingIncludingNewLines(
                    node.Body.GetStartIndex(_tree.LocationResolver),
                    GetFlowFunctionBraceInsertion(node.ParameterEnd, false, node.Body.GetStartIndex(_tree.LocationResolver)));
            }

            WalkBlock(node.Body);

            return false;
        }
 public override bool Walk(FunctionObject node) {
     return WalkFunction(node, false);
 }
 public abstract bool IsMatch(FunctionObject node);
 public MatchState(FunctionObject curFunction, MatchState outerState) {
     OuterState = outerState;
     _state = outerState._state;
     CurrentFunction = curFunction;
 }
Example #22
0
                private static TagSpan GetFunctionSpan(JsAst ast, ITextSnapshot snapshot, FunctionObject functionObject)
                {
                    IndexSpan indexSpan = functionObject.Body.GetSpan(ast.LocationResolver);

                    return(GetTagSpan(snapshot, indexSpan.Start, indexSpan.End, functionObject.ParameterEnd));
                }