From ee9687d441d625a420dc65590bbd0b930f800b3f Mon Sep 17 00:00:00 2001 From: James Huston Date: Tue, 16 Oct 2012 14:51:54 -0400 Subject: [PATCH] Fix #12751. Ensure parseJson throws in the same situations as JSON.parse. Close gh-993. --- AUTHORS.txt | 3 ++- src/core.js | 35 ++++++++++++++++------------- test/unit/ajax.js | 14 ++++++++++++ test/unit/core.js | 57 ++++++++++++++++++++++++++++++++++++++++++++--- 4 files changed, 90 insertions(+), 19 deletions(-) diff --git a/AUTHORS.txt b/AUTHORS.txt index 5a213d5a2..b2dd8bfab 100644 --- a/AUTHORS.txt +++ b/AUTHORS.txt @@ -133,4 +133,5 @@ Daniel Chatfield Nikita Govorov Michael Pennisi Markus Staab -Daniel Gálvez \ No newline at end of file +Daniel Gálvez +James Huston \ No newline at end of file diff --git a/src/core.js b/src/core.js index 5564a9870..2f5908b55 100644 --- a/src/core.js +++ b/src/core.js @@ -488,27 +488,32 @@ jQuery.extend({ }, parseJSON: function( data ) { - if ( !data || typeof data !== "string") { - return null; - } - - // Make sure leading/trailing whitespace is removed (IE can't handle it) - data = jQuery.trim( data ); - // Attempt to parse using the native JSON parser first if ( window.JSON && window.JSON.parse ) { return window.JSON.parse( data ); } - // Make sure the incoming data is actual JSON - // Logic borrowed from http://json.org/json2.js - if ( rvalidchars.test( data.replace( rvalidescape, "@" ) - .replace( rvalidtokens, "]" ) - .replace( rvalidbraces, "")) ) { - - return ( new Function( "return " + data ) )(); - + if ( data === null ) { + return data; } + + if ( typeof data === "string" ) { + + // Make sure leading/trailing whitespace is removed (IE can't handle it) + data = jQuery.trim( data ); + + if ( data ) { + // Make sure the incoming data is actual JSON + // Logic borrowed from http://json.org/json2.js + if ( rvalidchars.test( data.replace( rvalidescape, "@" ) + .replace( rvalidtokens, "]" ) + .replace( rvalidbraces, "")) ) { + + return ( new Function( "return " + data ) )(); + } + } + } + jQuery.error( "Invalid JSON: " + data ); }, diff --git a/test/unit/ajax.js b/test/unit/ajax.js index 4a93c65fe..c5185efb3 100644 --- a/test/unit/ajax.js +++ b/test/unit/ajax.js @@ -2759,4 +2759,18 @@ if ( jQuery.ajax && ( !isLocal || hasPHP ) ) { start(); }); }); + + test( "jQuery.ajax - empty json gets to error callback instead of success callback.", function() { + expect( 1 ); + + stop(); + + jQuery.ajax( url("data/echoData.php"), { + error: function( _, __, error ) { + equal( typeof error === "object", true, "Didn't get back error object for empty json response" ); + start(); + }, + dataType: "json" + }); + }); } diff --git a/test/unit/core.js b/test/unit/core.js index c0a719fe3..85d394e98 100644 --- a/test/unit/core.js +++ b/test/unit/core.js @@ -1150,9 +1150,13 @@ test("jQuery.parseHTML", function() { test("jQuery.parseJSON", function(){ expect(8); - equal( jQuery.parseJSON(), null, "Nothing in, null out." ); - equal( jQuery.parseJSON( null ), null, "Nothing in, null out." ); - equal( jQuery.parseJSON( "" ), null, "Nothing in, null out." ); + raises(function() { + jQuery.parseJSON(); + }, null, "parseJson now matches JSON.parse for empty input." ); + equal(jQuery.parseJSON( null ), null, "parseJson now matches JSON.parse on null input." ); + raises( function() { + jQuery.parseJSON( "" ); + }, null, "parseJson now matches JSON.parse for empty strings." ); deepEqual( jQuery.parseJSON("{}"), {}, "Plain object parsing." ); deepEqual( jQuery.parseJSON("{\"test\":1}"), {"test":1}, "Plain object parsing." ); @@ -1346,3 +1350,50 @@ test("jQuery.camelCase()", function() { equal( jQuery.camelCase( key ), val, "Converts: " + key + " => " + val ); }); }); + +test( "JQuery.parseJSON() test internal parseJson (using fallback) to make sure that it throws like JSON.parse", function() { + expect( 10 ); + + var jsonParse = window.JSON; + window.JSON = null; + + raises(function() { + jsonParse.parse("''"); + }); + + raises(function() { + jQuery.parseJSON("''"); + }); + + raises(function() { + jsonParse.parse(""); + }); + + raises(function() { + jQuery.parseJSON(""); + }); + + raises(function() { + jsonParse.parse({}); + }); + + raises(function() { + jQuery.parseJSON({}); + }); + + var parsedValue = jsonParse.parse(null); + equal( parsedValue, null ); + + parsedValue = jQuery.parseJSON(null); + equal( parsedValue, null ); + + parsedValue = jsonParse.parse("{}"); + equal( (typeof parsedValue === "object"), true ); + + parsedValue = jQuery.parseJSON("{}"); + equal( (typeof parsedValue === "object"), true ); + + + window.JSON = jsonParse; +} ); +