public override JSVariableField this[string name] { get { // check the name table JSVariableField variableField = base[name]; // not found so far, check the global properties if (variableField == null) { variableField = ResolveFromCollection(name, m_globalProperties, FieldType.Predefined); } // not found so far, check the global properties if (variableField == null) { variableField = ResolveFromCollection(name, m_globalFunctions, FieldType.Predefined); } // if not found so far, check to see if this value is provided in our "assumed" // global list specified on the command line if (variableField == null) { variableField = ResolveFromCollection(name, m_assumedGlobals, FieldType.Global); } return(variableField); } }
private void DefineField(ResolutionVisitor resolutionVisitor, INameDeclaration nameDecl) { if (nameDecl == null) { // malformed code, for example catch w/o a variable. return; } var field = this[nameDecl.Name]; if (nameDecl is ParameterDeclaration) { // function parameters are handled separately, so if this is a parameter declaration, // then it must be a catch variable. if (field == null) { // no collision - create the catch-error field field = new JSVariableField(FieldType.CatchError, nameDecl.Name); this.AddField(field); } else { // it's an error to declare anything in the catch scope with the same name as the // error variable ErrorSink.HandleError(JSError.DuplicateCatch, nameDecl.GetNameSpan(GlobalScope.Node.LocationResolver), resolutionVisitor._locationResolver, true); } } else { if (field == null) { // could be global or local depending on the scope, so let the scope create it. field = this.CreateField(nameDecl.Name); // if this field is a constant, mark it now var lexDeclaration = nameDecl.Parent as LexicalDeclaration; this.AddField(field); } else { // already defined! // if this is a lexical declaration, then it's an error because we have two // lexical declarations with the same name in the same scope. if (nameDecl.Parent is LexicalDeclaration) { _errorSink.HandleError( JSError.DuplicateLexicalDeclaration, nameDecl.GetNameSpan(GlobalScope.Node.LocationResolver), resolutionVisitor._locationResolver, true ); } } } nameDecl.VariableField = field; }
internal JSVariableField AddField(JSVariableField variableField) { // add it to our name table NameTable[variableField.Name] = variableField; // set the owning scope to this is we are the outer field, or the outer field's // owning scope if this is an inner field variableField.Scope = variableField.OuterField == null ? _node : variableField.OuterField.Scope; return(variableField); }
private JSVariableField ResolveFromCollection(string name, HashSet <string> collection, FieldType fieldType) { if (collection.Contains(name)) { var variableField = new JSVariableField(fieldType, name); return(AddField(variableField)); } return(null); }
internal JSVariableField(FieldType fieldType, JSVariableField outerField) { if (outerField == null) { throw new ArgumentNullException("outerField"); } // set values based on the outer field OuterField = outerField; Name = outerField.Name; }
public override JSVariableField CreateInnerField(JSVariableField outerField) { return outerField.IfNotNull(o => { // blindly create an inner reference field for with scopes, no matter what it // is. globals and predefined values can be hijacked by object properties in // this scope. var withField = AddField(CreateField(outerField)); return withField; }); }
public override JSVariableField CreateInnerField(JSVariableField outerField) { return(outerField.IfNotNull(o => { // blindly create an inner reference field for with scopes, no matter what it // is. globals and predefined values can be hijacked by object properties in // this scope. var withField = AddField(CreateField(outerField)); return withField; })); }
public virtual JSVariableField CreateInnerField(JSVariableField outerField) { JSVariableField innerField = null; if (outerField != null) { // create a new inner field to be added to our scope innerField = CreateField(outerField); AddField(innerField); } return(innerField); }
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 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 CloneVisitor(JSVariableField variable) { _clonedVar = variable; }
public void SetCatchVariable(JSVariableField field) { CatchParameter.VariableField = field; }
public override JSVariableField CreateField(JSVariableField outerField) { // when we create a field inside a with-scope, it's ALWAYS a with-field, no matter // what type the outer reference is. return new JSVariableField(FieldType.WithField, outerField); }
public override JSVariableField CreateField(JSVariableField outerField) { // should NEVER try to create an inner field in a global scope throw new NotImplementedException(); }
public virtual JSVariableField CreateInnerField(JSVariableField outerField) { JSVariableField innerField = null; if (outerField != null) { // create a new inner field to be added to our scope innerField = CreateField(outerField); AddField(innerField); } return innerField; }
public virtual JSVariableField CreateField(JSVariableField outerField) { // use the same type as the outer field by default return outerField.IfNotNull(o => new JSVariableField(o.FieldType, o)); }
public virtual JSVariableField CreateField(JSVariableField outerField) { // use the same type as the outer field by default return(outerField.IfNotNull(o => new JSVariableField(o.FieldType, o))); }
internal JSVariableField AddField(JSVariableField variableField) { // add it to our name table NameTable[variableField.Name] = variableField; // set the owning scope to this is we are the outer field, or the outer field's // owning scope if this is an inner field variableField.Scope = variableField.OuterField == null ? _node : variableField.OuterField.Scope; return variableField; }
private JSVariableField ResolveFromCollection(string name, HashSet<string> collection, FieldType fieldType) { if (collection.Contains(name)) { var variableField = new JSVariableField(fieldType, name); return AddField(variableField); } return null; }
public override JSVariableField CreateField(JSVariableField outerField) { // when we create a field inside a with-scope, it's ALWAYS a with-field, no matter // what type the outer reference is. return(new JSVariableField(FieldType.WithField, outerField)); }