X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=src%2Forg%2Fxwt%2Fjs%2FJS.java;h=ea117c4349435d182e7f14da0e6331875c5bbb97;hb=bf615a8d1871c2f8a9bf0044297ff253600862e3;hp=f2946ea1c009d475df89b11b3c13bac8974f99ec;hpb=345865827e473f64410c7e3c07e73d20a8db7c4f;p=org.ibex.core.git diff --git a/src/org/xwt/js/JS.java b/src/org/xwt/js/JS.java index f2946ea..ea117c4 100644 --- a/src/org/xwt/js/JS.java +++ b/src/org/xwt/js/JS.java @@ -1,29 +1,46 @@ -// Copyright 2002 Adam Megacz, see the COPYING file for licensing [GPL] +// 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.*; -/** The public API for the JS engine */ -// FEATURE: try using mutable, recycled 'Num' objects +/** + * 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. + */ public abstract class JS { + // Static Methods ////////////////////////////////////////////////////////////////////// - public static Function getCurrentFunction() { - return (Function)currentFunction.get(Thread.currentThread()); - } - public static String getCurrentFunctionSourceName() { - return getCurrentFunctionSourceName(Thread.currentThread()); - } + private static Hashtable currentFunction = new Hashtable(); + public static Function getCurrentFunction() { return (Function)currentFunction.get(Thread.currentThread()); } + public static String getCurrentFunctionSourceName() { return getCurrentFunctionSourceName(Thread.currentThread()); } + public static String getFileAndLine() { return getCurrentFunctionSourceName() + ":" + getCurrentFunction().getLine(); } public static String getCurrentFunctionSourceName(Thread t) { Function f = (Function)currentFunction.get(t); if (f == null) return "null"; return f.getSourceName(); } - public static String getFileAndLine() { - return "unknown:??"; + + public static boolean toBoolean(Object o) { + if (o == null) return false; + if (o instanceof Boolean) return ((Boolean)o).booleanValue(); + if (o instanceof Number) return o.equals(new Integer(0)); + return true; + } + + public static long toLong(Object o) { return toNumber(o).longValue(); } + public static double toDouble(Object o) { return toNumber(o).doubleValue(); } + public static Number toNumber(Object o) { + if (o == null) return new Long(0); + if (o instanceof Number) return ((Number)o); + if (o instanceof String) try { return new Double((String)o); } catch (NumberFormatException e) { return new Double(0); } + if (o instanceof Boolean) return ((Boolean)o).booleanValue() ? new Long(1) : new Long(0); + 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"); } @@ -40,6 +57,7 @@ public abstract class JS { // Subclasses ///////////////////////////////////////////////////////////////////////// + /** A slightly more featureful version of JS */ public static class Obj extends JS { private Hash entries = new Hash(); private boolean sealed = false; @@ -51,6 +69,7 @@ public abstract class JS { public Object[] keys() { return(entries.keys()); } } + /** An exception which can be thrown and caught by JavaScripts */ public static class Exn extends RuntimeException { private Object js = null; public Exn(Object js) { this.js = js; } @@ -59,8 +78,11 @@ public abstract class JS { public Object getObject() { return js; } } + /** A JavaScript Array */ public static class Array extends Obj { private Vec vec = new Vec(); + public Array() { } + public Array(int size) { vec.setSize(size); } private static int intVal(Object o) { if (o instanceof Number) { int intVal = ((Number)o).intValue(); @@ -86,7 +108,7 @@ public abstract class JS { } } public void put(Object key, Object val) { - if (key.equals("length")) vec.setSize(Parser.toNumber(val).intValue()); + if (key.equals("length")) vec.setSize(toNumber(val).intValue()); int i = intVal(key); if (i == Integer.MIN_VALUE) super.put(key, val); else { @@ -102,38 +124,42 @@ public abstract class JS { ret[vec.size()] = "length"; return ret; } + public void setSize(int i) { vec.setSize(i); } public int length() { return vec.size(); } public Object elementAt(int i) { return vec.elementAt(i); } public void addElement(Object o) { vec.addElement(o); } public void setElementAt(Object o, int i) { vec.setElementAt(o, i); } } - public static Hashtable currentFunction = new Hashtable(); + /** Anything that is callable */ public static abstract class Function extends Obj { - public abstract Object _call(JS.Array args) throws JS.Exn; public String getSourceName() throws JS.Exn { return "unknown"; } - public final Object call(JS.Array args) throws JS.Exn { return _call(args); } - } - - public static class Script extends Function { - 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); + public int getLine() throws JS.Exn { return -1; } + public abstract Object _call(JS.Array args) throws JS.Exn, ByteCodeBlock.ControlTransferException; + public final Object call(JS.Array args) throws JS.Exn { Function saved = (Function)currentFunction.get(Thread.currentThread()); currentFunction.put(Thread.currentThread(), this); try { - for(int i=0; i