+import java.io.*;
+import java.util.*;
+
+/**
+ * The public API for the JS engine. JS itself is actually a class
+ * implementing the absolute minimal amount of functionality for an
+ * Object which can be manipulated by JavaScript code. The static
+ * methods, fields, and inner classes of JS define the publicly
+ * visible API for the XWT JavaScript engine; code outside this
+ * package should never depend on anything not defined in this file.
+ */
+public abstract class JS {
+
+
+ // Public Helper Methods //////////////////////////////////////////////////////////////////////
+
+ /** parse and compile a function */
+ public static CompiledFunction parse(String sourceName, int firstLine, Reader sourceCode) throws IOException {
+ return new CompiledFunction(sourceName, firstLine, sourceCode, null);
+ }
+
+ /** coerce an object to a Boolean */
+ public static boolean toBoolean(Object o) {
+ if (o == null) return false;
+ if (o instanceof Boolean) return ((Boolean)o).booleanValue();
+ 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;
+ }
+
+ /** coerce an object to a Long */
+ public static long toLong(Object o) { return toNumber(o).longValue(); }
+
+ /** coerce an object to an Int */
+ public static int toInt(Object o) { return toNumber(o).intValue(); }
+
+ /** coerce an object to a Double */
+ public static double toDouble(Object o) { return toNumber(o).doubleValue(); }
+
+ /** coerce an object to a Number */
+ public static Number toNumber(Object o) {
+ if (o == null) return new Long(0);
+ if (o instanceof Number) return ((Number)o);
+ // 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("toNumber() got object of type " + o.getClass().getName() + " which we don't know how to handle");
+ }
+
+ // Instance Methods ////////////////////////////////////////////////////////////////////