Skip to content

Commit 01c360f

Browse files
committed
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
1 parent 53e31f4 commit 01c360f

File tree

2 files changed

+39
-4
lines changed

2 files changed

+39
-4
lines changed

src/ajax/xhr.js

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -112,10 +112,15 @@ jQuery.ajaxTransport(function( options ) {
112112
// Create the abort callback
113113
callback = xhrCallbacks[ id ] = callback("abort");
114114

115-
// Do send the request
116-
// This may raise an exception which is actually
117-
// handled in jQuery.ajax (so no try/catch here)
118-
xhr.send( options.hasContent && options.data || null );
115+
try {
116+
// Do send the request (this may raise an exception)
117+
xhr.send( options.hasContent && options.data || null );
118+
} catch ( e ) {
119+
// #14683: Only rethrow if this hasn't been notified as an error yet
120+
if ( callback ) {
121+
throw e;
122+
}
123+
}
119124
},
120125

121126
abort: function() {

test/unit/ajax.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1544,6 +1544,36 @@ module( "ajax", {
15441544
});
15451545
}
15461546

1547+
ajaxTest( "#14683 - jQuery.ajax() - Exceptions thrown synchronously by xhr.send should be caught", 4, [
1548+
{
1549+
url: "data/params_html.php",
1550+
method: "POST",
1551+
data: {
1552+
toString: function() {
1553+
throw "Can't parse";
1554+
}
1555+
},
1556+
processData: false,
1557+
done: function( data ) {
1558+
ok( false, "done: " + data );
1559+
},
1560+
fail: function( jqXHR, status, error ) {
1561+
ok( true, "exception caught: " + error );
1562+
strictEqual( jqXHR.status, 0, "proper status code" );
1563+
strictEqual( status, "error", "proper status" );
1564+
}
1565+
},
1566+
{
1567+
url: "http://domain.org:80d",
1568+
done: function( data ) {
1569+
ok( false, "done: " + data );
1570+
},
1571+
fail: function( _, status, error ) {
1572+
ok( true, "fail: " + status + " - " + error );
1573+
}
1574+
}
1575+
]);
1576+
15471577
//----------- jQuery.ajaxPrefilter()
15481578

15491579
ajaxTest( "jQuery.ajaxPrefilter() - abort", 1, {

0 commit comments

Comments
 (0)