Bug 1102347 - Add jump to lines in the debugger from new performance call tree. r=vp

This commit is contained in:
Jordan Santell 2014-12-10 17:34:00 +01:00
parent 8c0c28ff92
commit 14b95af383
6 changed files with 119 additions and 2 deletions

View File

@ -55,6 +55,10 @@ const EVENTS = {
// Emitted by the CallTreeView when a call tree has been rendered // Emitted by the CallTreeView when a call tree has been rendered
CALL_TREE_RENDERED: "Performance:UI:CallTreeRendered", CALL_TREE_RENDERED: "Performance:UI:CallTreeRendered",
// When a source is shown in the JavaScript Debugger at a specific location.
SOURCE_SHOWN_IN_JS_DEBUGGER: "Performance:UI:SourceShownInJsDebugger",
SOURCE_NOT_FOUND_IN_JS_DEBUGGER: "Performance:UI:SourceNotFoundInJsDebugger",
// Emitted by the WaterfallView when it has been rendered // Emitted by the WaterfallView when it has been rendered
WATERFALL_RENDERED: "Performance:UI:WaterfallRendered" WATERFALL_RENDERED: "Performance:UI:WaterfallRendered"
}; };

View File

@ -35,6 +35,8 @@ support-files =
[browser_perf-overview-selection.js] [browser_perf-overview-selection.js]
[browser_perf-details.js] [browser_perf-details.js]
[browser_perf-jump-to-debugger-01.js]
[browser_perf-jump-to-debugger-02.js]
[browser_perf-details-calltree-render-01.js] [browser_perf-details-calltree-render-01.js]
[browser_perf-details-calltree-render-02.js] [browser_perf-details-calltree-render-02.js]
[browser_perf-details-waterfall-render-01.js] [browser_perf-details-waterfall-render-01.js]

View File

@ -0,0 +1,27 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Tests if the performance tool can jump to the debugger.
*/
function spawnTest () {
let { target, panel, toolbox } = yield initPerformance(SIMPLE_URL);
let { viewSourceInDebugger } = panel.panelWin;
yield viewSourceInDebugger(SIMPLE_URL, 14);
let debuggerPanel = toolbox.getPanel("jsdebugger");
ok(debuggerPanel, "The debugger panel was opened.");
let { DebuggerView } = debuggerPanel.panelWin;
let Sources = DebuggerView.Sources;
is(Sources.selectedValue, getSourceActor(Sources, SIMPLE_URL),
"The correct source is shown in the debugger.");
is(DebuggerView.editor.getCursor().line + 1, 14,
"The correct line is highlighted in the debugger's source editor.");
yield teardown(panel);
finish();
}

View File

@ -0,0 +1,41 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Tests if the performance tool can jump to the debugger, when the source was already
* loaded in that tool.
*/
function spawnTest() {
let { target, panel, toolbox } = yield initPerformance(SIMPLE_URL, "jsdebugger");
let debuggerWin = panel.panelWin;
let debuggerEvents = debuggerWin.EVENTS;
let { DebuggerView } = debuggerWin;
let Sources = DebuggerView.Sources;
yield debuggerWin.once(debuggerEvents.SOURCE_SHOWN);
ok("A source was shown in the debugger.");
is(Sources.selectedValue, getSourceActor(Sources, SIMPLE_URL),
"The correct source is initially shown in the debugger.");
is(DebuggerView.editor.getCursor().line, 0,
"The correct line is initially highlighted in the debugger's source editor.");
yield toolbox.selectTool("performance");
let perfPanel = toolbox.getCurrentPanel();
let perfWin = perfPanel.panelWin;
let { viewSourceInDebugger } = perfWin;
yield viewSourceInDebugger(SIMPLE_URL, 14);
panel = toolbox.getPanel("jsdebugger");
ok(panel, "The debugger panel was reselected.");
is(DebuggerView.Sources.selectedValue, getSourceActor(Sources, SIMPLE_URL),
"The correct source is still shown in the debugger.");
is(DebuggerView.editor.getCursor().line + 1, 14,
"The correct line is now highlighted in the debugger's source editor.");
yield teardown(perfPanel);
finish();
}

View File

@ -158,7 +158,7 @@ function initBackend(aUrl) {
}); });
} }
function initPerformance(aUrl) { function initPerformance(aUrl, selectedTool="performance") {
info("Initializing a performance pane."); info("Initializing a performance pane.");
return Task.spawn(function*() { return Task.spawn(function*() {
@ -168,7 +168,7 @@ function initPerformance(aUrl) {
yield target.makeRemote(); yield target.makeRemote();
Services.prefs.setBoolPref("devtools.performance_dev.enabled", true); Services.prefs.setBoolPref("devtools.performance_dev.enabled", true);
let toolbox = yield gDevTools.showToolbox(target, "performance"); let toolbox = yield gDevTools.showToolbox(target, selectedTool);
let panel = toolbox.getCurrentPanel(); let panel = toolbox.getCurrentPanel();
return { target, panel, toolbox }; return { target, panel, toolbox };
}); });
@ -317,3 +317,8 @@ function dropSelection(graph) {
graph.dropSelection(); graph.dropSelection();
graph.emit("mouseup"); graph.emit("mouseup");
} }
function getSourceActor(aSources, aURL) {
let item = aSources.getItemForAttachment(a => a.source.url === aURL);
return item && item.value;
}

View File

@ -14,6 +14,7 @@ let CallTreeView = {
this.el = $(".call-tree"); this.el = $(".call-tree");
this._graphEl = $(".call-tree-cells-container"); this._graphEl = $(".call-tree-cells-container");
this._onRangeChange = this._onRangeChange.bind(this); this._onRangeChange = this._onRangeChange.bind(this);
this._onLink = this._onLink.bind(this);
this._stop = this._stop.bind(this); this._stop = this._stop.bind(this);
OverviewView.on(EVENTS.OVERVIEW_RANGE_SELECTED, this._onRangeChange); OverviewView.on(EVENTS.OVERVIEW_RANGE_SELECTED, this._onRangeChange);
@ -58,6 +59,13 @@ let CallTreeView = {
this.render(this._profilerData, beginAt, endAt); this.render(this._profilerData, beginAt, endAt);
}, },
_onLink: function (_, treeItem) {
let { url, line } = treeItem.frame.getInfo();
viewSourceInDebugger(url, line).then(
() => this.emit(EVENTS.SOURCE_SHOWN_IN_JS_DEBUGGER),
() => this.emit(EVENTS.SOURCE_NOT_FOUND_IN_JS_DEBUGGER));
},
/** /**
* Called when the recording is stopped and prepares data to * Called when the recording is stopped and prepares data to
* populate the call tree. * populate the call tree.
@ -85,6 +93,9 @@ let CallTreeView = {
inverted: options.inverted inverted: options.inverted
}); });
// Bind events
root.on("link", this._onLink);
// Clear out other graphs // Clear out other graphs
this._graphEl.innerHTML = ""; this._graphEl.innerHTML = "";
root.attachTo(this._graphEl); root.attachTo(this._graphEl);
@ -98,3 +109,30 @@ let CallTreeView = {
* Convenient way of emitting events from the view. * Convenient way of emitting events from the view.
*/ */
EventEmitter.decorate(CallTreeView); EventEmitter.decorate(CallTreeView);
/**
* Opens/selects the debugger in this toolbox and jumps to the specified
* file name and line number.
* @param string url
* @param number line
*/
let viewSourceInDebugger = Task.async(function *(url, line) {
// If the Debugger was already open, switch to it and try to show the
// source immediately. Otherwise, initialize it and wait for the sources
// to be added first.
let debuggerAlreadyOpen = gToolbox.getPanel("jsdebugger");
let { panelWin: dbg } = yield gToolbox.selectTool("jsdebugger");
if (!debuggerAlreadyOpen) {
yield new Promise((resolve) => dbg.once(dbg.EVENTS.SOURCES_ADDED, () => resolve(dbg)));
}
let { DebuggerView } = dbg;
let item = DebuggerView.Sources.getItemForAttachment(a => a.source.url === url);
if (item) {
return DebuggerView.setEditorLocation(item.attachment.source.actor, line, { noDebug: true });
}
return Promise.reject();
});