It appears that you are closing tabs inside a loop where you have stored the initial number of tabs len = tabs.length
and then comparing against the original number of tabs when the number of existing tabs may have changed due to your actions.
The construct:
for (let i = 2, len = tabs.length; i < len; i++) {...}
is more efficient under conditions where the length of tabs
will not change. However, in this case, you are changing the number of tabs and need to compare against tabs.length
each time you are checking the terminating condition for this loop. So:
for (let i = 2, len = tabs.length; i < len; i++) {...}
In fact, the only reason your current loop does not always fail is that window.gBrowser.removeTab()
is returning prior to the tab actually being deleted. You are in a race to see if you complete the loop prior to any tabs actually being removed.
However, that is not the only problem. You are removing the tab on which you are currently indexed. Under most conditions if the tab is removed, like most arrays, the remaining higher-index tabs are shifted down to be at the index you are already acting upon. The only reason that the current loop does not routinely skip every other tab is that window.gBrowser.removeTab()
returns prior to actually removing the tab you are currently indexed on. You only actually skip a tab on the occasions where you are seeing the undefined
error.
Your loop really should be something like:
for (let i = tabs.length - 1; i >=2; i--) {...}
This way you start at the end of the list and delete from there down. This prevents both the undefined
issue and the possibility of skipping a tab by eliminating the race condition of needing to complete the entire proces prior to any tab actually being removed.