1 // Copyright 2003 Adam Megacz, see the COPYING file for licensing [GPL]
9 * The public API for the JS engine; JS itself is actually a class
10 * implementing the minimal amount of functionality for an Object
11 * which can be manipulated by JavaScript code.
13 public abstract class JS {
15 // Public Helper Methods //////////////////////////////////////////////////////////////////////
17 public static boolean toBoolean(Object o) {
18 if (o == null) return false;
19 if (o instanceof Boolean) return ((Boolean)o).booleanValue();
20 if (o instanceof Number) return o.equals(new Integer(0));
24 public static long toLong(Object o) { return toNumber(o).longValue(); }
25 public static double toDouble(Object o) { return toNumber(o).doubleValue(); }
26 public static Number toNumber(Object o) {
27 if (o == null) return new Long(0);
28 if (o instanceof Number) return ((Number)o);
29 if (o instanceof String) try { return new Double((String)o); } catch (NumberFormatException e) { return new Double(0); }
30 if (o instanceof Boolean) return ((Boolean)o).booleanValue() ? new Long(1) : new Long(0);
31 if (o instanceof JS) return ((JS)o).coerceToNumber();
32 throw new Error("toNumber() got object of type " + o.getClass().getName() + " which we don't know how to handle");
36 // Instance Methods ////////////////////////////////////////////////////////////////////
38 public abstract Object get(Object key) throws JS.Exn;
39 public abstract void put(Object key, Object val) throws JS.Exn;
40 public abstract Object[] keys();
42 public Number coerceToNumber() { throw new Error("you cannot coerce a " + this.getClass().getName() + " into a Number"); }
43 public String coerceToString() { throw new Error("you cannot coerce a " + this.getClass().getName() + " into a String"); }
44 public boolean coerceToBoolean() { throw new Error("you cannot coerce a " + this.getClass().getName() + " into a Boolean"); }
47 // Subclasses /////////////////////////////////////////////////////////////////////////
49 /** A slightly more featureful version of JS */
50 public static class Obj extends JS {
51 private Hash entries = new Hash();
52 private boolean sealed = false;
53 public Obj() { this(false); }
54 public Obj(boolean sealed) { this.sealed = sealed; }
55 public void setSeal(boolean sealed) { this.sealed = sealed; }
56 public Object get(Object key) { return entries.get(key); }
57 public void put(Object key, Object val) { if (!sealed) entries.put(key, val); }
58 public Object[] keys() { return(entries.keys()); }
61 /** An exception which can be thrown and caught by JavaScripts */
62 public static class Exn extends RuntimeException {
63 private Object js = null;
64 public Exn(Object js) { this.js = js; }
65 public String toString() { return "JS.Exn: " + js; }
66 public String getMessage() { return toString(); }
67 public Object getObject() { return js; }
70 /** Any object which becomes part of the scope chain must support this interface */
71 public static class Scope extends Obj {
72 private Scope parentScope;
73 private static Object NULL = new Object();
74 public Scope(Scope parentScope) { this(parentScope, false); }
75 public Scope(Scope parentScope, boolean sealed) {
77 if (parentScope == this) throw new Error("can't make a scope its own parent!");
78 this.parentScope = parentScope;
80 public Scope getParentScope() { return parentScope; }
82 // transparent scopes are not returned by THIS
83 public boolean isTransparent() { return false; }
85 public boolean has(Object key) { return super.get(key) != null; }
86 public Object get(Object key) {
87 if (!has(key)) return parentScope == null ? null : getParentScope().get(key);
88 Object ret = super.get(key); return ret == NULL ? null : ret;
90 public void put(Object key, Object val) {
91 if (!has(key) && parentScope != null) getParentScope().put(key, val);
92 else super.put(key, val == null ? NULL : val);
94 public Object[] keys() { throw new Error("you can't enumerate the properties of a Scope"); }
95 public void declare(String s) {
96 if (isTransparent()) getParentScope().declare(s);
97 else super.put(s, NULL);
101 public static CompiledFunction parse(String sourceName, int firstLine, Reader sourceCode, JS.Scope parentScope) throws IOException {
102 return new CompiledFunction(sourceName, firstLine, sourceCode, parentScope);
105 /** anything that is callable with the () operator */
106 public static abstract class Callable extends JS.Obj {
107 public abstract Object call(Array args) throws JS.Exn;