]> source.dussan.org Git - jquery.git/commitdiff
Ajax: Protect against exceptions thrown synchronously by xhr.send
authorjaubourg <j@ubourg.net>
Sat, 25 Jan 2014 07:20:18 +0000 (08:20 +0100)
committerjaubourg <j@ubourg.net>
Wed, 29 Jan 2014 13:18:58 +0000 (14:18 +0100)
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

src/ajax/xhr.js
test/unit/ajax.js

index 55d526a4191339c16ac4908a6be4771aee57e4ac..bdeeee3f8220042cdb533685f67ced7b753c35dc 100644 (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() {
index 77648404cb90c483d044ead0ef34aef1eb440843..c7d7daba4fde894eead37235cbdf2778a1525bca 100644 (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, {