From 308d6cdad023da190ace2a698ee4815ed8dad9c5 Mon Sep 17 00:00:00 2001 From: jeresig Date: Thu, 7 Jan 2010 12:21:58 -0500 Subject: [PATCH] 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. --- src/ajax.js | 18 ++++++++++++------ test/data/badjson.js | 1 + test/unit/ajax.js | 23 +++++++++++++++++++++-- 3 files changed, 34 insertions(+), 8 deletions(-) create mode 100644 test/data/badjson.js diff --git a/src/ajax.js b/src/ajax.js index 9b8e800e8..4ba4548de 100644 --- a/src/ajax.js +++ b/src/ajax.js @@ -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 ); } } diff --git a/test/data/badjson.js b/test/data/badjson.js new file mode 100644 index 000000000..ec41ee5d6 --- /dev/null +++ b/test/data/badjson.js @@ -0,0 +1 @@ +{bad: 1} diff --git a/test/unit/ajax.js b/test/unit/ajax.js index 33937804b..298fb5bab 100644 --- a/test/unit/ajax.js +++ b/test/unit/ajax.js @@ -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); -- 2.39.5