Bug 790952 - Debugger server always creates new actor instances. f=glandium r=rcampbell
authorPanos Astithas <past@mozilla.com>
Fri, 21 Sep 2012 09:04:21 +0300
changeset 107867 f0ddac4f8973a07b0510fb47600ddfed47e01e3b
parent 107705 f731fa718465e7cfc252c0acf1aeec35913d7123
child 107868 cdc721f3f9c657cf8aceaab73f53309601116512
push id82
push usershu@rfrn.org
push dateFri, 05 Oct 2012 13:20:22 +0000
reviewersrcampbell
bugs790952
milestone18.0a1
Bug 790952 - Debugger server always creates new actor instances. f=glandium r=rcampbell
browser/devtools/debugger/test/browser_dbg_globalactor-01.js
toolkit/devtools/debugger/server/dbg-server.js
--- a/browser/devtools/debugger/test/browser_dbg_globalactor-01.js
+++ b/browser/devtools/debugger/test/browser_dbg_globalactor-01.js
@@ -17,17 +17,49 @@ function test()
     is(aType, "browser", "Root actor should identify itself as a browser.");
     gClient.listTabs(function(aResponse) {
       let globalActor = aResponse.testGlobalActor1;
       ok(globalActor, "Found the test tab actor.")
       ok(globalActor.indexOf("testone") >= 0,
          "testTabActor's actorPrefix should be used.");
       gClient.request({ to: globalActor, type: "ping" }, function(aResponse) {
         is(aResponse.pong, "pong", "Actor should respond to requests.");
-        finish_test();
+        // Send another ping to see if the same actor is used.
+        gClient.request({ to: globalActor, type: "ping" }, function(aResponse) {
+          is(aResponse.pong, "pong", "Actor should respond to requests.");
+
+          // Make sure that lazily-created actors are created only once.
+          let connections = Object.keys(DebuggerServer._connections);
+          is(connections.length, 1, "Only one connection is established.");
+          let connPrefix = connections[0];
+          ok(DebuggerServer._connections[connPrefix],
+             connPrefix + " is the only connection.");
+          // First we look for the pool of global actors.
+          let extraPools = DebuggerServer._connections[connPrefix]._extraPools;
+          let globalPool;
+          for (let pool of extraPools) {
+            if (Object.keys(pool._actors).some(function(elem) {
+              // Tab actors are in the global pool.
+              let re = new RegExp(connPrefix + "tab", "g");
+              return elem.match(re) !== null;
+            })) {
+              globalPool = pool;
+              break;
+            }
+          }
+          // Then we look if the global pool contains only one test actor.
+          let actorPrefix = connPrefix + "testone";
+          let actors = Object.keys(globalPool._actors).join();
+          info("Global actors: " + actors);
+          isnot(actors.indexOf(actorPrefix), -1, "The test actor exists in the pool.");
+          is(actors.indexOf(actorPrefix), actors.lastIndexOf(actorPrefix),
+             "Only one actor exists in the pool.");
+
+          finish_test();
+        });
       });
     });
   });
 }
 
 function finish_test()
 {
   gClient.close(function() {
--- a/toolkit/devtools/debugger/server/dbg-server.js
+++ b/toolkit/devtools/debugger/server/dbg-server.js
@@ -524,18 +524,21 @@ DebuggerServerConnection.prototype = {
       } catch (e) {
         Cu.reportError(e);
         this.transport.send({
           error: "unknownError",
           message: ("error occurred while creating actor '" + actor.name +
                     "': " + safeErrorString(e))
         });
       }
+      // We want the newly-constructed actor to completely replace the factory
+      // actor. Reusing the existing actor ID will make sure ActorPool.addActor
+      // does the right thing.
+      instance.actorID = actor.actorID;
       actor.registeredPool.addActor(instance);
-      actor.registeredPool.removeActor(actor);
       actor = instance;
     }
 
     var ret = null;
 
     // Dispatch the request to the actor.
     if (actor.requestTypes && actor.requestTypes[aPacket.type]) {
       try {