July 30 2015 Meeting Notes

Rick Waldron waldron.rick at gmail.com
Wed Aug 5 15:20:15 UTC 2015

(Slides are at https://github.com/tc39/tc39-notes/tree/master/es7/2015-07 )

# July 30 2015 Meeting Notes

Allen Wirfs-Brock (AWB), Sebastian Markbage (SM), Jafar Husain (JH), Eric
Farriauolo (EF), Caridy Patino (CP), Waldemar Horwat (WH), Istvan Sebastian
(IS), Mark Miller (MM), Adam Klein (AK), Michael Ficarra (MF), Peter Jensen
(PJ), Domenic Denicola (DD), Jordan Harband (JHD), Jonathan Turner (JT),
Paul Leathers (PL), Chip Morningstar (CM), Vladimir Matveev (VM), Ron
Buckton (MS), Brian Terlson (BT), Alan Schmitt (AS), Ben Newman (BN),
Mohamed Hegazy (MH), Abhijith Chatra (AC), Tom Care (TC), John Neumann
 (JN), Dave Herman (DH), Brendan Eich (BE), Daniel Ehrenberg (DE), Dan
Gohman (DG), Andreas Rossberg (ARB), Rick Waldron (RW), Mike Pennisi (MP),
Akrosh Gandhi (AG), Jonathan Sampson (JS)

## 7 Test262 Updates

(Brian Terlson, Mike Pennisi)


MP: Introduction

See slides

WH: (re:
http://jugglinmike.github.io/presentations/2015/tc39-test262-update/#7 )
question, re: es6draft, ecmascript spec, before/after publication?

?: es6draft ? ECMAScript 6 draft

BT: Ongoing. Could also add Chakra bugs

MF: raw flag? Does this prevent issues other than directive prologue issues?

MP/BT: "raw" means: don't touch the file, just run it. No access to assert
features, useful for syntax only tests

[discussing distinction between early errors and parse errors that test262


AWB: These are a specification artifact. An implementation doesn't have to
do parsing and early errors in separate passes.

WH: This becomes visible when there are multiple errors, some in parsing
and some early errors. Does the spec designate which error should be
reported when there are multiple of these?

AWB: No. An implementation is free to report any of these errors.

AWB: Distinguishing early and parsing errors in tests is overspecifying.

(re: website improvements)

BT: current test262 site does not have ES6 collatoral.
- Implementing ToLength appears to lock up the website
- Alot of work needed to get the test262 site into a functional state
- Is the work something that Bocoup is going to do?

MP: Nearing end of time, but ideally would like to take on this work

BT: Then we need to find a "resource" for this project
- Enumerating outstanding issues with test262 website

YK: Considered running tests in iframe or worker and timing out?

BT: Harness uses iframes

Discussion of implementation details of test harness

BT: Requirement of new site: use web workers

Moving on to

MP: (first example) TypedArray, 9 sets of the same tests. The tests might
start in sync, but it's hard to maintain over time.

- Typed Arrays (9)
- Destructuring Assignment (3)
  - AssignmentExpression evaluation
  - ForIn/OfBodyEvaluation
    - for..in statement
    - for..of statement
- Spread Operator (4)
  - ArrayLiteral: [...x]
  - ArgumentList
    - SuperCall: super(...x)
    - CallExpression: f(...x)
    - MemberExpression: new f(...x)
- Expressions & Declarations
  - Function
  - Generator
  - Class

AWB: Similar to wanting to share code in tests, implementations will want
to share code.
- Look at how an implementation and its tests go wrong?
- Tests that would catch the most common ways the implementation
abstractions might go wrong

YK: Instead of testing all the things, find the things that might fail
- things that look similar, but are subtley different: test that.

MP: (gives an example of how strict and non-strict tests are automattically
run, unless flagged)

WH: Value in testing exhaustively when the number of cases is reasonable.
Per the presentation, there are only 18 contexts in which destructuring is
used, which is reasonable for full cross-product testing.
- Re: Allen's point, there are subtle things that can go wrong. I can
imagine an implementation getting destructuring right in most contexts but
messing up some subtle aspect of it for, say, arrow function parameters.
- But still worthwhile to test try to be exhaustive

BT: Not suggesting that we won't test syntax in unique contexts
- More about the authoring
- For tests that cover identical syntax semantics and the only difference
is syntactic context, then test once
- Why not sweet.js or an existing templating engine? We need to test syntax
errors (and other negative tests)

WH: Just pick one that doesn't make you escape all of the ECMAScript syntax

Discussion, re:

AK: (concerns about useful output)

DD: most consumers clone the repo, so we need to make sure that we check
the output as well

AK: I'm less concerned about running, but about the output that will inform
me of the failure

BT: Don't want to check in the actual generated tests
- This proposal MUST make it easy to identify failures
- The test harness will write to disc the actual code that failed at the
moment of failure
- produce, on-demand, the filled-in template

DE: For tests users, this can be automated?

BT: Yes.

#### Conclusion/Resolution

- Continue exploring test generation

## Meeting Schedule

(John Neumann)

JN: will propose a 2016 schedule in september. Need to know if we'll be in
- Switzerland: Geneva, Lugano, Montreux, Lausanne (Geneva may not work: too
many attendants and too expensive)
- Germany: Munich
- France
- England

Discussion planned for next meeting

- September in Portland, hosted by jQuery/Yehuda
- November in Santa Clara, hosted by PayPal

JN: Need to confirm what the 7th edition will contain

YK: Straight forward, whatever is Stage 4 goes in the spec

AWB: (enumerating general spec process timelines)
- submission
- review
- 60 day opt-out

YK: That's after January?

AWB: Approximately end of January

YK: January is submission, work backward to find deadline.

Discussion re: time needed for Brian to integrate the stage 4 features.

#### Conclusion/Resolution

- Get proposals wrapped up if you want to get these features into the spec

## 6.4 Advance Async Functions to Stage 2

(Brian Terlson)



Updates from Last Time

- Complete spec available ( http://tc39.github.io/ecmascript-asyncawait/ /
https://github.com/tc39/ecmascript-asyncawait )
- Removed `await *`
- Implemented in Babel
- Losts of positive feedback from the web

DH: Future proof for potential future syntax extensions

DD: Clarify not `await *`

BT: `await *` was not useful. If there is a proposal for a useful
semantics, then good, but not in this proposal.


- Async Arrow Function
  - async (a, b) => await a + await b;
  - (a, b) @=> await a + await b;

DE: What's the issue with the first?

BT: `async` not a keyword and that could be a call: `async(a, b)`

MM: @ seems like a poor choice, but I don't have an alternate suggestion

AWB: only b/c "a"sync
- the `async` form defeats the conciseness

BT: I've worked out the grammar, it needs review, but it appears to work

YK: Shouldn't have 3 sigils right next to eachother.
- hard to google a sigil or set of symbols
- a "grawlix" problem

BT: Opposed with the top grammar? (assuming the grammar works)

(no opposition, pending review)

DH: Would like to see more code illustrating actual use cases

DD: There's a lot of code in the wild that's been using the top form

DH: Any higher order combinator is where this will have the most use.

MM: No consensus on the second. Consensus on the first contingient on
grammar validation

DH: Cannot make `async` a keyword, one of the most popular modules on npm
is `async`

DD: `Promise.all` doesn't quite work because it's a combinator that takes
promises, not functions that return promises

DH: The syntax that we've come up with for past features like `=>` map to
an extremely high use case with hardship. Not clear to me that we have the
full async callback picture

DD: should look into the ecosystem of Babel users and see where it's come up

Design Questions (continued)

- Newing an async function:
  - Error
  - Promise-for-instance

BT: Suggest "no"
(no disagreement)

Design Questions (continued)

- Errors in Parameter Initialization

function* foo(a = (function() { throw 1; }())) {

let iter = foo(); // throws 1

BT: the equivalent in async functions:

async function bar(a = (function() { throw 1; }())) {

bar(); // as of the latest proposal, this throws 1

// Alternative semantics would have the error deferred:
bar().catch(cb => ...); // Possible semantics

DD: Wish this was caught for generators

AWB: We knew about it, but nothing can be done

MM: For generators, we have immediate throw
- Async function: throw in body breaks the promise
- think about _when_ the throw happens
- what way is it reported?
- throw in generator body is reported with a throw
- throw in async body is reported by rejecting promise

YK: when use promise, you can catch all the errors into one place

AK: Arguing for throw immediately?

BT: Yes, found that error throwing default parameters don't happen (rare
- Mark's point about multiple symmetry in play

CM: setup preparation part, consumption part. The generator setup might
have error in setup, reported immediately

DD: Code will expect to receive the error via the catch path, not an
immediate throw path.
- Most promise ops go through the API
- Devs can muck with the built-ins and produce errors

AWB: What if you put a proxy on an async function and the call trap throws?

MM: There's not a problem with the [[Call]] trap. If the [[Call]] trap in
the Proxy throws, then you have a "throw".

AWB: Say the async function is actually a proxy wrapped around an async

MM: It's exactly the same hazard as if you hand someone a function that
wraps an async function and the wrapping function throws.

DD: Problem is thinking of async functions as a separate category. Just a

DH: Mark, I agree. There are errors we consider normal to happen in
programs that you should deal with, and those where soemthing went badly
wrong and you can't write code that has try/catch every where. A function
call that throws an exception should follow the error handling model for
the programming paradigm that we're in; since we're in an aync world, the
programming model for handlng errors is `catch`

BT: want to be very clear about rationalization, so that same can be
applied to `async` generator.

AWB: The generator function returns its value before evaluating its body.
- A generator is a function

MM: An async generator... I missed the rest of this

YK: Can you `yield` in a default parameter in a generator?

AWB: No, you cannot `yield` there because the object doesn't exist yet.

BT: We need to establish the rationale for the behavior of error handling
in non-simple generator parameter lists

YK: Might've been a mistake?

AWB: Generators do what generator functions previously did in Firefox. We
weren't sure if it should be changed. Different results:
- timing evaluation changes: happen on the first `next`, the values aren't
the same values at the time of the call.

DD: Generators suspend immediately, `async` suspend on the first `await`

DH: All cases, expect that parameter default expressions execute eagerly,
not that they execute at some time later

DH: Generators are all about order of execution. The fact that generator
functions and async functions have different control flow expectations
means that it's reasonable for their error handling behavior to differ.

Discussion about complications of the implicit `yield` in generators

DH: Don't need symmetry between generator and async

YK: Async function is just a function, but the generator is a different
- When calling a generator, you're not calling a function as shown

DD: When calling a generator function, the first line of the function does
not execute

DD/YK: Agreed.

YK: The consequence is that the refactoring doesn't make sense.

Design Questions Continued

- Await synchronous things synchronously
  - `await 1` does it trigger a turn of the event loop as in the desugaring?
  - allow synchronous await but ensure promise resoltion is async?
  - do neither and allow returning an already-resolved promise?

MM: describing the hazard of sometimes "sync" and sometimes "async"



YK: The same hazard doesn't exist with await, because the callback model is
changing which scope the function is called in, but doesn't exist in await.

MM: Agreed that the hazard to aync functions is smaller than that to
Promises. The bugs will be both fewer and more subtle and harder to figure

DD: no cost to go back to the event loop

YK: not true.
- hot code is always awaiting some promise, could be optimized to consider
inline-able. Never true if you always have to go back to the queue

MM: If an implementation can optimize, which is very hard and hazardous

YK: I'm making a different point. If you say. "you are not allowed to go
back to the event loop" and if you discover that it is synchronous, then
you can optimize by in-lining the synchronous code. In an ideal world, it
is "just a loop", and a loop is fast.

JH: The relative harm: cost not zero, need to weigh

MM: Experience with `asap`, cost is worth it to reduce the hazard.
- When bugs do occur, very subtle and hard for programmer to figure out

YK: Hazard in the callback case is in pieces of code that are right next to
eachother that appear to [...] Let me put it another way: the hazards you
are talking about are based on assumptions that I would never make when
writing a program.

MM: hazard as soon as mutated state is sufficiently non-local

YK: cannot rely on what interleavings are possible

BT: hazard here: order of your next turns change. not that callback could
be async, but that your callbacks mayb run out of order. What Yehuda is
saying is that people don't write programs with multiple Promises where
they expect the promises to resolve at specific turns of the event loop.

MM: Two different hazards:
- The order of events on the event loop is one hazard
- the isolation of side effects is job that was executed up to the await
point, completes before any code of the `await`
  - All invariants storing during the job

Mark, I need you to fill this in, we're moving too fast.

YK: Transaction committed before any await is called. This exists in Ember.
- Need to see an example of the invariant Mark is describing

MM: After the await point, the callee is starting with a fresh stack.
- Event loop programming paradigm that suspends an invariant must restore
the invariant before the job ends.
- Illustrates with example of doubly linked list operation

MM: Event loop concurrency requires restored invariants before the end of
the event loop turn

YK: Different from what's encountered in practice

DD: What's the position?

YK: Discussing already-resolved-promises

DD: `await 1` is not the same as `await Promise.resolve(1)`
- If you have a promise, you've said that the value is async and breaking
that is crazy

MM: Found with the Q.asap bug: I wrote my code, tested my code, then my
code had bugs. Result of code running out of turn with test code.

YK: consistency is absorbed by syntax

MM: disagree
- The bug was directly the result of assuming the invariant will be

Discussion re: invariant restoration on event turn completion

// BT:
foo().then( function() {
   /* 1 */
/* 2 */
// Which is first

async funcion foo() {
  /* 1 */
  await x;
  /* 2 */

  // are these the same turn?
// HAZARD: setup state required by /* 2 */

Currently, `await` is always async.

JH: Concern that the notion of asynchrony bound to...?


JH: predicts that await means async to developers. await is composition.

DD: yield is composition

MM: asynchrony is mandated by the async keyword

JH: is that adequate? `async` means asynchrony, `await` does not mean
asynchrony, just pause the execution.

YK: Come back to this?

Agreed. Next turn of the event loop.

JHD: Agree that `await x` always means `await Promise.resolve(x)`?

Some agreement.

YK: Doesn't fully describe the trade off

MM: Implementation prohibited from making optimization

JH: can we put together a program that illustrates the hazard?

// BT:
foo().then( function() {
   /* 1 */
/* 2 */
// Which is first

async funcion foo() {
  /* 1 */
  await x;
  /* 2 */

  // are these the same turn?
// HAZARD: setup state required by /* 2 */


let x;
foo().then( function(val) { x = val; /* 1 */ } );
// what is x?

JH: Is that an issue in asap? or were there other issues?

// BT & YK:
async function foo() {
  // relies on y being `1`
  await x;
  // relies on y being `2`

let y = 1;
y = 2;

MM/DD/YK: discussing the hazards above.

AK: Different conditions, different behavior.

Discussion about race conditions in JS

DH: largely around the interleaving asynchronous events
- Mark wants this to be limited

MM: confirms

YK: When type `await`, I expect unpredictability

MM: unpredictable interleaving of job


function dStuff() {
  if (window.state === 1) { doA(); }
  else { doB(); }

async function foo() {
  doStuff(); await x; doStuff();

window.state = 1;
window.state = 2;

MM: impossible to reason about a program without knowing something about
what is going on.
- testing in sync case, and it works
- execute in async case, and it fails

DD: Always have a consistent state on the next turn

Discussion, restating positions back and forth.

- Promise cancellation:
  - Depends on cancellation at the promise level
  - Urge promise champions to consider ergonomics with async functions

BT: not going to specify cancellation in this proposal

MM: Not sure that base Promise is going to change?

DD: Talk offline.

- Await at top-level
  - Can you await at the top level of a module?
  - Useful, especially in Node

DH: Issues.

YK: Previously, could assume that top level ran start to finish, if many
pieces have setup await

AWB: this changes the entire model of module execution

BT: modules are wrapped in async function which called immediately

MM: after top level await point, import/export, are these effected?

AWB: initialization happens in the order of import/export but before the
module body starts

MM: only "when" the execution happens

AWB: This could be misunderstood


import ... from ...;

let m;

if (dev) {
  m = await local.import("lib-dev");
} else {
  m = await local.import("lib-production");

export let x = 17;

DH: Requires module be async.

Unresolvable if node remains sync at the top level.


DH: we need to do more work offline.

BT: is top level await worth pursuing?

DH: Addresses a definite need, eg. dynamic module loading

BT: Flesh it out?

DH: No, this needs to be designed in concert with loader. Suggest
decoupling to unblock async/await

BT: Confirms.
- Waldemar's grammar concern?

WH: (presenting now)


- According to cover grammar, this is a division symbol
- Is await a keyword or identifier here?

BT: parsed like a keyword, but there is a static semantics that says any
occurence of await expression is an error.

async(a=await/x, b=c/i) => b;

- Parse cover grammar, don't know that you're in a arrow function. This
lets await sneak through as an identifier
- When you do the reparse, `/x, b=c/i` is treated as a regexp

MF: The reparse says it has to match this additional grammar, same set of

WH: It's not clear in the spec.

BT: Yes, the await would appear as an identifier until you apply the cover

MF: (reads from [ECMAScript 2015 specification, section](

MF: if await is always an await expression, this would fail to reparse,
resulting in a SyntaxError

BT: Correct, expected.

BT/WH to have offline discussion re: grammar.

BT: Those that know execution model should review this.

#### Conclusion/Resolution

- `async (a, b) => await a + await b;` contingent on grammar validation
- `async` functions: no construct slot
- errors occuring in parameter initialization take the catch path
- Approved for Stage 2
- Reviewers
  - Waldemar Horwat
  - Jafar Husain
  - Yehuda Katz

## 6.5 Proposed Changes to Observable API

(Jafar Husain)




Conclusions after 45 Issues and Impl Work

- Generator should not be used Sink
- Sync Subscription Affirmed Necessary
- Can implement EventTarget using Observable

Using Generators as Sinks

- Type Fudging (would like implicit {done: true})
- Priming Problem
  - issue with implicit yield
  - considered a decorator, but likely a footgun
- Return invoked on unsubscribe
  - mistake because it conflates two concepts: the need to free scarce
resources and the need to signal iteration has completed
  - the equivalent to breaking out of a for loop,

YK: Why does it end up not being important to generators? (dispose being
separated from return)

YK: Straight forward to add a `dispose()` method to Generator instance

JH: Believe adding `dispose()` is good

DD: And/or remove `return()`. To remove the try/finally that's implicitly
added around a for-of loop

Discussion, re: try/finally

JH: even if we fix the return/dispose conflation, the priming problem is
still a compelling reason not to use generators as sinks

Using Generators as Sinks (continued)

- Multiple unsub methods

Proposed Solution: Observer Type

(get bullets from slide)

Advantages of Observer Type

(get bullets from slide)

Proposed Observable Type Changes

(get code from slide)

DD: Strange to hide a method by using well-known symbol
- if sync subscription is allowed, just make it easy

WH: What does Symbol.observer return? (Not referring to the symbol, but to
the method to which this is the well-known symbol-as-computed property name)

JH: Nothing

DD: What happened to the flush that we discussed?

JH: In progress

MM: What is the `Object?` in `Observer` type?

JH: Allowed to return something

(Should be "any")

MM: Why not just support the Observer (in `subscribe` method)
- Prefer two separate methods

JH: previously had a forEach that returns a promise, still exists, just not

Discussing a swath of code on jsbin

Sync Subscription Affirmed Necessary

- Necessary to build EventTarget using Observable
(get rest of bullets from slide)

Jafar moves through slides too fast.

DD: Would prefer something simpler than Symbol.observer, instead just call
it something obvious

MM: Name it such a way that the name is clear to the user (no suggestion)

Discussion, re: await observable.

All scalar combinators produce promises or observables

#### Conclusion/Resolution

- Approved for Stage 1 (which means: nothing changed here)
- Offline discussion, re: sync subscription

## 6.13 Advance Rest/Spread Properties to Stage 2

(Sebastian Markbage)



Static Properties vs. Computed Properties

SM (slide): question on evaluating computed property keys multiple times on
the LHS of a destructuring assignment?

SM (slide): question when a "rest" destructured object param throws (via
getter, for example), should `rest` be undefined, or a partial object. or,
should the getter be copied rather than evaluated

try {
  var throwingObj = {
    x: 1,
    y: 2,
    get z() { throw myError; },
    w: 4

  var {x, ...rest} = throwingObj;

} catch (err) {
  x; // 1
  rest; // undefined (could be { y:2, w: 4 })

MM: possibilities?

- undefined
- { y: 2, w: 4 }

MF: also `{}` and `{ y: 2 }`

MM: further semantics need to be explored

#### Conclusion/Resolution

- Approved for Stage 2
- Reviewers
  - Andreas Rossberg
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20150805/fd8c1052/attachment-0001.html>

More information about the es-discuss mailing list