Bug 877686 - Add UI to toggle the blackboxing of specific sources; r=vporof
This commit is contained in:
@@ -423,6 +423,7 @@ function StackFrames() {
|
|||||||
this._onResumed = this._onResumed.bind(this);
|
this._onResumed = this._onResumed.bind(this);
|
||||||
this._onFrames = this._onFrames.bind(this);
|
this._onFrames = this._onFrames.bind(this);
|
||||||
this._onFramesCleared = this._onFramesCleared.bind(this);
|
this._onFramesCleared = this._onFramesCleared.bind(this);
|
||||||
|
this._onBlackBoxChange = this._onBlackBoxChange.bind(this);
|
||||||
this._afterFramesCleared = this._afterFramesCleared.bind(this);
|
this._afterFramesCleared = this._afterFramesCleared.bind(this);
|
||||||
this.evaluate = this.evaluate.bind(this);
|
this.evaluate = this.evaluate.bind(this);
|
||||||
}
|
}
|
||||||
@@ -447,6 +448,7 @@ StackFrames.prototype = {
|
|||||||
this.activeThread.addListener("resumed", this._onResumed);
|
this.activeThread.addListener("resumed", this._onResumed);
|
||||||
this.activeThread.addListener("framesadded", this._onFrames);
|
this.activeThread.addListener("framesadded", this._onFrames);
|
||||||
this.activeThread.addListener("framescleared", this._onFramesCleared);
|
this.activeThread.addListener("framescleared", this._onFramesCleared);
|
||||||
|
window.addEventListener("Debugger:BlackBoxChange", this._onBlackBoxChange, false);
|
||||||
this._handleTabNavigation();
|
this._handleTabNavigation();
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -462,6 +464,7 @@ StackFrames.prototype = {
|
|||||||
this.activeThread.removeListener("resumed", this._onResumed);
|
this.activeThread.removeListener("resumed", this._onResumed);
|
||||||
this.activeThread.removeListener("framesadded", this._onFrames);
|
this.activeThread.removeListener("framesadded", this._onFrames);
|
||||||
this.activeThread.removeListener("framescleared", this._onFramesCleared);
|
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.
|
// Make sure all the previous stackframes are removed before re-adding them.
|
||||||
DebuggerView.StackFrames.empty();
|
DebuggerView.StackFrames.empty();
|
||||||
|
|
||||||
|
let previousBlackBoxed = null;
|
||||||
for (let frame of this.activeThread.cachedFrames) {
|
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 frameLocation = NetworkHelper.convertToUnicode(unescape(url));
|
||||||
let frameTitle = StackFrameUtils.getFrameTitle(frame);
|
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) {
|
if (this.currentFrame == null) {
|
||||||
DebuggerView.StackFrames.selectedDepth = 0;
|
DebuggerView.StackFrames.selectedDepth = 0;
|
||||||
@@ -626,6 +639,18 @@ StackFrames.prototype = {
|
|||||||
window.setTimeout(this._afterFramesCleared, FRAME_STEP_CLEAR_DELAY);
|
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.
|
* Called soon after the thread client's framescleared notification.
|
||||||
*/
|
*/
|
||||||
@@ -1000,6 +1025,27 @@ SourceScripts.prototype = {
|
|||||||
window.dispatchEvent(document, "Debugger:AfterSourcesAdded");
|
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.
|
* Gets a specified source's text.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ function SourcesView() {
|
|||||||
this._onSourceSelect = this._onSourceSelect.bind(this);
|
this._onSourceSelect = this._onSourceSelect.bind(this);
|
||||||
this._onSourceClick = this._onSourceClick.bind(this);
|
this._onSourceClick = this._onSourceClick.bind(this);
|
||||||
this._onBreakpointRemoved = this._onBreakpointRemoved.bind(this);
|
this._onBreakpointRemoved = this._onBreakpointRemoved.bind(this);
|
||||||
|
this._onSourceCheck = this._onSourceCheck.bind(this);
|
||||||
this._onBreakpointClick = this._onBreakpointClick.bind(this);
|
this._onBreakpointClick = this._onBreakpointClick.bind(this);
|
||||||
this._onBreakpointCheckboxClick = this._onBreakpointCheckboxClick.bind(this);
|
this._onBreakpointCheckboxClick = this._onBreakpointCheckboxClick.bind(this);
|
||||||
this._onConditionalPopupShowing = this._onConditionalPopupShowing.bind(this);
|
this._onConditionalPopupShowing = this._onConditionalPopupShowing.bind(this);
|
||||||
@@ -34,9 +35,12 @@ SourcesView.prototype = Heritage.extend(WidgetMethods, {
|
|||||||
initialize: function() {
|
initialize: function() {
|
||||||
dumpn("Initializing the SourcesView");
|
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.emptyText = L10N.getStr("noSourcesText");
|
||||||
this.unavailableText = L10N.getStr("noMatchingSourcesText");
|
this.unavailableText = L10N.getStr("noMatchingSourcesText");
|
||||||
|
this._blackBoxCheckboxTooltip = L10N.getStr("blackBoxCheckboxTooltip");
|
||||||
|
|
||||||
this._commandset = document.getElementById("debuggerCommands");
|
this._commandset = document.getElementById("debuggerCommands");
|
||||||
this._popupset = document.getElementById("debuggerPopupset");
|
this._popupset = document.getElementById("debuggerPopupset");
|
||||||
@@ -48,6 +52,7 @@ SourcesView.prototype = Heritage.extend(WidgetMethods, {
|
|||||||
window.addEventListener("Debugger:EditorUnloaded", this._onEditorUnload, false);
|
window.addEventListener("Debugger:EditorUnloaded", this._onEditorUnload, false);
|
||||||
this.widget.addEventListener("select", this._onSourceSelect, false);
|
this.widget.addEventListener("select", this._onSourceSelect, false);
|
||||||
this.widget.addEventListener("click", this._onSourceClick, 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("popupshowing", this._onConditionalPopupShowing, false);
|
||||||
this._cbPanel.addEventListener("popupshown", this._onConditionalPopupShown, false);
|
this._cbPanel.addEventListener("popupshown", this._onConditionalPopupShown, false);
|
||||||
this._cbPanel.addEventListener("popuphiding", this._onConditionalPopupHiding, false);
|
this._cbPanel.addEventListener("popuphiding", this._onConditionalPopupHiding, false);
|
||||||
@@ -70,6 +75,7 @@ SourcesView.prototype = Heritage.extend(WidgetMethods, {
|
|||||||
window.removeEventListener("Debugger:EditorUnloaded", this._onEditorUnload, false);
|
window.removeEventListener("Debugger:EditorUnloaded", this._onEditorUnload, false);
|
||||||
this.widget.removeEventListener("select", this._onSourceSelect, false);
|
this.widget.removeEventListener("select", this._onSourceSelect, false);
|
||||||
this.widget.removeEventListener("click", this._onSourceClick, 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._onConditionalPopupShowing, false);
|
||||||
this._cbPanel.removeEventListener("popupshowing", this._onConditionalPopupShown, false);
|
this._cbPanel.removeEventListener("popupshowing", this._onConditionalPopupShown, false);
|
||||||
this._cbPanel.removeEventListener("popuphiding", this._onConditionalPopupHiding, false);
|
this._cbPanel.removeEventListener("popuphiding", this._onConditionalPopupHiding, false);
|
||||||
@@ -109,6 +115,8 @@ SourcesView.prototype = Heritage.extend(WidgetMethods, {
|
|||||||
this.push([label, url, group], {
|
this.push([label, url, group], {
|
||||||
staged: aOptions.staged, /* stage the item to be appended later? */
|
staged: aOptions.staged, /* stage the item to be appended later? */
|
||||||
attachment: {
|
attachment: {
|
||||||
|
checkboxState: !aSource.isBlackBoxed,
|
||||||
|
checkboxTooltip: this._blackBoxCheckboxTooltip,
|
||||||
source: aSource
|
source: aSource
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -639,6 +647,14 @@ SourcesView.prototype = Heritage.extend(WidgetMethods, {
|
|||||||
DebuggerView.Filtering.target = this;
|
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.
|
* 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.
|
* The line number to be displayed in the list.
|
||||||
* @param number aDepth
|
* @param number aDepth
|
||||||
* The frame depth specified by the debugger.
|
* 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.
|
// Create the element node and menu entry for the stack frame item.
|
||||||
let frameView = this._createFrameView.apply(this, arguments);
|
let frameView = this._createFrameView.apply(this, arguments);
|
||||||
let menuEntry = this._createMenuEntry.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.
|
* The line number to be displayed in the list.
|
||||||
* @param number aDepth
|
* @param number aDepth
|
||||||
* The frame depth specified by the debugger.
|
* The frame depth specified by the debugger.
|
||||||
|
* @param boolean aIsBlackBoxed
|
||||||
|
* Whether or not the frame is black boxed.
|
||||||
* @return nsIDOMNode
|
* @return nsIDOMNode
|
||||||
* The stack frame view.
|
* The stack frame view.
|
||||||
*/
|
*/
|
||||||
_createFrameView: function(aFrameTitle, aSourceLocation, aLineNumber, aDepth) {
|
_createFrameView: function(aFrameTitle, aSourceLocation, aLineNumber, aDepth, aIsBlackBoxed) {
|
||||||
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);
|
|
||||||
|
|
||||||
let container = document.createElement("hbox");
|
let container = document.createElement("hbox");
|
||||||
container.id = "stackframe-" + aDepth;
|
container.id = "stackframe-" + aDepth;
|
||||||
container.className = "dbg-stackframe";
|
container.className = "dbg-stackframe";
|
||||||
|
|
||||||
|
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);
|
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);
|
container.appendChild(frameDetailsNode);
|
||||||
|
|
||||||
return container;
|
return container;
|
||||||
@@ -510,10 +518,12 @@ StackFramesView.prototype = Heritage.extend(WidgetMethods, {
|
|||||||
* The line number to be displayed in the list.
|
* The line number to be displayed in the list.
|
||||||
* @param number aDepth
|
* @param number aDepth
|
||||||
* The frame depth specified by the debugger.
|
* The frame depth specified by the debugger.
|
||||||
|
* @param boolean aIsBlackBoxed
|
||||||
|
* Whether or not the frame is black boxed.
|
||||||
* @return object
|
* @return object
|
||||||
* An object containing the stack frame command and menu item.
|
* 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 =
|
let frameDescription =
|
||||||
SourceUtils.trimUrlLength(
|
SourceUtils.trimUrlLength(
|
||||||
SourceUtils.getSourceLabel(aSourceLocation),
|
SourceUtils.getSourceLabel(aSourceLocation),
|
||||||
|
|||||||
@@ -12,6 +12,10 @@ include $(DEPTH)/config/autoconf.mk
|
|||||||
|
|
||||||
MOCHITEST_BROWSER_TESTS = \
|
MOCHITEST_BROWSER_TESTS = \
|
||||||
browser_dbg_aaa_run_first_leaktest.js \
|
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_clean-exit.js \
|
||||||
browser_dbg_cmd.js \
|
browser_dbg_cmd.js \
|
||||||
browser_dbg_cmd_break.js \
|
browser_dbg_cmd_break.js \
|
||||||
@@ -112,6 +116,11 @@ MOCHITEST_BROWSER_TESTS = \
|
|||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
MOCHITEST_BROWSER_PAGES = \
|
MOCHITEST_BROWSER_PAGES = \
|
||||||
|
browser_dbg_blackboxing.html \
|
||||||
|
blackboxing_blackboxme.js \
|
||||||
|
blackboxing_one.js \
|
||||||
|
blackboxing_two.js \
|
||||||
|
blackboxing_three.js \
|
||||||
browser_dbg_cmd_break.html \
|
browser_dbg_cmd_break.html \
|
||||||
browser_dbg_cmd.html \
|
browser_dbg_cmd.html \
|
||||||
testactors.js \
|
testactors.js \
|
||||||
|
|||||||
9
browser/devtools/debugger/test/blackboxing_blackboxme.js
Normal file
9
browser/devtools/debugger/test/blackboxing_blackboxme.js
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
function blackboxme(fn) {
|
||||||
|
(function one() {
|
||||||
|
(function two() {
|
||||||
|
(function three() {
|
||||||
|
fn();
|
||||||
|
}());
|
||||||
|
}());
|
||||||
|
}());
|
||||||
|
}
|
||||||
1
browser/devtools/debugger/test/blackboxing_one.js
Normal file
1
browser/devtools/debugger/test/blackboxing_one.js
Normal file
@@ -0,0 +1 @@
|
|||||||
|
function one() { two(); }
|
||||||
1
browser/devtools/debugger/test/blackboxing_three.js
Normal file
1
browser/devtools/debugger/test/blackboxing_three.js
Normal file
@@ -0,0 +1 @@
|
|||||||
|
function three() { doDebuggerStatement(); }
|
||||||
1
browser/devtools/debugger/test/blackboxing_two.js
Normal file
1
browser/devtools/debugger/test/blackboxing_two.js
Normal file
@@ -0,0 +1 @@
|
|||||||
|
function two() { three(); }
|
||||||
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 + "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 + "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 + "blackboxing_one.js").click();
|
||||||
|
getBlackBoxCheckbox(EXAMPLE_URL + "blackboxing_two.js").click();
|
||||||
|
getBlackBoxCheckbox(EXAMPLE_URL + "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="blackboxing_blackboxme.js"></script>
|
||||||
|
<script type="text/javascript" src="blackboxing_one.js"></script>
|
||||||
|
<script type="text/javascript" src="blackboxing_two.js"></script>
|
||||||
|
<script type="text/javascript" src="blackboxing_three.js"></script>
|
||||||
|
<script>
|
||||||
|
function runTest() {
|
||||||
|
blackboxme(doDebuggerStatement);
|
||||||
|
}
|
||||||
|
function doDebuggerStatement() {
|
||||||
|
debugger;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -25,21 +25,28 @@ this.EXPORTED_SYMBOLS = ["SideMenuWidget"];
|
|||||||
*
|
*
|
||||||
* @param nsIDOMNode aNode
|
* @param nsIDOMNode aNode
|
||||||
* The element associated with the widget.
|
* The element associated with the widget.
|
||||||
* @param boolean aShowArrows
|
* @param Object aOptions
|
||||||
* Specifies if items in this container should display horizontal arrows.
|
* - 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.document = aNode.ownerDocument;
|
||||||
this.window = this.document.defaultView;
|
this.window = this.document.defaultView;
|
||||||
this._parent = aNode;
|
this._parent = aNode;
|
||||||
this._showArrows = aShowArrows;
|
|
||||||
|
let { showArrows, showCheckboxes } = aOptions;
|
||||||
|
this._showArrows = showArrows || false;
|
||||||
|
this._showCheckboxes = showCheckboxes || false;
|
||||||
|
|
||||||
// Create an internal scrollbox container.
|
// Create an internal scrollbox container.
|
||||||
this._list = this.document.createElement("scrollbox");
|
this._list = this.document.createElement("scrollbox");
|
||||||
this._list.className = "side-menu-widget-container";
|
this._list.className = "side-menu-widget-container";
|
||||||
this._list.setAttribute("flex", "1");
|
this._list.setAttribute("flex", "1");
|
||||||
this._list.setAttribute("orient", "vertical");
|
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.setAttribute("tabindex", "0");
|
||||||
this._list.addEventListener("keypress", e => this.emit("keyPress", e), false);
|
this._list.addEventListener("keypress", e => this.emit("keyPress", e), false);
|
||||||
this._list.addEventListener("mousedown", e => this.emit("mousePress", 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.
|
* A tooltip attribute for the displayed item.
|
||||||
* @param string aGroup [optional]
|
* @param string aGroup [optional]
|
||||||
* The group to place the displayed item into.
|
* The group to place the displayed item into.
|
||||||
|
* @param Object aAttachment [optional]
|
||||||
|
* Extra data for the user.
|
||||||
* @return nsIDOMNode
|
* @return nsIDOMNode
|
||||||
* The element associated with the displayed item.
|
* 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));
|
aTooltip = NetworkHelper.convertToUnicode(unescape(aTooltip));
|
||||||
aGroup = NetworkHelper.convertToUnicode(unescape(aGroup));
|
aGroup = NetworkHelper.convertToUnicode(unescape(aGroup));
|
||||||
|
|
||||||
@@ -115,7 +124,7 @@ SideMenuWidget.prototype = {
|
|||||||
(this._list.scrollTop + this._list.clientHeight >= this._list.scrollHeight);
|
(this._list.scrollTop + this._list.clientHeight >= this._list.scrollHeight);
|
||||||
|
|
||||||
let group = this._getMenuGroupForName(aGroup);
|
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);
|
let element = item.insertSelfAt(aIndex);
|
||||||
|
|
||||||
if (this.maintainSelectionVisible) {
|
if (this.maintainSelectionVisible) {
|
||||||
@@ -397,14 +406,17 @@ SideMenuWidget.prototype = {
|
|||||||
* The string or node displayed in the container.
|
* The string or node displayed in the container.
|
||||||
* @param string aTooltip [optional]
|
* @param string aTooltip [optional]
|
||||||
* A tooltip attribute for the displayed item.
|
* A tooltip attribute for the displayed item.
|
||||||
|
* @param object aAttachment [optional]
|
||||||
|
* The attachement object.
|
||||||
*/
|
*/
|
||||||
_getMenuItemForGroup: function(aGroup, aContents, aTooltip) {
|
_getMenuItemForGroup: function(aGroup, aContents, aTooltip, aAttachment) {
|
||||||
return new SideMenuItem(aGroup, aContents, aTooltip, this._showArrows);
|
return new SideMenuItem(aGroup, aContents, aTooltip, this._showArrows, this._showCheckboxes, aAttachment);
|
||||||
},
|
},
|
||||||
|
|
||||||
window: null,
|
window: null,
|
||||||
document: null,
|
document: null,
|
||||||
_showArrows: false,
|
_showArrows: false,
|
||||||
|
_showCheckboxes: false,
|
||||||
_parent: null,
|
_parent: null,
|
||||||
_list: null,
|
_list: null,
|
||||||
_boxObject: null,
|
_boxObject: null,
|
||||||
@@ -527,14 +539,30 @@ SideMenuGroup.prototype = {
|
|||||||
* The string or node displayed in the container.
|
* The string or node displayed in the container.
|
||||||
* @param boolean aArrowFlag
|
* @param boolean aArrowFlag
|
||||||
* True if a horizontal arrow should be shown.
|
* 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.document = aGroup.document;
|
||||||
this.window = aGroup.window;
|
this.window = aGroup.window;
|
||||||
this.ownerView = aGroup;
|
this.ownerView = aGroup;
|
||||||
|
|
||||||
// Show a horizontal arrow towards the content.
|
let makeCheckbox = () => {
|
||||||
if (aArrowFlag) {
|
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");
|
let container = this._container = this.document.createElement("hbox");
|
||||||
container.className = "side-menu-widget-item";
|
container.className = "side-menu-widget-item";
|
||||||
container.setAttribute("tooltiptext", aTooltip);
|
container.setAttribute("tooltiptext", aTooltip);
|
||||||
@@ -542,13 +570,22 @@ function SideMenuItem(aGroup, aContents, aTooltip, aArrowFlag) {
|
|||||||
let target = this._target = this.document.createElement("vbox");
|
let target = this._target = this.document.createElement("vbox");
|
||||||
target.className = "side-menu-widget-item-contents";
|
target.className = "side-menu-widget-item-contents";
|
||||||
|
|
||||||
let arrow = this._arrow = this.document.createElement("hbox");
|
// Show a checkbox before the content.
|
||||||
arrow.className = "side-menu-widget-item-arrow";
|
if (aCheckboxFlag) {
|
||||||
|
let checkbox = this._checkbox = makeCheckbox();
|
||||||
|
container.appendChild(checkbox);
|
||||||
|
}
|
||||||
|
|
||||||
container.appendChild(target);
|
container.appendChild(target);
|
||||||
|
|
||||||
|
// 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);
|
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 {
|
else {
|
||||||
let target = this._target = this._container = this.document.createElement("hbox");
|
let target = this._target = this._container = this.document.createElement("hbox");
|
||||||
target.className = "side-menu-widget-item side-menu-widget-item-contents";
|
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 PANE_APPEARANCE_DELAY = 50;
|
||||||
const PAGE_SIZE_ITEM_COUNT_RATIO = 5;
|
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/Services.jsm");
|
||||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||||
@@ -609,7 +610,7 @@ this.WidgetMethods = {
|
|||||||
* - relaxed: true if this container should allow dupes & degenerates
|
* - relaxed: true if this container should allow dupes & degenerates
|
||||||
* - attachment: some attached primitive/object for the item
|
* - attachment: some attached primitive/object for the item
|
||||||
* - attributes: a batch of attributes set to the displayed element
|
* - 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
|
* @return Item
|
||||||
* The item associated with the displayed element if an unstaged push,
|
* The item associated with the displayed element if an unstaged push,
|
||||||
* undefined if the item was staged for a later commit.
|
* undefined if the item was staged for a later commit.
|
||||||
@@ -1117,16 +1118,21 @@ this.WidgetMethods = {
|
|||||||
_focusChange: function(aDirection) {
|
_focusChange: function(aDirection) {
|
||||||
let commandDispatcher = this._commandDispatcher;
|
let commandDispatcher = this._commandDispatcher;
|
||||||
let prevFocusedElement = commandDispatcher.focusedElement;
|
let prevFocusedElement = commandDispatcher.focusedElement;
|
||||||
|
let currFocusedElement;
|
||||||
|
|
||||||
|
do {
|
||||||
commandDispatcher.suppressFocusScroll = true;
|
commandDispatcher.suppressFocusScroll = true;
|
||||||
commandDispatcher[aDirection]();
|
commandDispatcher[aDirection]();
|
||||||
|
currFocusedElement = commandDispatcher.focusedElement;
|
||||||
|
|
||||||
// Make sure the newly focused item is a part of this container.
|
// Make sure the newly focused item is a part of this container. If the
|
||||||
// If the focus goes out of bounds, revert the previously focused item.
|
// focus goes out of bounds, revert the previously focused item.
|
||||||
if (!this.getItemForElement(commandDispatcher.focusedElement)) {
|
if (!this.getItemForElement(currFocusedElement)) {
|
||||||
prevFocusedElement.focus();
|
prevFocusedElement.focus();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
} while (!WIDGET_FOCUSABLE_NODES.has(currFocusedElement.tagName));
|
||||||
|
|
||||||
// Focus remained within bounds.
|
// Focus remained within bounds.
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
@@ -1208,7 +1214,10 @@ this.WidgetMethods = {
|
|||||||
*/
|
*/
|
||||||
getItemForElement: function(aElement) {
|
getItemForElement: function(aElement) {
|
||||||
while (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) {
|
if (item) {
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,6 +65,11 @@ noMatchingGlobalsText=No matching globals
|
|||||||
# when there are no scripts.
|
# when there are no scripts.
|
||||||
noSourcesText=This page has no sources.
|
noSourcesText=This page has no sources.
|
||||||
|
|
||||||
|
# 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 (noMatchingSourcesText): The text to display in the
|
# LOCALIZATION NOTE (noMatchingSourcesText): The text to display in the
|
||||||
# sources menu when there are no matching scripts after filtering.
|
# sources menu when there are no matching scripts after filtering.
|
||||||
noMatchingSourcesText=No matching sources.
|
noMatchingSourcesText=No matching sources.
|
||||||
|
|||||||
@@ -17,6 +17,27 @@
|
|||||||
-moz-border-start-color: transparent;
|
-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 */
|
/* ListWidget items */
|
||||||
|
|
||||||
.list-widget-item {
|
.list-widget-item {
|
||||||
|
|||||||
@@ -19,6 +19,27 @@
|
|||||||
-moz-border-start-color: transparent;
|
-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 */
|
/* ListWidget items */
|
||||||
|
|
||||||
.list-widget-item {
|
.list-widget-item {
|
||||||
|
|||||||
@@ -17,6 +17,27 @@
|
|||||||
-moz-border-start-color: transparent;
|
-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 */
|
/* ListWidget items */
|
||||||
|
|
||||||
.list-widget-item {
|
.list-widget-item {
|
||||||
|
|||||||
Reference in New Issue
Block a user