protected ActivationObject(Statement node, ActivationObject parent, ErrorSink errorSink) {
            _node = node;
            m_useStrict = false;

            Parent = parent;
            NameTable = new Dictionary<string, JSVariableField>();
            ChildScopes = new List<ActivationObject>();

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

                // if the parent is strict, so are we
                UseStrict = parent.UseStrict;
            }

            // create the two lists of declared items for this scope
            ScopeLookups = new HashSet<Lookup>();
            VarDeclaredNames = new HashSet<INameDeclaration>();
            LexicallyDeclaredNames = new HashSet<INameDeclaration>();

            GhostedCatchParameters = new HashSet<ParameterDeclaration>();
            GhostedFunctions = new HashSet<FunctionObject>();

            _errorSink = errorSink;
        }
Beispiel #2
0
        protected ActivationObject(Statement node, ActivationObject parent, ErrorSink errorSink)
        {
            _node       = node;
            m_useStrict = false;

            Parent      = parent;
            NameTable   = new Dictionary <string, JSVariableField>();
            ChildScopes = new List <ActivationObject>();

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

                // if the parent is strict, so are we
                UseStrict = parent.UseStrict;
            }

            // create the two lists of declared items for this scope
            ScopeLookups           = new HashSet <Lookup>();
            VarDeclaredNames       = new HashSet <INameDeclaration>();
            LexicallyDeclaredNames = new HashSet <INameDeclaration>();

            GhostedCatchParameters = new HashSet <ParameterDeclaration>();
            GhostedFunctions       = new HashSet <FunctionObject>();

            _errorSink = errorSink;
        }
        private ResolutionVisitor(ActivationObject rootScope, LocationResolver indexResolver, ErrorSink errorSink) {
            // create the lexical and variable scope stacks and push the root scope onto them
            m_lexicalStack = new Stack<ActivationObject>();
            m_lexicalStack.Push(rootScope);

            m_variableStack = new Stack<ActivationObject>();
            m_variableStack.Push(rootScope);

            _locationResolver = indexResolver;
            _errorSink = errorSink;
        }
        private void CreateFields(ActivationObject scope)
        {
            // declare this scope
            scope.DeclareScope(this);

            // and recurse
            foreach (var childScope in scope.ChildScopes)
            {
                CreateFields(childScope);
            }
        }
Beispiel #5
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;
        }
Beispiel #6
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 ResolutionVisitor(ActivationObject rootScope, LocationResolver indexResolver, ErrorSink errorSink)
        {
            // create the lexical and variable scope stacks and push the root scope onto them
            m_lexicalStack = new Stack <ActivationObject>();
            m_lexicalStack.Push(rootScope);

            m_variableStack = new Stack <ActivationObject>();
            m_variableStack.Push(rootScope);

            _locationResolver = indexResolver;
            _errorSink        = errorSink;
        }
        private static void CollapseBlockScope(ActivationObject blockScope)
        {
            // copy over the stuff we want to carry over to the parent
            blockScope.ScopeLookups.CopyItemsTo(blockScope.Parent.ScopeLookups);
            blockScope.VarDeclaredNames.CopyItemsTo(blockScope.Parent.VarDeclaredNames);
            blockScope.ChildScopes.CopyItemsTo(blockScope.Parent.ChildScopes);
            blockScope.GhostedCatchParameters.CopyItemsTo(blockScope.Parent.GhostedCatchParameters);
            blockScope.GhostedFunctions.CopyItemsTo(blockScope.Parent.GhostedFunctions);

            // remove it from its parent's collection of child scopes
            blockScope.Parent.ChildScopes.Remove(blockScope);
        }
 private void ResolveLookup(ActivationObject scope, Lookup lookup)
 {
     // resolve lookup via the lexical scope
     lookup.VariableField = scope.FindReference(lookup.Name);
     if (lookup.VariableField.FieldType == FieldType.UndefinedGlobal)
     {
         _errorSink.HandleUndeclaredVariable(
             lookup.Name,
             lookup.GetSpan(_locationResolver),
             _locationResolver
             );
     }
 }
Beispiel #10
0
        private void ResolveLookups(ActivationObject scope)
        {
            // resolve each lookup this scope contains
            foreach (var lookup in scope.ScopeLookups)
            {
                ResolveLookup(scope, lookup);
            }

            // and recurse
            foreach (var childScope in scope.ChildScopes)
            {
                ResolveLookups(childScope);
            }
        }
Beispiel #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);
            }
        }
Beispiel #12
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;
        }
Beispiel #13
0
        private void AddGhostedFields(ActivationObject scope)
        {
            foreach (var catchParameter in scope.GhostedCatchParameters)
            {
                ResolveGhostedCatchParameter(scope, catchParameter);
            }

            foreach (var ghostFunc in scope.GhostedFunctions)
            {
                ResolveGhostedFunctions(scope, ghostFunc);
            }

            // recurse
            foreach (var childScope in scope.ChildScopes)
            {
                AddGhostedFields(childScope);
            }
        }
Beispiel #14
0
        private void ResolveGhostedCatchParameter(ActivationObject scope, ParameterDeclaration catchParameter)
        {
            // check to see if the name exists in the outer variable scope.
            var ghostField = scope[catchParameter.Name];

            if (ghostField == null)
            {
                // set up a ghost field to keep track of the relationship
                ghostField = new JSVariableField(FieldType.GhostCatch, catchParameter.Name);

                scope.AddField(ghostField);
            }
            else if (ghostField.FieldType == FieldType.GhostCatch)
            {
                // there is, but it's another ghost catch variable. That's fine; just use it.
                // don't even flag it as ambiguous because if someone is later referencing the error variable
                // used in a couple catch variables, we'll say something then because other browsers will have that
                // variable undefined or from an outer scope.
            }
            else
            {
                // there is, and it's NOT another ghosted catch variable. Possible naming
                // collision in IE -- if an error happens, it will clobber the existing field's value,
                // although that MAY be the intention; we don't know for sure. But it IS a cross-
                // browser behavior difference.

                if (ghostField.OuterField != null)
                {
                    // and to make matters worse, it's actually bound to an OUTER field
                    // in modern browsers, but will bind to this catch variable in older
                    // versions of IE! Definitely a cross-browser difference!
                    // throw a cross-browser issue error.
                    _errorSink.HandleError(JSError.AmbiguousCatchVar, catchParameter.GetSpan(_locationResolver), _locationResolver);
                }
            }

            // link them so they all keep the same name going forward
            // (since they are named the same in the sources)
            catchParameter.VariableField.OuterField = ghostField;
        }
Beispiel #15
0
        public static void Apply(Node node, ActivationObject scope, LocationResolver indexResolver, ErrorSink errorSink)
        {
            if (node != null && scope != null)
            {
                // create the visitor and run it. This will create all the child
                // scopes and populate all the scopes with the var-decl, lex-decl,
                // and lookup references within them.
                var visitor = new ResolutionVisitor(scope, indexResolver, errorSink);
                node.Walk(visitor);

                // now that all the scopes are created and they all know what decls
                // they contains, create all the fields
                visitor.CreateFields(scope);

                // now that all the fields have been created in all the scopes,
                // let's go through and resolve all the references
                visitor.ResolveLookups(scope);

                // now that everything is declared and resolved as per the language specs,
                // we need to go back and add ghosted fields for older versions of IE that
                // incorrectly implement catch-variables and named function expressions.
                visitor.AddGhostedFields(scope);
            }
        }
        public static void Apply(Node node, ActivationObject scope, LocationResolver indexResolver, ErrorSink errorSink)
        {
            if (node != null && scope != null)
            {
                // create the visitor and run it. This will create all the child
                // scopes and populate all the scopes with the var-decl, lex-decl,
                // and lookup references within them.
                var visitor = new ResolutionVisitor(scope, indexResolver, errorSink);
                node.Walk(visitor);

                // now that all the scopes are created and they all know what decls
                // they contains, create all the fields
                visitor.CreateFields(scope);

                // now that all the fields have been created in all the scopes,
                // let's go through and resolve all the references
                visitor.ResolveLookups(scope);

                // now that everything is declared and resolved as per the language specs,
                // we need to go back and add ghosted fields for older versions of IE that
                // incorrectly implement catch-variables and named function expressions.
                visitor.AddGhostedFields(scope);
            }
        }
Beispiel #17
0
 internal CatchScope(Statement node, ActivationObject parent, ParameterDeclaration catchParameter, ErrorSink errorSink)
     : base(node, parent, errorSink)
 {
     CatchParameter = catchParameter;
 }
Beispiel #18
0
 public BlockScope(Statement node, ActivationObject parent, ErrorSink errorSink)
     : base(node, parent, errorSink)
 {
 }
        private void ResolveLookups(ActivationObject scope)
        {
            // resolve each lookup this scope contains
            foreach (var lookup in scope.ScopeLookups)
            {
                ResolveLookup(scope, lookup);
            }

            // and recurse
            foreach (var childScope in scope.ChildScopes)
            {
                ResolveLookups(childScope);
            }
        }
 private void ResolveLookup(ActivationObject scope, Lookup lookup)
 {
     // resolve lookup via the lexical scope
     lookup.VariableField = scope.FindReference(lookup.Name);
     if (lookup.VariableField.FieldType == FieldType.UndefinedGlobal)
     {
         
             _errorSink.HandleUndeclaredVariable(
                 lookup.Name,
                 lookup.GetSpan(_locationResolver),
                 _locationResolver
             );
             
     }
 }
Beispiel #21
0
 private void SetScope(Node node, ActivationObject scope)
 {
     _scopes[node] = scope;
 }
        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 void CreateFields(ActivationObject scope)
        {
            // declare this scope
            scope.DeclareScope(this);

            // and recurse
            foreach (var childScope in scope.ChildScopes)
            {
                CreateFields(childScope);
            }
        }
Beispiel #24
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);
            }
        }
        private void ResolveGhostedCatchParameter(ActivationObject scope, ParameterDeclaration catchParameter)
        {
            // check to see if the name exists in the outer variable scope.
            var ghostField = scope[catchParameter.Name];
            if (ghostField == null)
            {
                // set up a ghost field to keep track of the relationship
                ghostField = new JSVariableField(FieldType.GhostCatch, catchParameter.Name);

                scope.AddField(ghostField);
            }
            else if (ghostField.FieldType == FieldType.GhostCatch)
            {
                // there is, but it's another ghost catch variable. That's fine; just use it.
                // don't even flag it as ambiguous because if someone is later referencing the error variable
                // used in a couple catch variables, we'll say something then because other browsers will have that
                // variable undefined or from an outer scope.
            }
            else
            {
                // there is, and it's NOT another ghosted catch variable. Possible naming
                // collision in IE -- if an error happens, it will clobber the existing field's value,
                // although that MAY be the intention; we don't know for sure. But it IS a cross-
                // browser behavior difference.

                if (ghostField.OuterField != null)
                {
                    // and to make matters worse, it's actually bound to an OUTER field
                    // in modern browsers, but will bind to this catch variable in older
                    // versions of IE! Definitely a cross-browser difference!
                    // throw a cross-browser issue error.
                    _errorSink.HandleError(JSError.AmbiguousCatchVar, catchParameter.GetSpan(_locationResolver), _locationResolver);
                }
            }

            // link them so they all keep the same name going forward
            // (since they are named the same in the sources)
            catchParameter.VariableField.OuterField = ghostField;
        }
 public WithScope(Statement node, ActivationObject parent, ErrorSink errorSink)
     : base(node, parent, errorSink)
 {
     IsInWithScope = true;
 }
Beispiel #27
0
 public BlockScope(Statement node, ActivationObject parent, ErrorSink errorSink)
     : base(node, parent, errorSink)
 {
 }
        private void AddGhostedFields(ActivationObject scope)
        {
            foreach (var catchParameter in scope.GhostedCatchParameters)
            {
                ResolveGhostedCatchParameter(scope, catchParameter);
            }

            foreach (var ghostFunc in scope.GhostedFunctions)
            {
                ResolveGhostedFunctions(scope, ghostFunc);
            }

            // recurse
            foreach (var childScope in scope.ChildScopes)
            {
                AddGhostedFields(childScope);
            }
        }
Beispiel #29
0
 internal CatchScope(Statement node, ActivationObject parent, ParameterDeclaration catchParameter, ErrorSink errorSink)
     : base(node, parent, errorSink)
 {
     CatchParameter = catchParameter;
 }
 private void SetScope(Node node, ActivationObject scope) {
     _scopes[node] = scope;
 }
Beispiel #31
0
 public WithScope(Statement node, ActivationObject parent, ErrorSink errorSink)
     : base(node, parent, errorSink)
 {
     IsInWithScope = true;
 }
        private static void CollapseBlockScope(ActivationObject blockScope)
        {
            // copy over the stuff we want to carry over to the parent
            blockScope.ScopeLookups.CopyItemsTo(blockScope.Parent.ScopeLookups);
            blockScope.VarDeclaredNames.CopyItemsTo(blockScope.Parent.VarDeclaredNames);
            blockScope.ChildScopes.CopyItemsTo(blockScope.Parent.ChildScopes);
            blockScope.GhostedCatchParameters.CopyItemsTo(blockScope.Parent.GhostedCatchParameters);
            blockScope.GhostedFunctions.CopyItemsTo(blockScope.Parent.GhostedFunctions);

            // remove it from its parent's collection of child scopes
            blockScope.Parent.ChildScopes.Remove(blockScope);
        }