From 3fa5aec6586d78545deed47d1d836ace7eeb49af Mon Sep 17 00:00:00 2001 From: Piro / YUKI Hiroshi Date: Tue, 10 Nov 2015 03:00:43 +0900 Subject: [PATCH] Add reference counter implementation to detect memory leak --- content/treestyletab/bookmarksOverlay.js | 7 ++ .../treestyletab/bookmarksOverlayEditable.js | 3 + content/treestyletab/treestyletab.js | 6 ++ content/treestyletab/windowHelper.js | 22 ++++- modules/ReferenceCounter.js | 42 +++++++++ modules/autoHide.js | 51 +++++++++++ modules/browser.js | 87 +++++++++++++++++++ modules/tabbarDNDObserver.js | 13 +++ modules/tabpanelDNDObserver.js | 7 ++ modules/window.js | 45 ++++++++++ 10 files changed, 279 insertions(+), 4 deletions(-) create mode 100644 modules/ReferenceCounter.js diff --git a/content/treestyletab/bookmarksOverlay.js b/content/treestyletab/bookmarksOverlay.js index 12707254..91e51d02 100644 --- a/content/treestyletab/bookmarksOverlay.js +++ b/content/treestyletab/bookmarksOverlay.js @@ -3,6 +3,7 @@ XPCOMUtils.defineLazyModuleGetter(this, 'TreeStyleTabUtils', 'resource://treestyletab-modules/utils.js'); (function() { +let { ReferenceCounter } = Components.utils.import('resource://treestyletab-modules/ReferenceCounter.js', {}); let { inherit } = Components.utils.import('resource://treestyletab-modules/lib/inherit.jsm', {}); var TreeStyleTabBookmarksService = inherit(TreeStyleTabService, { @@ -218,13 +219,17 @@ var TreeStyleTabBookmarksService = inherit(TreeStyleTabService, { preInit : function TSTBMService_preInit() { window.addEventListener('load', this, false); + ReferenceCounter.add('window,load,TSTBMService,false'); window.addEventListener(window['piro.sakura.ne.jp'].tabsDragUtils.EVENT_TYPE_TABS_DROP, this, false); + ReferenceCounter.add('window,EVENT_TYPE_TABS_DROP,TSTBMService,false'); }, init : function TSTBMService_init() { window.removeEventListener('load', this, false); + ReferenceCounter.remove('window,load,TSTBMService,false'); window.addEventListener('unload', this, false); + ReferenceCounter.add('window,unload,TSTBMService,false'); if (!('PlacesUIUtils' in window)) return; @@ -473,7 +478,9 @@ var TreeStyleTabBookmarksService = inherit(TreeStyleTabService, { destroy : function TSTBMService_destroy() { window.removeEventListener('unload', this, false); + ReferenceCounter.remove('window,unload,TSTBMService,false'); window.removeEventListener(window['piro.sakura.ne.jp'].tabsDragUtils.EVENT_TYPE_TABS_DROP, this, false); + ReferenceCounter.remove('window,EVENT_TYPE_TABS_DROP,TSTBMService,false'); }, // observer for nsINavBookmarksService diff --git a/content/treestyletab/bookmarksOverlayEditable.js b/content/treestyletab/bookmarksOverlayEditable.js index 8bf57d77..c529c3fe 100644 --- a/content/treestyletab/bookmarksOverlayEditable.js +++ b/content/treestyletab/bookmarksOverlayEditable.js @@ -3,6 +3,7 @@ XPCOMUtils.defineLazyModuleGetter(this, 'TreeStyleTabUtils', 'resource://treestyletab-modules/utils.js'); (function() { +let { ReferenceCounter } = Components.utils.import('resource://treestyletab-modules/ReferenceCounter.js', {}); let { inherit } = Components.utils.import('resource://treestyletab-modules/lib/inherit.jsm', {}); var TreeStyleTabBookmarksServiceEditable = inherit(TreeStyleTabBookmarksService, { @@ -386,6 +387,7 @@ var TreeStyleTabBookmarksServiceEditable = inherit(TreeStyleTabBookmarksService, { case 'DOMContentLoaded': window.removeEventListener('DOMContentLoaded', this, false); + ReferenceCounter.remove('window,DOMContentLoaded,TreeStyleTabBookmarksServiceEditable,false'); this.init(); break; } @@ -394,6 +396,7 @@ var TreeStyleTabBookmarksServiceEditable = inherit(TreeStyleTabBookmarksService, }); window.addEventListener('DOMContentLoaded', TreeStyleTabBookmarksServiceEditable, false); +ReferenceCounter.add('window,DOMContentLoaded,TreeStyleTabBookmarksServiceEditable,false'); window.TreeStyleTabBookmarksServiceEditable = TreeStyleTabBookmarksServiceEditable; })(); diff --git a/content/treestyletab/treestyletab.js b/content/treestyletab/treestyletab.js index cd47d712..4b63e06b 100644 --- a/content/treestyletab/treestyletab.js +++ b/content/treestyletab/treestyletab.js @@ -1,21 +1,27 @@ (function() { + let { ReferenceCounter } = Components.utils.import('resource://treestyletab-modules/ReferenceCounter.js', {}); /** * On secondary (and later) window, SSWindowStateBusy event can be fired * before DOMContentLoaded, on "domwindowopened". */ var SSWindowStateBusyListener = function TSTSSWindowStateBusyListener(aEvent) { window.removeEventListener(aEvent.type, TSTSSWindowStateBusyListener, false); + ReferenceCounter.remove('window,aEvent.type,TSTSSWindowStateBusyListener,false'); window.__treestyletab__WindowStateBusy = true; SSWindowStateBusyListener = undefined; }; window.addEventListener('SSWindowStateBusy', SSWindowStateBusyListener, false); + ReferenceCounter.add('window,SSWindowStateBusy,SSWindowStateBusyListener,false'); window.addEventListener('DOMContentLoaded', function onDOMContentLoaded(aEvent) { window.removeEventListener(aEvent.type, onDOMContentLoaded, false); + ReferenceCounter.remove('window,aEvent.type,onDOMContentLoaded,false'); if (SSWindowStateBusyListener) { window.removeEventListener('SSWindowStateBusy', SSWindowStateBusyListener, false); + ReferenceCounter.remove('window,SSWindowStateBusy,SSWindowStateBusyListener,false'); SSWindowStateBusyListener = undefined; } }, false); + ReferenceCounter.add('window,aEvent.type,onDOMContentLoaded,false'); var ns = {}; Components.utils.import('resource://treestyletab-modules/window.js', ns); diff --git a/content/treestyletab/windowHelper.js b/content/treestyletab/windowHelper.js index fd133404..0537e3bb 100644 --- a/content/treestyletab/windowHelper.js +++ b/content/treestyletab/windowHelper.js @@ -381,6 +381,8 @@ var TreeStyleTabWindowHelper = { initToolbarItems : function TSTWH_initToolbarItems() { + let { ReferenceCounter } = Components.utils.import('resource://treestyletab-modules/ReferenceCounter.js', {}); + var searchbar = document.getElementById('searchbar'); if (searchbar && searchbar.doSearch && @@ -395,35 +397,47 @@ var TreeStyleTabWindowHelper = { } var goButton = document.getElementById('urlbar-go-button'); - if (goButton) + if (goButton) { goButton.parentNode.addEventListener('click', this.service, true); + ReferenceCounter.add('goButton.parentNode,click,this.service,true'); + } var tabbar = this.service.getTabStrip(this.service.browser); tabbar.addEventListener('click', this.service, true); + ReferenceCounter.add('tabbar,click,this.service,true'); var newTabButton = document.getElementById('new-tab-button'); var nsIDOMNode = Ci.nsIDOMNode; if (newTabButton && - !(tabbar.compareDocumentPosition(newTabButton) & nsIDOMNode.DOCUMENT_POSITION_CONTAINED_BY)) + !(tabbar.compareDocumentPosition(newTabButton) & nsIDOMNode.DOCUMENT_POSITION_CONTAINED_BY)) { newTabButton.parentNode.addEventListener('click', this.service, true); + ReferenceCounter.add('newTabButton.parentNode,click,this.service,true'); + } this.service.updateAllTabsButton(gBrowser); }, destroyToolbarItems : function TSTWH_destroyToolbarItems() { + let { ReferenceCounter } = Components.utils.import('resource://treestyletab-modules/ReferenceCounter.js', {}); + var goButton = document.getElementById('urlbar-go-button'); - if (goButton) + if (goButton) { goButton.parentNode.removeEventListener('click', this.service, true); + ReferenceCounter.remove('goButton.parentNode,click,this.service,true'); + } var tabbar = this.service.getTabStrip(this.service.browser); tabbar.removeEventListener('click', this.service, true); + ReferenceCounter.remove('tabbar,click,this.service,true'); var newTabButton = document.getElementById('new-tab-button'); var nsIDOMNode = Ci.nsIDOMNode; if (newTabButton && - !(tabbar.compareDocumentPosition(newTabButton) & Ci.nsIDOMNode.DOCUMENT_POSITION_CONTAINED_BY)) + !(tabbar.compareDocumentPosition(newTabButton) & Ci.nsIDOMNode.DOCUMENT_POSITION_CONTAINED_BY)) { newTabButton.parentNode.removeEventListener('click', this.service, true); + ReferenceCounter.remove('newTabButton.parentNode,click,this.service,true'); + } var allTabsButton = document.getElementById('alltabs-button'); if (allTabsButton && allTabsButton.hasChildNodes()) diff --git a/modules/ReferenceCounter.js b/modules/ReferenceCounter.js new file mode 100644 index 00000000..b57318c0 --- /dev/null +++ b/modules/ReferenceCounter.js @@ -0,0 +1,42 @@ +/** + * How to use: + * + * 1. Insert "ReferenceCounter.add('unique key'); after "addEventListener()" + * 2. Insert "ReferenceCounter.remove('unique key'); after "removeEventListener()" + * 3. Open and close windows multiple times. + * 4. Go to the browser console and run the script: + * (function() { let { ReferenceCounter } = Components.utils.import('resource://treestyletab-modules/ReferenceCounter.js', {}); return ReferenceCounter.report() })(); + * + * Expected result for good case: + * + * Blank array is returned. + * + * Expected result for bad case: + * + * Not-removed counters are reported as the elements of the returned array. + */ + +"use strict"; + +var EXPORTED_SYMBOLS = ['ReferenceCounter']; + +var ReferenceCounter = { + _listeners: {}, + add: function(aKey) { + this._listeners[aKey] = this._listeners[aKey] || 0; + this._listeners[aKey]++; + }, + remove: function(aKey) { + this._listeners[aKey] = this._listeners[aKey] || 0; + this._listeners[aKey]--; + }, + report: function() { + var keys = []; + Object.keys(this._listeners).forEach(function(aKey) { + if (this._listeners[aKey] <= 1) + return; + keys.push(aKey+'('+this._listeners[aKey]+')'); + }, this); + return keys; + } +}; diff --git a/modules/autoHide.js b/modules/autoHide.js index a3db0dcc..c6eb9e07 100644 --- a/modules/autoHide.js +++ b/modules/autoHide.js @@ -44,6 +44,7 @@ Cu.import('resource://gre/modules/XPCOMUtils.jsm'); Cu.import('resource://gre/modules/Services.jsm'); Cu.import('resource://treestyletab-modules/lib/inherit.jsm'); Cu.import('resource://treestyletab-modules/constants.js'); +Cu.import('resource://treestyletab-modules/ReferenceCounter.js'); XPCOMUtils.defineLazyModuleGetter(this, 'utils', 'resource://treestyletab-modules/utils.js', 'TreeStyleTabUtils'); @@ -353,13 +354,21 @@ AutoHideBrowser.prototype = inherit(AutoHideBase.prototype, { if (!(aReason & this.kSHOWHIDE_BY_API)) { b.addEventListener('dragover', this, true); + ReferenceCounter.add('b,dragover,AHW,true'); b.addEventListener('dragleave', this, true); + ReferenceCounter.add('b,dragleave,AHW,true'); sv.tabStripPlaceHolder.addEventListener('mousedown', this, true); + ReferenceCounter.add('tabStripPlaceHolder,mousedown,AHW,true'); sv.tabStripPlaceHolder.addEventListener('mouseup', this, true); + ReferenceCounter.add('tabStripPlaceHolder,mouseup,AHW,true'); sv.tabStrip.addEventListener('mousedown', this, true); + ReferenceCounter.add('tabStrip,mousedown,AHW,true'); w.addEventListener('mouseup', this, true); + ReferenceCounter.add('w,mouseup,AHW,true'); w.addEventListener('dragend', this, true); + ReferenceCounter.add('w,dragend,AHW,true'); w.addEventListener('drop', this, true); + ReferenceCounter.add('w,drop,AHW,true'); if (this.shouldListenMouseMove) this.startListenMouseMove(); if (b == w.gBrowser && sv.shouldListenKeyEventsForAutoHide) @@ -368,7 +377,9 @@ AutoHideBrowser.prototype = inherit(AutoHideBase.prototype, { this.notifyStatusToAllTabs(); } w.addEventListener(sv.kEVENT_TYPE_PRINT_PREVIEW_ENTERED, this, false); + ReferenceCounter.add('w,kEVENT_TYPE_PRINT_PREVIEW_ENTERED,AHW,false'); w.addEventListener(sv.kEVENT_TYPE_PRINT_PREVIEW_EXITED, this, false); + ReferenceCounter.add('w,kEVENT_TYPE_PRINT_PREVIEW_EXITED,AHW,false'); this.updateTransparency(); @@ -394,13 +405,21 @@ AutoHideBrowser.prototype = inherit(AutoHideBase.prototype, { if (this.userActionListening) { b.removeEventListener('dragover', this, true); + ReferenceCounter.remove('b,dragover,AHW,true'); b.removeEventListener('dragleave', this, true); + ReferenceCounter.remove('b,dragleave,AHW,true'); sv.tabStripPlaceHolder.removeEventListener('mousedown', this, true); + ReferenceCounter.remove('tabStripPlaceHolder,mousedown,AHW,true'); sv.tabStripPlaceHolder.removeEventListener('mouseup', this, true); + ReferenceCounter.remove('tabStripPlaceHolder,mouseup,AHW,true'); sv.tabStrip.removeEventListener('mousedown', this, true); + ReferenceCounter.remove('tabStrip,mousedown,AHW,true'); w.removeEventListener('mouseup', this, true); + ReferenceCounter.remove('w,mouseup,AHW,true'); w.removeEventListener('dragend', this, true); + ReferenceCounter.remove('w,dragend,AHW,true'); w.removeEventListener('drop', this, true); + ReferenceCounter.remove('w,drop,AHW,true'); this.endListenMouseMove(); if (b == w.gBrowser) w.TreeStyleTabService.endListenKeyEventsFor(sv.LISTEN_FOR_AUTOHIDE); @@ -408,7 +427,9 @@ AutoHideBrowser.prototype = inherit(AutoHideBase.prototype, { this.notifyStatusToAllTabs(); } w.removeEventListener(sv.kEVENT_TYPE_PRINT_PREVIEW_ENTERED, this, false); + ReferenceCounter.remove('w,kEVENT_TYPE_PRINT_PREVIEW_ENTERED,AHW,false'); w.removeEventListener(sv.kEVENT_TYPE_PRINT_PREVIEW_EXITED, this, false); + ReferenceCounter.remove('w,kEVENT_TYPE_PRINT_PREVIEW_EXITED,AHW,false'); this.updateTransparency(); @@ -465,10 +486,15 @@ AutoHideBrowser.prototype = inherit(AutoHideBase.prototype, { return; this.screen.addEventListener('mousemove', this, true); + ReferenceCounter.add('screen,mousemove,AHW,true'); this.treeStyleTab.tabStripPlaceHolder.addEventListener('mousemove', this, true); + ReferenceCounter.add('tabStripPlaceHolder,mousemove,AHW,true'); this.treeStyleTab.tabStrip.addEventListener('mousemove', this, true); + ReferenceCounter.add('tabStrip,mousemove,AHW,true'); this.toggler.addEventListener('mousemove', this, true); + ReferenceCounter.add('toggler,mousemove,AHW,true'); this.window.addEventListener('TabRemotenessChange', this, false); + ReferenceCounter.add('window,TabRemotenessChange,AHW,false'); this.mouseMoveListening = true; @@ -481,10 +507,15 @@ AutoHideBrowser.prototype = inherit(AutoHideBase.prototype, { return; this.screen.removeEventListener('mousemove', this, true); + ReferenceCounter.remove('screen,mousemove,AHW,true'); this.treeStyleTab.tabStripPlaceHolder.removeEventListener('mousemove', this, true); + ReferenceCounter.remove('tabStripPlaceHolder,mousemove,AHW,true'); this.treeStyleTab.tabStrip.removeEventListener('mousemove', this, true); + ReferenceCounter.remove('tabStrip,mousemove,AHW,true'); this.toggler.removeEventListener('mousemove', this, true); + ReferenceCounter.remove('toggler,mousemove,AHW,true'); this.window.removeEventListener('TabRemotenessChange', this, false); + ReferenceCounter.remove('window,TabRemotenessChange,AHW,false'); this.mouseMoveListening = false; @@ -1441,14 +1472,23 @@ AutoHideBrowser.prototype = inherit(AutoHideBase.prototype, { this.onPrefChange('extensions.treestyletab.tabbar.autoHide.contentAreaScreen.enabled'); b.mTabContainer.addEventListener('TabOpen', this, false); + ReferenceCounter.add('mTabContainer,TabOpen,AHW,false'); b.mTabContainer.addEventListener('TabClose', this, false); + ReferenceCounter.add('mTabContainer,TabClose,AHW,false'); b.mTabContainer.addEventListener('TabMove', this, false); + ReferenceCounter.add('mTabContainer,TabMove,AHW,false'); b.mTabContainer.addEventListener('select', this, false); + ReferenceCounter.add('mTabContainer,select,AHW,false'); b.addEventListener(sv.kEVENT_TYPE_TABBAR_POSITION_CHANGING, this, false); + ReferenceCounter.add('b,kEVENT_TYPE_TABBAR_POSITION_CHANGING,AHW,false'); b.addEventListener(sv.kEVENT_TYPE_TABBAR_POSITION_CHANGED, this, false); + ReferenceCounter.add('b,kEVENT_TYPE_TABBAR_POSITION_CHANGED,AHW,false'); b.addEventListener(sv.kEVENT_TYPE_TAB_FOCUS_SWITCHING_KEY_DOWN, this, false); + ReferenceCounter.add('b,kEVENT_TYPE_TAB_FOCUS_SWITCHING_KEY_DOWN,AHW,false'); b.addEventListener(sv.kEVENT_TYPE_TAB_FOCUS_SWITCHING_START, this, false); + ReferenceCounter.add('b,kEVENT_TYPE_TAB_FOCUS_SWITCHING_START,AHW,false'); b.addEventListener(sv.kEVENT_TYPE_TAB_FOCUS_SWITCHING_END, this, false); + ReferenceCounter.add('b,kEVENT_TYPE_TAB_FOCUS_SWITCHING_END,AHW,false'); }, destroy : function AHB_destroy() @@ -1459,14 +1499,23 @@ AutoHideBrowser.prototype = inherit(AutoHideBase.prototype, { var sv = this.treeStyleTab; var b = this.browser; b.mTabContainer.removeEventListener('TabOpen', this, false); + ReferenceCounter.remove('mTabContainer,TabOpen,AHW,false'); b.mTabContainer.removeEventListener('TabClose', this, false); + ReferenceCounter.remove('mTabContainer,TabClose,AHW,false'); b.mTabContainer.removeEventListener('TabMove', this, false); + ReferenceCounter.remove('mTabContainer,TabMove,AHW,false'); b.mTabContainer.removeEventListener('select', this, false); + ReferenceCounter.remove('mTabContainer,select,AHW,false'); b.removeEventListener(sv.kEVENT_TYPE_TABBAR_POSITION_CHANGING, this, false); + ReferenceCounter.remove('b,kEVENT_TYPE_TABBAR_POSITION_CHANGING,AHW,false'); b.removeEventListener(sv.kEVENT_TYPE_TABBAR_POSITION_CHANGED, this, false); + ReferenceCounter.remove('b,kEVENT_TYPE_TABBAR_POSITION_CHANGED,AHW,false'); b.removeEventListener(sv.kEVENT_TYPE_TAB_FOCUS_SWITCHING_KEY_DOWN, this, false); + ReferenceCounter.remove('b,kEVENT_TYPE_TAB_FOCUS_SWITCHING_KEY_DOWN,AHW,false'); b.removeEventListener(sv.kEVENT_TYPE_TAB_FOCUS_SWITCHING_START, this, false); + ReferenceCounter.remove('b,kEVENT_TYPE_TAB_FOCUS_SWITCHING_START,AHW,false'); b.removeEventListener(sv.kEVENT_TYPE_TAB_FOCUS_SWITCHING_END, this, false); + ReferenceCounter.remove('b,kEVENT_TYPE_TAB_FOCUS_SWITCHING_END,AHW,false'); delete this.treeStyleTab; delete this.browser; @@ -1610,6 +1659,7 @@ AutoHideWindow.prototype = inherit(AutoHideBase.prototype, { this.waitingForWindowReady = true; this.window.addEventListener('SSWindowStateReady', this, false); + ReferenceCounter.add('window,SSWindowStateReady,AHW,false'); Services.obs.addObserver(this, 'browser-delayed-startup-finished', false); }, @@ -1620,6 +1670,7 @@ AutoHideWindow.prototype = inherit(AutoHideBase.prototype, { this.waitingForWindowReady = false; this.window.removeEventListener('SSWindowStateReady', this, false); + ReferenceCounter.remove('window,SSWindowStateReady,AHW,false'); Services.obs.removeObserver(this, 'browser-delayed-startup-finished'); }, diff --git a/modules/browser.js b/modules/browser.js index 426c3229..afd09487 100644 --- a/modules/browser.js +++ b/modules/browser.js @@ -45,6 +45,7 @@ const Cu = Components.utils; Cu.import('resource://gre/modules/XPCOMUtils.jsm'); Cu.import('resource://gre/modules/Timer.jsm'); Cu.import('resource://treestyletab-modules/lib/inherit.jsm'); +Cu.import('resource://treestyletab-modules/ReferenceCounter.js'); XPCOMUtils.defineLazyModuleGetter(this, 'Services', 'resource://gre/modules/Services.jsm'); XPCOMUtils.defineLazyModuleGetter(this, 'Promise', 'resource://gre/modules/Promise.jsm'); @@ -823,16 +824,26 @@ TreeStyleTabBrowser.prototype = inherit(TreeStyleTabWindow.prototype, { this.initTabbar(null, this.kTABBAR_TOP, true); w.addEventListener('resize', this, true); + ReferenceCounter.add('w,resize,TSTBrowser,true'); w.addEventListener('beforecustomization', this, true); + ReferenceCounter.add('w,beforecustomization,TSTBrowser,true'); w.addEventListener('aftercustomization', this, false); + ReferenceCounter.add('w,aftercustomization,TSTBrowser,false'); w.addEventListener('customizationchange', this, false); + ReferenceCounter.add('w,customizationchange,TSTBrowser,false'); w.addEventListener(this.kEVENT_TYPE_PRINT_PREVIEW_ENTERED, this, false); + ReferenceCounter.add('w,kEVENT_TYPE_PRINT_PREVIEW_ENTERED,TSTBrowser,false'); w.addEventListener(this.kEVENT_TYPE_PRINT_PREVIEW_EXITED, this, false); + ReferenceCounter.add('w,kEVENT_TYPE_PRINT_PREVIEW_EXITED,TSTBrowser,false'); w.addEventListener('tabviewframeinitialized', this, false); + ReferenceCounter.add('w,tabviewframeinitialized,TSTBrowser,false'); w.addEventListener(this.kEVENT_TYPE_TAB_FOCUS_SWITCHING_END, this, false); + ReferenceCounter.add('w,kEVENT_TYPE_TAB_FOCUS_SWITCHING_END,TSTBrowser,false'); w.addEventListener('SSWindowStateBusy', this, false); + ReferenceCounter.add('w,SSWindowStateBusy,TSTBrowser,false'); b.addEventListener('nsDOMMultipleTabHandlerTabsClosing', this, false); + ReferenceCounter.add('b,nsDOMMultipleTabHandlerTabsClosing,TSTBrowser,false'); w['piro.sakura.ne.jp'].tabsDragUtils.initTabBrowser(b); @@ -910,6 +921,7 @@ TreeStyleTabBrowser.prototype = inherit(TreeStyleTabWindow.prototype, { var tabContextMenu = b.tabContextMenu || d.getAnonymousElementByAttribute(b, 'anonid', 'tabContextMenu'); tabContextMenu.addEventListener('popupshowing', this, false); + ReferenceCounter.add('tabContextMenu,popupshowing,TSTBrowser,false'); if (!('MultipleTabService' in w)) { w.setTimeout(function(aSelf, aTabBrowser, aPopup) { let suffix = '-tabbrowser-'+(aTabBrowser.id || 'instance-'+parseInt(Math.random() * 65000)); @@ -987,7 +999,9 @@ TreeStyleTabBrowser.prototype = inherit(TreeStyleTabWindow.prototype, { var w = this.window; this._DNDObserversInitialized = false; w.addEventListener('mouseover', this, true); + ReferenceCounter.add('w,mouseover,TSTBrowser,true'); w.addEventListener('dragover', this, true); + ReferenceCounter.add('w,dragover,TSTBrowser,true'); }, _initDNDObservers : function TSTBrowser_initDNDObservers() @@ -1000,7 +1014,9 @@ TreeStyleTabBrowser.prototype = inherit(TreeStyleTabWindow.prototype, { var w = this.window; w.removeEventListener('mouseover', this, true); + ReferenceCounter.remove('w,mouseover,TSTBrowser,true'); w.removeEventListener('dragover', this, true); + ReferenceCounter.remove('w,dragover,TSTBrowser,true'); this._DNDObserversInitialized = true; }, @@ -1609,11 +1625,13 @@ TreeStyleTabBrowser.prototype = inherit(TreeStyleTabWindow.prototype, { return new Promise((function(aResolve, aReject) { var onInitialized = (function() { this.mTabBrowser.removeEventListener(this.kEVENT_TYPE_TABBAR_INITIALIZED, onInitialized, false); + ReferenceCounter.remove('mTabBrowser,kEVENT_TYPE_TABBAR_INITIALIZED,onInitialized,false'); if (!aIsTemporaryChange) delete this._temporaryPosition; aResolve(); }).bind(this); this.mTabBrowser.addEventListener(this.kEVENT_TYPE_TABBAR_INITIALIZED, onInitialized, false); + ReferenceCounter.add('mTabBrowser,kEVENT_TYPE_TABBAR_INITIALIZED,onInitialized,false'); }).bind(this)); }, @@ -1623,27 +1641,46 @@ TreeStyleTabBrowser.prototype = inherit(TreeStyleTabWindow.prototype, { var tabContainer = b.mTabContainer; tabContainer.addEventListener('TabOpen', this, true); + ReferenceCounter.add('tabContainer,TabOpen,TSTBrowser,true'); tabContainer.addEventListener('TabClose', this, true); + ReferenceCounter.add('tabContainer,TabClose,TSTBrowser,true'); tabContainer.addEventListener('TabMove', this, true); + ReferenceCounter.add('tabContainer,TabMove,TSTBrowser,true'); tabContainer.addEventListener('TabShow', this, true); + ReferenceCounter.add('tabContainer,TabShow,TSTBrowser,true'); tabContainer.addEventListener('TabHide', this, true); + ReferenceCounter.add('tabContainer,TabHide,TSTBrowser,true'); tabContainer.addEventListener('SSTabRestoring', this, true); + ReferenceCounter.add('tabContainer,SSTabRestoring,TSTBrowser,true'); tabContainer.addEventListener('SSTabRestored', this, true); + ReferenceCounter.add('tabContainer,SSTabRestored,TSTBrowser,true'); tabContainer.addEventListener('TabPinned', this, true); + ReferenceCounter.add('tabContainer,TabPinned,TSTBrowser,true'); tabContainer.addEventListener('TabUnpinned', this, true); + ReferenceCounter.add('tabContainer,TabUnpinned,TSTBrowser,true'); tabContainer.addEventListener('mouseover', this, true); + ReferenceCounter.add('tabContainer,mouseover,TSTBrowser,true'); tabContainer.addEventListener('mouseout', this, true); + ReferenceCounter.add('tabContainer,mouseout,TSTBrowser,true'); tabContainer.addEventListener('dblclick', this, true); + ReferenceCounter.add('tabContainer,dblclick,TSTBrowser,true'); tabContainer.addEventListener('select', this, true); + ReferenceCounter.add('tabContainer,select,TSTBrowser,true'); tabContainer.addEventListener('scroll', this, true); + ReferenceCounter.add('tabContainer,scroll,TSTBrowser,true'); var strip = this.tabStrip; strip.addEventListener('MozMouseHittest', this, true); // to block default behaviors of the tab bar + ReferenceCounter.add('strip,MozMouseHittest,TSTBrowser,true'); strip.addEventListener('mousedown', this, true); + ReferenceCounter.add('strip,mousedown,TSTBrowser,true'); strip.addEventListener('click', this, true); + ReferenceCounter.add('strip,click,TSTBrowser,true'); this.scrollBox.addEventListener('overflow', this, true); + ReferenceCounter.add('scrollBox,overflow,TSTBrowser,true'); this.scrollBox.addEventListener('underflow', this, true); + ReferenceCounter.add('scrollBox,underflow,TSTBrowser,true'); }, _ensureNewSplitter : function TSTBrowser__ensureNewSplitter() @@ -1691,6 +1728,7 @@ TreeStyleTabBrowser.prototype = inherit(TreeStyleTabWindow.prototype, { }, 0); }; grippy.addEventListener('click', grippy.grippyOnClick, true); + ReferenceCounter.add('grippy,click,grippy.grippyOnClick,true'); splitter.appendChild(grippy); } @@ -1700,8 +1738,11 @@ TreeStyleTabBrowser.prototype = inherit(TreeStyleTabWindow.prototype, { splitter.setAttribute('class', splitterClass); splitter.addEventListener('mousedown', this.windowService, false); + ReferenceCounter.add('splitter,mousedown,windowService,false'); splitter.addEventListener('mouseup', this.windowService, false); + ReferenceCounter.add('splitter,mouseup,windowService,false'); splitter.addEventListener('dblclick', this.windowService, false); + ReferenceCounter.add('splitter,dblclick,windowService,false'); var ref = this.mTabBrowser.mPanelContainer; ref.parentNode.insertBefore(splitter, ref); @@ -1716,10 +1757,14 @@ TreeStyleTabBrowser.prototype = inherit(TreeStyleTabWindow.prototype, { var splitter = this.splitter; try { splitter.removeEventListener('mousedown', this.windowService, false); + ReferenceCounter.remove('splitter,mousedown,windowService,false'); splitter.removeEventListener('mouseup', this.windowService, false); + ReferenceCounter.remove('splitter,mouseup,windowService,false'); splitter.removeEventListener('dblclick', this.windowService, false); + ReferenceCounter.remove('splitter,dblclick,windowService,false'); var grippy = splitter.firstChild; grippy.removeEventListener('click', grippy.grippyOnClick, true); + ReferenceCounter.remove('grippy,click,grippy.grippyOnClick,true'); delete grippy.grippyOnClick; } catch(e) { @@ -2259,22 +2304,33 @@ TreeStyleTabBrowser.prototype = inherit(TreeStyleTabWindow.prototype, { this._autoHide = undefined; // block to be re-initialized by property accesses w.removeEventListener('resize', this, true); + ReferenceCounter.remove('w,resize,TSTBrowser,true'); w.removeEventListener('beforecustomization', this, true); + ReferenceCounter.remove('w,beforecustomization,TSTBrowser,true'); w.removeEventListener('aftercustomization', this, false); + ReferenceCounter.remove('w,aftercustomization,TSTBrowser,false'); w.removeEventListener('customizationchange', this, false); + ReferenceCounter.remove('w,customizationchange,TSTBrowser,false'); w.removeEventListener(this.kEVENT_TYPE_PRINT_PREVIEW_ENTERED, this, false); + ReferenceCounter.remove('w,kEVENT_TYPE_PRINT_PREVIEW_ENTERED,TSTBrowser,false'); w.removeEventListener(this.kEVENT_TYPE_PRINT_PREVIEW_EXITED, this, false); + ReferenceCounter.remove('w,kEVENT_TYPE_PRINT_PREVIEW_EXITED,TSTBrowser,false'); w.removeEventListener('tabviewframeinitialized', this, false); + ReferenceCounter.remove('w,tabviewframeinitialized,TSTBrowser,false'); w.removeEventListener(this.kEVENT_TYPE_TAB_FOCUS_SWITCHING_END, this, false); + ReferenceCounter.remove('w,kEVENT_TYPE_TAB_FOCUS_SWITCHING_END,TSTBrowser,false'); w.removeEventListener('SSWindowStateBusy', this, false); + ReferenceCounter.remove('w,SSWindowStateBusy,TSTBrowser,false'); b.removeEventListener('nsDOMMultipleTabHandlerTabsClosing', this, false); + ReferenceCounter.remove('b,nsDOMMultipleTabHandlerTabsClosing,TSTBrowser,false'); w['piro.sakura.ne.jp'].tabsDragUtils.destroyTabBrowser(b); var tabContextMenu = b.tabContextMenu || d.getAnonymousElementByAttribute(b, 'anonid', 'tabContextMenu'); tabContextMenu.removeEventListener('popupshowing', this, false); + ReferenceCounter.remove('tabContextMenu,popupshowing,TSTBrowser,false'); if (this.tabbarCanvas) { this.tabbarCanvas.parentNode.removeChild(this.tabbarCanvas); @@ -2303,7 +2359,9 @@ TreeStyleTabBrowser.prototype = inherit(TreeStyleTabWindow.prototype, { if (aTab.__treestyletab__checkTabsIndentOverflowOnMouseLeave) { this.document.removeEventListener('mouseover', aTab.__treestyletab__checkTabsIndentOverflowOnMouseLeave, true); + ReferenceCounter.remove('document,mouseover,aTab.__treestyletab__checkTabsIndentOverflowOnMouseLeave,true'); this.document.removeEventListener('mouseout', aTab.__treestyletab__checkTabsIndentOverflowOnMouseLeave, true); + ReferenceCounter.remove('document,mouseout,aTab.__treestyletab__checkTabsIndentOverflowOnMouseLeave,true'); delete aTab.__treestyletab__checkTabsIndentOverflowOnMouseLeave; } @@ -2321,27 +2379,46 @@ TreeStyleTabBrowser.prototype = inherit(TreeStyleTabWindow.prototype, { var tabContainer = b.mTabContainer; tabContainer.removeEventListener('TabOpen', this, true); + ReferenceCounter.remove('tabContainer,TabOpen,TSTBrowser,true'); tabContainer.removeEventListener('TabClose', this, true); + ReferenceCounter.remove('tabContainer,TabClose,TSTBrowser,true'); tabContainer.removeEventListener('TabMove', this, true); + ReferenceCounter.remove('tabContainer,TabMove,TSTBrowser,true'); tabContainer.removeEventListener('TabShow', this, true); + ReferenceCounter.remove('tabContainer,TabShow,TSTBrowser,true'); tabContainer.removeEventListener('TabHide', this, true); + ReferenceCounter.remove('tabContainer,TabHide,TSTBrowser,true'); tabContainer.removeEventListener('SSTabRestoring', this, true); + ReferenceCounter.remove('tabContainer,SSTabRestoring,TSTBrowser,true'); tabContainer.removeEventListener('SSTabRestored', this, true); + ReferenceCounter.remove('tabContainer,SSTabRestored,TSTBrowser,true'); tabContainer.removeEventListener('TabPinned', this, true); + ReferenceCounter.remove('tabContainer,TabPinned,TSTBrowser,true'); tabContainer.removeEventListener('TabUnpinned', this, true); + ReferenceCounter.remove('tabContainer,TabUnpinned,TSTBrowser,true'); tabContainer.removeEventListener('mouseover', this, true); + ReferenceCounter.remove('tabContainer,mouseover,TSTBrowser,true'); tabContainer.removeEventListener('mouseout', this, true); + ReferenceCounter.remove('tabContainer,mouseout,TSTBrowser,true'); tabContainer.removeEventListener('dblclick', this, true); + ReferenceCounter.remove('tabContainer,dblclick,TSTBrowser,true'); tabContainer.removeEventListener('select', this, true); + ReferenceCounter.remove('tabContainer,select,TSTBrowser,true'); tabContainer.removeEventListener('scroll', this, true); + ReferenceCounter.remove('tabContainer,scroll,TSTBrowser,true'); var strip = this.tabStrip; strip.removeEventListener('MozMouseHittest', this, true); + ReferenceCounter.remove('strip,MozMouseHittest,TSTBrowser,true'); strip.removeEventListener('mousedown', this, true); + ReferenceCounter.remove('strip,mousedown,TSTBrowser,true'); strip.removeEventListener('click', this, true); + ReferenceCounter.remove('strip,click,TSTBrowser,true'); this.scrollBox.removeEventListener('overflow', this, true); + ReferenceCounter.remove('scrollBox,overflow,TSTBrowser,true'); this.scrollBox.removeEventListener('underflow', this, true); + ReferenceCounter.remove('scrollBox,underflow,TSTBrowser,true'); }, saveCurrentState : function TSTBrowser_saveCurrentState() @@ -2377,9 +2454,11 @@ TreeStyleTabBrowser.prototype = inherit(TreeStyleTabWindow.prototype, { return new Promise((function(aResolve, aReject) { var onRestored = (function() { this.mTabBrowser.removeEventListener(this.kEVENT_TYPE_TABBAR_POSITION_CHANGED, onRestored, false); + ReferenceCounter.remove('mTabBrowser,kEVENT_TYPE_TABBAR_POSITION_CHANGED,onRestored,false'); aResolve(); }).bind(this); this.mTabBrowser.addEventListener(this.kEVENT_TYPE_TABBAR_POSITION_CHANGED, onRestored, false); + ReferenceCounter.add('mTabBrowser,kEVENT_TYPE_TABBAR_POSITION_CHANGED,onRestored,false'); }).bind(this)) .then(this.destroyTabbarPostProcess.bind(this)); } @@ -2482,8 +2561,10 @@ TreeStyleTabBrowser.prototype = inherit(TreeStyleTabWindow.prototype, { if (aPopup.state == 'open') { aPopup.addEventListener('popuphidden', function onPopuphidden(aEvent) { aPopup.removeEventListener(aEvent.type, onPopuphidden, false); + ReferenceCounter.remove('aPopup,popuphidden,onPopuphidden,false'); aPopup.parentNode.removeChild(aPopup); }, false); + ReferenceCounter.add('aPopup,popuphidden,onPopuphidden,false'); aPopup.hidePopup(); } else { @@ -4368,6 +4449,7 @@ TreeStyleTabBrowser.prototype = inherit(TreeStyleTabWindow.prototype, { let self = this; aRestoredTab.addEventListener('SSTabRestoring', function onSSTabRestoring(aEvent) { aRestoredTab.removeEventListener(aEvent.type, onSSTabRestoring, false); + ReferenceCounter.remove('aRestoredTab,SSTabRestoring,onSSTabRestoring,false'); self.askUndoCloseTabSetBehavior(aRestoredTab, indexes.length) .then(function(aBehavior) { if (aBehavior & self.kUNDO_CLOSE_SET) @@ -4377,6 +4459,7 @@ TreeStyleTabBrowser.prototype = inherit(TreeStyleTabWindow.prototype, { Components.utils.reportError(aError); }); }, false); + ReferenceCounter.add('aRestoredTab,SSTabRestoring,onSSTabRestoring,false'); } else if (behavior & this.kUNDO_CLOSE_SET) { this.doRestoreClosedSet(aRestoredTab, indexes); @@ -6178,12 +6261,16 @@ TreeStyleTabBrowser.prototype = inherit(TreeStyleTabWindow.prototype, { if (x > rect.left && x < rect.right && y > rect.top && y < rect.bottom) return; self.document.removeEventListener('mouseover', aTab.__treestyletab__checkTabsIndentOverflowOnMouseLeave, true); + ReferenceCounter.remove('document,mouseover,aTab.__treestyletab__checkTabsIndentOverflowOnMouseLeave,true'); self.document.removeEventListener('mouseout', aTab.__treestyletab__checkTabsIndentOverflowOnMouseLeave, true); + ReferenceCounter.remove('document,mouseout,aTab.__treestyletab__checkTabsIndentOverflowOnMouseLeave,true'); delete aTab.__treestyletab__checkTabsIndentOverflowOnMouseLeave; self.checkTabsIndentOverflow(); }; this.document.addEventListener('mouseover', aTab.__treestyletab__checkTabsIndentOverflowOnMouseLeave, true); + ReferenceCounter.add('document,mouseover,aTab.__treestyletab__checkTabsIndentOverflowOnMouseLeave,true'); this.document.addEventListener('mouseout', aTab.__treestyletab__checkTabsIndentOverflowOnMouseLeave, true); + ReferenceCounter.add('document,mouseout,aTab.__treestyletab__checkTabsIndentOverflowOnMouseLeave,true'); } } }, diff --git a/modules/tabbarDNDObserver.js b/modules/tabbarDNDObserver.js index f23a85b6..e45033ee 100644 --- a/modules/tabbarDNDObserver.js +++ b/modules/tabbarDNDObserver.js @@ -43,6 +43,7 @@ const Cu = Components.utils; Cu.import('resource://gre/modules/XPCOMUtils.jsm'); Cu.import('resource://gre/modules/Services.jsm'); +Cu.import('resource://treestyletab-modules/ReferenceCounter.js'); XPCOMUtils.defineLazyModuleGetter(this, 'utils', 'resource://treestyletab-modules/utils.js', 'TreeStyleTabUtils'); @@ -1367,11 +1368,17 @@ catch(e) { { var target = this.treeStyleTab.ownerToolbar || this.treeStyleTab.tabStrip; target.addEventListener('dragstart', this, true); + ReferenceCounter.add('target,dragstart,TabbarDND,true'); target.addEventListener('dragover', this, true); + ReferenceCounter.add('target,dragover,TabbarDND,true'); target.addEventListener('dragenter', this, false); + ReferenceCounter.add('target,dragenter,TabbarDND,false'); target.addEventListener('dragleave', this, false); + ReferenceCounter.add('target,dragleave,TabbarDND,false'); target.addEventListener('dragend', this, true); + ReferenceCounter.add('target,dragend,TabbarDND,true'); target.addEventListener('drop', this, true); + ReferenceCounter.add('target,drop,TabbarDND,true'); }, destroy : function TabbarDND_destroy() @@ -1388,11 +1395,17 @@ catch(e) { { var target = this.treeStyleTab.ownerToolbar || this.treeStyleTab.tabStrip; target.removeEventListener('dragstart', this, true); + ReferenceCounter.remove('target,dragstart,TabbarDND,true'); target.removeEventListener('dragover', this, true); + ReferenceCounter.remove('target,dragover,TabbarDND,true'); target.removeEventListener('dragenter', this, false); + ReferenceCounter.remove('target,dragenter,TabbarDND,false'); target.removeEventListener('dragleave', this, false); + ReferenceCounter.remove('target,dragleave,TabbarDND,false'); target.removeEventListener('dragend', this, true); + ReferenceCounter.remove('target,dragend,TabbarDND,true'); target.removeEventListener('drop', this, true); + ReferenceCounter.remove('target,drop,TabbarDND,true'); } }; diff --git a/modules/tabpanelDNDObserver.js b/modules/tabpanelDNDObserver.js index 838df36b..d2eee66f 100644 --- a/modules/tabpanelDNDObserver.js +++ b/modules/tabpanelDNDObserver.js @@ -40,6 +40,7 @@ const Cc = Components.classes; const Ci = Components.interfaces; Components.utils.import('resource://gre/modules/XPCOMUtils.jsm'); +Components.utils.import('resource://treestyletab-modules/ReferenceCounter.js'); XPCOMUtils.defineLazyModuleGetter(this, 'utils', 'resource://treestyletab-modules/utils.js', 'TreeStyleTabUtils'); @@ -145,16 +146,22 @@ TabpanelDNDObserver.prototype = { var b = this.treeStyleTab.mTabBrowser; b.mPanelContainer.addEventListener('dragover', this, true); + ReferenceCounter.add('b.mPanelContainer,dragover,this,true'); b.mPanelContainer.addEventListener('dragleave', this, true); + ReferenceCounter.add('b.mPanelContainer,dragleave,this,true'); b.mPanelContainer.addEventListener('drop', this, true); + ReferenceCounter.add('b.mPanelContainer,drop,this,true'); }, destroy : function TabpanelDND_destroy() { var b = this.treeStyleTab.mTabBrowser; b.mPanelContainer.removeEventListener('dragover', this, true); + ReferenceCounter.remove('b.mPanelContainer,dragover,this,true'); b.mPanelContainer.removeEventListener('dragleave', this, true); + ReferenceCounter.remove('b.mPanelContainer,dragleave,this,true'); b.mPanelContainer.removeEventListener('drop', this, true); + ReferenceCounter.remove('b.mPanelContainer,drop,this,true'); delete this.treeStyleTab; delete this.browser; diff --git a/modules/window.js b/modules/window.js index 726489c9..866a890b 100644 --- a/modules/window.js +++ b/modules/window.js @@ -43,6 +43,7 @@ const Cu = Components.utils; Cu.import('resource://gre/modules/XPCOMUtils.jsm'); Cu.import('resource://gre/modules/Timer.jsm'); Cu.import('resource://treestyletab-modules/lib/inherit.jsm'); +Cu.import('resource://treestyletab-modules/ReferenceCounter.js'); XPCOMUtils.defineLazyGetter(this, 'window', function() { Cu.import('resource://treestyletab-modules/lib/namespace.jsm'); @@ -80,7 +81,9 @@ function TreeStyleTabWindow(aWindow) this.restoringCount = 0; aWindow.addEventListener('DOMContentLoaded', this, true); + ReferenceCounter.add('w,DOMContentLoaded,TSTWindow,true'); aWindow.addEventListener('load', this, false); + ReferenceCounter.add('w,load,TSTWindow,false'); aWindow.TreeStyleTabService = this; XPCOMUtils.defineLazyModuleGetter(aWindow, 'TreeStyleTabBrowser', 'resource://treestyletab-modules/browser.js'); @@ -377,10 +380,12 @@ TreeStyleTabWindow.prototype = inherit(TreeStyleTabBase, { var w = this.window; w.removeEventListener('DOMContentLoaded', this, true); + ReferenceCounter.remove('w,DOMContentLoaded,TSTWindow,true'); if (w.location.href.indexOf('chrome://browser/content/browser.xul') != 0) return; w.addEventListener('SSTabRestoring', this, true); + ReferenceCounter.add('w,SSTabRestoring,TSTWindow,true'); w.TreeStyleTabWindowHelper.preInit(); @@ -393,8 +398,10 @@ TreeStyleTabWindow.prototype = inherit(TreeStyleTabBase, { { var w = this.window; w.removeEventListener('load', this, false); + ReferenceCounter.remove('w,load,TSTWindow,false'); w.addEventListener('unload', this, false); + ReferenceCounter.add('w,unload,TSTWindow,false'); if ( w.location.href.indexOf('chrome://browser/content/browser.xul') != 0 || @@ -409,16 +416,25 @@ TreeStyleTabWindow.prototype = inherit(TreeStyleTabBase, { this.preInit(); } w.removeEventListener('SSTabRestoring', this, true); + ReferenceCounter.remove('w,SSTabRestoring,TSTWindow,true'); var d = this.document; d.addEventListener('popupshowing', this, false); + ReferenceCounter.add('d,popupshowing,TSTWindow,false'); d.addEventListener('popuphiding', this, true); + ReferenceCounter.add('d,popuphiding,TSTWindow,true'); d.addEventListener(this.kEVENT_TYPE_TAB_COLLAPSED_STATE_CHANGED, this, false); + ReferenceCounter.add('d,kEVENT_TYPE_TAB_COLLAPSED_STATE_CHANGED,TSTWindow,false'); d.addEventListener(this.kEVENT_TYPE_TABBAR_POSITION_CHANGED, this, false); + ReferenceCounter.add('d,kEVENT_TYPE_TABBAR_POSITION_CHANGED,TSTWindow,false'); d.addEventListener(this.kEVENT_TYPE_TABBAR_STATE_CHANGED, this, false); + ReferenceCounter.add('d,kEVENT_TYPE_TABBAR_STATE_CHANGED,TSTWindow,false'); d.addEventListener(this.kEVENT_TYPE_FOCUS_NEXT_TAB, this, false); + ReferenceCounter.add('d,kEVENT_TYPE_FOCUS_NEXT_TAB,TSTWindow,false'); w.addEventListener('beforecustomization', this, true); + ReferenceCounter.add('w,beforecustomization,TSTWindow,true'); w.addEventListener('aftercustomization', this, false); + ReferenceCounter.add('w,aftercustomization,TSTWindow,false'); w.messageManager.addMessageListener('SessionStore:restoreTabContentStarted', this); @@ -429,10 +445,14 @@ TreeStyleTabWindow.prototype = inherit(TreeStyleTabBase, { var appcontent = d.getElementById('appcontent'); appcontent.addEventListener('SubBrowserAdded', this, false); + ReferenceCounter.add('appcontent,SubBrowserAdded,TSTWindow,false'); appcontent.addEventListener('SubBrowserRemoveRequest', this, false); + ReferenceCounter.add('appcontent,SubBrowserRemoveRequest,TSTWindow,false'); w.addEventListener('UIOperationHistoryUndo:TabbarOperations', this, false); + ReferenceCounter.add('w,UIOperationHistoryUndo:TabbarOperations,TSTWindow,false'); w.addEventListener('UIOperationHistoryRedo:TabbarOperations', this, false); + ReferenceCounter.add('w,UIOperationHistoryRedo:TabbarOperations,TSTWindow,false'); prefs.addPrefListener(this); @@ -542,6 +562,7 @@ TreeStyleTabWindow.prototype = inherit(TreeStyleTabBase, { this.base.inWindowDestoructionProcess = true; try { w.removeEventListener('unload', this, false); + ReferenceCounter.remove('w,unload,TSTWindow,false'); w.TreeStyleTabWindowHelper.destroyToolbarItems(); @@ -559,13 +580,21 @@ TreeStyleTabWindow.prototype = inherit(TreeStyleTabBase, { let d = this.document; d.removeEventListener('popupshowing', this, false); + ReferenceCounter.remove('d,popupshowing,TSTWindow,false'); d.removeEventListener('popuphiding', this, true); + ReferenceCounter.remove('d,popuphiding,TSTWindow,true'); d.removeEventListener(this.kEVENT_TYPE_TAB_COLLAPSED_STATE_CHANGED, this, false); + ReferenceCounter.remove('d,kEVENT_TYPE_TAB_COLLAPSED_STATE_CHANGED,TSTWindow,false'); d.removeEventListener(this.kEVENT_TYPE_TABBAR_POSITION_CHANGED, this, false); + ReferenceCounter.remove('d,kEVENT_TYPE_TABBAR_POSITION_CHANGED,TSTWindow,false'); d.removeEventListener(this.kEVENT_TYPE_TABBAR_STATE_CHANGED, this, false); + ReferenceCounter.remove('d,kEVENT_TYPE_TABBAR_STATE_CHANGED,TSTWindow,false'); d.removeEventListener(this.kEVENT_TYPE_FOCUS_NEXT_TAB, this, false); + ReferenceCounter.remove('d,kEVENT_TYPE_FOCUS_NEXT_TAB,TSTWindow,false'); w.removeEventListener('beforecustomization', this, true); + ReferenceCounter.remove('w,beforecustomization,TSTWindow,true'); w.removeEventListener('aftercustomization', this, false); + ReferenceCounter.remove('w,aftercustomization,TSTWindow,false'); w.messageManager.removeMessageListener('SessionStore:restoreTabContentStarted', this); @@ -603,14 +632,19 @@ TreeStyleTabWindow.prototype = inherit(TreeStyleTabBase, { for (let i = 0, maxi = this._tabFocusAllowance.length; i < maxi; i++) { w.removeEventListener(this.kEVENT_TYPE_FOCUS_NEXT_TAB, this._tabFocusAllowance[i], false); + ReferenceCounter.remove('w,kEVENT_TYPE_FOCUS_NEXT_TAB,_tabFocusAllowance['+i+'],false'); } var appcontent = d.getElementById('appcontent'); appcontent.removeEventListener('SubBrowserAdded', this, false); + ReferenceCounter.remove('appcontent,SubBrowserAdded,TSTWindow,false'); appcontent.removeEventListener('SubBrowserRemoveRequest', this, false); + ReferenceCounter.remove('appcontent,SubBrowserRemoveRequest,TSTWindow,false'); w.removeEventListener('UIOperationHistoryUndo:TabbarOperations', this, false); + ReferenceCounter.remove('w,UIOperationHistoryUndo:TabbarOperations,TSTWindow,false'); w.removeEventListener('UIOperationHistoryRedo:TabbarOperations', this, false); + ReferenceCounter.remove('w,UIOperationHistoryRedo:TabbarOperations,TSTWindow,false'); prefs.removePrefListener(this); } @@ -752,9 +786,13 @@ TreeStyleTabWindow.prototype = inherit(TreeStyleTabBase, { if (!this.keyEventListening) { let w = this.window; w.addEventListener('keydown', this, true); + ReferenceCounter.add('w,keydown,TSTWindow,true'); w.addEventListener('keyup', this, true); + ReferenceCounter.add('w,keyup,TSTWindow,true'); w.addEventListener('keypress', this, true); + ReferenceCounter.add('w,keypress,TSTWindow,true'); w.addEventListener('blur', this, true); + ReferenceCounter.add('w,blur,TSTWindow,true'); this.keyEventListening = true; } this.keyEventListeningFlags |= aReason; @@ -768,9 +806,13 @@ TreeStyleTabWindow.prototype = inherit(TreeStyleTabBase, { if (!this.keyEventListeningFlags && this.keyEventListening) { let w = this.window; w.removeEventListener('keydown', this, true); + ReferenceCounter.remove('w,keydown,TSTWindow,true'); w.removeEventListener('keyup', this, true); + ReferenceCounter.remove('w,keyup,TSTWindow,true'); w.removeEventListener('keypress', this, true); + ReferenceCounter.remove('w,keypress,TSTWindow,true'); w.removeEventListener('blur', this, true); + ReferenceCounter.remove('w,blur,TSTWindow,true'); this.keyEventListening = false; } }, @@ -964,6 +1006,7 @@ TreeStyleTabWindow.prototype = inherit(TreeStyleTabBase, { aEvent.currentTarget.setCapture(true); aEvent.currentTarget.addEventListener('mousemove', this, false); + ReferenceCounter.add('currentTarget,mousemove,TSTWindow,false'); var b = this.getTabBrowserFromChild(aEvent.currentTarget); var box = aEvent.currentTarget.id == 'treestyletab-tabbar-resizer-splitter' ? @@ -987,6 +1030,7 @@ TreeStyleTabWindow.prototype = inherit(TreeStyleTabBase, { target.releaseCapture(); target.removeEventListener('mousemove', this, false); + ReferenceCounter.remove('currentTarget,mousemove,TSTWindow,false'); this.tabbarResizeStartWidth = -1; this.tabbarResizeStartHeight = -1; @@ -1719,6 +1763,7 @@ TreeStyleTabWindow.prototype = inherit(TreeStyleTabBase, { } }; this.window.addEventListener(this.kEVENT_TYPE_FOCUS_NEXT_TAB, listener, false); + ReferenceCounter.add('window,kEVENT_TYPE_FOCUS_NEXT_TAB,listener,false'); this._tabFocusAllowance.push(listener); }, _tabFocusAllowance : [],