A "too much recursion" error in Firefox only sometimes?

Viewed 77505

I have a pretty simple thing I'm doing with javascript and basically only sometimes will javascript give me a "too much recursion" error.

The code in question:

if(pageLoad===undefined){
  var pageLoad=function(){}; 
}
var pageLoad_uniqueid_11=pageLoad;
var pageLoad=function(){ 
  pageLoad_uniqueid_11();
  pageLoad_uniqueid_12(); 
};
var pageLoad_uniqueid_12=function(){
 alert('pageLoad');
};

$(document).ready(function(){
   pageLoad();
});

(yes I know there are better way of doing this. This is difficult to change though, especially because of ASP.Net partial postbacks which aren't shown).

Anyway, when the too much recursion error happens, it continues to happen until I restart Firefox. when I restart Firefox it all works as normal again. How do I fix this?

I've also made a jsbin example

Update

Ok I've found out how to reliably reproduce it in our code, but it doesn't work for the jsbin example. If I create a new tab and go to the same page(have two tabs of the same address) and then refresh the first tab two times then I get this error consistently. We are not using any kind of session or anything else that I can think of that could cause such a problem to only occur in one tab!

Update 2 Not as reliable as I thought, but it definitely only occurs when more than one tab of the same page is open. It'll occur every few reloads of one of the tabs open

I've also updated my code to show an alert when pageLoad(the if statement) is initially undefined and when it is initially defined. Somehow, both alerts are showing up. This code is not duplicated in the rendered page and there is no way that it is being called twice. It is in a top level script element not surrounded by a function or anything! My code ends up looking like

if(pageLoad===undefined){ 
  var pageLoad=function(){}; 
  alert('new'); 
} else {  
  alert('old'); 
}
5 Answers

This will also cause the "too much recursion" issue:

class account {
    constructor() {
        this.balance = 0;      // <-- property: balance
    }

    set balance( amount ) {    // <-- set function is the same name as the property.
        this.balance = amount; // <-- AND property: balance (unintended recursion here)
    }
}

var acc = new account();

Using unique names is important.

Ok, so why is this happening?

In the set function it isn't actually setting the property to amount, instead it's calling the set function again because in the scope of the set function it is the same syntax for both setting the property AND calling the set function.

Because in that scope this is the same as account and (account OR this).balance = amount can both call the set function OR set the property.

The solution to this is to simply change the name of either the property or the set function in any way (and of course update the rest of the code accordingly).

Related