2003/06/16 07:58:57
authormegacz <megacz@xwt.org>
Fri, 30 Jan 2004 07:01:12 +0000 (07:01 +0000)
committermegacz <megacz@xwt.org>
Fri, 30 Jan 2004 07:01:12 +0000 (07:01 +0000)
darcs-hash:20040130070112-2ba56-9c6602ded681d080c8f486cb25ad56180eac6dfb.gz

17 files changed:
src/org/xwt/Proxy.java
src/org/xwt/Resources.java
src/org/xwt/SOAP.java
src/org/xwt/SpecialBoxProperty.java
src/org/xwt/Template.java
src/org/xwt/ThreadMessage.java
src/org/xwt/Trap.java
src/org/xwt/XMLRPC.java
src/org/xwt/XWT.java
src/org/xwt/js/ArrayImpl.java [moved from src/org/xwt/js/Array.java with 94% similarity]
src/org/xwt/js/ByteCodes.java
src/org/xwt/js/CompiledFunctionImpl.java [moved from src/org/xwt/js/CompiledFunction.java with 89% similarity]
src/org/xwt/js/Context.java
src/org/xwt/js/JS.java
src/org/xwt/js/Math.java
src/org/xwt/js/Parser.java
src/org/xwt/js/ScopeImpl.java [new file with mode: 0644]

index 6067464..0f86f33 100644 (file)
@@ -114,15 +114,15 @@ public class Proxy {
                 if (Log.on) Log.log(Proxy.class, script);
             }
 
-           JS.Callable scr = JS.parse("PAC script at " + url, 0, new StringReader(script), proxyAutoConfigRootScope);
-            scr.call(new org.xwt.js.Array());
+           JS.CompiledFunction scr = JS.parse("PAC script at " + url, 0, new StringReader(script));
+            scr.call(new JS.Array(), proxyAutoConfigRootScope);
             return (JS.Callable)proxyAutoConfigRootScope.get("FindProxyForURL");
         } catch (Exception e) {
             if (Log.on) {
                 Log.log(Platform.class, "WPAD detection failed due to:");
                 if (e instanceof JS.Exn) {
                    try {
-                       org.xwt.js.Array arr = new org.xwt.js.Array();
+                       org.xwt.js.JS.Array arr = new org.xwt.js.JS.Array();
                        arr.addElement(((JS.Exn)e).getObject());
                        // FIXME
                        //XWT.recursivePrintObject.call();
@@ -202,19 +202,19 @@ public class Proxy {
             };
         
         private static final JS.Callable isPlainHostName = new JS.Callable() {
-                public Object call(org.xwt.js.Array args) throws JS.Exn {
+                public Object call(org.xwt.js.JS.Array args) throws JS.Exn {
                     return (args.elementAt(0).toString().indexOf('.') == -1) ? Boolean.TRUE : Boolean.FALSE;
                 }
             };
         
         private static final JS.Callable dnsDomainIs = new JS.Callable() {
-                public Object call(org.xwt.js.Array args) throws JS.Exn {
+                public Object call(org.xwt.js.JS.Array args) throws JS.Exn {
                     return (args.elementAt(0).toString().endsWith(args.elementAt(1).toString())) ? Boolean.TRUE : Boolean.FALSE;
                 }
             };
         
         private static final JS.Callable localHostOrDomainIs = new JS.Callable() {
-                public Object call(org.xwt.js.Array args) throws JS.Exn {
+                public Object call(org.xwt.js.JS.Array args) throws JS.Exn {
                     return (args.elementAt(0).toString().equals(args.elementAt(1).toString()) || 
                             (args.elementAt(0).toString().indexOf('.') == -1 && args.elementAt(1).toString().startsWith(args.elementAt(0).toString()))) ?
                         Boolean.TRUE : Boolean.FALSE;
@@ -222,7 +222,7 @@ public class Proxy {
             };
         
         private static final JS.Callable isResolvable = new JS.Callable() {
-                public Object call(org.xwt.js.Array args) throws JS.Exn {
+                public Object call(org.xwt.js.JS.Array args) throws JS.Exn {
                     try {
                         return (InetAddress.getByName(args.elementAt(0).toString()) != null) ? Boolean.TRUE : Boolean.FALSE;
                     } catch (UnknownHostException e) {
@@ -232,7 +232,7 @@ public class Proxy {
             };
         
         private static final JS.Callable isInNet = new JS.Callable() {
-                public Object call(org.xwt.js.Array args) throws JS.Exn {
+                public Object call(org.xwt.js.JS.Array args) throws JS.Exn {
                     if (args.length() != 3) return Boolean.FALSE;
                     try {
                         byte[] host = InetAddress.getByName(args.elementAt(0).toString()).getAddress();
@@ -250,7 +250,7 @@ public class Proxy {
             };
         
         private static final JS.Callable dnsResolve = new JS.Callable() {
-                public Object call(org.xwt.js.Array args) throws JS.Exn {
+                public Object call(org.xwt.js.JS.Array args) throws JS.Exn {
                     try {
                         return InetAddress.getByName(args.elementAt(0).toString()).getHostAddress();
                     } catch (UnknownHostException e) {
@@ -260,7 +260,7 @@ public class Proxy {
             };
         
         private static final JS.Callable myIpAddress = new JS.Callable() {
-                public Object call(org.xwt.js.Array args) throws JS.Exn {
+                public Object call(org.xwt.js.JS.Array args) throws JS.Exn {
                     try {
                         return InetAddress.getLocalHost().getHostAddress();
                     } catch (UnknownHostException e) {
@@ -271,7 +271,7 @@ public class Proxy {
             };
         
         private static final JS.Callable dnsDomainLevels = new JS.Callable() {
-                public Object call(org.xwt.js.Array args) throws JS.Exn {
+                public Object call(org.xwt.js.JS.Array args) throws JS.Exn {
                     String s = args.elementAt(0).toString();
                     int i = 0;
                     while((i = s.indexOf('.', i)) != -1) i++;
@@ -289,7 +289,7 @@ public class Proxy {
         }
         
         private static final JS.Callable shExpMatch = new JS.Callable() {
-                public Object call(org.xwt.js.Array args) throws JS.Exn {
+                public Object call(org.xwt.js.JS.Array args) throws JS.Exn {
                     StringTokenizer st = new StringTokenizer(args.elementAt(1).toString(), "*", false);
                     String[] arr = new String[st.countTokens()];
                     String s = args.elementAt(0).toString();
@@ -301,7 +301,7 @@ public class Proxy {
         public static String[] days = { "SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT" };
         
         private static final JS.Callable weekdayRange = new JS.Callable() {
-                public Object call(org.xwt.js.Array args) throws JS.Exn {
+                public Object call(org.xwt.js.JS.Array args) throws JS.Exn {
                     TimeZone tz = (args.length() < 3 || args.elementAt(2) == null || !args.elementAt(2).equals("GMT")) ? TimeZone.getTimeZone("UTC") : TimeZone.getDefault();
                     Calendar c = new GregorianCalendar();
                     c.setTimeZone(tz);
@@ -327,13 +327,13 @@ public class Proxy {
             };
         
         private static final JS.Callable dateRange = new JS.Callable() {
-                public Object call(org.xwt.js.Array args) throws JS.Exn {
+                public Object call(org.xwt.js.JS.Array args) throws JS.Exn {
                     throw new JS.Exn("XWT does not support dateRange() in PAC scripts");
                 }
             };
         
         private static final JS.Callable timeRange = new JS.Callable() {
-                public Object call(org.xwt.js.Array args) throws JS.Exn {
+                public Object call(org.xwt.js.JS.Array args) throws JS.Exn {
                     throw new JS.Exn("XWT does not support timeRange() in PAC scripts");
                 }
             };
index c4e512e..7e881b1 100644 (file)
@@ -87,9 +87,9 @@ public class Resources {
                     if (clear && callback != null) {
                         clear = false;
                         ThreadMessage.newthread(new JS.Callable() {
-                                public Object call(Array args_) throws JS.Exn {
+                                public Object call(JS.Array args_) throws JS.Exn {
                                     try {
-                                       Array args = new Array();
+                                       JS.Array args = new JS.Array();
                                        args.addElement(new Double(bytesDownloaded));
                                        args.addElement(new Double(length));
                                         callback.call(args);
index 648562f..7de30d3 100644 (file)
@@ -67,9 +67,9 @@ class SOAP extends XMLRPC {
                 } else if (value.endsWith("null")) {
                     objects.removeElementAt(objects.size() - 1);
                     objects.addElement(null);
-                } else if (value.endsWith("arrayType") || value.endsWith("Array") || key.endsWith("arrayType")) {
+                } else if (value.endsWith("arrayType") || value.endsWith("JS.Array") || key.endsWith("arrayType")) {
                     objects.removeElementAt(objects.size() - 1);
-                    objects.addElement(new Array());
+                    objects.addElement(new JS.Array());
                 }
             }
         }
@@ -147,9 +147,9 @@ class SOAP extends XMLRPC {
         if (objects.size() < 2) return;
 
         // our parent "should" be an aggregate type -- add ourselves to it.
-        if (parent != null && parent instanceof Array) {
+        if (parent != null && parent instanceof JS.Array) {
             objects.removeElementAt(objects.size() - 1);
-            ((Array)parent).addElement(me);
+            ((JS.Array)parent).addElement(me);
 
         } else if (parent != null && parent instanceof JS) {
             objects.removeElementAt(objects.size() - 1);
@@ -221,8 +221,8 @@ class SOAP extends XMLRPC {
             }
             sb.append("</" + name + ">\r\n");
 
-        } else if (o instanceof Array) {
-            Array a = (Array)o;
+        } else if (o instanceof JS.Array) {
+            JS.Array a = (JS.Array)o;
             sb.append("                <" + name + " SOAP-ENC:arrayType=\"xsd:ur-type[" + a.length() + "]\">");
             for(int i=0; i<a.length(); i++) appendObject("item", a.elementAt(i), sb);
             sb.append("</" + name + ">\r\n");
@@ -236,7 +236,7 @@ class SOAP extends XMLRPC {
         }
     }
 
-    protected String send(Array args, HTTP http) throws JS.Exn, IOException {
+    protected String send(JS.Array args, HTTP http) throws JS.Exn, IOException {
         // build up the request
         StringBuffer content = new StringBuffer();
         content.append("SOAPAction: " + action + "\r\n\r\n");
index b492e6c..c02314c 100644 (file)
@@ -690,7 +690,7 @@ class SpecialBoxProperty {
         Box b;
         public Apply(Box b) { super(); this.b = b; }
 
-        public Object call(Array args) throws JS.Exn {
+        public Object call(JS.Array args) throws JS.Exn {
 
             // apply a template
             if (args.elementAt(0) instanceof String) {
index 63a9daa..4ac78db 100644 (file)
@@ -73,10 +73,10 @@ public class Template {
     private boolean changed = false;
 
     /** the script on the static node of this template, null if it has already been executed */
-    private CompiledFunction staticscript = null;
+    private JS.CompiledFunction staticscript = null;
 
     /** the script on this node */
-    private CompiledFunction script = null;
+    private JS.CompiledFunction script = null;
 
     /** during XML parsing, this holds the list of currently-parsed children; null otherwise */
     private Vec childvect = new Vec();
@@ -206,9 +206,7 @@ public class Template {
         if (redirect != null && !"self".equals(redirect)) redir = (Box)b.get("$" + redirect);
 
         if (script != null) try {
-            script.cloneWithNewParentScope(b).call(new Array());
-        } catch (IOException e) {
-           throw new Error("this should never happen");
+            script.call(new JS.Array(), b);
         } catch (JS.Exn e) {
             if (Log.on) Log.log(this, "WARNING: uncaught ecmascript exception: " + e.getMessage());
         }
@@ -240,7 +238,7 @@ public class Template {
 
         if (callback != null)
             try {
-               Array args = new Array();
+               JS.Array args = new JS.Array();
                args.addElement(new Double(numerator));
                args.addElement(new Double(denominator));
                 callback.call(args);
@@ -286,7 +284,7 @@ public class Template {
 
         if (callback != null)
             try {
-               Array args = new Array();
+               JS.Array args = new JS.Array();
                args.addElement(new Double(1.0));
                args.addElement(new Double(1.0));
                 callback.call(args);
@@ -365,7 +363,7 @@ public class Template {
         if (staticscript != null) try { 
             JS.Scope s = Static.createStatic(nodeName, false);
             if (staticscript != null) {
-                CompiledFunction temp = staticscript;
+                JS.CompiledFunction temp = staticscript;
                 staticscript = null;
 
                // we layer a transparent scope over the Static so that we can catch requests for the xwt object
@@ -376,10 +374,8 @@ public class Template {
                            if ("xwt".equals(key)) return XWT.singleton; else return super.get(key);
                        } };
 
-               temp.cloneWithNewParentScope(varScope).call(null);
+               temp.call(new JS.Array(), varScope);
             }
-        } catch (IOException e) {
-           throw new Error("this should never happen");
         } catch (JS.Exn e) {
             if (Log.on) Log.log(this, "WARNING: uncaught ecmascript exception: " + e.getMessage());
         }
@@ -654,10 +650,10 @@ public class Template {
             }
         }
 
-        private CompiledFunction genscript(boolean isstatic) {
-            CompiledFunction thisscript = null;
+        private JS.CompiledFunction genscript(boolean isstatic) {
+            JS.CompiledFunction thisscript = null;
             try {
-                thisscript = JS.parse(t.nodeName + (isstatic ? "._" : ""), t.content_start, new StringReader(t.content.toString()), null);
+                thisscript = JS.parse(t.nodeName + (isstatic ? "._" : ""), t.content_start, new StringReader(t.content.toString()));
             } catch (JS.Exn ee) {
                 if (Log.on) Log.log(this, "  ERROR: " + ee.getMessage());
                 thisscript = null;
index faf7577..07a47d4 100644 (file)
@@ -79,7 +79,7 @@ public class ThreadMessage extends Thread implements Message {
             while (true) {
                 try {
                     go.block();
-                    f.call(new Array());
+                    f.call(new JS.Array());
                 } catch (JS.Exn e) {
                     if (Log.on) Log.log(this, "WARNING: uncaught ecmascript exception: " + e);
                 }
index 581bd2a..b2d0c4b 100644 (file)
@@ -44,7 +44,7 @@ public class Trap {
     private JS rp = null;
     
     /** the function for this trap */
-    CompiledFunction f = null;
+    JS.CompiledFunction f = null;
 
     /** the name of the property that this trap was placed on */
     private String name = null;
@@ -72,7 +72,7 @@ public class Trap {
      *  @param isreadtrap true iff this is a read (double-underscore) trap
      *  @param rp if this trap is being placed via a rootproxy, this is that proxy object.
      */
-    static void addTrap(Box trapee, String name, CompiledFunction f, boolean isreadtrap, JS rp) {
+    static void addTrap(Box trapee, String name, JS.CompiledFunction f, boolean isreadtrap, JS rp) {
 
         if (PROHIBITED.get(name) != null || name.startsWith("xwt_")) {
             Log.log(Trap.class, "Error: you cannot place traps on special property \"" + name + "\"");
@@ -80,7 +80,7 @@ public class Trap {
         }
 
         // find out what script is currently running
-       CompiledFunction placer = Context.getContextForThread(Thread.currentThread()).getCurrentFunction();
+       JS.CompiledFunction placer = Context.getContextForThread(Thread.currentThread()).getCurrentFunction();
        if (placer == null) { Log.log(Trap.class, "placer is null"); return; }
         String placerNodeName = placer.getSourceName();
 
@@ -122,8 +122,8 @@ public class Trap {
     public static final CascadeFunction cascadeFunction = new CascadeFunction();
     private static class CascadeFunction extends JS.Callable {
         CascadeFunction() { setSeal(true); }
-        public Object call(Array args) { return call(args, Context.getContextForThread(Thread.currentThread()).getCurrentFunction()); }
-        public Object call(Array args, CompiledFunction currentFunction) {
+        public Object call(JS.Array args) { return call(args, Context.getContextForThread(Thread.currentThread()).getCurrentFunction()); }
+        public Object call(JS.Array args, JS.CompiledFunction currentFunction) {
             Trap currentTrap = TrapContext.get().currentTrap;
             if (args.length() != 0) TrapContext.get().putCascadeHappened = true;
             Trap t = currentTrap.next;
@@ -158,7 +158,7 @@ public class Trap {
     private Trap() { allTraps.put(myWeak, dummy); }
 
     /** perform this trap -- arg.length == 0 if this is a get; otherwise it contains a single element to be put */
-    public Object perform(Array args) {
+    public Object perform(JS.Array args) {
         TrapContext tc = TrapContext.get();
 
         // save both thread-locals on the stack and update their values
index ce1fab2..f103ad0 100644 (file)
@@ -57,7 +57,7 @@ class XMLRPC extends JS.Callable {
      *
      *  If an &lt;array&gt; tag is encountered, a null is pushed onto the
      *  stack. When a &lt;/data&gt; is encountered, we search back on the
-     *  stack to the last null, replace it with a NativeArray, and
+     *  stack to the last null, replace it with a NativeJS.Array, and
      *  insert into it all elements above it on the stack.
      *
      *  If a &lt;struct&gt; tag is encountered, a JSObject is pushed
@@ -151,7 +151,7 @@ class XMLRPC extends JS.Callable {
            } else if (c.localName.equals("data")) {
                int i;
                for(i=objects.size() - 1; objects.elementAt(i) != null; i--);
-               Array arr = new Array();
+               JS.Array arr = new JS.Array();
                for(int j = i + 1; j<objects.size(); j++) arr.put(new Integer(j - i - 1), objects.elementAt(j));
                objects.setElementAt(arr, i);
                objects.setSize(i + 1);
@@ -263,11 +263,11 @@ class XMLRPC extends JS.Callable {
             sb.append("</dateTime.iso8601></value>\n");
            */
 
-        } else if (o instanceof Array) {
+        } else if (o instanceof JS.Array) {
             if (tracker.get(o) != null) throw new JS.Exn("attempted to send multi-ref data structure via XML-RPC");
             tracker.put(o, Boolean.TRUE);
             sb.append("                <value><array><data>\n");
-            Array a = (Array)o;
+            JS.Array a = (JS.Array)o;
             for(int i=0; i<a.length(); i++) appendObject(a.elementAt(i), sb);
             sb.append("                </data></array></value>\n");
 
@@ -292,7 +292,7 @@ class XMLRPC extends JS.Callable {
 
     // this is synchronized in case multiple threads try to make a call on the same object... in the future, change this
     // behavior to use pipelining.
-    public synchronized Object call2(Array args) throws JS.Exn, IOException {
+    public synchronized Object call2(JS.Array args) throws JS.Exn, IOException {
         if (Log.verbose) Log.log(this, "call to " + url + " : " + methodname);
 
         if (tracker == null) tracker = new Hash();
@@ -333,7 +333,7 @@ class XMLRPC extends JS.Callable {
         }
     }
 
-    protected String send(Array args, HTTP http) throws JS.Exn, IOException {
+    protected String send(JS.Array args, HTTP http) throws JS.Exn, IOException {
         StringBuffer content = new StringBuffer();
         content.append("\r\n");
         content.append("<?xml version=\"1.0\"?>\n");
@@ -366,7 +366,7 @@ class XMLRPC extends JS.Callable {
         return objects.elementAt(0);
     }
 
-    public final Object call(Array args) throws JS.Exn {
+    public final Object call(JS.Array args) throws JS.Exn {
 
         if (!ThreadMessage.suspendThread()) return null;
 
index f20cf26..a8880ae 100644 (file)
@@ -57,28 +57,28 @@ public final class XWT extends JS.Obj {
         put("tempDir", System.getProperty("java.io.tempdir"));
        put("math", org.xwt.js.Math.singleton);
 
-       put("newBrowserWindow", new JS.Callable() { public Object call(Array args) throws JS.Exn {
+       put("newBrowserWindow", new JS.Callable() { public Object call(JS.Array args) throws JS.Exn {
            if (args.length() != 1 || args.elementAt(0) == null) return null;
            Platform.newBrowserWindow(args.elementAt(0).toString());
            return null;
        }});
 
-       put("parseFloat", new JS.Callable() { public Object call(Array args) throws JS.Exn {
+       put("parseFloat", new JS.Callable() { public Object call(JS.Array args) throws JS.Exn {
            if (args.length() != 1 || args.elementAt(0) == null) return null;
            return new Float(args.elementAt(0).toString());
        }});
 
-       put("parseInt", new JS.Callable() { public Object call(Array args) throws JS.Exn {
+       put("parseInt", new JS.Callable() { public Object call(JS.Array args) throws JS.Exn {
            if (args.length() != 1 || args.elementAt(0) == null) return null;
            return new Float(args.elementAt(0).toString());
        }});
 
-       put("yield", new JS.Callable() { public Object call(Array args) throws JS.Exn {
+       put("yield", new JS.Callable() { public Object call(JS.Array args) throws JS.Exn {
            sleep(0);
            return null;
        }});
 
-       put("theme", new JS.Callable() { public Object call(Array args) throws JS.Exn {
+       put("theme", new JS.Callable() { public Object call(JS.Array args) throws JS.Exn {
                if (args.length() != 2) return null;
                if (args.elementAt(0) == null || args.elementAt(1) == null) return null;
                for(int i=1; i<args.length(); i++) {
@@ -96,38 +96,38 @@ public final class XWT extends JS.Obj {
                return null;
        }});
            
-       put("println", new JS.Callable() { public Object call(Array args) throws JS.Exn {
+       put("println", new JS.Callable() { public Object call(JS.Array args) throws JS.Exn {
            if (args.length() != 1) return null;
            if (Log.on) Log.log(this, Context.getCurrentSourceNameAndLine() + " " +
                                (args.elementAt(0) == null ? "**null**" : args.elementAt(0).toString()));
            return null;
        }});
 
-       put("date", new JS.Callable() { public Object call(Array args) throws JS.Exn {
+       put("date", new JS.Callable() { public Object call(JS.Array args) throws JS.Exn {
            Log.log(XWT.class, "date not implemented");
            //throw new Error("not implemented");
            return null;
         }});
 
-       put("regexp", new JS.Callable() { public Object call(Array args) throws JS.Exn {
+       put("regexp", new JS.Callable() { public Object call(JS.Array args) throws JS.Exn {
            //throw new Error("not implemented");
            Log.log(XWT.class, "regexp not implemented");
            return null;
        }});
 
-       put("listfonts", new JS.Callable() { public Object call(Array args) throws JS.Exn {
+       put("listfonts", new JS.Callable() { public Object call(JS.Array args) throws JS.Exn {
            Object[] fonts = Platform.listFonts();
-           Array ret = new Array();
+           JS.Array ret = new JS.Array();
            for(int i=0; i<fonts.length; i++) ret.addElement(fonts[i]);
            return ret;
        }});
 
-       put("xmlrpc", new JS.Callable() { public Object call(Array args) throws JS.Exn {
+       put("xmlrpc", new JS.Callable() { public Object call(JS.Array args) throws JS.Exn {
            if (args.length() != 1 || args.elementAt(0) == null) return null;
            return new XMLRPC(args.elementAt(0).toString(), "");
        }});
 
-       put("soap", new JS.Callable() { public Object call(Array args) throws JS.Exn {
+       put("soap", new JS.Callable() { public Object call(JS.Array args) throws JS.Exn {
            if (args.length() == 1 && args.elementAt(0) != null) return new SOAP(args.elementAt(0).toString(), "", null, null);
            else if (args.length() == 2 && args.elementAt(0) != null && args.elementAt(1) != null)
                return new SOAP(args.elementAt(0).toString(), "", args.elementAt(1).toString(), null);
@@ -136,7 +136,7 @@ public final class XWT extends JS.Obj {
            else return null;
        }});
 
-       put("textwidth", new JS.Callable() { public Object call(Array args) throws JS.Exn {
+       put("textwidth", new JS.Callable() { public Object call(JS.Array args) throws JS.Exn {
            if (args.length() < 1 || args.length() > 2) return null;
            if (args.elementAt(0) == null || (args.length() == 2 && args.elementAt(1) == null)) return null;
            String font = args.length() == 1 ? Platform.getDefaultFont() : args.elementAt(0).toString();
@@ -146,7 +146,7 @@ public final class XWT extends JS.Obj {
            else return new Integer(xwf.stringWidth(text));
        }});
 
-       put("textheight", new JS.Callable() { public Object call(Array args) throws JS.Exn {
+       put("textheight", new JS.Callable() { public Object call(JS.Array args) throws JS.Exn {
            if (args.length() > 1) return null;
            if (args.length() == 1 && args.elementAt(0) == null) return null;
            String font = args.length() == 0 || args.elementAt(0) == null ? Platform.getDefaultFont() : args.elementAt(0).toString();
@@ -155,7 +155,7 @@ public final class XWT extends JS.Obj {
            else return new Integer(xwf.getMaxAscent() + xwf.getMaxDescent());
        }});
        
-       put("newBox", new JS.Callable() { public Object call(Array args) throws JS.Exn {
+       put("newBox", new JS.Callable() { public Object call(JS.Array args) throws JS.Exn {
            if (args.length() > 0) Log.log(XWT.class, "DEPRECATED: xwt.newBox() with multiple arguments is deprecated; use xwt.newBox().apply()");
            JS.Callable callback = null;
            for(int i=1; i<args.length(); i++)
@@ -175,20 +175,20 @@ public final class XWT extends JS.Obj {
            return ret;
        }});
 
-       put("sleep", new JS.Callable() { public Object call(Array args) throws JS.Exn {
+       put("sleep", new JS.Callable() { public Object call(JS.Array args) throws JS.Exn {
            if (args != null && (args.length() != 1 || args.elementAt(0) == null)) return null;
            int i = args == null ? 0 : SpecialBoxProperty.stoi(args.elementAt(0).toString());
            sleep(i);
            return null;
        }});
 
-       put("openFile", new JS.Callable() { public Object call(Array args) throws JS.Exn {
+       put("openFile", new JS.Callable() { public Object call(JS.Array args) throws JS.Exn {
            if (args.length() != 1) return null;
            String file = Platform.fileDialog(args.elementAt(0).toString(), false);
            return file == null ? null : new ByteStream(file);
        }});
 
-       put("saveFile", new JS.Callable() { public Object call(Array args) throws JS.Exn {
+       put("saveFile", new JS.Callable() { public Object call(JS.Array args) throws JS.Exn {
            if (args.length() != 2) return null;
            if (!(args.elementAt(1) instanceof ByteStream)) return null;
            String file = args.elementAt(0).toString();
@@ -207,7 +207,7 @@ public final class XWT extends JS.Obj {
            }
        }});
 
-       put("saveFileAs", new JS.Callable() { public Object call(Array args) throws JS.Exn {
+       put("saveFileAs", new JS.Callable() { public Object call(JS.Array args) throws JS.Exn {
            if (args.length() != 2) return null;
            if (!(args.elementAt(1) instanceof ByteStream)) return null;
            String file = args.elementAt(0).toString();
@@ -224,12 +224,12 @@ public final class XWT extends JS.Obj {
            }
        }});
 
-       put("utfEncode", new JS.Callable() { public Object call(Array args) throws JS.Exn {
+       put("utfEncode", new JS.Callable() { public Object call(JS.Array args) throws JS.Exn {
            if (args == null || args.length() != 1) return null;
            return new ByteStream(args.elementAt(0).toString().getBytes());
        }});
 
-       put("parseHTML", new JS.Callable() { public Object call(Array args) throws JS.Exn {
+       put("parseHTML", new JS.Callable() { public Object call(JS.Array args) throws JS.Exn {
                 if (args == null || args.length() != 1 || args.elementAt(0) == null) return null;
                 try {
                     if (args.elementAt(0) instanceof ByteStream) {
@@ -245,13 +245,13 @@ public final class XWT extends JS.Obj {
             }
         });
     
-    put("recursivePrintObject", new JS.Callable() { public Object call(Array args) {
+    put("recursivePrintObject", new JS.Callable() { public Object call(JS.Array args) {
        if (args.length() != 1) return null;
        recurse("", "", args.elementAt(0));
        return null;
     }});
 
-    put("loadArchive", new JS.Callable() { public Object call(Array args) throws JS.Exn {
+    put("loadArchive", new JS.Callable() { public Object call(JS.Array args) throws JS.Exn {
        if (!ThreadMessage.suspendThread()) return null;
        try {
            if (args == null || args.length() < 1 || args.elementAt(0) == null) return null;
@@ -310,7 +310,7 @@ public final class XWT extends JS.Obj {
        return null;
     }});
 
-    put("prefetchImage", new JS.Callable() { public Object call(Array args) throws JS.Exn {
+    put("prefetchImage", new JS.Callable() { public Object call(JS.Array args) throws JS.Exn {
        if (args == null || args.length() < 1 || args.elementAt(0) == null) return null;
        Box.getImage(args.elementAt(0).toString(),
                     args.length() > 1 && args.elementAt(1) instanceof JS.Callable ? (JS.Callable)args.elementAt(1) : null);
@@ -324,9 +324,9 @@ public final class XWT extends JS.Obj {
         if (o == null) {
             Log.log(Context.getCurrentSourceNameAndLine() , indent + name + "<null>");
 
-        } else if (o instanceof Array) {
+        } else if (o instanceof JS.Array) {
             Log.log(Context.getCurrentSourceNameAndLine() , indent + name + "<array>");
-            Array na = (Array)o;
+            JS.Array na = (JS.Array)o;
             for(int i=0; i<na.length(); i++)
                 recurse(indent + "  ", i + "", na.elementAt(i));
 
similarity index 94%
rename from src/org/xwt/js/Array.java
rename to src/org/xwt/js/ArrayImpl.java
index 9fda147..49b98a0 100644 (file)
@@ -6,10 +6,10 @@ import java.io.*;
 import java.util.*;
 
 /** A JavaScript Array */
-public class Array extends JS.Obj {
+class ArrayImpl extends JS.Obj {
     private Vec vec = new Vec();
-    public Array() { }
-    public Array(int size) { vec.setSize(size); }
+    public ArrayImpl() { }
+    public ArrayImpl(int size) { vec.setSize(size); }
     private static int intVal(Object o) {
        if (o instanceof Number) {
            int intVal = ((Number)o).intValue();
index 1c73e9f..b23af2d 100644 (file)
@@ -48,10 +48,10 @@ interface ByteCodes {
     /** discard the top stack element */
     static public final byte POP = -14;          
 
-    /** pop two elements; call stack[-1](stack[top]) where stacktop is a JS.Array */
+    /** pop two elements; call stack[-1](stack[top]) where stacktop is a JS.JS.Array */
     public static final byte CALL = -15;         
 
-    /** pop an element; push a JS.Array containing the keys of the popped element */
+    /** pop an element; push a JS.JS.Array containing the keys of the popped element */
     public static final byte PUSHKEYS = -16;     
 
     /** swap the top two elements on the stack */
similarity index 89%
rename from src/org/xwt/js/CompiledFunction.java
rename to src/org/xwt/js/CompiledFunctionImpl.java
index ac14075..ae92d06 100644 (file)
@@ -5,7 +5,7 @@ import org.xwt.util.*;
 import java.io.*;
 
 /** a JavaScript function, compiled into bytecode */
-public final class CompiledFunction extends JS.Callable implements ByteCodes, Tokens {
+public class CompiledFunctionImpl extends JS.Callable implements ByteCodes, Tokens {
 
     // Fields and Accessors ///////////////////////////////////////////////
 
@@ -30,27 +30,23 @@ public final class CompiledFunction extends JS.Callable implements ByteCodes, To
     private int size = 0;
     int size() { return size; }
 
-    /** the scope in which this function was declared */
+    /** the scope in which this function was declared; by default this function is called in a fresh subscope of the parentScope */
     private JS.Scope parentScope;
-    JS.Scope getParentScope() { return parentScope; }
 
 
     // Constructors ////////////////////////////////////////////////////////
 
-    public CompiledFunction cloneWithNewParentScope(JS.Scope s) throws IOException {
-       CompiledFunction ret = new CompiledFunction(sourceName, firstLine, s);
+    private CompiledFunctionImpl cloneWithNewParentScope(JS.Scope s) throws IOException {
+       CompiledFunctionImpl ret = new JS.CompiledFunction(sourceName, firstLine, null, s);
        ret.paste(this);
        return ret;
     }
 
-    CompiledFunction(String sourceName, int firstLine, JS.Scope parentScope) throws IOException {
+    protected CompiledFunctionImpl(String sourceName, int firstLine, Reader sourceCode, JS.Scope parentScope) throws IOException {
        this.sourceName = sourceName;
        this.firstLine = firstLine;
        this.parentScope = parentScope;
-    }
-
-    CompiledFunction(String sourceName, int firstLine, Reader sourceCode, JS.Scope parentScope) throws IOException {
-       this(sourceName, firstLine, parentScope);
+       if (sourceCode == null) return;
        Parser p = new Parser(sourceCode, sourceName, firstLine);
        try {
            while(true) {
@@ -64,18 +60,16 @@ public final class CompiledFunction extends JS.Callable implements ByteCodes, To
        }
     }
     
-    public Object call(Array args) throws JS.Exn {
-       CompiledFunction saved = (CompiledFunction)Context.currentFunction.get(Thread.currentThread());
+    public Object call(JS.Array args) throws JS.Exn { return call(args, new FunctionScope(sourceName, parentScope)); }
+    public Object call(JS.Array args, JS.Scope scope) throws JS.Exn {
+       CompiledFunctionImpl saved = (CompiledFunctionImpl)Context.currentFunction.get(Thread.currentThread());
        try {
            Context.currentFunction.put(Thread.currentThread(), this);
            Context cx = Context.getContextForThread(Thread.currentThread());
            int size = cx.stack.size();
            cx.stack.push(new Context.CallMarker());
            cx.stack.push(args);
-           
-           // FIXME, ugly
-           eval(args == null ? parentScope : new FunctionScope(sourceName, parentScope));
-           
+           eval(scope);
            Object ret = cx.stack.pop();
            if (cx.stack.size() > size)
                Log.log(this, "warning, stack grew by " + (cx.stack.size() - size) +
@@ -93,9 +87,9 @@ public final class CompiledFunction extends JS.Callable implements ByteCodes, To
     int get(int pos) { return op[pos]; }
     void set(int pos, int op_, Object arg_) { op[pos] = op_; arg[pos] = arg_; }
     void set(int pos, Object arg_) { arg[pos] = arg_; }
-    void paste(CompiledFunction other) { for(int i=0; i<other.size; i++) add(other.line[i], other.op[i], other.arg[i]); }
-    CompiledFunction add(int line, int op_) { return add(line, op_, null); }
-    CompiledFunction add(int line, int op_, Object arg_) {
+    void paste(CompiledFunctionImpl other) { for(int i=0; i<other.size; i++) add(other.line[i], other.op[i], other.arg[i]); }
+    CompiledFunctionImpl add(int line, int op_) { return add(line, op_, null); }
+    CompiledFunctionImpl add(int line, int op_, Object arg_) {
         if (size == op.length - 1) {
             int[] line2 = new int[op.length * 2]; System.arraycopy(this.line, 0, line2, 0, op.length); this.line = line2;
             Object[] arg2 = new Object[op.length * 2]; System.arraycopy(arg, 0, arg2, 0, arg.length); arg = arg2;
@@ -119,7 +113,7 @@ public final class CompiledFunction extends JS.Callable implements ByteCodes, To
            switch(op[pc]) {
             case LITERAL: t.push(arg[pc]); break;
             case OBJECT: t.push(new JS.Obj()); break;
-            case ARRAY: t.push(new Array(JS.toNumber(arg[pc]).intValue())); break;
+            case ARRAY: t.push(new JS.Array(JS.toNumber(arg[pc]).intValue())); break;
             case DECLARE: s.declare((String)t.pop()); break;
             case TOPSCOPE: t.push(s); break;
             case JT: if (JS.toBoolean(t.pop())) pc += JS.toNumber(arg[pc]).intValue() - 1; break;
@@ -128,8 +122,8 @@ public final class CompiledFunction extends JS.Callable implements ByteCodes, To
             case POP: t.pop(); break;
             case SWAP: { Object o1 = t.pop(); Object o2 = t.pop(); t.push(o1); t.push(o2); break; }
             case DUP: t.push(t.peek()); break;
-            case NEWSCOPE: s = new JS.Scope(s); break;
-           case OLDSCOPE: s = s.getParentScope(); break;
+            case NEWSCOPE: /*s = new JS.Scope(s);*/ break;
+           case OLDSCOPE: /*s = s.getParentScope();*/ break;
             case ASSERT: if (!JS.toBoolean(t.pop())) throw je("assertion failed"); break;
             case BITNOT: t.push(new Long(~JS.toLong(t.pop()))); break;
             case BANG: t.push(new Boolean(!JS.toBoolean(t.pop()))); break;
@@ -147,9 +141,8 @@ public final class CompiledFunction extends JS.Callable implements ByteCodes, To
            }
 
             case NEWFUNCTION: {
-               CompiledFunction bytes = (CompiledFunction)arg[pc];
                try {
-                   t.push(bytes.cloneWithNewParentScope(s));
+                   t.push(((CompiledFunctionImpl)arg[pc]).cloneWithNewParentScope(s));
                } catch (IOException e) {
                    throw new Error("this should never happen");
                }
@@ -159,7 +152,7 @@ public final class CompiledFunction extends JS.Callable implements ByteCodes, To
             case PUSHKEYS: {
                 Object o = t.peek();
                 Object[] keys = ((JS)o).keys();
-                Array a = new Array();
+                JS.Array a = new JS.Array();
                 a.setSize(keys.length);
                 for(int j=0; j<keys.length; j++) a.setElementAt(keys[j], j);
                 t.push(a);
@@ -250,7 +243,7 @@ public final class CompiledFunction extends JS.Callable implements ByteCodes, To
             }
                     
             case CALL: {
-                Array arguments = new Array();
+                JS.Array arguments = new JS.Array();
                 int numArgs = JS.toNumber(arg[pc]).intValue();
                 arguments.setSize(numArgs);
                 for(int j=numArgs - 1; j >= 0; j--) arguments.setElementAt(t.pop(), j);
@@ -362,7 +355,7 @@ public final class CompiledFunction extends JS.Callable implements ByteCodes, To
     private Object getFromString(final String o, final Object v) {
        if (v.equals("length")) return new Integer(((String)o).length());
        else if (v.equals("substring")) return new JS.Callable() {
-               public Object call(Array args) {
+               public Object call(JS.Array args) {
                    if (args.length() == 1) return ((String)o).substring(JS.toNumber(args.elementAt(0)).intValue());
                    else if (args.length() == 2) return ((String)o).substring(JS.toNumber(args.elementAt(0)).intValue(),
                                                                              JS.toNumber(args.elementAt(1)).intValue());
@@ -370,24 +363,24 @@ public final class CompiledFunction extends JS.Callable implements ByteCodes, To
                }
            };
        else if (v.equals("toLowerCase")) return new JS.Callable() {
-               public Object call(Array args) {
+               public Object call(JS.Array args) {
                    return ((String)o).toLowerCase();
                } };
        else if (v.equals("toUpperCase")) return new JS.Callable() {
-               public Object call(Array args) {
+               public Object call(JS.Array args) {
                    return ((String)o).toString().toUpperCase();
                } };
        else if (v.equals("charAt")) return new JS.Callable() {
-               public Object call(Array args) {
+               public Object call(JS.Array args) {
                    return ((String)o).charAt(JS.toNumber(args.elementAt(0)).intValue()) + "";
                } };
        else if (v.equals("lastIndexOf")) return new JS.Callable() {
-               public Object call(Array args) {
+               public Object call(JS.Array args) {
                    if (args.length() != 1) return null;
                    return new Integer(((String)o).lastIndexOf(args.elementAt(0).toString()));
                } };
        else if (v.equals("indexOf")) return new JS.Callable() {
-               public Object call(Array args) {
+               public Object call(JS.Array args) {
                    if (args.length() != 1) return null;
                    return new Integer(((String)o).indexOf(args.elementAt(0).toString()));
                } };
index 8533f34..34e4028 100644 (file)
@@ -25,13 +25,13 @@ public class Context {
     }
 
     public static String getSourceNameAndLineForThread(Thread t) {
-       CompiledFunction cf = getContextForThread(t).getCurrentFunction();
+       JS.CompiledFunction cf = getContextForThread(t).getCurrentFunction();
        if (cf == null) return "null";
        return cf.getSourceName() + ":??";
     }
 
     /** fetches the currently-executing javascript function */
-    public CompiledFunction getCurrentFunction() { return (CompiledFunction)currentFunction.get(Thread.currentThread()); }
+    public JS.CompiledFunction getCurrentFunction() { return (JS.CompiledFunction)currentFunction.get(Thread.currentThread()); }
 
     public static Context getContextForThread(Thread t) {
        Context ret = (Context)javaThreadToContextMap.get(t);
index 72c9e2a..05251b8 100644 (file)
@@ -6,14 +6,23 @@ import java.io.*;
 import java.util.*;
 
 /**
- *  The public API for the JS engine; JS itself is actually a class
- *  implementing the minimal amount of functionality for an Object
- *  which can be manipulated by JavaScript code.
+ *  The public API for the JS engine.  JS itself is actually a class
+ *  implementing the absolute minimal amount of functionality for an
+ *  Object which can be manipulated by JavaScript code.  The static
+ *  methods, fields, and inner classes of JS define the publicly
+ *  visible API for the XWT JavaScript engine; code outside this
+ *  package should never depend on anything not defined in this file.
  */
 public abstract class JS { 
 
     // Public Helper Methods //////////////////////////////////////////////////////////////////////
 
+    /** parse and compile a function */
+    public static CompiledFunction parse(String sourceName, int firstLine, Reader sourceCode) throws IOException {
+       return new CompiledFunction(sourceName, firstLine, sourceCode, null);
+    }
+
+    /** coerce an object to a Boolean */
     public static boolean toBoolean(Object o) {
        if (o == null) return false;
        if (o instanceof Boolean) return ((Boolean)o).booleanValue();
@@ -21,8 +30,13 @@ public abstract class JS {
        return true;
     }
 
+    /** coerce an object to a Long */
     public static long toLong(Object o) { return toNumber(o).longValue(); }
+
+    /** coerce an object to a Double */
     public static double toDouble(Object o) { return toNumber(o).doubleValue(); }
+
+    /** coerce an object to a Number */
     public static Number toNumber(Object o) {
        if (o == null) return new Long(0);
        if (o instanceof Number) return ((Number)o);
@@ -44,9 +58,9 @@ public abstract class JS {
     public boolean coerceToBoolean() { throw new Error("you cannot coerce a " + this.getClass().getName() + " into a Boolean"); }
 
 
-    // Subclasses /////////////////////////////////////////////////////////////////////////
+    // Inner Classes /////////////////////////////////////////////////////////////////////////
 
-    /** A slightly more featureful version of JS */
+    /** A sensible implementation of the abstract methods in the JS class */
     public static class Obj extends JS {
        private Hash entries = new Hash();
        private boolean sealed = false;
@@ -58,7 +72,7 @@ public abstract class JS {
        public Object[] keys() { return(entries.keys()); }
     }
 
-    /** An exception which can be thrown and caught by JavaScripts */
+    /** An exception which can be thrown and caught by JavaScript code */
     public static class Exn extends RuntimeException { 
        private Object js = null; 
        public Exn(Object js) { this.js = js; } 
@@ -67,46 +81,40 @@ public abstract class JS {
        public Object getObject() { return js; } 
     } 
 
+    /** The publicly-visible face of JavaScript Array objects */
+    public static class Array extends ArrayImpl {
+       public Array() { }
+       public Array(int size) { super(size); }
+       public void setSize(int i) { super.setSize(i); }
+       public int length() { return super.length(); }
+       public Object elementAt(int i) { return super.elementAt(i); }
+       public void addElement(Object o) { super.addElement(o); }
+       public void setElementAt(Object o, int i) { super.setElementAt(o, i); }
+    }
+
     /** Any object which becomes part of the scope chain must support this interface */ 
-    public static class Scope extends Obj { 
-       private Scope parentScope;
-       private static Object NULL = new Object();
+    public static class Scope extends ScopeImpl { 
        public Scope(Scope parentScope) { this(parentScope, false); }
-       public Scope(Scope parentScope, boolean sealed) {
-           super(sealed);
-           if (parentScope == this) throw new Error("can't make a scope its own parent!");
-           this.parentScope = parentScope;
-       }
-       public Scope getParentScope() { return parentScope; }
-
-       // transparent scopes are not returned by THIS
-       public boolean isTransparent() { return false; }
-
-       public boolean has(Object key) { return super.get(key) != null; }
-       public Object get(Object key) {
-           if (!has(key)) return parentScope == null ? null : getParentScope().get(key);
-           Object ret = super.get(key); return ret == NULL ? null : ret;
-       }
-       public void put(Object key, Object val) {
-           if (!has(key) && parentScope != null) getParentScope().put(key, val);
-           else super.put(key, val == null ? NULL : val);
-       }
-       public Object[] keys() { throw new Error("you can't enumerate the properties of a Scope"); }
-       public void declare(String s) {
-           if (isTransparent()) getParentScope().declare(s);
-           else super.put(s, NULL);
-       }
+       public Scope(Scope parentScope, boolean sealed) { super(parentScope, sealed); }
+       public Scope getParentScope() { return super.getParentScope(); }
+       public boolean isTransparent() { return super.isTransparent(); }
+       public boolean has(Object key) { return super.has(key); }
+       public void declare(String s) { super.declare(s); }
     } 
 
-    public static CompiledFunction parse(String sourceName, int firstLine, Reader sourceCode, JS.Scope parentScope) throws IOException {
-       return new CompiledFunction(sourceName, firstLine, sourceCode, parentScope);
-    }
     /** anything that is callable with the () operator */
     public static abstract class Callable extends JS.Obj {
-       public abstract Object call(Array args) throws JS.Exn;
+       public abstract Object call(JS.Array args) throws JS.Exn;
     }
 
+    /** a Callable which was compiled from JavaScript code */
+    public static class CompiledFunction extends CompiledFunctionImpl {
+       public Object call(JS.Array args, JS.Scope scope) throws JS.Exn { return super.call(args, scope); }
+       CompiledFunction(String sourceName, int firstLine, Reader sourceCode, Scope scope) throws IOException {
+           super(sourceName, firstLine, sourceCode, scope);
+       }
+    }
 } 
 
 
index 4f8319a..4cf52e8 100644 (file)
@@ -11,39 +11,39 @@ public class Math extends JS.Obj {
     private Math() { setSeal(true); }
 
     public Object get(Object name) {
-       if ("ceil".equals(name)) return new JS.Callable() { public Object call(Array args)
+       if ("ceil".equals(name)) return new JS.Callable() { public Object call(JS.Array args)
                { if (args.elementAt(0) == null) return null;
                return new Long((long)java.lang.Math.ceil(Double.parseDouble(args.elementAt(0).toString()))); } };
-       else if ("floor".equals(name)) return new JS.Callable() { public Object call(Array args)
+       else if ("floor".equals(name)) return new JS.Callable() { public Object call(JS.Array args)
                { if (args.elementAt(0) == null) return null;
                return new Long((long)java.lang.Math.floor(Double.parseDouble(args.elementAt(0).toString()))); } };
-       else if ("round".equals(name)) return new JS.Callable() { public Object call(Array args)
+       else if ("round".equals(name)) return new JS.Callable() { public Object call(JS.Array args)
                { if (args.elementAt(0) == null) return null;
                return new Long((long)java.lang.Math.round(Double.parseDouble(args.elementAt(0).toString()))); } };
-       else if ("abs".equals(name)) return new JS.Callable() { public Object call(Array args)
+       else if ("abs".equals(name)) return new JS.Callable() { public Object call(JS.Array args)
                { if (args.elementAt(0) == null) return null;
                return new Long((long)java.lang.Math.abs(Double.parseDouble(args.elementAt(0).toString()))); } };
-       else if ("min".equals(name)) return new JS.Callable() { public Object call(Array args) {
+       else if ("min".equals(name)) return new JS.Callable() { public Object call(JS.Array args) {
            if (args.length() < 2 || args.elementAt(0) == null || args.elementAt(1) == null) return args.elementAt(0);
            return new Double(java.lang.Math.min(((Number)args.elementAt(0)).doubleValue(),
                                       ((Number)args.elementAt(1)).doubleValue())); } };
-       else if ("max".equals(name)) return new JS.Callable() { public Object call(Array args) {
+       else if ("max".equals(name)) return new JS.Callable() { public Object call(JS.Array args) {
            if (args.length() < 2) return args.elementAt(0);
            return new Double(java.lang.Math.max(((Number)args.elementAt(0)).doubleValue(),
                                       ((Number)args.elementAt(1)).doubleValue())); } };
-       else if ("cos".equals(name)) return new JS.Callable() { public Object call(Array args) {
+       else if ("cos".equals(name)) return new JS.Callable() { public Object call(JS.Array args) {
            return new Double(java.lang.Math.cos(((Number)args.elementAt(0)).doubleValue())); } };
-       else if ("sin".equals(name)) return new JS.Callable() { public Object call(Array args) {
+       else if ("sin".equals(name)) return new JS.Callable() { public Object call(JS.Array args) {
            return new Double(java.lang.Math.sin(((Number)args.elementAt(0)).doubleValue())); } };
-       else if ("tan".equals(name)) return new JS.Callable() { public Object call(Array args) {
+       else if ("tan".equals(name)) return new JS.Callable() { public Object call(JS.Array args) {
            return new Double(java.lang.Math.tan(((Number)args.elementAt(0)).doubleValue())); } };
-       else if ("acos".equals(name)) return new JS.Callable() { public Object call(Array args) {
+       else if ("acos".equals(name)) return new JS.Callable() { public Object call(JS.Array args) {
            return new Double(java.lang.Math.acos(((Number)args.elementAt(0)).doubleValue())); } };
-       else if ("asin".equals(name)) return new JS.Callable() { public Object call(Array args) {
+       else if ("asin".equals(name)) return new JS.Callable() { public Object call(JS.Array args) {
            return new Double(java.lang.Math.asin(((Number)args.elementAt(0)).doubleValue())); } };
-       else if ("atan".equals(name)) return new JS.Callable() { public Object call(Array args) {
+       else if ("atan".equals(name)) return new JS.Callable() { public Object call(JS.Array args) {
            return new Double(java.lang.Math.atan(((Number)args.elementAt(0)).doubleValue())); } };
-       else if ("sqrt".equals(name)) return new JS.Callable() { public Object call(Array args) {
+       else if ("sqrt".equals(name)) return new JS.Callable() { public Object call(JS.Array args) {
            return new Double(java.lang.Math.sqrt(((Number)args.elementAt(0)).doubleValue())); } };
        return null;
     }
index 76f223b..68cb87c 100644 (file)
@@ -5,7 +5,7 @@ import org.xwt.util.*;
 import java.io.*;
 
 /**
- *  Parses a stream of lexed tokens into a tree of CompiledFunction's.
+ *  Parses a stream of lexed tokens into a tree of CompiledFunctionImpl's.
  *
  *  There are three kinds of things we parse: blocks, statements, and
  *  expressions.
@@ -73,7 +73,7 @@ class Parser extends Lexer implements ByteCodes {
 
     /** for debugging */
     public static void main(String[] s) throws Exception {
-        CompiledFunction block = new CompiledFunction("stdin", 0, new InputStreamReader(System.in), null);
+        CompiledFunctionImpl block = new JS.CompiledFunction("stdin", 0, new InputStreamReader(System.in), null);
         if (block == null) return;
         System.out.println(block);
     }
@@ -142,14 +142,14 @@ class Parser extends Lexer implements ByteCodes {
      *  bytecodes for that expression to <tt>appendTo</tt>; the
      *  appended bytecodes MUST grow the stack by exactly one element.
      */ 
-    private void startExpr(CompiledFunction appendTo, int minPrecedence) throws IOException {
+    private void startExpr(CompiledFunctionImpl appendTo, int minPrecedence) throws IOException {
        int saveParserLine = parserLine;
        _startExpr(appendTo, minPrecedence);
        parserLine = saveParserLine;
     }
-    private void _startExpr(CompiledFunction appendTo, int minPrecedence) throws IOException {
+    private void _startExpr(CompiledFunctionImpl appendTo, int minPrecedence) throws IOException {
         int tok = getToken();
-        CompiledFunction b = appendTo;
+        CompiledFunctionImpl b = appendTo;
 
         switch (tok) {
         case -1: throw new ParserException("expected expression");
@@ -232,7 +232,7 @@ class Parser extends Lexer implements ByteCodes {
         case FUNCTION: {
             consume(LP);
             int numArgs = 0;
-            CompiledFunction b2 = new CompiledFunction(sourceName, parserLine, null);
+            CompiledFunctionImpl b2 = new JS.CompiledFunction(sourceName, parserLine, null, null);
             b.add(parserLine, NEWFUNCTION, b2);
 
             // function prelude; arguments array is already on the stack
@@ -299,12 +299,12 @@ class Parser extends Lexer implements ByteCodes {
      *  expression that modifies the assignable.  This method always
      *  decreases the stack depth by exactly one element.
      */
-    private void continueExprAfterAssignable(CompiledFunction b) throws IOException {
+    private void continueExprAfterAssignable(CompiledFunctionImpl b) throws IOException {
        int saveParserLine = parserLine;
        _continueExprAfterAssignable(b);
        parserLine = saveParserLine;
     }
-    private void _continueExprAfterAssignable(CompiledFunction b) throws IOException {
+    private void _continueExprAfterAssignable(CompiledFunctionImpl b) throws IOException {
         if (b == null) throw new Error("got null b; this should never happen");
         int tok = getToken();
        switch(tok) {
@@ -356,12 +356,12 @@ class Parser extends Lexer implements ByteCodes {
      *  If any bytecodes are appended, they will not alter the stack
      *  depth.
      */
-    private void continueExpr(CompiledFunction b, int minPrecedence) throws IOException {
+    private void continueExpr(CompiledFunctionImpl b, int minPrecedence) throws IOException {
        int saveParserLine = parserLine;
        _continueExpr(b, minPrecedence);
        parserLine = saveParserLine;
     }
-    private void _continueExpr(CompiledFunction b, int minPrecedence) throws IOException {
+    private void _continueExpr(CompiledFunctionImpl b, int minPrecedence) throws IOException {
         if (b == null) throw new Error("got null b; this should never happen");
         int tok = getToken();
         if (tok == -1) return;
@@ -436,13 +436,13 @@ class Parser extends Lexer implements ByteCodes {
     }
     
     /** Parse a block of statements which must be surrounded by LC..RC. */
-    void parseBlock(CompiledFunction b) throws IOException { parseBlock(b, null); }
-    void parseBlock(CompiledFunction b, String label) throws IOException {
+    void parseBlock(CompiledFunctionImpl b) throws IOException { parseBlock(b, null); }
+    void parseBlock(CompiledFunctionImpl b, String label) throws IOException {
        int saveParserLine = parserLine;
        _parseBlock(b, label);
        parserLine = saveParserLine;
     }
-    void _parseBlock(CompiledFunction b, String label) throws IOException {
+    void _parseBlock(CompiledFunctionImpl b, String label) throws IOException {
         if (peekToken() == -1) return;
         else if (peekToken() != LC) parseStatement(b, null);
         else {
@@ -453,12 +453,12 @@ class Parser extends Lexer implements ByteCodes {
     }
 
     /** Parse a single statement, consuming the RC or SEMI which terminates it. */
-    void parseStatement(CompiledFunction b, String label) throws IOException {
+    void parseStatement(CompiledFunctionImpl b, String label) throws IOException {
        int saveParserLine = parserLine;
        _parseStatement(b, label);
        parserLine = saveParserLine;
     }
-    void _parseStatement(CompiledFunction b, String label) throws IOException {
+    void _parseStatement(CompiledFunctionImpl b, String label) throws IOException {
         int tok = peekToken();
         if (tok == -1) return;
         switch(tok = getToken()) {
@@ -666,8 +666,8 @@ class Parser extends Lexer implements ByteCodes {
                 b.add(parserLine, NEWSCOPE);                             // grab a fresh scope
                     
                 parseStatement(b, null);                                 // initializer
-                CompiledFunction e2 =                                    // we need to put the incrementor before the test
-                    new CompiledFunction(sourceName, parserLine, null);  // so we save the test here
+                CompiledFunctionImpl e2 =                                    // we need to put the incrementor before the test
+                    new JS.CompiledFunction(sourceName, parserLine, null, null);  // so we save the test here
                 if (peekToken() != SEMI)
                     startExpr(e2, -1);
                 else
diff --git a/src/org/xwt/js/ScopeImpl.java b/src/org/xwt/js/ScopeImpl.java
new file mode 100644 (file)
index 0000000..10788fd
--- /dev/null
@@ -0,0 +1,37 @@
+// Copyright 2003 Adam Megacz, see the COPYING file for licensing [GPL] 
+
+package org.xwt.js; 
+import org.xwt.util.*; 
+import java.io.*;
+import java.util.*;
+
+/** A JavaScript Scope */
+class ScopeImpl extends JS.Obj { 
+    private JS.Scope parentScope;
+    private static Object NULL = new Object();
+    public ScopeImpl(JS.Scope parentScope) { this(parentScope, false); }
+    public ScopeImpl(JS.Scope parentScope, boolean sealed) {
+       super(sealed);
+       if (parentScope == this) throw new Error("can't make a scope its own parent!");
+       this.parentScope = parentScope;
+    }
+    public JS.Scope getParentScope() { return parentScope; }
+    
+    // transparent scopes are not returned by THIS
+    public boolean isTransparent() { return false; }
+    
+    public boolean has(Object key) { return super.get(key) != null; }
+    public Object get(Object key) {
+       if (!has(key)) return parentScope == null ? null : getParentScope().get(key);
+       Object ret = super.get(key); return ret == NULL ? null : ret;
+    }
+    public void put(Object key, Object val) {
+       if (!has(key) && parentScope != null) getParentScope().put(key, val);
+       else super.put(key, val == null ? NULL : val);
+    }
+    public Object[] keys() { throw new Error("you can't enumerate the properties of a Scope"); }
+    public void declare(String s) {
+       if (isTransparent()) getParentScope().declare(s);
+       else super.put(s, NULL);
+    }
+}