private static void ResolveGhostedCatchParameter(JsActivationObject scope, JsParameterDeclaration 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(JsFieldType.GhostCatch, catchParameter.Name, 0, null) { OriginalContext = catchParameter.Context }; scope.AddField(ghostField); } else if (ghostField.FieldType == JsFieldType.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. ghostField.IsAmbiguous = true; 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. catchParameter.Context.HandleError(JsError.AmbiguousCatchVar); } } // link them so they all keep the same name going forward // (since they are named the same in the sources) catchParameter.VariableField.OuterField = ghostField; // TODO: this really should be a LIST of ghosted fields, since multiple // elements can ghost to the same field. ghostField.GhostedField = catchParameter.VariableField; // if the actual field has references, we want to bubble those up // since we're now linking those fields if (catchParameter.VariableField.RefCount > 0) { // add the catch parameter's references to the ghost field ghostField.AddReferences(catchParameter.VariableField.References); } }
private static void ResolveGhostedFunctions(JsActivationObject scope, JsFunctionObject 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(JsFieldType.GhostFunction, funcObject.Name, 0, funcObject) { OriginalContext = functionField.OriginalContext, CanCrunch = funcObject.VariableField.IfNotNull(v => v.CanCrunch) }; scope.AddField(ghostField); } else if (ghostField.FieldType == JsFieldType.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. ghostField.IsAmbiguous = true; } 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 ghostField.IsFunction = true; 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 ghostField.IsAmbiguous = true; funcObject.IdContext.HandleError(JsError.AmbiguousNamedFunctionExpression); } else if (ghostField.IsReferenced) { // if the ghosted field isn't even referenced, then who cares? // but it is referenced. Let's see if it matters. // something like: var nm = function nm() {} // is TOTALLY cool common cross-browser syntax. var parentVarDecl = funcObject.Parent as JsVariableDeclaration; if (parentVarDecl == null || parentVarDecl.Name != funcObject.Name) { // see if it's a simple assignment. // something like: var nm; nm = function nm(){}, // would also be cool, although less-common than the vardecl version. JsLookup lookup; var parentAssignment = funcObject.Parent as JsBinaryOperator; if (parentAssignment == null || parentAssignment.OperatorToken != JsToken.Assign || parentAssignment.Operand2 != funcObject || (lookup = parentAssignment.Operand1 as JsLookup) == null || lookup.Name != funcObject.Name) { // something else. Flag it as ambiguous. ghostField.IsAmbiguous = true; } } } } // link them so they all keep the same name going forward // (since they are named the same in the sources) functionField.OuterField = ghostField; // TODO: this really should be a LIST of ghosted fields, since multiple // elements can ghost to the same field. ghostField.GhostedField = functionField; // if the actual field has references, we want to bubble those up // since we're now linking those fields if (functionField.RefCount > 0) { // add the function's references to the ghost field ghostField.AddReferences(functionField.References); } }
private static void ResolveGhostedCatchParameter(JsActivationObject scope, JsParameterDeclaration 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(JsFieldType.GhostCatch, catchParameter.Name, 0, null) { OriginalContext = catchParameter.Context }; scope.AddField(ghostField); } else if (ghostField.FieldType == JsFieldType.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. ghostField.IsAmbiguous = true; 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. catchParameter.Context.HandleError(JsError.AmbiguousCatchVar); } } // link them so they all keep the same name going forward // (since they are named the same in the sources) catchParameter.VariableField.OuterField = ghostField; // TODO: this really should be a LIST of ghosted fields, since multiple // elements can ghost to the same field. ghostField.GhostedField = catchParameter.VariableField; // if the actual field has references, we want to bubble those up // since we're now linking those fields if (catchParameter.VariableField.RefCount > 0) { // add the catch parameter's references to the ghost field ghostField.AddReferences(catchParameter.VariableField.References); } }
private static void ResolveGhostedFunctions(JsActivationObject scope, JsFunctionObject 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(JsFieldType.GhostFunction, funcObject.Name, 0, funcObject) { OriginalContext = functionField.OriginalContext, CanCrunch = funcObject.VariableField.IfNotNull(v => v.CanCrunch) }; scope.AddField(ghostField); } else if (ghostField.FieldType == JsFieldType.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. ghostField.IsAmbiguous = true; } 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 ghostField.IsFunction = true; 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 ghostField.IsAmbiguous = true; funcObject.IdContext.HandleError(JsError.AmbiguousNamedFunctionExpression); } else if (ghostField.IsReferenced) { // if the ghosted field isn't even referenced, then who cares? // but it is referenced. Let's see if it matters. // something like: var nm = function nm() {} // is TOTALLY cool common cross-browser syntax. var parentVarDecl = funcObject.Parent as JsVariableDeclaration; if (parentVarDecl == null || parentVarDecl.Name != funcObject.Name) { // see if it's a simple assignment. // something like: var nm; nm = function nm(){}, // would also be cool, although less-common than the vardecl version. JsLookup lookup; var parentAssignment = funcObject.Parent as JsBinaryOperator; if (parentAssignment == null || parentAssignment.OperatorToken != JsToken.Assign || parentAssignment.Operand2 != funcObject || (lookup = parentAssignment.Operand1 as JsLookup) == null || lookup.Name != funcObject.Name) { // something else. Flag it as ambiguous. ghostField.IsAmbiguous = true; } } } } // link them so they all keep the same name going forward // (since they are named the same in the sources) functionField.OuterField = ghostField; // TODO: this really should be a LIST of ghosted fields, since multiple // elements can ghost to the same field. ghostField.GhostedField = functionField; // if the actual field has references, we want to bubble those up // since we're now linking those fields if (functionField.RefCount > 0) { // add the function's references to the ghost field ghostField.AddReferences(functionField.References); } }