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
34 public static void invokePauseable(JSFunction function) {
35 new JSContext(function, true).invoke(new JSArray());
38 /** cannot be paused */
39 public static void invokeTrap(JSTrap.JSTrappable t, Object key, Object value) {
40 JSFunction invoker = new JSFunction("trap invoker", 0, null);
41 invoker.add(-1, ByteCodes.PUT, null);
42 JSContext cx = new JSContext(invoker, false);
49 JSContext(JSFunction f, boolean pauseable) {
50 this.pauseable = pauseable;
52 scope = new JSScope(f.parentJSScope);
55 void invoke(JSArray args) {
58 stack.push(new Interpreter.CallMarker(this));
64 /** returns a callback which will restart the context, or null if this context is not pauseable */
65 public static Callback pause() { return current().pause_(); }
66 private Callback pause_() {
67 if (!pauseable) return null;
69 return new Callback() { public Object call(Object o) {
77 private void resume() {
78 Thread t = Thread.currentThread();
79 JSContext old = (JSContext)threadToJSContext.get(t);
80 threadToJSContext.put(t, this);
82 Interpreter.eval(this);
84 if (old == null) threadToJSContext.remove(t);
85 else threadToJSContext.put(t, old);