move JS's Hashtable to JS.O
authorbrian <brian@brianweb.net>
Sat, 3 Jul 2004 17:22:04 +0000 (17:22 +0000)
committerbrian <brian@brianweb.net>
Sat, 3 Jul 2004 17:22:04 +0000 (17:22 +0000)
darcs-hash:20040703172204-24bed-f5fa869bb332cc32377a1abdba413b6e4a29c254.gz

13 files changed:
src/org/ibex/core/Box.java
src/org/ibex/core/Ibex.java
src/org/ibex/core/Template.java
src/org/ibex/graphics/HTML.java
src/org/ibex/js/Interpreter.java
src/org/ibex/js/JS.java
src/org/ibex/js/JSArray.java
src/org/ibex/js/JSRegexp.java
src/org/ibex/js/JSScope.java
src/org/ibex/net/HTTP.java
src/org/ibex/net/SOAP.java
src/org/ibex/net/XMLRPC.java
src/org/ibex/util/BalancedTree.java

index e39e201..bb8a27b 100644 (file)
@@ -232,7 +232,7 @@ public final class Box extends JSScope implements Task {
     
     void resize(int x, int y, int width, int height) {
         if (x == this.x && y == this.y && width == this.width && height == this.height) return;
-        boolean sizechange = (this.width != width || this.height != height) && getTrap("SizeChange") != null;
+        boolean sizechange = (this.width != width || this.height != height) && hasTrap("SizeChange");
         int thisx = parent == null ? 0 : this.x;
         int thisy = parent == null ? 0 : this.y;
         Box who = (parent == null ? this : parent);
@@ -448,7 +448,7 @@ public final class Box extends JSScope implements Task {
 
                 case "distanceto":
                     Box b = (Box)a0;
-                    JS ret = new JS();
+                    JS ret = new JS.O();
                     ret.put("x", N(b.localToGlobalX(0) - localToGlobalX(0)));
                     ret.put("y", N(b.localToGlobalY(0) - localToGlobalY(0)));
                     return ret;
index 7b5f8b5..b44ba5a 100644 (file)
@@ -307,7 +307,7 @@ public final class Ibex extends JS implements JS.Cloneable {
         }
 
         public void startElement(XML.Element c) throws XML.Exn { try {
-                JS attrs = new JS();
+                JS attrs = new JS.O();
                 // FIXME attribute URIs? add an additional hash?
                 for(int i=0; i<c.getAttrLen(); i++) attrs.put(c.getAttrKey(i), c.getAttrVal(i));
                 startElement.call(c.getLocalName(), attrs, c.getUri(), null, 3);
index 6e29c4a..1e742c4 100644 (file)
@@ -166,7 +166,7 @@ public class Template {
             initial_uri = "";
             parse(new InputStreamReader(is));
             JS staticScript = parseScript(static_content, static_content_start);
-            t.staticObject = new JS();
+            t.staticObject = new JS.O();
             t.staticScope = new PerInstantiationScope(null, ibex, null, t.staticObject);
             if (staticScript != null) JS.cloneWithNewParentScope(staticScript, t.staticScope).call(null, null, null, null, 0);
         }
index 47de2e0..8896e6f 100644 (file)
@@ -52,7 +52,7 @@ public class HTML {
 
     public static synchronized JS parseReader(Reader r) throws IOException, JSExn {
         CharStream cs = new CharStream(r);
-        JS h = new JS();
+        JS h = new JS.O();
 
         withinLI = false;
         h.put("$name", "html");
@@ -163,7 +163,7 @@ public class HTML {
             try {
                 // scan subelement
                 if (cs.peek() != '/') {
-                    JS kid = new JS();
+                    JS kid = new JS.O();
                     closetag = parseElement(cs, kid);
                     h.put(String.valueOf(length), kid); 
                     h.put("$numchildren", new Integer(++length));
index 5ad7014..d16c582 100644 (file)
@@ -75,7 +75,7 @@ class Interpreter implements ByteCodes, Tokens {
             }
             switch(op) {
             case LITERAL: stack.push(arg); break;
-            case OBJECT: stack.push(new JS()); break;
+            case OBJECT: stack.push(new JS.O()); break;
             case ARRAY: stack.push(new JSArray(JS.toNumber(arg).intValue())); break;
             case DECLARE: scope.declare((String)(arg==null ? stack.peek() : arg)); if(arg != null) stack.push(arg); break;
             case TOPSCOPE: stack.push(scope); break;
index 0290e46..81feec1 100644 (file)
@@ -6,29 +6,68 @@ import java.io.*;
 import java.util.*;
 
 /** The minimum set of functionality required for objects which are manipulated by JavaScript */
-public class JS extends org.ibex.util.BalancedTree { 
+public abstract class JS { 
 
     public static boolean checkAssertions = false;
 
     public static final Object METHOD = new Object() { public String toString() { return "JS.METHOD"; } };
     public final JS unclone() { return _unclone(); }
     public final JS jsclone() throws JSExn { return new Clone(this); }
-    public Enumeration keys() throws JSExn { return entries == null ? emptyEnumeration : entries.keys(); }
-    public Object get(Object key) throws JSExn { return entries == null ? null : entries.get(key, null); }
-    public void put(Object key, Object val) throws JSExn { (entries==null?entries=new Hash():entries).put(key,null,val); }
+
+    public Enumeration keys() throws JSExn { throw new JSExn("you can't enumerate the keys of this object (class=" + this.getClass().getName() +")"); }
+    public Object get(Object key) throws JSExn { return null; }
+    public void put(Object key, Object val) throws JSExn { throw new JSExn("this object is read only (class=" + this.getClass().getName() +")"); }
+        
+    public final boolean hasTrap(Object key) { return getTrap(key) != null; }
+    
     public Object callMethod(Object method, Object a0, Object a1, Object a2, Object[] rest, int nargs) throws JSExn {
-        throw new JSExn("you cannot call this object (class=" + this.getClass().getName() +")");
+        throw new JSExn("method not found (" + method + ")");
     }    
+    
     // FIXME: JSArgs objects, pointers into stack frame
     public Object call(Object a0, Object a1, Object a2, Object[] rest, int nargs) throws JSExn {
         throw new JSExn("you cannot call this object (class=" + this.getClass().getName() +")");
     }
 
+    Trap getTrap(Object key) { return null; }
+    void putTrap(Object key, Trap value) throws JSExn { throw new JSExn("traps cannot be placed on this object (class=" + this.getClass().getName() +")"); }
+    
+    public static class O extends JS {
+        private Hash entries;
+        
+        public Enumeration keys() throws JSExn { return entries == null ? emptyEnumeration : entries.keys(); }
+        public Object get(Object key) throws JSExn { return entries == null ? null : entries.get(key, null); }
+        public void put(Object key, Object val) throws JSExn { (entries==null?entries=new Hash():entries).put(key,null,val); }        
+
+        /** retrieve a trap from the entries hash */
+        final Trap getTrap(Object key) {
+            return entries == null ? null : (Trap)entries.get(key, Trap.class);
+        }
+        
+        /** retrieve a trap from the entries hash */
+        final void putTrap(Object key, Trap value) {
+            if (entries == null) entries = new Hash();
+            entries.put(key, Trap.class, value);
+        }    
+    }
+    
+    public static class BT extends O {
+        private BalancedTree bt;
+        private final BalancedTree bt() { if(bt != null) return bt; return bt = new BalancedTree(); }
+        public final void insertNode(int index, Object o) { bt().insertNode(index,o); }
+        public final void clear() { bt().clear(); }
+        public final Object getNode(int i) { return bt().getNode(i); }
+        public final int treeSize() { return bt().treeSize(); }
+        public final Object deleteNode(int i) { return bt().deleteNode(i); }
+        public final void replaceNode(int index, Object o) { bt().replaceNode(index,o); }
+        public final int indexNode(Object o) { return bt().indexNode(o); }
+    }
+    
     JS _unclone() { return this; }
     
     public interface Cloneable { }
     
-    public static class Clone extends JS implements Cloneable {
+    public static class Clone extends JS.O implements Cloneable {
         protected JS clonee;
         JS _unclone() { return clonee.unclone(); }
         public JS getClonee() { return clonee; }
@@ -178,8 +217,6 @@ public class JS extends org.ibex.util.BalancedTree {
             public Object nextElement() { throw new NoSuchElementException(); }
         };
     
-    private Hash entries = null;
-
     public static JS fromReader(String sourceName, int firstLine, Reader sourceCode) throws IOException {
         return JSFunction._fromReader(sourceName, firstLine, sourceCode);
     }
@@ -192,11 +229,6 @@ public class JS extends org.ibex.util.BalancedTree {
 
     // Trap support //////////////////////////////////////////////////////////////////////////////
 
-    /** override and return true to allow placing traps on this object.
-     *  if isRead true, this is a read trap, otherwise write trap
-     **/
-    protected boolean isTrappable(Object name, boolean isRead) { return true; }
-
     /** performs a put, triggering traps if present; traps are run in an unpauseable interpreter */
     public void putAndTriggerTraps(Object key, Object value) throws JSExn {
         Trap t = getTrap(key);
@@ -211,28 +243,16 @@ public class JS extends org.ibex.util.BalancedTree {
         else return get(key);
     }
 
-    /** retrieve a trap from the entries hash */
-    protected final Trap getTrap(Object key) {
-        return entries == null ? null : (Trap)entries.get(key, Trap.class);
-    }
-
-    /** retrieve a trap from the entries hash */
-    protected final void putTrap(Object key, Trap value) {
-        if (entries == null) entries = new Hash();
-        entries.put(key, Trap.class, value);
-    }
-
     /** adds a trap, avoiding duplicates */
     protected final void addTrap(Object name, JSFunction f) throws JSExn {
         if (f.numFormalArgs > 1) throw new JSExn("traps must take either one argument (write) or no arguments (read)");
         boolean isRead = f.numFormalArgs == 0;
-        if (!isTrappable(name, isRead)) throw new JSExn("not allowed "+(isRead?"read":"write")+" trap on property: "+name);
         for(Trap t = getTrap(name); t != null; t = t.next) if (t.f == f) return;
         putTrap(name, new Trap(this, name.toString(), f, (Trap)getTrap(name)));
     }
 
     /** deletes a trap, if present */
-    protected final void delTrap(Object name, JSFunction f) {
+    protected final void delTrap(Object name, JSFunction f) throws JSExn {
         Trap t = (Trap)getTrap(name);
         if (t == null) return;
         if (t.f == f) { putTrap(t.name, t.next); return; }
index 7b90de7..168bab3 100644 (file)
@@ -5,7 +5,7 @@ import org.ibex.util.*;
 import java.util.*;
 
 /** A JavaScript JSArray */
-public class JSArray extends JS {
+public class JSArray extends JS.BT {
     private static final Object NULL = new Object();
     
     public JSArray() { }
index da22d2e..f203426 100644 (file)
@@ -91,7 +91,7 @@ public class JSRegexp extends JS {
   
     private static Object matchToExecResult(REMatch match, RE re, String s) {
         try {
-            JS ret = new JS();
+            JS ret = new JS.O();
             ret.put("index", N(match.getStartIndex()));
             ret.put("input",s);
             int n = re.getNumSubs();
index e133f4c..663e24d 100644 (file)
@@ -4,7 +4,8 @@ package org.ibex.js;
 // FIXME: should allow parentScope to be a JS, not a JSScope
 // FIXME: Index local vars by number and lookup in an array
 /** Implementation of a JavaScript Scope */
-public class JSScope extends JS { 
+// HACK = JSScope doesn't really need the BT, this is just for Box.java 
+public class JSScope extends JS.BT { 
 
     private JSScope parentScope;
 
index 211bb46..5f8a4ed 100644 (file)
@@ -826,7 +826,7 @@ public class HTTP {
                 return super.get(name);
             }
         
-            private static final JS proxyConfigBindings = new JS();
+            private static final JS proxyConfigBindings = new JS.O();
             private static final JS ProxyConfig = new JS() {
                     public Object get(Object name) {
                         if (name.equals("bindings")) return proxyConfigBindings;
index 85670a3..55f18f5 100644 (file)
@@ -41,7 +41,7 @@ public 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 JS());
+        objects.addElement(new JS.O());
 
         for(int i=0; i<keys.length; i++) {
             String key = keys[i];
index 14aacb5..290415f 100644 (file)
@@ -84,7 +84,7 @@ public class XMLRPC extends JS {
             content.reset();
             //#switch(c.getLocalName())
             case "fault": fault = true;
-            case "struct": objects.setElementAt(new JS(), objects.size() - 1);
+            case "struct": objects.setElementAt(new JS.O(), objects.size() - 1);
             case "array": objects.setElementAt(null, objects.size() - 1);
             case "value": objects.addElement("");
             //#end
index a04b20f..24c474d 100644 (file)
@@ -25,8 +25,6 @@ public class BalancedTree {
     private int cached_index = -1;
     private int cached_slot = -1;
     
-    private FinalizationHelper fh;
-
     // Public API //////////////////////////////////////////////////////////////////////////
 
     /** the number of elements in the tree */
@@ -47,7 +45,6 @@ public class BalancedTree {
         if (root != 0) {
             insert(index, arg, root, 0, false, false);
         } else {
-            if(fh == null) fh = new FinalizationHelper(this);
             root = arg;
             left[arg] = right[arg] = parent[arg] = 0;
             size[arg] = 1;
@@ -425,12 +422,8 @@ public class BalancedTree {
             return slot;
         }
     }
-    
-    static class FinalizationHelper {
-        private BalancedTree bt;
-        FinalizationHelper(BalancedTree bt) { this.bt = bt; }
-        protected void finalize() { bt.clear(); }
-    }
+
+    protected void finalize() { clear(); }
 
     // Debugging ///////////////////////////////////////////////////////////////////////////