Re: Promises: unhandled rejections and finally()

2020-03-28 Thread Jordan Harband
It does pass through the fulfillment status - but it does that by adding
both an onFulfilled and an onRejected handler, so it does affect the
"unhandled rejection" hook.

On Sat, Mar 28, 2020 at 7:23 PM Felipe Gasper 
wrote:

> Hi Logan,
>
> Thank you .. that makes sense. I’m not sure why now but I had in mind that
> finally() creates a “passthrough” promise that doesn’t affect its parent
> promise’s resolved/rejected status.
>
> Cheers,
> -Felipe
>
> On Mar 28, 2020, at 21:40, Logan Smyth  wrote:
>
> 
> > Could someone point me to something that would help me to understand the
> logic here? It looks like the first finally() is getting a “free pass”
> while only the 2nd and subsequent ones trigger their own
> unhandled-rejection warnings.
>
> I think the best place to start in understanding this would be to step
> back and make sure you understand what it is that triggers these errors.
> Node triggers these errors when a promise object has been rejected but has
> no handlers to do respond to the rejection. I forget exactly what point
> Node checks for handlers these days, if that point is at the end of the job
> execution or on GC of promises now or what but that's not important for
> this case.
>
> Let's look at your example. I'm also simplifying it to
> ```
> var p = Promise.reject(789);
> var one = p.finally(() => {});
> var two = p.finally(() => {});
> var three = p.finally(() => {});
> ```
>
> 1)
> ```
> var p = Promise.reject(789);
> ```
> There is only one promise here, `p`, and it has no handlers ever attached
> to it so there is nothing to handle the rejection error, hence the single
> uncaught rejection error.
>
> 2)
> ```
> var p = Promise.reject(789);
> var one = p.finally(() => {});
> ```
> There are 2 promises here, `p`, which has one handler (the `finally` that
> will take the rejection of `p` and in turn reject `one`) and `one`, which
> has no handlers attached, so you again get a single uncaught rejection. It
> as not that the first "finally" gets a "free pass", it is that rejections
> from `p` are no longer uncaught, but you have added a new promise that is
> uncaught, so the overall number of uncaught rejections does not change.
>
> 3)
> ```
> var p = Promise.reject(789);
> var one = p.finally(() => {});
> var two = p.finally(() => {});
> ```
> Hopefully you can see where this is going. `p` now has 2 handlers attached
> so its rejection isn't uncaught, but now both `one` and `two` have no
> handlers, so _both_ will trigger an uncaught rejection error.
>
> 4)
> ```
> var p = Promise.reject(789);
> var one = p.finally(() => {});
> var two = p.finally(() => {});
> var three = p.finally(() => {});
> ```
> And finally now we have `one`, `two` and `three` all with no handlers
> attached, so you will get three uncaught rejection errors.
>
> Hope that helps!
>
>
> On Sun, Mar 29, 2020 at 9:03 AM Felipe Gasper 
> wrote:
>
>> Hello,
>>
>> In node 12 as well as the latest Chrome and FF (all on macOS) I see the
>> following:
>>
>> -
>> var y,n; var p = new Promise( (yy,nn) => { y=yy; n=nn } ); n(789);
>> ==> produces 1 unhandled-rejection warning
>>
>> var y,n; var p = new Promise( (yy,nn) => { y=yy; n=nn } ); p.finally( ()
>> => {} ); n(789);
>> ==> produces 1 unhandled-rejection warning
>>
>> var y,n; var p = new Promise( (yy,nn) => { y=yy; n=nn } ); p.finally( ()
>> => {} ); p.finally( () => {} ); n(789);
>> ==> produces 2 unhandled-rejection warnings
>>
>> var y,n; var p = new Promise( (yy,nn) => { y=yy; n=nn } ); p.finally( ()
>> => {} ); p.finally( () => {} ); p.finally( () => {} ); n(789);
>> ==> produces 3 unhandled-rejection warnings
>>
>> -
>>
>> Could someone point me to something that would help me to understand the
>> logic here? It looks like the first finally() is getting a “free pass”
>> while only the 2nd and subsequent ones trigger their own
>> unhandled-rejection warnings.
>>
>> Thank you!
>>
>> cheers,
>> -Felipe Gasper
>> ___
>> es-discuss mailing list
>> es-discuss@mozilla.org
>> https://mail.mozilla.org/listinfo/es-discuss
>>
> ___
> es-discuss mailing list
> es-discuss@mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Promises: unhandled rejections and finally()

2020-03-28 Thread Felipe Gasper
Hi Logan,

Thank you .. that makes sense. I’m not sure why now but I had in mind that 
finally() creates a “passthrough” promise that doesn’t affect its parent 
promise’s resolved/rejected status.

Cheers,
-Felipe

> On Mar 28, 2020, at 21:40, Logan Smyth  wrote:
> 
> 
> > Could someone point me to something that would help me to understand the 
> > logic here? It looks like the first finally() is getting a “free pass” 
> > while only the 2nd and subsequent ones trigger their own 
> > unhandled-rejection warnings.
> 
> I think the best place to start in understanding this would be to step back 
> and make sure you understand what it is that triggers these errors. Node 
> triggers these errors when a promise object has been rejected but has no 
> handlers to do respond to the rejection. I forget exactly what point Node 
> checks for handlers these days, if that point is at the end of the job 
> execution or on GC of promises now or what but that's not important for this 
> case. 
> 
> Let's look at your example. I'm also simplifying it to
> ```
> var p = Promise.reject(789); 
> var one = p.finally(() => {}); 
> var two = p.finally(() => {}); 
> var three = p.finally(() => {});
> ```
> 
> 1)
> ```
> var p = Promise.reject(789);
> ```
> There is only one promise here, `p`, and it has no handlers ever attached to 
> it so there is nothing to handle the rejection error, hence the single 
> uncaught rejection error.
> 
> 2) 
> ```
> var p = Promise.reject(789); 
> var one = p.finally(() => {});
> ```
> There are 2 promises here, `p`, which has one handler (the `finally` that 
> will take the rejection of `p` and in turn reject `one`) and `one`, which has 
> no handlers attached, so you again get a single uncaught rejection. It as not 
> that the first "finally" gets a "free pass", it is that rejections from `p` 
> are no longer uncaught, but you have added a new promise that is uncaught, so 
> the overall number of uncaught rejections does not change.
> 
> 3)
> ```
> var p = Promise.reject(789); 
> var one = p.finally(() => {}); 
> var two = p.finally(() => {});
> ```
> Hopefully you can see where this is going. `p` now has 2 handlers attached so 
> its rejection isn't uncaught, but now both `one` and `two` have no handlers, 
> so _both_ will trigger an uncaught rejection error.
> 
> 4)
> ```
> var p = Promise.reject(789); 
> var one = p.finally(() => {}); 
> var two = p.finally(() => {});
> var three = p.finally(() => {});
> ```
> And finally now we have `one`, `two` and `three` all with no handlers 
> attached, so you will get three uncaught rejection errors.
> 
> Hope that helps!
> 
> 
>> On Sun, Mar 29, 2020 at 9:03 AM Felipe Gasper  
>> wrote:
>> Hello,
>> 
>> In node 12 as well as the latest Chrome and FF (all on macOS) I see the 
>> following:
>> 
>> -
>> var y,n; var p = new Promise( (yy,nn) => { y=yy; n=nn } ); n(789);
>> ==> produces 1 unhandled-rejection warning
>> 
>> var y,n; var p = new Promise( (yy,nn) => { y=yy; n=nn } ); p.finally( () => 
>> {} ); n(789);
>> ==> produces 1 unhandled-rejection warning
>> 
>> var y,n; var p = new Promise( (yy,nn) => { y=yy; n=nn } ); p.finally( () => 
>> {} ); p.finally( () => {} ); n(789);
>> ==> produces 2 unhandled-rejection warnings
>> 
>> var y,n; var p = new Promise( (yy,nn) => { y=yy; n=nn } ); p.finally( () => 
>> {} ); p.finally( () => {} ); p.finally( () => {} ); n(789);
>> ==> produces 3 unhandled-rejection warnings
>> 
>> -
>> 
>> Could someone point me to something that would help me to understand the 
>> logic here? It looks like the first finally() is getting a “free pass” while 
>> only the 2nd and subsequent ones trigger their own unhandled-rejection 
>> warnings.
>> 
>> Thank you!
>> 
>> cheers,
>> -Felipe Gasper
>> ___
>> es-discuss mailing list
>> es-discuss@mozilla.org
>> https://mail.mozilla.org/listinfo/es-discuss
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Promises: unhandled rejections and finally()

2020-03-28 Thread Logan Smyth
> Could someone point me to something that would help me to understand the
logic here? It looks like the first finally() is getting a “free pass”
while only the 2nd and subsequent ones trigger their own
unhandled-rejection warnings.

I think the best place to start in understanding this would be to step back
and make sure you understand what it is that triggers these errors. Node
triggers these errors when a promise object has been rejected but has no
handlers to do respond to the rejection. I forget exactly what point Node
checks for handlers these days, if that point is at the end of the job
execution or on GC of promises now or what but that's not important for
this case.

Let's look at your example. I'm also simplifying it to
```
var p = Promise.reject(789);
var one = p.finally(() => {});
var two = p.finally(() => {});
var three = p.finally(() => {});
```

1)
```
var p = Promise.reject(789);
```
There is only one promise here, `p`, and it has no handlers ever attached
to it so there is nothing to handle the rejection error, hence the single
uncaught rejection error.

2)
```
var p = Promise.reject(789);
var one = p.finally(() => {});
```
There are 2 promises here, `p`, which has one handler (the `finally` that
will take the rejection of `p` and in turn reject `one`) and `one`, which
has no handlers attached, so you again get a single uncaught rejection. It
as not that the first "finally" gets a "free pass", it is that rejections
from `p` are no longer uncaught, but you have added a new promise that is
uncaught, so the overall number of uncaught rejections does not change.

3)
```
var p = Promise.reject(789);
var one = p.finally(() => {});
var two = p.finally(() => {});
```
Hopefully you can see where this is going. `p` now has 2 handlers attached
so its rejection isn't uncaught, but now both `one` and `two` have no
handlers, so _both_ will trigger an uncaught rejection error.

4)
```
var p = Promise.reject(789);
var one = p.finally(() => {});
var two = p.finally(() => {});
var three = p.finally(() => {});
```
And finally now we have `one`, `two` and `three` all with no handlers
attached, so you will get three uncaught rejection errors.

Hope that helps!


On Sun, Mar 29, 2020 at 9:03 AM Felipe Gasper 
wrote:

> Hello,
>
> In node 12 as well as the latest Chrome and FF (all on macOS) I see the
> following:
>
> -
> var y,n; var p = new Promise( (yy,nn) => { y=yy; n=nn } ); n(789);
> ==> produces 1 unhandled-rejection warning
>
> var y,n; var p = new Promise( (yy,nn) => { y=yy; n=nn } ); p.finally( ()
> => {} ); n(789);
> ==> produces 1 unhandled-rejection warning
>
> var y,n; var p = new Promise( (yy,nn) => { y=yy; n=nn } ); p.finally( ()
> => {} ); p.finally( () => {} ); n(789);
> ==> produces 2 unhandled-rejection warnings
>
> var y,n; var p = new Promise( (yy,nn) => { y=yy; n=nn } ); p.finally( ()
> => {} ); p.finally( () => {} ); p.finally( () => {} ); n(789);
> ==> produces 3 unhandled-rejection warnings
>
> -
>
> Could someone point me to something that would help me to understand the
> logic here? It looks like the first finally() is getting a “free pass”
> while only the 2nd and subsequent ones trigger their own
> unhandled-rejection warnings.
>
> Thank you!
>
> cheers,
> -Felipe Gasper
> ___
> es-discuss mailing list
> es-discuss@mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Promises, async functions, and requestAnimationFrame, together.

2017-03-18 Thread /#!/JoePea
Ah, I think the reason that this animation loop using promises works is
because promise handlers resolve in the next microtask after the current
macrotask. I believe that the animation frame fires in what is essentially
a macrotask, then immediately after this macrotask the resolution of the
`animationFrame()` promise happens in the following microtask. At some
point later, the browser renders stuff, which I think might the next
macrotask after the animation frame macrotask.

*/#!/*JoePea
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Promises, async functions, and requestAnimationFrame, together.

2016-04-26 Thread Matthew Robb
This is definitely interesting stuff. Have you considered rewriting this so
that it only uses generators? If you did then you could test natively in
Chrome and see if you get the same results.


- Matthew Robb

On Sat, Apr 23, 2016 at 7:01 PM, /#!/JoePea  wrote:

> Just to show a little more detail, here's a screenshot that shows that
> the logic of the while-loop version of my animation loop fires inside
> each animation frame. I've zoomed out and we can see there's nothing
> fired between the frames:
>
>
> https://cloud.githubusercontent.com/assets/297678/14764323/c28e83cc-0968-11e6-8771-8e726158aa52.png
>
> On Sat, Apr 23, 2016 at 3:18 PM, /#!/JoePea  wrote:
> > Alright, I did an experiment, and I'm really surprised at the results!
> > Apparently, the logic (what would be drawSomething() in my previous
> > example) is fired within the frame!!
> >
> > So, let me show you my original method for starting an animation loop.
> > I'm working on a 3D project at http://infamous.io. The Scene class
> > (https://github.com/infamous/infamous/blob/master/src/motor/Scene.js)
> > has a method for starting an animation loop the standard way:
> >
> > ```js
> > async _startAnimationLoopWhenMounted() {
> > this._animationLoopStarted = true
> >
> > if (!this._mounted) await this.mountPromise
> >
> > // So now we can render after the scene is mounted.
> > const loop = timestamp => {
> > this._inFrame = true
> >
> > this._runRenderTasks(timestamp)
> > this._renderNodes(timestamp)
> >
> > // If any tasks are left to run, continue the animation loop.
> > if (this._allRenderTasks.length)
> > this._rAF = requestAnimationFrame(loop)
> > else {
> > this._rAF = null
> > this._animationLoopStarted = false
> > }
> >
> > this._inFrame = false
> > }
> >
> > this._rAF = requestAnimationFrame(loop)
> > }
> > ```
> >
> > Here's what the Chrome timeline shows for the logic that is fired
> > inside the loop:
> >
> https://cloud.githubusercontent.com/assets/297678/14764236/8eb72d4a-0965-11e6-9bb9-5db02cc23520.png
> >
> > Now, I went ahead and modified my Scene class so the method now looks
> like this:
> >
> > ```js
> > function animationFrame() {
> > let resolve = null
> > const promise = new Promise(r => resolve = r)
> > window.requestAnimationFrame(resolve)
> > return promise
> > }
> >
> > // ...
> >
> > async _startAnimationLoopWhenMounted() {
> > this._animationLoopStarted = true
> >
> > if (!this._mounted) await this.mountPromise
> >
> > this._rAF = true
> > let timestamp = null
> > while (this._rAF) {
> > timestamp = await animationFrame()
> > this._inFrame = true
> >
> > this._runRenderTasks(timestamp)
> > this._renderNodes(timestamp)
> >
> > // If any tasks are left to run, continue the animation loop.
> > if (!this._allRenderTasks.length) {
> > this._rAF = null
> > this._animationLoopStarted = false
> > }
> >
> > this._inFrame = false
> > }
> > }
> > ```
> >
> > And the timeline results are surprising! As you can see in the
> > following screenshot, all of the logic happens within the frame
> > (though you can see there's extra overhead from what I assume are the
> > extra function calls due to the fact that I'm using Facebook
> > Regenerator for the async functions):
> >
> https://cloud.githubusercontent.com/assets/297678/14764237/8eb71ce2-0965-11e6-942a-3c556c48b9a0.png
> >
> > Near the bottom right of the screen shot, you can see the tooltip as
> > I'm hovering on the call to `animationFrame` which returns the promise
> > that I am awaiting in the loop.
> >
> > Although this behavior seems to be exactly what I was hoping for, it
> > seems like there is something wrong. Could there be a bug in
> > regenerator that is failing to defer my loop code to a following tick?
> > Or is my code deferred to a following tick that somehow the animation
> > frame knows to execute within the same tick? Maybe there's something
> > I'm missing about the Promise API that allows for .then() of a promise
> > (which I assume is what Regenerator is using) to be executed in the
> > same tick? What's going on here?
> >
> > I was expecting to see the code of my loop execute outside of the
> > "Animation Frame Fired" section.
> >
> > On Sat, Apr 23, 2016 at 6:28 AM, Boris Zbarsky  wrote:
> >> On 4/23/16 4:09 AM, Salvador de la Puente González wrote:
> >>>
> >>> AFAIK, that should execute `drawSomething()` once per frame. Given a
> >>> frame is each time the animatinFrame() promise resolves.
> >>
> >>
> >> What's not obvious to me is whether it will execute it before the actual
> >> paint for the frame (i.e. 

Re: Promises, async functions, and requestAnimationFrame

2016-04-24 Thread Benjamin Gruenbaum
Note that there is no guarantee that the `then` handlers (after the await)
will fire in the same loop since they defer execution on their own and
might defer it further.

In practice I assume they'll probe to see if they need to actually schedule
asynchronously or the constructed promise is already handling that (like
libraries do) and won't defer it any further but that's just a guess.

The only spec I'm aware of that does not defer in this case is the
es-observable spec.

There has also been talk about being able to set the scheduler for promises
which is something I wanted to bring up in ESDiscuss but haven't been able
to yet.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Promises, async functions, and requestAnimationFrame, together.

2016-04-23 Thread /#!/JoePea
Just to show a little more detail, here's a screenshot that shows that
the logic of the while-loop version of my animation loop fires inside
each animation frame. I've zoomed out and we can see there's nothing
fired between the frames:

https://cloud.githubusercontent.com/assets/297678/14764323/c28e83cc-0968-11e6-8771-8e726158aa52.png

On Sat, Apr 23, 2016 at 3:18 PM, /#!/JoePea  wrote:
> Alright, I did an experiment, and I'm really surprised at the results!
> Apparently, the logic (what would be drawSomething() in my previous
> example) is fired within the frame!!
>
> So, let me show you my original method for starting an animation loop.
> I'm working on a 3D project at http://infamous.io. The Scene class
> (https://github.com/infamous/infamous/blob/master/src/motor/Scene.js)
> has a method for starting an animation loop the standard way:
>
> ```js
> async _startAnimationLoopWhenMounted() {
> this._animationLoopStarted = true
>
> if (!this._mounted) await this.mountPromise
>
> // So now we can render after the scene is mounted.
> const loop = timestamp => {
> this._inFrame = true
>
> this._runRenderTasks(timestamp)
> this._renderNodes(timestamp)
>
> // If any tasks are left to run, continue the animation loop.
> if (this._allRenderTasks.length)
> this._rAF = requestAnimationFrame(loop)
> else {
> this._rAF = null
> this._animationLoopStarted = false
> }
>
> this._inFrame = false
> }
>
> this._rAF = requestAnimationFrame(loop)
> }
> ```
>
> Here's what the Chrome timeline shows for the logic that is fired
> inside the loop:
> https://cloud.githubusercontent.com/assets/297678/14764236/8eb72d4a-0965-11e6-9bb9-5db02cc23520.png
>
> Now, I went ahead and modified my Scene class so the method now looks like 
> this:
>
> ```js
> function animationFrame() {
> let resolve = null
> const promise = new Promise(r => resolve = r)
> window.requestAnimationFrame(resolve)
> return promise
> }
>
> // ...
>
> async _startAnimationLoopWhenMounted() {
> this._animationLoopStarted = true
>
> if (!this._mounted) await this.mountPromise
>
> this._rAF = true
> let timestamp = null
> while (this._rAF) {
> timestamp = await animationFrame()
> this._inFrame = true
>
> this._runRenderTasks(timestamp)
> this._renderNodes(timestamp)
>
> // If any tasks are left to run, continue the animation loop.
> if (!this._allRenderTasks.length) {
> this._rAF = null
> this._animationLoopStarted = false
> }
>
> this._inFrame = false
> }
> }
> ```
>
> And the timeline results are surprising! As you can see in the
> following screenshot, all of the logic happens within the frame
> (though you can see there's extra overhead from what I assume are the
> extra function calls due to the fact that I'm using Facebook
> Regenerator for the async functions):
> https://cloud.githubusercontent.com/assets/297678/14764237/8eb71ce2-0965-11e6-942a-3c556c48b9a0.png
>
> Near the bottom right of the screen shot, you can see the tooltip as
> I'm hovering on the call to `animationFrame` which returns the promise
> that I am awaiting in the loop.
>
> Although this behavior seems to be exactly what I was hoping for, it
> seems like there is something wrong. Could there be a bug in
> regenerator that is failing to defer my loop code to a following tick?
> Or is my code deferred to a following tick that somehow the animation
> frame knows to execute within the same tick? Maybe there's something
> I'm missing about the Promise API that allows for .then() of a promise
> (which I assume is what Regenerator is using) to be executed in the
> same tick? What's going on here?
>
> I was expecting to see the code of my loop execute outside of the
> "Animation Frame Fired" section.
>
> On Sat, Apr 23, 2016 at 6:28 AM, Boris Zbarsky  wrote:
>> On 4/23/16 4:09 AM, Salvador de la Puente González wrote:
>>>
>>> AFAIK, that should execute `drawSomething()` once per frame. Given a
>>> frame is each time the animatinFrame() promise resolves.
>>
>>
>> What's not obvious to me is whether it will execute it before the actual
>> paint for the frame (i.e. before or right after the loop that's notifying
>> the animation frame callbacks completes) or whether it will do
>> drawSomething() after the paint...
>>
>> -Boris
>>
>> ___
>> es-discuss mailing list
>> es-discuss@mozilla.org
>> https://mail.mozilla.org/listinfo/es-discuss
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Promises, async functions, and requestAnimationFrame, together.

2016-04-23 Thread /#!/JoePea
Alright, I did an experiment, and I'm really surprised at the results!
Apparently, the logic (what would be drawSomething() in my previous
example) is fired within the frame!!

So, let me show you my original method for starting an animation loop.
I'm working on a 3D project at http://infamous.io. The Scene class
(https://github.com/infamous/infamous/blob/master/src/motor/Scene.js)
has a method for starting an animation loop the standard way:

```js
async _startAnimationLoopWhenMounted() {
this._animationLoopStarted = true

if (!this._mounted) await this.mountPromise

// So now we can render after the scene is mounted.
const loop = timestamp => {
this._inFrame = true

this._runRenderTasks(timestamp)
this._renderNodes(timestamp)

// If any tasks are left to run, continue the animation loop.
if (this._allRenderTasks.length)
this._rAF = requestAnimationFrame(loop)
else {
this._rAF = null
this._animationLoopStarted = false
}

this._inFrame = false
}

this._rAF = requestAnimationFrame(loop)
}
```

Here's what the Chrome timeline shows for the logic that is fired
inside the loop:
https://cloud.githubusercontent.com/assets/297678/14764236/8eb72d4a-0965-11e6-9bb9-5db02cc23520.png

Now, I went ahead and modified my Scene class so the method now looks like this:

```js
function animationFrame() {
let resolve = null
const promise = new Promise(r => resolve = r)
window.requestAnimationFrame(resolve)
return promise
}

// ...

async _startAnimationLoopWhenMounted() {
this._animationLoopStarted = true

if (!this._mounted) await this.mountPromise

this._rAF = true
let timestamp = null
while (this._rAF) {
timestamp = await animationFrame()
this._inFrame = true

this._runRenderTasks(timestamp)
this._renderNodes(timestamp)

// If any tasks are left to run, continue the animation loop.
if (!this._allRenderTasks.length) {
this._rAF = null
this._animationLoopStarted = false
}

this._inFrame = false
}
}
```

And the timeline results are surprising! As you can see in the
following screenshot, all of the logic happens within the frame
(though you can see there's extra overhead from what I assume are the
extra function calls due to the fact that I'm using Facebook
Regenerator for the async functions):
https://cloud.githubusercontent.com/assets/297678/14764237/8eb71ce2-0965-11e6-942a-3c556c48b9a0.png

Near the bottom right of the screen shot, you can see the tooltip as
I'm hovering on the call to `animationFrame` which returns the promise
that I am awaiting in the loop.

Although this behavior seems to be exactly what I was hoping for, it
seems like there is something wrong. Could there be a bug in
regenerator that is failing to defer my loop code to a following tick?
Or is my code deferred to a following tick that somehow the animation
frame knows to execute within the same tick? Maybe there's something
I'm missing about the Promise API that allows for .then() of a promise
(which I assume is what Regenerator is using) to be executed in the
same tick? What's going on here?

I was expecting to see the code of my loop execute outside of the
"Animation Frame Fired" section.

On Sat, Apr 23, 2016 at 6:28 AM, Boris Zbarsky  wrote:
> On 4/23/16 4:09 AM, Salvador de la Puente González wrote:
>>
>> AFAIK, that should execute `drawSomething()` once per frame. Given a
>> frame is each time the animatinFrame() promise resolves.
>
>
> What's not obvious to me is whether it will execute it before the actual
> paint for the frame (i.e. before or right after the loop that's notifying
> the animation frame callbacks completes) or whether it will do
> drawSomething() after the paint...
>
> -Boris
>
> ___
> es-discuss mailing list
> es-discuss@mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Promises, async functions, and requestAnimationFrame, together.

2016-04-23 Thread Boris Zbarsky

On 4/23/16 4:09 AM, Salvador de la Puente González wrote:

AFAIK, that should execute `drawSomething()` once per frame. Given a
frame is each time the animatinFrame() promise resolves.


What's not obvious to me is whether it will execute it before the actual 
paint for the frame (i.e. before or right after the loop that's 
notifying the animation frame callbacks completes) or whether it will do 
drawSomething() after the paint...


-Boris
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Promises, async functions, and requestAnimationFrame, together.

2016-04-23 Thread Salvador de la Puente González
AFAIK, that should execute `drawSomething()` once per frame. Given a frame
is each time the animatinFrame() promise resolves.

On Sat, Apr 23, 2016 at 1:38 AM, /#!/JoePea  wrote:

> Is it possible?
>
>  I thought maybe something like this:
>
> ```js
> function animationFrame() {
> let resolve = null
> const promise = new Promise(r => resolve = r)
> window.requestAnimationFrame(resolve)
> return promise
> }
>
> async function game() {
> // the game loop
> while (true) {
> await animationFrame()
> drawSomething()
> }
> }
>
> game()
> ```
>
> But, I'm not sure what to expect: does the code that follows the await
> statement execute in the frame, sometimes in the frame, or never in
> the frame? What might we expect from the various browsers?
> ___
> es-discuss mailing list
> es-discuss@mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Promises as Cancelation Tokens

2016-01-13 Thread Benjamin Gruenbaum
*F# cancellation* - on second thought implicit cancellation through
cancellation like in F# is impractical because of the eagerness of
promises. I don't think it's a valid alternative here. I've discussed this
with Reed Copsey (an F# expert) and he explained the philosophy behind it
to me - it doesn't sound practical for JavaScript promises at all.

*Splitting into abort and ignore semantics - *that sounds like a great
idea, I think that ignore semantics are far more common for the use cases I
run into by the way. I think it might be a good idea to fire this off in a
separate ES-Discuss thread.

*Throwing and implicit cancellation *- I agree with Katelyn, throwing and
ignore cancellation are exclusive. As Bradley said - `return` (as in
generator `.return`) is a better mental model. `finally` blocks are run but
not `catch` blocks. In bluebird 3, cancellation is done with ignore
semantics - and we don't `throw` on cancellation (link again for
comparison: http://bluebirdjs.com/docs/api/cancellation.html ).

*Implicit cancellation being opt in - *I agree too, the nice property is
that cancellation becomes an optimization library authors get to make but
no other code breaks. A library can add support for freeing requests
earlier and you don't have to change your code in order to get the
optimization.

*Socket Lifetime Example - *In bluebird we map that with disposers (ref:
http://bluebirdjs.com/docs/api/promise.using.html ), we have found that in
the last few years although the library gets millions of downloads very few
people actually use `using`. It is an interesting motivating example and I
think we should collect those for any future proposal.

*XHR Example *- I think that ignore semantics can model that. The XHR
saving important changes would simply not be cancellable under implicit
cancellation - trying to cancel it would result in a no-op.

Cheers


On Wed, Jan 13, 2016 at 12:13 AM, Katelyn Gadd  wrote:

> Implicit cancellation doesn't make sense if it involves a throw.
> Furthermore, implicit cancellation would never happen for your example
> - the 'await' clearly depends on the result of the operation, so it is
> in use and it would not make sense for it to be implicitly cancelled.
> For the record, every time I've successfully dealt with implicit
> cancellation, it's opt-in - the library author implementing the
> asynchronous logic decides whether or not it will respond to implicit
> cancellation.
>
> Explicit cancellation ('abort', to use the terminology split Bradley
> advocated above) would potentially introduce a throw there, but that
> should be unsurprising, just as a socket being closed due to an
> ethernet cable getting unplugged would cause a socket operation to
> throw "unexpectedly".
>
>
> There are some subtle distinctions here that APIs tend to get wrong,
> of course. An example that might be informative:
>
> If you look at sockets, various APIs tend to have differences in how
> you deal with lifetime & closing handles. In some cases there are
> subtly different forms operations - for example if you look at Socket
> in the .NET framework, it exposes *three different/overlapping forms
> of lifetime management*, through the Shutdown, Close and Dispose
> methods. If you compare this with Rust's sockets API, the only
> explicit operation it exposes is 'shutdown', and the other two are
> expressed by dropping the value.
>
> For the average .NET user, you can treat all three as equivalent. For
> casual use cases you can just Dispose all IDisposable resources
> (files, sockets, graphics resources...) at the end of a function and
> be ready to go. But behaviorally they are different, and semantically
> they are different. A socket Shutdown followed by a Dispose will flush
> the read/write buffers (which can take time) and allow you to cleanly
> tear everything down, while a standalone Dispose is an instantaneous
> destruction of the socket, potentially breaking a transmission in the
> middle. In practice, this distinction represents that the socket is
> actually a group of related resources - read/write buffers, a network
> connection, etc - that can't simply be treated as a single unit with
> consistent lifetime.
>
> Oh yeah, and there's also the detail that you can shut down the write
> end of a socket but not the read end. :-)
>
> If you map this over to the browser, you can trivially come up with
> equivalent examples. When I issue XHR requests, some of those requests
> are more important than others. For example, an XHR that is saving
> important changes to an email draft should not be aborted if the user
> clicks on a hyperlink to load a new email. However, an XHR that is
> downloading an inline image for an email *can* be safely aborted at a
> moment's notice. You can think of this as equivalent to
> Shutdown/Dispose - you would want to Shutdown the draft save
> operation, flushing everything out, before closing the socket, and
> that takes time. In comparison, the 

Re: Promises as Cancelation Tokens

2016-01-12 Thread Bradley Meck
>
> For async functions, it would mean that any await expression could
> potentially throw a CancelError


Cancellation does not necessarily need to use `throw`, `return` is often
more apt. I find.

I would also recommend splitting the idea of cancellation into: abort
semantics, and ignorance semantics. Trying to use one term for both
separately is getting confusing.

My usage of cancellation is often being able to undo side-effects which can
happily be done using `finally`.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Promises as Cancelation Tokens

2016-01-12 Thread Katelyn Gadd
Implicit cancellation doesn't make sense if it involves a throw.
Furthermore, implicit cancellation would never happen for your example
- the 'await' clearly depends on the result of the operation, so it is
in use and it would not make sense for it to be implicitly cancelled.
For the record, every time I've successfully dealt with implicit
cancellation, it's opt-in - the library author implementing the
asynchronous logic decides whether or not it will respond to implicit
cancellation.

Explicit cancellation ('abort', to use the terminology split Bradley
advocated above) would potentially introduce a throw there, but that
should be unsurprising, just as a socket being closed due to an
ethernet cable getting unplugged would cause a socket operation to
throw "unexpectedly".


There are some subtle distinctions here that APIs tend to get wrong,
of course. An example that might be informative:

If you look at sockets, various APIs tend to have differences in how
you deal with lifetime & closing handles. In some cases there are
subtly different forms operations - for example if you look at Socket
in the .NET framework, it exposes *three different/overlapping forms
of lifetime management*, through the Shutdown, Close and Dispose
methods. If you compare this with Rust's sockets API, the only
explicit operation it exposes is 'shutdown', and the other two are
expressed by dropping the value.

For the average .NET user, you can treat all three as equivalent. For
casual use cases you can just Dispose all IDisposable resources
(files, sockets, graphics resources...) at the end of a function and
be ready to go. But behaviorally they are different, and semantically
they are different. A socket Shutdown followed by a Dispose will flush
the read/write buffers (which can take time) and allow you to cleanly
tear everything down, while a standalone Dispose is an instantaneous
destruction of the socket, potentially breaking a transmission in the
middle. In practice, this distinction represents that the socket is
actually a group of related resources - read/write buffers, a network
connection, etc - that can't simply be treated as a single unit with
consistent lifetime.

Oh yeah, and there's also the detail that you can shut down the write
end of a socket but not the read end. :-)

If you map this over to the browser, you can trivially come up with
equivalent examples. When I issue XHR requests, some of those requests
are more important than others. For example, an XHR that is saving
important changes to an email draft should not be aborted if the user
clicks on a hyperlink to load a new email. However, an XHR that is
downloading an inline image for an email *can* be safely aborted at a
moment's notice. You can think of this as equivalent to
Shutdown/Dispose - you would want to Shutdown the draft save
operation, flushing everything out, before closing the socket, and
that takes time. In comparison, the image load is implicitly cancelled
as soon as the image content is no longer needed, and that can
terminate the underlying request if appropriate.


On 11 January 2016 at 19:59, Kevin Smith  wrote:
>> I think F#'s cancellation approach is also worth mentioning in the
>> discussion of alternatives as it has implicit but token-based automatically
>> propagating cancellation.
>
>
> If you have any good links to reference materials on F#'s cancellation
> architecture, feel free to include them for future reference.  I was unable
> to find anything that clearly explained how implicit cancellation tokens are
> discovered by child tasks, for instance.
>
> I find implicit cancellation to be somewhat sketchy.  For async functions,
> it would mean that any await expression could potentially throw a
> CancelError:
>
> async function f() {
>   let a = await 1; // This could throw?  What?
> }
>
> And there are certainly going to be scenarios where you *don't* want to
> cancel a subtask.  It seems to me that cancellation semantics are best left
> to the async operation itself, rather than assuming "crash-and-burn".
>
>
> ___
> es-discuss mailing list
> es-discuss@mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Promises as Cancelation Tokens

2016-01-11 Thread Kevin Smith
>
> I think F#'s cancellation approach is also worth mentioning in the
> discussion of alternatives as it has implicit but token-based automatically
> propagating cancellation.
>

If you have any good links to reference materials on F#'s cancellation
architecture, feel free to include them for future reference.  I was unable
to find anything that clearly explained how implicit cancellation tokens
are discovered by child tasks, for instance.

I find implicit cancellation to be somewhat sketchy.  For async functions,
it would mean that any await expression could potentially throw a
CancelError:

async function f() {
  let a = await 1; // This could throw?  What?
}

And there are certainly going to be scenarios where you *don't* want to
cancel a subtask.  It seems to me that cancellation semantics are best left
to the async operation itself, rather than assuming "crash-and-burn".
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Promises as Cancelation Tokens

2016-01-11 Thread Benjamin Gruenbaum
> Another cancellation scenario is when the consumer of an asynchronous
task no longer
> needs the result of an operation. In this case, they will only have
access to the Promise
> unless the cancellation token is routed to them through some other path.

For what it's worth - this is exactly how promise cancellation is modeled
in bluebird 3 and we have found it very nice.

I think the distinction between cancellation because of disinterest and
cancellation because we actively want to cancel the operation is very
important - props for nailing it.

That said - I think most scenarios that work with tokens work without them
and vice versa.

I think F#'s cancellation approach is also worth mentioning in the
discussion of alternatives as it has implicit but token-based automatically
propagating cancellation.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Promises as Cancelation Tokens

2016-01-11 Thread Katelyn Gadd
One key thing to recognize is that there are different reasons to
cancel an operation and as a result, different approaches to
cancellation. .NET cancellation tokens address one scenario (and do it
fairly well), where the objective is for specific operations to expose
cancellation and allow the caller to set up a way to cancel the
operation once it is in progress. This requires co-operation on both
sides but is very easy to debug and reason about.

However, this does not address all cancellation scenarios.

Another cancellation scenario is when the *consumer* of an
asynchronous task no longer needs the result of an operation. In this
case, they will only have access to the Promise unless the
cancellation token is routed to them through some other path. This
becomes especially unwieldy if you are dealing with a graph of
asynchronous operations, where you want this 'no longer needed'
property to propagate through all of the promises. This is somewhat
equivalent to how you want a garbage collector to collect a whole tree
of objects once they are no longer reachable. In JS (and in my
opinion, basically all language environments) you want this to be
explicit even if the GC is able to lazily flag the result of a promise
as no longer needed. In the 'result no longer needed' scenario there
are also cases where you do not want to cancel the operation even if
it is not needed anymore.

A third form of cancellation is already addressed by Promise
implementations - error handling. In this case, an error occurs and
the whole asynchronous process (usually) needs to be aborted and
unwound so that the error can be responded to. In this scenario
cancellation can occur at any time and in some cases it is not
possible for the application to continue correctly under these
circumstances. You could use exceptions to implement the other forms
of cancellation, but it's pretty unwieldy - and injecting exceptions
into code that doesn't expect that is a generally bad policy. .NET
used to allow injecting exceptions into other threads but has since
deprecated it because of all the nasty corner cases it introduces.

In my opinion cancellation tokens are a great model that does not
require any browser vendor/VM implementer support, but it can be
beneficial for implementations of specific operations (i.e. XHR) to
provide some sort of cancellation mechanism. Essentially, the XHR
object acts as the cancellation token and you call a method on it to
cancel. In most cases you can implement that in user space.

'Result no longer needed' requires some amount of support at the
language/base framework level, so that it is possible to flag this
state on any given Promise and it is possible for all Promise
consumers to appropriately propagate this state through graphs of
asynchronous dependencies. For example, cancelling a HTML pageload
should flag any dependent image/script loads as 'no longer needed',
but not necessarily *abort* them (aborting might kill the keepalive
connection, and allowing the request to complete might helpfully prime
the cache with those resources).

-kg

On 5 January 2016 at 19:58, Kevin Smith  wrote:
> Thanks for posting this.  Great stuff!
>
>>
>> On a page that loads 100 images four at a time, you would want 4 cleanup
>> actions registered, not 100.
>
>
> And in order to keep it to 4 you need a way to unregister the action when
> you complete the operation, which the promise API doesn't give you.  I see.
>
> Conceptually, you could of course set some "complete" flag when you finish
> the operation and then have the cleanup action early-exit if that flag is
> set, but that would be unwieldy.  And it wouldn't stop the unbounded growth
> of the promise's handler list.
>
> Interesting!
>
>
> ___
> es-discuss mailing list
> es-discuss@mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Promises as Cancelation Tokens

2016-01-05 Thread Kevin Smith
Thanks for posting this.  Great stuff!


> On a page that loads 100 images four at a time, you would want 4 cleanup
> actions registered, not 100.
>

And in order to keep it to 4 you need a way to unregister the action when
you complete the operation, which the promise API doesn't give you.  I see.

Conceptually, you could of course set some "complete" flag when you finish
the operation and then have the cleanup action early-exit if that flag is
set, but that would be unwieldy.  And it wouldn't stop the unbounded growth
of the promise's handler list.

Interesting!
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Promises as Cancelation Tokens

2016-01-05 Thread Kevin Smith
Thanks Ron!  Comments inline...

> ·   Once a callback has been registered for asynchronous notification
> of a cancellation signal, it can later be unregistered.
>
Yes, I see how this could be helpful.

> ·   Asynchronous notifications are queued and handled at a higher
> priority than Promise continuations.
>
> ·   The reason for cancellation can be explicitly supplied. If not
> supplied, the reason would be a generic “The operation was canceled” error.
>
What's the benefit of allowing a user-supplied error?  (I assume that by
convention the reason should be an error type.)  I don't see that feature
in .NET.

> Since “source.cancel()” is executed synchronously, one would expect that
> `p` would be rejected. If the notification were merely added to the same
> micro-task queue as Promise “then” tasks, `p` would be resolved first.
>
I agree that your example, as written, is counter-intuitive.  However, is
it still counter-intuitive if I rewrite it like this?

// Suppose I have "cancelToken" and "cancel"
let p = new Promise((resolve, reject) => {
  Promise.resolve(1).then(resolve);
  cancelToken.promise.then(reject);
  cancel();
});

Written like this, it seems to me that the ordering is as expected.  Are
there use cases that require a higher priority, beyond user expectation
based on the API?

In .NET, cancellation notifications are executed synchronously, however
> this conflicts with the intent to ensure an asynchronous API is
> consistently asynchronous.
>
Right.  The trouble I have with introducing an ad-hoc callback API for
cancel tokens centers mostly around the handling and propagation of
errors.  In .NET, exceptions which occur inside of callbacks are propagated
synchronously to the caller via an AggregateException error collection.
But if the callbacks are truly executed asynchronously, where do the errors
go?  Do they propagate out to the host, like HTML event handlers?  It would
be unfortunate if no mechanism was provided by ECMAScript itself to handle
such errors.

Since we already have a well-defined and well-understood way to propagate
errors using promises, I would prefer to have the async registration
capability modeled as a promise, if possible.  There is that "unregister"
issue, though...
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Promises as Cancelation Tokens

2016-01-04 Thread /#!/JoePea
Since checking `promise.state` is synchronous, we may as well just
write a synchronous Cancel class instead:

```js
class CancelError extends Error { /* ... */ }

class Cancel {
constructor() { this.requested = false }
request() { this.requested = true }
throw() { throw new CancelError() }
}

async function f(cancel) {
await cheapOperation(cancel) // some other function might call
cancel.request() while we await here.
if (!cancel.requested)
await expensiveOperation(cancel)
}

let cancel = new Cancel
cancelButton.onclick = () => cancel.request()
f(cancel)
```

Wouldn't this be better than using a Promise if we are relying on a
synchronous check anyways?

On Mon, Jan 4, 2016 at 12:30 PM, Kevin Smith  wrote:
>> We have pretty sound cancellation semantics in bluebird 3.
>
>
> Cool, I'm aware that cancellable promises have been explored in depth.  I'd
> prefer to keep this thread focused on cancellation tokens though, and avoid
> comparisons.
>
>
> ___
> es-discuss mailing list
> es-discuss@mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Promises as Cancelation Tokens

2016-01-04 Thread /#!/JoePea
Cool, yeah, the reveal pattern would indeed be a good way to guard
against unwanted/unexpected cancels.

```js
class Cancel {
constructor(executor) {
this._requested = false
executor(() => this._requested = true)
}
get requested() {return this._requested}
throw() { throw new CancelError() }
}

let cancel = new Cancel(function(cancel) {
cancelButton.onclick = cancel
})
```

What would be the recommended way of keeping the internal state
private? With a WeakMap?

On Mon, Jan 4, 2016 at 1:01 PM, Kevin Smith  wrote:
>> Since checking `promise.state` is synchronous, we may as well just
>> write a synchronous Cancel class instead:
>
>
> Right - see upthread.  You do need some kind of callback method, though,
> like `whenCancelled(callback)`.
>
>>
>> class Cancel {
>> constructor() { this.requested = false }
>> request() { this.requested = true }
>> throw() { throw new CancelError() }
>> }
>
>
> We need to separate the capability to "read" the cancellation request from
> the ability to request the cancellation.  That's why in .NET you have
> CancellationTokenSource and CancellationToken.  But for JS, we should
> probably use the revealing constructor pattern instead (discussed upthread):
>
> let token = new CancelToken(cancel => { ... });
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Promises as Cancelation Tokens

2016-01-04 Thread Kevin Smith
>
> Since checking `promise.state` is synchronous, we may as well just
> write a synchronous Cancel class instead:
>

Right - see upthread.  You do need some kind of callback method, though,
like `whenCancelled(callback)`.


> class Cancel {
> constructor() { this.requested = false }
> request() { this.requested = true }
> throw() { throw new CancelError() }
> }
>

We need to separate the capability to "read" the cancellation request from
the ability to request the cancellation.  That's why in .NET you have
CancellationTokenSource and CancellationToken.  But for JS, we should
probably use the revealing constructor pattern instead (discussed upthread):

let token = new CancelToken(cancel => { ... });
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Promises as Cancelation Tokens

2016-01-04 Thread Kevin Smith
>
> We have pretty sound cancellation semantics in bluebird 3.
>

Cool, I'm aware that cancellable promises have been explored in depth.  I'd
prefer to keep this thread focused on cancellation tokens though, and avoid
comparisons.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Promises as Cancelation Tokens

2016-01-04 Thread Kevin Smith
>
> The best approach in cases like this is to avoid the word altogether.
> The fact that there's confusion at all means people will mess it up
> and get annoyed, even if there's a "winner" in overall usage.
>

Hmmm...  Maybe

class CancelToken {
  constructor(init);
  get cancelRequested() : bool;
  whenCancelRequested(callback) : void;
}

Or more/overly tersely:

class CancelToken {
  constructor(init);
  get requested() : bool;
  whenRequested(callback) : void;
}
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Promises as Cancelation Tokens

2016-01-04 Thread Benjamin Gruenbaum
We have pretty sound cancellation semantics in bluebird 3. 

http://bluebirdjs.com/docs/api/cancellation.html

Handles multiple subscribers soundly. Solves the common use cases pretty well - 
has absolutely zero magic and pretty simple semantics. They work with .all and 
.race too. 

We have had a lot of positive feedback regarding the change and it works well 
(at least in my code) with async/await and other newer proposals.

Biggest downside is that it hasn't been used for very long yet in production 
( On 4 Jan 2016, at 19:55, Tab Atkins Jr.  wrote:
> 
>> On Mon, Jan 4, 2016 at 9:01 AM, Domenic Denicola  wrote:
>> From: Kevin Smith [mailto:zenpars...@gmail.com]
>> 
>>> And what's the deal, is it canceled or cancelled?  : )
>> 
>> This is kind of the worst. Previous discussion at 
>> https://github.com/promises-aplus/cancellation-spec/issues/4.
>> 
>> Data seems to favor cancelled:
>> 
>> - 
>> https://books.google.com/ngrams/graph?content=canceled%2Ccancelled_start=1800_end=2020=15=3=_url=t1%3B%2Ccanceled%3B%2Cc0%3B.t1%3B%2Ccancelled%3B%2Cc0
>> - http://www.google.com/trends/explore#q=cancelled%2C%20canceled=q
>> - http://www.googlefight.com/canceled-vs-cancelled.php
> 
> The best approach in cases like this is to avoid the word altogether.
> The fact that there's confusion at all means people will mess it up
> and get annoyed, even if there's a "winner" in overall usage.
> 
> On Mon, Jan 4, 2016 at 9:36 AM, Kevin Smith  wrote:
>>> I am also unsure when .whenCanceled is necessary
>> 
>> Maybe in the case where you have a promise-returning function and you want
>> to reject the returned promise upon cancellation.
>> 
>>function delayWithCancel(ms, cancelToken) {
>>  return new Promise((resolve, reject) => {
>>setTimeout(resolve, ms);
>>cancelToken.whenCancelled(reject);
>>  });
>>}
> 
> Yes, forcing people to poll an attribute of a Promise-like thing is
> kinda ridic. ^_^
> 
> ~TJ
> 
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Promises as Cancelation Tokens

2016-01-04 Thread Benjamin Gruenbaum
> Cool, I'm aware that cancellable promises have been explored in depth.
I'd prefer to keep this thread focused on cancellation tokens though, and
avoid comparisons.

Cool, re-reading the discussion you asked for this in the first message - I
apologize for missing it.

I think using promises as tokens would be problematic. It would have
several issues:

 - You'd want to be able to  `cancel` things like Promise.all and
`Promise.race` - with a separate type you can use "the last argument", with
a promise you would not be able.
 - The names would get confusing for the users. Like Domenic said -
`whenCancelled` sounds a lot clearer. Sort of like the function vs. object
discussion on es-observable.
 - You get some weird scenarios like cancelling a cancellation.
 - You'd probably need to add properties anyway so that tokens can be
aggregated.

I do definitely see the use for `whenCancelled` and have used its
equivalent myself in C#.


It's also important to keep in mind that promises can be subclassed so it's
fine to add properties to them if used for a specific purpose like
cancellation.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Promises as Cancelation Tokens

2016-01-04 Thread Benjamin Gruenbaum
> We could use a promise subclass as the cancellation token, but then
tokens (and their constructor) would inherit things that really don't make
sense, like "CancelToken.resolve" and "CancelToken.prototype.catch".

Generally I dislike inheritance. I was merely saying it's an option. I
favor composition here as well.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Promises as Cancelation Tokens

2016-01-04 Thread Kevin Smith
>
> I think using promises as tokens would be problematic. It would have
> several issues:
>

Agreed with all of those.

It's also important to keep in mind that promises can be subclassed so it's
> fine to add properties to them if used for a specific purpose like
> cancellation.
>

We could use a promise subclass as the cancellation token, but then tokens
(and their constructor) would inherit things that really don't make sense,
like "CancelToken.resolve" and "CancelToken.prototype.catch".

On the other hand, it doesn't really make sense to create a new callback
API (`whenCancelled`), when we already have the necessary callback
semantics with promises.  Perhaps we can expose a promise on the token
instead:

class CancelToken {
get requested() : bool;
get promise() : Promise;
throwIfRequested() : void;
}

// Registering a callback
token.promise.then(_=> doSomething());

// Doing other things with the promise
Promise.race(token.promise, someOtherPromise);
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


RE: Promises as Cancelation Tokens

2016-01-04 Thread Ron Buckton

This gist<https://gist.github.com/rbuckton/b69be537e41feec7fea7> contains the 
TypeScript declarations for the version of CancellationToken I’ve been using 
for a number of small projects. The basic API shape is:

```ts
class CancellationTokenSource {
  constructor(linkedTokens?: CancellationToken[]);
  token: CancellationToken;
  cancel(reason?: any): void;
  close(): void;
}
class CancellationToken {
  static none: CancellationToken;
  canBeCanceled: boolean;
  canceled: boolean;
  reason: any;
  throwIfCanceled(reason?: any): void;
  register(callback: (reason?: any) => void): CancellationTokenRegistration;
}
interface CancellationTokenRegistration {
  unregister(): void;
}
```

The approach I use has the following considerations:


•   The responsibility for cancellation is split between two types:

o   CancellationTokenSource – This type is responsible for propagating a 
cancellation signal and linking multiple tokens together (useful to cancel a 
graph of async operations, such as cancelling all pending fetch request).

o   CancellationToken – A read-only sink for a cancellation signal. 
Asynchronous operations can either synchronously observe whether the 
cancellation signal has been set, or register an callback for asynchronous 
notification of a cancellation signal.

•   Once a callback has been registered for asynchronous notification of a 
cancellation signal, it can later be unregistered.

•   Asynchronous notifications are queued and handled at a higher priority 
than Promise continuations.

•   The reason for cancellation can be explicitly supplied. If not 
supplied, the reason would be a generic “The operation was canceled” error.

Splitting a cancellation signal across two classes has several benefits. One 
benefit is that it allows the producer of a cancellation signal to limit access 
to the ability to initiate that signal. This is important if you wish to have a 
single shared cancellation source for multiple concurrent asynchronous 
operations, but need to hand off a cancellation token to a third party without 
worrying that the third party code would unintentionally cancel operations that 
it does not itself own. Another benefit is the ability to create more complex 
cancellation graphs through linking multiple cancellation tokens.

I agree with Domenic that it is necessary to be able to synchronously observe 
the canceled state of a cancellation token, and that it is also necessary to be 
able to observe a cancellation signal asynchronously. However, I have found 
that the asynchronous notification needs to be triggered at a higher priority 
than Promise “then” tasks. Consider the following, albeit contrived, example:

```js
let source = new CancellationTokenSource();
let p = new Promise((resolve, reject) => {
  Promise.resolve(1).then(resolve);
  source.token.register(reject);
  source.cancel();
});
```

Since “source.cancel()” is executed synchronously, one would expect that `p` 
would be rejected. If the notification were merely added to the same micro-task 
queue as Promise “then” tasks, `p` would be resolved first. By making the 
micro-task queue into a priority queue, we can allow cancellation notifications 
to be processed at a higher priority while still keeping the API itself 
asynchronous. In .NET, cancellation notifications are executed synchronously, 
however this conflicts with the intent to ensure an asynchronous API is 
consistently asynchronous.

This approach also allows cancellation tokens to be more general-purpose. By 
not directly tying cancellation into Promises, they can be used with other 
future asynchronous primitives such as Observables, async generators, etc.

Ron

From: Kevin Smith<mailto:zenpars...@gmail.com>
Sent: Monday, January 4, 2016 11:44 AM
To: Tab Atkins Jr.<mailto:jackalm...@gmail.com>; Domenic 
Denicola<mailto:d...@domenic.me>
Cc: es-discuss<mailto:es-discuss@mozilla.org>
Subject: Re: Promises as Cancelation Tokens

The best approach in cases like this is to avoid the word altogether.
The fact that there's confusion at all means people will mess it up
and get annoyed, even if there's a "winner" in overall usage.

Hmmm...  Maybe

class CancelToken {
  constructor(init);
  get cancelRequested() : bool;
  whenCancelRequested(callback) : void;
}

Or more/overly tersely:

class CancelToken {
  constructor(init);
  get requested() : bool;
  whenRequested(callback) : void;
}




___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Promises as Cancelation Tokens

2016-01-04 Thread Dean Tribble
>From experience, I'm very much in favor of the cancellation token.  Though
promises provide a good inspiration for cancellation, they don't quite fit
the problem directly.

The approach has been explored, though the details are not published. I
implemented cancellation for the Midori system. Midori was an incubation
project to build a new OS, applications, etc. in a safe language (a C#
variant) using lightweight processes communicating via promises (easily 2M+
lines of C#). Among other things, it strongly influenced the C# async
support. See http://joeduffyblog.com/2015/11/19/asynchronous-everything/
for more info. After looking at various options, the approach developed for
.Net covered all the requirements we had and could be adapted surprisingly
well to the async world of promises and Midori. There were some important
differences though.

In a concurrent, async, or distributed system, cancellation is
*necessarily *asynchronous: there's fundamentally a race between a
computation "expanding" (spawning more work) and cancellation running it
down. But as you note, a cancellation system must support the ability to
*synchronously *and cheaply test whether a computation is being cancelled.
That allows one for example to write a loop over thousands of records that
will abort quickly when cancelled without scheduling activity for the
remaining records. (Because of the inherent race in cancellation, I named
that "isCancelling" rather than "isCancelled" to be a small reminder that
computation elsewhere might not yet have heard that it should stop.)

In async cancellation, the promise "then" seems like it could support the
asycn "cleanup" action on cancellation. However there are a lot of
cancellation use cases in which the appropriate cleanup action changes as a
computation proceeds. For those, using "then" is not adequate. For example,
a browser would have a cancellation token associated with a page load. Thus
the same token is used during parsing, retrieving secondary images, layout,
etc. If the user hits "stop", the token is cancelled, and so all the
various heterogeneous page rendering activities are cancelled. But the
cleanup action to "close the socket that you are retrieving an image over"
becomes expensive deadweight once the image has been retrieved. On a page
that loads 100 images four at a time, you would want 4 cleanup actions
registered, not 100.

For that and other reasons, we found it much clearer to give
cancellationToken it's own type. That also allows convenient patterns to be
directly supported, such as:

async function f(cancel) {
  await cheapOperation(cancel);
  cancel.*throwIfCancelling*(); // throws if the token is cancelling
  await expensiveOperation(cancel);
}

Note that the above would more likely have been written simply:

async function f(cancel) {
  await cheapOperation(cancel);
  await expensiveOperation(cancel);
}

The reason is that if the cheapOperation was aborted, the first await would
throw (assuming cheapOperation terminates abruptly or returns a broken
promise). If it got past cheapOperation, we already know that
expensiveOperation is going to be smart enough to cancel, so why clutter
our world with redundant aborts?  e.g.,

async function expensiveOperation(cancel) {
  while (hasFramesToRender() && !cancel.isCancelling()) {
  await renderFrame(this.nextFrame(), cancel);
  }
}

Thus, using cancellation tokens becomes simpler as cancellation becomes
more pervasive in the libraries. Typically, if an operation takes a
cancellation token as an argument, then you don't need to bother protecting
it from cancellation. As a result, explicit cancellation handling tends to
only be needed in lower level library implementation, and client code
passes their available token to either operations or to the creation of
objects (e.g., pass in your token when you open a file rather than on every
file operation).



On Mon, Jan 4, 2016 at 7:46 AM, Kevin Smith  wrote:

> I'm interested in exploring the idea of using an approach similar to
> .NET's cancelation tokens in JS for async task cancelation.  Since the
> cancelation "flag" is effectively an eventual value, it seems like promises
> are well-suited to modeling the token.  Using a promise for a cancelation
> token would have the added benefit that the eventual result of any
> arbitrary async operation could be used as a cancelation token.
>
> First, has this idea been fully explored somewhere already?  We've
> discussed this idea on es-discuss in the past, but I don't remember any
> in-depth analysis.
>
> Second, it occurs to me that the current promise API isn't quite ideal for
> cancelation tokens, since we don't have synchronous inspection
> capabilities.  For example, suppose that we have this async function:
>
> async function f(cancel) {
>   let canceled = false;
>   cancel.then(_=> canceled = true);
>   await cheapOperation(cancel);
>  

Re: Promises as Cancelation Tokens

2016-01-04 Thread Kevin Smith
> throw() { throw new CancelError() }
>

This should be `throwIfRequested` I think, e.g.

throwIfRequested() {
  if (this._requested)
throw new CancelError();
  }
}


> What would be the recommended way of keeping the internal state
> private? With a WeakMap?
>

Spec-defined objects can have "internal slots" (essentially private
fields), which can be simulated with WeakMaps.  Although a polyfill would
most likely just use underscored names.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Promises as Cancelation Tokens

2016-01-04 Thread Tab Atkins Jr.
On Mon, Jan 4, 2016 at 9:01 AM, Domenic Denicola  wrote:
> From: Kevin Smith [mailto:zenpars...@gmail.com]
>
>> And what's the deal, is it canceled or cancelled?  : )
>
> This is kind of the worst. Previous discussion at 
> https://github.com/promises-aplus/cancellation-spec/issues/4.
>
> Data seems to favor cancelled:
>
> - 
> https://books.google.com/ngrams/graph?content=canceled%2Ccancelled_start=1800_end=2020=15=3=_url=t1%3B%2Ccanceled%3B%2Cc0%3B.t1%3B%2Ccancelled%3B%2Cc0
> - http://www.google.com/trends/explore#q=cancelled%2C%20canceled=q
> - http://www.googlefight.com/canceled-vs-cancelled.php

The best approach in cases like this is to avoid the word altogether.
The fact that there's confusion at all means people will mess it up
and get annoyed, even if there's a "winner" in overall usage.

On Mon, Jan 4, 2016 at 9:36 AM, Kevin Smith  wrote:
>> I am also unsure when .whenCanceled is necessary
>
> Maybe in the case where you have a promise-returning function and you want
> to reject the returned promise upon cancellation.
>
> function delayWithCancel(ms, cancelToken) {
>   return new Promise((resolve, reject) => {
> setTimeout(resolve, ms);
> cancelToken.whenCancelled(reject);
>   });
> }

Yes, forcing people to poll an attribute of a Promise-like thing is
kinda ridic. ^_^

~TJ
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Promises as Cancelation Tokens

2016-01-04 Thread Kevin Smith
>
> I am also unsure when .whenCanceled is necessary
>

Maybe in the case where you have a promise-returning function and you want
to reject the returned promise upon cancellation.

function delayWithCancel(ms, cancelToken) {
  return new Promise((resolve, reject) => {
setTimeout(resolve, ms);
cancelToken.whenCancelled(reject);
  });
}
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Promises as Cancelation Tokens

2016-01-04 Thread Bradley Meck
I agree that without synchronous inspection cancellation tokens become very
hard to deal with as you may be queued for a long time prior to
cancellation on the event loop, and then the operation is cancelled while
you are waiting to check for cancellation. Is there a reason to use a
Promise as the cancellation token, rather than have something that is
synchronously inspectable? Even a small class/interface like:

```javascript
let cancelled = false;
myPromise.then(() => cancelled = true);
task[Symbol.cancelled] = () => cancelled;
```

For this reason I do not think Promises are the right data type to handle
Cancellation. There are several existing uses of cancellation tokens that
are just `{[nameForIsCancelledMethod](): {/*return boolean here*/}}`.

There are several reasons I don't think Promises should be extended any
further, but that causes a divide amongst people wanting them to represent
all possible async tasks and me.


> I am also unsure when .whenCanceled is necessary (maybe for interfacing
> with cancelable systems that are not cancelation token aware, like XHR?).
> And it seems likely that the rejection path is not necessary.


I don't think so, but you do need to create a way to allow canceling the
task from inside of another task (can be done by having a data structure
that is passed in to your task runner). I had to do that while working with
Node's `.pipe` in
https://github.com/bmeck/managed-task/blob/master/lib/examples/lockfile.js#L66

I know VSCode has that event, maybe they can shed light on why?

On Mon, Jan 4, 2016 at 10:04 AM, Domenic Denicola  wrote:

> In general I agree that there is a nice conceptual symmetry, but IMO the
> day-to-day impedance mismatch would be simply too great. Compare:
>
> ```js
> async function f(cancelationToken) {
>   cancelationToken.then(() => console.log("FYI you have been canceled"));
>
>   await cheapOperation(cancelationToken);
>   if (cancelationToken.state === "fulfilled") {
> throw new CanceledOperationError();
>   }
>   await expensiveOperation(cancelationToken);
> }
>
> const token = new Promise(resolve => {
>   cancelButton.onclick = resolve;
> });
>
> f(token);
> ```
>
> to the same thing with different names:
>
> ```js
> async function f(cancelationToken) {
>   cancelationToken.whenCanceled(() => console.log("FYI you have been
> canceled"));
>
>   await cheapOperation(cancelationToken);
>   if (cancelationToken.canceled) {
> throw new CanceledOperationError();
>   }
>   await expensiveOperation(cancelationToken);
> }
>
> const token = new CancelationToken(cancel => {
>   cancelButton.onclick = cancel;
> });
>
> f(token);
> ```
>
> I am also unsure when .whenCanceled is necessary (maybe for interfacing
> with cancelable systems that are not cancelation token aware, like XHR?).
> And it seems likely that the rejection path is not necessary.
>
> So, if cancelation tokens are the right path, I'd prefer not reusing
> promises for them. Maybe it argues for easily being able to create a
> cancelation token from a promise, though.
>
> Semi-related: I was recently reading
> http://joeduffyblog.com/2015/11/19/asynchronous-everything/, which has a
> section on Cancelation.
>
> ___
> es-discuss mailing list
> es-discuss@mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Promises as Cancelation Tokens

2016-01-04 Thread Kevin Smith
And what's the deal, is it canceled or cancelled?  : )


On Mon, Jan 4, 2016 at 11:30 AM Kevin Smith  wrote:

> Is there a reason to use a Promise as the cancellation token, rather than
>> have something that is synchronously inspectable?
>>
>
> The only real downside of coming up with a new interface is that we have
> to standardize it.  : )  It's a core protocol.
>
> I agree that using a promise directly would feel awkward without a helper
> library.  You'd probably also want a method that would throw an error if
> the cancel token was activated (as in .NET
> https://msdn.microsoft.com/en-us/library/system.threading.cancellationtoken.throwifcancellationrequested(v=vs.110).aspx
> ):
>
> cancelToken.throwIfCanceled();
>
> Instead of the more verbose:
>
> if (cancelToken.canceled)
>   throw new OperationCancelledError();
>
> I also like the revealing constructor pattern that Domenic mentioned.
> It's almost good enough, as-is, for converting from a promise to a
> cancelation token:
>
> new CancellationToken(cancel => somePromise.then(cancel));
>
> Nice!
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


RE: Promises as Cancelation Tokens

2016-01-04 Thread Domenic Denicola
In general I agree that there is a nice conceptual symmetry, but IMO the 
day-to-day impedance mismatch would be simply too great. Compare:

```js
async function f(cancelationToken) {
  cancelationToken.then(() => console.log("FYI you have been canceled"));

  await cheapOperation(cancelationToken);
  if (cancelationToken.state === "fulfilled") {
throw new CanceledOperationError();
  }
  await expensiveOperation(cancelationToken);
}

const token = new Promise(resolve => {
  cancelButton.onclick = resolve;
});

f(token);
```

to the same thing with different names:

```js
async function f(cancelationToken) {
  cancelationToken.whenCanceled(() => console.log("FYI you have been 
canceled"));

  await cheapOperation(cancelationToken);
  if (cancelationToken.canceled) {
throw new CanceledOperationError();
  }
  await expensiveOperation(cancelationToken);
}

const token = new CancelationToken(cancel => {
  cancelButton.onclick = cancel;
});

f(token);
```

I am also unsure when .whenCanceled is necessary (maybe for interfacing with 
cancelable systems that are not cancelation token aware, like XHR?). And it 
seems likely that the rejection path is not necessary.

So, if cancelation tokens are the right path, I'd prefer not reusing promises 
for them. Maybe it argues for easily being able to create a cancelation token 
from a promise, though.

Semi-related: I was recently reading 
http://joeduffyblog.com/2015/11/19/asynchronous-everything/, which has a 
section on Cancelation.

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Promises as Cancelation Tokens

2016-01-04 Thread Kevin Smith
>
> Is there a reason to use a Promise as the cancellation token, rather than
> have something that is synchronously inspectable?
>

The only real downside of coming up with a new interface is that we have to
standardize it.  : )  It's a core protocol.

I agree that using a promise directly would feel awkward without a helper
library.  You'd probably also want a method that would throw an error if
the cancel token was activated (as in .NET
https://msdn.microsoft.com/en-us/library/system.threading.cancellationtoken.throwifcancellationrequested(v=vs.110).aspx
):

cancelToken.throwIfCanceled();

Instead of the more verbose:

if (cancelToken.canceled)
  throw new OperationCancelledError();

I also like the revealing constructor pattern that Domenic mentioned.  It's
almost good enough, as-is, for converting from a promise to a cancelation
token:

new CancellationToken(cancel => somePromise.then(cancel));

Nice!
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


RE: Promises as Cancelation Tokens

2016-01-04 Thread Domenic Denicola
From: Kevin Smith [mailto:zenpars...@gmail.com] 

> And what's the deal, is it canceled or cancelled?  : )

This is kind of the worst. Previous discussion at 
https://github.com/promises-aplus/cancellation-spec/issues/4.

Data seems to favor cancelled:

- 
https://books.google.com/ngrams/graph?content=canceled%2Ccancelled_start=1800_end=2020=15=3=_url=t1%3B%2Ccanceled%3B%2Cc0%3B.t1%3B%2Ccancelled%3B%2Cc0
- http://www.google.com/trends/explore#q=cancelled%2C%20canceled=q
- http://www.googlefight.com/canceled-vs-cancelled.php

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Promises vs Streams

2015-03-28 Thread Brendan Eich

Domenic Denicola wrote:
Seeing as how I just produced a completely redundant message by 
failing to read the other responses before firing off my own, let me 
try to redeem myself with some more-original content.


(Nice post!)

It’s also important to realize that streams are not the only 
asynchronous-plural primitive out there. My favorite analogy is 
“streams are to asynchronous iterables as arrays are to synchronous 
iterables.” That is, streams are a specialized data structure, made to 
efficiently map to lower-level I/O syscalls while still providing a 
unified abstraction and being an instance of some general 
async-iteration protocol. Similarly, arrays are a specialized data 
structure, made to efficiently handle random indexed-access and 
sequential storage, while still being an instance of the general 
(synchronous) iteration protocol.


A more general overview of this entire space can be found in Kris 
Kowal’s [General Theory of Reactivity][gtor]. He explains how there's 
actually several representatives in each of the four quadrants of 
sync/async + singular/plural. (Or more generally, spatial/temporal + 
singular/plural.) As you might expect, the most-complicated quadrant 
(temporal + plural) has the most possible representatives, from async 
iterators to streams to observables to behaviors to signals.


As for what the general async iterable interface might look like, 
which streams would be a special case of (in the same way arrays are a 
special case of sync iterables), my favorite candidate at present is 
https://github.com/zenparsing/async-iteration/. It's a straightforward 
extension of the synchronous iterable interface, and matches with the 
GTOR's reasoning quite nicely. But, there's no committee consensus on 
this.


Just noting we haven't pushed for consensus either, we're still doing 
the hermenuetic spiral. I like Kevin Smith's proposal too, FWIW.


/be
You'll also notice that, similar to arrays, the more specialized type 
is being developed and shipped first (in response to a specific need 
of the platform), with its generalization following behind.


All of this, of course, doesn't change the fact that it's useful to 
distinguish between singular and plural data structures. You get many 
more guarantees with a singular data structure than you do with a 
plural---similarly to how you get more guarantees working with, say, a 
value of type number, than you do with a value of type any. These 
guarantees can be important for many things, from security invariants 
to simply being able to reason about the flow of your code. And it's 
also nice to be able to build one on top of the other, in the way 
streams are built on top of promises!


[gtor]: https://github.com/kriskowal/gtor/
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


RE: Promises vs Streams

2015-03-28 Thread Domenic Denicola
The same argument also implies that arrays are more powerful than scalar 
values, and we should e.g. never use a number when we could instead just use a 
single-element array with a number.

From: es-discuss [mailto:es-discuss-boun...@mozilla.org] On Behalf Of Boopathi 
Rajaa
Sent: Saturday, March 28, 2015 08:15
To: es-discuss@mozilla.org
Subject: Promises vs Streams

I feel this must have already been discussed but couldn't find any discussion 
threads, just trying to understand them better.

The basic doubt is that I feel promises are more like streams, and that streams 
are much more powerful than promises. With a promise you have a value or an 
exception, and with a stream, you have a list of values or an exception.

Why do we have both ? or more specifically, since we have both, when to use 
Promises and when to use Streams ? Whatever I imagine to be a Promise can be 
thought out to be solved by Streams, and sometimes whenever I use streams, it 
feels like I'm using similar API as Promises.

- Boopathi
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


RE: Promises vs Streams

2015-03-28 Thread Domenic Denicola
Seeing as how I just produced a completely redundant message by failing to read 
the other responses before firing off my own, let me try to redeem myself with 
some more-original content.

It’s also important to realize that streams are not the only 
asynchronous-plural primitive out there. My favorite analogy is “streams are to 
asynchronous iterables as arrays are to synchronous iterables.” That is, 
streams are a specialized data structure, made to efficiently map to 
lower-level I/O syscalls while still providing a unified abstraction and being 
an instance of some general async-iteration protocol. Similarly, arrays are a 
specialized data structure, made to efficiently handle random indexed-access 
and sequential storage, while still being an instance of the general 
(synchronous) iteration protocol.

A more general overview of this entire space can be found in Kris Kowal’s 
[General Theory of Reactivity][gtor]. He explains how there's actually several 
representatives in each of the four quadrants of sync/async + singular/plural. 
(Or more generally, spatial/temporal + singular/plural.) As you might expect, 
the most-complicated quadrant (temporal + plural) has the most possible 
representatives, from async iterators to streams to observables to behaviors to 
signals.

As for what the general async iterable interface might look like, which 
streams would be a special case of (in the same way arrays are a special case 
of sync iterables), my favorite candidate at present is 
https://github.com/zenparsing/async-iteration/. It's a straightforward 
extension of the synchronous iterable interface, and matches with the GTOR's 
reasoning quite nicely. But, there's no committee consensus on this. You'll 
also notice that, similar to arrays, the more specialized type is being 
developed and shipped first (in response to a specific need of the platform), 
with its generalization following behind.

All of this, of course, doesn't change the fact that it's useful to distinguish 
between singular and plural data structures. You get many more guarantees with 
a singular data structure than you do with a plural---similarly to how you get 
more guarantees working with, say, a value of type number, than you do with a 
value of type any. These guarantees can be important for many things, from 
security invariants to simply being able to reason about the flow of your code. 
And it's also nice to be able to build one on top of the other, in the way 
streams are built on top of promises!

[gtor]: https://github.com/kriskowal/gtor/
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Promises vs Streams

2015-03-28 Thread Anne van Kesteren
On Sat, Mar 28, 2015 at 1:14 PM, Boopathi Rajaa legend.r...@gmail.com wrote:
 Why do we have both?

Why do we have both values and arrays, not just the latter?


-- 
https://annevankesteren.nl/
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Promises vs Streams

2015-03-28 Thread Axel Rauschmayer
Synchronously, we have both normal (synchronous) function calls and iteration 
over a sequence of values (via `for-of` and iterators). It makes sense that we 
also should have two abstractions for asynchronous interaction.

 On 28 Mar 2015, at 13:14, Boopathi Rajaa legend.r...@gmail.com wrote:
 
 I feel this must have already been discussed but couldn't find any discussion 
 threads, just trying to understand them better.
 
 The basic doubt is that I feel promises are more like streams, and that 
 streams are much more powerful than promises. With a promise you have a value 
 or an exception, and with a stream, you have a list of values or an 
 exception. 
 
 Why do we have both ? or more specifically, since we have both, when to use 
 Promises and when to use Streams ? Whatever I imagine to be a Promise can be 
 thought out to be solved by Streams, and sometimes whenever I use streams, it 
 feels like I'm using similar API as Promises.
 
 - Boopathi
 ___
 es-discuss mailing list
 es-discuss@mozilla.org
 https://mail.mozilla.org/listinfo/es-discuss

-- 
Dr. Axel Rauschmayer
a...@rauschma.de
rauschma.de



___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Promises vs Streams

2015-03-28 Thread joe
Maybe the confusion stems from how Promises were used in ES5?  ES5 doesn't
support generators, so people ended up adding a sort of psuedo-generator
API to their promise APIs, but in reality the concepts solve different
problems?  FYI, python seems to use promises and event streams together in
its async libraries.

Joe

On Sat, Mar 28, 2015 at 8:20 AM, Anne van Kesteren ann...@annevk.nl wrote:

 On Sat, Mar 28, 2015 at 1:14 PM, Boopathi Rajaa legend.r...@gmail.com
 wrote:
  Why do we have both?

 Why do we have both values and arrays, not just the latter?


 --
 https://annevankesteren.nl/
 ___
 es-discuss mailing list
 es-discuss@mozilla.org
 https://mail.mozilla.org/listinfo/es-discuss

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Promises, the middle state : negociation

2014-05-15 Thread Tab Atkins Jr.
On Thu, May 15, 2014 at 11:33 AM, Michaël Rouges
michael.rou...@gmail.com wrote:
 Hi all,

 As I totally agree that a promise can only be resolved or rejected once ...
 so I think his behavior is perhaps too black or white.

 As IRL, when we receive a promise, we expect that the author makes every
 effort to resolve it, by any way.

 Progammatically, we can wish the same.

 By example, we can have :

 an error to ignore
 an error that requires to execute other operations leading to

 a rejection
 a continuation
 a retry

 To cover all these cases, in the current promises state, we can have (a
 quite) complex promises, easily solvable.

 My idea? the negociation, where the goal is to find a solution to resolve it
 (rejection reduction).

 For the promise fn argument, to add an optional negociate argument.

 ```
 promise = new Promise(function (resolve, reject, negociate) {
 // the promise body
 });
 ```

 An the related Promise.negociate method like :

 ```
 Promise.negociate = function negociate(resolve, reject, negociate, retry,
 value) {
 };
 ```

 That returns a promise, negociable too, where :

 resolve is shared with the original promise (that contains the negociate
 call) to continue the process
 reject is shared with the original promise (that contains the negociate
 call)
 negociate, it's own negociation, for multiple attempts/behaviors
 retry to recall the original promise fn argument (compliant with the
 promises concept, since our promise was neither rejected nor resolved, at
 this point)
 value (or values, I'm not sure) to pass some infos/tools that we need to
 take our decision, in the negociation process


 Lemme your advices. ;)

This is just normal promise chaining.  If you get a promise and want
to make *sure* it resolves in a particular way, just use .then() or
.catch() to create a new promise that handles things the way you want.

~TJ
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Re: Promises, the middle state : negociation

2014-05-15 Thread Michaël Rouges
I don't pretend that impossible to do with current promises.

I'm just saying that we can get a complexity that could be easily avoided.

And a catch/then doesn't allow to return in the first promise onFulfilled,
without embedded promises.

I think a practical example might better illustrate the thing.

Imagine, we have to check a data integrity, firstly internal, or from
external sources, if the internal data is corrupted.

The integrity controller is a foreign promisable controller , with a custom
hash method  a fingerprint... we can't touch it.


```
var foreignController;

foreignController = (function () {
var fingerPrint,
hash,
controller;

fingerPrint = 'aforeignfingerprint';

hash = function hash(data) {
// foreign ownmade hash calculator
};

controller = function controller(resolve, reject, negociate) {
var data,
isValid,
sources;

data = this.data;
isValid = fingerPrint === hash(data);

if (isValid) {
return resolve(data);
}

sources = this.sources;

if (sources.length) {
// not an error, we only remove that source
// and try with the next one
return negociate(sources.shift());
}

reject(new Error('No valid data found'));
};

return controller;
}());
```
Now, the data ownmade data checker :

```
var getDataSync,
onFulFilled,
onRejected,
onNegociated,
handler,
controller;

getDataSync function getDataSync(source) {
// data collector
};

onFulFilled = function onFulFilled(value) {
// valid data treatment
};

onRejected = function onRejected(reason) {
// no valid data found
};

onNegociated = function onNegociated(resolve, reject, negociate, retry,
value) {
var source;

source = this.sources[0];
this.data = getDataSync(source);

console.log('data source corrupted : ' + value);

retry();
};

handler = {
data: 'some data',
sources: ['internal', 'an.external.url', 'another.external.url', '...']
};

controller = foreignController.bind(handler);

new Promise(controller)
.then(onFulFilled, onRejected, onNegociated.bind(handler))
/* a lot of thens */;

```

Personnaly, I don't see how the current promises can solve it as simply.


Michaël Rouges - https://github.com/Lcfvs - @Lcfvs
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Re: Promises, the middle state : negociation

2014-05-15 Thread Calvin Metcalf
```
var sources = [internal, external1, external2];

function doStuff (e) {
   // likely check if it's the right kind of error;
   var url = sources.shift();
   if (typeof url === 'undefined) {
 return Promise.reject(new Error('out of sources'));
   }
   return get(url).then(check).catch(doStuff);
}
```


On Thu, May 15, 2014 at 10:52 AM, Michaël Rouges
michael.rou...@gmail.comwrote:

 I don't pretend that impossible to do with current promises.

 I'm just saying that we can get a complexity that could be easily avoided.

 And a catch/then doesn't allow to return in the first promise onFulfilled,
 without embedded promises.

 I think a practical example might better illustrate the thing.

 Imagine, we have to check a data integrity, firstly internal, or from
 external sources, if the internal data is corrupted.

 The integrity controller is a foreign promisable controller , with a
 custom hash method  a fingerprint... we can't touch it.


 ```
 var foreignController;

 foreignController = (function () {
 var fingerPrint,
 hash,
 controller;

 fingerPrint = 'aforeignfingerprint';

 hash = function hash(data) {
 // foreign ownmade hash calculator
 };

 controller = function controller(resolve, reject, negociate) {
 var data,
 isValid,
 sources;

 data = this.data;
 isValid = fingerPrint === hash(data);

 if (isValid) {
 return resolve(data);
 }

 sources = this.sources;

 if (sources.length) {
 // not an error, we only remove that source
 // and try with the next one
 return negociate(sources.shift());
 }

 reject(new Error('No valid data found'));
 };

 return controller;
 }());
 ```
 Now, the data ownmade data checker :

 ```
 var getDataSync,
 onFulFilled,
 onRejected,
 onNegociated,
 handler,
 controller;

 getDataSync function getDataSync(source) {
 // data collector
 };

 onFulFilled = function onFulFilled(value) {
 // valid data treatment
 };

 onRejected = function onRejected(reason) {
 // no valid data found
 };

 onNegociated = function onNegociated(resolve, reject, negociate, retry,
 value) {
 var source;

 source = this.sources[0];
 this.data = getDataSync(source);

 console.log('data source corrupted : ' + value);

 retry();
 };

 handler = {
 data: 'some data',
 sources: ['internal', 'an.external.url', 'another.external.url', '...']
 };

 controller = foreignController.bind(handler);

 new Promise(controller)
 .then(onFulFilled, onRejected, onNegociated.bind(handler))
 /* a lot of thens */;

 ```

 Personnaly, I don't see how the current promises can solve it as simply.


 Michaël Rouges - https://github.com/Lcfvs - @Lcfvs

 ___
 es-discuss mailing list
 es-discuss@mozilla.org
 https://mail.mozilla.org/listinfo/es-discuss




-- 
-Calvin W. Metcalf
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Promises and Decidability in Asynchronous Error Handling

2013-10-21 Thread K. Gadd
Requiring early registration prevents the use of futures as value
containers; i.e. kicking off an operation and storing the Future somewhere
so anyone can use it at a later date.

I agree that an improved error handling policy would be very, very good to
have, though.


On Mon, Oct 21, 2013 at 9:40 AM, Kevin Smith zenpars...@gmail.com wrote:

 A well-known problem with Promises, as implemented in various Javascript
 libraries, is that program errors are silenced by default.  Consider the
 following program, which simply makes an HTTP request and then prints out
 the HTTP response headers:

 fetchUri(http://someauthority.com/;).then(response = {
 for (let header of repsonse.heders) // Note the misspelling!
 console.log(header.key, header.value);
 });

 On line 2, the property headers is misspelled, which should cause the
 program to report an unhandled error.  Under the current Promises
 specification, however, the error will be silenced and the program will end
 happily with success.

 Various solutions have been proposed for dealing with this problem, such
 as:

 - Extending debugging tools so that unhandled rejections are visible
 through a specialized tab or view.

 - Using the garbage collector to determine when rejections can no longer
 be handled, and therefore constitute a program error.

 - Adding a `done` method to the promise type which propagates rejections
 as program errors.

 While each of these approaches provides a partial solution to the problem,
 they are ultimately inadequate because they do not address the underlying
 cause.

 The root cause of this issue is that, as currently specified, **the
 problem of determining whether a particular runtime error has an associated
 handler is Turing undecidable**.

 This is *not* a desirable property for an error handling mechanism to
 have, and it is not a design choice that can be reversed at a later date.

 In order to make error handling decidable, it is sufficient to require
 that an error handler must be attached to the promise *within a
 well-defined window*.  One such window would be the lifetime of the
 currently executing user call stack.

 The designers of Dart have made a similar decision with their Future API.
  In the following document, users are instructed to register error handlers
 early:


 https://www.dartlang.org/articles/futures-and-error-handling/#potential-problem-failing-to-register-error-handlers-early

 A quick search on StackOverflow relating to Futures and early error
 handling in Dart yielded no results.  This cursory evidence suggests that
 requiring early registration of error handlers is not a significant problem
 for Dart users.

 In my view, it would be a mistake to standardize the undecidable error
 handling model of current Promises design.

 Thanks,

 { Kevin }

 ___
 es-discuss mailing list
 es-discuss@mozilla.org
 https://mail.mozilla.org/listinfo/es-discuss


___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


RE: Promises and Decidability in Asynchronous Error Handling

2013-10-21 Thread Domenic Denicola
A well-known problem with loops, as implemented in various programming 
languages, is that infinite loops are silenced by default. Consider the 
following program, which simply adds some numbers in a loop:

```js
var sum = 0;
while (Math.random()  config.loopLimt) { // Note the misspelling!
  sum += Math.random();
}
```

On line two, the property loopLimit is misspelled, which should cause the 
program to report an infinite loop as the condition will never be true. Under 
the current programming language paradigm, however, the error will be silenced 
and the program will loop happily forever.

Various solutions have been proposed for dealing with this problem, such as:

- Extending debugging tools to allow some visibility into the code currently 
running in your program, through a specialized tab or view.

- Using CPU consumption to determine when a loop has locked up the program, and 
thus probably consistutes a program error.

- Adding a `safeWhile` construct to the language which ensures you cannot loop 
more than 64K times.

While each of these approaches provides a partial solution to the problem, they 
are ultimately inadequate because they do not address the underlying cause.

The root cause of this issue is that, as currently specified, **the problem of 
deciding whether a particular `while` loop terminates is Turing undecidable**.

This is *not* a desirable property for a looping mechanism to have, and it is 
not a design choice that can be reversed at a later date.

In order to make loop termination decidable, it is sufficient to require that 
the loop condition must be become true *within a well-defined window*. One such 
window would be the current second.

The designers of regular expressions have made a similar decision with their 
string matching API. A quick search on StackOverflow relating to loops and 
infinite loops in regular expressions yielded no results. This cursory 
evidence suggests that requiring looping constructs to be finite is not a 
significant problem for regular expression users.

In my view, it would be a mistake to standardize the undecidable looping model 
of the current `while` loop design.

---

Which is all to say, being unable to Turing-decide how a programming construct 
will work is not a particularly noteworthy disqualifier, and indeed opens up 
extremely powerful features in most cases. I believe the same is true of the 
current promise design.

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Promises and Decidability in Asynchronous Error Handling

2013-10-21 Thread Andrea Giammarchi
wouldn't events better suit and better solve the problem ?

fetchUri(http://someauthority.com/;).on('load', response = {
repsonse.heders() });

at least this is how it works in eddy.js and I've never had silent errors

in current specs would be an addEventListener() within the XHR object





On Mon, Oct 21, 2013 at 12:26 PM, K. Gadd k...@luminance.org wrote:

 Requiring early registration prevents the use of futures as value
 containers; i.e. kicking off an operation and storing the Future somewhere
 so anyone can use it at a later date.

 I agree that an improved error handling policy would be very, very good to
 have, though.


 On Mon, Oct 21, 2013 at 9:40 AM, Kevin Smith zenpars...@gmail.com wrote:

 A well-known problem with Promises, as implemented in various Javascript
 libraries, is that program errors are silenced by default.  Consider the
 following program, which simply makes an HTTP request and then prints out
 the HTTP response headers:

 fetchUri(http://someauthority.com/;).then(response = {
 for (let header of repsonse.heders) // Note the misspelling!
 console.log(header.key, header.value);
 });

 On line 2, the property headers is misspelled, which should cause the
 program to report an unhandled error.  Under the current Promises
 specification, however, the error will be silenced and the program will end
 happily with success.

 Various solutions have been proposed for dealing with this problem, such
 as:

 - Extending debugging tools so that unhandled rejections are visible
 through a specialized tab or view.

 - Using the garbage collector to determine when rejections can no longer
 be handled, and therefore constitute a program error.

 - Adding a `done` method to the promise type which propagates rejections
 as program errors.

 While each of these approaches provides a partial solution to the
 problem, they are ultimately inadequate because they do not address the
 underlying cause.

 The root cause of this issue is that, as currently specified, **the
 problem of determining whether a particular runtime error has an associated
 handler is Turing undecidable**.

 This is *not* a desirable property for an error handling mechanism to
 have, and it is not a design choice that can be reversed at a later date.

 In order to make error handling decidable, it is sufficient to require
 that an error handler must be attached to the promise *within a
 well-defined window*.  One such window would be the lifetime of the
 currently executing user call stack.

 The designers of Dart have made a similar decision with their Future API.
  In the following document, users are instructed to register error handlers
 early:


 https://www.dartlang.org/articles/futures-and-error-handling/#potential-problem-failing-to-register-error-handlers-early

 A quick search on StackOverflow relating to Futures and early error
 handling in Dart yielded no results.  This cursory evidence suggests that
 requiring early registration of error handlers is not a significant problem
 for Dart users.

 In my view, it would be a mistake to standardize the undecidable error
 handling model of current Promises design.

 Thanks,

 { Kevin }

 ___
 es-discuss mailing list
 es-discuss@mozilla.org
 https://mail.mozilla.org/listinfo/es-discuss



 ___
 es-discuss mailing list
 es-discuss@mozilla.org
 https://mail.mozilla.org/listinfo/es-discuss


___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Promises and Decidability in Asynchronous Error Handling

2013-10-21 Thread Kevin Smith
 Requiring early registration prevents the use of futures as value
 containers; i.e. kicking off an operation and storing the Future somewhere
 so anyone can use it at a later date.


One can always do that, provided that you register an error handler *before
your call stack is cleared*.

{ Kevin }
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Promises and Decidability in Asynchronous Error Handling

2013-10-21 Thread Kevin Smith
Domenic,

First, your caricature of my position is patently ridiculous.

Second, can you or someone else offer a clear use case which requires
undecidable error handling semantics?  I have asked for examples several
times and so far I haven't seen anything convincing.  Usually that
indicates that the supposed use case is exaggerated if not fictional.

{ Kevin }
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


RE: Promises and Decidability in Asynchronous Error Handling

2013-10-21 Thread Benjamin (Inglor) Gruenbaum
I don't think that's the same thing at all.

Detecting an infinite loop is _extremely_ hard at most cases (and of course
impossible at others. However instead of discussing the halting problem, I
think what's bothering this guy is that `.then` does not throw an error
when an error occurs within it even if that error is completely unhandled
by the promise flow.

Different libraries that implement promises handle errors differently. For
example bluebird[0] writes the stack trace to stderr (or console.error) if
the rejection is unhandled by the start of the second turn. I quote: your
quote doesn't work as expected and you open console and see a stack trace :
nice.

On that topic, I'd appreciate some reading on promises being added to the
spec of the language (since when does the ES language spec even deal with
concurrency? I thought that was a part of the host environment.

[0]: https://github.com/petkaantonov/bluebird#error-handling

Domenic Denicola dome...@domenicdenicola.com wrote
 A well-known problem with loops, as implemented in various programming
languages, is that infinite loops are silenced by default. Consider the
following program, which simply adds some numbers in a loop:
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


RE: Promises and Decidability in Asynchronous Error Handling

2013-10-21 Thread Domenic Denicola
You have been given examples in several previous conversations, but have chosen 
to not find them convincing. I (and others) tire of rehashing this argument 
with you monthly.

I instead responded to the novel content of your post, which was some sort of 
attempt to claim that a language feature allowing Turing-undecidable control 
flow means it is not a desirable language feature. Now that I have shown how 
patently ridiculous such a claim is, I do not feel a need to switch the 
conversation back to your usual line of inquiry. Perhaps others will take you 
up on it.

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Promises and Decidability in Asynchronous Error Handling

2013-10-21 Thread Andrea Giammarchi
Kevin I have no idea which library you are using but if you do this:

```
fetchUri(http://someauthority.com/;).then(response = {
for (let header of repsonse.heders) // Note the misspelling!
console.log(header.key, header.value);
}).then(Object, function error(e) {
  console.err(e);
});
```

Wouldn't that solve your problem?

Another thing worth trying is a generic window.on('error') handler ?
Wouldn't that notify you ? That does not solve the broken flow but it
should be an exit point to at least debug or notify problems, am I
missing/misunderstanding something?

Thanks for any extra hint, apologies if I cannot help further :-/




On Mon, Oct 21, 2013 at 1:39 PM, Domenic Denicola 
dome...@domenicdenicola.com wrote:

 You have been given examples in several previous conversations, but have
 chosen to not find them convincing. I (and others) tire of rehashing this
 argument with you monthly.

 I instead responded to the novel content of your post, which was some sort
 of attempt to claim that a language feature allowing Turing-undecidable
 control flow means it is not a desirable language feature. Now that I have
 shown how patently ridiculous such a claim is, I do not feel a need to
 switch the conversation back to your usual line of inquiry. Perhaps others
 will take you up on it.

 ___
 es-discuss mailing list
 es-discuss@mozilla.org
 https://mail.mozilla.org/listinfo/es-discuss

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


RE: Promises and Decidability in Asynchronous Error Handling

2013-10-21 Thread Nathan Wall
+1

Nathan


Domenic Denicola wrote:
 A well-known problem with loops, as implemented in various programming 
 languages, is that infinite loops are silenced by default. Consider the 
 following program, which simply adds some numbers in a loop:

 ```js
 var sum = 0;
 while (Math.random()  config.loopLimt) { // Note the misspelling!
 sum += Math.random();
 }
 ```

 On line two, the property loopLimit is misspelled, which should cause the 
 program to report an infinite loop as the condition will never be true. Under 
 the current programming language paradigm, however, the error will be 
 silenced and the program will loop happily forever.

 Various solutions have been proposed for dealing with this problem, such as:

 - Extending debugging tools to allow some visibility into the code currently 
 running in your program, through a specialized tab or view.

 - Using CPU consumption to determine when a loop has locked up the program, 
 and thus probably consistutes a program error.

 - Adding a `safeWhile` construct to the language which ensures you cannot 
 loop more than 64K times.

 While each of these approaches provides a partial solution to the problem, 
 they are ultimately inadequate because they do not address the underlying 
 cause.

 The root cause of this issue is that, as currently specified, **the problem 
 of deciding whether a particular `while` loop terminates is Turing 
 undecidable**.

 This is *not* a desirable property for a looping mechanism to have, and it is 
 not a design choice that can be reversed at a later date.

 In order to make loop termination decidable, it is sufficient to require that 
 the loop condition must be become true *within a well-defined window*. One 
 such window would be the current second.

 The designers of regular expressions have made a similar decision with their 
 string matching API. A quick search on StackOverflow relating to loops and 
 infinite loops in regular expressions yielded no results. This cursory 
 evidence suggests that requiring looping constructs to be finite is not a 
 significant problem for regular expression users.

 In my view, it would be a mistake to standardize the undecidable looping 
 model of the current `while` loop design.

 ---

 Which is all to say, being unable to Turing-decide how a programming 
 construct will work is not a particularly noteworthy disqualifier, and indeed 
 opens up extremely powerful features in most cases. I believe the same is 
 true of the current promise design.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Promises and Decidability in Asynchronous Error Handling

2013-10-21 Thread Kevin Smith
It has been shown that delayed registration, in general, is useful.
 However, it has not been demonstrated that delayed registration of a
primary error handler is necessary.

If use cases have been provided, then please provide links.  Otherwise,
let's not use ad hominem in place of logic.

{ Kevin }
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Promises: final steps

2013-09-08 Thread Aymeric Vitte
I have not read everything about the promise/future/re-promise subject 
but what I have read seems to show that everyone has a personal 
understanding of the thing.


So please see 
http://lists.w3.org/Archives/Public/public-webcrypto/2013Sep/0003.html , 
code example that I have written for WebCrypto (ie real working case not 
using WebCrypto rewritten with WebCrypto promises), as explained I am 
using 'done' despite of the fact that it might be removed, because I 
don't see why I should use 'then' if I am not chaining anything.


As explained again, the example shows maybe that promises here are a 
kind of artifice, until other APIs implement promises.


How should I write this without 'done'?

Regards

Aymeric

Le 08/09/2013 19:06, Anne van Kesteren a écrit :

(Added back the other lists.)

On Fri, Sep 6, 2013 at 3:58 AM, Brendan Eich bren...@secure.meer.net wrote:

Let's put done back in. It's the right thing.

Given what has been said thus far
https://github.com/domenic/promises-unwrapping/issues/19 my
inclination is still to leave it out initially and give a version
without done() six months to a year to mature. Not having done() can
make promises harder to debug in the short term, but adding done() is
trivial to do later. And given the lack of native promise
implementations to date there's no way for us to test the done()-less
design without trying it first.




--
jCore
Email :  avi...@jcore.fr
Peersm : http://www.peersm.com
iAnonym : http://www.ianonym.com
node-Tor : https://www.github.com/Ayms/node-Tor
GitHub : https://www.github.com/Ayms
Web :www.jcore.fr
Extract Widget Mobile : www.extractwidget.com
BlimpMe! : www.blimpme.com

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Subject=Re: Re: Promises: final steps

2013-09-08 Thread e...@evan-borden.com
 Tasks in C# throw the recorded exception when the Task is finalized by the
 GC if it hasn't been handled by user code, though I don't know if something
 similar could be supported for ES7 Promises nor whether or not that makes
 sense for ES7 promises either.


This is an interesting avenue. The problem is the chain-ability and value
like nature of promises. It is difficult to truly determine that the error
has not been handled. The error may be handled later down the chain or in a
separate context. When is the decision made that the error has not been
handled? Is the error determined not handled on garbage collection? Is
there a ttl on error handling? This is a curious case, but if feasible
would be the most elegant option.

rejectedPromise = promise.then(func)
.then(func) //Error swallowed
.then(func);

setTimeout(function () {
rejectedPromise.then(func, errorHandler); //Finally handle it
}, 2);
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


RE: Subject=Re: Re: Promises: final steps

2013-09-08 Thread Domenic Denicola
As your example points out, being unhandled is a changing state. All rejections 
start out unhandled, but can become handled either immediately or in a later 
turn. The only time in which you can be sure a rejection is unhandled is when 
the promise is garbage collected, which may never happen (but usually does).

From: es-discuss [mailto:es-discuss-boun...@mozilla.org] On Behalf Of 
e...@evan-borden.com
Sent: Sunday, September 8, 2013 20:25
To: To=; es-discuss@mozilla.org
Subject: Subject=Re: Re: Promises: final steps


Tasks in C# throw the recorded exception when the Task is finalized by the GC 
if it hasn't been handled by user code, though I don't know if something 
similar could be supported for ES7 Promises nor whether or not that makes sense 
for ES7 promises either.

This is an interesting avenue. The problem is the chain-ability and value like 
nature of promises. It is difficult to truly determine that the error has not 
been handled. The error may be handled later down the chain or in a separate 
context. When is the decision made that the error has not been handled? Is the 
error determined not handled on garbage collection? Is there a ttl on error 
handling? This is a curious case, but if feasible would be the most elegant 
option.

rejectedPromise = promise.then(func)
.then(func) //Error swallowed
.then(func);

setTimeout(function () {
rejectedPromise.then(func, errorHandler); //Finally handle it
}, 2);

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Promises: final steps

2013-09-05 Thread medikoo
While I can agree that monitor feature (that's proposed instead of `done`)
has some benefits, I see it only as an aid for developers that are
inexperienced with promises, or as a fallback for those experienced.
It looks more as a smart add-on, which to be complete can't be implemented
in plain JavaScript, is implementation specific and should be treated as
optional.

What's more important it still doesn't provide developer with full control
of error handling on JavaScript level and that can be achieved only with
`done`.

I have problems understanding why such complex and not natural feature is
favored over something so simple and straightforward.




--
View this message in context: 
http://mozilla.6506.n7.nabble.com/Promises-final-steps-tp290303p290518.html
Sent from the Mozilla - ECMAScript 4 discussion mailing list archive at 
Nabble.com.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Promises: final steps

2013-09-05 Thread Kevin Smith
Hi Kris,

Thanks for the details!  This gives us an idea what a promise monitoring
feature might look like in a browser's developer tools.  I think such a
feature would be really cool, but I believe that promise-using programs
ought to be debuggable using just a console.  Indeed, for a non-GUI
embedding like Node, they *must* be debuggable using just a console.

I don't think we should ship an API that is not debuggable using a console.
 However, I'm *not* in favor of a `done` method on the Promise prototype
because of functional overlap with `then`.

Another option is a static method which takes a promise and throws
rejections ala done:

   Promise.throw(makeSomePromise.then(...));

Personally, I consider it a shame that promise libraries punted on the
distinction between rejections and program errors, but I suppose it's too
late to go there.

{ Kevin }
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


RE: Promises: final steps

2013-09-05 Thread Domenic Denicola
From: Kevin Smith [zenpars...@gmail.com]

 Indeed, for a non-GUI embedding like Node, they *must* be debuggable using 
 just a console.

This is an important point. A provisional idea that preserves our desire to not 
introduce new features to promises themselves, requiring user choice at 
authoring time, might be some kind of `console.unhandledRejections()` function 
which returns you a snapshot of the current unhandled rejections bucket.

 Another option is a static method which takes a promise and throws rejections 
 ala done:

 ```js
 Promise.throw(makeSomePromise.then(...));
 ```

I find these kind of things confusing. RSVP did something similar, introducing

```js
RSVP.rethrow = r = setImmediate(() = throw r);
```

so that you write

```js
somePromise.then(...).catch(RSVP.rethrow); // actually RSVP uses `fail`.
```

It's not clear to me why this, or your `Promise.throw`, is better than

```js
somePromise.done(...)
// or
somePromise.then(...).done()
```

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Promises: final steps

2013-09-05 Thread Kevin Smith
 It's not clear to me why this, or your `Promise.throw`, is better than

 ```js
 somePromise.done(...)
 // or
 somePromise.then(...).done()
 ```


Not *much* better, I'd say, but IMO a `done` method which accepts a
callback overlaps too much with `then`, and a `done` method without a
callback just looks like a wart in need of removal.  : )

Visually, to me, wrapping beats capping.  But that's just me.

In the end, I like neither wrapping nor capping.  In my own work I've
preferred to define conditions under which certain rejections are
interpreted as program errors, thereby avoiding the wrapping/capping issue
entirely.  (I can elaborate if anyone's interested.)

{ Kevin }
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Promises: final steps

2013-09-05 Thread Mark Miller
On Thu, Sep 5, 2013 at 12:04 PM, Domenic Denicola 
dome...@domenicdenicola.com wrote:

 From: Kevin Smith [zenpars...@gmail.com]

  Indeed, for a non-GUI embedding like Node, they *must* be debuggable
 using just a console.

 This is an important point. A provisional idea that preserves our desire
 to not introduce new features to promises themselves, requiring user choice
 at authoring time, might be some kind of `console.unhandledRejections()`
 function which returns you a snapshot of the current unhandled rejections
 bucket.


That would be a global communications channel.




  Another option is a static method which takes a promise and throws
 rejections ala done:
 
  ```js
  Promise.throw(makeSomePromise.then(...));
  ```

 I find these kind of things confusing. RSVP did something similar,
 introducing

 ```js
 RSVP.rethrow = r = setImmediate(() = throw r);
 ```

 so that you write

 ```js
 somePromise.then(...).catch(RSVP.rethrow); // actually RSVP uses `fail`.
 ```

 It's not clear to me why this, or your `Promise.throw`, is better than

 ```js
 somePromise.done(...)
 // or
 somePromise.then(...).done()
 ```


As I said, I think we will eventually add something that provides this or
similar functionality. But it does not need to be added to the subset this
repository seeks to define -- for the immediate needs of DOM. Since the
topic of this thread is final steps, I'm just trying to be clear in this
context that this .done-ish issue is after these final steps.

This is the kind of issue that is best decided after more experience with
several of these debugging aids, in both browser and server. So we should
of course continue to discuss these options on es-discuss regarding ES7.
Also, we won't have Weak References until ES7, and that bears on this
discussion and expected experience. FWIW, so far, I still like .done better
than the suggested alternatives.



 ___
 es-discuss mailing list
 es-discuss@mozilla.org
 https://mail.mozilla.org/listinfo/es-discuss




-- 
Text by me above is hereby placed in the public domain

  Cheers,
  --MarkM
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Promises: final steps

2013-09-05 Thread Mark Miller
On Thu, Sep 5, 2013 at 1:21 PM, Kevin Smith zenpars...@gmail.com wrote:


 It's not clear to me why this, or your `Promise.throw`, is better than

 ```js
 somePromise.done(...)
 // or
 somePromise.then(...).done()
 ```


 Not *much* better, I'd say, but IMO a `done` method which accepts a
 callback overlaps too much with `then`, and a `done` method without a
 callback just looks like a wart in need of removal.  : )

 Visually, to me, wrapping beats capping.  But that's just me.

 In the end, I like neither wrapping nor capping.  In my own work I've
 preferred to define conditions under which certain rejections are
 interpreted as program errors, thereby avoiding the wrapping/capping issue
 entirely.  (I can elaborate if anyone's interested.)


Please do.




 { Kevin }

 ___
 es-discuss mailing list
 es-discuss@mozilla.org
 https://mail.mozilla.org/listinfo/es-discuss




-- 
  Cheers,
  --MarkM
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


RE: Promises: final steps

2013-09-05 Thread Ron Buckton
Tasks in C# throw the recorded exception when the Task is finalized by the GC 
if it hasn't been handled by user code, though I don't know if something 
similar could be supported for ES7 Promises nor whether or not that makes sense 
for ES7 promises either.

Having Promise rejections hold on to unhandled rejections can be mitigated 
either with eventual language support around Promises (either an 
async/await-style operator, or the ! operator in the strawman) or through a 
userland approach by way of trampoline functions. In the C# world with 
async/await, exceptions are thrown at the site of the await keyword when the 
operand becomes Faulted. In general this alleviates many of the issues around 
Tasks swallowing exceptions, although there are still a few cases where you 
have to take care around exception handling (e.g. an async method that returns 
`void` rather than `Task` or `TaskT`, as it cannot be awaited). 

Promises in the short-term may have some deficiencies until there is a syntax 
defined for asynchronous functions. That said, I'm fine with not having 
`Promise#done`, as useful as it is, as long as there is a reliable and well 
defined mechanism to raise the rejection to the host if needed (outside of 
reaching out to setImmediate to throw the exception, as it may not be obvious 
to consumers of the Promise API).

Ron

 -Original Message-
 From: es-discuss [mailto:es-discuss-boun...@mozilla.org] On Behalf Of
 medikoo
 Sent: Thursday, September 5, 2013 2:46 AM
 To: es-discuss@mozilla.org
 Subject: Re: Promises: final steps
 
 While I can agree that monitor feature (that's proposed instead of `done`) 
 has
 some benefits, I see it only as an aid for developers that are inexperienced 
 with
 promises, or as a fallback for those experienced.
 It looks more as a smart add-on, which to be complete can't be implemented in
 plain JavaScript, is implementation specific and should be treated as 
 optional.
 
 What's more important it still doesn't provide developer with full control of
 error handling on JavaScript level and that can be achieved only with `done`.
 
 I have problems understanding why such complex and not natural feature is
 favored over something so simple and straightforward.
 
 
 
 
 --
 View this message in context: http://mozilla.6506.n7.nabble.com/Promises-
 final-steps-tp290303p290518.html
 Sent from the Mozilla - ECMAScript 4 discussion mailing list archive at
 Nabble.com.
 ___
 es-discuss mailing list
 es-discuss@mozilla.org
 https://mail.mozilla.org/listinfo/es-discuss
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Promises: final steps

2013-09-04 Thread Kevin Smith
This looks like good work.  I like the name cast in particular, as I can
imagine a future casting operator which provides sugar for the cast
function defined on a constructor.

The only concern I have is over error-swallowing.  What's the approach for
this minimal API?

{ Kevin }
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Promises: final steps

2013-09-04 Thread Tab Atkins Jr.
On Wed, Sep 4, 2013 at 7:34 AM, Kevin Smith zenpars...@gmail.com wrote:
 This looks like good work.  I like the name cast in particular, as I can
 imagine a future casting operator which provides sugar for the cast function
 defined on a constructor.

 The only concern I have is over error-swallowing.  What's the approach for
 this minimal API?

As far as I know, the current plan is still that devtools should
handle swallowed exceptions, since we got rid of .done() some time
ago.  Plans may have changed without me knowing, though!

~TJ
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Promises: final steps

2013-09-04 Thread Kevin Smith
 As far as I know, the current plan is still that devtools should
 handle swallowed exceptions, since we got rid of .done() some time
 ago.  Plans may have changed without me knowing, though!

 ~TJ


I'd be interested in more detail since I think this will be an important
usability issue.  Are any of the various devtool efforts currently
implementing or planning such a feature?

{ Kevin }
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Promises: final steps

2013-09-04 Thread Kris Kowal
My colleagues and I are working on an extension for Chrome Web Inspector
that can communicate with promise libraries, particularly Q, over the
window message port. The tool, which will be renamed and rewritten before
it is ready for general use, adds a Promises tab to Web Inspector that
shows all currently pending and unhandled asynchronous errors, as well as
stack traces for both, and also progress information, albeit determinate,
indeterminate, or indeterminate but lively. There is a video accompanying
for demonstration.

https://github.com/montagejs/continuum

https://www.dropbox.com/s/2h68ax9j5mj7i6c/continuum.mov

The promise client broadcasts when a promise is deferred, when a deferred
promise is resolved, when a deferred promise makes progress (through the
`deferred.notify` interface), when a fulfilled promise is created, when a
rejected promise is created, and when a rejection is handled. As such, the
inspector can reconstruct whatever portion of the program’s promise history
it elects to retain.

In time, I intend to formalize a protocol. Ideally this system would be
useful for both “primordial” and library promises, and combinations of
both. Of course, any assistance would be valuable.

Also, ideally this would approach the functionality available to Causeway
and perhaps even *become* a manifestation of Causeway.

https://code.google.com/p/causeway/wiki/CausewayIntroduction

It would certainly be possible to show promises in multiple contexts,
including cross-origin iframes, and even show time sequence / Stevens
graphs for message passing between promises in multiple JavaScript
contexts, when promises are used as proxies for remote objects through a
facility like Q-Connection

https://github.com/kriskowal/q-connection

Kris Kowal
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Promises: final steps

2013-09-03 Thread Tab Atkins Jr.
On Tue, Sep 3, 2013 at 6:37 AM, Anne van Kesteren ann...@annevk.nl wrote:
 As many of you hopefully know, we're trying to nail down the design of
 promises in JavaScript so we can declare consensus on it and start
 shipping it in implementations. If you're interested in the
 particulars I strongly recommend reading through
 https://github.com/domenic/promises-unwrapping/blob/master/README.md
 and partaking in the
 https://github.com/domenic/promises-unwrapping/issues discussion. The
 next TC39 is coming close and this really needs to be resolved (not
 settled!) by then as there are many APIs relying on promises now.

 Eg in https://github.com/domenic/promises-unwrapping/issues/8 we
 decided on Promise.cast() as IsPromise(x) ? x : Promise.resolve(x).

 https://github.com/domenic/promises-unwrapping/issues/18 suggests
 adding Promise.prototype.finally() and
 https://github.com/domenic/promises-unwrapping/issues/13 discusses
 which convenience methods we should add in the first iteration.

 I suggest we focus on the minimal subset that works (which I know is
 different for people, but let's aim for consensus) and then iterate
 again after we have a couple of implementations out there.

I'm fine with the subset defined in Domenic's spec - it's compatible
with what we've discussed, and is easy to extend into the flatMap
semantics I want.

I've commented on the issue threads in github.

~TJ
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


RE: Promises Consensus

2013-08-19 Thread Domenic Denicola
From: Mark S. Miller [erig...@google.com]


 No. Assuming that p and q are both promises and that q is pending, p is 
 resolved to q when either p adopts q or p accepts q. From the .then 
 perspective these are the same, so we'd say p follows q or p is resolved to 
 q. In neither care would p.then fire until q is settled (fulfilled or 
 rejected). However, there's an operational difference between p adopts q 
 and p accepts q at the .flatMap level: p adopts q does not fire p.flapMap. 
 p accepts q does fire p.flatMap with q as the acceptance value.

After being confused on this point for a while, I hashed it out with Tab over 
IRC (thanks Tab!) and thought I'd share my moment of enlightenment with all 
involved.

```js
var foreverPending = new Promise(() = {});

var notAcceptedAndNotResolved = Promise.resolve(foreverPending);
var acceptedButNotResolved = Promise.fulfill(foreverPending);

// Neither of them are fulfilled, so the distinction doesn't matter for `then` 
usage.
notAcceptedAndNotResolved.then(() = console.log(this will never happen (never 
fulfilled)));
acceptedButNotResolved.then(() = console.log(this will never happen (never 
fulfilled)));

// But it matters for `flatMap` usage.
notAcceptedAndNotResolved.flatMap(() = console.log(this will never happen 
(never accepted)));
acceptedButNotResolved.flatMap(() = console.log(this *will* happen));
```


___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


RE: Promises Consensus

2013-08-19 Thread Domenic Denicola
Er, replace `notAcceptedAndNotResolved` with `resolvedButNotAccepted`. X_x
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Promises Consensus with /A+ terminology

2013-08-13 Thread Anne van Kesteren
On Fri, Aug 2, 2013 at 4:58 PM, Anne van Kesteren ann...@annevk.nl wrote:
 On Thu, Aug 1, 2013 at 8:25 PM, Tab Atkins Jr. jackalm...@gmail.com wrote:
 On Thu, Aug 1, 2013 at 11:27 AM, Mark S. Miller erig...@google.com wrote:
 For #2, since whatever DOM does quickly becomes a compat constraint on all
 future decisions, DOM should take the minimum subset of #1 which actually
 meets their short term needs. I leave it to those who understand those needs
 to argue about what these are.

 Unfortunately, the thenable question still impinges on the minimum subset. :/

 It seems there might be consensus on that now? It just seems safer and
 loads simpler to start out with deploying a subset that's more
 commonly agreed upon.

This remained unanswered for some reason. Promises are spreading like
wildfire through Gecko and B2G now. Chrome is implementing them.
Getting the details nailed down, or at least agreement on the /A+
subset, and then record them in http://dom.spec.whatwg.org/ as a start
would be great.


-- 
http://annevankesteren.nl/
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Promises Consensus

2013-08-02 Thread Claude Pache

Le 1 août 2013 à 00:53, Claude Pache claude.pa...@gmail.com a écrit :

 
 
 Le 31 juil. 2013 à 20:23, Tab Atkins Jr. jackalm...@gmail.com a écrit :
 
 
 The first issue still up for community discussion involves the
 definition of promise-like.
 
 We'd like the definition to be: (a) a Promise or subtype, or (b) a
 branded non-Promise (with the branding done via Symbol or similar).
 Promises/A+ wants the branding to be done via a method named then
 (the thenable concept).
 
 This, unfortunately, goes directly against TC39 practices in a number
 of other areas, such as iterators, where we don't want short string
 names as branding due to the possibility of collision.  (In the case
 of then, collision isn't a possibility, it's a certainty - we *know*
 there are libraries out there today that put a then method on their
 objects without referring to Promises.)  Thoughts?
 
 I suggest an @@isPromise builtin symbol, which works the same way as 
 @@isRegExp in the ES6 spec [1]: An object is reputed to be a promise if and 
 only if it has a property (either own or inherited) named @@isPromise. And 
 `Promise.prototype` has initially an @@isPromise own property, so that 
 instances of subclasses of `Promise` are recognised as promises.
 
 (With this solution, you have not to choose between subclassing or branding, 
 but you have the both. :-) )
 
 —Claude
 
 [1] search the occurrences of @@isRegExp in: 
 http://people.mozilla.org/~jorendorff/es6-draft.html
 

One more idea: a `Promise.register` function, which takes a class (i.e. a 
constructor) `C` as argument, and whose purpose is to declare that instances of 
`C` are to be treated as promises.

Concretely, if the @@isPromise design is retained, that function can be 
implemented as following:
```
Promise.register = function(C) {
C.prototype[@@isPromise] = true
}
```
But the trick with the symbol is an implementation detail.

—Claude



___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Promises Consensus with /A+ terminology

2013-08-02 Thread Anne van Kesteren
On Thu, Aug 1, 2013 at 8:25 PM, Tab Atkins Jr. jackalm...@gmail.com wrote:
 On Thu, Aug 1, 2013 at 11:27 AM, Mark S. Miller erig...@google.com wrote:
 For #2, since whatever DOM does quickly becomes a compat constraint on all
 future decisions, DOM should take the minimum subset of #1 which actually
 meets their short term needs. I leave it to those who understand those needs
 to argue about what these are.

 Unfortunately, the thenable question still impinges on the minimum subset. :/

It seems there might be consensus on that now? It just seems safer and
loads simpler to start out with deploying a subset that's more
commonly agreed upon.


-- 
http://annevankesteren.nl/
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Promises Consensus with /A+ terminology

2013-08-02 Thread David Bruant

Le 01/08/2013 20:27, Mark S. Miller a écrit :
whatever DOM does quickly becomes a compat constraint on all future 
decisions

(was the comma omitted on purpose? ;-) )
This also means that if there is a delta between the agreement and the 
implementation, we'll have yet another de facto standard. There are two 
ways in which this can happen:

* misunderstanding of intent
* misexpression of (even perfectly-)understood intent.

1) What should tc39 do quickly, to unblock the DOM's need for promises 
and avoid a design fork?

I apologize for being annoyingly insistent with this, but: tests.
An unwanted de facto standard is a de facto design fork.

I believe that to a large extent, the risk of both misunderstanding of 
intent and misexpression understood intent would be largely reduced by a 
test suite.


The people who (will) implement this feature aren't necessarily the ones 
involved in this, sometimes very subtle, discussion. I believe fewer 
information would be lost if the latters formalized their agreement in 
tests for the formers to implement against.


David

[1] https://bugzilla.mozilla.org/show_bug.cgi?id=856410
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Promises Consensus with /A+ terminology

2013-08-02 Thread Brendan Eich

David Bruant wrote:
I believe that to a large extent, the risk of both misunderstanding of 
intent and misexpression understood intent would be largely reduced by 
a test suite.


+∞

/be
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


RE: Promises Consensus with /A+ terminology

2013-08-02 Thread Domenic Denicola
From: Mark S. Miller [erig...@google.com]

 A good start would be to convert 
 https://github.com/promises-aplus/promises-tests to test262 form, extending 
 test262 in the process in order to accommodate async testing. Any volunteers?

If someone does the latter (preferably with a simple Mocha-like `done()` 
facility), I will happily do the former. I imagine there might be licensing 
issues with non-Ecma members; would that still be the case for code licensed 
under the WTFPL?

The only divergence between DOM promises and Promises/A+ so far are:

1. The handling of non-`undefined`, non-function arguments, which Promises/A+ 
mandates must be ignored while DOM Promises mandate must throw a synchronous 
`TypeError`. (This is a spec bug; it should result in an asynchronous 
`TypeError` rejection.)
2. DOM Promises requires `onFulfilled` and `onRejected` to be called as if they 
were methods of the promise itself, whereas Promises/A+ requires they be called 
as functions.
3. DOM Promises mandates an infinite loop for the code `const q = 
fulfilledPromise.then(() = fulfilledPromise)`, whereas Promises/A+ mandates 
that `q` be rejected with a `TypeError`.
4. DOM Promises mandates an infinite loop for the code `const q1 = 
fulfilledPromise.then(() = q2); const q2 = fulfilledPromise.then(() = q1)`, 
whereas Promises/A+ allows (but does not require) that implementations reject 
`q1` and `q2` with a `TypeError`.

Of these, 1 I am ambivalent on, 2 I think was a very strange mistake, and 3 and 
4 feel like oversights. But none of them are a big deal.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Promises Consensus with /A+ terminology

2013-08-02 Thread Mark Miller
On Fri, Aug 2, 2013 at 2:28 PM, Domenic Denicola 
dome...@domenicdenicola.com wrote:

 From: Mark S. Miller [erig...@google.com]

  A good start would be to convert
 https://github.com/promises-aplus/promises-tests to test262 form,
 extending test262 in the process in order to accommodate async testing. Any
 volunteers?

 If someone does the latter (preferably with a simple Mocha-like `done()`
 facility), I will happily do the former. I imagine there might be licensing
 issues with non-Ecma members; would that still be the case for code
 licensed under the WTFPL?


Damn. I'm glad you raised this. Yes, there are issues. I don't know what
they are. Would someone more knowledgeable of this minefield like to
answer? Thanks.




 The only divergence between DOM promises and Promises/A+ so far are:

 1. The handling of non-`undefined`, non-function arguments, which
 Promises/A+ mandates must be ignored while DOM Promises mandate must throw
 a synchronous `TypeError`. (This is a spec bug; it should result in an
 asynchronous `TypeError` rejection.)
 2. DOM Promises requires `onFulfilled` and `onRejected` to be called as if
 they were methods of the promise itself, whereas Promises/A+ requires they
 be called as functions.
 3. DOM Promises mandates an infinite loop for the code `const q =
 fulfilledPromise.then(() = fulfilledPromise)`, whereas Promises/A+
 mandates that `q` be rejected with a `TypeError`.
 4. DOM Promises mandates an infinite loop for the code `const q1 =
 fulfilledPromise.then(() = q2); const q2 = fulfilledPromise.then(() =
 q1)`, whereas Promises/A+ allows (but does not require) that
 implementations reject `q1` and `q2` with a `TypeError`.

 Of these, 1 I am ambivalent on, 2 I think was a very strange mistake, and
 3 and 4 feel like oversights. But none of them are a big deal.


I think tc39 quick consensus promises should not gratuitously differ from
promises/A+, i.e., they should only differ when there's a well motivated
reason, as with the addition of .flatMap and the shift of recursive
flattening from the output side of .then to the input side.

On #1, I like your parenthetical variant on DOM promise behavior (async
rejection) better than either what promises/A+ does or what DOM currently
mandates.

On the others, tc39 consensus promises should follow promises/A+.




 ___
 es-discuss mailing list
 es-discuss@mozilla.org
 https://mail.mozilla.org/listinfo/es-discuss




-- 
Text by me above is hereby placed in the public domain

  Cheers,
  --MarkM
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Promises Consensus with /A+ terminology

2013-08-02 Thread Mark S. Miller
On Fri, Aug 2, 2013 at 2:42 PM, Mark Miller erig...@gmail.com wrote:

 On Fri, Aug 2, 2013 at 2:28 PM, Domenic Denicola 
 dome...@domenicdenicola.com wrote:

 From: Mark S. Miller [erig...@google.com]

  A good start would be to convert
 https://github.com/promises-aplus/promises-tests to test262 form,
 extending test262 in the process in order to accommodate async testing. Any
 volunteers?

 If someone does the latter (preferably with a simple Mocha-like `done()`
 facility), I will happily do the former. I imagine there might be licensing
 issues with non-Ecma members; would that still be the case for code
 licensed under the WTFPL?


 Damn. I'm glad you raised this. Yes, there are issues. I don't know what
 they are. Would someone more knowledgeable of this minefield like to
 answer? Thanks.




 The only divergence between DOM promises and Promises/A+ so far are:

 1. The handling of non-`undefined`, non-function arguments, which
 Promises/A+ mandates must be ignored while DOM Promises mandate must throw
 a synchronous `TypeError`. (This is a spec bug; it should result in an
 asynchronous `TypeError` rejection.)
 2. DOM Promises requires `onFulfilled` and `onRejected` to be called as
 if they were methods of the promise itself, whereas Promises/A+ requires
 they be called as functions.
 3. DOM Promises mandates an infinite loop for the code `const q =
 fulfilledPromise.then(() = fulfilledPromise)`, whereas Promises/A+
 mandates that `q` be rejected with a `TypeError`.
 4. DOM Promises mandates an infinite loop for the code `const q1 =
 fulfilledPromise.then(() = q2); const q2 = fulfilledPromise.then(() =
 q1)`, whereas Promises/A+ allows (but does not require) that
 implementations reject `q1` and `q2` with a `TypeError`.

 Of these, 1 I am ambivalent on, 2 I think was a very strange mistake, and
 3 and 4 feel like oversights. But none of them are a big deal.


 I think tc39 quick consensus promises should not gratuitously differ from
 promises/A+, i.e., they should only differ when there's a well motivated
 reason, as with the addition of .flatMap and the shift of recursive
 flattening from the output side of .then to the input side.

 On #1, I like your parenthetical variant on DOM promise behavior (async
 rejection) better than either what promises/A+ does or what DOM currently
 mandates.


I retract this. Although I would like it better, it is not worth diverging
from promises/A+ on this one. Let's stick to promises/A+ except where it
really matters (.flatMap and recursive unwrapping on input side)




 On the others, tc39 consensus promises should follow promises/A+.




 ___
 es-discuss mailing list
 es-discuss@mozilla.org
 https://mail.mozilla.org/listinfo/es-discuss




 --
 Text by me above is hereby placed in the public domain

   Cheers,
   --MarkM




-- 
Cheers,
--MarkM
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Promises Consensus with /A+ terminology

2013-08-01 Thread Anne van Kesteren
On Thu, Aug 1, 2013 at 5:07 PM, Anne van Kesteren ann...@annevk.nl wrote:
 I basically took Tab's email and rewrote the terminology. I omitted
 the issues for brevity. Hopefully this helps.

Having done that. I wonder if we could leave the monad part out for
now. As Mark pointed out in the other thread it causes a bunch of
headaches to get that correct, and since we already decided (I
believe) to not break with existing practice we could ship the subset
that is that and figure out the superset-promise-that-works-for-monads
later. That might also give us some insight into how many people will
want to wrap promises to make the monad-suitable.


-- 
http://annevankesteren.nl/
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Promises Consensus with /A+ terminology

2013-08-01 Thread Tab Atkins Jr.
On Thu, Aug 1, 2013 at 9:09 AM, Anne van Kesteren ann...@annevk.nl wrote:
 On Thu, Aug 1, 2013 at 5:07 PM, Anne van Kesteren ann...@annevk.nl wrote:
 I basically took Tab's email and rewrote the terminology. I omitted
 the issues for brevity. Hopefully this helps.

Sorry, I was waiting until Mark and Domenic had finished up their
terminology discussion before I did a third rewrite.

 Having done that. I wonder if we could leave the monad part out for
 now. As Mark pointed out in the other thread it causes a bunch of
 headaches to get that correct, and since we already decided (I
 believe) to not break with existing practice we could ship the subset
 that is that and figure out the superset-promise-that-works-for-monads
 later. That might also give us some insight into how many people will
 want to wrap promises to make the monad-suitable.

Let's not reopen this, please.  The way I've outlined things means
that then()-based stuff works compatibly with the existing spec, so
that's not a concern.  We've already had long threads about why nested
promises are useful (namely, that promise in practice isn't a single
type - you have multiple types of promises from different promise
sources, and don't always want to smash them together).

~TJ
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Promises Consensus

2013-08-01 Thread Juan Ignacio Dopazo
If then() deep flattens, flatMap() only flattens one level and promises
assimilate thenables, is branding really necessary?

Juan
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Promises Consensus

2013-08-01 Thread Mark S. Miller
On the input side of .then and .flatMap, no.
On the output side of both .then and .flatMap, depending on what you mean
by branding, yes. If .flatMap's callback returns a non-promise the
promise it already returned gets rejected. If .then's callback returns a
non-promise, the promise it already returned accepts that non-promise.


On Thu, Aug 1, 2013 at 10:33 AM, Juan Ignacio Dopazo
dopazo.j...@gmail.comwrote:

 If then() deep flattens, flatMap() only flattens one level and promises
 assimilate thenables, is branding really necessary?

 Juan

 ___
 es-discuss mailing list
 es-discuss@mozilla.org
 https://mail.mozilla.org/listinfo/es-discuss




-- 
Cheers,
--MarkM
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Promises Consensus

2013-08-01 Thread Tab Atkins Jr.
On Thu, Aug 1, 2013 at 10:33 AM, Juan Ignacio Dopazo
dopazo.j...@gmail.com wrote:
 If then() deep flattens, flatMap() only flattens one level and promises
 assimilate thenables, is branding really necessary?

The concept of thenable *is* branding.  It's just branding with a
short, simple string property (then), rather than branding with a
hard-to-collide string (like __promiseBrand__ or something) or a
symbol.

~TJ
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Promises Consensus

2013-08-01 Thread Mark S. Miller
Between Tab's answer and mine, we see the two issues one might mean by
branding. Anne's clarifying summary at
https://mail.mozilla.org/pipermail/es-discuss/2013-August/032465.htmlspeaks
only in terms of promise-likes. One of the things we need to
settle is whether there is one predicate that applies to all the places in
this summary that says if ... promise-like. IMO we need to distinct tests
-- 

* isPromise for whether p is a promise and
* isThenable for whether p is thenable.

I would have the output-side tests for both .flatMap and .then be
isPromise. I would also have the input side test for .then use isThenable.
.flatMap has no input-side test, which is its point. A somewhat separable
question is what these two tests are testing.

The first hard reason why we must at least have an isPromise test on the
output side of .then is that the promise already returned by .then must
adopt this output promise without calling its .then method. Otherwise we
lose support for lazy evaluation and for promise pipelining.

If the output side of .then is a non-promise thenable, it is a separate
question whether it should be adopted by calling its .then method or
whether it should be accepted. IMO it should be accepted. The isThenable
test indicates something ugly is going on -- assimilation. With this AP2
based design, we can isolate this ugliness to the input side of .then.

The second reason why the two tests need to be separate is that the output
side of .flatMap cannot adopt simply by calling the output's .then method,
because otherwise you'd often get exactly the recursive unwrapping that
.flatMap is trying to avoid. In order to avoid this, it must test whether
there is anything it can do to adopt other than calling .then.


On Thu, Aug 1, 2013 at 10:43 AM, Tab Atkins Jr. jackalm...@gmail.comwrote:

 On Thu, Aug 1, 2013 at 10:33 AM, Juan Ignacio Dopazo
 dopazo.j...@gmail.com wrote:
  If then() deep flattens, flatMap() only flattens one level and promises
  assimilate thenables, is branding really necessary?

 The concept of thenable *is* branding.  It's just branding with a
 short, simple string property (then), rather than branding with a
 hard-to-collide string (like __promiseBrand__ or something) or a
 symbol.

 ~TJ
 ___
 es-discuss mailing list
 es-discuss@mozilla.org
 https://mail.mozilla.org/listinfo/es-discuss




-- 
Cheers,
--MarkM
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Promises Consensus

2013-08-01 Thread Tab Atkins Jr.
On Thu, Aug 1, 2013 at 11:04 AM, Mark S. Miller erig...@google.com wrote:
 Between Tab's answer and mine, we see the two issues one might mean by
 branding.

No, there's only the one concept. If you mean anything other than
type detection via properties on the instance or its prototype
chain, then I don't think you're using the right word.  (If I'm
wrong, please correct me.)

Detecting thenables via the presence of a function-valued then
property on the object is, explicitly, branding.

 Anne's clarifying summary at
 https://mail.mozilla.org/pipermail/es-discuss/2013-August/032465.html speaks
 only in terms of promise-likes. One of the things we need to settle is
 whether there is one predicate that applies to all the places in this
 summary that says if ... promise-like. IMO we need to distinct tests --

 * isPromise for whether p is a promise and
 * isThenable for whether p is thenable.

 I would have the output-side tests for both .flatMap and .then be isPromise.
 I would also have the input side test for .then use isThenable. .flatMap has
 no input-side test, which is its point. A somewhat separable question is
 what these two tests are testing.

 The first hard reason why we must at least have an isPromise test on the
 output side of .then is that the promise already returned by .then must
 adopt this output promise without calling its .then method. Otherwise we
 lose support for lazy evaluation and for promise pipelining.

Right.  You can go as far as testing for the existence of a then
property and verifying that its value is a Function, but you can't
call it without breaking these qualities.  (For example, you can't
call it and verify that it doesn't immediately throw, perhaps because
it's a false-positive and doesn't like being passed null/functions as
arguments.)  If we have a reliable brand unrelated to registering
callbacks, that's even better.

 If the output side of .then is a non-promise thenable, it is a separate
 question whether it should be adopted by calling its .then method or
 whether it should be accepted. IMO it should be accepted. The isThenable
 test indicates something ugly is going on -- assimilation. With this AP2
 based design, we can isolate this ugliness to the input side of .then.

Hm, that works for me.  It *is* undetectable whether you do
adoption/assimilation on the output side or do wait-for-a-non-promise
on the input side, except via measuring timeing/ordering of when
.then() is called (which you shouldn't be doing, hopefully).  This
strategy also makes us somewhat more consistent in behavior when you
do a .then().flatMap() chain, between returning from .then() a real
promise and a thenable - if you do detection on the output side, the
latter case will fully assimilate, while the former will only adopt
(one level unwrapping).  If you defer detection, then the latter case
just accepts, which is closer to the former case's adoption.

 The second reason why the two tests need to be separate is that the output
 side of .flatMap cannot adopt simply by calling the output's .then method,
 because otherwise you'd often get exactly the recursive unwrapping that
 .flatMap is trying to avoid. In order to avoid this, it must test whether
 there is anything it can do to adopt other than calling .then.

Yup, .flatMap() needs to do detection for a real/explicitly-branded
promise.  (It can't detect for flatMap-able, because that's meant to
be the generic monad operation.  Lots of different types of objects
can be monads in different ways, so the methods are *not* compatible
between types.)

~TJ
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Promises Consensus with /A+ terminology

2013-08-01 Thread Mark S. Miller
On Thu, Aug 1, 2013 at 10:00 AM, Tab Atkins Jr. jackalm...@gmail.comwrote:

 On Thu, Aug 1, 2013 at 9:09 AM, Anne van Kesteren ann...@annevk.nl
 wrote:
  On Thu, Aug 1, 2013 at 5:07 PM, Anne van Kesteren ann...@annevk.nl
 wrote:
  I basically took Tab's email and rewrote the terminology. I omitted
  the issues for brevity. Hopefully this helps.

 Sorry, I was waiting until Mark and Domenic had finished up their
 terminology discussion before I did a third rewrite.

  Having done that. I wonder if we could leave the monad part out for
  now. As Mark pointed out in the other thread it causes a bunch of
  headaches to get that correct, and since we already decided (I
  believe) to not break with existing practice we could ship the subset
  that is that and figure out the superset-promise-that-works-for-monads
  later. That might also give us some insight into how many people will
  want to wrap promises to make the monad-suitable.

 Let's not reopen this, please.


There are three questions here, which need to be settled in roughly this
chronological order:
1) What should tc39 do quickly, to unblock the DOM's need for promises and
avoid a design fork?
2) What should DOM do quickly the tc39's quick output?
3) Once #1 and #2 are settled, what should tc39 do for es7?

For #1 I agree with Tab. We should not reopen this issue, but should rather
proceed to settle the AP2ish design quickly. Otherwise we won't settle
anything quickly and DOM will go their own way.

For #2, since whatever DOM does quickly becomes a compat constraint on all
future decisions, DOM should take the minimum subset of #1 which actually
meets their short term needs. I leave it to those who understand those
needs to argue about what these are.

For #3, we will hopefully stay upwards compat with both #1 and #2. But
compat with #2 will be more pressing, as that will have been massively
deployed as part of the browser.



  The way I've outlined things means
 that then()-based stuff works compatibly with the existing spec, so
 that's not a concern.  We've already had long threads about why nested
 promises are useful (namely, that promise in practice isn't a single
 type - you have multiple types of promises from different promise
 sources, and don't always want to smash them together).


These have been long threads so I won't rehash them either. However, I will
point out that these long threads also explain why nested promises won't be
useful.





 ~TJ
 ___
 es-discuss mailing list
 es-discuss@mozilla.org
 https://mail.mozilla.org/listinfo/es-discuss




-- 
Cheers,
--MarkM
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Promises Consensus

2013-08-01 Thread Mark S. Miller
On Thu, Aug 1, 2013 at 11:26 AM, Tab Atkins Jr. jackalm...@gmail.comwrote:

 On Thu, Aug 1, 2013 at 11:04 AM, Mark S. Miller erig...@google.com
 wrote:
  Between Tab's answer and mine, we see the two issues one might mean by
  branding.

 No, there's only the one concept. If you mean anything other than
 type detection via properties on the instance or its prototype
 chain, then I don't think you're using the right word.


This is not a correct summary of the way we've been using branding. But
it is one kind of branding if you wish.



  (If I'm wrong, please correct me.)


Done ;)




 Detecting thenables via the presence of a function-valued then
 property on the object is, explicitly, branding.

  Anne's clarifying summary at
  https://mail.mozilla.org/pipermail/es-discuss/2013-August/032465.htmlspeaks
  only in terms of promise-likes. One of the things we need to settle is
  whether there is one predicate that applies to all the places in this
  summary that says if ... promise-like. IMO we need to distinct tests --
 
  * isPromise for whether p is a promise and
  * isThenable for whether p is thenable.
 
  I would have the output-side tests for both .flatMap and .then be
 isPromise.
  I would also have the input side test for .then use isThenable. .flatMap
 has
  no input-side test, which is its point. A somewhat separable question is
  what these two tests are testing.
 
  The first hard reason why we must at least have an isPromise test on the
  output side of .then is that the promise already returned by .then must
  adopt this output promise without calling its .then method. Otherwise we
  lose support for lazy evaluation and for promise pipelining.

 Right.  You can go as far as testing for the existence of a then
 property and verifying that its value is a Function, but you can't
 call it without breaking these qualities.  (For example, you can't
 call it and verify that it doesn't immediately throw, perhaps because
 it's a false-positive and doesn't like being passed null/functions as
 arguments.)  If we have a reliable brand unrelated to registering
 callbacks, that's even better.


+1




  If the output side of .then is a non-promise thenable, it is a separate
  question whether it should be adopted by calling its .then method or
  whether it should be accepted. IMO it should be accepted. The isThenable
  test indicates something ugly is going on -- assimilation. With this AP2
  based design, we can isolate this ugliness to the input side of .then.

 Hm, that works for me.  It *is* undetectable whether you do
 adoption/assimilation on the output side or do wait-for-a-non-promise
 on the input side, except via measuring timeing/ordering of when
 .then() is called (which you shouldn't be doing, hopefully).  This
 strategy also makes us somewhat more consistent in behavior when you
 do a .then().flatMap() chain, between returning from .then() a real
 promise and a thenable - if you do detection on the output side, the
 latter case will fully assimilate, while the former will only adopt
 (one level unwrapping).  If you defer detection, then the latter case
 just accepts, which is closer to the former case's adoption.


Excellent!




  The second reason why the two tests need to be separate is that the
 output
  side of .flatMap cannot adopt simply by calling the output's .then
 method,
  because otherwise you'd often get exactly the recursive unwrapping that
  .flatMap is trying to avoid. In order to avoid this, it must test whether
  there is anything it can do to adopt other than calling .then.

 Yup, .flatMap() needs to do detection for a real/explicitly-branded
 promise.  (It can't detect for flatMap-able, because that's meant to
 be the generic monad operation.  Lots of different types of objects
 can be monads in different ways, so the methods are *not* compatible
 between types.)


Great! I think we continue to converge very nicely.





 ~TJ




-- 
Cheers,
--MarkM
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Promises Consensus with /A+ terminology

2013-08-01 Thread Tab Atkins Jr.
On Thu, Aug 1, 2013 at 11:27 AM, Mark S. Miller erig...@google.com wrote:
 There are three questions here, which need to be settled in roughly this
 chronological order:
 1) What should tc39 do quickly, to unblock the DOM's need for promises and
 avoid a design fork?
 2) What should DOM do quickly the tc39's quick output?
 3) Once #1 and #2 are settled, what should tc39 do for es7?

 For #1 I agree with Tab. We should not reopen this issue, but should rather
 proceed to settle the AP2ish design quickly. Otherwise we won't settle
 anything quickly and DOM will go their own way.

And, importantly, except for the open question of thenable/branding,
our proposal is behaviorally and API-compatible with current DOM
promises.

 For #2, since whatever DOM does quickly becomes a compat constraint on all
 future decisions, DOM should take the minimum subset of #1 which actually
 meets their short term needs. I leave it to those who understand those needs
 to argue about what these are.

Unfortunately, the thenable question still impinges on the minimum subset. :/

~TJ
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


RE: Promises Consensus

2013-07-31 Thread Domenic Denicola
Just some terminology questions for this new proposal...

From: Tab Atkins Jr. [jackalm...@gmail.com]

 whatever p resolves to, gets passed to the flatMap() callbacks.

What does resolves mean in this context? I don't believe you are using it in 
the same way that it is used in Promises/A+ or DOM Promises. For example, using 
the existing definition, you could resolve `p` to a forever-pending promise; I 
doubt you'd want to pass that forever pending promise to either (both?) of the 
flatMap callbacks.

 if p accepts to a promise-like, the callbacks get moved down to that until it 
 either accepts with a non-promise-like, or rejects.

What does accepts mean?

 Promise.every() will eventually resolve to an array of non-promise-likes.

Again, what are you meaning by resolve here? Promises don't resolve to 
anything, so this is confusing.

 We can't just use magic internal operations to detect when the returned value 
 resolves, so the output promise will have to register callbacks on it.

Same question.

 This may have performance implications - is it possible that we just do eager 
 resolution now, but later have detection for lazy promises getting returned 
 and switch to lazy behavior in just those cases?

Here I believe you are using resolution in the same sense as Promises/A+ or 
DOM Promises, but differently from all the above uses.

 Should we reject with a TypeError, or fall back to using .then() resolution 
 semantics?

Again this seems correct, but in contradiction to earlier uses.

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Promises Consensus

2013-07-31 Thread Tab Atkins Jr.
[Gah, resending because I'm being *way* too loose with my terminology.
 Ignore previous email - this one has identical content, but uses
terms correctly.] (Scratch that, I added a new point #3 at the end of
the email.)

[For the purposes of this email, a promise accepting or rejecting
means that its resolver's accept() or reject() method was called, or
the equivalent internal magic.  fulfill means accept or reject.
resolve means adopt or accept, depending on whether the value is a
promise-like or not (in other words, what the resolver's resolve()
method does).  adopt means accepting or rejecting with the same
value as the adopted promise.  If I should be using better terms, let
me know.]

Heya!  I, Mark, and others have been hashing out our remaining
differences on Promises privately, and are all happy with each other
now, with only two remaining issues to be decided in a larger
audience.  Anne says that we should be able to get DOM Promises on
track with this consensus if we finish up the discussion in the next
month or so, since the differences from the current spec are mostly
internal/new API.

Here's our current consensus:

Promises have both a .then() and a .flatMap() method.

1. p.flatMap() does single-level resolution:
* whatever p fulfills to, gets passed to the flatMap() callbacks.
* The callback return value *must* be a promise-like, which is
adopted by the output promise; otherwise, the output promise rejects
with a TypeError.

2. p.then() does recursive resolution on the input side (per
consensus following 2 TC39-meetings ago):
* if p accepts to a promise-like, the .then() callbacks get moved
down to that promise-like until it either accepts with a
non-promise-like, or rejects.
* Rejection calls the rejection callback without delay; no extra
resolution mechanics happen here.
* The callback return value can be a promise-like or not.  If it
is, the output promise adopts it; if not, the output promise accepts
it.

3. The helper functions (Promise.every(), etc.) use .then() semantics.
That is, Promise.every() will eventually accept to an array of
non-promise-likes.


The first issue still up for community discussion involves the
definition of promise-like.

We'd like the definition to be: (a) a Promise or subtype, or (b) a
branded non-Promise (with the branding done via Symbol or similar).
Promises/A+ wants the branding to be done via a method named then
(the thenable concept).

This, unfortunately, goes directly against TC39 practices in a number
of other areas, such as iterators, where we don't want short string
names as branding due to the possibility of collision.  (In the case
of then, collision isn't a possibility, it's a certainty - we *know*
there are libraries out there today that put a then method on their
objects without referring to Promises.)  Thoughts?


The second issue still up for community discussion is what adopts
means, precisely.

1. Assume a .then() callback returns a non-native promise-like.  We
can't just use magic internal operations to detect when the returned
promise fulfills, so the output promise will have to register
callbacks on it.  This appears to break our desire to have lazy
promises in the future that don't compute a value until someone asks
for it. Should we specify that adoption is done late?  (That is, the
output promise would hold onto the returned promise without touching
it, until someone actually registers some callbacks on it.)  This may
have performance implications - is it possible that we just do eager
resolution now, but later have detection for lazy promises getting
returned and switch to lazy behavior in just those cases?

2. Assume a .flatMap() callback returns a non-native promise-like.
Obviously, the output promise adopts it by registering .flatMap()
callbacks on it.  But what if the promise-like only has a .then()
method?  Should we reject with a TypeError, or fall back to using
.then() resolution semantics?  (I suspect we need to do the former to
maintain monad laws.)

3. For that matter, what about adopting the returned promise value of
a .then() callback?  If you try and use .then() to listen for the
returned promise to fulfill, you'll end up imposing full recursive
semantics on the output promise, regardless of whether they're
observed with .flatMap() or .then().  Looks like we should default to
trying to adopt with .flatMap(), and then maybe fall back to .then()
for .then()-returned promise-likes.

~TJ
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


RE: Promises Consensus

2013-07-31 Thread Domenic Denicola
From: Tab Atkins Jr. [jackalm...@gmail.com]

 For the purposes of this email, a promise accepting or rejecting means 
 that its resolver's accept() or reject() method was called, or the equivalent 
 internal magic.  fulfill means accept or reject. resolve means adopt 
 or accept, depending on whether the value is a promise-like or not (in other 
 words, what the resolver's resolve() method does).  adopt means accepting 
 or rejecting with the same value as the adopted promise.  If I should be 
 using better terms, let me know.

Thanks for the clarifications :). I think this is a bit confusing because it is 
at odds with commonly-used terminology, from DOM Promises and Promises/A+, but 
at least now things are defined and used in a self-consistent way. Much 
appreciated.

For the record, since you asked for better terms, the community consensus is:

- Fulfill and reject are the two end states (as opposed to pending).
- Settle means fulfill or reject.
- Resolve means adopt or fulfill.

Accept was just a strange neologism introduced by the linguistic fork that 
was DOM Futures, now thankfully dead.

But for the purposes of this thread it may be best to stop worrying about these 
issues now that you've set out a set of self-consistent terminology, and simply 
go with the terms as you defined them. We can always re-kill the zombie 
accept at a later date, replacing it with the normal fulfill, once we 
understand its semantics.

I'll step back and let everyone else comment now, as I believe my views on the 
proposed semantics are well-known.

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Promises Consensus

2013-07-31 Thread Tab Atkins Jr.
On Wed, Jul 31, 2013 at 11:38 AM, Domenic Denicola
dome...@domenicdenicola.com wrote:
 From: Tab Atkins Jr. [jackalm...@gmail.com]
 For the purposes of this email, a promise accepting or rejecting means 
 that its resolver's accept() or reject() method was called, or the 
 equivalent internal magic.  fulfill means accept or reject. resolve 
 means adopt or accept, depending on whether the value is a promise-like or 
 not (in other words, what the resolver's resolve() method does).  adopt 
 means accepting or rejecting with the same value as the adopted promise.  If 
 I should be using better terms, let me know.

 Thanks for the clarifications :). I think this is a bit confusing because it 
 is at odds with commonly-used terminology, from DOM Promises and Promises/A+, 
 but at least now things are defined and used in a self-consistent way. Much 
 appreciated.

 For the record, since you asked for better terms, the community consensus is:

 - Fulfill and reject are the two end states (as opposed to pending).
 - Settle means fulfill or reject.
 - Resolve means adopt or fulfill.

Ah, I'd never heard the term settle before, in any of the threads
across the WGs here.  Got it.

~TJ
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Promises Consensus

2013-07-31 Thread Juan Ignacio Dopazo
Does this all mean that you're ok with having promises-for-promises?
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Promises Consensus

2013-07-31 Thread Tab Atkins Jr.
On Wed, Jul 31, 2013 at 12:48 PM, Juan Ignacio Dopazo
dopazo.j...@gmail.com wrote:
 Does this all mean that you're ok with having promises-for-promises?

I've always been okay with that.  ^_^  This consensus details how to
handle nested promises (use .flatMap()) *and* how to ignore that and
just get values out of them (use .then()).  Everyone's happy!

~TJ
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


RE: Promises Consensus

2013-07-31 Thread Domenic Denicola
From: Mark S. Miller [erig...@google.com]

 One thing I think Domenic is missing that I also missed at first: Once we 
 introduce .flatMap, then we need a distinct accepted state that is neither 
 fulfilled nor rejected. The issue is that p.then does not fire until the 
 promise p is fulfilled or rejected. If q is pending, and p is accepted to q, 
 then p.flatMap will fire but p.then will not yet fire. When q becomes 
 fulfilled or rejected, then p becomes fulfilled or rejected and p.then fires. 
 Thus, p is following q. So when p and q are both promises, p follows q when p 
 is accepted to q or when p adopts q. This hair splitting goes beyond any 
 previous conversations I've had with anyone, but becomes necessary to account 
 for the behavior or both .flatMap and .then under AP2.

Isn't this just what we've been calling resolved? As in p is resolved q, but 
still pending because q is pending?

I suppose that is ambiguous because you could resolve p to a non-promise-like 
and the behavior is a bit different. Perhaps you're proposing that resolve p 
with q will make p resolved with q, and we will additionally say either that p 
is accepted with q, if q is a promise-like, or fulfilled with q, if q is 
non-promise-like. Does that sound accurate?
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Promises Consensus

2013-07-31 Thread Claude Pache


Le 31 juil. 2013 à 20:23, Tab Atkins Jr. jackalm...@gmail.com a écrit :

 
 The first issue still up for community discussion involves the
 definition of promise-like.
 
 We'd like the definition to be: (a) a Promise or subtype, or (b) a
 branded non-Promise (with the branding done via Symbol or similar).
 Promises/A+ wants the branding to be done via a method named then
 (the thenable concept).
 
 This, unfortunately, goes directly against TC39 practices in a number
 of other areas, such as iterators, where we don't want short string
 names as branding due to the possibility of collision.  (In the case
 of then, collision isn't a possibility, it's a certainty - we *know*
 there are libraries out there today that put a then method on their
 objects without referring to Promises.)  Thoughts?

I suggest an @@isPromise builtin symbol, which works the same way as @@isRegExp 
in the ES6 spec [1]: An object is reputed to be a promise if and only if it has 
a property (either own or inherited) named @@isPromise. And `Promise.prototype` 
has initially an @@isPromise own property, so that instances of subclasses of 
`Promise` are recognised as promises.

(With this solution, you have not to choose between subclassing or branding, 
but you have the both. :-) )

—Claude

[1] search the occurrences of @@isRegExp in: 
http://people.mozilla.org/~jorendorff/es6-draft.html

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Promises Consensus

2013-07-31 Thread Mark Miller
On Wed, Jul 31, 2013 at 3:52 PM, Domenic Denicola 
dome...@domenicdenicola.com wrote:

 From: Mark S. Miller [erig...@google.com]

  One thing I think Domenic is missing that I also missed at first: Once
 we introduce .flatMap, then we need a distinct accepted state that is
 neither fulfilled nor rejected. The issue is that p.then does not fire
 until the promise p is fulfilled or rejected. If q is pending, and p is
 accepted to q, then p.flatMap will fire but p.then will not yet fire. When
 q becomes fulfilled or rejected, then p becomes fulfilled or rejected and
 p.then fires. Thus, p is following q. So when p and q are both promises, p
 follows q when p is accepted to q or when p adopts q. This hair splitting
 goes beyond any previous conversations I've had with anyone, but becomes
 necessary to account for the behavior or both .flatMap and .then under AP2.

 Isn't this just what we've been calling resolved? As in p is resolved
 q, but still pending because q is pending?


I'm sorry Domenic, but since I'm hair splitting and stated several
distinctions, I need to know which this you refer to.




 I suppose that is ambiguous because you could resolve p to a
 non-promise-like and the behavior is a bit different. Perhaps you're
 proposing that resolve p with q will make p resolved with q, and we will
 additionally say either that p is accepted with q, if q is a promise-like,
 or fulfilled with q, if q is non-promise-like. Does that sound accurate?
 ___
 es-discuss mailing list
 es-discuss@mozilla.org
 https://mail.mozilla.org/listinfo/es-discuss




-- 
Text by me above is hereby placed in the public domain

  Cheers,
  --MarkM
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


  1   2   >