January 28th 2016 Meeting Notes
Rick Waldron
waldron.rick at gmail.com
Fri Feb 5 17:08:45 UTC 2016
January 28th 2016 Meeting Notes
Eric Farriauolo (EF), Caridy Patino (CP), Michael Ficarra (MF), Peter
Jensen (PJ), Domenic Denicola (DD), Jordan Harband (JHD), Chip Morningstar
(CM), Brian Terlson (BT), John Neumann (JN), Dave Herman (DH), Yehuda Katz
(YK), Jeff Morrison (JM), Lee Byron (LB), Daniel Ehrenberg (DE), Lars
Hansen (LH), Nagy Hostafa (NH), Michael Saboff (MS), John Buchanan (JB),
Stefan Penner (SP), Sebastian McKenzie (SMK), Waldemar Horwat (WH), MarkS.
Miller (MM), Sebastian Markbage (SM), Zibi Braniecki (ZB), Andreas Rossberg
(ARB), Ian Halliday (IH), Keith Miller (KM), Tim Disney (TD), Misko Hevery
(MH), Brad Green (BG), Kevin Smith (KS), Brad Nelson (BN), JF Bastien
(JFB), Shu-yu Guo (SYG), Rick Waldron (RW), Staś Małolepszy (STM), Dean
Tribble (DT)
## Agenda
https://github.com/tc39/agendas/blob/master/2016/01.md
## Function#toString && Function#isPortable (MF)
Slides:
https://docs.google.com/presentation/d/1o8jVhyVHljCFyXdxe-V4X1pUmCgx0FuFvEO0fFP4LJU/edit?usp=sharing
Spec text:
https://raw.githubusercontent.com/michaelficarra/Function-prototype-toString-revision/fc69a0a31dc6d625736bfbb712ac782eb241ff3d/proposal.html
MF: No longer interested in "portability"
YK: Do your changes cause a method with super to produce an evaluatable
function with .toString()
MF: No.
MF: < Presents new spec text >
MF: Either you are a bound function exotic object or other callable or
throw an error.
WH: What case does calling toString on Math.sin fall into?
MF: The last one: [native code].
AWB: What if I want Math.sin to be self-hosted in ECMAScript?
MF: Host can control the internal slot...
AWB: Not if it's an ecmascript function object. An ECMAScript function
object is an object that is created syntactically from ECMAScript code.
MF: implementation cna pretend there's a slot.
AWB: Concern is for self hosted built-ins you want them to be opaque.
MF: We can add a case for built-in functions. Is that something that we
want to do?
BT: We should mandate that built-in functions show [Native Code]
YK/MF: Agree.
AWB: Are implementations allowed to hide source code for ES functions?
YK: toString is a defacto reflection mechanism. Web depends on it.
AWB: Not all code runs on the web.
AWB: Seems like a value add.
MM: It would be a value add for an implementation not to support sloppy
mode.... but it can't claim to be conformant.
(Discussion of how imortant toString returning source is...)
BT: Bound functions should show [Native Code]
MF: Currently an option.
(Agreement that it should be required)
MF: Ok.
*discussion about what method name to use, and what if it isn't an
identifier*
MM: Don't use the current value of the name property.
WH: This won't solve the problem of it sometimes not being an identifier.
You can have a computed property name for a method that doesn't evaluate to
an identifier.
MM: Treat the [computedname] expression, instead of the string it evaluates
to, as part of the source code of the function?
WH: That's not really part of the source code of the function. It's part of
the context.
MM: It's the same situation as with class extends expressions.
YK: The fact that you can omit the extends clause is an issue.
?: Just use the original source's AST.
MM: Let them throw away comments.
?: What about calls to `new Function`?
WH: Don't want to require comments and whitespace to be preserved. And what
about comments on the boundary of the function (before the first token or
after the last one)? Are they part of the function or not?
*back and forth about preserving whitespace or not*
WH: Current engines are inconsistent about whitespace, even within one
implementation. Firefox sometimes preserves whitespace, sometimes doesn't.
Different implementations differ in many ways on this. Reiterate not
mandating preservation of whitespace and comments.
MM: Agree.
*later MM changed his mind again*
No consensus on whitespace treatment.
#### Conclusion/Resolution
Keep exactly the original source text starting from the position of the
first token of the production and ending at the position of the last token.
Within this text, keep comments and newlines. Still no conclusion about
insignificant whitespace, i.e., whitespace other than newlines.
- MF will adapt what was discussed into the spec text, advance stage 2 that
is complete
- Reviewers: MM, WH, YK
## larse
LH: slide (formal reviewers)
LH: looking for multiple reviewers
WH: I have memory model expertise and will review that aspect. Also suggest
having Hans Boehm look at it.
BT: this specification requires continent etc.
LH: it doesn't have to be deep, but we require some framework to be
in-place.
DE: any typed array designers inovled
AWB: me
DD: If he comes to us in afew months, and presents the API, we would prefer
to not then have to dig in
DD: last time the TC made changes quite late, it would be great to catch
those early
...
LH: some changes to the typed array spec, to accomodate SharedArrayBuffer,
should be vetted
AWB: I would be happy to discuss
#### Concluson/resolution
* DD DE AWB will be reviewers
Rundown of reviewers (from LH's notes):
- littledan will represent v8
- brian for chakra (but he will look for a delegate)
- unclear for jsc (LH will ask filip pizlo)
- waldemar for the memory model
- allen (informally possibly) for TypedArray changes
- domenic for agents/vats/whatever
LH: Also desirable for everyone to read the spec and pitch in, the more
eyeballs the better.
## 5.xix Proxy Enumerate - revisit decision to exhaust iterator
(Brian Terlson)
https://github.com/tc39/ecma262/issues/160
BT: issue with proxy enumerate trap and for-in, where iimplementations are
prevented from pre-populating the list of keys in the object, because the
iterator causes observable affects. Which means the iterate must be pulled
for every iteration. Last meeting we thought it would be ok if the
enumerate trap exhausts the iterator, we thought that would solve the
problem. The issue was, now their is an observable difference between an
object and proxy of that object, mainly due to delete.
AWB: thats wrong
AWB: if you doit as part of for-in it wont be a problem, as for-in can be
specified to ignore deleted keys.
BT: right now, for-in does not do a has-check for every property. If a key
is deleted, it wont be seen. That is how proxies in edge work today,
deleted keys (during enumeratino) are not visited.
BT: We could say, for-in (or proxy enumerate trap) will exhaust the
iterator and check on each iteration
ARB: that is what v8 does
BT: I dont want an observable difference for for-in
YK: the has check on a proxy is non-observable anyways, and often it can be
skipped anyways.
AWB: the classic spec if i recall, you cannot get a duplicate key, if
something is added during enumeration you may or may not see it, if it is
deleted before you enumerate it you must not see it.
ARB: enumerability is also something we need to take into account, I think
more issues exist, we should likely keep it vague.
YK: thats one approach, as we don't have this defined, maybe the proxy
needs to reflect the implementation
AWB: proxies can do very interesting things
YK: the enumerability is already quite hazardous, this isn't really
anything new.
MM: it seems like these rules could be specified, could we just do that?
MM: v8 on normal objects does snapshot + has check, but not post-snapshot
enumerability check.
YK: So far, we have spec'd this as vague, to allow divergence
MM: we should specify this,
BT: i will need to do some exploration
MM: does anyone, based on their implementation know that they would object
to specifying proxy + regular objects, the semantics of snapshot + has-check
BT: I would love that
MM: let's leave this to you to investigate, and a future meeting.
YK: we want this for es7
DE: can we get consensus on GH.
WH: Are we specifying a long delay before you get the first element if you
begin iterating on an array with a billion elements, even if you just want
the first few?
BT: yes we are, but we all do this already
ARB: one issue with snapshotting, is how does it relate to the prototype
chain
BT: yes this is under specified
YK: we should try to
AWB: the reason it was under specified was
BT: jscript?
AWB: ya sorta, minor variations among implementations. At that point in
time, consensus was dificult it seemed like we couldn't do this. If we
can, we should
BT: unsure
YK: if we can, we should
AWB: the other issue is: it isn't clear to me why we have an enumerate trap
BT + ARB: me neither
AWB: for-in has enough meta operations to define what we want.
MM: we should ask tom, as he thought this stuff out in great detail
DH: isn't that question too late?
DE: it isn't a web compat issue yet.
DH: it isn't obviously a mut question, but we may not be able to.
DH: i do not know how often this is used, isn't enumerate a fundamental
trap.
YK: i agree that is a thing
... discussion if enumerate is fundamental ...
YK: spidermonkey people have the strongest here
BT: We have internal users of proxies, we may have a constraint
YK: that isn't a constraint it can be deprecated,
BT: comes at as cost, but i doubt its actually used.
ARB: one reason for enumerate trap may be that the set of all properties is
larger then the set of properties that are enumerable, so a performance
difference is pssible.
YK: getOwnPropertyDescriptors + filter out enumerable, covers this
BT: what is the trap name for all property names .... getOwnPropertyNames
BT: should for-in just be implemented as that.
BT: we would get rid of enumerate trap
ARB: doesn't one return an iterator
AWB: i think the enumerate trap was the only MOP operation that returned
the iterator
...: if we have serious performance implementations for internal, we will
keep it, but wont expose it
BT: it might not be possible to... we will have to give an explicit
ordering for prototype properties.
AWB: the only way to doit, is to set some requirements, vague or not
#### Conclusion/Resolution
- provisional consensus to kill enumerate trap, contingent on running it
by tom
- for-in does [[HasProperty]]
************** Response from Tom: **************
A few things come to mind:
1) Faithful virtualization of the prototype chain. We decided that the
Proxy should always be in control of operations involving prototype
inheritance. This includes has, get, set and enumerate. For all of these
operations, when executed on a normal object, they will walk the prototype
chain until they hit a Proxy. After that point, full control is delegated
to the Proxy. If a Proxy would only be able to override get() and set() but
not enumerate(), this may lead to inconsistencies (without an enumerate()
trap, the VM will have to externally walk the prototype chain of the Proxy
via getPrototypeOf()).
2) When we designed Proxies originally, we made the design decision to map
many built-in operations directly to specific traps, even if these
operations could be expressed in terms of more fundamental operations (get,
set, has, enumerate are all examples here). The design argument here was
always improved performance by reducing the number of temporary allocations.
Much later in the design, others started pushing back on the number of
traps, leading us to reconsider some traps, e.g. I recall the "hasOwn" trap
was dropped in favor of checking whether (getOwnProperty() !== undefined),
even though it is strictly less efficient. I don't have a view on the
actual cost of expressing enumerate() in terms of lower-level MOP
operations, but it seems obvious that there will be more allocation costs
involved. The question is then: if enumerate() gets dropped on these
grounds, why not get(), set() and has()?
3) As far as I recall, enumerate() is the only trap that actually returns
an *iterator* over the property names, allowing efficient virtualization of
objects with a large (or potentially, infinite) number of properties. The
only other trap that returns a list of property keys, "ownKeys", returns a
manifest array of property names.
4) enumerate() had weaker invariants than ownKeys() [just like all the
traps that deal with prototype inheritance, since a frozen object can still
inherit from a non-frozen object, leading to weaker observable invariants
in general]. If one would express for-in in terms of repeated calls to
ownKeys(), the invariant check overhead may be substantial compared to just
calling enumerate().
Unless there are really good reasons to get rid of enumerate(), I think it
should remain in. For me, (1) and (3) are the killer arguments: consistency
with has(),get(),set() and efficient enumeration via iteration.
Feel free to forward this mail to TC39. I'm happy to engage in follow-up
discussions, just ping me when needed.
*********************************************************
## 5.xviii Exponentiation Operator (RW)
RW: i implemented the changes, tried to get brendan to review it (no luck).
BT reviewed, and chakra implements
RW: BT and I went over it line/line, followed up with new tests, and in the
last 20 minutes per domenics suggestion I duplicated the applying **
operater tests, so both map.pow and ** tests. the SM folks will be happy
that they all passed (except for one, but that's expected).
RW: chakra implements, applause for OSS chakra
RW: motion to include to stage 4, inclusion for 2016
BT: thanks rick
RW: any objections
#### Conclusion/Resolution
- stage 4!
(Lunch)
## Afternoon Agenda
1. Date and place for the next meetings
#### Conclusion/Resolution
Meet in Munich Monday May 23-Wednesday May 25
## 2. 402 needs reviewers (20min)
CP: HTML version of the second edition is now public (
www.ecma-international.org/ecma-402/2.0/), just like 262. We have done
some re-orgs on the spec to make the new features easier to include. Many
new features have been proposed, lots of new contributors, good momentum.
At this point we need reviewers
DE: first we need to propose to stage 2.
CP: we want to move 3 things up, and get reviewers, and one small detail
AWB: before we get to stage 2 things, what is the status of 2016 402. COuld
we have a summary of what is in 2016 402.
CP: it will be very small, some fixes related to locale parsing. One or two
functions, that will expose existing abstract operations.
AWB: are those written up, you know the schedule, that means by the next
meeting you have to be done
CP: yup
EF: we have one potential problem to discuss,
EF: slide edition 1 [[CALL] Behavior (Considered a Spec bug)
AWB: thats basically, at the time the spec was drafted that was how the
current thinking of internal slots to happen. This allowed internal state
to be dynamically added to instances, that was decided inappropriate, and
ultiamtely abondoned.
EF: the problem was, a library intl, format cache. using memoizing used
this pattern. This pattern was introduced in sept 2014. The issues rolled
in nov 2015.
EF: I fixed this in a patch release of the library
EF: slide (tl;dr of intl-format-cache dep on Edition 1 Behavior)
EF: slide (intl-format-cache at 2.0.5)
EF: slide (Potential Impact? (Excluding Yahoo's Usage)
EF: slide (ative wart removal)
EF: impact is likely large.
AWB: in addition 1 of 402, it was possible for a single object to be
multiply constructed, and get the private state of each constructor.
Hopefully no-one has done that
EF: ya, not our problem.
AWB: it occurs me, leaving it as addition 2, their is likely a work-around.
Specializing object.create for this pattern.
DE: no...
EF: slide (tl;dr of intl-format-cache dep on Editirion 1 behavior)
DE: if we can scope these changes to the intl functions, rather then
O.create
AWB: you don't want this to be in the spec. So what is the smallest thing
one can do to maintain the compat.
EF: we can also rollback the changes in 3, and see the impact.
EF: slide (active wart removal)
RW: the first addition was a mistake,
everyone agrees
RW: we fixed it because it was broken, the fact that library relied on the
brokeness is unfortunate. The only way to fix this is to re-break it.
DE: What should implementations do
MM: i think we can fix this
RW: @MM, did you review the comment i posted?
MM: please send me the link to review.
EF: presents comments on GH issue 57
...MM explores the code...
MM: what you do, is the call behavior of Intl.Collator if its sees an
object that inherits from Collator.prototype that is not a collator, it
creates a new Collator and uses a unique Symbol to hang that newCollator
off of that object. All the builtin Collator methods then checks whether
their alleged Collator argument is a non-Collator with a property named by
that Symbol. If so, it looks up the Collator state on the value of that
property, i.e., it forwards all state lookup to the value of that property.
A hack to deal with an emergency. No security issue here, so no problem
that the Symbol can be read and used for other purposes. No accidental
collisions, all the primitives must then detect the collator.
SP: this isolates the fallout
MM: it can be self hosted, after the emergency is over can be removed.
RW: (Agree)
YK: We may want to leave a note
AWB: Annex in 3rd Edition that explains the compatibility issue and how to
address it.
YK: as long as its in the actual spec we are good
EF: DE could google try Mark's suggestion of restricting .call's extra
behavior to just this case, on the output of Object.create for a given Intl
instance type this out?
DE: yes, it seems reasonable
#### Conclusion/Resolution
- wont roll it back
- try MM suggestion in chrome to support web compat
- add note to 402 annex (third edition, references second and first)
## 5.xix (Revisit) Proxy Enumerate - revisit decision to exhaust iterator
BT: Proxy.enumerate is removed, should Reflect.enumerate be removed?
JDH: it would be unfortunate
YK: I think its worth having a bucket that is 1:1 with the MOP operations,
reflect happens to do that. If we remove Proxy traps, MOP should also see a
similar removal.
AWB: it seems alot harder for Reflect.enumerate then Proxy enumerate trap
BT: the usecases for Reflect.enumerate outside of proxy enumerate trap
isn't very compelling. If we feel comfortable removing the proxy trap, we
should feel comfortable removing Reflect.enumerate
MM: i think you are correct, but if some interleaving between enumeration +
proxy traps
MM: cross browser web-pages, can't
JHD: polyfils have this
YK: they will continue to work
BT: any objection to remove Reflect.enumerate
MM: We need to check with Tom Van Cutsem first.
#### Conclusion/Resolution
- Remove Reflect.enumerate, contingent on further information from Tom
************** Response from Tom: **************
A few things come to mind:
1) Faithful virtualization of the prototype chain. We decided that the
Proxy should always be in control of operations involving prototype
inheritance. This includes has, get, set and enumerate. For all of these
operations, when executed on a normal object, they will walk the prototype
chain until they hit a Proxy. After that point, full control is delegated
to the Proxy. If a Proxy would only be able to override get() and set() but
not enumerate(), this may lead to inconsistencies (without an enumerate()
trap, the VM will have to externally walk the prototype chain of the Proxy
via getPrototypeOf()).
2) When we designed Proxies originally, we made the design decision to map
many built-in operations directly to specific traps, even if these
operations could be expressed in terms of more fundamental operations (get,
set, has, enumerate are all examples here). The design argument here was
always improved performance by reducing the number of temporary allocations.
Much later in the design, others started pushing back on the number of
traps, leading us to reconsider some traps, e.g. I recall the "hasOwn" trap
was dropped in favor of checking whether (getOwnProperty() !== undefined),
even though it is strictly less efficient. I don't have a view on the
actual cost of expressing enumerate() in terms of lower-level MOP
operations, but it seems obvious that there will be more allocation costs
involved. The question is then: if enumerate() gets dropped on these
grounds, why not get(), set() and has()?
3) As far as I recall, enumerate() is the only trap that actually returns
an *iterator* over the property names, allowing efficient virtualization of
objects with a large (or potentially, infinite) number of properties. The
only other trap that returns a list of property keys, "ownKeys", returns a
manifest array of property names.
4) enumerate() had weaker invariants than ownKeys() [just like all the
traps that deal with prototype inheritance, since a frozen object can still
inherit from a non-frozen object, leading to weaker observable invariants
in general]. If one would express for-in in terms of repeated calls to
ownKeys(), the invariant check overhead may be substantial compared to just
calling enumerate().
Unless there are really good reasons to get rid of enumerate(), I think it
should remain in. For me, (1) and (3) are the killer arguments: consistency
with has(),get(),set() and efficient enumeration via iteration.
Feel free to forward this mail to TC39. I'm happy to engage in follow-up
discussions, just ping me when needed.
*********************************************************
## 8 Ecma 402, Edition 3, Advance stage 2
(Zibi Braniecki)
402-related slides:
https://drive.google.com/drive/u/1/folders/0B1rFz38aICo2YUpVd0VfTUdwRW8
## formatToParts
https://docs.google.com/presentation/d/1GuPC_pD84VFf4Yc8NKNDFBBmX6uY9DMA5CtKZoAdrzM/
ZB: slide (format to parts)
ZB: further customization, requires exposes of abstract operations such as
format to parts.
ZB: slide (current status)
ZB: polyfil has it, gecko has it behind flag
ZB: we are looking for reviewers
AWB: how about formatParts
DE: its the output not the input, so formatToParts
DE: I will review
RW: I will review
#### Conclusion/Resolution
- stage 2
- Reviewers:
- Rick Waldron
- Daniel Ehrenberg
## Intl.PluralRules
https://docs.google.com/presentation/d/1WflzD4YMOYYmJDAmjwmG0wi5GnLZd74EwvDRKSL9vA8/
ZB: slide (usage)
ZB: we are just following CLDR conventions here
ZB: we are at stage 1, we have spec text. Current status we worked on
decimal parts, which was a previous concern
WH: How do you distinguish between 1 and 1.0? These two have different
plural rules in some languages but 1 === 1.0.
DE: extra fields in the input to specify number of fractional digits
EF: to mirror what number format has
ZB: reviewers?
MF: Is there a reason why we are using strings instead of other output
ZB: yes, the users will use this in a switch catch, those categories are
part of the CLDR
MF: some other identifer could be used on a stable object
YK: the web has moved away from this
YK: the web has stopped to create constant that point at a number
DD: yes, absolutely
AR: Yes, anyone presenting a sepc with a number constant will be asked to
re-work it
DD: userland could implement if they want.
AWB: what value would we actually deliver, in both cases they need to know
the name
YK: they are both constant
SP: userland can do this
AWB: Yes, I don't know how...
ZB: reviewers?
SP: me
DE: me
#### Conclusion/Resolution
- stage 2
- Reviewers:
- Daniel Ehrenberg
- Stefan Penner
...
## Abstract Locale Operations
https://docs.google.com/presentation/d/1JvUv_i7rb0UF6G-nl-Eu3pHvJsmhpfqV6qWwJ6yP2aA/
ZB: we wont provide all formatters, but we will all users to build their
own.
ZB: will allow users to build language negotiations
ZB: slide (Intl.getCanoncialLocales(locales)
ZB: Intl.getParentLocales(locales)
ZB: many exceptions here,
ZB: we have all these operations, somewhat inconsistently used internally.
Now we will expose them, and also use them in-consistency
ZB: there are 100 exceptions to the rules
ZB: slide (Intl.resolveLocaleInfo(locale[ ,options])
WH: What's the point of passing in {direction:true, firstDay:true,
hour12:true} when retrieving the options object? Why not just return the
whole object?
CP: why filter, why not just return everything
ZB: optimization? We can drop it
ZB: slide (current status)
MM: can we agree that the second argument that contains the filter, that we
are getting rid of that
ZB: yes
CP: yes
WH: yes
MM: does the api return a fresh one?
MM: It needs to either return a fresh one or a deeply frozen one. Otherwise
you'd have a global communications channel.
ZB: unsure
DE: yes
CP: whats in the content of the object returned, is it spec'd
SP: needs further exploration
### Conclusion
- stage 2
reviewers
- Stefan Penner
- Daniel Ehrenberg
### Intl Formatter preview
ZB: this is still exploration
ZB: slide (Intl.UnitFormat)
ZB: lots of un-answered questions
ZB: slide (Intl.DurationFormat): Video player or timer in a watch. Distinct
from UnitFormat
ZB: slide (Intl.ListFormat): Localize "Mary, John and Nick", including
change String.prototype.toLocaleString()
ZB: slide (Intl.RelativeTimeFormat): "two seconds ago", etc.
ZB: everything is in CLDR, and we want to expose this
DH: A lot of these are solved in userland, what is the scope? Is it for
things that are already there, we want to surface those? If its not in CLDR
do we leave it to userland
ZB: yes
CP: also prioritize it on the amount of data and complexity
ZB: these 4 handle the most common problems we have seen.
CP: considerable existing bikesheeding, but more are invited to join.
ZB: stage 0?
### Conclusion
- advanced to stage 0
### Async generator functions
presenter: Kevin Smith
link to presentation:
https://docs.google.com/presentation/d/1OwDb4WH9pkdEFVhsY5kjaJ6MF1KrxBNQWpWc9SymweQ/edit#slide=id.p
KS: slide (overview)
KS: Async generator functions return AsyncGenerator objects, with a
for-await loop
KS: Review iterator interface. Async iterators are analogous, but return a
promise of the the IteratorResult, and use @@asyncIterator
DH: AsyncIterator extends AsyncIterable, right>?
KS: Yes.
KS: AsyncGenerator is what you expect, with next, throw and return. Why?
Integration of existing concepts, rather than creating a new one.
Pull-based, no extra backpressure protocol required, easily converted to
push-based Observables. A nice feature of this, with streaming applications
no backpressure is required. It can easily be converted to a push based
source, by taking the async iterable and pushing it.
MM: by convert you mean adapter
KS: yes, exactly
KS: slide (The async iteration statement) – async variant of for of
KS: slide(Bikeshedding: Why for-await?)
DH: pretty strongly agree, the thing that is actually signalling, is that
there are additional awaits
MM: additionally, these are interleaving points.
KS: ctrl-f for await, makes it easy to find interleaving points
YK: it is important that we are allowing two more control states to be
reified through this mechanism
KS: that isn't a bikeshedding concern, rather a concern about modelling...
YK: No, I am fine with the modeling. I want to be sure break/continue
control state to happen.
YK: async modifier takes a construct..
DD: it converts it into an async context, does it make it async itself.
DH: i dont think thats the intention
YK: Introducing more async functions would be good, but here we're talking
about not introducing one so await makes sense
KS: we can explore other contexts, async do etc No baring on this.
KS: Slide (Details: Promise Unwrapping)
SP: so yield will unwrap any thenable (not promise)
DH: i am having a danger will robinson moment, composing two concepts, and
now we merged them.
```js
async function* agf() {
yield Promise.resolve(1);
}
````
WH: Are you proposing that the above do the same thing as replacing the
yield line above by 'yield 1`?
KS: Yes
WH: We've had the discussion before about whether promises stack or they
are idempotent. We decided that one after a long debate to prevent promises
stacking.
DH: yield and await merging.
YK: yield and await have different precedence is pretty bad
DE: doesn't it already do this, as we recursively unwrap.
KS: But we recursively unwrap the IteratorResult, not the data slot!
DE: Oh! So you want to await that?
KS: Yes, and we await as part of yield.
KS: these are still open question, what if i swap `yield Promise.resolve`
with `yield Promise.reject`
DT: in midori we had iterator of promise, the producer can run ahead,
launching the subsequent async computations.
DD: these are both handled: sync iterator for promise, async iterator for
promises
DT: i think it is orthogonal
DD: there is no distinction, we can collapse them down to one level
DH: So because we don't have promise for promise, this structure wont
absorb them.
DH: yield / await wanted to absorb
KS: originally i didn't have this flattening, the discussion was that well
we have made choices were we dont want to have promises for promises, and
that would seem to make it the same as a promise for a promise with an
extra done bit
MM: I dont know what side of this I'm on yet, but let me put this into
other terms. The things you can have a promise for are non-promises.
Promises can only promise non-promises. The design question here, are async
generators sources for a sequence of non-promises, or are they are source
for a sequence of anything. Consistency cuts both ways, collapsing can be
good. On the flip side, when you create a container, a container can
contain any value not just non promises. A container can have more things
over time. If you see a stream like this as simply a container. Then most
containers can contain promises.
DD: you can swap the word "container" for promise, and the argument flips.
DD: complete abstract concepts should synergize
WH: i don't know what that means
DD: Async Iterator should have unique behavior that is the composition.
DD: I think that you are saying, that a type with a certain structure, that
semantics are entirely containeed rather the surrounding semantics.
DD: there could be semantics on top of the compositional concepts.
DH: you guys agree 90%, there could be a new type Asynciterableresult, or
you are saying promises could absorb this.
YK: or syntax could absorb it, but that is only half the battle
DH: absorption at all?
MM: Back when we were doing promises, one of the questions that came up
regard the collapsing or not. Given collapsing, with the cooperation for
both sides, can we still somehow express the functionality of a promise for
promises? I have needed this. The work around is to wrap the promise in a
cell, and the reciever needs to unwrap the cell. By a simple cooperative
adaptation, can either functionality be layered on top of the other? I
believe the answer is yes. Given that, the remaining design constraints
should be "Simple things should be simple, complex things should be
possible." (Famous Alan Kay quote).
DH: Are you saying async iterator can be implemented in terms of the other
version?
MM: either of the two forms of async iterator we are discussing can be
cooperatively represented via the other, so the main criteria should be
simple should be simple, complex should be possible. The dominent use-case
is delivering non promises.
MF: you are mistaken about several things, the goal isn't to deliver a
promise of a promise. The goal is to deliver a promise of anything. We
don't care about promise for promise, we care about a promise of anything.
People see that as the simpler thing.
MM: you are correct, simple isn't the right word as simple can be used on
both sides. A consumer that knows to only deal with non-promises, is the
dominant kind of consumer.
MF: people write libraries that need to support this
MM: general polymorphic libraries that want to support any type of input
DE: we already have this precedent in promises, we should have this be an
edge case.
DH: i think its really important to understand, some think interms of types
and parametricity. The fact of the history of promises, JS types are split
tino 2 universes. (promises and non-promises)
ARB: one is included in the other, which is the problem
YK: it is already the case ...
ARB: contents of promises is were the worlds "collide", otherwise
unwrapping wouldn't be useful
KS: let me put a bookend on this part, clearly strong feelings on promise
unwrapping.
KS: the difference would be, if you didn't do the unwrapping someone would
need to do yield + await
MM: a worse issue, consumer side. Does it see iterations. Are we trying to
define an abstraction to see an iteration of non-promises, or are we trying
to define and abstraction to asynchronously deliver values.
WH: Collapsing is trying to remove the need to say `await` when calling a
function in a `yield`. But how does this work in a regular async function?
Compare
``async function* f() {
yield g();
yield h();
yield i();
}```
with
```async function f() {
g();
h();
i();
}```
The latter one doesn't implicitly put awaits in front of the calls to g(),
h(), and i(). Consistency would imply that the former shouldn't either.
*more discussion*
KS: It unwraps it recursively
KS: for-await falls back to Symbol.iterator when Symbol.asyncIterator is
missing
DT, MF: This may be a hazard, or maybe not if you insert the right
turn-taking
KS: slide (Queueing). What do you do when someone calls next repeatedly
without awaiting?
DH: Unbounded queue?
KS: You could return a rejected promise, or put it into a queue and pick
them up as appropriate. I've been going back and forth on the various
options. It's not essential to the design yet--at some point, I switched to
rejecting, but this caused some bugs in my program, but it ended up being
fixable
MM: in the queueing case, it still returns the exact same thing
MM: the queueing up seems much friendlier.
SP: yes
MM: one guy calling .next (can take an argument) because the consumer is
assumed to be paused on a yield, allowing it to go to the consumer without
an intermediate buffer. The whole reason for this, is 2 async coupled
entities, allowing one to run ahead sounds very fine.
TD: we started with "it fails" and worked around it, ultimately giving up.
As soon as anything got speculative, it got complicated. Pushing it into
the infrastructure, making it queue, up so that everyone had it.
MM: This can be very useful, not buggy
YK: the fact that is different that is is different from the flip side algo
KS: actually, examples exist.
KS: this is the same
YK: ...
DH: mapping these to known analogies were i feel more confidence, falling
async is JS approach to threads. The analogy from a sync threading
language, I have a thread that is producing me abunch of values, I block
waiting for the next value, I as the consumer should not be sensitive to if
the other thread is blocked or not. It should be internal to the thread
implementation details, leaking this to the cosumer isn't correct
MM: both sides block, in JS that is a promise.
KS: slide (current status)
- partially implemented in regenerator
- its in there for several months, although for await isn't
- read for review
DH: please assume good faith, this is delicate. I think the space is
important, we need to figure out how these concepts work together, but
there is failure of our champion model, and that is over modularization...
DD: in the last meeting, we requested this specifically for big paper.
DH: No attack here.
DH: i don't see yet, how this fits in, with the other stuff that fits in
with Jafar. We have seen various variations, it is not clear to me... Maybe
the intention here is to drop all that stuff (possibly implied)
YK: is JH giving up on for on
JH: for on, wasn't in the proposal
DH: we can't do all these things
DH: we need to figure out what our are async data types, and we need to
figure out the grand unified theory. KS has submitted great work, I still
don't see how this all works together.
DD: we said something stronger, we wanted both AsyncIterable and
Observables on stage, so we can properly view this.
DH: if we continue to advance these overlapping ideas, we need to be sure
we don't defer how to ensure the grand unified theory works.
YK: stronger concern, both proposals want to arrive at syntax. We can
likely only get one of the two syntaxes.
YK: we can get for on, or for await, not both.
DH: it seems far less for us to imagine the coexistance of both data-types
in the languages, but with the new syntactic constructs present much overlap
KS: My opinion is this is await for in is the only syntax, and observables
could use it. As I discussed above. In that direction, it should be
complete fluid. The other direction, the subject of the await for is more
complicated due to buffer differences. In my vision, observables would have
a method that would allow observables to choose buffering strats, that
returned an async iterable. Making it compatible with for await.
JH: KS and I are in alignment, for await is what i want. We can adapt an
observable to an iterator via a buffering strategy. Other types can achieve
this.
YK: an alternative design would be async iterable result, and we should
explore
DE: these things seem like refinement process tasks. They can be explored
at stage 2
AWB: this feels like stage 1
DD: does anyone have fundamental disagreement?
YK: someone needs to respond to my exploration request. I am pretty
uncomfortable combining the two types.
.... discussion ....
DH: let me add structure
DH: their are several work areas, that have been structured as independent.
JH has been a champ in 1 direction, and KS in another. Several areas of
unstability:
- work on observables + syntax
- work on API for async sequences + syntax
- it sounds like KS + JH are in aligment, observables aren't the base
for syntax. And it is orthogonal
- observables championed by JH
- we want some syntax (which obviously needs a protocol)
- API for async sequences, but without full consensus. But we need to
continue exploring.
YK: I totally agree, I am concerned that I must present an adequate
argument but do not feel able to at this time.
DE: we should explore this explicitly
DH: we should explore for await, and async sequences. We need to shake more
out.
DH: its obvious to me that those could be stage 0
DD: my opinion is this proposal is ready for stage 2, if we can agree that
the changes can be resolved during stage 2.
YK: it depends how fundamental the type composition is to the proposal
KS: I think that we ought to use promises for something that will be
delivered async. As it works with the rest of the
YK: it can be skinned many ways, additional protocols can be created.
MM: await does a Promise.resolve, maps a value to a promise, and I don't
want to reopen this.
MM: if an AsyncIterationResult is something that is not a promise
YK: is it important that it is a nominal instance of the promise
constructor?
MM: yes i believe so
YK: i am surprised
MM: if it is a thenable that it will be adapted by Promise.resolve. I am
not ok with reopening await being Promise.resolve(x).then(continuation); I
am not willing to change what that means
DE: can we decide stage 1 or stage 2, we have more to cover.
AWB: we cannot make it stage 2,
DE: we can say its stage 1 pending further review.
MM: (Somewhere in here I made the following unrecorded observation)
There is a third alternative. The async generator can be a generator of
anything. "yield" does not imply an implicit await, so no collapsing
happens on the generation side. The async iterator that is produced is an
iterator of anything. No implicit collapsing within the async iterator
itself. Its API remains fully parametric. Rather, the for-await construct
does the collapsing, in service of the simple-dominant-use-case consumer,
who wants to see an asynchronous sequence of non-promises. Each iteration
of the for-await loop does a double await -- one to get the
IterationResult, and one to get the promised value.
Any consumer who, instead, wishes to see an asynchronous sequence of
anything, can instead write their own loop rather than using the convenient
for-await sugar.
Big advantages of not collapsing at the generation side:
* yielding an unresolved promise does not prevent the generator from
proceeding to generate. It is not surprising stalled at the yield point.
* yielding a rejected promise does not cause a generation-side
exception. Rather it simply transmits the rejected promise. A simple
for-await consumer is stopped by the rejection throwing the reason.
* (Pointed out by Dean): An implicit "await" at the "yield" violates
the rule that we can find all interleaving points by looking for "await".
### Conclusion/resolution
- Stage 1
- needs more exploration as per above discussion.
### Strong Mode Discussion
Presenter: Andreas Rossberg
link:
ARB: slide (recap)
ARB: slide (progress)
ARB: slide (strong mode)
ARB: slide (what worked well)
ARB: Disallowed implicit conversions.
WH: Even toBoolean???
ARB: toBoolean is the only one that remains
ARB: string conversion is used alot, but it wasn't a problem. In es6 we
have template strings, which becomes explicit.
AWB: what about toSelector, number -> string for property
ARB: ya, it comes down to some things. This one is still allowed.
ARB: slide (what not worked well) Mutually recursive classes,
MM: what was the motivation for unbound variable ban
ARB: to make errors static and avoid runtime checks
ARB: interopt made locking down classes via seal
... discussion above strong vs non-string inheritance mixtures ...
ARB: slide (takeaway)
ARB: slide (soundscript)
### Teset262
presenter: Dan
DE: reptitive tests, lots of tests that repeat each other. Their exists a
proposal to generate tests precedurally, we require implementors feedback.
Ask me and I will provide more information
### Conclusion / resolution
- implementors need to provide feedback
###
#### Conclusion/resolution
# Test262 Updates
Presenter: DE
DE: We have some changes coming into test262, e.g.,
https://github.com/tc39/test262/issues/470
https://github.com/tc39/test262/issues/467. Users, please give feedback as
to whether these are appropriate for you! Please reach out to me if you
have any concerns.
#### Conclusion/resolution
# Progress review: Callable class constructors (Allen)
presenters: AWB / YK
AWB: slide (callable Class Constructors)
AWB: slide (refresher)
AWB: slide (refresher pt.2)
AWB: slide (refresher pt.3)
AWB: slide (refresher pt.4)
AWB: slide (interesting feedback via twitter and other channels after
publicizing proposal)
YK: some feel the new fork is non compositional
AWB: slide (more feedback)
AWB: inheriting is complicated
MM: it is possible, make the default call behavior on a derived class to do
a super *call* to its superclass constructor.
YK: ya
YK: another way to say, is that we install a constructor
MM: not suggesting it is a good idea
YK: not including it, caused confusing.
YK: baseclass providing default functionality was a big concern
AWB: we will remove the rocket
AWB: we do want to enable the calling constructor
YK: almost all people people want call to delegate to new
AWB: ya, 99.9% case. Two bodies is confusing, it clearly seperates it for
the 0.1% case, like date function.
YK: it is a middle ground
AWB: todays proposal (slide An alternative approach)
```js
class RegExp {
factory constructor(pattern, flags) {
}
}
```
MM: what about inheritance?
SP: it could now just be made to work, because its a unique function body
MM: does the factory bit inherit
AWB: i would say no, but it could.
MM: if the subclass does not say factory?
AWB: it reverts back to the default behavior to throw
WH: Almost the same as the original proposal. Can you use this to implement
the Date use case as on the first slide?
AWB: yes, if you want to implement date (slide -> Use single body and
new.target for date-like case)
DD: something seems bad
YK: i would expect, it installs new
AWB: we don't quite support the date case, but the 99.9% has been sorted
AWB: I will think some more about this.
YK: ES5 can still be used for the edge-cases
..: it will be hard to implement
AWB: slide (an alternative approach)
```js
class RegExp {
factory constructor(pattern, flags) {
}
}
```
MM the only thing that gives me pause here, if long term we will only
address this with a specified mechanism. Date case goign back to es5, then
we are not gaining any value from having the default constructor throwing.
YK: incorrect.... i would make a looser term.
YK: lets go back to es5, a massive hazard to forget use. This made many
people not want the newless behavior.
MM: I'm not buying this
YK: the world you want to live in, they can choose new or old style, If you
happen to not like new, you call without. That world only works if all the
classes are es6 classes, if you encounter an es5 class you will likely
encounter a hazard.
MM: what I'm saying, we don't require new, the default call constructor is
to `new`
YK: i almost proposaed this...
...: from an implemenators perspective, we only included the new.target in
frames if we new we needed this. It is a huge pain in the neck to implement
this default forwarding
BE: some wont use classes anyways, we shouldn't cater to them
MM: we should not help them
DD: their is an implementors concern.
AWB: the factory world is almost noise
... discussion ...
WH: This is unnecessary. It's creating a redundant way to create instance,
for those who don't like `new`. Given the implementation concerns, we
should not be doing this at all.
... (the implementors) it wlil be crappy
MM: could we make something shorter than "factory constructor"
AWB: maybe, but it is a factory call
MM what about
````
class RegExp {
() {
// ..
}
}
```
DT: seems like syntax and implementation default are two seperate issues
WH: Again, we shouldn't be doing this at all. Drop it instead of
bikeshedding syntax.
MM: I withdraw my proposal due to the implementation concerns
YK: i am on the side, that not using new is a minority opinioin. We should
still not lock it out
DD: we should likelynot provide constructs that will allow those to shoot
themselves in the foot, they can just use =>...
YK: decorators could enable this ergonomically
MM: we should drop this completely, and solve it with decorators.
#### Conclusion/resolution
Proposal dropped.
# Object.getOwnPropertyDescriptors to stage 3? (Jordan Harband, low
priority, but super quick!)
presenter JDH:
JDH: reviewers and editors +1'd, can we move to stage 3
all: yes
## Conclusion/resolution
- advance stage 3
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20160205/72f24a01/attachment-0001.html>
More information about the es-discuss
mailing list