5 /** encapsulates the state of a JavaScript "thread" (no relation to Java threads) */
6 public class JSContext {
8 // Statics //////////////////////////////////////////////////////////////////////
9 private int getLine_() { return current().f == null || (pc < 0 || pc >= f.size) ? -1 : f.line[pc]; }
10 public static int getLine() { return current().getLine_(); }
11 public static String getSourceName() { return current().f == null ? null : current().f.sourceName; }
13 /** fetches the currently-executing javascript function */
14 private static JSContext current() { return (JSContext)threadToJSContext.get(Thread.currentThread()); }
15 private static Hashtable threadToJSContext = new Hashtable();
17 // Instance members and methods //////////////////////////////////////////////////////////////////////
20 * the number of times this context has been paused; used by
21 * Function.eval() to make sure it behaves properly even if the
22 * pause Callback is invoked *before* control is returned to
28 JSFunction f; ///< the currently-executing JSFunction
30 Vec stack = new Vec(); ///< the object stack
31 int pc = 0; ///< the program counter
33 public static void invokePauseable(JSFunction function) { new JSContext(function, true).invoke(new JSArray()); }
35 JSContext(JSFunction f, boolean pauseable) {
36 this.pauseable = pauseable;
38 scope = new JSScope(f.parentJSScope);
41 void invoke(JSArray args) {
44 stack.push(new JSFunction.CallMarker(this));
50 /** returns a callback which will restart the context, or null if this context is not pauseable */
51 public static Callback pause() { return current().pause_(); }
52 private Callback pause_() {
53 if (!pauseable) return null;
55 return new Callback() { public Object call(Object o) {
63 private void resume() {
64 Thread t = Thread.currentThread();
65 JSContext old = (JSContext)threadToJSContext.get(t);
66 threadToJSContext.put(t, this);
68 JSFunction.eval(this);
70 if (old == null) threadToJSContext.remove(t);
71 else threadToJSContext.put(t, old);