Fixes #8135. Makes sure any exception thrown by Firefox when trying to access an XMLHttpRequest property when a network error occured is caught and notified as an error. Added test/networkerror.html to test the behavior.
This commit is contained in:
parent
462bb1f66a
commit
b90369e8cb
2 changed files with 178 additions and 60 deletions
137
src/ajax/xhr.js
137
src/ajax/xhr.js
|
@ -115,76 +115,93 @@ if ( jQuery.support.ajax ) {
|
|||
// Listener
|
||||
callback = function( _, isAbort ) {
|
||||
|
||||
// Was never called and is aborted or complete
|
||||
if ( callback && ( isAbort || xhr.readyState === 4 ) ) {
|
||||
var status,
|
||||
statusText,
|
||||
responseHeaders,
|
||||
responses,
|
||||
xml;
|
||||
|
||||
// Only called once
|
||||
callback = 0;
|
||||
// Firefox throws exceptions when accessing properties
|
||||
// of an xhr when a network error occured
|
||||
// http://helpful.knobs-dials.com/index.php/Component_returned_failure_code:_0x80040111_(NS_ERROR_NOT_AVAILABLE)
|
||||
try {
|
||||
|
||||
// Do not keep as active anymore
|
||||
if ( handle ) {
|
||||
xhr.onreadystatechange = jQuery.noop;
|
||||
delete xhrs[ handle ];
|
||||
}
|
||||
// Was never called and is aborted or complete
|
||||
if ( callback && ( isAbort || xhr.readyState === 4 ) ) {
|
||||
|
||||
// If it's an abort
|
||||
if ( isAbort ) {
|
||||
// Abort it manually if needed
|
||||
if ( xhr.readyState !== 4 ) {
|
||||
xhr.abort();
|
||||
// Only called once
|
||||
callback = undefined;
|
||||
|
||||
// Do not keep as active anymore
|
||||
if ( handle ) {
|
||||
xhr.onreadystatechange = jQuery.noop;
|
||||
delete xhrs[ handle ];
|
||||
}
|
||||
} else {
|
||||
// Get info
|
||||
var status = xhr.status,
|
||||
statusText,
|
||||
responseHeaders = xhr.getAllResponseHeaders(),
|
||||
responses = {},
|
||||
|
||||
// If it's an abort
|
||||
if ( isAbort ) {
|
||||
// Abort it manually if needed
|
||||
if ( xhr.readyState !== 4 ) {
|
||||
xhr.abort();
|
||||
}
|
||||
} else {
|
||||
// Get info
|
||||
status = xhr.status;
|
||||
responseHeaders = xhr.getAllResponseHeaders();
|
||||
responses = {};
|
||||
xml = xhr.responseXML;
|
||||
|
||||
// Construct response list
|
||||
if ( xml && xml.documentElement /* #4958 */ ) {
|
||||
responses.xml = xml;
|
||||
}
|
||||
responses.text = xhr.responseText;
|
||||
// Construct response list
|
||||
if ( xml && xml.documentElement /* #4958 */ ) {
|
||||
responses.xml = xml;
|
||||
}
|
||||
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 = "";
|
||||
}
|
||||
// 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
|
||||
status =
|
||||
// Most browsers return 0 when it should be 200 for local files
|
||||
// Opera returns 0 when it should be 304
|
||||
// Webkit returns 0 for failing cross-domain no matter the real status
|
||||
!status ?
|
||||
// All: for local files, 0 is a success
|
||||
( location.protocol === "file:" ? 200 : (
|
||||
// Webkit, Firefox: filter out faulty cross-domain requests
|
||||
!s.crossDomain || statusText ?
|
||||
// Filter status for non standard behaviors
|
||||
status =
|
||||
// Most browsers return 0 when it should be 200 for local files
|
||||
// Opera returns 0 when it should be 304
|
||||
// Webkit returns 0 for failing cross-domain no matter the real status
|
||||
!status ?
|
||||
// All: for local files, 0 is a success
|
||||
( location.protocol === "file:" ? 200 : (
|
||||
// Webkit, Firefox: filter out faulty cross-domain requests
|
||||
!s.crossDomain || statusText ?
|
||||
(
|
||||
// Opera: filter out real aborts #6060
|
||||
responseHeaders ?
|
||||
304 :
|
||||
0
|
||||
) :
|
||||
// We assume 302 but could be anything cross-domain related
|
||||
302
|
||||
) ) :
|
||||
(
|
||||
// Opera: filter out real aborts #6060
|
||||
responseHeaders ?
|
||||
304 :
|
||||
0
|
||||
) :
|
||||
// We assume 302 but could be anything cross-domain related
|
||||
302
|
||||
) ) :
|
||||
(
|
||||
// IE sometimes returns 1223 when it should be 204 (see #1450)
|
||||
status == 1223 ?
|
||||
204 :
|
||||
status
|
||||
);
|
||||
|
||||
// Call complete
|
||||
complete( status, statusText, responses, responseHeaders );
|
||||
// IE sometimes returns 1223 when it should be 204 (see #1450)
|
||||
status == 1223 ?
|
||||
204 :
|
||||
status
|
||||
);
|
||||
}
|
||||
}
|
||||
} catch( firefoxAccessException ) {
|
||||
if ( !isAbort ) {
|
||||
complete( -1, firefoxAccessException );
|
||||
}
|
||||
}
|
||||
|
||||
// Call complete if needed
|
||||
if ( responses ) {
|
||||
complete( status, statusText, responses, responseHeaders );
|
||||
}
|
||||
};
|
||||
|
||||
|
|
101
test/networkerror.html
Normal file
101
test/networkerror.html
Normal file
|
@ -0,0 +1,101 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<!--
|
||||
Test for #8135
|
||||
|
||||
Thanks John Firebaugh for this test page based on his gist
|
||||
https://gist.github.com/807090
|
||||
|
||||
Access this page through a web server, then stop said server and click the button.
|
||||
-->
|
||||
<head>
|
||||
<title>
|
||||
jQuery Network Error Test for Firefox
|
||||
</title>
|
||||
<style>
|
||||
div { margin-top: 10px; }
|
||||
</style>
|
||||
<script src="../src/core.js"></script>
|
||||
<script src="../src/support.js"></script>
|
||||
<script src="../src/data.js"></script>
|
||||
<script src="../src/queue.js"></script>
|
||||
<script src="../src/attributes.js"></script>
|
||||
<script src="../src/event.js"></script>
|
||||
<script src="../src/sizzle/sizzle.js"></script>
|
||||
<script src="../src/sizzle-jquery.js"></script>
|
||||
<script src="../src/traversing.js"></script>
|
||||
<script src="../src/manipulation.js"></script>
|
||||
<script src="../src/css.js"></script>
|
||||
<script src="../src/ajax.js"></script>
|
||||
<script src="../src/ajax/jsonp.js"></script>
|
||||
<script src="../src/ajax/script.js"></script>
|
||||
<script src="../src/ajax/xhr.js"></script>
|
||||
<script src="../src/effects.js"></script>
|
||||
<script src="../src/offset.js"></script>
|
||||
<script src="../src/dimensions.js"></script>
|
||||
<script type="text/javascript">
|
||||
$('button').live('click', function () {
|
||||
$.ajax({
|
||||
url: '/',
|
||||
error: function() {
|
||||
console.log( "abort", arguments );
|
||||
}
|
||||
}).abort();
|
||||
$.ajax({
|
||||
url: '/',
|
||||
error: function() {
|
||||
console.log( "complete", arguments );
|
||||
}
|
||||
});
|
||||
return false;
|
||||
})
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<h1>
|
||||
jQuery Network Error Test for Firefox
|
||||
</h1>
|
||||
<div>
|
||||
This is a test page for
|
||||
<a href="http://bugs.jquery.com/ticket/8135">
|
||||
#8135
|
||||
</a>
|
||||
which was reported in Firefox when accessing properties
|
||||
of an XMLHttpRequest object after a network error occured.
|
||||
</div>
|
||||
<div>Take the following steps:</div>
|
||||
<ol>
|
||||
<li>
|
||||
make sure you accessed this page through a web server,
|
||||
</li>
|
||||
<li>
|
||||
stop the web server,
|
||||
</li>
|
||||
<li>
|
||||
open the console,
|
||||
</li>
|
||||
<li>
|
||||
click this
|
||||
<button>button</button>
|
||||
,
|
||||
</li>
|
||||
<li>
|
||||
wait for both requests to fail.
|
||||
</li>
|
||||
</ol>
|
||||
<div>
|
||||
Test passes if you get two log lines:
|
||||
<ul>
|
||||
<li>
|
||||
the first starting with "abort",
|
||||
</li>
|
||||
<li>
|
||||
the second starting with "complete",
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div>
|
||||
Test fails if the browser notifies an exception.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in a new issue