📄 dim.java
字号:
final String alertMessage; if (scriptException == null) { alertMessage = null; } else { alertMessage = scriptException.toString(); } int returnValue = -1; if (!eventThreadFlag) { synchronized (monitor) { if (insideInterruptLoop) Kit.codeBug(); this.insideInterruptLoop = true; this.evalRequest = null; this.returnValue = -1; callback.enterInterrupt(frame, threadTitle, alertMessage); try { for (;;) { try { monitor.wait(); } catch (InterruptedException exc) { Thread.currentThread().interrupt(); break; } if (evalRequest != null) { this.evalResult = null; try { evalResult = do_eval(cx, evalFrame, evalRequest); } finally { evalRequest = null; evalFrame = null; monitor.notify(); } continue; } if (this.returnValue != -1) { returnValue = this.returnValue; break; } } } finally { insideInterruptLoop = false; } } } else { this.returnValue = -1; callback.enterInterrupt(frame, threadTitle, alertMessage); while (this.returnValue == -1) { try { callback.dispatchNextGuiEvent(); } catch (InterruptedException exc) { } } returnValue = this.returnValue; } switch (returnValue) { case STEP_OVER: contextData.breakNextLine = true; contextData.stopAtFrameDepth = contextData.frameCount(); break; case STEP_INTO: contextData.breakNextLine = true; contextData.stopAtFrameDepth = -1; break; case STEP_OUT: if (contextData.frameCount() > 1) { contextData.breakNextLine = true; contextData.stopAtFrameDepth = contextData.frameCount() -1; } break; } } while (false); } finally { synchronized (eventThreadMonitor) { interruptedContextData = null; eventThreadMonitor.notifyAll(); } } } /** * Evaluates script in the given stack frame. */ private static String do_eval(Context cx, StackFrame frame, String expr) { String resultString; Debugger saved_debugger = cx.getDebugger(); Object saved_data = cx.getDebuggerContextData(); int saved_level = cx.getOptimizationLevel(); cx.setDebugger(null, null); cx.setOptimizationLevel(-1); cx.setGeneratingDebug(false); try { Callable script = (Callable)cx.compileString(expr, "", 0, null); Object result = script.call(cx, frame.scope, frame.thisObj, ScriptRuntime.emptyArgs); if (result == Undefined.instance) { resultString = ""; } else { resultString = ScriptRuntime.toString(result); } } catch (Exception exc) { resultString = exc.getMessage(); } finally { cx.setGeneratingDebug(true); cx.setOptimizationLevel(saved_level); cx.setDebugger(saved_debugger, saved_data); } if (resultString == null) { resultString = "null"; } return resultString; } /** * Proxy class to implement debug interfaces without bloat of class * files. */ private static class DimIProxy implements ContextAction, ContextFactory.Listener, Debugger { /** * The debugger. */ private Dim dim; /** * The interface implementation type. One of the IPROXY_* constants * defined in {@link Dim}. */ private int type; /** * The URL origin of the script to compile or evaluate. */ private String url; /** * The text of the script to compile, evaluate or test for compilation. */ private String text; /** * The object to convert, get a property from or enumerate. */ private Object object; /** * The property to look up in {@link #object}. */ private Object id; /** * The boolean result of the action. */ private boolean booleanResult; /** * The String result of the action. */ private String stringResult; /** * The Object result of the action. */ private Object objectResult; /** * The Object[] result of the action. */ private Object[] objectArrayResult; /** * Creates a new DimIProxy. */ private DimIProxy(Dim dim, int type) { this.dim = dim; this.type = type; } // ContextAction /** * Performs the action given by {@link #type}. */ public Object run(Context cx) { switch (type) { case IPROXY_COMPILE_SCRIPT: cx.compileString(text, url, 1, null); break; case IPROXY_EVAL_SCRIPT: { Scriptable scope = null; if (dim.scopeProvider != null) { scope = dim.scopeProvider.getScope(); } if (scope == null) { scope = new ImporterTopLevel(cx); } cx.evaluateString(scope, text, url, 1, null); } break; case IPROXY_STRING_IS_COMPILABLE: booleanResult = cx.stringIsCompilableUnit(text); break; case IPROXY_OBJECT_TO_STRING: if (object == Undefined.instance) { stringResult = "undefined"; } else if (object == null) { stringResult = "null"; } else if (object instanceof NativeCall) { stringResult = "[object Call]"; } else { stringResult = Context.toString(object); } break; case IPROXY_OBJECT_PROPERTY: objectResult = dim.getObjectPropertyImpl(cx, object, id); break; case IPROXY_OBJECT_IDS: objectArrayResult = dim.getObjectIdsImpl(cx, object); break; default: throw Kit.codeBug(); } return null; } /** * Performs the action given by {@link #type} with the attached * {@link ContextFactory}. */ private void withContext() { dim.contextFactory.call(this); } // ContextFactory.Listener /** * Called when a Context is created. */ public void contextCreated(Context cx) { if (type != IPROXY_LISTEN) Kit.codeBug(); ContextData contextData = new ContextData(); Debugger debugger = new DimIProxy(dim, IPROXY_DEBUG); cx.setDebugger(debugger, contextData); cx.setGeneratingDebug(true); cx.setOptimizationLevel(-1); } /** * Called when a Context is destroyed. */ public void contextReleased(Context cx) { if (type != IPROXY_LISTEN) Kit.codeBug(); } // Debugger /** * Returns a StackFrame for the given function or script. */ public DebugFrame getFrame(Context cx, DebuggableScript fnOrScript) { if (type != IPROXY_DEBUG) Kit.codeBug(); FunctionSource item = dim.getFunctionSource(fnOrScript); if (item == null) { // Can not debug if source is not available return null; } return new StackFrame(cx, dim, item); } /** * Called when compilation is finished. */ public void handleCompilationDone(Context cx, DebuggableScript fnOrScript, String source) { if (type != IPROXY_DEBUG) Kit.codeBug(); if (!fnOrScript.isTopLevel()) { return; } dim.registerTopScript(fnOrScript, source); } } /** * Class to store information about a stack. */ public static class ContextData { /** * The stack frames. */ private ObjArray frameStack = new ObjArray(); /** * Whether the debugger should break at the next line in this context. */ private boolean breakNextLine; /** * The frame depth the debugger should stop at. Used to implement * "step over" and "step out". */ private int stopAtFrameDepth = -1; /** * Whether this context is in the event thread. */ private boolean eventThreadFlag; /** * The last exception that was processed. */ private Throwable lastProcessedException; /** * Returns the ContextData for the given Context. */ public static ContextData get(Context cx) { return (ContextData) cx.getDebuggerContextData(); } /** * Returns the number of stack frames. */ public int frameCount() { return frameStack.size(); } /** * Returns the stack frame with the given index. */ public StackFrame getFrame(int frameNumber) { int num = frameStack.size() - frameNumber - 1; return (StackFrame) frameStack.get(num); } /** * Pushes a stack frame on to the stack. */ private void pushFrame(StackFrame frame) { frameStack.push(frame); } /** * Pops a stack frame from the stack. */ private void popFrame() { frameStack.pop(); } } /** * Object to represent one stack frame. */ public static class StackFrame implements DebugFrame { /** * The debugger. */ private Dim dim; /** * The ContextData for the Context being debugged. */ private ContextData contextData; /** * The scope. */ private Scriptable scope; /** * The 'this' object. */ private Scriptable thisObj; /**
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -