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; }
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); } }
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; }
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 ); } }
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); } }
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 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 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); } }
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 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); } }
internal CatchScope(Statement node, ActivationObject parent, ParameterDeclaration catchParameter, ErrorSink errorSink) : base(node, parent, errorSink) { CatchParameter = catchParameter; }
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 ); } }
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); } }
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; }
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); } }
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; }
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); }