cloneable is an interface
[org.ibex.core.git] / src / org / ibex / core / Ibex.java
index d97a9d5..7b5f8b5 100644 (file)
@@ -1,18 +1,21 @@
 // Copyright 2004 Adam Megacz, see the COPYING file for licensing [GPL]
-package org.ibex;
+package org.ibex.core;
 
 import java.io.*;
 import org.ibex.js.*;
 import org.ibex.util.*;
-import org.bouncycastle.util.encoders.Base64;
+import org.ibex.graphics.*;
+import org.ibex.plat.*;
+import org.ibex.net.*;
+import org.ibex.crypto.*;
 
 /** Singleton class that provides all functionality in the ibex.* namespace */
-public final class Ibex extends JS.Cloneable {
+public final class Ibex extends JS implements JS.Cloneable {
 
     // FIXME remove this
     private final JS rr;
 
-    public Ibex(Stream rr) { this.rr = bless(rr); }
+    public Ibex(Stream rr) { try { this.rr = bless(rr);} catch(JSExn e) { throw new Error("should never happen"); } }
 
     public JS resolveString(String str, boolean permitAbsolute) throws JSExn {
         if (str.indexOf("://") != -1) {
@@ -125,7 +128,7 @@ public final class Ibex extends JS.Cloneable {
 
     public void put(Object name, final Object value) throws JSExn {
         //#switch(name)
-        case "thread": Scheduler.add((Scheduler.Task)value); return;
+        case "thread": Scheduler.add((Task)value); return;
         case "ui.clipboard": Platform.setClipBoard((String)value); return;
         case "ui.frame": Platform.createSurface((Box)value, true, true); return;
         case "ui.window": Platform.createSurface((Box)value, false, true); return;
@@ -158,8 +161,8 @@ public final class Ibex extends JS.Cloneable {
                 case 1:
                     //#switch(name)
                     case "clone":
-                        if (!(a instanceof JS.Cloneable)) throw new JSExn("cannot clone a " + a.getClass().getName());
-                        return ((JS.Cloneable)a).jsclone();
+                        if(a == null) throw new JSExn("can't clone the null value");
+                        return ((JS)a).jsclone();
                     case "bless": return bless((JS)a);
                     case "ui.browser": Platform.newBrowserWindow((String)a); return null;
                     case "stream.unzip": return new Stream.Zip((Stream)a);
@@ -238,36 +241,59 @@ public final class Ibex extends JS.Cloneable {
     }
     
     public static final JSMath ibexMath = new JSMath() {
+            // FEATURE: find a cleaner way to do this
             private JS gs = new JSScope.Global();
             public Object get(Object key) throws JSExn {
                 //#switch(key)
-                case "isNaN": return gs.get("isNaN");
-                case "isFinite": return gs.get("isFinite");
-                case "NaN": return gs.get("NaN");
-                case "Infinity": return gs.get("Infinity");
+                case "isNaN": return METHOD;
+                case "isFinite": return METHOD;
+                case "NaN": return METHOD;
+                case "Infinity": return METHOD;
                 //#end
                 return super.get(key);
             }
-        };
+            public Object callMethod(Object name, Object a, Object b, Object c, Object[] rest, int nargs) throws JSExn {
+                //#switch(name)
+                case "isNaN": return gs.callMethod(name,a,b,c,rest,nargs);
+                case "isFinite": return gs.callMethod(name,a,b,c,rest,nargs);
+                case "NaN": return gs.callMethod(name,a,b,c,rest,nargs);
+                case "Infinity": return gs.callMethod(name,a,b,c,rest,nargs);
+                //#end
+                return super.callMethod(name,a,b,c,rest,nargs);
+            }
+    };
 
     public static final JS ibexString = new JS() {
             private JS gs = new JSScope.Global();
-            public void put(Object key, Object val) { }
             public Object get(Object key) throws JSExn {
                 //#switch(key)
-                case "parseInt": return gs.get("parseInt");
-                case "parseFloat": return gs.get("parseFloat");
-                case "decodeURI": return gs.get("decodeURI");
-                case "decodeURIComponent": return gs.get("decodeURIComponent");
-                case "encodeURI": return gs.get("encodeURI");
-                case "encodeURIComponent": return gs.get("encodeURIComponent");
-                case "escape": return gs.get("escape");
-                case "unescape": return gs.get("unescape");
-                case "fromCharCode": return gs.get("stringFromCharCode");
+                case "parseInt": return METHOD;
+                case "parseFloat": 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 "fromCharCode": return METHOD;
                 //#end
-                return null;
+                return super.get(key);
+            }
+            public Object callMethod(Object name, Object a, Object b, Object c, Object[] rest, int nargs) throws JSExn {
+                //#switch(name)
+                case "parseInt": return gs.callMethod(name,a,b,c,rest,nargs);
+                case "parseFloat": return gs.callMethod(name,a,b,c,rest,nargs);
+                case "decodeURI": return gs.callMethod(name,a,b,c,rest,nargs);
+                case "decodeURIComponent": return gs.callMethod(name,a,b,c,rest,nargs);
+                case "encodeURI": return gs.callMethod(name,a,b,c,rest,nargs);
+                case "encodeURIComponent": return gs.callMethod(name,a,b,c,rest,nargs);
+                case "escape": return gs.callMethod(name,a,b,c,rest,nargs);
+                case "unescape": return gs.callMethod(name,a,b,c,rest,nargs);
+                case "fromCharCode": return gs.callMethod(name,a,b,c,rest,nargs);
+                //#end
+                return super.callMethod(name,a,b,c,rest,nargs);
             }
-        };
+    };
 
     private class XMLHelper extends XML {
         private class Wrapper extends XML.Exn { public JSExn wrapee; public Wrapper(JSExn jse) { super(""); wrapee = jse; } }
@@ -315,19 +341,20 @@ public final class Ibex extends JS.Cloneable {
     }
 
     // FEATURE: move this into builtin.xwar
-    public Blessing bless(JS b) { return new Ibex.Blessing((JS.Cloneable)b, this, null, null); }
+    public Blessing bless(JS b) throws JSExn { return new Ibex.Blessing(b, this, null, null); }
+    // FIXME: Does this really need to extends JS.Clone?
     public static class Blessing extends JS.Clone {
         private Ibex ibex;
         private Template t = null;
         public Object parentkey = null;
         public Blessing parent = null;
         private Hash cache = new Hash();
-        public Blessing(JS.Cloneable clonee, Ibex ibex, Blessing parent, Object parentkey) {
+        public Blessing(JS clonee, Ibex ibex, Blessing parent, Object parentkey) throws JSExn {
             super(clonee); this.ibex = ibex; this.parentkey = parentkey; this.parent = parent; }
         public Object get(Object key) throws JSExn {
             if (key.equals("")) return ((Object)getStatic());
             if (cache.get(key) != null) return cache.get(key);
-            Object ret = new Blessing((JS.Cloneable)clonee.get(key), ibex, this, key);
+            Object ret = new Blessing((JS)clonee.get(key), ibex, this, key);
             cache.put(key, ret);
             return ret;
         }
@@ -353,7 +380,10 @@ public final class Ibex extends JS.Cloneable {
         }
         public JSScope getStatic() {
             try {
-                if (t == null) t = Template.buildTemplate(parentkey + ".t", parent.get(parentkey + ".t"), ibex);
+                if (t == null) {
+                    JS res = (JS) parent.get(parentkey + ".t");
+                    t = Template.buildTemplate(res.unclone().toString(), res, ibex);
+                }
                 return t.staticScope;
             } catch (Exception e) {
                 Log.error(this, e);