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 {
return new window.XMLHttpRequest();
} catch( e ) {}
}
function createActiveXHR() {
try { try {
return new window.ActiveXObject("Microsoft.XMLHTTP"); return new XMLHttpRequest();
} catch( e ) {} } catch( e ) {}
} };
// Create the request object var xhrSupported = jQuery.ajaxSettings.xhr(),
// (This is still attached to ajaxSettings for backward compatibility) xhrSuccessStatus = {
jQuery.ajaxSettings.xhr = window.ActiveXObject ? // file protocol always yields status code 0, assume 200
/* Microsoft failed to properly 0: 200,
* implement the XMLHttpRequest in IE7 (can't request local files), // IE - #1450: sometimes returns 1223 when it should be 204
* so we use the ActiveXObject when it is available 1223: 204
* 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
if ( xhrSupported ) {
jQuery.ajaxTransport(function( s ) {
// Cross domain only allowed if supported through XMLHttpRequest
if ( !s.crossDomain || jQuery.support.cors ) {
jQuery.ajaxTransport(function( options ) {
var callback; var callback;
// Cross domain only allowed if supported through XMLHttpRequest
if ( jQuery.support.cors || xhrSupported && !options.crossDomain ) {
return { return {
send: function( headers, complete ) { send: function( headers, complete ) {
var i,
// Get a new xhr xhr = options.xhr();
var handle, i,
xhr = s.xhr();
// Open the socket // Open the socket
// Passing null username, generates a login popup on Opera (#2865) xhr.open( options.type, options.url, options.async, options.username, options.password );
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 // Apply custom fields if provided
if ( s.xhrFields ) { if ( options.xhrFields ) {
for ( i in s.xhrFields ) { for ( i in options.xhrFields ) {
xhr[ i ] = s.xhrFields[ i ]; xhr[ i ] = options.xhrFields[ i ];
} }
} }
// Override mime type if needed // Override mime type if needed
if ( s.mimeType && xhr.overrideMimeType ) { if ( options.mimeType && xhr.overrideMimeType ) {
xhr.overrideMimeType( s.mimeType ); xhr.overrideMimeType( options.mimeType );
} }
// X-Requested-With header // X-Requested-With header
// For cross-domain requests, seeing as conditions for a preflight are // For cross-domain requests, seeing as conditions for a preflight are
// akin to a jigsaw puzzle, we simply never set it to be sure. // 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) // (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. // For same-domain requests, won't change header if already provided.
if ( !s.crossDomain && !headers["X-Requested-With"] ) { if ( !options.crossDomain && !headers["X-Requested-With"] ) {
headers["X-Requested-With"] = "XMLHttpRequest"; headers["X-Requested-With"] = "XMLHttpRequest";
} }
// Set headers
// Need an extra try/catch for cross domain requests in Firefox 3
try {
for ( i in headers ) { for ( i in headers ) {
xhr.setRequestHeader( i, headers[ i ] ); xhr.setRequestHeader( i, headers[ i ] );
} }
} catch( err ) {} // Callback
callback = function( type ) {
// Do send the request return function() {
// This may raise an exception which is actually if ( callback ) {
// handled in jQuery.ajax (so no try/catch here) callback = xhr.onload = xhr.onerror = null;
xhr.send( ( s.hasContent && s.data ) || null ); if ( type === "abort" ) {
// Listener
callback = function( _, isAbort ) {
var status,
statusText,
responseHeaders,
responses,
xml;
// Firefox throws exceptions when accessing properties
// of an xhr when a network error occurred
// http://helpful.knobs-dials.com/index.php/Component_returned_failure_code:_0x80040111_(NS_ERROR_NOT_AVAILABLE)
try {
// 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(); xhr.abort();
} } else if ( type === "error" ) {
complete( xhr.status, xhr.statusText );
} else { } else {
responses = {}; complete(
status = xhr.status; xhrSuccessStatus[ xhr.status ] || xhr.status,
xml = xhr.responseXML; xhr.statusText,
responseHeaders = xhr.getAllResponseHeaders(); // IE - #11426: When requesting binary data, IE9 will
// throw an exception on any attempt to access responseText
// Construct response list typeof xhr.responseText === "string" ? {
if ( xml && xml.documentElement /* #4958 */ ) { text: xhr.responseText
responses.xml = xml; } : undefined,
} xhr.getAllResponseHeaders()
);
// 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
if ( !xhrCallbacks ) {
xhrCallbacks = {};
jQuery( window ).unload( xhrOnUnloadAbort );
}
// Add to list of active xhrs callbacks
xhrCallbacks[ handle ] = callback;
}
xhr.onreadystatechange = callback;
}
}, },
abort: function() { abort: function() {
if ( callback ) { if ( callback ) {
callback( undefined, true ); callback();
} }
} }
}; };
} }
}); });
}
...@@ -1429,14 +1429,17 @@ module( "ajax", { ...@@ -1429,14 +1429,17 @@ 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;
window.onerror = function() {
ok( true, "Exception thrown" );
window.onerror = onerror;
start();
};
jQuery.ajax({ jQuery.ajax({
url: "data/badjson.js", url: "data/badjson.js",
dataType: "script", dataType: "script",
throws: true, throws: true,
// TODO find a way to test this asynchronously, too
async: false,
// Global events get confused by the exception // Global events get confused by the exception
global: false, global: false,
success: function() { success: function() {
...@@ -1446,7 +1449,6 @@ module( "ajax", { ...@@ -1446,7 +1449,6 @@ module( "ajax", {
ok( false, "Error." ); ok( false, "Error." );
} }
}); });
}, "exception bubbled" );
}); });
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