зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1354679 - Automatically display the PausedDebuggerOverlay when the debugger is paused. r=gl
Differential Revision: https://phabricator.services.mozilla.com/D35162 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
20ee1b2284
Коммит
5970b1a8fe
|
@ -69,6 +69,7 @@ if (isDevelopment()) {
|
|||
pref("devtools.debugger.features.event-listeners-breakpoints", true);
|
||||
pref("devtools.debugger.features.log-points", true);
|
||||
pref("devtools.debugger.log-actions", true);
|
||||
pref("devtools.debugger.features.overlay-step-buttons", false);
|
||||
}
|
||||
|
||||
export const prefs = new PrefsHelper("devtools", {
|
||||
|
@ -128,6 +129,7 @@ export const features = new PrefsHelper("devtools.debugger.features", {
|
|||
originalBlackbox: ["Bool", "original-blackbox"],
|
||||
eventListenersBreakpoints: ["Bool", "event-listeners-breakpoints"],
|
||||
logPoints: ["Bool", "log-points"],
|
||||
showOverlayStepButtons: ["Bool", "debugger.features.overlay-step-buttons"],
|
||||
});
|
||||
|
||||
export const asyncStore = asyncStoreHelper("debugger", {
|
||||
|
|
|
@ -583,6 +583,9 @@ Toolbox.prototype = {
|
|||
ignoreCaughtExceptions: Services.prefs.getBoolPref(
|
||||
"devtools.debugger.ignore-caught-exceptions"
|
||||
),
|
||||
showOverlayStepButtons: Services.prefs.getBoolPref(
|
||||
"devtools.debugger.features.overlay-step-buttons"
|
||||
),
|
||||
};
|
||||
const [, threadClient] = await this._target.attachThread(threadOptions);
|
||||
|
||||
|
|
|
@ -76,3 +76,4 @@ pref("devtools.debugger.features.original-blackbox", true);
|
|||
pref("devtools.debugger.features.windowless-workers", true);
|
||||
pref("devtools.debugger.features.event-listeners-breakpoints", true);
|
||||
pref("devtools.debugger.features.log-points", true);
|
||||
pref("devtools.debugger.features.overlay-step-buttons", false);
|
|
@ -584,8 +584,12 @@
|
|||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
zoom: 1;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
@ -596,7 +600,7 @@
|
|||
--text-color: #585959; /* --theme-body-color-alt */
|
||||
--toolbar-background: #fcfcfc; /* --theme-toolbar-background */;
|
||||
--toolbar-border: #dde1e4; /* --theme-splitter-color */
|
||||
--toolbar-box-shadow: 0 4px 4px 0 rgba(155, 155, 155, 0.26); /* --rdm-box-shadow */
|
||||
--toolbar-box-shadow: 0 2px 2px 0 rgba(155, 155, 155, 0.26); /* --rdm-box-shadow */
|
||||
--overlay-background: #dde1e4a8;
|
||||
}
|
||||
|
||||
|
@ -607,21 +611,64 @@
|
|||
|
||||
:-moz-native-anonymous .paused-dbg-toolbar {
|
||||
margin-top: 15px;
|
||||
padding: 4px 5px;
|
||||
display: inline-flex;
|
||||
-moz-user-select: none;
|
||||
pointer-events: auto;
|
||||
|
||||
color: var(--text-color);
|
||||
border-radius: 2px;
|
||||
box-shadow: var(--toolbar-box-shadow);
|
||||
background-color: var(--toolbar-background);
|
||||
border: 1px solid var(--toolbar-border);
|
||||
border-radius: 4px;
|
||||
|
||||
font: var(--highlighter-font-family);
|
||||
font-size: var(--highlighter-font-size);
|
||||
}
|
||||
|
||||
:-moz-native-anonymous .paused-dbg-toolbar button {
|
||||
margin: 8px 4px 6px 6px;
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
mask-size: contain;
|
||||
mask-repeat: no-repeat;
|
||||
mask-position: center;
|
||||
mask-size: 14px 14px;
|
||||
background-color: var(--text-color);
|
||||
|
||||
border: 0px;
|
||||
-moz-appearance: none;
|
||||
}
|
||||
|
||||
:-moz-native-anonymous .paused-dbg-toolbar button:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
:-moz-native-anonymous .paused-dbg-divider {
|
||||
width: 1px;
|
||||
height: 14px;
|
||||
margin-top: 8px;
|
||||
background-color: var(--toolbar-border);
|
||||
}
|
||||
|
||||
:-moz-native-anonymous button.paused-dbg-step-button {
|
||||
margin-left: 10px;
|
||||
mask-image: url(resource://devtools/client/debugger/images/stepOver.svg);
|
||||
}
|
||||
|
||||
:-moz-native-anonymous button.paused-dbg-resume-button {
|
||||
margin-right: 10px;
|
||||
mask-image: url(resource://devtools/client/debugger/images/resume.svg);
|
||||
}
|
||||
|
||||
:-moz-native-anonymous .paused-dbg-reason {
|
||||
padding: 1px 16px;
|
||||
margin: 6px 0px;
|
||||
line-height: 16px;
|
||||
font-size: 14px;
|
||||
font: var(--highlighter-font-family);
|
||||
font-size: var(--highlighter-font-size);
|
||||
}
|
||||
|
||||
/* Shapes highlighter */
|
||||
|
||||
:-moz-native-anonymous .shapes-root {
|
||||
|
|
|
@ -257,6 +257,10 @@ exports.HighlighterActor = protocol.ActorClassWithSpec(highlighterSpec, {
|
|||
_currentNode: null,
|
||||
|
||||
pick: function() {
|
||||
if (this._targetActor.threadActor) {
|
||||
this._targetActor.threadActor.hideOverlay();
|
||||
}
|
||||
|
||||
if (this._isPicking) {
|
||||
return null;
|
||||
}
|
||||
|
@ -484,6 +488,9 @@ exports.HighlighterActor = protocol.ActorClassWithSpec(highlighterSpec, {
|
|||
},
|
||||
|
||||
cancelPick: function() {
|
||||
if (this._targetActor.threadActor) {
|
||||
this._targetActor.threadActor.showOverlay();
|
||||
}
|
||||
if (this._isPicking) {
|
||||
this._highlighter.hide();
|
||||
this._stopPickerListeners();
|
||||
|
|
|
@ -9,6 +9,10 @@ const {
|
|||
createNode,
|
||||
} = require("./utils/markup");
|
||||
|
||||
const { LocalizationHelper } = require("devtools/shared/l10n");
|
||||
const STRINGS_URI = "devtools/client/shared/locales/debugger.properties";
|
||||
const L10N = new LocalizationHelper(STRINGS_URI);
|
||||
|
||||
/**
|
||||
* The PausedDebuggerOverlay is a class that displays a semi-transparent mask on top of
|
||||
* the whole page and a toolbar at the top of the page.
|
||||
|
@ -16,8 +20,12 @@ const {
|
|||
* The toolbar is used to display the reason for the pause in script execution as well as
|
||||
* buttons to resume or step through the program.
|
||||
*/
|
||||
function PausedDebuggerOverlay(highlighterEnv) {
|
||||
function PausedDebuggerOverlay(highlighterEnv, options) {
|
||||
this.env = highlighterEnv;
|
||||
this.showOverlayStepButtons = options.showOverlayStepButtons;
|
||||
this.resume = options.resume;
|
||||
this.stepOver = options.stepOver;
|
||||
|
||||
this.markup = new CanvasFrameAnonymousContentHelper(
|
||||
highlighterEnv,
|
||||
this._buildMarkup.bind(this)
|
||||
|
@ -68,6 +76,37 @@ PausedDebuggerOverlay.prototype = {
|
|||
prefix,
|
||||
});
|
||||
|
||||
if (this.showOverlayStepButtons) {
|
||||
createNode(window, {
|
||||
parent: toolbar,
|
||||
attributes: {
|
||||
id: "divider",
|
||||
class: "divider",
|
||||
},
|
||||
prefix,
|
||||
});
|
||||
|
||||
createNode(window, {
|
||||
nodeType: "button",
|
||||
parent: toolbar,
|
||||
attributes: {
|
||||
id: "step-button",
|
||||
class: "step-button",
|
||||
},
|
||||
prefix,
|
||||
});
|
||||
|
||||
createNode(window, {
|
||||
nodeType: "button",
|
||||
parent: toolbar,
|
||||
attributes: {
|
||||
id: "resume-button",
|
||||
class: "resume-button",
|
||||
},
|
||||
prefix,
|
||||
});
|
||||
}
|
||||
|
||||
return container;
|
||||
},
|
||||
|
||||
|
@ -77,35 +116,55 @@ PausedDebuggerOverlay.prototype = {
|
|||
this.env = null;
|
||||
},
|
||||
|
||||
onClick(target) {
|
||||
if (target.id == "paused-dbg-step-button") {
|
||||
this.stepOver();
|
||||
} else if (target.id == "paused-dbg-resume-button") {
|
||||
this.resume();
|
||||
}
|
||||
},
|
||||
|
||||
handleEvent(e) {
|
||||
switch (e.type) {
|
||||
case "click":
|
||||
case "mouseup":
|
||||
this.onClick(e.target);
|
||||
break;
|
||||
case "DOMMouseScroll":
|
||||
// Prevent scrolling. That's because we only took a screenshot of the viewport, so
|
||||
// scrolling out of the viewport wouldn't draw the expected things. In the future
|
||||
// we can take the screenshot again on scroll, but for now it doesn't seem
|
||||
// important.
|
||||
e.preventDefault();
|
||||
break;
|
||||
case "mouseover":
|
||||
console.log(`> mouse over ${e.target.id}`);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
getElement(id) {
|
||||
return this.markup.getElement(this.ID_CLASS_PREFIX + id);
|
||||
},
|
||||
|
||||
show(node, options = {}) {
|
||||
if (this.env.isXUL) {
|
||||
if (this.env.isXUL || !options.reason) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Show the highlighter's root element.
|
||||
const root = this.getElement("root");
|
||||
root.removeAttribute("hidden");
|
||||
|
||||
// The page overlay is only shown upon request. Sometimes we just want the toolbar.
|
||||
if (options.onlyToolbar) {
|
||||
root.removeAttribute("overlay");
|
||||
} else {
|
||||
root.setAttribute("overlay", "true");
|
||||
}
|
||||
root.setAttribute("overlay", "true");
|
||||
|
||||
// Set the text to appear in the toolbar.
|
||||
const toolbar = this.getElement("toolbar");
|
||||
if (options.reason) {
|
||||
this.getElement("reason").setTextContent(options.reason);
|
||||
toolbar.removeAttribute("hidden");
|
||||
} else {
|
||||
toolbar.setAttribute("hidden", "true");
|
||||
}
|
||||
this.getElement("reason").setTextContent(
|
||||
L10N.getStr(`whyPaused.${options.reason}`)
|
||||
);
|
||||
toolbar.removeAttribute("hidden");
|
||||
|
||||
this.env.window.document.setSuppressedEventListener(this);
|
||||
return true;
|
||||
},
|
||||
|
||||
|
|
|
@ -53,6 +53,19 @@ loader.lazyRequireGetter(
|
|||
);
|
||||
loader.lazyRequireGetter(this, "throttle", "devtools/shared/throttle", true);
|
||||
|
||||
loader.lazyRequireGetter(
|
||||
this,
|
||||
"HighlighterEnvironment",
|
||||
"devtools/server/actors/highlighters",
|
||||
true
|
||||
);
|
||||
loader.lazyRequireGetter(
|
||||
this,
|
||||
"PausedDebuggerOverlay",
|
||||
"devtools/server/actors/highlighters/paused-debugger",
|
||||
true
|
||||
);
|
||||
|
||||
/**
|
||||
* JSD2 actors.
|
||||
*/
|
||||
|
@ -91,6 +104,7 @@ const ThreadActor = ActorClassWithSpec(threadSpec, {
|
|||
this._observingNetwork = false;
|
||||
this._activeEventBreakpoints = new Set();
|
||||
this._activeEventPause = null;
|
||||
this._pauseOverlay = null;
|
||||
|
||||
this._priorPause = null;
|
||||
|
||||
|
@ -241,6 +255,10 @@ const ThreadActor = ActorClassWithSpec(threadSpec, {
|
|||
}
|
||||
},
|
||||
|
||||
isPaused() {
|
||||
return this._state === "paused";
|
||||
},
|
||||
|
||||
/**
|
||||
* Remove all debuggees and clear out the thread's sources.
|
||||
*/
|
||||
|
@ -396,6 +414,40 @@ const ThreadActor = ActorClassWithSpec(threadSpec, {
|
|||
}
|
||||
},
|
||||
|
||||
get pauseOverlay() {
|
||||
if (this._pauseOverlay) {
|
||||
return this._pauseOverlay;
|
||||
}
|
||||
|
||||
const env = new HighlighterEnvironment();
|
||||
env.initFromTargetActor(this._parent);
|
||||
const highlighter = new PausedDebuggerOverlay(env, {
|
||||
showOverlayStepButtons: this._options.showOverlayStepButtons,
|
||||
resume: () => this.onResume({ resumeLimit: null }),
|
||||
stepOver: () => this.onResume({ resumeLimit: { type: "next" } }),
|
||||
});
|
||||
this._pauseOverlay = highlighter;
|
||||
return highlighter;
|
||||
},
|
||||
|
||||
showOverlay() {
|
||||
if (
|
||||
this._parent.on &&
|
||||
this.pauseOverlay &&
|
||||
!this._parent.window.isChromeWindow &&
|
||||
this.isPaused()
|
||||
) {
|
||||
const reason = this._priorPause.why.type;
|
||||
this.pauseOverlay.show(null, { reason });
|
||||
}
|
||||
},
|
||||
|
||||
hideOverlay(msg) {
|
||||
if (this._parent.on && !this._parent.window.isChromeWindow) {
|
||||
this.pauseOverlay.hide();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Tell the thread to automatically add a breakpoint on the first line of
|
||||
* a given file, when it is first loaded.
|
||||
|
@ -712,6 +764,7 @@ const ThreadActor = ActorClassWithSpec(threadSpec, {
|
|||
|
||||
this._priorPause = pkt;
|
||||
this.conn.sendActorEvent(this.actorID, "paused", pkt);
|
||||
this.showOverlay();
|
||||
} catch (error) {
|
||||
reportError(error);
|
||||
this.conn.send({
|
||||
|
@ -1229,6 +1282,7 @@ const ThreadActor = ActorClassWithSpec(threadSpec, {
|
|||
// Tell anyone who cares of the resume (as of now, that's the xpcshell harness and
|
||||
// devtools-startup.js when handling the --wait-for-jsdebugger flag)
|
||||
this.conn.sendActorEvent(this.actorID, "resumed");
|
||||
this.hideOverlay();
|
||||
|
||||
if (Services.obs) {
|
||||
Services.obs.notifyObservers(this, "devtools-thread-resumed");
|
||||
|
|
|
@ -25,7 +25,7 @@ window.onload = function() {
|
|||
const env = new HighlighterEnvironment();
|
||||
env.initFromWindow(window);
|
||||
|
||||
const highlighter = new PausedDebuggerOverlay(env);
|
||||
const highlighter = new PausedDebuggerOverlay(env, {});
|
||||
const anonymousContent = highlighter.markup.content;
|
||||
|
||||
const id = elementID => `${highlighter.ID_CLASS_PREFIX}${elementID}`;
|
||||
|
@ -53,32 +53,28 @@ window.onload = function() {
|
|||
ok(isHidden("root"), "The highlighter is hidden");
|
||||
|
||||
info("Show the highlighter with overlay and toolbar");
|
||||
let didShow = highlighter.show(null, {"reason": "Paused in debugger"});
|
||||
let didShow = highlighter.show(null, { "reason": "breakpoint" });
|
||||
ok(didShow, "Calling show returned true");
|
||||
ok(!isHidden("root"), "The highlighter is shown");
|
||||
ok(isOverlayShown(), "The overlay is shown");
|
||||
is(getReason(), "Paused in debugger", "The reason displayed in the toolbar is correct");
|
||||
is(
|
||||
getReason(),
|
||||
"Paused on breakpoint",
|
||||
"The reason displayed in the toolbar is correct"
|
||||
);
|
||||
|
||||
info("Call show again with another reason");
|
||||
didShow = highlighter.show(null, {"reason": "Paused for another reason"});
|
||||
didShow = highlighter.show(null, {"reason": "debuggerStatement"});
|
||||
ok(didShow, "Calling show returned true too");
|
||||
ok(!isHidden("root"), "The highlighter is still shown");
|
||||
is(getReason(), "Paused for another reason",
|
||||
is(getReason(), "Paused on debugger statement",
|
||||
"The reason displayed in the toolbar is correct again");
|
||||
ok(isOverlayShown(), "The overlay is still shown too");
|
||||
|
||||
info("Call show again but with no reason");
|
||||
highlighter.show();
|
||||
ok(isHidden("toolbar"), "The toolbar is hidden");
|
||||
ok(isOverlayShown(), "The overlay is shown however");
|
||||
|
||||
info("Call show again with a reason but no overlay");
|
||||
highlighter.show(null, {reason: "no overlay this time", onlyToolbar: true});
|
||||
ok(!isHidden("toolbar"), "The toolbar is shown this time");
|
||||
is(getReason(), "no overlay this time",
|
||||
"The reason displayed in the toolbar is correct again");
|
||||
ok(!isOverlayShown(), "The overlay is hidden");
|
||||
|
||||
info("Hide the highlighter");
|
||||
highlighter.hide();
|
||||
ok(isHidden("root"), "The highlighter is now hidden");
|
||||
|
|
Загрузка…
Ссылка в новой задаче