2003/11/17 01:53:25
authormegacz <megacz@xwt.org>
Fri, 30 Jan 2004 07:41:36 +0000 (07:41 +0000)
committermegacz <megacz@xwt.org>
Fri, 30 Jan 2004 07:41:36 +0000 (07:41 +0000)
darcs-hash:20040130074136-2ba56-23f7e0eb79a2ee30722d69fc7140bdf5d031cd45.gz

16 files changed:
src/org/xwt/Res.java
src/org/xwt/SOAP.java
src/org/xwt/Template.java
src/org/xwt/XMLRPC.java
src/org/xwt/XWT.java
src/org/xwt/js/Internal.java
src/org/xwt/js/JS.java
src/org/xwt/js/JSArray.java
src/org/xwt/js/JSCallable.java
src/org/xwt/js/JSDate.java
src/org/xwt/js/JSFunction.java
src/org/xwt/js/JSMath.java
src/org/xwt/js/JSObj.java [deleted file]
src/org/xwt/js/JSRegexp.java
src/org/xwt/js/JSScope.java
src/org/xwt/translators/HTML.java

index e9a9465..0652e09 100644 (file)
@@ -185,10 +185,8 @@ public abstract class Res extends JS {
                         int ret = super.read(b, off, len);
                         if (ret != 1) bytesDownloaded += ret;
                         Scheduler.add(new Scheduler.Task() { public void perform() {
-                            JSArray args = new JSArray();
-                            args.addElement(new Integer(bytesDownloaded));
-                            args.addElement(new Integer(is instanceof KnownLength ? ((KnownLength)is).getLength() : 0));
-                            callback.call(args);
+                            callback.call(N(bytesDownloaded),
+                                          N(is instanceof KnownLength ? ((KnownLength)is).getLength() : 0), null, null, 2);
                         } });
                         return ret;
                     }
index 4ffb8a0..113e01b 100644 (file)
@@ -43,7 +43,7 @@ class SOAP extends XMLRPC {
         if (name.equals("SOAP-ENV:Fault")) fault = true;
  
         // add a generic struct; we'll change this if our type is different
-        objects.addElement(new JSObj());
+        objects.addElement(new JS());
 
         for(int i=0; i<keys.length; i++) {
             String key = keys[i];
index 35de96b..bd57bf9 100644 (file)
@@ -98,7 +98,7 @@ public class Template {
         if (staticscript == null) return staticJSScope;
         JSFunction temp = staticscript;
         staticscript = null;
-        temp.cloneWithNewParentJSScope(staticJSScope).call(new JSArray());
+        temp.cloneWithNewParentJSScope(staticJSScope).call(null, null, null, null, 0);
         return staticJSScope;
     }
     
@@ -122,10 +122,10 @@ public class Template {
         for (int i=0; children != null && i<children.size(); i++) {
             Box kid = new BoxTree();
             ((Template)children.elementAt(i)).apply(kid, xwt, pis);
-            b.putAndTriggerJSTraps(JSObj.N(b.numchildren), kid);
+            b.putAndTriggerJSTraps(JS.N(b.numchildren), kid);
         }
 
-        if (script != null) script.cloneWithNewParentJSScope(pis).call(new JSArray());
+        if (script != null) script.cloneWithNewParentJSScope(pis).call(null, null, null, null, 0);
 
         for(int i=0; keys != null && i<keys.length; i++)
             if (vals[i] instanceof String && ((String)vals[i]).charAt(0) == '$') b.putAndTriggerJSTraps(keys[i], pis.get(vals[i]));
index 43654c7..efcccf7 100644 (file)
@@ -58,7 +58,7 @@ class XMLRPC extends JSCallable {
      *  stack to the last null, replace it with a NativeJSArray, and
      *  insert into it all elements above it on the stack.
      *
-     *  If a &lt;struct&gt; tag is encountered, a JSObject is pushed
+     *  If a &lt;struct&gt; tag is encountered, a JSect is pushed
      *  onto the stack. If a &lt;name&gt; tag is encountered, its CDATA is
      *  pushed onto the stack. When a &lt;/member&gt; is encountered, the
      *  name (second element on stack) and value (top of stack) are
@@ -82,7 +82,7 @@ class XMLRPC extends JSCallable {
         public void startElement(XML.Element c) {
             content.reset();
             if (c.localName.equals("fault")) fault = true;
-            else if (c.localName.equals("struct")) objects.setElementAt(new JSObj(), objects.size() - 1);
+            else if (c.localName.equals("struct")) objects.setElementAt(new JS(), objects.size() - 1);
             else if (c.localName.equals("array")) objects.setElementAt(null, objects.size() - 1);
             else if (c.localName.equals("value")) objects.addElement("");
         }
@@ -128,7 +128,7 @@ class XMLRPC extends JSCallable {
                                                                     Double.valueOf(s.substring(15, 17)).doubleValue(),
                                                                     (double)0
                                                                     );
-                    nd.jsJSFunction_setTime(JSDate.internalUTC(date));
+                    nd.setTime(JSDate.internalUTC(date));
                     objects.setElementAt(nd, objects.size() - 1);
                     
                 } catch (Exception e) {
@@ -356,6 +356,11 @@ class XMLRPC extends JSCallable {
         return objects.elementAt(0);
     }
 
+    public final Object call(Object a0, Object a1, Object a2, Object[] rest, int nargs) throws JS.Exn {
+        JSArray args = new JSArray();
+        for(int i=0; i<nargs; i++) args.addElement(i==0?a0:i==1?a1:i==2?a2:rest[i-3]);
+        return call(args);
+    }
     public final Object call(final JSArray args) throws JS.Exn {
         final Callback callback = JSContext.pause();
         new java.lang.Thread() {
index 811a643..263120d 100644 (file)
@@ -22,15 +22,20 @@ public final class XWT extends JSCallable {
         Sub(String key) { this.key = key; }
         public String toString() { return "XWTSUB " + key; }
         public void put(Object key, Object val) { XWT.this.put(this.key + "." + key, val); }
-        public Object get(Object key) { return XWT.this._get(this.key + "." + key); }
-        public Object call(Object method, JSArray args) { return XWT.this.call(method == null ? key : this.key + "." + method, args); }
+        public Object get(Object key) { return XWT.this.get(this.key + "." + key); }
+        public Object call(Object a0, Object a1, Object a2, Object[] rest, int nargs) {
+            return XWT.this.callMethod(this.key, a0, a1, a2, rest, nargs);
+        }
+        public Object callMethod(Object method, Object a0, Object a1, Object a2, Object[] rest, int nargs) {
+            return XWT.this.callMethod(this.key + "." + method, a0, a1, a2, rest, nargs);
+        }
     }
 
-    public Object _get(Object name) {
+    public Object get(Object name) {
         //#switch(name)
         case "math": return xwtMath;
         case "string": return xwtString;
-        case "date": return new JSDate();
+        case "date": return METHOD;
         case "origin": return Main.origin;
         case "box": return new BoxTree();
         case "log": return new Sub("log");
@@ -58,23 +63,38 @@ public final class XWT extends JSCallable {
             else return new Integer(0);
         case "undocumented": return new Sub("undocumented");
         case "undocumented.internal": return new Sub("undocumented.internal");
+        case "thread.yield": return METHOD;
+        case "thread.sleep": return METHOD;
+        case "res.watch": return METHOD;
+        case "soap": return METHOD;
+        case "apply": return METHOD;
+        case "graft": return METHOD;
+        case "ui.browser": return METHOD;
+        case "clone": return METHOD;
+        case "res.unzip": return METHOD;
+        case "res.uncab": return METHOD;
+        case "res.cache": return METHOD;
+        case "res.url": return METHOD;
+        case "log.println": return METHOD;
+        case "log.dump": return METHOD;
+        case "regexp": return METHOD;
+        case "rpc.xml": return METHOD;
+        case "rpc.soap": return METHOD;
+        case "crypto.rsa": return METHOD;
+        case "crypto.md5": return METHOD;
+        case "crypto.sha1": return METHOD;
+        case "crypto.rc4": return METHOD;
+        case "stream.parse.html": return METHOD;
+        case "stream.parse.xml": return METHOD;
+        case "stream.parse.utf8": return METHOD;
         //#end
         return null;
     }
 
-    public Object get(Object name) {
-        Object ret = _get(name);
-        if (ret != null) return ret;
-        return !name.equals("clone") && !name.equals("apply") ? rr.get(name) : null;
-    }
-
     public void put(Object name, final Object value) {
         //#switch(name)
         case "thread":
-            System.out.println("new thread " + value);
-            Scheduler.add(new Scheduler.Task() {
-                    public String toString() { return "thread task"; }
-                    public void perform() { JSContext.invokePauseable((JSFunction)value); } });
+            Scheduler.add(new Scheduler.Task() { public void perform() { JSContext.invokePauseable((JSFunction)value); } });
         case "ui.clipboard": Platform.setClipBoard((String)value);
         case "ui.frame": Platform.createSurface((Box)value, true, true);
         case "ui.window": Platform.createSurface((Box)value, false, true);
@@ -84,23 +104,24 @@ public final class XWT extends JSCallable {
         //#end
     }
 
-    public Object call(Object name, JSArray args) throws JS.Exn {
-        Object a = args.elementAt(0);
-        Object b = args.elementAt(1);
-        Object c = args.elementAt(2);
-        if (name.equals("date")) return new org.xwt.js.JSDate(args);
-        else if (args.length() == 0 && name.equals("thread.yield")) { sleep(0); return null; }
-        else if (args.length() == 2) {
+    public Object callMethod(Object name, Object a, Object b, Object c, Object[] rest, int nargs) throws JS.Exn {
+        if (name.equals("date")) {
+            JSArray args = new JSArray();
+            for(int i=0; i<nargs; i++) args.addElement(i==0?a:i==1?b:i==2?c:rest[i-3]);
+            return new org.xwt.js.JSDate(args);
+        }
+        else if (nargs == 0 && name.equals("thread.yield")) { sleep(0); return null; }
+        else if (nargs == 2) {
             //#switch(name)
             case "res.watch": return new Res.ProgressWatcher((Res)a, (JSFunction)b);
-            case "soap": return new SOAP((String)args.elementAt(0), "", (String)args.elementAt(1), null);
+            case "soap": return new SOAP((String)a, "", (String)b, null);
             case "apply":
-                Template.getTemplate((Res)args.elementAt(1)).apply((Box)args.elementAt(0), XWT.this);
-                return args.elementAt(0);
+                Template.getTemplate((Res)b).apply((Box)a, XWT.this);
+                return a;
             //#end
-        } else if (args.length() == 3 && name.equals("soap")) {
+        } else if (nargs == 3 && name.equals("soap")) {
             if (name.equals("soap")) {
-                return new SOAP((String)args.elementAt(0), "", (String)args.elementAt(1), (String)args.elementAt(2));
+                return new SOAP((String)a, "", (String)b, (String)c);
             } else if (name.equals("graft")) {
                 if (a instanceof Box) throw new JS.Exn("can't graft onto Boxes (yet)");
                 if (a instanceof Number) throw new JS.Exn("can't graft onto Numbers (yet)");
@@ -108,7 +129,7 @@ public final class XWT extends JSCallable {
                 if (a instanceof Res) return new Res.Graft((Res)a, b, c);
                 return new JS.Graft((JS)a, b, c);
             }
-        } else if (args.length() == 1) {
+        } else if (nargs == 1) {
             //#switch(name)
             case "ui.browser": Platform.newBrowserWindow((String)a); return null;
             case "clone": return new XWT((Res)a);
@@ -123,7 +144,6 @@ public final class XWT extends JSCallable {
                 else if (url.startsWith("data:")) return new Res.ByteArray(Base64.decode(url.substring(5)), null);
                 else if (url.startsWith("utf8:")) return new Res.ByteArray(url.substring(5).getBytes(), null);
                 throw new JS.Exn("invalid resource specifier " + url);
-
             case "thread.sleep": sleep(JS.toInt(a)); return null;
             case "log.println": Log.logJS(this, a== null ? "**null**" : a.toString()); return null;
             case "log.dump": Log.recursiveLog("","",a); return null;
@@ -167,7 +187,7 @@ public final class XWT extends JSCallable {
             }
         };
 
-    public static final JSObj xwtString = new JSObj() {
+    public static final JS xwtString = new JS() {
             private JS gs = new JSScope.Global(null);
             public void put(Object key, Object val) { }
             public Object get(Object key) {
@@ -182,7 +202,7 @@ public final class XWT extends JSCallable {
                 case "unescape": return gs.get("unescape");
                 case "fromCharCode": return gs.get("stringFromCharCode");
                 //#end
-                return super.get(key);
+                return null;
             }
         };
 
@@ -190,7 +210,7 @@ public final class XWT extends JSCallable {
         Vector obStack = new Vector();
         public XMLHelper() { super(BUFFER_SIZE); }
         public void startElement(XML.Element c) throws XML.SchemaException {
-            JS o = new JSObj();
+            JS o = new JS();
             o.put("$name", c.localName);
             for(int i=0; i<c.len; i++) o.put(c.keys[i], c.vals[i]);
             o.put("$numchildren", new Integer(0));
index 6d1fece..4cddef1 100644 (file)
@@ -130,6 +130,7 @@ class Internal {
             final Object target = o;
             final String method = key.toString();
             return new JSCallable() {
+                    // FIXME
                 public Object call(Object notUsed, JSArray args) { return callMethodOnPrimitive(target,method,args); }
             };
         }
@@ -138,8 +139,10 @@ class Internal {
     
     static class JSCallableStub extends JSCallable {
         private Object method;
-        private JSObj obj;
-        public JSCallableStub(JSObj obj, Object method) { this.obj = obj; this.method = method; }
-        public Object call(JSArray args) { return ((JSCallable)obj).call(method,args); }
+        private JS obj;
+        public JSCallableStub(JS obj, Object method) { this.obj = obj; this.method = method; }
+        public Object call(Object a0, Object a1, Object a2, Object[] rest, int nargs) {
+            return ((JSCallable)obj).callMethod(method, a0, a1, a2, rest, nargs);
+        }
     }
 }
index f1f6726..327d35c 100644 (file)
@@ -11,7 +11,7 @@ import java.util.*;
  *  implementing the absolute minimal amount of functionality for an
  *  Object which can be manipulated by JavaScript code.
  */
-public abstract class JS { 
+public class JS { 
 
     // Public Helper Methods //////////////////////////////////////////////////////////////////////
 
@@ -74,10 +74,29 @@ public abstract class JS {
     
     // Instance Methods ////////////////////////////////////////////////////////////////////
  
-    public abstract Object get(Object key) throws JS.Exn; 
-    public void put(Object key, Object val) throws JS.Exn { throw new JS.Exn("you cannot put to this object"); }
+    // this gets around a wierd fluke in the Java type checking rules for ?..:
+    public static final Object T = Boolean.TRUE;
+    public static final Object F = Boolean.FALSE;
+
+    // FEATURE: be smart here; perhaps intern
+    public static final Number N(int i) { return new Integer(i); }
+    public static final Number N(long l) { return new Long(l); }
+    public static final Number N(double d) { return new Double(d); }
+    public static final Boolean B(boolean b) { return b ? Boolean.TRUE : Boolean.FALSE; }
+    
+    private static Enumeration emptyEnumeration = new Enumeration() {
+            public boolean hasMoreElements() { return false; }
+            public Object nextElement() { throw new NoSuchElementException(); }
+        };
+    
+    private Hash entries = null;
+    public Enumeration keys() { return entries == null ? emptyEnumeration : entries.keys(); }
+    public Object get(Object key) { return entries == null ? null : entries.get(key, null); }
+    public void put(Object key, Object val) { if (entries == null) entries = new Hash(); entries.put(key, null, val); }
 
-    public Enumeration keys() { throw new Error("you cannot apply for..in to a " + this.getClass().getName()); }
+    // note that we don't actually implement trappable... we just provide these for subclasses which choose to
+    public JSTrap getTrap(Object key) { return entries == null ? null : (JSTrap)entries.get(key, JSTrap.class); }
+    public void putTrap(Object key, JSTrap t) { if (entries == null) entries = new Hash(); entries.put(key, JSTrap.class, t); }
 
     public Number coerceToNumber() { throw new JS.Exn("tried to coerce a JavaScript object to a Number"); }
     public String coerceToString() { throw new JS.Exn("tried to coerce a JavaScript object to a String"); }
@@ -98,6 +117,7 @@ public abstract class JS {
     } 
 
     /** the result of a graft */
+    // FIXME: uber-broken
     public static class Graft extends JSCallable {
         private JS graftee;
         private Object replaced_key;
@@ -114,11 +134,13 @@ public abstract class JS {
         public int hashCode() { return graftee.hashCode(); }
         public Object get(Object key) { return replaced_key.equals(key) ? replaced_val : graftee.get(key); }
         public void put(Object key, Object val) { graftee.put(key, val); }
+        /*
         public Object call(Object method, JSArray args) {
             if (replaced_key.equals(method)) return ((JSCallable)replaced_val).call(null, args);
             else if (graftee instanceof JSCallable) return ((JSCallable)graftee).call(method, args);
             else throw new JS.Exn("cannot call this value");
         }
+        */
         public Number coerceToNumber() { return graftee.coerceToNumber(); }
         public String coerceToString() { return graftee.coerceToString(); }
         public boolean coerceToBoolean() { return graftee.coerceToBoolean(); }
index 880e64f..c918bda 100644 (file)
@@ -22,49 +22,62 @@ public class JSArray extends JSCallable {
         return Integer.parseInt(s);
     }
     
-    public Object call(Object method, JSArray args) {
-        if(method.equals("push")) {
-            for(int i=0;i<args.length();i++)
-                vec.push(args.elementAt(i));
-            return new Integer(vec.size());
-        }
-        if(method.equals("pop")) {
-            return vec.pop(); // this'll return null on size()==0 
-        }
-        if(method.equals("shift")) {
-            if(length() > 0) {
-                Object o = vec.elementAt(0);
-                vec.removeElementAt(0);
-                return o;
-            } else {
-                return null;
-            }
-        }
-        if(method.equals("unshift")) {
-            // FEATURE: could be optimized a bit with some help from Vec
-            for(int i=0;i<args.length();i++)
-                vec.insertElementAt(args.elementAt(i),i);
-            return new Integer(vec.size());
-        }
-        if(method.equals("slice")) return slice(args);
-        if(method.equals("join")) return join(args);
-        if(method.equals("reverse")) return reverse(args);
-        if(method.equals("toString")) return join(",");
-        if(method.equals("sort")) return sort(args);
-        if(method.equals("splice")) return splice(args);
-        throw new JS.Exn("unknown method " + method);
+    public Object callMethod(Object method, Object a0, Object a1, Object a2, Object[] rest, int nargs) {
+        //#switch(method)
+        case "pop": return vec.pop();
+        case "reverse": return reverse();
+        case "toString": return join(",");
+        case "shift":
+            if(length() == 0) return null;
+            Object o = vec.elementAt(0);
+            vec.removeElementAt(0);
+            return o;
+        case "join":
+            return join(nargs == 0 ? "," : JS.toString(a0));
+        case "sort":
+            return sort(nargs < 1 ? null : a0);
+        case "slice":
+            int start = toInt(nargs < 1 ? null : a0);
+            int end = nargs < 2 ? length() : toInt(a1);
+            return slice(start, end);
+        case "push":
+            for(int i=0; i<nargs; i++) vec.push(i==0?a0:i==1?a1:i==2?a2:rest[i-3]);
+            return N(vec.size());
+        case "unshift":
+            for(int i=0; i<nargs; i++) vec.insertElementAt(i==0?a0:i==1?a1:i==2?a2:rest[i-3], i);
+            return N(vec.size());
+        case "splice":
+            JSArray array = new JSArray();
+            for(int i=0; i<nargs; i++) array.addElement(i==0?a0:i==1?a1:i==2?a2:rest[i-3]);
+            return splice(array);
+        //#end
+        return super.callMethod(method, a0, a1, a2, rest, nargs);
     }
         
     public Object get(Object key) throws JS.Exn {
-        if (key.equals("length")) return new Long(vec.size());
-                
-        int i = intVal(key);
-        if (i == Integer.MIN_VALUE) return super.get(key);
-        try {
-            return vec.elementAt(i);
-        } catch (ArrayIndexOutOfBoundsException e) {
-            return null;
+        if (key instanceof Number) {
+            int i = intVal(key);
+            if (i == Integer.MIN_VALUE) return super.get(key);
+            try {
+                return vec.elementAt(i);
+            } catch (ArrayIndexOutOfBoundsException e) {
+                return null;
+            }
         }
+        //#switch(key)
+        case "pop": return METHOD;
+        case "reverse": return METHOD;
+        case "toString": return METHOD;
+        case "shift": return METHOD;
+        case "join": return METHOD;
+        case "sort": return METHOD;
+        case "slice": return METHOD;
+        case "push": return METHOD;
+        case "unshift": return METHOD;
+        case "splice": return METHOD;
+        case "length": return N(vec.size());
+        //#end
+        return super.get(key);
     }
 
     public void put(Object key, Object val) {
@@ -96,10 +109,6 @@ public class JSArray extends JSCallable {
     public int size() { return vec.size(); }
     public String typeName() { return "array"; }
         
-    private Object join(JSArray args) {
-        return join(args.length() == 0 ? "," : JS.toString(args.elementAt(0)));
-    }
-    
     private Object join(String sep) {
         int length = vec.size();
         if(length == 0) return "";
@@ -114,20 +123,17 @@ public class JSArray extends JSCallable {
         return sb.toString();
     }
     
-    private Object reverse(JSArray args) {
+    private Object reverse() {
         Vec oldVec = vec;
         int size = oldVec.size();
         if(size < 2) return this;
         vec = new Vec(size);
-        for(int i=size-1;i>=0;i--)
-            vec.addElement(oldVec.elementAt(i));
+        for(int i=size-1;i>=0;i--) vec.addElement(oldVec.elementAt(i));
         return this;
     }
     
-    private Object slice(JSArray args) {
+    private Object slice(int start, int end) {
         int length = length();
-        int start = JS.toInt(args.length() < 1 ? null : args.elementAt(0));
-        int end = args.length() < 2 ? length : JS.toInt(args.elementAt(1));
         if(start < 0) start = length+start;
         if(end < 0) end = length+end;
         if(start < 0) start = 0;
@@ -145,8 +151,7 @@ public class JSArray extends JSCallable {
             return JS.toString(a).compareTo(JS.toString(b));
         }
     };
-    private Object sort(JSArray args) {
-        Object tmp = args.length() < 1 ? null : args.elementAt(0);
+    private Object sort(Object tmp) {
         if(tmp instanceof JSCallable) {
             final JSArray funcArgs = new JSArray(2);
             final JSCallable jsFunc = (JSCallable) tmp;
@@ -154,7 +159,7 @@ public class JSArray extends JSCallable {
                 public int compare(Object a, Object b) {
                     funcArgs.setElementAt(a,0);
                     funcArgs.setElementAt(b,1);
-                    return JS.toInt(jsFunc.call(null, funcArgs));
+                    return JS.toInt(jsFunc.call(a, b, null, null, 2));
                 }
             });
         } else {
index 8865f3b..c9c09d0 100644 (file)
@@ -1,35 +1,18 @@
 package org.xwt.js;
 
 /** anything that is callable with the () operator and wasn't compiled from JS code */
-public abstract class JSCallable extends JSObj {
-    public Object call0(Object method) throws JS.Exn {
-        JSArray args = new JSArray();
-        return call(method, args);
-    }
-    public Object call1(Object method, Object arg1) throws JS.Exn {
-        JSArray args = new JSArray();
-        args.addElement(arg1);
-        return call(method, args);
-    }
-    public Object call2(Object method, Object arg1, Object arg2) throws JS.Exn {
-        JSArray args = new JSArray();
-        args.addElement(arg1);
-        args.addElement(arg2);
-        return call(method, args);
+public abstract class JSCallable extends JS {
+
+    // return this from get() if the key was actually a method.
+    public static final Object METHOD = new Object();
+
+    public Object callMethod(Object method, Object a0, Object a1, Object a2, Object[] rest, int nargs) {
+        throw new JS.Exn("attempted to call an undefined method");
     }
-    public Object call(Object method, JSArray args) throws JS.Exn {
-        if (method != null) {
-            Object meth = get(method);
-            if (meth == null) throw new JS.Exn("attempt to invoke the null method");
-            if (!(meth instanceof JSCallable)) throw new JS.Exn("cannot call a " + meth.getClass().getName());
-            switch (args.size()) {
-                case 0: return ((JSCallable)meth).call0(null);
-                case 1: return ((JSCallable)meth).call1(null, args.elementAt(0));
-                case 2: return ((JSCallable)meth).call2(null, args.elementAt(0), args.elementAt(1));
-                default: return ((JSCallable)meth).call(null, args);
-            }
-        }
-        throw new JS.Exn("cannot invoke method " + method + " on object " + this.getClass().getName() + " with " + args.size() + " arguments");
+
+    public Object call(Object a0, Object a1, Object a2, Object[] rest, int nargs) {
+        throw new JS.Exn("you cannot call this object");
     }
+
 }
 
index 37624b4..901ee9d 100644 (file)
@@ -46,6 +46,7 @@ import java.text.SimpleDateFormat;
  * This class implements the Date native object.
  * See ECMA 15.9.
  * @author Mike McCabe
+ * @author Adam Megacz (many modifications
  */
 public class JSDate extends JSCallable {
 
@@ -60,207 +61,118 @@ public class JSDate extends JSCallable {
 
     public String coerceToString() { return date_format(date, FORMATSPEC_FULL); }
 
-    public Object call(Object name, JSArray args_) {
-        Object[] args = new Object[args_.length()];
-        for(int i=0; i<args.length; i++) args[i] = args_.elementAt(i);
-
-        if (name.equals(getIdName(ConstructorId_UTC))) { 
-            return new Double(jsStaticJSFunction_UTC(args));
-            
-        } else if (name.equals(getIdName(ConstructorId_parse))) { 
-            return new Double(jsStaticJSFunction_parse(args[0].toString()));
-            
-        } else if (name.equals(getIdName(Id_constructor))) {
-            return new JSDate(args_);
-            
-        } else if (name.equals(getIdName(Id_toString))) {
-            double t = date;
-            return date_format(t, FORMATSPEC_FULL);
-
-        } else if (name.equals(getIdName(Id_toTimeString))) {
-            double t = date;
-            return date_format(t, FORMATSPEC_TIME);
-
-        } else if (name.equals(getIdName(Id_toDateString))) {
-            double t = date;
-            return date_format(t, FORMATSPEC_DATE);
-
-        } else if (name.equals(getIdName(Id_toLocaleString))) {
-            double t = date;
-            return jsJSFunction_toLocaleString(t);
-
-        } else if (name.equals(getIdName(Id_toLocaleTimeString))) {
-            double t = date;
-            return jsJSFunction_toLocaleTimeString(t);
-
-        } else if (name.equals(getIdName(Id_toLocaleDateString))) {
-            double t = date;
-            return jsJSFunction_toLocaleDateString(t);
-
-        } else if (name.equals(getIdName(Id_toUTCString))) {
-            double t = date;
-            return jsJSFunction_toUTCString(t);
-
-        } else if (name.equals(getIdName(Id_valueOf))) { 
-            return new Double(this.date);
-
-        } else if (name.equals(getIdName(Id_getTime))) { 
-            return new Double(this.date);
-
-        } else if (name.equals(getIdName(Id_getYear))) {
-            double t = date;
-            t = jsJSFunction_getYear(t);
-            return new Double(t);
-
-        } else if (name.equals(getIdName(Id_getFullYear))) {
-            double t = date;
-            t = YearFromTime(LocalTime(t));
-            return new Double(t);
-
-        } else if (name.equals(getIdName(Id_getUTCFullYear))) {
-            double t = date;
-            t = YearFromTime(t);
-            return new Double(t);
-
-        } else if (name.equals(getIdName(Id_getMonth))) {
-            double t = date;
-            t = MonthFromTime(LocalTime(t));
-            return new Double(t);
-                
-        } else if (name.equals(getIdName(Id_getUTCMonth))) {
-            double t = date;
-            t = MonthFromTime(t);
-            return new Double(t);
-
-        } else if (name.equals(getIdName(Id_getDate))) {
-            double t = date;
-            t = DateFromTime(LocalTime(t));
-            return new Double(t);
-
-        } else if (name.equals(getIdName(Id_getUTCDate))) {
-            double t = date;
-            t = DateFromTime(t);
-            return new Double(t);
-
-        } else if (name.equals(getIdName(Id_getDay))) {
-            double t = date;
-            t = WeekDay(LocalTime(t));
-            return new Double(t);
-
-        } else if (name.equals(getIdName(Id_getUTCDay))) {
-            double t = date;
-            t = WeekDay(t);
-            return new Double(t);
-
-        } else if (name.equals(getIdName(Id_getHours))) {
-            double t = date;
-            t = HourFromTime(LocalTime(t));
-            return new Double(t);
-
-        } else if (name.equals(getIdName(Id_getUTCHours))) {
-            double t = date;
-            t = HourFromTime(t);
-            return new Double(t);
-
-        } else if (name.equals(getIdName(Id_getMinutes))) {
-            double t = date;
-            t = MinFromTime(LocalTime(t));
-            return new Double(t);
-
-        } else if (name.equals(getIdName(Id_getUTCMinutes))) {
-            double t = date;
-            t = MinFromTime(t);
-            return new Double(t);
-
-        } else if (name.equals(getIdName(Id_getSeconds))) {
-            double t = date;
-            t = SecFromTime(LocalTime(t));
-            return new Double(t);
-
-        } else if (name.equals(getIdName(Id_getUTCSeconds))) {
-            double t = date;
-            t = SecFromTime(t);
-            return new Double(t);
-                
-        } else if (name.equals(getIdName(Id_getMilliseconds))) {
-            double t = date;
-            t = msFromTime(LocalTime(t));
-            return new Double(t);
-
-        } else if (name.equals(getIdName(Id_getUTCMilliseconds))) {
-            double t = date;
-            t = msFromTime(t);
-            return new Double(t);
-
-        } else if (name.equals(getIdName(Id_getTimezoneOffset))) {
-            double t = date;
-            t = jsJSFunction_getTimezoneOffset(t);
-            return new Double(t);
-
-        } else if (name.equals(getIdName(Id_setTime))) { 
-            return new Double(this.jsJSFunction_setTime(_toNumber(args, 0)));
-
-        } else if (name.equals(getIdName(Id_setMilliseconds))) { 
-            return new Double(this.
-                               makeTime(args, 1, true));
-
-        } else if (name.equals(getIdName(Id_setUTCMilliseconds))) { 
-            return new Double(this.
-                               makeTime(args, 1, false));
-
-        } else if (name.equals(getIdName(Id_setSeconds))) { 
-            return new Double(this.
-                               makeTime(args, 2, true));
-
-        } else if (name.equals(getIdName(Id_setUTCSeconds))) { 
-            return new Double(this.
-                               makeTime(args, 2, false));
-
-        } else if (name.equals(getIdName(Id_setMinutes))) { 
-            return new Double(this.
-                               makeTime(args, 3, true));
-
-        } else if (name.equals(getIdName(Id_setUTCMinutes))) { 
-            return new Double(this.
-                               makeTime(args, 3, false));
-
-        } else if (name.equals(getIdName(Id_setHours))) { 
-            return new Double(this.
-                               makeTime(args, 4, true));
-
-        } else if (name.equals(getIdName(Id_setUTCHours))) { 
-            return new Double(this.
-                               makeTime(args, 4, false));
-
-        } else if (name.equals(getIdName(Id_setDate))) { 
-            return new Double(this.
-                               makeDate(args, 1, true));
-
-        } else if (name.equals(getIdName(Id_setUTCDate))) { 
-            return new Double(this.
-                               makeDate(args, 1, false));
-
-        } else if (name.equals(getIdName(Id_setMonth))) { 
-            return new Double(this.
-                               makeDate(args, 2, true));
-
-        } else if (name.equals(getIdName(Id_setUTCMonth))) { 
-            return new Double(this.
-                               makeDate(args, 2, false));
-
-        } else if (name.equals(getIdName(Id_setFullYear))) { 
-            return new Double(this.
-                               makeDate(args, 3, true));
-
-        } else if (name.equals(getIdName(Id_setUTCFullYear))) { 
-            return new Double(this.
-                               makeDate(args, 3, false));
-
-        } else if (name.equals(getIdName(Id_setYear))) { 
-            return new Double(this.
-                               jsJSFunction_setYear(_toNumber(args, 0)));
+    public Object callMethod(Object method, Object a0, Object a1, Object a2, Object[] rest, int nargs) {
+        switch(nargs) {
+            case 0: {
+                //#switch(method)
+                case "toString": return date_format(date, FORMATSPEC_FULL);
+                case "toTimeString": return date_format(date, FORMATSPEC_TIME);
+                case "toDateString": return date_format(date, FORMATSPEC_DATE);
+                case "toLocaleString": return toLocaleString(date);
+                case "toLocaleTimeString": return toLocaleTimeString(date);
+                case "toLocaleDateString": return toLocaleDateString(date);
+                case "toUTCString": return toUTCString(date);
+                case "valueOf": return N(this.date);
+                case "getTime": return N(this.date);
+                case "getYear": return N(getYear(date));
+                case "getFullYear": return N(YearFromTime(LocalTime(date)));
+                case "getUTCFullYear": return N(YearFromTime(date));
+                case "getMonth": return N(MonthFromTime(LocalTime(date)));
+                case "getUTCMonth": return N(MonthFromTime(date));
+                case "getDate": return N(DateFromTime(LocalTime(date)));
+                case "getUTCDate": return N(DateFromTime(date));
+                case "getDay": return N(WeekDay(LocalTime(date)));
+                case "getUTCDay": return N(WeekDay(date));
+                case "getHours": return N(HourFromTime(LocalTime(date)));
+                case "getUTCHours": return N(HourFromTime(date));
+                case "getMinutes": return N(MinFromTime(LocalTime(date)));
+                case "getUTCMinutes": return N(MinFromTime(date));
+                case "getSeconds": return N(SecFromTime(LocalTime(date)));
+                case "getUTCSeconds": return N(SecFromTime(date));
+                case "getMilliseconds": return N(msFromTime(LocalTime(date)));
+                case "getUTCMilliseconds": return N(msFromTime(date));
+                case "getTimezoneOffset": return N(getTimezoneOffset(date));
+                //#end
+                return super.callMethod(method, a0, a1, a2, rest, nargs);
+            }
+            case 1: {
+                //#switch(method)
+                case "setTime": return N(this.setTime(toDouble(a0)));
+                case "setYear": return N(this.setYear(toDouble(a0)));
+                //#end
+                // fall through
+            }
+            default: {
+                Object[] args = new Object[nargs];
+                for(int i=0; i<nargs; i++) args[i] = i==0 ? a0 : i==1 ? a1 : i==2 ? a2 : rest[i-3];
+                //#switch(method)
+                case "setMilliseconds": return N(this.makeTime(args, 1, true));
+                case "setUTCMilliseconds": return N(this.makeTime(args, 1, false));
+                case "setSeconds": return N(this.makeTime(args, 2, true));
+                case "setUTCSeconds": return N(this.makeTime(args, 2, false));
+                case "setMinutes": return N(this.makeTime(args, 3, true));
+                case "setUTCMinutes": return N(this.makeTime(args, 3, false));
+                case "setHours": return N(this.makeTime(args, 4, true));
+                case "setUTCHours": return N(this.makeTime(args, 4, false));
+                case "setDate": return N(this.makeDate(args, 1, true));
+                case "setUTCDate": return N(this.makeDate(args, 1, false));
+                case "setMonth": return N(this.makeDate(args, 2, true));
+                case "setUTCMonth": return N(this.makeDate(args, 2, false));
+                case "setFullYear": return N(this.makeDate(args, 3, true));
+                case "setUTCFullYear": return N(this.makeDate(args, 3, false));
+                //#end
+            }
         }
-        return null;
+        return super.callMethod(method, a0, a1, a2, rest, nargs);
+    }
+
+    public Object get(Object key) {
+        //#switch(key)
+        case "toString": return METHOD;
+        case "toTimeString": return METHOD;
+        case "toDateString": return METHOD;
+        case "toLocaleString": return METHOD;
+        case "toLocaleTimeString": return METHOD;
+        case "toLocaleDateString": return METHOD;
+        case "toUTCString": return METHOD;
+        case "valueOf": return METHOD;
+        case "getTime": return METHOD;
+        case "getYear": return METHOD;
+        case "getFullYear": return METHOD;
+        case "getUTCFullYear": return METHOD;
+        case "getMonth": return METHOD;
+        case "getUTCMonth": return METHOD;
+        case "getDate": return METHOD;
+        case "getUTCDate": return METHOD;
+        case "getDay": return METHOD;
+        case "getUTCDay": return METHOD;
+        case "getHours": return METHOD;
+        case "getUTCHours": return METHOD;
+        case "getMinutes": return METHOD;
+        case "getUTCMinutes": return METHOD;
+        case "getSeconds": return METHOD;
+        case "getUTCSeconds": return METHOD;
+        case "getMilliseconds": return METHOD;
+        case "getUTCMilliseconds": return METHOD;
+        case "getTimezoneOffset": return METHOD;
+        case "setTime": return METHOD;
+        case "setYear": return METHOD;
+        case "setMilliseconds": return METHOD;
+        case "setUTCMilliseconds": return METHOD;
+        case "setSeconds": return METHOD;
+        case "setUTCSeconds": return METHOD;
+        case "setMinutes": return METHOD;
+        case "setUTCMinutes": return METHOD;
+        case "setHours": return METHOD;
+        case "setUTCHours": return METHOD;
+        case "setDate": return METHOD;
+        case "setUTCDate": return METHOD;
+        case "setMonth": return METHOD;
+        case "setUTCMonth": return METHOD;
+        case "setFullYear": return METHOD;
+        case "setUTCFullYear": return METHOD;
+        //#end
+        return super.get(key);
     }
 
     /* ECMA helper functions */
@@ -650,7 +562,7 @@ public class JSDate extends JSCallable {
                               array[3], array[4], array[5], array[6]);
         d = TimeClip(d);
         return d;
-        //        return new Double(d);
+        //        return N(d);
     }
 
     /*
@@ -898,7 +810,7 @@ public class JSDate extends JSCallable {
 
     private static String date_format(double t, int format) {
         if (t != t)
-            return jsJSFunction_NaN_date_str;
+            return NaN_date_str;
 
         StringBuffer result = new StringBuffer(60);
         double local = LocalTime(t);
@@ -1051,7 +963,7 @@ public class JSDate extends JSCallable {
     }
 
     /* constants for toString, toUTCString */
-    private static String jsJSFunction_NaN_date_str = "Invalid Date";
+    private static String NaN_date_str = "Invalid Date";
 
     private static String[] days = {
         "Sun","Mon","Tue","Wed","Thu","Fri","Sat"
@@ -1066,13 +978,13 @@ public class JSDate extends JSCallable {
                                           java.text.DateFormat formatter)
     {
         if (t != t)
-            return jsJSFunction_NaN_date_str;
+            return NaN_date_str;
 
         java.util.Date tempdate = new java.util.Date((long) t);
         return formatter.format(tempdate);
     }
 
-    private static String jsJSFunction_toLocaleString(double date) {
+    private static String toLocaleString(double date) {
         if (localeDateTimeFormatter == null)
             localeDateTimeFormatter =
                 DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG);
@@ -1080,21 +992,21 @@ public class JSDate extends JSCallable {
         return toLocale_helper(date, localeDateTimeFormatter);
     }
 
-    private static String jsJSFunction_toLocaleTimeString(double date) {
+    private static String toLocaleTimeString(double date) {
         if (localeTimeFormatter == null)
             localeTimeFormatter = DateFormat.getTimeInstance(DateFormat.LONG);
 
         return toLocale_helper(date, localeTimeFormatter);
     }
 
-    private static String jsJSFunction_toLocaleDateString(double date) {
+    private static String toLocaleDateString(double date) {
         if (localeDateFormatter == null)
             localeDateFormatter = DateFormat.getDateInstance(DateFormat.LONG);
 
         return toLocale_helper(date, localeDateFormatter);
     }
 
-    private static String jsJSFunction_toUTCString(double date) {
+    private static String toUTCString(double date) {
         StringBuffer result = new StringBuffer(60);
 
         String dateStr = Integer.toString(DateFromTime(date));
@@ -1140,17 +1052,17 @@ public class JSDate extends JSCallable {
         return result.toString();
     }
 
-    private static double jsJSFunction_getYear(double date) {
+    private static double getYear(double date) {
         int result = YearFromTime(LocalTime(date));
         result -= 1900;
         return result;
     }
 
-    private static double jsJSFunction_getTimezoneOffset(double date) {
+    private static double getTimezoneOffset(double date) {
         return (date - LocalTime(date)) / msPerMinute;
     }
 
-    public double jsJSFunction_setTime(double time) {
+    public double setTime(double time) {
         this.date = TimeClip(time);
         return this.date;
     }
@@ -1231,11 +1143,11 @@ public class JSDate extends JSCallable {
         return date;
     }
 
-    private double jsJSFunction_setHours(Object[] args) {
+    private double setHours(Object[] args) {
         return makeTime(args, 4, true);
     }
 
-    private double jsJSFunction_setUTCHours(Object[] args) {
+    private double setUTCHours(Object[] args) {
         return makeTime(args, 4, false);
     }
 
@@ -1308,7 +1220,7 @@ public class JSDate extends JSCallable {
         return date;
     }
 
-    private double jsJSFunction_setYear(double year) {
+    private double setYear(double year) {
         double day, result;
         if (year != year || Double.isInfinite(year)) {
             this.date = Double.NaN;
@@ -1332,228 +1244,9 @@ public class JSDate extends JSCallable {
         return this.date;
     }
 
-    protected String getIdName(int id) {
-            switch (id) {
-                case ConstructorId_UTC:     return "UTC";
-                case ConstructorId_parse:   return "parse";
-                case Id_constructor:        return "constructor"; 
-                case Id_toString:           return "toString";
-                case Id_toTimeString:       return "toTimeString";
-                case Id_toDateString:       return "toDateString";
-                case Id_toLocaleString:     return "toLocaleString";
-                case Id_toLocaleTimeString: return "toLocaleTimeString";
-                case Id_toLocaleDateString: return "toLocaleDateString";
-                case Id_toUTCString:        return "toUTCString";
-                case Id_valueOf:            return "valueOf";
-                case Id_getTime:            return "getTime";
-                case Id_getYear:            return "getYear";
-                case Id_getFullYear:        return "getFullYear";
-                case Id_getUTCFullYear:     return "getUTCFullYear";
-                case Id_getMonth:           return "getMonth";
-                case Id_getUTCMonth:        return "getUTCMonth";
-                case Id_getDate:            return "getDate";
-                case Id_getUTCDate:         return "getUTCDate";
-                case Id_getDay:             return "getDay";
-                case Id_getUTCDay:          return "getUTCDay";
-                case Id_getHours:           return "getHours";
-                case Id_getUTCHours:        return "getUTCHours";
-                case Id_getMinutes:         return "getMinutes";
-                case Id_getUTCMinutes:      return "getUTCMinutes";
-                case Id_getSeconds:         return "getSeconds";
-                case Id_getUTCSeconds:      return "getUTCSeconds";
-                case Id_getMilliseconds:    return "getMilliseconds";
-                case Id_getUTCMilliseconds: return "getUTCMilliseconds";
-                case Id_getTimezoneOffset:  return "getTimezoneOffset";
-                case Id_setTime:            return "setTime";
-                case Id_setMilliseconds:    return "setMilliseconds";
-                case Id_setUTCMilliseconds: return "setUTCMilliseconds";
-                case Id_setSeconds:         return "setSeconds";
-                case Id_setUTCSeconds:      return "setUTCSeconds";
-                case Id_setMinutes:         return "setMinutes";
-                case Id_setUTCMinutes:      return "setUTCMinutes";
-                case Id_setHours:           return "setHours";
-                case Id_setUTCHours:        return "setUTCHours";
-                case Id_setDate:            return "setDate";
-                case Id_setUTCDate:         return "setUTCDate";
-                case Id_setMonth:           return "setMonth";
-                case Id_setUTCMonth:        return "setUTCMonth";
-                case Id_setFullYear:        return "setFullYear";
-                case Id_setUTCFullYear:     return "setUTCFullYear";
-                case Id_setYear:            return "setYear";
-            }
-        return null;        
-    }
-
-// #string_id_map#
-
-    protected int mapNameToId(String s) {
-        int id;
-// #generated# Last update: 2001-04-22 23:46:59 CEST
-        L0: { id = 0; String X = null; int c;
-            L: switch (s.length()) {
-            case 6: X="getDay";id=Id_getDay; break L;
-            case 7: switch (s.charAt(3)) {
-                case 'D': c=s.charAt(0);
-                    if (c=='g') { X="getDate";id=Id_getDate; }
-                    else if (c=='s') { X="setDate";id=Id_setDate; }
-                    break L;
-                case 'T': c=s.charAt(0);
-                    if (c=='g') { X="getTime";id=Id_getTime; }
-                    else if (c=='s') { X="setTime";id=Id_setTime; }
-                    break L;
-                case 'Y': c=s.charAt(0);
-                    if (c=='g') { X="getYear";id=Id_getYear; }
-                    else if (c=='s') { X="setYear";id=Id_setYear; }
-                    break L;
-                case 'u': X="valueOf";id=Id_valueOf; break L;
-                } break L;
-            case 8: c=s.charAt(0);
-                if (c=='g') {
-                    c=s.charAt(7);
-                    if (c=='h') { X="getMonth";id=Id_getMonth; }
-                    else if (c=='s') { X="getHours";id=Id_getHours; }
-                }
-                else if (c=='s') {
-                    c=s.charAt(7);
-                    if (c=='h') { X="setMonth";id=Id_setMonth; }
-                    else if (c=='s') { X="setHours";id=Id_setHours; }
-                }
-                else if (c=='t') { X="toString";id=Id_toString; }
-                break L;
-            case 9: X="getUTCDay";id=Id_getUTCDay; break L;
-            case 10: c=s.charAt(3);
-                if (c=='M') {
-                    c=s.charAt(0);
-                    if (c=='g') { X="getMinutes";id=Id_getMinutes; }
-                    else if (c=='s') { X="setMinutes";id=Id_setMinutes; }
-                }
-                else if (c=='S') {
-                    c=s.charAt(0);
-                    if (c=='g') { X="getSeconds";id=Id_getSeconds; }
-                    else if (c=='s') { X="setSeconds";id=Id_setSeconds; }
-                }
-                else if (c=='U') {
-                    c=s.charAt(0);
-                    if (c=='g') { X="getUTCDate";id=Id_getUTCDate; }
-                    else if (c=='s') { X="setUTCDate";id=Id_setUTCDate; }
-                }
-                break L;
-            case 11: switch (s.charAt(3)) {
-                case 'F': c=s.charAt(0);
-                    if (c=='g') { X="getFullYear";id=Id_getFullYear; }
-                    else if (c=='s') { X="setFullYear";id=Id_setFullYear; }
-                    break L;
-                case 'M': X="toGMTString";id=Id_toGMTString; break L;
-                case 'T': X="toUTCString";id=Id_toUTCString; break L;
-                case 'U': c=s.charAt(0);
-                    if (c=='g') {
-                        c=s.charAt(9);
-                        if (c=='r') { X="getUTCHours";id=Id_getUTCHours; }
-                        else if (c=='t') { X="getUTCMonth";id=Id_getUTCMonth; }
-                    }
-                    else if (c=='s') {
-                        c=s.charAt(9);
-                        if (c=='r') { X="setUTCHours";id=Id_setUTCHours; }
-                        else if (c=='t') { X="setUTCMonth";id=Id_setUTCMonth; }
-                    }
-                    break L;
-                case 's': X="constructor";id=Id_constructor; break L;
-                } break L;
-            case 12: c=s.charAt(2);
-                if (c=='D') { X="toDateString";id=Id_toDateString; }
-                else if (c=='T') { X="toTimeString";id=Id_toTimeString; }
-                break L;
-            case 13: c=s.charAt(0);
-                if (c=='g') {
-                    c=s.charAt(6);
-                    if (c=='M') { X="getUTCMinutes";id=Id_getUTCMinutes; }
-                    else if (c=='S') { X="getUTCSeconds";id=Id_getUTCSeconds; }
-                }
-                else if (c=='s') {
-                    c=s.charAt(6);
-                    if (c=='M') { X="setUTCMinutes";id=Id_setUTCMinutes; }
-                    else if (c=='S') { X="setUTCSeconds";id=Id_setUTCSeconds; }
-                }
-                break L;
-            case 14: c=s.charAt(0);
-                if (c=='g') { X="getUTCFullYear";id=Id_getUTCFullYear; }
-                else if (c=='s') { X="setUTCFullYear";id=Id_setUTCFullYear; }
-                else if (c=='t') { X="toLocaleString";id=Id_toLocaleString; }
-                break L;
-            case 15: c=s.charAt(0);
-                if (c=='g') { X="getMilliseconds";id=Id_getMilliseconds; }
-                else if (c=='s') { X="setMilliseconds";id=Id_setMilliseconds; }
-                break L;
-            case 17: X="getTimezoneOffset";id=Id_getTimezoneOffset; break L;
-            case 18: c=s.charAt(0);
-                if (c=='g') { X="getUTCMilliseconds";id=Id_getUTCMilliseconds; }
-                else if (c=='s') { X="setUTCMilliseconds";id=Id_setUTCMilliseconds; }
-                else if (c=='t') {
-                    c=s.charAt(8);
-                    if (c=='D') { X="toLocaleDateString";id=Id_toLocaleDateString; }
-                    else if (c=='T') { X="toLocaleTimeString";id=Id_toLocaleTimeString; }
-                }
-                break L;
-            }
-            if (X!=null && X!=s && !X.equals(s)) id = 0;
-        }
-// #/generated#
-        return id;
-    }
 
-    private static final int
-        ConstructorId_UTC       = -2,
-        ConstructorId_parse     = -1,
-
-        Id_constructor          =  1,
-        Id_toString             =  2,
-        Id_toTimeString         =  3,
-        Id_toDateString         =  4,
-        Id_toLocaleString       =  5,
-        Id_toLocaleTimeString   =  6,
-        Id_toLocaleDateString   =  7,
-        Id_toUTCString          =  8,
-        Id_valueOf              =  9,
-        Id_getTime              = 10,
-        Id_getYear              = 11,
-        Id_getFullYear          = 12,
-        Id_getUTCFullYear       = 13,
-        Id_getMonth             = 14,
-        Id_getUTCMonth          = 15,
-        Id_getDate              = 16,
-        Id_getUTCDate           = 17,
-        Id_getDay               = 18,
-        Id_getUTCDay            = 19,
-        Id_getHours             = 20,
-        Id_getUTCHours          = 21,
-        Id_getMinutes           = 22,
-        Id_getUTCMinutes        = 23,
-        Id_getSeconds           = 24,
-        Id_getUTCSeconds        = 25,
-        Id_getMilliseconds      = 26,
-        Id_getUTCMilliseconds   = 27,
-        Id_getTimezoneOffset    = 28,
-        Id_setTime              = 29,
-        Id_setMilliseconds      = 30,
-        Id_setUTCMilliseconds   = 31,
-        Id_setSeconds           = 32,
-        Id_setUTCSeconds        = 33,
-        Id_setMinutes           = 34,
-        Id_setUTCMinutes        = 35,
-        Id_setHours             = 36,
-        Id_setUTCHours          = 37,
-        Id_setDate              = 38,
-        Id_setUTCDate           = 39,
-        Id_setMonth             = 40,
-        Id_setUTCMonth          = 41,
-        Id_setFullYear          = 42,
-        Id_setUTCFullYear       = 43,
-        Id_setYear              = 44,
-
-        MAX_PROTOTYPE_ID        = 44;
-
-    private static final int
-        Id_toGMTString  =  Id_toUTCString; // Alias, see Ecma B.2.6
+    //    private static final int
+    //        Id_toGMTString  =  Id_toUTCString; // Alias, see Ecma B.2.6
 // #/string_id_map#
 
     /* cached values */
index 55741a5..92e3eff 100644 (file)
@@ -55,8 +55,13 @@ public class JSFunction extends JSCallable implements ByteCodes, Tokens {
     }
 
     /** Note: code gets run in an <i>unpauseable</i> context. */
-    public Object call(JSArray args) {
+    public Object call(Object a0, Object a1, Object a2, Object[] rest, int nargs) {
         JSContext cx = new JSContext(this, false);
+        JSArray args = new JSArray();
+        if (nargs > 0) args.addElement(a0);
+        if (nargs > 1) args.addElement(a1);
+        if (nargs > 2) args.addElement(a2);
+        for(int i=3; i<nargs; i++) args.addElement(rest[i-3]);
         cx.invoke(args);
         return cx.stack.pop();
     }
index 91a8a9e..7a27f28 100644 (file)
@@ -10,35 +10,6 @@ public class JSMath extends JSCallable {
 
     public static JSMath singleton = new JSMath();
 
-    public Object call(Object method, JSArray args) {
-        if (method == null) throw new JS.Exn("you cannot call this object");
-        //#switch(method)
-        case "ceil": return new Long((long)java.lang.Math.ceil(JS.toNumber(args.elementAt(0)).doubleValue()));
-        case "floor": return new Long((long)java.lang.Math.floor(JS.toNumber(args.elementAt(0)).doubleValue()));
-        case "round": return new Long((long)java.lang.Math.round(JS.toNumber(args.elementAt(0)).doubleValue()));
-        case "min": return new Double(java.lang.Math.min(JS.toNumber(args.elementAt(0)).doubleValue(),
-                                                         JS.toNumber(args.elementAt(1)).doubleValue()));
-        case "max": return new Double(java.lang.Math.max(JS.toNumber(args.elementAt(0)).doubleValue(),
-                                                         JS.toNumber(args.elementAt(1)).doubleValue()));
-        case "pow": return new Double(java.lang.Math.pow(JS.toNumber(args.elementAt(0)).doubleValue(),
-                                                         JS.toNumber(args.elementAt(1)).doubleValue()));
-        case "atan2": return new Double(java.lang.Math.atan2(JS.toNumber(args.elementAt(0)).doubleValue(),
-                                                             JS.toNumber(args.elementAt(1)).doubleValue()));
-        case "abs": return new Double(java.lang.Math.abs(JS.toNumber(args.elementAt(0)).doubleValue()));
-        case "sin": return new Double(java.lang.Math.sin(JS.toNumber(args.elementAt(0)).doubleValue()));
-        case "cos": return new Double(java.lang.Math.cos(JS.toNumber(args.elementAt(0)).doubleValue()));
-        case "tan": return new Double(java.lang.Math.tan(JS.toNumber(args.elementAt(0)).doubleValue()));
-        case "asin": return new Double(java.lang.Math.asin(JS.toNumber(args.elementAt(0)).doubleValue()));
-        case "acos": return new Double(java.lang.Math.acos(JS.toNumber(args.elementAt(0)).doubleValue()));
-        case "atan": return new Double(java.lang.Math.atan(JS.toNumber(args.elementAt(0)).doubleValue()));
-        case "sqrt": return new Double(java.lang.Math.sqrt(JS.toNumber(args.elementAt(0)).doubleValue()));
-        case "exp": return new Double(java.lang.Math.exp(JS.toNumber(args.elementAt(0)).doubleValue()));
-        case "log": return new Double(java.lang.Math.log(JS.toNumber(args.elementAt(0)).doubleValue()));
-        case "random": return new Double(java.lang.Math.random());
-        //#end
-        return null;
-    }
-
     private static final Double E       = new Double(java.lang.Math.E);
     private static final Double PI      = new Double(java.lang.Math.PI);
     private static final Double LN10    = new Double(java.lang.Math.log(10));
@@ -48,9 +19,48 @@ public class JSMath extends JSCallable {
     private static final Double SQRT1_2 = new Double(1/java.lang.Math.sqrt(2));
     private static final Double SQRT2   = new Double(java.lang.Math.sqrt(2));
 
+    public Object callMethod(Object method, Object a0, Object a1, Object a2, Object[] rest, int nargs) {
+        switch(nargs) {
+            case 0: {
+                //#switch(method)
+                case "random": return new Double(java.lang.Math.random());
+                //#end
+                break;
+            }
+            case 1: {
+                //#switch(method)
+                case "ceil": return new Long((long)java.lang.Math.ceil(toDouble(a0)));
+                case "floor": return new Long((long)java.lang.Math.floor(toDouble(a0)));
+                case "round": return new Long((long)java.lang.Math.round(toDouble(a0)));
+                case "abs": return new Double(java.lang.Math.abs(toDouble(a0)));
+                case "sin": return new Double(java.lang.Math.sin(toDouble(a0)));
+                case "cos": return new Double(java.lang.Math.cos(toDouble(a0)));
+                case "tan": return new Double(java.lang.Math.tan(toDouble(a0)));
+                case "asin": return new Double(java.lang.Math.asin(toDouble(a0)));
+                case "acos": return new Double(java.lang.Math.acos(toDouble(a0)));
+                case "atan": return new Double(java.lang.Math.atan(toDouble(a0)));
+                case "sqrt": return new Double(java.lang.Math.sqrt(toDouble(a0)));
+                case "exp": return new Double(java.lang.Math.exp(toDouble(a0)));
+                case "log": return new Double(java.lang.Math.log(toDouble(a0)));
+                //#end
+                break;
+            }
+            case 2: {
+                //#switch(method)
+                case "min": return new Double(java.lang.Math.min(toDouble(a0), toDouble(a1)));
+                case "max": return new Double(java.lang.Math.max(toDouble(a0), toDouble(a1)));
+                case "pow": return new Double(java.lang.Math.pow(toDouble(a0), toDouble(a1)));
+                case "atan2": return new Double(java.lang.Math.atan2(toDouble(a0), toDouble(a1)));
+                //#end
+                break;
+            }
+        }
+        return super.callMethod(method, a0, a1, a2, rest, nargs);
+    }
+
     public void put(Object key, Object val) { return; }
 
-    public Object get(Object key, Object val) {
+    public Object get(Object key) {
         //#switch(key)
         case "E": return E;
         case "LN10": return LN10;
@@ -60,7 +70,25 @@ public class JSMath extends JSCallable {
         case "PI": return PI;
         case "SQRT1_2": return SQRT1_2;
         case "SQRT2": return SQRT2;
+        case "ceil": return METHOD;
+        case "floor": return METHOD;
+        case "round": return METHOD;
+        case "min": return METHOD;
+        case "max": return METHOD;
+        case "pow": return METHOD;
+        case "atan2": return METHOD;
+        case "abs": return METHOD;
+        case "sin": return METHOD;
+        case "cos": return METHOD;
+        case "tan": return METHOD;
+        case "asin": return METHOD;
+        case "acos": return METHOD;
+        case "atan": return METHOD;
+        case "sqrt": return METHOD;
+        case "exp": return METHOD;
+        case "log": return METHOD;
+        case "random": return METHOD;
         //#end
-        return null;
+        return super.get(key);
     }
 }
diff --git a/src/org/xwt/js/JSObj.java b/src/org/xwt/js/JSObj.java
deleted file mode 100644 (file)
index e096521..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-package org.xwt.js;
-import java.util.*;
-import org.xwt.util.*;
-
-// FEATURE: static slots for four objects?
-/** A sensible implementation of the abstract methods in the JS class */
-public class JSObj extends JS {
-    
-    // this gets around a wierd fluke in the Java type checking rules for ?..:
-    public static final Object T = Boolean.TRUE;
-    public static final Object F = Boolean.FALSE;
-
-    // FEATURE: be smart here; perhaps intern
-    public static final Number N(int i) { return new Integer(i); }
-    public static final Number N(long l) { return new Long(l); }
-    public static final Number N(double d) { return new Double(d); }
-    public static final Boolean B(boolean b) { return b ? Boolean.TRUE : Boolean.FALSE; }
-    
-    private static Enumeration emptyEnumeration = new Enumeration() {
-            public boolean hasMoreElements() { return false; }
-            public Object nextElement() { throw new NoSuchElementException(); }
-        };
-    
-    private Hash entries = null;
-    public JSObj() { }
-    public Enumeration keys() { return entries == null ? emptyEnumeration : entries.keys(); }
-    public Object get(Object key) { return entries == null ? null : entries.get(key, null); }
-    public void put(Object key, Object val) { if (entries == null) entries = new Hash(); entries.put(key, null, val); }
-
-    // note that we don't actually implement trappable... we just provide these for subclasses which choose to
-    public JSTrap getTrap(Object key) { return entries == null ? null : (JSTrap)entries.get(key, JSTrap.class); }
-    public void putTrap(Object key, JSTrap t) { if (entries == null) entries = new Hash(); entries.put(key, JSTrap.class, t); }
-}
index b0359ba..819e1f3 100644 (file)
@@ -28,34 +28,38 @@ public class JSRegexp extends JSCallable {
                 }
             }
             re = newRE(pattern,flags);
-            _put("source",pattern);
-            _put("global",wrapBool(global));
-            _put("ignoreCase",wrapBool(flags & RE.REG_ICASE));
-            _put("multiline",wrapBool(flags & RE.REG_MULTILINE));
+            put("source",pattern);
+            put("global",wrapBool(global));
+            put("ignoreCase",wrapBool(flags & RE.REG_ICASE));
+            put("multiline",wrapBool(flags & RE.REG_MULTILINE));
         }
     }
 
-    public Object call(Object method, JSArray args) throws JS.Exn {
-        if (method.equals("exec")) {
-            return exec(args);
-        } else if (method.equals("test")) {
-            return test(args);
-        } else if (method.equals("toString")) {
-            return toString();
+    public Object callMethod(Object method, Object a0, Object a1, Object a2, Object[] rest, int nargs) {
+        switch(nargs) {
+            case 1: {
+                //#switch(method)
+                case "exec": return exec((String)a0);
+                case "test": return test((String)a0);
+                case "toString": return toString(a0);
+                //#end
+                break;
+            }
         }
-        return null;
+        return super.callMethod(method, a0, a1, a2, rest, nargs);
     }
     
-    // gcj bug...
-    public Object get(Object key) { return _get(key); }
-    public void put(Object key,Object value) { _put(key,value); }
-
-    public Object _get(Object key) {
-        if(key.equals("lastIndex")) return new Integer(lastIndex);
+    public Object get(Object key) {
+        //#switch(key)
+        case "exec": return METHOD;
+        case "test": return METHOD;
+        case "toString": return METHOD;
+        case "lastIndex": return new Integer(lastIndex);
+        //#end
         return super.get(key);
     }
     
-    public void _put(Object key, Object value) {
+    public void put(Object key, Object value) {
         if(key.equals("lastIndex")) lastIndex = JS.toNumber(value).intValue();
         super.put(key,value);
     }
@@ -77,7 +81,7 @@ public class JSRegexp extends JSCallable {
     }
     
     private static Object matchToExecResult(REMatch match, RE re, String s) {
-        JSObj ret = new JSObj();
+        JS ret = new JS();
         ret.put("index",new Integer(match.getStartIndex()));
         ret.put("input",s);
         int n = re.getNumSubs();
@@ -95,10 +99,7 @@ public class JSRegexp extends JSCallable {
         return exec(s);
     }
     
-    private Object test(JSArray args)  throws JS.Exn {
-        if(args.length() < 1) throw new JS.Exn("Not enough args to match");
-        String s = args.elementAt(0).toString();
-        
+    private Object test(String s)  throws JS.Exn {
         if(global) {
             int start = global ? lastIndex : 0;
             if(start < 0 || start >= s.length()) {
@@ -117,11 +118,11 @@ public class JSRegexp extends JSCallable {
     public String toString() {
         StringBuffer sb = new StringBuffer();
         sb.append('/');
-        sb.append(_get("source"));
+        sb.append(get("source"));
         sb.append('/');
         if(global) sb.append('g');
-        if(Boolean.TRUE.equals(_get("ignoreCase"))) sb.append('i');
-        if(Boolean.TRUE.equals(_get("multiline"))) sb.append('m');
+        if(Boolean.TRUE.equals(get("ignoreCase"))) sb.append('i');
+        if(Boolean.TRUE.equals(get("multiline"))) sb.append('m');
         return sb.toString();
     }
     
index 54dc446..44bfec1 100644 (file)
@@ -34,39 +34,61 @@ public class JSScope extends JSCallable {
         private final static Double NaN = new Double(Double.NaN);
         private final static Double POSITIVE_INFINITY = new Double(Double.POSITIVE_INFINITY);
     
-        public Global(JSScope parent) {
-            super(parent);
-        }
-        public Object get(Object key) {
-            if(key.equals("NaN")) return NaN;
-            if(key.equals("Infinity")) return POSITIVE_INFINITY;
-            if(key.equals("undefined")) return null;
-            return super.get(key);
-        }
-
-        public Object call(Object method, JSArray args) {
-            if (method.equals("stringFromCharCode")) return stringFromCharCode(args);
-            return super.call(method, args);
-        }
+        public Global(JSScope parent) { super(parent); }
 
-        public Object call1(Object method, Object arg0) {
-            //#switch(method)
-            case "parseInt": return parseInt(arg0, N(0));
-            case "isNaN": { double d = toDouble(arg0); return d == d ? F : T; }
-            case "isFinite": { double d = toDouble(arg0); return (d == d && !Double.isInfinite(d)) ? T : F; }
-            case "decodeURI": throw new JS.Exn("unimplemented");
-            case "decodeURIComponent": throw new JS.Exn("unimplemented");
-            case "encodeURI": throw new JS.Exn("unimplemented");
-            case "encodeURIComponent": throw new JS.Exn("unimplemented");
-            case "escape": throw new JS.Exn("unimplemented");
-            case "unescape": throw new JS.Exn("unimplemented");
+        public Object get(Object key) {
+            //#switch(key)
+            case "NaN": return NaN;
+            case "Infinity": return POSITIVE_INFINITY;
+            case "undefined": return null;
+            case "stringFromCharCode": return METHOD;
+            case "parseInt": return METHOD;
+            case "isNaN": return METHOD;
+            case "isFinite": return METHOD;
+            case "decodeURI": return METHOD;
+            case "decodeURIComponent": return METHOD;
+            case "encodeURI": return METHOD;
+            case "encodeURIComponent": return METHOD;
+            case "escape": return METHOD;
+            case "unescape": return METHOD;
+            case "parseInt": return METHOD;
             //#end
-            return super.call1(method, arg0);
+            return super.get(key);
         }
 
-        public Object call2(Object method, Object arg1, Object arg2) {
-            if (method.equals("parseInt")) return parseInt(arg1, arg2);
-            return super.call2(method, arg1, arg2);
+        public Object callMethod(Object method, Object a0, Object a1, Object a2, Object[] rest, int nargs) {
+            switch(nargs) {
+                case 0: {
+                    //#switch(method)
+                    case "stringFromCharCode":
+                        JSArray args = new JSArray();
+                        for(int i=0; i<nargs; i++) args.addElement(i==0?a0:i==1?a1:i==2?a2:rest[i-3]);
+                        return stringFromCharCode(args);
+                    default: break;
+                    //#end
+                }
+                case 1: {
+                    //#switch(method)
+                    case "parseInt": return parseInt(a0, N(0));
+                    case "isNaN": { double d = toDouble(a0); return d == d ? F : T; }
+                    case "isFinite": { double d = toDouble(a0); return (d == d && !Double.isInfinite(d)) ? T : F; }
+                    case "decodeURI": throw new JS.Exn("unimplemented");
+                    case "decodeURIComponent": throw new JS.Exn("unimplemented");
+                    case "encodeURI": throw new JS.Exn("unimplemented");
+                    case "encodeURIComponent": throw new JS.Exn("unimplemented");
+                    case "escape": throw new JS.Exn("unimplemented");
+                    case "unescape": throw new JS.Exn("unimplemented");
+                    default: break;
+                    //#end
+                }
+                case 2: {
+                    //#switch(method)
+                    case "parseInt": return parseInt(a0, a1);
+                    default: break;
+                    //#end
+                }
+            }
+            return super.callMethod(method, a0, a1, a2, rest, nargs);
         }
 
         private Object stringFromCharCode(JSArray args) {
index 055a1c3..4801971 100644 (file)
@@ -52,7 +52,7 @@ public class HTML {
 
     public static synchronized JS parseReader(Reader r) throws IOException {
         CharStream cs = new CharStream(r);
-        JSObj h = new JSObj();
+        JS h = new JS();
 
         withinLI = false;
         h.put("$name", "html");
@@ -163,7 +163,7 @@ public class HTML {
             try {
                 // scan subelement
                 if (cs.peek() != '/') {
-                    JS kid = new JSObj();
+                    JS kid = new JS();
                     closetag = parseElement(cs, kid);
                     h.put(String.valueOf(length), kid); 
                     h.put("$numchildren", new Integer(++length));