Bug 1494796 - get rid of ThreadClient specifics in DebuggerClient ; r=jdescottes
authoryulia <ystartsev@mozilla.com>
Fri, 14 Jun 2019 04:24:15 +0000
changeset 478964 eacdf422f58676c0ab759d9a6c4dbc36273fd90d
parent 478963 9d24fd51deb422b107e5155647de6fbf9f863e36
child 478965 2a4f4639567ad479cd211dbe16159db2b4a830bf
push id88004
push userystartsev@mozilla.com
push dateFri, 14 Jun 2019 22:34:23 +0000
treeherderautoland@ae4f5a5b9feb [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjdescottes
bugs1494796
milestone69.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1494796 - get rid of ThreadClient specifics in DebuggerClient ; r=jdescottes This is part one of removing threadClient specifics out of the debuggerClient. We were managing messages from the thread client in a special way -- this was the "Unsolicited Pauses" object that we had before. This patch updates the threadClient to use Front style events. This required updating the spec for the threadClient, and several of the methods. What has not been fully migrated here is the "resumed" event, as this is much more complex. This is taken care of in the next patch. Differential Revision: https://phabricator.services.mozilla.com/D32695
devtools/server/tests/unit/head_dbg.js
devtools/server/tests/unit/test_nesting-03.js
devtools/shared/client/deprecated-thread-client.js
devtools/shared/client/thread-client.js
devtools/shared/specs/thread.js
--- a/devtools/server/tests/unit/head_dbg.js
+++ b/devtools/server/tests/unit/head_dbg.js
@@ -387,19 +387,22 @@ async function attachTestTab(client, tit
 }
 
 // Attach to |client|'s tab whose title is |title|, and then attach to
 // that tab's thread. Pass |callback| the thread attach response packet, a
 // TargetFront referring to the tab, and a ThreadClient referring to the
 // thread.
 async function attachTestThread(client, title, callback = () => {}) {
   const targetFront = await attachTestTab(client, title);
-  const [response, threadClient] = await targetFront.attachThread({
+  const threadClient = await targetFront.getFront("context");
+  const onPaused = threadClient.once("paused");
+  await targetFront.attachThread({
     autoBlackBox: true,
   });
+  const response = await onPaused;
   Assert.equal(threadClient.state, "paused", "Thread client is paused");
   Assert.ok("why" in response);
   Assert.equal(response.why.type, "attached");
   callback(response, targetFront, threadClient);
   return { targetFront, threadClient };
 }
 
 // Attach to |client|'s tab whose title is |title|, attach to the tab's
--- a/devtools/server/tests/unit/test_nesting-03.js
+++ b/devtools/server/tests/unit/test_nesting-03.js
@@ -41,18 +41,16 @@ async function test_nesting() {
     await gThreadClient1.resume();
   } catch (e) {
     Assert.equal(e.error, "wrongOrder");
   }
   try {
     await gThreadClient2.resume();
   } catch (e) {
     Assert.ok(!e.error);
-    Assert.equal(e.from, gThreadClient2.actor);
   }
 
   gThreadClient1.resume().then(response => {
     Assert.ok(!response.error);
-    Assert.equal(response.from, gThreadClient1.actor);
 
     gClient1.close(() => finishClient(gClient2));
   });
 }
--- a/devtools/shared/client/deprecated-thread-client.js
+++ b/devtools/shared/client/deprecated-thread-client.js
@@ -224,17 +224,16 @@ ThreadClient.prototype = {
 
   /**
    * Detach from the thread actor.
    */
   detach: DebuggerClient.requester({
     type: "detach",
   }, {
     after: function(response) {
-      this.client.unregisterClient(this);
       return response;
     },
   }),
 
   /**
    * Promote multiple pause-lifetime object actors to thread-lifetime ones.
    *
    * @param array actors
@@ -337,17 +336,17 @@ ThreadClient.prototype = {
    * Handle thread state change by doing necessary cleanup and notifying all
    * registered listeners.
    */
   _onThreadState: function(packet) {
     this._state = ThreadStateTypes[packet.type];
     // The debugger UI may not be initialized yet so we want to keep
     // the packet around so it knows what to pause state to display
     // when it's initialized
-    this._lastPausePacket = packet.type === "resumed" ? null : packet;
+    this._lastPausePacket = packet;
     this._clearPauseGrips();
     packet.type === ThreadStateTypes.detached && this._clearThreadGrips();
     this.client._eventsEnabled && this.emit(packet.type, packet);
   },
 
   getLastPausePacket: function() {
     return this._lastPausePacket;
   },
--- a/devtools/shared/client/thread-client.js
+++ b/devtools/shared/client/thread-client.js
@@ -33,16 +33,22 @@ loader.lazyRequireGetter(
 class ThreadClient extends FrontClassWithSpec(threadSpec) {
   constructor(client, actor) {
     super(client);
     this.events = ["newSource", "progress"];
     this.client = client;
     this._pauseGrips = {};
     this._threadGrips = {};
     this._state = "paused";
+    this._beforePaused = this._beforePaused.bind(this);
+    this._beforeResumed = this._beforeResumed.bind(this);
+    this._beforeDetached = this._beforeDetached.bind(this);
+    this.before("paused", this._beforePaused);
+    this.before("resumed", this._beforeResumed);
+    this.before("detached", this._beforeDetached);
     this.actorID = actor;
     this.manage(this);
   }
 
   destroy() {
     this.client.unregisterClient(this);
     super.destroy();
   }
@@ -271,28 +277,41 @@ class ThreadClient extends FrontClassWit
   /**
    * Invalidate thread-lifetime grip clients and clear the list of current grip
    * clients.
    */
   _clearThreadGrips() {
     this._clearObjectClients("_threadGrips");
   }
 
+  _beforePaused(packet) {
+    this._state = "paused";
+    this._onThreadState(packet);
+  }
+
+  _beforeResumed() {
+    this._state = "attached";
+    this._onThreadState(null);
+  }
+
+  _beforeDetached(packet) {
+    this._state = "detached";
+    this._onThreadState(packet);
+    this._clearThreadGrips();
+  }
+
   /**
    * Handle thread state change by doing necessary cleanup
    */
   _onThreadState(packet) {
-    this._state = ThreadStateTypes[packet.type];
     // The debugger UI may not be initialized yet so we want to keep
     // the packet around so it knows what to pause state to display
     // when it's initialized
-    this._lastPausePacket = packet.type === "resumed" ? null : packet;
+    this._lastPausePacket = packet;
     this._clearPauseGrips();
-    packet.type === ThreadStateTypes.detached && this._clearThreadGrips();
-    this.client._eventsEnabled && this.emit(packet.type, packet);
   }
 
   getLastPausePacket() {
     return this._lastPausePacket;
   }
 
   /**
    * Return an instance of SourceFront for the given source actor form.
--- a/devtools/shared/specs/thread.js
+++ b/devtools/shared/specs/thread.js
@@ -13,18 +13,28 @@ types.addDictType("available-breakpoint-
   id: "string",
   name: "string",
 });
 
 const threadSpec = generateActorSpec({
   typeName: "context",
 
   events: {
+    paused: {
+      actor: Option(0, "nullable:string"),
+      frame: Option(0, "nullable:json"),
+      why: Option(0, "nullable:json"),
+      poppedFrames: Option(0, "nullable:json"),
+      error: Option(0, "nullable:json"),
+    },
+    resumed: {},
+    detached: {},
+    willInterrupt: {},
     newSource: {
-      source: Option(0, "source"),
+      source: Option(0, "json"),
     },
     progress: {
       recording: Option(0, "json"),
       executionPoint: Option(0, "json"),
     },
   },
 
   methods: {
@@ -56,17 +66,17 @@ const threadSpec = generateActorSpec({
         count: Arg(1, "number"),
       },
       response: RetVal("json"),
     },
     interrupt: {
       request: {
         when: Arg(0, "json"),
       },
-      response: RetVal("array:json"),
+      response: RetVal("nullable:json"),
     },
     sources: {
       response: RetVal("array:json"),
     },
     skipBreakpoints: {
       request: {
         skip: Arg(0, "json"),
       },