Ecma/TC39 Meeting – Jan 30 2014

link Jan 30 Meeting Notes

John Neumann (JN), Allen Wirfs-Brock (AWB), Yehuda Katz (YK), Eric Ferraiuolo (EF), Erik Arvidsson (EA), Rick Hudson (RH), Matt Sweeney (MS), Dmitry Soshnikov (DS), Sebastian Markbage (SM), Ben Newman (BN), Jeff Morrison (JM), Reid Burke (RB), Waldemar Horwat (WH), Doug Crockford (DC), Mark Miller (MM), Brian Terlson (BT), Luke Hoban (LH), Andreas Rossberg (ARB), Istvan Sebestyen (IS), Niko Matsakis (NM), Brendan Eich (BE), Rick Waldron (RW), Sam Tobin-Hochstadt (STH), Rafael Weinstein (RWS), Dmitry Lomov (DL), Niko Matsakis (NM), Simon Kaegi (SK), Dave Herman (DH)

link Parallel JavaScript

RH: API is stable

RH: Parallel array data type is no longer there. Instead as methods on arrays and typed objects.

NM: To be clear you can have an array with structs in it.

RH: The sweet spot is games and image processing.

RH: No current show stoppers on implementation. Some things to work out related to GC. The strategy going forward. Be complimentary to the typed object spec. Will track it and spec parts of it Typed Object spec. "Close follower". Will move in tandem.

LH: To move to phase 1 we need to see some examples.

YK: Agree, we need to see where we're at.

AWB: Agree, we should have presentations to move from phase 0 to phase 1.

RH: I have presented twice already...

YK: Moving to phase 1 should require a presentation.

YK: Concerned that we are exploding the API with mapPar, filterPar, fooPar etc.

YK: Prefer static functions

EA: Or a standard module import {map} from '@parallel'

YK: this in functions?

1
arr.map(obj.method, obj)

DH: The signature should just match the existing functions.

RH: Not less surprising. Just as surprising.

1
2
parallelModule.map(arr, func, ...)
// [T] -> .... -> [T] // same return type

NM: What would you call from?

WH: It's too confusing to require completely different static function style for invoking parallel maps as compared to non-parallel maps. mapPar etc. method style is better than the proposed alternatives.

DH: It is always nicer to write a method call than a function call.

DH: Don't want a "bring me a rock" exercise.

EA: File issues on GitHub on the drafts (that are also hosted on GitHub).

MM: Worked well for Promises.

YK/MN to talk through the concern about a "ton of methods".

link Conclusion/resolution

  • Move Parallel JavaScript to phase 1
  • Talk offline about design issues further

link Structured Clone

DL: Is implemented in all browsers. Part of HTML spec. Hixie speced it. Hixie is happy with TC39 moving this to ES.

YK: Like to object to this motion. It is currently a giant set of scenario hacks.

DL: We want to add language objects that we want to transfer.

AWB: Cloning framework in ES.

DH: Is it possible to reform or do we have to start from scratch? Seems hard to reform. Too many issues.

MM: Fears that if we do not take it over and introduce something new. The old will continue to exist. We need a path to replace the existing system, including what PostMessage does.

DH: We need a roadmap. How do we handle transferables?

DH: Hixie (or Anne) added Map and Set to structured clone to HTML spec.

DL: We cannot add extensibility mechanisms if we do not own the spec.

YK: We should own the spec. Opposed to DOM specific extensibility methods. General extensibility mechanism are important.

BE: How would symbols work?

AWB: We have a symbol registry. As long as both side cooperate. Serialize to a registration key. The two sides need to agree.

MM: It is unobservable that the symbol is not the same across the two workers.

WH: What if you have the same symbol registered under two different strings?

MM: That can't be allowed.

BE: in the cross-machine limit, structured clone is serlialization/deserialization; start there, allow optimizations like Sun XDR, Van Jacobsen TCP/IP, Google protocolbuffers [discussion on optimization]

WH: What do we mean by optimization?

DH: [explains difference between opaque and structured clone, including implications on optimization]

WH: Are we going to settle on one of the two or do both?

DH: Both [more discussion on optimization]

BE: [explains history of prior work]

BE: Can't tell Hixie and Anne to stop adding to structured clone. Anne: Want to give them assurance that we will take over the effort.

WH: What's the consensus?

YK: We'll take it on. Move to stage 0.x

link defineGetter, defineSetter etc in Annex B?

BT: IE ships this.

MM: It would just be speced using defineProperty etc

AWB: Firefox does some strange things.

BE: please enumerate "strange things", file bugs

YK: It starts at level 1. Or 3? there are already implementations.

RW: What sites?

BT: Will attempt to furnish a list of sites...

link Conclusion/resolution:

  • Makes sense to put in ES7 annex B
  • Brian to write an initial speec draft

link Process document

Process doc is now public https://docs.google.com/a/chromium.org/document/d/1QbEE0BsO4lvl7NFTn5WXWeiEIBfaVUF7Dk0hpPpPDzU

link Scheduling for next meeting

April 8-10 at Mozilla, San Francisco May 20-22 at Facebook, Menlo Park July 29-32 at Microsoft, Redmond Sept 23-25 at Bocoup, Boston Nov 18-20 at PayPal, San Jose

link Async/await

LH: https://github.com/lukehoban/ecmascript-asyncawait

LH, MM: await syntax is important because the precedence of await needs to be different than yield.

LH: async functions could be combined with function*; in such a thing we'd need both yield and await

MM, WH: What would the behavior of such a thing be?

LH: That's a seperate proposal - something we can discuss later.

BE: Syntax conflict with => functions (elided parameters). what does: async() // newline, no semi here => {...} ... mean? We can make it be an async arrow if we want, but second line looks like 0-param arrow function expression....

WH: async (a, b, c) => await d looks too much like a function call of a function named 'async'. Need to parse a long way before figuring out it's an async lambda. This wouldn't fall under the existing cover grammar.

LH: I'll look into that.

DH: Initially concerned about hard-coding the scheduler.

LH: Identical to Q.async. There is only one way to do this.

MM: September Promises consensus is superior to the Promises spec we have now. [Debate about whether we'll end up with two Promises APIs]

WH: Do the two APIs use the same scheduler (that would be hardcoded)?

DH: No.

LH: Can we move async/await to stage 1? General agreement

AWB: This means that we agree that this is something in a future version of ES

link Conclusion/Resolution

  • Moved async/await to stage 1.
  • Next step is to write real spec language

link Promises discussion

MM: Advocacy for .then()/.cast()

STH: Advocacy for .chain()

LH: Proposal of Promise.chain() compromise

YK: I would probably be ok with this

MM: I would probably be ok with this ... extensive discussion ...

MM: A resolve of a resolve does not create multiple levels of wrapping. Without chain this is not observable.

BE: .chain() requires over-wrapping/-unwrapping, without chain this is unobservable and therefore optimizable -- says to reject chain (surprised by own position changing)

YK: This persuades me that we shouldn't have .chain()

STH: I strongly disagree, but I'm not going to hold up ES6 over this

link Conclusion/Resolution

  • 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

Some further discussion on keeping the spec inheritance/AOP-friendly by not using .then internally some times, short-cutting through internal methods or internal helpers other times YK, MM, AWB have details

Ecma/TC39 Meeting – Jan 29 2014

link Jan 29 Meeting Notes

John Neumann (JN), Allen Wirfs-Brock (AWB), Yehuda Katz (YK), Eric Ferraiuolo (EF), Erik Arvidsson (EA), Rick Hudson (RH), Matt Sweeney (MS), Dmitry Soshnikov (DS), Sebastian Markbage (SM), Ben Newman (BN), Jeff Morrison (JM), Reid Burke (RB), Waldemar Horwat (WH), Doug Crockford (DC), Mark Miller (MM), Brian Terlson (BT), Luke Hoban (LH), Andreas Rossberg (ARB), Istvan Sebestyen (IS), Niko Matsakis (NM), Brendan Eich (BE), Rick Waldron (RW), Sam Tobin-Hochstadt (STH), Rafael Weinstein (RWS), Dmitry Lomov (DL), Niko Matsakis (NM), Simon Kaegi (SK), Kevin Reid (KR), Dave Herman (DH)

link Function in Blocks in non strict mode.

(Ask Brian for slides)

BT: In ES6 draft in appendix B (since functions in block are not in ES5 but implemented)

BT: IE11 shipped with function in block in non strict mode.

BT: Hoists across let blocks

AWB: If you start using a let then you'll get an error. Since old code does not use let.

LH: If the code falls out of the known patterns you hit a rough edge and then it is better to get an error than undefined behavior.

WH: Concerned about expanding past the minimal crazy intersection semantics we agreed to in the past. The proposal expands the set of cases that produce surprise captures.

WH: [on whiteboard] This is not just about eliminating errors. It will silently change the meaning of working code:

1
2
3
4
5
6
7
function foo() { ... 1 ... }
function bar() {
if (...) {
function foo() { ... 2 ... }
}
foo(); // Thought it would refer to the outer scope foo. Surprise!
}
1
2
3
4
5
6
7
8
9
10
function foo() { ... 1 ... }
function bar() {
if (...) {
let foo =...;
{
function foo() { ... 2 ... }
}
}
foo();
}

LH: Since 1.5% depend on the crazy behavior we have no real option.

WH: Let's limit the craziness to just the cases in the minimal intersection semantics.

BT: Allow hoisting past a let.

ARB: What was the motivation for this special case, i.e., why not drop all hoists that would normally be an error?

LH: Creates 2 bindings. The FunctionDeclaration itself mutates both the var binding and the let binding.

1
2
3
4
5
6
7
8
9
10
(function() {
{
let foo;
{
function f() {} // Why no error?
}
console.log(foo); // undefined
}
console.log(foo); // funtion foo() {}
})();

DH: If you inject a let and it shadows a var it should be a static error.

LH: In strict mode it is legal so it cannot be an error in non strict.

DH: It is consistent with a var in a block.

ARB: What happens if you have two functions

LH: You conceptually get two var bindings.

WH: That's not part of the intersection semantics. Shouldn't get any if you have two foo's in inner blocks.

YK: Writing new ES6 code in non strict should still work.

WH: It will silently do different and surprising things, as per examples above.

DH: If there is any intervening let binding do not hoist past the let.

LH: If introducing would introduce a static error. Do not introduce the var binding. [Discussion on the behavior of the new var bindings, along with whether assignment to foo updates one or both.]

WH: When are the crazy introduced var bindings initialized? At entry to outer function bar (just like ES5 inner functions in the top-level of an outer function), or at the time the inner function function foo definition is executed? Various: Set to undefined on entry to outer function. Set when inner function definition foo is executed. Various: Executing function definition updates both the let and the var bindings. Assignment updates only the let binding.

WH: [points out (and likes) warning on cases "for which the above steps are performed" in Annex B of the current draft] [Long discussion about warnings, SHOULD, and their audience]

LH: A SHOULD warning seems a reasonable addition to the proposal here.

link Conclusion/resolution

  • 2 bindings.
  • Hoist a var binding for the FunctionDeclaration, unless it would introduce a static error (ie. hoisting past a let will not cause an error but also not create the var binding).
  • Also create a let binding as per pure (strict mode) ES6 semantics. (Change from IE11 semantics). Within the scope of the let binding, assignment will only touch the let binding (ie. normal semantics).
  • The var binding is only initialized at dynamic evaluation of function declaration.
  • A SHOULD warning if there is a reference to any such var binding of a function

link Object.observe Status Report

RWS: Suggest moving OO to the second stage. :: Approved

RWS: Wants to move OO to the third stage, which requires a spec text review.

YK: Has reviewed it already.

AWB: Might have time to review.

RWS: The plan is to ship OO in Chrome sometime around April.

AWB: Should not be a problem to advance without scrutizing the proposal. Willing to rubber stamp at this point. Since we are in a state where we are. (?)

YK: Once we are at stage 3 we are committed to not revisit.

RWS/YK to talk about task scheduling.

link Conclusion/resolution

???

link Post ES6 process

AWB: First step is to post the process somewhere public

AWB: Second, need a place to track the progress

AWB: Thinking we should do this on GitHub. Project TC39/meta. Master table. Or maybe 2 tables?

WH: Are we abandoning the wiki? Various: yes

WH: How do I view HTML instead of the HTML source on GitHub?

EA: We should also move the meeting notes from rwaldron/* to TC39/*

YK: We should use the GitHub API to extract the comments for keeping the paper-trail.

RWS: Agenda changes since last time 1. Add a designated reviewer. 2. At step 3 and 4 there is a requirement to get an approval from the spec editor.

RWS: Also managing spec in flight

YK: I'm going to work in that.

link Do Expression

(Ask for slides from ARB)

MM: An engine can statically detect an IIFE and treat it as a do expression.

DS: Important to scope var declarations to the enclosing function rather than the do block because that's what happens in a do-while loop, and it's hard to tell if you're looking at a do block or a do-while loop.

1
2
3
4
5
do {
...
}
while(true);

WH, DH: Expression statements cannot start with do to avoid syntactic conflicts.

BE: Just like function for FunctionExression which cannot start ExpressionStatement.

DH: Just use a parentheses if you really need to start ExpressionStatement with do.

AWB: What step is this in the new process? Step 0?

ARB: Can write spec

DH: Primary reviewer.

link Conclusion/resolution

  • do-expressions as generailsation of block statements
  • Progresses do-expressions to the next state in the new process.

link Security Review for Loaders/Realms

MM: We have considered a security review for Loaders & Realms

YK: Talked about this earlier, seemed positive

STH: Concerned about definition/scope KR Gave vague definition

MM: We'd like to do the same things we did in ES5 KR Considering porting SES to ES6. DH/ STH: this is an excellent goal

MM: What's the implementation status of Loaders/Realms

DH: Unpolyfillable, YK + DH tried some things w/ iframes, didn't work

DH: That's part of why we think it's a fundamental new primitive

link Conclusion/Resolution

  • MM et al to port SES to ES6, contact module champions w/ results

link Typed Objects

Dmitry Lomov + Niko Matsakis

NM: Not objects

WH: Likes that === compares identities, but would prefer that == compare values.

NM: THat would be dangerous since structs are mutable.

WH: In that case, how do you compare values? That's a really common thing that users will want to be able to do.

ARB: Accessing a sub struct of a struct does not allocate any object.

NM: You can stack allocate

1
2
3
4
5
Line = new StructType({from: Point, ...})
line = Line(...)
while ( ... ) {
foo(line.from)
}

DH: If line.from heap allocates it would be suprising.

WH: How does stack allocation work if the reference to the allocated object escapes the scope?

WH: Important to be able to mark StructTypes to always generate opaque fat pointers even if they don't have any 'any' field.

WH: This helps with optimization. Knowing that all instances of a StructType are opaque lets NaN-boxing implementations optimize out protection against NaN-injection on reads.

link Value Objects

http://www.slideshare.net/BrendanEich/value-objects2

Ecma/TC39 Meeting – Jan 28 2014

link Jan 28 Meeting Notes

John Neumann (JN), Allen Wirfs-Brock (AWB), Yehuda Katz (YK), Eric Ferraiuolo (EF), Erik Arvidsson (EA), Rick Hudson (RH), Matt Sweeney (MS), Dmitry Soshnikov (DS), Sebastian Markbage (SM), Ben Newman (BN), Jeff Morrison (JM), Reid Burke (RB), Waldemar Horwat (WH), Doug Crockford (DC), Mark Miller (MM), Brian Terlson (BT), Luke Hoban (LH), Andreas Rossberg (ARB), Istvan Sebestyen (IS), Niko Matsakis (NM), Brendan Eich (BE), Rick Waldron (RW), Sam Tobin-Hochstadt (STH), Simon Kaegi (SK), Dave Herman (DH)

IS: Talk about the royalty free task group

JN: Approved, 9 in favor. 0 opposed. 0 abstains. We are now operating as a Royalty Free Task Group

JN: Netflix and Apple haven't returned the paper work.

IS: Neither from Brown University. (and a bunch of other universities that are not active any more)

link Agenda

JN: Agenda approved https://github.com/tc39/agendas/blob/master/2014/01.md

JN: Minutes from Nov meetings also approved. (https://github.com/rwaldron/tc39-notes/tree/master/es6/2013-11)

link Spec Status update

AWB: Latest draft (Rev22) is the "almost feature complete" version. (Discussion about process troubles). Spec now uses a master document and is split into multiple files.

AWB: Still some work to do on Direct Proxies. Update spec for C-style for-let. Loaders and Realms are integrated into the spec draft. Lots of review needed.

EA: Standard modules were deferred at last F2F

LH: We agreed on globally reachable names for all pre-modules APIs last September. New names for module loaders APIs need similar design.

AWB: Loader and Realm are speced as %Loader% and %Realm% since we haven't talked about their public names.

DH: Where does Reflect go?

AWB: Use a global.

DH: Realm can go in Reflect since it is a very reflective thing.

DH: We can probably defer System too.

YK: We need an entry point and a global named System seems to be good.

DH: Loader can go in Reflect too.

AWB: Need to update the spec draft to match the scoping rules we agreed to before.

link Resolution

link Aside on detecting Module vs. Script (see http://esdiscuss.org/topic/detecting-js-language-mode-for-tools)

Debate about whether it's required (partial agreement that it is since they are clearly distinct)

WH: Even though they're distinct, doesn't mean that they must be ambiguous with each other at the source text level. We could easily say that a module has to start with some syntax that designates it as a module.

AWB: Spec doesn't necessarily need to address this (why?) but we should consider setting the direction here. If we're fine with the community coming up with something here we can lean on that too.

LH: This process has to happen, there will be lots of solutions, we might not pick the best one.

Potential solutions:

  • YK: Bower uses metadata for packages that say they're ES6 module
  • DH: Possibly do nothing, we live in this world already today
  • DH: Come up with some kind of syntactical distinction
    • DH: This sucks, modules should not require additional boilerplate to be valueable
  • Possibly use file extensions...

link Conclusion/resolution:

  • DH to do the work?

link Task and Tasks Queues

Postponed until tomorrow when Raf is here.

link Process for ratifying ES6?

LH: We have now effectively met the "feature complete draft" requirement we were targetting. Are there any process requirements this group is placing on progressing the spec to ratifica

BE: Have nothing, same as ES5. (Discussion about whether we can be strict)

LH: For example, do we have "multiple compatibile implementations" requirements? Or "test262 coverage" requirements? Our ES7 process proposal has these, but do we want/need some limitied version of this for ES6?

AWB: We just need to ship it and get to the stricter process for ES7.

MM: We can always postpone features to ES7 if they seem to be problematic.

BE: For example, there is unlikely to be an implementation of proper tail calls before we send ES6 to the GA, then to ISO. I don't think we should defer them on that basis, but it's a fact. We should not slip ES6's schedule.

LH: If by the time we ratify ES7 and there are still ES6 features that have not yet been implemented by anyone, we should re-evaluate if we can remove them.

link Resolution

The commitee is putting no blocking requirements of implementations or tests on standardization of ES6.

link Concise methods and Enumerability

YK: People have object literals today and use these objects with for-in loops to find the properties and if they change to non enumerable consise methods things will break.

AWB: Concise methods were initially non-enumerable. This was to match the built-in classes, like Date, Array etc. One possibility is to make methods in classes non enumerable but concise methods in object literals enumerable.

RW: The same issue happens when people use object literals as the prototype.

AWB: Should Map and Set methods be enumerable then?

RW: The spec should be consistent with itself.

WH: User-defined classes should be consistent with built-in classes. Classes are new in ES6. The question is whether it's the class that turns off enumerability or the concise method that turns off enumerability.

WH: My preference is for the consise method syntax to turn off enumerability. In the rare cases that you want an enumerable method in a prototype, you can define it the longer way.

YK: Refactoring should be simple and not have side effects like these.

RW: hasOwnProperty solves the problem of filtering out class methods inherited from the prototype, so we don't need to make them non-enumerable.

BE: people don't use hasOwnProperty

YK: enumerability is broken, we should not discuss the Platonic ideal form of enumerability

BE: According to Neo-Platonic Mystics, the material world was created by the evil Demiurge, not by Sophia (wisdom). Enumerability and 'for-in' are from the Demiurge.

BE: Enumerating options: * Concise methods and class methods are enumerable * Current es6 draft state * Split the difference, concise methods enumerable, class methods non-enumerable. * can't refactor between es5 object literal and es6 class/concise methods depending on which is non-enumerable * Make both non-enumerable (Waldemar supports) * same refactoring hazard, possibly not desirable * Some tilde-based or better syntax to allow developers to pick, but go with option 1

YK: Hope that we can use annotations in ES.Future that can control this kind of details.

BE: Agree, so fourth option above.

YK/LH: High bar to make a change, does this meet the bar?

link Conclusion/Resolution

  • Status quo. Keep concise methods enumerable.

link More on toMethod

AWB: Function.prototype.toMethod(superBinding, methodName = undefined) Footgun to put this on Function.prototype.

MM: potential suprise: in the absence of toMethod, super's interpretation can't change, but now people have to account for possibility of shifting interpretation, which requires them to know about toMethod (not sure if I'm getting this right- BN)

AWB: The footgun is that we do not propagate any properties.

AWB: Suggest moving toMethod to Reflect

DH: Needs to be renamed then.

?: Suggests renaming to bindSuper.

WH: We've discussed all of this before and reached consensus. bindSuper is a bad name because it intentionally doesn't commute with bind.

WH: [reviews consensus from past meeting]

AWB: expect people to define Object.defineMethod in terms of toMethod, with copying of properties

DS: do we also need toStaticMethod?

AWB: no, you can just use toMethod with the constructor function as the superBinding / home object

BN: are static/class methods inherited?

AWB: yes

AWB: should we copy .name and/or .length to the new function object?

MM: use bind as a precedent to decide what to copy (mixed messages though: bind does copy .length, minus the number of curried arguments, and (in SpiderMonkey at least) copies the .name, though V8 gives the bound function an empty string .name)

AWB: What should happen if toMethod is called on a non ECMAScipt function object (built-in)

MM: How about just returning a clone of the function. You could even even delegate in a similar way as bind.

AWB: Only allow toMethod on unbound methods?

MM: to preserve possibility of transparent monkey-patching, either make toMethod return something that can't be toMethod-ed again, or allow built-in (non-ECMAScript Function Object) functions to be cloned, which requires an additional path in the internal CloneMethod operation (because it currently asserts that the clonee is an ESFO)

link Conclusion/Resolution

  • Allen to take it back to the lab. To get it to work with bound functions and built-ins.
    • Make it match old concensus func.bind().toMethod(...) should throw
    • Does not work on proxies

link Clz (count leading zeros)

WH: Don't like deliberately introducing anachronisms a la 1900-origin getYear into the language. Would prefer to have it be origin-0 instead of origin-32 (i.e. return 0 instead of 32 when called on 0) to avoid hardwiring a machine word size. However, understand that we want this to compile to an efficient low-level primitive, so it would still have the toUInt32 as part of its semantics. In that case we should call it clz32 instead of clz so that later we can do clz64 (that would call a future toUInt64) or other variants.

BE: Want it to map to one single machine instruction

BE: Mislocated, should be on Math

BE: (missed the third point)

BE: CLZ - for cases when you're doing DSP-level hacking, and want to count the number of populated bits. Also important for native-to-js compilers, there is an intrinsic for this in GCC and Clang. BE: Math.clz32 wins.

link Conclusion/Resolution

  • Rename to Math.clz32 (rename and move from Number.prototype)

link Array.from

AWB: What should happen with Array.from(undefined)?

EA: Array.from is a likely replacement for Array.prototype.slice.call and the array generics do ToObject.

AWB: Array with holes would lead to to a dense array.

YK: Want to keep the holes.

BE: "Holes are from the devil"

link Conclusion/Resolution

Keep as spec'ed. * Array.from will throw on undefined and null * Array.from will return [] for 3 * Array.from([0, , 2]) => [0, undefined, 2]

link Test 262

BT: Up on GitHub. https://github.com/tc39/test262. Conversion from Mercurial done by Brandon Benvie.

BT: AttendedTest the web forward. Got a lot of PR (22).

BT: Pending contributor guidelines.

BT: Going to work on style guidelines since the PRs are inconsistent.

IS: Getting CLA working is highest prioroty.

BT: Do we need any test coverage before approving ES6?

BT: For ES7 we agreed that we need tests before final spec.

BT: Instead of using numbered section plan to use the HTML anchor names from the HTML version of the spec.

link Yield and its precendence

Code Samples: https://gist.github.com/lukehoban/8678463

LH: Presents code samples. All but "yield 1+2" seem strange. Any time you have a generator that pumps values in you want good expression semantics.

WH: Points to yield 1+2 alternatives in LH's code samples; one makes it mean (yield 1)+2, the other makes it mean yield(1+2). Strongly prefers the latter.

BE: Have to make a choice that yield should be high precedence or low precedence. yield x + y must be yield(x + y) without parens, the rest follows by the grammar.

LH: concede

:: conversation about whether implementing iterators is more common or taskjs-like scenarios are more common ::

BN: Status quo causes more errors but errors encourage parenthesization, and enables yield 1 + 2 to yield the value 3

LH: For the async use case, important to have high precendence, but willing to concede that yield should remain low precenedence due to iterators use cases. Async use cases could have new "await" syntax with high precendence.

YK: task.js requires (yield a) + (yield b) paren style

BE: revenge of Lisp, you get used to it

link Conclusion/Resolution

  • Status Quo

link Newborn generator behavior

(Ben)

See issue here: https://github.com/tc39/agendas/pull/25

DH: Intention was for generators to be composable.

BN: Proposal: generator with yield* doesn't throw when receiving a value

DH: Breaks correspondance between yield* and for-of desugaring. Also... wrappers are not equivalent unless both wrapper and wrapped are newborn.

BN: Can be fixed... but is hairy. Presents updated wrapper code... Proposal is that we remove the type error for passing in a value to an unborn generator. Then, if the first yield we encounter is a yield *, pass in the value that was passed to the unborn generator. :: Concerns with proposal (please fill?) ::

DH: Possibly other alternatives to fix this?

WH: There are two problems here:

  1. A function* can't capture the first value passed to the 'next' that invoked it. Instead, it currently requires it to be undefined.
  2. No way to pass an initial 'next' value to yield *. This means that manually doing the first yield followed by a yield * wouldn't help because the problem would then reappear on the second yield.

WH: The proposal is proposing a hidden channel (a la Perl's $_) that ties 1 to 2 here. Would prefer mechanisms to do those separately and more explicitly.

BN: yield syntax that says delegate but don't care about value?

DH: Let's think about it more...

DH: Went through the mental excercise to do an implicit yield upon calling the generator. Leads to a lot of other issues.

1
2
3
function* first() {
return yield* push(first, delegate);
}

link Concensus/Resolution

  • BN: Have to go back and think more about this. Maybe a helper function can be created.

link ECMA-404 and IETF interactions

AWB: IETF is not comfortable referencing ECMA.

IS: IETF includes ECMA-404 as an informative reference (?)

AWB: Proposed doing a second edition if IETF wanted to work with ECMA. :: Discussion about IETF participation, general dissatisfaction with the process and end result :: See http://www.ietf.org/mail-archive/web/json/current/threads.html#02131 and look for "R S" (Rob Sayre) fighting the good fight

Ecma/TC39 Meeting – Nov 21 2013

link Nov 21 Meeting Notes

John Neumann (JN), Allen Wirfs-Brock (AWB), Yehuda Katz (YK), Eric Ferraiuolo (EF), Erik Arvidsson (EA), Rick Hudson (RH), Matt Sweeney (MS), Rick Waldron (RW), Dmitry Soshnikov (DS), Sebastian Markbage (SM), Ben Newman (BN), Jeff Morrison (JM), Reid Burke (RB), Waldemar Horwat (WH), Doug Crockford (DC), Tom Van Custem (TVC), Mark Miller (MM), Brian Terlson (BT), Andreas Rossberg (ARB), Alex Russell (AR), Mark Miller (MM)

link Follow Up on IETF JSON WG Communication document

(review)

link Conclusion/Resolution

  • Unanimous consent

link 4.5 Modules

(Dave Herman, Sam Tobin-Hochstadt)

(request slides)

(fighting Google Hangouts for fun and profit)

DH: Spec draft: Done. Initial implementation for Firefox, POC for spec: https://github.com/jorendorff/js-loaders

End-to-End Draft Done:

  • Linking semantics
  • Loading semantics
  • Execution semantics
  • Loader API
  • Dynamic: CommonJS, AMD, Node compatibility layer
  • Bonus: literate implementation starting to pass simple tests

DH: there's a compat layer for dynamic import systems. Hope is that in a couple of months it can ship in nightly FF.

EA: is there a license on this?

DH: no, but we'll add one.

AWB: if you're contributing to ECMA, it has to be under the ECMA software contribution rules (ie, BSD license)

AR: can you add a license today?

ARB: how are these files related to each other?

DH: things are extracted from the source, and the short version is that the actual wording is now done. Then next steps are to improve the formatting and work with AWB to reconcile editorial issues.

AWB: yes, this is what we've done with Proxies/Promises/etc. Something we know how todo. if there are normative changes, they'll get resolved.

ES6 Draft

  • Updated syntax for new parameterized grammar
  • Static semantics done and implemented

DH: stuff that has been through the editorial process are the syntax, the static grammar, and static semantic rules. Don't have a doc dump this morning but can generate one today and send it around.

DH: didn't have a chance this morning to do it yet.

ARB: was only looking at the docx fragments so far...

DH: wanted to talk a bit about the last bits of the semantic cleanups. The distinction between scripts and modules and the browser integration: <script async> was a way to allow you to use the module system at the top level. This creates 3 global non-terminals. I say you dont' need <script async>.

Clean Ups

  • Scripts and Modules

  • Three goal non-terminals (Modules, Script, ScriptAsync) is one too many

  • Elimintaing imports from scripts simplifies the Loader API—loading is purely about modules

  • <script async> was a non-start anyway

DH: in additon, the idea of using <script async> was misguided.

AR: no, we can fix <script async>

WH: we discussed this at previous meetings, what happened to the need for script async?

DH: <module> instead. A nicer path forward for the web. Automatic async semantics. More concise than <script async>.

  • Not part of ECMAScript
  • As concise as <script>
  • More concise than <script async>
  • allows inline source
  • implicitly strict (as all modules are)
  • Named <module> provide source up front
  • Anonymous <module> async but force exec

AR: this has real security issues.

YK: this can have other forms -- <script type="module">...etc...

DH: the goal here is to come up with the cleanest design we can come up with on the JS side and drawing a sharper distinction between scripts and modules. You get to start in a clean scope. Top-level decls are scoped to the module.

DH: you also get implicit strict mode. And inline source.

AR: this is never going to work in the field. This will violate expectations.

YK: can you show me what's secure today that does blacklisting?

AR: no, but that's not the argument.

<module> is a better 1JS

  • Better global scoping: starts in a nested scope
  • To Create persistent globals, must opt in, by mutating window/this
  • Conservation of concepts: no special semantics required for reforming global scope, just a module
  • A carrot to lead away from blocking scripts
  • still accessible to scripts via System.import

WH: Universal parsing is a problem. HTML parsers know that escaping rules are different within a script tag but not within some other random tags such as module.

EA: you can see a transition path that starts with <script type="module"> and move to <module> later

(some agreement)

DH: if <module> turns out not to work, we have other options. One of these is likely to work

AR: agree.

Alternatives:

  • script module
  • script type="module"

DH: benefits include: top-level decls are local. You can persist by opting in (window.foo = ...), but it's not a foot gun via var. No special semantics for the global scope; it's jsut a module. Still accessible via System.import.

1
2
3
4
5
6
7
<module>
var foo = 1;
</module>
<script>
foo; // undefined.
</script>

DH: Recapping the concatenation story.

(didn't we all do this before?)

YK: <module> and <script module> are morally equivalent

STH: to address issues with <script async>, we need a separate entry point. Any of the others listed here address the use cases brought up that <script async> addresses.

WH:now you have 3 things

(emphatic disagreement)

DH: there are 2 terminals in the global of JS in this world, not 3. <script> and <script async> have the same terminal production

DH: we've had a hard time working through the global scoping semantics. We don't need special semantics for a reformed global scope. Deflty avoids implicating global semantics. Just write modules.

ARB: you still need the lexical contour, no?

DH: yes, but lets talk about that at the end.

DH/YK: there's an unnamed module loading timing that's before <script defer>

EA: you can't wait till domcontentloaded to run stuff. Need stuff running sooner.

ARB: Multiple module elements?

AR: Document order

EA: I jsut don't want us to cripple the system for this use-case, e.g. the HTML5 doc.

AR: you need both.

YK: a sync attr seems fine.

DH: we can't operate as if the web didn't exist, but we can't define HTML elements, so we need a story but not the answer.

BE: partial progress if possible

DH: lets talk about the loader API. Will send out slides soon;

Loader API

1
2
3
4
5
6
7
var l = new Loader({
normalize: n, // Promise<stringable>
locate l, // Promise<address>, formerly "resolve"
fetch f, // Promise<source>
translate t, // Promise<source>
instantiate f, // Promise<factory?>, formerly "link"
});

address -> where to find this source -> the source text

WH: what's fetch for?

DH: gets the bits that are stored. The translate hook provides ways of transforming bits into other bits.

YK: instantiate is the bridge for legacy module forms: amd, node, etc.

WH: What exactly is promised in each step? (see gist)

Core API

1
2
3
4
5
6
7
8
9
// Loader API
// Promise<void>
l.load(name[, opts]);
// Promise<void>
l.define(name, src[, opts]);
// Promise<Module>
l.module(src[, opts]);

WH: If load is called twice, does it reuse the same module?

DH: Yes

WH: Concerned about options. How close do the options have to be to reuse instead of loading twice?

DH: the main option here is that you can skip the locate step. Load lets you start at multiple places.

DH: define() lets you do things after the fetch step, while module() lets you do the anonymous module thing.

EA: I'm worried that define() is a new eval().

DH: yes, that's what it's about. Downloading and evaulating code. Some people say "eval is evil" and I say "there would be no JS on the web without it". This is a more controlled and sandboxed way of doing it.

WH: define returns a promise of void. How do you safely use the defined module?

EA: I'm worried about CSP.

DH: l.import() as a convenience api. Kicks off a load and forces an execution of the module. Resolves to the module object. It's a nice way of doing it all in one shot.

DH: the registry API

1
2
3
4
5
6
7
// Registry API, methods on a Loader instance
l.get(name) // Module?
l.set(name, m) // void
l.has(name) // boolean
l.keys() // Iter<string>
l.values() // Iter<Module>
l.entries() // Iter<[string, Module]>

MM: delete?

BE/RW: size property?

AR: if you can change it, you can delete...why not have it?

DH: you might astonish a running system

STH: it only removes it from the mapping. Agree with the misgivvings, but we should have it.

YK: I can imagine delete for security purposes

STH: clear() would be insane to use, but....

MM: if we have an existing contract, we should have it, else we should define some supertype

DH: it's a no-op in JS to do that. People are warming up on delete()

WH: what do these things actually do? eg. l.define(name, ...); then l.get(name)?

YK: there's a turn between when things are done and when they're ocmmitte. You see the "old" view.

WH: What happens when you call define twice with the same name?

DH: They race. Name stays what it was until one of them gets fulfilled; it's nondeterministic which one.

WH: How do you find out if there's a pending define on a name?

DH: You can't.

WH: That makes it impossible to write safe modular code unless you're the very first thing to run. Otherwise anything you try to define could be racing with something already started.

DH: set is synchronous "add this eagerly". Get is sync get.

DH: this is an inherently racy API because module loading is racy.

WH: why not placeholders indicating that a load is in progress?

DH: there's an implicit one in the system, and we try to have sanity checks, but ....

STH: now it's observable that things are loading in some order

WH: That turns a race condition into a reliable fail. If someone tries to load a module and then I load a module of the same name, I want that to fail.

STH: (explains pollyfill)

WH: True, but don't see how that's relevant. I have no problem with module replacing. I want it done in a safe way, not in a racy way.

DH: We have handling

EF: Do yo have slides for all the exceptions?

DH: Do not, Jason has it documented, but could not be here.

STH: There are thousands of lines that explain all of this very precisely.

WH: I asked this earlier, what happens when I call define with the same name twice and was told it's non-deterministic.

DH: I stand by the statement that this is non-deterministic, there are too many cases. (explains several common and uncommon cases)

e.g., jquery dep fails, but something else depends on it. zero refcount. Common deps may cause successful subsets to succeed or fail together.

WH: agree that you'll get non-determinism. But should we hide the started/unstarted state from the user?

(discussion of observability)

BE: Let's take

DS: The registry is global or tied to a particular loader

DH: A built in loader called "System"

Decoupling Realms from Loaders

(smells)

  • Loaders are really about modules, but eval/evalAsync represnt scripts
  • Mixing concerns: scripts vs modules
  • Mixing concerns: module loading vs sandboxing
  • Capability hazard: new Loader({ intrinsics: otherLoader })

Realms: Globals, Intrinsics, Eval Hooks

(facts)

  • Global object & Function/eval are "intertwingled"
  • Intrinsics and standard constructors, prototypes are "intertwingled"
  • Realm and intrinsics are "intertwingled"
  • Everything is deeply "intertwingled"

YK: (explains import from registry) ... Can create a different Loader for maintaining state in a specific module while loading another module of the same name.

Realm API

A realm object abstracts the notion of a distinct global environment.

1
2
3
let loader = new Loader({
realm: r, // a Realm object
});

https://gist.github.com/dherman/7568885

1
2
3
4
5
let r = new Realm({ ... });
r.global.myGlobal = 17;
r.eval(...);

AWB: This "Realm" as a global object is questionable.

DH: Talking about "Realm", "Loader" and "Module", likely should be in a "module" module.

Seperable From Loader API

  • Important, but it's a separate concern
  • Loader defaults to its own realm
  • Realms; sandboxing, sync script executuon
  • Loaders: async module execution

DH: a "Realm" is a "virtual iframe" from the same domain. It's a global with the DOM stripped out of it.

WH: Think there should be commonalities between API surface of Realm and Worker

MM: When you create a new Realm, what do you provide in order to give it initial state? ... Let's just keep this in mind.

Realm API

1
2
3
4
5
6
7
8
9
10
let realm = new Realm({
eval: ...,
Function: ...
}, function(builtins) {
// global object starts empty
// populate with standard builtins
mixin(this.global, builtins);
});

DH: First object contains things to explicitly add to the Realm's global.

EA: What happens when you omit it.

DH: you get an object that inherits from Object.prototype

WH: Is the global object always accessible at this.global?

DH: Yes

EA: This is the wrong default, we need something else.

MM: The only properties on global object that are non-configurable are NaN, Infinity, and undefined

DH: Better to start out empty and fill it yourself then to create something that almost looks like global

EA: The most common case is a global environment with all the builtins, should be the default

RW: agree

MM: So, if the callback is omitted, you get a realm that is the default environment with all the builtins.

EA/RW/DH: yes

STH: If the callback is provide, the realm's global is a null prototype object

(summarize change)

  • no callback, default environment with all the builtins
  • w/ callback, object with null [[Prototype]]

WH: What does the init provide?

DH: Allows you to whitelist what goes into your realm

AR: what about the second arg? can that be folded into the first?

DH: yes, perhaps "init: function(...) { }"

Indirect Eval

1
2
3
4
5
6
7
8
9
let caja = new Realm({
indirectEval: function(args) {
return anything
}
});
caja.eval(`
(0, eval)("1 + 2")
`);

STH: I was really skeptical of this, but I was persuaded.

WH: Why not use something simpler such as define realm.evalToken as the function to compare against what the eval identifier evaluates to in order to check for direct vs. indirect eval?

(Offline conversation with MM/DH/YK/BT: indirectEval hook returning the result of eval wont' work without a way to refer to eval. Fix is to make indrectEval a translate hook similar to directEval.)

Direct Eval

1
2
3
4
5
6
7
8
9
10
let caja = new Realm({
eval: {
direct: {
translate: (s) => { ... }
}
}
});
caja.eval(`{ let tmp = f();
eval("tmp") }`);

Direct Eval

1
2
3
4
5
6
7
8
9
10
let caja = new Realm({
eval: {
direct: {
fallback: (f, ...rest) => { ... }
}
}
});
caja.eval(`{ let tmp = f();
eval("tmp") }`);

WH: Why so many levels of destructuring in the first parameter to the Realm constructor? Do we need then all?

Function

1
2
3
4
5
6
7
let caja = new Realm({
Function: (args, body) => { ... }
});
caja.eval(`
Function("x", "return x + 1")
`);

ARB: Why not spec it by defined concatenation plus eval?

STH: Explains the issues the exist with toString.

WH: If the engine validates the arguments before calling Function then that limits the ability to provide new syntax for Function (for transpilers).

DH:

  • Can't create new arguments syntax
  • Simpler apis lose strong guarantees from validation?
  • (need the third reason)

Function*

1
2
3
4
5
6
7
let caja = new Realm({
Function: (args, body, prefix) => { ... }
});
caja.eval(`
(function*().constructor("x", "return x + 1")
`);

prefix is the string that is either "function" or "function *"

DS: concern for changes in semantics of

discussion re: eval of source code

DH: Returning source code is the more conservative

MM: script injection problems because people want to create source from concatenation. If we translate an array of source pieces, then we're not doing concatenation in the spec.

MM: The string that's the prefix piece determines the constructor. "function" => Function, "function*" => Generator

DH: two place you can reach the function constructor

  • Function global
  • Function.prototype.constructor

If you mutate Function.prototype.constructor

  1. Create a new Realm
  2. Save the original Function.prototype.constructor to the side
  3. Create a new Function in that global
  4. Mutate its Function.prototype.constructor to whatever you want

MM: This strategy has been field tested in SES

STH: Function.prototype.proto?

BT: Object.prototype

Realm API

1
2
3
4
5
6
7
8
9
let r = new Realm({
eval: {
indirect,
direct: {
translate, fallback
}
},
Function
});

DH: A compiler for ES7 -> ES6. The compiler has some static source its carrying around and comes to:

1
2
3
4
|-
|-
|-
eval(x)

And contains source:

1
{t1, t2, t3}

Translate to an Identifier "eval", no way around this

1
2
3
4
5
6
7
8
...
translate: function(s, src) {
return compile(s, src);
}
fallback: function(f, ...rest) {
return f(...rest);
}

WH: Fallback needs a this binding to handle cases with 'with' such as this one: a.eval = with (a) { eval(b) }

[ agreed ]

Cross-Domain Modules

  • browser loader should allow cross-domain loads
  • ServiceWorker requires cross-domain sources (XHR) and sinks (,

Ecma/TC39 Meeting – Nov 20 2013

link Nov 20 Meeting Notes

John Neumann (JN), Allen Wirfs-Brock (AWB), Yehuda Katz (YK), Eric Ferraiuolo (EF), Erik Arvidsson (EA), Rick Hudson (RH), Matt Sweeney (MS), Rick Waldron (RW), Dmitry Soshnikov (DS), Sebastian Markbage (SM), Ben Newman (BN), Reid Burke (RB), Waldemar Horwat (WH), Doug Crockford (DC), Tom Van Custem (TVC), Mark Miller (MM), Brian Terlson (BT), Andreas Rossberg (ARB), Alex Russell (AR)

link Report from the Ecma Secretariat (CC Report)

(Istvan Sebestyen)

link Status of the TC39 RFTG

January 2014 Meeting deadline

link 4.2 Clarification of the interaction of unicode escapes and identification syntax

(Waldemar Horwat)

WH: In ES3 we added the ability to use unicode escape sequences in Identifiers, ie.

1
var f\u1234o = 17;

The restriction was that the unicode escape sequence still had to be a valid identifier. ES3 and ES5 never allowed unicode escapes to substitute non-user-data characters of other tokens such as reserved words or punctuation.

the contention is that ES6 has an incompatible lexical grammar change that lets you write things like:

1
2
3
4
5
6
7
8
9
10
\u0069f(x===15)
// if(x===15)
There also was a bit confusion about whether escape sequences can occur in regexp flags, even though the grammar never allowed them there either:
/abc/\u...
// unicode for the flags

AWB: Things that came up in ES5:

  • can you declare a variable that has the same unicode escape sequence as a keyword?
1
var f\u0
  • introduced in ES5:
1
2
// allow
foo.for()

ie. Identifier vs IdentifierName

WH: Cannot use escapes to create identifiers that would be invalid. Also opposed to allowing escapes inside keywords; there should be just one spelling of the keyword if, and it should not include \u0069f.

So what should we do about \u0069f(x===15) ? It depends on how we interpret the ES3/ES5 rule that states that escapes cannot be used to create identifiernames that don't conform to the identifiername grammar.

Option A: Treat the if there as an identifier because there are some contexts in which "if" can be used as an identifier (notably after a dot), making this into a function call.

Option B: The if there cannot be an identifier in this context, so it's a syntax error because we're trying to spell a reserved word with an escape.

AWB: Agree there is ambiguity

MM: https://code.google.com/p/google-caja/wiki/SecurityAdvisory20131121 "Handling of unicode escapes in identifiers can lead to security issues" Records the vulnerability that has now been fixed in Caja at the price of additional pre-processing. This vulnerability which was caused by ambiguity in interpretations of the ES5 spec by different browser makers.

STH: If there are systems that need to search code for specific forms

MM: It would be harmful to code that looked at keywords, then this could circumvent those assumptions.

AWB/WH: (recapping acceptable use of reserved words as identifiernames)

BE: We can fix it, but it's just not how ES6 spec works

WH: If it is a ReservedWord, it may not be spelled with an escape.

MM: This solves Sam's static code case

BE: No escape processing upstream?

WH: (agreeing)

AWB: We can specify in the grammar that where we write "if" it means that exact character sequence

...Anywhere we express literal keywords, we mean those character sequences.

link Consensus/Resolution

  • ReservedWords, including contextual, can only be spelled with ascii characters, ie. the literal character sequence.
  • No escapes allowed in such ReservedWords

link Performance impact of Tail Calls

(Brian Terlson)

BT: Wondering if any implementors have begun work on these? Are there considerations for existing code that will become tail call?

YK/AWB: Any examples?

BT: Stack frame manipulation

BE: It's not a zero work to new work, it's an old work to different work.

STH: There's a lot of work on this subject, presumably tail calls should be able to run as fast as it does currently. No advice that's implementation independent.

ARB: Standard techniques should be applicable. Foresee a lot of work.

YK: The only real value for practioners is for compile-to-js cases.

DC: This is actually the most exciting feature for me, because it allows

BE: Will have someone work on this for SpiderMonkey

RW: Agree that implementors will feel the pressure once practioners experience the benefits that Doug describes.

DH: Allows for real cps transformations that won't blow the stack and don't require awful setTimeout hacks. FP idioms being available to JS.

link Consensus/Resolution

  • Share implementation experience

link super and object literals

(Allen Wirfs-Brock)

(needs slides)

AWB: Issue: how do you mixin some methods that reference super?

1
Object.mixin(obj, ???);

In the process of mixing, Object.mixin will rebind super references to the target. The big problem: super is currently explicitly illegal within an object literal:

1
2
3
4
5
Object.mixin(obj, {
toString() {
return `mixed(super.toString())`;
}
});

BE: are we asking to allow super anywhere?

MM: We're not adding a restriction?

AWB: No, removing.

MM: Strictly a simplification.

Discussion re: Object.mixin

WH: Curious about the design of exposing super to user code, but only via the Object.mixin API. If we're going to be storing and retrieving super from a hidden slot, this seems a very roundabout API that's going to bite us.

AWB: Allow super in concise methods

EA: All object literals?

RW: No, because the property value could be defined elsewhere. Ensure invalid in function and it's ok

EA/AWB/RW: Allow super in concise methods within object literals.

Clarification of Object.mixin capabilities.

MM: (has issue with the naming)

AWB: Let's defer discussion of naming.

YK: We should allow super in function expressions within object literals

MM: Refactoring hazard

DH: There is always a refactoring hazard when scope is involved (super)

RW: On board with Erik and Yehuda, super should be allowed in both concise methods and function expression literals that are the value of properties defined in an object literal.

DH: Object.mixin creates a new function when rebound?

AWB: Yes.

MM: (whiteboard)

1
2
3
4
5
6
7
8
9
{ foo() {}, ... }
// vs
{ foo: function() {}, ... }
// vs
{ foo: (function() { return function () {}; })(), ... }

DS: Concern about having a reference to a function object that doesn't equal the rebound method

1
2
3
4
5
6
7
function f() { super.foo(); }
Object.mixin(o, {
f: f
});
o.f !== f;

BE: No way to define a property on a concise method declaratively.

WH: RebindSuper doesn't copy expandos (referring to Allen's claim that it does) http://people.mozilla.org/~jorendorff/es6-draft.html#sec-rebindsuper (The actual copying of expandos takes place in MixinProperties http://people.mozilla.org/~jorendorff/es6-draft.html#sec-mixinproperties

DH: Issue: bind does a similar operation, but doesn't copy expandos. ... Any other deep traversals? If you have a non-callable object, it only does a shallow copy? ... The existance of super creates an inconsistency.

AWB: Alternatives are always clone or never.

DS: All methods should be copied to avoid the distinction

YK: Don't copy exandos?

EA: Happy to go back to Object.defineMethod

YK: Still need to decide if it copies expandos

DH: That's the smallest operation that you can build on

WH: Object.mixin breaks membranes, no way to intercept the super rebinding when the method is a proxy.

AWB: There are many operations like this

EA: No different from Function.prototype.bind

MM: What happens when the method is a Proxy?

AWB: A proxy for a method is not a function.

MM: A Proxy whose target is a function?

AWB: It's not an ordinary ECMAScript function

MM: Anything we do, we should ask "What does it do across membranes?" There are two criteria that often come into conflict:

  • Security
  • Transparency

Discussion about Security vs. Transparency

EA: What happens when do bind on a function proxy?

MM: fail?

DH: This is shocking.

MM: bind is a perfect example, there is no conflict between security and transparency. You'd like bind to work on proxy functions

EA: (whiteboard)

1
Function.prototype.bindSuper

MM: They're saying, do the [[get]] on the proxy, you don't get bindSuper back, you get a proxy for bindSuper ... membrane safe.

YK: Change bind?

DH: Can't change bind, varargs

Mixed discussion re: home binding.

AWB: Expose the home binding via trap?

DH: trap makes sense to me

MM: From the method you have access to the home binding?

AWB: yes

MM: Don't like that

AWB: Another way

WH: The method calls "super" and expects to reach it's super

AWB: There could be a super call trap

YK: Any objects to bindSuper?

DH: No idea what this means.

BN: What is the material difference between defineMethod and bindSuper?

bindSuper: like bind, but only changes super. Could be defined in terms of Object.defineMethod:

1
2
3
4
// illustrative only
Function.prototype.bindSuper = function(homeObj) {
return Object.defineMethod(homeObj, this);
};

changing this and super is a two step change:

1
2
3
4
5
6
7
8
function f() { super.foo(this); }
var o = {
foo(target) {
}
}
(fill in later

DH: bindSuper is the max/min of define

  • takes one target argument
  • copies code and changes super references to target

on a bound function?

BE: On a function with this and super, changing both will create two new functions

AWB: This is a "clone function"

DH: Meaning, only clone the this-binding, not the expandos

...

AWB: you'll need to bindSuper, then bind

AWB: If you want it to work in either direction

WH: binding super after binding this will cause problems. That would be an anti-feature that breaks abstraction. A lot of times, code will return a bound function specifically to prevent you from changing this. Changing super in such a function would break the abstraction.

?: Want bind and bindSuper to commute

WH: Don't want them to commute. They're fundamentally different. bind can only be done once and freezes the this binding. bindSuper can be done repeatedly and doesn't freeze the super binding.

?: You can already rebind this in a bound function

MM: No. If you bind it again, it doesn't mutate the bound this value; the second one is ignored.

DH: (whiteboard)

  • mixin -> defer, focus on primitive
  • defineMethod -> not proxyable
  • bindSuper -> good
  • proxying -> good
  • composition with bind bind().bindSuper() -> ERROR. bindSuper().bind() -> OK.

bindSuper can be called on the result of bindSuper (which is why YK/MM dislike the use of "bind")

Alternative names: resuper, bindSuper, supersede, withSuper, super?

withSuper, bindSuper?

bindSuper(obj[, ...])

BN: what does super.valueOf() return?

DH: should be this, similar to what super evaluates to in Smalltalk (according to AWB)

  • static error vs dynamic error? DYNAMIC.
  • where is super given a binding (other then class)?
    • class methods
    • method shorthand
    • in obj literal wherever name inferrable

Discussion re: naming. The shed is pink? It's more of a mauve, I think. You would.

link Consensus/Resolution

  • Remove Object.mixin
  • "toMethod()" wins -- debate about argument order
  • debate about what [[MName]] is and what it's derived from
    • super delegation uses [[Name]]
    • there's a prototype property for name as well
    • and functions with names have an own property that's .name, while function.prototype has a .name that's a null string
    • .name is configurable, non-writeable, but not necessarialy an own property -- depends on how the function was defined
    • clarification that ".name" has no effect on [[Name]]
    • clarification that ".name" has no semantic effect on other methods that might consume a name
    • copied: length
    • result name: whatever we decided [[mname]] was
    • bound functions cannot be converted to methods
    • bind().toMethod() -> throws

Function.prototype.toMethod(home[, mname])

Dave, please review the details above.

link Reconsidering the Map custom comparator API

(Dave Herman)

DH: Something incredibly gross about having an API that allows exactly one string, but I know we need to solve the bigger problem which is being able to provide performant custom comparators.

Can we just get rid of this argument?

WH: [Recaps consensus decision from prior meeting and the reasoning route by which we arrived at it.]

MM: (gives memoization example)

DH: This can be addressed in ES7

Discussion re: -0/+0 difference.

It was pointed out the only difference between the default comparator and the is comparation is the handling of -0/+0 and that a subclass of Map that ditingishes between +0 and -1 using Object.is can easily be written in ES code.

link Consensus/Resolution

  • Remove second param to Map and Set constructor
  • Defer to ES7

link Math.hypot() and precision

(Dave Herman)

http://people.mozilla.org/~jorendorff/es6-draft.html#sec-math.hypot

DH: Oliver Hunt brought this up, do we want to maximize precision (by sorting) and take the performance hit? Or do them in the provided order. Prefer the latter. Oliver prefererred sorting for precision but taking the performance hit.

BE/DH: He's not here.

Referring to IEEE 754

Luke provided the original spec text, but it's changed since then.

BE: need to look at SpiderMonkey implementation and possibly provide new spec text.

WH: Sorting doesn't matter much in this case; it's a second-order effect. Cancellation is impossible because all squares being added are nonnegative.

WH: What does greatly matter is not overflowing for values > sqrt(largest finite double). What does hypot(1e200, 1e210) do? BE (runs it on bleeding edge Firefox): About 1e210 WH: Good. We do want to avoid the intermediate overflow that would turn this into +?.

[ more discussion ]

?: This isn't just about hypot. How should we specify precision in general for things such as transcendental function.

WH: It's a moving target. Do not want to encode precision requirements in the standard on anything other than basic arithmetic or number?string conversion in the spec because those are complicated and how to specify them varies depending on the function. Best thing to do is link to some existing writeup describing best practices.

BE: I'll beat the drum to get a spec. Dave's right that it's bad language.

link Consensus/Resolution

  • Brendan to propose replacement for last two steps.

link 4.10 Generator arrow function syntax

(Brendan Eich)

BE: This isn't a big deal and should be easy to bring into ES6. Experience so far has been that people love arrow functions and generators and want a generator arrow

(whiteboard)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// current
x => x * x;
(...) => { statements }
(...) => ( expr )
// proposed generator arrows...
// Irregular
() =*>
// Hostile to ! (async function)
() => * { ...yield... }
// Not good
() => * (yield a, yield b)
// Ok if 1 token
x *=> x * x;
// Bad (ASI)
*() => ...
// Hostile to !
(x) =* {...}

WH: Don't like => because it swaps the order from function.

WH: The ! problem in =>* can be solved by using % or ? instead of !. Would prefer those characters anyway.

BN: Another (strawman) possibility is the presense of yield.

BE/WH: No

DH: Recalls implied generator (yield presense) footgun

DH: There is not a 1-to-1 correspondance to where you'd use function or function *. Arrow is not a replacement for all functions that want lexical this.

link Consensus/Resolution

  • No addition, revisit for ES7

link for-let

(Brian Terlson)

BT: We've shipped for-let without fresh bindings per iteration (according to the current spec) but we're ok with updating.

MM: Consensus?

RW: recalling the consensus from yahoo 2012

DH: Need consensus on the semantics of capturing in the expression positions

DH: if there's something that "closes over" that variable, what's that referring to? I remember that thead, but I don't reacall the otucome

AWB: no definitive outcome... no satisfactory solutions

DH: we have this job on this committee... ;-)

BT: that we shipped in IE has no weighting on this?

AWB: nope. Should have looked at the spec which has notes to this effect

(discussion about binding per iteration)

AWB: C# addresses this by saying "this is insane, so for C-style of or, we have per-iteration bindings, not per-loop bindings"

MM: so let in the head of the loop creates only one location?

(yes)

EA: if we don't resolve this today, we sould fallback to what IE 11 does.

DH: sure, but we have to go through this thread

AWB: The first time you initialize, create an extra scope contour, the zeroth iteration. This is where the capture occurs and the subsequent iterations propagate to that scope.

AWB: if you order these things right, the 3rd part happens at the end, but before your propagate

MM: you mutate and then the value gets copied... seems fine

1
2
3
4
5
6
7
var a = [];
for(let i = 0, f = () => i * i, a.push(f); i < N; i++) {
a.push(f);
}
for (let f of a) {
console.log(f());
}
1
2
for(let i = 0, f = () => i++; i < 1; f()) {
}

This is an infinite loop. Reasoning: 1) The outer scope receives its initial value for i and f. Critically, f's i now binds to this outer binding. 2) The outer scope forwards these values into the first iteration of the loop 3) In the beginning of the 1st loop iteration, the test is executed. At this point, i is still zero. 4) After, still on the first iteration, the test for i < 1 fails because i is zero. 5) Since we never modify the loop variable, this must be an infinite loop.

BE: FWIW, Dart has the same semantics.

1
2
3
4
5
6
7
8
9
10
void main() {
foo(fun) {
print('pre');
print(fun());
}
for (var i = 0, inc = () => i++, j = foo(inc); i < 5; inc = () => i++) {
print(i);
inc();
}
}

outputs

1
2
3
4
5
6
pre
0
1
2
3
4

link Consensus/Resolution

  • Brand new outer scope created around the entire loop that has variables that are declared in the loop head, and it gets the initial values
  • There is a new scope for each iteration that receives values from the previous iteration

link 5 Post ES6 Spec Process.

(Rafael Weinstein)

Train model.

link Consensus/Resolution

  • Sounds reasonable, we're going to try it.

link Ordering of scheduling of microtasks

BE: FIFO

AWB: In the ES6 we need to say something.

?: Examples of why browsers want to use priority queues to schedule tasks

[ Debate about whether in ES6 we need to mention the priority queues ]

?: DOM and other tasks are beyond the scope of the standard. Just say that ES6 tasks are in FIFO.

WH: Would prefer to mention a richer priority structure in the spec; otherwise other groups (W3C) will want to fit their tasks into our FIFO, which is not desirable. At the very least we must say that other tasks with visible effects may get arbitrarily interleaved between the ES6 tasks we talk about in the spec, so don't assume that nothing can come between adjacent ES6 tasks in the FIFO.

MM: Rafael and I went throught the existing DOM behavior...

YK: Disagrees with Rafael. Bucketing. Series of buckets. The first bucket is the cheapest operations and the last bucket is the most expensive bucket. If a bucket adds something to an earlier bucket then you go back to to earliest bucket that has items in it. Each bucket is a FIFO queue.

WH: Can you reorder the operations so that the DOM operation happens next to each other.

YK: I think a priority queue is isomorphic to buckets.

AWB: In ES6 we only have one class of priority which is the priority of Promises. We do not need to spec that there might be different priorities.

link Consensus/Resolution

  • ES6 spec needs to spec that Promises are serviced in a FIFO queue
  • Other non ES6 tasks might be interleaved arbitrarily
  • Interleaving of the Promise queue by other non ES6 operations

Ecma/TC39 Meeting – Nov 19 2013

link Nov 19 Meeting Notes

John Neumann (JN), Allen Wirfs-Brock (AWB), Yehuda Katz (YK), Eric Ferraiuolo (EF), Erik Arvidsson (EA), Rick Hudson (RH), Matt Sweeney (MS), Rafael Weinstein (RWS), Alex Russell (AR), Rick Waldron (RW), Dmitry Soshnikov (DS), Jeff Morrison (JM), Sebastian Markbage (SM), Ben Newman (BN), Reid Burke (RB), Waldemar Horwat (WH), Doug Crockford (DC), Tom Van Custem (TVC), Mark Miller (MM)

link Welcome

JN: (Introductions)

DC: (Logistics)

JN: ...updating status of RFTG ...Adopt agenda?

Unanimous approval

JN: Approval of Sept Minutes?

Unanimous approval

link ES6 Status

AWB: (presenting Luke's spreadsheet with remaining features that need attention) https://skydrive.live.com/view.aspx?resid=704A682DC00D8AAD!59602&app=Excel&authkey=!AAMixsO0TuyPYwc

...Function.prototype.toString still needs attention

BE: Mark is to write spec, in this case under-specify

AWB:

  • Refutable pattern matching is deferred
  • still need specification for enumerate / getOwnPropertyKeys/Symbols in various places
  • Proxy handlers, cut
  • C-style for-let

BE: We agreed on semantics

AWB: We agreed on outer capture, but won't try to update per iteration. Need per iteration binding.

YK: This is the consensus I recall

AWB:

  • Modules, static semantics complete
  • No loader/runtime semantics yet.
  • Dave will have a complete spec this meeting

YK: (confirms that it's complete)

AWB: Yes, but not yet in the spec.

  • Standard Modules deferred.

(TVC dials in)

link 4.4 Finalizing the Proxy API for ES6

(Presented by Tom Van Cutsem)

TVC: First three relate to es-discuss threads, re: simplifying Proxy. Jason Orendorff expressed concerns.

  • hasOwn()
  • invoke()

WH:

AWB: Looked for traps for call

BE: Total traps?

AWB: Now 14 traps.

BE: Cool. Not including hasOwn()?

AWB: Not including

TVC: The next is invoke() trap. Leave out for now to avoid inconsistencies with get()?

YK: How do you implement virtual objects? ie. an object whose this object is always the proxy. Can't do it reliably without invoke.

WH: Still not reliable, even with invoke.

YK: So what are the cases?

AWB: Can still implement a virtual object or full membrane, or thin wrapper.

YK: Not the use case. Want to make an object where this is the proxy and not the target.

TVC: Are you arguing that this should remain bound to the proxy object upon forwarding? If yes, this is the default.

YK: As long as maintaining equivalence between foo.bar() and bar.call(foo)

AWB: yes.

TVC: Regarding Handler API: not enough motivating use cases for proxy handlers without community use. Propose to defer.

AWB: Let's publish the library code TVC: It's already on github, as part of my shim. I will publish it as a separate project to make it more accessible.

TVC: Proxy as a constructor? Currently, no new throws TypeError

AWB: Not really a "class"

AR: You create new ones?

AWB: No prototype

AR: Gives an instance, why not "new"

AWB: Would need an @@create

YK: Then shouldn't be capitalized

BE: We can do "proxy"

AWB: (to Tom) the concern is: if it's not "new-able", should it be little-p proxy?

TVC: Given choice between little-p proxy and requiring new, I prefer new

RW: Agree with Alex, new Proxy() creates new Proxies, so allow new

AR: Let's not duck the charge on @@create.

WH: Proxy is not a class.

YK: ...But has allocation

WH: I would hate to specify what happens when subclassing from Proxy

AWB: Must create a special constructor

TVC: @@create doesn't make sense here

BE: Is Proxy a class?

(General: no)

TVC:

DS: What is typeof and instanceof

AWB/BE: object

BE: Capital P

AWB: Ca???

DS: Whatever Proxy creates?

BE: That depends on what is created.

DS: By default?

BE: typeof depends if there is a call trap. instanceof depends on the prototype chain. All in the spec, so can create any object (apart from private state issues)

AWB: Ok, into the future... would value objects allow new?

BE: (int64 example)

...back to why should new throw on Proxy constructor.

BE: Seems counter intuitive: Proxy constructs objects. int64 creates a value. callables construct objects

[ inaudible ]

BE: these are object constructor functions, which is what people want to do with "new"

AWB: this is somewhere in the middle between newing a class and a random function that returns an object

BE: in either case, it returns a new object and proxies are factories for object

AWB: yeah, I agree...spec currently calls them "proxy factory functions"

BE: pretty weird not to have "new" on this.. feels natural

YK: Intuitively, the difference between returning an object and not a value

AWB: we can do it...need to make it an exotic object with a special [[Construct]]

AR: agree. Making it exotic is good.

TVC: what's the summary?

AWB: we allow new, we do it by making it exotic.

EA: Do we REQUIRE "new"?

WH: what does Map do without new?

EA: Throws

BE: Why are we requiring new again?

RW: Needed for subclassing

AWB: my objection is that we're trying to tell a story about objects, classes, and @@create... this confuses the story

YK: there's already a weird split...saying you have to use new avoids the confusion

AR/RW: agree

AWB: we could go either way, and it's subtle, but most people won't see the subtlety

RW/BE: the conservative thing to do is to throw now and we can walk it back later

AWB: agree

JM: Removing the throw might change control flows?

BE: non-issue, rare.

link Consensus/Resolution

  • Drop hasOwn()
  • Drop invoke()
  • Postpone proxy handlers API
  • REQUIRE new Proxy by making Proxy an exotic function that has it's own internal construct. (this is only "action" item)

link ES6 Status (cont)

AWB: - Symbols in place - Binary data deferred - RegExp look behind deferred

WH: No comprehensive specification of which variant of RegExp lookbehind was wanted. Followed up on es-discuss and got no good answer to questions.

AWB: No one has stepped up, deferred to ES7

  • Completion reform has bugs, but that's just work for me
  • Global scope, Dave has some possible changes he wants to discuss at this meeting
  • Eval scope, now simplified because can't eval a module
  • function scope, needs spec some design issues still open
  • Promises, Domenic has a complete delta, just needs to be added
  • Internal Method Invariants. If we're going to keep this section, someone needs to provide spec ready text.

MM: If Tom will collaborate with me on this, I will commit to producing this.

AWB: I can live without this section

MM: ES5 had that section, I will talk to Tom about creating this for ES6

...

AWB: For the end of this year, we need a feature complete spec. Essentially a "candidate spec". This means all the features there are sufficiently specified to allow an implementor to implement. I think we have a shot at it. There is work to do. Questions remain in modules, but Dave can update us. Dave and Jason (Orendorff) have been working like crazy to finish modules, including a reference implementation.

MM: The spec we want to be feature complete includes modules?

AWB: Yes.

MM: The loader stuff as well?

AWB: Yes. ... Over the next 6-9 months, we need implementors to work and provide feedback. We should push forward with what he have now (this includes modules)

link 4.1 Review Latest Specification Draft

(Allen Wirfs-Brock)

(request slides)

Discussion re: arguments.caller, arguments.callee in non-strict and strict mode.

Discussion re: default param aliasing

BE: (tries aliasing on SM)

YK: Issues with arguments.caller, arguments.callee in framework uses.

BE: Do we want three types of arguments?

YK: It's not really three types

...

link BE: Fair to say there are three observably different kinds of arguments

YK:

MM: Adopt some semantics where aliasing

BE: Deep aliasing of destructured parameters is bad

AR: Walk back poisoning entirely?

MM: No.

MM: Any simple parameter is aliased and any new style parameter is not ... on defaults I could go either way.

AWB: Back to scheduling

BE: If there is destructuring, no deep aliasing.

WH: Easier to explain if the rules are compositional.

link Consensus/Resolution

  • Parameter issues
  • default params, alias is independent
  • destructuring has no name for top level object, no aliasing
  • rest has no aliasing
  • non-strict mode arguments have unpoisoned caller and callee

... Continue discussion re: do Arrow Functions have an arguments object?

link 4.3 Should 'arguments' in an arrow body be from nearest outer defining scope, or early error?

(Brendan Eich)

AWB: Arrows don't have an arguments object, but arguments is a keyword inside arrow functions.

WH: let arguments = ...?

not allowed, recapping ES5 strict rules that were applied to new forms in ES6.

questions about conditionally reserved words

AWB: what if the outer function does say let arguments = ...;, what is it in the arrow function?

MM: (whiteboard)

1
2
3
4
5
function f() {
var arguments = 1;
[3, 2, 1].forEach(v => v + arguments);
}

YK: this, super, arguments should refer to its outer.

WH: 11.6.2.2 and 13.2.1.1 are inconsistent. The former omits keywords such as "arguments", while claiming to be based on the latter.

link Consensus/Resolution

  • arguments is lexically captured by arrow functions
  • 11.6.2.2 and 13.2.1.1 are inconsistent (file a bug)
  • yield cannot mean "yield to the outer"

AWB/BE: yield just follows the rules for yield

MM: (whiteboard)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function foo() {
var yield = 8;
return function * bar() {
yield baz();
function baz() {
return yield;
}
}
}
var f = foo();
console.log(f().next().value);
// 8

AWB: ...Computed property keys: No dynamic checking for duplicate computed property name in object literals or classes

1
2
3
4
5
{
[expr1]: 1,
[expr2]: 2
}
// Does not check if expr1 === expr2

MM: Cannot statically repeat properties in object literals

AWB: This isn't a static object literal

MM: ...

YK: The most common usage will by for symbols, eg. @@iterator

AWB: We don't have a mechanism for runtime checks like this and shouldn't be adding such checks

MM: The create and overwrite paths are very different (define v. assign)

WH: Pick one or the other. If we're going to do static checking, do it consistently. Either always check or never check

AWB: The complications I ran into were in gets and sets, it's not just "does this property exist"...

BE: We do want computed property gets and sets ...We should do checks.

AWB: It's not that non-strict doesn't check...

MM: given that we do dynamic checks in strict mode, you prefer NOT doing them in sloppy mode?

AWB: I don't like the dynamic checks either way

MM: that wasn't the question

AWB: the precedent in ES5 for object literals is that strict mode has "more" static checks.

AWB: "from a language design perspective", we should have them the same in both cases

BE: I'm w/ WH and ARB, we want the check in strict mode

AWB: so you don't want the check in sloppy mode?

BE: I don't think there is only one consistent position, and I'm ok with no dynamic check in non-strict mode

... discussion of the current static checks in non-strict mode ...

link Consensus/Resolution

  • No change, this is the semantics:
1
2
3
4
5
var name = "x";
var o = {x:42, x:45}, // static strict error
o2 = {x:42, get x()}, // static error
o3 = {x:42, [name]:45 }, // dynamic strict error
o4 = {x:42, get [name]() {}}; // dynamic error

AWB: the consensus is that for dynamically computed property names we will dynamically check the things we would have statically checked.

WH: Pop quiz. What does the following parse as?

1
2
3
4
5
6
7
8
9
10
11
baz = ...
function foo() {
var yield = 8;
return function * bar() {
yield
baz
yield
* baz
yield (baz) => yield * baz
}
}

[Almost nobody guessed all of these right.]

Current answer, with all optional semicolons inserted:

1
2
3
4
5
6
7
8
9
10
11
baz = ...
function foo() {
var yield = 8;
return function * bar() {
yield; // The yield expression rule has a [no LineTerminator here]
baz;
yield // The yield * expression rule doesn't. No optional semicolon here!
* baz;
yield (baz) => yield * baz; // The * here is a product of two variables
}
}

link Consensus/Resolution

  • Update yield * [Lexical goal InputElementRegexp] => yield [no LineTerminator here] * [Lexical goal InputElementRegexp]

link Class/optional yield arg ambiguity

1
2
3
4
function *g() {
class foo extends yield {} // is that an object or the class body?
{}
}

Proposed solutions:

  • Disallow trailing yield in extends clause
  • Requires an extra parameter to Expression and AssignmentExpression
  • extends LeftHandSideExpression
  • would be only place an expression isnt explicitly Expression or AssignmentExpression

BE: (whiteboard)

1
2
3
4
// Don't want to require these parens:
class C extends (A + B) {
}

BE: Should have no trailing yield, as a static error

... lost track here...

WH: (whiteboard) Counterexample to claim about never requiring parentheses in expressions that would be unambiguous without them:

1
a = b * (yield c)

WH: Think of "extends" as having the same precedence as assignment operators. That's why class C extends (A + B) would require parentheses.

link Consensus/Resolution

  • extends LeftHandSideExpression
  • would be only place an expression isnt explicitly Expression or AssignmentExpression

link Cross-Realm Symbol Registration

(need slide)

AWB:

1
2
3
4
// key is a string
Symbol.for(key) => aSymbol // creates a new Symbol if key is not registered
Symbol.keyFor(aSymbol) => key
  • Where for all strings S: Symbol.keyFor(Symbol.for(S)) === S
  • the use case for Symbol.keyFor is serialization

Revisiting discussion from last meeting, re: Symbol.

Discussion regarding the value, or lack of, registered Symbols over Strings.

DH: Is it necessary to be Symbol.keyFor()? What about Symbol.prototype.key`

DS: Is there direct correspondance between Symbol and toString?

DH: If the symbol is registered, toString does the same as Symbol.keyFor

AWB: is this good?

DH: What does Symbol.keyFor return if the symbol is unregistered?

undefined

link Consensus/Resolution

  • Agree on proposed API.
  • If the symbol is unregistered: Symbol.keyFor(unregistered symbol) returns undefined
  • Symbol.keyFor(not a symbol) throws

AWB: An issue about Symbols not being usable as WeakMap keys... ...which is ok...

This lead to discussion about (re)naming of WeakMap. It's possible that WeakMap may be renamed SideTable

link Introduce a Prototype object that contains sloppy arguments object @@iterator function?

Discussion re:

  • arguments prototype
  • arguments.prototype.constructor

AWB/MM: instanceof is generally misused

AWB: Current spec: all built-in iterators. Self hostable

MM: Issues are with consistency.

BE: (whiteboard)

1
2
3
Array.prototype[Symbol.iterator] !== (function() {
return arguments[Symbol.iterator];
})();

MM: ...future JS programmers learning classes without understanding prototypes. Let's not unnecessarily introduce new abstractions that can't be understood within these semantics.

(meta discussion)

AWB: (describing a spec that used class inheritance for all new inherited objects, eg. Array.Iterator)

BE: Return to the question... should arguments be iterable, and how?

AWB/MM: (discussion re:

link Consensus/Resolution

...?

link Conventions for ignore over-ride of @@iterator

MM: Why is this a spec issue?

AWB: @@iterator is bad example, @@toStringTag is better

BE: Use undefined, not "falsey"

AWB: re: new Map(?, "is")

BE/RW: new Map(undefined, "is") defaults to empty list

AWB: Happy with undefined.

link Consensus/Resolution

  • Just use undefined

link (function Foo() {}).bind(x).name?

See: http://wiki.ecmascript.org/doku.php?id=harmony:function_name_property

AWB: What about anonymous function expressions?

RW: No name is made

AWB: What about bound anonymous function expressions?

RW: Same, no name.

DS: Could bound functions delegate their name? Do we want to do that?

BE: Might be interesting to find out, can chat with Brandon about this.

link Consensus/Resolution

  • "bind" wins over "bound"
  • Brandon needs to review the spec.

link 9 ECMA 404 W3C TAG / TPAC report

(Alex Russell)

AR: (recapping JSON specification leading to 404) ... There are people at the IETF that want more restrictions, eg. a number types, character encoding.

WH/MM: what does that mean?

AWB: Let's avoid doing what they're doing.

AR: They want to restrict all the things, that we're simply not willing to do. ... The draft revision includes non-normative "advice". They've also diverged on what is "valid JSON".

RW: Specifically, they've changed JSON so that JSONValue is not the top level grammar production, using JSONText instead. This means only "{}" and "[]", which is incompatible with Ecma-404.

AR: (proposal to work together)

STH: 3 levels.

  1. Bytes on the wire. For example reject UTF-32
  2. Sequence of unicode code points that make up a valid JSON sequence. This is covered by ECMA 404.
  3. Semantics of this structure. For example, reject numbers with a thousand digits.

link Consensus/Resolution

  • Alex will draft statement to send to IETF last call, due Thursday

link 4.9 Reconsidering Object.is

(Dave Herman)

DH: Object.is might be a mistake

AWB: Could be trying to fill one of two purposes:

  • the finest distinction possible
  • what you really wish triple equal was

For general use, you want -0 and +0 to be equated, NaN to equal NaN

MM, WH: Multiple NaNs are not visible in JavaScript

AWB, DH: Different NaNs are distinguishable if aliased via TypedArrays

AWB: Hence Object.is does not discriminate as finely as possible

WH: That would be a mistake. ES1-5 clearly state that the NaN values are indistinguishable, and some implementations rely on that for NaN-boxing. Object.is should consider all NaNs to be the same.

[ discussion ]

AWB: NaNs are technically still not distinguishable in ECMAScript because an implementation has the freedom to write any quiet NaN bit pattern into a TypedArray, not necessarily the one that generated the NaN; in fact, writing the same NaN twice might generate different bit patterns.

Discussion about equating NaN values (https://github.com/rwaldron/tc39-notes/blob/master/es6/2013-01/jan-29.md#conclusionresolution)

MM: The spec allows 0/0 to be written to a TypedArray twice with different actual bit pattern.

More discussion re: IEEE NaN

link Consensus/Resolution

  • Status Quo

Ecma/TC39 Meeting – Sep 19 2013

link Sept 19 Meeting Notes

John Neumann (JN), Dave Herman (DH), Istvan Sebestyen (IS), Alex Russell (AR), Allen Wirfs-Brock (AWB), Erik Arvidsson (EA), Eric Ferraiuolo (EF), Doug Crockford (DC), Luke Hoban (LH), Anne van Kesteren (AVK), Brian Terlson (BT), Rick Waldron (RW), Waldemar Horwat (WH), Rafael Weinstein (RWS), Boris Zbarsky (BZ), Domenic Denicola (DD), Tim Disney (TD), Niko Matsakis (NM), Jeff Morrison (JM), Sebastian Markbage (SM), Oliver Hunt (OH), Sam Tobin-Hochstadt (STH), Dmitry Lomov (DL), Andreas Rossberg (ARB), Matt Sweeney (MS), Reid Burke (RB), Philippe Le Hégaret (PLH), Simon Kaegi (SK), Paul Leathers (PL), Corey Frang (CF), Mark Miller (MM)

(discussion re: destructuring concerns)

AWB: If you want to not throw for no value you have to define the default value.

DH: That's not YK's position. He wants to not throw.

DH/AR: The way you pull things out of an object is to do a [[Get]] wich does not throw and returns undefined

WH: What about {a:b, c:{x}} = {}? If you emulate the [[Get]] model, you'll still throw on a two-level destructuring pattern. Not clear what the useful point of sometimes soft-failing and sometimes hard-failing, even within the same pattern, is.

DH: That is not the same issue.

DH: In the case where the thing you are destructuring is an object, and the property you're looking for is not there, it should not throw. That matches existing JavaScript

1
{ a: { b: c } } = {};

The inner object is the source of the error.

ARB: Confused because notes different from what just said.

AWB: Currently spec throws unless a default value is provided.

YK/DH: Not happy with that outcome.

RW: (recalling agreement between AC/YK/RW at last meeting on feeling that we're not following expected JS behaviour)

DH: The obvious case is using an object.

  • What does the syntax most naturally correspond to?
  • Looking for smooth refactoring paths

ARB: I don't buy that it will be common to refactor like this

ARB: Common bug that you get undefined for o.x

DH: That is just how JS works and we cannot redo JS.

AWB: I can represent YK's position. Personally fine either way. But we need to decide. We cannot keep putting this off.

DH: I believe we would dissappoint the community if it threw. It is just too different from what they are used to.

AVK: My recolection was that we woudl go with no exception and maybe add a ! in the future.

LH: Ultimate consensus at last meeting was fail soft, waiting for ARB to object.

ARB: Other consistency arg with a future formal pattern matching

AWB: Yes, but for pattern matching we'd have something else

LH: If pattern matching used something else, and you were in that context, it's not a stretch to tell people there are new rules in that context.

ARB: Results in two semantics for one syntactic class (patterns). Bad for consistency and language economy

DH: Whatever familiarity from other languages and contexts, we need to align with JS and align with fail soft

AR: (to ARB) the practioners in the room are consistently disagreeing with your position.

RW: In a pattern matching context it is fine to do things more strict. People will not be surprised by the difference between destructuring and pattern matching

DD: (recalling recent extensive destructuring experience)

DH: Opposed to having two different semantics. Throw in destructuring but fail soft in [[Get]].

JB: What was the problem with ?

DH: Default behavior is backwards.

AWB: There plenty of unresolved syntactic and semantic issues and not enuogh time to get them done in ES6.

JB: and !?

AWB: No bang for ES6

RW: opposed to re-appropriation of !...

ARB: I think this makes for a worse and more error-prone language. But acknowledge that I am alone and I will not stand in the way of this.

link Consensus/Resolution

  • Throw if not an object
  • Then do a (fail-soft) [[Get]].

link start="9">
  • Promises
  • <

    Domenic Denicola

    https://github.com/domenic/promises-unwrapping

    DD: Consensus on AP3. Some issues with extending toward the future. Some bugs in the DOM spec. Tried to fix those.

    MM: Recommending that TC39 adopt promises-unwrapping so that w3c can proceed, and TC39 also get consensus on adding .done, .flatMap, and .of.

    AVK: promises-unwrapping is wanted for shipping in browsers. A lot of specs that rely on promises and we'd like a blessing.

    • AP3 was initial consensus
    • changes were made to make new consensus

    MM: Can we agree on promises-unwrapping to move forward?

    STH: The promises-unwrapping spec, in that it doesn't include ... (Google Hangouts misbehaves.)

    MM: (explaining semantics and benefits of flatMap etc)

    DD: without flatMap they will unwrap on the way out

    STH: unwrapping?

    DD: input side doesn't unwrap, only the output side

    STH: Then I'm happy with this.

    MM: No dissent from promises-unwrapping with the addition of .done, .flatMap, .of

    WH: What is the unwrapping doing

    DD/MM: explains that unwrapping occurs as long as there is a then() on down until there is no then()

    ARB: (to Sam) I share the compositionality concerns. Are we sure there is compositional abstraction if you use two levels of abstraction?

    STH: if you ever write .then, your system is not going to be compositional where promises are a data type (or you'll have to do extra work)

    WH: What is a then-able promise?

    DD/AVK: Just an object with a then function and you assimilate. It's "promise like".

    WH: .then does what?

    DD: .then is how you extract values

    MM: (explains unwrapping again)

    WH: What is .flatMap?

    MM: A promise accepting another object, causes the .flatMap to

    CF: it's "then" without magic

    MM: it's lower level, .then is built on top of .flatMap

    ARB: .flatMap is parametric and does no magic on it's values, where .then does

    LH: the only way you can convert a thenable to a promise is return it from a promise. Promise.cast and Promise.resolve will not convert a thenable?

    MM/DD: no, Promise.cast and Promise.resolve work the same way, storing any thenables as their value, and then the unwrapping happens when you call .then on the promise who has that stored as its value.

    WH: What is "The ThenableCoercions Weak Map"

    MM/DD: (explanations of security concerns)

    • No code contributed by the arbitrary object will execute during that call
    • assimilation of thenables was constructed so that the object cannot cause side effects during the operation

    DD: It's clearer when the code intends to run async, vs. some code running when assimilation occurs and some code later.

    MM: Then I should talk about .done now

    AVK: I think we have consensus on promises-unwrapping, and can defer .done.

    MM: declaring consensus now is crucial to unblock the DOM. If we can defer .done I am fine with that.

    (General agreement that promises-unwrapping with .flatMap and .of has consensus and .done can be deferred.)

    LH: Will need to add cancellation capabilities

    • Want to make sure that if we're sticking this in DOM apis, make sure there is back-compat safe to add them

    AVK: I believe that Mark and Domenic have given plenty of thought here

    DD: (confirms)

    MM: Notes that test262 will need to be extended to support async testing

    DH: This is really well developed and thoroughly spec'ed... what is the possibility of getting this into ES6?

    (murmurs of insanity)

    AWB: We're close approximate spec deltas here. Not quite cut and paste, but encourage that we might be able to fill in the editorial aspects.

    • What about the event loop interaction

    MM: I think the right precedent is Object.observe, it was very well written, very complete and we adopted to ES7 (for as much as that means)

    DH: Doesn't need to be tied to the event loop

    • event loop is very clear.
    • would love to recast the loader api in terms of promises.

    MM: That's a better pay off

    AR: Not quite that simple... in many cases result in void return types

    AR/DH: agree that this is better overall

    AWB: More confident about Promises, vs other features. If editorially practical, we should try.

    AR/AWB: No syntax, so no issue there.

    PLH: Makes life easier for w3c specs as well.

    AWB: What about an ECMA technical report in the interim? Or an independant spec in the interim?

    DH: In practical terms, that would mean I couldn't use them in the Loader api?

    MM: w/r to synergy between module Loader and Promises

    • how much of a difference does it make, if you could rephrase the api in terms of promises?

    STH: Many methods would change to use promises, a few cases would be drastically simpler, and all cases would be improvements in useability.

    MM: I would be over-joyed to have this in ES6

    DH: Most important to this: Domenic, Anne and whoever need to provide Allen with complete works as needed.

    WH: It's weird that if having a "then" property that's not a function is equivalent to not having a "then" property (the object is considered non-thenable), but having a "then" property that throws prevents the object from being returned from a promise. Too ad-hoc.

    WH: Let's say we introduce structs where if you mis-define fields it throws?

    DD: if you introduce changes like that, you'll have to re-factor checks throughout the spec and .then can be refactored in kind

    DC: To be clear, a thenable is:

    DD: An object that has a .then property whose value is a function (is callable)

    WH: understood (but don't like it)

    DC: ok

    AWB: A bit of legacy around "callable"...

    (Discussion about detecting then properties)

    DD/MM: JSON.stringify precedent: determining whether to return a property based on whether it's callable

    AWB: JSON.stringify is filtering...

    DD: But same meaning

    AWB: These callability tests are unnecessary?

    DD: Proven to be necessary

    WH: To avoid objects with .then that isn't callable... Why aren't we using [a well known symbol] instead of the string "then"?

    AR/DH: There is no way we can introduce this feature that has a change like that.

    • A lot of existing code to interop with

    DC: "then" is the wrong word.

    MM: for a long time I fought for "when", but there is too much web-reality that calls it "then" and it wasn't worth fighting

    WH: What happens if a thenable doesn't call onFulfilled or onRejected?

    DD: then it stays forever pending. This is a valid use case, e.g. a server that never responds to a request.

    DH: and it's actually a really nice zero of the promise algebra!

    link Consensus/Resolution

    link start="7">
  • Object.observe status report.
  • <

    Rafael Weinstein Slides <--- etherpad fucks this up :(

    Discussion related to how nested observers should chain.

    AWB: Maybe have performChange do take one more parameter, that is the record a function that calls notify.

    NM: Or have performChange return the record.

    AVK: You can skip the object in the record because the notifier knows which object it is working with.

    MM: Does not seem like a good path to not handle expecptions???

    RWS: The mutation records from array methods are about the intent to mutate the object. It cannot tell what the new state is of the object.

    MM: If somethings fails, and you try to perform the same operation on a replica you will get the same failure on the replica.

    RWS: I attempted to do the work and this what I intended to do.

    MM: I'm fine with this as long as it maintains the ability to keep a replica consistent.

    AWB: Would it be ok to not record property changes on array propert changes.

    WH: What kind of a change record would "sort" generate? In particular, how would the change record describe how the array was sorted (ascending, descending, by what key?)?

    RWS: If the array only said it was sorted then the code would need to keep a copy around to know what happened.

    WH: In that case would reverse also emit a sorted change record?

    AVK: Is "sort" proposed.

    EA: No

    (discussion about observing changes of attributes such as making an object non-extensable)

    AWB: It is uncommon to care about property changes for lists.

    AVK: .files might want to use Array.observe. It only cares about the items in the array.

    AWB: It seems strange to use observer for this use case.

    DD: generally DOM has a lot of things where the only difference from normal ES constructs is that when the object changes, you need to update something on the user's screen. New subclasses seems unnecessary, there's no new API.

    AVK: Considering using array or a small sub class. Reusing array as is easier because you get a lot of things for free.

    AWB: Use more specific class than array.

    (Discussion about Array.observe vs. Object.observe.)

    RWS: Allen, I think what you're saying makes sense, and it's a specific instance of a more general thing of filtering, which we may want for performance. Let's defer that.

    CF: An API question---what about { new: newCallback, updated: updateCallback, ... }, instead of (callback, ['new', 'updated', ...]).

    DH: yes, callback-last is definitely important

    RW: (explains in depth the benefits of this)

    RWS: I'm not especially excited about separate callbacks, because often you want a stream of change records, and not to react individually to each of the operations.

    RW clarifies with some code Corey's proposal:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    // either
    Object.observe(foo, {
    updated: function() {},
    deleted: function() {}
    });
    // or
    Object.observe(foo, function() {});

    RWS: This is an antipattern. We don't want to split the callback like that because the change log is the important part and if you split it it is hard to get ordering right.

    RW: The misunderstanding: the list of change types is a "white list" of change types to include in the change list, not a 1-to-1 "events to handle" list.

    WH: Want the names to be consistently present tense: new, update, delete, prototype, reconfigure

    RWS: prototype is used when [[Prototype]] is changed

    WH: how often do you observe an object whose prototype chain changes?

    RWS: well, a common use case is using the prototype chain to represent concentric scopes, e.g. Angular

    RW: It is valid to want to observe changes in the prototype chain, but I don't think Angular is a good supporting argument.

    DD/RW: Object.setPrototypeOf is the supporting case for observing prototype replacement

    DD: so then why not include observing the changing of extensibility

    AR/AWB/RW: I think we need that for completeness anyway.

    MM: yes, any mutable state should be observable; as long as it is observable by polling, Object.observe should work.

    RW: agreed, you could definitely implement it.

    Moved on to "Thought Experimental" slide.

    WH/DD: the names on this slide are weird. "deleted" doesn't work (it's already used by normal objects). "set" vs. "updated". It seems like namespacing is necessary.

    RWS: Agreed, there is a namespacing issue.

    WH: Would prefer to keep the simple notification names ("splice", "set", etc.) to match method names that generate those notifications. It would be bad if we got into a pattern where method Foo generated ArrayFoo notifications when used on arrays, MapFoo notifications when used on maps, etc. This would be an annoying abstraction leak for observers who don't care which particular data structure is used to store the things being observed.

    RW: Map and Set operations have potential to be deceptive; since the actual data is held internally, freeze operations have no effect (freeze is on the surface for tamper proofing), so there might be a situation where a Map or Set is "accidentally" assumed to be locked down but is still observable. FWIW, I do like the addition of change observation for Map and Set.

    MM: Freeze is not about freezing the object, it is about making it tamper proof. I think we can postpone this to ES7.

    RW: (to RWS) we can talk about this more offline

    AVK: it would be nice if there was a recommendation for how to do namespacing, for other specs etc.

    WH: Asks about ordering semantics

    RWS: there is an unresolved issue about ordering of different types of work in microtasks (promises vs. MutationObservers vs. Object.observe); this is still undecided.

    ... Moved on to the performance slides.

    WH: The slides are comparing the proposed language mechanism to polling, which is a bad choice for the comparison control group. If I were implementing observers in existing ES5, I definitely would not do polling; I'd set dirty flags and keep a list of dirty things. That should be the control group for the performance comparisons.

    RWS: the point of these graphs was not to show anything particularly interesting, but to show that there were no major surprises awaiting implementations.

    AR: What do you need from this group? How close are we to being "done"?

    RWS: Got good feedback on a few things to change. Maybe next meeting we'll have something that's really "done" and we can't go any further without implementations.

    AVK/RW: just be sure to update us on es-discuss when you make changes.

    link Consensus/Resolution

    • failure cases, what to do when an exception happens midway through performChange
    • change type naming, eg. "sorted" => "sort"
    • 2nd/3rd argument order (offline discussion)
    • Post to es-discuss when wiki page is updated.

    link Licensing Concerns?

    AWB: there was some discussion on the mailing list...

    RW: I am pretty sure that was a troll.

    STH: So this same guy actually came on the scheme mailing list and behaved similarly. It seems he just wanted to upload the PDFs somewhere, and did not actually care about the contents of the spec.

    link start="8">
  • Data Parallelism
  • <

    Dave Herman & Niko Matsakis

    DH: I wanted to explain why the issue of sequential fallback is not as simple as "we should just throw" for synchronous code.

    NM: I want to separate out throwing on non-parallelized execution vs. non-parallelizable execution. The former is not what people want.

    (General agreement.)

    DH: yes, you want the engine to be able to make dynamic decisions about whether parallelism is profitable.

    NM: it turns out there are many reasons why an execution may be non-parallelizable, not all of which a user should concern themselves with. There are implementation constraints that make it very hard to parallelize in some cases, but in theory they should be parallelizable. For example, in SpiderMonkey, string operations: they are currently implemented in a very scary imperative way that is hard to make threadsafe, but from a high-level perspective it should be obviously parallelizable. (It's not mutating shared state.)

    NM: Our conclusion was, we would instrument our JIT compiler to generate parallel-safe code, which needs a warmup; we'll run sequentially for a while, before we're ready to try parallel execution. It's going to be hard to implement a parellization strategy that doesn't work like this.

    ARB: I totally agree.

    DH: Cannot get to paralelizing until have done some serial exucution to gather information.

    NM: Implementations will grow the set of code it can parallelize over time. Cannot force any constraints on the closure. The alternative would be to instrument the entire the engine ot keep track of what cannot be parallelized.

    NM: The other option is to formalize what can be parelized in the spec. For the end user they will still not know what will run in parallel.

    EA: What is preventing engines for running Array map/filter etc in paralel if it cannot be detected.

    DH: It would be an interesting thing to try out.

    NM: There are other methods like reduce that cannot be parallelized. We therefore still need the par* methods.

    ARB: Throwing if it is not parallelized is not sensible because it is too hard to specify what things can be parallelized.

    DH: The order is non deterministic. That is the big difference. And this makes it easier to parallelized.

    NM: THe order is only crucial for reduce.

    WH: Even if an operation has no side effects, if several of the constituents of a map throws, you might get the wrong exception.

    WH/NM: (discussion about definition of side effect, whether throw is a side effect.)

    NM: 1) mutation of external state; throws; and straying into native code (that we don't have a safe version of).

    LH: if I'm interpreting this correctly, it sounds like the whole parallel JS thing becomes less of a standards thing, and more of an implementation concern, except there will also be some non-deterministic parallelizable array method.

    DH: but it's also important to give the parallelism recommendations teeth because then authors can depend on it.

    NM: it's also useful to have a specification available for users to read to understand what works where. It doesn't effect the semantics, and it probably doesn't belong in ES spec, but it would be useful to have to point users to.

    NM: for example we only lazily make function.arguments do crazy things, so that's not an easy thing to spec.

    WH: do we really need new nondeterministic array methods? I agree that you don't want reduce operations that have serial semantics (add first element to second, the sum to the third, the sum to fourth, etc.) but could deterministic tree operations (add elements pairwise, then add the pair sums, then add those in paris, etc.) be sufficient?

    NM: the main one is reduce. You can do a tree-reduction, but that is not always the right thing to do on all architectures; it has a performance cost.

    DH: also, we want to have developer tools give feedback on what can be parallelized; we are talking with a PhD student about working on this.

    ARB: How does this interact with GC?

    NM: Works well using nurseries.

    AWS: A version of region based collection.

    link Newly Added to Global Object

    DH: Straw proposal Symbol.iterator, Symbol.create

    AWS: A single method on Symbol, Symbol.for('iterator')

    EA: You can have get and set and use set to register user defined known symbols.

    MM: registration needs to be like interning

    DH: We're only talking about location of these new things.

    EA: Libraries want to register well known symbols

    DH: This is not what LH is trying to address

    MM: Built-in symbols, as specified by the spec: no mutation and no global channel

    Well-Known Symbols available on the Symbol object itself

    LH:

    • well-known symbols
    • Symbol
    • Reflect
    • System

    LH: We should be designing the library system independent of modules

    DH: (clarifies) Implementation dependency graph, can't rely on these new objects without knowing where they come from (modules)

    LH: We need to decide, concretely, if these are exposed on the Global Object.

    (RW clarifies for MM)

    MM: Will this break the web?

    LH: Conflicts are soft conflicts because the objects are configurable

    LH: How will symbols be held?

    1
    2
    Symbol.iterator = @@iterator
    Symbol.create = @@create

    The value is the initial value (as done with other items in the spec)

    writable: false configurable: true enumerable: ?

    AWB: need to discuss @@toPrimitive

    RW: Does this really need to be exposed?

    AWB: It's useful for any objects that have internal data (like Date)

    link Consensus/Resolution

    Next Meeting:

    Nov 19 - 21 at PayPal

    Ecma/TC39 Meeting – Sep 18 2013

    link Sept 18 Meeting Notes

    John Neumann (JN), Dave Herman (DH), Istvan Sebestyen (IS), Alex Russell (AR), Allen Wirfs-Brock (AWB), Erik Arvidsson (EA), Eric Ferraiuolo (EF), Doug Crockford (DC), Luke Hoban (LH), Anne van Kesteren (AVK), Brendan Eich (BE), Brian Terlson (BT), Rick Waldron (RW), Waldemar Horwat (WH), Rafael Weinstein (RWS), Boris Zbarsky (BZ), Domenic Denicola (DD), Tim Disney (TD), Niko Matsakis (NM), Jeff Morrison (JM), Sebastian Markbage (SM), Oliver Hunt (OH), Sam Tobin-Hochstadt (STH), Dmitry Lomov (DL), Andreas Rossberg (ARB), Matt Sweeney (MS), Reid Burke (RB), Philippe Le Hégaret (PLH), Simon Kaegi (SK), Paul Leathers (PL), Corey Frang (CF)

    link 4.2 Reconsider decision to make Typed Arrays non-extensible (Cont)

    RW: (recapping yesterday's discussion)

    EA: Can we pick 3 people to champion a recommendation?

    RW: Ideal

    (support in the room)

    link Consensus/Resolution

    • 2 People to come back with a recommendation:
    • Dmitry Lomov
    • Allen Wirfs-Brock

    Post meeting update: Dmitry and I discussed the issue and our recommendation is that Typed Array instances should come into existance being extensible. This is only about the objects created by the current set of built-in typed array constructors (or any subclasses derived from them). It does not imply that fixed size array types introduced by the future typed objects proposal will necesarily also be extensible. -- Allen

    As part of that consensus, variable-length (but not fixed-length!) typed array instances that are part of a future Typed Object spec should also be extensible in the same way as current Typed Array objects. In that way, full compatibility and equivalence between say "Uint8Array" and "new ArrayType(uint8)" will be maintained. As part of typed objects proposal, we will also consider having a different "type constructor" names for variable- and fixed-length typed arrays (e.g. "new ArrayType(uint8)" vs. "new FixedArrayType(uint8, 10)"). -- Dmitry

    4.4 Symbols

    Dave Herman presenting (follow up slides)

    DH: Symbols: object or primitive?

    Open issues: - privacy - object or primitive

    (1) Statelessness

    • Symbols should not share state
    • Encapsulates key and nothing else

    (2) Cross-Frame Compatibility

    1
    obj[iterator] = function*() {};

    Another frame must also know what this iterator symbol is

    EA: Workers?

    AWB: Only an issue when you want to move a value...

    EA: Case where you use a name as a brand (branding using public symbols do not work. Branding needs true private state.)

    YK: can these be structure-cloned?

    (3) Methods

    DH: The one place that most objects can't have methods is prototypeless objects, but they can have instance methods. For most most of the interesting data (strings) there are things you can do on them:

    1
    2
    3
    4
    5
    alert.call();
    Math.sin(0);
    document.getElementById("body");

    DH: if you only allow things to work via functions with arguments, you are turning off a powerful tool

    (4) Mutable Prototypes

    Monkey-patching standard methods is a best practice

    The evolution of the web depends on it

    DH: This is important to the language

    DH: mutable prototypes are the way that developers provide a consistent platform across user agents they don't control

    STH: This is assuming that Symbol will grow methods

    YK: It's actually an assumption that it won't

    DH: If we freeze a prototype, we're closing the door to ever evolving the API and closing the door to user code experimenting

    • No experience to show that freezing a prototype "works"

    WH: By "mutable prototype", you mean add and change methods, not change the prototype

    DH: Yes, changing the shape of the prototype object

    AR: (general defense of mutability, in prototypes and otherwise)

    AWB: Freezing the prototype can be undone safely, if there is reason in the future.

    AR: this is not a conservative position, despite the claim.

    DH: It doesn't matter, if we design depending on the invariance that the prototype is immutable then we can't change

    (5) Non-Answers

    (6) Shallow-Frozen Objects

    1
    O.getPrototypeOf(iterator).foo = 12;
    • Fails Desideratum #1: is stateful
    • Fails Desideratum #3: distinct cross frame iterators

    WH: What doesn't work?

    DH: The standard iterator symbol would be different in different frames because they exist in different heaps

    (6) Deep-Frozen Objects

    1
    O.getPrototypeOf(iterator).foo = 12; // strict error
    • Fails Desideratum #4: no evolution

    YK: How does the current spec deal with the function.prototype linkage

    AWB: The prototype is null

    DH/YK/AWB: this is incoherent, doesn't work at all.

    (7) Missed? Something about prototype-less wrappers, fill in from slides...

    (8) JS already has an answer for this! Autowrapping of primitives

    • typeof iterator === "symbol"
    • Get/Call operations auto wrap
    • Prototype state is global per-frame

    "People think auto-wrapping is gross"

    • provides uniform OO surface
    • does so without runing immutability
    • doesn't ruing API patchability
    • need a solution for value types

    (9) Remaining Issues

    • [[ToPropertyKey]] of Symbol objects" auto-unwrap? Does it matter in practice?
    • Worry about toString for symbols and Symbol objects? Does it matter in practice?

    WH: We should be consistent with the way we already do things. We don't unwrap boolean wrappers when used in a condition; we shouldn't unwrap symbol wrappers when used to look up a property. If you use Boolean(false) in an if statement, it will evaluate true.

    AWB: In ES5, there was special treatment of wrappers, e.g. in JSON.

    • no reason you should have a wrapper value in most contexts
    • I would say, don't use

    YK: Is it important that === works cross frame or just the indexing

    • Have a mechanism that allows them to

    DH: A kind of object that overloads ===

    YK: No, don't

    • If you go with new Symbol() returns object with mutable prototype

    DH: No "object" solution works because of methods

    • Need to move to next slide
    • w/r to toString, I can't construct a plausible scenario where this would be encountered

    YK: Accidentally construct a wrapper

    WH: People explicitly convert to string before doing an operation. It would be impractical to make symbols survive the various kinds of string conversions.

    ARB: Lot's of existing code that has code paths that converts a value to a string to get property key, would subtly misbehave with implicit symbol-to-string conversion

    (10) typeof Extensibility

    We don't know that it wont break the web

    MSIE "unknown type may simply be rare enough to be undiscovered.

    Fallback: "object" with [[Get]] et al that behave like auto-wrapper? (Object.isValue()?)

    WH: It won't break the web because existing scripts won't see the new type. Seeing one of these things requires changing the script. WH: We said that array subclasses are new and safe because unmodified code won't see them break things like Array.prototype.slice.call; why isn't the same argument applicable to symbols?

    AWB: when I did symbols originally, as primitives and not wrappers, it was a bug farm, because everywhere that assumed a primitive type, now had to explicitly account for the possibility of a symbol. The standard library in particular had to do this. In practice, anyone who is writing a general-purpose library would have to do the same thing. If you have wrappers, then the value "turns into an object" when you use them as such, which works fine.

    ARB: I implemented symbols in V8 with wrappers and there were no places where they needed special handling.

    AWB: yes I agree! Wrappers address most of the issues.

    YK: (Concerns about existing code that might not be resilient to typeof)

    DH: the most straightforward thing to do is extend typeof, but you can have code that's not resilient to new typeof values.

    (More discussion of existing library code having to deal with symbols).

    DH: Many new things in ES6 are objects with new APIs, so passing them in would violate basic interfaces expected. Whereas for typeof, many APIs will take any value whatsoever, and then figure out what to do via discriminating via typeof. So introducing a new typeof will break their assumption that they can handle any case.

    JM: I don't think it's so different; they will fail in similar ways.

    AWB: This is different; it's at the core of the language, and there is a different expectation.

    DC: Yes, this is different. There is an idiom that will fail, and it's a common. switch (typeof something).

    DH: if the only conservative extension guarantee we can make is that if you don't use any new features, everything is fine...

    DH: the difference is that there are APIs that say "I'll take any JavaScript value," they don't mean "I'll take any JavaScript value that was present in the ES5 era." This is different from saying "I'll take something with an array interface," and you passing in something like Map which happens to violate the array interface.

    WH: you are picking the wrong strawman. We are introducing things that do keep to the array interface (array subclasses) but break existing idioms such as using Array.prototype.slice.call to coerce to an Array object.

    DH: right, I'm picking Jeff's strawman, not yours.

    AWB: the issue with slice() is about realms, not kinds of objects, or subclasses.

    WH: The slice problem is not about realms. It arises merely if you introduce an array subclass and never use more than one realm.

    WH/AWB: (arguing about what they're arguing about)

    JM: You say it's clear when you pass in the wrong interface to an array-expecting vs. an all-expecting. Can you expand on why that's clear?

    DH: Difference between an api says "I will take an arraylike thing" and I will operate correctly and API that accepts "any"

    JM: but it's not about types for the "any" APIs; they usually just pass them through, e.g. a datastore API.

    LH: Rare that any API says "I'll accept any"

    DH: we're talking about parametricity, passing through the value vs. inspecting it. My experience is that I see type inspection of the type-any inputs a lot.

    LH: How often does an API take type "any"

    DH: A lot of JS programs don't protect against wrong values

    WH: No such thing as an API reliably taking type "any" and portably doing anything useful with it. Suppose we later introduce a new Decimal primitive that obeys the IEEE standard in that a DecimalNaN is not === to itself. Would a map work with it? Code that exhaustively type-dispatches primitives simply must change once in a while.

    YK: (recalling a point AWB made) people using typeof to defeat autowrap, tell the difference between a thing that auto-wraps and a thing that does not

    DH: The reason we shouldn't be afraid, is typeof of serves the purpose ...

    EA: If typeof primitive symbol returns "object" there is no way to distinguish a primitive symbol from a wrapped symbol.

    DH: we'd have to add a gross check for distinguishing

    • slipperly slope

    WH: "the future is bigger then the past" and it seems we're trying to perpetually mortgage the future to fix a relatively transitory fear we're not even sure is real. The cost is forever having yet another mechanism to distinguish the types of primitives.

    DH: Then there is the "browser game theory" argument, who will implement in the face of danger first?!

    WH: (interrupts)

    DH: I also like finishing my sentences. I'm willing to give it a try, but...

    EA: FWIW, V8 is shipping typeof symbol under a flag and no bug reports

    DH: under a flag is not the web

    • Willing to take this back to SM implementors

    AWB: Explicitly checking for "object"

    DH: Existing code breaking, this needs to be considered.

    • New code can find old code that can be fixed

    RW: Will put Symbol through jQuery in test suite to see what "breaks"

    Agreement that auto-wrapping is the way to go

    WH: Yes, use auto-wrapping the way we know it

    re: toString

    DH: One way or another we'll have to have it, whether it throws or produces a string

    DH: There are values that throw, like proto-less objects

    • conversion to string is not infallable in JavaScript

    ARB: implemented two toString methods

    • Symbol.prototype.toString => throws to avoid the implicit coercion hazard
    • Object.prototype.toString => applicable to Symbol, but have to be explicit

    AWB: Plausible that Symbols could have a printable "name"

    DH: Proposal summary:

    • Symbols are primitive
    • typeof is "symbol"
    • standard Symbol prototype
    • construct to create wrapped symbol
    • Symbol wrapper object does not auto unwrap. ToPropertyKey will eventually call Symbol.prototype.toString which will throw.

    ARB: for the record: that is exaclty what V8 implements

    YH: to the implementers in the room, please make the error message when you use a wrapper very nice.

    ARB: V8 gives explicit error message

    DD: new Symbol() is a probable footgun; should it do anything at all? Maybe just throw? Because we don't have symbol literals, so unlike new Number(5) vs. Number(5) vs 5, the choice is not obvious; people will try to do new Symbol() not realizing that this creates a wrapper.

    RW: Agree.

    ARB: but then it's weird that there is an object you can get access to, but whose constructor doesn't actually work.

    DD: but the only way you can get access to these objects is via the this value inside Symbol.prototype methods, in sloppy mode.

    DH: no, Object(primitiveSymbol) would give you back the wrapper.

    DD: ah, damn.

    AWB/ARB: Discussing valueOf returns, used in contexts where a numeric value is expected

    DC: But string.valueOf produces strings

    AWB: Do you anticipate future value types having auto-wrapping?

    DH: BE has thoughts about typeof modifyability

    RW: Defer until BE is present.

    Agreement

    AWB: How does user code define a "well known Symbol"? One that works across Realms?

    DH: not sure

    • Standard library, we can create something that exists everywhere
    • Library code, not sure

    ARB: Think this is a serious problem that needs to be addressed

    DH: Proposal

    • Agree that it's bad to have a Symbol with BOTH a private and public form
    • Private by default? Public by access?
    • Need to solve the remaining proxy leak problem

    AWB: We've discussed and concluded that we're nowhere near a solution to the private state problem.

    YK: Mark's solution inverts where the transaction occurs

    DH: If private symbols really behave like WeakMaps and you invert where they live, then they are truly private

    YK: You want the proxy to trap them.

    Why?

    AWB: It's just a property name.

    DH: If you have access to the symbol

    EA: What about iterator?

    STH: If you want the proxy to have iterator behaviour, you need access to @@iterator

    ...

    AWB: Mistake to conflate symbols, which are guaranteed unique property keys, with private state. There is a temptation to do it, but we run into problems. I want private state, but there are better ways to do it.

    DH: I am pretty exhausted from years of this debate, but from all the things we have to decide, this has to be decided now. And I am willing to fall on either side of the fence (private vs. public vs. both), for the sake of resolving this, but we need to resolve it.

    LH: agree; we can't leave this meeting without a decision on this. But Arv's proposal (GUIDs) does give us a path.

    AWB: but Arv's proposal doesn't solve privacy at all; it's just about the representation of symbols (strings vs. real symbols).

    RW/DH: strings as symbols have bad usability and problematic to use.

    YK: No solution to the enumerability question (are symbols enumerable)

    DH: yes, if we were going to go with this, we would just have iterator and create be a shitty string.

    YK: worse, it would have to be a UUID published in the spec.

    AWB/DD/AR: underscores are better than GUIDs.

    DD/RW: Symbols not for private state, use a WeakMap. Symbols for uniqueness, move on.

    DH: Arv, what is your issue with just having public symbols?

    EA: they don't carry their own weight. They behave like strings, except for reflection.

    (silence)

    AWB: there is one difference. They are in a different meta-level of the system. There is no way that user data can coincidentally be confused for a symbol.

    DD: also, symbols do not show up in JSON.stringify.

    DH: This allows us to add a meta level. Just like __proto__ in the past. Underscores are, until now, our magic feather that we wave around to say "This is the meta-level! This will not be confused with data!" And that's BS.

    LH: unless you enforce the distinction, people will build abstractions that break through the layers.

    EA: before we had for-in; then we gave people getOwnPropertyNames and people started using that; now we're going to give them getOwnPropertyKeys and they'll use that.

    discussion about the string display

    YK: debugger could recognize that it's a uuid and replace with a readable value

    discussion about "__" names.

    LH: if you use any english word, someone could create a conflict. If you use "__", there is no accidental conflict.

    YK: Using "iterator" or "iterator", no one can reliably ducktype for an ES6 iterator

    STH: leaving for lunch, in favor of Symbols

    EA: I'm still in favor of keeping symbols, sorry for derailing the discussion a bit; what helps is the possibility of removing getOwnPropertyKeys. That makes them secure in the absence of proxies.

    LH: but then existing libraries cannot implement a real mixin that moves symbol-keyed properties over to a target object (if symbols aren't given reflective capabilities)

    (Brief discussion of making Object.mixin be the only way to do this.)

    DH: Object.mixin that can transfer symbols plus proxies allows you to reimplement Object.getOwnPropertyKeys.

    AWB: Still think we should have Symbols, getOwnPropertyKeys

    WH: I object to getOwnPropertyKeys (because of too many historical layers: in every spec we seem to be adding yet another layer of enumerating the properties of an object with a we-really-mean-it-use-this-one-instead-of-the-previous-edition's vibe).

    DD/AR/DH: (discussion of Object.mixin + proxies trick.)

    YK: It sounds like we're slipping down the path of doing privacy with symbols again, and we're going to appease people for the wrong

    LH: the concern for getOwnPropertyKeys is that people would just use it in place of getOwnPropertyNames. Maybe if we separate into getOwnPropertySymbols + getOwnPropertyNames that will make it sufficiently painful that people won't just use getOwnPropertyKeys together.

    link Consensus/Resolution

    • Symbols are a new primitive type with regular wrapper objects
    • typeof symbol === "symbol"
    • implicit conversion to string throws
    • new Symbol throws
    • Symbols are public, not private ok that they leak to Proxy
    • Symbols are unique
    • Only exposed via Object.getOwnPropertySymbols instead of Object.getOwnPropertyKeys
    • Object.mixin copies both symbol and string properties

    Additionally:

    • AWB commits to bringing a proposal for user defined well-known symbol registration

    link start="6">
  • Post ES6 Spec Process
  • <

    (Rafael Weinstein) - http://slid.es/rafaelweinstein/tc39-process

    RWS: put together some thoughts after the last meeting with DL, EA, AWB, etc.

    RWS: most of it is good except that it's date driven and the consensus requirements lead to a high-stakes game for getting features into the game.

    RWS: The second problem is that with large-quanta spec releases, there's a varrying maturity level for proposals. Stable stuff is "held hostage" to newer features.

    RWS: as we near a release, we end up with large pressure around things which may or may-not make it. Argue that this is destructive to feature quality.

    RWS: we also have an informal process. It occurs to us that acceptance of features comes before details are sorted out. Implementers, therefore, lack a clear signal about when it's time to start implementing features. Might be unavoidable, but other groups show a different way (W3C, e.g.)

    RWS: we also have a single spec writer who bears the full burden of authoring spec text.

    RWS: a few ideas:

    • decouple additions from dates
    • put structure around stages of maturity
    • what does each stage mean? Get clarity

    RWS: non-goal: componentize the spec or break apart responsibility from the whole group. Also a non-goal to change the rate of evolution (necessarialy).

    RWS: looked at how the W3C works and tried to extract the bits that seem to work well. A 4-stage process: 1.) proposal 2.) working draft 3.) candidate draft 4.) last call

    RWS: At a (much more) regular interval, we'd post (smaller delta) drafts to ECMA.

    AWB: do these stages line up with W3C terminology?

    (sort of, not really)

    RWS: proposals outline the problem, need, API, key algorithms, and identification of cross-cutting concerns. Also, and identified champion. Acceptance signifies the idea that the solution is something the committee wants to keep working on.

    RWS: note that we don't explicitly slate a specific revision is targeted for a proposal. That comes later.

    AWB: concerned that we might accumulate accepted proposals that there's no activity on. How can we structure a cull?

    BE: as needed. FileSystem API as example.

    RWS: the analog might be the "deliverables list" used by W3C -- removing something from the list on the wiki could be that thing

    DH: Not to componentize? Seems like there is something of a componentization and that's the value?

    RWS: don't want to abandon the goal of language coherence. CSS did this wrong and have lots of weirdness as a result. Non-communicating editors lead to pain. This model is different: everything merges into a single spec.

    DH: how is this different to what we're doing now? Maybe this is a smaller tweak?

    BE: What this does is adds more staging before "proposal"

    RWS: this is saying the first stage doesn't have spec text, but the second stage does.

    DH: Makes a lot of sense, might make sense to spell out the earlier "incubator" stage.

    RWS: so there might be a stage-0, which is sort of the strawman we've had before

    RWS: what we want to see at stage 2 is draft spec text. It can have early-quality notes, etc. but thought should be put into the text for the feature before we collectively accept the feature.

    RWS: there are a couple of key things to look at: can we decouple spec editions from specific features? what are the substantives stages of maturity?

    BE: quick question: the i18n spec was on a different track, is this only for core stuff (quotes FakeAlexRussell??)

    (sort of, might be a way to draw stuff into the main spec)

    RWS: stage 3 is the "Candidate Draft". It signifies that the committee thinks the scope of the feature is set. We can incorporate changes, but the key thing is that implementations are potentially costly. This stage is a green-light for implementing and final feed-back

    RWS: stage 4 is "last call draft". 2 implementations and an acceptance test that they pass. Once accepted at this stage, the draft can be scheduled for the next spec to be published.

    RWS: what about dependencies? The committee isn't absolved of this. IT's up to us to manage them and there isn't any silver bullet. We need to make decisions.

    RWS: thought a lot about linkage as a part of this. A champion's interests might work against the language (ducking dependencies, etc.). The committee still needs to advise and continue to look over the landscape.

    (discussion)

    AWB: implicit in this is redefining the role of the editor to be more of an EDITOR, and less of an author. Should probably have a role in advancing proposals.

    RWS: so still a world where there's a single editor?

    AWB: yes.

    (general agreement)

    PLH: Noting that some of the process order might be confusing/out of order, with regard to naming?

    RWS: yes, "last call" means somethign different in W3C that doesn't map well

    YK: the year might be a red-herring. The point isn't the date and the goal isn't to rush things under the wire.

    RWS: (refers to Chrome release process) (not quite Chrome, but close and relevant: https://developers.google.com/v8/launchprocess )

    AWS: some of the non-technical overhead can be offloaded

    DL: part of the goal is to help offload the work, getting more people writing more spec text.

    (notes that this happened for Proxies and O.o)

    DL: inside the v8 team, we don't have a ton of visibility into the maturity of features.

    BE: spidermonkey has shipped many things over the years, but at a cost

    (discussion about implementations and style)

    RWS: so we can imagine that you'd have different styles of implamentations at each stage? Makes sense.

    (agreement)

    AVK: the w3c is removing the last couple of these steps

    PLH: there's a new draft on github somewhere

    (some discussion that you need implementations, hence the new W3C process)

    AR: the chrome process shows that some features might slip multiple features, and that's very good for overall quality.

    AWB: are the criteria here entry or exit criteria?

    (discussion)

    WH: What about mutualy beneficial features?

    AR: that's the dependency question, we talked about that

    RWS: it's sort of arbitrary, but that exists no matter what. There's no silver bullet. It's the job of the committee to keep an eye on what's in flight. Not sure a process can ensure that we can do that well or poorly.

    WH: not componentizing is good, but want to make sure that the process doesn't get in the way.

    BE: true.

    AWS: if we see things that are tightly linked, we might treat them that way

    RWS: as I said earlier, the committee can choose to merge them

    WH: is the intent that the spec will be written by many people? or a single author?

    RWS: the hope is that we'll have more authors for sections of the text, and it'll continue to be the responsibility of the (single) editor to maintain quality.

    YK: I've found it useful to go throuh the exercise of writing spec text

    LH: I like that aspect of this proposal quite a lot

    DH: I've found it useful to write things in pseudo-code when exploring many alternatives...there's a cost for writing it out that way

    AR: things are meant to get more "specy" and improve in quality over time

    (Reviewing previous approaches to specificying new features)

    BE: I think ES7 should follow this

    AWB: Yes

    STH: As long as we're realistic about how much process change can really be helpful

    DH: Smaller features can ship and large pieces can take the time that they need.

    DH: need a way to post features in progress

    WH: Difficult to do refactorings the spec if various folks write parts of it independently.

    BE: Integration step left out? (eg. when does feature integration to the spec occur?)

    • huge costs
    • potentially huge conflicts
    • need to identify necessary changes early as possible

    WH: Concerned that the one-edition-per-year timeline is unrealistic both for us and for our users.

    WH: Once-per-year would be too much of a moving target for users. For example, writing (and re-reading) books about ECMAScript would be difficult.

    WH: Imagine trying to fast-track one edition per year through ISO, with yet another one done in ECMA by the time the previous one gets done in ISO. Also note that ISO has been known to generate interesting comments.

    ??: We don't need to send every edition to ISO.

    ??: Yes we do. They don't like it when you update an existing ISO standard and don't send them the update.

    ??: ISO likes their specs updated once every three years.

    WH: How many simultaneous internal versions of the spec (the master Word document) would we maintain? Three?

    AWB: One.

    WH: Really? Let's say we'd plan to ship a new edition every December. When would we fork our internal spec to work on new features for the next edition while preparing to send the current edition to the General Assembly?

    AWB: Every January

    WH: Then we'd be editing two editions simultaneously almost all the time.

    AWB: I can handle it.

    WH: Yes, but can the reviewers of the spec handle it? We have enough trouble getting folks to re-read stuff as it is.

    WH: Once every two years would be more reasonable.

    link Consensus/Resolution

    link 5.10 Function parameter scoping and instantiation

    Andreas Rossberg

    [Slides](need to commit for a link)

    Default Parameters/Arguments

    Goals: Convenience Feature

    • Readable!

    Non-goal: subtle expressiveness

    Should be able to understand the defaults without looking at the function body

    ARB: Two Issues

    • Scoping related to the function body

    (examples of really weird cases)

    Solution:

    1
    - Defaults should behave as if provided by wrapper function

    Solution: - Evaluate defaults in seperate scope - Can see "this", "arguments" and function name (where applicable) - Can see other parameters - Cannot see bindings created in function body - Cannot see bindings created in function body LATER (via eval)

    Evaluation Order

    1
    2
    3
    4
    5
    function f(x = y, y = 2) {}
    function f(x = eval("y"), y = 2) {}
    function f(x = (y = 3, 1), y = 2) {}

    ARB: Preferably should be const bindings in that scope (not the funciton body)

    AWB: (describes the TDZ)

    Solution:

    • parameters have TDZ
    • Initialized in sequence

    WH: No distinction between a missing parameter and explicit undefined?

    AWB: We agreed on that a long time ago.

    BE: I thought there was agreement/discussion?

    (referring to: https://github.com/rwaldron/tc39-notes/blob/master/es6/2012-11/nov-29.md#proposal-part-2 )

    (need slide examples)

    DH: Most concerned with implicit rebinding

    STH: The rebinding is only observable

    (discussion re: mutation in parameter bound closures)

    STH: Can fix this while preserving

    ARB: Can change the "nutshell" to meet the needs of the concern items:

    1
    const => let

    BE: In the example that binds

    AWB:

    • parameters are in separate scope contour
    • visible to the body scope
    • the body is disallowed from creating
    • "namespace" for parameters

    NM/RW: (agreeable points about curly brace boundaries reinforcing scope)

    BE: Summary:

    • Outer Scope
    • Parameter Scope
    • Function Body Scope

    YK: (recalling names declared in parameter scopes being rebound in the function body)

    AWB: I can express this with one Environment Record

    ARB: Cannot, because of eval. A delayed eval in the parameter list must not see bindings from the body

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    function g() {
    return 3 * 3;
    }
    function f(h = () => eval("g()")) {
    function g() {
    return 2 * 3;
    }
    h();
    }

    AWB: Agreed

    DH: (post-clarification)

    • Two Scopes
      • The Function Head/parameter list
      • The Function Body

    In the function head/parameter list, cannot see the scope to the right (the function body).

    AWB: Any new syntax in the parameters, changes the handling?

    (vast disagreement)

    AWB: The spec currently says var-like bindings. If you have new syntax, they're still var-like

    • Duplicates are illegal
    • Rules about redeclaration
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    // If...
    function f(x) {
    var x;
    }
    // changes to...
    function f(x = {}) {
    var x;
    }
    // No difference.
    // But changes to...
    function f(x = {}) {
    let x;
    }
    // Error for redeclaration.

    (clarification re: nothing changes var bindings to let bindings)

    WH: (whiteboard) What is the value of y in this example? 5 or 2?

    1
    2
    3
    4
    function f( x=(y=3, 2), y ) {
    console.log( x, y );
    }
    f(undefined, 5);

    (discussion without a clear resolution)

    CF: What about:

    1
    2
    3
    4
    5
    6
    var y = 2;
    function f( x=y, y=3 ) {
    console.log( x, y );
    }
    f();

    BE & Others: y is shadowed result is (undefined, 3)

    WH: What is the value of y in this example? 2, undefined, or 5?

    1
    2
    function f(x = (y = undefined, 7), y = 5) { ... }
    f(undefined, 2);

    AWB: The original value of the parameter is used to decide whether to default it or not.

    BE: Surprised. Unhappy with having to store the original values of the parameters, thereby making for two copies of each one.

    AWB: Already need to do this for the arguments object.

    BE: The arguments object is easy to statically detect. These are more insidious.

    (no clear resolution)

    ARB: Fundamendally these are mutually recursive bindings.

    BE: We agreed on two scopes. Head and body.

    • If another parameter has a default?

    link Consensus/Resolution

    • Two Scopes
      • Head/Parameter List
      • Body
    • Temporal dead zone?
    • Details unresolved?

    link 4.5 Modules Update

    Dave Herman

    [Slides](need to commit for a link)

    link Generic Bundling Slide

    (Debate about hash as the delimiter. Agreement that this discussion can take place elsewhere.)

    DH: the browser loader is not something that belongs in Ecma-262. It's a separate spec. We can do it concurrently. We definitely want to start now and get feedback early, but it doesn't need to block ES6.

    (Discussion of confusion on parsing vs. evaluation timing. Custom loaders can implement the desired esoteric use case; see caching slides.)

    DH/LH/JM: Use case under discussion is lazy module execution, like AMD bundles or previous named module declarations. If you have a console.log inside a module, is there a way for that not to get executed?

    DH: we may need to check to ensure that is possible, but it probably is. And the simplification of removing named module declarations still seems worth it.

    link 4.6 Unbound variable checking

    Dave Herman

    DH: Proposes that if m is an imported module, then m.bar should be a compile-time error if the module doesn't have a property named bar.

    WH on whiteboard: Should this be a static error in that case?

    1
    2
    3
    4
    5
    module m from "foo";
    with (a) {
    m.bar;
    }

    ?: Modules are in strict mode and don't allow 'with'. WH: But this isn't a module; it's just referencing one.

    link Module loading

    DH: it used to be that <script async> would be able to do I/O, including import declarations; I've relaxed that. Now <script> can do that.

    DD/DH: (clarification that you can use module syntax in scripts, not just modules>

    BE/DH: (discussion of allowing <script> without async to load modules.>

    AR: note that inline scripts with async or defer attributes currently do not impact execution or parsing. This may change in the future.

    JM: if people want to use import in a synchronous script definition, that should be OK; just throw

    DH: that was the direction I was moving, but LH was objecting to. And DD has an interesting point that if we don't let import happen at the top level, that would work well too.

    STH: What do we like?

    YK: Adding a form to HTML that says "this is a module." This reduces the need to allow imports in scripts.

    BE: that would mean we're betting on getting something into HTML

    DH: yes, but you could just use the loader API.

    BE (whiteboard): four cases

    1
    2
    3
    4
    5
    6
    7
    <script>(1)</script>
    <script src="...">(2)</script>
    <script async>(3)</script>
    <script src="..." async>(4)</script>

    WH: how do you load a module without async scripts?

    YK/LH: System.load("module")

    WH: and you wouldn't need to import System or similar

    DH: no, that's just a global

    WH: but we have features that require modules, e.g. iterator

    DH/YK: yes, but you can just do System.get("std:iterator").iterator.

    WH/DH: if it's hard to use a module inline in the page, then it's hard to write the good code we want them to write.

    DH: this is something that needs to happen for multiple reasons, so it should happen in HTML.

    YK: import in top-level scripts doesn't give us modules in top-level scripts, only import in top-level scripts.

    JM: so how do you enter the module system from HTML?

    DH: two ways. The loader API, or the hypothetical <module>.

    BE (whiteboard); top level script looks like

    1
    let { keys, values } = System.get("@iter");

    DH: BTW JS practictioners, I'd like to reiterate if you have concerns about the standard module system.

    LH: Implementers will ship iterators before modules, so we need a way to get at these things more easily.

    DD (jokingly): We can just use a proxy to trap @@iterator in the meantime.

    DH: I really think this how-to-enter-the-system conversation can occur outside TC39.

    BE: so we can provide two top-level environments.

    BE: OK, this is all about separation of standards-body concerns.

    DH: and this helps not block TC39.

    (Discussion somehow turns back to <script> vs. <script async> getting module-loading abilities.)

    BE (to LH): so you're worried about an attractive nuisance, people doing more synchronous loading than they should

    LH: Well today, import always succeeds, but with this proposal, it's order dependent, like today's System.get.

    WH: as a new HTML element won't work due to HTML parsing issues. Note that scripts contain un-HTML-escaped <'s (and even larger chunks of HTML tags) while other HTML elements don't. An HTML parser wouldn't know how to properly skip past an element (such as the proposed ) that it doesn't know about.

    DH: I think <script type="module"> or similar is going to be necessary, for many reasons.

    DH: so to recap, there's the two possibilities: allow gradual integration via import etc. in scripts, or the green path where you enter the module system once and then are there.

    JM: Facebook wants both, so we can do initial page load and async load.

    DH: that's fine, you can do that with System.set in the initial page load.

    DH/BE: (Agreement that this should go in other standards bodies.)

    link Back to Static Checking

    LH: back to static checking?

    BE: you have to do label checking. It's not that bad.

    ARB/BE/DH: we have to implement to find out.

    BE: how much parsing do you have to do?

    ARB: so that's in the pre-parser for V8

    BE/DH/ARB: (discussion of V8's pre-parser)

    DH: somewhere in between a reader (along the lines of SweetJS) and a parser, and that's what I don't understand.

    ARB: it's a parser, but it just glosses over a lot of the grammar.

    ARB: to be completely honest, we would like to get rid of this thing.

    BE: so we won't know if adding this static checking for modules has implementation consequences, until implementers actually go implement it. So if they have appetite for it, we should try to do that.

    DH: JSHint or TypeScript could do all these things... We need to at the very least provide the basic foundation. But that would shut the door on further static things.

    BE: V8, do you guys have an appetite for trying it?

    ARB: I'd like to try, but not sure if it's possible within the ES6 time frame.

    BE: and what about Chakra?

    LH: we can try it, but we don't know...

    DH: it would be OK with me to close the door on static things like guards.

    BE (to ARB): wait I'm confused. If you're doing import/export checking, aren't you doing about the same work you'd be doing for full static variable checking?

    ARB/LH: no

    DH: import/export is top-level only; you don't have to walk the full AST

    LH: you would have to freeze the global environment at the point in which the static checking happens, and test against that

    DH: yes, that's right

    BE: OK, so maybe it's enough to have import/export checking. That spot-in-time check could be a problem. Yes, this is a problem for monkey-patching.

    DH: every time we go through these cases it takes hours to remember the global object semantics.

    AWB: I thought we concluded a long time ago that we had to preserve global semantics.

    DH: clarifies: only talking about within the body of a module.

    • Check the script against the current state of the Global object at compile time
    • This is an unsound and incomplete analysis, but, it's one that you can program to.

    BE: so if we say that module bodies do not have this type of static name checking, we're closing the door to guards, hygenic macros, type checking, ...

    WH: how does it close the door to guards?

    DH: we always talk about guards as if we knew what their semantics were...

    BE: OK, well, how about truly static stuff like types or macros.

    DH: my experience in ES4 was that it was fighting with the dynamic aspect of the language

    WH: in Lisp we have a multi-level time-of-execution (i.e. eval-when) system... it was very messy...

    BE: I think static types and static metaprogramming as an option are shown to be not possible, really, via the fact that TypeScript and Dart are both basically WarnScript.

    DH: I think that it's been shown that tooling is generally how the web solves this problem.

    LH: and we could do this outside the language itself, the opt-in could be e.g. opening the debug tools instead of being in a module body.

    STH: But, nobody's said that this is a horrible feature, there's just some implementer reluctance.

    DH: JSHint works fine; modules alone will allow JSHint's undefined variable checking to work without having to provide a large list of globals.

    LH: we've started creeping a little bit toward doing more static analysis, but this would be a big step.

    DH: what do you mean static analysis.

    LH: I mean more early errors. We added more in ES5, e.g. duplicate variables. ES6 has added more with let and const. This is the next big jump. It's not clear where that's trying to go... We could go much further, we could build the whole linter into that point.

    DH: I have years of experience writing Racket code, which works exactly like this. Once you're in module code, you have static variable checking.

    LH: but no global object in the scope chain.

    DH: actually kind of, but yes, people don't use it nearly as much as on the web.

    DH: The static variable checking is both unsound and incomplete; the former is because of snapshot-in-time globals, and the latter is because of the halting problem.

    WH: I want a way to get static variable checking but also monkey patching. Perhaps declare which global bindings you might want to monkey-patch.

    checks on import/export

    Ecma/TC39 Meeting – Sep 17 2013

    link Sept 17 Meeting Notes

    John Neumann (JN), Dave Herman (DH), Istvan Sebestyen (IS), Alex Russell (AR), Allen Wirfs-Brock (AWB), Erik Arvidsson (EA), Eric Ferraiuolo (EF), Doug Crockford (DC), Luke Hoban (LH), Anne van Kesteren (AVK), Brendan Eich (BE), Brian Terlson (BT), Rick Waldron (RW), Waldemar Horwat (WH), Rafael Weinstein (RWS), Boris Zbarsky (BZ), Domenic Denicola (DD), Tim Disney (TD), Niko Matsakis (NM), Jeff Morrrison (JM), Sebastian Markbage (SM), Oliver Hunt (OH), Sam Tobin-Hochstadt (STH), Dmitry Lomov (DL), Andreas Rossberg (ARB), Reid Burke (RB)

    link Welcome

    RW: ...Logistics...

    link Agenda

    Promises to be discussed Thurs. PLH from W3C will be here on Wed/Thurs.

    BE: won't be here thurs, and that suits me.

    JN: objections to using this agenda?

    (crickets>

    JN: next issue is approving the agenda.

    Approved.

    JN: Minutes approval?

    RW: (Confirms no changes since last review)

    Approved.

    JN: have a strong duty to surface the agenda to ECMA and right now we don't know how to do that. Want to publish something to ECMA 3 weeks before the meeting and one week before, a final version of the agenda.

    AVK: how about we give them a URL?

    IS: the issue is that we haven't had a fleshed-out agenda 3 weeks before the meeting. There hasn't been anything there.

    AR: this seems like a mismatch between the historical timings of meetings and our accelerated cadence.

    DH: We talked about this in last meeting, where we agreed that everything would be in the agenda one week prior. If we don't accept new items, the agenda is a dead letter.

    AR: we can commit to having a skeleton that has stuff we will usually talk about, but not more.

    RW: in the past, an email went out that helped remind people. If we sent out a reminder email at the halfway point, it might help people remember to add agenda items then.

    DH: Let's strategize which items are best to work on and which day.

    • Modules: Wait for Andreas

    • Typed Arrays: Wait for Dmitry, Oliver

    • Symbols: wait for Andreas

    • Proxies: wait for Tom VC

    DH: Arrows, Math.hypot today

    EA: Spec process

    DH: We can do this out of order. ...Let's discuss Data parallelism while Niko Matsakis is present.

    link start="11">
  • Status Report 262
  • <

    AWB: I'd like feedback and comments on the new re-orderings.

    DH: I know that Jason Orendorff has some issues (es-discuss: https://mail.mozilla.org/pipermail/es-discuss/2013-September/033314.html (starting with Olliver Hunt))

    AWB: New sections...

    • Runtime Abstractions
    • Group Of Chapters that define the language
    • Lexical Grammars
    • Syntactic Grammars

    AWB: There was some recent discussion about how you track down semantics when you have so many named semantic algorighms that are associated with productions. I've done work subsequent to r18 that adds a "see also" section at the top of each segment so you can

    BE: what do people think of the new organization?

    (general approval>

    WH: The latest version sent to the ECMA document repository is from May. Why aren't new versions being sent to the ECMA repository?

    (group directs WH to the latest version not in the ECMA document repository>

    (googlers + facebookers arrive>

    BE: wait there's more Googlers? We have to bring more Mozillans now... (I kid, I kid.)

    AWB: At the last meeting we sucessfuly deluded ourselves into thinking we didn't need NoIn productions. We've been unconvinced, so I reintroduced them.

    WH: I've been looking into this NoIn business

    AWB: OK, well if you come up with a solution for it!

    WH: I got my grammar verifier up and running again.

    DH: Ollie spent a long time looking at them and didn't come up with a solution.

    AWB: naked yield is supported. The assignment part is optional.

    EA: for yeild*, the expression is needed.

    DH: agreed

    • yield * wouldn't make sense without

    AWB: WH brought up that you can't have a conditional reserved word, so what I did is ensure that yield is always a reserved word which, in contexts where it can be an identifier is treated as such.

    DH: contextual reserved would would be another instance of feedback from parser back to lexer (a la slash); Allen's approach is more elegant.

    BE: yes, it's the right tradeoff.

    AWB: overall status: thanks to Dave, in the current working draft we're starting to bring in module grammar productions and semantics.

    • module grammar productions
    • module semantics
    • Confident in the progress

    BE: we have a separate agenda item on this, yes?

    (yes>

    AWB: still hanging out there and need work

    • no work done on unicode regexp
    • no work done on updating regexp to web reality

    LH: Last consensus on "web reality" was that it would be in an annex ...

    LH: there's text (http://wiki.ecmascript.org/doku.php?id=strawman:match_web_reality_spec) that patches some rules.

    LH: the reason we got hung up is we thought there might be some grander unification with the regexp unicode flag, and I don't know what the status is on that.

    LH: we should integrate the web reality piece into the spec.

    AWB: do we want to defer the Unicode part

    BE: did we have someone identified to work on it?

    (norbert>

    AVK: I thought there was discussion that agreed what was in and what was out?

    BE: If Norbert doesn't do it, it's not going to happen for ES6

    WH: (Q about the yield)

    • Will allow yield as an identifier?

    AWB: Yes

    WH: This will break

    (whiteboard)

    1
    yield * 1;

    is that a multiplication or yield *?

    AWB: (whiteboard)

    YieldExpression := [inside a generator] yield aaugh this keeps getting erased

    AWB: inside a generator function, "yield" is a keyword that introduces a generator expression.

    WH: inside a generator, this ("/") will be a RE, outside it will be a division symbol?

    WH:

    1
    yield /a/g;

    is this yield divided by a? or yield a regexp?

    BE: so this is like the regular expression delimiter, it's going to need to have feedback from the parser to the lexer.

    ?: If you're inside a generator, it's lexed as a regexp. If not, it's lexed as division.

    DH: I think that isn't affected here, the lexer is always fed the parsing context; it's not an ambiguity because it's determined by context.

    WH: What's "inside a generator"? What if you're inside, say, an arrow function inside a generator?

    ?: Then you're not actually inside a generator.

    WH: But you need to lex the thing to parse the thing to find out that you're inside something nested inside a generator, so that's begging the question.

    BE: split grammar at higher level, InGenerator, NotInGenerator, something something something.

    BE & DH: use new tricks, e.g. parametric productions. Even NoIn, back in the day, we would have preferred to use those.

    AWB: Yeah, if we have to do this for yield, I'd be happy to switch to parametric productions, since it avoids having four forms of the expression grammar.

    BE: alternatives is to make generator bodies strict.

    DH: We shouldn't make the users life worse just to make the spec easier.

    WH: well we are prioritizing the user, think of syntax-coloring editors, they also now need to know these complicated rules, too complicated and they'll get them wrong.

    DH: in practice editors get things wrong

    BE: and then you can pull request against them so it's all good.

    DH: new implicit modes will bite more often

    BE: let and yield are reserved in strict mode since ES5

    DH: Parameterized productions are the cleanest solution

    BE: Much better to parameterize then to duplicate productions.

    BE & AWB: let's do a smaller group on parametrizing the productions.

    ...

    AWB: Is there a point on binary data?

    • Don't think we're going to get them in

    BE: related to spec process, getting things done painless and in a rapid-release fashion. let's talk separately.

    AWB: Status wise: no progress on Binary data Typed Objects proposal with regard to the spec.

    RW: (clarified binary data vs "typed objects")

    DH: binary data name is bad, "typed objects" better. Because typed objects as specced are not actually good for binary data.

    Typed Objects (formerly known as binary data)

    AWB: typed arrays and dataviews are in ES6 spec, "structs" are not.

    DH: Dmitry is working on this, it's not 2014 yet, we shouldn't definitively say it's not going in.

    AWB: well, I'm trying to manage expectations.

    BE: Let's revisit after we get a little further with the other items.

    link 4.1 Arrow Functions

    BE: When I proposed Arrow Functions, the empty parameter list was made optional. The omission

    LH: C# requires formal parameters?

    DC: Who is asking for this?

    BE: Community feedback, Domenic has mentioned it as well.

    DD: Possibly due to CoffeeScript, but is nice to omit the parens where they aren't necessary.

    BE: For this proposal, there is no issue in leaving the param list out

    1
    2
    3
    4
    let foo = => ...;
    x = (y) // note missing semilicon
    => z

    BE: but nobody does this.

    DC: A concern, x = y, as written without the parens...

    1
    2
    x = y
    => z

    (This is a valid Arrow Function: http://traceur-compiler.googlecode.com/git/demo/repl.html#let%20x%20%3D%20y%0A%20%20%20%20%3D%3E%20z )

    AWB: No parameters: no LineTerminator here?

    BE: If someone began with an arrow,

    WH: I'm fine with this being an arrow function, but don't want this to depend on line breaking. I consider the following to be legitimate:

    1
    2
    x = averylongid
    => foo

    DH: This would introduce a new sigil that you'd have to worry about

    BE: npm style is a thing. People actually put semicolons at the beginning of lines starting with + - / { [ (, this would introduce => to that list.

    1
    2
    var i = "1"
    ;+i

    WH: (laughter)

    BE: you laugh, but people do this

    WH: I thought I'd seen it all...

    BE: Do we extend the short list of characters that can begin an ExpressionStatement

    DH: It's not worth it

    EA: I think it's worth it

    BE: Writing "()" is too hard?

    DD: It's ugly.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    it("should do something", => {
    // ...
    });
    vs.
    it("should do something", () => {
    // ...
    });

    DH: I'd prefer not to have the hazard.

    AR, DC: Agree with DH

    link Consensus/Resolution

    • No consensus on removing the empty param list

    link 4.3 Math.hypot

    DH: The idea is that it returns the square root of the sum of its arguments, but we have 2 and 3 argument special casing.

    http://wiki.ecmascript.org/doku.php?id=harmony:more_math_functions

    It's an offense to mathematics if it's not: "The square root of the sum of the squares of all the arguments"

    Defend the pristine purity of math. If it's only a 2-argument function, that's OK, but having it a 2- and 3-argument function is not good, just make it an n-argument function.

    BE: Jason Orendorff outlined these problematic cases... (see es-discuss)

    DH: this is no good man.

    LH: Should be variadic

    DC: Programming in general is an insult to mathematics. Because what we call functions are not what they call functions. One convention we have in JS is that calling a function with three parameters is the same as calling it with two plus undefined.

    DH: but not for variadic functions. Since we want it for arity 2 and arity 3, cleanest way is to make it variadic. If you have 2 cases, yo have n cases.

    link Consensus/Resolution

    • variadic
    • call ToNumber on all actual arguments
    • if one is NaN, no special behaviour, allow to fall out.

    link 4.7 JSON.stringify and unpaired surrogates

    https://mail.mozilla.org/pipermail/es-discuss/2013-September/033293.html

    AWB: The concern is that JSON.stringify, as specified in ES5, if there is an unpaired surrugate

    AVK: There's a bug in V8 where lone surrogates passed to the utf-8 encoder turn into CESU-8 byte sequences.

    • What is the defined failure space

    DC: The new spec is code points, so it could be unpaired surrogates

    AVK: So it's 16-bit code units

    DC: Yes

    • JSON currently passes unpaired surrogates right through
    • Suggest escaping them

    AWB: Only for unpaired surrogates

    DC: Will get through a UTF 8 Encoder, but will blow up

    AVK: If you want the surrogates to make a round trip, then escape them

    LH: Seems like it's saying, in practice, JSON will only admit into a JSON document UTF8

    DC: (Question about range of affected)

    AVK: only surrogates are affected

    LH: were people running into this problem in practice?

    AVK: Right now, roundtripping unpaired surrogates does not work. We could fix this by escaping them.

    AWB: But this is an incompatible change from ES5, since the length of the string would change to include \uXXXX (or \uXXXX\uYYYY) instead of the surrogate itself.

    AVK: (whiteboard)

    1
    JSON.stringiyf("\uD800")

    AVK: \uD800 is a single sixteen-bit code unit that is also a surrogate.

    BE: this seems incompatible, so I say no

    LH: this just seems like a single case...not sure why we'd patch just this case

    AWB: this is about unicode/UTF-8 which is very common

    LH: any time I serialize any JS string, I have this issue, JSON isn't necessarily what's in question

    AVK: this is also about JSON as it's a network format

    DC: why are people doing this anyway

    AWB: e.g. because they're passing binary data as strings

    BE: murphy was an optimist

    WH: Note the CESU-8 spec, which is a mutant of UTF-8 that encodes individual surrogates individually (even if they're paired).

    AR: if CESU-8 is bad, why isn't this fix bad?

    AVK: you get subtle security bugs and it's incompatible with UTF-8. I don't really mind that we lose surrogates as I don't care about them

    BZ: if you pass unparied surrogtates, you'll just get bytes. If people are trying to use the high bits to store binary data, there are going to be problems.

    DC: the problem is that you're trying to pass 16-bit data through to UTF-8.

    (binary data through UTF-8 requires separate escaping)

    AVK: is a network format, it has strings

    BE: JSON is more then a network format

    ?: If you want to pass binary data, just escape unpaired surrogates before serializing them as JSON.

    WH: Won't work. JSON will escape the backslashes in the escape sequences and you'll get double backslashes.

    link Consensus/Resolution

    • No Change. If you want to use lone surrogates you'll have to escape them after JSON.stringify().

    link 5.1 splice, cross-realm Arrays and subclassing

    http://esdiscuss.org/topic/array-prototype-slice-web-compat-issue

    AWB: (whiteboard)

    1
    let newA = a.slice();

    AWB: it turns out people use this to make a copy of an array

    In the general case, assume you have:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    class SA extends Array {}
    let sa = new SA(10);
    sa.slice(1, 5);
    // What does this return?
    // - a new SA?
    // - a new Array?

    It seems to make sense that when you slice a SA, you should get a new instance of SA

    WH: (recalling Mark's points about Caja(?) use of slice) Array.prototype.slice.call(a)

    AWB: This all makes sense, but the problem came up: what if "a" came from a different realm? Under ES5, slice() always gives you an array from the realm from which the slice function itself was defined.

    EA: the expecation that you'll get an array is flawed since you are just calling "slice" on an unknown object. "slice" could return 42.

    WH: Not what I asked. I was asking about the common existing idiom of calling Array.prototype.slice.call on an unknown object to coerce it into something known to be the built-in array. This breaks that.

    1
    2
    3
    [].slice.call(a);
    // This result will be an array from the [].slice.call realm

    AWB: I've tweaked the spec to say:

    • If the constructor I'm using to make the new instance is in fact a built-in Array constructor (not a subclass) from any realm, it then creates an instance of the Array constructor of the slice function.
    • So it essentially does what ES5 does, but if it's a subclass it doesn't do what ES5 does, but ES5 does

    RW: my concern was if NodeList was eventually to become a subclass of Array, what happens to existing code that does...

    1
    [].slice.call(nodelist);

    RW: it may solve itself? (the returned thing has the expected "shape")

    (returned thing IS a realm-local Array instance)

    AVK: we're not going to change NodeList (we're still trying to maybe put Array in its prototype chain), we're creating a new thing, Elements, which will work great.

    RW: A new thing avoid breaking the old things.

    BZ: well note that HTMLCollection can never get fixed in any way.

    AR: just to clarify, if I have subclassInstance.slice(...), I get back what?

    AWB: a subclass instance

    (yay)

    WH: If we adopt this, what would be the new blessed way to coerce something to an actual Array?

    AWB: ES6 has numerous ways to force things to be an actual Array (not a subclass) from a given realm. Anyone who wants to force it can do that.

    BE: yes, Array.from, or spread, i.e. [...otherArray].

    DC/LH: you're proposing a breaking change?

    AWB: no, I'm actually removing a breaking change. For all existing cases, the behavior will be exactly the ES5 behavior.

    WH: It is a change for the uses that expect Array.prototype.slice.call to coerce to an actual Array. They will need to change if they interact with any ES6 code.

    (General concern to ensure the behaviour remains the same)

    BZ: In the subclassing world, and I add method to Array.prototype, if I had an actual array, I will get an array from this realm.

    BE: If the first arg to [].slice.call(a) (a) is an instance of a subclass of an Array in this realm, as constructor will be used, otherwise, use

    BZ: if the realm of the thisObj and the method do not match, create it in the realm of the method using the stardard Array constructor there.

    AWB: Agree

    WH: How do you find the realm of a Proxy?

    DH: really don't want to go in the direction of relying to heavily on the realm

    BE: What are you using to construct?

    AWB: it's constructor property

    AR: Mark counts on this behaviour to ensure that he'll always get "clean arrays" from something that may or may not be "dirty". He could accomplish this by using a frozen version of the method?

    AR: Concerned about the Array "redirection", different prototype depending on what you call slice with

    BZ: If you're doing "a.slice()", there is no problem, the result is a new instance of the thing you called slice

    RW: Right, the issue arises when doing [].slice.call(arguments), nodelist, etc.

    AWB: And these aren't arrays

    (arguing the meaning of subclassing in ES5)

    AWB: BZ's proposal of matching the realm of the function with the realm of the constructor is probably the right way.

    DH: Seems like creating a patch for a scenario

    DD: But this is what user code would do, using this.constructor

    AWB: none of these are guaranteed, where you can wack the prototype...

    #### Consensus/Resolution
    • When slice is call, what is the realm of the slice method and the realm of the constructor of the thisObj (since objects don't have realms, only functions do, we have to look up constructor).
    • If they do not match, create it in the realm of the method using the stardard Array constructor there.

    DH: why not actually find out what realm an object was created in, instead of trying to infer it from this.constructor.

    AWB: Is there any other way of creating an instance of this object without knowing what this.constructor is?

    BE: In ES6, class B extends A {}

    AWB: Need to know two things:

    1. How to query what the constructor object is
    2. What the protocol is for invoking that constructor

    DH: So for slice, we have a default

    AWB: Yes. Considering adding to collection constructors, a factory for creating

    DD: Sounds like an unforgeable symbol that effectively is the same as .constructor, but can't be messed up like .constructor can.

    DH: Object to something that is an approximation to what we want

    BE: It's a reflective approximation

    • Implementations do not want

    AWB: What I am proposing and BZ:

    1
    2
    3
    What is the realm of the object I would create?
    Is the object going to create an Array?

    BZ: Seperate the concerns, two conversations about creation:

    1. "How?"
    2. "What?"

    WH: Are you expecting to construct or call

    (back to "how")

    AWB: In my proposal you check if it's a constructor

    BE: Opposed to that

    DH: Have you audited these cases, how does it work for them all? Does it work for them all, except this case?

    AWB: Yes. (The fix for splice is the fix for all of them)

    BE: You've added a new reflection on the constructor

    • Let's take this back and make it completely backward compatible

    BE: I can write code that sets constructor, and now it works differently in ES5 and ES6.

    AR: (mumbled something relevant)

    BE: Don't think Mark would want the constructor check

    AR: The dot operator is the root of all evil in JavaScript.

    BE: I thought it was the NaNs...

    AR: We've got a lot of evil.

    DH: How much breakage are we talking about? Given the semantics Allen originally wanted?

    AWB: under what situations does getting an array instance from a different realm break something? Well, if you've tweaked Array.prototype across your realms, that will make a difference.

    BE: The odds are non-trivial that we'll break something

    WH: If you're looking at the prototype of things, Caja will break. If you're looking at the constructor property, ES5 code will break for anything that has a custom constructor

    AWB: Ignoring the Realm, unless we add some new operation on instances that reveal what Realm they are originally from.

    BE/DH: need to go back and work on this.

    link Consensus/Resolution

    • Needs revision of proposal.

    link 5.2 Evaluation Order and The [[Invoke]] Operation

    DH: Yehuda was interested in this.

    link 5.3 @@unscopeable

    AWB: Inheritance?

    ARB: Wrong to apply this across inheritance

    AWB: Changed in r18

    ARB: How was this changed?

    AWB: Own property

    The remaining question, do we lookup on entry of with block or for every access?

    WH: which one is slower?

    AWB: every access

    WH: OK, let's do the slower one.

    (general laughter and applause)

    ARB: (question about lookups that occur up a prototype chain that might encounter an @@unscopeable)

    DH: The semantics of with:

    • There is an object that we'll do all lookups on

    We're adding to that:

    • Check the black list first

    BZ: Consider you have two objects in your prototype chain, with two different @@unscopeable black lists

    AWB: The first

    ARB: What if you've put a "values" property directly on the instance?

    RW: This was meant to fix that problem.

    ARB/BZ: On the prototype, but what about an own property on the instance

    (acknowledged)

    ARB/DH: Discussion about predicted breakage.

    BZ: Possibly as a descriptor?

    RW: That was also considered

    ARB: But if you [[Set]] it won't go away

    1
    2
    var a = [];
    a.values = 1; <--

    DH: (Recalling the issue that created this problem)

    1
    2
    3
    4
    5
    6
    7
    function f(values) {
    ^-------------------------+
    with(values) { |
    values = 1; |
    ^--"values" here is pointing to-+
    }
    }

    But, if the parameter bound values object has a property called values, the values access INSIDE with(){} is accessed.

    RW: The case that hits @@unscopeable in its current form is far on the edge. Ext.js is generally an outlier in their use of with(){} (in a world that's continuing to progress towards strict mode). Future versions of Ext.js won't have the offending with(){} code, so it won't break on @@unscopeable. Ext.js has also committed to evangelising and getting the patched code out to clients, it was just a matter of needing time to do so.

    AWB: Someone could have created his own Array instance with names that @@unscopeable would hide. This would be also not be compatible.

    BE: This is why I find find/fill kind of short, you might get collisions. ??

    AVK/EA: But but but DOM

    BE: Don't rush!

    BE: Gecko did ship Array.prototype.values and backed out which is why we added @@unscopeable.

    BZ: In the DOM we want Element.prototype.remove and friends which are problematic due to event handlers, which use with semantics.

    BZ: You could have a proxy that does the same thing.

    AVK: Ouch.

    ARB: When an access occurs in with(){}, and a property is found, look at the @@unscopeable on THAT object

    DH: Do we want to blacklist names or name-object pairs.

    • Distinguish between allowing instance properties

    BE: How does this change for MOP?

    AWB: Changes from Get to GetOwn, etc.

    BZ: DOM Proxies are nicely behaved.

    ...

    AWB: Is anyone actually going to implement?

    DH: This is easy for SpiderMonkey

    ARB: This is easier then the previous.

    BE: Concerns about changing the Identifier resolution for Proxy

    AWB: Only for with

    DH: If you want to not bypass the proxy mechanisms, you have have to give them a new trap to define how they behave when [[Get]] in with(){}

    BZ: Have to give Proxy a way to know that it's happening in with(){}

    (working through issues with document.forms)

    hasOwn on @@unscopeable

    DH:

    • Walk the prototype chain
    • foreach one,
    • check if it hasOwn @@unscopeable
    • hit a proxy, does the same

    ...This prohibits Proxy from participating in the object operation.

    WH: Summarize?

    BE: We have a problem adding names to mature the API. Let's move forward with @@unscopeable

    AWB: For the @@unscopeable arrays I specify in the specification, should they be frozen?

    DH: No, need to be able to polyfill feature additions.

    AWB: You could always replace the array object.

    BE: When in doubt, don't freeze. Why isn't it a Set?

    DH: put down the freeze gun. Put it down.

    EA: Set is the right answer, semantically.

    AWB: Yeah.

    DH: I don't really care.

    AWB: You asked for a Set no, I think it should be a Set.

    link Consensus/Resolution

    • Continueing with @@unscopeable, with changes w/r to lookup to be defined.

    • Noted change:

      • When a property is found, look at the @@unscopeable on THAT object
    • @@unscopeable

    • a Set

    link 5.5 Math.roundFloat32

    AWB/DH: Offline discussion to rename to something more Math object familiar

    Suggestions:

    1. Math.fround()
    2. Math.f32round()
    3. Math.roundF32()

    DC: This isn't a round operation

    DH: It is, according to IEE 754

    BE: fround. f means float, i means integer

    AWB: What this effectively does, is "round" (observably)

    link Consensus/Resolution

    • Math.fround

    link 5.6 Backwards compatability, Unicode UTR31, and ES identifiers (U2e2f)

    http://esdiscuss.org/topic/backwards-compatibility-and-u-2e2f-in-identifier-s

    AWB: Traditionally, ES has said that Identifier are composed of unicode characters. There are changes to Unicode that rescind it's ability to be an Identifier.

    AVK: According to Norbert, the character in question was not part of Unicode 3.0 and therefore not a change

    (group testing identifier creation with U2e2f)

    link Consensus/Resolution

    link 5.7 note in 11.6 WRT Unicode versions, update to Unicode 5.1

    http://people.mozilla.org/~jorendorff/es6-draft.html#sec-11.6

    AWB: (Norbert proposal)

    link Consensus/Resolution

    • Remove: "NOTE 2 If maximal portability is a concern, programmers should only employ the identifier characters that were defined in Unicode 3.0."

    link 5.8 line terminators in template strings. Should they be normalized?

    (discussion re line terminators)

    AVK: HTML parser does normalization, but e.g. DOM setters do not

    BE: not normalizing would introduce more interop hazards than we want.

    AWB: just to be clear, this is both cooked and raw form.

    BE: yes. Add \r\n to the list of special things, alongside closing backtick and ${

    • Propose: CR and CR+LF are canonicalized

    AR: why isn't this just part of the data? Why canonicalize?

    BE: it's not a byte string, it's a string.

    BE: but raw should be raw

    DD: no but then you have an interop hazard, because people will write code that works great on Unix, then some poor Windows user ends up with \r's in his strings that the Unix-using author did not anticipate.

    BE: but you should be using cooked

    DD: but a lot of the examples, e.g. on the wiki, use raw

    BE: ah right, like the regex one, because you need all those slashes. Hmm.

    BE: Python normalizes, Ruby normalizes

    link Consensus/Resolution

    • Normalize CR, LF, and CRLF to LF

    [WH: Is this consensus recorded correctly? I understood the consensus to be normalizing all lexical grammar LineTerminatorSequences to LF.]

    EDIT RW: Yes, and was re-stated for confirmation.

    link 5.9 12.2.4 note says we decided (Jan 2012) tail calls only in strict mode. Is this still correct?

    http://wiki.ecmascript.org/doku.php?id=harmony:proper_tail_calls

    DH: function.arguments is poisoned in strict mode. This opened up doing tail calls.

    LH: Are the tail call locations on the wiki still up to date?

    DH, AWB: yes, to the best of our knowledge; let us know ASAP if there's something wrong with them.

    • Discussion about tail call location opportunities

    AWB: getting close to the point of getting tail call stuff into the spec (depending on how busy Dave keeps me); any comments appreciated sooner rather than later.

    AWB: Implicit calls to accessor properties in tail positions, e.g. return x.y, and x.y turns out to be a getter, do we want this to be a tail call.

    1
    return x.y;

    If x.y turns out to be a getter, is that a tail call?

    AWB: also consider return x.y() where x turns out to be a proxy; then it's not just a simple call, it goes through the proxy handler.

    DH: More generally, if anything, syntactically not a call, turns out to be a call, do we include that as a tail call?

    DH: basically, is the spec mandating something that makes too much work for implementations. The definition of tail position is not in question; it's the semantics of what things in tail position become tail calls.

    LH: Function calls?

    AWB/DH: and method calls

    AWB: Calls in general

    WH: new?

    DH: no, new doesn't really work, because of the IsObject check afterward.

    AWB: OK, what about the proxy case.

    DH: I think it works fine; the semantics is just tail-calling the call trap.

    STH: I agree with Dave; we're just making a tail call to some arbitrary code. The code we're worried about is in the call-ing function, not in the MOP operation/trap handler.

    link Consensus/Resolution

    • Yes, the list is still correct.
    • function.arguments in non-strict makes tail call effectively impossible.

    (increasing insistence on break time)

    AWB: but let's do point 5.11.

    link 5.11 Disallow? let undefined; const undefined; class undefined {}; module undefined from "foo";

    No one thinks that disallowing this is a good idea.

    link Consensus/Resolution

    • Allow

    BE: Let's make it a keyword inside generators! Just kidding.

    link 4.2 Reconsider decision to make Typed Arrays non-extensible

    http://esdiscuss.org/topic/non-extensibility-of-typed-arrays

    AWB: Last f2f we decided to make typed arrays non extensible.

    ARB: Chrome makes them extensible but I'm in favor of making them non extensible.

    AWB: the most significant thing I saw is that if you create a subclass of a typed array, the reason for doing so might include adding some additional state, and so the only direct way to do that is by adding own properties to the instance of the subclass, and if typed array instances are created non-extensible, then subclasses couldn't do this.

    DD: You cannot add indexed properties to typed array. It would be surprising if you could add identifier name properties.

    DL: There are no objects in JavaScript that have this behavior right now.

    OH: Certain restrictions exist for numeric properties. There is no other object that doesn't allow you to add an expando.

    OH: Neutering is a performance issue as well. If we should make decision based on performance we should kill neutering.

    BE: the real issue is not performance (although the thread may have misdirected in that direction).

    AWB: we could go back to having numeric expandos, if you want...

    BE: No no no no, there was a performance counterargument there, unlike for named expandos.

    DL: (clarifying

    1
    2
    3
    4
    5
    6
    A = new ArrayType(uint8, 10);
    s = new StructType({a: A, ...});
    a = new A();
    a.foo = 5;
    s.a = a; // ??
    b = s.a

    DH: A "Typed Object" is effectively a pointer to a shared backing store. If those objects can carry addition state

    OH: If

    DL: With typed objects we can do

    1
    Uint8Array = new ArrayType(uint8);

    AWB: There may differences between TypedArray types

    ...

    DH: There's an example, wherein two views on the same backing store will not be === or ==, but there are implementation strategies that could make it possible.

    STH: It's easy to use getters where writing to one

    I'm behind....

    OH: Structs aren't expandable so therefore Typed Arrays shouldn't be expandable

    BE: Do we need extensible array types

    DL: All variable length array types to be extensible?

    AWB: We'd have to have a form of class, whose instance properties are defined by a Typed Object

    DH: Foresee a mechanism

    WH: Prefix properties?

    DH: Yes, if you have super type, its subtype is

    OH: Index properties are seen first in ForIn

    DH: Recalls discussion to allow index names to diverge, object model reform, etc.

    DH: most beginner references establish that all properties are strings

    RW: There is a lot of attention paid, in learning resources, to establish Array and Object as two different things, based on their property name "type". It's not until much later that realization is made that they are the not different, aside from special length property behaviour.

    ARB: not allowing them is more conservative for now. We can always relax them later.

    BE: that conservative argument seems strictly stronger than consistency arguments which always pick their preferred dimension of consistency.

    WH: I haven't seem any good arguments for allowing expandos in arrays but not structs.

    BE: the arguments are: it's useful; it works on arrays.

    AWB: as currently specified, you can create a subclass of Uint32Array.

    (Discussion of how buffer semantics work in subclasses. Decided it's not really relevant.)

    AWB: the subclass wants to add new properties

    DD: but it's OK to add prototype properties...

    AWB: yes, but, most people represent per-instance state with own properties. Yes, you could use a weak map, that's the universal answer, but that's not what people do currently in JavaScript.

    WH: composition over inheritance

    AWB: but then you don't get any inherited behavior

    AWB: Here's what I would advise. Use composition when you're composing base abstractions into a new abstraction. But if your new thing is a specialized kind of array, which may need some extra state, then that's not a composition type of situation, it's an inheritance type of situation.

    DH/AWB: we could not make @@create create a non-extensible object, instead we would make the typed array constructor call Object.preventExtensions on this.

    WH: extensibility breaks compositionality.

    AR: this is a strange argument; you serialize and deserialize the object, losing expandos seems fine.

    BE: serialization/deserialization is not the model.

    DD&DH: so if you don't call super, or wait until the end of the constructor to call super, the constructor can extend with per-instance properties

    OH: Have @@create produce an extensible object and have the constructor call Object.preventExtensions

    DH: Yes

    DH/AWB: What order does super get called?

    DH: Seems like a solution, but not one that everyone is fully in support of.

    DH: Points are not about speed of accessing properties of objects and more about layout of objects

    BE: Most users of typed arrays are not naive. We should not be promoting these overal normal arrays.

    AWB: Not even numeric?

    BE: Define numeric. Unless you actually know what you're doing, you shouldn't be using these and we shouldn't be promoting them for these.

    BE: Typed arrays are power tools.

    (Float-containing normal array is almost equal in perf to float64 typed array in JavaScriptCore.)

    OH: Agreed.

    OH: Transfering large amounts of data to a worker.

    ??: Better not have any expandos.

    BE: How do we make progress? Stand-off!

    DH, WH: to be clear, it would be sad if typed objects and typed arrays were inconsistent. so if we say typed arrays should allow expandos, then so should typed objects.

    DH: You can't put a variable-sized array in a struct.

    OH: Do we have a ToArrayIndexedProperty somewhere? Might have been internal to JavaScriptCore.

    AWB: The problem here is what array index meant when there was only the built-in array type doesn't fit with the typed array usage we have now.

    BE: I don't see it.

    Straw poll: 8 non-extensible, 8 mu (abstain), 1 (Ollie) extensible (I think it was moo, way more of a cow sound.) ( https://en.wikipedia.org/wiki/Mu_%28negative%29 )

    OH: We don't see any reason to remove extensibility, you can always make them non-extensible

    OH: The view of the JavaScriptCore team is that making them non-extensible removes what developers can do, whereas making them extensible does not have to cost and provides more freedom.

    OH: examples of behaviour equivalent to TypeArrays with expandos:

    1
    2
    3
    4
    array = [1,2,3]
    Object.defineProperty(array, "length", {writable:false})
    array[3] = 0;
    array[3] => undefined

    Various DOM lists allow non integer expandos, but don't allow integer expandos

    BE: The conservative argument is that if we're unsure we should make it non-extensible so we can make it extensible later.

    AR: You can interpret it both ways.

    DH: Non-extensible is conservative because you can change it later. It being extensible cannot.

    DH: Extensible is probably my preference at this point, but we can't leave it unspecified.

    BE: Due to duplicate bug of https://bugzilla.mozilla.org/show_bug.cgi?id=695438 -- namely https://bugzilla.mozilla.org/show_bug.cgi?id=828599 with its adding .stride to WebGL vertex typed arrays -- I am now in the extensible camp.

    Straw poll:

    Extensible: 10 Non-extensible: 6

    STH: (points about the mental model of operating on the backing store)

    DC: (points about the hazard of user code that abuses Array and creating a new hazard)

    link Consensus/Resolution

    • Consensus deferred.

    Ecma/TC39 Meeting – Jul 25 2013

    link July 25 Meeting Notes

    John Neumann (JN), Luke Hoban (LH), Rick Hudson (RH), Allen Wirfs-Brock (AWB), Yehuda Katz (YK), Anne van Kesteren (AVK), Jeff Morrison (JM), Sebastian Markbage (SM), Alex Russell (AR), Istvan Sebestyen (IS), Mark Miller (MM), Norbert Lindenberg (NL), Erik Arvidsson (EA), Waldemar Horwat (WH), Eric Ferraiuolo (EF), Matt Sweeney (MS), Doug Crockford (DC), Rick Waldron (RW), Rafael Weinstein (RWS), Dmitry Lomov (DL), Brendan Eich (BE), Ian Halliday (IH), Paul Leathers (PL),

    link 5.6 Can let/const/class/function* in non-strict code bind "eval" and "arguments"

    (Allen Wirfs-Brock)

    AWB: Currently, only var and function have any rules: non-strict is not

    YK: Reduce the refactoring hazards

    MM: What happens in arrows?

    EA: Formal params follow the strict rules (no duplicates, no param named arguments etc), but the bodies are not strict.

    RW/BE: Confirm

    AWB: If someone writes...

    1
    class eval {}

    And later moves this to a module...

    1
    2
    3
    module "foo" {
    class eval {}
    }

    This will blow up

    RW: But the same issue exists if:

    1
    function eval() {}

    And later moves this to a module...

    1
    2
    3
    module "foo" {
    function eval() {}
    }

    MM, WH: We need to make sure that whatever rule we decide on, is the simplest and easiest to remember

    BE: Recall the issue of micro-modes

    BE: Based on the decision make Arrows non-strict, the same reasoning applies to params

    EA: Strict formal parameters are an early error, strict function body have different runtime semantics so those are a refactorig hazard.

    AWB: The spec draft uses StrictFormalParameter for ArrowFunction and MethodDefinition.

    YK: Easy to get sanity, by opting into modules and classes

    RW: The January notes include rationale regarding the boundary of module and class, but not arrow, there is no note about arrow params being implicitly strict mode

    AWB: method names in sloppy mode (object literals) do not allow duplicat names.

    YK: Seems OK. ... Code may exist that has methods called "eval" or duplicate params named "_"

    MM:

    • eval & arguments
    • duplicate arrow & method params
    • duplicate non-data names in object literals

    LH: Agrees that these rules should be applied where code opts-in, not by layered addition of language features

    MM: Agrees with LH, in terms of the memory burden (developer end). This wont be clear to anyone but us.

    • If you're in non-strict, it should act non-strictly

    BE/RW: Yes

    Various: explored the consequences of allowing duplicate method parameters even in new-style parameter lists when in non-strict mode. That would be the simplest rule, but it would cause too many edge cases for duplicate parameter names in destructuring, rest parameters, etc., so we all agreed not to pursue that approach.

    AWB: The rule that we agreed on, in that past is that when new syntax forms are involved.

    • Depends on form of the parameter list

    MM: We need to lower the memory burden

    EA: This is going to make it greater

    MM: Defending exception for new forms of parameter list.

    AWB: More complex set of rules if you allow multiple names in simple parameter lists.

    • Duplicate param names not allowed, except for function definitions (things declared with function) with simple parameter lists

    MM: That's more complex

    link Consensus/Resolution

    General Rule

    • Non-strict code operates in consistently non-strict manner (This covers the let/const/function* cases)
    • Exception:
    • Only allow duplicate parameter names in simple parameter lists
    • Simple parameter lists are defined by those that do not include rest or defaults or destructuring.

    Consensus: The name of the ClassDeclaration/ClassExpression follows the strict rules for its name. So it cannot be named "eval" or "arguments". Just like for strict function names.

    link 5.9 Semantics and bounds of Number.isInteger and Number.MAX_INTEGER

    (Allen Wirfs-Brock, originally proposed by Doug Crockford?)

    AWB: What is the value of MAX_INTEGER

    WH; Whatever the largest finite double

    DC: But there are two

    WH: But I said "double"

    DC: That's ambiguous

    WH: No

    MM: WH is not constraining to the contiguous range.

    WH: If you want 2^53, call it something else

    MM: Likewise with isInteger ...Propose:

    1
    2
    Number.MAX_SAFE_INTEGER = 2^53-1
    Number.isSafeInteger => n > -(2^53)

    AWB:

    1
    2
    3
    2^53-1, 2^53, 2^53+2
    2^53+1 === 2^53

    After 2^53, you can add 2

    WH: Alternate proposal:

    1
    2
    Number.MAX_CONTIGUOUS_INTEGER = 2^53
    Number.isContiguousInteger = n => n >= -(2^53) && n <= (2^53);

    MM: Gives history of "isSafeInteger"

    Caja had a Nat test that tested that a number was a primitive integer within the range of continguously representable non-negative integers. I used Nat in a small piece of security critical code, to ensure I was doing accurate integer addition and subtraction. Because I was using this definition, Nat admitted 2^53. This introduced a security hole, which escaped notice in a highly examined piece of code which has been published several times and has been the subject of several exercises to do machine checked proofs of some security properties. Despite all this attention and examination, no one caught the vulnerability caused by admitting 2^53. By excluding 2^53, we have the nice invariant that if

    isSafeInteger(a) isSafeInteger(b) isSafeInteger(a+b)

    are all true, then (a+b) is an accurate sum of a and b.

    WH: OK

    DC: Want to call this Integer

    WH: Can't call this integer. 2^54 is an integer, just not inside of the contiguous range. Like the concept, but not ok to name it "isInteger", as 2^100 also happens to be an integer.

    BE: Agrees with Mark's "Safe"

    YK: Easy to explain that Integers outside of the range

    AWB: Current spec checks for mathematical integer

    ...toInteger makes use of internal ToInteger

    MM: Makes sure there is no fractional part?

    WH: Yes

    WH: If we have toInteger, then we need isInteger or isSafeInteger

    AWB:

    isInteger isSafeInteger

    MM:

    MAX_SAFE_INTEGER = (2^53)-1

    isInteger

    • Infinity => false
    • NaN => false
    • value !== truncated value => false
    • -0 => true

    isSafeInteger

    • -0 => true

    toInteger

    • Does not guarantee a safe integer

    ToInteger

    • Does not guarantee a safe integer

    WH: The only place where ToInteger is divergent is +/-Infinity

    WH: We already have Math.trunc, which does the same thing as ToInteger would. Don't need Number.toInteger.

    link 5.8 Number.prototype.clz or Math.clz?

    WH/AWB: Is an instance operation.

    WH: If it's on Math.clz(), it will return the wrong answer if we have different value objects in the future

    WH: In particular, this specifies that the value is 32 bits wide, which makes it inappropriate as something in Math. Consider what happens if we add a uint64 type. Then we'd want Uint64.clz to count starting from the 64th bit instead of from the 32nd bit. We can do that if it's Uint64.clz. We can't (without creating weirdness) if we use Math.clz for both.

    AWB: Then it belongs on the instance side.

    Any objections?

    link Consensus/Resolution

    • Number.prototype.clz

    AWB: What about the following:

    1
    2
    3
    4
    5
    Number.isInteger
    Number.isSafeInteger
    Number.isFinite
    Number.isNaN
    Number.toInteger

    link Consensus/Resolution

    Remove Number.toInteger (already exists as Math.trunc)

    (Reference: https://github.com/rwldrn/tc39-notes/blob/42cf4dd15b0760d87b35714fa2e417b589d76bdc/es6/2013-01/jan-29.md#conclusionresolution-1)

    link 5.13 Which existing built-in properties that are read-only/non-configurable do we want to make read-only/configurable?

    (Allen Wirfs-Brock)

    AWB: Previously, we've discussed setting data properties as {writable: false, configurable: true}

    One of these built in properties that discussed is the length property of function

    MM: Points about function properties, eg. the prototype property

    EA: Classes are a constructor and the prototype, can't use function for the argument to how classes behave

    MM: Don't think this is a question that should be addressed for ES6, it's too late.

    AWB: Not too late, we've discussed this

    AWB: The "prototype" property of the class constructor object is configurable, non-writable

    AWB: {writable: false, configurable: true} allows enough control

    EA: We also discussed this for methods

    YK: This is part of the refactoring hazard I mentioned earlier.

    MM: Don't want to consider a change of that magnitude this late in the game

    AWB: All of the existing properties from ES5, should we address the whole list?

    When define a class:

    1
    (Foo.prototype) -C-> <-P- (Foo)

    AWB: Foo.prototype.constructor property {writable: false, configurable: true}?

    MM: This hazard:

    1
    2
    3
    function Bar() {}
    Bar.prototype = Object.create(Foo.prototype);
    Bar.prototype.constructor = Bar;

    Code that exists like this, once Foo gets refactored to a class, if constructor is non-writable, the above breaks.

    AWB: @@create

    1
    Array[@@create]

    Recap:

    1
    @@create sets the prototype property of the new instance, but referencing the prototype property of the constructor itself.

    MM: With regard to function.name and function.length and making them "tamper resistant", but mucking around with the built-in prototype chain has unknown implications and it could be addressed in ES7.

    This change allows the actual Array.prototype to be changed.

    WH: When does @@create get called?

    AWB: when new is used.

    link Consensus/Resolution

    {writable: false, configurable: true}?

    • length property of functions: yes
    • prototype property of functions: no
    • new properties, ie. @@create: yes

    link TC39 + W3C

    Discussion joint meeting with W3C at TPAC, Nov 11-15, in Shenzhen, China.

    link 5.1 Symbol primitive value or object? One more time.

    (Allen Wirfs-Brock)

    EA: There is discontent that there isn't private state. Symbols don't cover this. Unique Strings solve the uniqueness case

    Proposal: Postpone Symbols to ES7

    BE: The reason we seperated private and unique was exposure in Reflection modules

    YK: You don't need unique symbols when you can just expose private symbols.

    MM: The @@iterator symbol must be transitively immutable

    In the relationships case, the WeakMap

    BE: There are classes that outlive any instances

    Why can't we just have (private) Symbols

    MM: Two subsystems that aren't supposed to be able to communicate with each other should be able to share anything that is transitively immutable.

    BE: Can we unwind the split between private and unique?

    YK: (fill this in)

    AWB: We deferred private symbols

    Private state should not be mixed up with Private Symbols

    Symbols are guaranteed uniqueness, wrong way to go for private state.

    BE: We aren't going to resolve this now, need to take it to es-discuss

    AWB: For the spec, how do I spec Symbols?

    Strings won't guarantee

    MM/BE: (quick discussion about uuid strings)

    WH: What you're saying is that we need a gensym?

    AWB: Essentially, what we need is a gensym

    BE: Andreas implemented Symbol

    AWB: Dug in against wrapper objects for Symbols

    1. (did someone catch this one)?

    2. Unique objects, unforgeable, can't set or access properties. Are actually objects.

    BE: ARB says that v8 internal architecture makes it hard to add new

    link Consensus/Resolution

    • Leave the spec as it is now
    • Postpone until next f2f

    link 5.12 Should we remove [[Construct]] from the MOP and Proxy handler API?

    (Allen Wirfs-Brock)

    AWB: recapping @@create changes...

    1
    new C(...args);

    Essentially breaks down to:

    1
    2
    3
    4
    5
    [[Construct]] =>
    let obj = C[@@create]();
    return C.[[Call]](obj, ...args);

    YK: This means that [[Construct]] will always call [[Call]].

    AWB: The way the built-ins work, override @@create, eg. Date, creates a private data slot for the time

    1
    2
    3
    4
    5
    6
    7
    8
    9
    function String(value) {
    if (!(this has an unitialized instance)) {
    return "" + value;
    }
    this.value = "" + value
    }
    String[@@create] => { value: uninitialized instance }

    WH: Disapproves having String when called as a function do different things based on this. This breaks the invariant that String(x) always returns a primitive string.

    WH, MM: Also concerned about adding a new uninitialized String instance type as a specing helper but which becomes reified and user-visible. Someone could call String's @@create directly, obtain one of these values, and cause mayhem. Too much surface area of potential problems here, and this is unnecessary complexity.

    YK: Objects to removal [[Construct]]

    AWB: A Proxy trap?

    BE/YK: Keep

    link Consensus/Resolution

    • [[Construct]] remains.

    link Anti-Pattern to call a constructor without new

    (Allen Wirfs-Brock)

    AWB: In ES6, with class, it will be an anti-pattern... Don't call without "new"

    BE: This is style/convention

    Promote the use of new with classes

    MM: Might want a constructor to refuse to initialize an instance of that class if the call object is not the

    EA: Three browsers have implemented Map, Set, WeakMap, WeakSet and all are allowed to be called without new, which breaks subclassing

    General agreement that this is bad.

    AWB/MM: Function.prototype.@@construct

    MM: If it implies runtime overhead that is not easily optimized, that would be a perfectly valid argument against. Does it?

    In general, wherever we can replace a [[Foo]] internal property with an @@foo unique symbol named property, without penalty, we should. Especially if proxies would otherwise need a special trap for [[Foo]].

    YK: Need to be careful when we change the MOP since other specs refers to the mop methods.

    link Consensus/Resolution

    • Giving up on the convenience of calling constructors without new, with any expectation
    • Throw when Map, Set, WeakMap, WeakSet are called without new

    link JSON

    Any objections to sending the JSON draft 7 version to the general assembly

    DC: Made changes. Specifiy code point. Removed summary of grammar. It was redundant. As well as the whitespace issue.

    JN: Send proposal to ???. If you don't reply to this thread then it is an implicit approval.

    link 6.2 Interfacing ECMAScript & HTML/DOM Event Loops

    (Rafael Weinstein)

    RWS: (A single slide) How does ES inegrate with the rest of the specified environment with regard to scheduling tasks.

    • Enqueue A Task

    • The environment must run the task at some point in the future

    • The task must be run after all previous enqueued tasks

    • The task must be run on an empty stack.

    • Enqueue A Microtask

    • The environment must run the microtask at some point in the future

    • The microtask must be run before all previously enqueued tasks

    • The microtask must be run after all previously enqueued microtasks

    • The microtask must be run on an empty stack

    WH: Note that this defines a total order.

    MM: We need to decide how tasks or microtasks that originate from EcmaScript behave

    MM: No nested event loop?

    General agreement that the ES spec not support nested event loops. If the browser specs require them, i.e., for running JS code while a modal dialog is blocked, then the browser specs would need to state that this is an intended violation of the ES event loop model.

    YK: Timing is another issue

    MM: Promise scheduling, fifo

    Discussion re: the host vs.

    w3c bug...

    link Consensus/Resolution

    • Needs more offline discussion

    link Value Objects Update

    (Brendan Eich) ValueObjects.pdf

    BE:

    Use Cases:

    • Symbol
    • int64, uint64 (53 bits not enough)
    • Int32x4, Int32x8 (SIMD)
    • float32
    • Float32x4, Float32x8 (SIMD)
    • gignum
    • decimal
    • rational
    • complex

    Overloadable Operators

    • | ^ &
    • ==
    • < <=
    • << >> >>>
      • / %
    • ~ boolean-test unary- unary+

    Preserving Boolean Algebra

    • != and ! are not overloadable to preserve identities including
    • X ? A : B <=> !X ? B : A

    ... Too fast, request slides.

    http://www.slideshare.net/BrendanEich/value-objects

    "complex and rational cannot be composed to make ratplex"

    AVK: Multiple globals will cause issues.

    BE: That is not an issue with this proposal. It is an issue with multiple globals. ... we need literal syntax for readability. ... no solution for user defined literal suffixes.

    BE: Some have requested mutable value objects in order to represent small tuples and be able to do updates on them in a loop.

    WH: This no more requires value objects to be mutable than incrementing a loop counter requires integers to be mutable. It's the variable that holds the integer 3 that's mutable and an be changed to refer to a different integer; you can't change the integer 3 itself to be 5. If the value is a small tuple and the source and destination are the same, it's easy enough for a compiler to transform a functional-style tuple update into imperative code if it likes.

    WH, MM: Don't want mutable number literals/objects. No new Float32x4(a, b, c, d). This would break === (which would then need to do identity matching instead of same-value matching).

    1
    2
    3
    4
    5
    6
    7
    typeof x == typeof y && x == y
    <=>
    x === y
    0m === 0
    0L == 0
    0m == 0L

    BE: typeof become advisory

    AWB: You can register typeof result once during registration. That way we can enforce that it does not changes.

    link Consensus/Resolution

    • NaN requires separately overloadable <= and < [Slide 5]
    • Intersection means function identity matters, so multimethods can break cross-realm [Slide 9]
    • Mark objects that I or i as bignum suffix conflicts with complex [Slide 11].
    • Always throw on new -- value objects are never mutable and should not appear to be so, even if aggregate [Slide 12]
    • Need to work through any side channel hazard of the typeof registry [Slide 13] and the multimethod dispatch "registry"

    link 6.5 Parallel JavaScript (River Trail)

    (Rick Hudson) ...need slides

    RH: We have to go parallel to keep up with other langauages

    YK: Don't want to fallback into sequential

    Various: Debate about what happens when the parallel computations have side effects that introduce dependencies between them. Options are either devolving into sequential computation or throwing an exception.

    RH: The code behaves the same way as sequential code but goes faster if there are no side effects.

    WH: What happens if there are no side effects but some of the computations throw exceptions? Which exception do you get?

    RH: Any of them. There are also other implementation options here.

    WH: If it's any of them, then this is not like sequential code.

    WH: What exactly is a side effect? How would a programmer know that some ECMAScript construct has an internal side effect?

    WH: In particular, suppose that I want to use a parallel loop to fill a big matrix with random numbers. Is calling a random number generator considered to be a side effect or not? If the answer is yes (it is a side effect), then how would one fill a big matrix with random numbers in parallel, as that is something that one would reasonably want to be able to do?

    link Consensus/Resolution

    • Throw instead of falling back to sequential.
    • Focus on concurrency/scheduling in ES7. Make sure it fits with other concurrency constructs (promises/event queues)
    • Discussion/Acceptance in ES7 process.

    link RWS Proposal For Specification Process (for ES7 process)

    link Consensus/Resolution

    • Go forth

    link 7 Internationalization

    NL: Implementations of ECMAScript Internationalization API: - Microsoft has shipped it in Internet Explorer 11 beta - Opera has shipped it in Opera 15 (based on Chromium)

    link Future Meetings

    Sept 17-19, Boston Nov 19-21, San Jose