|
|
* of script is sliced into compilation units. | * of script is sliced into compilation units. |
* For instance, the script text may contain a function | * For instance, the script text may contain a function |
* declaration and an expression to eval. The compilation | * declaration and an expression to eval. The compilation |
* will result in two compilation units: the function and |
* will result in two compilation units: the function and |
* the expression. Each compilation unit will correspond | * the expression. Each compilation unit will correspond |
* to a range of the lines of the original script compiled. | * to a range of the lines of the original script compiled. |
* All line numbers are global to the document the compiled | * All line numbers are global to the document the compiled |
|
|
* It is on compilation units that breakpoints can be set | * It is on compilation units that breakpoints can be set |
* or removed, more exactly on the DebuggableScript attached | * or removed, more exactly on the DebuggableScript attached |
* to them. See Rhino for more details. | * to them. See Rhino for more details. |
* |
* |
* @author: Olivier Gruber. | * @author: Olivier Gruber. |
*/ |
*/ |
public class CompilationUnit { | public class CompilationUnit { |
| |
FnOrScript m_fnOrScript; |
FnOrScript m_fnOrScript; |
int m_firstLine; |
int m_firstLine; |
int m_lineCount; |
int m_lineCount; |
String m_fnName; |
String m_fnName; |
DebuggableScript m_dbgScript; |
DebuggableScript m_dbgScript; |
int m_validBrkptLines[]; |
boolean[] m_breakpoints; |
|
|
/** |
/** |
* CompilationUnit constructor comment. |
* CompilationUnit constructor comment. |
*/ |
*/ |
public CompilationUnit(FnOrScript fnOrScript, DebuggableScript dbgScript) { |
public CompilationUnit(FnOrScript fnOrScript, DebuggableScript dbgScript) { |
|
|
int lastLine, lineno; |
m_fnOrScript = fnOrScript; |
|
m_dbgScript = dbgScript; |
m_fnOrScript = fnOrScript; |
|
m_dbgScript = dbgScript; |
int[] lines = dbgScript.getLineNumbers(); |
|
if (lines.length != 0) { |
try { |
int lastLine; |
m_validBrkptLines = dbgScript.getLineNumbers(); |
m_firstLine = lines[0]; |
m_firstLine = 99999; |
lastLine = m_firstLine; |
lastLine = 0; |
for (int i = 1; i != lines.length; ++i) { |
for (int l = 0; l < m_validBrkptLines.length; l++) { |
int lineno = lines[i]; |
lineno = m_validBrkptLines[l]; |
if (m_firstLine > lineno) { |
if (m_firstLine > lineno) |
m_firstLine = lineno; |
m_firstLine = lineno; |
} else if (lastLine < lineno) { |
if (lastLine < lineno) |
lastLine = lineno; |
lastLine = lineno; |
} |
} |
} |
m_lineCount = lastLine - m_firstLine + 1; |
m_lineCount = lastLine - m_firstLine + 1; |
} catch (Throwable t) { |
m_breakpoints = new boolean[m_lineCount]; |
DebugLog.stderrPrintln("\nWarning: can't get valid line numbers for breakpoints.", DebugLog.BSF_LOG_L2); |
} |
m_validBrkptLines = null; |
|
} |
String name = dbgScript.getFunctionName(); |
|
if (name != null && name.length() != 0 && !name.equals("anonymous")) { |
Scriptable scriptable = dbgScript.getScriptable(); |
m_fnName = name; |
if (scriptable instanceof NativeFunction) { |
} |
NativeFunction f = (NativeFunction) scriptable; |
} |
String name = f.getFunctionName(); |
//---------------------------------------------------------- |
if (name.length() > 0 && !name.equals("anonymous")) { |
boolean contains(int lineno) { |
m_fnName = name; |
return (m_firstLine <= lineno && lineno < m_firstLine + m_lineCount); |
} |
} |
} |
/** |
} |
* Returns true if the compilation unit contains |
//---------------------------------------------------------- |
* the breakpoint. |
boolean contains(int lineno) { |
* Notice only breakpoint defined at a line number |
return (m_firstLine <= lineno && lineno < m_firstLine + m_lineCount); |
* are supported here. |
} |
*/ |
/** |
boolean contains(BreakPoint bp) { |
* Returns true if the compilation unit contains |
try { |
* the breakpoint. |
return contains(bp.getLineNo()); |
* Notice only breakpoint defined at a line number |
} catch (BSFException ex) { |
* are supported here. |
return false; |
*/ |
} |
boolean contains(BreakPoint bp) { |
} |
try { |
/** |
return contains(bp.getLineNo()); |
* Set a breakpoint at the given line if Rhino has provided us with the |
} catch (BSFException ex) { |
* valid lines information. |
return false; |
*/ |
} |
void propagate(int lineno) { |
} |
if (m_breakpoints != null) { |
/** |
int i = lineno - m_firstLine; |
* Propagates (i.e. set) this breakpoint to the underlying Rhino |
if (0 <= i && i < m_lineCount) { |
* engine if Rhino has provided us with the valid lines |
m_breakpoints[i] = true; |
* information. Otherwise, Rhino crashes with a NullPointerException. |
} |
*/ |
} |
void propagate(int lineno) { |
} |
if (m_validBrkptLines != null) { |
/** |
m_dbgScript.placeBreakpoint(lineno); |
* Clear a breakpoint at the given line if Rhino has provided us with the |
} |
* valid lines information. |
} |
*/ |
/** |
void unpropagate(int lineno) { |
* Unpropagates (i.e. unset) this breakpoint to the underlying Rhino |
if (m_breakpoints != null) { |
* engine if Rhino has provided us with the valid lines |
int i = lineno - m_firstLine; |
* information. Otherwise, Rhino crashes with a NullPointerException. |
if (0 <= i && i < m_lineCount) { |
*/ |
m_breakpoints[i] = false; |
void unpropagate(int lineno) { |
} |
if (m_validBrkptLines != null) { |
} |
m_dbgScript.removeBreakpoint(lineno); |
} |
} |
|
} |
boolean hasBreakpoint(int lineno) { |
|
if (m_breakpoints != null) { |
|
int i = lineno - m_firstLine; |
|
return 0 <= i && i < m_lineCount && m_breakpoints[i]; |
|
} |
|
return false; |
|
} |
} | } |
|
|
* This class represents a function or script, that is, | * This class represents a function or script, that is, |
* a piece of a document that is provided to the JavaScript | * a piece of a document that is provided to the JavaScript |
* engine for evaluation, execution, or simply compilation. | * engine for evaluation, execution, or simply compilation. |
* |
* |
* A FnOrScript represents a range of lines or characters | * A FnOrScript represents a range of lines or characters |
* in its document. For now, Rhino only supports ranges |
* in its document. For now, Rhino only supports ranges |
* of lines, really, but the code for offsets is there anyway. | * of lines, really, but the code for offsets is there anyway. |
* | * |
* Warning: Offsets have never been quite tested yet... | * Warning: Offsets have never been quite tested yet... |
* |
* |
* A FnOrScript has compilation units. When Rhino compiles | * A FnOrScript has compilation units. When Rhino compiles |
* a function or a script, even in interpreted mode where the | * a function or a script, even in interpreted mode where the |
* compilation is done to JavaScript bytecode, it calls back | * compilation is done to JavaScript bytecode, it calls back |
* its debugger with different compilation units; see |
* its debugger with different compilation units; see |
* Debugger::handleCompilationDone method on the RhinoEngineDebugger | * Debugger::handleCompilationDone method on the RhinoEngineDebugger |
* class. | * class. |
* | * |
* A FnOrScript also keeps track of the known breakpoints | * A FnOrScript also keeps track of the known breakpoints |
* in its range of lines or characters. It makes sure | * in its range of lines or characters. It makes sure |
* that they are propagated to the underlying Rhino |
* that they are propagated to the underlying Rhino |
* engine (i.e. set) as well as unpropagated (i.e. unset). | * engine (i.e. set) as well as unpropagated (i.e. unset). |
* |
* |
* @author: Olivier Gruber | * @author: Olivier Gruber |
*/ | */ |
public class FnOrScript { | public class FnOrScript { |
|
|
| |
protected StringBuffer m_text; | protected StringBuffer m_text; |
| |
protected Vector m_units; // of CompilationUnit. |
|
protected Script m_script; | protected Script m_script; |
| |
|
private Vector m_units; // of CompilationUnit. |
|
private Hashtable m_functionToUnit; |
|
|
protected Hashtable m_functionMap; | protected Hashtable m_functionMap; |
| |
public FnOrScript(DocumentCell cell) { | public FnOrScript(DocumentCell cell) { |
|
|
m_lineCount = 0; | m_lineCount = 0; |
m_breakpoints = new Vector(); | m_breakpoints = new Vector(); |
m_text = new StringBuffer(); | m_text = new StringBuffer(); |
|
|
m_units = new Vector(); | m_units = new Vector(); |
|
m_functionToUnit = new Hashtable(); |
m_functionMap = new Hashtable(); | m_functionMap = new Hashtable(); |
} | } |
| |
|
|
| |
m_breakpoints.addElement(bp); | m_breakpoints.addElement(bp); |
| |
// now, look for a unit containing it and |
// now, look for a unit containing it and |
// if one is found, set the breakpoint unit | // if one is found, set the breakpoint unit |
// and propagate... | // and propagate... |
Enumeration e; | Enumeration e; |
|
|
} | } |
return bp; | return bp; |
} | } |
|
|
private BreakPoint _removeBreakpoint(int brkptId) { | private BreakPoint _removeBreakpoint(int brkptId) { |
Enumeration e; | Enumeration e; |
BreakPoint bp; | BreakPoint bp; |
|
|
bp = (BreakPoint) e.nextElement(); | bp = (BreakPoint) e.nextElement(); |
if (bpid == bp.getId()) { | if (bpid == bp.getId()) { |
m_breakpoints.removeElement(bp); | m_breakpoints.removeElement(bp); |
bp.unpropagate(); |
bp.unpropagate(); |
return bp; | return bp; |
} | } |
} | } |
return null; | return null; |
} | } |
|
|
boolean contains(BreakPoint bp) throws BSFException { | boolean contains(BreakPoint bp) throws BSFException { |
if (m_lineDefined) { | if (m_lineDefined) { |
int line = bp.getLineNo(); | int line = bp.getLineNo(); |
|
|
// This protected method works as a factory | // This protected method works as a factory |
// for language-specific breakpoints. | // for language-specific breakpoints. |
// The default behavior is to use the provided | // The default behavior is to use the provided |
// generic breakpoint. |
// generic breakpoint. |
// See javascript for an example of language-specific | // See javascript for an example of language-specific |
// breakpoints. | // breakpoints. |
| |
|
|
| |
public void addCompilationUnit(Context cx, | public void addCompilationUnit(Context cx, |
DebuggableScript dbgScript, | DebuggableScript dbgScript, |
StringBuffer source) { |
String source) { |
| |
CompilationUnit unit; | CompilationUnit unit; |
| |
unit = new CompilationUnit(this, dbgScript); | unit = new CompilationUnit(this, dbgScript); |
m_units.addElement(unit); | m_units.addElement(unit); |
|
m_functionToUnit.put(dbgScript, unit); |
if (unit.m_fnName != null) { | if (unit.m_fnName != null) { |
m_functionMap.put(unit.m_fnName, unit); | m_functionMap.put(unit.m_fnName, unit); |
} | } |
| |
// Associate breakpoints to this unit if |
// Associate breakpoints to this unit if |
// the unit contains them... | // the unit contains them... |
Enumeration e; | Enumeration e; |
BreakPoint bp; | BreakPoint bp; |
|
|
propagateAll(); | propagateAll(); |
} | } |
| |
|
CompilationUnit getCompilationUnit(DebuggableScript dbgScript) { |
|
return (CompilationUnit)m_functionToUnit.get(dbgScript); |
|
} |
|
|
public void compile(Context cx, Scriptable global) | public void compile(Context cx, Scriptable global) |
throws BSFException, IOException { | throws BSFException, IOException { |
| |
Enumeration e; | Enumeration e; |
Reader reader = new StringReader(m_text.toString()); | Reader reader = new StringReader(m_text.toString()); |
m_script = | m_script = |
cx.compileReader(global, reader, m_cell.getName(), |
cx.compileReader(global, reader, m_cell.getName(), |
m_startLine, null); | m_startLine, null); |
if (m_script == null) | if (m_script == null) |
throw new BSFException("Compilation of the script " | throw new BSFException("Compilation of the script " |
|
|
public void disconnectedDebuggerNotify() { | public void disconnectedDebuggerNotify() { |
m_rhinoDbg.disconnectedDebuggerNotify(); | m_rhinoDbg.disconnectedDebuggerNotify(); |
} | } |
|
|
BSFDebugManagerImpl getDebugManager() { | BSFDebugManagerImpl getDebugManager() { |
return dbgmgr; | return dbgmgr; |
} | } |
|
|
m_rhinoDbg.placeBreakpointAtLine(brkptid, docname, lineno); | m_rhinoDbg.placeBreakpointAtLine(brkptid, docname, lineno); |
} | } |
| |
public void placeBreakpointAtOffset(int brkptid, String docname, |
public void placeBreakpointAtOffset(int brkptid, String docname, |
int offset) throws BSFException { | int offset) throws BSFException { |
m_rhinoDbg.placeBreakpointAtOffset(brkptid, docname, offset); | m_rhinoDbg.placeBreakpointAtOffset(brkptid, docname, offset); |
} | } |
|
|
public Object call(Object object, String method, Object[] args) | public Object call(Object object, String method, Object[] args) |
throws BSFException { | throws BSFException { |
Object theReturnValue = null; | Object theReturnValue = null; |
DebuggableEngine engine; |
|
Context cx; | Context cx; |
try { | try { |
| |
|
|
| |
cx.setOptimizationLevel(-1); | cx.setOptimizationLevel(-1); |
| |
engine = cx.getDebuggableEngine(); |
cx.setDebugger(m_rhinoDbg, new RhinoContextProxy(m_rhinoDbg)); |
engine.setDebugger(m_rhinoDbg); |
|
| |
theReturnValue = ScriptRuntime.call(cx, fun, global, args, |
theReturnValue = ScriptRuntime.call(cx, fun, global, args, |
null); | null); |
| |
} |
} |
else { | else { |
cx.setOptimizationLevel(-1); | cx.setOptimizationLevel(-1); |
| |
|
|
| |
cx.setOptimizationLevel(0); | cx.setOptimizationLevel(0); |
| |
engine = cx.getDebuggableEngine(); |
cx.setDebugger(null, null); |
engine.setDebugger(null); |
|
| |
theReturnValue = ScriptRuntime.call(cx, fun, global, args, |
theReturnValue = ScriptRuntime.call(cx, fun, global, args, |
null); | null); |
} | } |
if (theReturnValue instanceof Wrapper) { | if (theReturnValue instanceof Wrapper) { |
|
|
} | } |
| |
public void declareBean(BSFDeclaredBean bean) throws BSFException { | public void declareBean(BSFDeclaredBean bean) throws BSFException { |
// Must wrap non-scriptable objects before presenting to Rhino |
if ((bean.bean instanceof Number) || |
Scriptable wrapped = Context.toObject(bean.bean, global); |
(bean.bean instanceof String) || |
global.put(bean.name, global, wrapped); |
(bean.bean instanceof Boolean)) { |
|
global.put(bean.name, global, bean.bean); |
|
} else { |
|
// Must wrap non-scriptable objects before presenting to Rhino |
|
Scriptable wrapped = Context.toObject(bean.bean, global); |
|
global.put(bean.name, global, wrapped); |
|
} |
} | } |
| |
/** | /** |
|
|
DocumentCell cell; | DocumentCell cell; |
FnOrScript fnOrScript; | FnOrScript fnOrScript; |
Script script; | Script script; |
DebuggableEngine engine; |
|
Context cx; | Context cx; |
| |
try { | try { |
|
|
| |
cx.setOptimizationLevel(-1); | cx.setOptimizationLevel(-1); |
| |
engine = cx.getDebuggableEngine(); |
cx.setDebugger(m_rhinoDbg, new RhinoContextProxy(m_rhinoDbg)); |
engine.setDebugger(m_rhinoDbg); |
|
|
|
// Muck w/ this iff someone else hasn't already got it true |
|
if (!engine.getBreakNextLine()) { |
|
engine.setBreakNextLine(cell.getEntryExit()); |
|
} |
|
| |
fnOrScript.compile(cx, global); | fnOrScript.compile(cx, global); |
m_rhinoDbg.setCompilingFnOrScript(null); | m_rhinoDbg.setCompilingFnOrScript(null); |
|
|
| |
if (script != null) retval = script.exec(cx, global); | if (script != null) retval = script.exec(cx, global); |
else retval = null; | else retval = null; |
} |
} |
else { | else { |
cx.setOptimizationLevel(-1); | cx.setOptimizationLevel(-1); |
| |
|
|
| |
cx.setOptimizationLevel(0); | cx.setOptimizationLevel(0); |
| |
engine = cx.getDebuggableEngine(); |
cx.setDebugger(null, null); |
engine.setDebugger(null); |
|
| |
retval = cx.evaluateString(global, scriptText, | retval = cx.evaluateString(global, scriptText, |
source, lineNo, |
source, lineNo, |
null); | null); |
} | } |
| |
|
|
// Display its stack trace as a diagnostic | // Display its stack trace as a diagnostic |
target = (Throwable) value; | target = (Throwable) value; |
} | } |
} |
} |
else if (t instanceof EvaluatorException || |
else if (t instanceof EvaluatorException || |
t instanceof SecurityException) { | t instanceof SecurityException) { |
message = t.getLocalizedMessage(); | message = t.getLocalizedMessage(); |
} |
} |
else if (t instanceof RuntimeException) { | else if (t instanceof RuntimeException) { |
message = "Internal Error: " + t.toString(); | message = "Internal Error: " + t.toString(); |
} |
} |
else if (t instanceof StackOverflowError) { | else if (t instanceof StackOverflowError) { |
message = "Stack Overflow"; | message = "Stack Overflow"; |
} | } |
|
|
} | } |
| |
//REMIND: can we recover the line number here? I think | //REMIND: can we recover the line number here? I think |
// Rhino does this by looking up the stack for bytecode |
// Rhino does this by looking up the stack for bytecode |
// see Context.getSourcePositionFromStack() | // see Context.getSourcePositionFromStack() |
// but I don't think this would work in interpreted mode | // but I don't think this would work in interpreted mode |
| |
|
|
// corrected the situation by aborting the loop and | // corrected the situation by aborting the loop and |
// a long stacktrace would end up on the user's console | // a long stacktrace would end up on the user's console |
throw (Error) t; | throw (Error) t; |
} |
} |
else { | else { |
throw new BSFException(BSFException.REASON_OTHER_ERROR, | throw new BSFException(BSFException.REASON_OTHER_ERROR, |
"JavaScript Error: " + message, | "JavaScript Error: " + message, |
|
|
| |
/** | /** |
* initialize the engine. put the manager into the context -> manager | * initialize the engine. put the manager into the context -> manager |
* map hashtable too. |
* map hashtable too. |
*/ | */ |
public void initialize(BSFManager mgr, String lang, Vector declaredBeans) | public void initialize(BSFManager mgr, String lang, Vector declaredBeans) |
throws BSFException { | throws BSFException { |
|
|
* @author: Administrator | * @author: Administrator |
*/ | */ |
| |
public class JsContextStub |
public class JsContextStub |
extends org.apache.bsf.debug.util.Skeleton | extends org.apache.bsf.debug.util.Skeleton |
implements JsContext { | implements JsContext { |
| |
RhinoContextProxy m_rcp; |
RhinoContextProxy m_rcp; |
RhinoEngineDebugger m_rhinoDbg; |
RhinoEngineDebugger m_rhinoDbg; |
DebugFrame m_frame; |
int m_frameno; |
int m_frameno; |
int m_lineno; |
boolean m_atBreakpoint; |
boolean m_atBreakpoint; |
boolean m_invalid; |
boolean m_invalid; |
|
|
/** |
CompilationUnit m_unit; |
* JsContextStub constructor comment. |
Scriptable m_variableObject; |
*/ |
Scriptable m_thisObj; |
public JsContextStub(RhinoContextProxy rcp, DebugFrame frame, int frameno) |
|
throws RemoteException { |
/** |
super(org.apache.bsf.debug.util.DebugConstants.JS_CONTEXT_TID); |
* JsContextStub constructor comment. |
|
*/ |
m_rhinoDbg = rcp.getRhinoEngineDebugger(); |
JsContextStub(RhinoContextProxy rcp, CompilationUnit unit) |
m_rcp = rcp; |
throws RemoteException { |
m_frame = frame; |
super(org.apache.bsf.debug.util.DebugConstants.JS_CONTEXT_TID); |
m_frameno = frameno; |
|
m_invalid = false; |
m_rhinoDbg = rcp.getRhinoEngineDebugger(); |
m_atBreakpoint = true; |
m_rcp = rcp; |
} |
m_unit = unit; |
//-------------------------------------------------- |
m_invalid = false; |
void atBreakpoint(boolean atbrkpt) { |
m_atBreakpoint = true; |
m_atBreakpoint = atbrkpt; |
} |
} |
|
public JsObject bind(String id) throws RemoteException { |
DebugFrame getRhinoDebugFrame() { |
try { |
return new RhinoDebugFrame(this); |
Context.enter(); |
} |
Scriptable obj = m_frame.getVariableObject(); |
|
Object prop; |
//-------------------------------------------------- |
while (obj != null) { |
void atBreakpoint(boolean atbrkpt) { |
Scriptable m = obj; |
m_atBreakpoint = atbrkpt; |
do { |
} |
if (m.has(id, obj)) |
public JsObject bind(String id) throws RemoteException { |
return m_rhinoDbg.marshallScriptable(obj); |
try { |
m = m.getPrototype(); |
Context.enter(); |
} while (m != null); |
Scriptable obj = m_variableObject; |
obj = obj.getParentScope(); |
Object prop; |
} |
while (obj != null) { |
throw new JsdiException("Name not in scope."); |
Scriptable m = obj; |
} finally { |
do { |
Context.exit(); |
if (m.has(id, obj)) |
} |
return m_rhinoDbg.marshallScriptable(obj); |
} |
m = m.getPrototype(); |
//-------------------------------------------------- |
} while (m != null); |
public JsCode getCode() { |
obj = obj.getParentScope(); |
if (m_invalid) |
} |
throw new JsdiException("This context no longer exists."); |
throw new JsdiException("Name not in scope."); |
if (!m_atBreakpoint) |
} finally { |
throw new JsdiException("Resumed context, can't get the code."); |
Context.exit(); |
|
} |
try { |
} |
Context.enter(); |
//-------------------------------------------------- |
return null; |
public JsCode getCode() { |
} finally { |
if (m_invalid) |
Context.exit(); |
throw new JsdiException("This context no longer exists."); |
} |
if (!m_atBreakpoint) |
} |
throw new JsdiException("Resumed context, can't get the code."); |
public int getDepth() { |
|
return m_frameno; |
try { |
} |
Context.enter(); |
//-------------------------------------------------- |
return null; |
public JsEngine getEngine() { |
} finally { |
RhinoEngineDebugger redbg; |
Context.exit(); |
redbg = m_rcp.getRhinoEngineDebugger(); |
} |
return (JsEngine) redbg.getDebugInterface(); |
} |
|
public int getDepth() { |
} |
return m_frameno; |
//-------------------------------------------------- |
} |
public int getLineNumber() { |
//-------------------------------------------------- |
if (m_invalid) |
public JsEngine getEngine() { |
throw new JsdiException("This context no longer exists."); |
RhinoEngineDebugger redbg; |
if (!m_atBreakpoint) |
redbg = m_rcp.getRhinoEngineDebugger(); |
throw new JsdiException("Resumed context, can't get line number."); |
return (JsEngine) redbg.getDebugInterface(); |
|
|
try { |
} |
Context.enter(); |
//-------------------------------------------------- |
return m_frame.getLineNumber(); |
public int getLineNumber() { |
} finally { |
if (m_invalid) |
Context.exit(); |
throw new JsdiException("This context no longer exists."); |
} |
if (!m_atBreakpoint) |
} |
throw new JsdiException("Resumed context, can't get line number."); |
//------------------------------------------------------ |
|
public JsObject getScope() throws RemoteException { |
return m_lineno; |
|
} |
if (m_invalid) |
//------------------------------------------------------ |
throw new JsdiException("This context no longer exists."); |
public JsObject getScope() throws RemoteException { |
if (!m_atBreakpoint) |
|
throw new JsdiException("Resumed context, can't get line number."); |
if (m_invalid) |
|
throw new JsdiException("This context no longer exists."); |
try { |
if (!m_atBreakpoint) |
Context.enter(); |
throw new JsdiException("Resumed context, can't get line number."); |
Scriptable varobj = m_frame.getVariableObject(); |
|
JsObject scope = m_rhinoDbg.marshallScriptable(varobj); |
try { |
return scope; |
Context.enter(); |
} finally { |
JsObject scope = m_rhinoDbg.marshallScriptable(m_variableObject); |
Context.exit(); |
return scope; |
} |
} finally { |
} |
Context.exit(); |
//------------------------------------------------------ |
} |
public String getSourceName() { |
} |
if (m_invalid) |
//------------------------------------------------------ |
throw new JsdiException("This context no longer exists."); |
public String getSourceName() { |
if (!m_atBreakpoint) |
if (m_invalid) |
throw new JsdiException("Resumed context, can't get line number."); |
throw new JsdiException("This context no longer exists."); |
|
if (!m_atBreakpoint) |
try { |
throw new JsdiException("Resumed context, can't get line number."); |
Context.enter(); |
|
return m_frame.getSourceName(); |
return m_unit.m_dbgScript.getSourceName(); |
} finally { |
} |
Context.exit(); |
//------------------------------------------------------ |
} |
public JsObject getThis() throws RemoteException { |
} |
|
//------------------------------------------------------ |
if (m_invalid) |
public JsObject getThis() throws RemoteException { |
throw new JsdiException("This context no longer exists."); |
|
if (!m_atBreakpoint) |
if (m_invalid) |
throw new JsdiException("Resumed context, can't get line number."); |
throw new JsdiException("This context no longer exists."); |
|
if (!m_atBreakpoint) |
try { |
throw new JsdiException("Resumed context, can't get line number."); |
Context.enter(); |
|
JsObject thisobj = null; |
try { |
Scriptable obj = null; |
Context.enter(); |
NativeCall call = null; |
JsObject thisobj = null; |
Scriptable varobj = m_variableObject; |
Scriptable obj = null; |
if (varobj instanceof NativeCall) { |
NativeCall call = null; |
call = (NativeCall) varobj; |
Scriptable varobj = m_frame.getVariableObject(); |
obj = call.getThisObj(); |
if (varobj instanceof NativeCall) { |
thisobj = m_rhinoDbg.marshallScriptable(varobj); |
call = (NativeCall) varobj; |
} |
obj = call.getThisObj(); |
return thisobj; |
thisobj = m_rhinoDbg.marshallScriptable(varobj); |
} finally { |
} |
Context.exit(); |
return thisobj; |
} |
} finally { |
} |
Context.exit(); |
//-------------------------------------------------- |
} |
void invalidate() { |
} |
m_invalid = true; |
//-------------------------------------------------- |
} |
void invalidate() { |
//------------------------------------------------------ |
m_invalid = true; |
public boolean isEvalContext() { |
} |
if (m_invalid) |
//------------------------------------------------------ |
throw new JsdiException("This context no longer exists."); |
public boolean isEvalContext() { |
if (!m_atBreakpoint) |
if (m_invalid) |
throw new JsdiException("Resumed context, can't get line number."); |
throw new JsdiException("This context no longer exists."); |
|
if (!m_atBreakpoint) |
try { |
throw new JsdiException("Resumed context, can't get line number."); |
Context.enter(); |
|
return false; |
try { |
} finally { |
Context.enter(); |
Context.exit(); |
return false; |
} |
} finally { |
} |
Context.exit(); |
//------------------------------------------------------ |
} |
public boolean isFunctionContext() { |
} |
if (m_invalid) |
//------------------------------------------------------ |
throw new JsdiException("This context no longer exists."); |
public boolean isFunctionContext() { |
if (!m_atBreakpoint) |
if (m_invalid) |
throw new JsdiException("Resumed context, can't get line number."); |
throw new JsdiException("This context no longer exists."); |
|
if (!m_atBreakpoint) |
try { |
throw new JsdiException("Resumed context, can't get line number."); |
Context.enter(); |
|
return false; |
try { |
} finally { |
Context.enter(); |
Context.exit(); |
return false; |
} |
} finally { |
} |
Context.exit(); |
//------------------------------------------------------ |
} |
public boolean isScriptContext() { |
} |
if (m_invalid) |
//------------------------------------------------------ |
throw new JsdiException("This context no longer exists."); |
public boolean isScriptContext() { |
if (!m_atBreakpoint) |
if (m_invalid) |
throw new JsdiException("Resumed context, can't get line number."); |
throw new JsdiException("This context no longer exists."); |
try { |
if (!m_atBreakpoint) |
Context.enter(); |
throw new JsdiException("Resumed context, can't get line number."); |
return true; |
try { |
} finally { |
Context.enter(); |
Context.exit(); |
return true; |
} |
} finally { |
} |
Context.exit(); |
public Object lookupName(String name) { |
} |
|
} |
try { |
public Object lookupName(String name) { |
Context.enter(); |
|
Scriptable obj = m_variableObject; |
try { |
Object prop; |
Context.enter(); |
while (obj != null) { |
Scriptable obj = m_frame.getVariableObject(); |
Scriptable m = obj; |
Object prop; |
do { |
while (obj != null) { |
Object result = m.get(name, obj); |
Scriptable m = obj; |
if (result != Scriptable.NOT_FOUND) |
do { |
return result; |
Object result = m.get(name, obj); |
m = m.getPrototype(); |
if (result != Scriptable.NOT_FOUND) |
} while (m != null); |
return result; |
obj = obj.getParentScope(); |
m = m.getPrototype(); |
} |
} while (m != null); |
throw new JsdiException("Name is not in scope."); |
obj = obj.getParentScope(); |
} finally { |
} |
Context.exit(); |
throw new JsdiException("Name is not in scope."); |
} |
} finally { |
} |
Context.exit(); |
/** |
} |
* Looks up a name in the scope chain and returns its value. |
} |
*/ |
/** |
public Object lookupName(Scriptable scopeChain, String id) { |
* Looks up a name in the scope chain and returns its value. |
|
*/ |
try { |
public Object lookupName(Scriptable scopeChain, String id) { |
Context.enter(); |
|
Scriptable obj = scopeChain; |
try { |
Object prop; |
Context.enter(); |
while (obj != null) { |
Scriptable obj = scopeChain; |
Scriptable m = obj; |
Object prop; |
do { |
while (obj != null) { |
Object result = m.get(id, obj); |
Scriptable m = obj; |
if (result != Scriptable.NOT_FOUND) |
do { |
return result; |
Object result = m.get(id, obj); |
m = m.getPrototype(); |
if (result != Scriptable.NOT_FOUND) |
} while (m != null); |
return result; |
obj = obj.getParentScope(); |
m = m.getPrototype(); |
} |
} while (m != null); |
return null; |
obj = obj.getParentScope(); |
} finally { |
} |
Context.exit(); |
return null; |
} |
} finally { |
} |
Context.exit(); |
} |
} |
|
} |
class RhinoDebugFrame implements DebugFrame { |
|
|
|
JsContextStub m_stub; |
|
|
|
RhinoDebugFrame(JsContextStub stub) { |
|
m_stub = stub; |
|
} |
|
|
|
public void onEnter(Context cx, Scriptable activation, |
|
Scriptable thisObj, Object[] args) |
|
{ |
|
m_stub.m_variableObject = activation; |
|
m_stub.m_thisObj = thisObj; |
|
m_stub.m_frameno = m_stub.m_rcp.m_frameStack.size(); |
|
m_stub.m_rcp.m_frameStack.push(m_stub); |
|
} |
|
|
|
public void onExit(Context cx, boolean byThrow, Object resultOrException) |
|
{ |
|
m_stub.m_rcp.m_frameStack.pop(); |
|
m_stub.invalidate(); |
|
} |
|
|
|
public void onExceptionThrown(Context cx, Throwable ex) { |
|
m_stub.m_rcp.m_reDbg.handleExceptionThrown(cx, m_stub.m_rcp, ex); |
|
} |
|
|
|
public void onLineChange(Context cx, int lineNumber) { |
|
m_stub.m_lineno = lineNumber; |
|
if (m_stub.m_unit.hasBreakpoint(lineNumber)) { |
|
m_stub.m_rcp.m_reDbg.handleBreakpointHit(cx, m_stub.m_rcp); |
|
} |
|
} |
} | } |
|
|
import org.apache.bsf.debug.jsdi.*; | import org.apache.bsf.debug.jsdi.*; |
import org.mozilla.javascript.Context; | import org.mozilla.javascript.Context; |
import org.mozilla.javascript.Script; | import org.mozilla.javascript.Script; |
import org.mozilla.javascript.debug.DebuggableEngine; |
|
| |
/** | /** |
* Insert the type's description here. | * Insert the type's description here. |
* Creation date: (9/6/2001 1:21:46 PM) | * Creation date: (9/6/2001 1:21:46 PM) |
* @author: Administrator | * @author: Administrator |
*/ | */ |
public class JsEngineStub |
public class JsEngineStub |
extends org.apache.bsf.debug.util.Skeleton | extends org.apache.bsf.debug.util.Skeleton |
implements JsEngine { | implements JsEngine { |
| |
RhinoEngineDebugger m_rhinoDbg; | RhinoEngineDebugger m_rhinoDbg; |
boolean m_inCallback; | boolean m_inCallback; |
boolean m_resumeExecution; | boolean m_resumeExecution; |
Object m_lock; |
Object m_lock; |
|
|
/** | /** |
* JsEngineStub constructor comment. | * JsEngineStub constructor comment. |
*/ | */ |
public JsEngineStub(RhinoEngineDebugger rhinoDbg) |
public JsEngineStub(RhinoEngineDebugger rhinoDbg) |
throws RemoteException { | throws RemoteException { |
super(org.apache.bsf.debug.util.DebugConstants.JS_ENGINE_TID); | super(org.apache.bsf.debug.util.DebugConstants.JS_ENGINE_TID); |
m_rhinoDbg = rhinoDbg; | m_rhinoDbg = rhinoDbg; |
m_lock = new Object(); | m_lock = new Object(); |
} | } |
|
|
public boolean isSuspended() throws RemoteException { | public boolean isSuspended() throws RemoteException { |
return m_inCallback; | return m_inCallback; |
} | } |
|
|
public boolean poll() { return true; } | public boolean poll() { return true; } |
|
|
public Object eval(String docname, String exp, int lineNo) | public Object eval(String docname, String exp, int lineNo) |
throws RemoteException { | throws RemoteException { |
| |
|
|
try { | try { |
Context.enter(); | Context.enter(); |
count = m_rhinoDbg.getContextCount(); | count = m_rhinoDbg.getContextCount(); |
DebugLog.stdoutPrintln(" count = "+count, |
DebugLog.stdoutPrintln(" count = "+count, |
DebugLog.BSF_LOG_L3); | DebugLog.BSF_LOG_L3); |
return count; | return count; |
} finally { | } finally { |
|
|
} | } |
| |
} | } |
|
|
public String getThread() throws RemoteException { | public String getThread() throws RemoteException { |
return m_rhinoDbg.getThread(); | return m_rhinoDbg.getThread(); |
} | } |
|
|
public void stepIn() throws RemoteException { | public void stepIn() throws RemoteException { |
try { | try { |
Context.enter(); | Context.enter(); |
DebugLog.stdoutPrintln("Step In command on "+this, |
DebugLog.stdoutPrintln("Step In command on "+this, |
DebugLog.BSF_LOG_L3); | DebugLog.BSF_LOG_L3); |
m_rhinoDbg.stepIn(this); | m_rhinoDbg.stepIn(this); |
} catch (Exception ex) { | } catch (Exception ex) { |
|
|
} | } |
| |
public void stepOver() throws RemoteException { | public void stepOver() throws RemoteException { |
RhinoContextProxy rcp; |
|
try { | try { |
Context.enter(); | Context.enter(); |
m_rhinoDbg.stepOver(this); | m_rhinoDbg.stepOver(this); |
|
|
| |
import java.rmi.RemoteException; | import java.rmi.RemoteException; |
| |
public class RhinoContextProxy { |
class RhinoContextProxy { |
| |
RhinoEngineDebugger m_reDbg; | RhinoEngineDebugger m_reDbg; |
Context m_context; |
|
JsContextStub m_contextStub; |
|
| |
DebuggableEngine m_engine; |
ObjArray m_frameStack = new ObjArray(); |
|
|
boolean m_atBreakpoint; |
|
int m_frameCount; |
|
JsContextStub m_frames[]; |
|
| |
private static final int NO_STEP = 0, STEP_IN = 1, STEP_OVER = 2, | private static final int NO_STEP = 0, STEP_IN = 1, STEP_OVER = 2, |
STEP_OUT = 3, STOP_ENGINE = 4, RUNNING = 5; | STEP_OUT = 3, STOP_ENGINE = 4, RUNNING = 5; |
| |
private int m_stepCmd, m_stepDepth; | private int m_stepCmd, m_stepDepth; |
| |
RhinoContextProxy(RhinoEngineDebugger reDbg, Context cx) { |
RhinoContextProxy(RhinoEngineDebugger reDbg) { |
m_reDbg = reDbg; | m_reDbg = reDbg; |
m_context = cx; |
|
m_engine = cx.getDebuggableEngine(); |
|
} | } |
| |
public void cancelStepping() { |
static RhinoContextProxy getCurrent() { |
|
Context cx = Context.getCurrentContext(); |
|
if (cx == null) { return null; } |
|
return (RhinoContextProxy)cx.getDebuggerContextData(); |
|
} |
|
|
|
void cancelStepping() { |
m_stepCmd = NO_STEP; | m_stepCmd = NO_STEP; |
m_stepDepth = -1; | m_stepDepth = -1; |
m_engine.setBreakNextLine(false); |
|
} | } |
| |
public JsContextStub getContext(int depth) { |
int getContextCount() { |
return m_frames[depth]; |
return m_frameStack.size(); |
} | } |
| |
public int getContextCount() { |
JsContextStub getContextStub(int no) { |
return m_frameCount; |
if (!(0 <= no && no < m_frameStack.size())) { return null; } |
|
return (JsContextStub)m_frameStack.get(no); |
} | } |
| |
public JsContextStub getFrame(int no) { |
JsContextStub getTopContextStub() { |
if (no < 0 || no > m_frameCount) |
return getContextStub(m_frameStack.size() - 1); |
return null; |
|
if (no == m_frameCount) |
|
return m_contextStub; |
|
else |
|
return m_frames[no]; |
|
} | } |
| |
public int getLineNumber() { |
int getLineNumber() { |
DebugFrame frame = m_engine.getFrame(0); |
JsContextStub stub = getTopContextStub(); |
|
return stub.m_lineno; |
return frame.getLineNumber(); |
|
} | } |
| |
public RhinoEngineDebugger getRhinoEngineDebugger() { |
RhinoEngineDebugger getRhinoEngineDebugger() { |
return m_reDbg; | return m_reDbg; |
} | } |
| |
String getSourceName() { | String getSourceName() { |
DebugFrame frame = m_engine.getFrame(0); |
JsContextStub stub = getTopContextStub(); |
|
return stub.m_unit.m_dbgScript.getSourceName(); |
return frame.getSourceName(); |
|
} | } |
| |
|
|
// We hit a known breakpoint. | // We hit a known breakpoint. |
// We need to update the stack. | // We need to update the stack. |
// Also, cancel any pending stepping operation. | // Also, cancel any pending stepping operation. |
public JsContextStub hitBreakpoint() throws RemoteException { |
JsContextStub hitBreakpoint() throws RemoteException { |
cancelStepping(); | cancelStepping(); |
updateStack(); |
return getTopContextStub(); |
return m_frames[0]; |
|
} | } |
| |
|
JsContextStub exceptionThrown() throws RemoteException { |
public JsContextStub exceptionThrown() throws RemoteException { |
|
cancelStepping(); | cancelStepping(); |
updateStack(); |
return getTopContextStub(); |
return m_frames[0]; |
|
} | } |
| |
public void resumed() { |
void resumed() { |
JsContextStub stub; |
for (int f = 0, N = getContextCount(); f != N; ++f) { |
DebugFrame frame; |
getContextStub(f).atBreakpoint(false); |
|
|
m_atBreakpoint = false; |
|
|
|
for (int f = 0; f < m_frameCount; f++) { |
|
stub = m_frames[f]; |
|
stub.atBreakpoint(false); |
|
} | } |
} | } |
| |
public void run() { |
void run() { |
m_engine.setBreakNextLine(false); |
|
m_stepCmd = RUNNING; | m_stepCmd = RUNNING; |
m_stepDepth = -1; | m_stepDepth = -1; |
|
|
} | } |
| |
public void stepIn() { |
void stepIn() { |
m_engine.setBreakNextLine(true); |
|
m_stepCmd = STEP_IN; | m_stepCmd = STEP_IN; |
m_stepDepth = m_frameCount; |
m_stepDepth = getContextCount(); |
} | } |
| |
public void stepOut() { |
void stepOut() { |
m_engine.setBreakNextLine(true); |
|
m_stepCmd = STEP_OUT; | m_stepCmd = STEP_OUT; |
m_stepDepth = m_frameCount; |
m_stepDepth = getContextCount(); |
|
|
} | } |
| |
public void stepOver() { |
void stepOver() { |
m_engine.setBreakNextLine(true); |
|
m_stepCmd = STEP_OVER; | m_stepCmd = STEP_OVER; |
m_stepDepth = m_frameCount; |
m_stepDepth = getContextCount(); |
} | } |
| |
public JsContextStub entry_exit_mode() throws RemoteException { |
JsContextStub entry_exit_mode() throws RemoteException { |
cancelStepping(); | cancelStepping(); |
updateStack(); |
return getTopContextStub(); |
return m_frames[0]; |
|
} | } |
| |
public JsContextStub stepping() { |
JsContextStub stepping() { |
// Did we hit a known breakpoint? | // Did we hit a known breakpoint? |
| |
int frameCount = m_engine.getFrameCount(); |
int frameCount = getContextCount(); |
| |
try { | try { |
switch (m_stepCmd) { | switch (m_stepCmd) { |
|
|
cancelStepping(); | cancelStepping(); |
break; | break; |
case STOP_ENGINE : | case STOP_ENGINE : |
updateStack(); |
|
cancelStepping(); | cancelStepping(); |
return m_frames[0]; |
return getTopContextStub(); |
case STEP_IN : | case STEP_IN : |
// OG if ((frameCount == m_stepDepth + 1) || |
// OG if ((frameCount == m_stepDepth + 1) || |
// (frameCount == m_stepDepth)) { | // (frameCount == m_stepDepth)) { |
// step if we are in the same frame (nothing to step in... :-) | // step if we are in the same frame (nothing to step in... :-) |
// if we are in a called frame... | // if we are in a called frame... |
// but also if we stepped out of the current frame... | // but also if we stepped out of the current frame... |
if ((frameCount >= m_stepDepth) |
|
|| (frameCount < m_stepDepth)) { |
|
updateStack(); |
|
cancelStepping(); | cancelStepping(); |
return m_frames[0]; |
return getTopContextStub(); |
} |
|
break; |
|
case STEP_OVER : | case STEP_OVER : |
// OG if (frameCount == m_stepDepth) { | // OG if (frameCount == m_stepDepth) { |
// step if we are in the same frame or above... | // step if we are in the same frame or above... |
// this basically avoids any children frame but |
// this basically avoids any children frame but |
// covers the return of the current frame. | // covers the return of the current frame. |
if (frameCount <= m_stepDepth) { | if (frameCount <= m_stepDepth) { |
updateStack(); |
|
cancelStepping(); | cancelStepping(); |
return m_frames[0]; |
return getTopContextStub(); |
} | } |
break; | break; |
case STEP_OUT : | case STEP_OUT : |
// OG if (frameCount == m_stepDepth - 1) { | // OG if (frameCount == m_stepDepth - 1) { |
if (frameCount < m_stepDepth) { | if (frameCount < m_stepDepth) { |
updateStack(); |
|
cancelStepping(); | cancelStepping(); |
return m_frames[0]; |
return getTopContextStub(); |
} | } |
break; | break; |
default : | default : |
|
|
return null; | return null; |
} | } |
| |
public void stopEngine() { |
void stopEngine() { |
m_engine.setBreakNextLine(true); |
|
m_stepCmd = STOP_ENGINE; | m_stepCmd = STOP_ENGINE; |
m_stepDepth = -1; | m_stepDepth = -1; |
} |
|
|
|
public void updateStack() throws RemoteException { |
|
JsContextStub frames[]; |
|
JsContextStub stub; |
|
DebugFrame frame; |
|
int nf, of, frameCount; |
|
|
|
m_atBreakpoint = true; |
|
|
|
frameCount = m_engine.getFrameCount(); |
|
frames = new JsContextStub[frameCount]; |
|
|
|
// scan the stacks from the outer frame down |
|
// to the inner one of the shortest of the old |
|
// and the new known stack. |
|
// The goal is to recognize the DebugFrame objects |
|
// that are the sames so that we can reuse the |
|
// stubs for those. |
|
// As soon as a DebugFrame object is found different, |
|
// the rest of the stack is different, all the old |
|
// stubs can be dropped and invalidated, new ones |
|
// must be created. |
|
|
|
for (nf = frameCount - 1, of = m_frameCount - 1; |
|
nf >= 0 && of >= 0; |
|
nf--, of--) { |
|
frame = m_engine.getFrame(nf); |
|
if (frame == m_frames[of].m_frame) { |
|
frames[nf] = m_frames[of]; |
|
} else |
|
break; |
|
} |
|
// now drop all old frames that diverged. |
|
// Also invalidate the frame stubs so to |
|
// tracked that they are no longer valid. |
|
for (; of >= 0; of--) { |
|
m_reDbg.dropStub(m_frames[of].m_frame); |
|
m_frames[of].invalidate(); |
|
} |
|
for (; nf >= 0; nf--) { |
|
frame = m_engine.getFrame(nf); |
|
frames[nf] = new JsContextStub(this, frame, nf); |
|
} |
|
m_frames = frames; |
|
m_frameCount = frameCount; |
|
} | } |
} | } |
|
|
import org.apache.bsf.debug.*; | import org.apache.bsf.debug.*; |
import org.apache.bsf.debug.jsdi.*; | import org.apache.bsf.debug.jsdi.*; |
| |
public class RhinoEngineDebugger implements Debugger { |
class RhinoEngineDebugger implements Debugger { |
| |
/** The global script object, where all embedded functions are defined, | /** The global script object, where all embedded functions are defined, |
* as well as the standard ECMA "core" objects. | * as well as the standard ECMA "core" objects. |
*/ |
*/ |
private Scriptable global; | private Scriptable global; |
private JsObject globalstub; | private JsObject globalstub; |
| |
private RhinoContextProxy m_rcp; |
|
private Scriptable undefined; | private Scriptable undefined; |
private JsObject undefinedStub; | private JsObject undefinedStub; |
| |
/** |
/** |
* Hashtable allowing to find the stub for an object in the JavaScript | * Hashtable allowing to find the stub for an object in the JavaScript |
* environment if one exists. | * environment if one exists. |
* Typically: Scriptable, Function, Script, etc. | * Typically: Scriptable, Function, Script, etc. |
* This is not used for Context and DebugFrame. | * This is not used for Context and DebugFrame. |
* They typically contains JsObject associated to |
* They typically contains JsObject associated to |
* org.mozilla.javascript.ScriptableObject | * org.mozilla.javascript.ScriptableObject |
*/ | */ |
private Hashtable stubs; | private Hashtable stubs; |
|
|
private FnOrScript m_compilingFnOrScript; | private FnOrScript m_compilingFnOrScript; |
private JavaScriptEngine m_eng; | private JavaScriptEngine m_eng; |
| |
private Thread m_thread; |
|
|
|
private Hashtable m_documents; | private Hashtable m_documents; |
| |
BSFDebugManagerImpl dbgmgr; | BSFDebugManagerImpl dbgmgr; |
| |
public RhinoEngineDebugger(JavaScriptEngine eng) |
RhinoEngineDebugger(JavaScriptEngine eng) |
throws RemoteException { | throws RemoteException { |
super(); | super(); |
m_thread = Thread.currentThread(); |
|
m_eng = eng; | m_eng = eng; |
dbgmgr = eng.getDebugManager(); | dbgmgr = eng.getDebugManager(); |
| |
|
|
/** | /** |
* Called when our debugger has been disconnected. | * Called when our debugger has been disconnected. |
*/ | */ |
public void disconnectedDebuggerNotify() { |
void disconnectedDebuggerNotify() { |
m_callbacks = null; | m_callbacks = null; |
} | } |
| |
void addStub(Context cx, RhinoContextProxy jscx) { |
|
stubs.put(cx, jscx); |
|
} |
|
|
|
void addStub(DebugFrame frame, JsContextStub stub) { |
|
stubs.put(frame, stub); |
|
} |
|
|
|
void addStub(Scriptable sobj, JsObject jsobj) { | void addStub(Scriptable sobj, JsObject jsobj) { |
stubs.put(sobj, jsobj); | stubs.put(sobj, jsobj); |
} | } |
| |
void dropStub(Object key) { |
void dropStub(Scriptable key) { |
stubs.remove(key); | stubs.remove(key); |
} | } |
| |
public synchronized DocumentCell getDocumentCell(String name) { |
synchronized DocumentCell getDocumentCell(String name) { |
return (DocumentCell) m_documents.get(name); | return (DocumentCell) m_documents.get(name); |
} | } |
| |
// Called upon creation of a BSFManager. | // Called upon creation of a BSFManager. |
public synchronized DocumentCell loadDocumentNotify(String name) { |
synchronized DocumentCell loadDocumentNotify(String name) { |
DocumentCell cell; | DocumentCell cell; |
| |
cell = (DocumentCell) m_documents.get(name); | cell = (DocumentCell) m_documents.get(name); |
if (cell == null) { | if (cell == null) { |
cell = new DocumentCell(this, name); | cell = new DocumentCell(this, name); |
m_documents.put(name, cell); | m_documents.put(name, cell); |
if (dbgmgr!=null) |
if (dbgmgr!=null) |
dbgmgr.loadDocumentNotify(m_eng, name); | dbgmgr.loadDocumentNotify(m_eng, name); |
} | } |
return cell; | return cell; |
} | } |
| |
public synchronized void placeBreakpointAtLine(int brkptid, |
synchronized void placeBreakpointAtLine(int brkptid, |
String docname, | String docname, |
int lineno) { | int lineno) { |
| |
|
|
cell.addBreakpointAtLine(brkptid, lineno); | cell.addBreakpointAtLine(brkptid, lineno); |
} | } |
| |
public synchronized void placeBreakpointAtOffset(int brkptid, |
synchronized void placeBreakpointAtOffset(int brkptid, |
String docname, | String docname, |
int offset) { | int offset) { |
| |
|
|
cell.addBreakpointAtOffset(brkptid, offset); | cell.addBreakpointAtOffset(brkptid, offset); |
} | } |
| |
public void removeBreakpoint(String docname, int brkptid) |
void removeBreakpoint(String docname, int brkptid) |
throws BSFException { | throws BSFException { |
| |
DocumentCell cell; | DocumentCell cell; |
|
|
cell.removeBreakpoint(brkptid); | cell.removeBreakpoint(brkptid); |
} | } |
| |
public void setEntryExit(String docname, boolean on) |
void setEntryExit(String docname, boolean on) |
throws BSFException { | throws BSFException { |
| |
DocumentCell cell; | DocumentCell cell; |
|
|
cell.setEntryExit(on); | cell.setEntryExit(on); |
} | } |
| |
public Object eval(String docname, String fnOrScript, int lineno) |
Object eval(String docname, String fnOrScript, int lineno) |
throws RemoteException { | throws RemoteException { |
Object retval; | Object retval; |
try { | try { |
|
|
} | } |
} | } |
| |
public JsContext getContext(int depth) { |
JsContext getContext(int depth) { |
if (m_rcp != null) return m_rcp.getContext(depth); |
RhinoContextProxy rcp = RhinoContextProxy.getCurrent(); |
|
if (rcp != null) return rcp.getContextStub(depth); |
return null; | return null; |
} | } |
| |
public int getContextCount() { |
int getContextCount() { |
if (m_rcp != null) return m_rcp.getContextCount(); |
RhinoContextProxy rcp = RhinoContextProxy.getCurrent(); |
|
if (rcp != null) return rcp.getContextCount(); |
return -1; | return -1; |
} | } |
| |
|
|
* Return the current debugger. | * Return the current debugger. |
* @return the debugger, or null if none is attached. | * @return the debugger, or null if none is attached. |
*/ | */ |
public JsCallbacks getDebugger() { |
JsCallbacks getDebugger() { |
return m_callbacks; | return m_callbacks; |
} | } |
| |
public Object getDebugInterface() { |
Object getDebugInterface() { |
return engineStub; | return engineStub; |
} | } |
| |
public JsObject getGlobalObject() { |
JsObject getGlobalObject() { |
return globalstub; | return globalstub; |
} | } |
| |
public RhinoContextProxy getRhinoContextProxy() { |
|
return m_rcp; |
|
} |
|
|
|
RhinoContextProxy getStub(Context cx) { | RhinoContextProxy getStub(Context cx) { |
return (RhinoContextProxy) stubs.get(cx); |
return (RhinoContextProxy)cx.getDebuggerContextData(); |
} | } |
| |
JsContextStub getStub(DebugFrame frame) { | JsContextStub getStub(DebugFrame frame) { |
|
|
return (JsObject) stubs.get(sobj); | return (JsObject) stubs.get(sobj); |
} | } |
| |
public JsObject getUndefinedValue() { |
JsObject getUndefinedValue() { |
return undefinedStub; | return undefinedStub; |
} | } |
| |
public String getThread() { |
String getThread() { |
|
Context cx = Context.getCurrentContext(); |
String resultstr = ""; | String resultstr = ""; |
| |
if (m_thread != null) { |
if (cx != null) { |
try { | try { |
final String resultstrf = (String) | final String resultstrf = (String) |
AccessController.doPrivileged(new PrivilegedExceptionAction() { | AccessController.doPrivileged(new PrivilegedExceptionAction() { |
public Object run() throws Exception { | public Object run() throws Exception { |
return m_thread.getName(); |
return Thread.currentThread().getName(); |
} | } |
}); | }); |
resultstr = resultstrf; | resultstr = resultstrf; |
|
|
return resultstr; | return resultstr; |
} | } |
| |
public String getThreadGroup() { |
String getThreadGroup() { |
|
Context cx = Context.getCurrentContext(); |
String resultstr = ""; | String resultstr = ""; |
| |
if (m_thread != null) { |
if (cx != null) { |
try { | try { |
final String resultstrf = (String) | final String resultstrf = (String) |
AccessController.doPrivileged(new PrivilegedExceptionAction() { | AccessController.doPrivileged(new PrivilegedExceptionAction() { |
public Object run() throws Exception { | public Object run() throws Exception { |
return m_thread.getThreadGroup().getName(); |
return Thread.currentThread().getThreadGroup(). |
|
getName(); |
} | } |
}); | }); |
resultstr = resultstrf; | resultstr = resultstrf; |
|
|
// to implement STEP_IN, STEP_OUT, and STEP_OVER. | // to implement STEP_IN, STEP_OUT, and STEP_OVER. |
//--------------------------------------------------------- | //--------------------------------------------------------- |
| |
public void handleBreakpointHit(Context cx) { |
void handleBreakpointHit(Context cx, RhinoContextProxy rcp) { |
JsCallbacks debugger; | JsCallbacks debugger; |
BreakPoint bp; | BreakPoint bp; |
Enumeration e; | Enumeration e; |
|
|
boolean breakpointFound=false; | boolean breakpointFound=false; |
String name; | String name; |
int lineno; | int lineno; |
boolean suspend=false; |
|
|
DebugLog.stdoutPrintln("**** Handling a breakpoint hit...", |
m_thread = Thread.currentThread(); |
|
DebugLog.stdoutPrintln("**** Handling a breakpoint hit...", |
|
DebugLog.BSF_LOG_L3); | DebugLog.BSF_LOG_L3); |
m_rcp = getStub(cx); |
// if we have no callbacks... then just |
if (m_rcp == null) { |
|
m_rcp = new RhinoContextProxy(this, cx); |
|
addStub(cx, m_rcp); |
|
} |
|
// if we have no callbacks... then just |
|
// ignore the breakpoint hit, do a run | // ignore the breakpoint hit, do a run |
// so that execution resumes... | // so that execution resumes... |
if (m_callbacks==null) { | if (m_callbacks==null) { |
DebugLog.stdoutPrintln(" No callbacks, resuming...", DebugLog.BSF_LOG_L3); |
DebugLog.stdoutPrintln(" No callbacks, resuming...", DebugLog.BSF_LOG_L3); |
m_rcp.run(); |
rcp.run(); |
| |
} else { | } else { |
// First, check that we didn't hit a known breakpoint. | // First, check that we didn't hit a known breakpoint. |
// First, search if we have breakpoints for the current documents | // First, search if we have breakpoints for the current documents |
| |
name = m_rcp.getSourceName(); |
name = rcp.getSourceName(); |
lineno = m_rcp.getLineNumber(); |
lineno = rcp.getLineNumber(); |
| |
DebugLog.stdoutPrintln(" in "+name+" at "+lineno, DebugLog.BSF_LOG_L3); |
DebugLog.stdoutPrintln(" in "+name+" at "+lineno, DebugLog.BSF_LOG_L3); |
| |
cell = getDocumentCell(name); | cell = getDocumentCell(name); |
if (cell != null) |
if (cell != null) |
_handleBreakpointHit(cell,lineno); |
_handleBreakpointHit(rcp,cell,lineno); |
} |
} |
m_rcp = null; |
|
} | } |
| |
public void _handleBreakpointHit(DocumentCell cell, int lineno) { |
void _handleBreakpointHit(RhinoContextProxy rcp, |
|
DocumentCell cell, int lineno) |
|
{ |
JsCallbacks debugger; | JsCallbacks debugger; |
BreakPoint bp; | BreakPoint bp; |
Enumeration e; | Enumeration e; |
JsContext stub=null; | JsContext stub=null; |
boolean breakpointFound=false; | boolean breakpointFound=false; |
boolean suspend=false; | boolean suspend=false; |
|
|
try { | try { |
bp = cell.findBreakpointAtLine(lineno); | bp = cell.findBreakpointAtLine(lineno); |
} catch (BSFException bsfex) { | } catch (BSFException bsfex) { |
|
|
if (bp != null) { | if (bp != null) { |
breakpointFound = true; | breakpointFound = true; |
try { | try { |
stub = m_rcp.hitBreakpoint(); |
stub = rcp.hitBreakpoint(); |
DebugLog.stdoutPrintln(" breakpoint callback...", DebugLog.BSF_LOG_L3); |
DebugLog.stdoutPrintln(" breakpoint callback...", DebugLog.BSF_LOG_L3); |
m_callbacks.createFuture(m_rcp); |
m_callbacks.createFuture(rcp); |
m_callbacks.handleBreakpointHit(stub); | m_callbacks.handleBreakpointHit(stub); |
suspend = true; | suspend = true; |
} catch (RemoteException rex) { | } catch (RemoteException rex) { |
DebugLog.stderrPrintln(" EXCEPTION OCCURED DURING BREAKPOINT CALLBACK", DebugLog.BSF_LOG_L0); |
DebugLog.stderrPrintln(" EXCEPTION OCCURED DURING BREAKPOINT CALLBACK", DebugLog.BSF_LOG_L0); |
DebugLog.stderrPrintln(rex.getMessage(), DebugLog.BSF_LOG_L0); | DebugLog.stderrPrintln(rex.getMessage(), DebugLog.BSF_LOG_L0); |
rex.printStackTrace(); | rex.printStackTrace(); |
suspend = false; | suspend = false; |
} | } |
} else { | } else { |
DebugLog.stdoutPrintln(" didn't find a breakpoint...", DebugLog.BSF_LOG_L3); |
DebugLog.stdoutPrintln(" didn't find a breakpoint...", DebugLog.BSF_LOG_L3); |
breakpointFound = false; | breakpointFound = false; |
} | } |
| |
|
|
// line in the current document, we must be stepping | // line in the current document, we must be stepping |
// or in entry/exit mode | // or in entry/exit mode |
try { | try { |
stub = m_rcp.stepping(); |
stub = rcp.stepping(); |
FnOrScript current = cell.findFnOrScriptContaining(lineno); | FnOrScript current = cell.findFnOrScriptContaining(lineno); |
if (stub != null) { | if (stub != null) { |
cell.setLastFnOrScript(current); | cell.setLastFnOrScript(current); |
DebugLog.stdoutPrintln(" stepping-done callback...", |
DebugLog.stdoutPrintln(" stepping-done callback...", |
DebugLog.BSF_LOG_L3); | DebugLog.BSF_LOG_L3); |
m_callbacks.createFuture(m_rcp); |
m_callbacks.createFuture(rcp); |
m_callbacks.handleSteppingDone(stub); | m_callbacks.handleSteppingDone(stub); |
suspend = true; | suspend = true; |
} |
} |
else if (cell.getEntryExit() && | else if (cell.getEntryExit() && |
(current != cell.getLastFnOrScript()) && | (current != cell.getLastFnOrScript()) && |
(m_rcp.getContextCount() == 0)) { |
(rcp.getContextCount() == 0)) { |
cell.setLastFnOrScript(current); | cell.setLastFnOrScript(current); |
stub = m_rcp.entry_exit_mode(); |
stub = rcp.entry_exit_mode(); |
DebugLog.stdoutPrintln(" entry/exit mode...", |
DebugLog.stdoutPrintln(" entry/exit mode...", |
DebugLog.BSF_LOG_L3); | DebugLog.BSF_LOG_L3); |
m_callbacks.createFuture(m_rcp); |
m_callbacks.createFuture(rcp); |
m_callbacks.handleSteppingDone(stub); | m_callbacks.handleSteppingDone(stub); |
suspend = true; | suspend = true; |
} | } |
else { | else { |
DebugLog.stdoutPrintln(" No reason to suspend execution.", DebugLog.BSF_LOG_L3); |
DebugLog.stdoutPrintln(" No reason to suspend execution.", DebugLog.BSF_LOG_L3); |
suspend = false; | suspend = false; |
} | } |
} catch (RemoteException rex) { | } catch (RemoteException rex) { |
DebugLog.stderrPrintln(" EXCEPTION OCCURED DURING STEPPING-DONE CALLBACK", DebugLog.BSF_LOG_L0); |
DebugLog.stderrPrintln(" EXCEPTION OCCURED DURING STEPPING-DONE CALLBACK", DebugLog.BSF_LOG_L0); |
DebugLog.stderrPrintln(rex.getMessage(), DebugLog.BSF_LOG_L0); | DebugLog.stderrPrintln(rex.getMessage(), DebugLog.BSF_LOG_L0); |
rex.printStackTrace(); | rex.printStackTrace(); |
suspend = false; | suspend = false; |
} | } |
} | } |
if (suspend) { | if (suspend) { |
// now, suspend this thread... until |
// now, suspend this thread... until |
// we restart. | // we restart. |
try { | try { |
m_callbacks.suspendFuture(m_rcp); |
m_callbacks.suspendFuture(rcp); |
} catch (Exception ex) { | } catch (Exception ex) { |
DebugLog.stdoutPrintln("Future creation failed... releasing the engine", DebugLog.BSF_LOG_L3); | DebugLog.stdoutPrintln("Future creation failed... releasing the engine", DebugLog.BSF_LOG_L3); |
m_rcp.run(); |
rcp.run(); |
} | } |
} |
} |
} | } |
| |
public void run(JsEngineStub eng) throws Exception { |
void run(JsEngineStub eng) throws Exception { |
DebugLog.stdoutPrintln("RhinoEngineDebugger::run()...", | DebugLog.stdoutPrintln("RhinoEngineDebugger::run()...", |
DebugLog.BSF_LOG_L3); | DebugLog.BSF_LOG_L3); |
m_rcp.run(); |
RhinoContextProxy rcp = RhinoContextProxy.getCurrent(); |
m_callbacks.completeFuture(m_rcp); |
rcp.run(); |
|
m_callbacks.completeFuture(rcp); |
} | } |
| |
public void stepIn(JsEngineStub eng) throws Exception { |
void stepIn(JsEngineStub eng) throws Exception { |
DebugLog.stdoutPrintln("RhinoEngineDebugger::stepIn()...", | DebugLog.stdoutPrintln("RhinoEngineDebugger::stepIn()...", |
DebugLog.BSF_LOG_L3); | DebugLog.BSF_LOG_L3); |
m_rcp.stepIn(); |
RhinoContextProxy rcp = RhinoContextProxy.getCurrent(); |
m_callbacks.completeFuture(m_rcp); |
rcp.stepIn(); |
|
m_callbacks.completeFuture(rcp); |
} | } |
| |
public void stepOut(JsEngineStub eng) throws Exception { |
void stepOut(JsEngineStub eng) throws Exception { |
DebugLog.stdoutPrintln("RhinoEngineDebugger::stepOut()...", | DebugLog.stdoutPrintln("RhinoEngineDebugger::stepOut()...", |
DebugLog.BSF_LOG_L3); | DebugLog.BSF_LOG_L3); |
m_rcp.stepOut(); |
RhinoContextProxy rcp = RhinoContextProxy.getCurrent(); |
m_callbacks.completeFuture(m_rcp); |
rcp.stepOut(); |
|
m_callbacks.completeFuture(rcp); |
} | } |
public void stepOver(JsEngineStub eng) throws Exception { |
void stepOver(JsEngineStub eng) throws Exception { |
| |
DebugLog.stdoutPrintln("RhinoEngineDebugger::stepOver()...", | DebugLog.stdoutPrintln("RhinoEngineDebugger::stepOver()...", |
DebugLog.BSF_LOG_L3); | DebugLog.BSF_LOG_L3); |
m_rcp.stepOver(); |
RhinoContextProxy rcp = RhinoContextProxy.getCurrent(); |
m_callbacks.completeFuture(m_rcp); |
rcp.stepOver(); |
|
m_callbacks.completeFuture(rcp); |
} | } |
|
|
public void handleCompilationDone(Context cx, | public void handleCompilationDone(Context cx, |
DebuggableScript fnOrScript, | DebuggableScript fnOrScript, |
StringBuffer source) { |
String source) { |
| |
m_thread = Thread.currentThread(); |
|
m_compilingFnOrScript.addCompilationUnit(cx, fnOrScript, source); | m_compilingFnOrScript.addCompilationUnit(cx, fnOrScript, source); |
} | } |
| |
public void handleExceptionThrown(Context cx, Object exceptionThrown) { |
public DebugFrame getFrame(Context cx, DebuggableScript fnOrScript) { |
|
CompilationUnit unit; |
|
unit = m_compilingFnOrScript.getCompilationUnit(fnOrScript); |
|
RhinoContextProxy rcp = getStub(cx); |
|
try { |
|
JsContextStub stub = new JsContextStub(rcp, unit); |
|
return stub.getRhinoDebugFrame(); |
|
} catch (RemoteException rex) { |
|
DebugLog.stderrPrintln(" EXCEPTION OCCURED DURING FRAME INITIALIZATION", DebugLog.BSF_LOG_L0); |
|
DebugLog.stderrPrintln(rex.getMessage(), DebugLog.BSF_LOG_L0); |
|
rex.printStackTrace(); |
|
return null; |
|
} |
|
} |
|
|
|
void handleExceptionThrown(Context cx, RhinoContextProxy rcp, |
|
Throwable exceptionThrown) |
|
{ |
JsContext stub; | JsContext stub; |
JsCallbacks debugger; | JsCallbacks debugger; |
BreakPoint bp; | BreakPoint bp; |
|
|
String name,msg; | String name,msg; |
Exception ex; | Exception ex; |
int lineno; | int lineno; |
NativeError error; |
|
|
// if we have no callbacks... then just |
m_thread = Thread.currentThread(); |
// ignore the breakpoint hit, do a run |
m_rcp = getStub(cx); |
// so that execution resumes... |
if (m_rcp == null) { |
if (m_callbacks==null) { |
m_rcp = new RhinoContextProxy(this, cx); |
rcp.run(); |
addStub(cx, m_rcp); |
return; |
} | } |
try { |
|
// if we have no callbacks... then just |
|
// ignore the breakpoint hit, do a run |
|
// so that execution resumes... |
|
if (m_callbacks==null) { |
|
m_rcp.run(); |
|
return; |
|
} |
|
| |
// First, check that we didn't hit a known breakpoint. |
// First, check that we didn't hit a known breakpoint. |
// First, search if we have breakpoints for the current documents |
// First, search if we have breakpoints for the current documents |
name = m_rcp.getSourceName(); |
name = rcp.getSourceName(); |
lineno = m_rcp.getLineNumber(); |
lineno = rcp.getLineNumber(); |
try { |
if (exceptionThrown instanceof EcmaError) { |
error = (NativeError)exceptionThrown; |
msg = ((EcmaError)exceptionThrown).getErrorObject().toString(); |
msg = error.getName() + ": " + error.getMessage(); |
} else { |
} catch (ClassCastException ccex) { |
msg = exceptionThrown.toString(); |
msg = "Unknown JavaScript Exception"; |
} |
} |
ex = new Exception(msg); |
ex = new Exception(msg); |
|
| |
cell = getDocumentCell(name); |
cell = getDocumentCell(name); |
if (cell == null) return; |
if (cell == null) return; |
| |
try { |
try { |
stub = m_rcp.exceptionThrown(); |
stub = rcp.exceptionThrown(); |
m_callbacks.createFuture(m_rcp); |
m_callbacks.createFuture(rcp); |
m_callbacks.handleExceptionThrown(stub,ex); |
m_callbacks.handleExceptionThrown(stub,ex); |
|
|
// now, suspend this thread... until |
// now, suspend this thread... until |
// we restart. |
// we restart. |
m_callbacks.suspendFuture(m_rcp); |
m_callbacks.suspendFuture(rcp); |
|
|
} catch (Exception ex2) { |
} catch (Exception ex2) { |
m_rcp.run(); |
rcp.run(); |
|
|
} |
|
} finally { |
|
m_rcp = null; |
|
} | } |
} | } |
| |
|
|
* The engine will call the attached debugger's handleBreakpointHit | * The engine will call the attached debugger's handleBreakpointHit |
* method on the next line it executes if isLineStep is true. | * method on the next line it executes if isLineStep is true. |
* May be used from another thread to interrupt execution. | * May be used from another thread to interrupt execution. |
* |
* |
* @param isLineStep if true, break next line | * @param isLineStep if true, break next line |
*/ | */ |
public void setBreakNextLine(JsContext context, boolean isLineStep) { |
void setBreakNextLine(JsContext context, boolean isLineStep) { |
} | } |
| |
void setCompilingFnOrScript(FnOrScript fnOrScript) { | void setCompilingFnOrScript(FnOrScript fnOrScript) { |
|
|
* @param debugger the debugger to be used on callbacks from | * @param debugger the debugger to be used on callbacks from |
* the engine. | * the engine. |
*/ | */ |
public void setDebugger(JsCallbacks debugger) { |
void setDebugger(JsCallbacks debugger) { |
m_callbacks = debugger; | m_callbacks = debugger; |
} | } |
} | } |