public static boolean toBoolean(Object o) {
if (o == null) return false;
if (o instanceof Boolean) return ((Boolean)o).booleanValue();
- if (o instanceof Number) return o.equals(new Integer(0));
+ if (o instanceof Long) return ((Long)o).longValue() != 0;
+ if (o instanceof Integer) return ((Integer)o).intValue() != 0;
+ if (o instanceof Number) {
+ double d = ((Number) o).doubleValue();
+ // NOTE: d == d is a test for NaN. It should be faster than Double.isNaN()
+ return d != 0.0 && d == d;
+ }
+ if (o instanceof String) return ((String)o).length() != 0;
return true;
}
public static Number toNumber(Object o) {
if (o == null) return new Long(0);
if (o instanceof Number) return ((Number)o);
- if (o instanceof String) try { return new Double((String)o); } catch (NumberFormatException e) { return new Double(0); }
+ // FIXME: There are about 3 pages of rules in ecma262 about string to number conversions
+ // We aren't even close to following all those rules
+ if (o instanceof String) try { return new Double((String)o); } catch (NumberFormatException e) { return new Double(Double.NaN); }
if (o instanceof Boolean) return ((Boolean)o).booleanValue() ? new Long(1) : new Long(0);
if (o instanceof JS) return ((JS)o).coerceToNumber();
- throw new Error("a " + o.getClass().getName() + " has no numeric value");
+ throw new Error("toNumber() got object of type " + o.getClass().getName() + " which we don't know how to handle");
}