aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjaubourg <j@ubourg.net>2014-01-25 08:20:18 +0100
committerjaubourg <j@ubourg.net>2014-01-29 14:18:58 +0100
commit01c360f96390ff16edfe65ef3b34e167087ef645 (patch)
tree2419904105326230d25b97dcececc92a134f2f8d
parent53e31f478e1d88d056aa52f6575d200fe3dcf047 (diff)
downloadjquery-01c360f96390ff16edfe65ef3b34e167087ef645.tar.gz
jquery-01c360f96390ff16edfe65ef3b34e167087ef645.zip
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
-rw-r--r--src/ajax/xhr.js13
-rw-r--r--test/unit/ajax.js30
2 files changed, 39 insertions, 4 deletions
diff --git a/src/ajax/xhr.js b/src/ajax/xhr.js
index 55d526a41..bdeeee3f8 100644
--- a/src/ajax/xhr.js
+++ b/src/ajax/xhr.js
@@ -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() {
diff --git a/test/unit/ajax.js b/test/unit/ajax.js
index 77648404c..c7d7daba4 100644
--- a/test/unit/ajax.js
+++ b/test/unit/ajax.js
@@ -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, {