+++ /dev/null
-package org.xwt.js;
-import java.util.*;
-import org.xwt.util.*;
-
-/** encapsulates the state of a JavaScript "thread" (no relation to Java threads) */
-public class JSContext {
-
- // Statics //////////////////////////////////////////////////////////////////////
- private int getLine_() { return current().f == null || (pc < 0 || pc >= f.size) ? -1 : f.line[pc]; }
- public static int getLine() { return current().getLine_(); }
- public static String getSourceName() { return current().f == null ? null : current().f.sourceName; }
-
- /** fetches the currently-executing javascript function */
- private static JSContext current() { return (JSContext)threadToJSContext.get(Thread.currentThread()); }
- private static Hashtable threadToJSContext = new Hashtable();
-
- // Instance members and methods //////////////////////////////////////////////////////////////////////
-
- /**
- * the number of times this context has been paused; used by
- * Function.eval() to make sure it behaves properly even if the
- * pause Callback is invoked *before* control is returned to
- * eval()
- */
- int pausecount = 0;
- boolean pauseable;
-
- JSFunction f; ///< the currently-executing JSFunction
- JSScope scope;
- Vec stack = new Vec(); ///< the object stack
- int pc = 0; ///< the program counter
-
- /** can be paused */
- public static void invokePauseable(JSFunction function) {
- new JSContext(function, true).invoke(new JSArray());
- }
-
- /** cannot be paused */
- public static void invokeTrap(JSTrap.JSTrappable t, Object key, Object value) {
- JSFunction invoker = new JSFunction("trap invoker", 0, null);
- invoker.add(-1, ByteCodes.PUT, null);
- JSContext cx = new JSContext(invoker, false);
- cx.stack.push(t);
- cx.stack.push(key);
- cx.stack.push(value);
- cx.resume();
- }
-
- JSContext(JSFunction f, boolean pauseable) {
- this.pauseable = pauseable;
- this.f = f;
- scope = new JSScope(f.parentJSScope);
- }
-
- void invoke(JSArray args) {
- JSFunction tf = f;
- f = null;
- stack.push(new Interpreter.CallMarker(this));
- f = tf;
- stack.push(args);
- resume();
- }
-
- /** returns a callback which will restart the context, or null if this context is not pauseable */
- public static Callback pause() { return current().pause_(); }
- private Callback pause_() {
- if (!pauseable) return null;
- pausecount++;
- return new Callback() { public Object call(Object o) {
- stack.push(o);
- pc++;
- resume();
- return null;
- } };
- }
-
- private void resume() {
- Thread t = Thread.currentThread();
- JSContext old = (JSContext)threadToJSContext.get(t);
- threadToJSContext.put(t, this);
- try {
- Interpreter.eval(this);
- } finally {
- if (old == null) threadToJSContext.remove(t);
- else threadToJSContext.put(t, old);
- }
- }
-}