Ajax: Protect against exceptions thrown synchronously by xhr.send

When xhr.send throws an exception synchronously, the onerror handler may have
been called already which, unchecked, makes the exception bubble up outside of
jQuery.ajax.

We now catch the exception pre-emptively and only rethrow if we know it hasn't
already been notified through the onerror handler.

Fixes #14683
This commit is contained in:
jaubourg 2014-01-25 08:20:18 +01:00
parent 53e31f478e
commit 01c360f963
2 changed files with 39 additions and 4 deletions

View File

@ -112,10 +112,15 @@ jQuery.ajaxTransport(function( options ) {
// Create the abort callback
callback = xhrCallbacks[ id ] = callback("abort");
// Do send the request
// This may raise an exception which is actually
// handled in jQuery.ajax (so no try/catch here)
xhr.send( options.hasContent && options.data || null );
try {
// Do send the request (this may raise an exception)
xhr.send( options.hasContent && options.data || null );
} catch ( e ) {
// #14683: Only rethrow if this hasn't been notified as an error yet
if ( callback ) {
throw e;
}
}
},
abort: function() {

View File

@ -1544,6 +1544,36 @@ module( "ajax", {
});
}
ajaxTest( "#14683 - jQuery.ajax() - Exceptions thrown synchronously by xhr.send should be caught", 4, [
{
url: "data/params_html.php",
method: "POST",
data: {
toString: function() {
throw "Can't parse";
}
},
processData: false,
done: function( data ) {
ok( false, "done: " + data );
},
fail: function( jqXHR, status, error ) {
ok( true, "exception caught: " + error );
strictEqual( jqXHR.status, 0, "proper status code" );
strictEqual( status, "error", "proper status" );
}
},
{
url: "http://domain.org:80d",
done: function( data ) {
ok( false, "done: " + data );
},
fail: function( _, status, error ) {
ok( true, "fail: " + status + " - " + error );
}
}
]);
//----------- jQuery.ajaxPrefilter()
ajaxTest( "jQuery.ajaxPrefilter() - abort", 1, {