WebKit Bugzilla
New
Browse
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
RESOLVED FIXED
40952
Onloadend event is not supported in XMLHttpRequest
https://bugs.webkit.org/show_bug.cgi?id=40952
Summary
Onloadend event is not supported in XMLHttpRequest
Stuart Ng
Reported
2010-06-21 16:15:04 PDT
- Send XHR request for website that should return OK - Check that load and loadstart event handler was fired - onloadend event handler was never fired. According to W3C Spec onloadend event should fired upon successful completion of XHR request.
Attachments
Patch
(23.19 KB, patch)
2011-12-09 09:15 PST
,
Hans Muller
no flags
Details
Formatted Diff
Diff
Patch
(25.95 KB, patch)
2011-12-12 08:34 PST
,
Hans Muller
no flags
Details
Formatted Diff
Diff
Patch
(33.03 KB, patch)
2011-12-13 08:19 PST
,
Hans Muller
no flags
Details
Formatted Diff
Diff
Patch
(37.03 KB, patch)
2011-12-16 11:09 PST
,
Hans Muller
no flags
Details
Formatted Diff
Diff
Patch
(34.24 KB, patch)
2011-12-20 12:00 PST
,
Hans Muller
no flags
Details
Formatted Diff
Diff
Show Obsolete
(4)
View All
Add attachment
proposed patch, testcase, etc.
Joe Mason
Comment 1
2010-06-21 17:12:06 PDT
http://atg05-yyz/html5/xhrasync/stateTest.htm
shows this bug. (I can't seem to add it to the url field. Guess I don't have access?)
Joe Mason
Comment 2
2010-06-21 17:23:10 PDT
(In reply to
comment #1
)
>
http://atg05-yyz/html5/xhrasync/stateTest.htm
shows this bug. (I can't seem to add it to the url field. Guess I don't have access?)
Oops, that's not a public url. Ignore.
Hans Muller
Comment 3
2011-12-07 09:53:59 PST
Per the W3C XMLHttpRequest2 Working Draft,
http://www.w3.org/TR/XMLHttpRequest2
, the loadend ProgressEvent should be dispatched by the XMLHttpRequest or it's XMLHttpRequestUpload after the load, error, and abort events for requests that have successfully completed, failed, or been aborted respectively. Support for loadend requires a small number of changes: - adding an onloadend EventListener attribute to Source/WebCore/xml/XMLHttpRequest.idl,XMLHttpRequestUpload.idl - Similarly defining the event listener in Source/WebCore/xml/XMLHttpRequest.h, XMLHttpRequestUpload.h - Dispatching the loadend after load/error/abort events are dispatched in Source/WebCore/xml/XMLHttpRequest.cpp
Hans Muller
Comment 4
2011-12-09 09:15:23 PST
Created
attachment 118587
[details]
Patch
Hans Muller
Comment 5
2011-12-09 09:17:00 PST
I've attached a patch that adds the feature as proposed in
comment #3
. I've included five tests which verify that the loadend progress event is dispatched last, as specfied in the XMLHttpRequest2 spec. The tests haven't been combined to keep them simple and because they test independent code paths. I did not include a test that verifies that upload error progress events are followed by a loadend because I wasn't sure how to generate a network error in that scenario.
WebKit Review Bot
Comment 6
2011-12-09 09:18:20 PST
Attachment 118587
[details]
did not pass style-queue: Failed to run "['Tools/Scripts/check-webkit-style', '--diff-files', u'LayoutTests/ChangeLog', u'LayoutTests/http..." exit_code: 1 LayoutTests/ChangeLog:8: Line contains tab character. [whitespace/tab] [5] Source/WebCore/ChangeLog:9: Line contains tab character. [whitespace/tab] [5] Total errors found: 2 in 18 files If any of these errors are false positives, please file a bug against check-webkit-style.
Julien Chaffraix
Comment 7
2011-12-09 09:43:49 PST
Comment on
attachment 118587
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=118587&action=review
You are going in the right direction, some comments inlined. Also you are only testing half of the change: what happened to the synchronous case.
> Source/WebCore/ChangeLog:15 > +
The ChangeLog should have some information on the exact change you did. Here is an example of what you could write: Patches the different sites where we dispatch a 'load', 'error' or 'abort' event to also dispatch a 'loadend' event. Also added the plumbing for the new 'loadend' event. You can also put the details next to the lines below too (some reviewers prefer it this way but it is not mandated by our coding style).
> Source/WebCore/xml/XMLHttpRequest.cpp:346 > + m_progressEventThrottle.dispatchEvent(XMLHttpRequestProgressEvent::create(eventNames().loadendEvent));
It would actually be more bullet proof for you to patch XMLHttpRequestProgressEventThrottle and XMLHttpRequestUpload. It's super easy to forget to add the loadend event at one call site and we would like to avoid that.
> LayoutTests/http/tests/xmlhttprequest/onloadend-event-after-abort-expected.txt:7 > +XHR Events: loadstart readyState=DONE abort loadend
Global remarks on the tests: it looks like the result could be checked automatically by the script and just print PASSED instead of the string. It would make the output a passing case a lot more readable. You would have to do some simple post-processing though. There are some examples in the same directory that follow this format, see xmlhttprequest-multiple-open.html for example.
> LayoutTests/http/tests/xmlhttprequest/upload-onloadend-event-after-abort.html:7 > +<p> Verify that a loadend ProgressEvent is dispatched after the error ProgressEvent when an async upload request is aborted.</p>
looks like this description is not up to date as you are not expecting any errors.
Hans Muller
Comment 8
2011-12-09 12:52:38 PST
I've made all of the changes you suggested. I added dispatchEventAndLoadEnd() methods to XMLHttpRequestUpload and XMLHttpRequestProgressEventThrottle which ensures that a loadend progress event is dispatched so long as the ...AndLoadEnd() method is called. I could make the existing dispatchEvent() methods do as much automtically but that seems a presumptious, since the (I guess) the progress event protocol might not always pair events in this way?
WebKit Review Bot
Comment 9
2011-12-09 18:08:00 PST
Comment on
attachment 118587
[details]
Patch
Attachment 118587
[details]
did not pass chromium-ews (chromium-xvfb): Output:
http://queues.webkit.org/results/10828488
New failing tests: media/event-attributes.html
Julien Chaffraix
Comment 10
2011-12-10 08:08:33 PST
(In reply to
comment #8
)
> I added dispatchEventAndLoadEnd() methods to XMLHttpRequestUpload and XMLHttpRequestProgressEventThrottle which ensures that a loadend progress event is dispatched so long as the ...AndLoadEnd() method is called.
Great!
> I could make the existing dispatchEvent() methods do as much automtically but that seems a presumptious, since the (I guess) the progress event protocol might not always pair events in this way?
I agree with you on this one. Not necessarily based on the ordering argument but more on the fact that it would be confusing for dispatchEvent() to have this side effect. dispatchEvent() should be just about properly filling an Event and dispatching it in the DOM.
Hans Muller
Comment 11
2011-12-12 08:34:05 PST
Created
attachment 118792
[details]
Patch
Julien Chaffraix
Comment 12
2011-12-12 19:27:54 PST
Comment on
attachment 118792
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=118792&action=review
I still don't see the synchronous case covered even if you mentioned it in the patch description.
> Source/WebCore/ChangeLog:10 > + and XMLHttpRequestUpload to foolproof the common case of dispatching a load,abort,error
Space after the comma.
> Source/WebCore/xml/XMLHttpRequest.cpp:772 > + if (m_upload && m_uploadEventsAllowed)
Trailing whitespace.
> Source/WebCore/xml/XMLHttpRequest.cpp:784 > + if (m_upload && m_uploadEventsAllowed)
Ditto.
> Source/WebCore/xml/XMLHttpRequestProgressEventThrottle.cpp:84 > +void XMLHttpRequestProgressEventThrottle::dispatchEventAndLoadEnd(PassRefPtr<Event> event, ProgressEventAction progressEventAction)
This is really not much more fool-proof than calling the 2 methods together at the call sites. We really want to prevent people from mis-using the API as much as we could so at least white-listing the events you expect here with an ASSERT is a minimum. It would be really neat to have some checks at the dispatchEvent level to prevent people from forgetting dispatchEventAndLoadEnd. I would really love to see your patch handle that properly. It would involve having 2 code path in dispatchEvent (2 functions like dispatchEvent and dispatchEventWithoutLoadEnd - in which case dispatchEventWithLoadEnd would be a better fit for this function), one common to every one and one specific for events that don't need a 'loadend'. The latter would black-list the events we expect to go through dispatchEventAndLoadEnd. You may see some issues with this approach, feel free to push back in this case.
> Source/WebCore/xml/XMLHttpRequestProgressEventThrottle.h:53 > + void dispatchEventAndLoadEnd(PassRefPtr<Event>, ProgressEventAction = DoNotFlushProgressEvent);
I did not see any call sites passing |ProgressEventAction| so let's just remove it and pass this value down to dispatchEvent.
> LayoutTests/http/tests/xmlhttprequest/onloadend-event-after-abort.html:59 > + xhr.open("GET", "resources/get.txt");
Nit: for consistency it would be nice to put |true| here (also for people who don't know that the default is true).
> LayoutTests/http/tests/xmlhttprequest/onloadend-event-after-error.html:58 > + xhr.open("GET", "resources/infinite-loop.php");
Ditto.
> LayoutTests/http/tests/xmlhttprequest/onloadend-event-after-load.html:57 > + xhr.open("GET", "resources/get.txt");
Ditto.
Hans Muller
Comment 13
2011-12-13 08:19:29 PST
Created
attachment 119020
[details]
Patch
Hans Muller
Comment 14
2011-12-13 08:35:40 PST
Sorry about leaving out the new sync tests, I'm still getting used to git addition. I've made all of the changes you suggested except for the one about the new dispatchEventAndLoadEnd() methods. Assuming I'm understanding you correctly, adding an ASSERT to the two new methods which verifies that the event parameter is either abort, error, or load, makes sense. The other approach you suggested, if I'm likewise understanding what you meant, would mean adding dispatch methods for each progress event type, where the abort, error, and load event methods would be aptly named because they would dispatch a loadend event too. Then, so long as XMLHttpRequest.cpp did not call dispatchEvent() directly, it might be a little clearer that the implementation wasn't dispatching unpaired xx/loadend events. Perhaps I'm not seeing the point, but this seems like a lot of defensive code to diminish the probability of one kind of error?
Julien Chaffraix
Comment 15
2011-12-13 08:50:34 PST
(In reply to
comment #14
)
> Sorry about leaving out the new sync tests, I'm still getting used to git addition. > > Assuming I'm understanding you correctly, adding an ASSERT to the two new methods which verifies that the event parameter is either abort, error, or load, makes sense.
You're understanding correctly.
> Perhaps I'm not seeing the point, but this seems like a lot of defensive code to diminish the probability of one kind of error?
But an extremely easy to make. If we decide to refactor our code to support some new XHR feature, you could end up just calling dispatchEvent([...].errorEvent). That's the use case I am trying to prevent. I don't deny that it will be some work to get that implemented. I still think it would be worthwhile but if that doesn't cut, then I am OK to go without that check.
Hans Muller
Comment 16
2011-12-14 15:52:10 PST
I've refactored the changes to reduce the probability of dispatching a solitary load, error, timeout, or abort event. Events are no longer dispatched directly (with dispatchEvent()) in XMLHttpRequest. If this sounds like what you wanted, let me know and I'll upload a new patch. Having done this, it doesn't seem to me like the extra complexity balances the added safety, however I'm new to the code. - Added the following public methods to XMLHttpRequestUpload. Upload void dispatchLoadStartProgressEvent(); void dispatchProgressEvent(bool lengthComputable, unsigned long long loaded, unsigned long long total); void dispatchFinalProgressEvent(PassRefPtr<Event>); // ASSERTs that event is load, abort, error, or timeout - Added similar public methods to XMLHttpRequestProgressEventThrottle as well as a method to dispatch the readystatechange event. Note that XMLHttpRequestProgressEventThrottle::dispatchProgressEvent() was already defined. void dispatchReadyStateChangeEvent(ProgressEventAction = DoNotFlushProgressEvent); void dispatchLoadStartProgressEvent(); void dispatchFinalProgressEvent(PassRefPtr<Event>); // ASSERTs that event is load, abort, error, or timeout I've overridden the dispatchEvent() methods with an ASSERT that the event parameter is *not* load, abort, error, or timeout.
Julien Chaffraix
Comment 17
2011-12-16 02:14:59 PST
(In reply to
comment #16
)
> I've refactored the changes to reduce the probability of dispatching a solitary load, error, timeout, or abort event. Events are no longer dispatched directly (with dispatchEvent()) in XMLHttpRequest. If this sounds like what you wanted, let me know and I'll upload a new patch.
It was exactly what I wanted. I would be happy to look at such a patch (even if it is rough just to assess the added complexity).
> Having done this, it doesn't seem to me like the extra complexity balances the added safety, however I'm new to the code.
Let me look at that and tell you if your gut feeling is OK. Thanks for following up!
Hans Muller
Comment 18
2011-12-16 11:09:55 PST
Created
attachment 119636
[details]
Patch
Hans Muller
Comment 19
2011-12-16 11:10:43 PST
I've uploaded a version of the patch that implements the changes I specified in
comment #16
except for the XMLHttpRequestUpload::dispatchEvent() override. This patch is just for the sake of review: - The XMLHttpRequestUpload::dispatchEvent() override is needed. - XMLHttpRequestProgressEventThrottle::dispatchEvent() should probably "black list" the events that should be dispatched with dispatchFinalProgressEvent() rather than asserting which events are OK. - The ChangeLogs haven't been updated yet.
Julien Chaffraix
Comment 20
2011-12-20 05:48:34 PST
Comment on
attachment 119636
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=119636&action=review
OK, I think your gut feeling was right, If you just upload something along the line of the previous patch with the different comments addressed and the synchronous test cases from this patch, it should be fine by me. Thanks.
> Source/WebCore/ChangeLog:11 > + or error event followed by a loadend event.
ChangeLog not up-to-date as mentioned.
> Source/WebCore/loader/ImageLoader.cpp:1 > +
Unrelated (bad) change.
> Source/WebCore/xml/XMLHttpRequest.cpp:345 > + m_progressEventThrottle.dispatchFinalProgressEvent(XMLHttpRequestProgressEvent::create(eventNames().loadEvent));
You are subtly changing the semantics of the willLoadXHR / didLoadXHR here as we now include 2 events instead of one. I would rather see that the loadendEvent is dispatched after didLoadXHR was called and a bug filed about giving access to the "loadend" event from the WebInspector.
> Source/WebCore/xml/XMLHttpRequestProgressEventThrottle.h:51 > + virtual void dispatchEvent(PassRefPtr<Event>, ProgressEventAction = DoNotFlushProgressEvent);
It shouldn't be virtual.
> Source/WebCore/xml/XMLHttpRequestUpload.h:68 > + void dispatchProgressEvent(bool lengthComputable, unsigned long long loaded, unsigned long long total);
Those 2 should be removed as they don't seem to add much. Same remarks for the XHR throttle.
> Source/WebCore/xml/XMLHttpRequestUpload.h:69 > + void dispatchFinalProgressEvent(PassRefPtr<Event>);
I think I preferred the old name dispatchEventAndLoadendEvent(). ProgressEvent hints a the "progress" event and yet you allow other type of events.
> LayoutTests/http/tests/xmlhttprequest/onloadend-event-after-sync-requests.html:93 > + xhr.open("GET", "resources/get.txt", false);
Great that you added the synchronous case! For coherency, it would be better to have those splitted but it's not a strong requirement.
Hans Muller
Comment 21
2011-12-20 12:00:35 PST
Created
attachment 120053
[details]
Patch
Hans Muller
Comment 22
2011-12-20 12:01:38 PST
This patch is the same as one uploaded on 2011-12-13 08:19 PST, with the following additional changes: Added ASSERT to XMLHttpRequestProgressEventThrottle::dispatchEventAndLoadEnd(), XMLHttpRequestProgressEventUpload::dispatchEventAndLoadEnd(): ASSERT(event->type() == eventNames().loadEvent || event->type() == eventNames().abortEvent || event->type() == eventNames().errorEvent || event->type() == eventNames().timeoutEvent); Removed use of dispatchEventAndLoadEnd() from XMLHttpRequest::callReadyStateChangeListener() to avoid subtly changing the semantics of InspectorInstrumentation:: willLoadXHR()/didLoadXHR(). Will file a bug per (review)
comment #20
.
Julien Chaffraix
Comment 23
2011-12-21 00:58:41 PST
Comment on
attachment 120053
[details]
Patch Please don't forget to file a WebInspector bug about supporting loadend. Also if you want your patch to be committed, you should set for the cq flag to '?'.
WebKit Review Bot
Comment 24
2011-12-22 00:55:21 PST
Comment on
attachment 120053
[details]
Patch Clearing flags on attachment: 120053 Committed
r103502
: <
http://trac.webkit.org/changeset/103502
>
WebKit Review Bot
Comment 25
2011-12-22 00:55:27 PST
All reviewed patches have been landed. Closing bug.
Hans Muller
Comment 26
2012-01-03 11:54:51 PST
(In reply to
comment #23
)
> (From update of
attachment 120053
[details]
) > Please don't forget to file a WebInspector bug about supporting loadend.
Sorry about the delay, it's
https://bugs.webkit.org/show_bug.cgi?id=75483
Note
You need to
log in
before you can comment on or make changes to this bug.
Top of Page
Format For Printing
XML
Clone This Bug