// Convert an object into a primitive value. internal static Object ToPrimitive(Object value, DefaultValueHint hint) { if (value is ScriptObject) { // Let the object handle conversion for JScript objects. return(((ScriptObject)value).DefaultValue(hint)); } else { // Handle non-JScript objects. switch (hint) { case DefaultValueHint.None: { switch (Support.TypeCodeForObject(value)) { case TypeCode.SByte: case TypeCode.Byte: case TypeCode.Int16: case TypeCode.UInt16: case TypeCode.Int32: case TypeCode.UInt32: case TypeCode.Int64: case TypeCode.UInt64: case TypeCode.Single: case TypeCode.Double: case TypeCode.Decimal: { value = ToNumber(value); } break; default: { value = ToString(value); } break; } } break; case DefaultValueHint.Number: { value = ToNumber(value); } break; case DefaultValueHint.String: case DefaultValueHint.LocaleString: { value = ToString(value); } break; } return(value); } }
// Normalize a value down to primitive, but don't apply hard conversions. internal static Object NormalizePrimitive(Object value) { switch (Support.TypeCodeForObject(value)) { case TypeCode.Char: return(Convert.ToString(value)); case TypeCode.SByte: case TypeCode.Byte: case TypeCode.Int16: case TypeCode.UInt16: case TypeCode.Int32: case TypeCode.UInt32: case TypeCode.Int64: case TypeCode.UInt64: case TypeCode.Single: case TypeCode.Double: return(Convert.ToNumber(value)); default: break; } return(value); }
// Convert a value to boolean. public static bool ToBoolean(Object value) { if (value is Boolean) { return((bool)value); } switch (Support.TypeCodeForObject(value)) { case TypeCode.Empty: case TypeCode.DBNull: return(false); case TypeCode.Object: { if (value is Missing #if ECMA_COMPAT ) #else || value is System.Reflection.Missing) #endif { return(false); } // TODO: look for "op_True" and use that if present return(true); } // Not reached. case TypeCode.Boolean: return(ExtractBoolean(value)); case TypeCode.Char: return(ExtractChar(value) != '\0'); case TypeCode.SByte: case TypeCode.Byte: case TypeCode.Int16: case TypeCode.UInt16: return(ExtractInt32Smaller(value) != 0); case TypeCode.Int32: return(ExtractInt32(value) != 0); case TypeCode.UInt32: case TypeCode.Int64: return(ExtractInt64(value) != (long)0); case TypeCode.UInt64: return(ExtractUInt64(value) != (ulong)0); case TypeCode.Single: case TypeCode.Double: { double dvalue = ExtractDouble(value); if (Double.IsNaN(dvalue) || dvalue == 0.0) { return(false); } else { return(true); } } // Not reached. case TypeCode.Decimal: return(ExtractDecimal(value) != 0.0m); case TypeCode.DateTime: return(true); case TypeCode.String: return(ExtractString(value).Length != 0); default: return(true); } }
// Convert a value into a number. public static double ToNumber(Object value) { Object nvalue; if (value is Double) { return((double)value); } else if (value is Int32) { return((double)(int)value); } switch (Support.TypeCodeForObject(value)) { case TypeCode.Empty: return(Double.NaN); case TypeCode.DBNull: return(0.0); case TypeCode.Object: { nvalue = Normalize(value); if (nvalue != value) { return(ToNumber(nvalue)); } else { return(Double.NaN); } } // Not reached. case TypeCode.Boolean: return(ExtractBoolean(value) ? 1.0 : 0.0); case TypeCode.SByte: case TypeCode.Byte: case TypeCode.Int16: case TypeCode.UInt16: case TypeCode.Char: return((double)(ExtractInt32Smaller(value))); case TypeCode.Int32: return((double)(ExtractInt32(value))); case TypeCode.UInt32: case TypeCode.Int64: return((double)(ExtractInt64(value))); case TypeCode.UInt64: return((double)(ExtractUInt64(value))); case TypeCode.Single: case TypeCode.Double: return(ExtractDouble(value)); case TypeCode.Decimal: return((double)(ExtractDecimal(value))); case TypeCode.DateTime: { value = ExtractDateTime(value); nvalue = Normalize(value); if (nvalue != value) { return(ToNumber(nvalue)); } else { return(Double.NaN); } } // Not reached case TypeCode.String: return(ToNumber(ExtractString(value))); default: return(0.0); } }
// Perform a constructor call on this object. internal override Object Construct(VsaEngine engine, Object[] args) { ArrayObject obj; int index, len; if (args.Length != 1) { // Construct an array from a list of values. obj = new ArrayObject (EngineInstance.GetEngineInstance(engine) .GetArrayPrototype(), (uint)(args.Length)); len = args.Length; for (index = 0; index < len; ++index) { obj.PutIndex(index, args[index]); } } else if (args[0] is Array) { // Wrap an existing array. Array array = (Array)(args[0]); if (array.Rank != 1) { throw new JScriptException(JSError.TypeMismatch); } obj = new ArrayObject.Wrapper (EngineInstance.GetEngineInstance(engine) .GetArrayPrototype(), (Array)(args[0])); } else { // Construct an array from a length value. switch (Support.TypeCodeForObject(args[0])) { case TypeCode.Byte: case TypeCode.SByte: case TypeCode.Char: case TypeCode.Int16: case TypeCode.UInt16: case TypeCode.Int32: case TypeCode.UInt32: case TypeCode.Int64: case TypeCode.UInt64: case TypeCode.Single: case TypeCode.Double: case TypeCode.Decimal: { double num = Convert.ToNumber(args[0]); uint inum = Convert.ToUInt32(args[0]); if (num == (double)inum) { return(new ArrayObject (EngineInstance.GetEngineInstance(engine) .GetArrayPrototype(), inum)); } else { throw new JScriptException (JSError.ArrayLengthConstructIncorrect); } } // Not reached. } // The length is not numeric, so it is actually a value. obj = new ArrayObject (EngineInstance.GetEngineInstance(engine) .GetArrayPrototype()); obj.PutIndex(0, args[0]); } return(obj); }