mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 877686 - Add UI to toggle the blackboxing of specific sources; r=vporof
This commit is contained in:
parent
17c6d3866d
commit
b68e635891
@ -423,6 +423,7 @@ function StackFrames() {
|
||||
this._onResumed = this._onResumed.bind(this);
|
||||
this._onFrames = this._onFrames.bind(this);
|
||||
this._onFramesCleared = this._onFramesCleared.bind(this);
|
||||
this._onBlackBoxChange = this._onBlackBoxChange.bind(this);
|
||||
this._afterFramesCleared = this._afterFramesCleared.bind(this);
|
||||
this.evaluate = this.evaluate.bind(this);
|
||||
}
|
||||
@ -447,6 +448,7 @@ StackFrames.prototype = {
|
||||
this.activeThread.addListener("resumed", this._onResumed);
|
||||
this.activeThread.addListener("framesadded", this._onFrames);
|
||||
this.activeThread.addListener("framescleared", this._onFramesCleared);
|
||||
window.addEventListener("Debugger:BlackBoxChange", this._onBlackBoxChange, false);
|
||||
this._handleTabNavigation();
|
||||
},
|
||||
|
||||
@ -462,6 +464,7 @@ StackFrames.prototype = {
|
||||
this.activeThread.removeListener("resumed", this._onResumed);
|
||||
this.activeThread.removeListener("framesadded", this._onFrames);
|
||||
this.activeThread.removeListener("framescleared", this._onFramesCleared);
|
||||
window.removeEventListener("Debugger:BlackBoxChange", this._onBlackBoxChange, false);
|
||||
},
|
||||
|
||||
/**
|
||||
@ -594,12 +597,22 @@ StackFrames.prototype = {
|
||||
// Make sure all the previous stackframes are removed before re-adding them.
|
||||
DebuggerView.StackFrames.empty();
|
||||
|
||||
let previousBlackBoxed = null;
|
||||
for (let frame of this.activeThread.cachedFrames) {
|
||||
let { depth, where: { url, line } } = frame;
|
||||
let { depth, where: { url, line }, isBlackBoxed } = frame;
|
||||
let frameLocation = NetworkHelper.convertToUnicode(unescape(url));
|
||||
let frameTitle = StackFrameUtils.getFrameTitle(frame);
|
||||
|
||||
DebuggerView.StackFrames.addFrame(frameTitle, frameLocation, line, depth);
|
||||
if (isBlackBoxed) {
|
||||
if (previousBlackBoxed == url) {
|
||||
continue;
|
||||
}
|
||||
previousBlackBoxed = url;
|
||||
} else {
|
||||
previousBlackBoxed = null;
|
||||
}
|
||||
|
||||
DebuggerView.StackFrames.addFrame(frameTitle, frameLocation, line, depth, isBlackBoxed);
|
||||
}
|
||||
if (this.currentFrame == null) {
|
||||
DebuggerView.StackFrames.selectedDepth = 0;
|
||||
@ -626,6 +639,18 @@ StackFrames.prototype = {
|
||||
window.setTimeout(this._afterFramesCleared, FRAME_STEP_CLEAR_DELAY);
|
||||
},
|
||||
|
||||
/**
|
||||
* Handler for the debugger's BlackBoxChange notification.
|
||||
*/
|
||||
_onBlackBoxChange: function() {
|
||||
if (this.activeThread.state == "paused") {
|
||||
// We have to clear out the existing frames and refetch them to get their
|
||||
// updated black boxed status.
|
||||
this.activeThread._clearFrames();
|
||||
this.activeThread.fillFrames(CALL_STACK_PAGE_SIZE);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Called soon after the thread client's framescleared notification.
|
||||
*/
|
||||
@ -1000,6 +1025,27 @@ SourceScripts.prototype = {
|
||||
window.dispatchEvent(document, "Debugger:AfterSourcesAdded");
|
||||
},
|
||||
|
||||
/**
|
||||
* Set the black boxed status of the given source.
|
||||
*
|
||||
* @param Object aSource
|
||||
* The source form.
|
||||
* @param bool aBlackBoxFlag
|
||||
* True to black box the source, false to un-black box it.
|
||||
*/
|
||||
blackBox: function(aSource, aBlackBoxFlag) {
|
||||
const sourceClient = this.activeThread.source(aSource);
|
||||
sourceClient[aBlackBoxFlag ? "blackBox" : "unblackBox"](function({ error, message }) {
|
||||
if (error) {
|
||||
let msg = "Could not toggle black boxing for "
|
||||
+ aSource.url + ": " + message;
|
||||
dumpn(msg);
|
||||
return void Cu.reportError(msg);
|
||||
}
|
||||
window.dispatchEvent(document, "Debugger:BlackBoxChange", sourceClient);
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets a specified source's text.
|
||||
*
|
||||
|
@ -18,6 +18,7 @@ function SourcesView() {
|
||||
this._onSourceSelect = this._onSourceSelect.bind(this);
|
||||
this._onSourceClick = this._onSourceClick.bind(this);
|
||||
this._onBreakpointRemoved = this._onBreakpointRemoved.bind(this);
|
||||
this._onSourceCheck = this._onSourceCheck.bind(this);
|
||||
this._onBreakpointClick = this._onBreakpointClick.bind(this);
|
||||
this._onBreakpointCheckboxClick = this._onBreakpointCheckboxClick.bind(this);
|
||||
this._onConditionalPopupShowing = this._onConditionalPopupShowing.bind(this);
|
||||
@ -34,9 +35,12 @@ SourcesView.prototype = Heritage.extend(WidgetMethods, {
|
||||
initialize: function() {
|
||||
dumpn("Initializing the SourcesView");
|
||||
|
||||
this.widget = new SideMenuWidget(document.getElementById("sources"));
|
||||
this.widget = new SideMenuWidget(document.getElementById("sources"), {
|
||||
showCheckboxes: true
|
||||
});
|
||||
this.emptyText = L10N.getStr("noSourcesText");
|
||||
this.unavailableText = L10N.getStr("noMatchingSourcesText");
|
||||
this._blackBoxCheckboxTooltip = L10N.getStr("blackBoxCheckboxTooltip");
|
||||
|
||||
this._commandset = document.getElementById("debuggerCommands");
|
||||
this._popupset = document.getElementById("debuggerPopupset");
|
||||
@ -48,6 +52,7 @@ SourcesView.prototype = Heritage.extend(WidgetMethods, {
|
||||
window.addEventListener("Debugger:EditorUnloaded", this._onEditorUnload, false);
|
||||
this.widget.addEventListener("select", this._onSourceSelect, false);
|
||||
this.widget.addEventListener("click", this._onSourceClick, false);
|
||||
this.widget.addEventListener("check", this._onSourceCheck, false);
|
||||
this._cbPanel.addEventListener("popupshowing", this._onConditionalPopupShowing, false);
|
||||
this._cbPanel.addEventListener("popupshown", this._onConditionalPopupShown, false);
|
||||
this._cbPanel.addEventListener("popuphiding", this._onConditionalPopupHiding, false);
|
||||
@ -70,6 +75,7 @@ SourcesView.prototype = Heritage.extend(WidgetMethods, {
|
||||
window.removeEventListener("Debugger:EditorUnloaded", this._onEditorUnload, false);
|
||||
this.widget.removeEventListener("select", this._onSourceSelect, false);
|
||||
this.widget.removeEventListener("click", this._onSourceClick, false);
|
||||
this.widget.removeEventListener("check", this._onSourceCheck, false);
|
||||
this._cbPanel.removeEventListener("popupshowing", this._onConditionalPopupShowing, false);
|
||||
this._cbPanel.removeEventListener("popupshowing", this._onConditionalPopupShown, false);
|
||||
this._cbPanel.removeEventListener("popuphiding", this._onConditionalPopupHiding, false);
|
||||
@ -109,6 +115,8 @@ SourcesView.prototype = Heritage.extend(WidgetMethods, {
|
||||
this.push([label, url, group], {
|
||||
staged: aOptions.staged, /* stage the item to be appended later? */
|
||||
attachment: {
|
||||
checkboxState: !aSource.isBlackBoxed,
|
||||
checkboxTooltip: this._blackBoxCheckboxTooltip,
|
||||
source: aSource
|
||||
}
|
||||
});
|
||||
@ -639,6 +647,14 @@ SourcesView.prototype = Heritage.extend(WidgetMethods, {
|
||||
DebuggerView.Filtering.target = this;
|
||||
},
|
||||
|
||||
/**
|
||||
* The check listener for the sources container.
|
||||
*/
|
||||
_onSourceCheck: function({ detail: { checked }, target }) {
|
||||
let item = this.getItemForElement(target);
|
||||
DebuggerController.SourceScripts.blackBox(item.attachment.source, !checked);
|
||||
},
|
||||
|
||||
/**
|
||||
* The click listener for a breakpoint container.
|
||||
*/
|
||||
|
@ -424,8 +424,10 @@ StackFramesView.prototype = Heritage.extend(WidgetMethods, {
|
||||
* The line number to be displayed in the list.
|
||||
* @param number aDepth
|
||||
* The frame depth specified by the debugger.
|
||||
* @param boolean aIsBlackBoxed
|
||||
* Whether or not the frame is black boxed.
|
||||
*/
|
||||
addFrame: function(aFrameTitle, aSourceLocation, aLineNumber, aDepth) {
|
||||
addFrame: function(aFrameTitle, aSourceLocation, aLineNumber, aDepth, aIsBlackBoxed) {
|
||||
// Create the element node and menu entry for the stack frame item.
|
||||
let frameView = this._createFrameView.apply(this, arguments);
|
||||
let menuEntry = this._createMenuEntry.apply(this, arguments);
|
||||
@ -471,29 +473,35 @@ StackFramesView.prototype = Heritage.extend(WidgetMethods, {
|
||||
* The line number to be displayed in the list.
|
||||
* @param number aDepth
|
||||
* The frame depth specified by the debugger.
|
||||
* @param boolean aIsBlackBoxed
|
||||
* Whether or not the frame is black boxed.
|
||||
* @return nsIDOMNode
|
||||
* The stack frame view.
|
||||
*/
|
||||
_createFrameView: function(aFrameTitle, aSourceLocation, aLineNumber, aDepth) {
|
||||
let frameDetails =
|
||||
SourceUtils.trimUrlLength(
|
||||
SourceUtils.getSourceLabel(aSourceLocation),
|
||||
STACK_FRAMES_SOURCE_URL_MAX_LENGTH,
|
||||
STACK_FRAMES_SOURCE_URL_TRIM_SECTION) + SEARCH_LINE_FLAG + aLineNumber;
|
||||
|
||||
let frameTitleNode = document.createElement("label");
|
||||
frameTitleNode.className = "plain dbg-stackframe-title breadcrumbs-widget-item-tag";
|
||||
frameTitleNode.setAttribute("value", aFrameTitle);
|
||||
|
||||
let frameDetailsNode = document.createElement("label");
|
||||
frameDetailsNode.className = "plain dbg-stackframe-details breadcrumbs-widget-item-id";
|
||||
frameDetailsNode.setAttribute("value", frameDetails);
|
||||
|
||||
_createFrameView: function(aFrameTitle, aSourceLocation, aLineNumber, aDepth, aIsBlackBoxed) {
|
||||
let container = document.createElement("hbox");
|
||||
container.id = "stackframe-" + aDepth;
|
||||
container.className = "dbg-stackframe";
|
||||
|
||||
container.appendChild(frameTitleNode);
|
||||
let frameDetails = SourceUtils.trimUrlLength(
|
||||
SourceUtils.getSourceLabel(aSourceLocation),
|
||||
STACK_FRAMES_SOURCE_URL_MAX_LENGTH,
|
||||
STACK_FRAMES_SOURCE_URL_TRIM_SECTION);
|
||||
|
||||
if (aIsBlackBoxed) {
|
||||
container.classList.add("dbg-stackframe-black-boxed");
|
||||
} else {
|
||||
let frameTitleNode = document.createElement("label");
|
||||
frameTitleNode.className = "plain dbg-stackframe-title breadcrumbs-widget-item-tag";
|
||||
frameTitleNode.setAttribute("value", aFrameTitle);
|
||||
container.appendChild(frameTitleNode);
|
||||
|
||||
frameDetails += SEARCH_LINE_FLAG + aLineNumber;
|
||||
}
|
||||
|
||||
let frameDetailsNode = document.createElement("label");
|
||||
frameDetailsNode.className = "plain dbg-stackframe-details breadcrumbs-widget-item-id";
|
||||
frameDetailsNode.setAttribute("value", frameDetails);
|
||||
container.appendChild(frameDetailsNode);
|
||||
|
||||
return container;
|
||||
@ -510,10 +518,12 @@ StackFramesView.prototype = Heritage.extend(WidgetMethods, {
|
||||
* The line number to be displayed in the list.
|
||||
* @param number aDepth
|
||||
* The frame depth specified by the debugger.
|
||||
* @param boolean aIsBlackBoxed
|
||||
* Whether or not the frame is black boxed.
|
||||
* @return object
|
||||
* An object containing the stack frame command and menu item.
|
||||
*/
|
||||
_createMenuEntry: function(aFrameTitle, aSourceLocation, aLineNumber, aDepth) {
|
||||
_createMenuEntry: function(aFrameTitle, aSourceLocation, aLineNumber, aDepth, aIsBlackBoxed) {
|
||||
let frameDescription =
|
||||
SourceUtils.trimUrlLength(
|
||||
SourceUtils.getSourceLabel(aSourceLocation),
|
||||
|
@ -12,6 +12,10 @@ include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
MOCHITEST_BROWSER_TESTS = \
|
||||
browser_dbg_aaa_run_first_leaktest.js \
|
||||
browser_dbg_blackboxing-01.js \
|
||||
browser_dbg_blackboxing-02.js \
|
||||
browser_dbg_blackboxing-03.js \
|
||||
browser_dbg_blackboxing-04.js \
|
||||
browser_dbg_clean-exit.js \
|
||||
browser_dbg_cmd.js \
|
||||
browser_dbg_cmd_break.js \
|
||||
@ -110,6 +114,11 @@ MOCHITEST_BROWSER_TESTS = \
|
||||
$(NULL)
|
||||
|
||||
MOCHITEST_BROWSER_PAGES = \
|
||||
browser_dbg_blackboxing.html \
|
||||
browser_dbg_blackboxing_blackboxme.js \
|
||||
browser_dbg_blackboxing_one.js \
|
||||
browser_dbg_blackboxing_two.js \
|
||||
browser_dbg_blackboxing_three.js \
|
||||
browser_dbg_cmd_break.html \
|
||||
browser_dbg_cmd.html \
|
||||
testactors.js \
|
||||
|
76
browser/devtools/debugger/test/browser_dbg_blackboxing-01.js
Normal file
76
browser/devtools/debugger/test/browser_dbg_blackboxing-01.js
Normal file
@ -0,0 +1,76 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Test that if we black box a source and then refresh, it is still black boxed.
|
||||
*/
|
||||
|
||||
const TAB_URL = EXAMPLE_URL + "binary_search.html";
|
||||
|
||||
var gPane = null;
|
||||
var gTab = null;
|
||||
var gDebuggee = null;
|
||||
var gDebugger = null;
|
||||
|
||||
function test()
|
||||
{
|
||||
let scriptShown = false;
|
||||
let framesAdded = false;
|
||||
let resumed = false;
|
||||
let testStarted = false;
|
||||
|
||||
debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
|
||||
resumed = true;
|
||||
gTab = aTab;
|
||||
gDebuggee = aDebuggee;
|
||||
gPane = aPane;
|
||||
gDebugger = gPane.panelWin;
|
||||
|
||||
testBlackBoxSource();
|
||||
});
|
||||
}
|
||||
|
||||
function testBlackBoxSource() {
|
||||
once(gDebugger, "Debugger:SourceShown", function () {
|
||||
const checkbox = gDebugger.document.querySelector(".side-menu-widget-item-checkbox");
|
||||
ok(checkbox, "Should get the checkbox for black boxing the source");
|
||||
ok(checkbox.checked, "Should not be black boxed by default");
|
||||
|
||||
once(gDebugger, "Debugger:BlackBoxChange", function (event) {
|
||||
const sourceClient = event.detail;
|
||||
ok(sourceClient.isBlackBoxed, "The source should be black boxed now");
|
||||
ok(!checkbox.checked, "The checkbox should no longer be checked.");
|
||||
|
||||
testBlackBoxReload();
|
||||
});
|
||||
|
||||
checkbox.click();
|
||||
});
|
||||
}
|
||||
|
||||
function testBlackBoxReload() {
|
||||
once(gDebugger, "Debugger:SourceShown", function () {
|
||||
const checkbox = gDebugger.document.querySelector(".side-menu-widget-item-checkbox");
|
||||
ok(checkbox, "Should get the checkbox for black boxing the source");
|
||||
ok(!checkbox.checked, "Should still be black boxed");
|
||||
|
||||
closeDebuggerAndFinish();
|
||||
});
|
||||
|
||||
gDebuggee.location.reload();
|
||||
}
|
||||
|
||||
function once(target, event, callback) {
|
||||
target.addEventListener(event, function _listener(...args) {
|
||||
target.removeEventListener(event, _listener, false);
|
||||
callback.apply(null, args);
|
||||
}, false);
|
||||
}
|
||||
|
||||
registerCleanupFunction(function() {
|
||||
removeTab(gTab);
|
||||
gPane = null;
|
||||
gTab = null;
|
||||
gDebuggee = null;
|
||||
gDebugger = null;
|
||||
});
|
87
browser/devtools/debugger/test/browser_dbg_blackboxing-02.js
Normal file
87
browser/devtools/debugger/test/browser_dbg_blackboxing-02.js
Normal file
@ -0,0 +1,87 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Test that black boxed frames are compressed into a single frame on the stack
|
||||
* view.
|
||||
*/
|
||||
|
||||
const TAB_URL = EXAMPLE_URL + "browser_dbg_blackboxing.html";
|
||||
const BLACKBOXME_URL = EXAMPLE_URL + "browser_dbg_blackboxing_blackboxme.js"
|
||||
|
||||
var gPane = null;
|
||||
var gTab = null;
|
||||
var gDebuggee = null;
|
||||
var gDebugger = null;
|
||||
|
||||
function test()
|
||||
{
|
||||
let scriptShown = false;
|
||||
let framesAdded = false;
|
||||
let resumed = false;
|
||||
let testStarted = false;
|
||||
|
||||
debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
|
||||
resumed = true;
|
||||
gTab = aTab;
|
||||
gDebuggee = aDebuggee;
|
||||
gPane = aPane;
|
||||
gDebugger = gPane.panelWin;
|
||||
|
||||
testBlackBoxSource();
|
||||
});
|
||||
}
|
||||
|
||||
function testBlackBoxSource() {
|
||||
once(gDebugger, "Debugger:SourceShown", function () {
|
||||
const checkbox = getBlackBoxCheckbox(BLACKBOXME_URL);
|
||||
ok(checkbox, "Should get the checkbox for blackBoxing the source");
|
||||
|
||||
once(gDebugger, "Debugger:BlackBoxChange", function (event) {
|
||||
const sourceClient = event.detail;
|
||||
ok(sourceClient.isBlackBoxed, "The source should be black boxed now");
|
||||
|
||||
testBlackBoxStack();
|
||||
});
|
||||
|
||||
checkbox.click();
|
||||
});
|
||||
}
|
||||
|
||||
function testBlackBoxStack() {
|
||||
const { activeThread } = gDebugger.DebuggerController;
|
||||
activeThread.addOneTimeListener("framesadded", function () {
|
||||
const frames = gDebugger.DebuggerView.StackFrames.widget._list;
|
||||
|
||||
is(frames.querySelectorAll(".dbg-stackframe").length, 3,
|
||||
"Should only get 3 frames");
|
||||
|
||||
is(frames.querySelectorAll(".dbg-stackframe-black-boxed").length, 1,
|
||||
"And one of them should be the combined black boxed frames");
|
||||
|
||||
closeDebuggerAndFinish();
|
||||
});
|
||||
|
||||
gDebuggee.runTest();
|
||||
}
|
||||
|
||||
function getBlackBoxCheckbox(url) {
|
||||
return gDebugger.document.querySelector(
|
||||
".side-menu-widget-item[tooltiptext=\""
|
||||
+ url + "\"] .side-menu-widget-item-checkbox");
|
||||
}
|
||||
|
||||
function once(target, event, callback) {
|
||||
target.addEventListener(event, function _listener(...args) {
|
||||
target.removeEventListener(event, _listener, false);
|
||||
callback.apply(null, args);
|
||||
}, false);
|
||||
}
|
||||
|
||||
registerCleanupFunction(function() {
|
||||
removeTab(gTab);
|
||||
gPane = null;
|
||||
gTab = null;
|
||||
gDebuggee = null;
|
||||
gDebugger = null;
|
||||
});
|
96
browser/devtools/debugger/test/browser_dbg_blackboxing-03.js
Normal file
96
browser/devtools/debugger/test/browser_dbg_blackboxing-03.js
Normal file
@ -0,0 +1,96 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Test that black boxed frames are compressed into a single frame on the stack
|
||||
* view when we are already paused.
|
||||
*/
|
||||
|
||||
const TAB_URL = EXAMPLE_URL + "browser_dbg_blackboxing.html";
|
||||
const BLACKBOXME_URL = EXAMPLE_URL + "browser_dbg_blackboxing_blackboxme.js"
|
||||
|
||||
var gPane = null;
|
||||
var gTab = null;
|
||||
var gDebuggee = null;
|
||||
var gDebugger = null;
|
||||
|
||||
function test()
|
||||
{
|
||||
let scriptShown = false;
|
||||
let framesAdded = false;
|
||||
let resumed = false;
|
||||
let testStarted = false;
|
||||
|
||||
debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
|
||||
resumed = true;
|
||||
gTab = aTab;
|
||||
gDebuggee = aDebuggee;
|
||||
gPane = aPane;
|
||||
gDebugger = gPane.panelWin;
|
||||
|
||||
once(gDebugger, "Debugger:SourceShown", function () {
|
||||
testBlackBoxStack();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function testBlackBoxStack() {
|
||||
const { activeThread } = gDebugger.DebuggerController;
|
||||
activeThread.addOneTimeListener("framesadded", function () {
|
||||
const frames = gDebugger.DebuggerView.StackFrames.widget._list;
|
||||
|
||||
is(frames.querySelectorAll(".dbg-stackframe").length, 6,
|
||||
"Should get 6 frames");
|
||||
|
||||
is(frames.querySelectorAll(".dbg-stackframe-black-boxed").length, 0,
|
||||
"And none of them are black boxed");
|
||||
|
||||
testBlackBoxSource();
|
||||
});
|
||||
|
||||
gDebuggee.runTest();
|
||||
}
|
||||
|
||||
function testBlackBoxSource() {
|
||||
const checkbox = getBlackBoxCheckbox(BLACKBOXME_URL);
|
||||
ok(checkbox, "Should get the checkbox for black boxing the source");
|
||||
|
||||
once(gDebugger, "Debugger:BlackBoxChange", function (event) {
|
||||
const { activeThread } = gDebugger.DebuggerController;
|
||||
activeThread.addOneTimeListener("framesadded", function () {
|
||||
const sourceClient = event.detail;
|
||||
ok(sourceClient.isBlackBoxed, "The source should be black boxed now");
|
||||
|
||||
const frames = gDebugger.DebuggerView.StackFrames.widget._list;
|
||||
is(frames.querySelectorAll(".dbg-stackframe").length, 3,
|
||||
"Should only get 3 frames");
|
||||
is(frames.querySelectorAll(".dbg-stackframe-black-boxed").length, 1,
|
||||
"And one of them is the combined black boxed frames");
|
||||
|
||||
closeDebuggerAndFinish();
|
||||
});
|
||||
});
|
||||
|
||||
checkbox.click();
|
||||
}
|
||||
|
||||
function getBlackBoxCheckbox(url) {
|
||||
return gDebugger.document.querySelector(
|
||||
".side-menu-widget-item[tooltiptext=\""
|
||||
+ url + "\"] .side-menu-widget-item-checkbox");
|
||||
}
|
||||
|
||||
function once(target, event, callback) {
|
||||
target.addEventListener(event, function _listener(...args) {
|
||||
target.removeEventListener(event, _listener, false);
|
||||
callback.apply(null, args);
|
||||
}, false);
|
||||
}
|
||||
|
||||
registerCleanupFunction(function() {
|
||||
removeTab(gTab);
|
||||
gPane = null;
|
||||
gTab = null;
|
||||
gDebuggee = null;
|
||||
gDebugger = null;
|
||||
});
|
84
browser/devtools/debugger/test/browser_dbg_blackboxing-04.js
Normal file
84
browser/devtools/debugger/test/browser_dbg_blackboxing-04.js
Normal file
@ -0,0 +1,84 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Test that we get a stack frame for each black boxed source, not a single one
|
||||
* for all of them.
|
||||
*/
|
||||
|
||||
const TAB_URL = EXAMPLE_URL + "browser_dbg_blackboxing.html";
|
||||
|
||||
var gPane = null;
|
||||
var gTab = null;
|
||||
var gDebuggee = null;
|
||||
var gDebugger = null;
|
||||
|
||||
function test()
|
||||
{
|
||||
let scriptShown = false;
|
||||
let framesAdded = false;
|
||||
let resumed = false;
|
||||
let testStarted = false;
|
||||
|
||||
debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
|
||||
resumed = true;
|
||||
gTab = aTab;
|
||||
gDebuggee = aDebuggee;
|
||||
gPane = aPane;
|
||||
gDebugger = gPane.panelWin;
|
||||
|
||||
once(gDebugger, "Debugger:SourceShown", function () {
|
||||
blackBoxSources();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function blackBoxSources() {
|
||||
let timesFired = 0;
|
||||
gDebugger.addEventListener("Debugger:BlackBoxChange", function _onBlackboxChange() {
|
||||
if (++timesFired !== 3) {
|
||||
return;
|
||||
}
|
||||
gDebugger.removeEventListener("Debugger:BlackBoxChange", _onBlackboxChange, false);
|
||||
|
||||
const { activeThread } = gDebugger.DebuggerController;
|
||||
activeThread.addOneTimeListener("framesadded", testStackFrames);
|
||||
|
||||
gDebuggee.one();
|
||||
}, false);
|
||||
|
||||
getBlackBoxCheckbox(EXAMPLE_URL + "browser_dbg_blackboxing_one.js").click();
|
||||
getBlackBoxCheckbox(EXAMPLE_URL + "browser_dbg_blackboxing_two.js").click();
|
||||
getBlackBoxCheckbox(EXAMPLE_URL + "browser_dbg_blackboxing_three.js").click();
|
||||
}
|
||||
|
||||
function testStackFrames() {
|
||||
const frames = gDebugger.DebuggerView.StackFrames.widget._list;
|
||||
is(frames.querySelectorAll(".dbg-stackframe").length, 4,
|
||||
"Should get 4 frames (one -> two -> three -> doDebuggerStatement)");
|
||||
is(frames.querySelectorAll(".dbg-stackframe-black-boxed").length, 3,
|
||||
"And one, two, and three should each have their own black boxed frame.");
|
||||
|
||||
closeDebuggerAndFinish();
|
||||
}
|
||||
|
||||
function getBlackBoxCheckbox(url) {
|
||||
return gDebugger.document.querySelector(
|
||||
".side-menu-widget-item[tooltiptext=\""
|
||||
+ url + "\"] .side-menu-widget-item-checkbox");
|
||||
}
|
||||
|
||||
function once(target, event, callback) {
|
||||
target.addEventListener(event, function _listener(...args) {
|
||||
target.removeEventListener(event, _listener, false);
|
||||
callback.apply(null, args);
|
||||
}, false);
|
||||
}
|
||||
|
||||
registerCleanupFunction(function() {
|
||||
removeTab(gTab);
|
||||
gPane = null;
|
||||
gTab = null;
|
||||
gDebuggee = null;
|
||||
gDebugger = null;
|
||||
});
|
23
browser/devtools/debugger/test/browser_dbg_blackboxing.html
Normal file
23
browser/devtools/debugger/test/browser_dbg_blackboxing.html
Normal file
@ -0,0 +1,23 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset='utf-8'/>
|
||||
<title>Browser Debugger Blackbox Test</title>
|
||||
<!-- Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ -->
|
||||
<script type="text/javascript" src="browser_dbg_blackboxing_blackboxme.js"></script>
|
||||
<script type="text/javascript" src="browser_dbg_blackboxing_one.js"></script>
|
||||
<script type="text/javascript" src="browser_dbg_blackboxing_two.js"></script>
|
||||
<script type="text/javascript" src="browser_dbg_blackboxing_three.js"></script>
|
||||
<script>
|
||||
function runTest() {
|
||||
blackboxme(doDebuggerStatement);
|
||||
}
|
||||
function doDebuggerStatement() {
|
||||
debugger;
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,9 @@
|
||||
function blackboxme(fn) {
|
||||
(function one() {
|
||||
(function two() {
|
||||
(function three() {
|
||||
fn();
|
||||
}());
|
||||
}());
|
||||
}());
|
||||
}
|
@ -0,0 +1 @@
|
||||
function one() { two(); }
|
@ -0,0 +1 @@
|
||||
function three() { doDebuggerStatement(); }
|
@ -0,0 +1 @@
|
||||
function two() { three(); }
|
@ -25,21 +25,28 @@ this.EXPORTED_SYMBOLS = ["SideMenuWidget"];
|
||||
*
|
||||
* @param nsIDOMNode aNode
|
||||
* The element associated with the widget.
|
||||
* @param boolean aShowArrows
|
||||
* Specifies if items in this container should display horizontal arrows.
|
||||
* @param Object aOptions
|
||||
* - showArrows: Specifies if items in this container should display
|
||||
* horizontal arrows.
|
||||
* - showCheckboxes: Specifies if items in this container should display
|
||||
* checkboxes.
|
||||
*/
|
||||
this.SideMenuWidget = function SideMenuWidget(aNode, aShowArrows = true) {
|
||||
this.SideMenuWidget = function SideMenuWidget(aNode, aOptions={}) {
|
||||
this.document = aNode.ownerDocument;
|
||||
this.window = this.document.defaultView;
|
||||
this._parent = aNode;
|
||||
this._showArrows = aShowArrows;
|
||||
|
||||
let { showArrows, showCheckboxes } = aOptions;
|
||||
this._showArrows = showArrows || false;
|
||||
this._showCheckboxes = showCheckboxes || false;
|
||||
|
||||
// Create an internal scrollbox container.
|
||||
this._list = this.document.createElement("scrollbox");
|
||||
this._list.className = "side-menu-widget-container";
|
||||
this._list.setAttribute("flex", "1");
|
||||
this._list.setAttribute("orient", "vertical");
|
||||
this._list.setAttribute("with-arrow", aShowArrows);
|
||||
this._list.setAttribute("with-arrow", showArrows);
|
||||
this._list.setAttribute("with-checkboxes", showCheckboxes);
|
||||
this._list.setAttribute("tabindex", "0");
|
||||
this._list.addEventListener("keypress", e => this.emit("keyPress", e), false);
|
||||
this._list.addEventListener("mousedown", e => this.emit("mousePress", e), false);
|
||||
@ -91,10 +98,12 @@ SideMenuWidget.prototype = {
|
||||
* A tooltip attribute for the displayed item.
|
||||
* @param string aGroup [optional]
|
||||
* The group to place the displayed item into.
|
||||
* @param Object aAttachment [optional]
|
||||
* Extra data for the user.
|
||||
* @return nsIDOMNode
|
||||
* The element associated with the displayed item.
|
||||
*/
|
||||
insertItemAt: function(aIndex, aContents, aTooltip = "", aGroup = "") {
|
||||
insertItemAt: function(aIndex, aContents, aTooltip = "", aGroup = "", aAttachment={}) {
|
||||
aTooltip = NetworkHelper.convertToUnicode(unescape(aTooltip));
|
||||
aGroup = NetworkHelper.convertToUnicode(unescape(aGroup));
|
||||
|
||||
@ -115,7 +124,7 @@ SideMenuWidget.prototype = {
|
||||
(this._list.scrollTop + this._list.clientHeight >= this._list.scrollHeight);
|
||||
|
||||
let group = this._getMenuGroupForName(aGroup);
|
||||
let item = this._getMenuItemForGroup(group, aContents, aTooltip);
|
||||
let item = this._getMenuItemForGroup(group, aContents, aTooltip, aAttachment);
|
||||
let element = item.insertSelfAt(aIndex);
|
||||
|
||||
if (this.maintainSelectionVisible) {
|
||||
@ -397,14 +406,17 @@ SideMenuWidget.prototype = {
|
||||
* The string or node displayed in the container.
|
||||
* @param string aTooltip [optional]
|
||||
* A tooltip attribute for the displayed item.
|
||||
* @param object aAttachment [optional]
|
||||
* The attachement object.
|
||||
*/
|
||||
_getMenuItemForGroup: function(aGroup, aContents, aTooltip) {
|
||||
return new SideMenuItem(aGroup, aContents, aTooltip, this._showArrows);
|
||||
_getMenuItemForGroup: function(aGroup, aContents, aTooltip, aAttachment) {
|
||||
return new SideMenuItem(aGroup, aContents, aTooltip, this._showArrows, this._showCheckboxes, aAttachment);
|
||||
},
|
||||
|
||||
window: null,
|
||||
document: null,
|
||||
_showArrows: false,
|
||||
_showCheckboxes: false,
|
||||
_parent: null,
|
||||
_list: null,
|
||||
_boxObject: null,
|
||||
@ -527,14 +539,30 @@ SideMenuGroup.prototype = {
|
||||
* The string or node displayed in the container.
|
||||
* @param boolean aArrowFlag
|
||||
* True if a horizontal arrow should be shown.
|
||||
* @param boolean aCheckboxFlag
|
||||
* True if a checkbox should be shown.
|
||||
* @param object aAttachment [optional]
|
||||
* The attachment object.
|
||||
*/
|
||||
function SideMenuItem(aGroup, aContents, aTooltip, aArrowFlag) {
|
||||
function SideMenuItem(aGroup, aContents, aTooltip, aArrowFlag, aCheckboxFlag, aAttachment={}) {
|
||||
this.document = aGroup.document;
|
||||
this.window = aGroup.window;
|
||||
this.ownerView = aGroup;
|
||||
|
||||
// Show a horizontal arrow towards the content.
|
||||
if (aArrowFlag) {
|
||||
let makeCheckbox = () => {
|
||||
let checkbox = this.document.createElement("checkbox");
|
||||
checkbox.className = "side-menu-widget-item-checkbox";
|
||||
checkbox.setAttribute("checked", aAttachment.checkboxState);
|
||||
checkbox.setAttribute("tooltiptext", aAttachment.checkboxTooltip);
|
||||
checkbox.addEventListener("command", function () {
|
||||
ViewHelpers.dispatchEvent(checkbox, "check", {
|
||||
checked: checkbox.checked,
|
||||
});
|
||||
}, false);
|
||||
return checkbox;
|
||||
};
|
||||
|
||||
if (aArrowFlag || aCheckboxFlag) {
|
||||
let container = this._container = this.document.createElement("hbox");
|
||||
container.className = "side-menu-widget-item";
|
||||
container.setAttribute("tooltiptext", aTooltip);
|
||||
@ -542,13 +570,22 @@ function SideMenuItem(aGroup, aContents, aTooltip, aArrowFlag) {
|
||||
let target = this._target = this.document.createElement("vbox");
|
||||
target.className = "side-menu-widget-item-contents";
|
||||
|
||||
let arrow = this._arrow = this.document.createElement("hbox");
|
||||
arrow.className = "side-menu-widget-item-arrow";
|
||||
// Show a checkbox before the content.
|
||||
if (aCheckboxFlag) {
|
||||
let checkbox = this._checkbox = makeCheckbox();
|
||||
container.appendChild(checkbox);
|
||||
}
|
||||
|
||||
container.appendChild(target);
|
||||
container.appendChild(arrow);
|
||||
|
||||
// Show a horizontal arrow towards the content.
|
||||
if (aArrowFlag) {
|
||||
let arrow = this._arrow = this.document.createElement("hbox");
|
||||
arrow.className = "side-menu-widget-item-arrow";
|
||||
container.appendChild(arrow);
|
||||
}
|
||||
}
|
||||
// Skip a few redundant nodes when no horizontal arrow is shown.
|
||||
// Skip a few redundant nodes when no horizontal arrow or checkbox is shown.
|
||||
else {
|
||||
let target = this._target = this._container = this.document.createElement("hbox");
|
||||
target.className = "side-menu-widget-item side-menu-widget-item-contents";
|
||||
|
@ -11,6 +11,7 @@ const Cu = Components.utils;
|
||||
|
||||
const PANE_APPEARANCE_DELAY = 50;
|
||||
const PAGE_SIZE_ITEM_COUNT_RATIO = 5;
|
||||
const WIDGET_FOCUSABLE_NODES = new Set(["vbox", "hbox"]);
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
@ -609,7 +610,7 @@ this.WidgetMethods = {
|
||||
* - relaxed: true if this container should allow dupes & degenerates
|
||||
* - attachment: some attached primitive/object for the item
|
||||
* - attributes: a batch of attributes set to the displayed element
|
||||
* - finalize: function invoked when the item is removed
|
||||
* - finalize: function invokde when the item is removed
|
||||
* @return Item
|
||||
* The item associated with the displayed element if an unstaged push,
|
||||
* undefined if the item was staged for a later commit.
|
||||
@ -1117,16 +1118,21 @@ this.WidgetMethods = {
|
||||
_focusChange: function(aDirection) {
|
||||
let commandDispatcher = this._commandDispatcher;
|
||||
let prevFocusedElement = commandDispatcher.focusedElement;
|
||||
let currFocusedElement;
|
||||
|
||||
commandDispatcher.suppressFocusScroll = true;
|
||||
commandDispatcher[aDirection]();
|
||||
do {
|
||||
commandDispatcher.suppressFocusScroll = true;
|
||||
commandDispatcher[aDirection]();
|
||||
currFocusedElement = commandDispatcher.focusedElement;
|
||||
|
||||
// Make sure the newly focused item is a part of this container. If the
|
||||
// focus goes out of bounds, revert the previously focused item.
|
||||
if (!this.getItemForElement(currFocusedElement)) {
|
||||
prevFocusedElement.focus();
|
||||
return false;
|
||||
}
|
||||
} while (!WIDGET_FOCUSABLE_NODES.has(currFocusedElement.tagName));
|
||||
|
||||
// Make sure the newly focused item is a part of this container.
|
||||
// If the focus goes out of bounds, revert the previously focused item.
|
||||
if (!this.getItemForElement(commandDispatcher.focusedElement)) {
|
||||
prevFocusedElement.focus();
|
||||
return false;
|
||||
}
|
||||
// Focus remained within bounds.
|
||||
return true;
|
||||
},
|
||||
@ -1208,7 +1214,10 @@ this.WidgetMethods = {
|
||||
*/
|
||||
getItemForElement: function(aElement) {
|
||||
while (aElement) {
|
||||
let item = this._itemsByElement.get(aElement);
|
||||
let item =
|
||||
this._itemsByElement.get(aElement) ||
|
||||
this._itemsByElement.get(aElement.nextElementSibling) ||
|
||||
this._itemsByElement.get(aElement.previousElementSibling);
|
||||
if (item) {
|
||||
return item;
|
||||
}
|
||||
|
@ -73,6 +73,11 @@ noMatchingSourcesText=No matching sources.
|
||||
# global search results when there are no matching strings after filtering.
|
||||
noMatchingStringsText=No matches found
|
||||
|
||||
# LOCALIZATION NOTE (blackBoxCheckboxTooltip) = The tooltip text to display when
|
||||
# the user hovers over the checkbox used to toggle black boxing its associated
|
||||
# source.
|
||||
blackBoxCheckboxTooltip=Toggle black boxing
|
||||
|
||||
# LOCALIZATION NOTE (emptyFilterText): This is the text that appears in the
|
||||
# filter text box when it is empty and the scripts container is selected.
|
||||
emptyFilterText=Filter scripts (%S)
|
||||
|
@ -17,6 +17,27 @@
|
||||
-moz-border-start-color: transparent;
|
||||
}
|
||||
|
||||
.side-menu-widget-item-checkbox {
|
||||
-moz-appearance: none;
|
||||
padding: 0;
|
||||
margin: 0 -4px 0 4px;
|
||||
}
|
||||
|
||||
.side-menu-widget-item-checkbox > .checkbox-check {
|
||||
-moz-appearance: none;
|
||||
background: none;
|
||||
background-image: url(itemToggle.png);
|
||||
background-repeat: no-repeat;
|
||||
background-clip: content-box;
|
||||
background-position: -24px 0;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
.side-menu-widget-item-checkbox[checked] > .checkbox-check {
|
||||
background-position: 0 0;
|
||||
}
|
||||
|
||||
/* ListWidget items */
|
||||
|
||||
.list-widget-item {
|
||||
|
@ -19,6 +19,27 @@
|
||||
-moz-border-start-color: transparent;
|
||||
}
|
||||
|
||||
.side-menu-widget-item-checkbox {
|
||||
-moz-appearance: none;
|
||||
padding: 0;
|
||||
margin: 0 -4px 0 4px;
|
||||
}
|
||||
|
||||
.side-menu-widget-item-checkbox > .checkbox-check {
|
||||
-moz-appearance: none;
|
||||
background: none;
|
||||
background-image: url(itemToggle.png);
|
||||
background-repeat: no-repeat;
|
||||
background-clip: content-box;
|
||||
background-position: -24px 0;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
.side-menu-widget-item-checkbox[checked] > .checkbox-check {
|
||||
background-position: 0 0;
|
||||
}
|
||||
|
||||
/* ListWidget items */
|
||||
|
||||
.list-widget-item {
|
||||
|
@ -17,6 +17,27 @@
|
||||
-moz-border-start-color: transparent;
|
||||
}
|
||||
|
||||
.side-menu-widget-item-checkbox {
|
||||
-moz-appearance: none;
|
||||
padding: 0;
|
||||
margin: 0 -4px 0 4px;
|
||||
}
|
||||
|
||||
.side-menu-widget-item-checkbox > .checkbox-check {
|
||||
-moz-appearance: none;
|
||||
background: none;
|
||||
background-image: url(itemToggle.png);
|
||||
background-repeat: no-repeat;
|
||||
background-clip: content-box;
|
||||
background-position: -24px 0;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
.side-menu-widget-item-checkbox[checked] > .checkbox-check {
|
||||
background-position: 0 0;
|
||||
}
|
||||
|
||||
/* ListWidget items */
|
||||
|
||||
.list-widget-item {
|
||||
|
Loading…
Reference in New Issue
Block a user