Bug 1540693 - Fix BrowserTabList leak. r=jdescottes
authorAlexandre Poirot <poirot.alex@gmail.com>
Tue, 23 Apr 2019 08:23:16 +0000
changeset 470463 696aa652a9e1d48b993802b0c82dbb3f817a57f1
parent 470462 cf05b09d3f3a726f554d2600f3b9b5e5f629972b
child 470464 d6cdc1f35851af085218a5306a171599c92885fb
push id35906
push useraciure@mozilla.com
push dateTue, 23 Apr 2019 22:14:56 +0000
treeherdermozilla-central@0ce3633f8b80 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjdescottes
bugs1540693
milestone68.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 1540693 - Fix BrowserTabList leak. r=jdescottes BrowserTabList._actorByBrowser still contains opened tab we attached to when destroying the RootActor. This prevents correctly unregistering the DOM listener set on browser.xul, leading to permanent leaks. Differential Revision: https://phabricator.services.mozilla.com/D26110
devtools/server/actors/root.js
devtools/server/actors/webbrowser.js
devtools/server/tests/unit/testactors.js
devtools/shared/security/tests/unit/testactors.js
devtools/shared/transport/tests/unit/testactors.js
--- a/devtools/server/actors/root.js
+++ b/devtools/server/actors/root.js
@@ -197,17 +197,17 @@ RootActor.prototype = {
   },
 
   /**
    * Destroys the actor from the browser window.
    */
   destroy: function() {
     /* Tell the live lists we aren't watching any more. */
     if (this._parameters.tabList) {
-      this._parameters.tabList.onListChanged = null;
+      this._parameters.tabList.destroy();
     }
     if (this._parameters.addonList) {
       this._parameters.addonList.onListChanged = null;
     }
     if (this._parameters.workerList) {
       this._parameters.workerList.onListChanged = null;
     }
     if (this._parameters.serviceWorkerRegistrationList) {
--- a/devtools/server/actors/webbrowser.js
+++ b/devtools/server/actors/webbrowser.js
@@ -193,16 +193,21 @@ function BrowserTabList(connection) {
   /* True if we're testing, and should throw if consistency checks fail. */
   this._testing = false;
 
   this._onAndroidDocumentEvent = this._onAndroidDocumentEvent.bind(this);
 }
 
 BrowserTabList.prototype.constructor = BrowserTabList;
 
+BrowserTabList.prototype.destroy = function() {
+  this._actorByBrowser.clear();
+  this.onListChanged = null;
+};
+
 /**
  * Get the selected browser for the given navigator:browser window.
  * @private
  * @param window nsIChromeWindow
  *        The navigator:browser window for which you want the selected browser.
  * @return Element|null
  *         The currently selected xul:browser element, if any. Note that the
  *         browser window might not be loaded yet - the function will return
--- a/devtools/server/tests/unit/testactors.js
+++ b/devtools/server/tests/unit/testactors.js
@@ -62,16 +62,17 @@ function TestTabList(connection) {
   }
   if (this._targetActors.length > 0) {
     this._targetActors[0].selected = true;
   }
 }
 
 TestTabList.prototype = {
   constructor: TestTabList,
+  destroy() {},
   getList: function() {
     return Promise.resolve([...this._targetActors]);
   },
 };
 
 exports.createRootActor = function createRootActor(connection) {
   ActorRegistry.registerModule("devtools/server/actors/webconsole", {
     prefix: "console",
--- a/devtools/shared/security/tests/unit/testactors.js
+++ b/devtools/shared/security/tests/unit/testactors.js
@@ -39,16 +39,17 @@ function TestTabList(connection) {
   }
   if (this._targetActors.length > 0) {
     this._targetActors[0].selected = true;
   }
 }
 
 TestTabList.prototype = {
   constructor: TestTabList,
+  destroy() {},
   getList: function() {
     return promise.resolve([...this._targetActors]);
   },
 };
 
 exports.createRootActor = function createRootActor(connection) {
   const root = new RootActor(connection, {
     tabList: new TestTabList(connection),
--- a/devtools/shared/transport/tests/unit/testactors.js
+++ b/devtools/shared/transport/tests/unit/testactors.js
@@ -38,16 +38,17 @@ function TestTabList(connection) {
   }
   if (this._targetActors.length > 0) {
     this._targetActors[0].selected = true;
   }
 }
 
 TestTabList.prototype = {
   constructor: TestTabList,
+  destroy() {},
   getList: function() {
     return Promise.resolve([...this._targetActors]);
   },
 };
 
 exports.createRootActor = function createRootActor(connection) {
   const root = new RootActor(connection, {
     tabList: new TestTabList(connection),