Suppress errors from operations for already closed windows or tabs

This commit is contained in:
Piro / SHIMODA Hiroshi 2012-08-05 02:53:57 +09:00
parent 6c64656446
commit 7063c166d1

View File

@ -237,6 +237,9 @@ TreeStyleTabBrowser.prototype = {
}, },
_changeTabbarPosition : function TSTBrowser_changeTabbarPosition(aNewPosition) _changeTabbarPosition : function TSTBrowser_changeTabbarPosition(aNewPosition)
{ {
if (this.deferredTasks['_changeTabbarPosition'])
this.deferredTasks['_changeTabbarPosition'].cancel();
var oldPosition = this.position; var oldPosition = this.position;
this.fireTabbarPositionEvent(true, oldPosition, aNewPosition); this.fireTabbarPositionEvent(true, oldPosition, aNewPosition);
@ -244,10 +247,12 @@ TreeStyleTabBrowser.prototype = {
this.reinitAllTabs(); this.reinitAllTabs();
var self = this; var self = this;
this.Deferred.next(function() { (this.deferredTasks['_changeTabbarPosition'] = this.Deferred.next(function() {
self.checkTabsIndentOverflow(); self.checkTabsIndentOverflow();
self.fireTabbarPositionEvent(false, oldPosition, aNewPosition); self.fireTabbarPositionEvent(false, oldPosition, aNewPosition);
}).error(this.defaultDeferredErrorHandler); })).error(this.defaultDeferredErrorHandler).next(function() {
delete self.deferredTasks['_changeTabbarPosition'];
});
}, },
/* status getters */ /* status getters */
@ -477,10 +482,14 @@ TreeStyleTabBrowser.prototype = {
style.setProperty('margin-top', (- height * (maxRow - row))+'px', 'important'); style.setProperty('margin-top', (- height * (maxRow - row))+'px', 'important');
style.top = style.bottom = ''; style.top = style.bottom = '';
if (aJustNow) if (aJustNow) {
this.Deferred.next(function() { // "transition" must be cleared after the reflow. let key = 'positionPinnedTabs_tab_'+parseInt(Math.random() * 65000);
(this.deferredTasks[key] = this.Deferred.next(function() { // "transition" must be cleared after the reflow.
style.MozTransition = style.transition = transitionStyleBackup; style.MozTransition = style.transition = transitionStyleBackup;
}).error(this.defaultDeferredErrorHandler); })).error(this.defaultDeferredErrorHandler).next(function() {
delete self.deferredTasks[key];
});
}
col++; col++;
if (col >= maxCol) { if (col >= maxCol) {
@ -491,24 +500,27 @@ TreeStyleTabBrowser.prototype = {
}, },
positionPinnedTabsWithDelay : function TSTBrowser_positionPinnedTabsWithDelay() positionPinnedTabsWithDelay : function TSTBrowser_positionPinnedTabsWithDelay()
{ {
if (this._positionPinnedTabsWithDelayTimer) if (this.deferredTasks['positionPinnedTabsWithDelay'])
return; return;
var args = Array.slice(arguments); var args = Array.slice(arguments);
var lastArgs = this._positionPinnedTabsWithDelayTimerArgs || [null, null, false]; var lastArgs = this.deferredTasks['positionPinnedTabsWithDelay'] ?
this.deferredTasks['positionPinnedTabsWithDelay'].__treestyletab__args :
[null, null, false] ;
lastArgs[0] = lastArgs[0] || args[0]; lastArgs[0] = lastArgs[0] || args[0];
lastArgs[1] = lastArgs[1] || args[1]; lastArgs[1] = lastArgs[1] || args[1];
lastArgs[2] = lastArgs[2] || args[2]; lastArgs[2] = lastArgs[2] || args[2];
this._positionPinnedTabsWithDelayTimerArgs = lastArgs;
this._positionPinnedTabsWithDelayTimer = this.window.setTimeout(function(aSelf) { var self = this;
aSelf.Deferred.next(function() { (this.deferredTasks['positionPinnedTabsWithDelay'] = this.Deferred.wait(0).next(function() {
return self.Deferred.next(function() {
// do with delay again, after Firefox's reposition was completely finished. // do with delay again, after Firefox's reposition was completely finished.
aSelf.positionPinnedTabs.apply(aSelf, aSelf._positionPinnedTabsWithDelayTimerArgs); self.positionPinnedTabs.apply(self, lastArgs);
}).error(aSelf.defaultDeferredErrorHandler); });
aSelf._positionPinnedTabsWithDelayTimer = null; })).error(this.defaultDeferredErrorHandler).next(function() {
aSelf._positionPinnedTabsWithDelayTimerArgs = null; delete self.deferredTasks['positionPinnedTabsWithDelay'];
}, 0, this); });
this.deferredTasks['positionPinnedTabsWithDelay'].__treestyletab__args = lastArgs;
}, },
resetPinnedTabs : function TSTBrowser_resetPinnedTabs() resetPinnedTabs : function TSTBrowser_resetPinnedTabs()
@ -574,6 +586,8 @@ TreeStyleTabBrowser.prototype = {
init : function TSTBrowser_init() init : function TSTBrowser_init()
{ {
this.id = Date.now() + '-' + parseInt(Math.random() * 65000);
this.stopRendering(); this.stopRendering();
var w = this.window; var w = this.window;
@ -584,6 +598,8 @@ TreeStyleTabBrowser.prototype = {
if (b.tabContainer.parentNode.localName == 'toolbar') if (b.tabContainer.parentNode.localName == 'toolbar')
b.tabContainer.parentNode.classList.add(this.kTABBAR_TOOLBAR); b.tabContainer.parentNode.classList.add(this.kTABBAR_TOOLBAR);
this.deferredTasks = {};
this.tabsHash = {}; this.tabsHash = {};
this.tabVisibilityChangedTabs = []; this.tabVisibilityChangedTabs = [];
this._updateFloatingTabbarReason = 0; this._updateFloatingTabbarReason = 0;
@ -688,8 +704,11 @@ TreeStyleTabBrowser.prototype = {
this.startRendering(); this.startRendering();
if (this.deferredTasks['init'])
this.deferredTasks['init'].cancel();
var self = this; var self = this;
this.Deferred.next(function() { (this.deferredTasks['init'] = this.Deferred.next(function() {
// On Firefox 12 and later, this command is always enabled // On Firefox 12 and later, this command is always enabled
// and the TabsOnTop can be enabled by <tabbrowser>.updateVisibility(). // and the TabsOnTop can be enabled by <tabbrowser>.updateVisibility().
// So we have to reset TabsOnTop state on the startup. // So we have to reset TabsOnTop state on the startup.
@ -700,6 +719,8 @@ TreeStyleTabBrowser.prototype = {
if (TabsOnTop.enabled && TabsOnTop.toggle) if (TabsOnTop.enabled && TabsOnTop.toggle)
TabsOnTop.toggle(); TabsOnTop.toggle();
} }
})).error(this.defaultDeferredErrorHandler).next(function() {
delete self.deferredTasks['init'];
}); });
}, },
@ -830,13 +851,18 @@ TreeStyleTabBrowser.prototype = {
initTab : function TSTBrowser_initTab(aTab) initTab : function TSTBrowser_initTab(aTab)
{ {
if (!aTab.parentNode) return; // do nothing for closed tab!
if (!aTab.hasAttribute(this.kID)) { if (!aTab.hasAttribute(this.kID)) {
let id = this.getTabValue(aTab, this.kID) || this.makeNewId(); let id = this.getTabValue(aTab, this.kID) || this.makeNewId();
aTab.setAttribute(this.kID, id); aTab.setAttribute(this.kID, id);
aTab.setAttribute(this.kSUBTREE_COLLAPSED, true); aTab.setAttribute(this.kSUBTREE_COLLAPSED, true);
aTab.setAttribute(this.kALLOW_COLLAPSE, true); aTab.setAttribute(this.kALLOW_COLLAPSE, true);
let self = this; let self = this;
this.Deferred.next(function() { let key = 'initTab_'+id;
if (this.deferredTasks[key])
this.deferredTasks[key].cancel();
(this.deferredTasks[key] = this.Deferred.next(function() {
// changed by someone! // changed by someone!
if (aTab.getAttribute(self.kID) != id) if (aTab.getAttribute(self.kID) != id)
return; return;
@ -846,7 +872,9 @@ TreeStyleTabBrowser.prototype = {
if (!(id in self.tabsHash)) if (!(id in self.tabsHash))
self.tabsHash[id] = aTab; self.tabsHash[id] = aTab;
} }
}).error(this.defaultDeferredErrorHandler); })).error(this.defaultDeferredErrorHandler).next(function() {
delete self.deferredTasks[key];
});
if (!(id in this.tabsHash)) if (!(id in this.tabsHash))
this.tabsHash[id] = aTab; this.tabsHash[id] = aTab;
} }
@ -899,6 +927,8 @@ TreeStyleTabBrowser.prototype = {
initTabAttributes : function TSTBrowser_initTabAttributes(aTab) initTabAttributes : function TSTBrowser_initTabAttributes(aTab)
{ {
if (!aTab.parentNode) return; // do nothing for closed tab!
var pos = this.position; var pos = this.position;
if (pos == 'left' || pos == 'right') { if (pos == 'left' || pos == 'right') {
aTab.setAttribute('align', 'stretch'); aTab.setAttribute('align', 'stretch');
@ -922,6 +952,8 @@ TreeStyleTabBrowser.prototype = {
initTabContents : function TSTBrowser_initTabContents(aTab) initTabContents : function TSTBrowser_initTabContents(aTab)
{ {
if (!aTab.parentNode) return; // do nothing for closed tab!
var d = this.document; var d = this.document;
var twisty = this.getTabTwisty(aTab); var twisty = this.getTabTwisty(aTab);
@ -966,6 +998,8 @@ TreeStyleTabBrowser.prototype = {
initTabContentsOrder : function TSTBrowser_initTabContentsOrder(aTab, aForce) initTabContentsOrder : function TSTBrowser_initTabContentsOrder(aTab, aForce)
{ {
if (!aTab.parentNode) return; // do nothing for closed tab!
var d = this.document; var d = this.document;
var namedNodes = { var namedNodes = {
@ -1080,7 +1114,8 @@ TreeStyleTabBrowser.prototype = {
node.style.visibility = 'hidden'; node.style.visibility = 'hidden';
node.style.position = 'fixed'; node.style.position = 'fixed';
} }
this.Deferred.wait(0.1).next(function() { let key = 'initTabContentsOrderInternal_'+parseInt(Math.random() * 65000);
(this.deferredTasks[key] = this.Deferred.wait(0.1).next(function() {
for (let i = 0, maxi = nodes.length; i < maxi; i++) for (let i = 0, maxi = nodes.length; i < maxi; i++)
{ {
let node = nodes[i]; let node = nodes[i];
@ -1088,14 +1123,17 @@ TreeStyleTabBrowser.prototype = {
if (shouldHideTemporaryState) if (shouldHideTemporaryState)
node.style.visibility = ''; node.style.visibility = '';
} }
}).error(this.defaultDeferredErrorHandler); })).error(this.defaultDeferredErrorHandler).next(function() {
delete self.deferredTasks[key];
});
} }
}, },
updateInvertedTabContentsOrder : function TSTBrowser_updateInvertedTabContentsOrder(aTarget) updateInvertedTabContentsOrder : function TSTBrowser_updateInvertedTabContentsOrder(aTarget)
{ {
var self = this; var self = this;
this.Deferred.next(function() { let key = 'updateInvertedTabContentsOrder_'+parseInt(Math.random() * 65000);
(this.deferredTasks[key] = this.Deferred.next(function() {
var b = self.mTabBrowser; var b = self.mTabBrowser;
var tabs = !aTarget ? var tabs = !aTarget ?
[b.selectedTab] : [b.selectedTab] :
@ -1108,7 +1146,9 @@ TreeStyleTabBrowser.prototype = {
{ {
self.initTabContentsOrder(tabs[i]); self.initTabContentsOrder(tabs[i]);
} }
}).error(this.defaultDeferredErrorHandler); })).error(this.defaultDeferredErrorHandler).next(function() {
delete self.deferredTasks[key];
});
}, },
initTabbar : function TSTBrowser_initTabbar(aNewPosition, aOldPosition) initTabbar : function TSTBrowser_initTabbar(aNewPosition, aOldPosition)
@ -1366,8 +1406,11 @@ TreeStyleTabBrowser.prototype = {
this.updateTabbarState(false); this.updateTabbarState(false);
if (this.deferredTasks['initTabbar'])
this.deferredTasks['initTabbar'].cancel();
var self = this; var self = this;
this.Deferred.next(function() { (this.deferredTasks['initTabbar'] = this.Deferred.next(function() {
delayedPostProcess(self, b, splitter, toggler); delayedPostProcess(self, b, splitter, toggler);
self.updateTabbarOverflow(); self.updateTabbarOverflow();
self.updateAllTabsButton(b); self.updateAllTabsButton(b);
@ -1380,7 +1423,9 @@ TreeStyleTabBrowser.prototype = {
self.mTabBrowser.dispatchEvent(event); self.mTabBrowser.dispatchEvent(event);
self.startRendering(); self.startRendering();
}).error(this.defaultDeferredErrorHandler); })).error(this.defaultDeferredErrorHandler).next(function() {
delete self.deferredTasks['initTabbar'];
});
pos = null; pos = null;
scrollFrame = null; scrollFrame = null;
@ -1526,9 +1571,13 @@ TreeStyleTabBrowser.prototype = {
// is modified dynamically. So, we don' have to do it before // is modified dynamically. So, we don' have to do it before
// the browser window is completely initialized. // the browser window is completely initialized.
TabsOnTop.enabled = !currentState; TabsOnTop.enabled = !currentState;
this.Deferred.next(function() { if (this.deferredTasks['updateTabbarState_TabsOnTop'])
this.deferredTasks['updateTabbarState_TabsOnTop'].cancel();
(this.deferredTasks['updateTabbarState_TabsOnTop'] = this.Deferred.next(function() {
TabsOnTop.enabled = currentState; TabsOnTop.enabled = currentState;
}).error(this.defaultDeferredErrorHandler); })).error(this.defaultDeferredErrorHandler).next(function() {
delete self.deferredTasks['updateTabbarState_TabsOnTop'];
});
} }
} }
} }
@ -1557,11 +1606,15 @@ TreeStyleTabBrowser.prototype = {
this.Deferred.next(updateTabsOnTop); this.Deferred.next(updateTabsOnTop);
} }
this.Deferred.next(function() { if (this.deferredTasks['updateTabbarState'])
this.deferredTasks['updateTabbarState'].cancel();
(this.deferredTasks['updateTabbarState'] = this.Deferred.next(function() {
self.updateFloatingTabbar(self.kTABBAR_UPDATE_BY_APPEARANCE_CHANGE); self.updateFloatingTabbar(self.kTABBAR_UPDATE_BY_APPEARANCE_CHANGE);
self._fireTabbarStateChangedEvent(); self._fireTabbarStateChangedEvent();
self.startRendering(); self.startRendering();
}).error(this.defaultDeferredErrorHandler); })).error(this.defaultDeferredErrorHandler).next(function() {
delete self.deferredTasks['updateTabbarState'];
});
var allowToCollapse = this.getTreePref('allowSubtreeCollapseExpand.'+orient); var allowToCollapse = this.getTreePref('allowSubtreeCollapseExpand.'+orient);
if (this.allowSubtreeCollapseExpand != allowToCollapse) if (this.allowSubtreeCollapseExpand != allowToCollapse)
@ -1883,6 +1936,13 @@ TreeStyleTabBrowser.prototype = {
{ {
this.animationManager.removeTask(this.smoothScrollTask); this.animationManager.removeTask(this.smoothScrollTask);
Object.keys(this.deferredTasks).forEach(function(key) {
if (this.deferredTasks[key].cancel) {
this.deferredTasks[key].cancel();
delete this.deferredTasks[key];
}
}, this);
this.autoHide.destroy(); this.autoHide.destroy();
delete this._autoHide; delete this._autoHide;
@ -2340,17 +2400,25 @@ TreeStyleTabBrowser.prototype = {
case 'extensions.treestyletab.counter.role.horizontal': case 'extensions.treestyletab.counter.role.horizontal':
if (!this.isVertical) { if (!this.isVertical) {
let self = this; let self = this;
this.Deferred if (this.deferredTasks[aPrefName])
.next(function() { self.updateAllTabsCount(); }) this.deferredTasks[aPrefName].cancel();
.error(this.defaultDeferredErrorHandler); (this.deferredTasks[aPrefName] = this.Deferred
.next(function() { self.updateAllTabsCount(); }))
.error(this.defaultDeferredErrorHandler).next(function() {
delete self.deferredTasks[aPrefName];
});
} }
return; return;
case 'extensions.treestyletab.counter.role.vertical': case 'extensions.treestyletab.counter.role.vertical':
if (this.isVertical) { if (this.isVertical) {
let self = this; let self = this;
this.Deferred if (this.deferredTasks[aPrefName])
.next(function() { self.updateAllTabsCount(); }) this.deferredTasks[aPrefName].cancel();
.error(this.defaultDeferredErrorHandler); (this.deferredTasks[aPrefName] = this.Deferred
.next(function() { self.updateAllTabsCount(); }))
.error(this.defaultDeferredErrorHandler).next(function() {
delete self.deferredTasks[aPrefName];
});
} }
return; return;
@ -2603,19 +2671,19 @@ TreeStyleTabBrowser.prototype = {
} }
this.clearLastScrollPosition(); this.clearLastScrollPosition();
if (this.cancelingPerformingAutoScroll) if (this.deferredTasks['cancelPerformingAutoScroll'])
this.cancelingPerformingAutoScroll.cancel(); this.deferredTasks['cancelPerformingAutoScroll'].cancel();
var self = this; var self = this;
this.cancelingPerformingAutoScroll = this.Deferred.wait(0.3).next(function() { (this.deferredTasks['cancelPerformingAutoScroll'] = this.Deferred.wait(0.3).next(function() {
self.cancelingPerformingAutoScroll = null; delete self.deferredTasks['cancelPerformingAutoScroll'];
}).error(this.defaultDeferredErrorHandler); })).error(this.defaultDeferredErrorHandler);
}, },
shouldCancelEnsureElementIsVisible : function TSTBRowser_shouldCancelEnsureElementIsVisible() shouldCancelEnsureElementIsVisible : function TSTBRowser_shouldCancelEnsureElementIsVisible()
{ {
return ( return (
this.cancelingPerformingAutoScroll && this.deferredTasks['cancelPerformingAutoScroll'] &&
(new Error()).stack.indexOf('onxblDOMMouseScroll') < 0 (new Error()).stack.indexOf('onxblDOMMouseScroll') < 0
); );
}, },
@ -2744,12 +2812,16 @@ TreeStyleTabBrowser.prototype = {
scrollToNewTab : function TSTBrowser_scrollToNewTab(aTab) scrollToNewTab : function TSTBrowser_scrollToNewTab(aTab)
{ {
if (!aTab.parentNode) return; // do nothing for closed tab!
if (this.scrollToNewTabMode > 0) if (this.scrollToNewTabMode > 0)
this.scrollToTab(aTab, this.scrollToNewTabMode < 2); this.scrollToTab(aTab, this.scrollToNewTabMode < 2);
}, },
updateInsertionPositionInfo : function TSTBrowser_updateInsertionPositionInfo(aTab) updateInsertionPositionInfo : function TSTBrowser_updateInsertionPositionInfo(aTab)
{ {
if (!aTab.parentNode) return; // do nothing for closed tab!
var prev = this.getPreviousSiblingTab(aTab); var prev = this.getPreviousSiblingTab(aTab);
if (prev) { if (prev) {
this.setTabValue(aTab, this.kINSERT_AFTER, prev.getAttribute(this.kID)); this.setTabValue(aTab, this.kINSERT_AFTER, prev.getAttribute(this.kID));
@ -2887,12 +2959,16 @@ TreeStyleTabBrowser.prototype = {
this.detachTab(tab, { dontUpdateIndent : true }); this.detachTab(tab, { dontUpdateIndent : true });
if (shouldCloseParentTab) { if (shouldCloseParentTab) {
this.Deferred.next(function() { let key = 'onTabClose_'+parseInt(Math.random() * 65000);
let self = this;
(this.deferredTasks[key] = this.Deferred.next(function() {
if (parentTab.parentNode) if (parentTab.parentNode)
b.removeTab(parentTab, { animate : true }); b.removeTab(parentTab, { animate : true });
parentTab = null; parentTab = null;
b = null; b = null;
}).error(this.defaultDeferredErrorHandler); })).error(this.defaultDeferredErrorHandler).next(function() {
delete self.deferredTasks[key];
});
} }
} }
else if (!nextFocusedTab) { else if (!nextFocusedTab) {
@ -2950,7 +3026,7 @@ TreeStyleTabBrowser.prototype = {
_reserveCloseNeedlessGroupTabSibling : function TSTBrowser_reserveCloseNeedlessGroupTabSibling(aTab) _reserveCloseNeedlessGroupTabSibling : function TSTBrowser_reserveCloseNeedlessGroupTabSibling(aTab)
{ {
if (!aTab) if (!aTab || !aTab.parentNode)
return null; return null;
var parent = this.getParentTab(aTab); var parent = this.getParentTab(aTab);
@ -2987,13 +3063,16 @@ TreeStyleTabBrowser.prototype = {
trees.forEach(this.markAsClosedSet, this); trees.forEach(this.markAsClosedSet, this);
var self = this; var self = this;
this.Deferred.next(function() { let key = 'onTabClosing_'+parseInt(Math.random() * 65000);
(this.deferredTasks[key] = this.Deferred.next(function() {
for (let i = 0, maxi = trees.length; i < maxi; i++) for (let i = 0, maxi = trees.length; i < maxi; i++)
{ {
let tabs = trees[i]; let tabs = trees[i];
self.fireTabSubtreeClosedEvent(b, tabs[0], tabs); self.fireTabSubtreeClosedEvent(b, tabs[0], tabs);
} }
}).error(this.defaultDeferredErrorHandler); })).error(this.defaultDeferredErrorHandler).next(function() {
delete self.deferredTasks[key];
});
return true; return true;
}, },
@ -3148,6 +3227,8 @@ TreeStyleTabBrowser.prototype = {
updateChildrenArray : function TSTBrowser_updateChildrenArray(aTab) updateChildrenArray : function TSTBrowser_updateChildrenArray(aTab)
{ {
if (!aTab.parentNode) return; // do nothing for closed tab!
var children = this.getChildTabs(aTab); var children = this.getChildTabs(aTab);
children.sort(this.sortTabsByOrder); children.sort(this.sortTabsByOrder);
this.setTabValue( this.setTabValue(
@ -3165,6 +3246,7 @@ TreeStyleTabBrowser.prototype = {
rearrangeTabViewItems : function TSTBrowser_rearrangeTabViewItems(aTab) rearrangeTabViewItems : function TSTBrowser_rearrangeTabViewItems(aTab)
{ {
if ( if (
!aTab.parentNode || // do nothing for closed tab!
!aTab.tabItem || !aTab.tabItem ||
!aTab.tabItem.parent || !aTab.tabItem.parent ||
!aTab.tabItem.parent.reorderTabItemsBasedOnTabOrder !aTab.tabItem.parent.reorderTabItemsBasedOnTabOrder
@ -3393,13 +3475,16 @@ TreeStyleTabBrowser.prototype = {
* On this timing, the next "SSTabRestoring" is not fired yet. * On this timing, the next "SSTabRestoring" is not fired yet.
* We only register the countdown task for the next event loop. * We only register the countdown task for the next event loop.
*/ */
self.windowService.Deferred.next(function() { let key = 'onTabRestoring_'+parseInt(Math.random() * 65000);
(self.deferredTasks[key] = self.windowService.Deferred.next(function() {
/** /**
* On this timing, the next "SSTabRestoring" was fired. * On this timing, the next "SSTabRestoring" was fired.
* Now we can decrement the counter. * Now we can decrement the counter.
*/ */
self.windowService.restoringCount--; self.windowService.restoringCount--;
}).error(self.defaultDeferredErrorHandler); })).error(self.defaultDeferredErrorHandler).next(function() {
delete self.deferredTasks[key];
});
}, 0); }, 0);
if (!tab.selected && if (!tab.selected &&
@ -3734,6 +3819,8 @@ TreeStyleTabBrowser.prototype = {
correctChildTabsOrder : function TSTBrowser_correctChildTabsOrder(aTab) correctChildTabsOrder : function TSTBrowser_correctChildTabsOrder(aTab)
{ {
if (!aTab.parentNode) return; // do nothing for closed tab!
var restoringChildren = aTab.getAttribute(this.kCHILDREN_RESTORING); var restoringChildren = aTab.getAttribute(this.kCHILDREN_RESTORING);
if (!restoringChildren) return; if (!restoringChildren) return;
@ -4044,7 +4131,7 @@ TreeStyleTabBrowser.prototype = {
}, },
handleNewActiveTab : function TSTBrowser_handleNewActiveTab(aTab, aOptions) handleNewActiveTab : function TSTBrowser_handleNewActiveTab(aTab, aOptions)
{ {
if (this.doingCollapseExpand || !aTab) return; if (this.doingCollapseExpand || !aTab || !aTab.parentNode) return;
aOptions = aOptions || {}; aOptions = aOptions || {};
@ -4498,10 +4585,12 @@ TreeStyleTabBrowser.prototype = {
return; return;
this.windowService.tabsOnTopChangingByUI = true; this.windowService.tabsOnTopChangingByUI = true;
var self = this; var self = this;
this.Deferred if (this.deferredTasks['onTabsOnTopSyncCommand'])
this.deferredTasks['onTabsOnTopSyncCommand'].cancel();
(this.deferredTasks['onTabsOnTopSyncCommand'] = this.Deferred
.next(function() { .next(function() {
self.windowService.toggleFixed(self.mTabBrowser); self.windowService.toggleFixed(self.mTabBrowser);
}) }))
.next(function() { .next(function() {
if (self.window.TabsOnTop.enabled != aEnabled) if (self.window.TabsOnTop.enabled != aEnabled)
self.window.TabsOnTop.enabled = aEnabled; self.window.TabsOnTop.enabled = aEnabled;
@ -4509,6 +4598,7 @@ TreeStyleTabBrowser.prototype = {
.error(this.defaultDeferredErrorHandler) .error(this.defaultDeferredErrorHandler)
.next(function() { .next(function() {
self.windowService.tabsOnTopChangingByUI = false; self.windowService.tabsOnTopChangingByUI = false;
delete self.deferredTasks['onTabsOnTopSyncCommand'];
}); });
}, },
@ -4528,6 +4618,8 @@ TreeStyleTabBrowser.prototype = {
resetTab : function TSTBrowser_resetTab(aTab, aDetachAllChildren) resetTab : function TSTBrowser_resetTab(aTab, aDetachAllChildren)
{ {
if (!aTab.parentNode) return; // do nothing for closed tab!
if (aDetachAllChildren) if (aDetachAllChildren)
this.detachAllChildren(aTab, { this.detachAllChildren(aTab, {
dontUpdateIndent : true, dontUpdateIndent : true,
@ -4545,6 +4637,8 @@ TreeStyleTabBrowser.prototype = {
resetTabState : function TSTBrowser_resetTabState(aTab) resetTabState : function TSTBrowser_resetTabState(aTab)
{ {
if (!aTab.parentNode) return; // do nothing for closed tab!
aTab.removeAttribute(this.kID); aTab.removeAttribute(this.kID);
aTab.removeAttribute(this.kID_RESTORING); aTab.removeAttribute(this.kID_RESTORING);
aTab.removeAttribute(this.kPARENT); aTab.removeAttribute(this.kPARENT);
@ -4633,6 +4727,8 @@ TreeStyleTabBrowser.prototype = {
attachTabTo : function TSTBrowser_attachTabTo(aChild, aParent, aInfo) /* PUBLIC API */ attachTabTo : function TSTBrowser_attachTabTo(aChild, aParent, aInfo) /* PUBLIC API */
{ {
if (!aChild.parentNode || (aParent && !aParent.parentNode)) return; // do nothing for closed tab!
aInfo = aInfo || {}; aInfo = aInfo || {};
if (aParent && this.maxTreeLevelPhisical && this.maxTreeLevel > -1) { if (aParent && this.maxTreeLevelPhisical && this.maxTreeLevel > -1) {
@ -4798,7 +4894,7 @@ TreeStyleTabBrowser.prototype = {
detachTab : function TSTBrowser_detachTab(aChild, aInfo) /* PUBLIC API */ detachTab : function TSTBrowser_detachTab(aChild, aInfo) /* PUBLIC API */
{ {
if (!aChild) return; if (!aChild || !aChild.parentNode) return;
if (!aInfo) aInfo = {}; if (!aInfo) aInfo = {};
var parentTab = this.getParentTab(aChild); var parentTab = this.getParentTab(aChild);
@ -4851,6 +4947,8 @@ TreeStyleTabBrowser.prototype = {
detachAllChildren : function TSTBrowser_detachAllChildren(aTab, aInfo) detachAllChildren : function TSTBrowser_detachAllChildren(aTab, aInfo)
{ {
if (!aTab.parentNode) return; // do nothing for closed tab!
aInfo = aInfo || {}; aInfo = aInfo || {};
if (!('behavior' in aInfo)) if (!('behavior' in aInfo))
aInfo.behavior = this.kCLOSE_PARENT_BEHAVIOR_SIMPLY_DETACH_ALL_CHILDREN; aInfo.behavior = this.kCLOSE_PARENT_BEHAVIOR_SIMPLY_DETACH_ALL_CHILDREN;
@ -5011,6 +5109,8 @@ TreeStyleTabBrowser.prototype = {
updateTabIndent : function TSTBrowser_updateTabIndent(aTab, aIndent, aJustNow) updateTabIndent : function TSTBrowser_updateTabIndent(aTab, aIndent, aJustNow)
{ {
if (!aTab.parentNode) return; // do nothing for closed tab!
this.stopTabIndentAnimation(aTab); this.stopTabIndentAnimation(aTab);
if (aTab.hasAttribute('pinned')) if (aTab.hasAttribute('pinned'))
@ -5101,6 +5201,8 @@ TreeStyleTabBrowser.prototype = {
}, },
stopTabIndentAnimation : function TSTBrowser_stopTabIndentAnimation(aTab) stopTabIndentAnimation : function TSTBrowser_stopTabIndentAnimation(aTab)
{ {
if (!aTab.parentNode) return; // do nothing for closed tab!
this.animationManager.removeTask( this.animationManager.removeTask(
aTab.__treestyletab__updateTabIndentTask aTab.__treestyletab__updateTabIndentTask
); );
@ -5186,6 +5288,8 @@ TreeStyleTabBrowser.prototype = {
updateCanCollapseSubtree : function TSTBrowser_updateCanCollapseSubtree(aTab, aLevel) updateCanCollapseSubtree : function TSTBrowser_updateCanCollapseSubtree(aTab, aLevel)
{ {
if (!aTab.parentNode) return; // do nothing for closed tab!
if ( if (
!aLevel || !aLevel ||
this.maxTreeLevel < 0 || this.maxTreeLevel < 0 ||
@ -5202,6 +5306,8 @@ TreeStyleTabBrowser.prototype = {
updateTabsCount : function TSTBrowser_updateTabsCount(aTab, aDontUpdateAncestor) updateTabsCount : function TSTBrowser_updateTabsCount(aTab, aDontUpdateAncestor)
{ {
if (!aTab.parentNode) return; // do nothing for closed tab!
var count = this.document.getAnonymousElementByAttribute(aTab, 'class', this.kCOUNTER); var count = this.document.getAnonymousElementByAttribute(aTab, 'class', this.kCOUNTER);
if (count) { if (count) {
let value = this.getDescendantTabs(aTab).length; let value = this.getDescendantTabs(aTab).length;
@ -5257,7 +5363,7 @@ TreeStyleTabBrowser.prototype = {
moveTabSubtreeTo : function TSTBrowser_moveTabSubtreeTo(aTab, aIndex) moveTabSubtreeTo : function TSTBrowser_moveTabSubtreeTo(aTab, aIndex)
{ {
if (!aTab) return; if (!aTab || !aTab.parentNode) return;
var b = this.mTabBrowser; var b = this.mTabBrowser;
this.subTreeMovingCount++; this.subTreeMovingCount++;
@ -5436,6 +5542,8 @@ TreeStyleTabBrowser.prototype = {
importTab : function TSTBrowser_importTab(aTab) importTab : function TSTBrowser_importTab(aTab)
{ {
if (!aTab.parentNode) return null; // do nothing for closed tab!
var newTab = this.mTabBrowser.addTab(); var newTab = this.mTabBrowser.addTab();
newTab.linkedBrowser.stop(); newTab.linkedBrowser.stop();
newTab.linkedBrowser.docShell; newTab.linkedBrowser.docShell;
@ -5446,6 +5554,8 @@ TreeStyleTabBrowser.prototype = {
duplicateTabAsOrphan : function TSTBrowser_duplicateTabAsOrphan(aTab) duplicateTabAsOrphan : function TSTBrowser_duplicateTabAsOrphan(aTab)
{ {
if (!aTab.parentNode) return null; // do nothing for closed tab!
var newTab = this.mTabBrowser.duplicateTab(aTab); var newTab = this.mTabBrowser.duplicateTab(aTab);
this.deleteTabValue(newTab, this.kCHILDREN); this.deleteTabValue(newTab, this.kCHILDREN);
this.deleteTabValue(newTab, this.kPARENT); this.deleteTabValue(newTab, this.kPARENT);
@ -5473,7 +5583,7 @@ TreeStyleTabBrowser.prototype = {
collapseExpandSubtree : function TSTBrowser_collapseExpandSubtree(aTab, aCollapse, aJustNow) /* PUBLIC API */ collapseExpandSubtree : function TSTBrowser_collapseExpandSubtree(aTab, aCollapse, aJustNow) /* PUBLIC API */
{ {
if (!aTab) return; if (!aTab || !aTab.parentNode) return;
if (this.isSubtreeCollapsed(aTab) == aCollapse) return; if (this.isSubtreeCollapsed(aTab) == aCollapse) return;
@ -5511,7 +5621,7 @@ TreeStyleTabBrowser.prototype = {
collapseExpandTab : function TSTBrowser_collapseExpandTab(aTab, aCollapse, aJustNow, aCallbackToRunOnStartAnimation) collapseExpandTab : function TSTBrowser_collapseExpandTab(aTab, aCollapse, aJustNow, aCallbackToRunOnStartAnimation)
{ {
if (!aTab || !this.getParentTab(aTab)) return; if (!aTab || !aTab.parentNode || !this.getParentTab(aTab)) return;
this.setTabValue(aTab, this.kCOLLAPSED, aCollapse); this.setTabValue(aTab, this.kCOLLAPSED, aCollapse);
this.updateTabCollapsed(aTab, aCollapse, aJustNow, aCallbackToRunOnStartAnimation); this.updateTabCollapsed(aTab, aCollapse, aJustNow, aCallbackToRunOnStartAnimation);
@ -5548,6 +5658,8 @@ TreeStyleTabBrowser.prototype = {
}, },
updateTabCollapsed : function TSTBrowser_updateTabCollapsed(aTab, aCollapsed, aJustNow, aCallbackToRunOnStartAnimation) updateTabCollapsed : function TSTBrowser_updateTabCollapsed(aTab, aCollapsed, aJustNow, aCallbackToRunOnStartAnimation)
{ {
if (!aTab.parentNode) return; // do nothing for closed tab!
this.stopTabCollapseAnimation(aTab); this.stopTabCollapseAnimation(aTab);
aTab.removeAttribute(this.kX_OFFSET); aTab.removeAttribute(this.kX_OFFSET);
@ -5724,6 +5836,8 @@ TreeStyleTabBrowser.prototype = {
kSTACKED_TAB_MARGIN : 15, kSTACKED_TAB_MARGIN : 15,
stopTabCollapseAnimation : function TSTBrowser_stopTabCollapseAnimation(aTab) stopTabCollapseAnimation : function TSTBrowser_stopTabCollapseAnimation(aTab)
{ {
if (!aTab.parentNode) return; // do nothing for closed tab!
this.animationManager.removeTask( this.animationManager.removeTask(
aTab.__treestyletab__updateTabCollapsedTask aTab.__treestyletab__updateTabCollapsedTask
); );
@ -5732,6 +5846,7 @@ TreeStyleTabBrowser.prototype = {
collapseExpandTreesIntelligentlyFor : function TSTBrowser_collapseExpandTreesIntelligentlyFor(aTab, aJustNow) collapseExpandTreesIntelligentlyFor : function TSTBrowser_collapseExpandTreesIntelligentlyFor(aTab, aJustNow)
{ {
if (!aTab || if (!aTab ||
!aTab.parentNode ||
this.doingCollapseExpand || this.doingCollapseExpand ||
!this.canCollapseSubtree(aTab)) !this.canCollapseSubtree(aTab))
return; return;
@ -5801,7 +5916,7 @@ TreeStyleTabBrowser.prototype = {
scrollTo : function TSTBrowser_scrollTo(aEndX, aEndY) scrollTo : function TSTBrowser_scrollTo(aEndX, aEndY)
{ {
if (this.cancelingPerformingAutoScroll) return; if (this.deferredTasks['cancelPerformingAutoScroll']) return;
if (this.animationEnabled || this.smoothScrollEnabled) { if (this.animationEnabled || this.smoothScrollEnabled) {
this.smoothScrollTo(aEndX, aEndY); this.smoothScrollTo(aEndX, aEndY);
@ -5844,8 +5959,8 @@ TreeStyleTabBrowser.prototype = {
this.smoothScrollTask = function(aTime, aBeginning, aChange, aDuration) { this.smoothScrollTask = function(aTime, aBeginning, aChange, aDuration) {
if (self.isDestroying) return true; if (self.isDestroying) return true;
var scrollBoxObject = self.scrollBoxObject; var scrollBoxObject = self.scrollBoxObject;
if (aTime >= aDuration || this.cancelingPerformingAutoScroll) { if (aTime >= aDuration || this.deferredTasks['cancelPerformingAutoScroll']) {
if (!this.cancelingPerformingAutoScroll) { if (!this.deferredTasks['cancelPerformingAutoScroll']) {
scrollBoxObject.scrollTo(aEndX, aEndY); scrollBoxObject.scrollTo(aEndX, aEndY);
/** /**
@ -5853,7 +5968,8 @@ TreeStyleTabBrowser.prototype = {
* if the scroll box was expanded. * if the scroll box was expanded.
*/ */
let oldSize = self._getMaxScrollSize(scrollBoxObject); let oldSize = self._getMaxScrollSize(scrollBoxObject);
self.Deferred.next(function() { let key = 'smoothScrollTo_'+parseInt(Math.random() * 65000);
(self.deferredTasks[key] = self.Deferred.next(function() {
let newSize = self._getMaxScrollSize(scrollBoxObject); let newSize = self._getMaxScrollSize(scrollBoxObject);
let lastTab = self.getLastVisibleTab(self.mTabBrowser); let lastTab = self.getLastVisibleTab(self.mTabBrowser);
if ( if (
@ -5870,7 +5986,9 @@ TreeStyleTabBrowser.prototype = {
self.smoothScrollTo(aEndX, aEndY, parseInt(aDuration * 0.5)); self.smoothScrollTo(aEndX, aEndY, parseInt(aDuration * 0.5));
self = null; self = null;
scrollBoxObject = null; scrollBoxObject = null;
}).error(self.defaultDeferredErrorHandler); })).error(this.defaultDeferredErrorHandler).next(function() {
delete self.deferredTasks[key];
});
} }
b = null; b = null;
@ -5945,6 +6063,8 @@ TreeStyleTabBrowser.prototype = {
scrollToTabSubtree : function TSTBrowser_scrollToTabSubtree(aTab) scrollToTabSubtree : function TSTBrowser_scrollToTabSubtree(aTab)
{ {
if (!aTab.parentNode) return; // do nothing for closed tab!
var b = this.mTabBrowser; var b = this.mTabBrowser;
var descendant = this.getDescendantTabs(aTab); var descendant = this.getDescendantTabs(aTab);
var parentTabBox = aTab.boxObject; var parentTabBox = aTab.boxObject;
@ -6001,17 +6121,17 @@ TreeStyleTabBrowser.prototype = {
if (!animateElement) if (!animateElement)
return; return;
if (this.lastNotifyBackgroundTabAnimation) if (this.deferredTasks['notifyBackgroundTab'])
this.lastNotifyBackgroundTabAnimation.cancel(); this.deferredTasks['notifyBackgroundTab'].cancel();
if (!animateElement.hasAttribute(attrName)) if (!animateElement.hasAttribute(attrName))
animateElement.setAttribute(attrName, 'ready'); animateElement.setAttribute(attrName, 'ready');
var self = this; var self = this;
this.lastNotifyBackgroundTabAnimation = this.Deferred (this.deferredTasks['notifyBackgroundTab'] = this.Deferred
.next(function() { .next(function() {
animateElement.setAttribute(attrName, 'notifying'); animateElement.setAttribute(attrName, 'notifying');
}) }))
.wait(0.15) .wait(0.15)
.next(function() { .next(function() {
animateElement.setAttribute(attrName, 'finish'); animateElement.setAttribute(attrName, 'finish');
@ -6019,9 +6139,10 @@ TreeStyleTabBrowser.prototype = {
.wait(1) .wait(1)
.next(function() { .next(function() {
animateElement.removeAttribute(attrName); animateElement.removeAttribute(attrName);
self.lastNotifyBackgroundTabAnimation = null;
}) })
.error(this.defaultDeferredErrorHandler); .error(this.defaultDeferredErrorHandler).next(function() {
delete self.deferredTasks['notifyBackgroundTab'];
});
}, },
restoreTree : function TSTBrowser_restoreTree() restoreTree : function TSTBrowser_restoreTree()