Reviewed by a tired Geoff.
authorthatcher <thatcher@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 11 Jul 2006 07:51:34 +0000 (07:51 +0000)
committerthatcher <thatcher@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 11 Jul 2006 07:51:34 +0000 (07:51 +0000)
        Bug 9597: [Drosera] hook up the variables table to show stack variables
        http://bugzilla.opendarwin.org/show_bug.cgi?id=9597

        * Drosera/DebuggerDocument.m:
        (-[WebScriptObject isSelectorExcludedFromWebScript:]):
        (-[WebScriptObject webScriptAttributeKeysForScriptObject:]):
        (-[WebScriptObject localScopeVariableNamesForCallFrame:]):
        (-[WebScriptObject valueForScopeVariableNamed:inCallFrame:]):
        (-[WebScriptObject webView:didReceiveTitle:forFrame:]):
        (-[WebScriptObject webView:didLoadMainResourceForDataSource:]):
        (-[WebScriptObject webView:didParseSource:baseLineNumber:fromURL:sourceId:forWebFrame:]):
        (-[WebScriptObject webView:didEnterCallFrame:sourceId:line:forWebFrame:]):
        (-[WebScriptObject webView:willExecuteStatement:sourceId:line:forWebFrame:]):
        (-[WebScriptObject webView:willLeaveCallFrame:sourceId:line:forWebFrame:]):
        * Drosera/debugger.css:
        * Drosera/debugger.html:
        * Drosera/debugger.js:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@15332 268f45cc-cd09-0410-ab3c-d52691b4dbfc

WebKitTools/ChangeLog
WebKitTools/Drosera/DebuggerDocument.m
WebKitTools/Drosera/debugger.css
WebKitTools/Drosera/debugger.html
WebKitTools/Drosera/debugger.js

index 3811e60e6daa2f64117fa9a040c3d333fbf87b2b..d389f594a1aba691e0f9117cee83120a05029996 100644 (file)
@@ -1,3 +1,25 @@
+2006-07-11  Timothy Hatcher  <timothy@apple.com>
+
+        Reviewed by a tired Geoff.
+
+        Bug 9597: [Drosera] hook up the variables table to show stack variables
+        http://bugzilla.opendarwin.org/show_bug.cgi?id=9597
+
+        * Drosera/DebuggerDocument.m:
+        (-[WebScriptObject isSelectorExcludedFromWebScript:]):
+        (-[WebScriptObject webScriptAttributeKeysForScriptObject:]):
+        (-[WebScriptObject localScopeVariableNamesForCallFrame:]):
+        (-[WebScriptObject valueForScopeVariableNamed:inCallFrame:]):
+        (-[WebScriptObject webView:didReceiveTitle:forFrame:]):
+        (-[WebScriptObject webView:didLoadMainResourceForDataSource:]):
+        (-[WebScriptObject webView:didParseSource:baseLineNumber:fromURL:sourceId:forWebFrame:]):
+        (-[WebScriptObject webView:didEnterCallFrame:sourceId:line:forWebFrame:]):
+        (-[WebScriptObject webView:willExecuteStatement:sourceId:line:forWebFrame:]):
+        (-[WebScriptObject webView:willLeaveCallFrame:sourceId:line:forWebFrame:]):
+        * Drosera/debugger.css:
+        * Drosera/debugger.html:
+        * Drosera/debugger.js:
+
 2006-07-10  Tim Omernick  <timo@apple.com>
 
         Reviewed by Beth Dakin.
index e5721bfe474855fef20546740bb77b0cf99d3751..12e841d8330d2e889543515f507338665785da26 100644 (file)
@@ -35,6 +35,10 @@ static NSString *DebuggerStepIntoToolbarItem = @"DebuggerStepIntoToolbarItem";
 static NSString *DebuggerStepOverToolbarItem = @"DebuggerStepOverToolbarItem";
 static NSString *DebuggerStepOutToolbarItem = @"DebuggerStepOutToolbarItem";
 
+@interface WebScriptObject (WebScriptObjectPrivate)
+- (unsigned int)count;
+@end
+
 @implementation DebuggerDocument
 + (BOOL)isSelectorExcludedFromWebScript:(SEL)aSelector
 {
@@ -87,6 +91,63 @@ static NSString *DebuggerStepOutToolbarItem = @"DebuggerStepOutToolbarItem";
     return [result autorelease];
 }
 
+- (NSArray *)webScriptAttributeKeysForScriptObject:(WebScriptObject *)object
+{
+    WebScriptObject *func = [object evaluateWebScript:@"(function () { var result = new Array(); for (var x in this) { result.push(x); } return result; })"];
+    [object setValue:func forKey:@"__drosera_introspection"];
+
+    NSMutableArray *result = [[NSMutableArray alloc] init];
+    WebScriptObject *variables = [object callWebScriptMethod:@"__drosera_introspection" withArguments:nil];
+    unsigned length = [variables count];
+    for (unsigned i = 0; i < length; i++) {
+        NSString *key = [variables webScriptValueAtIndex:i];
+        if (![key isEqualToString:@"__drosera_introspection"])
+            [result addObject:key];
+    }
+
+    [object removeWebScriptKey:@"__drosera_introspection"];
+
+    [result sortUsingSelector:@selector(compare:)];
+    return [result autorelease];
+}
+
+- (NSArray *)localScopeVariableNamesForCallFrame:(int)frame
+{
+    WebScriptCallFrame *cframe = currentFrame;
+    for (unsigned count = 0; count < frame; count++)
+        cframe = [cframe caller];
+
+    if (![[cframe scopeChain] count])
+        return nil;
+
+    WebScriptObject *scope = [[cframe scopeChain] objectAtIndex:0]; // local is always first
+    return [self webScriptAttributeKeysForScriptObject:scope];
+}
+
+- (NSString *)valueForScopeVariableNamed:(NSString *)key inCallFrame:(int)frame
+{
+    WebScriptCallFrame *cframe = currentFrame;
+    for (unsigned count = 0; count < frame; count++)
+        cframe = [cframe caller];
+
+    if (![[cframe scopeChain] count])
+        return nil;
+
+    unsigned scopeCount = [[cframe scopeChain] count];
+    for (unsigned i = 0; i < scopeCount; i++) {
+        WebScriptObject *scope = [[cframe scopeChain] objectAtIndex:i];
+        id value = [scope valueForKey:key];
+        if ([value isKindOfClass:NSClassFromString(@"WebScriptObject")])
+            return [value callWebScriptMethod:@"toString" withArguments:nil];
+        if (value && ![value isKindOfClass:[NSString class]])
+            return [NSString stringWithFormat:@"%@", value];
+        if (value)
+            return value;
+    }
+
+    return nil;
+}
+
 #pragma mark -
 #pragma mark Pause & Step
 
@@ -367,9 +428,10 @@ static NSString *DebuggerStepOutToolbarItem = @"DebuggerStepOutToolbarItem";
         return;
 
     NSString *urlCopy = [[[[dataSource response] URL] absoluteString] copy];
-    NSArray *args = [NSArray arrayWithObjects:(documentSourceCopy ? documentSourceCopy : @""), (urlCopy ? urlCopy : @""), [NSNumber numberWithBool:NO], nil];
+    NSArray *args = [[NSArray alloc] initWithObjects:(documentSourceCopy ? documentSourceCopy : @""), (urlCopy ? urlCopy : @""), [NSNumber numberWithBool:NO], nil];
     [[webView windowScriptObject] callWebScriptMethod:@"updateFileSource" withArguments:args];
 
+    [args release];
     [documentSourceCopy release];
     [urlCopy release];
 }
@@ -395,9 +457,10 @@ static NSString *DebuggerStepOutToolbarItem = @"DebuggerStepOutToolbarItem";
             urlCopy = [[[[dataSource response] URL] absoluteString] copy];
     }
 
-    NSArray *args = [NSArray arrayWithObjects:sourceCopy, (documentSourceCopy ? documentSourceCopy : @""), (urlCopy ? urlCopy : @""), [NSNumber numberWithInt:sid], [NSNumber numberWithUnsignedInt:baseLine], nil];
+    NSArray *args = [[NSArray alloc] initWithObjects:sourceCopy, (documentSourceCopy ? documentSourceCopy : @""), (urlCopy ? urlCopy : @""), [NSNumber numberWithInt:sid], [NSNumber numberWithUnsignedInt:baseLine], nil];
     [[webView windowScriptObject] callWebScriptMethod:@"didParseScript" withArguments:args];
 
+    [args release];
     [sourceCopy release];
     [documentSourceCopy release];
     [urlCopy release];
@@ -416,8 +479,9 @@ static NSString *DebuggerStepOutToolbarItem = @"DebuggerStepOutToolbarItem";
     currentFrame = [frame retain];
     [old release];
 
-    NSArray *args = [NSArray arrayWithObjects:[NSNumber numberWithInt:sid], [NSNumber numberWithInt:lineno], nil];
+    NSArray *args = [[NSArray alloc] initWithObjects:[NSNumber numberWithInt:sid], [NSNumber numberWithInt:lineno], nil];
     [[webView windowScriptObject] callWebScriptMethod:@"didEnterCallFrame" withArguments:args];
+    [args release];
 }
 
 - (void)webView:(WebView *)view willExecuteStatement:(WebScriptCallFrame *)frame sourceId:(int)sid line:(int)lineno forWebFrame:(WebFrame *)webFrame
@@ -425,8 +489,9 @@ static NSString *DebuggerStepOutToolbarItem = @"DebuggerStepOutToolbarItem";
     if (!webViewLoaded)
         return;
 
-    NSArray *args = [NSArray arrayWithObjects:[NSNumber numberWithInt:sid], [NSNumber numberWithInt:lineno], nil];
+    NSArray *args = [[NSArray alloc] initWithObjects:[NSNumber numberWithInt:sid], [NSNumber numberWithInt:lineno], nil];
     [[webView windowScriptObject] callWebScriptMethod:@"willExecuteStatement" withArguments:args];
+    [args release];
 }
 
 - (void)webView:(WebView *)view willLeaveCallFrame:(WebScriptCallFrame *)frame sourceId:(int)sid line:(int)lineno forWebFrame:(WebFrame *)webFrame
@@ -434,8 +499,9 @@ static NSString *DebuggerStepOutToolbarItem = @"DebuggerStepOutToolbarItem";
     if (!webViewLoaded)
         return;
 
-    NSArray *args = [NSArray arrayWithObjects:[NSNumber numberWithInt:sid], [NSNumber numberWithInt:lineno], nil];
+    NSArray *args = [[NSArray alloc] initWithObjects:[NSNumber numberWithInt:sid], [NSNumber numberWithInt:lineno], nil];
     [[webView windowScriptObject] callWebScriptMethod:@"willLeaveCallFrame" withArguments:args];
+    [args release];
 
     id old = currentFrame;
     currentFrame = [[frame caller] retain];
index 9d0e3135070c89babefb83608b658fefeb871086..2469943af9f410bbb9b98c8a3935b6c1707bc723 100644 (file)
@@ -27,7 +27,7 @@
  */
 
 img { padding: 0; margin: 0; }
-body { margin: 0; padding: 0; }
+body { margin: 0; padding: 0; overflow: hidden; }
 
 #main { position: absolute; top: 0; bottom: 0; left: 0; right: 0; }
 #info { position: absolute; top: 0; height: 175px; left: 0; right: 0; }
@@ -196,7 +196,20 @@ table {
     border: 0;
 }
 
-td { padding: 3px 7px 3px 9px; height: 15px; box-sizing: border-box; }
+td {
+    padding: 3px 7px 3px 9px;
+    height: 15px;
+    box-sizing: border-box;
+    -webkit-user-select: none;
+    overflow: hidden;
+    text-overflow: ellipsis;
+    white-space: nowrap;
+}
+
+tr.current {
+    background-color: rgb(56, 117, 215);
+    color: white;
+}
 
 .stackNumber {
     width: 2em;
index 466f0c403cbfbf39602a90a23063be8e4c3792f5..c998a928ffd84f7c6e75d00a8818fe6261a44860 100644 (file)
@@ -53,7 +53,7 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 <div id="infoDivider"></div>
 <div id="variables">
 <table id="variablesTableHeader">
-<tr class="column"><th class="variable" id ="variable" onmousedown="headerMouseDown(this);" onmouseup="headerMouseUp(this);" onmouseout="headerMouseOut(this);">Variable<div id="variableColumnResizer"></div>
+<tr class="column"><th class="variable" id="variable" onmousedown="headerMouseDown(this);" onmouseup="headerMouseUp(this);" onmouseout="headerMouseOut(this);">Variable<div id="variableColumnResizer"></div>
 </th><th onmousedown="headerMouseDown(this);" onmouseup="headerMouseUp(this);" onmouseout="headerMouseOut(this);">Value</th><th class="scrollCorner"></th></tr>
 </table>
 <div id="variablesBody">
index 8025ca8e15948f76d985fd92bc6fe4a9232c8ca3..7f9bcb459599fc498f7fa495242b6c3dad31fc5c 100644 (file)
@@ -32,6 +32,7 @@ var scripts = new Array();
 var currentFile = -1;
 var currentRow = null;
 var currentStack = null;
+var currentCallFrame = null;
 var previousFiles = new Array();
 var nextFiles = new Array();
 var isResizingColumn = false;
@@ -41,6 +42,43 @@ var steppingOver = false;
 var steppingStack = 0;
 var pauseOnNextStatement = false;
 
+ScriptCallFrame = function (functionName, index, row)
+{
+    this.functionName = functionName;
+    this.index = index;
+    this.row = row;
+    this.localVariableNames = null;
+}
+
+ScriptCallFrame.prototype.valueForScopeVariable = function (name)
+{
+    return DebuggerDocument.valueForScopeVariableNamed_inCallFrame_(name, this.index);
+}
+
+ScriptCallFrame.prototype.loadVariables = function ()
+{
+    if (!this.localVariableNames)
+        this.localVariableNames = DebuggerDocument.localScopeVariableNamesForCallFrame_(this.index);
+
+    var variablesTable = document.getElementById("variablesTable");
+    variablesTable.innerHTML = "";
+
+    for(var i = 0; i < this.localVariableNames.length; i++) {
+        var tr = document.createElement("tr");
+        var td = document.createElement("td");
+        td.innerText = this.localVariableNames[i];
+        td.className = "variable";
+        tr.appendChild(td);
+
+        td = document.createElement("td");
+        td.innerText = this.valueForScopeVariable(this.localVariableNames[i]);
+        tr.appendChild(td);
+        tr.addEventListener("click", selectVariable, true);
+
+        variablesTable.appendChild(tr);
+    }
+}
+
 function sleep(numberMillis) {
     var now = new Date();
     var exitTime = now.getTime() + numberMillis;
@@ -112,12 +150,20 @@ function columnResizerDrag(event) {
     if (element.dragging == true) {
         var main = document.getElementById("rightPane");
         var variableColumn = document.getElementById("variable");
+        var rules = document.defaultView.getMatchedCSSRules(variableColumn, "");
+        for (var i = 0; i < rules.length; i++) {
+            if (rules[i].selectorText == ".variable") {
+                var columnRule = rules[i];
+                break;
+            }
+        }
+
         var x = event.clientX + window.scrollX;
         var delta = element.dragLastX - x;
         var newWidth = constrainedWidthFromElement(variableColumn.clientWidth - delta, main);
         if ((variableColumn.clientWidth - delta) == newWidth) // the width wasn't constrained
             element.dragLastX = x;
-        variableColumn.style.width = newWidth + "px";
+        columnRule.style.width = newWidth + "px";
         element.style.left = newWidth + "px";
         event.preventDefault();
     }
@@ -194,11 +240,12 @@ function resume()
         currentRow = null;
     }
 
-    if (currentStack) {
-        var stackframeTable = document.getElementById("stackframeTable");
-        stackframeTable.innerHTML = ""; // clear the content
-        currentStack = null;
-    }
+    var stackframeTable = document.getElementById("stackframeTable");
+    stackframeTable.innerHTML = ""; // clear the content
+    var variablesTable = document.getElementById("variablesTable");
+    variablesTable.innerHTML = ""; // clear the content
+    currentStack = null;
+    currentCallFrame = null;
 
     pauseOnNextStatement = false;
     steppingOut = false;
@@ -559,8 +606,9 @@ function updateFunctionStack()
     var stackframeTable = document.getElementById("stackframeTable");
     stackframeTable.innerHTML = ""; // clear the content
 
-    currentStack = DebuggerDocument.currentFunctionStack();
-    for(var i = 0; i < currentStack.length; i++) {
+    currentStack = new Array();
+    var stack = DebuggerDocument.currentFunctionStack();
+    for(var i = 0; i < stack.length; i++) {
         var tr = document.createElement("tr");
         var td = document.createElement("td");
         td.className = "stackNumber";
@@ -568,23 +616,42 @@ function updateFunctionStack()
         tr.appendChild(td);
 
         td = document.createElement("td");
-        td.innerText = currentStack[i];
+        td.innerText = stack[i];
         tr.appendChild(td);
+        tr.addEventListener("click", selectStackFrame, true);
 
         stackframeTable.appendChild(tr);
-    }
 
-    var tr = document.createElement("tr");
-    var td = document.createElement("td");
-    td.className = "stackNumber";
-    td.innerText = i;
-    tr.appendChild(td);
+        var frame = new ScriptCallFrame(stack[i], i, tr);
+        tr.callFrame = frame;
+        currentStack.push(frame);
 
-    td = document.createElement("td");
-    td.innerText = "Global";
-    tr.appendChild(td);
+        if (i == 0) {
+            addStyleClass(tr, "current");
+            frame.loadVariables();
+            currentCallFrame = frame;
+        }
+    }
+}
+
+function selectStackFrame(event)
+{
+    var stackframeTable = document.getElementById("stackframeTable");
+    var rows = stackframeTable.childNodes;
+    for (var i = 0; i < rows.length; i++)
+        removeStyleClass(rows[i], "current");
+    addStyleClass(this, "current");
+    this.callFrame.loadVariables();
+    currentCallFrame = this.callFrame;
+}
 
-    stackframeTable.appendChild(tr);
+function selectVariable(event)
+{
+    var variablesTable = document.getElementById("variablesTable");
+    var rows = variablesTable.childNodes;
+    for (var i = 0; i < rows.length; i++)
+        removeStyleClass(rows[i], "current");
+    addStyleClass(this, "current");
 }
 
 function loadFile(fileIndex, manageNavLists)