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();
};
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;
};
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) {
};
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();
};
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) {
};
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) {
};
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++;
}
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();
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);
};
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");
}
};
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);
} 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());
}
}
}
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);
}
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");
}
}
- 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");
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) {
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();
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());
}
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);
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);
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
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());
}
}
}
- 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;
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);
}
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;
* @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 + "\"");
}
// 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();
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;
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
*
* 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
} 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);
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");
// 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();
}
}
- 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");
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;
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++) {
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);
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();
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();
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++)
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();
}
}});
- 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();
}
}});
- 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) {
}
});
- 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;
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);
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));
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();
/** 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 */
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 ///////////////////////////////////////////////
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) {
}
}
- 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) +
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;
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;
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;
}
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");
}
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);
}
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);
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());
}
};
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()));
} };
}
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);
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();
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);
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;
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; }
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);
+ }
+ }
+
}
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;
}
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.
/** 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);
}
* 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");
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
* 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) {
* 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;
}
/** 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 {
}
/** 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()) {
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
--- /dev/null
+// 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);
+ }
+}