Bug 687093 - Clicking on a stack frame in the debugger should put the caret in the proper source line; r=msucan

This commit is contained in:
Panos Astithas 2012-02-11 11:44:20 +02:00
Родитель 7e346e6cb2
Коммит 1f5a412d16
8 изменённых файлов: 177 добавлений и 61 удалений

Просмотреть файл

@ -38,9 +38,7 @@
***** END LICENSE BLOCK *****/
"use strict";
/*global Components, XPCOMUtils, Services, StackFrames, ThreadState, dump */
const Cu = Components.utils;
const DBG_STRINGS_URI = "chrome://browser/locale/devtools/debugger.properties";
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
@ -1070,6 +1068,49 @@ DebuggerView.Scripts = {
}
},
/**
* Checks whether the script with the specified URL is among the scripts
* known to the debugger and shown in the list.
*
* @param string aUrl
* The script URL.
*/
contains: function DVS_contains(aUrl) {
if (this._scripts.getElementsByAttribute("value", aUrl).length > 0) {
return true;
}
return false;
},
/**
* Checks whether the script with the specified URL is selected in the list.
*
* @param string aUrl
* The script URL.
*/
isSelected: function DVS_isSelected(aUrl) {
if (this._scripts.selectedItem &&
this._scripts.selectedItem.value == aUrl) {
return true;
}
return false;
},
/**
* Selects the script with the specified URL from the list.
*
* @param string aUrl
* The script URL.
*/
selectScript: function DVS_selectScript(aUrl) {
for (let i = 0; i < this._scripts.itemCount; i++) {
if (this._scripts.getItemAtIndex(i).value == aUrl) {
this._scripts.selectedIndex = i;
break;
}
}
},
/**
* Adds a script to the scripts container.
* If the script already exists (was previously added), null is returned.
@ -1086,7 +1127,7 @@ DebuggerView.Scripts = {
*/
addScript: function DVS_addScript(aUrl, aSource, aScriptNameText) {
// make sure we don't duplicate anything
if (this._scripts.getElementsByAttribute("value", aUrl).length > 0) {
if (this.contains(aUrl)) {
return null;
}

Просмотреть файл

@ -257,11 +257,19 @@ var StackFrames = {
DebuggerView.Stackframes.highlightFrame(this.selectedFrame, true);
}
// Display the local variables.
let frame = this.activeThread.cachedFrames[aDepth];
if (!frame) {
return;
}
// Move the editor's caret to the proper line.
if (DebuggerView.Scripts.isSelected(frame.where.url) && frame.where.line) {
window.editor.setCaretPosition(frame.where.line - 1);
} else if (DebuggerView.Scripts.contains(frame.where.url)) {
DebuggerView.Scripts.selectScript(frame.where.url);
SourceScripts.onChange({ target: DebuggerView.Scripts._scripts });
window.editor.setCaretPosition(frame.where.line - 1);
}
// Display the local variables.
let localScope = DebuggerView.Properties.localScope;
localScope.empty();
// Add "this".
@ -457,7 +465,6 @@ var SourceScripts = {
* Handler for the thread client's scriptsadded notification.
*/
onScripts: function SS_onScripts() {
this.onScriptsCleared();
for each (let script in this.activeThread.cachedScripts) {
this._addScript(script);
}
@ -473,8 +480,11 @@ var SourceScripts = {
/**
* Handler for changes on the selected source script.
*/
onChange: function SS_onClick(aEvent) {
onChange: function SS_onChange(aEvent) {
let scripts = aEvent.target;
if (!scripts.selectedItem) {
return;
}
let script = scripts.selectedItem.getUserData("sourceScript");
this.setEditorMode(script.url, script.contentType);
this._showScript(script);

Просмотреть файл

@ -71,6 +71,7 @@ _BROWSER_TEST_FILES = \
browser_dbg_script-switching.js \
browser_dbg_pause-resume.js \
browser_dbg_update-editor-mode.js \
browser_dbg_select-line.js \
head.js \
$(NULL)

Просмотреть файл

@ -33,35 +33,24 @@ function test()
function testScriptsDisplay() {
gPane.activeThread.addOneTimeListener("scriptsadded", function() {
Services.tm.currentThread.dispatch({ run: function() {
let count = 0;
gScripts = gDebugger.DebuggerView.Scripts._scripts;
is(gDebugger.StackFrames.activeThread.state, "paused",
"Should only be getting stack frames while paused.");
is(gScripts.itemCount, 2, "Found the expected number of scripts.");
ok(gDebugger.editor.getText().search(/debugger/) != -1,
"The correct script was loaded initially.");
gDebugger.editor.addEventListener(SourceEditor.EVENTS.TEXT_CHANGED,
function onScriptLoad() {
// Skip the first change event, since we're only interested in the
// second.
if (count++ < 1) {
return;
}
function onChange() {
gDebugger.editor.removeEventListener(SourceEditor.EVENTS.TEXT_CHANGED,
onScriptLoad);
gScripts = gDebugger.DebuggerView.Scripts._scripts;
is(gDebugger.StackFrames.activeThread.state, "paused",
"Should only be getting stack frames while paused.");
is(gScripts.itemCount, 2, "Found the expected number of scripts.");
ok(gDebugger.editor.getText().search(/debugger/) != -1,
"The correct script was loaded initially.");
gDebugger.editor.addEventListener(SourceEditor.EVENTS.TEXT_CHANGED,
function onChange() {
gDebugger.editor.removeEventListener(SourceEditor.EVENTS.TEXT_CHANGED,
onChange);
testSwitchPaused();
});
gScripts.selectedIndex = 0;
gDebugger.SourceScripts.onChange({ target: gScripts });
onChange);
testSwitchPaused();
});
gScripts.selectedIndex = 0;
gDebugger.SourceScripts.onChange({ target: gScripts });
}}, 0);
});

Просмотреть файл

@ -0,0 +1,81 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Make sure that selecting a stack frame loads the right script in the editor
* pane and highlights the proper line.
*/
const TAB_URL = "http://example.com/browser/browser/devtools/debugger/" +
"test/browser_dbg_script-switching.html";
let tempScope = {};
Cu.import("resource:///modules/source-editor.jsm", tempScope);
let SourceEditor = tempScope.SourceEditor;
var gPane = null;
var gTab = null;
var gDebuggee = null;
var gDebugger = null;
var gScripts = null;
function test()
{
debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
gTab = aTab;
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.debuggerWindow;
testSelectLine();
});
}
function testSelectLine() {
gPane.activeThread.addOneTimeListener("scriptsadded", function() {
Services.tm.currentThread.dispatch({ run: function() {
gScripts = gDebugger.DebuggerView.Scripts._scripts;
is(gDebugger.StackFrames.activeThread.state, "paused",
"Should only be getting stack frames while paused.");
is(gScripts.itemCount, 2, "Found the expected number of scripts.");
ok(gDebugger.editor.getText().search(/debugger/) != -1,
"The correct script was loaded initially.");
// getCaretPosition is 0-based.
is(gDebugger.editor.getCaretPosition().line, 5,
"The correct line is selected.");
gDebugger.editor.addEventListener(SourceEditor.EVENTS.TEXT_CHANGED,
function onChange() {
gDebugger.editor.removeEventListener(SourceEditor.EVENTS.TEXT_CHANGED,
onChange);
ok(gDebugger.editor.getText().search(/debugger/) == -1,
"The second script is no longer displayed.");
ok(gDebugger.editor.getText().search(/firstCall/) != -1,
"The first script is displayed.");
// Yield control back to the event loop so that the debugger has a
// chance to highlight the proper line.
executeSoon(function(){
// getCaretPosition is 0-based.
is(gDebugger.editor.getCaretPosition().line, 4,
"The correct line is selected.");
gDebugger.StackFrames.activeThread.resume(function() {
removeTab(gTab);
finish();
});
});
});
// Click the oldest stack frame.
let element = gDebugger.document.getElementById("stackframe-3");
EventUtils.synthesizeMouseAtCenter(element, {}, gDebugger);
}}, 0);
});
gDebuggee.firstCall();
}

Просмотреть файл

@ -33,38 +33,27 @@ function test()
function testScriptsDisplay() {
gPane.activeThread.addOneTimeListener("scriptsadded", function() {
Services.tm.currentThread.dispatch({ run: function() {
let count = 0;
gScripts = gDebugger.DebuggerView.Scripts._scripts;
is(gDebugger.StackFrames.activeThread.state, "paused",
"Should only be getting stack frames while paused.");
is(gScripts.itemCount, 2, "Found the expected number of scripts.");
is(gDebugger.editor.getMode(), SourceEditor.MODES.HTML,
"Found the expected editor mode.");
ok(gDebugger.editor.getText().search(/debugger/) != -1,
"The correct script was loaded initially.");
gDebugger.editor.addEventListener(SourceEditor.EVENTS.TEXT_CHANGED,
function onScriptLoad() {
// Skip the first change event, since we're only interested in the
// second.
if (count++ < 1) {
return;
}
function onChange() {
gDebugger.editor.removeEventListener(SourceEditor.EVENTS.TEXT_CHANGED,
onScriptLoad);
gScripts = gDebugger.DebuggerView.Scripts._scripts;
is(gDebugger.StackFrames.activeThread.state, "paused",
"Should only be getting stack frames while paused.");
is(gScripts.itemCount, 2, "Found the expected number of scripts.");
is(gDebugger.editor.getMode(), SourceEditor.MODES.HTML,
"Found the expected editor mode.");
ok(gDebugger.editor.getText().search(/debugger/) != -1,
"The correct script was loaded initially.");
gDebugger.editor.addEventListener(SourceEditor.EVENTS.TEXT_CHANGED,
function onChange() {
gDebugger.editor.removeEventListener(SourceEditor.EVENTS.TEXT_CHANGED,
onChange);
testSwitchPaused();
});
gScripts.selectedIndex = 0;
gDebugger.SourceScripts.onChange({ target: gScripts });
onChange);
testSwitchPaused();
});
gScripts.selectedIndex = 0;
gDebugger.SourceScripts.onChange({ target: gScripts });
}}, 0);
});

Просмотреть файл

@ -2,5 +2,6 @@
http://creativecommons.org/publicdomain/zero/1.0/ */
function secondCall() {
// This comment is useful for browser_dbg_select-line.js.
eval("debugger;");
}

Просмотреть файл

@ -1095,6 +1095,10 @@ FrameActor.prototype = {
grip.environment = envActor ? envActor.grip() : envActor;
grip["this"] = this.threadActor.createValueGrip(this.frame["this"]);
grip.arguments = this._args();
if (this.frame.script) {
grip.where = { url: this.frame.script.url,
line: this.frame.script.getOffsetLine(this.frame.offset) };
}
if (!this.frame.older) {
grip.oldest = true;