Commit 17049c73 authored by jaubourg's avatar jaubourg Committed by Dave Methvin

2.0: reduced xhr transport

parent c6115042
var xhrCallbacks, xhrSupported, jQuery.ajaxSettings.xhr = function() {
xhrId = 0,
// #5280: Internet Explorer will keep connections alive if we don't abort on unload
xhrOnUnloadAbort = window.ActiveXObject && function() {
// Abort all pending requests
var key;
for ( key in xhrCallbacks ) {
xhrCallbacks[ key ]( undefined, true );
}
};
// Functions to create xhrs
function createStandardXHR() {
try { try {
return new window.XMLHttpRequest(); return new XMLHttpRequest();
} catch( e ) {} } catch( e ) {}
} };
function createActiveXHR() { var xhrSupported = jQuery.ajaxSettings.xhr(),
try { xhrSuccessStatus = {
return new window.ActiveXObject("Microsoft.XMLHTTP"); // file protocol always yields status code 0, assume 200
} catch( e ) {} 0: 200,
} // IE - #1450: sometimes returns 1223 when it should be 204
1223: 204
// Create the request object };
// (This is still attached to ajaxSettings for backward compatibility)
jQuery.ajaxSettings.xhr = window.ActiveXObject ?
/* Microsoft failed to properly
* implement the XMLHttpRequest in IE7 (can't request local files),
* so we use the ActiveXObject when it is available
* Additionally XMLHttpRequest can be disabled in IE7/IE8 so
* we need a fallback.
*/
function() {
return !this.isLocal && createStandardXHR() || createActiveXHR();
} :
// For all other browsers, use the standard XMLHttpRequest object
createStandardXHR;
// Determine support properties
xhrSupported = jQuery.ajaxSettings.xhr();
jQuery.support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported ); jQuery.support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported );
xhrSupported = jQuery.support.ajax = !!xhrSupported; jQuery.support.ajax = xhrSupported = !!xhrSupported;
// Create transport if the browser can provide an xhr jQuery.ajaxTransport(function( options ) {
if ( xhrSupported ) { var callback;
// Cross domain only allowed if supported through XMLHttpRequest
jQuery.ajaxTransport(function( s ) { if ( jQuery.support.cors || xhrSupported && !options.crossDomain ) {
// Cross domain only allowed if supported through XMLHttpRequest return {
if ( !s.crossDomain || jQuery.support.cors ) { send: function( headers, complete ) {
var i,
var callback; xhr = options.xhr();
// Open the socket
return { xhr.open( options.type, options.url, options.async, options.username, options.password );
send: function( headers, complete ) { // Apply custom fields if provided
if ( options.xhrFields ) {
// Get a new xhr for ( i in options.xhrFields ) {
var handle, i, xhr[ i ] = options.xhrFields[ i ];
xhr = s.xhr();
// Open the socket
// Passing null username, generates a login popup on Opera (#2865)
if ( s.username ) {
xhr.open( s.type, s.url, s.async, s.username, s.password );
} else {
xhr.open( s.type, s.url, s.async );
}
// Apply custom fields if provided
if ( s.xhrFields ) {
for ( i in s.xhrFields ) {
xhr[ i ] = s.xhrFields[ i ];
}
}
// Override mime type if needed
if ( s.mimeType && xhr.overrideMimeType ) {
xhr.overrideMimeType( s.mimeType );
} }
}
// X-Requested-With header // Override mime type if needed
// For cross-domain requests, seeing as conditions for a preflight are if ( options.mimeType && xhr.overrideMimeType ) {
// akin to a jigsaw puzzle, we simply never set it to be sure. xhr.overrideMimeType( options.mimeType );
// (it can always be set on a per-request basis or even using ajaxSetup) }
// For same-domain requests, won't change header if already provided. // X-Requested-With header
if ( !s.crossDomain && !headers["X-Requested-With"] ) { // For cross-domain requests, seeing as conditions for a preflight are
headers["X-Requested-With"] = "XMLHttpRequest"; // akin to a jigsaw puzzle, we simply never set it to be sure.
} // (it can always be set on a per-request basis or even using ajaxSetup)
// For same-domain requests, won't change header if already provided.
// Need an extra try/catch for cross domain requests in Firefox 3 if ( !options.crossDomain && !headers["X-Requested-With"] ) {
try { headers["X-Requested-With"] = "XMLHttpRequest";
for ( i in headers ) { }
xhr.setRequestHeader( i, headers[ i ] ); // Set headers
} for ( i in headers ) {
} catch( err ) {} xhr.setRequestHeader( i, headers[ i ] );
}
// Do send the request // Callback
// This may raise an exception which is actually callback = function( type ) {
// handled in jQuery.ajax (so no try/catch here) return function() {
xhr.send( ( s.hasContent && s.data ) || null ); if ( callback ) {
callback = xhr.onload = xhr.onerror = null;
// Listener if ( type === "abort" ) {
callback = function( _, isAbort ) { xhr.abort();
} else if ( type === "error" ) {
var status, complete( xhr.status, xhr.statusText );
statusText, } else {
responseHeaders, complete(
responses, xhrSuccessStatus[ xhr.status ] || xhr.status,
xml; xhr.statusText,
// IE - #11426: When requesting binary data, IE9 will
// Firefox throws exceptions when accessing properties // throw an exception on any attempt to access responseText
// of an xhr when a network error occurred typeof xhr.responseText === "string" ? {
// http://helpful.knobs-dials.com/index.php/Component_returned_failure_code:_0x80040111_(NS_ERROR_NOT_AVAILABLE) text: xhr.responseText
try { } : undefined,
xhr.getAllResponseHeaders()
// Was never called and is aborted or complete );
if ( callback && ( isAbort || xhr.readyState === 4 ) ) {
// Only called once
callback = undefined;
// Do not keep as active anymore
if ( handle ) {
xhr.onreadystatechange = jQuery.noop;
if ( xhrOnUnloadAbort ) {
delete xhrCallbacks[ handle ];
}
}
// If it's an abort
if ( isAbort ) {
// Abort it manually if needed
if ( xhr.readyState !== 4 ) {
xhr.abort();
}
} else {
responses = {};
status = xhr.status;
xml = xhr.responseXML;
responseHeaders = xhr.getAllResponseHeaders();
// Construct response list
if ( xml && xml.documentElement /* #4958 */ ) {
responses.xml = xml;
}
// When requesting binary data, IE6-9 will throw an exception
// on any attempt to access responseText (#11426)
if ( typeof xhr.responseText === "string" ) {
responses.text = xhr.responseText;
}
// Firefox throws an exception when accessing
// statusText for faulty cross-domain requests
try {
statusText = xhr.statusText;
} catch( e ) {
// We normalize with Webkit giving an empty statusText
statusText = "";
}
// Filter status for non standard behaviors
// If the request is local and we have data: assume a success
// (success with no data won't get notified, that's the best we
// can do given current implementations)
if ( !status && s.isLocal && !s.crossDomain ) {
status = responses.text ? 200 : 404;
// IE - #1450: sometimes returns 1223 when it should be 204
} else if ( status === 1223 ) {
status = 204;
}
}
}
} catch( firefoxAccessException ) {
if ( !isAbort ) {
complete( -1, firefoxAccessException );
} }
} }
// Call complete if needed
if ( responses ) {
complete( status, statusText, responses, responseHeaders );
}
}; };
};
if ( !s.async ) { // Listen to events
// if we're in sync mode we fire the callback xhr.onload = callback();
callback(); xhr.onerror = callback("error");
} else if ( xhr.readyState === 4 ) { // Create the abort callback
// (IE6 & IE7) if it's in cache and has been callback = callback("abort");
// retrieved directly we need to fire the callback // Do send the request
setTimeout( callback ); // This may raise an exception which is actually
} else { // handled in jQuery.ajax (so no try/catch here)
handle = ++xhrId; xhr.send( options.hasContent && options.data || null );
if ( xhrOnUnloadAbort ) { },
// Create the active xhrs callbacks list if needed
// and attach the unload handler abort: function() {
if ( !xhrCallbacks ) { if ( callback ) {
xhrCallbacks = {}; callback();
jQuery( window ).unload( xhrOnUnloadAbort );
}
// Add to list of active xhrs callbacks
xhrCallbacks[ handle ] = callback;
}
xhr.onreadystatechange = callback;
}
},
abort: function() {
if ( callback ) {
callback( undefined, true );
}
} }
}; }
} };
}); }
} });
...@@ -1429,24 +1429,26 @@ module( "ajax", { ...@@ -1429,24 +1429,26 @@ module( "ajax", {
} }
}); });
test( "#11743 - jQuery.ajax() - script, throws exception", 1, function() { asyncTest( "#11743 - jQuery.ajax() - script, throws exception", 1, function() {
raises(function() { var onerror = window.onerror;
jQuery.ajax({ window.onerror = function() {
url: "data/badjson.js", ok( true, "Exception thrown" );
dataType: "script", window.onerror = onerror;
throws: true, start();
// TODO find a way to test this asynchronously, too };
async: false, jQuery.ajax({
// Global events get confused by the exception url: "data/badjson.js",
global: false, dataType: "script",
success: function() { throws: true,
ok( false, "Success." ); // Global events get confused by the exception
}, global: false,
error: function() { success: function() {
ok( false, "Error." ); ok( false, "Success." );
} },
}); error: function() {
}, "exception bubbled" ); ok( false, "Error." );
}
});
}); });
jQuery.each( [ "method", "type" ], function( _, globalOption ) { jQuery.each( [ "method", "type" ], function( _, globalOption ) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment