From 345865827e473f64410c7e3c07e73d20a8db7c4f Mon Sep 17 00:00:00 2001 From: megacz Date: Fri, 30 Jan 2004 07:00:33 +0000 Subject: [PATCH] 2003/05/26 10:38:33 darcs-hash:20040130070033-2ba56-fce2537a9388c844ea135a2483d59a3eaed8001c.gz --- src/org/xwt/Box.java | 8 +- src/org/xwt/Resources.java | 4 +- src/org/xwt/SpecialBoxProperty.java | 16 ++-- src/org/xwt/Static.java | 3 +- src/org/xwt/XWT.java | 135 ++++++++++++++++--------------- src/org/xwt/js/JS.java | 36 +++++++-- src/org/xwt/js/Parser.java | 150 +++++++++++++++++++++++++---------- 7 files changed, 227 insertions(+), 125 deletions(-) diff --git a/src/org/xwt/Box.java b/src/org/xwt/Box.java index 2ab32b9..a18d888 100644 --- a/src/org/xwt/Box.java +++ b/src/org/xwt/Box.java @@ -1099,14 +1099,17 @@ public final class Box extends JS.Scope { // check if box being moved is currently target of a redirect for(Box cur = newnode.getParent(); cur != null; cur = cur.getParent()) if (cur.redirect == newnode) { - if (Log.on) Log.log(this, "attempt to move a box that is the target of a redirect at "+ JS.getCurrentFunctionSourceName()); + if (Log.on) Log.log(this, "attempt to move a box that is the target of a redirect at "+ + JS.getCurrentFunctionSourceName()); return; } // check for recursive ancestor violation for(Box cur = this; cur != null; cur = cur.getParent()) if (cur == newnode) { - if (Log.on) Log.log(this, "attempt to make a node a parent of its own ancestor at " + JS.getCurrentFunctionSourceName()); + if (Log.on) Log.log(this, "attempt to make a node a parent of its own ancestor at " + + JS.getCurrentFunctionSourceName()); + if (Log.on) Log.log(this, "box == " + this + " ancestor == " + newnode); return; } @@ -1205,6 +1208,7 @@ public final class Box extends JS.Scope { public void put(Object name_, Object value, boolean ignoretraps, RootProxy rp) { if (name_ instanceof Number) { put(((Number)name_).intValue(), value); return; } String name = (String)name_; + if (name == null) return; // FIXME, shouldn't be necessary if (name.startsWith("xwt_")) { if (Log.on) Log.log(this, "attempt to set reserved property " + name + " at " + JS.getFileAndLine()); return; diff --git a/src/org/xwt/Resources.java b/src/org/xwt/Resources.java index c0240ca..a152bf8 100644 --- a/src/org/xwt/Resources.java +++ b/src/org/xwt/Resources.java @@ -48,7 +48,9 @@ public class Resources { /** Load a directory as if it were an archive */ public static synchronized void loadDirectory(File dir) throws IOException { loadDirectory(dir, ""); } private static synchronized void loadDirectory(File dir, String prefix) throws IOException { - new Static(prefix.replace(File.separatorChar, '.')); + String n = prefix.replace(File.separatorChar, '.'); + if (n.endsWith(".")) n = n.substring(0, n.length() - 1); + new Static(n); String[] subfiles = dir.list(); for(int i=0; i 0 && s.charAt(0) == '#') - newcolor = 0xFF000000 | - (Integer.parseInt(s.substring(1, 3), 16) << 16) | - (Integer.parseInt(s.substring(3, 5), 16) << 8) | - Integer.parseInt(s.substring(5, 7), 16); + try { + newcolor = 0xFF000000 | + (Integer.parseInt(s.substring(1, 3), 16) << 16) | + (Integer.parseInt(s.substring(3, 5), 16) << 8) | + Integer.parseInt(s.substring(5, 7), 16); + } catch (NumberFormatException e) { + Log.log(this, "invalid color " + s); + return; + } else if (s.equals("black")) newcolor = black; else if (s.equals("blue")) newcolor = blue; else if (s.equals("green")) newcolor = green; @@ -214,7 +219,8 @@ class SpecialBoxProperty { specialBoxProperties.put("static", new SpecialBoxProperty() { public Object get(Box b) { - String cfsn = JS.getCurrentFunction().getSourceName(); + JS.Function cf = JS.getCurrentFunction(); + String cfsn = cf.getSourceName(); for(int i=0; i '9') return Integer.MIN_VALUE; return Integer.parseInt(s); } - public Object get(Object key) { + public Object get(Object key) throws JS.Exn { // FIXME: HACK! if (key.equals("cascade")) return org.xwt.Trap.cascadeFunction; + if (key.equals("trapee")) return org.xwt.Trap.currentTrapee(); if (key.equals("length")) return new Long(vec.size()); int i = intVal(key); if (i == Integer.MIN_VALUE) return super.get(key); - return vec.elementAt(i); + try { + return vec.elementAt(i); + } catch (ArrayIndexOutOfBoundsException e) { + throw new JS.Exn(e.getMessage()); + } } public void put(Object key, Object val) { if (key.equals("length")) vec.setSize(Parser.toNumber(val).intValue()); int i = intVal(key); if (i == Integer.MIN_VALUE) super.put(key, val); - else vec.setElementAt(val, i); + else { + if (i >= vec.size()) vec.setSize(i+1); + vec.setElementAt(val, i); + } } public Object[] keys() { Object[] sup = super.keys(); @@ -108,24 +116,36 @@ public abstract class JS { } public static class Script extends Function { - Parser.Expr e = null; - private Script(Parser.Expr e) { this.e = e; } + Vector e = null; + private Script(Vector e) { this.e = e; } + public String getSourceName() throws JS.Exn { return ((Parser.Expr)e.elementAt(0)).sourceName; } public Object _call(JS.Array args) throws JS.Exn { Scope rootScope = (Scope)args.elementAt(0); + Function saved = (Function)currentFunction.get(Thread.currentThread()); + currentFunction.put(Thread.currentThread(), this); try { - e.eval(rootScope); + for(int i=0; i> toLong(right.eval(s))); case Lexer.URSH: return new Long(toLong(left.eval(s)) >>> toLong(right.eval(s))); + // FIXME: these need to work on strings case Lexer.LT: return toDouble(left.eval(s)) < toDouble(right.eval(s)) ? Boolean.TRUE : Boolean.FALSE; case Lexer.LE: return toDouble(left.eval(s)) <= toDouble(right.eval(s)) ? Boolean.TRUE : Boolean.FALSE; case Lexer.GT: return toDouble(left.eval(s)) > toDouble(right.eval(s)) ? Boolean.TRUE : Boolean.FALSE; case Lexer.GE: return toDouble(left.eval(s)) >= toDouble(right.eval(s)) ? Boolean.TRUE : Boolean.FALSE; - case Lexer.OR: return new Boolean(toBoolean(left.eval(s)) || toBoolean(right.eval(s))); - case Lexer.AND: return new Boolean(toBoolean(left.eval(s)) && toBoolean(right.eval(s))); + case Lexer.OR: { + boolean b1 = toBoolean(left.eval(s)); + if (b1) return Boolean.TRUE; + return new Boolean(b1 || toBoolean(right.eval(s))); + } + + case Lexer.AND: { + boolean b1 = toBoolean(left.eval(s)); + if (!b1) return Boolean.FALSE; + return new Boolean(b1 && toBoolean(right.eval(s))); + } + case Lexer.BANG: return new Boolean(!toBoolean(left.eval(s))); case Lexer.EQ: @@ -532,7 +558,14 @@ public class Parser extends Lexer { // FIXME: should use Javascript coercion-equality rules Object l = left.eval(s); Object r = right.eval(s); - boolean ret = (l == null && r == null) || (l != null && l.equals(r)); + boolean ret; + if (l == null) { Object t = r; r = l; l = t; } + if (l == null && r == null) ret = true; + else if (l instanceof Boolean) ret = new Boolean(toBoolean(r)).equals(l); + else if (l instanceof Number) ret = toNumber(r).doubleValue() == toNumber(l).doubleValue(); + else if (l instanceof String) ret = r != null && l.equals(r.toString()); + else ret = l.equals(r); + return new Boolean(code == Lexer.EQ ? ret : !ret); } @@ -549,7 +582,7 @@ public class Parser extends Lexer { } else if (o instanceof Boolean) { throw new EvaluatorException("can't set properties on a Boolean"); } else { - JS target = (JS)left.left.eval(s); + JS target = (JS)o; if (target == null) throw new JS.Exn(new EvaluatorException("attempted to put to the null value")); target.put(left.right.eval(s), v); return v; @@ -581,10 +614,10 @@ public class Parser extends Lexer { case Lexer.THROW: throw new JS.Exn(left.eval(s)); case Lexer.NAME: return s.get(string); case Lexer.THIS: return s.isTransparent() ? s : this.eval(s.getParentScope()); - case Lexer.DOT: { final Object o = left.eval(s); - Object v = ((right.code == Lexer.NAME) || (right.code == Lexer.STRING)) ? right.string : right.eval(s); + if (o == null) throw new EvaluatorException("tried to get a property from the null value"); + Object v = (right.code == Lexer.STRING) ? right.string : right.eval(s); if (o instanceof String) { if (v.equals("length")) return new Integer(((String)o).length()); else if (v.equals("substring")) return new JS.Function() { @@ -595,17 +628,35 @@ public class Parser extends Lexer { else throw new EvaluatorException("String.substring() can only take one or two arguments"); } }; + else if (v.equals("toLowerCase")) return new JS.Function() { + public Object _call(JS.Array args) { + return ((String)o).toLowerCase(); + } }; + else if (v.equals("toUpperCase")) return new JS.Function() { + public Object _call(JS.Array args) { + return ((String)o).toString().toUpperCase(); + } }; + else if (v.equals("charAt")) return new JS.Function() { + public Object _call(JS.Array args) { + return ((String)o).charAt(toNumber(args.elementAt(0)).intValue()) + ""; + } }; + else if (v.equals("lastIndexOf")) return new JS.Function() { + 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.Function() { public Object _call(JS.Array args) { if (args.length() != 1) return null; return new Integer(((String)o).indexOf(args.elementAt(0).toString())); - } - }; + } }; throw new EvaluatorException("Not Implemented: properties on String objects"); } else if (o instanceof Boolean) { throw new EvaluatorException("Not Implemented: properties on Boolean objects"); } else if (o instanceof Number) { - throw new EvaluatorException("Not Implemented: properties on Number objects"); + Log.log(this, "Not Implemented: properties on Number objects"); + return null; + //throw new EvaluatorException("Not Implemented: properties on Number objects"); } else if (o instanceof JS) { return ((JS)o).get(v); } @@ -652,7 +703,6 @@ public class Parser extends Lexer { JS.Scope scope = new JS.Scope(s) { // FIXME public String getSourceName() { return sourceName; } - public boolean isTransparent() { return true; } public Object get(Object key) throws JS.Exn { if (key.equals("trapee")) return org.xwt.Trap.currentTrapee(); else if (key.equals("cascade")) return org.xwt.Trap.cascadeFunction; @@ -661,7 +711,10 @@ public class Parser extends Lexer { } }; int i = 0; - for(Expr e = left; e != null; e = e.next) scope.put(e.string, args.get(new Integer(i++))); + for(Expr e = left; e != null; e = e.next) { + scope.declare(e.string); + scope.put(e.string, args.get(new Integer(i++))); + } try { return right.eval(scope); } catch (ReturnException r) { @@ -680,7 +733,8 @@ public class Parser extends Lexer { Object[] keys = ((JS)left.right.eval(s)).keys(); for(int i=0; i