case "y": return N(globalToLocalY(getSurface()._mousey));
// this might not get recomputed if we change mousex/mousey...
- case "inside": return B(MOUSEINSIDE);
+ case "inside": return B(test(MOUSEINSIDE));
//#end
return null;
}
case "Maximized": if (parent == null && getSurface() != null) getSurface().maximized = toBoolean(value); // FEATURE
case "Close": if (parent == null && getSurface() != null) getSurface().dispose(true);
case "redirect": if (redirect == this) redirect = (Box)value; else Log.info(this, "redirect can only be set once");
- case "font": font = value == null ? null : Font.getFont((Stream)value, font == null ? 10 : font.pointsize); MARK_RESIZE; dirty();
+ case "font":
+ if(!(value instanceof Stream)) throw new JSExn("You can only put streams to the font property");
+ font = value == null ? null : Font.getFont((Stream)value, font == null ? 10 : font.pointsize);
+ MARK_RESIZE;
+ dirty();
case "fontsize": font = Font.getFont(font == null ? null : font.res, toInt(value)); MARK_RESIZE; dirty();
case "x": if (parent==null && Surface.fromBox(this)!=null) { CHECKSET_INT(x); } else { if (test(PACKED) && parent != null) return; CHECKSET_INT(x); dirty(); MARK_RESIZE; dirty(); }
case "y": if (parent==null && Surface.fromBox(this)!=null) { CHECKSET_INT(y); } else { if (test(PACKED) && parent != null) return; CHECKSET_INT(y); dirty(); MARK_RESIZE; dirty(); }
-
+ case "titlebar":
+ if (getSurface() != null && value != null) getSurface().setTitleBarText(JS.toString(value));
+ super.put(name,value);
+
case "Press1": if (!test(STOP_UPWARD_PROPAGATION) && parent != null) parent.putAndTriggerTraps(name, value);
case "Press2": if (!test(STOP_UPWARD_PROPAGATION) && parent != null) parent.putAndTriggerTraps(name, value);
case "Press3": if (!test(STOP_UPWARD_PROPAGATION) && parent != null) parent.putAndTriggerTraps(name, value);
if (surface.cursor != tempcursor) surface.syncCursor();
}
- private void setFill(Object value) {
- if (value == null) return;
- if (value instanceof String) {
+ private void setFill(Object value) throws JSExn {
+ if (value == null) {
+ // FIXME: Check this... does this make it transparent?
+ texture = null;
+ fillcolor = 0;
+ } else if (value instanceof String) {
// FIXME check double set
int newfillcolor = stringToColor((String)value);
if (newfillcolor == fillcolor) return;
fillcolor = newfillcolor;
- dirty();
- return;
+ } else if(value instanceof Stream) {
+ texture = Picture.load((Stream)value, this);
+ } else {
+ throw new JSExn("fill must be null, a String, or a stream");
}
- if (!(value instanceof Stream)) return;
- texture = Picture.load((Stream)value, this);
+ dirty();
}
// FIXME: mouse move/release still needs to propagate to boxen in which the mouse was pressed and is still held down
// FIXME support three-char strings by doubling digits
if (s == null) return 0x00000000;
else if (SVG.colors.get(s) != null) return 0xFF000000 | toInt(SVG.colors.get(s));
- else if (s.length() > 0 && s.charAt(0) == '#') try {
+ else if (s.length() == 7 && s.charAt(0) == '#') try {
// FEATURE alpha
return 0xFF000000 |
(Integer.parseInt(s.substring(1, 3), 16) << 16) |
void putAndTriggerTrapsAndCatchExceptions(Object name, Object val) {
try {
putAndTriggerTraps(name, val);
+ } catch (JSExn e) {
+ JS.log("caught js exception while putting to trap \""+name+"\"");
+ JS.log(e);
} catch (Exception e) {
JS.log("caught exception while putting to trap \""+name+"\"");
JS.log(e);
Glyph g = (Glyph)glyphsToBeRendered.remove(false);
if (g == null) { glyphRenderingTaskIsScheduled = false; return; }
if (g.isLoaded) { perform(); /* tailcall to the next glyph */ return; }
- Log.info(Glyph.class, "rendering glyph " + g.c);
+ //Log.info(Glyph.class, "rendering glyph " + g.c);
try { freetype.renderGlyph(g); } catch (IOException e) { Log.info(Freetype.class, e); }
g.isLoaded = true;
Scheduler.add(this); // keep ourselves in the queue until there are no glyphs to render
renderAll();
} catch (JSExn e) {
Log.info(Scheduler.class, "a JavaScript thread spawned with xwt.thread() threw an exception:");
- Log.info(Scheduler.class, e);
+ Log.info(Scheduler.class, "JS Exception: " + e.getObject() + "\n" + e.backtrace());
+ Log.info(Scheduler.class,e);
} catch (Exception e) {
Log.info(Scheduler.class, "a Task threw an exception which was caught by the scheduler:");
Log.info(Scheduler.class, e);
r.t = new Template(r);
new TemplateHelper().parseit(r.getInputStream(), r.t);
return r.t;
- } catch (Exception e) { throw new JSExn(e.toString());
+ } catch (Exception e) {
+ throw new JSExn("Error reading template stream: " + r + "\n" + e.toString());
}
}
* @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) {
+ void apply(Box b, XWT xwt) throws JSExn {
try {
apply(b, xwt, null);
} catch (JSExn e) {
b.clear(b.VISIBLE);
b.mark_for_repack();
- Log.info(Template.class, "WARNING: exception (below) thrown during application of template;");
- Log.info(Template.class, " setting visibility of target box to \"false\"");
- JS.log(e);
+ throw e;
}
}
}
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);
- b.putAndTriggerTraps(JS.N(b.treeSize()), kid);
+ b.putAndTriggerTraps(b.get("numchildren"), kid);
}
if (script != null) script.cloneWithNewParentScope(pis).call(null, null, null, null, 0);
if (val == null) throw new JSExn("redirect target '"+vals[i]+"' not found");
}
- b.putAndTriggerTraps(key, val);
+ try {
+ b.putAndTriggerTraps(key, val);
+ } catch(JSExn e) {
+ e.addBacktrace(fileName + ":attr-" + key,0);
+ throw e;
+ }
}
}
//#switch(name)
case "thread": Scheduler.add((JSFunction)value); return;
case "ui.clipboard": Platform.setClipBoard((String)value); return;
- case "ui.frame": Platform.createSurface((Box)value, true, true); return;
+ case "ui.frame":
+ Box b = (Box)value;
+ Surface s = Platform.createSurface(b,true, true);
+ 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":
HTTP.Proxy.Authorization.authorization = value.toString();
}
}
return a;
+ case "regexp": return new JSRegexp(a, b);
//#end
break;
}
} catch (RuntimeException e) {
// FIXME: maybe JSExn should take a second argument, Exception
- Log.info(this, "xwt."+name+"() threw: "+e);
+ Log.info(this, "xwt."+name+"() threw: " + e);
throw new JSExn("invalid argument for xwt object method "+name+"()");
}
if(op == FINALLY_DONE) {
FinallyData fd = (FinallyData) stack.pop();
if(fd == null) continue OUTER; // NOP
+ if(fd.exn != null) throw fd.exn;
op = fd.op;
arg = fd.arg;
}
int[] jmps = (int[]) arg;
// jmps[0] is how far away the catch block is, jmps[1] is how far away the finally block is
// each can be < 0 if the specified block does not exist
- stack.push(new TryMarker(jmps[0] < 0 ? -1 : pc + jmps[0], jmps[1] < 0 ? -1 : pc + jmps[1], scope));
+ stack.push(new TryMarker(jmps[0] < 0 ? -1 : pc + jmps[0], jmps[1] < 0 ? -1 : pc + jmps[1], this));
break;
}
break;
}
- case THROW: {
- Object o = stack.pop();
- if(o instanceof JSExn) throw (JSExn)o;
- throw new JSExn(o);
- }
+ case THROW:
+ throw new JSExn(stack.pop());
case ASSIGN_SUB: case ASSIGN_ADD: {
Object val = stack.pop();
- Object old = stack.pop();
Object key = stack.pop();
Object obj = stack.peek();
- if (val instanceof JSFunction && obj instanceof JSScope) {
- JSScope parent = (JSScope)obj;
- while(parent.getParentScope() != null) parent = parent.getParentScope();
- if (parent instanceof JS) {
- JS b = (JS)parent;
- if (op == ASSIGN_ADD) b.addTrap(key, (JSFunction)val);
- else b.delTrap(key, (JSFunction)val);
- // skip over the "normal" implementation of +=/-=
- pc += ((Integer)arg).intValue() - 1;
- break;
- }
+ if (val instanceof JSFunction && obj instanceof JS) {
+ // A trap addition/removal
+ JS js = obj instanceof JSScope ? ((JSScope)obj).top() : (JS) obj;
+ if(op == ASSIGN_ADD) js.addTrap(key, (JSFunction)val);
+ else js.delTrap(key, (JSFunction)val);
+ pc += ((Integer)arg).intValue() - 1;
+ } else {
+ // The following setup is VERY important. The generated bytecode depends on the stack
+ // being setup like this (top to bottom) KEY, OBJ, VAL, KEY, OBJ
+ stack.push(key);
+ stack.push(val);
+ stack.push(obj);
+ stack.push(key);
}
- // use the "normal" implementation
- stack.push(key);
- stack.push(old);
- stack.push(val);
break;
}
}
} catch(JSExn e) {
+ if(f.op[pc] != FINALLY_DONE) e.addBacktrace(f.sourceName,f.line[pc]);
while(stack.size() > 0) {
Object o = stack.pop();
if (o instanceof CatchMarker || o instanceof TryMarker) {
stack.push(o);
stack.push(catchMarker);
stack.push(e.getObject());
+ f = ((TryMarker)o).f;
scope = ((TryMarker)o).scope;
pc = ((TryMarker)o).catchLoc - 1;
continue OUTER;
} else {
- stack.push(e);
- stack.push(new FinallyData(THROW));
+ stack.push(new FinallyData(e));
+ f = ((TryMarker)o).f;
scope = ((TryMarker)o).scope;
pc = ((TryMarker)o).finallyLoc - 1;
continue OUTER;
}
+ } else if(o instanceof CallMarker) {
+ CallMarker cm = (CallMarker) o;
+ if(cm.f == null)
+ e.addBacktrace("<java>",0); // This might not even be worth mentioning
+ else
+ e.addBacktrace(cm.f.sourceName,cm.f.line[cm.pc-1]);
}
- // no handler found within this func
- if(o instanceof CallMarker) throw e;
}
throw e;
} // end try/catch
public int catchLoc;
public int finallyLoc;
public JSScope scope;
- public TryMarker(int catchLoc, int finallyLoc, JSScope scope) {
+ public JSFunction f;
+ public TryMarker(int catchLoc, int finallyLoc, Interpreter cx) {
this.catchLoc = catchLoc;
this.finallyLoc = finallyLoc;
- this.scope = scope;
+ this.scope = cx.scope;
+ this.f = cx.f;
}
}
public static class FinallyData {
public int op;
public Object arg;
- public FinallyData(int op, Object arg) { this.op = op; this.arg = arg; }
+ public JSExn exn;
public FinallyData(int op) { this(op,null); }
+ public FinallyData(int op, Object arg) { this.op = op; this.arg = arg; }
+ public FinallyData(JSExn exn) { this.exn = exn; } // Just throw this exn
}
return JS.N(s.lastIndexOf(search,start));
}
case "match": return JSRegexp.stringMatch(s,arg0);
- case "replace": return JSRegexp.stringReplace(s,(String)arg0,arg1);
+ case "replace": return JSRegexp.stringReplace(s,arg0,arg1);
case "search": return JSRegexp.stringSearch(s,arg0);
case "split": return JSRegexp.stringSplit(s,arg0,arg1,alength);
case "toLowerCase": return s.toLowerCase();