Permalink
Browse files

Make sure that a parsererror is thrown whenever malformed JSON comes …

…back from a server (so that the Ajax error handler is called). Makes it uniform across browsers that do and don't have JSON.parse support.
  • Loading branch information...
1 parent c14fa51 commit 308d6cdad023da190ace2a698ee4815ed8dad9c5 @jeresig jeresig committed Jan 7, 2010
Showing with 34 additions and 8 deletions.
  1. +12 −6 src/ajax.js
  2. +1 −0 test/data/badjson.js
  3. +21 −2 test/unit/ajax.js
View
@@ -570,20 +570,26 @@ jQuery.extend({
// The filter can actually parse the response
if ( typeof data === "string" ) {
- // If the type is "script", eval it in global context
- if ( type === "script" || !type && ct.indexOf("javascript") >= 0 ) {
- jQuery.globalEval( data );
- }
-
// Get the JavaScript object, if JSON is used.
if ( type === "json" || !type && ct.indexOf("json") >= 0 ) {
// Try to use the native JSON parser first
if ( window.JSON && window.JSON.parse ) {
data = window.JSON.parse( data );
+ // Make sure the incoming data is actual JSON
+ // Logic borrowed from http://json.org/json2.js
+ } else if (/^[\],:{}\s]*$/.test(data.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, "@")
+ .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, "]")
+ .replace(/(?:^|:|,)(?:\s*\[)+/g, ""))) {
+ data = (new Function("return " + data))();
+
} else {
- data = (new Function("return " + data))();
+ throw "JSON Syntax Error: " + data;
}
+
+ // If the type is "script", eval it in global context
+ } else if ( type === "script" || !type && ct.indexOf("javascript") >= 0 ) {
+ jQuery.globalEval( data );
}
}
@@ -0,0 +1 @@
+{bad: 1}
View
@@ -341,13 +341,13 @@ test("jQuery.param()", function() {
test("synchronous request", function() {
expect(1);
- ok( /^{ "data"/.test( jQuery.ajax({url: url("data/json_obj.js"), async: false}).responseText ), "check returned text" );
+ ok( /^{ "data"/.test( jQuery.ajax({url: url("data/json_obj.js"), dataType: "text", async: false}).responseText ), "check returned text" );
});
test("synchronous request with callbacks", function() {
expect(2);
var result;
- jQuery.ajax({url: url("data/json_obj.js"), async: false, success: function(data) { ok(true, "sucess callback executed"); result = data; } });
+ jQuery.ajax({url: url("data/json_obj.js"), async: false, dataType: "text", success: function(data) { ok(true, "sucess callback executed"); result = data; } });
ok( /^{ "data"/.test( result ), "check returned text" );
});
@@ -821,6 +821,25 @@ test("jQuery.ajax() - script, Remote with scheme-less URL", function() {
});
});
+test("jQuery.ajax() - malformed JSON", function() {
+ expect(1);
+
+ stop();
+
+ jQuery.ajax({
+ url: "data/badjson.js",
+ dataType: "json",
+ success: function(){
+ ok( false, "Success." );
+ start();
+ },
+ error: function(xhr, msg) {
+ equals( "parsererror", msg, "A parse error occurred." );
+ start();
+ }
+ });
+});
+
test("jQuery.ajax() - script by content-type", function() {
expect(1);

3 comments on commit 308d6cd

@DBJDBJ
DBJDBJ commented on 308d6cd Jan 7, 2010

Ugh, I feel petty , but I had to note that this line in ajax.js (line: 576 ):

     if ( window.JSON && window.JSON.parse ) {

Should probably be :

     if ( window.JSON && ("function" === typeof window.JSON.parse) ) {

Thanks: DBJ

@DBJDBJ
DBJDBJ commented on 308d6cd Jan 8, 2010

Ah, I get it now ... For all modern browsers you are simply passing the data string to JSON.parse() without any checks whatsoever.
Leaving it to the implementers of it to throw exception or not if wrong JSON string has arrived.
Your logic is to simply "pass the bucket" to window.JSON ... So if one wants to have her JSON working in all browsers, the same one should sort out her JSON, first. This is OK logic, of course. Not entirely jQuery "hand holding" style, but OK.
In this case you are actually throwing an exception, which I think you should do much more in jQuery in general ;o)

@DBJDBJ
DBJDBJ commented on 308d6cd Jan 11, 2010

My attempt is here (at the bottom)
http://dbj.org/dbj/?p=470
I had a luxury of mulling over this while You are in a 1.4 releasing frenzy. Maybe You will find it usefull therefore ...

Thanks: DBJ

Please sign in to comment.