RE: Error objects in W3C APIs

2014-02-05 Thread Domenic Denicola
From: Jonas Sicking [mailto:jo...@sicking.cc] 

> I agree. Creating hierarchies of error "types" seems fragile to me.

> A better approach seems like having a short list of flat error types. In 
> cases where it might be useful to have a more specific error type, instead 
> include additional information on the error. So for example, rather than 
> having a NetworkResourceNotFound error, use NetworkError but add a property 
> which indicate what type of network failure. Not sure if that was what you 
> were proposing with the "proximate cause"?

Yeah, basically. Although I question the utility of the types at all. As 
discussed in [the earlier thread about an InvalidOperationError][1], in 
practice bucketing errors into the short list of types isn't particularly 
helpful, I think.

> (... a bunch of stuff I agree with regarding DOM errors.)

I agree.

> I'm not sure that there's a difference between these two. Or at least I don't 
> think there's a difference between the stuff that the DOM puts in .name, and 
> that ES puts in the classname. They express the same thing just in different 
> ways.

Yeah. And the divergence is unfortunate, although not that big a deal, since 
it's kind of minor and in practice nobody really tries to use either the 
classname or name to distinguish, from what I see.

> I don't think we should specify the exact string that goes into these 
> messages. It's good if implementations are free to add additional details if 
> they see developers struggling with something.
>
> But we could definitely do with more recommendations for implementations 
> about what information to include here.

That would be cool in my opinion. The removal at [2] saddened me a bit. I 
wonder what other spec writers' perspectives are, given that nobody does so. 
Are we all just following accepted practice, but would be happy to switch? Or 
are there people that believe such guidance would be a bad thing?

> I think a proposed solution would help clarify.
>
> For your Stream example above I would propose using an InvalidStateError but 
> give it a couple of properties so that code could understand what went wrong. 
> Maybe a property which contains "BaseWritableStream.write" to indicate that 
> that was the function that failed, and a second property which contains 
> "closing" or "closed" to indicate which wrong state was hit. This is 
> definitely a very unpolished proposal, but might illustrate something that 
> could work.

Yeah, basically. My initial thought was some kind of identifier. E.g.

```js
var closingError = new TypeError("nice human message");
closingError.cause = "wrote_while_closing";

var closedError = new TypeError("another nice human message");
closedError.cause = "wrote_while_closed";
```

(The underscores could actually be replaced with spaces, but then it feels less 
identifier-ey. Kind of a strange thing when you think about it.)

The idea would be that you try to maintain a globally-unique list of causes, so 
that people can match on exactly the cause they care about. Unlike 
`DOMException` names, you don't maintain a global list so that people can 
consult it and find a cause that matches; you maintain that global list so that 
people can consult it and *not* accidentally re-use a cause. It has all the 
normal fragility properties of a global registry, of course. Hmm.

Your idea of indicating which method caused the failure is a very interesting 
one as well. I wonder if it is related to the error stack trace in a universal 
fashion. Certainly for user-space errors it is not, since if you refactor to 
call a helper function outside of your public API that throws an error, you'd 
want the "causer" to be the public API method, not the helper function. But it 
might be for web platform APIs, since in practice they hide their helper 
functions using self-hosted or C++ tricks.

I've asked some Node people what info they think is most useful, since 
apparently they're starting to realize that they've built up some de-facto 
standards in Node core around this stuff and are thinking of making those more 
explicit and universal. It'll be interesting to see what they come up with. 
(Trevor Norris, if you're listening, feel free to chime in!)

[1]: http://esdiscuss.org/topic/exception-type-for-invalid-operations
[2]: 
https://github.com/whatwg/streams/commit/05369d410d89b34b001a2607d7dc7f7a0ed4af7e#diff-04c6e90faac2675aa89e2176d2eec7d8L859


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


Syntactic parameters

2014-02-05 Thread Michael Dyck

When I take the ECMAScript grammar and expand its abbreviations as outlined
in section 5.1.5, I get a grammar with lots of unreachable nonterminals
(i.e., symbols that can't appear in any sentential form derived from Script
or Module).

For instance, consider StrictFormalParameters. With its parameters Yield
and GeneratorParameter, it expands to 4 nonterminals:
StrictFormalParameters
StrictFormalParameters_Yield
StrictFormalParameters_GeneratorParameter
StrictFormalParameters_Yield_GeneratorParameter
(I use underscores to make the resulting names easier to read.)

In the unexpanded grammar, it's used in only 3 productions:

14.2:
ArrowFormalParameters :
( StrictFormalParameters )

14.3:
MethodDefinition[Yield] :
PropertyName[?Yield] ( StrictFormalParameters ) { FunctionBody }

14.4:
GeneratorMethod[Yield] :
* PropertyName[?Yield]
( StrictFormalParameters[Yield,GeneratorParameter] )
{ FunctionBody[Yield] }

The first two of these expand to productions that reference
 StrictFormalParameters
and the last one expands to productions that reference
 StrictFormalParameters_Yield_GeneratorParameter.
So
 StrictFormalParameters_Yield and
 StrictFormalParameters_GeneratorParameter
are never referenced, and are thus unreachable.

Is this intentional? Or should StrictFormalParameters have a "?Yield"
subscript in the 14.3 and 14.4 productions? (And while we're in the
neighborhood, should FunctionBody also have a "?Yield" subscript in those
productions?) If not, why not?

Similarly, I'm also wondering about the unreachability of
Statement_Yield
Declaration_Yield_Default
BindingIdentifier_Default_Yield

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


Re: Promise.cast and Promise.resolve

2014-02-05 Thread Kevin Smith
>
>
> I really don't know what to do about this.
>
>
A few facts:

- Promises have a long history of controversy (I was there on the CommonJS
list!)
- The AP2 design was found acceptable (if not ideal) to all parties,
providing us with a path through the controversy
- Promises were a *very* late addition to ES6

With these facts at hand, the way forward seems clear:

- Stick to AP2 like glue.
- Sacrifice to deferment any non-fundamental part of the API which might
re-ignite controversy.

The committee failure mode of "do-both" should be stated more precisely as:
 "do-both at the expense of design coherency".  AP2 is, in my opinion, a
coherent design and therefore does not represent such a failure mode.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Promise.cast and Promise.resolve

2014-02-05 Thread Mark S. Miller
Just noting that with the infix ! syntax proposed for ES7, this would be

e.respondWith(cache.get('foo') ! [0])


On Wed, Feb 5, 2014 at 4:44 PM, Tab Atkins Jr.  wrote:

> On Wed, Feb 5, 2014 at 3:51 PM, Brendan Eich  wrote:
> > Tab Atkins Jr. wrote:
> >> But say you wanted to do something a bit more complicated.  For
> >> example, if the cache hits, but the result is a Promise, you might
> >> want to show a throbber until the Promise resolves.  Under the old
> >> consensus, you could do this pretty easily - just do
> >> "cache.get().chain(...)" and then operate on the result.  Under the
> >> new, you can't, because the cache promise won't resolve until after
> >> the response promise resolves.  We can't say "just hand-box", because
> >> it breaks the easy pattern above when you*don't*  want to do anything
> >>
> >> complicated - you have to .then() it and unbox there.
> >
> > Yeah, that would suck for the pretty one-liner. But is it really that
> much
> > more? Write it out and let's see A vs. B.
>
> e.respondWith(cache.get('foo').then(x=>x[0]))
>
> ...which doesn't look like much until you realize you have to repeat
> the invocation on every single cache retrieval.  (And remember to box
> with [] on every cache set, or else the retrieval will error out.)
>
> ~TJ
>



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


Re: Promise.cast and Promise.resolve

2014-02-05 Thread Tab Atkins Jr.
On Wed, Feb 5, 2014 at 3:51 PM, Brendan Eich  wrote:
> Tab Atkins Jr. wrote:
>> But say you wanted to do something a bit more complicated.  For
>> example, if the cache hits, but the result is a Promise, you might
>> want to show a throbber until the Promise resolves.  Under the old
>> consensus, you could do this pretty easily - just do
>> "cache.get().chain(...)" and then operate on the result.  Under the
>> new, you can't, because the cache promise won't resolve until after
>> the response promise resolves.  We can't say "just hand-box", because
>> it breaks the easy pattern above when you*don't*  want to do anything
>>
>> complicated - you have to .then() it and unbox there.
>
> Yeah, that would suck for the pretty one-liner. But is it really that much
> more? Write it out and let's see A vs. B.

e.respondWith(cache.get('foo').then(x=>x[0]))

...which doesn't look like much until you realize you have to repeat
the invocation on every single cache retrieval.  (And remember to box
with [] on every cache set, or else the retrieval will error out.)

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


Re: Promise.cast and Promise.resolve

2014-02-05 Thread Brendan Eich

Tab Atkins Jr. wrote:

The APIs for Caches and dealing with responses are designed so that
they work nicely together, acting the same way whether you pass a
Response or a Promise.  So you can often respond to requests
with a simple "e.respondWith(cache.get('foo'))" and it Just Works®.


Nice.


But say you wanted to do something a bit more complicated.  For
example, if the cache hits, but the result is a Promise, you might
want to show a throbber until the Promise resolves.  Under the old
consensus, you could do this pretty easily - just do
"cache.get().chain(...)" and then operate on the result.  Under the
new, you can't, because the cache promise won't resolve until after
the response promise resolves.  We can't say "just hand-box", because
it breaks the easy pattern above when you*don't*  want to do anything
complicated - you have to .then() it and unbox there.


Yeah, that would suck for the pretty one-liner. But is it really that 
much more? Write it out and let's see A vs. B.



There are various ways to work around this.  One way is to
auto-handbox:


Heh, an oxymoron, like "Military Intelligence".

But I know what you mean!


  we subclass Promise to CachePromise and hang a .chain()
off of it which receives the actual value you stored in the map, while
.then() silently unboxes and continues flattening as normal.  Another
way is to just guarantee that Cache promises never hand promises to
their callbacks, and ensure that there are alternate ways to check if
a Response is ready yet (maybe just forcing people to more explicitly
track the Response promises directly, and make sure they're synced
with the stuff in the Cache).


Sure, there are longer ways to go, but they seem to require if-else's or 
similar. I still would like to see the A-B test.


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


Re: Promise.cast and Promise.resolve

2014-02-05 Thread Tab Atkins Jr.
On Wed, Feb 5, 2014 at 12:34 PM, Brendan Eich  wrote:
> Tab Atkins Jr. wrote:
>> (Fixing it does involve magic, or
>> subclassing, but those are things that can be done internally, rather
>> than exposed to authors as terrible API.)
>
> Could you say a bit more? Do you mean APIs that defensively "hand-box" so
> the user doesn't have to, with async map and its overloaded get return
> value?

So, to get a bit more concrete, the ServiceWorker spec introduces
Cache objects, which are asynchronous maps.  When you get/set/etc
anything, you get back a promise for the result.

ServiceWorker also has Response objects, which are what you're
supposed to be putting into the Caches.  Some parts of the API return
Response objects directly, some return promises for Responses.  So
sometimes you'll be storing promises in the Cache.

The APIs for Caches and dealing with responses are designed so that
they work nicely together, acting the same way whether you pass a
Response or a Promise.  So you can often respond to requests
with a simple "e.respondWith(cache.get('foo'))" and it Just Works®.

So, that part's not affected by the promise change, because the whole
point is that this part of the API unwraps things until it hits a
Response.

But say you wanted to do something a bit more complicated.  For
example, if the cache hits, but the result is a Promise, you might
want to show a throbber until the Promise resolves.  Under the old
consensus, you could do this pretty easily - just do
"cache.get().chain(...)" and then operate on the result.  Under the
new, you can't, because the cache promise won't resolve until after
the response promise resolves.  We can't say "just hand-box", because
it breaks the easy pattern above when you *don't* want to do anything
complicated - you have to .then() it and unbox there.

There are various ways to work around this.  One way is to
auto-handbox: we subclass Promise to CachePromise and hang a .chain()
off of it which receives the actual value you stored in the map, while
.then() silently unboxes and continues flattening as normal.  Another
way is to just guarantee that Cache promises never hand promises to
their callbacks, and ensure that there are alternate ways to check if
a Response is ready yet (maybe just forcing people to more explicitly
track the Response promises directly, and make sure they're synced
with the stuff in the Cache).

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


Re: Promise.cast and Promise.resolve

2014-02-05 Thread Brendan Eich

Tab Atkins Jr. wrote:

(Fixing it does involve magic, or
subclassing, but those are things that can be done internally, rather
than exposed to authors as terrible API.)


Could you say a bit more? Do you mean APIs that defensively "hand-box" 
so the user doesn't have to, with async map and its overloaded get 
return value?


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


Re: Promise.cast and Promise.resolve

2014-02-05 Thread Tab Atkins Jr.
On Wed, Feb 5, 2014 at 12:17 PM, Brendan Eich  wrote:
> Tab Atkins Jr. wrote:
>> Note, though, that you can still have consensus*and*  strong
>> objections.  Design-by-committee is still a failure mode to be
>> avoided.
>
> Excellent point. Argues against "do both". Can't ditch .then/resolve given
> library code interop constraint. That forces the conclusion from last week's
> meeting.
>
> What do you think at this point? My Futures cereal next year will be
> delicious and nutritious!

I still think it's a mistake, and though most APIs won't care as they
won't produce nested promises, some types of APIs *will* be negatively
affected in hard-to-workaround ways.

But I also respect champion-based design, and I've talked with Alex
Russell who believes it's not as huge an impediment to some of our
planned APIs as I believed.  (Fixing it does involve magic, or
subclassing, but those are things that can be done internally, rather
than exposed to authors as terrible API.)

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


Re: Promise.cast and Promise.resolve

2014-02-05 Thread Brendan Eich

Tab Atkins Jr. wrote:

Note, though, that you can still have consensus*and*  strong
objections.  Design-by-committee is still a failure mode to be
avoided.


Excellent point. Argues against "do both". Can't ditch .then/resolve 
given library code interop constraint. That forces the conclusion from 
last week's meeting.


What do you think at this point? My Futures cereal next year will be 
delicious and nutritious!


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


Re: async decision making (was Re: Promise.cast and Promise.resolve)

2014-02-05 Thread Brendan Eich

Alex Russell wrote:



I'd rather we keep separate and conflict-prone APIs in separate
objects, though. I'd rather we acknowledge that Promises are a
library de-facto quasi-standard we are trying to codify, not
green-field work where we can start over or "do both".


Excited to hear someone else recognize this reality.


Another realist! I will subscribe to your newsletter if you will buy my 
cereal!


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


Re: async decision making (was Re: Promise.cast and Promise.resolve)

2014-02-05 Thread Alex Russell
On Wed, Feb 5, 2014 at 12:00 PM, Brendan Eich  wrote:

> Edward O'Connor wrote:
>
>> Perhaps TC39 should consider adopting a similar policy.
>>
>
> Policy, schmolicy :-P.
>
> (Presumably clocks with deadlines are required; consensus could break
> afterwards, in spite of the formal rules.)
>
> Let's let our hair down a bit and get real here. We did not "declare
> consensus" Thursday last week, in any formal or informal fashion. We knew
> Andreas wasn't there. We heard his position articulated by Sam (who dialed
> in). We knew most of what we now know.
>
> At this point we must forge async consensus. Is Andreas and anyone else
> (I'm not singling him out; I sympathize and started on his/Sam's/Kevin's
> "side" earlier last week) objecting doing so in a consensus-breaking way,
> for sure? We should async-check this.
>
> Often one objects or finds a survivable fault in a consensus position, and
> works to persuade others to overcome it. Sometimes this leads to
> minimization (and over-minimization) and deferment of troublesome but
> important bits (@medikoo on twitter reminds me we dropped .done after
> June's big thread -- a semi-consensus deferment, I found from (re-)reading
> a bunch of messages).
>
> If we really have broken consensus in the async sense, we will have to
> back up to Kevin's fixup of AP2, as Mark suggests. I have no idea how this
> will shake out.
>
> I'd rather we keep separate and conflict-prone APIs in separate objects,
> though. I'd rather we acknowledge that Promises are a library de-facto
> quasi-standard we are trying to codify, not green-field work where we can
> start over or "do both".
>

Excited to hear someone else recognize this reality.


> Is any of this persuasive to anyone? Dunno, you tell me. If DOM only
> wanted .then/.resolve, you should join my "realist" camp :-P.
>
> /be
>
> ___
> 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: async decision making (was Re: Promise.cast and Promise.resolve)

2014-02-05 Thread Brendan Eich

Edward O'Connor wrote:

Perhaps TC39 should consider adopting a similar policy.


Policy, schmolicy :-P.

(Presumably clocks with deadlines are required; consensus could break 
afterwards, in spite of the formal rules.)


Let's let our hair down a bit and get real here. We did not "declare 
consensus" Thursday last week, in any formal or informal fashion. We 
knew Andreas wasn't there. We heard his position articulated by Sam (who 
dialed in). We knew most of what we now know.


At this point we must forge async consensus. Is Andreas and anyone else 
(I'm not singling him out; I sympathize and started on his/Sam's/Kevin's 
"side" earlier last week) objecting doing so in a consensus-breaking 
way, for sure? We should async-check this.


Often one objects or finds a survivable fault in a consensus position, 
and works to persuade others to overcome it. Sometimes this leads to 
minimization (and over-minimization) and deferment of troublesome but 
important bits (@medikoo on twitter reminds me we dropped .done after 
June's big thread -- a semi-consensus deferment, I found from 
(re-)reading a bunch of messages).


If we really have broken consensus in the async sense, we will have to 
back up to Kevin's fixup of AP2, as Mark suggests. I have no idea how 
this will shake out.


I'd rather we keep separate and conflict-prone APIs in separate objects, 
though. I'd rather we acknowledge that Promises are a library de-facto 
quasi-standard we are trying to codify, not green-field work where we 
can start over or "do both".


Is any of this persuasive to anyone? Dunno, you tell me. If DOM only 
wanted .then/.resolve, you should join my "realist" camp :-P.


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


async decision making (was Re: Promise.cast and Promise.resolve)

2014-02-05 Thread Edward O'Connor
Hi,

Mark wrote:

> Unfortunately, just as Yehuda was not there in September and did not
> agree to the consensus then, Andreas was not there on Thursday of
> January and (above in this thread) does not agree to that consensus.
> This indicates a different failure mode we should be concerned about.
> Not everyone is at every meeting. If anyone absent from any meeting
> can veto the hard-won consensus achieved by those who did attend, it
> is hard to see how to make progress.

At the W3C, both HTML and WebApps are chartered to only declare
consensus asynchronously. This policy is in place precisely to avoid the
scenario where key people are disenfranchised because they couldn't be
at some F2F.

Perhaps TC39 should consider adopting a similar policy.


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


Re: Error objects in W3C APIs

2014-02-05 Thread Oliver Hunt

On Feb 5, 2014, at 12:05 AM, Jonas Sicking  wrote:

> On Tue, Feb 4, 2014 at 9:49 AM, Domenic Denicola
>  wrote:
>> From: es-discuss  on behalf of Allen 
>> Wirfs-Brock 
>> 
>>> I've designed exception handling systems before and designed and worked 
>>> with complex exception hierarchies. My main caveat is that they are 
>>> somewhat of an attractive nuisance.  It's easy to get into designing  
>>> beautiful classification hierarchies of dozens of different kinds of 
>>> exceptions, each with their own specific failure information that is 
>>> captured. In practice, I've found very little actual utility for them.
>> 
>> My (more limited) experience is the same.
> 
> I agree. Creating hierarchies of error "types" seems fragile to me.
> 

The other problem (an extension of “fragile”) is error objects when more than 
one global object/realm is involved.  Once you’re in that scenario type 
selection (e.g. making use of |instanceof|) can no longer be used in any 
meaningful way.

—Oliver

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


Re: Promise.cast and Promise.resolve

2014-02-05 Thread Tab Atkins Jr.
On Wed, Feb 5, 2014 at 11:17 AM, Mark S. Miller  wrote:
> Unfortunately, just as Yehuda was not there in September and did not agree
> to the consensus then, Andreas was not there on Thursday of January and
> (above in this thread) does not agree to that consensus. This indicates a
> different failure mode we should be concerned about. Not everyone is at
> every meeting. If anyone absent from any meeting can veto the hard-won
> consensus achieved by those who did attend, it is hard to see how to make
> progress. OTOH, without this dynamic, we might proceed despite strongly held
> objections, which really is not consensus. Only our insistence on true
> consensus has saved us from prior disasters like ES4. I really don't know
> what to do about this.

The W3C treats in-person consensus as only a weak consensus (at least,
in most working groups, most of the time).  Async consensus is the
only one that's worthwhile, because it avoids problems like this, plus
allows people more time to think through issues than they might get
when put on the spot during a meeting.

Note, though, that you can still have consensus *and* strong
objections.  Design-by-committee is still a failure mode to be
avoided.

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


Re: Promise.cast and Promise.resolve

2014-02-05 Thread Mark S. Miller
On Wed, Feb 5, 2014 at 10:34 AM, Andreas Rossberg wrote:

> On 5 February 2014 18:35, Domenic Denicola 
> wrote:
> > The evolution of DOM and ES promises, and the related fragile
> consensuses, has been an involved process.
> >
> > Going back to the source documents, consider what the May AP2
> proto-consensus really is: "Abashed Monadic Promises 2," from [Mark's
> presentation][1], page 18. Using modern terminology, this consisted of
> "resolve," "then," "accept," and "flatMap" (monads+promises, for short).
> The outcome of that meeting was that the DOM would proceed with
> standardizing the subset of AP2 that it needs, namely "resolve" and "then"
> (promises, for short).
>
> Just to be clear, that is not my recollection at all.
>
> I'm still puzzled where this interpretation of the consensus came in.
> I was present in both respective meetings and don't remember this ever
> being said. Nor does anybody else I asked so far. It's not in the
> notes either. OTOH, I know that several participants have been under
> the assumption that the consensus was to include all of AP2 in ES6.
> That includes Mark, btw.
>
> Sorry to dwell on this, but this misunderstanding is what I find
> particularly irritating.
>

I don't want to dwell on this either. Different people do indeed have
different memories of both of the crucial meetings. And AFAIK, the notes do
not adequately resolve the memory disputes. But just for the record, my
memory regarding the memory-conflict issues are:

At the end of May mtg, the consensus compromise was actually AP3. This
rapidly fell apart due to discussion of its consequences on es-discuss,
where AP2 was (correctly IMO) seen as strictly superior to AP3.

At the end of Sept mtg, my memory of the state on entry to the meeting
agrees completely with Domenic's. On exit, my memory is

a) We had agreed to promote both the .then level and the .chain level to
ES6. (This is probably the biggest disagreement among the memory of the
attendees.)
b) At the .then level, we agreed essentially to promises-unwrapping as it
was at the time, which did one-level unwrapping of the output side of .then
by use of internal properties. (Or what Domenic now characterizes as "by
magic".)
c) Domenic and Allen had talked about subclassing, and Domenic came up with
a nice subclassing proposal that kept this "by magic" unwrapping.

After the September mtg

Yehuda did not attend the end-of-Sept mtg, and afterwards rejected the "by
magic" unwrapping as hostile to subclassing goals I have yet to understand.
Domenic responded by changing the output unwrapping of .then to use .then,
which, as Kevin correctly points out, broke the AP2 consensus.

However, at my urging, Domenic initiated a private thread with the main
.chain level advocates, including IIRC Andreas, Sam, and Tab, to see if any
objected to the switch to .then doing unwrapping by use of .then. I was
privately shocked that none did. At this point, perhaps I did the community
a disservice by staying silent, and not pointing out more forcefully to the
.chain advocates why they should object to this switch. But since
* they were not objecting,
* the switch only harmed properties that they care about and none that I
care about,
* we knew of no way to restore the AP2 consensus and also achieve Yehuda's
subclassing goals
I did stay silent until this problem was independently noticed by Kevin and
brought to my attention and (at my urging) Domenic's attention as well.

Kevin's suggested a good way to meet all goals simultaneously. If we were
still trying to do AP2, I think it would be worth considering:

* On the output side of .then, still use some kind of nominalish type test
to recognize whether the callback has returned a promise.
* If it has, rather than use so-called "magic" to unwrap it one level, use
that Promise's .chain.

By calling the returned promise's .chain rather than .then, we preserve the
one-level unwrapping of AP2. By calling its .chain rather than accessing
its internal properties, we preserve the subclassing flexibility Yehuda
wants. If we were still going to do the standards committee "do both"
failure mode, Kevin's suggestion is the best way I've seen to reconcile all
the conflicting demands.

At Thursday of the end-of-January meeting, everyone there including the
.chain advocates agreed to avoid the do-both compromise, and just adopt the
.then level. This was an excellent decision, and one much better than I
thought could be achieved.


THE BIGGER ISSUE

Unfortunately, just as Yehuda was not there in September and did not agree
to the consensus then, Andreas was not there on Thursday of January and
(above in this thread) does not agree to that consensus. This indicates a
different failure mode we should be concerned about. Not everyone is at
every meeting. If anyone absent from any meeting can veto the hard-won
consensus achieved by those who did attend, it is hard to see how to make
progress. OTOH, without this dynamic, we might proceed despite str

Re: Promise.cast and Promise.resolve

2014-02-05 Thread Brendan Eich

Sam Tobin-Hochstadt wrote:

Just to be clear, that is not my recollection at all.


For whatever the history is worth, this is also not my recollection of
the consensus in May.


Rashomon.

Who is the Woodcutter?

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


Re: Promise.cast and Promise.resolve

2014-02-05 Thread Sam Tobin-Hochstadt
On Wed, Feb 5, 2014 at 1:34 PM, Andreas Rossberg  wrote:
> On 5 February 2014 18:35, Domenic Denicola  
> wrote:
>> The evolution of DOM and ES promises, and the related fragile consensuses, 
>> has been an involved process.
>>
>> Going back to the source documents, consider what the May AP2 
>> proto-consensus really is: "Abashed Monadic Promises 2," from [Mark's 
>> presentation][1], page 18. Using modern terminology, this consisted of 
>> "resolve," "then," "accept," and "flatMap" (monads+promises, for short). The 
>> outcome of that meeting was that the DOM would proceed with standardizing 
>> the subset of AP2 that it needs, namely "resolve" and "then" (promises, for 
>> short).
>
> Just to be clear, that is not my recollection at all.

For whatever the history is worth, this is also not my recollection of
the consensus in May. In particular, in May my memory is that we
decided on a _single_ constructor (ie, not both of "resolve" and
"accept"), and that there wasn't any discussion or consensus for DOM
to do something else.

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


Re: Promise.cast and Promise.resolve

2014-02-05 Thread Andreas Rossberg
On 5 February 2014 18:35, Domenic Denicola  wrote:
> The evolution of DOM and ES promises, and the related fragile consensuses, 
> has been an involved process.
>
> Going back to the source documents, consider what the May AP2 proto-consensus 
> really is: "Abashed Monadic Promises 2," from [Mark's presentation][1], page 
> 18. Using modern terminology, this consisted of "resolve," "then," "accept," 
> and "flatMap" (monads+promises, for short). The outcome of that meeting was 
> that the DOM would proceed with standardizing the subset of AP2 that it 
> needs, namely "resolve" and "then" (promises, for short).

Just to be clear, that is not my recollection at all.

I'm still puzzled where this interpretation of the consensus came in.
I was present in both respective meetings and don't remember this ever
being said. Nor does anybody else I asked so far. It's not in the
notes either. OTOH, I know that several participants have been under
the assumption that the consensus was to include all of AP2 in ES6.
That includes Mark, btw.

Sorry to dwell on this, but this misunderstanding is what I find
particularly irritating.

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


Re: Specification styles

2014-02-05 Thread Boris Zbarsky

On 2/5/14 1:02 PM, Kevin Reid wrote:

suppose that in windowB we previously evaluated
 function later(f, ...as) { setTimeout(function() { f(...as); }, 0); }
and then in windowA we do
 proxyForB.later(proxyForB.postMessage, 5, "*");
then if I understand your description correctly, this would perform a
postMesage from B's origin.


Correct.  In fact, you don't even need the setTimeout.  Just this in 
windowB:


  function doNow(f, ...as) {
f(...as);
  }

and then windowA doing:

  proxyForB.doNow(proxyForB.postMessage, 5, "*")

would have the same effect: the message would seem to come from windowB...


In particular, what if "later" instead is something that is built-in,
_not_ defined by the DOM, but has the effect of calling a function
passed in?


The way HTML5 attempts to define things right now is that if your 
"later" or my "doNow" is built-in as opposed to explicitly written in 
script then the message will come from window A.


This is unfortunately gross, I agree...


there needs to be a well-defined and preferably sensible
decision about what happens upon something like:

proxyForB.Array.prototype.forEach.call([5], proxyForB.postMessage);


Right.  That's what led to the concept of the script settings stack...

The behavior here is in fact well-defined-ish, but it relies on this 
distinction between scripted and built-in functions.  I believe the 
relevant text at 
http://www.whatwg.org/specs/web-apps/current-work/multipage/webappapis.html#calling-scripts 
is this:


  When a JavaScript SourceElements production is to be
  evaluated, the settings object of the script corresponding to
  that SourceElements must be pushed onto the stack of script
  settings objects before the evaluation begins, and popped when
  the evaluation ends (regardless of whether it's an abrupt
  completion or not).

Again, this doesn't so much make me happy; it's just the best people 
have come up with so far.


In this case, since there is no SourceElements involved in 
Array.prototype.forEach (lots of handwaving involved in _that_ claim!) 
there would be no change to the script settings stack when forEach is 
invoked, so the message would be posted in the same way as if the 
forEach caller had directly invoked postMessage.


Yes, this means that if you replace forEach with a scripted version you 
get different behavior.  :( I'd love a consistent proposal that avoids 
that problem that browsers that aren't currently using any sort of 
membranes for their DOM are actually willing to implement.


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


Re: Promise.cast and Promise.resolve

2014-02-05 Thread Brendan Eich

Domenic Denicola wrote:

The amount of heat Kevin has piled on to promises-unwrapping, repeatedly, has 
been puzzling and unwarranted, but I have chosen mostly to set it aside, as the 
words of someone who did not care to understand the whole history and design 
constraints involved in writing this spec.


Apologies for seeming to side with Kevin's "shenanigans", that's the 
wrong word. I shouldn't have cited it without noting how it usually 
implies bad intent. What I was reacting too, perhaps Kevin is as well, 
is the difficulty in getting something seemingly simple (as library 
code) standardized.


And you're right, there was a lot of hard work to get to where we are. 
Thanks for all you've done. I am in no position to complain, having 
stayed away from the long promises threads over the last many months, 
mostly.


But (and I fell for this too, no excuses) combining two conflicting APIs 
into one proposal was always a mistake.


Andreas R. argues we can live with the over-wrapping in resolve, and 
seems to argue that my higher priority points (1, committee "do both" 
error; 2, .all etc. use .then not .chain) are either not problems or 
minor enough to live with.


Ron Buckton just proposed a "do both" solution that is at least properly 
parameterized in the constructor, so combinators (2) work. But it's 
still a stinking optional state flag that forks runtime semantics and 
API reasoning chains (1), creating bug habitat and probably pleasing no 
one much.


My "realism" argument seems strong, and your summary backs it: DOM was 
only using .then and .resolve, that's all they needed. That's all 
library Promise users use, in general (please correct me if I'm wrong). 
That is what Promises "are" in a real sense that constrains our 
standards efforts for ES6 and the DOM.


HTH, and thanks again for all your work.

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


Re: Specification styles

2014-02-05 Thread Kevin Reid
On Tue, Feb 4, 2014 at 9:21 AM, Boris Zbarsky  wrote:

> On 2/4/14 12:08 PM, Kevin Reid wrote:
>
>> Could not this be done while matching the above principle as follows?
>>
>> proxyForB, or more precisely the proxy for the function object
>> (windowB.postMessage), does not actually invoke windowB.postMessage
>> itself but a corresponding "post message from origin A" function.
>>
>
> That's actually pretty complicated.  Now you have two not-object-identical
> representations of windowB.postMessage in the scope of windowB, no?  The
> current membrane in SpiderMonkey has a single per-global representation of
> each object, for sanity's sake.  As a simple example, consider this code in
> window A:
>
>   proxyForB.setTimeout(proxyForB.postMessage, 0, 5, "*");
>
> What function object should the setTimeout implementation see?  What
> should happen when the timeout fires?


You point out that this is indeed more complicated to get “right” than I
had realized. I think it could still be done but things like setTimeout
would have to be proxied in the same way.

This arguably shows that the legacy policy is even more of a bad idea,
though, because it breaks a property kind of like TCP (I don't know a name
for it offhand, but it's related to the confused deputy). For example,
suppose that in windowB we previously evaluated
function later(f, ...as) { setTimeout(function() { f(...as); }, 0); }
and then in windowA we do
proxyForB.later(proxyForB.postMessage, 5, "*");
then if I understand your description correctly, this would perform a
postMesage from B's origin. But why should it, just because there's an
intervening user-defined HOF?

In particular, what if "later" instead is something that is built-in, _not_
defined by the DOM, but has the effect of calling a function passed in?
Whether or not one were to implement the mechanics in the way I propose,
there needs to be a well-defined and preferably sensible decision about
what happens upon something like:

proxyForB.Array.prototype.forEach.call([5], proxyForB.postMessage);
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


RE: Promise.cast and Promise.resolve

2014-02-05 Thread Domenic Denicola
From: es-discuss [mailto:es-discuss-boun...@mozilla.org] On Behalf Of Brendan 
Eich

> Kevin Smith wrote:
>> So basically, since September, we've seen:
>>
>> - A design proposal which achieved "consensus"
>> - A spec implementation which completely ignored that "consensus"
>> - And now a third design, which also throws out "consensus" and has 
>> been implemented by precisely no-one
>>
>> And all of this over 200 to 300 LOC.
>>
>> These shenanigans are deeply disturbing.
>
> I agree. I kept my nose out of it until it was front-and-center on the last 
> day of the last TC39 meeting, and in context of threads here that were 
> pushing (I was on side with you) to add .chain.
>
> The design proposal in September did not have consensus, for real. That 
> proposal was changed after the September meeting (Mark has details). The 
> implementation in V8 then added .chain based on an understanding from the May 
> 2013 meeting (multiple, "Rashomon" views of consensus).
>
> There's still some concern about supporting Promise subclassing, too, but I 
> think it can be handled without controversy (I could be wrong). It entails 
> using the public-named methods (in case of overrides) consistently, and not 
> using internal methods or other such shortcuts some of the time. Basically 
> "always use .then".

Like Mark, I've been mostly not engaging due to the lack of original points 
being raised. But I think it's important not to let Kevin's mischaracterization 
of the situation stand on the record, especially as it denigrates the hard work 
done by the many involved parties to come up with a workable promises design 
that meets all constraints, relegating it to such phrases as "shenanigans" and 
"200 to 300 LOC."

The evolution of DOM and ES promises, and the related fragile consensuses, has 
been an involved process.

Going back to the source documents, consider what the May AP2 proto-consensus 
really is: "Abashed Monadic Promises 2," from [Mark's presentation][1], page 
18. Using modern terminology, this consisted of "resolve," "then," "accept," 
and "flatMap" (monads+promises, for short). The outcome of that meeting was 
that the DOM would proceed with standardizing the subset of AP2 that it needs, 
namely "resolve" and "then" (promises, for short).

This resulted in the work at domenic/promises-unwrapping, which was targeted 
for the DOM. Coming to the September meeting, the documented that was 
distributed beforehand and presented was [this revision][2]. Committee members 
reviewed this document---some beforehand as per the agenda, some seemingly at 
the meeting---and declared it was a good subset to proceed with and would not 
prevent future problems if ES7 wanted to standardize monads+promises on top of 
the DOM's standard promises.

Dave Herman made the bold suggestion that promises, as they were, would be 
useful for the module loader API, and that the spec was in good enough shape 
that we could move it from the DOM into ES6. This was accepted, and as such 
domenic/promises-unwrapping at the time was declared as September consensus for 
ES6 promises. My understanding of that meeting was that the September consensus 
was for ES6 promises, and that everyone in the room understood that. But I have 
heard conflicting accounts from people who were also in the room, who believed 
that the September consensus was for ES6 monads+promises. At the same time, 
others have told me that they understood the September consensus to be for 
promises, and would not have declared consensus if they were being told to 
agree on monads+promises. So we can already see how the "consensus" did not 
have consensus, for real, as Brendan puts it.

That aside, let us consider Kevin's allegations about 
domenic/promises-unwrapping. At this point we have to say some words about the 
amount of work that goes in to producing a fully functioning spec, that 
respects all the constraints. Let those words be: it is nontrivial.

Thus, it may come as no surprise that the version presented at the September 
meeting was not perfect. In particular, it had two large related problems:

- It had not even the most naïve support for subclassing (cf. `Array` and 
`Date`, pre-ES6: the `Array.prototype.map` problem, the 
`Array.prototype.concat` problem, and the `(new (class extends 
Date)).getTime()` problem, all solved in ES6)
- It created a new class of magic-objects with hidden, inaccessible, 
un-proxyable, internal state (cf. `Date`, still not solved in ES6)

Both of these stemmed from, essentially, overuse of magic abstract operations 
and internal slots. This was yet another consensus-blocker, as discussions with 
several committee members revealed; another such object would never be allowed 
into ES6. So we had to do some work to reduce the reliance on magic, and move 
toward the usage of public APIs (viz. `then`), for accessing the state of other 
promises.

This resulted in a few design revisions, largely based on the work of Andreas 
Rossberg in his

RE: Promise.cast and Promise.resolve

2014-02-05 Thread Ron Buckton
Perhaps the unwrapping behavior of .then could be specified as an optional 
argument in the Promise constructor and .resolve methods.  The default behavior 
is the current standard (i.e. .then auto-unwraps), but a different behavior 
could be specified:

```
var unwrapPromise1 = Promise.resolve(1);
var unwrapPromise2 = Promise.resolve(unwrapPromise);
unwrapPromise2.then(value => { 
  assert(value === 1); // unwraps
}) 

var flatPromise1 = Promise.resolve(1, "flat"); // or some other indicator of a 
monadic promise
var flatPromise2 = Promise.resolve(flatPromise1, "flat"); 
flatPromise2.then(value => { 
  assert(value === flatPromise1);
}) 

var mixedPromise = unwrapPromise2.then(value => flatPromise2);
mixedPromise.then(value => { 
  assert(value === flatPromise1); // mixedPromise's unwrapping stops at 
flatPromise1 as it starts to unwrap flatPromise2 but stops unwrapping due to 
the defined behavior. 
  return value;
}).then(value => {
  assert(value === flatPromise1); // Since the previous .then was unwrapped 
into a "flat" promise, chained .then calls remain "flat". 
});
```

Basically, unwrapping of .then stops once the monadic behavior is reached.  
This would work for Promise.all/Promise.race as well since they could respect 
this behavior.  This has the added benefit of specifying Promises with a 
minimal API surface that auto-unwrap for ES6, but add optional arguments to the 
constructor and .resolve for ES7 or later to specify this behavior. As far as 
the Promise consumer is concerned, when they use .then, they will get the 
result the Promise producer expects them to get (the final underlying value in 
the common use case, or a possible promise in the monadic case).  The API 
surface area does not change, and monadic promises become an opt-in for those 
that need the specialized case.

Best regards,
Ron

> -Original Message-
> From: es-discuss [mailto:es-discuss-boun...@mozilla.org] On Behalf Of
> Brendan Eich
> Sent: Wednesday, February 5, 2014 7:46 AM
> To: Quildreen Motta
> Cc: Mark S. Miller; EcmaScript
> Subject: Re: Promise.cast and Promise.resolve
> 
> Quildreen Motta wrote:
> > but as with other parts of JavaScript, the simpler, orthogonal
> > primitives are not available for users to derive more complex
> > functionality from easily.
> 
> So true. JS is like a mini-toolkit of three-tool Swiss Army Knife
> (functions) with constructor and closure tools as well as the big first-class
> function edged tool; and super-caulk (objects) usable in a pinch as adhesive
> as well as sealant. Kind of what you want when you are traveling light, in a
> hurry running from zombies, no time to get a proper toolbox.
> 
> Part of TC39's work has been decomposing some of the multi-tools into new
> forms that do one thing well (arrow functions are my favorite in this regard).
> But it is both hard to justify the effort, and actually a lot of effort, to
> decompose fully in all cases.
> 
> Still I agree with Paolo. If we had functional (even value-like, featureless,
> then-able only via a special form, as in E) Futures, we could rebuild Promises
> on them and let Promises remain the library they've always been.
> 
> /be
> ___
> 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: Promise.cast and Promise.resolve

2014-02-05 Thread Andreas Rossberg
I really regret that I couldn't be there on the last day of the
meeting, and share the frustration I hear in this thread. I honestly
have a hard time viewing this as a "consensus", if for nothing else
than that I do not consent. :)

For the record, let me repeat what I wrote in a private conversation
with Brendan the other day:

"This destroys the fragile consensus we had built last May, on which
my and others' consent to moving forward with the spec work had been
based since then. I am deeply concerned how a strategy of (largely)
ignoring that consensus and creating a different precedent instead has
been successful here.

I don't buy the over-wrapping argument. I doubt it will be an issue in
practice, for the same reason that recursive unwrapping is rarely
needed in practice. The committee is prematurely optimising for the
odd case out that can always be avoided by [careful] design. On the
other hand, I'm far more concerned about the cost that the unwrapping
and thenable-assimilation machinery imposes on the _common_ case, and
which can _not_ be avoided (lacking .chain).

A [separate] library would be dead on arrival, especially since the
DOM and other libraries won't use it. It wouldn't even allow you to
hygienicly wrap them, since you'd always have to go through the
tainted operations.

Anyway, we've discussed this briefly in the V8 team and decided to
keep the .chain method in V8. We've heard enough voices, from inside
and outside Google, who dislike the spec'ed API and much rather use
chain. Unfortunately, you cannot polyfill it...
"

To add to that, I don't view the "double functionality" as a serious
issue either. Chain is the (compositional) primitive, .then is a
convenience abstraction on top. We have plenty of those in the lib.

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


Re: Promise.cast and Promise.resolve

2014-02-05 Thread Brendan Eich

Quildreen Motta wrote:
but as with other parts of JavaScript, the simpler, orthogonal 
primitives are not available for users to derive more complex 
functionality from easily. 


So true. JS is like a mini-toolkit of three-tool Swiss Army Knife 
(functions) with constructor and closure tools as well as the big 
first-class function edged tool; and super-caulk (objects) usable in a 
pinch as adhesive as well as sealant. Kind of what you want when you are 
traveling light, in a hurry running from zombies, no time to get a 
proper toolbox.


Part of TC39's work has been decomposing some of the multi-tools into 
new forms that do one thing well (arrow functions are my favorite in 
this regard). But it is both hard to justify the effort, and actually a 
lot of effort, to decompose fully in all cases.


Still I agree with Paolo. If we had functional (even value-like, 
featureless, then-able only via a special form, as in E) Futures, we 
could rebuild Promises on them and let Promises remain the library 
they've always been.


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


Re: Promise.cast and Promise.resolve

2014-02-05 Thread Brendan Eich

Paolo Amadini wrote:

I think the conclusion of using two distinct objects for that
(with the other named FuctionalPromise, Future, or anything else)
resolves the issue. Imperative Promise implementations may use those
alternative primitives internally.


+1

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


Re: Promise.cast and Promise.resolve

2014-02-05 Thread Quildreen Motta
I can understand the "you can't have your cake and eat it too" sentiment.
Indeed, I do think that having `.then()` and `.chain()` in the spec is a
mistake. The only thing that saddens me (and this also with some other
parts of the spec, such as Object.create) is that `.then()` is not an
orthogonal and composable primitive, it's a multi-method on top of simpler
primitives, but as with other parts of JavaScript, the simpler, orthogonal
primitives are not available for users to derive more complex functionality
from easily. That is, these higher-level primitives provide support to a
class of higher-level use cases, but not the necessary basis to support
these use cases in general, and this is a bummer for modularity and
re-usability. More so, I do think that just following de-facto standards
without acknowledging that there might be "bugs" on them you want to fix
when they are cheap to do so (i.e.: now, rather than after it becomes
standard) really bothers me. Fixing libraries today, specially with a
relatively new thing such as Promises/A+ is relatively "cheap."

At any rate, I'm just venting now, and I agree that the spec should only
support either one or the other (even if `.then()` is just a combinator,
the addition of it on the specs would lead to unnecessary headache, since
it doesn't compose cleanly with other constructs). I am just sad that the
specs are once again favouring the higher-level, limited use cases.


On 5 February 2014 12:39, Mark S. Miller  wrote:

>
>
>
> On Wed, Feb 5, 2014 at 6:37 AM, Mark S. Miller  wrote:
>
>> On Wed, Feb 5, 2014 at 12:43 AM, Brendan Eich wrote:
>>
>>> Kevin Smith wrote:
>>>


 - Promise.cast is renamed to Promise.resolve (remove old
 Promise.resolve)
 - Keep then, reject chain (NOT DEFER, reject!)
 - Renaming .cast thus removes over-wrapping (always-wrap)
 deoptimization in old Promise.resolve

 So basically, since September, we've seen:

 - A design proposal which achieved "consensus"
 - A spec implementation which completely ignored that "consensus"
 - And now a third design, which also throws out "consensus" and has
 been implemented by precisely no-one

 And all of this over 200 to 300 LOC.

 These shenanigans are deeply disturbing.

>>>
>>> I agree. I kept my nose out of it until it was front-and-center on the
>>> last day of the last TC39 meeting, and in context of threads here that were
>>> pushing (I was on side with you) to add .chain.
>>>
>>> The design proposal in September did not have consensus, for real. That
>>> proposal was changed after the September meeting (Mark has details). The
>>> implementation in V8 then added .chain based on an understanding from the
>>> May 2013 meeting (multiple, "Rashomon" views of consensus).
>>>
>>> There's still some concern about supporting Promise subclassing, too,
>>> but I think it can be handled without controversy (I could be wrong). It
>>> entails using the public-named methods (in case of overrides) consistently,
>>> and not using internal methods or other such shortcuts some of the time.
>>> Basically "always use .then".
>>>
>>> Can we regain consensus on the September status quo ante, minus any "do
>>> both" half-hearted compromises that don't work? Mark, what do you think?
>>
>>
>> I see no need to reopen this yet again. At this last meeting, we declared
>> a new consensus, to keep the .cast and .then level, dispense with the
>> .accept (previously renamed .resolve) and .chain level, and to rename .cast
>> to .resolve.
>>
>> This kills the September AP2 consensus, in that we are no longer
>> constraining the .then level's mechanics to be compatible with introducing
>> (whether now or in the future) a .chain level. The September consensus was
>> a compromise, in the "do both" mode that standards committees are tempted
>> by. I have a deeper appreciation of those temptations now, having promoted
>> it at the time. Given that we were trying to do both, Todd's AP2 was a
>> wonderful way to minimize the pain. But I am now proud to see our committee
>> once again rise above the "do both" failure mode.
>>
>> IMO, the most important argument against "do both" is that it would lead
>> to perpetual confusion, as some libraries are written to the .then style
>> and others are written to the .chain style. With AP2, these would live
>> together as well as possible, but that's still not well.
>>
>> Regarding the comments in this thread, I haven't engaged since I have not
>> seen any new points raised. All the old arguments are publicly archived. If
>> you're about to repost a previously posted argument, please instead just go
>> read the previously posted response. No one convinced anyone of very much
>> that time, and repetition is unlikely to do better.
>>
>> The one remaining open issue for me is the means of flattening the output
>> side of a .then operation. The end-of-september "consensus" flattened one
>> level, but nom

Re: Promise.cast and Promise.resolve

2014-02-05 Thread Mark S. Miller
On Wed, Feb 5, 2014 at 6:37 AM, Mark S. Miller  wrote:

> On Wed, Feb 5, 2014 at 12:43 AM, Brendan Eich  wrote:
>
>> Kevin Smith wrote:
>>
>>>
>>>
>>> - Promise.cast is renamed to Promise.resolve (remove old
>>> Promise.resolve)
>>> - Keep then, reject chain (NOT DEFER, reject!)
>>> - Renaming .cast thus removes over-wrapping (always-wrap)
>>> deoptimization in old Promise.resolve
>>>
>>> So basically, since September, we've seen:
>>>
>>> - A design proposal which achieved "consensus"
>>> - A spec implementation which completely ignored that "consensus"
>>> - And now a third design, which also throws out "consensus" and has been
>>> implemented by precisely no-one
>>>
>>> And all of this over 200 to 300 LOC.
>>>
>>> These shenanigans are deeply disturbing.
>>>
>>
>> I agree. I kept my nose out of it until it was front-and-center on the
>> last day of the last TC39 meeting, and in context of threads here that were
>> pushing (I was on side with you) to add .chain.
>>
>> The design proposal in September did not have consensus, for real. That
>> proposal was changed after the September meeting (Mark has details). The
>> implementation in V8 then added .chain based on an understanding from the
>> May 2013 meeting (multiple, "Rashomon" views of consensus).
>>
>> There's still some concern about supporting Promise subclassing, too, but
>> I think it can be handled without controversy (I could be wrong). It
>> entails using the public-named methods (in case of overrides) consistently,
>> and not using internal methods or other such shortcuts some of the time.
>> Basically "always use .then".
>>
>> Can we regain consensus on the September status quo ante, minus any "do
>> both" half-hearted compromises that don't work? Mark, what do you think?
>
>
> I see no need to reopen this yet again. At this last meeting, we declared
> a new consensus, to keep the .cast and .then level, dispense with the
> .accept (previously renamed .resolve) and .chain level, and to rename .cast
> to .resolve.
>
> This kills the September AP2 consensus, in that we are no longer
> constraining the .then level's mechanics to be compatible with introducing
> (whether now or in the future) a .chain level. The September consensus was
> a compromise, in the "do both" mode that standards committees are tempted
> by. I have a deeper appreciation of those temptations now, having promoted
> it at the time. Given that we were trying to do both, Todd's AP2 was a
> wonderful way to minimize the pain. But I am now proud to see our committee
> once again rise above the "do both" failure mode.
>
> IMO, the most important argument against "do both" is that it would lead
> to perpetual confusion, as some libraries are written to the .then style
> and others are written to the .chain style. With AP2, these would live
> together as well as possible, but that's still not well.
>
> Regarding the comments in this thread, I haven't engaged since I have not
> seen any new points raised. All the old arguments are publicly archived. If
> you're about to repost a previously posted argument, please instead just go
> read the previously posted response. No one convinced anyone of very much
> that time, and repetition is unlikely to do better.
>
> The one remaining open issue for me is the means of flattening the output
> side of a .then operation. The end-of-september "consensus" flattened one
> level, but nominal typing and use of internal properties.
>

Should be

*by* nominal typing and use of internal properties.



> The current spec flattens using .then. The change was made to make
> subclassing more flexible in ways I have yet to appreciate. But since we
> are no longer trying to co-exist with .chain, now or in the future, I no
> longer object to using .then for the output flattening of .then. I am fine
> with the .then spec as currently written, in the context of the rest of our
> decisions at the end of January meeting.
>
>
>>
>> /be
>>
>
>
>
> --
> Cheers,
> --MarkM
>



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


Re: Promise.cast and Promise.resolve

2014-02-05 Thread Mark S. Miller
On Wed, Feb 5, 2014 at 12:43 AM, Brendan Eich  wrote:

> Kevin Smith wrote:
>
>>
>>
>> - Promise.cast is renamed to Promise.resolve (remove old
>> Promise.resolve)
>> - Keep then, reject chain (NOT DEFER, reject!)
>> - Renaming .cast thus removes over-wrapping (always-wrap)
>> deoptimization in old Promise.resolve
>>
>> So basically, since September, we've seen:
>>
>> - A design proposal which achieved "consensus"
>> - A spec implementation which completely ignored that "consensus"
>> - And now a third design, which also throws out "consensus" and has been
>> implemented by precisely no-one
>>
>> And all of this over 200 to 300 LOC.
>>
>> These shenanigans are deeply disturbing.
>>
>
> I agree. I kept my nose out of it until it was front-and-center on the
> last day of the last TC39 meeting, and in context of threads here that were
> pushing (I was on side with you) to add .chain.
>
> The design proposal in September did not have consensus, for real. That
> proposal was changed after the September meeting (Mark has details). The
> implementation in V8 then added .chain based on an understanding from the
> May 2013 meeting (multiple, "Rashomon" views of consensus).
>
> There's still some concern about supporting Promise subclassing, too, but
> I think it can be handled without controversy (I could be wrong). It
> entails using the public-named methods (in case of overrides) consistently,
> and not using internal methods or other such shortcuts some of the time.
> Basically "always use .then".
>
> Can we regain consensus on the September status quo ante, minus any "do
> both" half-hearted compromises that don't work? Mark, what do you think?


I see no need to reopen this yet again. At this last meeting, we declared a
new consensus, to keep the .cast and .then level, dispense with the .accept
(previously renamed .resolve) and .chain level, and to rename .cast to
.resolve.

This kills the September AP2 consensus, in that we are no longer
constraining the .then level's mechanics to be compatible with introducing
(whether now or in the future) a .chain level. The September consensus was
a compromise, in the "do both" mode that standards committees are tempted
by. I have a deeper appreciation of those temptations now, having promoted
it at the time. Given that we were trying to do both, Todd's AP2 was a
wonderful way to minimize the pain. But I am now proud to see our committee
once again rise above the "do both" failure mode.

IMO, the most important argument against "do both" is that it would lead to
perpetual confusion, as some libraries are written to the .then style and
others are written to the .chain style. With AP2, these would live together
as well as possible, but that's still not well.

Regarding the comments in this thread, I haven't engaged since I have not
seen any new points raised. All the old arguments are publicly archived. If
you're about to repost a previously posted argument, please instead just go
read the previously posted response. No one convinced anyone of very much
that time, and repetition is unlikely to do better.

The one remaining open issue for me is the means of flattening the output
side of a .then operation. The end-of-september "consensus" flattened one
level, but nominal typing and use of internal properties. The current spec
flattens using .then. The change was made to make subclassing more flexible
in ways I have yet to appreciate. But since we are no longer trying to
co-exist with .chain, now or in the future, I no longer object to using
.then for the output flattening of .then. I am fine with the .then spec as
currently written, in the context of the rest of our decisions at the end
of January meeting.


>
> /be
>



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


Re: Promise.cast and Promise.resolve

2014-02-05 Thread Paolo Amadini
On 05/02/2014 9.43, Brendan Eich wrote:
> Can we regain consensus on the September status quo ante, minus any "do
> both" half-hearted compromises that don't work? Mark, what do you think?

For what it's worth, I've been planning to file a bug on GitHub before
I saw the most recent conclusion, that dispelled my concerns.

My conclusion, deriving from the explanations of the design that I
received on this list (very informative by the way, thanks!) was that
"Promise objects for imperative and functional use should be distinct".

In fact, in the design I was concerned about, when calling a function
that returns a Promise object generated by code that uses "imperative"
promises (i.e. expects "then" to be used), a consumer that works with
"functional" promises (i.e. uses "chain") cannot reasonably know which
Promise type is returned, potentially leading to subtle bugs.

Consider this scenario, with a typical documentation of an opaque
imperative library: "The getResponse() method will return a Promise
resolved with the response string." Will getResponse return a
Promise(String) or a Promise(Promise(String))?

It may actually return one or the other. To be sure about the type when
used in a functional context, the promise will require unwrapping at
the boundary between the two usage styles. Using the same object for
both uses might lead to confusion and forgetting the unwrapping.

I think the conclusion of using two distinct objects for that
(with the other named FuctionalPromise, Future, or anything else)
resolves the issue. Imperative Promise implementations may use those
alternative primitives internally.

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


Re: Promise.cast and Promise.resolve

2014-02-05 Thread Brendan Eich

Kevin Smith wrote:



- Promise.cast is renamed to Promise.resolve (remove old
Promise.resolve)
- Keep then, reject chain (NOT DEFER, reject!)
- Renaming .cast thus removes over-wrapping (always-wrap)
deoptimization in old Promise.resolve

So basically, since September, we've seen:

- A design proposal which achieved "consensus"
- A spec implementation which completely ignored that "consensus"
- And now a third design, which also throws out "consensus" and has 
been implemented by precisely no-one


And all of this over 200 to 300 LOC.

These shenanigans are deeply disturbing.


I agree. I kept my nose out of it until it was front-and-center on the 
last day of the last TC39 meeting, and in context of threads here that 
were pushing (I was on side with you) to add .chain.


The design proposal in September did not have consensus, for real. That 
proposal was changed after the September meeting (Mark has details). The 
implementation in V8 then added .chain based on an understanding from 
the May 2013 meeting (multiple, "Rashomon" views of consensus).


There's still some concern about supporting Promise subclassing, too, 
but I think it can be handled without controversy (I could be wrong). It 
entails using the public-named methods (in case of overrides) 
consistently, and not using internal methods or other such shortcuts 
some of the time. Basically "always use .then".


Can we regain consensus on the September status quo ante, minus any "do 
both" half-hearted compromises that don't work? Mark, what do you think?


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


Re: Promise.cast and Promise.resolve

2014-02-05 Thread Kevin Smith
>
>
> - Promise.cast is renamed to Promise.resolve (remove old Promise.resolve)
> - Keep then, reject chain (NOT DEFER, reject!)
> - Renaming .cast thus removes over-wrapping (always-wrap) deoptimization
> in old Promise.resolve
>
>
So basically, since September, we've seen:

- A design proposal which achieved "consensus"
- A spec implementation which completely ignored that "consensus"
- And now a third design, which also throws out "consensus" and has been
implemented by precisely no-one

And all of this over 200 to 300 LOC.

These shenanigans are deeply disturbing.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Error objects in W3C APIs

2014-02-05 Thread Jonas Sicking
On Tue, Feb 4, 2014 at 9:49 AM, Domenic Denicola
 wrote:
> From: es-discuss  on behalf of Allen 
> Wirfs-Brock 
>
>> I've designed exception handling systems before and designed and worked with 
>> complex exception hierarchies. My main caveat is that they are somewhat of 
>> an attractive nuisance.  It's easy to get into designing  beautiful 
>> classification hierarchies of dozens of different kinds of exceptions, each 
>> with their own specific failure information that is captured. In practice, 
>> I've found very little actual utility for them.
>
> My (more limited) experience is the same.

I agree. Creating hierarchies of error "types" seems fragile to me.

A better approach seems like having a short list of flat error types.
In cases where it might be useful to have a more specific error type,
instead include additional information on the error. So for example,
rather than having a NetworkResourceNotFound error, use NetworkError
but add a property which indicate what type of network failure. Not
sure if that was what you were proposing with the "proximate cause"?
More on that below.

I think the general direction that we've been heading lately has been
pretty good. I.e. error types like NetworkError, QuotaExceededError
are descriptive and have clear use cases for code to catch and handle.

On the flip side, the DOM also has some overlapping errors that are
too specific. IndexSizeError should simply have been RangeError, no
need to use a separate exception because it was an index that was
out-of-range, rather than some other type of argument.

Then there's a bunch of errors which are unclear why you'd ever want
to catch them at runtime. For example HierarchyRequestError,
NotFoundError, NamespaceError and URLMismatchError is unclear to me
why you'd ever want to catch. It seems useful to provide detailed
information so that a developer is helped with understanding what went
wrong, but that can be done through the .message property. TypeError
is probably fine for many of these. Though I sort of hate its name and
would be happy to see something more descriptive become available.

> However, I think the utility that the DOM specs try to capture with their 
> errors is different than that captured by the exception hierarchy that one 
> might think of when looking at them. Let me set the stage:
>
> There seem to be a few possible properties of an exception that could be 
> varied depending on the situation:
>
> - The type. Typically this is very broad in ES, and in the DOM even more so 
> (everything is `DOMException`). In ES this is the same as the `.name` 
> property, but not in the DOM.
> - The category. ES has no such concept, but DOM specs use the `.name` 
> property for this, with a variety of generic categories like 
> "InvalidStateException," "NetworkError," etc. [1]

I'm not sure that there's a difference between these two. Or at least
I don't think there's a difference between the stuff that the DOM puts
in .name, and that ES puts in the classname. They express the same
thing just in different ways.

But that might not be relevant to your proposed solution.

> - The human-readable message. This is never specified, from what I can see.

I don't think we should specify the exact string that goes into these
messages. It's good if implementations are free to add additional
details if they see developers struggling with something.

But we could definitely do with more recommendations for
implementations about what information to include here.

> - The proximate cause. By this I mean the exact situation or line of the 
> relevant spec that caused the error to be thrown. Every such cause should be 
> distinguishable, even if they belong to the same category. Usually there will 
> be a one-to-one correspondence between human-readable messages (or message 
> format strings, with appropriate placeholders) and machine-readable proximate 
> causes. I've seen this rarely, but some parts of Node.js use error codes for 
> this.
>
> I have not seen much attention paid to the "proximate cause" idea in the 
> wild. But I think it is perhaps the most important. Allen's point about 
> hierarchies being largely useless resonates with me on the type and category 
> level. That is, even the DOM's more fine-grained exception categorization is 
> not that useful if I am trying to recover from a specific scenario. Whereas, 
> the ability to specify specific situations to recover from would be much more 
> fruitful.
>
> For a great example of these levels, see [recent discussions on the streams 
> repo][2]. We have two situations: writing to a closing stream, and writing to 
> a closed stream. On an ES level, these would end up as both `TypeError`s, as 
> [discussed][3], with no further distinguishing information besides 
> implementation-defined `message`. Working on a DOM level would be no 
> different, I think: both would likely become `DOMException`s with `name` of 
> `"InvalidStateError"`. What we really want is a mach