OK, figured out the problem. There really was no recursion in my code. It is indeed possible to call JavaScript functions with hundreds of arguments if they are "varargs" functions like for example <array>.splice(...)
, which was my offender.
Aside: GWT implements the Java function System.arraycopy(...)
using the JavaScript splice function in a more-or-less clever way.
splice accepts an arbitrary number of input elements to insert into the target array. It is possible to pass these input elements from another array by using the following construct:
var arguments = [index, howmany].concat(elements);
Arrays.prototype.splice.apply(targetarray, arguments);
This is equivalent to calling:
targetarray.splice(index, howmany, elements[0], elements[1], elements[2], ...);
If elements gets big (see below for what "big" means for different browsers), you can get a "Maximum call stack size exceeded" error without recursion as the contents of it will be loaded onto the stack for the function call.
Here's a short script that demonstrates this issue:
var elements = new Array();
for (i=0; i<126000; i++) elements[i] = 1;
try {
var arguments = [0, 0].concat(elements);
Array.prototype.splice.apply(elements, arguments);
alert("OK");
} catch (err) {
alert(err.message);
}
Using this script, "big" means the following:
- Chrome 19: elements contains ~ 125,000 numbers
- Safari 5.1 (on Windows): elements contains ~ 65,000 numbers
- Firefox 12: elements contains ~ 500,000 numbers
- Opera 11.61: elements contains ~ 1,000,000 numbers
And the winner is: Internet Explorer 8 for a change! It can use up all system memory, before this function call fails.
A side note: Firefox and Opera actually throw a different (more useful) error message: Function.prototype.apply: argArray is too large