July 28 2015 Meeting Notes
(Slides are at tc39/tc39-notes/tree/master/es7/2015-07 )
July 29 2015 Meeting Notes
Allen Wirfs-Brock (AWB), Sebastian Markbage (SM), Jafar Husain (JH), Eric Farriauolo (EF), Caridy Patino (CP), Waldemar Horwat (WH), Istvan Sebastian (IS), Mark Miller (MM), Adam Klein (AK), Michael Ficarra (MF), Peter Jensen (PJ), Domenic Denicola (DD), Jordan Harband (JHD), Jonathan Turner (JT), Paul Leathers (PL), Chip Morningstar (CM), Vladimir Matveev (VM), Ron Buckton (MS), Brian Terlson (BT), Alan Schmitt (AS), Ben Newman (BN), Mohamed Hegazy (MH), Abhijith Chatra (AC), Tom Care (TC), John Neumann (JN), Dave Herman (DH), Brendan Eich (BE), Daniel Ehrenberg (DE), Dan Gohman (DG), Andreas Rossberg (ARB), Rick Waldron (RW), Mike Pennisi (MP), Akrosh Gandhi (AG), Jonathan Sampson (JS)
6.11 The scope of "use strict" with respect to destructuring in
parameter lists
(Andreas Rossberg, on phone)
ARB: Strictness Scoping
Issues:
- VMs need to do parsing & static checks in single pass
- w/o building an AST (lazy compilation)
- Backtracking is not an option (at least not for V8)
DH: clarify backtracking (2 possibilities?)
ARB: rewinding token stream
ARB: easy in ES5 because only additional check is duplicate parameter names
"use sloppy";
function f(x, x) { "use strict"; }
Difficult in ES6, b/c default parameters
"use sloppy";
function f(g = (o) => {with (o) {}}) { "use strict"; }
ARB: also cannot determine scope due to interactions between Annex B and strict mode:
"use sloppy";
function f(g = function(h) {
{ function h() {} } return h;
}) {
"use strict";
}
WH: The issue in this example is hoisting and variable binding, which is more than just error checking. Function h here is nested inside a local block, which means that the 'h' in the return statement refers to different bindings in strict vs. non-strict mode. But you don't know that strict mode is in effect until encountering the 'use strict' later!
DH: Don't know yet whether this is an error until later. Previous examples: Store a "dirty bit". This example: have to have a data structure that will hoist in 1 of 2 ways if it turns out to be strict mode. Implementable without backtracking.
WH: Note that a single state bit is insufficient. You can have these things nested arbitrarily deep, leading to a potential exponential explosion of states.
ARB:
Much More Difficult in ES6
- The directive can affect arbitrary code
- Nested arbitrarily deep
- Would need ot defer any sort of mode-specific decisions in the parser for code that occurs in parameters
- But with arrow functions, we do not even know (in time) that we are in a parameter list
"use sloppy";
let f = (g = () => { /* Are we a parameter? Do we have to defer? */ with
(o) {} }) => { "use strict"; }
ARB:
BE: The arrows are parsed with a cover grammar
- When initially implementing strict mode, SpiderMonkey had to implement token stream backtracking to account for the function body "use strict" prologue affecting to the left
ARB:
Categories of mode specific logic
-
Mode-specifc errors: (eg. with, delete, for-in, octals, let, variable name validity, parameter conflicts) -> Easy to defer, at least in principle, but may have measurable cost
-
Special handling of eval (scoping, variable modes) -> Not an issue
-
Actual divergence in parsing/scoping (Annex B function scoping, yield?) -> Affect downstream decisions, transitively defer
DH: yield doesn't have contextual differences in strict mode, in generator functions
AWB: restricted in strict mode (non-generator) functions
- other differences?
DH: this-binding
YK: to be clear, these disadvantages only apply to sloppy mode programs; modules and strict mode programs are not affected
ARB: 3 modes, effectively:
- sloppy
- strict
- "don't know"
DH: (discussing potential for performance regression)
- Any parenthesis expression could potentially end up in slow mode
ARB: Agree
AWB: Don't see this as a problem for JITs
BE: (asks implementors what they're doing to solve)
- SpiderMonkey uses token stream rewinding and it covers all the cases
PL: We haven't gotten this far
ARB: This has been brought up with the team before, and token stream rewinding has been off the table
- Don't want to do token stream rewinding in V8, various issues (e.g. with Blink interaction?)
BE: If it can be done and satisfies performance constraints, then engines should consider
ARB: Compiling functions separately, ie. if function in parameters, compile sep. More than just rewind, would have to record all the functions, may be done with them, may not be done with them
MF: Can we see a proposal/solution?
ARB: Make it an error to have a "use strict" directive in a function with a non-simple parameter list.
YK: Should implement ES6 as written while this is resolved.
- Don't block implementing default parameters on this
- Just a suggestion
BE: "more of a guideline than rule"
AWB: You could make the restriction more specific: only disallow functions that declare "use strict" and contain a function in their formals list
ARB: Could be that only error when "use strict" inside function would change the mode, as the outer mode might already be strict
YK: refactoring hazard.
BE: Jason Orendorff says "works for me"
AC: don't like this suggestion, I don't want to impose an error because an implementor couldn't make it work
Discussion, re: hardship of implementation
YK: Don't like that end developers have to know why this won't work, b/c implementing hard.
BE: implementors are considered second to developers
AWB: previously, sloppy mode was restricted to simple parameter lists.
BE: No micro modes: no runtime semantic differences due to
AC: Chakra implements with rewinding
YK: objection: semantically this is the wrong thing
DD: but we're moving to all-strict world, so making the mixed mode cases more painful might be ok
DH: This is such an edge case that I don't tihnk there is an adoption risk.
- "use strict" retroactively providing subtle differences in the parameter list is a gotcha
- preventing diversions in the semantics to close window of confusion
BE: Suggestion fixes the right-to-left violation
DH: Could enumerate all those cases and make errors, but much harder.
- Fixes, but means new rule
YK: Poisioning function () { "use strict" }
BE: use top level "use strict"
YK: Not realistic
BE: Andreas reduced list to parameter lists that contain:
- functions
- arrows
- future "do" expressions
Discussion re: "use strict" expectations
YK: Prefer the stricter rule
DH: appear to have consensus on Andreas' solution
AWB: What exactly do we mean by "a function with a 'use strict'; prologue? Are we only talking about "strict transitions" (i.e. functions that declare "use strict" that are in non-strict contexts) or do we mean "use strict" in any functions.
MM: Functions that have a "use strict" know that they are strict, whether they are "pasted" or typed
- Taking the strict function out of strict context may cause errors as a result of code execution that previously expected strict context, which is a refactoring hazard
MP: Another (less difficult/serious) case where strict-function-rewinding is relevant is in the case of named function expressions. e.g.
(function static() { "use strict"; });
Ref: ecmascript#4243
Discussing implemention strategies
- checking for duplicates
- eval, arguments
- yield, let
BE/AWB: existing semantics imply some right-to-left checking
BE: Non-simple is:
- default
- destructuring
- rest
(Anything that is not a list of identifiers)
YK: Need to acknowledge that we'll need to tell people to not "use strict" in functions, if they use non-simple parameters.
Acknowledged.
The solution is just use top level "use strict"
DH: We'll fail to explain this at the level of enumerating ES6 features they can or can't use in this case. The outcome is something like "just use top-level strict, or iife strict"
- Would like to revisit
YK: Not just this edge case: ES6 and strict mode has created this weird window.
AK: Functions in the parameter list might become strict if the function is "use strict"
DH: this
behaviour changes
YK: Ultimately breaking "use strict" for function
AWB: Any function whose mode (lost track)
Discussion about ES6 feature adoption.
RW: disagreed with error when "use strict" occurs locally, but outer mode is already strict (ie. no mode change)
Discussion about developer expectation.
AWB: there is another alternative spec function that is more restrictive: ContainsExpression
RW demures ("You might say I am not willing to die on this hill.")
Conclusion/Resolution
- Make it an error to have a "use strict" directive in a function with a non-simple parameter list.
- Early error
- No matter what mode you were already in
- When people want to use local "use strict", doing it b/c they want to
know that this is always strict, no matter where it ends up.
- Applies to all kinds of function/generator syntax
- IsSimpleParameterList www.ecma-international.org/ecma-262/6.0/#sec-function-definitions-static-semantics-issimpleparameterlist
6.9 Reconsidering the Number.prototype-as-an-ordinary-object change
(Daniel Ehrenberg)
DE: This change breaks the web (specifically: mootools calls
Number.prototype.valueOf(Number.prototype)
)
esdiscuss.org/topic/number-prototype-not-being-an-instance-breaks-the-web-too, mootools/mootools-core#2711
Solution: roll back the change.
BE: Number, String, Boolean should be
MM: To be clear: Date.prototype will be an object, not Date; RegExp.protototype will be an object, not RegExp. Every built-in constructor introduced after ES5 will have a plain object prototype.
MM: Prefer we do Number, Boolean, String together
Conclusion/Resolution
- Boolean.prototype, Number.prototype, String.prototype rolled back
- File a spec bug?
6.12 Spec defacto String.prototype.trimLeft/trimRight
(Sebastian Markbage)
sebmarkbage/ecmascript-string-left-right-trim
SM: Already shipping in all major engines. Controversy: what to call it?
JHD: in JavaScript, left-to-rightness of strings is a rendering artifact. The conceptual "first" character of any string, whether LTR or RTL, is index 0, and the "last" is index length minus 1. Thus, in JS, left/start/index zero are the same, and right/end/index length minus one are the same.
DH: These are extremely common in programming languages
Discussing semantics of "left", "right" and "start", "end"
DH: There is precedence for JavaScript interpreting the word "right" to
mean "the end of a sequence", from ES5: Array.prototype.reduceRight
Conclusion/Resolution
- Approved for Stage 1?
REVISIT: 6.11 The scope of "use strict" with respect to destructuring in
parameter lists
DH: The only thing that "use strict" can cause (in ES5) is an error (to the left)
- Our resolution was to say, "the use strict prologue in functions is now defunct"
- An alternative, w/ better outcome: revise "use strict" to no longer affect anything to the left.
- A back-compat change, because it only allows things that were previously disallowed.
- no semantic difference
AWB: There are implementation semantics, w/r to parameters
- extra scope contour for eval context
- duplicate parameters
WH: How does it affect hoisting checks?
AWB: Hoisting rules in annex b don't apply if there is decl of same name (need to double check)
MM: How did we resolve names introduced in the function head vs names introduced in the function body, w/r let/const
AWB: disallowed
Discussion, re: strict in blocks?
AWB: need to check this against the existing function declaration instantiation, re: strict/non-strict checks
STH: Expressions in parameter list are not in strict mode.
- Enter strict mode due to prologue at beginning of function, does put parameter list expressions in strict mode
YK: Bigger picture: ES5 introduced the concept of a strict function.
- The proposal before is honest about admitting that's not a thing
- Sam's proposal ignores that and introduce's a new thing
Discussion, re: expectations of strict mode in functions
AWB: parameter with an initializer that uses this
- Assuming that's called with nothing in that position, what is
this
? - If strict,
this
is undefined - If sloppy,
this
is global object
"use sloppy";
function f(foo = this) {
"use strict";
return foo;
}
f();
// what is the value of this expression? the global object? or `undefined`?
// w/r to Sam's proposal (eliminating right-to-left strict-ness effect)
YK:
With Sam's proposa, this would return [undefined, Global]
, despite
expecting [undefined, undefined]
(function(foo = this) {
"use strict";
return [this, foo];
})();
DH: In ES5, there was a fundamental confusion about "use strict" in
functions. This was excacerbated by es6. In the fullness of time, TC39 is
saying, the directive prologue should be used:
- Global "use strict" (being careful of script concatenation)
- Top-level IIFE "use strict"
- module code
MM: We should be explicit w/r to "top level strict mode", in that we
actually mean "top level iife with strict mode"—to avoid the concatenation
problem.
Advice: "Just use modules".
#### Conclusion/Resolution
- The previous consensus remains
## REVISIT: 6.7 new & GeneratorFunction
AWB: (answers to questions from yesterday)
- Generator functions are new-able
- Generator methods are new-able
- Implicit body
```js
function * g() { this.foo }
x = {
*f() { this.foo }
};
new f(); // ok
new x.f(); // ok
Relevant SpiderMonkey bug: bugzilla.mozilla.org/show_bug.cgi?id=1166950
DH: Bare generator function call behaviour is correct?
AWB: Confirm
Updated:
S | I | Code |
---|---|---|
X | X | { *foo() {} } (no [[construct]]) |
X | X | function * () {} (no [[construct]]) |
? | ? | function * () { this } is exactly like function() { this } |
AWB: Concern about removing new:
- Implemented to allow it without throwing
- No TDZ on
this
Acceptable risk?
BT: Implementors on both V8 and SpiderMonkey have shown interest in making generator not newable
Conclusion/Resolution
- Spec change: generator functions and methods do not have a [[construct]]
trap, so
new
throws
Process Document discussion (to settle things once and for all)
(Domenic Denicola)
DD: (Showing tc39.github.io/process-document)
Reviewed:
AWB: w/r to reviewers, committee should assign reviewers.
DD/RW: reviewers attached at Stage 1. Stage 2 entrance requires review
RW: Propose: At Stage 0, reviewers get "attached", but non-binding. (basically, it's a "champion group")
... Next thing...
What is an "implementation"?
Discussion re: Stage 4
- Important to get feedback from engaged implementors
RW: Concerns about flag/no flag
DD: Must be unflagged
RW: Disagree, will result in stonewalling from implementors
DH: Transpilers should count
Discussion, re: experiences had with other new features.
"Significant in-the-field experience with shipping implementations, such as that provided by independent VMs"
Stage 3: "Will require feedback from implementations and users"
Conclusion/Resolution
- need links to Domenic's commits
6.8 SIMD.js: Start the process to move towards Stage 3
(Dan Gohman, John Mccutchan, Peter Jensen, Daniel Ehrenberg)
DE: (introducing topic)
-
Boolean vectors Previously, the result of SIMD.Float32x4.greaterThan was a SIMD.Int32x4 vector, with -1/0 for true/false Now, new boolean vector types, e.g. SIMD.Bool32x4, represent boolean results and values Used for select and logic operations More efficiently implementable on some architectures Not simply Boolx4 because the registers in implementations may be represented differently based on width.
-
Unsigned operations
Unsigned comparisons Unsigned saturating add/sub Unsigned extractLane No changes needed for constructor, replaceLane because coercion will wrap unsigned values to the appropriate signed value No separate unsigned type
- Postponed features
Float64x2--we couldn’t find an important use case with improved performance Int64x2--Not needed due to boolean vectors, and really not needed because Float64x2 is out selectBits--minimal utility due to select, and efficiently implementable in terms of other boolean operations
- sumOfAbsoluteDifferences replacement
widenedAbsoluteDifference, unsignedHorizontalSum, absoluteDifference Seeking implementation feedback: applications and benchmarks Replaces sumOfAbsoluteDifferences (slow on ARM)
- Other spec changes
Homoiconic toString()
SIMD.Float32x4(1, 2, 3, 4).toString()
=> "SIMD.Float32x4(1, 2, 3, 4)"
Shift operations max out at 0/-1, rather than wrapping around Ops like reciprocalApproximation are loosely specified, like Math.sin Removed operations on DataView--TypedArray ops suffice Operations on subnormals may flush to 0, unlike ES scalars Various minor spec bug fixes
AWB: w/r toString. The approach shown is a new precedent
DD: Similar to Symbol
AWB: Will this be the new way
BE: value types with literal form should convert, but this isn't value types. I like it.
AWB: Should other new things have this toString() output? Map & Set?
(moving on)
- Strong type checks on lanes
Lanes are required to be Int32s and not implicitly coerced
(See 5.1.2, littledan.github.io/simd.html )
AWB: for WebIDL, we advised to use normal ES coercions
DE: Considered specified getX, getY, etc.
DH: I don't know if it's that important to coerce or check.
BE: Doesn't want this to be an enumerated type. Symbols?
AWB: The advantage is that Symbol is not coercible and you only accept those that you've defined.
DE: if we had a Symbol API, we'd still want an extract lane API
STH: numbers are the right thing here
AWB: ToNumber, because that's what ES does
- Actually ToInteger
- ToLength
WH: Note that the proposal is a bit inconsistent in validating numeric inputs. For example, shifts use ToUint32 for the shift count, which turns -1 into a huge shift amount. ECMAScript's built-in shifts treat the shift amount mod 32, while the proposed ones treat it mod 2^32.
DE:
- load and store operating on any TypedArrays
load and store take TypedArrays as arguments and permit array element type mismatch with SIMD type
WH: Reading spec, cannot load and store booleans. Looks intentional.
DE: Fails on booleans, intentionally.
- Intentionally abstract data type
- Want concrete data type, call select
WH: Fix other places in the spec for booleans, such as the statement that bitwise cast can cast any SIMD type into another SIMD type.
AWB: (requests justification for extracting values of a different type than the type of the Typed Array)
DE: DataView doesn't really work, in an asm context. Operations on DataView accept endianness where this has to use native endianness to be efficient
AWB: if int8 array, extracting floar 64, does it
DE: No, it is element-aligned. The hardware supports this.
DG: (phone) confirms hardware support
AWB: If you're talking about a float32array and you're extracting int16's, that just seems like a type error.
DE: Better?
DH: Go back and change array buffer, can't do that
- ArrayBuffer was defined as opaque
- Everyone wants to change rthat now
- No real world constraint
DE: how is opacity enforced?
(no answer yet)
WH: Some ArrayBuffers are indeed opaque. Restricted exposure for security reason
DH: TypedArray views on ArrayBuffer, detached
- Allow operation on ArrayBuffer
- We'll have to break the invariant
BE/DH: what they're doing will work
WH: Not a pointless invariant. Move on.
(moved on)
Questions for Committee
- Should wrapper constructors be explicitly [[Construct]]-able, like Number, or not, like Symbol?
BE: have to call with new to get the object
AWB: Symbol is just odd because concern that new Symbol()
would be used
to get a generative object.
DD: Necessary to impose a rule for creating a Symbol
- No literal form? No wrapper
DE: if you call construct, if NewTarget undefined, construct wrapper
AWB: Minimize new patterns. Overloading constructor is not new.
AK: Why this route instead of Symbol route?
DE: Symbol is special throwing on new? But maybe Symbol is the new way
DD: If no literal, then no new
. If a literal is added later, then re-open
new
BE: (explains wrapper history, aggree with DD)
(moving on)
Spec Language Innovation Acceptable?
- Rest parameters
- SIMD as a spec meta-variable
AWB: There was use of rest early in ES6, but taken out
BE: parameters that were optional
AWB: implies JS level parameter list
DE: no
Discussion, re: spec mechanisms
(moving on)
RW: Recommend moving this to a separate spec, similar to Intl (Ecma-402). (Note that this was considered ideal by the champions as well, despite the opposition from other members).
DH: disagrees
WH: Also disagrees with separate spec. This defines primitives tightly bound into the core of ES, with serious interactions and precedence-setting with other ES work such as value types.
DE: Issues surrounding value type definitions, but don't want to to wait for value types. Don't want to be blocked and separate spec ensures that
(moving on to implementation status)
Firefox Implementation Status
In Firefox nightly:
- Float32x4 and Int32x4 entirely implemented and optimized in JavaScript (regular and asm.js) on x86 and x64.
- Missing boolean vectors
- Other SIMD types (Int16x8, Int8x16, Float64x2) partially implemented in the interpreter only (ergo not optimized). The newer APIs (SAD) haven't been implemented yet.
- All SIMD types are implemented as value objects, at the moment.
Microsoft Edge Implementation Status
- Majority of SIMD.. APIS supported.
- Some of the new APIS need to be implemented such as ExtractLane and ReplaceLane, and unsigned operations
- Asm.js optimization is complete (minus new api support).
- Non-asm.js optimization we plan to start soon.
V8 Implementation Status
- Intel object implementation will not be used for V8 and work has started to implement value types from scratch. Intel code generation may be rewritten to the new model.
- Bill Budge has added a Float32x4 type with correct value semantics and basic operations, without acceleration, behind a flag.
Specification Status
- SIMD.js Specification v0.7.2
- Updated polyfill and tests validate all operations, basic value semantics
- SIMD.js is ready for reviewers and and editor comments/signoff
- Hope to move to Stage 3 in the September meeting
Requesting reviewers
WH: purpose of spec, disagreement whether to support only use cases experienced or useful with a more ecmascripty orthogonal feel. For example, the spec currently can load int8, uint8, int16, uint16, int32, uint32, but it can only extract the first five of them (can't extract uint32 even though can extract int32 or uint16). Min and max work on floats but not on integers, even though there is no hardware obstacle to do so and even though there are much more complex intrinsics defined such as unsignedAbsoluteDifference.
DE: support unsigned operations on int16 and int8
BE: waldemar wants max on integers that can
DH: SIMD building clear layer to hardware
WH: want consistency:
- integer max
- uint32
- for usability, uint8 SIMD pixel values printing liked TypedArrays as 255,255,0 instead of -1,-1,0.
WH: Diverged from TypedArray,
AWB: TypedArray both have int32 and uint32, JS programmer expects that
BE: argument to be consistent
DE: TypedArray is the model going forward, with the exception of Uint8ClampedArray
AWB/BE: Yes
WH: treatment of denorms non-deterministic
DE:
- operation and flush to 0
- operation only
WH: Does the hardware flush both inputs and outputs to 0, or is there some major hardware that flashes only inputs or only outputs to zero? (an arithmetic operation might take denorms as inputs, or it could produce a denorm output even though all inputs are norms)
DE: Both inputs and outputs
WH: [later in the discussion] Intel has FTZ and DAZ bits which control these separately, so they can be independent.
(Difference between Arm and Intel)
DG: Arm 64, arm v8 corrects this
MM: this non-determinism is actually just difference between platform
WH: The SIMD spec doesn't state that. It could differ operation-by-operation.
DE: The spec can't state that.
WH: Really? Why?
Discussion re: nan encoding
DE: www.ecma-international.org/ecma-262/6.0/#sec-setvalueinbuffer (step 9.a)
AWB: (explaining why spec says this)
DH: we should change the def of SameValueZero to say that two different bit patterns for a NaN are not equivalent
DE: create a data property and set value to one bit pattern, non-writable, non-configurable, call Object.defineProperty with a different NaN, then do [[Get]] and you'll receive old bit pattern
DH: No mutation, but incorrectly states that change was successful
DE: spec says a platform will have one endianess or the other; this can be applied to denorms. Spec dependent.
WH: What do relational operations (.equal, .lessThan, etc.) do when they see a denorm? treat as zero?
DG: treat as zero
WH: So then what will === do? Do they equate all distinct denorms to zero (which would be really weird as ES behavior)? Are you going for the fast implementation of === or the precise implementation?
DG: === does not equate denorms to zero, even on platforms that flush denorms. It can be slower than .equal.
ieeexplore.ieee.org/stamp/stamp.jsp?tp=&arnumber=4610935
DE: One outstanding question was whether this work should be done in a separate specification.
RW: Yes, I had suggested that. But you said something about a polyfill for SIMD.js?
DE: It is incomplete
BE: It can't express value object; it can't intercept ==
or ===
RW: Alright, then it is no longer a suggestion of mine
Unsigned Types? Argument for them?
Consistency with TypedArray
DH: I want to know more about what SIMD use cases are, operations should map to need
WH: want unsigned types:
- consistency with typed array
- printing (want 255, not -1)
(not an explosion of the API)
DE: fewer function names, more function objects.
AWB: lot's of domains with similar conventions
- once integrated, it becomes part of the spec as a whole and will require understanding of these irregularities
- an argument for separate spec
DE: it's a large thing, mostly irreducible
JHD: non-specialists are going to write this stuff by hand.
(Argument to make the API more like JS)
DE: prefer to keep it as is
YK: So a specialist doesn't need the unsigned types?
- then don't worry about use by non-specialists
DH: Either accept Waldemar's argument, or state case based on historical precedence. If no consistency, then don't care.
WH: Note that I'm not alone with that argument. I don't want this to become personal.
Conclusion/Resolution
new
throws- not separate spec
- spec mechansisms: Allen, Brian, Rick and Dan to work through
- Reviewers:
- Waldemar Horwat
- Jordan Harband
- Brendan Eich
- Mark Miller
(Slides are at tc39/tc39-notes/tree/master/es7/2015-07 )
July 30 2015 Meeting Notes
Allen Wirfs-Brock (AWB), Sebastian Markbage (SM), Jafar Husain (JH), Eric Farriauolo (EF), Caridy Patino (CP), Waldemar Horwat (WH), Istvan Sebastian (IS), Mark Miller (MM), Adam Klein (AK), Michael Ficarra (MF), Peter Jensen (PJ), Domenic Denicola (DD), Jordan Harband (JHD), Jonathan Turner (JT), Paul Leathers (PL), Chip Morningstar (CM), Vladimir Matveev (VM), Ron Buckton (MS), Brian Terlson (BT), Alan Schmitt (AS), Ben Newman (BN), Mohamed Hegazy (MH), Abhijith Chatra (AC), Tom Care (TC), John Neumann (JN), Dave Herman (DH), Brendan Eich (BE), Daniel Ehrenberg (DE), Dan Gohman (DG), Andreas Rossberg (ARB), Rick Waldron (RW), Mike Pennisi (MP), Akrosh Gandhi (AG), Jonathan Sampson (JS)
7 Test262 Updates
(Brian Terlson, Mike Pennisi)
MP: Introduction
See slides
WH: (re: jugglinmike.github.io/presentations/2015/tc39-test262-update/#7 ) question, re: es6draft, ecmascript spec, before/after publication?
?: es6draft ? ECMAScript 6 draft
BT: Ongoing. Could also add Chakra bugs
MF: raw flag? Does this prevent issues other than directive prologue issues?
MP/BT: "raw" means: don't touch the file, just run it. No access to assert features, useful for syntax only tests
[discussing distinction between early errors and parse errors that test262 does]
jugglinmike.github.io/presentations/2015/tc39-test262-update/#12
AWB: These are a specification artifact. An implementation doesn't have to do parsing and early errors in separate passes.
WH: This becomes visible when there are multiple errors, some in parsing and some early errors. Does the spec designate which error should be reported when there are multiple of these?
AWB: No. An implementation is free to report any of these errors.
AWB: Distinguishing early and parsing errors in tests is overspecifying.
(re: website improvements)
BT: current test262 site does not have ES6 collatoral.
- Implementing ToLength appears to lock up the website
- Alot of work needed to get the test262 site into a functional state
- Is the work something that Bocoup is going to do?
MP: Nearing end of time, but ideally would like to take on this work
BT: Then we need to find a "resource" for this project
- Enumerating outstanding issues with test262 website
YK: Considered running tests in iframe or worker and timing out?
BT: Harness uses iframes
Discussion of implementation details of test harness
BT: Requirement of new site: use web workers
Moving on to jugglinmike.github.io/presentations/2015/tc39-test262-update/#15
MP: (first example) TypedArray, 9 sets of the same tests. The tests might start in sync, but it's hard to maintain over time.
- Typed Arrays (9)
- Destructuring Assignment (3)
- AssignmentExpression evaluation
- ForIn/OfBodyEvaluation
- for..in statement
- for..of statement
- Spread Operator (4)
- ArrayLiteral: [...x]
- ArgumentList
- SuperCall: super(...x)
- CallExpression: f(...x)
- MemberExpression: new f(...x)
- Expressions & Declarations
- Function
- Generator
- Class
AWB: Similar to wanting to share code in tests, implementations will want to share code.
- Look at how an implementation and its tests go wrong?
- Tests that would catch the most common ways the implementation abstractions might go wrong
YK: Instead of testing all the things, find the things that might fail
- things that look similar, but are subtley different: test that.
MP: (gives an example of how strict and non-strict tests are automattically run, unless flagged)
WH: Value in testing exhaustively when the number of cases is reasonable. Per the presentation, there are only 18 contexts in which destructuring is used, which is reasonable for full cross-product testing.
- Re: Allen's point, there are subtle things that can go wrong. I can imagine an implementation getting destructuring right in most contexts but messing up some subtle aspect of it for, say, arrow function parameters.
- But still worthwhile to test try to be exhaustive
BT: Not suggesting that we won't test syntax in unique contexts
- More about the authoring
- For tests that cover identical syntax semantics and the only difference is syntactic context, then test once
- Why not sweet.js or an existing templating engine? We need to test syntax errors (and other negative tests)
WH: Just pick one that doesn't make you escape all of the ECMAScript syntax
Discussion, re: gist.github.com/jugglinmike/476bdb6dd69ffddaf9d2#syntax
AK: (concerns about useful output)
DD: most consumers clone the repo, so we need to make sure that we check the output as well
AK: I'm less concerned about running, but about the output that will inform me of the failure
BT: Don't want to check in the actual generated tests
- This proposal MUST make it easy to identify failures
- The test harness will write to disc the actual code that failed at the moment of failure
- produce, on-demand, the filled-in template
DE: For tests users, this can be automated?
BT: Yes.
Conclusion/Resolution
- Continue exploring test generation
Meeting Schedule
(John Neumann)
JN: will propose a 2016 schedule in september. Need to know if we'll be in Europe?
- Switzerland: Geneva, Lugano, Montreux, Lausanne (Geneva may not work: too many attendants and too expensive)
- Germany: Munich
- France
- England
Discussion planned for next meeting
- September in Portland, hosted by jQuery/Yehuda
- November in Santa Clara, hosted by PayPal
JN: Need to confirm what the 7th edition will contain
YK: Straight forward, whatever is Stage 4 goes in the spec
AWB: (enumerating general spec process timelines)
- submission
- review
- 60 day opt-out
YK: That's after January?
AWB: Approximately end of January
YK: January is submission, work backward to find deadline.
Discussion re: time needed for Brian to integrate the stage 4 features.
Conclusion/Resolution
- Get proposals wrapped up if you want to get these features into the spec
6.4 Advance Async Functions to Stage 2
(Brian Terlson)
BT:
Updates from Last Time
- Complete spec available ( tc39.github.io/ecmascript-asyncawait / tc39/ecmascript-asyncawait )
- Removed
await *
- Implemented in Babel
- Losts of positive feedback from the web
DH: Future proof for potential future syntax extensions
DD: Clarify not await *
BT: await *
was not useful. If there is a proposal for a useful
semantics, then good, but not in this proposal.
Questions
- Async Arrow Function
- async (a, b) => await a + await b;
- (a, b) @=> await a + await b;
DE: What's the issue with the first?
BT: async
not a keyword and that could be a call: async(a, b)
MM: @ seems like a poor choice, but I don't have an alternate suggestion
AWB: only b/c "a"sync
- the
async
form defeats the conciseness
BT: I've worked out the grammar, it needs review, but it appears to work correctly
YK: Shouldn't have 3 sigils right next to eachother.
- hard to google a sigil or set of symbols
- a "grawlix" problem
BT: Opposed with the top grammar? (assuming the grammar works)
(no opposition, pending review)
DH: Would like to see more code illustrating actual use cases
DD: There's a lot of code in the wild that's been using the top form
DH: Any higher order combinator is where this will have the most use.
MM: No consensus on the second. Consensus on the first contingient on grammar validation
DH: Cannot make async
a keyword, one of the most popular modules on npm
is async
DD: Promise.all
doesn't quite work because it's a combinator that takes
promises, not functions that return promises
DH: The syntax that we've come up with for past features like =>
map to
an extremely high use case with hardship. Not clear to me that we have the full async callback picture
DD: should look into the ecosystem of Babel users and see where it's come up
Design Questions (continued)
- Newing an async function:
- Error
- Promise-for-instance
BT: Suggest "no" (no disagreement)
Design Questions (continued)
- Errors in Parameter Initialization
function* foo(a = (function() { throw 1; }())) {
}
let iter = foo(); // throws 1
BT: the equivalent in async functions:
async function bar(a = (function() { throw 1; }())) {
}
bar(); // as of the latest proposal, this throws 1
// Alternative semantics would have the error deferred:
bar().catch(cb => ...); // Possible semantics
DD: Wish this was caught for generators
AWB: We knew about it, but nothing can be done
MM: For generators, we have immediate throw
- Async function: throw in body breaks the promise
- think about when the throw happens
- what way is it reported?
- throw in generator body is reported with a throw
- throw in async body is reported by rejecting promise
YK: when use promise, you can catch all the errors into one place
AK: Arguing for throw immediately?
BT: Yes, found that error throwing default parameters don't happen (rare case?)
- Mark's point about multiple symmetry in play
CM: setup preparation part, consumption part. The generator setup might have error in setup, reported immediately
DD: Code will expect to receive the error via the catch path, not an immediate throw path.
- Most promise ops go through the API
- Devs can muck with the built-ins and produce errors
AWB: What if you put a proxy on an async function and the call trap throws?
MM: There's not a problem with the [[Call]] trap. If the [[Call]] trap in the Proxy throws, then you have a "throw".
AWB: Say the async function is actually a proxy wrapped around an async function?
MM: It's exactly the same hazard as if you hand someone a function that wraps an async function and the wrapping function throws.
DD: Problem is thinking of async functions as a separate category. Just a function
DH: Mark, I agree. There are errors we consider normal to happen in
programs that you should deal with, and those where soemthing went badly
wrong and you can't write code that has try/catch every where. A function
call that throws an exception should follow the error handling model for
the programming paradigm that we're in; since we're in an aync world, the
programming model for handlng errors is catch
BT: want to be very clear about rationalization, so that same can be
applied to async
generator.
AWB: The generator function returns its value before evaluating its body.
- A generator is a function
MM: An async generator... I missed the rest of this
YK: Can you yield
in a default parameter in a generator?
AWB: No, you cannot yield
there because the object doesn't exist yet.
BT: We need to establish the rationale for the behavior of error handling in non-simple generator parameter lists
YK: Might've been a mistake?
AWB: Generators do what generator functions previously did in Firefox. We weren't sure if it should be changed. Different results:
- timing evaluation changes: happen on the first
next
, the values aren't the same values at the time of the call.
DD: Generators suspend immediately, async
suspend on the first await
DH: All cases, expect that parameter default expressions execute eagerly, not that they execute at some time later
DH: Generators are all about order of execution. The fact that generator functions and async functions have different control flow expectations means that it's reasonable for their error handling behavior to differ.
Discussion about complications of the implicit yield
in generators
DH: Don't need symmetry between generator and async
YK: Async function is just a function, but the generator is a different thing.
- When calling a generator, you're not calling a function as shown
DD: When calling a generator function, the first line of the function does not execute
DD/YK: Agreed.
YK: The consequence is that the refactoring doesn't make sense.
Design Questions Continued
- Await synchronous things synchronously
await 1
does it trigger a turn of the event loop as in the desugaring?- allow synchronous await but ensure promise resoltion is async?
- do neither and allow returning an already-resolved promise?
MM: describing the hazard of sometimes "sync" and sometimes "async"
????????????????Z??????????A???????????L????????????G????????????????????????? !????????????
:applause:
YK: The same hazard doesn't exist with await, because the callback model is changing which scope the function is called in, but doesn't exist in await.
MM: Agreed that the hazard to aync functions is smaller than that to Promises. The bugs will be both fewer and more subtle and harder to figure out.
DD: no cost to go back to the event loop
YK: not true.
- hot code is always awaiting some promise, could be optimized to consider inline-able. Never true if you always have to go back to the queue
MM: If an implementation can optimize, which is very hard and hazardous
YK: I'm making a different point. If you say. "you are not allowed to go back to the event loop" and if you discover that it is synchronous, then you can optimize by in-lining the synchronous code. In an ideal world, it is "just a loop", and a loop is fast.
JH: The relative harm: cost not zero, need to weigh
MM: Experience with asap
, cost is worth it to reduce the hazard.
- When bugs do occur, very subtle and hard for programmer to figure out
YK: Hazard in the callback case is in pieces of code that are right next to eachother that appear to [...] Let me put it another way: the hazards you are talking about are based on assumptions that I would never make when writing a program.
MM: hazard as soon as mutated state is sufficiently non-local
YK: cannot rely on what interleavings are possible
BT: hazard here: order of your next turns change. not that callback could be async, but that your callbacks mayb run out of order. What Yehuda is saying is that people don't write programs with multiple Promises where they expect the promises to resolve at specific turns of the event loop.
MM: Two different hazards:
- The order of events on the event loop is one hazard
- the isolation of side effects is job that was executed up to the await
point, completes before any code of the
await
- All invariants storing during the job
Mark, I need you to fill this in, we're moving too fast.
YK: Transaction committed before any await is called. This exists in Ember.
- Need to see an example of the invariant Mark is describing
MM: After the await point, the callee is starting with a fresh stack.
- Event loop programming paradigm that suspends an invariant must restore the invariant before the job ends.
- Illustrates with example of doubly linked list operation
MM: Event loop concurrency requires restored invariants before the end of the event loop turn
YK: Different from what's encountered in practice
DD: What's the position?
YK: Discussing already-resolved-promises
DD: await 1
is not the same as await Promise.resolve(1)
- If you have a promise, you've said that the value is async and breaking that is crazy
MM: Found with the Q.asap bug: I wrote my code, tested my code, then my code had bugs. Result of code running out of turn with test code.
YK: consistency is absorbed by syntax
MM: disagree
- The bug was directly the result of assuming the invariant will be resolved.
Discussion re: invariant restoration on event turn completion
// BT:
foo().then( function() {
/* 1 */
});
/* 2 */
// Which is first
async funcion foo() {
/* 1 */
await x;
/* 2 */
// are these the same turn?
}
foo();
// HAZARD: setup state required by /* 2 */
Currently, await
is always async.
JH: Concern that the notion of asynchrony bound to...?
MM:
JH: predicts that await means async to developers. await is composition.
DD: yield is composition
MM: asynchrony is mandated by the async keyword
JH: is that adequate? async
means asynchrony, await
does not mean
asynchrony, just pause the execution.
YK: Come back to this?
Agreed. Next turn of the event loop.
JHD: Agree that await x
always means await Promise.resolve(x)
?
Some agreement.
YK: Doesn't fully describe the trade off
MM: Implementation prohibited from making optimization
JH: can we put together a program that illustrates the hazard?
// BT:
foo().then( function() {
/* 1 */
});
/* 2 */
// Which is first
async funcion foo() {
/* 1 */
await x;
/* 2 */
// are these the same turn?
}
foo();
// HAZARD: setup state required by /* 2 */
YK:
let x;
foo().then( function(val) { x = val; /* 1 */ } );
// what is x?
JH: Is that an issue in asap? or were there other issues?
// BT & YK:
async function foo() {
// relies on y being `1`
await x;
// relies on y being `2`
}
let y = 1;
foo();
y = 2;
MM/DD/YK: discussing the hazards above.
AK: Different conditions, different behavior.
Discussion about race conditions in JS
DH: largely around the interleaving asynchronous events
- Mark wants this to be limited
MM: confirms
YK: When type await
, I expect unpredictability
MM: unpredictable interleaving of job
DD:
function dStuff() {
if (window.state === 1) { doA(); }
else { doB(); }
}
async function foo() {
doStuff(); await x; doStuff();
}
window.state = 1;
foo();
window.state = 2;
MM: impossible to reason about a program without knowing something about what is going on.
- testing in sync case, and it works
- execute in async case, and it fails
DD: Always have a consistent state on the next turn
Discussion, restating positions back and forth.
- Promise cancellation:
- Depends on cancellation at the promise level
- Urge promise champions to consider ergonomics with async functions
BT: not going to specify cancellation in this proposal
MM: Not sure that base Promise is going to change?
DD: Talk offline.
- Await at top-level
- Can you await at the top level of a module?
- Useful, especially in Node
DH: Issues.
YK: Previously, could assume that top level ran start to finish, if many pieces have setup await
AWB: this changes the entire model of module execution
BT: modules are wrapped in async function which called immediately
MM: after top level await point, import/export, are these effected?
AWB: initialization happens in the order of import/export but before the module body starts
MM: only "when" the execution happens
AWB: This could be misunderstood
DH:
import ... from ...;
let m;
if (dev) {
m = await local.import("lib-dev");
} else {
m = await local.import("lib-production");
}
export let x = 17;
DH: Requires module be async.
Unresolvable if node remains sync at the top level.
(break)
DH: we need to do more work offline.
BT: is top level await worth pursuing?
DH: Addresses a definite need, eg. dynamic module loading
BT: Flesh it out?
DH: No, this needs to be designed in concert with loader. Suggest decoupling to unblock async/await
BT: Confirms.
- Waldemar's grammar concern?
WH: (presenting now)
async(a=await/
- According to cover grammar, this is a division symbol
- Is await a keyword or identifier here?
BT: parsed like a keyword, but there is a static semantics that says any occurence of await expression is an error.
async(a=await/x, b=c/i) => b;
- Parse cover grammar, don't know that you're in a arrow function. This lets await sneak through as an identifier
- When you do the reparse,
/x, b=c/i
is treated as a regexp
MF: The reparse says it has to match this additional grammar, same set of tokens
WH: It's not clear in the spec.
BT: Yes, the await would appear as an identifier until you apply the cover grammar.
MF: (reads from ECMAScript 2015 specification, section 12.2.1.1
MF: if await is always an await expression, this would fail to reparse, resulting in a SyntaxError
BT: Correct, expected.
BT/WH to have offline discussion re: grammar.
BT: Those that know execution model should review this.
Conclusion/Resolution
async (a, b) => await a + await b;
contingent on grammar validationasync
functions: no construct slot- errors occuring in parameter initialization take the catch path
- Approved for Stage 2
- Reviewers
- Waldemar Horwat
- Jafar Husain
- Yehuda Katz
6.5 Proposed Changes to Observable API
(Jafar Husain)
zenparsing/es-observable/tree/zenlike
JH:
Conclusions after 45 Issues and Impl Work
- Generator should not be used Sink
- Sync Subscription Affirmed Necessary
- Can implement EventTarget using Observable
Using Generators as Sinks
Issues:
- Type Fudging (would like implicit {done: true})
- Priming Problem
- issue with implicit yield
- considered a decorator, but likely a footgun
- Return invoked on unsubscribe
- mistake because it conflates two concepts: the need to free scarce resources and the need to signal iteration has completed
- the equivalent to breaking out of a for loop,
YK: Why does it end up not being important to generators? (dispose being separated from return)
YK: Straight forward to add a dispose()
method to Generator instance
objects
www.ecma-international.org/ecma-262/6.0/#sec-properties-of-generator-prototype
JH: Believe adding dispose()
is good
DD: And/or remove return()
. To remove the try/finally that's implicitly
added around a for-of loop
Discussion, re: try/finally
JH: even if we fix the return/dispose conflation, the priming problem is still a compelling reason not to use generators as sinks
Using Generators as Sinks (continued)
Issues: ...
- Multiple unsub methods
Proposed Solution: Observer Type
(get bullets from slide)
Advantages of Observer Type
(get bullets from slide)
Proposed Observable Type Changes
(get code from slide)
DD: Strange to hide a method by using well-known symbol
- if sync subscription is allowed, just make it easy
WH: What does Symbol.observer return? (Not referring to the symbol, but to the method to which this is the well-known symbol-as-computed property name)
JH: Nothing
DD: What happened to the flush that we discussed?
JH: In progress
MM: What is the Object?
in Observer
type?
JH: Allowed to return something
(Should be "any")
MM: Why not just support the Observer (in subscribe
method)
- Prefer two separate methods
JH: previously had a forEach that returns a promise, still exists, just not shown
Discussing a swath of code on jsbin
Sync Subscription Affirmed Necessary
- Necessary to build EventTarget using Observable (get rest of bullets from slide)
Jafar moves through slides too fast.
DD: Would prefer something simpler than Symbol.observer, instead just call it something obvious
MM: Name it such a way that the name is clear to the user (no suggestion)
Discussion, re: await observable.
All scalar combinators produce promises or observables
Conclusion/Resolution
- Approved for Stage 1 (which means: nothing changed here)
- Offline discussion, re: sync subscription
6.13 Advance Rest/Spread Properties to Stage 2
(Sebastian Markbage)
sebmarkbage/ecmascript-rest-spread
SM:
Static Properties vs. Computed Properties
SM (slide): question on evaluating computed property keys multiple times on the LHS of a destructuring assignment?
SM (slide): question when a "rest" destructured object param throws (via
getter, for example), should rest
be undefined, or a partial object. or,
should the getter be copied rather than evaluated
try {
var throwingObj = {
x: 1,
y: 2,
get z() { throw myError; },
w: 4
};
var {x, ...rest} = throwingObj;
} catch (err) {
x; // 1
rest; // undefined (could be { y:2, w: 4 })
}
MM: possibilities?
SM:
- undefined
- { y: 2, w: 4 }
MF: also {}
and { y: 2 }
MM: further semantics need to be explored
Conclusion/Resolution
- Approved for Stage 2
- Reviewers
- Andreas Rossberg
On Wed 05 Aug 2015 17:19, Rick Waldron <waldron.rick at gmail.com> writes:
6.7 new & GeneratorFunction
(Brian Terlson)
BT:
Current Semantics:
- [[call]]
this
set normally by caller- [[construct]]
this
is a dynamic ReferenceError Issues:- Potentially confusing
- new doesn't do anything useful Possible Solution:
- GenerationFunction doesn't implement constructor, so new throws
this
is not a dynamic ReferenceError, but instead refers to the GeneratorFunction instance (align with current implementations: Babel, V8, SM)
FWIW the behavior as implemented in V8 aligned at one point with a spec draft:
Andy
Rick Waldron wrote:
(Slides are at tc39/tc39-notes/tree/master/es7/2015-07 )
July 30 2015 Meeting Notes
Allen Wirfs-Brock (AWB), Sebastian Markbage (SM), Jafar Husain (JH), Eric Farriauolo (EF), Caridy Patino (CP), Waldemar Horwat (WH), Istvan Sebastian (IS), Mark Miller (MM), Adam Klein (AK), Michael Ficarra (MF), Peter Jensen (PJ), Domenic Denicola (DD), Jordan Harband (JHD), Jonathan Turner (JT), Paul Leathers (PL), Chip Morningstar (CM), Vladimir Matveev (VM), Ron Buckton (MS), Brian Terlson (BT), Alan Schmitt (AS), Ben Newman (BN), Mohamed Hegazy (MH), Abhijith Chatra (AC), Tom Care (TC), John Neumann (JN), Dave Herman (DH), Brendan Eich (BE), Daniel Ehrenberg (DE), Dan Gohman (DG), Andreas Rossberg (ARB), Rick Waldron (RW), Mike Pennisi (MP), Akrosh Gandhi (AG), Jonathan Sampson (JS)
6.4 Advance Async Functions to Stage 2
(Brian Terlson)
BT: Updates from Last Time
- Complete spec available ( tc39.github.io/ecmascript-asyncawait / tc39/ecmascript-asyncawait )
- Removed
await *
- Implemented in Babel
- Losts of positive feedback from the web
DH: Future proof for potential future syntax extensions
DD: Clarify not
await *
BT:
await *
was not useful. If there is a proposal for a useful semantics, then good, but not in this proposal.Questions
- Async Arrow Function
- async (a, b) => await a + await b;
- (a, b) @=> await a + await b;
DE: What's the issue with the first?
BT:
async
not a keyword and that could be a call:async(a, b)
MM: @ seems like a poor choice, but I don't have an alternate suggestion
Just a feeling-based one, but contrary to the straight sync =>, the
async could be curly ~>.
July 26 2016 Meeting Notes
Brian Terlson (BT), Michael Ficarra (MF), Jordan Harband (JHD), Waldemar Horwat (WH), Tim Disney (TD), Michael Saboff (MS), Eric Faust (FST), Chip Morningstar (CM), Daniel Ehrenberg (DE), Leo Balter (LB), Yehuda Katz (YK), Jafar Husain (JH), István Sebestyén (IS), John Neumann (JN), Domenic Denicola (DD), Rick Waldron (RW), Stefan Penner (SP), Jonathan Sampson (JS), Caridy Patiño (CP), Sam Tobin-Hochstadt (STH), John Buchanan (JB), Kevin Gibbons (KG), Lars Hansen (LHN), Peter Jensen (PJ), Tom Care (TC), Dave Herman (DH), Bradley Farias (BF), Kris Gray (KSG), Adam Klein (AK), Dean Tribble (DT), Eric Faust (EFT), Jeff Morrison (JM), Sebastian Markbåge (SM), Saam Barati (SB), Kris Gray (KGY), John-David Dalton (JDD), Ben Newman (BN)
(I need the list when it's complete)
Template link: tc39/Reflector#19
Introduction
JN: (agenda)
IS: (wishes to determine a log.... I am not sure I understand what this means... :-))
DE: We could go through the agenda and appoint reviewers for each topic
DD: I think we should appoint note-takers at the beginning of this meeting
YK: I think we should appoint note-takers as we start each topic
RW: If we have different note-takers, they might not follow the right format, making my job of cleaning up the notes harder
DE: Let's defer to Brian when he gets back
IS: Different Ecma groups do different things; there is no single solution. Some e.g. only record the subject and outcome of the discussion, but not the actual discussion itself. This has to be decided by the TC. Anyway, with the current practice, which is very similar what the W3C does, we need the support of the group. e.g. Ecma can not hire any pay for a professional technical notetaker, that has to be organized / fulfilled by TC39 members.
JN: Looks like some things are timeboxed
BT: Does anyone want to volunteer to take notes the whole day?
RW: Me
AWB: (punt on addressing this now?)
BT: Let's go with Rick taking notes for now, since he volunteered, but long-term we'll go item by item
Conclusion/Resolution
- Moving on, further discussion to be on github as before this meeting. Interested members are encouraged to participate there directly.
3 Agenda Adoption
- Approved
4 May Minutes Approval
-Approved
JN: Agenda?
(Discussion re: backing documents not present for a handful of agenda items, should we start requiring these?)
WH: I'm fine with occasional items not having backing materials — there are situations where that's appropriate — as long as they're relatively rare and not looking to advance.
WH: ECMA has a global policy (we all agreed to) that documents up for significant decisions shall be provided 2-3 weeks in advance. I'd interpret this as applying to proposals looking to advance in TC39.
IS: It's 3 weeks. This is e.g. to formally move forward or approve a TC39 draft speciafication. But for things for information, to start a discussion on new items, not to strive for a formal decision anything until the meeting is allowed. But of course it is encouraged to submit and post on Github as soon as possible.
JN: Approval of minutes?
Conclusion/Resolution
- Agenda Adopted
- May Minutes approved
- Add item to discuss the agenda item locking.
5. Report from the Ecma Secretariat
IS: Submitted the ECMAScript Suite Standard (approved by the GA as Ecma 414) to ISO/IEC JTC1 for fast-track. This should enable not to submit anymore ECMA-262 and ECMA-402, etc. to JTC1 separately anymore. This would allow to solve the speed difference problem and the RF patent policy problem. However, JTC1 editors wanted to have more text in the standard and not only the list of normative and informative references. IS said that he will work with Allen Wirfs-Brock on that. If possible we try to beed up ECMA-414 until the September 2016 meeting that isót can be approved as new Edition in the Decemmber 2016 GA. If the plan is delayed we finish it by June 2017.
-
Link IETF spec to Ecma 404 (that was already fast tracked to ISO actually before the May 2016 TC39 meeting). On that one JTC1 has not given any feedback yet. So we guess that is on track.
-
On the issue we are in close contacts with the IETF. When we get the IETF spec number (when available) we will make a 2nd Edition of ECMA-404 and fast track that edition to JTC1. With that we want to link the Ecma Standrad with the IETF specification that they should be in full harmony.
-
Awards: BT and RW received ECMA awards for ECMA-262 7 th Edition and ECMA-402 (plus the many notetaking). Congratulations!
-
New Executive Committee, made from a combination of ECMA management and the former Coordinating Committee.
- A change from the past is that up to two ECMA members from categories other than ordinary members may now be elected into the the Executive Committee. Nominations for that can come from anybody, but in the end the December GA will vote on the nominations. The membership in the Executive comiittee is always one year, but with the possibility of reelection.
- All members can now participate in the General Assembly and take actively part in the discussions, not just ordinary members. However, only ordinary members can vote (that is unchanged).
-IS also noted that TC39 is now by far the largest Ecma Group and it has grown to a size where he feels that we have to organize our structure and work better, otherwise at the face-to-face meetings there might be disappointment by some who prepare for a topic for discussion and presentation but in the shortness of time the subject is not discussed properly. Discussion on that to be continued by those who are interested on GitHub.
- What IS forgot to tell, that actually with the publication of ECMAScript 2016 and ECMA-402 new Edition etc. it would be a good idea to make more PR, e.g. Press Release.
8. Test 262 Status Update
IS: Technical Report 104 needs to be updated. He added that all specs related to TC39 work are being downloaded very heavily (actually at least 2/3 of all Ecma downloads are TC39 related). The HTML version of ECMA-262 and ECMA-402 is in addition to it, and compared to full downloads that is even significantly higher.This is actually more than e.g. what is being downloaded from the ISO Shop (of course that is not free of charge...). So automativally also TR-104 gets downloaded rather heavily. But e.g. in TR/104 the URL to the tests does not work. Also the text needs to be updated. It reflects a situation when only ES5 was covered, but e.g. not ECMA-402.
AWB: Propose updating TR 104 to be descriptive only?
BT: Is this just a readme? Possible get rid of it?
AWB: Just reduce to an abstract description of the content and motivation of test262
DE: Should ecma site link to draft spec?
AWB: The draft isn't the published standard
(Suggestions to link both, with clear identifiers)
Note IS: I did not say that in the meeting, but In case of TC39 actually we give links to the latest ECMAScript drafts.
Conclusion/Resolution
- Bring to reflector for further discussion
- TR104 update (or withdrawal)
- Linking standard and draft?
- It's there, but some want it to be more prominent
Note IS: The TC39 website pages at Ecma have always room for improvement. If anything you want to include just contact Patrick from the Secretariat who maintains the webpages.
6. Ecma 262 Status Update
Brian Terlson
BT: 6 months left for ES2017
- Object.values
- Object.entries
- String.prototype.padStart
- String.prototype.padEnd
- RegExp changes to case insensitive flags ( tc39/ecma262#525)
AWB: (questions about consolidated changelog that provides complete document of changes from previous edition to present edition)
YK: Make a single place for all published changlogs?
BT: There has never been such a document, isn't Annex B's change listing sufficient?
- Want changelogs in annex?
AWB: Yes
DD: Use links instead of copy/paste?
BT: Links to releases tab?
AWB: Cannot stand alone without github
BT: (has a plan)
...
AWB: Do we have a "focus on 2017 items list"?
BT: No, not yet.
JHD: Benefit of knowing what year a thing will be ready?
BT: Addressing the cross cutting issues, knowing the big picture
AWB: Resolving issues discovered in an implementation
BT: Champions responsible
Conclusion/Resolution
- Bring to reflector for further discussion
- Need changelog for each edition
- Discuss form/forum/format
7. Ecma 402 Status Update
Caridy Patiño
No updates
8. Test262 Update Revisit
Leo Balter
LB: Bocoup has just wrapped project delivering coverage for ES2015
- Iterating on feedback from other members
- Moving forward on ES2016 tests
- More work to be done, but need volunteers
- Deprecated Python runner
- Working on test262 harness that runs from node.js
DE: Work to be done on test262 presence
- Spoke with Kangax about including test262 in the compat table sites
LB: More visibility for test262
TC: Need help with reviewing contributions
- Promises
- Yield
TC: Barrier to entry quite lower based on the work that's been done in the last year.
SP: (asking about test submission with new features)
BT: Staged features require tests. Known issue: normative changes haven't been blocked by any requirement for tests
RW: Previously, not a lot of contribution, so this wasn't an issue. Now we're seeing more contribution, so it needs to be addressed (this is a concern that we have at Bocoup)
BT: Possibly a requirement to create an issue on test262?
SP: Block merge?
Conclusion/Resolution
- Labels to mark normative changes that need tests
- Work with change author to make tests
- Block on normative changes until they have tests
- Due diligence on both the tests and normative spec changes
- Authors, champions, leads must be satisfied with changes on both repositories
- Include mention of available mentorship for test writing.
9.i.a Reintroduce for-in-initializer
Kevin Gibbons
KG: V8, SM, JSC implemented and later reverted. Chakra did not implement
- Web breakage happens!
Proposing changes to Annex B
AWB: Annex B are generally items not allowed in strict mode
KG: Not consistent
YK: Can we make illegal in strict mode?
KG: Chrome does
?: JSC does too
AWB, WH: So we should add for-var-in initializers with the old semantics to Annex B, for non-strict mode only.
RW: (brief discussion about strict mode additions: resolved, non-issue)
YK: Does this mean sloppy mode changes are always in annex b?
Generally, no.
Conclusion/Resolution
- Add for-var-in initializers with the old semantics to Annex B, for non-strict mode only.
- ecma262/pull/614
- Kevin will write tests for the change, based on the new policy
9.i.b Update on Async Iteration
Domenic Denicola
(No slides)
DD: Kevin Smith has left the committee; I am taking over as champion. I did not have time to address spec issues, so it is not ready to advance, but they are minor and I will work on it. Who should be Stage 3 reviewers?
Conclusion/Resolution
- Reviewers: Bradley Farias, Daniel Ehrenberg
AWB: Going back to the previous topic, Kevin, could you please share a PDF on the notes page, since links rot?
9.i.e Trailing commas in functions
Jeff Morrison
JM: It's implemented in two browsers (JSC, Edge)
AK: Actually V8 also
BT: Actually we ship it already. Are there test262 tests?
JM: I thought so. Stage 4?
WH: I don't object to advancing this to stage 4, but I'm sad to see this in the language.
?: Ditto.
(We can't find tests)
Conclusion/Resolution
- Stage 4 pending on writing and merging test262 tests
9.i.f Unify String and Array maximum lengths
Michael Saboff
MS: Unify the length of strings and arrays. Strings are 2^53-1, Arrays are 2^32-1 indexed elements. A few APIs cross over. Really, browsers are all 2^31 or less. I don't care which way we go, but I'd like Strings and Arrays to be unified. Maybe we should delay this a little until we figure out how to make Arrays bigger; I originally proposed reducing everything to 2^32-1
MF: What's the motivation?
MS: Consistency, so they all use the same type of index.
AWB: There was a lot of thought that went into it. We increased the size of everything that we could — strings, typed arrays — and held off on Arrays for compatibility reasons.
DD: As Michael was saying, in current VMs this isn't a good idea, but maybe in a few years, it could be reasonable.
AWB: And Arrays can be sparse anyway
YK: Seems like a bad idea. Use Maps here instead for spare Arrays, or TypedArrays for big Strings or Arrays. We have TextDecoder in the DOM to deal with TypedArrays that have encoded Strings.
DD: Why not even lower?
AWB: We use 2^53 for basically everything, except for Array length calculation, which maxes out at 2^32-1
DD: It seems like bigger would be better
DE: What was the web compatibility evidence presented in the past?
BE: The motivation [of increasing it] was weak, and no one wanted to jump on the hand grenade.
AWB: Well, we have a motivated implementer here. Maybe Michael should try it out.
MS: I don't think any browser believes we need more than 2^32 for browsers. However, for servers, it could be an important limit to hit. I don't think this is important for JSC as we are just a browser implementation.
AWB: There's a chicken and egg problem. Someone has to prove the feasibility of it, and you're the only major implementation who has brought it up as a possibility.
MS: My proposal was to make string lengths smaller.
AWB: We don't want to make string lengths smaller
DD: It would be nice if everything were as big as it could possibly be, but I don't have a problem with making it smaller
AWB: The max size is implementation-dependent
YK: It seems OK to just choose the lowest common denominator size
BF: It seems like large Arrays or Strings are important for some applications
YK: We can just make those things use TypedArrays. Wouldn't you want to use binary data for such big things?
WH: We'd need to shrink TypedArrays too if we're shrinking strings; otherwise we wouldn't get the consistency that's the whole motivation of this.
EF: If we don't shrink TypedArrays, we wouldn't get a level paying field.
AK: What is the motivation for this change, given that JSC already limits strings to 2^31?
MS: It's consistency. In regular expressions, for split, we have to do these 53-bit calculations, but really strings are smaller
AWB: For split, we made a change to use ToUint32 rather than ToLength, but we should've made it throw
AK: that's a separate proposal
AWB: It's gotten worse with recent changes
DE: We've hit the timebox limit; Add this to the end of the agenda?
MS: This isn't a hill for me to die on; i think it's something we should address, but not my #1 priority
Conclusion/Resolution
- Not finished; will revisit
9.i.h Standardize Date.UTC when called with < 2 arguments
Brian Terlson
BT: All implementations except Edge return NaN for Date.UTC for < 2 arguments, but Edge treats those missing arguments as 0.
AWB: What discussion have we had before?
BT: I couldn't find it. As Chakra is the only holdout, and we have no compelling reason, we're willing to return NaN. So I believe we should update the spec text and return NaN, and Chakra will do that.
DT: Is this part of a more general principle?
DD: Actually the spec had a specific cop-out there
BT: OK, consensus on the change?
AK: Are there test262 tests?
BT: I'll write them! But I'll merge the Chakra PR first
AWB: Why not actually make them optional like Chakra does? Maybe those are good semantics.
YK: We're just standardizing what's there in browsers
DD: Does anyone want to experiment?
BT: We're shipping this already. I'm concerned about interoperability.
YK: NaN is horrible and we should avoid letting it leak out into programs.
DE: We can't generally be in the business of making bad arguments to things return useful values. Date uses NaN all over the place as a way to stand in for something having gone wrong. The Date library is horrible and legacy; our job should be to standardize what's there. The Date.parse presentation will show a significantly worse case than this, but we should standardize it anyway. Given that we have three browsers agreeing, we should just standardize that. I would be OK with standardizing the other behavior.
WH: We shouldn't create a second Date library just to fix this, we should make this one good.
WH: UTC(year) should return the first day of that year, just like UTC(year, month) returns the first day of that month. We know that works because Chakra does it.
AWB: Oh, I see what's going on. This fills in a missing case from the Date overload. Date does something completely different when passed one argument than when it gets two.
BT: Let's pick one of the two existing semantics, not something in between. Oh, wait, it's actually December 31, 1899
DD: that's two-digit year 0, timezone-shifted
DE: Sounds like Chakra's semantics are significantly bad
BT: Let's standardize returning NaN now, and we could revisit it later.
DE: Returning NaN is sorta like throwing an exception, so we could make it return a useful value later. DE: We are running into the timebox. Do we have consensus on the PR?
WH: No. I think that, barring additional evidence, it would be good for the one-argument case to return the beginning of the year. I'm fine with NaN for the zero-argument case.
AK: What would be the use case for this? is it worth it to ask implementations to make this change? We're making a normative change; there should be some reasonable motivation.
BT: It's a grand compromise
AWB: 1) Interoperability among implementations 2) Usability going forward--what would users expect? This is forward-looking, not backwards-looking.
BT: That seems like a reasonable rational. Are other implementers reluctant to return a useful value for that case?
AK: My point is a little higher-level, that if we are making normative changes, we should have a motivation for it.
AWB: Good design aesthetics would be to revisit what things are, rather than just polling implementations
AK: This is adding to the incompatibility for the future and churn.
BE: It is what it was. I support the status quo, copying Java, returning NaN
MS: I support returning NaN for less than two arguments, just because of the confusion that Date has 0 arguments, 1 arguments, and then 2 or more is just like Date.UTC
AWB: The Date constructor has an overload for one argument, so it can't treat that as the year and be analogous to Date.UTC for the one-argument case.
Conclusion/Resolution
- No consensus on the full change. The zero-argument change is agreed to return NaN, but disagreement about what the one-argument case
9.i.d Revisiting NaN
Daniel Ehrenberg
Slides: docs.google.com/presentation/d/1eqimbmVpMZET_5H9NacVkXGP2WNATg8bXWi3Ky2bsGo/edit
DE: (presenting slides)
- Some implementations fit pointers in NaN payloads, so canonicalize
- V8 does not do NaN tagging, so pointers are 32-bits on 32-bit archs
- Extra canonicalization writing into a TypedArray is a perf regression (see slide for link)
Slide: "What does ES2015 day about NaN?"
-
The Number Type "to ECMAScript code, all NaN values are indistinguishable from each other"
-
SetValueInBuffer( arrayBuffer, byteIndex, type, value [ , isLittleEndian ] ) "An implementation must always choose the same encoding for each implementation distinguishable NaN value."
DE: ok with: "anytime you use SetValueInBuffer, use whatever you have"
"Why would property writes make a new NaN?"
SetValueInBuffer ( arrayBuffer, byteIndex, type, value [ , isLittleEndian ] )
- V8's FAST_HOLEY_DOUBLE_ARRAY ElementsKind
- Sample code:
let x = new Array(6)
for (let i = 0; i < x.length; i++) x[i] = 0.5
- Initially "filled with holes" (missing properties), then entries are added V8 canonicalizes NaNs when setting elements into such an array so it can have a distinct "hole" NaN value
WH: This is an instance of the general problem that implementations will sometimes do NaN-boxing and sometimes not within the same program, depending on code and data structure optimizations.
DH: Easiest solution: maximally non-deterministic: allowed to non-deterministically change bit pattern Problem: many places possible to predict the bit pattern. Can convey information, want to preserve that preciseness.
MM: Uncontrolled non-determinism of NaN bit pattern, depends on unspecified nullable
(discussion re: intentionally evil implementations)
WH: My view is that what NaN bit pattern you get should be unspecified. I understand MM's concern and wouldn't want them to be evilly unspecified, although I'm not sure if there is a reasonable way of expressing that.
- timebox ran out, discussion continued *
DH: expectations:
- want implementation flexibility, use cases for changing bit patterns
- frozen properties, should not be able to reliably observe changes
DH:
- NaNs carry around bit pattern,
- specific places can scramble
- specific places preserve
EFT: Over the time box, no new points made
MM: Don't understand the optimization in V8
AK: I think this needs to be discuss offline?
DH: (taking issue with time box)
DH: Some predictable behavior that has changed over the years and some implementations are doing different things, new use cases.
Conclusion/Resolution
- Allen, Mark, Dave, Waldemar, Dan to have discussion and come back for another time box discussion.
(More discussion re: time box)
9.ii.a Object.getOwnPropertyDescriptors: when a Proxy returns an
undefined descriptor?
Jordan Harband
JHD: Any non-proxy, call built-in op claims foo in object, call
Object.getOwnPropertyDescriptor(foo, "prop"), you get that property
descriptor. Proxy can lie, which is problematic when passing the returned
value from Object.getOwnPropertyDescriptors(...)
BT: Side-effecting proxies. If a proxy says "no descriptor for this property", then there is none. Object.getOwnPropertyDescriptors(...) shouldn't be seen as the authority.
- Property should be skipped on the grounds that "it doesn't exist"
MM: once an obj is not observable, ownkeys cannot give an answer that was not previously true
DE: Cait Potter implemented both semantics and there are no noticeable differences.
AWB: No guarantee once you get a descriptor that it remains valid to do something with it in the future - operations are unknown
JHD: The change is: only properties with valid property descriptors are returned.
Conclusion/Resolution
- Recommended change approved for merging the PR
AWB: obligated to notify implementors?
JHD: Implementors are aware and following progress
9.ii.b Object.enumerable{Keys,Values,Entries}
Leo Balter & John-David Dalton
LB: Discussing leobalter/object-enumerables
JDD: No built-in API that allows getting own and inherited properties
EFT/DD: for loop?
JDD: Want built-in functionality, not syntax
DH: Something more?
JDD: Allows a shim path.
DH: An example?
JDD: (showing an example in lodash)
STH: Can't the shim write the for in loop?
DD: Spec seems to treat objects as maps, but specifically objects and their prototype properties as values in the map
JDD: (further examples, showing: leobalter/object-enumerables#use-cases )
DH: Not impossible to write in library code?
JDD: no, but not the point
STH: Offers shim authors something to coordinate on to fix bugs in older browsers, but not sure we should be in the business of doing so.
YK: It's rare to encounter an enumerable property on the prototype, it happens
- If there are properties on a class prototype that are enumerable
AWB: Effectively creating for-in
YK: Yes
DD: Do we want to further encourage the programming model that these encourage?
MM: (concurring, discussing value of such a feature)
DH: A number of libraries want to use this functionality and it would be nice expose as built-in, but why not define in one library and that's that.
AWB: Back to "inherited, enumerable things". The only definition we have is via for-in
DH: can also crawl the prototype chain
AWB: then have to impose your own rules re: side effects
BE: for-in is bad legacy
"Never invest in the trailing edge"
DD: Adding new features, in new browsers, to fix features in old browsers, is not what we should be doing.
MM: I don't think this is going to get consensus
Conclusion/Resolution
- No advance
9.ii.c RegExp Unicode Property Escapes
Brian Terlson, Daniel Ehrenberg, Mathias Bynens
mathiasbynens/es-regex-unicode-property-escapes
Slides: docs.google.com/presentation/d/1o31S9RqDdkoWW2zfPMNIZdPDIp25Rr0-XW0gro_cskk/edit
DE: Expose more unicode data to RegExps
- Properties with values: /\p{UnicodePropertyName=UnicodePropertyValue}/
- Binary properties: /\p{LoneUnicodePropertyNameOrValue}/ Inverse:
- \P
Example:
i.gyazo.com/0dcfc195d891a36c4b0c04d460cb5d72.png In text form: mathiasbynens/es-regexp-unicode-property-escapes#illustrative-examples
DE: Have full spec text, implementation in V8, tests for V8 (need to be updated for test262)
BT: If ok with deviating from what’s allowed inside \u, then we can overload \u instead of \p
(TODO: @rick we'll likely have to escape those ^^^^^ when this is published as markdown)
DD: Are there conflicts with other languages and use of \u?
WH: \u could be trouble if anyone comes up with classname consisting entirely of characters A-F
DE: I can find out if this is an invariant that will be maintained. If it is, then we should use \u, otherwise \p. If Unicode advises us not to depend on existing \u invariants, then we won't
DE: Stage 2?
MF: Is there a syntax error when type any random character where in /\p{UnicodePropertyName=UnicodePropertyValue}/, /\p{LoneUnicodePropertyNameOrValue}/ ?
DE: No UnicodePropertyName syntactic restrictions in present spec
Addendum by Mathias: a SyntaxError is thrown at runtime in such cases. But yeah, maybe these should trigger early errors instead? No strong opinion here.
AWB: Need to specify the syntax
WH: If we choose to use \u{}, then we must make unknown classes (or typos) into early errors because we need typos in hex numbers to be early errors. With \p{} we'd have a choice of standardizing on early or runtime errors.
Revisiting String.prototype.normalize specification.
This may need to be "normative optional"? Inclusion of new data tables may be problematic?
Discussion re: ICU data, Unicode data on constrained devices.
RW: When Tessel 2 moves to Node 6, we'll be shipping Node.js compiled with the disable flags, which means normalize is useless, but the additional data isn't included.
AWB: Can define it such that, if the data is not available, the character set is empty
DE: Stage 1?
Conclusion/Resolution
- Stage 1: Approved.
- YK wants confirmation about \u
9.ii.d Async Functions for Stage 4
Brian Terlson
BT: no updates, no changes
- Shipping in Edge
- Implementations in V8 and SpiderMonkey
YK: Worried about cancellation?
DD: Cancel token integrate well with async functions
YK: Not at stage 2 with cancellation, hard to be sure that it's compatible
KG: not sure it could change, given widepsread use in transpilation
YK: (concerns with cancellation intuition)
DE: the correct time for this was prior to stage 3
YK: I made these objections then
DE: I'm pretty optimistic about Domenic's cancellation specification
DD: If I had held off on Cancel tokens, this would've made it to stage 4
BT: Off topic.
YK: Certain assumption that one can reasonably assume that an expression that exist can become abrupt
- Have to know that X cannot throw
- Cancellation exists, now X might throw
WH: I'm trying to understand the concerns here. Should this proposal be blocked on the cancellation proposal advancing a few levels?
WH: I hear vague uneasiness about interactions between async functions and cancellations, but need something more concrete to be able to judge the merits.
BT: willing to postpone this until we know more about interaction with cancellation
SP: Can we revisit this after cancellation?
(Discussion, re: some people that object, that are apparently in the room, but aren't speaking)
MM: concerns: === should never throw, typeof should never throw. I don't recall where cancellation would make await throw, where it previously would not throw.
Was
DD:
async function foo() {
try {
await f();
g();
} catch (e) {
h();
}
}
might call neither g nor h. But then there are other situations where
neither g nor h is called. Use finally
if you want cleanup code.
DD: Objecting to the third
JHD: If f
is changed to return new Promise(() => {})
, then both g
and
h
will never run now, without cancellation existing - therefore if you
expect g
or h
to always run, you are simply wrong, and your expectation
is invalid.
async function foo() {
try {
await f();
g();
} catch (e) {
h();
}
i();
}
DD: however, currently you can guarantee that either g
or h
will always
run before i
, and it's possible with cancellation that this might not
hold.
MM: the example here has nothing to do with something that was not abrupt, becoming abrupt
- A new way to be abrupt, in addition to the old way to be abrupt
DH: If from scratch, no issue. The issue is that catch expectations no longer valid.
DD: There is past precedent for moving ahead. We introduced proxies, which created objects that behaved outside the past invariants that code might have relied on. We introduced new typeof types with similar effect.
JHD/EFT: No call site can be defensive against code it didn't write
JHD: In the case of Promises, if you're returning a promise that you didn't
create, in a then
, you can't defend against it, because you can't know if
the other promise will ever settle.
(Questions about "Third State")
Conclusion/Resolution
Will revisit after discussing cancels more; hopefully reshuffle non-timeboxed agenda items to enable that to happen in this meeting.
9.ii.e Math extensions
Rick Waldron
RW: There are some nasty npm modules for these sorts of math functions. This comes up in IoT, cool animations, etc. We could add some more functions to the standard library. This stuff happens over and over and over again; typing things into consoles.
YK: leftPad went well
RW: This falls into the leftPad box. This is putting down pavement where a cowpath once was.
RW: Math.constrain: Could be called Math.clamp. Like Uint8ClampedArray. Very straightforward.
RW: Math.map is just scaling x from one range to another
YK: scale is better than map
RW: Scale is my favorite actually; I didn't want to seem biased. fmap is the version where the result is converted to a float32.
DD: Looks like it'll move x to the corresponding point in the 'out' linear range as it was in the 'in' range.
RW: Yes
DD: Why not just use fround composed with it? Is there a hardware operation for this?
RW: No; we can take this or leave it
AWB: Since we're doing multiplies, the fround won't end up commuting with the operations, so this won't get those efficiency advantages. This is specified to do double precision scaling. This is just a nice-to-have.
DH: is every one on the list something that you found in other languages?
RW: Yes, the readme has links to standard library features analogous to these in tons of other languages.
MM: Shouldn't these be in a new built-in module?
RW: I'd love to do that. If between now and 2017 lockout day, I will change the writing for that.
DH: Part of your motivation is that it's trivially accessible from the console, and you can't import from the console.
RW: If it's a built-in standard lib module
DH: From the console, that extra line is a pain, and further, I can't see why we should be inconsistent with the other Math functions that exist. Seems silly to be out of sync with each other.
DT: Built-in modules just in the console?
MM: Seems like adding functions for radians and degrees when they are so trivial is just a waste of time.
DD: I don't feel so strongly about this, but taking conversions for different unit systems takes Math in a totally different direction.
RW: If you look at other languages, they include these conversions for radians/degrees and not other things
STH: And degrees are unitless
DD: They are not natural
CM: But degrees are widespread as a notation
DH: There's a high bar for adding something to the JavaScript standard library, given that our library is rather more limited. We do want to add things that are common enough.
RW: And it's painful to install someone's bad npm library
DH: We make these generic arguments about the benefits of standardizing functions, but we can't standardize all functions in npm. The argument should be, we know what the costs are, we know that we can't do it for everything, so we have to make the argument that these are extraordinarily common for important use cases.
STH: Two other reasons why these functions have a strong claim: Unlike other domains, JavaScript has as reasonably strong Math standard library, for historical reasons, and so programmers expect Math.whatever to be the math standard library in a way that they don't expect for Strings or TCP connections. Second, these are things that are commonly in the standard library of other languages. Yet again, programmers expect, when they look for functions like the ones Rick is proposing, where their counterparts are in other languages.
DD: I agree with these points, but maybe we should group these under "Units" and include time constants, also RAD PER_DEG not "TO"
YK: I agree that time conversions are very common.
RW: I'm asking for stage 1.
JHD: Do we expect to devote time to the problem space?
RW: Single-precision values are important because some datasheets ask for things to a certain precision. You want the rounding to happen in your own code, not implicitly when writing it into the actual register. But really, Math.fmap is not all that important.
WH: I was wondering why we have fmap but not fmax, etc. What does this actually do?
RW: It maps a range
YK: We are interested in this subject; in stage 1 we can look into unit conversions generally
DD: I feel really strongly that it shouldn't be in Math
JHD: We don't have to come to all of these answers in order to get to Stage 1.
RW: As part of Stage 1, I will document why these should go within Math
MF: I want to define a selection criteria for math functions. This seems like a random bag.
RW: I used subjective criteria, for what is the most painful in my everyday programming
DH: Some possible selection criteria: 1) Incredibly high applicability 2) known hardware fastpaths
DE: Or known VM fastpaths, like Object.values
DH: Neither of those has anything to do with whether it's in Math. Domenic makes a good point that some of these don't belong in Math.
WH: I would have expected math library extensions to include common math functions like the gamma function. Why aren't those in here?
RW: That was my long list, but I pared it down. Maybe we should be incuding a lot of functions from other standard libraries.
AWB: We went through a similar process in ES2015 where we made a big spreadsheet of various languages and functions, and chose what to add to Math based on that
RW: How about looking at Racket and Python
MF: We should look at rather broad datasources, like utility libraries for JS today, a number of different programming languages, etc
DH: We should avoid the slippery slope that, if we do one thing, we do all the things. We should have a high bar
DD: We shouldn't tell the champion that they need to add more than they want; they should be able to put in what they value
AWB: Seems like this request is a valid input.
RW: This is really robotics-driven
WH: Last time, we got bogged down in specifying precision of math functions. How should we avoid that here?
CM: If there are subtleties in the implementation, that's a good reason for standards.
Conclusion/Resolution
- Stage 1
July 27 2016 Meeting Notes
Brian Terlson (BT), Michael Ficarra (MF), Jordan Harband (JHD), Waldemar Horwat (WH), Tim Disney (TD), Michael Saboff (phone) (MS), Eric Faust (FST), Chip Morningstar (CM), Daniel Ehrenberg (DE), Leo Balter (LB), Yehuda Katz (YK), Jafar Husain (JH), István Sebestyén (IS), John Neumann (JN), Domenic Denicola (DD), Rick Waldron (RW), Stefan Penner (SP), Jonathan Sampson (JS), Caridy Patiño (CP), Sam Tobin-Hochstadt (STH), John Buchanan (JB), Kevin Gibbons (KG), Lars Hansen (LHN), Peter Jensen (PJ), Tom Care (TC), Dave Herman (DH), Bradley Farias (BF), Kris Gray (KSG), Adam Klein (AK), Dean Tribble (DT), Eric Faust (EFT), Jeff Morrison (JM), Sebastian Markbage (SM), Saam Barati (SB), Kris Gray (KGY), John David Dalton (JDD), Ben Newman (BN), Morgan Phillips (phone) (MP), Shu-yu Gho (SYG), Paul Leathers (PL), Ben Smith (BS), Zibi Braniecki (ZB)
9.i.g Date.parse fallback semantics
Morgan Phillips
mrrrgn/proposal-date-time-string-format
MP: (see link) Date.parse accepts strings that are implementation specific, this is causing incompatibilities across runtimes with new and repeat bugs filed regularly.
Suggesting: specify the intersection of supported string formats, specify this as the fallback for Date.parse.
mrrrgn/proposal-date-time-string-format/blob/master/data/results.csv
DE: How much which is currently allowed to parse is banned under this proposal?
AWB: In general, implementations are allowed to add extensions to do something else rather than throwing whenever they want.
DE: If any impl. doesn't apply extensions to spec: what sort of strings that currently parse, would not parse (by only implementing this format)?
WH: (what are the data in results.csv?)
MP: Those are data generated by a fuzzer and the columns on the right are "yes" or "no" whether the string parsed
WH: The table lists which dates are accepted, but what dates do they generate? For a concrete example, line 30 is "may,may,-000000". It's accepted, but what date does that produce?
MP: This will parse as May 1, 2000. Almost all of this is crazy, hacks on hacks
(shock and awe)
SP: Web compatibility concerns?
MP: Working with V8 dev to add telemetry probes into V8 and SpiderMonkey. The web is fairly broken already—implementing an intersection as a fallback should not break the web.
SP: Is the goal to find the intersection, or a refinement on the intersection?
MP: Refinement.
WH: Are there places where different impl. accept a string but generate different dates?
MP: Possible, but haven't explored. So far have only looked for producing a NaN
SP: Should that be included?
MP/AWB: Yes
AWB: Can we replace "yes" and "no" in the table with the actual output?
MP: Yes
WH: Does the table include all "yes" rows (i.e. rows where the existing implementations all accept the string)?
MP: removed, there are millions.
EFT: Those are covered by the proposed grammar
MP: In the table there's a column for whether the proposed grammar accepts the string. It's the "parser" column.
WH: Row 4839 is accepted by three implementations but not the proposed grammar.
MF: There are 60 examples like that in the table.
MP: The grammar needs to accept more. The current grammar isn't what I want to propose in the end.
AWB: I want to reference back to ES5 and when we added ISO dates and what our thinking at that time was. What we did in ES5, we introduced the ISO date format and we did a quick look at this sort of stuff, and decided it was such an incredible mess that maybe there's no way to fix it. Part of the thinking there was, do we fix up this thing that's here, and identify which dates we take and which we don't take, or do we leave and assume that some day in the future we'll introduce a new API that is a date parser, and that we've designed from first principles of what dates we want to parse, and we don't simply include funny weird cases that exist in implementation-defined stuff simply because it's there. Because it's a new API, we wouldn't have compatibility requirements. That's still possible--we could try to find this intersection, or we could leave it alone and find the date parser implementation that we want.
YK: [Agree, but Date API is generally the sort of thing that accepts junk and is expected to do the right thing]
DE: Unfortunately, browsers don't have the luxury of doing what AWB suggests, and the demands of web compatibility mean that we have to support what other browsers support.
MP: noting reports that a company identified some large number of bugs being date based.
DE: We have found that at least 4 out of 10k page loads uses the "legacy date parser" in Chrome
Conclusion/Resolution
- Stage 1
9.iii.a System.global
Jordan Harband
JHD: We reached Stage 2 previously, and the remaining open question is which name should be used. window would break lots of code, since everyone assumes 'typeof window' indictates whether you're running in a main page. The remaining options are self, global, and System.global
DD: there's also frames! (jokingly)
JHD: This is about breaking libraries like lodash, as well as breaking code which runs in Node. self has for a long time indicated that your code is used on the web, but it doesn't seem like a really big hazard; not much code for that. Also, self is used to store the receiver, though you can use arrow functions for most of those use cases these days. var self = this is a frequent idiom. Ultimately, if we pick self, Node is broken.
DD: We (TC39) make breaking changes to Node all the time. I think "breaking Node" is overstating it
JHD: This is a very common pattern, though it sometimes dispatches on window or module.exports.
DD: We already have a lot of ways to refer to the global. Do we really need another one? Further (lower priority), there is a distinction between the global proxy and the global object. Setting properties on the global scope sets it on the global object, but referring to it gets the global proxy.
(Discussing Domenic's concerns listed here: tc39/proposal-global#16 )
WH: How does this work across realms? The global object is a funny thing, as depending on where you evaluate it from, you may get different ones. If the global object is a proxy, is the system object also a proxy?
MM: The System object is very much like the Math object
WH: In an environment with multiple realms, there will be multiple System objects.
DD: (draws diagram to explain WindowProxy)
AK: Is this relevant to the System.global discussion?
JHD: I'll reiterate that this is not adding a new capability, as you can use the Function constructor; this just gives a way to do that without eval.
DD: Actually IE/Edge is restricted in a way that I don't understand for calling the function constructor in some ways
MM: This is one case where it's been hard for me to contribute to the web side of the standards world
BE: Ultimately this is about things like window.setTimeout (with a string so it will do eval)? Or what situations?
DD: Even executing a closure.
DD: WindowProxy is there so that, if you navigate a frame within another frame, the "window" object of that frame stays the same identity, so it is a "proxy" to an inner global object which changes on navigation. There's no way to access the inner object from within script.
JHD: Regardless of WindowProxy, System.global returns the global object, the same one that's accessed through 'this' or whatever else.
DH: Yes, this is the thing in the space of globalness that's relevant.
JHD: So we need a way to access the global 'this' value, a way that's the same across all environments. The function constructor can't be called from CSP. So we have two options--the bare 'global', or System.global. I haven't found anyone do typeof global
BF: Browserify's wrapper uses typeof global
JHD: But actually everyone uses 'typeof process' together with that when detecting Node-ness.
AWB: Two other options for names: Object.global
MM: I veto that as it would violate authority separation. I want to separate authority-carrying objects from non-autority-separating objects.
DD: But Object.proto is Function, which gives you the authority to get the global object anyway.
MM: Function and eval are evaluators; CSP gives you the option to turn off evaluators. Any other environment such as SES/frozen realms has to intervene in the evaluators in order to constrain the scope of the evaluation. In any such environment, the function constructor has to be sanitized.
YK: Doesn't that mean that we don't currently have authority separation, and you already have to do some work for this?
MM: We've addressed current pain points; let's not add to the burden.
AWB: A lot of this seems to revolve around the function constructor. Another place to hang this would be Function.global.
MM: Let's not spend time on things that are strictly worse
JHD: Mark has argued that this cannot be a global variable so that it's more easily secured.
DH: Sounds like a good time to bring in the Realms API and the global scope contour, which introduce additional concepts that want work in the language. It's an open area for discussion, where we might want to expose the actual current realm.
AK: There's something special about global. There's already three ways to access this thing; adding new ways is sorta bad. We're not adding a bunch of things; this is just accessing one thing.
MM: Right now, none of the ways of accessing global are not in the ECMAScript spec, and it's a beautiful thing that the boundary between the ES spec and the host corresponds very closely to user-mode computation and system mode computation. ES standardizes no way to cause effects on the outside world; the host provides bindings on the global object to cause effects on the outside world. Because the other things are put on the global, the global itself should be considered a host object that provides access to these things. Because there is no binding to the global object, nothing grants authority. There are several future proposals which do things like that.
AK: We don't have any of those. Global is special. There is some advantage to making the name short. Let's say it doesn't set a convention.
AWB: This should be a built-in module
JHD: So far, every time this came up, we said that we don't want to block it on this; once there's a standard modules proposal, we can consider this.
DD: We have a strong precedent for just calling this global. I want to understand your objection, Mark. It sounds like you're saying, let's not set the precedent of exposing a power object, when it's already exposed in reality in so many ways.
MM: Because it's not in scope in the ES spec, an environment could claim conformance to ES without exposing this.
DE: It is in the intersection of the various popular embedding environments, however.
JHD: I went with System.global because of the nonzero compat risk of bare 'global'. However, I haven't found any concrete compat risks. The second reason is that Mark thought it would help restrict authority to put it under a namespace.
YK: SES already has to care about this kind of thing.
MM: We currently have a whitelist in SES. global is not one of them.]
JHD: So if you're OK with not adding a global, you don't have to do anything to SES?
MM: I'm concerned about the maintenance cost and initialization time. Spec changes cause SES to trail, which users find painful.
JHD: But sounds like SES users will be protected anyway
AK: The difference between other things considered to add to System, Loader, etc and global is that they add new capabilities, whereas global does not add a new capability. It's just exposing an existing thing. Therefore it doesn't need to be added in a particular namespace, and doesn't set a precedent.
MM: I hope that frozen realms will be added and hide the global object.
JHD: It sounds like the requirement that it be under a namespace is not very strong, simply a preference
MM: "simply a reference is too weak. The issue of distinctions and psychological burden and precedent setting are pretty important.
DT: You're talking about the burden on developers?
JHD: I agree that they're real issues, but users already have the burden of having this reference.
YK: Given that you expose the global object, seems like it doesn't give a new capability.
MM: I'll have to think about this, but I can't approve that as a sound choice at the moment.
JHD: If Mark were to agree to Yehuda's point, if we changed the name to 'global', would anyone object to it with the name simply 'global'?
DD: I'd prefer 'self'
CM: no self
DD: Would prefer self
AK: 'global' seems fine. Most people don't seem to want 'self', Domenic.
YK, AK: This doesn't give any new capability as
JHD: Sounds like the next steps are for Mark to think through Yehuda's objection and see if he can support bare 'global', and for me to follow up with Mark, Dean and <who?>
Conclusion/Resolution
- Remain at Stage 2
10.ii.b Template literal revision to stage 3
Tim Disney
tc39.github.io/proposal-template-literal-revision
Reviewers: Mark Miller and Waldemar Horwat
TD: (recap) w/ tagged template literals, escape seq. illegal. Changes seek to allow
- Only change: tc39.github.io/proposal-template-literal-revision/#sec-static-semantics-template-early-errors removed the parametrization of the lexical grammar productions and instead enforce early errors via static semantics attached to the syntactic grammar. This change was result of Mark and Waldemar's review.
TD: Approval Stage 3?
Conclusion/Resolution
- Stage 3 approved
9.i.i ECMA402 formatToParts
Zibi Braniecki
ZB: Have implementation in SpiderMonkey, looking for a second implementor to proceed stage.
DE: To help formatToParts to Stage 4, ideal to upstream to ICU
CP: upstreaming to ICU should not be a requirement
AK: V8 not waiting for Stage 4
YK: The chicken-egg problem is about unflagging, not implementing.
ZB: Hoping Chakra, JSC, or any would implement
DD: What is the rush?
ZB: Not a rush, but the proposal has been ready for half a year. This is the last change that remodels the API. Everything else is new editions. This change opens abilities for cleanup.
YK: My opinion is that we've met the criteria
AWB: Do we have two implementations?
ZB: Yes
AWB: Compatibility issues?
ZB: Shipped in SM behind flag
CP: There are alot of new Intl features that need formatToParts
DD: They can just be dependent
EFT/RW: That's bogus.
AWB: There is experience from significant usage? Want to hear about that
ZB: Used in consumer facing product, Panasonic TVs running FirefoxOS. Proven that necessity to format is satisfied by this API.
AWB: With this exact proposal?
ZB: Yes
Implementations:
- Intl.js
- SpiderMonkey
ZB: The only feedback we've had is that developers want it in other browsers.
DE: Need to forward that feedback to other browser vendors
ZB: Want to plan for ES2017/402
RW: What is 262 cutoff?
BT/AWB: January/March (January for opt out, March for absolutely latest)
WH: I personally think you have enough implementation experience to advance to stage 4 now.
ZB: Can we advance to stage 4?
AK/DE: Some cases need 2 or more browsers, but this is not one.
Conclusion/Resolution
- Stage 4 Approved
- tc39/test262/pull/734/files
9.i.j ECMA402 Intl.PluralRules
Zibi Braniecki
ZB: Can we advanced to stage 3?
ZB: Both reviewers (CP and DE) have finished the review!
CP: Thumbs up!
DE: The spec text is complete. No worries in terms of performance and memory allocation.
ZB: All data needed for PluralRules to function are already in place, and used by Number and Date, no extra data is needed.
Conclusion/Resolution
- Stage 3 Approved
10.i.a Require Unicode 9.0.0
Brian Terlson
Patch: Require Unicode 9.0.0 instead of 8.0.0
BT: We can update every year, or change language
EFT: "use latest"
AWB: Normatively referencing a spec with no version means "the latest"
BT: There are no changes in 9.0.0. Committed to reviewing changes each year.
RW: The 402 editor will have to do the same task
(agreement)
WH: New Unicode case mappings might cause \p{}
(and especially ^\P{}
)
problems analogous to the \W
problem we recently encountered.
BT: This won't be added in the future, but they can't be "fixed" because they can't break compatibility.
DT: Should the requirements be clear for ES implementations?
BT: risk w/r to breaking change updating Unicode, larger possibility with
\p
- Unicode is reluctant to touch case mapping
- characters might move
DE: But these tend to be bug fixes?
BT: Still a risk of a breaking change
Conclusion/Resolution
- Do not merge the PR
- Use language for "the latest" ie. unbounded reference
- This should be applied to 402 as well
10.ii.c trimStart/trimEnd
Sebastian Markbage
SM: change from "trimLeft" and "trimRight" to "trimStart" and "trimEnd". Put an "alias" in Annex B?
SM: Web compatibility risk: the names of the functions changes.
DE: We changed a separately named Date method to an alias in V8 and didn't experience any web compatibility concerns, so I wouldn't anticipate any web compatibility issues here.
SM: We have other aliases in the spec; I was trying to follow existing precedent
JHD: e.g., Array.prototype.values/[Symbol.iterator]
AWB: If there was evolution of mainstream functions, the web compatibility functions
DE: Code is likely not relying on the name, likely not much risk
SM: Need reviewers
Jordan Harband + Daniel Ehrenberg
AWB: Spec for trimLeft/Right is the same as trimStart/End?
JHD: Exactly the same, only a name change
MM: That's the breaking change?
JHD: Yes, otherwise there is no issue
Conclusion/Resolution
- Stage 2 Approved
Array.prototype.values
Adam Klein
AK: We tried shipping Array.prototype.values and it broke some random Microsoft property, with the "'values' in" pattern
BT: We shipped it
EF: We didn't ship it on Release, but it's on Beta.
AK: Safari shipped it, but it seems like people who depend on Chrome are not shipping it. There's a switch between an object with a values property and an array. This is a general problem with adding a property to existing objects.
YK: We could add a function to get the values out.
AK: Chrome is not going to ship this any time soon, as we tried a year and a half ago and it didn't work, and we tried now and it didn't work.
AWB: This isn't a web interoperability issue; it's a Chrome interoperability issue.
AK: I'm not so concerned about it because it's not used so often, but it might make people sad that it's not shipped.
AWB: This isn't a new thing in the world of JS, but eventually everyone converges to standards, see IE/Edge
AK: Please do not add any more things to Array.prototype
BE: ES4 tried to do namespaces. Modules should give us a way to do this. I'm agreeing, we can't really extend things too much.
RW: what software?
AK: CRM Dynamics 2013
BT: It is fixed, but people don't update their on-premises software. They hire a contractor to install it, and then the contractor walks away. We tell them just use IE11 rather than Edge. You can configure a group policy to open certain pages in IE11
Conclusion/Resolution
- No change; Firefox will proceed with caution in shipping values.
10.iv.a Class Field Initializers: this semantics
Jeff Morrison
JM: main issues
-
Contextual things in the initializer scope.
-
Initializers execute at the time of the last
-
static field initializers are executed as the last step of class definition evaluation, need access to the class name binding itself.
(discussion of the scope of initializers)
JM: What should be available inside the initializer?
- Banning arguments, new.target (b/c unclear) -- these are static semantics
errors when occurring literally, and
undefined
in direct eval - Allowing this and super property access
YK: It would be confusing to have the old enclosing copies of new.target or arguments inside of the initializers, which run later
AWB: Can't you write "arguments" in computed properties?
YK: We discussed this in the context of the cross-cutting class proposal with Brian
- You might want this in a static property to refer to the class you just created
JM: There have been issues created in the Babel tracker filed about the scoping of this
AWB: In a static method this refers to the constructor function
- The constructor function that the static property is defined on
AWB: A consistency for static initializers for the left and right hand side of initializers would be to be "the same as in a static body"
JM: open q: "Do we permit or ban new.target or arguments in the right hand side of initializers?"
YK: This becomes tricky because some people expect that a field referecnes ambient bindings, but it's easy to get confused if you treat the initializer as a method
AWB: These initializers are very shorthand for a function, which always has new.target
MM: In favor of banning
AWB: A usecase is a static method on subclasses that filters the initializers, as called from a superclass constructor. In that case, you want to call |new.target.initializerFilter()|, and so want new.target to work
YK: Even though you can construct models which are consistent about which is which with new.target and arguemtns, it's equally hard to construct one that is unambiguously clear which one you are referring to
YK: This isn't a catchall; there will still be imperative cases that benefit from being written in the constructor
JM: If we ban them now, we can always add them later.
JM: We also need to decide what to do with eval('new.target')
MM: Presumably if it's an early error without eval, then it will throw early during the eval as well
(discussion of alternatives)
MM: Because this is a convenience tool, we can ban eval without loss of expressiveness. It's just a loss of convenience
DH: On instinct, this scares me. Just because we can't come up with a usecase, doesn't mean that something won't ever come up
WH: How deep would the direct eval ban go? Expression, subexpressions, within arrow functions inside subexpressions, ...?
DH: banning direct eval is hard, because it's undecidable whether it's direct eval
YK: Yeah, we'd have to ban the entire class of things that could wind up being direct eval
MM; The only reason we're allowing these outside of the constructor at all, is for common well-behaved cases
AWB: This of this as shorthand for function. If it was a function, all functions define new.target. When invoked you get undefined. Functions have arguments. There are no functions. If you just treat an initializer like an anonymous function, then you get exactly everything falling out
DE: If you treat it like just a method, then you get everything you want
AWB: This avoids a laundry list of special cases
KG: What about statics? The easy corolary is that for statics, it's an anonymous static method.
YK: This also allows for sane semantics for this
KG: (whiteboard)
class Base {
prop = new.target.filter ? new.target.filter(val) : val;
}
class Derived extends Base {
static filter() {}
}
AK: Does this restrict impl ablitie to optimize away? No, we should be able to statically determine whether eval or arguments are possible.
EF: This is a simple front-end optimization.
Consensus: Initializers run with the semantics of individual anonymous methods with no arguments being run on the class. That explains the scope of this and super property access; new.target would be undefined, and each would get a new empty arguments object.
JM: Do properties get created with DefinePropertyOrThrow() or Set()?
(whiteboard)
class FooText extends TextNode {
textValue = "asdlsk";
}
YK: Users would likely expect to get a Set; most users don't understand setters, and would expect that setters are always called
WH, MM: Would be really surprised by a Set in this example. The intuition is for initializers to use define.
JM: You could phrase this either way; either it's a hazard, or it sets the expectations that users can depend on a predictable DefinePropertyOrThrow.
WH: The reason why Set doesn't work is that it's not extensible to const, to typed properties, all of these can only be done on DefinePropertyOrThrow
textValue = "adadad"
^^^ Authors don't immediately recognize that the difference between Set() and DefinePropertyOrThrow()
WH: Can't use Set() to define const or typed properties. Only DefinePropertyOrThrow will work.
MM: A frozen data property, overriding with Set() will throw
JM: Having spent some time on this, I think neither is more intuitive than the other. People are very split on this. So as an argument for which is more intuitive, that's a wishy argument. We should go based on what is more useful.
AWB: If you define a method named textValue, you can't
BE: = looks like Set
AWB: So we should use colon
YK: Colon is reserved for type annotations
BE/WH: the only robust semantics is DefinePropertyOrThrow()
WH: Only DefinePropertyOrThrow will work across future extensions, for const properties and typed properties
- evaluate the type, around time of initializer, can't create it and later change type, so it MUST be created with DefinePropertyOrThrow()
SP: How is this conflated?
MM: The idea that an initializer does a Set(), but a const does a DefinePropertyOrThrow() is just (confusing?)
MM: We already have in ES6 practice for how to initialize objects
imperatively, with this.textValue = "asdf"
inside the constructor. That's
imperative, that does a Set(), it has all the properties that Yehuda is
advocating. Any proposal that adds new syntax should, to justify the cost
of the new syntax, it should have less overlap with something you can
easily say already.
this.textValue = "...";
...is a Set()
YK: This is shocking. That means that you are saying we shouldn't have symmetry
MM: I value symmetry, but I don't see a symmetry argument. Leaving aside BE's point about the token, for object literals, all properties in object literals are initialized with DefinePropertyOrThrow
YK: But most people will have the imperfect but good-enough mental model to view this as a desugaring to this.textValue = ...
BE: This isn't true, as object literals already do something different compared to manipulating the object, if you put a setter on Object.prototype
YK: But that is suprising to many useres
AK: What about developers of other languages who define fields and expect those to not trigger setters (as in other languages, where setters don't happen when you declare fields)
MM: This is just like an object literal. Writing object literals has the same problem.
YK: That's different because object literals don't have superclasses. People don't use proto: very much
BE: What's the robust, future-proof semantics? Seems like DefinePropertyOrThrow, as Waldemar says.
DE: If you subclass an HTMLElement and try to define an onclick, that would be fired either
JM: What about :=
SM: Having setters already be there is one use case. The primary use case is turning an existing property into a setter or getter, to shadow something else or make something lazy. If that's the upgrade path, then this will break.
DD: That's a good point; people do deprecations by adding setters or getters, and that would fail because it would just shadow
MM: If the semantics of this is Set, I would ask, what is the added value of the proposal as a whole such that the proposal pulls its weight. You could get these semantics just by writing the right lines in the constructor.
DE: Good from an optimizability stand point. We've been encouraging people
to be explicit about properties on this
by adding them all in the
constructor, assigning undefined
if necessary. This is a nice synaxt for
that.
WH: Using Set() is dangerous, if derived class has foo, exposes you to a super class that didn't have accessor foo, which is later added.
YK: Lots of classes which are designed to be subclassed assume that they can intercept Set()s
DT: Initialization in C#, Java, etc is explicitly settting up the world and invariants aren't there
DD: For us it's different, because super has already returned, etc
DT: Using DefinePropertyOrThrow is good because it'll give us that capability from other languages, where you add the properties without invoking setters.
SP: In the current proposal (with Set), it's the same as doing the code in the constructor, so the constrained DSL is nice because it is not so order-dependent, right?
JM: Sounds like we won't resolve the issue in this meeting; I'll work with some people offline to come to more of a conclusion on this.
JM: The last open question: For fields that do not have an initializer, these implicitly initialize to undefined, not copying this.x = this.x as previously. I went back and forth on this; one of the reasons I was against this is that I was concerned about shadowing the same-named property on the parent class. But what convinced me is that, presumably, if you put that declaration there without an initializer, you would intend to initialize it later at some point, in which case you would be shadowing the parent property anyway. So the expectation is that, when you put the field there, you will be shadowing the field above it. So the initialization happening in order makes sense.
class FooText extends TextNode {
textValue; // textValue = undefined;
}
WH, AWB: Good.
AWB: In lexical scoping, we decided that the same name in the same scope would always refer to the same binding. The analogue here points in this direction as well.
JM: Cases where it's useful to define the value of a child in terms of the parent property value...
this.x = this.x + 1;
AWB: Suggest creating the fields first, presumably undefined, then assign.
WH: Separating creation from initialization is not future compatible with const or typed properties either unless we want to do something equivalent of a TDZ for properties, which I don't.
WH: Back to JM's original question, the only sensible thing for a field declaration without an initializer to do is to create the field with the initial value undefined.
DD: left hand side of computed property evaluates once (for definition), the right hand side many times (for instantiation)
[this.counter] = this.counter++;
JM: concern about syntax, further syntax might help solve, will consider
AWB:
DD: It should be consistent with fields
JM: I see the analogy with methods as being stronger. Anyway, most use cases will be with Symbols.
AWB: Want consistency across the whole construct, whether method, field or getter/setter
AK: This isn't thought of as a statement, but rather as a declaration, so the evaluation of the computed property names gods with the other declarations
(discussion re: transpilers)
DH: "identifier : identifier" currently means type annotation
w/r to this ^^ tc39.github.io/ecma262/#sec-forbidden-extensions:
The Syntactic Grammar must not be extended in any manner that allows the
token : to immediate follow source text that matches the BindingIdentifier nonterminal symbol.
JHD: Babel is doing fine with Set, this scoping, etc, and we should take that as a datapoint. No user complaints.
MM: Should the properties be defined as configurable or non-configurable?
JM: Currently it creates a non-configurable property with DefinePropertyOrThrow
YK: Seems strange why we would do it differently from methods
MM: I strongly prefer non-configurable. We already have an imperative syntax for imperative initialization, properties that are configurable and disappear. The time-dependent nature of configurable properties don't give you as many guarantees. Non-configurable properties lets you minimize gratuitious differences with private state and get static analyzability and static shape. The behavior of private fields is more like a nonconfigurable property than anything else.
AWB: I support your position, but in addition: one of the advantages of this new syntax, is that it allows to declaratively define the shape of the object.
- Value in readability
- Make non-configurable is a powerful value
AWB: what happens when a super class has already defined one of these? When they are configurable?
MM: Silent replacement
- Prefer: two declarations of the same own property, an error.
- Set() alone doesn't produce an error, DefinePropertyOrThrow() alone doesn't produce an error.
DE: super constructor might return a Proxy
EFT/AK: Implementors can't infer more about shape than before
JM: Objections to Stage 2?
AWB: I want to see this and private fields merged. I don't think we should advance either on their own to stage 3.
Conclusion/Resolution
- Initializers run with the semantics of individual anonymous methods with no arguments being run on the class. That explains the scope of this and super property access; new.target would be undefined, and each would get a new empty arguments object.
- No consensus on Set() vs. DefinePropertyOrThrow()
- A field with no initializer should create the property with the value undefined
- No consensus on configurable vs non-configurable
- Revisit initializer token choice of =
- Stage 2
10.iii.c [Nested import declaration](
benjamn/reify/blob/master/PROPOSAL.md)
Ben Newman
BN: Potentially relaxing restriction that import
can only appear at the
top level.
BN: proposal would allow import
s that are nestable; hoisted (declarative
over imperative); lexically scoped; sync evald; back compat.
BN: We have been shipping this to the Meteor community in a transpiler context. The semantics are more subtle than you would expect to allow, due to the subtleties of modules. They are synchronous (hoisted to the top of the scope) and backwards compatible.
MM: [clarifying that bindings are immutable on the import side]
YK: [clarifying that currently proposal is transpiled to commonJS require]
… discussion about the spec; request to skip the spec discussion at this stage …
AWB: How about we consider these to be ordinary lexically scoped variables?
WH: If I sit inside a loop, importing a module mutiple times, will I get the same module namespace object?
BN: Yes. In subsequent iterations, it doesn't get imported again
WH: Is the module specifier still restricted to only being a string literal?
BN: Yes.
DH: in this proposal, no matter what, all imports will be loaded beforehand. it's only that evaluation will be deferred until it reaches that point in the code.
AWB: do you hoist evaluation as well as instantiation - i would expect that hoisting for consistency with top-level imports
BN: the ability to have nested imports gives you a tool to control relative execution of import declarations to other statements
WH: Yes, that's the Optimistic Imports example from the proposal.
YK: DH's point is important. If you want predictability, you do not want interleaving.
BN: Modules get all loaded before the program starts. Their instantiations are done as their blocks are encountered in the program.
WH: So then what happens if a module is missing when being loaded? How do Optimistic Imports work?
BN: necessarily an error if it fails to load.
BN: … talking about a use case for cross-env code with conditional imports … if it turns out that the fetching of the module source fails, it is entirely conceivable that the dev knows this was a possibility and that that import is inside a conditional block that prevents it from evaluating
- so i think it's less fatal for the fetch to fail.
YK: an important use case for this is "if i'm in env X, import stuff for env X"
DH: proposal: we unconditionally do all the fetches, but if any fail, we don't actually fail - just hang onto the error for later. and only if control flow reaches the point where it's needed, does it end up being an error. iow, if you only have conditional imports, failures will not create a compile time error, and only create a runtime error when the module is needed and missing.
AWB: consistent with the current spec.
AK: changing what used to be early errors into not-early errors.
AWB: i mean consistent in that it treats each block as if it's its own module.
YK: ?? conditional importing means the dev knows it's benign if it's missing, and can work around that.
BN: … explaining "isolated scopes" example … ability to reuse identifiers in the same file, but in separate scopes. With top-level, you need slight identifier variations.
SP: also refactoring hazard - if the imports are in the describe, it's easier to split up large files without breaking things.
BN: in top-level model you still have to do all the same fetching
CP: at what point in this program is the error triggered? we intentionally chose declarative import evaluation as well as initialization/loading.
BN: the specific "it" test in my example will fail if the import nested inside it fails to load.
BN: it should fail every time it's import is attempted
DH: it should be possible via the registry to clear things out and make it possible to retry, but only in a staged way - ie, you have to kick off an evaluation, not in the middle of a module.
BF: in node, if it evaluates, it's put into the cache; if it fails to evaluate, it's not put into the cache.
… discussion about entire dep graph being resolved before any evaluation …
DT: … general argument that nested imports would have to be VERY compelling to make it worth it …
AWB: what about imperatively using a dynamic import API?
DH: loader API does not let you statically express dependencies, so we talked about a syntax that allows dynamic async importing
… more discussion ?? …
DH: inherent conflict with top-level await
BN: I think the dynamic syntax you're proposing is essential for top-level
await. what would happens with current import
if you pull in a module
using top-level await
?
CP: top-level import
would handle it
DH: essentially forks the world - ie, "modules that can use top-level await" and "modules that can't"
BN: still some motivating examples worth talking about
BF: a point: top-level await is going to pretty much wreck node's sync loading anyways
BN: if top-level await turns out to be infeasible, then the conflict here is moot, but still worth talking about
YK: my concern is that it makes loading unconditional + evaluating conditional, and i think conditional loading is important too
BN: skipping over "lazy eval" claim. will note that in node, which has sync i/o, pushing requires into functions has helped startup perf (likely from deferring the i/o)
SP: depends on the complexity of the file you're importing
SM: biggest perf problem at FB is parsing and initialization. we load everything and only evaluate the things we need. we can't switch to modules without lazy eval + lazy loading.
BN: i think it will not interfere with lazy loading.
BN: if you treat all module identifiers the same, then you don't have to parse the whole file, you just have to tokenize it and look for "import" tokens.
EF: i think you grossly underestimate the costs involved.
… discussion about tokenizing vs parsing; costs thereof; etc …
BN: in my naive understanding of tokenizing and parsing, you could
tokenize, iterate, locate import
, locate the possible path - then
optimistically parse that path whether it's a module or not.
AK: unless you're talking about throwing away all module early errors, you need to know the exports, so you still have to parse. your approach only would allow easier fetching.
BN: if i'm wrong about the tokenizing trick, it still doesn't matter where the import declarations are
YK: i think the point is that if it turns out that conditional import …
SM: what matters is "do you do the fetch if there's a syntax error"
CP: Do we need to have a user make a change to allow for this tokenizing optimization?
BN: The optimization is orthogonal
DH: He means deferring evaluation
BN: That seems unsafe to me.
BN: Colocating imports and code should be good long-term for code hygiene because it should keep the things together and help you as you move the code around. And of course you can keep putting them all at the top level if you want.
BN: Further justification: Put an import in a try/catch block in case you have fallback behavior.
SP: But what if it's not the first time? This scares me. You don't get the chance to execute your fallback behavior.
MM: Maybe you should remember the throw and rethrow if it failed.
CP: You were saying that it should go to the top
BN: To the top of the block. It will still throw from within the try block.
AK: To me, this looks like a nested module. It seems like it would be a module in the tree which fails.
BN: Another benefit is dead code elimination--you can avoid running the code by importing only when needed, and this then doesn't run the top-level statements.
AK: Dead code elimination will be approximate in JavaScript. It couldn't be done by implementations, but could be done by preprocessors which are OK with changing semantics.
MM: Is it valid to eliminate the fetch?
BN: Technically these change semantics, but may be OK for the application.
BF: Module resolution may not include fetch; for Node, things will be pre-populated
YK: We did a lot to support the web's asynchronous fetching.
BN: Yes, we needed to support browsers. Nested import declarations seem problematic mostly because of the browser and asynchronous fetch.
BN: I have a grammar in the proposal. Import is not allowed in non-modules. There is a PR, I invite people to participate there. Nested imports from scripts are prohibited with static semantics.
BN: We have settled on declarative imports, hoisting them. But nested imports give you a tool for doing imperative imports, though no deferred fetching and specifiers are literal
BN: Stage 1?
DH: Suggested area of exploration: await import
async fn() {
await import {x} from m;
}
AWB, YK: We should merge this group with the loader group to come back in a few moths.
AK: I'm surprised you're not upset about it being a promise.
DH: But the Promise is not reified
BN: I would prefer synchronous semantics, if possible, but we could live with this. For one, it would be nice to run successive import lines in parallel.
Conclusion/Resolution
- Does not reach Stage 1; a synthesis proposal will be pursued at a future meeting. Remains at Stage 0.
July 28 2016 Meeting Notes
Brian Terlson (BT), Michael Ficarra (MF), Jordan Harband (JHD), Waldemar Horwat (WH), Tim Disney (TD), Michael Saboff(phone) (MS), Eric Faust (FST), Chip Morningstar (CM), Daniel Ehrenberg (DE), Leo Balter (LB), Yehuda Katz (YK), Jafar Husain (JH), István Sebestyén (IS), John Neumann (JN), Domenic Denicola (DD), Rick Waldron (RW), Stefan Penner (SP), Jonathan Sampson (JS), Caridy Patiño (CP), Sam Tobin-Hochstadt (STH), John Buchanan (JB), Kevin Gibbons (KG), Lars Hansen (LHN), Tom Care (TC), Dave Herman (DH), Bradley Farias (BF), Kris Gray (KSG), Adam Klein (AK), Dean Tribble (DT), Eric Faust (EFT), Jeff Morrison (JM), Sebastian Markbage (SM), Saam Barati (SB), Kris Gray (KGY), John David Dalton (JDD), Ben Newman (BN), Morgan Phillips (phone) (MP), Shu-yu Guo (SYG), Paul Leathers (PL), Ben Smith (BS), Zibi Braniecki (ZB)
10.ii.a Shared Memory And Atomics
Lars Hansen
LHN:
Agent Semantics
Blocking: an agent can block waiting to be woken without rturning to its event loop
Web awareness: an embeddinging can deny some agents the abiluty to block (eg. browsers man thread)
Forward progress: agents must eventually advance if
All agents die at the same time
SharedArrayBuffer
- New Data Type
-
Like ArrayBuffer
- map TypedArray and DataView onto it
-
Unlike (see slide)
-
Sharing Memory
Atomics
The global Atomics
namespace has static methods that operate on
TypedArrays
Atomic access:
load
store
add
sub
- `and
or
xor
exchange
compareExchange
BF: Is it possible to have another worker store between wake
EFT: Yes
DT: A spin instruction that doesn't spin, on x86?
LHN: Yes
- Investigated
pause
as a lightweightwait
, that wouldn't go into a spin, but wait
for a short time- if hot
wait
, could've usedpause
before going into await
- you could use
pause
instead of direct intowait
(I'm not sure I captured this as well as it could be, wuold appreciate more eyes/brains to revise appropriately)
Memory Model
... see slide
Challenges
... see slide
Opportunities
ES is "easier" than C/C++
- Performance demands slightly lower
- Shared Mrmory sep. from non-shared
- Only flat shared memory, no pointers or objects
... see slide
Two Level memory model 1
Conventional axiomatic high level model
- Defines sync accesses
- sync order
- "happens=before" relationship
... see slide
Two Level memory model 2
... see slide
Synchronization Order
... see slide
Viability 1
... see slide
Viability 2
... see slide
LHN: WH found an important bug in the memory model's definition of viability that causes the synchronization order to not be well-defined. Without a well-defined synchronization order we don't have a workable model. This will require a rewrite using an operational approach instead of the current two-phase viability and synchronization approach.
LHN: [talking about slide] Races "leaking" into the memory model of the sequential language.
WH: Agree that they don't leak (and must not leak). The price we pay for that is significant loss of opportunities for optimizations. It remains to be seen whether that's a reasonable price, but I assume it is for now for the purposes of this proposal.
LHN: [talking about slide] Security issues are the "cost of doing business" of shipping shared memory, at least according to one major browser vendor. Mozilla is less sanguine about that.
MM: Is there any way to ameliorate this?
LHN: Add a switch to settings to turn multithreading off.
(discussion, re: changes that need to be made)
WH: The memory model will need to be rewritten.
?: Why rewrite? Can't we just fix the bugs that WH found in the presented memory model?
LHN: What I just presented is the new memory model I'm developing to fix the bugs, not the one currently in the spec.
- Avoid a circular
WH: What was in the spec had fundamental incorrect assumptions such as defining viability as a separate phase before synchronization, or the ability to put all memory accesses (including non-atomic ones) into a global total order, which just isn't true.
WH: We all agree on what the simple cases where everything is synchronized properly ought to do, such as what happens in an atomic load that sees the result of a prior atomic store. It's in the other cases that need to be nailed down where the big memory model issues lie.
SYG: How to test?
- An impl to be compliant, must be able to observe the memory model
- Is that possible?
BS: without particular axiom, here is X that breaks.
SYG:
STH: Write the memory model, rep. all the legal executions. Run X times, ensure that all
SYG: How to test the actual implementation
Conclusion/Resolution
- API freeze granted?
- Stage 3 after Waldemar is satisfied with rewrite of memory model
10.i.b Disregard lastIndex for non-global non-sticky regexps
Leo Balter
PR from Claude Pache tc39/ecma262#627
LB: The change is: "don't do the lastIndex step unless isn't actually necessary" tc39/ecma262#625
DE: Global regexp don't make sense when frozen
- Some programs freeze regexps, unsure why.
- This is in use, received bug reports
(discussion, re: how long this might've been allowed?)
AWB: user freezable properties and strict mode introduced in ES5
DE: Doesn't make sense to read/write lastIndex unless actually necessary.
AWB: Could break something
DE: True
- The plan is to attempt the fix, ship on chrome/canary and see what happens
AWB: (recapping the proposed fix)
LB: This PR also adds a change to avoid get and ToLength operations on lastIndex for the same regexps. A poisoned RegExp lastIndex property wouldn't affect it.
function test(rx) {
rx.lastIndex = { valueOf: function () { throw "ok" } }
try {
rx.exec('foo')
}
catch (e) {
if (e === "ok")
return true
}
return false
}
LB: After this patch, a test(/a/)
should return false.
MM: That does not only address the web compatibility issue, but does a clean-up on the lastIndex.
Conclusion/Resolution
- Merge it
- Implement in canary and report what happens
10.iii.d Object.shallowEqual
Sebastian Markbage
sebmarkbage/ecmascript-shallow-equal
SB: Problem...
Memoization
... see slide
function eq(a, b) {
return Object.is(a, b);
}
function memoize(fn) {
let lastArg, lastResult;
return function(arg) {
if (lastArg !== undefined && eq(lastArg, arg)) {
return lastResult;
}
lastArg = arg;
lastResult = fn(arg);
return lastResult;
};
}
function calc(obj) {
return obj.x + obj.y;
}
let memoizedCalc = memoize(calc);
let obj = { x: 1, y: 2 };
let res1 = memoizedCalc(obj); // slow
let res2 = memoizedCalc(obj); // quick
let res3 = memoizedCalc({ x: 3, y: 4 }); // slow
SM: Would like to be able to compare only the own property values
WH/MM: (discussion about concerns and objections that have been previously discussed)
YK: Does this anticipate being faster on value types?
WH: As an evil villain I love the ability this might give me to compare the internal variables captured inside closures [scary emoji]. Mwa ha ha ha ha!
MM: That's one of the issues I had raised.
YK: ?
SM: Most of the time, returns false.
YK: (equating semantics to memcmp)
AK: No, memcmp is just implementation suggestion
MM: The semantics:
- If the answer is true, guarantees follow
- If returns false, no guarantees follow
YK: The guarantee using Object.is?
MM: Uses identity
SM: Compare objects across realms is also a question
YK: Ok, the intended implementation is memcmp
(confirm)
FST: There's a browser war on. If [browser x] returns true 30% of the time in this case, then I must return true at least 25% of the time.
AWB: Are there other approaches you could use to obtain much better performance?
YK: The whole thing is a performance detail which we don't really specify. There are some things that look like value types but in fact have expensive === operations.
AWB: We chose to have multiple representations of things like strings for performance reasons. Now they will cost us. It's hard to specify semantics.
FST: As a browser vendor I don't want to constrain otherwise efficient representations due to the performance implications of wanting to return true from this feature.
MM: This is affected by the transposed implementation of weak maps.
WH: And it leaks information about what's in the weak map.
MM: You'd want closure state to not be part of the comparison.
MM: We want to store private state in object slots, but we want object scans to not reveal anything about the private state.
FST: Implementations will need to distinguish different kinds of internal slots anyway.
WH: This presents similar issues to NaN comparison, but for strings. As the example in the presentation showed, now you can figure out the pedigree of whether a string was constructed in one piece or as a rope by something on the other side of an abstraction boundary — something that must not be leaked for security reasons.
BE: leaking string implementation details (Rope vs. Flat representation) has been constructive for Heartbleed-like security attacks in past.
STH: evidence of the code you've written being slow enough
SM: no evidence yet
AWB: Here's another path... bring the slow path code to implementors and try to optimize in the runtime. Then with this experience, determine a proposal for language or built-in library changes
SM: Will try
WH: Do implementations ever store hashes along with strings to be able to quickly determine that they are not equal?
FST: We intern some strings, but not all.
(discussion, re: hashing, string interning)
YK: MM, are you not worried about the moving gc leak?
MM: I am.
YK: Moving GC... do a comparison, it's true. The object is changed by gc, and becomes false
STH: No
EFT: If there is a concrete case that shows instability, we can explore
WH: Can discover if implementations do lazy string interning
MM: Do meet S1 criteria, but not worth trying to move this forward because this doesn't have a chance of advancing further. Identified real issues, that we can find a way to address. Sam's suggestion might be the only viable
STH: Actual shallow comparison, implement that in VM and work on optimizing.
AWB: Essentially same as my suggestion
Agreement, but comments from implementors that I didn't quite catch
SM: Object.assign could be done much faster in VM, WeakRefs... Plausible to find other ways to accomplish same thing. Difficult reach non-leaking solution.
MM:
Something about exploring alternative solutions
It's hard to hear because they are across the room and basically mumbling as far as I can tell. Mark is facing away and it sounds like "mmph mm-mmmph err mmph foo sh mmph sh"
(discussing "fast")
YK: VM authors recognize security issue of fast
MM: How much slower would be an accurate implementation of shallow comparison be?
SM: Would it be possible to expose the ability to compare shapes [or use the shape as a key in a map]?
MM: The nondeterminism arguments apply to anything that assumes same shape.
Conclusion/Resolution
- Explore STH/AWB recommendations
10.iii.b Promise.prototype.finally
Jordan Harband
ljharb/proposal-promise-finally
JHD: (presenting from the link above)
AWB: How would a user write something that is rejected from a finalizer?
WH: What does finally return?
JHD: A new promise
DD: Conceptually wrong to overwrite return values
YK: There is control flow model and have way to...
WH: How does this interact with thenables?
JHD: If the finally return value is a thenable that's resolved normally then it gets replaced with the prior resolved value.
WH: Does this introduce a notion of finally-able with parts of the system probing for the presence of a "finally" method analogous to what they do with probing for a "then" method?
MM/JHD: No, just like we don't have a "catchable"
JHD: (explanation of naming, can be reviewed in proposal)
BE: names are metaphorical and analogical, not only identical up to isomorphism; finally seems good to me.
- Existing implementations noted as well
MM: Some "wrinkle" in Q?
JHD: Will identify and note if necessary
DD: Could be naming, ie. "fin" for ES3?
BE: promise'finally'
JHD: No conflict re: cancellable promises proposal
YK: Might be good to have finally in language, before 3rd state
JHD: Same
- Devs can proactively use finally where semantics match
YK: Might be hard to convince that finally is the right thing to do
AWB: Why wasn't finally included in ES6?
YK/MM: The ES6 Promise feature was "maximally minimal", so finally, along with others, eg. queue, were postponed
JHD: Stage 1? Note that this meets the Stage 2 requirements.
JHD: Stage 2?
DD/DE: There are issues that need to be addressed in this spec text
JHD: changes needed in this spec, to reach Stage 3
- PromiseReactionJob needs attention
MM: Want to revert my Stage 2 agreement...?
JHD: (cites Stage 2 from process doc)
MM: (something about Stages)
JHD: If I get Stage 2 now, I can work towards Stage 3 in September
(General discussion about process)
YK: We frequently have disagreements about the process.
DD: Disagreements on process aren't helpful
AWB: Don't wqant to jump feature two stages in one meeting
YK: The criteria is met
- I want criteria that's objectively applicable
AK: The criteria is "there is spec text to review"
JHD: Since this was on the agenda for May, then everyone diligently reviewed—Right?
AK: There is no review requirement on Stage 2 spec text. Achieving Stage 3 requires review and revision, etc.
JHD: So, AWB objects to Stage 2 on the grounds that it's two stages in one meeting.
AWB: Won't block if the rest of the room wants to advance
WH: Have no objection to this, but in the future I'd love a prior notice on the agenda for any item that wants to jump more than one stage so I can look at it much more carefully before the meeting.
Conclusion/Resolution
- Stage 1 approved
- Stage 2 approved
10.iv.b Cancelable promises update
Domenic Denicola
DD: Major change: third state
- A new completion type is unable o achieve consensus
- Concern:
try {
f();
g();
} catch (e) {
h();
}
A new exception that is not an error: Cancel
- Does not subclass Error
- Branded with a [[CancelBrand]] internal slot
- Does not get reported to the host
- window.onerror
- process.on("uncaughtException", …)
- Does not get tracked as an unhandled rejection either
- throw Cancel("message")
Making it easy to treat cancelations as non-errors
Bad code...
try {
await fetch(...);
} catch (e) {
if (!(e instanceof CancelError)) {
showUserMessage("No data for you, sorry.");
}
} finally {
stopLoadingSpinner();
}
Proposal:
try {
await fetch(...);
} else (e) {
showUserMessage("No data for you, sorry.");
} finally {
stopLoadingSpinner();
}
// Also, Promise.prototype.else
Addresses the new code, old code issue, because no old code will have this form,
JHD: (question about brand checks)
WH: Can you do try/catch/else?
DD: No
JHD: Any catch cancel?
DD: No, this is everything but
Cancel token’s cancel() always creates a Cancel
const { token, cancel } = CancelToken.source();
cancel("message");
// internally does: new Cancel("message") and stores
token.throwIfRequested(); // throws the stored Cancel
token.promise.then(value => {
// value is the stored Cancel
});
MM: Then still invokes the second callback?
DD: Always has been
- source of bugs
- throws happen, people expect their catch handler to be called
MM: I disagree with your opinion on the usefulness of .then
's second
argument
DD: it's more of a power user feature.
DE: This works better with the two argument then
. previously there was a
back compat concern (with third state), and with this proposal, it's more
compatible with 2-arg then.
MM: Having else
in relation to then
..,
Cut off by other members who are time constrained
BE: Is dependent on state of the stack?
DD: No
DE: Sounds like this is analogous to then/else, letting cancels propagate, where 'then' handles the next try and 'else' captures the non-cancel reject; I think this is consistent with the two-argument form
DT: A wants to suppress errors if A is being canceled, regardless of what B does. If B errors, it goes up to A and A can decide what to do.
DD: I recall this concern, I disagree that this matches all reality
DT: Back to try/else. Q: try this thing and my local token is cancelling, suppress error, otherwise...
- Need
MM: The test: is it a cancellation?
DT: A cancellation is a fine way to implement shut down
- Need to allow the shutdown, avoid thrashing
DD: Experience shows that it's important to suppress the...
DE: Sounds like the disagreement between Dean and Domenic is whether to just supress the one cancellation, right?
MM: Asking for: source of information is a distinct thing, expanding the syntax taking into account the token as a source of information.
DT: I'm saying we can get a syntactic form that can do both
DD: I'm only trying to address this problem,
DT: (describing example of cancellation where a download was stopped, but results in a parse error of the incomplete download the contents)
YK: hard to imagine a library creating a cancel token... (I missed the entire scenario, Dean started talking)
DT: I create a file and a cancel token and hand the file to the parser, then trigger the cancel token, which stops the parser. For example, stopping a page
DD: Stopping a page is a bigger deal
BE: (asking for summary of what needs to actually be address)
DD: The question is, is there an unobtrusive way to have syntax that provides the semantics that Dean wants?
DT: The Question: The indirect cancellation, does it turn into an error?
DD: Don't think we need to address the case of "buggy code"
- Part of why no longer championing try/catch/else
DD: The concern is about calling into a library which, you cancel the library's overall operation, and it gives you an error rather than a cancellation. The conclusion is that that is very hard for the library to do; these syntactic affordances make it hard to do as you'd have to do a catch, followed by a brand check, which is intentionally hard.
DD: I'd like the committee's feedback on the full spec, which is now much smaller due to fewer modifications to promises, etc.
DD: Some more ideas on making Promsies more ergonomic: Make cancellation easy in async functions.
More Ideas...
- Inserting cancelation opportunities into async functions
Simplest case, pass the token:
async function cancelMe(cancelToken) {
doSyncThing();
await doAsyncThing(cancelToken);
await anotherOne(cancelToken);
}
What about uncancellable things?
With the current proposal...
async function cancelMe(cancelToken) {
doSyncThing();
cancelToken.throwIfRequested();
await doAsyncUncancelableThing();
cancelToken.throwIfRequested();
await anotherOne();
}
Probably want...
async function cancelMe(cancelToken) {
doSyncThing();
await Promise.race([
doAsyncUncancelableThing(),
cancelToken.promise.then(c => { throw c; })
]);
await Promise.race([
anotherOne(),
cancelToken.promise.then(c => { throw c; })
]);
}
...But that's gross.
This is better:
async function cancelMe(cancelToken) {
await.cancelToken = cancelToken;
doSyncThing();
await doAsyncUncancelableThing();
await anotherOne();
}
Defines a new meta property:
await.cancelToken
MM: Which awaits does that change?
DD: The ones afterward?
DP: How do you get rid of it in that execution?
DD: Set to null
SP: An await inside an arrow function?
- Carry over?
DD: Syntax error
DT: Do uncancellable thing might be multi-turn, the only reason for race is you might want to do the stuff after to as a result of cancellation (I need that double checked, I don't think I got it correctly)
(We're looking at...)
async function cancelMe(cancelToken) {
doSyncThing();
await Promise.race([
doAsyncUncancelableThing(),
cancelToken.promise.then(c => { throw c; })
]);
await Promise.race([
anotherOne(),
cancelToken.promise.then(c => { throw c; })
]);
}
DT: Moves final behavior from the end, to middle
DD:
DT: The conse. not obvious, not possible to test, is the "re-ordering"
DD: Not reordering
DT: it's fundamental reordering. You're moving something that is syntactically ordered, to execute out of order
YK: When async thing, await means "some promise". await.cancelToken is a new promise.
EFT: (confirm)
YK: Arrow functions do not inherit await.cancelToken because they do not generally inherit control-flow (like return) and async/await is control-flow
...
SP: There is a potential memory leak to discuss.
DD: CAn we defer that?
SP: Yes.
(discussion, re: es-discuss request for changes to this proposal)
SP: Scope of cancel? Race and All
DD: coming...
(next)
With the proposal as it is:
function delay(ms, cancelToken) {
return new Promise((resolve, reject, cancel) => {
const id = setTimeout(resolve, ms);
if (!cancelToken) return;
cancelToken.promise.then(cancelation => {
cancel(cancelation);
clearTimeout(id);
});
});
}
JHD: Would have to pass cancelation through that cancel function?
DD: Yes
Similar for XHR...
function xhrAdapted(url, { cancelToken } = {}) {
return new Promise((resolve, reject, cancel) => {
const xhr = new XMLHttpRequest();
xhr.addEventListener("load", () => resolve(xhr.responseText));
xhr.addEventListener("error", () => reject(new Error("could not XHR")));
if (!cancelToken) return;
cancelToken.promise.then(cancelation => {
cancel(cancelation);
xhr.abort();
});
});
}
DD: Note using new Promise
which really only used when your doing async
that doesn't use promises
New API:
function delay(ms, cancelToken) {
return Promise.cancelable(cancelToken, resolve => {
const id = setTimeout(resolve, ms);
return () => clearTimeout(id);
});
}
SP: want to make async function cancelable...?
DD: Still use promise constr with legacy code that doesn't use promises
DT: question about [token].promise.then...?
DD: Come back to it.
Cancel Token Composition?
Precedent from .NET:
const { token, cancel } = CancelToken.linked([ct1, ct2, …]);
Here token is canceled if any of the following is true:
cancel() is called
ct1 becomes canceled
ct2 becomes canceled
…
I haven’t really investigated what this is used for in the .NET ecosystem…
The extra cancel() seems useless and an artifact of the .NET setup, so instead:
.NET’s version but a little better
const token = CancelToken.some([ct1, ct2, …]);
Here token is canceled if any of the following is true:
ct1 becomes canceled
ct2 becomes canceled
...
Still unsure what the exact use cases are, but it seems plausible.
DD: Call it "some" or "any"
SP: The leak: scenario where cancel token is much longer lived thatn the code being canceled.
DD: You have one cancel token with long lifetime and components with shorter lifetime
YK: In Ember's cases, you rapidly get into situations where the cancellation is complicated to thread, e.g., async methods.
DT: You end up creating links at different points in lifecycles
DD: So there are good use cases, for CancelToken.some.
Strike: "Still unsure what the exact use cases are, but it seems plausible."
DD: So does anyone need CancelToken.every? .NET doesn't have it.
DT: Never needed it [in Midori]
YK: We should think about it because it's symmetric
DT: It's asymmetric; cancellation is monotonoic. We just don't get this pattern in Midori.
SP: Doesn't sound useful
DT: You might end up with some nice usages of 'some', so it is a good thing to have.
RW: Why not call it CancelToken.all?
DD: I should think about that harder; there was some argument about all rather than every. Anyway, this is more about 'some' given that 'every' is not useful.
RW: In favor of 'all': For explanation purposes, it would be nice to have this analogy. Apply what you already know.
YK: I have become comfortable with a cancel token as a parameter.
DD: The concern Yehuda has raised is, the semantic burden on developers of threading the cancel tokens through all the APIs, and changing all the signatures, is an issue. Should we mostly do options objects or bare parameters?
YK: Seems difficult to have a universal convention
DD: In .NET you have static types and overloads so it's easier.
DD: YK's idea was to introduce syntax for allowing cancelTokens and awaits to work better together:
async function cancelMe(cancelToken) {
doSyncThing();
await doAsyncUncancelableThing(cancelToken);
await anotherOne(cancelToken);
}
To...
async function cancelMe() {
doSyncThing();
await doAsyncUncancelableThing(await.cancelToken);
await anotherOne(await.cancelToken);
}
YK: This would continue with our tradition of implicit parameters, e.g. implicitly passing 'this'. You don't want to have to add it explicitly
YK:
async function cancelMe() {
doSyncThing();
await doAsyncUncancelableThing(await.cancelToken);
await anotherOne(await.cancelToken);
}
let [cancelToken, promise] = [some ambiguous token] fetch(...);
MM: What would this correspond to with explicit characterization?
function fetch() {
return await.cancelToken;
}
YK: There is a pervasive threading problem. This is analogous to new.target.
YK: [some ambiguous token]
is the machinery that represents the longhand
that Domenic showed
let token = new CancelToken(function(c) {
});
function fetch(
@Yehuda, can you fill in this example with some code that illustrates
whatever you were going to write,
DD: What I'm hearing is that people are not heavily concerned. Sounds like this might be worth pursuing. Cancellation already has a lot of stuff in it, and it's hard to get a read on how many people are going to have objections. Dean already raised several objections and we didn't have time in the timebox to raise all of them.
DT: good effort and really want something along the lines
YK: If the implicit argument fails, I'm not sure whether I'll be OK with this whole proposal.
DD: There is some enthusiasm for this proposal, it seems, including some of the additions. More is available in the repo. I'll add more spec'd things, including await.cancelToken, Promise.cancellable, and CancelToken.any
BT: What do cancellable promises change about async functions? Seems purely additive.
DD: Yes, seems purely additive. We don't have third state.
YK: It'd be possible for await to send cancellation tokens, but only if you do extra things to thread things through.
BT: Another question about Domenic's proposal: Is the rationale for why third state is bad documented?
DD: I'll write it up.
BT: I think it needs to be reflected, so we know years from now why we didn't go with third state.
Conclusion/Resolution
- Continued development based on today's discussion
- await.cancelToken
- Promise.cancelable(...)
- CancelToken.any|some (whichever?)
- DT to provide direct feedback
- DD to write up reasons why not going with third state: gist.github.com/domenic/f3ecf2dd1b27409567ba59e3fabbc047 documents the reasons briefly, as well as arguments against those reasons which were not found compelling enough to re-gain consensus on it.
- Next meeting, I'd like to move to Stage 2
10.iv Async functions
Brian Terlson
tc39.github.io/ecmascript-asyncawait
BT: When we got async functions to Stage 3, we did spend hours talking about possible futures for cancellation and how those futures would impact async functions. We found that additive things to async functions would also be additive things to Promises. So whatever you would add to one that would be a breaking change would be a breaking change for the other. I didn't see anything in Domenic's preentation that made me think otherwise. Even the third state proposal, I'm not sure would run afowl of that.
YK: The only issue is that, in the syntactic form there's a try/catch/finally, and in the method form there isn't
AK: There is also a conern about using try and catch, without finally
YK: And it's just worse in Promises anyway
MM: The only one that makes me nervous about a possible cross-cutting concern is getting a syntax for passing the cancel token. That's the one most likely to be one where we might end up regretting simply accepting async functions as is, without also having it be a lifting mechanism for threading the cancel token.
YK: I feel pretty confident that the kind of syntaxes that we would want to use would be the same syntax for regular functions. We need the same mechanism to work within functions that aren't async functions anyway, as they need to have the parallel calling convention.
MM: of the things we heard in the previous conversation. the only cross coupling concern is the issue that YK brought up is trying ot get some useful syntact for threading the cancelToken.
MM: I don't think we should implicitly pass a parameter to existing sync function calls and change the semantics retroactively. Anyway, given the overall situation, I'm not arguing that we should hold async functions back.
WH: The grammar is both impressive and really scary, trying to see how much it can dance on the edge of a cliff without falling over — cover grammars inside of cover grammars — but I haven't found any flaws yet.
When is "await" usable as an identifier?
DE: anytime you are not in an async function. <then more details> We
implemented it all in V8
BT: It's just like yield
WH: await is different from yield in that it appears at a much higher precedence than yield.
YK: What are you worried about?
WH: Ambiguities on code sequences that start with await/ and then get interpreted in diverging ways (due to the await-as-identifier vs await-as-operator distinction that flips the / between division and starting a regexp) by cover grammars vs. real grammars. It's a potential bug farm.
WH: I am not opposed to Stage 4, just noting the potential danger.
BE: is there a way to look at the grammar of "yield" to have it work?
Conclusion/Resolution
- Stage 4
9.iii.c Decorators
Yehuda Katz and Brian Terlson
tc39.github.io/proposal-decorators
YK: Has been working closely with Dan since the last meeting to come up with how to move forward. I want to address the technical issues. The spec is now in a Stage 2 complete state. Many have asked, why can't this be a transpiler feature. I think it's possible in principle for that to be true, but it's not as cut and dry. One problem is that it absorbs a bunch of syntax from the class body; it's important to coordinate that somewhere. You'd imagine that private state could use the @ sign, and you would want to understand that this is reserved for decorators. Also, it would be difficult to have a conversation in this committee about the class evaluation order (as last time) and interaction with features like private state. We have a lot of cross-cutting concerns to think through. The concerns from implementors is that adding more syntax features slows down the parser, which affects startup time.
MM: I was surprised by the idea of just doing this in the transpiler world.
YK: This will be standardized somehow; there are already two implementations. We should have a document that defines it, with some sort of spec. So it would have to be a delta on top of the JavaScript spec, if we keep it in transpiler land.
AWB: if it's done as a preprocessor, you'd have to do it to standard JavaScript semantics. So everything would have to be expressible in terms of the core syntax/semantics. So if the core isn't sufficient, it won't be possible to do it correctly.
YK: In order to get the semantics for high fidelity, the preprocessor will have to target ES5.
AWB: But then you can't get classes completely correct. If you were going to go the route of a preprocessor, what changes would you have to make to the current spec?
YK: We've been doing some refactoring. But it'll be hard to target ES6
MM: The decorator proposal allows a decorated constructor to result in a wrapping of the constructor. But since it's only recognized as a constructor in ES6 if it's written as a constructor, there's no way to translate
BT: In practice, you have to target functions, not classes. We will have responsibility for the problem no matter how we decide to layer it.
MM: Creating high-fidelity transpilation options on the way is a perfectly fine sequence of activity.
YK: And we will give this spec to the current transpilers. The only question is whether it's done here, or actually my opinion is that it would be somewhat possible to do as a layering
AWB: I don't think it's possible
YK: Anyone opposed to this spec being eventually in the language?
DE: I'm not convinced this spec should be in the language. Looking at Angular use cases, this doesn't support annotating parameters and other things, and there is no clear migration path to supporting those from this proposal.
DE: There is a competing feature from Angular for annotations
(There is no spec, but it's documented)
YK: I object to Angular approach, there are very real issues with that proposal that are unexplainable
JHD: The things they want don't block the addition of this feature? Why not add the other kinds of decorators later?
DE: Hard for me to see how imperative decorators like in this proposal would map to declarative ones that annotate parameters.
BE: Not here to future proof against all possible proposals by champions not in the room
YK: There is a spec here, this has years of development.
BE: too far to block
YK: Are you saying these use cases are insufficient
WH: Concerns about missing capabilities. Want to see a consistent path to annotating properties.
YK: This has become maximally minimal
DE: Concerns Andreas has raised: the decorator can run and do all kinds of things, which prevents optimizations
JHD: This is no different than the inelegant solution of O.dP after the class is defined.
BE: The question is: are we saying that we never want to do this?
EFT: Surprised that this feature is being shied from when it's beloved and widely used in other languages.
WH: I like decorators! I just want to make sure that we create a consistent design of decorators for various kinds of entities and needs rather than falling into a max-min tarpit that supports some but then precludes others due to poor design choices.
YK: Willing to champion additions to this proposal to satisfy outstanding needs.
- The interop issue (with "annotations") has existed for some time, we can keep coming back with new features
- The work can be done in Stage 2
- Babel is skeptical now
- Stage 2 signals to community
AWB: My understanding is that Stage 2 is "not locked down", the language wants to solve this problem and will eventually include the feature.
Massive agreement.
BE: Are we in favor of adding a decorators thing?
DE: Not convinced an imperative decorator is the way to go
YK: Agree to explore decorators in other positions before Stage 3
WH: Concerns about missing capabilties. Want to see a consistent path to annotating properties.
BE: (@Dan) Worry about dynamic meta programming in class declarations?
DE: (some kind of agreement)
BE: Would love static decorators, but it's a hard problem and
YK: The Annotations feature requires evaluation of expressions, is not itself static
(discussion re: static decorators)
YK: Is the concern that adding this encourages too much dynamism in class declaration code?
SM: Will existance slow it down?
- Believes optimizations can be made to mitigate
YK: The decorator returns a descriptor that can be used, but cannot have effects on the object itself.
BT: Want to push for Stage 2
WH: If we approve this, are you committing to explore property and parameter annotations?
YK: Yes, I will do that before stage 3.
BT: Fair to make that separate?
NO.
Conclusion/Resolution
- Stage 2 Approval
9.iii.b Private State
Daniel Ehrenberg
Slides: docs.google.com/presentation/d/1RM_DEWAYh8PmJRt02IunIRaUNjlwprXF3yPW6NltuMA/edit
DE: I've taken on Private State proposal from Kevin Smith
AWB: Get WeakMaps out of the proposal! I don't want to see them anywhere near this proposal, whether in implementation or spec language.
- Remove the layering violation
WH: Don't want proposal formalized in terms of weak maps either because of gc correctness concerns.
See slides
DE: Should this be "actually private"?
WH: Yes
AWB: Yes
DE: Or Reflective?
No.
See "Why inaccessible private state?" slide
"Soft Private" already available through explicit Symbol use
AWB: Big issue: we changed class instantiation to predictable shapes at the request of google. This completely throws that away
DE: We addressed that two meetings ago.
MM: The shape is static enough for the fast path to be fast. The only things that cause it not to have the shape that you expect are bizarre, rare things such as a return override or prototype mutations. Engines can still optimize for the fast path.
DE: two things we want to optimize for. 1) at the allocation site, how large (allocation size). 2) map transitions between different object states.
AWB: that's plausible; i'll need to think through it and reserve the right to bring it up again.
YK: I realize a lot of people disagree with me wanting soft-private, but we actually have to discuss it.
BT: could you expose a lower-level capability without syntax for now? (ie with computed properties + private symbols)
MM: private symbols don't work
YK: proposal would be a private object that looks a lot like a WeakMap
DE: one option is as YK said; another option would be trying private symbols, and we could work through the issue with them.
MM: if you reify private symbols, you break membranes.
MM: We're rehashing arguments we had years ago like "should private be soft or hard". There are notes.
YK: i object to the precedent "we had a binding conversation 5 years ago"
Call for Stage 2?
Conclusion/Resolution
- We don't have enough time?
(Slides are at tc39/tc39-notes/tree/master/es7/2015-07 )
July 28 2015 Meeting Notes
Allen Wirfs-Brock (AWB), Sebastian Markbage (SM), Jafar Husain (JH), Eric Farriauolo (EF), Caridy Patino (CP), Waldemar Horwat (WH), István Sebestyén (IS), Mark Miller (MM), Adam Klein (AK), Michael Ficarra (MF), Peter Jensen (PJ), Domenic Denicola (DD), Jordan Harband (JHD), Jonathan Turner (JT), Paul Leathers (PL), Chip Morningstar (CM), Vladimir Matveev (VM), Ron Buckton (MS), Brian Terlson (BT), Alan Schmitt (AS), Ben Newman (BN), Mohamed Hegazy (MH), Abhijith Chatra (AC), Tom Care (TC), John Neumann (JN), Dave Herman (DH), Brendan Eich (BE), Rick Waldron (RW), Mike Pennisi (MP)
Introduction
BT: (logistics)
AWB: I will chair until John N. arrives.
Adoption of Agenda
AWB: tc39/agendas/blob/master/2015/07.md
YK: Propose that future agendas be organized by stage advancement
(Agreement)
IS: Need to add Ecma Secretariat items (Allen adds) like report from the GA.
Conclusion/Resolution
Approval of Minutes from May 2015
AWB: Posted on Github and es-discuss
IS: Ecma is archiving (mirroring) the most significant documents from GitHub, like technical notes as well as summaries associated with the agendas. This practice should satisfy both the requirements of Ecma as an SDO as well as of Tc39.
Report from Ecma Secretariat
4.i Status of ISO/IEC Fast Track of ECMA-262 Ed.6, ECMA-402 Ed.2 and
ECMA-404
IS: Need an Ecma-262, Ecma-402 and Ecma-404 package "Explanatory Report"
AWB: Can we push through our current documents, as-is? Without changes?
IS: Similar to 5.0 -> 5.1, editorial changes allowed. Any technical
changes, no. Concerns about stability.
AWB: Concerns about an ISO document that says one thing, vs. the Ecma document that says another.
IS: Can disallow discrepancies, therefore it is always the policy to synchronize the standard on both sides
WH: What happens if the ISO reviewers discover technical issues?
IS: The problem is that the yearly update for JTC1 might to be too fast. We are elaborating on them. Theoretically worst case, we withdraw the "fast track"
WH: [incredulous] Withdraw instead of fixing bugs? That wouldn't be nice.
IS: (explains why fast track). We have started this about 17 years ago, as long TC39 came out with big time gaps between Edition, no problem, but the current "turbo speed" like standardization (update) may create problems in synchronization. we are discussing this new thing with ISO.
AWB: Good to communicate to ISO
IS: Explained to Rex Jaeschke (JTC1 SC22 Chair) the new schedule. Normally ISO likes to update standards every three years, have expressed our one year schedule plans.
WH: Afraid ISO might not like "take it or leave it". In the past, we got excellent technical reviews from them and have integrated the changes into the ISO standard and to the Ecma standard.
AWB: But that would be next June
WH: That's how we've always done it. The ISO version was a year behind the ECMA version. If we don't integrate the known defect fixes, the ISO version would be multiple years behind ECMA.
AWB: Ignoring unknown issues, we have 5 or 6 technical issues that could comprise a 6.1
RW: If we have a yearly release for full edition points, perhaps we can also include a 6 month "sub release" to address minor changes to current
YK: Not unreasonable when the work is done by a group using shared tools
IS: Theoretically in Ecma we could have a 6 month correction cycle (TC52 Dart uses that). Depends on TC39 what they want.
AWB: What does the GA think about doing this process every six month?
IS: no problem there, this could be reasonable solution, for Dart it has been accepted. Of course Impose a deadline of 2 months before December GA meeting for the version to be voted upon and published.
RW: Can correspond with our September meeting.
IS: (agreed)
AWB: Trivial to make minor changes, willing to work through the first round as we transition editorship.
bugs.ecmascript.org/describecomponents.cgi?product=ECMA-262 Edition 6
RW: Does this need to include the ISO review comments (Waldemar's concern)
YK: Would like to come back to this after we have a more in depth discussion about the future of our tooling.
Discussion about what we produce.
AWB: We can produce errata any time, but it's not the standard
DD: If we have the base covered, avoiding shipping bugs, do we publish errata every year or every six month?
WH: It's not ok to ship a standard with known defects. We can publish standards on whatever schedule we want, but anything we publish should have all known defects fixed.
YK: Think "annual" is enough time to fix bugs
AWB: The issue is ISO. There is concern about divergence between those two documents (ISO document with changes made by their reviewers, Ecma version)
BT/IS clarifying why we need ISO version?
BT: Why?
WH: There are benefits to ISO publication
AWB: There are organizations that may require
IS: Public procurement, if it's an Ecma standard, maybe problematic. ISO is in the "highest level" of international standard category.
BT: Are there concrete examples of using ISO specification over Ecma?
(Spending too much time on something we don't know the value of)
DD: Propose that we don't do this process unless an external request for it is made.
IS: We are already for 17 years in this process, and it is expected that we continue for future editions as well. So this is automatic and not exteranl request is needed. How to explain why ES 1, 2, 3, 5 & 5.1 are ISO standards, but 6 and 7 etc. not and what if Ecma is already e.g. at 7 and ISO still on 5.1?.
Can we be forced to do this?
IS: Yes, the current rule for synchronization "forces" it.
YK: (clarify) Once we issue any ISO spec, we're required to maintain?
Several "yes"
WH: We don't want to destroy the relationship between Ecma and ISO
STH: How does is hurt to not create ES 6.1?
YK: ISO was ok with a two year wait for 5 to 5.1, should be ok with a year between 6 and 7
WH: But much longer since 5.1
AWB:
Discusson re: schedule, responsibilities, etc.
AWB: We will submit to ISO, with exact same text (subject to ISO naming, etc). But the text will include any known errors.
WH: No, they have to be fixed. I'm not ok with shipping standard with defects known to us.
DD: We agreed to fast track at the last meeting and Waldemar is now disagreeing?
WH: Incorrect
DD: You said you won't allow us to fast track with defects
WH: No, we must fix defects
STH: Why does fast track require fixing errata?
WH: Not a lot of work
DD: You're saying that you no longer agree to fast track
WH: We will get ocmments from ISO reviewers, these will identify defects, these need to be fixed. It is our job to fix
CM: Exactly the proposal: take the existing text and put it in the pipeline and publish the errata later.
YK: Treat ISO as an LTS?
WH: That's what it is
DD: Can we have members of the committee that are responsible for incorporating the errata, as a separate task.
AWB: That's the editor's job. Incorporating errata is not a lot of work.
RW: This is exactly my suggestion, but with a schedule requirement.
Discussion about who and how.
AK/JT: What is the cut off for known defects?
DD: Suggest that we let whoever volunteers be responsible for making those decisions
YK: With better tooling, we could really just do this as branches in a repository where all work is tracked.
AWB: Don't think that any editorial difficulty. Bigger isssue: what are we going to do with ISO on a regular basis? Yearly ISO and it's the same document?
BT: Agreed.
AWB: Ideally we'd have "fast track authority", submit the Ecma document and they either take it or leave it.
YK: Can we revisit this after we've read the agenda items? (Specifically item 5)
AWB: That item is Editorship?
YK: That seems to determine tooling.
JN: Assignment of Editorship role.
BT/AWB: Yearly release, give them to ISO without change, accept them as is. Take their changes and roll them into next year's edition.
WH: This is agreed to an incorrect assumption. All ISO comments must be addressed.
IS: That's correct. That's required by the ISO process.
BT: If Istvan can convince ISO to accept yearly releases "as-is", are you ok with this?
WH: If ISO can accept as-is, then let's discuss this again, but I don't think they can
IS: I told ISO at the last meeting that we are moving much faster and that we need to create a new way to submit. This is a way to handle that and I can present it to them as a solution. Normally, they don't update until every 3 years. I pointed out the issue with their timeline and they agreed. This is a possible solution and I will work with them to sort out this problem.
WH: Are they ok with not making comments?
IS: From some members, but not all, awaiting final word.
WH: Not ok with making decision until we know where they stand.
Conclusion/Resolution
Propose Life Membership for Allen Wirfs-Brock
(Rick Waldron)
RW: As we have for Brendan, I'd like to propose inviting Allen Wirfs-Brock as a lifetime member of TC39
IS: Such a category does not exists officially at Ecma, only some freedom for the Secretary General to allow partication as invited expert. He will bring this to Ecma Management for seeking agreement. This is a special case, and I am confident.
Conclusion/Resolution
5 ECMA-262, Editorship
JN: Need to appoint a new editor, only one volunteer has come forward and that's Brian Terlson.
YK/RW: Seconded
JN: Discussion?
WH: Do you see your approach as different from Allen?
BT: Only in that I'm a different person, but generally the same. I'm not Allen, but I will do my best.
AWB: Appropriate to also appoint a manager for the content that we're producing.
Conclusion/Resolution
Discussion of the Manager Role
AWB: Useful to have some web content which will need a manager
Discussion, re: content manager
"web master"
IS: Need procedures to archive the github material
AWB: Unless someone wants to volunteer now, then let's resolve to appoint someone by the next meeting.
JN: Allen please generate a "job description"
Conclusion/Resolution
Exponentiation Operator
(The room is very excited about technical discussion finally starting.)
RW: SpiderMonkey is ready; V8 is ready; spec material is ready rwaldron.github.io/exponentiation-operator/; it meets the requirements for stage 3
WH: This is incomplete; it is missing details on the lexical grammar.
RW: Agreed; I can address that issue before the end of this session. Perhaps we can revisit in the coming days.
DH: Let's avoid a precedent that if anyone finds any minor hole, they can stop advancement.
WH: This is an issue of completeness
DH/BT: The resolution of this problem is obvious and trivial to implementors
AWB: We need to improve the process document to include expectations for reviewership
DD: The process document is now published as an HTML document in an public repository on GitHub.com. I have migrated it from Google Docs with no changes to content. I have opened two issues to discuss details that have historically vexed this committee.
WH: I have no doubt that you can address this by the end of this meeting.
RW: I am literally done.
BT: We have agreed that technical issues should not block advancement to Stage 3. Does anyone object to advancement?
AWB/DH: We have technical questions, but they have no bearing on advancement to Stage 3.
(break for lunch)
Conclusion/Resolution
6.2 RegExp.escape
(Domenic Denicola)
benjamingr/RegExp.escape
Slides
DD: (presents slides)
YK: Don't make user think about escaping.
AWB: Generate a complete regexp from string. Append cases
WH: What does it mean to create a regexp from a string? (w/r to Proposal Ruled Out)
AWB: Regexp construction that will exactly match
YK: A simple example: a lexer, the lexemes provided as a string
DD:
SyntaxCharacter Proposal
AWB: Used as argument to the RegExp constructor
DD: yes
Safe Wth Extra Escape Set
-
addl. for the context sentive inside-character-class matchingWH: Escaping
d
by replacing it with\d
completely changes its meaning. The latter matches any digit but not the letter 'd'.YK: Issue is
RegExp.escape(...)
what?WH: Second use case ( benjamingr/RegExp.escape/blob/master/EscapedChars.md,
0-9a-fA-F
) is not useful. There is no good reason for someone to concatenate the erroneously short (three digits instead of four)\u004
to user-defined input. The first use case there is also not common.MF: Should be a
RegExp.compose
, not use+
to concatenate strings forRegExp()
AWB: illegal in the grammar, but allowed in the annex extentions (annex b grammar allows < 4 characters following the
\\u
)WH: Why would you do this on purpose?
WH: How do you escape these things?
\d
, or\0
which does not mean0
MM: Issue about fragment hazards, not using + for composition. I actually think that a template string tag is the solution
DD: Extended "Safe" Proposal, Allen had concerns?
AWB: ES5 takes efforts to roundtrip the string returned for a regex has forward slashes
WH: RegExp's toSource creates a string that, when eval'ed, produces a valid RegExp
DD: No change to output of
RegExp.prototype.toString
DD: benjamingr/RegExp.escape#4 explains why not a template string tag, but reviewing now, the arguments are not strong
MM: You get the escape functionality in terms of the template string tag.
MF: Concerns about unnecessary escaping
DD:
WH: Readability costs. Don't want RegExp.escape to turn '7' into '\u0037'.
MM: template string doesn't have those costs
DD: cannot compose a variable number of strings together with template string tag
YK: Assumes certain amount of "static-ness".
... Would like to see an injection scenario that seems realistic.
DD: it's possible, it can happen. Reasonable for a TC created solution to address all the cases. All we need to do is address all of the cases presented, at the beginning of the string
AWB: Why do we thing there is one
escape
function that covers all cases?WH: Whoever is writing the things that are not escapes, limits themselves to a subset of "well behaved regexp". In a well-behaved regexp:
DD: What if you want to match backreference \1
WH: If you want to do it just before a concatenation point, write it as (?:\1). A trailing backreference is such a rare case, this is a reasonable constraint to do to simplify readability of all escaped strings that start with digits.
MM: Object to template string solution?
WH: No. My argument is orthogonal to whether we use template strings or RegExp.escape. Object to escaping individual non-punctuation characters a, b, c, d, e, f, 0, 1, 2, 3, 7...
DD: Objection to any proposal but the SyntaxCharacter Proposal?
WH: No. Fine with other punctuation-escaping-only variants such as also escaping '/' if we choose to do so.
YK: Does SyntaxCharacter escape
-
?DD: No
YK: That's a mistake
AWB: SyntaxCharacter has specific meaning
DD: Current thing on table: SyntaxCharacter and hyphen
YK: Why?
DD: eval
Discussion re: template string availability
DD: Proposal coming from people that need to ship code to non-edge browsers
YK: Use today? Library code.
DD: Has been a request for a long time, give what's requested even if unsafe? Give them what they want plus things that make it safe? or make a new thing from template strings.
Discussion, re: issues with template strings in this use case
YK: Maybe template string API is flawed and needs work to be dynamic
MM: Agreed with need.
CM: this output from one piece of code to another
STH: The spec can say "the output looks like literally the input"
YK: People will then rely on it
STH: State the goal, then go back and specify to reach the goal.
DD: We've done this, and the constraints are illustrated benjamingr/RegExp.escape/blob/master/EscapedChars.md
MM: What is the motivation for readable output?
BE/YK: Debugging
MM: Ok, then issue is debugging vs creating less bugs?
DD: Then escape everything
YK/MM: Agreed
DD: Any objections to escape everything?
MM: I think the template string proposal is better in all dimensions
YK: Maybe do both?
RegExp.escape
AWB: Stage 1? Will the champions know that this could change from RegExp.escape to template strings?
DD: Want to say that
RegExp.escape
can move forward for nowYK: ?
MM: template strings handle all of the malformed fragment cases
AWB: and is 100% convinced is safe?
MM: eval thing is safer than
DD: "only beginning of string"
WH: What mark is suggesting conflicts with what I was saying
YK: What is the constraint?
WH: Readability
Ok to escape everything, but don't have to
MM: Rather not inro hazards, ok with either solution that doesn't
DD: Ok to advance is escape everuthing?
WH: if we don't, escape everything, unnecessary to escape "d" at the beginning of string
DD: This has been identified as a security issue
WH: it does't buy anything and there are others that aren't covered.
DD: Can you give example
WH:
MM: "\" is a regexp fragment.
WH: Yes (in this case), but in practice so what? There's nothing in the concatenation example that would ensure you only concatenate complete fragments.
MM: Right, this is still a security issue. Unresolvable by escaping due to the odd-even problem.
DD: Ok, the point was to handle all cases
YK: Non capturing parens solution
WH: Stick to well-behaved
Each case fails where another does not. Template strings address all issues, but fails for not being dynamic
MM: Would Benjamin be interested in pursuing the template string solution.
DD: Will bring this to Benjamin
?: Need to work to resolve the caveats in RegExp.escape.
WH: The caveats of protecting against all possible prefixes are inherent and irremovable. I want RegExp.escape to move forward despite those. It's safe for concatenating arbitrary escaped user input with well-behaved regexp fragments.
MM: I'm not ok
Conclusion/Resolution
6.i Advance Array.prototype.includes to stage 3
(Domenic Denicola)
tc39/Array.prototype.includes
DD: Walking through tc39/Array.prototype.includes#12
Conclusion/Resolution
Introduce promise rejection tracking proposal
(Domenic Denicola)
domenic/unhandled-rejections-browser-spec#changes-to-ecmascript
DD: (introduction)
YK: (summarizing) Some want to be notified when a Promise is rejected without an error handler
MM: prefer this to solution had consider
YK: Easily be used incorrectly
BE: Regardless of our intentions, it will be misused
DD: Use to correlate
Discussion, re: potential hazards
YK: People often try to deal with promise debugging incorrectly
MM: This provides diagnotistic tools that allow for better debugging
YK:
MM: Instead of using the turn boundary, await gc, but gc may never happen
DD: (refocusing) All I'm hoping for is the addition of these non-observable steps to the specification (showing domenic/unhandled-rejections-browser-spec#promise--executor- )
AWB: Nothing there that an implemenation couldn't do in terms of the current spec, it's totally allowed.
DD: You'd have to say "insert steps here"
AWB: When putting in the hooks, we more than say "this is allowed", we're saying "this is supported"
BE: This is more like a debugger API
Agree
YK/MM: An innocent refactoring to register a rejection handler
MM: The utility of having a diagnostic outweighs the noise of introducing
DD: There is no delay, occurs immediately, at the earliest step possible
MM: If I call Promise.reject?
DD: Will trigger the HostPromiseRejectionTracker
YK: Persuaded by Mark's argument
Discussion, re: .done
AWB: Different promise's can have different handlers? No
AWB: no reason an implementation needs to define HostPromiseRejectionTracker, so a default handler should be specified.
DD: Didn't see something like that
YK: Move to stage 2, because already implemented.
Discussion, re: stage process? Yes.
Conclusion/Resolution
9 Tooling Updates
(Brian Terlson)
Slides
BT:
Grammarkdown (Grmd)
AsyncArrowFunction[In, Yield] ::
async
[no LineTerminator here] AsyncArrowBindingIdentifier[?Yield] [no LineTerminator here]=>
AsyncConciseBosy[?In] #1MM: Can I use this standalone?
BT: Sure, but it's just part of Emu
Ecmarkup (Emu)
AWB: note that the Python program that Jason wrote has evolved
Ecmarkdown (Emd)
6.6 BindingRestElement should allow a BindingPattern ala
AssignmentRestElement
(Brian Terlson)
Slides
BT: AssignmentRestElement allows destructuring, BindingRestElement throws. Destructure rest on assignment, but not on binding
Possible Avenues
BindingRestElement[Yield] :
...
BindingIdentifier[?Yield]...
BindingPattern[?Yield]Plus necessary statc and runtime semantics to align with BindingPattern
MM: Made and fixed this error in research.google.com/pubs/pub43462.html
BT: No
BT: Babel already treats the same
Conclusion/Resolution
6.7 new & GeneratorFunction
(Brian Terlson)
Slides
BT:
Current Semantics:
this
set normally by callerthis
is a dynamic ReferenceErrorIssues:
Possible Solution:
this
is not a dynamic ReferenceError, but instead refers to the GeneratorFunction instance (align with current implementations: Babel, V8, SM)AWB: Doesn't act like derived constructor, does ave a prototype property that's used to initialize instances
BT: No case where a subclass will always throw
AWB: Body of function is not run as part of the constructor. The body is not a constructor body in the typical sense
BT: Breaks down the
this
andnew
behavior, b/c can't usethis
withnew
AWB: The body isn't run as part of the constructor, it's run as "next"
DH: A generator used with new is weird. (giving an example)
function * Thing(x) { this.x = x } Thing.prototype.sayHi = function() {}; let thing = new Thing("tc", 39); thing.x // undefined thing.y // undefined thing.next(); thing.x // "tc" thing.y // undefined thing.next(); thing.x // "tc" thing.y // 39
DH: Why would want to pause before fully constructing the object?
AWB: Generator method
let obj = { *foo() { yield this; } }; let iter = new obj.foo();
RW: Non-generator method would throw a TypeError when
new ...
MM/DH: (discussing special cases)
BT: Potential argument for why we should allow
this
inside generator, observables, where you might initialize this before the first yield (by callingnext
before handing out your iterator)AWB: this binding is actually set up when the iterator is created
MM: A generator method, that does not mention super, has a call behaviour that sets this from it's caller the way that a generator function does
AWB: imagine "MyCollection"
class MyCollection { constructor() { // ... } * values() { let k = 0; let length = this.length; while (k < length) { yield this[k++]; } } } let collection = new MyCollection(); let values = collection.values();
class MyCollection { constructor() { // } } let collection = new MyCollection(); collection.values = function * () { console.log(this); };
DH: Have a construct trap, normal new object passed in. Generator function is a generator implementation of a function.
BN: If trying to discourage using new, this may already be the case, since this.next(), this.throw(), this.return() will all throw if called from within the generator, because the generator is already executing
AWB: Cannot re-enter
function * Thing(x, y) { this.x = x // current ES6: throw here. yield; this.y = y; } Thing.prototype.sayHi = function() {}; let thing = new Thing("tc", 39); thing.x // undefined thing.y // undefined thing.next(); // current ES6: ReferenceError on `this` thing.x // "tc" thing.y // undefined thing.next(); thing.x // "tc" thing.y // 39
(Note that SpiderMonkey doesn't throw at either of the places called out above)
DH: The * is a way of saying that you're providing a way to the precise thing you would do by hand, but without the long form hand written
RW: Then generator method should throw TypeError when called with new
DH: Agreed
MM: What is the instance created from whehn a generator method is called with new?
AWB: instance of Generator
MM:
let coll = {*values() {}}; let it = coll.values(); it instanceof coll.values; // true
MM: Unseen: allocatiing a new generator instance. Contains an implicit
new
and implcit constructor body.DH: * imputes an implicit
new
(in both the method and constructor)MM: Acting like a function that's calling an implicit constructor
BT: it's a factory
DH: Simpler: "* is never new-able"
Alternative 2: a function * has
MM:
let coll = { *values() { this; } } coll.values(); // ? coll.items = function * () { this; }; coll.items(); // ?
DH:
{ *foo() {} }
(no [[construct]])function * () {}
(no [[construct]])function * () { this }
is exactly likefunction() { this }
AK (offline): Further spec reading suggests that GeneratorMethods need to have their [[Construct]] removed just like GeneratorFunctions (they both pass "generator" to FunctionInitialize, which is where the decision to set up [[Construct]] is made).
Conclusion/Resolution
new
throwsthis
should be set by the caller, as is normal (global or undefined)6.12 String.prototype.split, its limit argument, and ToLength vs ToUint32
(Adam Klein)
gist.github.com/ajklein/335e0f948c500a0c25dc
AK: Issues:
Problems:
AWB: One of the discussions was to change arrays to be larger
AK: That would make sense
Discussion about changes
Proposal: Revert this spec change. Existing implementations still match ES5, and the old behavior still makes sense (even with ES6's longer String length limit).
WH: The spec needs a geocities-style "Under Construction" animated GIF here ;). This was the first phase of a series of changes attempting to move the spec to eliminate the 2^32 array length limit, with the changes spread over time.
Conclusion/Resolution