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);
            }
        }