From 2fa20bbe798c44d0443d7b80d8dbcf7eb13fff4a Mon Sep 17 00:00:00 2001 From: megacz Date: Fri, 30 Jan 2004 07:01:12 +0000 Subject: [PATCH] 2003/06/16 07:58:57 darcs-hash:20040130070112-2ba56-9c6602ded681d080c8f486cb25ad56180eac6dfb.gz --- src/org/xwt/Proxy.java | 30 +++---- src/org/xwt/Resources.java | 4 +- src/org/xwt/SOAP.java | 14 ++-- src/org/xwt/SpecialBoxProperty.java | 2 +- src/org/xwt/Template.java | 24 +++--- src/org/xwt/ThreadMessage.java | 2 +- src/org/xwt/Trap.java | 12 +-- src/org/xwt/XMLRPC.java | 14 ++-- src/org/xwt/XWT.java | 52 ++++++------ src/org/xwt/js/{Array.java => ArrayImpl.java} | 6 +- src/org/xwt/js/ByteCodes.java | 4 +- ...iledFunction.java => CompiledFunctionImpl.java} | 57 ++++++------- src/org/xwt/js/Context.java | 4 +- src/org/xwt/js/JS.java | 84 +++++++++++--------- src/org/xwt/js/Math.java | 26 +++--- src/org/xwt/js/Parser.java | 34 ++++---- src/org/xwt/js/ScopeImpl.java | 37 +++++++++ 17 files changed, 220 insertions(+), 186 deletions(-) rename src/org/xwt/js/{Array.java => ArrayImpl.java} (94%) rename src/org/xwt/js/{CompiledFunction.java => CompiledFunctionImpl.java} (89%) create mode 100644 src/org/xwt/js/ScopeImpl.java diff --git a/src/org/xwt/Proxy.java b/src/org/xwt/Proxy.java index 6067464..0f86f33 100644 --- a/src/org/xwt/Proxy.java +++ b/src/org/xwt/Proxy.java @@ -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"); } }; diff --git a/src/org/xwt/Resources.java b/src/org/xwt/Resources.java index c4e512e..7e881b1 100644 --- a/src/org/xwt/Resources.java +++ b/src/org/xwt/Resources.java @@ -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); diff --git a/src/org/xwt/SOAP.java b/src/org/xwt/SOAP.java index 648562f..7de30d3 100644 --- a/src/org/xwt/SOAP.java +++ b/src/org/xwt/SOAP.java @@ -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("\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\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"); diff --git a/src/org/xwt/SpecialBoxProperty.java b/src/org/xwt/SpecialBoxProperty.java index b492e6c..c02314c 100644 --- a/src/org/xwt/SpecialBoxProperty.java +++ b/src/org/xwt/SpecialBoxProperty.java @@ -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) { diff --git a/src/org/xwt/Template.java b/src/org/xwt/Template.java index 63a9daa..4ac78db 100644 --- a/src/org/xwt/Template.java +++ b/src/org/xwt/Template.java @@ -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; diff --git a/src/org/xwt/ThreadMessage.java b/src/org/xwt/ThreadMessage.java index faf7577..07a47d4 100644 --- a/src/org/xwt/ThreadMessage.java +++ b/src/org/xwt/ThreadMessage.java @@ -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); } diff --git a/src/org/xwt/Trap.java b/src/org/xwt/Trap.java index 581bd2a..b2d0c4b 100644 --- a/src/org/xwt/Trap.java +++ b/src/org/xwt/Trap.java @@ -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 diff --git a/src/org/xwt/XMLRPC.java b/src/org/xwt/XMLRPC.java index ce1fab2..f103ad0 100644 --- a/src/org/xwt/XMLRPC.java +++ b/src/org/xwt/XMLRPC.java @@ -57,7 +57,7 @@ class XMLRPC extends JS.Callable { * * If an <array> tag is encountered, a null is pushed onto the * stack. When a </data> 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 <struct> 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\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(" \n"); - Array a = (Array)o; + JS.Array a = (JS.Array)o; for(int i=0; i\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("\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; diff --git a/src/org/xwt/XWT.java b/src/org/xwt/XWT.java index f20cf26..a8880ae 100644 --- a/src/org/xwt/XWT.java +++ b/src/org/xwt/XWT.java @@ -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 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 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 + ""); - } else if (o instanceof Array) { + } else if (o instanceof JS.Array) { Log.log(Context.getCurrentSourceNameAndLine() , indent + name + ""); - Array na = (Array)o; + JS.Array na = (JS.Array)o; for(int i=0; i 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= 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())); } }; diff --git a/src/org/xwt/js/Context.java b/src/org/xwt/js/Context.java index 8533f34..34e4028 100644 --- a/src/org/xwt/js/Context.java +++ b/src/org/xwt/js/Context.java @@ -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); diff --git a/src/org/xwt/js/JS.java b/src/org/xwt/js/JS.java index 72c9e2a..05251b8 100644 --- a/src/org/xwt/js/JS.java +++ b/src/org/xwt/js/JS.java @@ -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); + } + } + } diff --git a/src/org/xwt/js/Math.java b/src/org/xwt/js/Math.java index 4f8319a..4cf52e8 100644 --- a/src/org/xwt/js/Math.java +++ b/src/org/xwt/js/Math.java @@ -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; } diff --git a/src/org/xwt/js/Parser.java b/src/org/xwt/js/Parser.java index 76f223b..68cb87c 100644 --- a/src/org/xwt/js/Parser.java +++ b/src/org/xwt/js/Parser.java @@ -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 appendTo; 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 index 0000000..10788fd --- /dev/null +++ b/src/org/xwt/js/ScopeImpl.java @@ -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); + } +} -- 1.7.10.4