Re: [FileAPI] FileReader.abort() and File[Saver|Writer].abort have different behaviors
On Mon, Oct 3, 2011 at 6:13 PM, Jonas Sicking jo...@sicking.cc wrote: On Mon, Oct 3, 2011 at 5:57 PM, Glenn Maynard gl...@zewt.org wrote: On Mon, Oct 3, 2011 at 8:10 PM, Jonas Sicking jo...@sicking.cc wrote: 1. Make loadend not fire in case a new load is started from onabort/onload/onerror. Thus loadend and loadstart isn't always paired up. Though there is always a loadend fired after every loadstart. 2. Make FileReader/FileWriter/FileSaver not behave like XHR. This also leaves the problem unsolved for XHR. Are there other options I'm missing? Or do both, improving XHR as much as backwards-compatibility allows and don't try to match other APIs to it exactly. I'd much prefer weirdness be isolated to XHR than be perpetuated through every PE-based API. So what exactly are you proposing we do for XHR and for FileReader/FileWriter? I'm still not convinced that it's better for authors to require them to use setTimeout to start a new load as opposed to let them restart the new load from within an event and cancel all following events. I agree that this introduces some inconsistency, but it only does so when authors explicitly reuses a FileReader/XHR/FileWriter for multiple requests. And it only weakens the invariant, not removes it. So instead of * There's exactly one 'loadend' event for each 'loadstart' event. we'll have * There's always a 'loadend' event fired after each 'loadstart' event. However there might be other 'loadstart' events fired in between. I'm for this. It lets FileReader and FileWriter match XHR, avoids [in the odd case] long strings of stacked-up loadend events, and users can avoid all the issues either by creating a new FileReader or by wrapping nested calls in timers if they care. I believe Jonas is in favor of this as well. Can we put this one to bed? Eric
Re: [FileAPI] FileReader.abort() and File[Saver|Writer].abort have different behaviors
On Wed, Nov 2, 2011 at 9:56 AM, Eric U er...@google.com wrote: On Mon, Oct 3, 2011 at 6:13 PM, Jonas Sicking jo...@sicking.cc wrote: On Mon, Oct 3, 2011 at 5:57 PM, Glenn Maynard gl...@zewt.org wrote: On Mon, Oct 3, 2011 at 8:10 PM, Jonas Sicking jo...@sicking.cc wrote: 1. Make loadend not fire in case a new load is started from onabort/onload/onerror. Thus loadend and loadstart isn't always paired up. Though there is always a loadend fired after every loadstart. 2. Make FileReader/FileWriter/FileSaver not behave like XHR. This also leaves the problem unsolved for XHR. Are there other options I'm missing? Or do both, improving XHR as much as backwards-compatibility allows and don't try to match other APIs to it exactly. I'd much prefer weirdness be isolated to XHR than be perpetuated through every PE-based API. So what exactly are you proposing we do for XHR and for FileReader/FileWriter? I'm still not convinced that it's better for authors to require them to use setTimeout to start a new load as opposed to let them restart the new load from within an event and cancel all following events. I agree that this introduces some inconsistency, but it only does so when authors explicitly reuses a FileReader/XHR/FileWriter for multiple requests. And it only weakens the invariant, not removes it. So instead of * There's exactly one 'loadend' event for each 'loadstart' event. we'll have * There's always a 'loadend' event fired after each 'loadstart' event. However there might be other 'loadstart' events fired in between. I'm for this. It lets FileReader and FileWriter match XHR, avoids [in the odd case] long strings of stacked-up loadend events, and users can avoid all the issues either by creating a new FileReader or by wrapping nested calls in timers if they care. I believe Jonas is in favor of this as well. Can we put this one to bed? So the proposal here is to allow new loads to be started from within abort/error/load event handlers, and for loadend to *not* fire if a new load has already started by the time the abort/error/load event is done firing. And the goal is that XMLHttpRequest, FileReader and FileWriter all behave this way. Is this correct? If so, I agree that this sounds like a good solution. / Jonas
Re: [FileAPI] FileReader.abort() and File[Saver|Writer].abort have different behaviors
On Wed, Nov 2, 2011 at 3:56 PM, Jonas Sicking jo...@sicking.cc wrote: On Wed, Nov 2, 2011 at 9:56 AM, Eric U er...@google.com wrote: On Mon, Oct 3, 2011 at 6:13 PM, Jonas Sicking jo...@sicking.cc wrote: On Mon, Oct 3, 2011 at 5:57 PM, Glenn Maynard gl...@zewt.org wrote: On Mon, Oct 3, 2011 at 8:10 PM, Jonas Sicking jo...@sicking.cc wrote: 1. Make loadend not fire in case a new load is started from onabort/onload/onerror. Thus loadend and loadstart isn't always paired up. Though there is always a loadend fired after every loadstart. 2. Make FileReader/FileWriter/FileSaver not behave like XHR. This also leaves the problem unsolved for XHR. Are there other options I'm missing? Or do both, improving XHR as much as backwards-compatibility allows and don't try to match other APIs to it exactly. I'd much prefer weirdness be isolated to XHR than be perpetuated through every PE-based API. So what exactly are you proposing we do for XHR and for FileReader/FileWriter? I'm still not convinced that it's better for authors to require them to use setTimeout to start a new load as opposed to let them restart the new load from within an event and cancel all following events. I agree that this introduces some inconsistency, but it only does so when authors explicitly reuses a FileReader/XHR/FileWriter for multiple requests. And it only weakens the invariant, not removes it. So instead of * There's exactly one 'loadend' event for each 'loadstart' event. we'll have * There's always a 'loadend' event fired after each 'loadstart' event. However there might be other 'loadstart' events fired in between. I'm for this. It lets FileReader and FileWriter match XHR, avoids [in the odd case] long strings of stacked-up loadend events, and users can avoid all the issues either by creating a new FileReader or by wrapping nested calls in timers if they care. I believe Jonas is in favor of this as well. Can we put this one to bed? So the proposal here is to allow new loads to be started from within abort/error/load event handlers, and for loadend to *not* fire if a new load has already started by the time the abort/error/load event is done firing. And the goal is that XMLHttpRequest, FileReader and FileWriter all behave this way. Is this correct? I think I may have missed something important. XHR2 specs just this behavior w.r.t. abort [another open will stop the abort's loadend] but /doesn't/ spec that for error or load. That is, an open() in onerror or onload does not appear to cancel the pending loadend. Anne, can you comment on why? If so, I agree that this sounds like a good solution. / Jonas
Re: [FileAPI] FileReader.abort() and File[Saver|Writer].abort have different behaviors
On 9/30/11 11:14 AM, Anne van Kesteren wrote: On Thu, 29 Sep 2011 23:17:21 +0200, Eric U er...@google.com wrote: I think that works; #2 will be especially important. However, if I read this right, we *don't* have the invariant that a loadstart will always have a loadend. Now that Anne's explained XHR2's model, it seems that an open can cancel the loadend that an abort would have sent. So the invariants need to be a bit more complex. Well lets not accept as XHR2 as set-in-stone. We could also change XHR2 to not cancel abort() when invoking open(). Then you get scenarios such as: abort() - abort event that invokes open() - readystatechange event - loadend event - abort event on XHRUpload - loadend event on XHRUpload Instead of everything after the readystatechange event not happening. We could also introduce a flag and make it impossible to call open() from an event handler. Maybe the simplest is the above. You can call open() from event handlers, but events will still be dispatched (and readyState will have changed). This is somewhat ugly, but then you should probably not invoke open() from event handlers anyway. This gives us the desirable invariant that a loadstart will always have a loadend, which I think simplifies this model. It seems useful to proceed with this in FileAPI. -- A*
Re: [FileAPI] FileReader.abort() and File[Saver|Writer].abort have different behaviors
On Fri, Sep 30, 2011 at 8:14 AM, Anne van Kesteren ann...@opera.com wrote: On Thu, 29 Sep 2011 23:17:21 +0200, Eric U er...@google.com wrote: I think that works; #2 will be especially important. However, if I read this right, we *don't* have the invariant that a loadstart will always have a loadend. Now that Anne's explained XHR2's model, it seems that an open can cancel the loadend that an abort would have sent. So the invariants need to be a bit more complex. Well lets not accept as XHR2 as set-in-stone. We could also change XHR2 to not cancel abort() when invoking open(). Then you get scenarios such as: abort() - abort event that invokes open() - readystatechange event - loadend event - abort event on XHRUpload - loadend event on XHRUpload Instead of everything after the readystatechange event not happening. We could also introduce a flag and make it impossible to call open() from an event handler. Maybe the simplest is the above. You can call open() from event handlers, but events will still be dispatched (and readyState will have changed). This is somewhat ugly, but then you should probably not invoke open() from event handlers anyway. Unfortunately I suspect wanting to call open from event handlers is a pretty common use case. Here are two use cases: 1. In case of a network error, let the onerror handler retry the request. 2. Implementing a auto-complete UI backed by data stored on the server. Any time the user hits another character, abort the current request and perform a new request with the newly typed value. In the first case it makes sense to call .open/.send from the onerror handler. In the second case it makes sense to do so from the onabort handler. I'm personally split on the issue. On one hand I really like the simplicity of saying that each loadstart is always paired with a loadend. On the other hand, I have a hard time thinking of any use cases which *wouldn't* be helped by simply dropping the loadend event if a new load had been started. For example if you're implementing a progress bar, it would be very easy to make the mistake of hiding the progress bar from loadend and showing it in loadstart. In the two use cases above, that would result in the progress bar not showing during the second load. I'll leave as an exercise to the reader how to avoid such a bug ;-) / Jonas
Re: [FileAPI] FileReader.abort() and File[Saver|Writer].abort have different behaviors
On Mon, Oct 3, 2011 at 6:00 PM, Jonas Sicking jo...@sicking.cc wrote: Unfortunately I suspect wanting to call open from event handlers is a pretty common use case. Here are two use cases: 1. In case of a network error, let the onerror handler retry the request. 2. Implementing a auto-complete UI backed by data stored on the server. Any time the user hits another character, abort the current request and perform a new request with the newly typed value. These can be handled trivially by wrapping in a timer. This is a basic platform concept, an approximation of queue a task so common in specs. (#2 isn't actually a problem, since it's an event from a different source--it's only recursing back into the same XHR/FileReader/etc. object from its own events that causes ugliness.) For example if you're implementing a progress bar, it would be very easy to make the mistake of hiding the progress bar from loadend and showing it in loadstart. In the two use cases above, that would result in the progress bar not showing during the second load. I'll leave as an exercise to the reader how to avoid such a bug ;-) This shouldn't be a mistake--it's the natural, obvious way to use these events. You shouldn't have to worry about receiving two loadstarts in a row, or two loadends in a row, or missing loadends, depending on what object is firing the event, how its API is being used, or where your event listener is in the event handler list. Needing to use setTimeout in some cases is a tiny price to pay, to avoid having to worry about that mess and keep these events straightforward and predictable. -- Glenn Maynard
Re: [FileAPI] FileReader.abort() and File[Saver|Writer].abort have different behaviors
On Mon, Oct 3, 2011 at 4:16 PM, Glenn Maynard gl...@zewt.org wrote: On Mon, Oct 3, 2011 at 6:00 PM, Jonas Sicking jo...@sicking.cc wrote: Unfortunately I suspect wanting to call open from event handlers is a pretty common use case. Here are two use cases: 1. In case of a network error, let the onerror handler retry the request. 2. Implementing a auto-complete UI backed by data stored on the server. Any time the user hits another character, abort the current request and perform a new request with the newly typed value. These can be handled trivially by wrapping in a timer. This is a basic platform concept, an approximation of queue a task so common in specs. (#2 isn't actually a problem, since it's an event from a different source--it's only recursing back into the same XHR/FileReader/etc. object from its own events that causes ugliness.) For example if you're implementing a progress bar, it would be very easy to make the mistake of hiding the progress bar from loadend and showing it in loadstart. In the two use cases above, that would result in the progress bar not showing during the second load. I'll leave as an exercise to the reader how to avoid such a bug ;-) This shouldn't be a mistake--it's the natural, obvious way to use these events. You shouldn't have to worry about receiving two loadstarts in a row, or two loadends in a row, or missing loadends, depending on what object is firing the event, how its API is being used, or where your event listener is in the event handler list. Exactly! Needing to use setTimeout in some cases is a tiny price to pay, to avoid having to worry about that mess and keep these events straightforward and predictable. Except that we can't do that for XHR since there's already tons of content out there. Most likely enough of that content starts a new load from onabort/onload/onerror that we can't make that throw. Which leaves us with the following options: 1. Make loadend not fire in case a new load is started from onabort/onload/onerror. Thus loadend and loadstart isn't always paired up. Though there is always a loadend fired after every loadstart. 2. Make FileReader/FileWriter/FileSaver not behave like XHR. This also leaves the problem unsolved for XHR. Are there other options I'm missing? / Jonas
Re: [FileAPI] FileReader.abort() and File[Saver|Writer].abort have different behaviors
On Mon, Oct 3, 2011 at 5:57 PM, Glenn Maynard gl...@zewt.org wrote: On Mon, Oct 3, 2011 at 8:10 PM, Jonas Sicking jo...@sicking.cc wrote: 1. Make loadend not fire in case a new load is started from onabort/onload/onerror. Thus loadend and loadstart isn't always paired up. Though there is always a loadend fired after every loadstart. 2. Make FileReader/FileWriter/FileSaver not behave like XHR. This also leaves the problem unsolved for XHR. Are there other options I'm missing? Or do both, improving XHR as much as backwards-compatibility allows and don't try to match other APIs to it exactly. I'd much prefer weirdness be isolated to XHR than be perpetuated through every PE-based API. So what exactly are you proposing we do for XHR and for FileReader/FileWriter? I'm still not convinced that it's better for authors to require them to use setTimeout to start a new load as opposed to let them restart the new load from within an event and cancel all following events. I agree that this introduces some inconsistency, but it only does so when authors explicitly reuses a FileReader/XHR/FileWriter for multiple requests. And it only weakens the invariant, not removes it. So instead of * There's exactly one 'loadend' event for each 'loadstart' event. we'll have * There's always a 'loadend' event fired after each 'loadstart' event. However there might be other 'loadstart' events fired in between. / Jonas / Jonas
Re: [FileAPI] FileReader.abort() and File[Saver|Writer].abort have different behaviors
On Mon, Oct 3, 2011 at 9:13 PM, Jonas Sicking jo...@sicking.cc wrote: So what exactly are you proposing we do for XHR and for FileReader/FileWriter? For APIs other than XHR, don't allow calling read* or abort during events fired on the object from its own algorithms. This should give the guarantee that loadstart and loadend will always be paired and non-interleaved, and give developers a simple rule: if you need to start a new operation from these events, push it into a timer (queue a task). (More precisely, no method that starts or finishes a loadstart/loadend sequence can be called from within an algorithm that also starts or finishes a sequence. abort() from within onprogress is fine, for example.) I don't have a strong opinion about what to do with XHR--my main worry is not perpetuating ugliness into every PE API in order to mimic XHR. And it only weakens the invariant, not removes it. So instead of * There's exactly one 'loadend' event for each 'loadstart' event. we'll have * There's always a 'loadend' event fired after each 'loadstart' event. However there might be other 'loadstart' events fired in between. When can this happen, with the above restriction in place (speaking of eg. FileReader, not XHR)? -- Glenn Maynard
Re: [FileAPI] FileReader.abort() and File[Saver|Writer].abort have different behaviors
On Mon, Oct 3, 2011 at 6:39 PM, Glenn Maynard gl...@zewt.org wrote: On Mon, Oct 3, 2011 at 9:13 PM, Jonas Sicking jo...@sicking.cc wrote: So what exactly are you proposing we do for XHR and for FileReader/FileWriter? For APIs other than XHR, don't allow calling read* or abort during events fired on the object from its own algorithms. This should give the guarantee that loadstart and loadend will always be paired and non-interleaved, and give developers a simple rule: if you need to start a new operation from these events, push it into a timer (queue a task). (More precisely, no method that starts or finishes a loadstart/loadend sequence can be called from within an algorithm that also starts or finishes a sequence. abort() from within onprogress is fine, for example.) I think this is a higher cost to developers than the cost of having loadstart always be paired up with exactly one loadend. Note that this would mean that you also couldn't start a new load from within the loadend event since that would cause event listeners after yours to receive interleaved loadstart/loadend events. The main problem here is actually the fact that loadend is fired synchronously from read*. If we removed that constraint then we could allow loads to start from anywhere without having to worry about interleaved loadstart/loadend. But it's somewhat doubtful that we can make such a big change to FileReader given that it's been in the wild for a while :( / Jonas
Re: [FileAPI] FileReader.abort() and File[Saver|Writer].abort have different behaviors
On Fri, 30 Sep 2011 19:15:17 +0200, Arun Ranganathan a...@mozilla.com wrote: Anne: I think simplifying the model like this makes sense, although previous discussions seemed to suggest that previous implementation history made these kinds of changes hard. I'd be happy to match this in FileReader if that's what you're doing in XHR2. I believe Glenn said this is what Gecko is doing now (rather than what the standard says). I'm interested in hearing from Glenn, Jonas, and others, but I think Eric's on paternity leave so we'll have to channel him w.r.t. FileSaver/FileWriter :) Yeah, getting more feedback would be nice. -- Anne van Kesteren http://annevankesteren.nl/
Re: [FileAPI] FileReader.abort() and File[Saver|Writer].abort have different behaviors
On Thu, 29 Sep 2011 23:17:21 +0200, Eric U er...@google.com wrote: I think that works; #2 will be especially important. However, if I read this right, we *don't* have the invariant that a loadstart will always have a loadend. Now that Anne's explained XHR2's model, it seems that an open can cancel the loadend that an abort would have sent. So the invariants need to be a bit more complex. Well lets not accept as XHR2 as set-in-stone. We could also change XHR2 to not cancel abort() when invoking open(). Then you get scenarios such as: abort() - abort event that invokes open() - readystatechange event - loadend event - abort event on XHRUpload - loadend event on XHRUpload Instead of everything after the readystatechange event not happening. We could also introduce a flag and make it impossible to call open() from an event handler. Maybe the simplest is the above. You can call open() from event handlers, but events will still be dispatched (and readyState will have changed). This is somewhat ugly, but then you should probably not invoke open() from event handlers anyway. -- Anne van Kesteren http://annevankesteren.nl/
Re: [FileAPI] FileReader.abort() and File[Saver|Writer].abort have different behaviors
On Thu, Sep 29, 2011 at 12:22 PM, Arun Ranganathan a...@mozilla.com wrote: On 9/21/11 8:07 PM, Eric U wrote: Update: I have made the changes to FileWriter/FileSaver's event sequences; they now match FileReader. That's not to say it won't change pending discussion, but FileWriter should continue to match FileReader whatever else happens. Eric Eric: After reading this email thread, and looking at your changes, I think I'll make the following changes: 1. Tighten requirement on onprogress such that we mandate firing *at least one* progress event with a must. Right now this is unclear as you point out, not least of all because we don't mandate the user agent calling onprogress. 2. Include a discussion of the invariants Jonas mentions [1], so that event order is fleshed in the event section. 3. Clarify exceptions to the 50ms event dispatch timeframe (notably for progress events before load+loadend). To be clear, you've decided we're NOT going to veer from XHR2's abort/open behavior (and thus what FileReader says now) in FileWriter/FileSaver right? Is this a good summary of changes that we should make? -- A* [1] http://lists.w3.org/Archives/Public/public-webapps/2011JulSep/1512.html I think that works; #2 will be especially important. However, if I read this right, we *don't* have the invariant that a loadstart will always have a loadend. Now that Anne's explained XHR2's model, it seems that an open can cancel the loadend that an abort would have sent. So the invariants need to be a bit more complex. I've updated FileWriter to take most of this into account, but *not* that last bit yet; as written, I've got Jonas's original invariants, which would lead to the stacked up loadend events at the end.
Re: [FileAPI] FileReader.abort() and File[Saver|Writer].abort have different behaviors
On 9/21/11 8:07 PM, Eric U wrote: Update: I have made the changes to FileWriter/FileSaver's event sequences; they now match FileReader. That's not to say it won't change pending discussion, but FileWriter should continue to match FileReader whatever else happens. Eric Eric: After reading this email thread, and looking at your changes, I think I'll make the following changes: 1. Tighten requirement on onprogress such that we mandate firing *at least one* progress event with a must. Right now this is unclear as you point out, not least of all because we don't mandate the user agent calling onprogress. 2. Include a discussion of the invariants Jonas mentions [1], so that event order is fleshed in the event section. 3. Clarify exceptions to the 50ms event dispatch timeframe (notably for progress events before load+loadend). To be clear, you've decided we're NOT going to veer from XHR2's abort/open behavior (and thus what FileReader says now) in FileWriter/FileSaver right? Is this a good summary of changes that we should make? -- A* [1] http://lists.w3.org/Archives/Public/public-webapps/2011JulSep/1512.html
Re: [FileAPI] FileReader.abort() and File[Saver|Writer].abort have different behaviors
On Wed, 21 Sep 2011 20:12:17 +0200, Glenn Maynard gl...@zewt.org wrote: Yuck. I agree that's not a good thing to mimic for the sake of consistency. Anne, is this intentional, or just something XHR is just stuck with for compatibility? It looks like a new problem in XHR2--this couldn't happen in XHR1, because there was no abort event fired before loadend. The send() method can be terminated in similar fashion. I made this change almost a year ago now. It was to prevent weird situations from occurring event-wise if you invoke open() from one of the events dispatched by e.g. send() or abort(). One of the silly things from XMLHttpRequest is that open() can always be invoked. This seemed like the simplest way of dealing with that. I am open to suggestions however (and tests!). -- Anne van Kesteren http://annevankesteren.nl/
Re: [FileAPI] FileReader.abort() and File[Saver|Writer].abort have different behaviors
On Thu, 22 Sep 2011 04:01:40 +0200, Glenn Maynard gl...@zewt.org wrote: To my reading, a substep is a type of step. The after finishing... sounds like it's saying not to terminate the currently-executing step; that is, the event dispatch isn't stopped in the middle. Maybe steps vs. substeps are precisely defined somewhere else, but either way this could probably be clearer. Anne? Your interpretation is correct. I could make it say step or substep but it seems people might want something else altogether. I just tried this in FF6, and the behavior is inconsistent. If the TCP connection has been established, then it follows your interpretation, and you get onloadstart, onabort, onloadstart, onloadend, onloadend [1][3]. If the TCP connection hasn't yet been established [2][4], calling open() from either onabort or onloadend throws NS_ERROR_IN_PROGRESS. But open() has to dispatch a readystatechange event. That will get somewhere in the middle of that, no? With the various inconsistencies, I wonder if the spec can't actually be changed to disallow open() during the events, following FF6--that NS_ERROR_IN_PROGRESS is probably unintentional, but it's in a shipping browser nonetheless. Wishful thinking, maybe... There is the same problem with send() but there it was not a problem before either because you just had readystatechange. This sounds like a bug in the XHR spec as it doesn't fulfill the invariants I listed. I agree with those invariants, but they aren't normative anywhere, are they? Nope. -- Anne van Kesteren http://annevankesteren.nl/
Re: [FileAPI] FileReader.abort() and File[Saver|Writer].abort have different behaviors
On Thu, Sep 22, 2011 at 5:19 AM, Anne van Kesteren ann...@opera.com wrote: I just tried this in FF6, and the behavior is inconsistent. If the TCP connection has been established, then it follows your interpretation, and you get onloadstart, onabort, onloadstart, onloadend, onloadend [1][3]. If the TCP connection hasn't yet been established [2][4], calling open() from either onabort or onloadend throws NS_ERROR_IN_PROGRESS. But open() has to dispatch a readystatechange event. That will get somewhere in the middle of that, no? Sorry, I meant calling send() throws NS_ERROR_IN_PROGRESS. -- Glenn Maynard
Re: [FileAPI] FileReader.abort() and File[Saver|Writer].abort have different behaviors
On Tue, Sep 20, 2011 at 8:40 PM, Eric U er...@google.com wrote: Indeed--however, from a quick skim of XHR and XHR2, that's not what they do. They let open() terminate abort(), however far along it's gotten. If we did that, then an abort killed by a read might lead to the aborted read never getting an onloadend. But you could still get the stack-busting chain of onloadstart/onabort. Yuck. I agree that's not a good thing to mimic for the sake of consistency. Anne, is this intentional, or just something XHR is just stuck with for compatibility? It looks like a new problem in XHR2--this couldn't happen in XHR1, because there was no abort event fired before loadend. If we wanted to prevent read methods from being called during abort, we'd probably want to do that by setting an aborting flag or mucking around with yet another readyState of ABORTING. That's annoying, but it's better than the current situation, and I think better than the XHR situation. Receiving loadstart should guarantee the receipt of loadend. On Tue, Sep 20, 2011 at 7:43 PM, Jonas Sicking jo...@sicking.cc wrote: 1. onloadstart fires exactly once 2. There will be one onprogress event fired when 100% progress is reached 3. Exactly one of onabort, onload and onerror fires 4. onloadend fires exactly once. 6. no onprogress events fire before onloadstart 5. no onprogress events fire after onabort/onload/onerror 6. no onabort/onoad/onerror events fire after onloadend 7. after loadstart is fired, loadstart is not fired again until loadend has been fired (ie. only one set of progress events can be active on an object at one time). More precisely: loadstart should not be fired again until the dispatch of loadend *has completed*. That is, you can't start a new progress sequence from within loadend, either, because there may be other listeners on the object that havn't yet received the loadend. -- Glenn Maynard
Re: [FileAPI] FileReader.abort() and File[Saver|Writer].abort have different behaviors
On Wed, Sep 21, 2011 at 11:12 AM, Glenn Maynard gl...@zewt.org wrote: On Tue, Sep 20, 2011 at 8:40 PM, Eric U er...@google.com wrote: Indeed--however, from a quick skim of XHR and XHR2, that's not what they do. They let open() terminate abort(), however far along it's gotten. If we did that, then an abort killed by a read might lead to the aborted read never getting an onloadend. But you could still get the stack-busting chain of onloadstart/onabort. Yuck. I agree that's not a good thing to mimic for the sake of consistency. Anne, is this intentional, or just something XHR is just stuck with for compatibility? It looks like a new problem in XHR2--this couldn't happen in XHR1, because there was no abort event fired before loadend. If we wanted to prevent read methods from being called during abort, we'd probably want to do that by setting an aborting flag or mucking around with yet another readyState of ABORTING. That's annoying, but it's better than the current situation, and I think better than the XHR situation. Receiving loadstart should guarantee the receipt of loadend. On Tue, Sep 20, 2011 at 7:43 PM, Jonas Sicking jo...@sicking.cc wrote: 1. onloadstart fires exactly once 2. There will be one onprogress event fired when 100% progress is reached 3. Exactly one of onabort, onload and onerror fires 4. onloadend fires exactly once. 6. no onprogress events fire before onloadstart 5. no onprogress events fire after onabort/onload/onerror 6. no onabort/onoad/onerror events fire after onloadend 7. after loadstart is fired, loadstart is not fired again until loadend has been fired (ie. only one set of progress events can be active on an object at one time). More precisely: loadstart should not be fired again until the dispatch of loadend *has completed*. That is, you can't start a new progress sequence from within loadend, either, because there may be other listeners on the object that havn't yet received the loadend. I don't think we can do that for XHR without breaking backwards compat. / Jonas
Re: [FileAPI] FileReader.abort() and File[Saver|Writer].abort have different behaviors
On Wed, Sep 21, 2011 at 2:28 PM, Jonas Sicking jo...@sicking.cc wrote: On Wed, Sep 21, 2011 at 11:12 AM, Glenn Maynard gl...@zewt.org wrote: On Tue, Sep 20, 2011 at 8:40 PM, Eric U er...@google.com wrote: Indeed--however, from a quick skim of XHR and XHR2, that's not what they do. They let open() terminate abort(), however far along it's gotten. If we did that, then an abort killed by a read might lead to the aborted read never getting an onloadend. But you could still get the stack-busting chain of onloadstart/onabort. Yuck. I agree that's not a good thing to mimic for the sake of consistency. Anne, is this intentional, or just something XHR is just stuck with for compatibility? It looks like a new problem in XHR2--this couldn't happen in XHR1, because there was no abort event fired before loadend. If we wanted to prevent read methods from being called during abort, we'd probably want to do that by setting an aborting flag or mucking around with yet another readyState of ABORTING. That's annoying, but it's better than the current situation, and I think better than the XHR situation. Receiving loadstart should guarantee the receipt of loadend. On Tue, Sep 20, 2011 at 7:43 PM, Jonas Sicking jo...@sicking.cc wrote: 1. onloadstart fires exactly once 2. There will be one onprogress event fired when 100% progress is reached 3. Exactly one of onabort, onload and onerror fires 4. onloadend fires exactly once. 6. no onprogress events fire before onloadstart 5. no onprogress events fire after onabort/onload/onerror 6. no onabort/onoad/onerror events fire after onloadend 7. after loadstart is fired, loadstart is not fired again until loadend has been fired (ie. only one set of progress events can be active on an object at one time). More precisely: loadstart should not be fired again until the dispatch of loadend *has completed*. That is, you can't start a new progress sequence from within loadend, either, because there may be other listeners on the object that havn't yet received the loadend. I don't think we can do that for XHR without breaking backwards compat. I just spent a bit more time with the XHR2 spec, and it looks like the same looping behavior's legal there too, bouncing between onreadystatechange and onabort, and stacking up a pending call to onloadend for each loop. When open terminates abort, abort completes the step of the algorithm [here step 5], which includes a subsequent call to onloadend. It's not a queued task to be cancelled, as it's all synchronous calls back and forth. If we want the file specs to match the XHR spec, then we can just leave this as it is in File Reader, and I'll match it in File Writer. Recursion depth limit is up to the UA to set. But I look forward to hearing what Anne has to say about it before we settle on copying it.
Re: [FileAPI] FileReader.abort() and File[Saver|Writer].abort have different behaviors
On Wed, Sep 21, 2011 at 2:44 PM, Eric U er...@google.com wrote: On Wed, Sep 21, 2011 at 2:28 PM, Jonas Sicking jo...@sicking.cc wrote: On Wed, Sep 21, 2011 at 11:12 AM, Glenn Maynard gl...@zewt.org wrote: On Tue, Sep 20, 2011 at 8:40 PM, Eric U er...@google.com wrote: Indeed--however, from a quick skim of XHR and XHR2, that's not what they do. They let open() terminate abort(), however far along it's gotten. If we did that, then an abort killed by a read might lead to the aborted read never getting an onloadend. But you could still get the stack-busting chain of onloadstart/onabort. Yuck. I agree that's not a good thing to mimic for the sake of consistency. Anne, is this intentional, or just something XHR is just stuck with for compatibility? It looks like a new problem in XHR2--this couldn't happen in XHR1, because there was no abort event fired before loadend. If we wanted to prevent read methods from being called during abort, we'd probably want to do that by setting an aborting flag or mucking around with yet another readyState of ABORTING. That's annoying, but it's better than the current situation, and I think better than the XHR situation. Receiving loadstart should guarantee the receipt of loadend. On Tue, Sep 20, 2011 at 7:43 PM, Jonas Sicking jo...@sicking.cc wrote: 1. onloadstart fires exactly once 2. There will be one onprogress event fired when 100% progress is reached 3. Exactly one of onabort, onload and onerror fires 4. onloadend fires exactly once. 6. no onprogress events fire before onloadstart 5. no onprogress events fire after onabort/onload/onerror 6. no onabort/onoad/onerror events fire after onloadend 7. after loadstart is fired, loadstart is not fired again until loadend has been fired (ie. only one set of progress events can be active on an object at one time). More precisely: loadstart should not be fired again until the dispatch of loadend *has completed*. That is, you can't start a new progress sequence from within loadend, either, because there may be other listeners on the object that havn't yet received the loadend. I don't think we can do that for XHR without breaking backwards compat. I just spent a bit more time with the XHR2 spec, and it looks like the same looping behavior's legal there too, bouncing between onreadystatechange and onabort, and stacking up a pending call to onloadend for each loop. When open terminates abort, abort completes the step of the algorithm [here step 5], which includes a subsequent call to onloadend. It's not a queued task to be cancelled, as it's all synchronous calls back and forth. If we want the file specs to match the XHR spec, then we can just leave this as it is in File Reader, and I'll match it in File Writer. Recursion depth limit is up to the UA to set. But I look forward to hearing what Anne has to say about it before we settle on copying it. I think we're basically limited here by over 10 years of IE code. For what it's worth, it's fairly easy for pages to avoid the problems here. If a page listens to the loadend event, it should do any aborting or new-load-starting here. If it doesn't listen to loadend, then the event order it will see will be quite sensible. I.e. if you remove loadend from the list of events that you had, it looks quite logical. / Jonas
Re: [FileAPI] FileReader.abort() and File[Saver|Writer].abort have different behaviors
On Wed, Sep 21, 2011 at 5:44 PM, Eric U er...@google.com wrote: If we want the file specs to match the XHR spec, then we can just leave this as it is in File Reader, and I'll match it in File Writer. Recursion depth limit is up to the UA to set. But I look forward to hearing what Anne has to say about it before we settle on copying it. In my opinion, providing the no nesting guarantee is more useful than being consistent with XHR, if all new APIs provide it. This sort of thing seems obviously useful: function showActivity(obj) { obj.addEventHandler(loadstart, function() { div.hidden = false; }, false); obj.addEventHandler(loadend, function() { div.hidden = true; }, false); } With the currently specced behavior, this doesn't work--the div would end up hidden when it should be shown. You shouldn't have to care how other code is triggering reads to do something this simple. -- Glenn Maynard
Re: [FileAPI] FileReader.abort() and File[Saver|Writer].abort have different behaviors
On Wed, Sep 21, 2011 at 3:09 PM, Glenn Maynard gl...@zewt.org wrote: On Wed, Sep 21, 2011 at 5:44 PM, Eric U er...@google.com wrote: If we want the file specs to match the XHR spec, then we can just leave this as it is in File Reader, and I'll match it in File Writer. Recursion depth limit is up to the UA to set. But I look forward to hearing what Anne has to say about it before we settle on copying it. In my opinion, providing the no nesting guarantee is more useful than being consistent with XHR, if all new APIs provide it. If we eliminate it entirely, then you can't ever start a new read on the same object from the abort handler. That seems like a reasonable use case. This sort of thing seems obviously useful: function showActivity(obj) { obj.addEventHandler(loadstart, function() { div.hidden = false; }, false); obj.addEventHandler(loadend, function() { div.hidden = true; }, false); } With the currently specced behavior, this doesn't work--the div would end up hidden when it should be shown. You shouldn't have to care how other code is triggering reads to do something this simple. Adding a number-of-reads-outstanding counter isn't that much more code. And if you're really trying to keep things simple, you're not aborting and then starting another read during the abort, so the above code works in your app.
Re: [FileAPI] FileReader.abort() and File[Saver|Writer].abort have different behaviors
On Wed, Sep 21, 2011 at 6:14 PM, Eric U er...@google.com wrote: If we eliminate it entirely, then you can't ever start a new read on the same object from the abort handler. That seems like a reasonable use case. It's trivial to stuff it into a zero-second timeout to knock it out of the event handler. This is such a common and useful pattern that libraries have shorthand for it, eg. Prototype's Function#defer. I don't think that's an onerous requirement at all; it's basically the same as specs saying queue an event. Adding a number-of-reads-outstanding counter isn't that much more code. It's not much more code, but it's code dealing with a case that doesn't have to exist, working around a very ugly and unobvious sequence of events, and it's something that you really shouldn't have to worry about every single time you use loadstart/loadend pairs. And if you're really trying to keep things simple, you're not aborting and then starting another read during the abort, so the above code works in your app. The above code and the code triggering the reads might not even be written by the same people--the activity display might be a third-party component (who very well might not have thought of this; I wouldn't have, before this discussion). -- Glenn Maynard
Re: [FileAPI] FileReader.abort() and File[Saver|Writer].abort have different behaviors
On Wed, Sep 21, 2011 at 3:29 PM, Glenn Maynard gl...@zewt.org wrote: On Wed, Sep 21, 2011 at 6:14 PM, Eric U er...@google.com wrote: If we eliminate it entirely, then you can't ever start a new read on the same object from the abort handler. That seems like a reasonable use case. It's trivial to stuff it into a zero-second timeout to knock it out of the event handler. This is such a common and useful pattern that libraries have shorthand for it, eg. Prototype's Function#defer. I don't think that's an onerous requirement at all; it's basically the same as specs saying queue an event. While it's certainly not hard to work around, as you say, it seems more complex and less likely to be obvious than the counter-for-activity example, which feels like the classic push-pop paradigm. And expecting users to write their event handlers one way for XHR and a different way for FileReader/FileWriter seems like asking for trouble--you're going to get issues that only come up in exceptional cases, and involve a fairly subtle reading of several specs to get right. I think we're better off going with consistency. Adding a number-of-reads-outstanding counter isn't that much more code. It's not much more code, but it's code dealing with a case that doesn't have to exist, working around a very ugly and unobvious sequence of events, and it's something that you really shouldn't have to worry about every single time you use loadstart/loadend pairs. And if you're really trying to keep things simple, you're not aborting and then starting another read during the abort, so the above code works in your app. The above code and the code triggering the reads might not even be written by the same people--the activity display might be a third-party component (who very well might not have thought of this; I wouldn't have, before this discussion). -- Glenn Maynard
Re: [FileAPI] FileReader.abort() and File[Saver|Writer].abort have different behaviors
On Wed, Sep 21, 2011 at 6:51 PM, Eric U er...@google.com wrote: While it's certainly not hard to work around, as you say, it seems more complex and less likely to be obvious than the counter-for-activity example, which feels like the classic push-pop paradigm. The *need* to have counters to use loadstart/loadend at all isn't obvious, and it's a guarantee that many (perhaps most) users won't do this. Pulling code out of events with a timer isn't at all complex--it's a simple, common pattern. I think it's much more obvious, since if you don't do it an exception is raised (that you can search for if you don't know what to do), instead of a subtle bug being introduced. Also note that XHR cancels the abort method entirely if you start a new request during onabort, which means loadend isn't fired. Having mismatched loadstart/loadend events seems equally ugly, and not something to try to be consistent with even if we're stuck with it for XHR. And expecting users to write their event handlers one way for XHR and a different way for FileReader/FileWriter seems like asking for trouble--you're going to get issues that only come up in exceptional cases, and involve a fairly subtle reading of several specs to get right. I think we're better off going with consistency. You can write code for XHR in the same way, if you want, punting open() calls out of abort/loadend event handlers with a timer. It'd be depressing to see PE turn so ugly in an attempt to be consistent with a flawed legacy API; better to isolate the problem as much as possible. (Are there any other APIs with this problem besides XHR that couldn't be fixed?) Another way to deal with this is to make loadstart (and other parts of those calls, the error paths in particular) async, so if you start a new read within onabort, it won't actually start until the abort finishes. (That's a more invasive behavioral change, of course, and I'm not sure I'd like it myself, but it's worth at least mentioning.) -- Glenn Maynard
Re: [FileAPI] FileReader.abort() and File[Saver|Writer].abort have different behaviors
On Wed, Sep 21, 2011 at 7:51 PM, Eric U er...@google.com wrote: Again, that's not what the XHR2 spec says. See my summary up-thread about the actual behavior, and Anne can correct my interpretation if I'm wrong. I don't know what you mean by again; this is the first time I've described this behavior. The spec says The abort() algorithm can only be terminated by invoking open() from an event handler. If you call open() from 5.6.2's onabort, then step 14 of the open() algorithm terminates abort(), and step 5.6.3 never happens, thus onloadend is never fired and loadstart and loadend events are mismatched. Expecting users to rewrite handlers for XHR to match a new API, where it's not necessary for XHR's use, seems wildly optimistic. I don't know what you're referring to. If it clearly doesn't work (because it's throwing an exception), they have to change their code, and it'll be immediately obvious that they need to do so; there's no optimism involved. -- Glenn Maynard
Re: [FileAPI] FileReader.abort() and File[Saver|Writer].abort have different behaviors
On Wed, Sep 21, 2011 at 5:16 PM, Glenn Maynard gl...@zewt.org wrote: On Wed, Sep 21, 2011 at 7:51 PM, Eric U er...@google.com wrote: Again, that's not what the XHR2 spec says. See my summary up-thread about the actual behavior, and Anne can correct my interpretation if I'm wrong. I don't know what you mean by again; this is the first time I've described this behavior. The spec says The abort() algorithm can only be terminated by invoking open() from an event handler. If you call open() from 5.6.2's onabort, then step 14 of the open() algorithm terminates abort(), and step 5.6.3 never happens, thus onloadend is never fired and loadstart and loadend events are mismatched. This sounds like a bug in the XHR spec as it doesn't fulfill the invariants I listed. / Jonas
Re: [FileAPI] FileReader.abort() and File[Saver|Writer].abort have different behaviors
On Wed, Sep 21, 2011 at 8:32 PM, Eric U er...@google.com wrote: 5.6.3 is a substep, not a step; all of 5's substeps are referred to as such in step 5: Otherwise run these substeps:. However, I believe we were actually discussing 5.5, loadend on the XHR itself. Either way, the below applies to both. Regarding what happens on abort: This algorithm can be terminated by invoking the open() method. When it is terminated the user agent must terminate the algorithm after finishing the step it is on. I read that as saying that if you call open while in onabort [5.4], it completes step 5, including all of substep 5.6, including 5.5 and 5.6.3. Do you think I'm mistaken? I haven't run any test cases. To my reading, a substep is a type of step. The after finishing... sounds like it's saying not to terminate the currently-executing step; that is, the event dispatch isn't stopped in the middle. Maybe steps vs. substeps are precisely defined somewhere else, but either way this could probably be clearer. Anne? I just tried this in FF6, and the behavior is inconsistent. If the TCP connection has been established, then it follows your interpretation, and you get onloadstart, onabort, onloadstart, onloadend, onloadend [1][3]. If the TCP connection hasn't yet been established [2][4], calling open() from either onabort or onloadend throws NS_ERROR_IN_PROGRESS. Chrome 14 is also inconsistent. If the TCP connection has been established [1][3], and it's still waiting for the HTTP response, abort() seems to do nothing. If the connection hasn't yet been established [2], abort() does work, and open() can be called. onloadend is unimplemented, so the above question is untestable [4]. (IE9 doesn't implement any of these events.) With the various inconsistencies, I wonder if the spec can't actually be changed to disallow open() during the events, following FF6--that NS_ERROR_IN_PROGRESS is probably unintentional, but it's in a shipping browser nonetheless. Wishful thinking, maybe... Tests: [1] https://zewt.org/~glenn/test-open-during-onabort.html#http/https://zewt.org/%7Eglenn/test-open-during-onabort.html#timeout/loadend onaborthttps://zewt.org/%7Eglenn/test-open-during-onabort.html#timeout/loadend(HTTP timeout) [2] https://zewt.org/~glenn/test-open-during-onabort.html#tcp/onaborthttps://zewt.org/%7Eglenn/test-open-during-onabort.html#timeout/loadend(TCP timeout) [3] https://zewt.org/~glenn/test-open-during-onabort.html#http/onloadendhttps://zewt.org/%7Eglenn/test-open-during-onabort.html#timeout/loadend [4] https://zewt.org/~glenn/test-open-during-onabort.html#tcp/onloadendhttps://zewt.org/%7Eglenn/test-open-during-onabort.html#timeout/loadend My point was that if it doesn't throw an exception in XHR, they won't write their XHR handlers that way. And so they haven't, and have legacy code. And when they add FileWriter handlers, they'll copy the XHR code, and it will work most of the time, because an abort is an exceptional case, and then it will fail in the field. It's exceptional, but not obscure--this couldn't go unnoticed through basic testing, since it fails with an exception. (If people don't test their abort code path *at all*, it isn't going to work regardless of what we do--the goal should be to make things reliably testable, not to allow people to deploy code without testing anything.) I think the bugs resulting from out-of-order loadstart/loadend messages would be very easy to miss through regular testing, more annoying to have to work around, and more likely to be triggered by code written by another party (eg. the activity-monitor case). On Wed, Sep 21, 2011 at 8:34 PM, Jonas Sicking jo...@sicking.cc wrote: The spec says The abort() algorithm can only be terminated by invoking open() from an event handler. If you call open() from 5.6.2's onabort, then step 14 of the open() algorithm terminates abort(), and step 5.6.3 never happens, thus onloadend is never fired and loadstart and loadend events are mismatched. This sounds like a bug in the XHR spec as it doesn't fulfill the invariants I listed. I agree with those invariants, but they aren't normative anywhere, are they? -- Glenn Maynard
Re: [FileAPI] FileReader.abort() and File[Saver|Writer].abort have different behaviors
On Mon, May 23, 2011 at 6:19 PM, Arun Ranganathan a...@mozilla.com wrote: On 5/23/11 6:14 PM, Arun Ranganathan wrote: On 5/23/11 1:20 PM, Kyle Huey wrote: To close the loop a bit here, Firefox 6 will make the change to FileReader.abort()'s throwing behavior agreed upon here. (https://bugzilla.mozilla.org/show_bug.cgi?id=657964) We have not changed the timing of the events, which are still dispatched synchronously. The editor's draft presently does nothing when readyState is EMPTY, but if readyState is DONE it is specified to set result to null and fire events (but flush any pending tasks that are queued). http://dev.w3.org/2006/webapi/FileAPI/#dfn-abort Also note that we're NOT firing *both* error and abort; we should only fire abort, and *not* error. I should change the spec. to throw. Eric, you might change the spec. (and Chrome) to NOT fire error and abort events :) Sorry, to be a bit clearer: I'm talking about Eric changing http://dev.w3.org/2009/dap/file-system/file-writer.html#widl-FileSaver-abort-void to match http://dev.w3.org/2006/webapi/FileAPI/#dfn-abort -- A* Sorry about the long delay here--a big release and a new baby absorbed a lot of my time. I'm going through the abort sequence right now, and it turns out that there are a number of places in various algorithms in FileWriter that should match FileReader more closely than they do. However, there a couple of edge cases I'm unsure about. 1) Do you expect there to be an event called progress that indicates a complete read, before the load event? user agents MUST return at least one such result while processing this read method, with the last returned value at completion of the read -- Does that mean during onprogress, or would during onloadend be sufficient? What if the whole blob is read in a single backend operation--could there be no calls to onprogress at all? [Side note--the phrasing there is odd. You say that useragents MUST return, but the app's not required to call for the value, and it can't return it if not asked. Did you want to require the useragent to make at least one onprogress call?] 2) The load and loadend events are queued When the data from the blob has been completely read into memory. If the user agent fires an onprogress indicating all the data's been loaded, and the app calls abort in that event handler, should those queued events be fired or not? If there are any tasks from the object's FileReader task source in one of the task queues, then remove those tasks. makes it look like no, but I wanted to make sure. If #1 above is no or not necessarily, then this might not ever come up anyway. Thanks, Eric
Re: [FileAPI] FileReader.abort() and File[Saver|Writer].abort have different behaviors
On Tue, Sep 20, 2011 at 3:36 PM, Eric U er...@google.com wrote: On Mon, May 23, 2011 at 6:19 PM, Arun Ranganathan a...@mozilla.com wrote: On 5/23/11 6:14 PM, Arun Ranganathan wrote: On 5/23/11 1:20 PM, Kyle Huey wrote: To close the loop a bit here, Firefox 6 will make the change to FileReader.abort()'s throwing behavior agreed upon here. (https://bugzilla.mozilla.org/show_bug.cgi?id=657964) We have not changed the timing of the events, which are still dispatched synchronously. The editor's draft presently does nothing when readyState is EMPTY, but if readyState is DONE it is specified to set result to null and fire events (but flush any pending tasks that are queued). http://dev.w3.org/2006/webapi/FileAPI/#dfn-abort Also note that we're NOT firing *both* error and abort; we should only fire abort, and *not* error. I should change the spec. to throw. Eric, you might change the spec. (and Chrome) to NOT fire error and abort events :) Sorry, to be a bit clearer: I'm talking about Eric changing http://dev.w3.org/2009/dap/file-system/file-writer.html#widl-FileSaver-abort-void to match http://dev.w3.org/2006/webapi/FileAPI/#dfn-abort -- A* Sorry about the long delay here--a big release and a new baby absorbed a lot of my time. I'm going through the abort sequence right now, and it turns out that there are a number of places in various algorithms in FileWriter that should match FileReader more closely than they do. However, there a couple of edge cases I'm unsure about. 1) Do you expect there to be an event called progress that indicates a complete read, before the load event? On further reflection, another requirement prevents this in some cases. If you've made a non-terminal progress event less than 50ms before completion, you're not permitted to make another at completion, so I think you'd go straight to load and loadend. However, if the entire load took place in a single underlying operation that took less than 50ms, do you have your choice of whether or not to fire onprogress once before onload? user agents MUST return at least one such result while processing this read method, with the last returned value at completion of the read -- Does that mean during onprogress, or would during onloadend be sufficient? What if the whole blob is read in a single backend operation--could there be no calls to onprogress at all? [Side note--the phrasing there is odd. You say that useragents MUST return, but the app's not required to call for the value, and it can't return it if not asked. Did you want to require the useragent to make at least one onprogress call?] 2) The load and loadend events are queued When the data from the blob has been completely read into memory. If the user agent fires an onprogress indicating all the data's been loaded, and the app calls abort in that event handler, should those queued events be fired or not? If there are any tasks from the object's FileReader task source in one of the task queues, then remove those tasks. makes it look like no, but I wanted to make sure. If #1 above is no or not necessarily, then this might not ever come up anyway. Thanks, Eric
Re: [FileAPI] FileReader.abort() and File[Saver|Writer].abort have different behaviors
On Tue, Sep 20, 2011 at 4:43 PM, Jonas Sicking jo...@sicking.cc wrote: On Tue, Sep 20, 2011 at 4:28 PM, Eric U er...@google.com wrote: On Tue, Sep 20, 2011 at 3:36 PM, Eric U er...@google.com wrote: On Mon, May 23, 2011 at 6:19 PM, Arun Ranganathan a...@mozilla.com wrote: On 5/23/11 6:14 PM, Arun Ranganathan wrote: On 5/23/11 1:20 PM, Kyle Huey wrote: To close the loop a bit here, Firefox 6 will make the change to FileReader.abort()'s throwing behavior agreed upon here. (https://bugzilla.mozilla.org/show_bug.cgi?id=657964) We have not changed the timing of the events, which are still dispatched synchronously. The editor's draft presently does nothing when readyState is EMPTY, but if readyState is DONE it is specified to set result to null and fire events (but flush any pending tasks that are queued). http://dev.w3.org/2006/webapi/FileAPI/#dfn-abort Also note that we're NOT firing *both* error and abort; we should only fire abort, and *not* error. I should change the spec. to throw. Eric, you might change the spec. (and Chrome) to NOT fire error and abort events :) Sorry, to be a bit clearer: I'm talking about Eric changing http://dev.w3.org/2009/dap/file-system/file-writer.html#widl-FileSaver-abort-void to match http://dev.w3.org/2006/webapi/FileAPI/#dfn-abort -- A* Sorry about the long delay here--a big release and a new baby absorbed a lot of my time. I'm going through the abort sequence right now, and it turns out that there are a number of places in various algorithms in FileWriter that should match FileReader more closely than they do. However, there a couple of edge cases I'm unsure about. 1) Do you expect there to be an event called progress that indicates a complete read, before the load event? On further reflection, another requirement prevents this in some cases. If you've made a non-terminal progress event less than 50ms before completion, you're not permitted to make another at completion, so I think you'd go straight to load and loadend. However, if the entire load took place in a single underlying operation that took less than 50ms, do you have your choice of whether or not to fire onprogress once before onload? This is a spec-bug. We need to make an exception from the 50ms rule for the last onprogress event. From the webpage point of view, the following invariants should hold for each load: 1. onloadstart fires exactly once 2. There will be one onprogress event fired when 100% progress is reached 3. Exactly one of onabort, onload and onerror fires 4. onloadend fires exactly once. 6. no onprogress events fire before onloadstart 5. no onprogress events fire after onabort/onload/onerror 6. no onabort/onoad/onerror events fire after onloadend The reason for 2 is so that the page always renders a complete progress bar if it only does progressbar updates from the onprogress event. Hope that makes sense? It makes sense, and in general I like it. But the sequence can get more complicated [specifically, nested] if you have multiple read calls, which is the kind of annoyance that brought me to send the email. I have a read running, and at some point I abort it--it could be in onprogress or elsewhere. In onabort I start another read. In onloadstart I abort again. Repeat as many times as you like, then let a read complete. I believe we've specced that the event sequence should look like this: loadstart [progress]* --[events from here to XXX happen synchronously, with no queueing] abort loadstart abort loadstart abort loadstart loadend loadend loadend --[XXX] [progress]+ load loadend Does that look like what you'd expect? Am I reading it right? Yes, this is a wacky fringe case. But it's certainly reasonable to expect someone to start a new read in onabort, so you have to implement at least enough bookkeeping for that case. And UAs will want to defend against stack overflow, in the event that a bad app sticks in an abort/loadstart loop.
Re: [FileAPI] FileReader.abort() and File[Saver|Writer].abort have different behaviors
On Tue, Sep 20, 2011 at 8:01 PM, Eric U er...@google.com wrote: I have a read running, and at some point I abort it--it could be in onprogress or elsewhere. In onabort I start another read. In onloadstart I abort again. Repeat as many times as you like, then let a read complete. I believe we've specced that the event sequence should look like this: loadstart [progress]* --[events from here to XXX happen synchronously, with no queueing] abort loadstart abort loadstart XHR handles this by not allowing a new request to be opened until the abort() method terminates. Could that be done here? It seems like an important thing to be consistent about. http://dev.w3.org/2006/webapi/XMLHttpRequest/#the-abort-method -- Glenn Maynard
Re: [FileAPI] FileReader.abort() and File[Saver|Writer].abort have different behaviors
On Tue, Sep 20, 2011 at 5:26 PM, Glenn Maynard gl...@zewt.org wrote: On Tue, Sep 20, 2011 at 8:01 PM, Eric U er...@google.com wrote: I have a read running, and at some point I abort it--it could be in onprogress or elsewhere. In onabort I start another read. In onloadstart I abort again. Repeat as many times as you like, then let a read complete. I believe we've specced that the event sequence should look like this: loadstart [progress]* --[events from here to XXX happen synchronously, with no queueing] abort loadstart abort loadstart XHR handles this by not allowing a new request to be opened until the abort() method terminates. Could that be done here? It seems like an important thing to be consistent about. http://dev.w3.org/2006/webapi/XMLHttpRequest/#the-abort-method Ooh, that's a good idea. / Jonas
Re: [FileAPI] FileReader.abort() and File[Saver|Writer].abort have different behaviors
On Tue, Sep 20, 2011 at 5:32 PM, Jonas Sicking jo...@sicking.cc wrote: On Tue, Sep 20, 2011 at 5:26 PM, Glenn Maynard gl...@zewt.org wrote: On Tue, Sep 20, 2011 at 8:01 PM, Eric U er...@google.com wrote: I have a read running, and at some point I abort it--it could be in onprogress or elsewhere. In onabort I start another read. In onloadstart I abort again. Repeat as many times as you like, then let a read complete. I believe we've specced that the event sequence should look like this: loadstart [progress]* --[events from here to XXX happen synchronously, with no queueing] abort loadstart abort loadstart XHR handles this by not allowing a new request to be opened until the abort() method terminates. Could that be done here? It seems like an important thing to be consistent about. http://dev.w3.org/2006/webapi/XMLHttpRequest/#the-abort-method Ooh, that's a good idea. / Jonas Indeed--however, from a quick skim of XHR and XHR2, that's not what they do. They let open() terminate abort(), however far along it's gotten. If we did that, then an abort killed by a read might lead to the aborted read never getting an onloadend. But you could still get the stack-busting chain of onloadstart/onabort. If we wanted to prevent read methods from being called during abort, we'd probably want to do that by setting an aborting flag or mucking around with yet another readyState of ABORTING.
Re: [FileAPI] FileReader.abort() and File[Saver|Writer].abort have different behaviors
To close the loop a bit here, Firefox 6 will make the change to FileReader.abort()'s throwing behavior agreed upon here. ( https://bugzilla.mozilla.org/show_bug.cgi?id=657964) We have not changed the timing of the events, which are still dispatched synchronously. - Kyle On Tue, May 17, 2011 at 3:01 PM, Kyle Huey m...@kylehuey.com wrote: There is actually another difference, the writing API sets the error, readystate value, and dispatches events off of a queued task, while the reading API does that synchronously. I'm inclined to think the synchronous version is the way to go here, since then the FileReader or FileWriter is totally ready for another use once the abort method returns. This is less interesting for FileSaver since that can only do one thing. - Kyle On Tue, May 17, 2011 at 2:35 PM, Kyle Huey m...@kylehuey.com wrote: The abort behaviors of FileReader and File[Saver|Writer] differ. The writing objects throw if the abort method is called when a write is not currently under way, while the reading object does not throw. The behaviors should be consistent. I don't particularly care either way, but I believe Jonas would like to change FileReader to match File[Saver|Writer]. - Kyle
Re: [FileAPI] FileReader.abort() and File[Saver|Writer].abort have different behaviors
On 5/23/11 1:20 PM, Kyle Huey wrote: To close the loop a bit here, Firefox 6 will make the change to FileReader.abort()'s throwing behavior agreed upon here. (https://bugzilla.mozilla.org/show_bug.cgi?id=657964) We have not changed the timing of the events, which are still dispatched synchronously. The editor's draft presently does nothing when readyState is EMPTY, but if readyState is DONE it is specified to set result to null and fire events (but flush any pending tasks that are queued). http://dev.w3.org/2006/webapi/FileAPI/#dfn-abort Also note that we're NOT firing *both* error and abort; we should only fire abort, and *not* error. I should change the spec. to throw. Eric, you might change the spec. (and Chrome) to NOT fire error and abort events :) -- A* - Kyle On Tue, May 17, 2011 at 3:01 PM, Kyle Huey m...@kylehuey.com mailto:m...@kylehuey.com wrote: There is actually another difference, the writing API sets the error, readystate value, and dispatches events off of a queued task, while the reading API does that synchronously. I'm inclined to think the synchronous version is the way to go here, since then the FileReader or FileWriter is totally ready for another use once the abort method returns. This is less interesting for FileSaver since that can only do one thing. - Kyle On Tue, May 17, 2011 at 2:35 PM, Kyle Huey m...@kylehuey.com mailto:m...@kylehuey.com wrote: The abort behaviors of FileReader and File[Saver|Writer] differ. The writing objects throw if the abort method is called when a write is not currently under way, while the reading object does not throw. The behaviors should be consistent. I don't particularly care either way, but I believe Jonas would like to change FileReader to match File[Saver|Writer]. - Kyle
Re: [FileAPI] FileReader.abort() and File[Saver|Writer].abort have different behaviors
On 5/23/11 6:14 PM, Arun Ranganathan wrote: On 5/23/11 1:20 PM, Kyle Huey wrote: To close the loop a bit here, Firefox 6 will make the change to FileReader.abort()'s throwing behavior agreed upon here. (https://bugzilla.mozilla.org/show_bug.cgi?id=657964) We have not changed the timing of the events, which are still dispatched synchronously. The editor's draft presently does nothing when readyState is EMPTY, but if readyState is DONE it is specified to set result to null and fire events (but flush any pending tasks that are queued). http://dev.w3.org/2006/webapi/FileAPI/#dfn-abort Also note that we're NOT firing *both* error and abort; we should only fire abort, and *not* error. I should change the spec. to throw. Eric, you might change the spec. (and Chrome) to NOT fire error and abort events :) Sorry, to be a bit clearer: I'm talking about Eric changing http://dev.w3.org/2009/dap/file-system/file-writer.html#widl-FileSaver-abort-void to match http://dev.w3.org/2006/webapi/FileAPI/#dfn-abort -- A*
Re: [FileAPI] FileReader.abort() and File[Saver|Writer].abort have different behaviors
On Tue, May 17, 2011 at 2:35 PM, Kyle Huey m...@kylehuey.com wrote: The abort behaviors of FileReader and File[Saver|Writer] differ. The writing objects throw if the abort method is called when a write is not currently under way, while the reading object does not throw. The behaviors should be consistent. I don't particularly care either way, but I believe Jonas would like to change FileReader to match File[Saver|Writer]. Yeah, since we made FileReader.readAsX throw when called in the wrong state, I believe doing the same for abort() is the better option. / Jonas
Re: [FileAPI] FileReader.abort() and File[Saver|Writer].abort have different behaviors
On Tue, May 17, 2011 at 2:41 PM, Jonas Sicking jo...@sicking.cc wrote: On Tue, May 17, 2011 at 2:35 PM, Kyle Huey m...@kylehuey.com wrote: The abort behaviors of FileReader and File[Saver|Writer] differ. The writing objects throw if the abort method is called when a write is not currently under way, while the reading object does not throw. The behaviors should be consistent. I don't particularly care either way, but I believe Jonas would like to change FileReader to match File[Saver|Writer]. Yeah, since we made FileReader.readAsX throw when called in the wrong state, I believe doing the same for abort() is the better option. / Jonas Sounds good to me.
Re: [FileAPI] FileReader.abort() and File[Saver|Writer].abort have different behaviors
On Tue, May 17, 2011 at 2:42 PM, Eric U er...@google.com wrote: It was likely just an oversight on my part that they differ. It does seem a bit odd to dispatch error/abort/loadend if aborting with no write in progress, so I favor the FileWriter/FileSaver behavior, but as long as they match, I'm not too bothered. For what it's worth, FileReader.abort() currently follows what XHR.abort() does, which is to do nothing if called in the wrong state. I.e. no events are aborted and no exceptions are thrown. / Jonas
Re: [FileAPI] FileReader.abort() and File[Saver|Writer].abort have different behaviors
It was likely just an oversight on my part that they differ. It does seem a bit odd to dispatch error/abort/loadend if aborting with no write in progress, so I favor the FileWriter/FileSaver behavior, but as long as they match, I'm not too bothered. On Tue, May 17, 2011 at 2:35 PM, Kyle Huey m...@kylehuey.com wrote: The abort behaviors of FileReader and File[Saver|Writer] differ. The writing objects throw if the abort method is called when a write is not currently under way, while the reading object does not throw. The behaviors should be consistent. I don't particularly care either way, but I believe Jonas would like to change FileReader to match File[Saver|Writer]. - Kyle
Re: [FileAPI] FileReader.abort() and File[Saver|Writer].abort have different behaviors
On Tue, May 17, 2011 at 2:48 PM, Jonas Sicking jo...@sicking.cc wrote: On Tue, May 17, 2011 at 2:42 PM, Eric U er...@google.com wrote: It was likely just an oversight on my part that they differ. It does seem a bit odd to dispatch error/abort/loadend if aborting with no write in progress, so I favor the FileWriter/FileSaver behavior, but as long as they match, I'm not too bothered. For what it's worth, FileReader.abort() currently follows what XHR.abort() does, which is to do nothing if called in the wrong state. I.e. no events are aborted and no exceptions are thrown. Ah, my mistake; I was reading http://www.w3.org/TR/FileAPI/#abort instead of http://dev.w3.org/2006/webapi/FileAPI/#abort.
Re: [FileAPI] FileReader.abort() and File[Saver|Writer].abort have different behaviors
There is actually another difference, the writing API sets the error, readystate value, and dispatches events off of a queued task, while the reading API does that synchronously. I'm inclined to think the synchronous version is the way to go here, since then the FileReader or FileWriter is totally ready for another use once the abort method returns. This is less interesting for FileSaver since that can only do one thing. - Kyle On Tue, May 17, 2011 at 2:35 PM, Kyle Huey m...@kylehuey.com wrote: The abort behaviors of FileReader and File[Saver|Writer] differ. The writing objects throw if the abort method is called when a write is not currently under way, while the reading object does not throw. The behaviors should be consistent. I don't particularly care either way, but I believe Jonas would like to change FileReader to match File[Saver|Writer]. - Kyle