Changes from Christopher Oliver:
Hi Norris,
Would you mind checking in the attached changes to the debugger. The
attached files include the following changes:
1) Use ScriptableObject.getAllIds to obtain an object's properties (if
the object extends ScriptableObject). This makes non-enumerable
properties visible in the debugger for ScriptableObject's.
2) Made the coding style more consistent with the rest of Rhino.
3) Better support for displaying and stepping through eval-ed code.
As Igor suggested to me once, it might be a good idea to define a new
interface to similarly support debugging host objects that don't extend
ScriptableObject, something like the following:
public interface Debuggable extends Scriptable {
public Object[] getAllIds();
}
The debugger could check for this interface and if a host object chose
to implement it, the debugger would be able to display its
non-enumerable properties.
Chris
git-svn-id: svn://10.0.0.236/trunk@117520 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
parent
028a31b09c
commit
d1eb87d2d8
File diff suppressed because it is too large
Load Diff
@ -13,10 +13,10 @@
|
||||
* The Original Code is Rhino JavaScript Debugger code, released
|
||||
* November 21, 2000.
|
||||
*
|
||||
* The Initial Developer of the Original Code is See Beyond Corporation.
|
||||
* The Initial Developer of the Original Code is SeeBeyond Corporation.
|
||||
|
||||
* Portions created by See Beyond are
|
||||
* Copyright (C) 2000 See Beyond Communications Corporation. All
|
||||
* Portions created by SeeBeyond are
|
||||
* Copyright (C) 2000 SeeBeyond Technology Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
@ -44,11 +44,11 @@ public class VariableModel extends AbstractTreeTableModel
|
||||
implements TreeTableModel {
|
||||
|
||||
// Names of the columns.
|
||||
//static protected String[] cNames = {"Name", "Type", "Value"};
|
||||
|
||||
static protected String[] cNames = { " Name", " Value"};
|
||||
|
||||
// Types of the columns.
|
||||
//static protected Class[] cTypes = {TreeTableModel.class, String.class, String.class};
|
||||
|
||||
static protected Class[] cTypes = {TreeTableModel.class, String.class};
|
||||
|
||||
|
||||
@ -62,7 +62,7 @@ public class VariableModel extends AbstractTreeTableModel
|
||||
|
||||
protected Object getObject(Object node) {
|
||||
VariableNode varNode = ((VariableNode)node);
|
||||
if(varNode == null) return null;
|
||||
if (varNode == null) return null;
|
||||
return varNode.getObject();
|
||||
}
|
||||
|
||||
@ -86,10 +86,10 @@ public class VariableModel extends AbstractTreeTableModel
|
||||
|
||||
// The superclass's implementation would work, but this is more efficient.
|
||||
public boolean isLeaf(Object node) {
|
||||
if(node == null) return true;
|
||||
if (node == null) return true;
|
||||
VariableNode varNode = (VariableNode)node;
|
||||
Object[] children = varNode.getChildren();
|
||||
if(children != null && children.length > 0) {
|
||||
if (children != null && children.length > 0) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@ -116,46 +116,51 @@ public class VariableModel extends AbstractTreeTableModel
|
||||
}
|
||||
|
||||
public Object getValueAt(Object node, int column) {
|
||||
Object value = getObject(node);
|
||||
Context cx = Context.enter();
|
||||
try {
|
||||
switch(column) {
|
||||
Object value = getObject(node);
|
||||
switch (column) {
|
||||
case 0: // Name
|
||||
VariableNode varNode = (VariableNode)node;
|
||||
String name = "";
|
||||
if(varNode.name != null) {
|
||||
if (varNode.name != null) {
|
||||
return name + varNode.name;
|
||||
}
|
||||
return name + "[" + varNode.index + "]";
|
||||
case 1: // value
|
||||
if(value == Undefined.instance ||
|
||||
case 1: // Value
|
||||
if (value == Undefined.instance ||
|
||||
value == ScriptableObject.NOT_FOUND) {
|
||||
return "undefined";
|
||||
}
|
||||
if(value == null) {
|
||||
if (value == null) {
|
||||
return "null";
|
||||
}
|
||||
if(value instanceof NativeCall) {
|
||||
if (value instanceof NativeCall) {
|
||||
return "[object Call]";
|
||||
}
|
||||
String result;
|
||||
try {
|
||||
result = Context.toString(value);
|
||||
} catch(RuntimeException exc) {
|
||||
result = value.toString();
|
||||
if (value instanceof BaseFunction) {
|
||||
result = ((BaseFunction)value).decompile(cx, 0,
|
||||
false);
|
||||
} else {
|
||||
result = Context.toString(value);
|
||||
}
|
||||
} catch (RuntimeException exc) {
|
||||
result = exc.getMessage();
|
||||
}
|
||||
StringBuffer buf = new StringBuffer();
|
||||
int len = result.length();
|
||||
for(int i = 0; i < len; i++) {
|
||||
for (int i = 0; i < len; i++) {
|
||||
char ch = result.charAt(i);
|
||||
if(Character.isISOControl(ch)) {
|
||||
if (Character.isISOControl(ch)) {
|
||||
ch = ' ';
|
||||
}
|
||||
buf.append(ch);
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
} catch(Exception exc) {
|
||||
} catch (Exception exc) {
|
||||
//exc.printStackTrace();
|
||||
} finally {
|
||||
cx.exit();
|
||||
@ -199,151 +204,119 @@ class VariableNode {
|
||||
|
||||
public Object getObject() {
|
||||
try {
|
||||
if(scope == null) return null;
|
||||
if(name != null) {
|
||||
if(name.equals("this")) {
|
||||
if (scope == null) return null;
|
||||
if (name != null) {
|
||||
if (name.equals("this")) {
|
||||
return scope;
|
||||
}
|
||||
Object result;
|
||||
if(name.equals("__proto__")) {
|
||||
Object result = ScriptableObject.NOT_FOUND;
|
||||
if (name.equals("__proto__")) {
|
||||
result = scope.getPrototype();
|
||||
} else if(name.equals("__parent__")) {
|
||||
} else if (name.equals("__parent__")) {
|
||||
result = scope.getParentScope();
|
||||
} else {
|
||||
result = scope.get(name, scope);
|
||||
try {
|
||||
result = ScriptableObject.getProperty(scope, name);
|
||||
} catch (Exception e) {
|
||||
result = e.getMessage();
|
||||
}
|
||||
}
|
||||
if(result == ScriptableObject.NOT_FOUND) {
|
||||
if (result == ScriptableObject.NOT_FOUND) {
|
||||
result = Undefined.instance;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
Object result = scope.get(index, scope);
|
||||
if(result == ScriptableObject.NOT_FOUND) {
|
||||
Object result = ScriptableObject.getProperty(scope, index);
|
||||
if (result == ScriptableObject.NOT_FOUND) {
|
||||
result = Undefined.instance;
|
||||
}
|
||||
return result;
|
||||
} catch(Exception exc) {
|
||||
} catch (Exception exc) {
|
||||
return "undefined";
|
||||
}
|
||||
}
|
||||
|
||||
Object[] children;
|
||||
|
||||
/**
|
||||
* Loads the children, caching the results in the children ivar.
|
||||
*/
|
||||
static final Object[] empty = new Object[0];
|
||||
static Scriptable builtin[];
|
||||
|
||||
protected Object[] getChildren() {
|
||||
if(children != null) return children;
|
||||
if (children != null) return children;
|
||||
Context cx = Context.enter();
|
||||
try {
|
||||
Object value = getObject();
|
||||
if(value == null) return children = empty;
|
||||
if(value == ScriptableObject.NOT_FOUND ||
|
||||
if (value == null) return children = empty;
|
||||
if (value == ScriptableObject.NOT_FOUND ||
|
||||
value == Undefined.instance) {
|
||||
return children = empty;
|
||||
}
|
||||
if(value instanceof Scriptable) {
|
||||
if (value instanceof Scriptable) {
|
||||
Scriptable scrip = (Scriptable)value;
|
||||
Scriptable proto = scrip.getPrototype();
|
||||
Scriptable parent = scrip.getParentScope();
|
||||
if(value instanceof NativeCall) {
|
||||
if(name != null && name.equals("this")) {
|
||||
// this is the local variables table root
|
||||
// don't show the __parent__ property
|
||||
parent = null;
|
||||
} else if(!(parent instanceof NativeCall)) {
|
||||
// don't bother showing [object Global] as
|
||||
// the __parent__ property which just creates
|
||||
// more noise
|
||||
parent = null;
|
||||
}
|
||||
}
|
||||
if(proto != null) {
|
||||
if(builtin == null) {
|
||||
builtin = new Scriptable[6];
|
||||
builtin[0] =
|
||||
ScriptableObject.getObjectPrototype(scrip);
|
||||
builtin[1] =
|
||||
ScriptableObject.getFunctionPrototype(scrip);
|
||||
builtin[2] =
|
||||
ScriptableObject.getClassPrototype(scrip,
|
||||
"String");
|
||||
builtin[3] =
|
||||
ScriptableObject.getClassPrototype(scrip,
|
||||
"Boolean");
|
||||
builtin[4] =
|
||||
ScriptableObject.getClassPrototype(scrip,
|
||||
"Array");
|
||||
builtin[5] =
|
||||
ScriptableObject.getClassPrototype(scrip,
|
||||
"Number");
|
||||
}
|
||||
for(int i = 0; i < builtin.length; i++) {
|
||||
if(proto == builtin[i]) {
|
||||
proto = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(scrip.has(0, scrip)) {
|
||||
if (scrip.has(0, scrip)) {
|
||||
int len = 0;
|
||||
try {
|
||||
Scriptable start = scrip;
|
||||
Scriptable obj = start;
|
||||
Object result = Undefined.instance;
|
||||
do {
|
||||
if(obj.has("length", start)) {
|
||||
if (obj.has("length", start)) {
|
||||
result = obj.get("length", start);
|
||||
if (result != Scriptable.NOT_FOUND)
|
||||
break;
|
||||
}
|
||||
obj = obj.getPrototype();
|
||||
} while (obj != null);
|
||||
if(result instanceof Number) {
|
||||
if (result instanceof Number) {
|
||||
len = ((Number)result).intValue();
|
||||
}
|
||||
} catch(Exception exc) {
|
||||
} catch (Exception exc) {
|
||||
}
|
||||
if(parent != null) {
|
||||
if (parent != null) {
|
||||
len++;
|
||||
}
|
||||
if(proto != null) {
|
||||
if (proto != null) {
|
||||
len++;
|
||||
}
|
||||
children = new VariableNode[len];
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
if(proto != null) {
|
||||
children[i++] = new VariableNode(scrip, "__proto__");
|
||||
j++;
|
||||
}
|
||||
if(parent != null) {
|
||||
if (parent != null) {
|
||||
children[i++] = new VariableNode(scrip, "__parent__");
|
||||
j++;
|
||||
}
|
||||
for(; i < len; i++) {
|
||||
if (proto != null) {
|
||||
children[i++] = new VariableNode(scrip, "__proto__");
|
||||
j++;
|
||||
}
|
||||
for (; i < len; i++) {
|
||||
children[i] = new VariableNode(scrip, i-j);
|
||||
}
|
||||
} else {
|
||||
int len = 0;
|
||||
Hashtable t = new Hashtable();
|
||||
Object[] ids = scrip.getIds();
|
||||
if(proto != null) t.put("__proto__", "__proto__");
|
||||
if(parent != null) t.put("__parent__", "__parent__");
|
||||
if(ids.length > 0) {
|
||||
for(int j = 0; j < ids.length; j++) {
|
||||
Object[] ids;
|
||||
if (scrip instanceof ScriptableObject) {
|
||||
ids = ((ScriptableObject)scrip).getAllIds();
|
||||
} else {
|
||||
ids = scrip.getIds();
|
||||
}
|
||||
if (ids == null) ids = empty;
|
||||
if (proto != null) t.put("__proto__", "__proto__");
|
||||
if (parent != null) t.put("__parent__", "__parent__");
|
||||
if (ids.length > 0) {
|
||||
for (int j = 0; j < ids.length; j++) {
|
||||
t.put(ids[j], ids[j]);
|
||||
}
|
||||
}
|
||||
ids = new Object[t.size()];
|
||||
Enumeration e = t.keys();
|
||||
int j = 0;
|
||||
while(e.hasMoreElements()) {
|
||||
while (e.hasMoreElements()) {
|
||||
ids[j++] = e.nextElement().toString();
|
||||
}
|
||||
if(ids != null && ids.length > 0) {
|
||||
if (ids != null && ids.length > 0) {
|
||||
java.util.Arrays.sort(ids, new java.util.Comparator() {
|
||||
public int compare(Object l, Object r) {
|
||||
return l.toString().compareToIgnoreCase(r.toString());
|
||||
@ -353,10 +326,10 @@ class VariableNode {
|
||||
len = ids.length;
|
||||
}
|
||||
children = new VariableNode[len];
|
||||
for(int i = 0; i < len; i++) {
|
||||
for (int i = 0; i < len; i++) {
|
||||
Object id = ids[i];
|
||||
children[i] =
|
||||
new VariableNode(scrip, id.toString());
|
||||
children[i] = new
|
||||
VariableNode(scrip, id.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user