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
137
src/ajax/xhr.js
137
src/ajax/xhr.js
|
@ -115,76 +115,93 @@ if ( jQuery.support.ajax ) {
|
||||||
// Listener
|
// Listener
|
||||||
callback = function( _, isAbort ) {
|
callback = function( _, isAbort ) {
|
||||||
|
|
||||||
// Was never called and is aborted or complete
|
var status,
|
||||||
if ( callback && ( isAbort || xhr.readyState === 4 ) ) {
|
statusText,
|
||||||
|
responseHeaders,
|
||||||
|
responses,
|
||||||
|
xml;
|
||||||
|
|
||||||
// Only called once
|
// Firefox throws exceptions when accessing properties
|
||||||
callback = 0;
|
// 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
|
// Was never called and is aborted or complete
|
||||||
if ( handle ) {
|
if ( callback && ( isAbort || xhr.readyState === 4 ) ) {
|
||||||
xhr.onreadystatechange = jQuery.noop;
|
|
||||||
delete xhrs[ handle ];
|
|
||||||
}
|
|
||||||
|
|
||||||
// If it's an abort
|
// Only called once
|
||||||
if ( isAbort ) {
|
callback = undefined;
|
||||||
// Abort it manually if needed
|
|
||||||
if ( xhr.readyState !== 4 ) {
|
// Do not keep as active anymore
|
||||||
xhr.abort();
|
if ( handle ) {
|
||||||
|
xhr.onreadystatechange = jQuery.noop;
|
||||||
|
delete xhrs[ handle ];
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
// Get info
|
// If it's an abort
|
||||||
var status = xhr.status,
|
if ( isAbort ) {
|
||||||
statusText,
|
// Abort it manually if needed
|
||||||
responseHeaders = xhr.getAllResponseHeaders(),
|
if ( xhr.readyState !== 4 ) {
|
||||||
responses = {},
|
xhr.abort();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Get info
|
||||||
|
status = xhr.status;
|
||||||
|
responseHeaders = xhr.getAllResponseHeaders();
|
||||||
|
responses = {};
|
||||||
xml = xhr.responseXML;
|
xml = xhr.responseXML;
|
||||||
|
|
||||||
// Construct response list
|
// Construct response list
|
||||||
if ( xml && xml.documentElement /* #4958 */ ) {
|
if ( xml && xml.documentElement /* #4958 */ ) {
|
||||||
responses.xml = xml;
|
responses.xml = xml;
|
||||||
}
|
}
|
||||||
responses.text = xhr.responseText;
|
responses.text = xhr.responseText;
|
||||||
|
|
||||||
// Firefox throws an exception when accessing
|
// Firefox throws an exception when accessing
|
||||||
// statusText for faulty cross-domain requests
|
// statusText for faulty cross-domain requests
|
||||||
try {
|
try {
|
||||||
statusText = xhr.statusText;
|
statusText = xhr.statusText;
|
||||||
} catch( e ) {
|
} catch( e ) {
|
||||||
// We normalize with Webkit giving an empty statusText
|
// We normalize with Webkit giving an empty statusText
|
||||||
statusText = "";
|
statusText = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Filter status for non standard behaviors
|
// Filter status for non standard behaviors
|
||||||
status =
|
status =
|
||||||
// Most browsers return 0 when it should be 200 for local files
|
// Most browsers return 0 when it should be 200 for local files
|
||||||
// Opera returns 0 when it should be 304
|
// Opera returns 0 when it should be 304
|
||||||
// Webkit returns 0 for failing cross-domain no matter the real status
|
// Webkit returns 0 for failing cross-domain no matter the real status
|
||||||
!status ?
|
!status ?
|
||||||
// All: for local files, 0 is a success
|
// All: for local files, 0 is a success
|
||||||
( location.protocol === "file:" ? 200 : (
|
( location.protocol === "file:" ? 200 : (
|
||||||
// Webkit, Firefox: filter out faulty cross-domain requests
|
// Webkit, Firefox: filter out faulty cross-domain requests
|
||||||
!s.crossDomain || statusText ?
|
!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
|
// IE sometimes returns 1223 when it should be 204 (see #1450)
|
||||||
responseHeaders ?
|
status == 1223 ?
|
||||||
304 :
|
204 :
|
||||||
0
|
status
|
||||||
) :
|
);
|
||||||
// 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 );
|
|
||||||
}
|
}
|
||||||
|
} 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