Skip to content

Commit

Permalink
improve abort handling
Browse files Browse the repository at this point in the history
  • Loading branch information
rbri committed Jul 4, 2021
1 parent 5d42992 commit 9fc7f77
Show file tree
Hide file tree
Showing 4 changed files with 189 additions and 28 deletions.
2 changes: 1 addition & 1 deletion src/changes/changes.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
<body>
<release version="2.51.0" date="June xx, 2021" description="Bugfixes, Firefox 89, Chrome/Edge 91, JS Template support">
<action type="fix" dev="rbri" issue="365">
XMLHttpRequest-abort() sets the state to 0.
XMLHttpRequest-abort() sets the state back to 0 and the webResponse to a network error.
</action>
<action type="fix" dev="RhinoTeam">
core-js: Various fixes for undefined.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1671,6 +1671,10 @@ public enum BrowserVersionFeatures {
@BrowserFeature(IE)
XHR_LENGTH_COMPUTABLE,

/** XMLHttpRequest triggers the load events also if the abort was signaled. */
@BrowserFeature({FF, FF78})
XHR_LOAD_ALWAYS_AFTER_DONE,

/** XMLHttpRequest triggers the load start event async. */
@BrowserFeature(IE)
XHR_LOAD_START_ASYNC,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import static com.gargoylesoftware.htmlunit.BrowserVersionFeatures.XHR_FIRE_STATE_OPENED_AGAIN_IN_ASYNC_MODE;
import static com.gargoylesoftware.htmlunit.BrowserVersionFeatures.XHR_HANDLE_SYNC_NETWORK_ERRORS;
import static com.gargoylesoftware.htmlunit.BrowserVersionFeatures.XHR_LENGTH_COMPUTABLE;
import static com.gargoylesoftware.htmlunit.BrowserVersionFeatures.XHR_LOAD_ALWAYS_AFTER_DONE;
import static com.gargoylesoftware.htmlunit.BrowserVersionFeatures.XHR_LOAD_START_ASYNC;
import static com.gargoylesoftware.htmlunit.BrowserVersionFeatures.XHR_NO_CROSS_ORIGIN_TO_ABOUT;
import static com.gargoylesoftware.htmlunit.BrowserVersionFeatures.XHR_OPEN_ALLOW_EMTPY_URL;
Expand Down Expand Up @@ -54,6 +55,7 @@
import org.apache.http.auth.UsernamePasswordCredentials;

import com.gargoylesoftware.htmlunit.AjaxController;
import com.gargoylesoftware.htmlunit.BrowserVersion;
import com.gargoylesoftware.htmlunit.FormEncodingType;
import com.gargoylesoftware.htmlunit.HttpHeader;
import com.gargoylesoftware.htmlunit.HttpMethod;
Expand Down Expand Up @@ -204,7 +206,10 @@ private void fireJavascriptEvent(final String eventName) {

return;
}
fireJavascriptEventIgnoreAbort(eventName);
}

private void fireJavascriptEventIgnoreAbort(final String eventName) {
if (LOG.isDebugEnabled()) {
LOG.debug("Firing javascript XHR event: " + eventName);
}
Expand Down Expand Up @@ -371,13 +376,21 @@ public String getStatusText() {
public void abort() {
getWindow().getWebWindow().getJobManager().stopJob(jobID_);

webResponse_ = null;
setState(DONE);
fireJavascriptEvent(Event.TYPE_READY_STATE_CHANGE);
fireJavascriptEvent(Event.TYPE_ABORT);
fireJavascriptEvent(Event.TYPE_LOAD_END);
if (state_ == OPENED
|| state_ == HEADERS_RECEIVED
|| state_ == LOADING) {
setState(DONE);
webResponse_ = new NetworkErrorWebResponse(webRequest_, null);
fireJavascriptEvent(Event.TYPE_READY_STATE_CHANGE);
fireJavascriptEvent(Event.TYPE_ABORT);
fireJavascriptEvent(Event.TYPE_LOAD_END);
}

// ScriptRuntime.constructError("NetworkError",
// "Failed to execute 'send' on 'XMLHttpRequest': Failed to load '" + webRequest_.getUrl() + "'");

setState(UNSENT);
webResponse_ = new NetworkErrorWebResponse(webRequest_, null);
aborted_ = true;
}

Expand Down Expand Up @@ -670,7 +683,8 @@ else if (content instanceof Blob) {
* @param context the current context
*/
void doSend() {
if (async_ && getBrowserVersion().hasFeature(XHR_LOAD_START_ASYNC)) {
final BrowserVersion browserVersion = getBrowserVersion();
if (async_ && browserVersion.hasFeature(XHR_LOAD_START_ASYNC)) {
fireJavascriptEvent(Event.TYPE_LOAD_START);
}

Expand Down Expand Up @@ -715,7 +729,7 @@ void doSend() {
|| statusCode == HttpStatus.SC_NOT_MODIFIED;
if (!successful || !isPreflightAuthorized(preflightResponse)) {
setState(DONE);
if (async_ || getBrowserVersion().hasFeature(XHR_HANDLE_SYNC_NETWORK_ERRORS)) {
if (async_ || browserVersion.hasFeature(XHR_HANDLE_SYNC_NETWORK_ERRORS)) {
fireJavascriptEvent(Event.TYPE_READY_STATE_CHANGE);
fireJavascriptEvent(Event.TYPE_ERROR);
fireJavascriptEvent(Event.TYPE_LOAD_END);
Expand Down Expand Up @@ -768,7 +782,7 @@ public String getContentType() {
@Override
public Charset getContentCharset() {
if (charsetNameFinal.isEmpty()
|| (charsetFinal == null && getBrowserVersion()
|| (charsetFinal == null && browserVersion
.hasFeature(XHR_USE_CONTENT_CHARSET))) {
return super.getContentCharset();
}
Expand Down Expand Up @@ -797,8 +811,15 @@ public Charset getContentCharset() {

setState(DONE);
fireJavascriptEvent(Event.TYPE_READY_STATE_CHANGE);
fireJavascriptEvent(Event.TYPE_LOAD);
fireJavascriptEvent(Event.TYPE_LOAD_END);

if (browserVersion.hasFeature(XHR_LOAD_ALWAYS_AFTER_DONE)) {
fireJavascriptEventIgnoreAbort(Event.TYPE_LOAD);
fireJavascriptEventIgnoreAbort(Event.TYPE_LOAD_END);
}
else {
fireJavascriptEvent(Event.TYPE_LOAD);
fireJavascriptEvent(Event.TYPE_LOAD_END);
}
}
catch (final IOException e) {
if (LOG.isDebugEnabled()) {
Expand All @@ -807,7 +828,7 @@ public Charset getContentCharset() {

if (async_) {
if (e instanceof SocketTimeoutException
&& getBrowserVersion().hasFeature(XHR_LOAD_START_ASYNC)) {
&& browserVersion.hasFeature(XHR_LOAD_START_ASYNC)) {
try {
webResponse_ = wc.loadWebResponse(WebRequest.newAboutBlankRequest());
}
Expand All @@ -820,7 +841,7 @@ && getBrowserVersion().hasFeature(XHR_LOAD_START_ASYNC)) {

if (!preflighted
&& e instanceof NoHttpResponseException
&& getBrowserVersion().hasFeature(XHR_PROGRESS_ON_NETWORK_ERROR_ASYNC)) {
&& browserVersion.hasFeature(XHR_PROGRESS_ON_NETWORK_ERROR_ASYNC)) {
fireJavascriptEvent(Event.TYPE_PROGRESS);
}
}
Expand All @@ -839,7 +860,7 @@ && getBrowserVersion().hasFeature(XHR_PROGRESS_ON_NETWORK_ERROR_ASYNC)) {
}
else {
setState(DONE);
if (getBrowserVersion().hasFeature(XHR_HANDLE_SYNC_NETWORK_ERRORS)) {
if (browserVersion.hasFeature(XHR_HANDLE_SYNC_NETWORK_ERRORS)) {
fireJavascriptEvent(Event.TYPE_READY_STATE_CHANGE);
if (e instanceof SocketTimeoutException) {
fireJavascriptEvent(Event.TYPE_TIMEOUT);
Expand Down
Loading

0 comments on commit 9fc7f77

Please sign in to comment.