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