views:

67

answers:

3

Hey all,

Recently I ran into a problem: Valid JSON when passed to the eval() function causes it to throw the error -- "script stack space quota is exhausted".

It is consistently reproducible, and through initial examination, it seems that this is a limitation on the number of object attributes/properties that can be defined (and not the size of the content).

Here's the sample code:

function starttest()
{      
       var d = new Array(50000);
       var i = 0;

       for (i = 0; i < d.length; i++) {
            d[i] = new Object();
            d[i].a1 = 1;
            d[i].a2 = 2;
            d[i].a3 = i;
            d[i].a4 = i;
            d[i].a5 = i;
            d[i].a6 = i;
            d[i].a7 = i;
            d[i].a8 = i;
            d[i].a9 = i;
            d[i].a10 = i;
            d[i].a11 = i;
            d[i].a12 = i;
            d[i].a13 = i;
            d[i].a14 = i;
            d[i].a15 = i;
       }       



    var jsonString = JSON.stringify(d);  
    alert(jsonString.length);

    var obj = eval(jsonString);
    var count = 0;
    for( var i = 0; i< obj.length; i++) {

        for (var k in obj[i]) {
            if (obj[i].hasOwnProperty(k)) {
               ++count;
            }
        }
    }

    alert("Done! || Len: " + obj.length + " || " + "Attrib Count: " + count + " || " + typeof obj)
}

The funny thing is I can define many more objects than seen in the code snippet; the problem arises only when using the eval() function.

Any new insights into this would be greatly helpful. I know using eval() is not safe, and all... and I'm open to suggestions!

+3  A: 

It means what it says. eval is obviously using recursion, and you're exceeding your limit when evaluating a long and complex JSON literal. It works fine with JSON.parse (at least in Firefox 3.6.11pre), which is the right tool for the job, and often faster.

Matthew Flaschen
Note, however, that if your browser doesn't have native `JSON.parse`, the implementation defined in http://www.json.org/json2.js uses `eval` internally, so it would have the same issue. `json_parse` (as mentioned in Alex's answer) doesn't. So I'd use native JSON parsing if available, and `json_parse` as a fallback.
Daniel Vandersluis
+1  A: 

It looks like you're using the JSON class to create a JSON string. Why don't you just use the opposite function to stringify to get the JSON back into an object syntax?

http://www.json.org/json_parse.js - is the javsacript JSON class. Just call json_parse(str); and you'll get a nice object back.

As you said yourself, eval() is not safe. It's damn-right evil!

Alex
+1  A: 

Yeah, this is a problem with Firefox's JavaScript interpreter in general. It's not just eval: if you put fifty thousand lines of:

{a:1,b:2,c:3,d:4,e:5,f:6,g:7,h:8,i:9,j:10,a2:1,b2:2,c2:3,d2:4,e2:5,f2:6,g2:7,h2:8,i2:9,j2:10},

in an array literal in a plain script file or <script> element, you get exactly the same error.

It seems the complexity of a script block is limited by the compile-time JS_DEFAULT_SCRIPT_STACK_QUOTA. See 420869 and the related linked bugs.

It's relatively unlikely you should meet this in normal circumstances. Of course for the case of JSON you can use JSON.parse which, not being a full JavaScript interpreter, is not affected by this limitation. If you needed a non-valid-JSON JS literal parser that's not affected, I guess you'd have to write it yourself... though it'd probably be annoyingly slow when you get to input this long.

bobince