Bug 1354679 - Show the paused debugger overlay when script gets paused; r=ochameau
MozReview-Commit-ID: FhKLGEtocTl
--- a/devtools/server/actors/highlighters/paused-debugger.js
+++ b/devtools/server/actors/highlighters/paused-debugger.js
@@ -79,30 +79,27 @@ PausedDebuggerOverlay.prototype = {
/**
* Show this highlighter. This is the usual show method that all highlighters need to
* implement so they can be used via the CustomHighlighterActor mechanism.
* @param {DOMNode} node The context node for this highlighter.
* @param {Object} options See showOverlay for doc about this.
* @return {Boolean}
*/
show(node, options = {}) {
- return this.showOverlay(options);
- },
- /**
- * This contains the actual logic to show the highlighter. In comparison to the show
- * method, it does not need a first DOMNode parameter which makes it simpler to be
- * called by other server-side modules if needed.
- * @param {Object} options A config object that can take 2 properties:
- * - {String} reason The text that will be shown in the toolbar. If not given, the
- * toolbar will not be displayed.
- * - {Boolean} onlyToolbar Set to true to only show the toolbar, and not the overlay.
- * @return {Boolean}
- */
- showOverlay(options = {}) {
+ /**
+ * This contains the actual logic to show the highlighter. In comparison to the show
+ * method, it does not need a first DOMNode parameter which makes it simpler to be
+ * called by other server-side modules if needed.
+ * @param {Object} options A config object that can take 2 properties:
+ * - {String} reason The text that will be shown in the toolbar. If not given, the
+ * toolbar will not be displayed.
+ * - {Boolean} onlyToolbar Set to true to only show the toolbar, and not the overlay.
+ * @return {Boolean}
+ */
if (this.env.isXUL) {
return false;
}
// Show the highlighter's root element.
let root = this.getElement("root");
root.removeAttribute("hidden");
--- a/devtools/server/actors/script.js
+++ b/devtools/server/actors/script.js
@@ -424,16 +424,18 @@ const ThreadActor = ActorClassWithSpec(t
this._frameActors = [];
this._parent = parent;
this._dbg = null;
this._gripDepth = 0;
this._threadLifetimePool = null;
this._tabClosed = false;
this._scripts = null;
this._pauseOnDOMEvents = null;
+ EventEmitter.decorate(this);
+ attachPauseStateListeners(this)
this._options = {
useSourceMaps: false,
autoBlackBox: false
};
this.breakpointActorMap = new BreakpointActorMap();
this.sourceActorStore = new SourceActorStore();
@@ -600,17 +602,17 @@ const ThreadActor = ActorClassWithSpec(t
this._dbg.enabled = false;
this._dbg = null;
},
/**
* destroy the debugger and put the actor in the exited state.
*/
exit: function () {
- destroyPausedStateOverlays();
+ this.emit("exited");
this.destroy();
this._state = "exited";
},
// Request handlers
onAttach: function (request) {
if (this.state === "exited") {
return { type: "exited" };
@@ -745,17 +747,16 @@ const ThreadActor = ActorClassWithSpec(t
reportError(error);
return {
error: "unknownError",
message: error.message + "\n" + error.stack
};
})
.then(pkt => {
this.conn.send(pkt);
- showPausedStateOverlay(this._parent);
});
return undefined;
});
this._pushThreadPause();
} catch (e) {
reportError(e, "Got an exception during TA__pauseAndRespond: ");
@@ -1035,18 +1036,16 @@ const ThreadActor = ActorClassWithSpec(t
let resumeLimitHandled;
if (request && request.resumeLimit) {
resumeLimitHandled = this._handleResumeLimit(request);
} else {
this._clearSteppingHooks(this.youngestFrame);
resumeLimitHandled = resolve(true);
}
- hidePausedStateOverlay(this._parent);
-
return resumeLimitHandled.then(() => {
if (request) {
this._options.pauseOnExceptions = request.pauseOnExceptions;
this._options.ignoreCaughtExceptions = request.ignoreCaughtExceptions;
this.maybePauseOnExceptions();
this._maybeListenToEvents(request);
}
@@ -1538,16 +1537,17 @@ const ThreadActor = ActorClassWithSpec(t
// We don't want to actually have nested pauses (although we
// have nested event loops). If code runs in the debuggee during
// a pause, it should cause the actor to resume (dropping
// pause-lifetime actors etc) and then repause when complete.
if (this.state === "paused") {
return undefined;
}
+ this.emit("pausing", this.state);
// Clear stepping hooks.
this.dbg.onEnterFrame = undefined;
this.dbg.onExceptionUnwind = undefined;
if (frame) {
frame.onStep = undefined;
frame.onPop = undefined;
}
@@ -1603,16 +1603,17 @@ const ThreadActor = ActorClassWithSpec(t
_resumed: function () {
this._state = "running";
// Drop the actors in the pause actor pool.
this.conn.removeActorPool(this._pausePool);
this._pausePool = null;
this._pauseActor = null;
+ this.emit("resumed");
return { from: this.actorID, type: "resumed" };
},
/**
* Expire frame actors for frames that have been popped.
*
* @returns A list of actor IDs whose frames have been popped.
@@ -1897,18 +1898,16 @@ const ThreadActor = ActorClassWithSpec(t
}
packet.why = { type: "exception",
exception: createValueGrip(value, this._pausePool,
this.objectGrip)
};
this.conn.send(packet);
- showPausedStateOverlay(this._parent);
-
this._pushThreadPause();
} catch (e) {
reportError(e, "Got an exception during TA_onExceptionUnwind: ");
}
return undefined;
},
@@ -2388,16 +2387,27 @@ exports.unwrapDebuggerObjectGlobal = wra
return undefined;
}
};
// Manage a collection of PausedDebuggerOverlays and their HighlighterEnvironments indexed
// by TabActors (export it so it the paused state can be tested).
const pausedStateOverlays = exports.pausedStateOverlays = new Map();
+function attachPauseStateListeners(threadActor) {
+ EventEmitter.on(threadActor, "pausing", (pausingState) => {
+ if (pausingState !== "attached") {
+ console.log(pausingState);
+ return showPausedStateOverlay(threadActor._parent);
+ }
+ });
+ EventEmitter.on(threadActor, "resumed",() => hidePausedStateOverlay(threadActor._parent));
+ EventEmitter.on(threadActor, "exiting",() => destroyPausedStateOverlay(threadActor._parent));
+}
+
/**
* Get the instance of the PausedDebuggerOverlay for a TabActor.
*
* @param {TabActor} tabActor
* The parent of the threadActor.
*
* @return {PausedDebuggerOverlay}
* The instance of the overlay, or null if it can't be created in this TabActor.
--- a/devtools/server/tests/unit/test_pausedOverlay.js
+++ b/devtools/server/tests/unit/test_pausedOverlay.js
@@ -24,17 +24,18 @@ var mockOverlay = {
isOverlayVisible = true;
},
hide: () => {
isOverlayVisible = false;
}
}
};
-function run_test() {
+
+add_task(async function() {
do_test_pending();
Task.spawn(function* () {
initTestDebuggerServer(DebuggerServer);
gDebuggee = addTestGlobal("test-overlay", DebuggerServer);
gClient = new DebuggerClient(DebuggerServer.connectPipe());
yield gClient.connect();
@@ -49,17 +50,17 @@ function run_test() {
yield test_debugger_statement();
yield test_exception();
yield test_breakpoint();
yield gClient.close();
do_test_finished();
});
-}
+});
function* test_debugger_statement() {
ok(!isOverlayVisible, "The overlay is hidden at first");
yield executeOnNextTickAndWaitForPause(() => {
Cu.evalInSandbox("debugger;", gDebuggee);
}, gClient);