Beispiel #1
0
        private static void GetFieldScopeType(JSVariableField variableField, ActivationObject immediateScope, out string scope, out string type)
        {
            JSLocalField      localField                 = variableField as JSLocalField;
            JSPredefinedField predefinedField            = variableField as JSPredefinedField;
            JSNamedFunctionExpressionField namedFuncExpr = variableField as JSNamedFunctionExpressionField;

            // default scope is blank
            scope = string.Empty;

            if (variableField is JSArgumentField)
            {
                type = StringMgr.GetString("MemberInfoTypeArgument");
            }
            else if (variableField is JSArgumentsField)
            {
                type = StringMgr.GetString("MemberInfoTypeArguments");
            }
            else if (predefinedField != null)
            {
                switch (predefinedField.GlobalObject)
                {
                case GlobalObjectInstance.GlobalObject:
                    scope = StringMgr.GetString("MemberInfoScopeGlobalObject");
                    break;

                case GlobalObjectInstance.WindowObject:
                    scope = StringMgr.GetString("MemberInfoScopeWindowObject");
                    break;

                case GlobalObjectInstance.Other:
                    scope = StringMgr.GetString("MemberInfoScopeOtherObject");
                    break;
                }
                switch (predefinedField.MemberType)
                {
                case MemberTypes.Method:
                    type = StringMgr.GetString("MemberInfoBuiltInMethod");
                    break;

                case MemberTypes.Property:
                    type = StringMgr.GetString("MemberInfoBuiltInProperty");
                    break;

                default:
                    type = StringMgr.GetString("MemberInfoBuiltInObject");
                    break;
                }
            }
            else if (variableField is JSGlobalField)
            {
                if ((variableField.Attributes & FieldAttributes.RTSpecialName) == FieldAttributes.RTSpecialName)
                {
                    // this is a special "global." It might not be a global, but something referenced
                    // in a with scope somewhere down the line.
                    type = StringMgr.GetString("MemberInfoPossiblyUndefined");
                }
                else if (variableField.FieldValue is FunctionObject)
                {
                    if (variableField.NamedFunctionExpression == null)
                    {
                        type = StringMgr.GetString("MemberInfoGlobalFunction");
                    }
                    else
                    {
                        type = StringMgr.GetString("MemberInfoFunctionExpression");
                    }
                }
                else
                {
                    type = StringMgr.GetString("MemberInfoGlobalVar");
                }
            }
            else if (variableField is JSWithField)
            {
                type = StringMgr.GetString("MemberInfoWithField");
            }
            else if (namedFuncExpr != null)
            {
                type = StringMgr.GetString("MemberInfoSelfFuncExpr");
            }
            else if (localField != null)
            {
                // type string
                if (localField.FieldValue is FunctionObject)
                {
                    if (localField.NamedFunctionExpression == null)
                    {
                        type = StringMgr.GetString("MemberInfoLocalFunction");
                    }
                    else
                    {
                        type = StringMgr.GetString("MemberInfoFunctionExpression");
                    }
                }
                else if (localField.IsLiteral)
                {
                    type = StringMgr.GetString("MemberInfoLocalLiteral");
                }
                else
                {
                    type = StringMgr.GetString("MemberInfoLocalVar");
                }

                // scope string
                // this is a local variable, so there MUST be a non-null function scope passed
                // to us. That function scope will be the scope we are expecting local variables
                // to be defined in. If the field is defined in that scope, it's local -- otherwise
                // it must be an outer variable.
                JSVariableField scopeField = immediateScope[variableField.Name];
                if (scopeField == null || scopeField.OuterField != null)
                {
                    scope = StringMgr.GetString("MemberInfoScopeOuter");
                }
                else
                {
                    scope = StringMgr.GetString("MemberInfoScopeLocal");
                }
            }
            else
            {
                type = StringMgr.GetString("MemberInfoBuiltInObject");
            }
        }
Beispiel #2
0
        private string NumericToString()
        {
            // numerics are doubles in JavaScript, so force it now as a shortcut
            double doubleValue = (double)Value;

            if (double.IsNaN(doubleValue) || double.IsInfinity(doubleValue))
            {
                // weird number -- just return the uncrunched source code as-is.
                // we've should have already thrown an error alerting the developer
                // to the overflow mistake, and it might alter the code to change the value
                if (this.Context != null && !string.IsNullOrEmpty(Context.Code) &&
                    string.CompareOrdinal(Context.Code, "[generated code]") != 0)
                {
                    return(Context.Code);
                }

                // Hmmm... don't have a context source.
                // Must be generated. Just generate the proper JS literal.
                //
                // DANGER! If we just output NaN and Infinity and -Infinity blindly, that assumes
                // that there aren't any local variables in this scope chain with that
                // name, and we're pulling the GLOBAL properties. Might want to use properties
                // on the Number object -- which, of course, assumes that Number doesn't
                // resolve to a local variable...
                string objectName = double.IsNaN(doubleValue) ? "NaN" : "Infinity";

                ActivationObject enclosingScope = EnclosingScope;
                if (!(enclosingScope is GlobalScope))
                {
                    JSPredefinedField globalReference = enclosingScope.FindReference(objectName) as JSPredefinedField;
                    if (globalReference == null)
                    {
                        // the name doesn't resolve to the global object properties! Must be a local field in the way!
                        // we can't assume the local field of this name contains the proper numeric value or we
                        // could get into big trouble.
                        // try the Number object
                        globalReference = enclosingScope.FindReference("Number") as JSPredefinedField;
                        if (globalReference != null)
                        {
                            // use the properties off this object. Not very compact, but accurate.
                            // I don't think there will be any precedence problems with these constructs --
                            // the member-dot operator is pretty high on the precedence scale.
                            if (double.IsPositiveInfinity(doubleValue))
                            {
                                return("Number.POSITIVE_INFINITY");
                            }
                            if (double.IsNegativeInfinity(doubleValue))
                            {
                                return("Number.NEGATIVE_INFINITY");
                            }
                            return("Number.NaN");
                        }
                        else
                        {
                            // that doesn't resolve to the global Number object, either!
                            // well, extreme circumstances. Let's use literals to generate those values.
                            if (double.IsPositiveInfinity(doubleValue))
                            {
                                // 1 divided by zero is +Infinity
                                return("(1/0)");
                            }
                            if (double.IsNegativeInfinity(doubleValue))
                            {
                                // 1 divided by negative zero is -Infinity
                                return("(1/-0)");
                            }
                            // the unary plus converts to a number, and "x" will generate NaN
                            return("(+'x')");
                        }
                    }
                }

                // we're good to go -- just return the name because it will resolve to the
                // global properties (make a special case for negative infinity)
                return(double.IsNegativeInfinity(doubleValue) ? "-Infinity" : objectName);
            }
            else if (doubleValue == 0)
            {
                // special case zero because we don't need to go through all those
                // gyrations to get a "0" -- and because negative zero is different
                // than a positive zero
                return(IsNegativeZero ? "-0" : "0");
            }
            else
            {
                // normal string representations
                string normal = GetSmallestRep(doubleValue.ToString("R", CultureInfo.InvariantCulture));

                // if this is an integer (no decimal portion)....
                if (Math.Floor(doubleValue) == doubleValue)
                {
                    // then convert to hex and see if it's smaller.
                    // only really big numbers might be smaller in hex.
                    string hex = NormalOrHexIfSmaller(doubleValue, normal);
                    if (hex.Length < normal.Length)
                    {
                        normal = hex;
                    }
                }
                return(normal);
            }
        }