private Vec children = new Vec(); ///< during XML parsing, this holds the list of currently-parsed children; null otherwise
private int numunits = -1; ///< see numUnits(); -1 means that this value has not yet been computed
- private JSFunction script = null; ///< the script on this node
+ private JS script = null; ///< the script on this node
private String fileName = "unknown"; ///< the filename this node came from; used only for debugging
private Vec preapply = new Vec(); ///< templates that should be preapplied (in the order of application)
// Instance Members that are only meaningful on root Template //////////////////////////////////////
private JSScope staticScope = null; ///< the scope in which the static block is executed
- private JSFunction staticscript = null; ///< the script on the static node of this template, null already performed
+ private JS staticscript = null; ///< the script on the static node of this template, null already performed
// Only used during parsing /////////////////////////////////////////////////////////////////
private StringBuffer content = null; ///< during XML parsing, this holds partially-read character data; null otherwise
private int content_start = 0; ///< line number of the first line of <tt>content</tt>
private int startLine = -1; ///< the line number that this element starts on
- private final Stream r; ///< the resource we came from
+ private XWT xwt;
// Static data/methods ///////////////////////////////////////////////////////////////////
- // FIXME need to provide the XWT object too
- public static Template getTemplate(Stream r) throws JSExn {
+ public Template(InputStream is, XWT xwt) {
+ this.xwt = xwt;
try {
- r = r.addExtension(".xwt");
- if (r.t != null) return r.t;
- r.t = new Template(r);
- new TemplateHelper().parseit(r.getInputStream(), r.t);
- return r.t;
+ new TemplateHelper().parseit(is, this);
} catch (Exception e) {
- throw new JSExn("Error reading template stream: " + r + "\n" + e.toString());
+ throw new RuntimeException(e.toString());
}
}
- public static Stream resolveStringToResource(String str, XWT xwt, boolean permitAbsolute) throws JSExn {
+ public Template(XWT xwt) {
+ this.xwt = xwt;
+ }
+
+ public static JS resolveStringToResource(String str, XWT xwt, boolean permitAbsolute) throws JSExn {
// URL
+ /* FIXME
if (str.indexOf("://") != -1) {
if (permitAbsolute) return (Stream)xwt.url2res(str);
throw new JSExn("absolute URL " + str + " not permitted here");
}
-
+ */
// root-relative
- Stream ret = xwt.rr;
+ JS ret = (JS)xwt.getAndTriggerTraps("");
while(str.indexOf('.') != -1) {
String path = str.substring(0, str.indexOf('.'));
str = str.substring(str.indexOf('.') + 1);
- ret = (Stream)ret.get(path);
+ ret = (JS)ret.get(path);
}
- ret = (Stream)ret.get(str);
+ ret = (JS)ret.get(str);
return ret;
}
// Methods to apply templates ////////////////////////////////////////////////////////
- private Template(Stream r) {
- this.r = r;
- String f = r.toString();
- if (f != null && !f.equals(""))
- fileName = f.substring(f.lastIndexOf('/')+1, f.endsWith(".xwt") ? f.length() - 4 : f.length());
- }
-
/** called before this template is applied or its static object can be externally referenced */
- JSScope getStatic(XWT xwt) throws JSExn {
+ JSScope getStatic() throws JSExn {
if (staticScope == null) staticScope = new PerInstantiationJSScope(null, xwt, null, null);
if (staticscript == null) return staticScope;
- JSFunction temp = staticscript;
+ JS temp = staticscript;
staticscript = null;
- temp.cloneWithNewParentScope(staticScope).call(null, null, null, null, 0);
+ JS.cloneWithNewParentScope(temp, staticScope).call(null, null, null, null, 0);
return staticScope;
}
* @param pboxes a vector of all box parents on which to put $-references
* @param ptemplates a vector of the fileNames to recieve private references on the pboxes
*/
- void apply(Box b, XWT xwt) throws JSExn {
+ void apply(Box b) throws JSExn {
try {
- apply(b, xwt, null);
+ apply(b, null);
+ } catch (IOException e) {
+ b.clear(b.VISIBLE);
+ b.mark_for_repack();
+ throw new JSExn(e.toString());
} catch (JSExn e) {
b.clear(b.VISIBLE);
b.mark_for_repack();
}
}
-
- private void apply(Box b, XWT xwt, PerInstantiationJSScope parentPis) throws JSExn {
- getStatic(xwt);
+ private void apply(Box b, PerInstantiationJSScope parentPis) throws JSExn, IOException {
+ getStatic();
if (id != null) parentPis.putDollar(id, b);
for(int i=0; i<preapply.size(); i++) {
- Template t = getTemplate(resolveStringToResource((String)preapply.elementAt(i), xwt, false));
+ Template t = new Template(Stream.getInputStream(resolveStringToResource((String)preapply.elementAt(i), xwt, false)), xwt);
if (t == null) throw new RuntimeException("unable to resolve resource " + preapply.elementAt(i));
- t.apply(b, xwt);
+ t.apply(b);
}
PerInstantiationJSScope pis = new PerInstantiationJSScope(b, xwt, parentPis, staticScope);
for (int i=0; children != null && i<children.size(); i++) {
Box kid = new Box();
- ((Template)children.elementAt(i)).apply(kid, xwt, pis);
+ ((Template)children.elementAt(i)).apply(kid, pis);
b.putAndTriggerTraps(b.get("numchildren"), kid);
}
- if (script != null) script.cloneWithNewParentScope(pis).call(null, null, null, null, 0);
+ if (script != null) JS.cloneWithNewParentScope(script, pis).call(null, null, null, null, 0);
Object key, val;
for(int i=0; keys != null && i < keys.length; i++) {
// push the last node we were in onto the stack
nodeStack.addElement(t);
// instantiate a new node, and set its fileName/importlist/preapply
- Template t2 = new Template(t.r);
+ Template t2 = new Template(t.xwt);
t2.startLine = getLine();
if (!c.getLocalName().equals("box") && !c.getLocalName().equals("template"))
t2.preapply.addElement((c.getUri().equals("") ? "" : (c.getUri() + ".")) + c.getLocalName());
}
}
- private JSFunction parseScript(boolean isstatic) throws IOException {
- JSFunction thisscript = null;
+ private JS parseScript(boolean isstatic) throws IOException {
+ JS thisscript = null;
String contentString = t.content.toString();
if (contentString.trim().length() > 0)
- thisscript = JSFunction.fromReader(t.fileName + (isstatic ? "._" : ""),
+ thisscript = JS.fromReader(t.fileName + (isstatic ? "._" : ""),
t.content_start,
new StringReader(contentString));
t.content = null;
public Object get(Object key) throws JSExn {
if (super.has(key)) return super.get(key);
if (key.equals("xwt")) return xwt;
- if (key.equals("")) return xwt.rr;
+ if (key.equals("")) return xwt.get("");
if (key.equals("static")) return myStatic;
return super.get(key);
}
/** this holds character content as we read it in -- since there is only one per instance, we don't support mixed content */
protected AccessibleCharArrayWriter content = new AccessibleCharArrayWriter(100);
- protected String url = null; ///< the url to connect to
- protected String method = null; ///< the method name to invoke on the remove server
- protected HTTP http = null; ///< the HTTP connection to use
+ protected String url = null; ///< the url to connect to
+ protected String method = null; ///< the method name to invoke on the remove server
+ protected HTTP http = null; ///< the HTTP connection to use
private Hash tracker; ///< used to detect multi-ref data
protected boolean fault = false; ///< True iff the return value is a fault (and should be thrown as an exception)
case "boolean": objects.setElementAt(content.getBuf()[0] == '1' ? Boolean.TRUE : Boolean.FALSE, objects.size() - 1);
case "string": objects.setElementAt(new String(content.getBuf(), 0, content.size()), objects.size() - 1);
case "double": objects.setElementAt(new Double(new String(content.getBuf(), 0, content.size())), objects.size() - 1);
- case "base64": objects.setElementAt(new Stream.ByteArray(Base64.decode(new String(content.getBuf(), 0, content.size())),
- null), objects.size() - 1);
+ case "base64":
+ objects.setElementAt(new Stream.ByteArray(Base64.decode(new String(content.getBuf(), 0, content.size())),
+ null), objects.size() - 1);
case "name": objects.addElement(new String(content.getBuf(), 0, content.size()));
case "value": if ("".equals(objects.lastElement()))
objects.setElementAt(new String(content.getBuf(), 0, content.size()), objects.size() - 1);
try {
JSDate nd = new JSDate();
double date = JSDate.date_msecFromDate(Double.valueOf(s.substring(0, 4)).doubleValue(),
- Double.valueOf(s.substring(4, 6)).doubleValue() - 1,
- Double.valueOf(s.substring(6, 8)).doubleValue(),
- Double.valueOf(s.substring(9, 11)).doubleValue(),
- Double.valueOf(s.substring(12, 14)).doubleValue(),
- Double.valueOf(s.substring(15, 17)).doubleValue(),
- (double)0
- );
+ Double.valueOf(s.substring(4, 6)).doubleValue() - 1,
+ Double.valueOf(s.substring(6, 8)).doubleValue(),
+ Double.valueOf(s.substring(9, 11)).doubleValue(),
+ Double.valueOf(s.substring(12, 14)).doubleValue(),
+ Double.valueOf(s.substring(15, 17)).doubleValue(),
+ (double)0
+ );
nd.setTime(JSDate.internalUTC(date));
objects.setElementAt(nd, objects.size() - 1);
} catch (Exception e) {
- if (Log.on) Log.info(this, "error parsing date : " + s);
- if (Log.on) Log.info(this, e);
+ throw new RuntimeException("xwt.net.rpc.xml.recieve.malformedDateTag" +
+ "the server sent a <dateTime.iso8601> tag which was malformed: " + s);
}
case "member":
Object memberValue = objects.elementAt(objects.size() - 1);
+// FIXME
// Copyright 2004 Adam Megacz, see the COPYING file for licensing [GPL]
package org.xwt;
import org.bouncycastle.util.encoders.Base64;
/** Singleton class that provides all functionality in the xwt.* namespace */
-public final class XWT extends JS {
+public final class XWT extends JS.Cloneable {
- public final Stream rr;
- public XWT(Stream rr) { this.rr = rr; }
+ private final JS rr;
+ public XWT(Stream rr) { this.rr = bless(rr); }
private Cache subCache = new Cache(20);
private Sub getSub(String s) {
private class Sub extends JS {
String key;
Sub(String key) { this.key = key; }
- public String toString() { return "XWTSUB " + key; }
public void put(Object key, Object val) throws JSExn { XWT.this.put(this.key + "." + key, val); }
public Object get(Object key) throws JSExn { return XWT.this.get(this.key + "." + key); }
- public boolean coerceToBoolean() {
- if (key.equals("ui.key.alt")) return Surface.alt ? true : false;
- return super.coerceToBoolean();
- }
public Object call(Object a0, Object a1, Object a2, Object[] rest, int nargs) throws JSExn {
return XWT.this.callMethod(this.key, a0, a1, a2, rest, nargs);
}
case "math": return xwtMath;
case "string": return xwtString;
case "date": return METHOD;
- case "origin": return Main.origin; // FIXME not in ref
case "box": return new Box();
case "apply": return METHOD;
case "graft": return METHOD;
case "clone": return METHOD;
+ case "bless": return METHOD;
case "regexp": return METHOD;
case "ui.font": return getSub("ui.font");
case "ui.font.sansserif": return Main.builtin.get("fonts/vera/Vera.ttf");
else if (!Surface.button1 && !Surface.button2 && Surface.button3) return N(3);
else return ZERO;
case "ui.key": return getSub("ui.key");
- case "ui.key.alt": return getSub("ui.key.alt");
- case "ui.key.alt.name": return Platform.altKeyName();
+ case "ui.key.name": return getSub("ui.key.name");
+ case "ui.key.name.alt": return Platform.altKeyName();
+ case "ui.key.alt": return Surface.alt ? T : F;
case "ui.key.control": return Surface.control ? T : F;
case "ui.key.shift": return Surface.shift ? T : F;
case "ui.clipboard": return Platform.getClipBoard();
- case "ui.maxdim": return new Integer(Short.MAX_VALUE);
+ case "ui.maxdim": return N(Short.MAX_VALUE);
case "ui.screen": return getSub("ui.screen");
- case "ui.screen.width": return new Integer(Platform.getScreenWidth());
- case "ui.screen.height": return new Integer(Platform.getScreenHeight());
+ case "ui.screen.width": return N(Platform.getScreenWidth());
+ case "ui.screen.height": return N(Platform.getScreenHeight());
case "undocumented": return getSub("undocumented");
- case "undocumented.internal": return getSub("undocumented.internal");
+ case "undocumented.initialOrigin": return Main.origin;
case "thread": return getSub("thread");
case "thread.yield": return METHOD;
case "thread.sleep": return METHOD;
case "stream": return getSub("stream");
- case "stream.home": return url2res("file:" + System.getProperty("user.home"));
- case "stream.temp": return url2res("file:" + System.getProperty("java.io.tempdir"));
+ case "stream.homedir": return url2res("file:" + System.getProperty("user.home"));
+ case "stream.tempdir": return url2res("file:" + System.getProperty("java.io.tempdir"));
case "stream.watch": return METHOD;
case "stream.unzip": return METHOD;
case "stream.uncab": return METHOD;
public void put(Object name, final Object value) throws JSExn {
//#switch(name)
- case "thread": Scheduler.add((JSFunction)value); return;
+ case "thread": Scheduler.add((Scheduler.Task)value); return;
case "ui.clipboard": Platform.setClipBoard((String)value); return;
case "ui.frame":
Box b = (Box)value;
if(b.get("titlebar") != null) s.setTitleBarText(JS.toString(b.get("titlebar")));
return;
case "ui.window": Platform.createSurface((Box)value, false, true); return;
- case "undocumented.internal.proxyAuthorization":
+ case "undocumented.proxyAuthorization":
HTTP.Proxy.Authorization.authorization = value.toString();
HTTP.Proxy.Authorization.waitingForUser.release(); return;
//#end
try {
//#switch(name)
case "date": return new JSDate(a, b, c, rest, nargs);
- case "rpc.soap": return new SOAP((String)a, "", (String)b, (String)c);
- case "graft":
- if (a instanceof Box) throw new JSExn("can't graft onto Boxes");
- if (a instanceof String) throw new JSExn("can't graft onto Strings");
- if (a instanceof Number) throw new JSExn("can't graft onto Numbers");
- if (a instanceof Stream) return new Stream.Graft((Stream)a, b, c);
- // FEATURE: grafting onto JS
- throw new JSExn("cannot graft onto "+a.getClass());
+ case "net.rpc.soap": return new SOAP((String)a, "", (String)b, (String)c);
//#end
switch (nargs) {
break;
case 1:
//#switch(name)
+ case "clone":
+ if (!(a instanceof JS.Cloneable)) throw new JSExn("cannot clone a " + a.getClass().getName());
+ return ((JS.Cloneable)a).jsclone();
+ case "bless": return bless((JS)a);
case "ui.browser": Platform.newBrowserWindow((String)a); return null;
- case "clone": return new XWT((Stream)a);
case "stream.unzip": return new Stream.Zip((Stream)a);
case "stream.uncab": return new Stream.Cab((Stream)a);
case "stream.cache": try { return new Stream.CachedStream((Stream)a, "resources", true); }
catch (Stream.NotCacheableException e) { throw new JSExn("this resource cannot be cached"); }
- case "stream.url": return url2res((String)a);
+ case "stream.url": {
+ String url = (String)a;
+ if (url.startsWith("http://")) return new Stream.HTTP(url);
+ else if (url.startsWith("https://")) return new Stream.HTTP(url);
+ else if (url.startsWith("data:")) return new Stream.ByteArray(Base64.decode(url.substring(5)), null);
+ else if (url.startsWith("utf8:")) return new Stream.ByteArray(url.substring(5).getBytes(), null);
+ throw new JSExn("invalid resource specifier " + url);
+ }
case "thread.sleep": sleep(JS.toInt(a)); return null;
case "log.debug": JS.log(this, a== null ? "**null**" : a.toString()); return null;
case "log.info": JS.log(this, a== null ? "**null**" : a.toString()); return null;
case "crypto.md5": /* FEATURE */ return null;
case "crypto.sha1": /* FEATURE */ return null;
case "crypto.rc4": /* FEATURE */ return null;
- case "stream.parse.html": /* FIXME */ return null;
- case "stream.parse.xml": /* FIXME -- SAX NOT DOM!! */ return null;
- case "stream.parse.utf8": /* FIXME */ return null;
+ case "stream.parse.html": throw new JSExn("not implemented yet"); //return null;
+ case "stream.parse.xml": new XMLHelper((JS)b).doParse((JS)a); return null;
+ case "stream.parse.utf8":
+ //return new String(InputStreamToByteArray.convert(((Stream)a).getInputStream()));
+ return null;
//#end
break;
case 2:
//#switch(name)
- case "stream.watch": return new Stream.ProgressWatcher((Stream)a, (JSFunction)b);
- case "apply":
- if (b instanceof Stream) Template.getTemplate((Stream)b).apply((Box)a, XWT.this);
- else {
- JS to = (JS)a, from = (JS)b; Object k;
- for (Enumeration e = from.keys(); e.hasMoreElements();) {
- k = e.nextElement(); to.put(k, from.get(k));
- }
- }
- return a;
+ case "stream.watch": return new Stream.ProgressWatcher((Stream)a, (JS)b);
case "regexp": return new JSRegexp(a, b);
//#end
break;
};
private class XMLHelper extends XML {
- Vector obStack = new Vector();
- public XMLHelper() { super(BUFFER_SIZE); }
+ private JS characters, whitespace, endElement, startElement;
+ public XMLHelper(JS b) throws JSExn {
+ super(BUFFER_SIZE);
+ // FIXME: trigger traps?
+ startElement = (JS)b.get("startElement");
+ endElement = (JS)b.get("endElement");
+ characters = (JS)b.get("characters");
+ whitespace = (JS)b.get("whitespace");
+ }
+ private class XMLJSWrapper extends XML.Exn {
+ public JSExn wrapee; public XMLJSWrapper(JSExn jse) { super(""); wrapee = jse; } }
public void startElement(XML.Element c) throws XML.Exn {
try {
- JS o = new JS();
- o.put("$name", c.getLocalName());
- for(int i=0; i < c.getAttrLen(); i++) o.put(c.getAttrKey(i), c.getAttrVal(i));
- o.put("$numchildren", new Integer(0));
- obStack.addElement(o);
+ JS attrs = new JS();
+ for(int i=0; i<c.getAttrLen(); i++) attrs.put(c.getAttrKey(i), c.getAttrVal(i)); // FIXME attribute URIs?
+ startElement.call(c.getLocalName(), attrs, c.getUri(), null, 3);
} catch (JSExn jse) {
- throw new Error("this should never happen");
+ throw new XMLJSWrapper(jse);
}
}
public void endElement(XML.Element c) throws XML.Exn {
try {
- if (obStack.size() == 1) return;
- JS me = (JS)obStack.lastElement();
- obStack.setSize(obStack.size() - 1);
- JS parent = (JS)obStack.lastElement();
- int numchildren = ((Integer)parent.get("$numchildren")).intValue();
- parent.put("$numchildren", new Integer(numchildren + 1));
- parent.put(new Integer(numchildren), me);
+ endElement.call(c.getLocalName(), c.getUri(), null, null, 2);
} catch (JSExn jse) {
- throw new Error("this should never happen");
+ throw new XMLJSWrapper(jse);
}
}
public void characters(char[] ch, int start, int length) throws XML.Exn {
try {
- String s = new String(ch, start, length);
- JS parent = (JS)obStack.lastElement();
- int numchildren = ((Integer)parent.get("$numchildren")).intValue();
- Object lastChild = parent.get(new Integer(numchildren - 1));
- if (lastChild instanceof String) {
- parent.put(new Integer(numchildren - 1), lastChild + s);
- } else {
- parent.put("$numchildren", new Integer(numchildren + 1));
- parent.put(new Integer(numchildren), s);
- }
+ characters.call(new String(ch, start, length), null, null, null, 1);
} catch (JSExn jse) {
- throw new Error("this should never happen");
+ throw new XMLJSWrapper(jse);
}
}
- public void whitespace(char[] ch, int start, int length) {}
- public JS doParse(InputStream is) throws JSExn {
+ public void whitespace(char[] ch, int start, int length) throws XML.Exn {
+ try {
+ whitespace.call(new String(ch, start, length), null, null, null, 1);
+ } catch (JSExn jse) {
+ throw new XMLJSWrapper(jse);
+ }
+ }
+ public void doParse(JS s) throws JSExn {
try {
- BufferedReader r = new BufferedReader(new InputStreamReader(is));
- parse(r);
+ parse(new BufferedReader(new InputStreamReader(Stream.getInputStream(s))));
+ } catch (XMLJSWrapper e) {
+ throw e.wrapee;
} catch (XML.Exn e) {
throw new JSExn("error parsing XML: " + e.toString());
} catch (IOException e) {
if (Log.on) Log.info(this, e);
throw new JSExn("error reading from Resource");
}
- return obStack.size() >= 1 ? (JS)obStack.elementAt(0) : null;
}
}
+
+ public Blessing bless(JS b) { return new XWT.Blessing((JS.Cloneable)b, this, null, null); }
+ public static class Blessing extends JS.Clone {
+ private XWT xwt;
+ private Template t = null;
+ private Object parentkey = null;
+ private Blessing parent = null;
+ public Blessing(JS.Cloneable clonee, XWT xwt, Blessing parent, Object parentkey) {
+ super(clonee); this.xwt = xwt; this.parentkey = parentkey; this.parent = parent; }
+ public Object get(Object key) throws JSExn {
+ return key.equals("") ? ((Object)getStatic()) : (new Blessing((JS.Cloneable)clonee.get(key), xwt, this, key));
+ }
+ public InputStream getImage() throws JSExn {
+ InputStream in = null;
+ try {
+ in = Stream.getInputStream(this);
+ if (in != null) return in;
+ } catch (IOException e) { /* DELIBERATE */ in = null; }
+ String[] exts = new String[] { ".png", ".jpeg", ".gif" };
+ for (int i=0; i < exts.length && in == null; i++) {
+ try {
+ in = Stream.getInputStream(parent.get(parentkey + exts[i]));
+ if (in != null) return in;
+ } catch (IOException f) { in = null; }
+ }
+ return null;
+ }
+ public JSScope getStatic() throws JSExn {
+ try {
+ // FIXME background?
+ if (t == null) t = new Template(Stream.getInputStream(parent.get(parentkey + ".xwt")), xwt);
+ return t.getStatic();
+ } catch (Exception e) {
+ Log.error(this, e);
+ return null;
+ }
+ }
+ public Object call(Object a, Object b, Object c, Object[] rest, int nargs) throws JSExn {
+ if (nargs != 1) throw new JSExn("FIXME can only call with one arg");
+ getStatic();
+ t.apply((Box)a);
+ return a;
+ }
+ }
+
}
var new_xwt = xwt.clone(new_rr);
xwt.thread = function() {
-for(var i=0; 100>i; i++) {
-progress(i, 100);
-xwt.thread.yield();
-}
- new_xwt.apply(xwt.box, new_xwt["main.xwt"]);
- thisbox = null;
+ for(var i=0; 100>i; i++) {
+ progress(i, 100);
+ xwt.thread.yield();
}
+ new_xwt.apply(xwt.box, new_xwt["main.xwt"]);
+ thisbox = null;
+ }
xwt.log.println("leaving");
}
}
}
- private static JSExn je(String s) { return new JSExn(JS.getSourceName() + ":" + JS.getLine() + " " + s); }
+ static int getLine() {
+ Interpreter c = Interpreter.current();
+ return c == null || c.f == null || c.pc < 0 || c.pc >= c.f.size ? -1 : c.f.line[c.pc];
+ }
+
+ static String getSourceName() {
+ Interpreter c = Interpreter.current();
+ return c == null || c.f == null ? null : c.f.sourceName;
+ }
+
+ private static JSExn je(String s) { return new JSExn(getSourceName() + ":" + getLine() + " " + s); }
// FIXME: double check the trap logic
private Object run() throws JSExn {
case ASSERT: if (!JS.toBoolean(stack.pop())) throw je("xwt.assertion.failed" /*FEATURE: line number*/); break;
case BITNOT: stack.push(JS.N(~JS.toLong(stack.pop()))); break;
case BANG: stack.push(JS.B(!JS.toBoolean(stack.pop()))); break;
- case NEWFUNCTION: stack.push(((JSFunction)arg).cloneWithNewParentScope(scope)); break;
+ case NEWFUNCTION: stack.push(((JSFunction)arg)._cloneWithNewParentScope(scope)); break;
case LABEL: break;
case TYPEOF: {
Object o = stack.pop();
if (o == null) stack.push(null);
- else if (o instanceof JS) stack.push(((JS)o).typeName());
+ else if (o instanceof JS) stack.push("object");
else if (o instanceof String) stack.push("string");
else if (o instanceof Number) stack.push("number");
else if (o instanceof Boolean) stack.push("boolean");
- else stack.push("unknown");
+ else throw new Error("this should not happen");
break;
}
}
}
throw new Error("CONTINUE/BREAK invoked but couldn't find LoopMarker at " +
- JS.getSourceName() + ":" + JS.getLine());
+ getSourceName() + ":" + getLine());
case TRY: {
int[] jmps = (int[]) arg;
/** The minimum set of functionality required for objects which are manipulated by JavaScript */
public class JS extends org.xwt.util.BalancedTree {
- // Static Interpreter Control Methods ///////////////////////////////////////////////////////////////
+ public static final Object METHOD = new Object();
+ public final JS unclone() { return _unclone(); }
+ public Enumeration keys() throws JSExn { return entries == null ? emptyEnumeration : entries.keys(); }
+ public Object get(Object key) throws JSExn { return entries == null ? null : entries.get(key, null); }
+ public void put(Object key, Object val) throws JSExn { (entries==null?entries=new Hash():entries).put(key,null,val); }
+ public Object callMethod(Object method, Object a0, Object a1, Object a2, Object[] rest, int nargs) throws JSExn {
+ throw new JSExn("attempted to call the null value (method "+method+")");
+ }
+ public Object call(Object a0, Object a1, Object a2, Object[] rest, int nargs) throws JSExn {
+ throw new JSExn("you cannot call this object (class=" + this.getClass().getName() +")");
+ }
- /** log a message with the current JavaScript sourceName/line */
- public static void log(Object o, Object message) { log(message); }
- public static void log(Object message) { Log.echo(JS.getSourceName() + ":" + JS.getLine(), message); }
- public static void log(JSExn e) {
- Log.echo(e,"JS Exception: " + e.getObject() + "\n" + e.backtrace());
- Log.echo(e,e);
+ JS _unclone() { return this; }
+ public static class Cloneable extends JS {
+ public Cloneable() { }
+ public Object jsclone() throws JSExn {
+ throw new JSExn("cloning not yet implemented");
+ }
}
- public static int getLine() {
- Interpreter c = Interpreter.current();
- return c == null || c.f == null || c.pc < 0 || c.pc >= c.f.size ? -1 : c.f.line[c.pc];
+ public static class Clone extends JS.Cloneable {
+ protected JS.Cloneable clonee = null;
+ JS _unclone() { return clonee; }
+ public Clone(JS.Cloneable clonee) { this.clonee = clonee; }
+ public boolean equals(Object o) {
+ if (!(o instanceof JS)) return false;
+ return unclone() == ((JS)o).unclone();
+ }
+ public Enumeration keys() throws JSExn { return clonee.keys(); }
+ public Object get(Object key) throws JSExn { return clonee.get(key); }
+ public void put(Object key, Object val) throws JSExn { clonee.put(key, val); }
+ public Object callMethod(Object method, Object a0, Object a1, Object a2, Object[] rest, int nargs) throws JSExn {
+ return clonee.callMethod(method, a0, a1, a2, rest, nargs);
+ }
+ public Object call(Object a0, Object a1, Object a2, Object[] rest, int nargs) throws JSExn {
+ return clonee.call(a0, a1, a2, rest, nargs);
+ }
}
- public static String getSourceName() {
- Interpreter c = Interpreter.current();
- return c == null || c.f == null ? null : c.f.sourceName;
- }
+ // Static Interpreter Control Methods ///////////////////////////////////////////////////////////////
+
+ /** log a message with the current JavaScript sourceName/line */
+ public static void log(Object o, Object message) { log(message); }
+ public static void log(Object message) { Log.echo(Interpreter.getSourceName() + ":" + Interpreter.getLine(), message); }
+ public static void log(JSExn e) { Log.echo(e,"JS Exception: " + e.getObject() + "\n" + e.backtrace()); Log.echo(e,e); }
public static class NotPauseableException extends Exception { NotPauseableException() { } }
// NOTE: There are about 3 pages of rules in ecma262 about string to number conversions
// We aren't even close to following all those rules. We probably never will be.
- if (o instanceof String)
- try { return N((String)o); } catch (NumberFormatException e) { return N(Double.NaN); }
+ if (o instanceof String) try { return N((String)o); } catch (NumberFormatException e) { return N(Double.NaN); }
if (o instanceof Boolean) return ((Boolean)o).booleanValue() ? N(1) : ZERO;
- if (o instanceof JS) return ((JS)o).coerceToNumber();
throw new Error("toNumber() got object of type " + o.getClass().getName() + " which we don't know how to handle");
}
if(o == null) return "null";
if(o instanceof String) return (String) o;
if(o instanceof Integer || o instanceof Long || o instanceof Boolean) return o.toString();
- if(o instanceof JS) return ((JS)o).coerceToString();
+ if(o instanceof JSArray) return o.toString();
+ if(o instanceof JSDate) return o.toString();
if(o instanceof Double || o instanceof Float) {
double d = ((Number)o).doubleValue();
if((int)d == d) return Integer.toString((int)d);
return o.toString();
}
- return o.toString();
+ throw new RuntimeException("can't coerce that!");
}
-
// Instance Methods ////////////////////////////////////////////////////////////////////
public static final Integer ZERO = new Integer(0);
};
private Hash entries = null;
- public Enumeration keys() throws JSExn {
- return entries == null ? emptyEnumeration : entries.keys();
+
+ public static JS fromReader(String sourceName, int firstLine, Reader sourceCode) throws IOException {
+ return JSFunction._fromReader(sourceName, firstLine, sourceCode);
}
- public Object get(Object key) throws JSExn { return entries == null ? null : entries.get(key, null); }
- public void put(Object key, Object val) throws JSExn {
- if (entries == null) entries = new Hash();
- entries.put(key, null, val);
+
+ // HACK: caller can't know if the argument is a JSFunction or not...
+ public static JS cloneWithNewParentScope(JS j, JSScope s) {
+ return ((JSFunction)j)._cloneWithNewParentScope(s);
}
// Trap support //////////////////////////////////////////////////////////////////////////////
/** override and return true to allow placing traps on this object.
- * if isRead true, this is a read trap, otherwise write trap
- **/
+ * if isRead true, this is a read trap, otherwise write trap
+ **/
protected boolean isTrappable(Object name, boolean isRead) { return true; }
/** performs a put, triggering traps if present; traps are run in an unpauseable interpreter */
}
- // Call Support //////////////////////////////////////////////////////////////////////////////
-
- // return this from get() if the key was actually a method.
- public static final Object METHOD = new Object();
- public Object callMethod(Object method, Object a0, Object a1, Object a2, Object[] rest, int nargs) throws JSExn {
- throw new JSExn("attempted to call the null value (method "+method+")");
- }
- public Object call(Object a0, Object a1, Object a2, Object[] rest, int nargs) throws JSExn {
- throw new JSExn("you cannot call this object (class=" + this.getClass().getName() +")");
- }
-
-
- // Typing Support //////////////////////////////////////////////////////////////////////////////
-
- public Number coerceToNumber() { throw new JSRuntimeExn("tried to coerce a JavaScript object of type " +
- getClass().getName() + " to a Number"); }
- public String coerceToString() { throw new JSRuntimeExn("tried to coerce a JavaScript object of type " +
- getClass().getName() + " to a String"); }
- public boolean coerceToBoolean() { throw new JSRuntimeExn("tried to coerce a JavaScript object of type " +
- getClass().getName() + " to a Boolean"); }
-
- public String typeName() { return "object"; }
-
}
}
}
- public String coerceToString() { return JS.toString(join(",")); }
+ public String toString() { return JS.toString(join(",")); }
}
}
}
- public String coerceToString() { return date_format(date, FORMATSPEC_FULL); }
+ public String toString() { return date_format(date, FORMATSPEC_FULL); }
public Object callMethod(Object method, Object a0, Object a1, Object a2, Object[] rest, int nargs) throws JSExn {
switch(nargs) {
private Vec backtrace = new Vec();
private Object js = null;
public JSExn(Object js) { this.js = js; }
- public String toString() { return "JSExn: " + JS.toString(js); }
+ public String toString() { return "JSExn: " + js; }
public String getMessage() { return toString(); }
public Object getObject() { return js; }
public void addBacktrace(String sourceName, int lineNo) { backtrace.addElement(sourceName + ":" + lineNo); }
import java.io.*;
/** A JavaScript function, compiled into bytecode */
-public class JSFunction extends JS implements ByteCodes, Tokens, org.xwt.Scheduler.Task {
+class JSFunction extends JS implements ByteCodes, Tokens, org.xwt.Scheduler.Task {
// Fields and Accessors ///////////////////////////////////////////////
}
/** parse and compile a function */
- public static JSFunction fromReader(String sourceName, int firstLine, Reader sourceCode) throws IOException {
+ public static JSFunction _fromReader(String sourceName, int firstLine, Reader sourceCode) throws IOException {
JSFunction ret = new JSFunction(sourceName, firstLine, null);
if (sourceCode == null) return ret;
Parser p = new Parser(sourceCode, sourceName, firstLine);
return ret;
}
- public JSFunction cloneWithNewParentScope(JSScope s) {
+ public JSFunction _cloneWithNewParentScope(JSScope s) {
JSFunction ret = new JSFunction(sourceName, firstLine, s);
// Reuse the same op, arg, line, and size variables for the new "instance" of the function
// NOTE: Neither *this* function nor the new function should be modified after this call
import java.io.*;
import java.util.*;
+// FIXME: should allow parentScope to be a JS, not a JSScope
/** Implementation of a JavaScript Scope */
public class JSScope extends JS {
/** for debugging */
public static void main(String[] s) throws Exception {
- JSFunction block = JSFunction.fromReader("stdin", 0, new InputStreamReader(System.in));
+ JS block = JS.fromReader("stdin", 0, new InputStreamReader(System.in));
if (block == null) return;
System.out.println(block);
}
Grammar g = parseGrammar(null);
if (peekToken() == LC) {
g.action = new JSFunction(sourceName, parserLine, null);
- parseBlock(g.action);
- g.action.add(parserLine, LITERAL, null); // in case we "fall out the bottom", return NULL
- g.action.add(parserLine, RETURN);
+ parseBlock((JSFunction)g.action);
+ ((JSFunction)g.action).add(parserLine, LITERAL, null); // in case we "fall out the bottom", return NULL
+ ((JSFunction)g.action).add(parserLine, RETURN);
}
b.add(parserLine, MAKE_GRAMMAR, g);
b.add(parserLine, PUT);
import org.xwt.util.*;
import java.net.*;
import java.io.*;
+import org.xwt.js.*;
import java.util.*;
import java.awt.*;
import java.awt.datatransfer.*;
protected String getDescriptiveName() { return "Generic JDK 1.1+ with AWT"; }
protected PixelBuffer _createPixelBuffer(int w, int h, Surface owner) { return new AWTPixelBuffer(w, h); }
- protected Picture _createPicture(Stream r) { return new AWTPicture(r); }
+ protected Picture _createPicture(JS r) { return new AWTPicture(r); }
protected int _getScreenWidth() { return Toolkit.getDefaultToolkit().getScreenSize().width; }
protected int _getScreenHeight() { return Toolkit.getDefaultToolkit().getScreenSize().height; }
protected Surface _createSurface(Box b, boolean framed) { return new AWTSurface(b, framed); }
private static ColorModel cmodel = new DirectColorModel(32, 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000);
boolean initialized = false;
- public AWTPicture(Stream r) { super(r); }
+ public AWTPicture(JS r) { super(r); }
public void init() {
if (initialized) return;
initialized = true;
HTTP.Proxy ret = new HTTP.Proxy();
if (container[2] != null) {
- ret.proxyAutoConfigJSFunction = HTTP.Proxy.getProxyAutoConfigJSFunction(container[2]);
- if (ret.proxyAutoConfigJSFunction != null) return ret;
+ ret.proxyAutoConfigFunction = HTTP.Proxy.getProxyAutoConfigFunction(container[2]);
+ if (ret.proxyAutoConfigFunction != null) return ret;
}
if (container[0] == null) return null;
try {
Log.info(this, "loading font " + res);
loadedStream = res;
- InputStream is = res.getInputStream();
+ InputStream is = Stream.getInputStream(res);
byte[] fontstream = InputStreamToByteArray.convert(is);
vm = new MIPSApps();
int baseAddr = vm.sbrk(fontstream.length);
public abstract class Grammar extends JS {
- public JSFunction action = null;
+ public JS action = null;
public Grammar() { }
// means we call()ed a Grammar that hasn't been bound to a scope yet
final int ret = match(s, start, v2, scope);
Object result = ret == -1 ? NULL : action == null ?
s.substring(start, ret) :
- action.cloneWithNewParentScope(new JSScope(scope) {
+ JS.cloneWithNewParentScope(action, new JSScope(scope) {
public Object get(Object key) throws JSExn {
Object val = v2.get(key);
if (val == NULL) return null;