Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

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
  • Loading branch information...
commit 01c360f96390ff16edfe65ef3b34e167087ef645 1 parent 53e31f4
@jaubourg jaubourg authored
Showing with 39 additions and 4 deletions.
  1. +9 −4 src/ajax/xhr.js
  2. +30 −0 test/unit/ajax.js
View
13 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 {
@mzgol Collaborator
mzgol added a note

@jaubourg Shouldn't there be a support comment about Chrome: Support: Chrome 32+?

@jaubourg Collaborator

I'm still trying to determine if this behaviour is within the boundaries of the standard or not. From my current understanding, there's nothing preventing an implementation from acting like this hence the absence of a support comment.

@mzgol Collaborator
mzgol added a note

OK, got it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+ // 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
30 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, {
Please sign in to comment.
Something went wrong with that request. Please try again.