Re: FileReader abort, again

2012-03-06 Thread Eric U
On Mon, Mar 5, 2012 at 2:01 PM, Eric U er...@google.com wrote:
 On Thu, Mar 1, 2012 at 11:20 AM, Arun Ranganathan
 aranganat...@mozilla.com wrote:
 Eric,

   So we could:
   1. Say not to fire a loadend if onloadend or onabort

 Do you mean if onload, onerror, or onabort...?


 No, actually.  I'm looking for the right sequence of steps that results in 
 abort's loadend not firing if terminated by another read*.  Since abort will 
 fire an abort event and a loadened event as spec'd 
 (http://dev.w3.org/2006/webapi/FileAPI/#dfn-abort), if *those* event 
 handlers initiate a readAs*, we could then suppress abort's loadend.  This 
 seems messy.

 Ah, right--so a new read initiated from onload or onerror would NOT
 suppress the loadend of the first read.  And I believe that this
 matches XHR2, so we're good.  Nevermind.

No, I retract that.  In
http://lists.w3.org/Archives/Public/public-webapps/2011OctDec/1627.html
Anne confirmed that a new open in onerror or onload /would/ suppress
the loadend of the first send.  So we would want a new read/write in
onload or onerror to do the same, not just those in onabort.

 Actually, if we really want to match XHR2, we should qualify all the
 places that we fire loadend.  If the user calls XHR2's open in
 onerror
 or onload, that cancels its loadend.  However, a simple check on
 readyState at step 6 won't do it.  Because the user could call
 readAsText in onerror, then call abort in the second read's
 onloadstart, and we'd see readyState as DONE and fire loadend twice.

 To emulate XHR2 entirely, we'd need to have read methods dequeue any
 leftover tasks for previous read methods AND terminate the abort
 algorithm AND terminate the error algorithm of any previous read
 method.  What a mess.


 This may be the way to do it.

 The problem with emulating XHR2 is that open() and send() are distinct 
 concepts in XHR2, but in FileAPI, they are the same.  So in XHR2 an open() 
 canceling abort does make sense; abort() cancels a send(), and thus an 
 open() should cancel an abort().  But in FileAPI, our readAs* methods are 
 equivalent to *both* open() and send().  In FileAPI, an abort() cancels a 
 readAs*; we now have a scenario where a readAs* may cancel an abort().  How 
 to make that clear?

 I'm not sure why it's any more confusing that read* is open+send.
 read* can cancel abort, and abort can cancel read*.  OK.


 Perhaps there's a simpler way to say successfully calling a read
 method inhibits any previous read's loadend?

 I'm in favor of any shorthand :)  But this may not do justice to each 
 readAs* algorithm being better defined.

 Hack 1: Don't call loadend synchronously.  Enqueue it, and let read*
 methods clear the queues when they start up.  This differs from XHR,
 though, and is a little odd.

Still works, but needs to be applied in multiple places.

 Hack 2: Add a virtual generation counter/timestamp, not exposed to
 script.  Increment it in read*, check it in abort before sending
 loadend.  This is kind of complex, but works [and might be how I end
 up implementing this in Chrome].


Still works, but needs to be applied in multiple places.

 But really, I don't think either of those is better than just saying,
 in read*, something like terminate the algorithm for any abort
 sequence being processed.

...or any previously-initiated read being processed.



RE: FileReader abort, again

2012-03-06 Thread Feras Moussa
 Anne confirmed that a new open in onerror or onload /would/ suppress the 
 loadend of the first send.  
So we would want a new read/write in onload or onerror to do the same, not 
just those in onabort.
We encountered this same ambiguity in the spec, and we agree with the above. 
This is also what we 
have implemented and shipped in the consumer preview.

 Hack 2: Add a virtual generation counter/timestamp, not exposed to 
 script.  Increment it in read*, check it in abort before sending 
 loadend.  This is kind of complex, but works [and might be how I end 
 up implementing this in Chrome].
Of the list of 'hacks', we also implemented hack #2 to get the correct behavior.



 -Original Message-
 From: Eric U [mailto:er...@google.com]
 Sent: Tuesday, March 06, 2012 12:16 PM
 To: Arun Ranganathan
 Cc: Web Applications Working Group WG
 Subject: Re: FileReader abort, again
 
 On Mon, Mar 5, 2012 at 2:01 PM, Eric U er...@google.com wrote:
  On Thu, Mar 1, 2012 at 11:20 AM, Arun Ranganathan
  aranganat...@mozilla.com wrote:
  Eric,
 
So we could:
1. Say not to fire a loadend if onloadend or onabort
 
  Do you mean if onload, onerror, or onabort...?
 
 
  No, actually.  I'm looking for the right sequence of steps that results in
 abort's loadend not firing if terminated by another read*.  Since abort will 
 fire
 an abort event and a loadened event as spec'd
 (http://dev.w3.org/2006/webapi/FileAPI/#dfn-abort), if *those* event
 handlers initiate a readAs*, we could then suppress abort's loadend.  This
 seems messy.
 
  Ah, right--so a new read initiated from onload or onerror would NOT
  suppress the loadend of the first read.  And I believe that this
  matches XHR2, so we're good.  Nevermind.
 
 No, I retract that.  In
 http://lists.w3.org/Archives/Public/public-webapps/2011OctDec/1627.html
 Anne confirmed that a new open in onerror or onload /would/ suppress the
 loadend of the first send.  So we would want a new read/write in onload or
 onerror to do the same, not just those in onabort.
 
  Actually, if we really want to match XHR2, we should qualify all the
  places that we fire loadend.  If the user calls XHR2's open in
  onerror or onload, that cancels its loadend.  However, a simple
  check on readyState at step 6 won't do it.  Because the user could
  call readAsText in onerror, then call abort in the second read's
  onloadstart, and we'd see readyState as DONE and fire loadend twice.
 
  To emulate XHR2 entirely, we'd need to have read methods dequeue
 any
  leftover tasks for previous read methods AND terminate the abort
  algorithm AND terminate the error algorithm of any previous read
  method.  What a mess.
 
 
  This may be the way to do it.
 
  The problem with emulating XHR2 is that open() and send() are distinct
 concepts in XHR2, but in FileAPI, they are the same.  So in XHR2 an open()
 canceling abort does make sense; abort() cancels a send(), and thus an
 open() should cancel an abort().  But in FileAPI, our readAs* methods are
 equivalent to *both* open() and send().  In FileAPI, an abort() cancels a
 readAs*; we now have a scenario where a readAs* may cancel an
 abort().  How to make that clear?
 
  I'm not sure why it's any more confusing that read* is open+send.
  read* can cancel abort, and abort can cancel read*.  OK.
 
 
  Perhaps there's a simpler way to say successfully calling a read
  method inhibits any previous read's loadend?
 
  I'm in favor of any shorthand :)  But this may not do justice to each
 readAs* algorithm being better defined.
 
  Hack 1: Don't call loadend synchronously.  Enqueue it, and let read*
  methods clear the queues when they start up.  This differs from XHR,
  though, and is a little odd.
 
 Still works, but needs to be applied in multiple places.
 
  Hack 2: Add a virtual generation counter/timestamp, not exposed to
  script.  Increment it in read*, check it in abort before sending
  loadend.  This is kind of complex, but works [and might be how I end
  up implementing this in Chrome].
 
 
 Still works, but needs to be applied in multiple places.
 
  But really, I don't think either of those is better than just saying,
  in read*, something like terminate the algorithm for any abort
  sequence being processed.
 
 ...or any previously-initiated read being processed.
 





Re: FileReader abort, again

2012-03-05 Thread Eric U
On Thu, Mar 1, 2012 at 11:20 AM, Arun Ranganathan
aranganat...@mozilla.com wrote:
 Eric,

   So we could:
   1. Say not to fire a loadend if onloadend or onabort

 Do you mean if onload, onerror, or onabort...?


 No, actually.  I'm looking for the right sequence of steps that results in 
 abort's loadend not firing if terminated by another read*.  Since abort will 
 fire an abort event and a loadened event as spec'd 
 (http://dev.w3.org/2006/webapi/FileAPI/#dfn-abort), if *those* event handlers 
 initiate a readAs*, we could then suppress abort's loadend.  This seems messy.

Ah, right--so a new read initiated from onload or onerror would NOT
suppress the loadend of the first read.  And I believe that this
matches XHR2, so we're good.  Nevermind.



 Actually, if we really want to match XHR2, we should qualify all the
 places that we fire loadend.  If the user calls XHR2's open in
 onerror
 or onload, that cancels its loadend.  However, a simple check on
 readyState at step 6 won't do it.  Because the user could call
 readAsText in onerror, then call abort in the second read's
 onloadstart, and we'd see readyState as DONE and fire loadend twice.

 To emulate XHR2 entirely, we'd need to have read methods dequeue any
 leftover tasks for previous read methods AND terminate the abort
 algorithm AND terminate the error algorithm of any previous read
 method.  What a mess.


 This may be the way to do it.

 The problem with emulating XHR2 is that open() and send() are distinct 
 concepts in XHR2, but in FileAPI, they are the same.  So in XHR2 an open() 
 canceling abort does make sense; abort() cancels a send(), and thus an open() 
 should cancel an abort().  But in FileAPI, our readAs* methods are equivalent 
 to *both* open() and send().  In FileAPI, an abort() cancels a readAs*; we 
 now have a scenario where a readAs* may cancel an abort().  How to make that 
 clear?

I'm not sure why it's any more confusing that read* is open+send.
read* can cancel abort, and abort can cancel read*.  OK.


 Perhaps there's a simpler way to say successfully calling a read
 method inhibits any previous read's loadend?

 I'm in favor of any shorthand :)  But this may not do justice to each readAs* 
 algorithm being better defined.

Hack 1: Don't call loadend synchronously.  Enqueue it, and let read*
methods clear the queues when they start up.  This differs from XHR,
though, and is a little odd.
Hack 2: Add a virtual generation counter/timestamp, not exposed to
script.  Increment it in read*, check it in abort before sending
loadend.  This is kind of complex, but works [and might be how I end
up implementing this in Chrome].

But really, I don't think either of those is better than just saying,
in read*, something like terminate the algorithm for any abort
sequence being processed.

Eric



Re: FileReader abort, again

2012-03-01 Thread Arun Ranganathan
Eric,

   So we could:
   1. Say not to fire a loadend if onloadend or onabort 
 
 Do you mean if onload, onerror, or onabort...?


No, actually.  I'm looking for the right sequence of steps that results in 
abort's loadend not firing if terminated by another read*.  Since abort will 
fire an abort event and a loadened event as spec'd 
(http://dev.w3.org/2006/webapi/FileAPI/#dfn-abort), if *those* event handlers 
initiate a readAs*, we could then suppress abort's loadend.  This seems messy.


 
 Actually, if we really want to match XHR2, we should qualify all the
 places that we fire loadend.  If the user calls XHR2's open in
 onerror
 or onload, that cancels its loadend.  However, a simple check on
 readyState at step 6 won't do it.  Because the user could call
 readAsText in onerror, then call abort in the second read's
 onloadstart, and we'd see readyState as DONE and fire loadend twice.
 
 To emulate XHR2 entirely, we'd need to have read methods dequeue any
 leftover tasks for previous read methods AND terminate the abort
 algorithm AND terminate the error algorithm of any previous read
 method.  What a mess.


This may be the way to do it.

The problem with emulating XHR2 is that open() and send() are distinct concepts 
in XHR2, but in FileAPI, they are the same.  So in XHR2 an open() canceling 
abort does make sense; abort() cancels a send(), and thus an open() should 
cancel an abort().  But in FileAPI, our readAs* methods are equivalent to 
*both* open() and send().  In FileAPI, an abort() cancels a readAs*; we now 
have a scenario where a readAs* may cancel an abort().  How to make that clear?

 
 Perhaps there's a simpler way to say successfully calling a read
 method inhibits any previous read's loadend?

I'm in favor of any shorthand :)  But this may not do justice to each readAs* 
algorithm being better defined. 

-- A*



Re: FileReader abort, again

2012-02-29 Thread Eric U
Incidentally, the way XHR gets around this is to have open cancel any
in-progress abort.  We could certainly do the same thing, having any
readAs* cancel abort().

On Tue, Feb 28, 2012 at 4:15 PM, Eric U er...@google.com wrote:
 I like the Event Invariants writeup at the end.  It's only
 informative, but it is, indeed, informative.

 However, I'm not sure it quite matches the normative text in one
 respect.  Where you say [8.5.6 step 4]: Terminate any steps while
 processing a read method.  Does that also terminate the steps
 associated with an abort that terminated the read method?  Basically
 I'm not sure what steps while processing a read method means.

 Otherwise, if you start a new read in onabort [8.5.6 step 5], you'll
 still deliver the loadend [8.5.6 step 6].
 This contradicts 8.5.9.2.1 Once a loadstart has been fired, a
 corresponding loadend fires at completion of the read, EXCEPT if the
 read method has been cancelled using abort() and a new read method has
 been invoked.

        Eric [copying this into FileWriter]



Re: FileReader abort, again

2012-02-29 Thread Arun Ranganathan
FileReader.abort is like a bad penny :)


 
 However, I'm not sure it quite matches the normative text in one
 respect.  Where you say [8.5.6 step 4]: Terminate any steps while
 processing a read method.  Does that also terminate the steps
 associated with an abort that terminated the read method?  Basically
 I'm not sure what steps while processing a read method means.

I've changed this to terminate only the read algorithm (and hopefully it is 
clear this isn't the same as the abort steps): 

http://dev.w3.org/2006/webapi/FileAPI/#terminate-an-algorithm and



 
 Otherwise, if you start a new read in onabort [8.5.6 step 5], you'll
 still deliver the loadend [8.5.6 step 6].
 This contradicts 8.5.9.2.1 Once a loadstart has been fired, a
 corresponding loadend fires at completion of the read, EXCEPT if the
 read method has been cancelled using abort() and a new read method
 has
 been invoked.

This seems like familiar ground, and I'm sorry this contradiction still exists.

So we could:

1. Say not to fire a loadend if onloadend or onabort re-initiate a read.  But 
this may be odd in terms of analyzing a program before.

2. Simply not fire loadend on abort.  I'm not sure this is a good idea.

What's your counsel?  Have I missed something easier?

-- A*



Re: FileReader abort, again

2012-02-29 Thread Eric U
On Wed, Feb 29, 2012 at 1:43 PM, Arun Ranganathan
aranganat...@mozilla.com wrote:
 FileReader.abort is like a bad penny :)



 However, I'm not sure it quite matches the normative text in one
 respect.  Where you say [8.5.6 step 4]: Terminate any steps while
 processing a read method.  Does that also terminate the steps
 associated with an abort that terminated the read method?  Basically
 I'm not sure what steps while processing a read method means.

 I've changed this to terminate only the read algorithm (and hopefully it is 
 clear this isn't the same as the abort steps):

 http://dev.w3.org/2006/webapi/FileAPI/#terminate-an-algorithm and




 Otherwise, if you start a new read in onabort [8.5.6 step 5], you'll
 still deliver the loadend [8.5.6 step 6].
 This contradicts 8.5.9.2.1 Once a loadstart has been fired, a
 corresponding loadend fires at completion of the read, EXCEPT if the
 read method has been cancelled using abort() and a new read method
 has
 been invoked.

 This seems like familiar ground, and I'm sorry this contradiction still 
 exists.

 So we could:

 1. Say not to fire a loadend if onloadend or onabort re-initiate a read.  But 
 this may be odd in terms of analyzing a program before.

 2. Simply not fire loadend on abort.  I'm not sure this is a good idea.

 What's your counsel?  Have I missed something easier?

 -- A*

My email must have crossed yours mid-flight, but just in case, how
about speccing that read* methods terminate the abort algorithm?
That's what XHR2 does, and it looks like it works.  It's not the
easiest thing to figure out when reading the spec.  It took me a while
to get my mind around it in XHR2, but then that's a much more
complicated spec.  FileReader's small enough that I think it's not
unreasonable, and of course matching XHR2 means fewer surprises all
around.

Eric



Re: FileReader abort, again

2012-02-29 Thread Arun Ranganathan
 On Wed, Feb 29, 2012 at 1:43 PM, Arun Ranganathan
  Otherwise, if you start a new read in onabort [8.5.6 step 5],
  you'll
  still deliver the loadend [8.5.6 step 6].
  This contradicts 8.5.9.2.1 Once a loadstart has been fired, a
  corresponding loadend fires at completion of the read, EXCEPT if
  the
  read method has been cancelled using abort() and a new read method
  has
  been invoked.
 
  This seems like familiar ground, and I'm sorry this contradiction
  still exists.
 
  So we could:
 
  1. Say not to fire a loadend if onloadend or onabort re-initiate a
  read.  But this may be odd in terms of analyzing a program before.
 
  2. Simply not fire loadend on abort.  I'm not sure this is a good
  idea.
 
  What's your counsel?  Have I missed something easier?
 
  -- A*
 
 My email must have crossed yours mid-flight, but just in case, how
 about speccing that read* methods terminate the abort algorithm?
 That's what XHR2 does, and it looks like it works.  It's not the
 easiest thing to figure out when reading the spec.  It took me a
 while
 to get my mind around it in XHR2, but then that's a much more
 complicated spec.  FileReader's small enough that I think it's not
 unreasonable, and of course matching XHR2 means fewer surprises all
 around.


OK, I'll study XHR2 and figure this out.  Spec'ing this isn't a quick win, 
though, since abort's role is to terminate a read*!  So to have a re-initiated 
read* terminate an abort will require some thought on invocation order.

-- A*



Re: FileReader abort, again

2012-02-29 Thread Eric U
On Wed, Feb 29, 2012 at 2:57 PM, Arun Ranganathan
aranganat...@mozilla.com wrote:
 On Wed, Feb 29, 2012 at 1:43 PM, Arun Ranganathan
  Otherwise, if you start a new read in onabort [8.5.6 step 5],
  you'll
  still deliver the loadend [8.5.6 step 6].
  This contradicts 8.5.9.2.1 Once a loadstart has been fired, a
  corresponding loadend fires at completion of the read, EXCEPT if
  the
  read method has been cancelled using abort() and a new read method
  has
  been invoked.
 
  This seems like familiar ground, and I'm sorry this contradiction
  still exists.
 
  So we could:
 
  1. Say not to fire a loadend if onloadend or onabort re-initiate a
  read.  But this may be odd in terms of analyzing a program before.

Do you mean if onload, onerror, or onabort...?

  2. Simply not fire loadend on abort.  I'm not sure this is a good
  idea.

Agreed.  It should be there unless another read starts.

  What's your counsel?  Have I missed something easier?
 
  -- A*

 My email must have crossed yours mid-flight, but just in case, how
 about speccing that read* methods terminate the abort algorithm?
 That's what XHR2 does, and it looks like it works.  It's not the
 easiest thing to figure out when reading the spec.  It took me a
 while
 to get my mind around it in XHR2, but then that's a much more
 complicated spec.  FileReader's small enough that I think it's not
 unreasonable, and of course matching XHR2 means fewer surprises all
 around.


 OK, I'll study XHR2 and figure this out.  Spec'ing this isn't a quick win, 
 though, since abort's role is to terminate a read*!  So to have a 
 re-initiated read* terminate an abort will require some thought on invocation 
 order.

I don't see a conflict--abort terminates read, and read terminates abort.

Actually, if we really want to match XHR2, we should qualify all the
places that we fire loadend.  If the user calls XHR2's open in onerror
or onload, that cancels its loadend.  However, a simple check on
readyState at step 6 won't do it.  Because the user could call
readAsText in onerror, then call abort in the second read's
onloadstart, and we'd see readyState as DONE and fire loadend twice.

To emulate XHR2 entirely, we'd need to have read methods dequeue any
leftover tasks for previous read methods AND terminate the abort
algorithm AND terminate the error algorithm of any previous read
method.  What a mess.

Perhaps there's a simpler way to say successfully calling a read
method inhibits any previous read's loadend?

[steps 5 and 6 there are missing trailing periods, BTW]