Ecma/TC39 Meeting – Jul 24 2013

link July 24 Meeting Notes

John Neumann (JN), Luke Hoban (LH), Rick Hudson (RH), Allen Wirfs-Brock (AWB), Yehuda Katz (YK), Anne van Kesteren (AVK), Jeff Morrison (JM), Sebastian Markbage (SM), Paul Leathers (PL), Avik Chaudhuri (AC), Ian Halliday (IH), Alex Russell (AR), Dave Herman (DH), Istvan Sebestyen (IS), Mark Miller (MM), Norbert Lindenberg (NL), Erik Arvidsson (EA), Waldemar Horwat (WH), Eric Ferraiuolo (EF), Matt Sweeney (MS), Doug Crockford (DC), Rick Waldron (RW), Rafael Weinstein (RWS), Dmitry Lomov (DL), Brendan Eich (BE), Brian Terlson (BT)

link 4.6 Binary Data Update

(Dave Herman & Dmitry Lomov)

DH: (Introduces Binary Data) A mechanism for creating objects that guarantee a shape (Struct)

Use case that has become less important, I/O

Dmitry has given use cases where we still want control over endianness

MM: A little surprised by this direction (not objection)

If you have something like a class, do you an imagine something like an array buffer, per instance?

DH: it's still possible to overlay structs over larger sections

MM: if you want the instances to be gc'able...?

DH: they'd have to have separate backing storage, but those could be GC'd like normal

There's more work we've been doing with Rick and his group at Mozilla on parallelism patterns by describing the shape the data you're operating on. You still want the ability to do things like parallel iteration over arbitrary JS values, which means things like "object" and "any".

Those are high-fidelity drop-in replacements for JS arrays, but with no holes.

DH: once you introduce pointers, you have to bifurcate the design a bit; opaqe vs. non-opaque structs. Don't want to go into details, but will put that on the wiki.

MM: You can use structs to model more classical class object model where all the data is on the instance. (structural types)

YK: Do you imagine people using this in regular JS?

DH: Yes, but if they're writing regular JS, they'll profile and find that they want to use these sorts of structs in hot places.

1
2
3
4
5
function ThingBackingStore() {...}
function Thing() {
return new ThingBackingStore();
}

... Becomes something like...

1
2
3
4
5
6
7
8
9
10
var ThingBackingStore = StructType({
stuff: new ArrayType(object)
});
function Thing() {
var selfie = new ThingBackingStore();
selfie.stuff = ....;
return selfie;
}

WH: What kind of fields can be had?

DH: Type descriptor algebra, set of combinators. (atomic types) Uint8, Uint8Clamped, Uint16, Uint32, float32, float64, ObjectRef, StringRef, "any" new ArrayType(T), new ArrayType(T, )

WH: no uint64?

DH: no.

BE: I'm proposing it separately

WH: what's the difference between ObjectRef and any?

DH: ObjectRef can be a object or null, while any can be any valid JS value.

DH: SymbolRef is mostly an optimization over any.

EA: What about SymbolRef?

DH: Symbols should be objects. We'll have that discussion later.

AWB: Why isn't there a Uint16Clamped?

DH: That was just needed by canvas.

MM: Only Uint8Clamped?

DH: Yes, compatibility with canvas' ImageData.data.

AR: Y U NO CLAMPED EVERYWHERE!?

1
2
3
4
5
6
7
8
9
10
var Point = Struct({
x: uint32,
y: unit32
});
var p = new Point({ x: 1, y: 12 });
p.buffer;
p.byteLength;

WH: Can you replace the buffer?

DH: No, {[[writable]]: false, [[configurable]]: false, [[enumerable]]: false}

WH: Can you write to the buffer?

DH: Yes

DH: V8 team also wants reflection so that they can check the type and the field offsets.

WH: what if there's an object field in the buffer somewhere?

DH: let me outline what I'm doing, mayble that'll clear it up

if I have:

1
2
3
var q = new Thing();
q.buffer == null; // true
q.byteLength == undefined; // true

One of the things we've talked about is being able to censor access to the buffer at various points.

Lets say you want some computation is working on a sub-view of a buffer, we need to be able to cordon off access between these parallel things.

We can imagine putting/removing things from the "opaque" state. p.buffer is originally some buffer object, but then I'd be able to set the opaque state. Having an access to the buffer will let me re-set that constraint later, ocap style.

WH: I'd like the type itself to denote if it's buffer-backed or not.

DH: once I can lock down the instances, that doesn't matter so much.

WH: it's one more thing I have to write out at creation time

WH: I'm looking at this as a backing store for classes

DH: my feeling is that it's more type and design consistent to not have this depend on having the property

AR: how do I know it's in the opaque state?

DH: I'm trying to avoid competing with the namespace for property names, so I haven't solved that yet

LH: I think that's weird. I don't think anything in the current draft indicates the per-instance-of struct type that goes along with the type.

BE: that's been diagramed.

DH: We should stratify buffer and byteLength.

WH: are there any other special names besides "buffer" and "byteLength" that you're thinking of adding?

DH: the other major ones are methods that do getting and setting for things like multi-hop getting that avoids intermediate alloc.

1
2
3
4
5
var S1 = { foo: , bar: }
var S2 = { ... s1: s1, ... }
var x = new S2();
x.s1.foo
x.get("s1", "foo")

// lots of discussion about structs, prototype chains, and confusion about how long this has been agreed

AR: don't worry about so much about this object/buffer split; it's showing up because DH is enamoured of return overloading

DH: the main feedback I'm hearing is that they don't want default stuff in the prototype chain

// AR: what's the controversy?

DH: getOwnPropertyNames() matters and should behavle as much as possible like a normal JS object that it's emulating. If it has ergonimic issues that we discover later, so be it, but that's the general approach.

MM: if we find a problem, I'm happy to deal with it -- but I want to take it seriously and not as a detail.

AWB: I think this is extremely promising and there are lots of ways we can leverage this. But I don't see how we can get this into the ES6 spec. So many details. So many interactions.

WH: so there won't be binary data in the spec?

AWB: no, there are TypedArrays.

We might be able to do this as a self-contained thing after ES6.

Speaking editorially, we probably need to accept we won't get this done for Dec.

BE: if we're going to discuss if this is ES6 or ES7, we can have that discussion, but that's not how this started.

LH: this began as a technical update.

AWB: Need to explore the interaction with classes, @@create, etc. to me it's hard to separate some of the tech discussions from the schedule discussions.

DH: Objection to the exxageration of "newness" of this conversation.

BE: (Right, we've seen this)

MM: First time I've understood, so first time I'm reacting. Where the buffer is used as an instance itself

AR: No, not the buffer.

MM: What are these called?

DH: Structs, always. These examples are just to show what you can do with them

MM: the idea that these things inherit from the struct-making function's prototype...was that always there?

BE: I'd like to intervene. We're mixing things up still. Can I be blunt? The thing that set mark off was the "I don't have a strong opinion about that". If it's too late for ES6, it's ES7. We need details and there's sentiment in favor of stratification.

...Champions should have a strong opinion about these aspects

These should look like objects as much as possible

DH: Fair, but these weren't on my agenda to talk about. My dismissal was out of unpreparedness for the question.

WH: I would much prefer for this to be in ES6. TypedArrays without Struct seems half-baked

DH: YEs, agree, but the specing of modules trumps the specing of binary data.

YK: IIRC, you've said that Struct is polyfillable

WH: What does "polyfillable" mean in this case?

YK: Does not need to be in the spec for user code to use.

DH: Polyfillable in the sense of perfect semantics, but not the level of performance.

DH: yes, but this enables a class of optimiztions

LH: it's not strictly enabling the perf optimizations...right?

DH: no, you can't infer that there's an invariant that it won't change.

WH: You cannot know that a property is uint8 for example. It's hard to efficiently allocate just a byte for it if you can't tell that no one will try to write a larger value to it.

DH: I want to make another point which I had to learn along the way: I came to understand that there are 2 large, distinct classes of use-case: 1.) efficient representations of memory within pure computation 2.) serialization and de-serialization The design constraints are very different. For I/O, you want a LOT of control. And JS is expressive for those things. Doing it in a built-in library is a waste of TC39's time. Where TC39 can add something programmers can't is the memory-internal set of use-cases. Polyfilling only gets you a little bit of benefit there, but if it's built in, the optimizations can happen.

BE: the typed-array use-cases motivated the structs work for efficient overlays.

WH: but why would you polyfill something that doesn't perform or only has TypedArray?

DH: it's better to put it in TC39 even if we don't get full-structs. I'm gonna do the best I can to get it into ES6, but it's important. No reason not to have TypedArrays if we can't get it done, though. Better for us to control the sharp corners than to leave it in Khronos.

DH: I've focused on the in-memory patterns and others probably haven't thought about these as hard. But i haven't even gotten to the stuff that the V8 team brought up: for webgl, since you can have structs and they can be overlayed with buffers, what's the alignment story? TypedArrays haven't had unaligned access. The safest thing to do here is to provide a universal padding scheme that's portable.

DH: gl programmers want the ability to use structs on the JS side, but on the GL side, want the ability to demonstrate exact offsets and optimize for specific systems. They want aligned fields, but they want complete control.

WH: do they want holes? if we use C-padding, they can re-order fields explicitly to get the least total size.

DH: I'm unclear what's specified and not in C

WH: The C language spec states only that the fields must be in ascending address order. However, in order to be able to link code and have it interoperate, every ABI must spec it. As far as I know, they all specify it as "naturally aligned" using greedy allocation: for each field pick the next position that has the correct alignment.

WH: This is sufficient control to allow users to minimize padding to the minimum possible if they want to. I sometimes do this to my C++ classes. All you need to do is to reorder your fields to avoid doing things such as interleaving bytes and float64's.

DH: the proposal from dslomov's group is that the struct ctor can specify offsets:

1
2
3
4
new ST([
[0, uint32, "le"],
...
]);

MM: dave, can you state the alignment rule?

DH: every leaf type in a struct has natural alignment

WH: this is like most C systems, if you make an array of structs, the elements cannot be misaligned. struct sizes are rounded up, padding them up to their largest alignment to avoid possibly putting them in a misaligned context and breaking the alignment. A struct {x: double, y:uint8} has size 16 instead of 9 so that alignment of the double field works if you create an array of such structs. On the other hand, the struct {x1:uint32, x2:uint32, y:uint8} would have size 12 instead of 9 because it only needs 4-byte alignment.

MM: I heard there was soemthing about a reflective operation for obtaining the layout?

DH: it's work I still ahve to do.

MM: what object do you get back?

DH: TBD. Tempted to say it looks like the thing you passed in originally.

WH: I dont' see bool...deliberate?

DH: yep.

WH: let me go on record as requesting a bool field.

?: Can't you use uint8 for bool? ?: Use object type for bool. ?: What about other types such as different kinds of objects?

WH: bool is different. I am only asking for bool here. A bool stored in a single byte, so using 8 bytes for an object reference for it would be a substantial cost. A uint8 is not a suitable replacement because one of the major use cases for structs is to use them as an efficient backing store for objects, and getting 0 and 1 instead of false and true would be a really annoying impedance mismatch.

MM: how many bits per bool does an array of bool's contain?

BE: needs to be exactly 1 byte

WH: Don't want to repeat the C++ vector mistake that tried to pack it to 1 bit/bool and ended up breaking lots of things. The C++ committtee now regrets having done this.

link 9 JSON (Continued)

(Doug Crockford)

DC: Explaining updates made since yesterday

  • Reordered Appendix
  • Moved ECMAScript mention

The last big change is that Rick suggested removing the security section (10) and I think I agree

AWB: Those don't apply to a spec at this level

DC: Agree, I don't think it belongs

AWB: what's the start symbol of the grammar?

DC: unspecified.

RW: my suggestion was to re-order the appendix to ensure that Value comes first and that anything that is one starts the gammar

AWB: I think it should specify a start symbol.

DC: some uses of JSON won't want a bool at the top level

AWB: ..or array, or object. All this describes is the universally valid syntax, and that has to start somewhere.

DC: I don't think it does

AWB: then I don't know how to parse/validate.

YC: I think you do need a root symbol. I've had this exact issue.

AR: C++ experience backs that up. Lots of incompat.

RW: can't we just say that anything that's a value can begin the production?

MM: we have a historical conflict. As I read the ES spec vs. this, we see value vs. object/array.

DC: it should be value, then. How should we specify that?

AWB: just say that any input that can be parsed that uses that start symbol is valid JSON text

MM: we should decide if we want to be compatible with reality or the RFC. Given that we decided on value in ES, we have incompat. Shifting to value as the start symbol would be up-compat with reality and current practice.

AWB: doesn't say what a "reader" does with this grammar, so can allow/disallow however it wants. There's no universal JSON reader.

MM: JS might accept those things but not give you access to the literal content of the values

NL: this should be based on Unicode code points. We don't know how to convert between things if we don't.

DC: best practice might be to use Unicode, but this grammar doesn't need to.

NL: I differ. We care about computing in this group.

DC: if someone wants to use a 6-bit code to send JSON from a satellite, JSON is agnostic.

AWB/NL: The title says "interchange format", should probably just be a "grammar"

NL: Without reference to Unicode code points, we can't decide which characters Unicode escape sequences are equivalent to, e.g. \uxxxx ===? ö \uxxxx\uxxxx ===? ö

AVK/NL: current best practice is to base document formats on Unicode, e.g. HTML

WH: The description of where whitespace can go is broken. Currently it's described as only being allowed before or after one of the punctuation symbols. That means that "{3}␊" parses but "3␊" does not.

MM: Crock, what purpose does the document serve?

DC: ... i forgot what he said

MM: Comparison to RFC

AVK: Refers to ECMAScript's JSON, not the RFC

AWB: Wants other standards to make references to this normative standard and not some other. ...To avoid the inclusion of anything that isn't the grammar, eg. mime type

MM: The danger of the IETF is trying to go beyond the RFC.

AWB: This document to have the grammar over an abstract alphabet, normative Unicode mapping to that abstract alphabet.

MM: Ok, a two level grammar. Still a refactoring of the RFC and that's ok.

AVK: You don't have to refactor, just define the grammar as a code point stream

note differences between code points and character encodings

MM: Why retreat from the RFC?

DC: There is contraversy in that it tolerates unmatched surrogate pairs. Want a standard that avoid that contraversy

NL: You can avoid it by talking about code points. The transfer format can outlaw unpaired surrogate, e.g. utf-8.

AVK: Right, utf-8 does not allow lone surrogates, it can only encode Unicode scalar values.

[After the fact note, we neglected escapes here...]

BE: Try to avoid duplicating efforts

DC: This is meant to be a guard against other efforts going out of bounds.

BE/AWB: Need to be addressed:

  • Goal symbol
  • "e" production
  • leading/trailing whitespace
  • character sets

NL/AVK: Without describing the character encoding

Discussion about character => code point

AVK: Need to define a representation you're using

AWB: Define the alphabet

AVK: Use the Unicode alphabet, without talking about utf-8, etc.

AWB: DC might be rejecting the discussion of encoding.

DH: The purpose of code point is to avoid talking about encoding.

AR: Why is this so important?

AVK: In order to describe the grammar, you need to define an abstract alphabet, Unicode is sufficient.

MM: This differs the RFC is code units instead of code points

DC: I will add a sentense in the section about JSON text, that it's a sequence of code points

AWB: Unicode code points

Include an informative note that it doesn't imply a specific character encoding

Character sets:

1
"json text is a sequence of Unicode code points that conforms to this grammar"

Start symbol:

1
value

MM: Move to declare consensus?

AWB/WH: Doug needs to finish an editorial pass

link Consensus/Resolution

  • Pending the remaining edits, to be discussed for approval tomorrow.

link Test 262 Update

(Brian Terlson) Test262-ES6.pdf

Talk about moving test262 to github.

BT: What do we need to make that happen?

DH: Use CLA for pull requests.

DH: Lets not solve this now. Lets stick to the current process that only we can only approve PR from members of TC39/ECMA

Apporoved to move the source code to GitHub, keeping all the current process for approval of tests.

IS: We will need to have a way to download the tests from ECMA.

IS/AWB: Needs to be an update to the tech report. Describing what the different packages are good for.

BT: In due course backporting will be hard, but in the ES6 timeframe it should be okay.

MM: Are we anticipating backwards incompatible changes to the testing harness?

BT: There migth be some, we can probably avoid it.

MM: good, good.

BT: In ES6 a number of tests moved location. We'll create a map and move them programmatically.

AWB: I'm planning on making the reorganization within the next few weeks.

BT: We'll annotate the tests with previous and new locations.

BT: Norbert's proposal is to rename the folders to use English names and remove the multitude of subfolders.

[Discussed moved to organization of the spec.]

AWB: There could be an arbitrary number of chapters in the spec. It's somewhat convenient to be able to say "chapter 15".

BE: Core shouldn't depend on 15.

AWB: Trying to get to that situation.

MM: I don't object to a part 1 / part 2 organization, but I also don't see the point.

MM: Back to tests, I want test directories to match spec chapters.

BT: Agreed.

BT: Contributors: http://wiki.ecmascript.org/doku.php?id=test262:coreteam Need to expand.

DH: We could use github pages and make test262.ecmascript.org point to that.

DH: BT, you set up a mirror for the site. I will do the DNS switch, call me, maybe.

BT: Given the new algorithms, designating algorithm step is not always feasible. Proposal is to require identifying the section, and maybe the algorithm step.

BT: Ensuring full coverage becomes harder.

[Much discussion on algorithm step designation not minuted.]

YK: This should probably be dealt with at the champion level.

BT: Open issues: How to create cross-host-compatible collateral for realms and scripts?

MM: ??

MM: We might only be testing the slow path of JavaScript engines. Testing things in a loop will help.

[Insert poison attack.]

link Consensus/Resolution

  • move the repo and test262 web presence to github.com/tc39

link 5.2 Can computed properties name in object literals produce string prop names? Duplicates?

(Allen Wirfs-Brock)

http://esdiscuss.org/topic/on-ie-proto-test-cases#content-5

AWB: Latest revision include computed properties

1
{ [x]: 1, [y]: 2 }
  1. Can x evaluate to a string or a symbol? The concern is that people hope to determine the shape of objects by looking at them (but engines also want to determine the shape statically)
  1. Duplicates?

EA: I thought we allowed any value as a computed property

DH: Yes, and converted with ToPropertyKey

Discussion re: duplicate computed property keys

DH: Comes down to "how likely are there going to be consequences

WH: I draw a distinction between definition and assignment and I view this example as definition.

EA: If you call defineProperty twice with the same property you do not get an exception. We should have the same semantics for define property in an object literal (and class).

MM: Often enough, if you get a

MM: The importance of throwing an error at the point

YK:

MM: If these are symbols, the programer did not intend to override a previous property.

DH: JavaScript practioners consistently tell us they prefer fail-soft with opt-in. Having said that, we are deploying strict mode more widely.

BE: We don't know, people will write top-level functions.

DH: It's the direction we're heading in.

WH: Main motivation here is consistency. In strict mode we intentionally made having duplicate properties such as {a: 3, a: 4} be an error. That rule is simpler and easier to remember than a rule that constructs another exception such as it being an error unless one of the properties is specified using [].

[debate]

WH: This has nothing to do with allegations of trying to make the language less dynamic. I want the simplest, easiest to remember rules. Had duplicate textual properties been allowed in strict mode, I'd be campaigning to also allow them if they're specified using [].

...

Discussion re: strict mode checking vs non-strict mode checking

There was an assumption that computed properties would disallow duplicates in strict mode (throw)

MM: The failure will frustrate programmers, but the lack of a failure will frustrate programmers. You say some prefer fail soft, I know of some that want fail fast.

DH: Static checks are easy to reason about and easy to justify. Dynamic checks are harder to justify and lead to unpredictable results.

AWB: What happens when x is undefined?

BE: Let's stick to duplicates

It's unlikely to want duplicates

The most common case is that you write two lines like the above and that's what you want

We should not creep into B&D language with runtime errors

Quick poll:

1
2
3
- error, 7
- no error, 6
- abstain, 9

DH: I want to hear a response to Mark's point about being bitten by fail-soft

AR: In Google Wave, you'd get notices that the application "crashed"... the rest of the web doesn't behave that way. Fail soft is seen be some as "wrong" and others as "going along". I put more favor towards getting "going along".

AVK: In specifying web APIs, authors regularly requesting less errors. Back in 2000's, WebKit had asked for less errors...

YK: Identifies committee pathology

EA: Waldemar wanted symmetry with the iterable parameter to the Map constructor regarding duplicate keys.

LH: Do not agree that we need symmetry here.

BE: This is syntax, Map parameter is not symmetry.

Recapping Waldemar's position about consistency with duplicate string keys in Objects in strict mode.

Break.

Post break discussion, after the points made about @@iterator and @@create

link Consensus/Resolution

  • Strings allowed
  • Strict Mode: Duplicates are an Error
  • Non-Strict Mode: No error

link 5.3 Special syntax for proto in an object literal

(Allen Wirfs-Brock)

AWB:

1
{"__proto__": foo}

MM: Uncomfortable with either semantics for this issues

YK: This is new syntax that looks like old syntax

...quotation marks and no quotation marks should do the same thing.

DH: But then there is...

1
{ ["__proto__"]: foo}

YK: So for dict, we want "proto" as a regular property?

MM: Yes

DH: Allows...?

MM: I'm ok with either decision, because equally uncomfortable

DH: What happens today?

1
2
{__proto__: foo }
{"__proto__": foo}

Same.

MM: Then the quoted case should remain as is.

BE: The

MM: computed form:

1
2
- no compat hazard
- new special case that requires checks
  • too much overhead
  • syntactically unclear re: outcome.

link Consensus/Resolution

  • proto: magic
  • "proto": magic
  • ["proto"]: no magic, just a string
  • ["" + "proto"]: no magic, just a string

link 5.4 Are TypedArray insances born non-extensible?

LH: Pretty sure all are extensible.

DH: I'd like them to be not extensible. There's performance benefits. No reason for expandos. Put them on another object. Gecko is not extensible.

WH: Second

DL: Current implementation allows them to be extensible

AR: does anyone think they should be extensible?

crickets

tumble weed

link Consensus/Resolution

  • TypedArray instances are not extensible.

link 5.5 concat and typed arrays

(Allen Wirfs-Brock)

AWB: Anything that's an exotic array (ie. Array.isArray(a) === true), will "spread"

...Gets weird with Typed Arrays

Proposing:

1
Specifically for concat, we give Typed Arrays a new special concat that auto spreads

MM: The only sensible approach has to be type compatible

DH: concat is badly designed

...If we have to do a new method, we shouldn't try to simulate bad behaviour

Conversation leans toward:

  • Two new methods that represent the two behaviours of concat, but as single operations each
  • Names need to be added to @@unscopeable

LH: Does not like a new method that does 90% of the same as another existing method

DC: can't we just lean on the new syntax? Use "..." for this:

1
new Uint8Array([...array1, ...array2]);

AWB: if this isn't heavily optimized, this is going to create a large intermediate object

DH: this might create issues until people get "..." and engines want to stack-allocate args

AWB: not an arg

// agreement

Mixed discussion about general purpose apis that are lacking in the language.

BE: how should we settle those issues?

AR: with science. Look around the world and see what's most common; then put those things in the std lib

link Consensus/Resolution

  • No concat on Typed Arrays

link 5.11 ToUint32(length) and Array.prototype methods

(Allen Wirfs-Brock)

AWB:

1
2
let len = Get(o, "length");
let len = ToUint32(len);

If "o" is a Typed Array, this above will

Can duplicate all the algorithms to handle Type Arrays

Don't want to do that

What is the impact of changing to:

1
2
let len = Get(o, "length");
let len = ToInteger(len);

53 bits

DH: Wrapping around?

AWB: Getting there, not done with points

For regular arrays, already there, constrained to uint 32

Only talking about Get, not Put

1
[].forEach.call({ 1: 1, [Math.pow(2, 32) - 2 ]: "pow", length: Math.pow(2, 32) -1 }, e => ...)

Visits only the first (nothing after, because holes)

1
[].forEach.call({ 1: 1, [Math.pow(2, 32)]: "pow", length: Math.pow(2, 32) 2 }, e => ...)

Visits the first and last (nothing in between, because holes)

1
[].forEach.call({ 1: 1, [Math.pow(2, 32)]: "pow", length: Math.pow(2, 32) -1 }, e => ...)

Readers: That would be really slow and insane. Don't do that.

Propose ToLength()

  • return length >= 0 ? Truncate to 2^53-1 : 0;

WH: Note that this only applies to the length property. In other places where the Array method take positions or lengths as parameters, they already call ToInteger, not ToUint32.

MM: Are there places where the operational meaning of -1 is changing?

BE: There's hope to make this change, sure that the only things that will be broken will be tests.

WH: [[Put]] still has a restriction?

AWB: Yes

Typed Arrays are not exotic arrays

BE: Typed Arrays are going to use 64 bit unsigned for the length, gonna be nice.

link 5.14 keys(), entries() return numbers for array index properties

(Allen Wirfs-Brock)

https://bugs.ecmascript.org/show_bug.cgi?id=1560

AWB: Arv filed a bug re: Array iterators, the keys() iterator (as well as entries()). Currently it is speced to use strings for the indexes. It would be better to use numbers.

RW: Agree, the string property would be unexpected.

General agreement

link Consensus/Resolution

  • keys(), entries() use numbers for array index properties

link 5.7 Does Object.freeze need an extensibility hook?

(Allen Wirfs-Brock)

AWB:

1
2
let y = Object.freeze([1, 2, 3]);
let x = Object.freeze(new Uint8Array([1, 2, 3]));

The second does not really freeze the underlying buffer. So, the following does not work as the array case:

1
x[1] = 1;

Discussion about the operational understanding of Object.freeze, clarifications by Mark Miller.

Lengthy discussion about Object.freeze

AWB: Proposes the freeze hook

@@freeze

Called before the freeze occurs

DH: I'm pro mops, but you have to be careful with thems.

LH: Don't think it's wrong that the second item (from above) doesn't freeze the data, that's not what Object.freeze does.

WH: Object.freeze is part of the API and should match what reading and writing properties does (at least for "own" properties). Having Object.freeze not freeze the data is bad design

LH: Object.freeze is bad design, Typed Arrays are bad design, we're stuck with them, so what should they do.

DH: (agrees)

MM: Object.freeze is named badly. Other than that, there's nothing bad about its design. Its purpose is to make an object's API tamper proof

LH: (agrees)

AWB: Method that creates frozen data?

1
Object.freeze(new Date())

link Consensus/Resolution

  • No @@freeze MOP hook.

link 5.4 Typed Array MOP behaviours (Continued)

AWB: Talking about the descriptors of the properties of TypedArrays

1
{value: ?, writable: true, enumerable: true, configurable: false}

MM: Doing a defineProperty on a single one, should throw. Doing a freeze on the whole thing, is allowed.

BE: Right now we throw from freeze

MM: Making these appear like properties in the MOP, throw on individual properties changes.

1
2
3
4
var b = new Uint8Array([1, 2, 3]);
Object.defineProperty(b, "1", {});
// Throws!

BE: This makes sense.

link Consensus/Resolution

  • Object.defineProperty on Typed Array will throw
  • Object.freeze on Typed Array will throw

Ecma/TC39 Meeting – Jul 23 2013

link July 23 Meeting Notes

John Neumann (JN), Luke Hoban (LH), Rick Hudson (RH), Allen Wirfs-Brock (AWB), Yehuda Katz (YK), Anne van Kesteren (AVK), Jeff Morrrison (JM), Sebastian Markage (SM), Paul Leathers (PL), Avik Chaudhuri (AC), Ian Halliday (IH), Alex Russell (AR), Dave Herman (DH), Istvan Sebestyen (IS), Mark Miller (MM), Norbert Lindenberg (NL), Erik Arvidsson (EA), Waldemar Horwat (WH), Eric Ferraiuolo (EF), Matt Sweeney (MS), Doug Crockford (DC), Rick Waldron (RW)

JN: Brendan will be here tomorrow

Introductions.

link Agenda

(https://github.com/tc39/agendas/blob/master/2013/07.md)

Discussion about getting agenda items in earlier, general agreement.

AWB: Clarifying #5 Open Issues (previously presented as a slide deck, now easier to track)

link Consensus/Resolution

Will continue to use Github as the agenda tool, with the constraints:

  • Agenda should be "locked in" 1 week prior to meeting
  • Agenda URL will be posted to es-discuss immediately following the current meeting
  • Allen has running "Open Items" section.

Corrections:

  • What to expect in the RFTG mode
  • Add JSON document to #9 JSON

Agenda Approved.

JN: Welcomes new Facebook participants

link 4.1 ES6 Status Report

(Allen Wirfs-Brock)

AWB: Draft published, Revision 16

  • Backed out the Symbols as non-wrapper types from Revision 15
  • Section items renumbered for clarity
  • Want to re-org/re-order the entire document
    • Primarily re-order the lexical grammar and syntax (currently out of order by 3 sections)

LH: (asked for motivation)

WH: Noticed...

  • Changed for-in to disallow left side assignment expression.
  • Syntax for arrow doesn't propagate the NoIn-ness of grammar rule. A NoIn arrow grammar production expands into a seqence that ends with a non-NoIn expression. If we hadn't changed for-in to disallow left side initializers, this would break the grammar by allowing in's to leak into a NoIn expression. However, we have changed for-in to disallow left side initializers. Given that, the regular/NoIn syntax rule bifurcation is now pointless. We have an opportunity to simplify and regularize the grammar here.

AWB: Will look into removing the NoIn productions.

LH: This was discussed recently on es-discuss (need reference)

AWB:

  • Further rationalization of alphabetizing Chapter 15
  • Reminder that people should use the bug tracker for spec revision issues.
  • Implementor feedback will be prioritized

LH: Re: initializer argument with an "entries" property will be used to create the entries in the Map (7.a)

"Let hasValues be the result of HasProperty(iterable, "entries")."

AWB: Explains the rationale of creating a new map from an existing map

1
2
var m1 = new Map();
var m2 = new Map(m1);

LH/DH/YK/RW: Should be:

1
2
var m1 = new Map();
var m2 = new Map(m1.entries());

EA: Should just use @@iterator, which is entries, but without explicitly checking for a property called entries.

DH: Advocate for uniform API, test for existance, assumes it's iterable, 2 element array-likes and initialize.

MM: Have we decided on the convention that an iterator of X is also an interable of X. A map.entries() gives you an iterator.

YK: map is already an iterable

DH: Should make sense to pass an iterator to Map

AWB: All the built in iterators are also iterables

DH: Agree, though this has been debated

WH: What happens...

1
2
new Map([ "abc", "defg", "hi" ]);
new Map([{ 1: 10, 0: 20 }]);

BE: The first one makes a map mapping "a" → "b", "d" → "e", "h" → "i". The second one makes a map of 20 → 10.

AWB: The algorithm for Map should check for entries to be Object

DH:

MM: I don't think we should special case for string

AR: Agree, but not with example

MM: Making a special case for String seems like an odd decision

AR: In the case of i18n where we can't change the code point... you can imagine having a string map, but if I can just pass in a string.

... Don't object, just exploring

AWB: Objecting. What use case can you imagine where programmers intend for strngs to be array-like?

MM: None reasonable

...

MM: Question about value objects. If the value object responds to Get(0) or Get(1)

WH: with Mark, don't want special tests for different types

LH: If I do...

1
new Map([ 1, 2, 3 ]);

I will get undefined, undefined, undefined, which is a stronger case for making the check

DH: +1

WH: Elsewhere, we've gone to detect duplicate errors

AWB: Checking for duplicates will duplicate the cost

MM: The impl of any hash table will require a test for duplicate keys

AWB: What about key, values that have been collected over time?

MM: There are use cases for duplicate key checks

LH: Historically, we make duplicate checks when it's syntactic, and this is the first time we're trying to apply duplicate checks to runtime semantics

MM: If something you didn't expect happens once, i'd much prefer an error

YK/RW: That's bad for the web

RW: Map would become a "try/catch" case

... mixed discussion about the precedent for loud or quiet handling

WH: Are there any other constructor that throw when created "incorrectly"?

RW: In non-strict mode, a program can create an object with all duplicate keys and never fail in production

...

MM:

AC: Creation can be what is the least requirement for what it takes to create a map. Taking an arbitrary structure and make a map and it's perfectly good semantics to

LH/MM: Offline conversation about what qualifies for extra defense.

DH: Select cases where there is easy to argue that there few legitimate uses, ok to have occassion sanity tests. In general, JavaScript does not go out of it's way to provide you with defensive mechanisms. It's hard to predict where people are going to get hurt, better to allow them to decide.

WH: Paying for consequences where with doesn't protect against collisions.

AWB: Try to apply my model when writing these algorithms, please try to read the algorithms when they are published

link Consensus/Resolution

  • Map contructor, accepts optional initializer
  • If initializer undefined, creates an empty map
  • If initializer defined, invoke the @@iterator to create the entries from.

    • For each entry, check if non-null object, throw if not (If Type(map) is not Object then, throw a TypeError exception.)
    • pull off the 0 and 1 property
    • make 0 a key and 1 value
    • No check for duplicate keys
  • Remove the explicit check for an "entries" property, this is implied by the check for "@@iterator"

UNRESOLVED

AWB: Will put a note in the spec: "Unresolved: how to handle duplicate keys"

WH: Don't yet have consensus on how to handle duplicates, would like to discuss computed properties

link 4.3 Array.prototype.values

(Allen Wirfs-Brock, Rick Waldron)

AWB: Ext.js uses a with(...) {}

1
2
3
4
5
6
7
function f(values) {
with(values) {
...
}
}
f([]);

YK: Means that we can't add common names for common objects?

RW: ...Explained that Ext.js fixed the issues, but face a commercial customer update challenge. In the meantime, it continues to break several large scale sites.

AWB: Brendan's workaround (from post on the list)

1
2
3
values() -> @@values();
keys() -> @@keys();
entries() -> @@entries();

Importing from a module...

1
2
3
values() -> values([]);
keys() -> keys([]);
entries() -> entries([]);

DH: Warming up to the idea of a general purpose protocol, implement your map-like protocol.

WH: But now you need an import

EA/AR/DH: Web breaking... but why not break

AR: Meta property, [[withinvisible]]

(Way too much support for this)

DH: This idea is fantastic

EA: Very useful to the DOM, may not need another bit on the object, maybe just a "whitelist".

MM: A very small list of names that "with" doesn't intercept

YK: Could, but semantically almost the same thing

EA: But without the extra bit on all objects

MM: Don't want to require a new bit for all objects.

DH: Need to fully explore the effects on the rest of the language..

  • Blacklist for just Array or all objects?

EA: A blacklist that exists, string names, when you enter with(){}, the blacklist must be checked.

MM: If the base object is Array, if the name is on the whitelist

EA: Have an instanceof check? This problem happens in the DOM with Node

EA/YK/AR: We can actually use this for several use cases.

EA: The issue needs instanceof to check the prototype chain.

AWB: For objects you want to treat this way.

DH: The middle ground...

@@withinvisible, well known symbol

1
2
3
4
5
Array.prototype[ @@withinvisible ] = [
"values",
"keys",
"entries"
];

AVK: Might have a more generic name, can be used with event handlers

DH: @@unscopable?

1
2
3
4
5
Array.prototype[ @@unscopeable ] = [
"values",
"keys",
"entries"
];

WH/MM/RW/YK: actual clapping

... Mixed discussion about performance. General agreement that penalties for using with is ok.

AWB: Code may override this, but at their own risk. For example

link Consensus/Resolution

  • @@unscopeable
  • A blacklist, array of strings names that will not resolve to that object within with() {}

DH: This is about the extensible web ;)

link 3 Approval of the minutes from May 2013 (2013/029)

JN: Need to approve the notes...

Are there are any changes to approve?

(none)

link Consensus/Resolution

  • Approved.

link 9 JSON

(Doug Crockford)

DC: Gives background re: JSON WG and presents a proposed JSON standard to be submitted to Ecma.

  • Please read tonight for review tomorrow

NL: Benefit from reading the JSON mailing list threads.

YK: Will be painful.

AR: This document seems completely unobjectional

DC: IETF claims abstract formats cannot work

Mixed discussion about consequences.

(Read and be prepared for meeting tomorrow)

link 4.2 Add fill and copySlice methods to Array.prototype and Typed Arrays

(Allen Wirfs-Brock)

http://wiki.ecmascript.org/doku.php?id=strawman:array_fill_and_move

AWB: The Chronos group want to add methods

  • fill a span of a typed array
  • move copy, with care for the overlap

link Array.prototype.fill (Informal Spec)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Array.prototype.fill = function fill(value, start=0, end=this.length) {
/*
Every element of array from start up to but not including end is assigned value.
start and end are coerced to Number and truncated to integer values.
Negative start and end values are converted to positive indices relative to the length of the array:
if (start < 0) start = this.length-start
Reference to start and count below assume that conversion has already been applied
If end <= start no elements are modified.
If end > this.length and this.length is read-only a Range error is thrown and no elements are modified.
If end > this.length and this.length is not read-only, this.length is set to end
Array elements are set sequentially starting with the start index.
If an element is encountered that cannot be assigned, a TypeError is thrown.
Element values are assigned using [[Set]]
The array is returned as the value of this method
*/
}

Examples

1
2
3
4
5
6
7
aFloatArray.fill(Infinity); // Fill all elements with Infinity
aFloatArray.fill(-1, 6); // Fill all elements starting at index 6 with -1
aFloatArray(1.5, 0, 5); // Fill the first five elements with 1.5
aUint8Array(0xff, -2); // Place 0xff in the last two elements
[ ].fill("abc", 0, 12)
.fill("xyz", 12, 24); // Create a regular array, fill its first dozen
// elements with "abc", and its 2nd dozen elements

link Array.prototype.copySlice (Informal Spec)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Array.prototype.copySlice = function copySlice(target = 0,start = 0, end = this.length ) {
/*
The sequence of array elements from start index up to but not including end index are copied within
the array to the span of elements starting at the target index.
target, start, and end are coerced to Number and truncated to integer values.
Negative indices are converted to positive indices relative to the length of the array.
If end <= start no elements are modified.
If end > this.length a Range error is thrown and no elements are modified.
If target + (end-start) > this.length and this.length is read-only a Range error is thrown and no elements are modified.
If target + (end-start) > this.length and this.length is not read-only, this.length is set to target+(end-start).
The transfers takes into account the possibility that the source and target ranges overlap. Array elements are
sequentially transferred in a manner appropriate to avoid overlap conflicts. If target <= start a left to right
transfer is performed. If target>start a right to left transfer is performed.
If a target element is encountered that cannot be assigned, a type error is thrown and no additional elements are modified.
Sparse array "holes" are transferred just like for other array functions.
The array is returned as the value of this method
*/
}

Examples

1
2
3
4
5
6
7
8
9
10
11
12
[ 0, 1, 2, 3, 4 ].copySlice(0, 2);
// [ 2, 3, 4, 3, 4 ]
[ 0, 1, 2, 3, 4 ].copySlice(2, 0, 2);
// [ 0, 1, 0, 1, 4 ]
[ 0, 1, 2 ].copySlice(1);
// [ 0, 0, 1, 2 ]
Int8Array.from([ 0, 1, 2 ]).copySlice(1); // RangeError
Int8Array.from([ 0, 1, 2 ]).copySlice(1, 0, 2); // Int8Array 0,0,1
Int8Array.from([ 0, 1, 2 ]).copySlice(0, 1, 2); // Int8Array 1,2,2

Moving data within an array, destructively on the calling array

AWB: Possibly rename copySlice => copyWithin

LH: Should Typed Arrays have the same surface as Array?

DH: Typed arrays better behaving and better performing since they guarantee density. (non-sparse)

  • Notes concat as the only array method that expects explicit array-ness

RW: Do we have consensus

DH: Brendan had issue with fill

AWB: Brendan's issue was the similarity with copySlice and had suggested fillSlice.

DH: Not sure I understand his objection...

link Consensus/Resolution

  • Agreement in room
  • Would like Brendan's input

link 4.4 Consider deferring ES6 Refutable Matching.

(Allen Wirfs-Brock)

AWB: In March, we agreed to add refutable pattern matching; began working on adding this to destructuring and realized the work involved would be too great, considering the time frame remaining for ES6.

Propose to defer refutable pattern matching.

(whiteboard)

The current spec would attempt to do a ToObject(10); and would throw:

1
let { a, b } = 10;

What happens when you reference a property that doesn't exist on the object, will throw:

1
let { a, b } = { a: 10, c: 20 };

To avoid throwing:

1
let { a, b = undefined } = { a: 10, c: 20 };

YK: Removing the question mark breaks the consensus.

AVK: Is it hard to spec the "?" on the outside? Allowing only one level?

AWB: It wouldn't be hard, but it creates a weird language issue.

YK/AWB: It's easy to do in the grammar

LH: What was in the spec, solved 80% of the cases, we moved to a solution for 100% and this will set us back to 20%, which isn't acceptable.

AWB: What happens at the parameter list level?

YK: Ah, there is no place to put the out "?"

DH: Agrees... as long as we have a fail-soft, we're ok (YK/LH/RW agree)

YK: We could make the extra sigil mean refutable.

WH:

1
let [a, b] = "xyz";

YK: Why Andreas would have argued strongly against a refutable sigil?

DH: I think this will fail without inclusion of Brendan and Andreas

AWB: Andreas is fine with dropping refutable matching

DH: Are you sure?

Current spec is fail soft

As long as Brendan and Andreas are ok with it, we can fall back to fail soft.

AC: The fail soft is consistent with JS behaviour. If you want something stricter, then the problem should be on the right side, not the left side. Otherwise you need to introduce an operator for the left.

AWB: (reads back conversation from Andreas)

DH/YK: He doesn't seem to say anything about returning to fail soft.

LH: I think we've exhausted the conversation

WH: If we don't do it now, the behavior of refutable and regular rules will be inconsistent in the future; i.e., a trivial refutable rule that doesn't actually make use of the refutable features will behave inconsistently with a textually identical nonrefutable rule.

YK: But you'll be able to opt-in to the full set of "refutables"

WH: I think it's uglifying the future.

YK/LH: It is.

DH: There is precendence in Mozilla's destructuring, that doesnt have refutable matching.

LH: If we added the bang which is the strict mode for this and adds the bang in front, opts in.

AWB: The next part...

WH: The string example:

1
let [a, b] = "xyz";

Should there be implicit ToObject on the right side?

YK: We agreed new String() solves the problem, if that's what you actually wanted to do.

link Consensus/Resolution

  • No implicit ToObject() on the right side (eg. the string will throw)

link x.x Review of Proposed Features

(Luke Hoban)

link Function toString

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

MM: The one issue about Function toString, discovered since the strawman was written:

Since eval()uating a function declaration or function expression defaults to non-strict, a strict function must present the source code of its body as beginning with a “use strict” directive, even if the original function inherited its strictness from its context. This is the one case where the original local source code of the function is inadequate to satisfy this spec.

YK: Doesn't account for super, either

Discussion about identifiers captured from lexical environments.

Was the lexical environment strict?

link Consensus/Resolution

Change wiki strictness included in notion of lexical context. Thus

  • always adequte for toString to preserve the original source
  • result behaviour equivalence does not require injecting "use strict"

link Function name property

(Allen Wirfs-Brock) http://wiki.ecmascript.org/doku.php?id=harmony:function_name_property

AWB: The spec doesn't have mechanisms for capturing the name based on the syntactic context.

LH:

1
let f = function() {}

...Needs to know "f".

AWB: It's not an insignificant amount of work.

...Conversation Moves towards prioritization.

link Modules

LH: Need to know that modules are going to be spec'ed asap.

DH: This is my next item to work on

AWB: Modules are the next most important and significant to address in the spec.

High priority

link Standard Modules

DH: Back off on standard modules for ES6, very few things.

Standard Modules:

  • Math
  • Reflect

YK: All of the built-ins.

RW: If I want to avoid using a tainted built-in, import { Array } from "builtins";

DH: What does this directly solve?

YK/RW: When you want to get a fresh, untainted _.

AWB: Who will write out the standard modules?

EF/YK/RW can work on this

Mixed discussion about feature dependency.

DH: Luke and I can craft a dependency graph offline.

link Binary Data

On track (wiki near complete)

High priority

link Regexp Updates

Low priority

DH: Optimistic that we can get Modules and Binary Data to green (in the spreadsheet)

link Proper Tail Calls

DH: Just need to identify the tail position and finish the spec.

AWB: It's just a time consuming project. Property access in tail position? Not tail call.

DH: Safely:

  • function call
  • method call

link Consensus/Resolution

  • Plenty of work left.

link 4.7 Math

(Dave Herman)

DH: Introduces need for 64bit float => 32bit float and projecting back into 64bit float. If we had a way to coerce into 32bit

  • Can be simulated with TypedArray (put in a value, coerced, pull out)
  • To have a toFloat32

EA: Does JSIDL Need this?

YK: Not that I know of

MM: The real number it designates is a number that is designatable as 64bit

DH: (confirms) If you have a coercion, the implementation could do a 32bit operation

WH: Note that for this to work, you must religiously coerce the result of every suboperation to float32. You can't combine operators such as adding three numbers together.

Given x, y, z are all float32 values stored as regular ECMAScript doubles, the expressions

x+y+z float32(x+y+z) float32(float32(x+y)+z)

can all produce different results. Here's an example:

x = 1; y = 1e-10; z = -1;

Computing x+y+z using float32 arithmetic would result in 0. Computing float32(x+y+z) would not.

On the other hand, there is a very useful property that holds between float32 and float64 (but not between two numeric types in general such as float64 and float80), which is that, for the particular case of float32 and float64, DOUBLE ROUNDING is ok:

Given x, y are float32 values, the following identity holds, where +_32 is the ieee single-precision addition and +_64 is the ieee double-precision addition:

float32(x +_64 y) === x +_32 y

And similarly for -, *, /, and sqrt.

Note that this does not hold in general for arbitrary type pairs.

Here's an example of how DOUBLE ROUNDING can fail for other type pairs. Suppose that we're working in decimal (the issues are the same, I'm just using decimal for presentation reasons), and we compute a sum using arithmetic that has four decimal places and then round it to store it into a type that has two decimal places.

Let's say that the sum x+y is mathematically equal to 2.49495. 2.49495 (mathematically exact sum)

Then we get: 2.4950 (properly rounded result of invoking + on the wider 4-decimal place type) 2.50 (rounded again by coercion to narrower 2-decimal place type)

Yet, if we had invoked + on the narrower 2-decimal place type, we'd instead have gotten the result: 2.49 (mathematically exact sum rounded to narrower 2-decimal place type)

AWB: Is the proposal to expose a toFloat32?

DH: Yes and the Math object seems like the obvious place

RH: Also, toFloat16

DH: Long term, the solution will be value objects, but in the near term, this will have benefit much more quickly

WH: Found evidence that the optimizations are safe as long as the wider type is at least double the width of the narrower type plus two more bits: http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html . This is the case for the float32/float64 pair (they're 24 and 53 bits wide respectively), but not in general.

link Consensus/Resolution

  • Math.toFloat32()

    More discussion about where (Math, Number.prototype)

link 4.8 Stable Array.prototype.sort

(Norbert Lindenberg)

https://mail.mozilla.org/pipermail/es-discuss/2013-June/thread.html#31276

NL: Does anyone know of performance issues that prevent going to stable sort.

DH: Tread lightly, no one wants regression

EA: Libraries implement stable sort today because they need it.

YK: D3

MM: If the answer is that performance is negligible, then we should mandate stable sort. Otherwise, we don't. We need to answer the question first.

link Consensus/Resolution

  • Deferred

link 4.9 Time zones 1: Bugs or spec issues?

(Norbert Lindenberg)

https://mail.mozilla.org/pipermail/es-discuss/2013-July/032087.html

Discussion around the semantics of Date

AVK/MM: Be able to create a date instance with a timezone, other then the current timezone

MM: ES5 implies a live communication channel into the Date instance

AWB: It's part of the algorithms

MM: We could say that we're going to stand on the ES5 spec.

link Consensus/Resolution

  • Deferred

link 4.10 Time zones 2: Time zone as property

(Norbert Lindenberg)

https://mail.mozilla.org/pipermail/es-discuss/2013-July/032080.html

NL: Dean Landolt proposed a property on Date.prototype for the timezone, that all the functions look for, born with the default timezone, but can be changed.

MM: Should be static, like Date.now()

RW: Otherwise there would be Date objects with different timezones.

link Consensus/Resolution

  • Deferred

link Date/Timezone

Proposal 1 AVK: Having Date objects that have timezone as internal data instead of system data.

Proposal 2 NL: Pass time zone information separate from Date (as a parameter to methods)

link Consensus/Resolution

  • Write a strawman for ES7 (either)

Ecma/TC39 Meeting – May 23 2013

link May 23 Meeting Notes

(by Erik Arvidsson)

John Neumann (JN), Allen Wirfs-Brock (AWB), Eric Ferraiuolo (EF), Erik Arvidsson (EA), Luke Hoban (LH), Doug Crockford (DC), Yehuda Katz (YK), Sam Tobin-Hochstadt (STH), Alex Russell (AR), Dave Herman (DH) (calling in), Bernd Mathiske (BM), Andreas Rossberg (ARB), Mark Miller (MM), Tom Van Cutsem (TVC), Istvan Sebestyen (IS)

link Promises vs Monads

MM: ...Continuing from yesterday

AR: https://github.com/slightlyoff/Futures/blob/master/Promise.idl

STH: Don't like resolve but not willing to die on this hill.

AR: DOM has a bunch of ad hoc APIs to do promise like things.

YK: Mozilla is also actively working on APIs using promises.

AR: A lot of methods today return void so we can change these to return a promise. This is forward compatible.

AR: then does recursive unwrapping...

link ES6, ES7, ES8... Mark's Strawman Roadmap

LH: The important part is not the features but the process.

AWB: Can things be decoupled?

LH: These kind of structural questions are the important part

MM: Suggests "concurrency" to be the main theme.

AWB: Thought about the event loop. All we need is a processing queue... put things in the front and the back.

DH: Only need to add to the back.

AWB: OK.

STH: The callback is called at some later point.

AR: Don't think we need to specify the order.

STH: If we are going to specify promises etc we need to be able to specify things in detail. We can be loose in ES6 and then come back in ES7 and provide a more tight spec.

DH: We could specify the pending events as a set or something. Not sure if there is a consensus that we want a fast small ES7. Not opposed to a modularized approach.

AR: Are there any browsers that are not shipping stable ES6 features today.

YK: Yes. V8.

AWB: Where we have problem today is that there is a lot of interdependency.

MM: These ("concurrency") are coupled together to the event loop

AWB: We can do it as a separate non 262 spec

DH: Opposed to a separate spec. Introduces versioning confusion.

AWB: Roll up

DH: Think of all the extra overhead.

STH: Big difference with 402 since it was run by different people.

LH: Lack of confidence in new features has been an issue for implementers. Good exceptions were Object.observe and Proxies where the wiki contained a mostly complete spec.

AWB: We need to have wiki proposals be deltas to the spec.

TVC: We could have "stable" wiki pages. These would have complete spec deltas.

DH: Very concerned about over modularizing.

AWB: We need to find a way to work faster and be less monolithic.

DH: Agree. ES6 process has blocked implementation work.

LH: We are not committed to our designs.

STH: We are not resolving issues until we start to spec. We are not getting feedback until engines starts to implement.

EA: The problem is that we didn't start to spec things until very late. We had agreements on features long before there was any spec drafts for them.

YK: More from our champions before we get to concensus.

ARB: Lots of the proposals were very vague.

AWB: The more complete spec you bring to tc39 the better chance you have to reach consensus.

ARB: Lack of early spec leads to lack of early implementations...

AWB: ...which leads to lack of feedback.

LH: Not more work, just doing the work earlier before things pile up too much.

DH: Need to look at the dependency graph. Hold of the work of later feature.

ARB: We need to higher bar before we accept proposals.

MM: What we agreed to 2 years ago was that the features are the one we want to spend work on speccing.

LH: Less features to bite of.

DH: A lot of us have a hard time not getting too engage in too many features.

YK: if we focused more effort on managing the overall complexity instead of getting stuck on a lot of technical discussions (and nit picking).

DH: Object.observe and Proxy moved fast but are fairly isolated features

TVC: Didn't involve syntax.

AWB: With ES6 we had a long backlog.

DH: A language will have smaller and smaller complexity budgets as it grows.

AR: ES future needs events

DH: Since this is Mark's wishlist people will throw in their pet features.

MM: This is the direction I am going to work.

LH: There is a page on the wiki outlining the goals.

LH: Looking for 2 things: Something that would allow earlier implementations. Have not brought proposals (over the last 2 years) because we have been blocked by ES6.

LH: When is the appropriate time to bring new proposals to TC39?

AWB: We are free to do what we want. We can issue 6.1, 6.2 etc or technical reports which would serve as a recommendation.

DH: We cannot exclusively work on ES6.

YK: Time at f2f is the most important. Champions can go off and do what they want.

DH: Suggests adding non ES6 items to the agenda. We will prioritize the non ES6 stuff we can get to given our limited time.

YK: We should reinstate the rule that agenda items needs links to wiki pages.

YK: Spec language is good but examples at the top are a must.

ARB: Add step after proposal. For example "stable" or "spec" which a proposal gets promoted to once there is a spec draft, good enough to start implementing.

DH: Strawman: Anything goes.

YK: Proposals used to mean approved.

DH: 3 sections: strawman, proposal, spec/candidate. Keep strawman. Work on improving as a proposal, and when mature enough promoted to next level.

Ecma/TC39 Meeting – May 22 2013

link May 22 Meeting Notes

(by Erik Arvidsson)

John Neumann (JN), Allen Wirfs-Brock (AWB), Eric Ferraiuolo (EF), Erik Arvidsson (EA), Luke Hoban (LH), Doug Crockford (DC), Yehuda Katz (YK), Brendan Eich (BE), Sam Tobin-Hochstadt (STH), Alex Russell (AR), Dave Herman (DH) (calling in), Bernd Mathiske (BM), Andreas Rossberg (ARB), Mark Miller (MM), Tom Van Cutsem (TVC), Istvan Sebestyen (IS), Jasvir Naga (JNA)

link 4.16 Spec update

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

YK: ToPositiveInteger is needed by JSIDL

AI(YK+AWB): Put an algorithm in the spec that DOM can use so that we get the same behavior in JS and DOM.

6 General implementation experiences

ARB: We started implementing generators but things are pretty smooth.

BE: Doing modules at the moment.

AWB: Bunch of bug fixes in the spec related to classes.

link 4.9 Template Strings (Template Literals)

MM: Suggests status quo.

AR: Objects

MM: Controversy related to tag-less templates. Alternatives include making tag-less templates an error, delayed evaluation (contextually provided)

AR: Econics: naked interpolation is too attractive. Should always have a tag to encourage users to think about which behavior is correct.

YK: I cannot support Alex's proposal.

STH: What would the name of this tag be?

AR: Something that is imported from a module.

STH: Concerned about short names and conflicts.

YK: People will just use 's' without thinking.

YK: People should use HTML templating engines.

DC: Alex's testimony about application developer feedback is relevant.

LH: it sounded like Google engineers were using a template system

EA: Correct.

MM: Does anyone prefer taking out TS if they don't get tag-less TS?

Everyone: Agrees that it is better to require tag than to remove TS from ES6.

AR: Strings are always used later in some context. Communicating the intent

AWB: String concat vs string interpolation have the same issue.

LH: Assumes that maybe only 20% of the uses of TS are susceptible to XSS

MM: Removing tag-less does not reduce XSS because people will just use

1
s`...`

TS helps people transition to a better world. Once they have have a TS it will be easy to add an html tag at the front as needed.

ST: It will be painful to import String raw and alias that to s.

MM: Maybe put tag-less in appendix? Withdrawn idea because no one likes it.

YK: You should not have use string based APIs.

AR: Willing to abstain but "Y'all are making a big mess"

BM: Half convinced by Alex.

LH: Different code bases will use different tags for normal string interpolation so moving between code bases will be hard to.

AR: That is a good thing. Forces people to think.

MM: Template strings in E.

STH: Lots of contexts where XSS is not an issue.

BM: More ways to XSS is a bad thing.

BE: if people have to import s then the economics change and people will stick to +

link Consensus/Resolution:

  • AR and BM sustains.
  • Continue with the status quo (tag-less TS is supported)

link JSON

DC: IETF wants to change JSON

MM: The 2 documents should have exactly the same text except for boilerplate.

IS: Should it be done in TC39?

DC: Most of the work will be on the mailing lists

AWB: Who will be the editor?

DC: Hopes they (IETF) will provide an editor.

JN: Should this be fast tracked to ISO?

DC: That makes sense.

JN: How long do you expect this to take?

DC: Has taken a long time to coordinate and get started. 5.1 specs the 2 functions that uses the JSON format.

link 4.10 Modules

STH: Progress since last meeting. Discuss "module naming", "naming standard modules". http://wiki.ecmascript.org/doku.php?id=harmony:modules Wiki is up to date with the current proposal. Spec is "wiki complete".

Jason Orendorff of Mozilla has worked on flushing out semantic issues. Moz is implementing parsing of modules.

STH: Syntax: Made a couple of changes.

A. To support anonymous exports

1
2
3
export default expr;
import $ from "jquery"; // imports default anonymous export

If there is no default then the above is an error

1
2
3
import {ajax} from "jquery";
import {ajax as A} from "jquery";

to reduce confusion and to make it clear that this is not destructuring.

1
module fs from "js/fs"
  • fs is a module instance object

The following is not valid:

1
import {...} from fs; // SyntaxError

Renaming on export:

1
2
3
let foo = 13;
export { foo as bar };
export { foo };

The following is not valid:

1
export foo;

STH: The only evaluation here is "13". The rest are just bindings that are shared with the outside/module importer.

MM: Bad idea to allow external modules to assign to imports.

DH: Imported bindings are read only to the importer.

AWB: This is new semantics to the language. Is there a list of these new semantics modules introduce?

AWB: Is there a way to get the default export from the instance module obejct.

STH: There will be a well known symbol name to get to it.

AWB: Does module instance objects inherit from Object.prototype.

DH: No. Because we do not want any pollution.

JNA: Is it an error to assign to an imported binding?

1
2
import {ajax} from "jquery";
ajax = 14; // Error

AR: What is the reason for not extending Object.prototype or some other object?

YK: To prevent people from expecting toString to be there (???)

DH: fs.readFile We don't want to statically check this deeply inside an expression.

1
fs.toString

THS: The plan is to allow the above to be a static error in the future.

DH: To keep things clean.

AWB: Concerned about the dot operator

ARB: Don't want less checking if you do not use import.

DH: Do not want refactoring hazards.

ARB: This only affect the static semantics.

AWB: Can you use square bracket?

STH: Square bracket is dynamic.

AR: This is only a static check that is lost. At runtime there will still be errors.

LH: Concerned about default export. Now people will have to decide which approach to use.

STH: This is already the case in Node.js today.

LH: Today you might get any object, it might be callable with properties.

1
2
3
4
5
6
7
8
var fs = require("fs"); // module instance
var glob = require("glob"); // function with properties
var parse = require("parse"); // function
module fs from "fs";
import glob from "glob";
import {sync} from "glob";
import parse from "parse";

Lots of discussion...

1
import {sync} from "glob";

alt

1
2
3
import glob from "glob";
var {sync} = glob;
import {ajax} from "jquery";

LH: Prefers export = and lose static checking when people opt in to single anonymous export.

STH/YK: We already agreed that we want static checking.

LH: Even for new things being built, this is causing a confusion.

AWB: It is unclear when and what you want to export as the default export.

BM: Wants

1
import default $ from "jquery"

...to ensure that people have to be explicit about what they import.

DH: This is just syntax and we are wasting time "bikeshedding"

AWB: What is the best practice? Is there a single module containing Map, Set & WeakMap or...

YK: WeakMap should be its own import:

1
import WeakMap from "collections/WeakMap";

BE: We have to pay attention to what Node/AMD do today.

YK: AMD tries to make modules small to reduced byte size of the dependencies.

STH: And now to semantics https://github.com/jorendorff/js-loaders/blob/master/browser-loader.js

Major things that changed. Use options object more consistently. The wiki page is up to date. Need to decide whether the browser loader is in the appendix or if it is in some w3c spec. Want core language semantics to treat the names as strings, not the semantics of these strings. Bulk loading. One HTTP request to load multiple modules. Possible to implement. Create fecth hook. Stores module notations in a side table. In the xhr response, split the result and call the different fulfill hooks.

EF: Sounds like what we do today in YUI loaders. How would you write the HTML?

DH: Initial script tag with configuration. Second script tag as usual. Alt 2 is to have configuration and dynamic module load in the same script block.

1
2
3
4
<script>
ondemand
</script>
<script src="main.js" async></script>

alt 2

1
2
3
4
<script>
ondemand
System.require("main.js", function() { .... });
</script>

DH: script[async] today have to use an external src.

STH: Naming and declarations of modules.

ARB: Presenting slides...

AWB: The rate that internal vs external names changes is very different.

STH:

1
2
3
4
5
6
module "m" { ... }
module "n" {
import x from "m";
...// this part is not executed.
}
import x from "m";

STH: Configuration step is mostly about other people's code.

1
2
3
4
5
6
7
8
9
<script>
module "m" { ... }
module "n" {
import m from "m";
function f() {
Loader.eval("import m from 'n'");
}
}
</script>

m is fixed at compile time

ARB: Not opposed to logical modules. Wants both lexical and logical

DH: Not opposed to lexical modules.

YK: Too late to work out lexical modules for ES6.

ARB: If we wait we will have redundancy.

YK: Want declarative form to be able to prefetch etc.

BE: I want lexical modules (in the future) but logical modules are easier to use.

ARB: Since I don't seem to be able to convince anyone I'm going to drop this

ARB: For the record. Major concern about the global registry becoming the new global object.

link Consensus/Resolution:

  • Move along with Dave and Sam's proposal.
  • Work on lexical modules for ES7

Ecma/TC39 Meeting – May 21 2013

link May 21 Meeting Notes

(by Erik Arvidsson)

John Neumann (JN), Allen Wirfs-Brock (AWB), Eric Ferraiuolo (EF), Erik Arvidsson (EA), Luke Hoban (LH), Doug Crockford (DC), Yehuda Katz (YK), Brendan Eich (BE), Sam Tobin-Hochstadt (STH), Alex Russell (AR), Dave Herman (DH) (calling in), Bernd Mathiske (BM), Andreas Rossberg (ARB), Mark Miller (MM), Tom Van Cutsem (TVC), Jasvir Naga (JNA), Istvan Sebestyen (IS)

JN: Going through the agenda Adding proto Unifying iterator/generator APIs Talking about getting user stats for test-262... YK: Prioritize ES6 items. So that we don't get do ES7+ items before

Minutes approved unanimously

link 4.1 Object.freeze

DC: Today Object.freeze throws when primitives are passed in. Suggesting not throwing when a value type is passed in.

MM: Object.isExtensible would return false for primitives

EA: This would give an inconstint view for primitives.

AWB/YK: (In strict mode) numbers and strings lazily box so the assignment never fails.

MM: Proxies are allowed to be non extensible and throw away.

ARB: Is the suggestion to lazily wrap primitives?

MM: No, then Object.isExtensible(7) would return true because the wrapper is extensible.

AWB: In most of the new changes we are not doing unnecessary coercion.

YK: The Chrome dev tools, console.dir(7), says "no properties" which supports treating these as empty objects.

MM: The only observable wrapper is the this wrapper in non strict mode.

AWB: In the new spec, Object.setPrototypeOf(7) throws.

MM: Agrees violently!

link Conclusion/Resolution

  • DC+AWB to work out the details

link 4.2 WeakSet

Do we need them?

MM: Trivial shim around WeakMap.

YK: Often wanted it

AWB: Adds no new capabilities.

AR: We should not limit ourselves to what is a new primitive capabilities

AI(AWB): add to spec

link Consensus/Resolution:

  • Add WeakSet in ES6

link 4.4 Proxies

TVC's presentation on Notification Proxies: https://docs.google.com/file/d/0B9iYRsLxmdqUd1RsdHZtazliWmc/edit?usp=sharing

Arguments against:

  • shifts the burden from spec writers/implementors to users (need to use shadow target even for non-frozen objects)
  • implementors will deal with spec bugs related to invariant violations as they come up

link Consensus/Resolution:

  • Notification proxies are not approved.
  • MM & TVC are still happy with direct proxies.

link Proxy Invoke Trap and wrong |this|-binding on built-in methods

AWB: with current default behavior of "get", "Caretaker" will break on built-ins such as Date, because the |this| binding is by default set to the proxy, so the Date built-in method will not find the correct private state.

ARB: Same issue with binary methods

STH: We should add invoke trap but not change the object model

MM: Pleasant to have. Separate from private state.

AWB: used to think this was an issue with proxies, but convinced that it's an API issue: we need to provide default handlers that do the right thing, and which users can subclass. In particular, want a handler that, on forwarding, rebinds |this| to the target.

STH: If you want to proxy a Date method the underlying this needs to be a non wrapped Date object.

TVC: previously proposed a Handler API that defines derived traps and fundamental traps, allows you to subclass and inherit correct behavior for derived traps. Can be used as the basis.

AWB/TVC: invoke trap would make it easier to control |this|-binding

DH: Never liked breaking the semantics of [[Get]] + [[Call]]

TVC: there already exist invoke-only properties on platforms with __noSuchMethod__

AWB: For a [[Call]] it might be important to control this but by the time the [[Call]] is happening you do not know what this to use.

DH: ActionScript has a proxy and they do have an invoke trap.

BM: The most common action is to invoke a method.

? : we already gave up on the |this| invariant for accessors: in ES5, if obj.x is a getter, |this| will always be bound to obj in the getter. With proxies this is no longer true.

AI(AWB, TVC): Add spec for invoke. Tom and Allen to work out details of a Handler API that accommodates both "caretaker" (aka forwarding) and "virtual object" use cases.

link Consensus/Resolution:

  • Add invoke trap.

link 4.11

MM: Everybody in this room wants classes and want to post pone private state to after ES6

ARB: Disagrees.

ARB: Based on feedback, people do not want unique symbols, only private symbols.

MM: Private symbols do not work with proxies.

TVC: can still use WeakMap for private state.

DH: The most common cases where true information hiding is self hosting. The stakes are too high for the browser engines.

YK: If "iterator" would be a private symbol, you cannot create a proxy that will work with for-of loops.

ARB: Symbols (unique and private) and relations overlap.

BE: If we add symbols now we are stuck with them.

LH: Future users will be confused. They will not know what to use

BE: Unique symbol is very different from class private syntax.

AWB/MM: If we first did relationships we might not need symbols.

MM: Relationship published but not reflective.

MM: Difference between relationships and symbols: where is the mutability? This forces us to have both relationships and unique symbols.

link Consensus/Resolution:

  • ?

link 4.13 Endianness of Typed array

ARB: Remember it as if we should specify this.

BE: Endianness in Typed Arrays is unspecified.

DH: Keep it open for now... Same system to same system. Using data view, which is explicit, there is no problem.

STH: We don't know what WiiU will do?

AWB: Or they decide not to comply to the spec

DH: WebGL is endian agnostic.

link Consensus/Resolution:

  • Leaving it unspecified in ES6.

link 4.18 proto

STH: Recollection, first as data property, then as an accessor. Then discussed the power of that setter. Set the [[Prototype]] in the [[Realm]]. Then Allen wrote the spec. Realized that there were some problems with that design. Roughly the same power as Object.setPrototypeOf.

MM: Existence of a setter... as long as we have the extensibility restriction, that is sufficient.

AWB: Why restrict __proto__ and not other

DH: Objects belonging to a realm is a bad idea.

MM: No more reason to restrict the setter.

STH: Bind __proto__ setter to the object upon extraction

MM: In SES objects that are non extensible. Not going to remove __proto__ going forward.

ARB: If Object.prototype.__proto__ is a data property, making it non writable prevents other objects to use assign to set __proto__.

AWB: If Object.prototype.__proto__ is an accessor that just calls Object.{set,get}PrototypeOf.

AR: Best practice on the web is important even in the future.

TVC: If we have Object.prototype.__proto__ do we want Object.setPrototypeOf or just Reflect.setPrototypeOf?

AWB: Makes sense to have Object.setPrototypeOf for consistency.

EA: Where do we draw the line (Object.x or Reflect.x)?

DH: People will need to be able to get this before we have a reflect module.

TVC: We need both because they have different return value (Reflect.setPrototypeOf returns boolean success value).

link Consensus/Resolution:

  • __proto__ is an accessor on Object.prototype.
    • The setter mutates [[Prototype]].
    • There is no "poison pill".
  • Add Object.setPrototypeOf and std:reflect setPrototypeOf.

link Naming of @@iterator

AWB: Suffix with $

STH: Opposed to special naming. People don't do this kind of naming convention. Why do we want to introduce this concept?

1
2
3
4
5
class Foo {
*[iterator]() {
yield ...
}
}

link Consensus/Resolution:

  • No special naming

link Generators and iterators

AWB: send is gone in favor of next(arg) (only first arg is passed through in yield*)

YK: Whether generators return a frozen object or not?

BE: close is gone

link Consensus/Resolution:

  • Removed: send and close

Ecma/TC39 Meeting – Mar 14 2013

link March 14 2013 Meeting Notes

John Neumann (JN), Norbert Lindenberg (NL), Allen Wirfs-Brock (AWB), Rick Waldron (RW), Waldemar Horwat (WH), Eric Ferraiuolo (EF), Erik Arvidsson (EA), Luke Hoban (LH), Matt Sweeney (MS), Doug Crockford (DC), Yehuda Katz (YK), Brendan Eich (BE), Sam Tobin-Hochstadt (STH), Alex Russell (AR), Dave Herman (DH), Adam Klein (AK), Bernd Mathiske (BM), John Pampuch (JP), Avik Chaudhuri (AC), Edward O'Connor (EOC), Rick Hudson (RH), Andreas Rossberg (ARB), Rafeal Weinstein (RWN), Mark Miller (MM), Reid Burke (RB),

link 4.8 Object.observe Implementation Report

(Presented by Adam Klein, on behalf of Rafael Weinstein)

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

Slides (PDF, will prompt download): http://wiki.ecmascript.org/lib/exe/fetch.php?id=meetings%3Ameeting_mar_12_2013&cache=cache&media=meetings:object.observe_implementation_report.pdf

(Slide 1)


  • Results are encouraging
  • Two Google projects are pleanning to deploy run-time support
  • Use cases ?

(Slide 2)


  • Spec fully implemented (behind flag)
  • Mostly self hosted: changRecord allocation, enqueing and delivery is in JS
  • Mutation sites of observed objects deoptimize. Observed arrays are alwas slow mode
  • Biggest perf bottleneck is feting changeRecords; plan to speed up Object.freeze()

YK: Concern about changeRecord spam (build up of changes delivered at the end of the turn)

AK: There are places were large numbers of changeRecords are a concern

AWB: (missed question)

AK: We could define the properties as non-configurable, this is orthogonal to the isFrozen check.

AWB: Even if there isn't a specified state for a frozen object

EA: With proxies, that becomes observable

AK: There are changes to the spec since last brought to the committee...

(Slide 3)


  • Object.deliverChangeRecords() continues delivery until pending
  • Added { type: "prototype" } changeRecord which reports changes to __proto__
  • Minor changes to changeRecord generation to enforce consistency invariants

DC: Does that cause the turn to never end?

AK: Yes, same as recursive calls

ARB: Just another footgun in that respect

(Slide 4)


ChangeSummary JS Library

  • Supports dirty-checking and Object.observe (polyfill to fast/safe object observation)
  • Exposes semantics for a "diffing summary (Tn -> Tn+1 changes)
  • Observe

    • "Values at a path" eg. var foo = { bar: { baz: "..." } }; observe.observePath(foo, "bar.baz");
    • Entire Objects
    • Array splice
  • ??


WH: What is "values at a path"

AK: If you have:

1
2
3
var foo = { bar: { baz: "..." } };
observe.observePath(foo, "bar.baz");

?: Observing paths leaks objects if we only have weak maps, not weak references

WH: Please explain

?: Path observers observe mutations anywhere on an object path a.b.c.d. Without weak refs these will leak a if d is still alive but a wouldn't otherwise be.

(Slide 5)


Per Analysis (dirty checking vs Object.observe)

  • Results not surprising (this is good!)
  • nothing-changed case is overwhelming win
    • Discovering that nothing changed only incurs the cost of de-optimizing observed objects
  • Object.oberse case never needs to keep a copy of observed data
  • Object.observe appears to observed properties have changed (depending on observation "type")
  • Arrays encourage "hidden" everything-changed cases eg. unshift();

AK: One of the worst cases is observing Arrays

WH: If you do that, do you get one record for the array, or one for all properties?

AK: One for every index and length

?: Which then can get (inefficiently) summarized back to one change record for the array if you use a summarizing adaptor.

EA: We knew about this from the very beginning, but decided to address it after we had implementation experience.

(Slide 6)


Adding Support for Array "splice mutations"

  • Report on changes to Array elements (isUInt32(propertyName)) as "splice mutations"
  • Degrade to "normal" property mutations if...
    • !Array.isArray(array)
    • array has non-data index properties
    • array has non-writable or non-configurable index properties
    • operation will affect indices > UInt32

WH: What happens when you observe a WeakMap?

AK: It's an object, but nothing interesting happens, because there are no exposed properties that will be changed. We could have synthetic events for Map, Set etc.

LH: We would have to specify these synthetic events ahead of time

AK: The requirement for Map and Set would be to come up with new types.

WH: Observers make changes between properties and getters/setters (such as what we're doing to regexp flags to support the compile method) uncomfortably likely to break user code that observes such objects.

LH: But these can already use synthetic events

WH: What are synthetic events?

LH: (explains the synthetic events api)

AR: We may want a declarative way to "squelch" certain event types.

AK: ...discussion of the cost of notifying for all changes

YK: As we add more "types" there will absolutely need to be a way filter the types you care about.

RW: It would be nice to specify the "type", similar to registering handlers for specific event types. eg. Object.observe(o, "type:prototype", ...) gives me only changes to the prototype. etc.

YK/AK: ...more discussion about complexity of adding the feature now or later.

AR: If you have filtering, users can choose the level of changes they are shown, without taking away any of the low level type notifications.

STH: What is the consequence of changing the system now? Can't we just do the right thing here for arrays?

LH: It introduces new complexity

AK: ...discussion of failure cases

AR: Fixing the Array thing for ES7 is a reasonable thing. But this is an example of something we will want to do in the future. This is also a chance to get the filtering feature and maintain upward compatibility.

YK: An array as an identity map

LH: An array as a tuple, its an object data type.

YK: Arrays used in Ember, specifically for numeric indices

...

YK: Do exceptions bubble up?

AK: There are many issues.

...May be better to special case splices

YK: ...discussion about spamming of changeRecords at the end of the turn and the sync behavior.

STH: If you're counting typing speed, you want all of the changeRecords

ARB: What happens when there are new observers or removed observers during a changeRecord delivery.

YK: I'm happy with the current implementation, but it would be nice to be able to squelch certain types of changeRecords

AK: Let's take this offline and look into ways of making this possible.

BE: (to ARB) are you ok with staying off the fast path?

ARB/YK/AK: ...Discussion about the possibility of a fast path for properly implemented Arrays

AWB: What happens if the object is implemented via Proxy, and doesn't have the normal representation of properties.

ARB: Treated the same as accessors

AR: To clarify, we call this the "slow path", but for apps that are going to use this, it's demonstrably preferable to existing art.

link 4.6 Symbols

(Presented by Andreas Rossberg)

ARB: Update on implementation of (unique) symbols in V8: mostly finished, and as efficient as strings as property names. But symbols don't fully behave like objects yet, as would be required by current spec.

ARB: Propose two changes to the proposal:

  1. Make symbol a primitive type
  2. Change toString behavior to avoid hazard

Problem with 1: extending typeof

AWB: Symbols as objects allows for useful operations like toString

ARB: Can be solved the same way as for other primitive types: wrapper object

AWB: From a spec perspective, making them not an object is more pervasive

ARB: Very different for implementations. You can use them in context of string or object, but you can pick only one representation. Chose string-like context because that's more important to optimize. But makes special-casing all object contexts costly

DH: Would have to do this if we made this a primitive type as well.

ARB: it would just fall into similar cases as other primitive types (in v8 at least)

AWB: ...compares to primitive and object wrapper classes

DH: And we would have to provide wrapper class

AWB/DH: We should have a new typeof type

DH: Real implementations have other typeof types, eg. IE

STH/BE: ...recalling prior discussion that had no definitive conclusion re: new typeof types.

ARB: Can we really afford precluding new typeof results for all eternity?

DH: If we can get away with this, then it supports adding new types for future additions, eg. int 64

BE: This is important:

1
2
3
typeof x == typeof y && x == y
<=>
x === y

...: The proposal from AR preserves this.

STH/DH: Giving the switch(typeof...) example

YK/RW: When would symbols be passed to this code anyway?

YK: It's a fuzzy case that is already broken, because null can't be checked

BE: We should just do it and that'll learn 'em. ;)

DH: A new type in typeof is good and we should just do it.

General agreement.

DH: Now that these are essentially primitives, we need ways to discern private and unique

STH/YK: Committed to a new global because we use Symbol to construct them.

AWB: Symbol is a factory that creates symbols, new Symbol creates instance of the wrapper class. (same as Number)

BE: Value objects allow "new"

AWB: I can define the Symbol[@@create] to throw

ARB: The current spec has a toString for implicit conversion, which makes it too easy to convert the symbol to a string accidentally without realizing.

STH: Have a name property, and a toString that throws

ARB: Or simply no toString. But {}.toString.call still works.

EA: String conversion already throws for null-prototype objects

DH: That's fair, it makes senses to have some sort of infallible stringify.

DH: Proto-less dictionaries will become more widely used

AWB: ...recalling existing specification of ToString conversion

...Mixed discussion about ToString

link Conclusion/Resolution

  • New addition to typeof table
    • typeof symbol === "symbol"
  • [ToString] => throws
    • therefore symbol + "" => fails w/ error
  • Object.prototype.toString.call(symbol) => "[object Symbol]" (ARB: or rather something else, given that we just decided symbols shouldn't be objects)

link 4.17 Legacy Compatibility for Block Level Function Declarations

(Presented by Allen Wirfs-Brock)

See: http://wiki.ecmascript.org/lib/exe/fetch.php?id=meetings%3Ameeting_mar_12_2013&cache=cache&media=meetings:legacyblockfunctiondcl2.pdf (This is a PDF that will initiate a download!)

(Copied from PDF)

Prior to the Sixth Edition, the ECMAScript specification did not define the occurrence of a FunctionDeclaration as an element of a Block statement’s StatementList. However, support for that form of FunctionDeclaration was an allowable extension and most browser-hosted ECMAScript implementations permitted them. Unfortunately, the semantics of such declarations differ among those implementations. Because of these semantic differences, existing web ECMAScript code that uses Block level function declarations is only portable among browser implementation if the usage only depends upon the semantic intersection of all of the browser implementations for such declarations. The following are the use cases that fall within that intersection semantics:

  1. A function is declared and only reference within a single block:

    • A function declaration with the name f is declared exactly once within the function code of an enclosing function g and that declaration is nested within a Block.
    • No other declaration of f that is not a var declaration occurs within the function code of g
    • All references to f occur within the StatementList of the Block containing the declaration of f.
  2. A function is declared and possibly used within a single block but also referenced within subsequent blocks.

    • A function declaration with the name f is declared exactly once within the function code of an enclosing function g and that declaration is nested within a Block.
    • No other declaration of f that is not a var declaration occurs within the function code of g
    • References to f may occur within the StatementList of the Block containing the declaration of f.
    • References to f occur within the function code of g that lexically follows the Block containing the declaration of f.
  3. A function is declared and possibly used within a single Block but also referenced by an inner function definition that is not contained within that same Block.

    • A function declaration with the name f is declared exactly once within the function code of an enclosing function g and that declaration is nested within a Block.
    • No other declaration of f that is not a var declaration occurs within the function code of g
    • References to f occur within another function h that is nested within g and no other declaration of f shadows the references to f from within h.
    • All invocations of h occur after the declaration of f has been evaluated.

Use cases 2 and 3 for a given function declaration f might occur within the same function.

The first use case is interoperable with the inclusion of Block level function declarations in the sixth edition. Any pre-existing ECMAScript code that employees that use case will operate using the Block level function declarations semantics defined by clauses 10 and 13 of this specification.

LH: Has to be a statically verifiable approach

DH: We can statically declare a conservation class of blocks

AWB: Most blocks are conditional in some form.

WH: (whiteboard)

1
2
3
4
5
6
7
8
9
function g() {}
function f() {
if (false) {
function g(){}
} else {
g();
}
g();
}

WH: This example illustrates that #2 is not interoperable. It's not even clear to me what #2 means.

  • Does the first call to g (in the else close) lexically follow the inner definition of g?
  • Regardless of the answer, the second call to g is not in the intersection semantics (the inner g is never defined due to the if false) yet is treated by #2 as though it were.

AWB: A fix for this case: Add an additional clause that says the subsequent

AWB: The semantics we want, for non-legacy cases, in non-strict mode are the ES6 semantics.

DH: Not compatibility with reality.

...

Sixth edition interoperability for the second and third use cases requires the following extensions to the clauses 10 and 13 semantics. These extensions are applied to a non-strict mode functions g if the above pre-conditions of use cases 2 and/or 3 exist at the time of static semantic analysis of g. However, the last pre-condition of use case 3 is not included in this determination and the determination is only applied to function declarations that are nested within syntactic constructs that are specified in the Fifth edition of this specification.

  1. Let B be environment record for the construct within g that introduces a new environment contour and which most closely encloses the declaration of f, all function code references to f, and the definitions of all nested functions that contain syntactically unshadowed references to f. This syntactic construct may be the definition of g itself, in which case B is the function environment record for g.
  1. As part of the instantiation of B, its CreateMutableBinding concrete method is called with arguments "f" (the string name of the function) and false. This creates an unitialised binding for the name f. Any reference that resolves to that binding prior to step 3 below will throw a ReferenceError exception.

  2. When the InitializeBinding concrete method is used to initialise the binding for the function declaration f also invoke InitializeBind on B using the same arguments.

If an ECMAScript implementation has a mechanism that produces diagnostic warning messages, a warning should be produced for each function g for which the above steps are performed.

WH: #1 is a circular definition. Some references to g will go to the outer g in the example. It is up to us to define which definition points to which.

AC: It would be beneficial to look at examples and then apply the fix rules and allow that inform the direction.

AWB: (whiteboard)

1
2
3
4
5
6
7
8
9
10
// A dynamic ReferenceError.
// There is no binding to g()
function f() {
{
if (false) {
function g() {}
}
g();
}
}

AWB: The interoperable fix:

  • As if there was a let g; at the top of the inner block...
  • the g() reference points to the g() declaration in the same scope

WH: ok, put back the outer g()

AWB: (whiteboard)

1
2
3
4
5
6
7
8
9
function g() {}
function f() {
{
if (false) {
function g() {}
}
g();
}
}

...Didn't take into account this case, will need time to consider.

AWB: Could be two inner blocks, with declaration of g()...

WH: (whiteboard)

1
2
3
4
5
6
7
8
9
function g() {}
function f() {
{
g();
if (true) {
function g() {}
}
}
}

WH: What happens when the first g() is called?

AWB: the first g() is bound to the outer g(), then a new g() is defined.

WH: (whiteboard)

1
2
3
4
5
6
7
8
9
10
function g() {}
function f() {
{
g();
if (true) {
function g() {}
}
g();
}
}

WH: Now what happens?

AWB: Per the proposed rules, both calls to g() are bound to the inner definition via the phantom let binding [presumably with the first one encountering a dead zone?].

[MM walks into the room and expresses speechless incredulity when he learns that adding the second call to g in this example changes which g the first call to g is referring to.]

AC: There is merit to avoid being clever. Benefit to preserving any existing semantics.

BM: There should be a vision for a desired semantics goal

STH/LH: Two goals, which are competing:

  1. We must remain compatibility with the web
  2. Introduce block scope bindings

BM: Bad that an outer binding can change

AC: ...correlates to AS

STH: We have sensible semantics for ES6/strict mode

AWB: We have sensible semantics for both modes

AC: Confident that we might be able cover all existing use cases. But what happens when someone discovers a case that was covered?

STH: Easy to come up with sensible rules from other languages

AC: All practical purposes

[? trying to start a meta-discussion about getting sidetracked on theoretical rather than practical problems]

WH: We are discussing because we know this is a real, practical problem based on research demonstrated at the previous meeting.

STH: The only guiding principle is to avoid breaking the web.

AWB: Where we're at, is the hypothesis that we can identify and fix the cases that break the 1% of sites that have code that violates. Introduce a declaration that spans the point of declaration and the point of reference

STH: ...clarifies the subset semantics definition

AC: Two cases:

  1. What to do?
  2. Identify that subset.

STH: Yes

AWB: This conversation only applies to the 1% of code that exists that must be dealt with in a way that matches the 99% semantics

LH: ...recapping

AWB: JavaScript programmers will have two learn that non-strict mode always uses odd-ball semantics in addition to the strict mode semantics. If we make this work, there is one semantics to learn.

DH: Inclined to agree with Allen. A worse semantics, easy to explain vs. a better semantics that serves the 99% but loses the 1%... and we'll lose the 1% in a deep dark hole. ...Arguing for:

  1. One set of rules, that is weird and less pleasant
  2. Carve out heuristics for identifying ... giving the good semantics to 99%

BM: Missing analysis?

STH: Presented at last meeting

DH: Arguing for #2 (99%)

WH: Want to see the semantics of strict mode in non-strict mode as often as possible. Don't want to legitimize new quirks, even if that means that the transition rules are more complex. Hope that in a few years the strange semantics can be eliminated in favor of what strict mode is doing.

LH: This is exactly Allen's point. If Allen's point achievable? If it is, then I support it, but I don't think it's achievable.

AWB: This is a first draft.

YK: Function in block is oddball already. If we have a semantics for non-strict FIB and different from strict mode, it will make it hard to upgrade to strict mode.

Note: AC/BM please send Allen any materials that might be useful for specifying the semantics for FIB.

link Conclusion/Resolution

  • All (esp. AWB) to continue working through known issues in the 1% cases

link 8.1 Comments from Istvan, stated by John Neumann

  • The ECMAscript trademark is rather through. We have it in the most important countries, incl. US and EU.

  • The EU formal recognition for ECMA-402 and TR/104 is progressing. We are now in the evaluation phase by a small group. They asked me to make a first draft for evalutation, which I did. Informally I have one "yes" so far, and no "no" yet. If the small group gives an ok, then the member countries have to vote. The process will take a few months more (but I do not know how long, because this is the first experience with the new EU policy).

  • Regarding the IPR Adhoc. We are progressing. I think I can distribute an updated package to TC39 at the end of March. GA vote is planned for June 2013. Comments back to the IPR Adhoc, GA, or GA members. Just as last time.

WH: ECMA's TC39 email reflector is incompatible with gmail. If a gmail user sends an email to the reflector, non-gmail users will receive it but no other gmail user will receive it in his inbox. It will always arrive in the spam folder due to some SPF issue.

[Various people checking their spam folders now and discovering TC39 emails in there.]

link 4.10 Array Extras

(Presented by Rick Waldron) (notes from EA)

RW: Wrote spec (using spec prose) Array.prototype.find and Array.prototype.findIndex. Found in most PL and JS libraries

1
Array.prototype.find( predicate [ , thisArg ] )

https://gist.github.com/rwaldron/5079436

1
Array.prototype.findIndex( predicate [ , thisArg ] )

https://gist.github.com/rwaldron/5079427

MM: What about start indedx? Does it go before the thisArg or not?

RW: None of the existing languages supports passing a start index.

RW: Not sure if this is for ES6 or Harmony

AWB: Feature creep

DH: Common, makes sense.

link Conclusion/Resolution

  • Exception being made. Approved for ES6.

link 4.15 Template Strings

(Presented by Adam Barth [present], Mike Samuel [phone] guests from Google)

BE: What can we do to template strings to make them secure by default and not an XSS hazard.

  • tagless?
  • a default tag?

AWB: They're useful for making strings.

BE: (reiterating) The obvious problem: using backticks with no prefix/tag, you create potential for xss.

DH: Ok, so we've outlined the security argument, but important to note that tagless are useful and the security fix is still not enough to "fix" the bug picture security problems.

DC: No placeholders in tagless?

BE: Possible

YK: ...recalling discussion with Mark where the rabbit hole became extremely deep when trying to avoid accidentally coercing to a string.

MM: String.prototype.trim apply to delayed template string, which turns it into a string. ...Delayed template string inherits from template string

YK: Implicit coercions.

MM: This is one option

BE: Make the default case somehow not present, or neutered

AWB: Remember for "+" and explicit coercion cases, we're falling into the DefaultValue mechanism, which has a unique Symbol hook (in ES6), which means that what is sent to the object initially does not have a toString. The DefaultValue for the delayed template string is... ...DefaultValue applied in concatenation could throw,

MM: ...specifically the deferred template string. Specifically for the tagless template string case.

(RW: some terminology issues addressed)

WH: Understand the utility of tagged template strings, with possibly a default tag that does string concatenation, but what's the rationale for deferred template strings?

[some discussion, with no answer to WH's question]

MM: If the behavior is for the DefaultValue to throw, reject the implicit coercion. However, if you're writing a REPL and want to stringify, you can explicitly call toString

STH: This is insane

DH: This is destroying the usefulness of tagless template strings.

YK: It's not clear how taking a nice feature and making it harder to use will fix a security issue, the problem will still exist with string concatenation.

DH/RW: Agree

Mixed discussion re: security issues in the DOM.

AR: Security issues revolve around reasoning about data and behavior which you'd like to think is benign, but combining them create abilities that they shouldn't have.

DH: By calling out template strings, we're effectively blaming "strings" for these security issues.

AR: innerHTML

STH: That's the problem

AR: This isn't about hard-and-fast, right-and-wrong. Security is about doing the right thing more often. Security bugs are just a subclass of bugs that bite very hard. The biggest thing any system can do to improve the security situation is to set the economics of doing the right vs. wrong thing in such a way that it's "cheaper" to do the right thing. So we can't pretend that this is about some perfect answer; it's about the economics of designing a solution that leads to doing the right thing more often, and that's a question about probabilities and psychology. We want to build a honeypot for doing it the right way.

MM: Key, either get rid of tagless template string or make them unpleasant; have we created a situation where developers would or would not have used the feature...

AR: What is the reality that adding a no-op tag? What does it actually provide? Stopping developers from using tagless by giving them a tag that does interpolation.

DH: Strings are the most used data structure in all programming. Yes, they are used heavily in secure code construction. ...Then there is the pitchforks and torches cost of making this harder.

MM: Also, the cost of companies that will be screaming about being bit by a security issue

RW: But these are no different then the existing security issues today.

AR: That's not a fair argument to discussion.

MM: The screaming over vulnerabilities is probably more costly then developer hardship. ...If you use a tagless template string in particular context, you can have a an autoescaped context.

BE: So, you could change innerHTML setter to check if the RHS was a tagless template string

MS: (phone) If you don't try applying the string concatenation operators to the tagless template string, you get secure auto escaping. innerHTML

MM: Let's call that "Mike's Original Proposal"

STH: (listing)

  1. Current status with default handler that interpolates
  2. No tagless template strings
  3. tagless template strings with no interpolation
  4. tagless template strings produce delayed template string objects, with toString
  5. tagless template strings produce delayed template string w/ special handling that coerces
  6. tagless template strings produce delayed template string w/ special handling that throws
  7. Allow overloading of the default handler for the tagless template strings

MM: (whiteboard)

1
2
3
4
5
6
7
8
9
10
class DelayedQ {
constructor(callSiteId, ...args) {
this.force = function(handler) {
return handler(callSiteId, ...args);
};
this.toString = function() {
return stringer(callSiteId, ...args);
}
}
}
1
2
3
html`<script>
"${...}"
</script>`

WH:

1
2
3
4
5
6
7
html`<script>
"${foo()}"
</script>`
function foo() {
return `...`;
}

WH: Using a tagless template string to construct an english sentence and I stick it into html, what do I get out of that?

AWB: You'll probably get garbage, because the innerHTML parser rules will be applied.

WH: How does foo in the example know how its deferred template will be interpreted? It becomes a really sneaky part of the API, where foo can return different things depending on the context it's called in -- can be string concatenation, various kinds of escaping, etc. This is too brittle and dangerous.

LH: innerHTML should've been forced to apply cleansing on all strings.

BM: How about immediately constructing and scrubbing?

STH: Same issue with E4H

DC: Don't forget about the off-browser cases.

YK: So the socket API should check strings that are created in Node?

AB: Yes

YK: Ok, I said this to be ludicrous.

AB: If you eagerly coerce to a string, you lose the structure of the object: which part of was a template and which part was data.

WH: We have no way to tell which part is which. [In the example above, if foo returns a deferred quasi, it's like it returns a bag of stuff that it wants joined together but it doesn't say what the stuff is (individual characters? names? rows in a table? entities? script statements? HTML elements?) or how it should be joined. It's not clear to anyone reading foo's code how what the semantics of the bag of stuff is. This is too brittle.]

STH: The point Yehuda is making, is that people make code and ship it out over the wire.

AB: ...describes the way Ruby server programs create outbound blobs that from templates and data that are flatten just before sending.

YK: I wrote that.

...Discussion about JavaScript developers, use of strings vs. DOM authors creating APIs that can handle template strings

AR: This is a new string of a different type

YK: We'll need to blacklist all strings if this is the case.

MM: ...introduces Mike Samuel's work

BM: Summarizing...

  1. Adam: We control all user code
  2. Yehuda: We control no user code

AK: Specifically, Yehuda refers to all existing code that follows a form where: "string..." + " is concatenated"; and used to assign to innerHTML (or similar)

MS: Able to successfully migrate a codebase from ad hoc work-arounds. This used closure templates. Statically compiled version of templates.

STH: Is the argument leaning towards tagless or tagged, or is that not relevant?

MS: The system worked with nested script, css and html. In cases where developers needed, they circumvented the system.

YK: ...recalling hardships of Rails upgrading for a similar auto-escape system.

...

YK: Happy with current system + html default handler provided by the browser(*)

DH: Template strings are useful for other reasons: multiline strings, etc.

MM: Yehuda's suggestion (*) is good

STH: Established that we wanted a delay handler, which produced a delayed template string per Mark's suggestion

MM:

  1. Immediate String interpolation
  2. Delayed Template String

(Summarized from 1 & 4 from the list above)

LH: This delayed template string concept is now a second string type in the language and I'd be afraid to use them because they I can't rely on them.

MM: Is anyone opposed to #1? (Adam)

RW: Will any of the implementors here remove the template string feature or tagless template string handler.

No?

LH: I was not comfortable with "quasis" when they required a tag, and even less if they produce a delayed thing. ...This forks the string "type" WH: That's exactly what I was trying to say earlier. Deferred quasis are too brittle.

MM: Can process based on context

WH: This is just another bug. Makes the problem far worse if you have a function that returns a template string.

DC: The reason we went with template string over String.prototype.format was because this was safer.

MM: (to Mike) Do you find #1 & #4 acceptable?

MS: Yes.

AB: (whiteboard)

1
2
3
4
var firstName = ...
var lastName = ...
elem.innerHTML = `<h1>Hi ${firstName} ${lastName}</h1>`;
elem.innerHTML = "<h1>Hi " + firstName + " " + lastName + "</h1>";

LH & AB: ...discussing the value of #1 & #4

STH: Reviving #2 & #3

  1. Drop template strings
  2. Current status with default handler that interpolates
  3. No tagless template strings
  4. tagless template strings with no interpolation
  5. tagless template strings produce delayed template string objects, with toString

AR: Leaning on #2 or #3

YK: Nobody wants #2 or #3

WH: I want #2

DH: If we go with #2 or #3, we should just take it out of ES6

Discussion about a provided tag, called "s"

RW: Which means we now have a binding "s" and minifiers and existing code conflicts.

MM: Argument for #3...

DH: This is a tremendous failure of our duty.

MM: My preferred option is that we agree on something ...#2 does not subtract value

BE: Opportunity cost

MS: (Arguments for the current system.)

WH: Some browsers used to have a behavior that allowed regexp to be called without exec, and called directly—should we be able to take that out?

STH: Should a programming language not be allowed to have a feature that all other languages have?

AB: I'm not a programming language designer, I can't answer that

STH: That's a cop-out, because that's what you're asking us to do.

DH: (disdain)

WH: Originally, I wanted #1, now I want #2 because its too easy for people to forget to add "html``"

BM: #0 and #1 are the best cases, #0 adds no additional security risks. #1 is the pure option. #2 changes because you add to the boilerplate. The rest are a new thing. ...I'm for #1 because either you do it or you don't.

STH: Answer this... Is this something that all languages should do? Or just JavaScript because it's bound to the web?

AR: Yes, we have to pay the cost for the good of the web and yes other languages should've done this (ie, not had the equivalent of untagged template strings). ...wants #3

RB: re: #3, important to have to think about what kind of handler need you need to use.

YK: That might work for your case, but the wider world will just use the interpolation tag.

...

DH: We're flailing. We should just go #2 and just move on, because I'm failing to make my case.

WH: I like #1 and #2, which are similar, but prefer #2 purely for a couple of practical considerations:

  • Forgetting the html in html... causes a syntax error instead of introducing a security hole.
  • s... is preferable to ... because it's practical to search for sin general-purpose editors, while it's not practical to search for only the occurrences of that do string concatenation.

AC: If using this feature and just want to use string interpolation, why should I have to think about "raw" when "raw" doesn't really even reflect what I want.

(Allen leaving. 4, 1, 3, 2)

AR/AC: ...continued discussion

Beginning to devolve.

YK/STH: arguing that it's not the language's job to hand hold

AR/AK/AB: ...disagree

WH: (whiteboard)

1
AT&amp;amp;amp;T

(illustrating the dangers of blindly coding with html`` concatenations everywhere)

(Running out of time)

MM: What is the intersection?

DH: We're headed the wrong way, forcing into a design approach that we don't do.

RW: Should we table?

DH: Yes, that's where I'm heading.

AC: We may never get consensus

DH: We won't give up, we've gained consensus under worse duress.

link Conclusion/Resolution

  • Tabled.

Ecma/TC39 Meeting – Mar 13 2013

link March 13 2013 Meeting Notes

John Neumann (JN), Norbert Lindenberg (NL), Allen Wirfs-Brock (AWB), Rick Waldron (RW), Waldemar Horwat (WH), Eric Ferraiuolo (EF), Erik Arvidsson (EA), Luke Hoban (LH), Matt Sweeney (MS), Doug Crockford (DC), Yehuda Katz (YK), Brendan Eich (BE), Sam Tobin-Hochstadt (STH), Alex Russell (AR), Dave Herman (DH), Adam Klein (AK), Bernd Mathiske (BM), John Pampuch (JP), Avik Chaudhuri (AC), Edward O'Connor (EOC), Rick Hudson (RH), Andreas Rossberg (ARB), Rafeal Weinstein (RWN), Mark Miller (MM), Reid Burke (RB), Edward Yang (EY), Dan Stefan (DS),

link 4.14 Make new Date(dateObj)

(Presented by Allen Wirfs-Brock)

See: https://bugs.ecmascript.org/show_bug.cgi?id=1257

AWB: Propose to fix this by spec'ing the Date constructor to special case date object arguments and produce an accurate copy of the date object.

DC: Produces a clone?

AWB: Yes.

DC: a Issues with toString?

AWB: No

NL: Bug mixes ES5/ES6 spec language: DefaultValue/DateValue?

AWB: Not an issue

link Conclusion/Resolution

  • When date object is passed to the Date constructor, it makes an accurate copy of the date object.

link 4.4 Spec Update

(Presented by Allen Wirfs-Brock)

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

link RegExp global, ignoreCase, multiline, source, sticky are now prototype accessor properties rather than instance own data properties.

AWB: WH's question, "why are the flags now accessor properties?" (re: RegExp global, ignoreCase, multiline, source, sticky) is necessary to support a web compatible "compile" method. The web reality takes an existing instance and reinitializes a new instance.

MM: SES doesn't whitelist "compile", but could we specify "compile" to be SES whitelistable. Freeze, no longer modifiable by compile

Example:

1
2
3
4
5
6
7
8
9
10
11
12
13
var re = /abc/;
re.compile("changed");
console.log(re);
// > /changed/
Object.freeze(re);
re.compile("again");
console.log(re);
// > /again/
// oops

DC: What is the history of "compile"?

AWB: Not sure, but I believe it was JScript

link ArrayBuffer and TypedArray object length no longer restricted to 2^32 limit

DH: We should talk offline about making sure this is future proof

MM: is the new length 2^53? If it goes over, there will be a length that can't be represented

...Mixed discussion about the length limitations of existing arrays.

AWB: Isn't really an issue, just allows the length of arrays to be sufficiently large. I believe this is the future proof solution

ARB: Is it inconceivable that you might want to create a TypedArray backed by a large mapped memory?

DH: Not inconceivable. ...Regardless of whether you want something 2^53 or above

YK: Agree with Allen that this is probably sufficient.

DH/AR: (brief discussion about ownership of TypedArray spec)

AWB: Can't use the same methods as Array, because they use 2^32 length.

MM: And are all generic, so really work on "array likes"

AWB: It's not clear that they should work and it may not make sense to have these methods. There are possible solutions

WH: An example of non backwards compatible?

MM: Sparse array that's not populated up to the limit and push on it? What happens?

WH: Calls ToUint32 on it?

AWB: Yes

WH: Doesn't consider those array like?

AWB: Array spec, gets and sets, does its own Uint32 ...Need to look at each of these methods and see what can be done to make these compatible.

BE/AWB: (mixed discussion about historic compatibility issues)

BE: We can try it and the first sign of trouble, back off.

MM/AWB/BE: (agreement)

WH: The main use I see of ToUint32 is to call it on the existing length. Indices passed in as arguments are generally processed via ToInteger. As such, getting rid of the ToUint32 in generic Array methods applied to non-Array objects shouldn't present much difficulty (when they're applied to Array objects the change would be invisible because Array length can't reach 2^32).

AWB: But it doesn't have to be an array ...We should move on.

link 4.5 Private Symbols, WeakMaps, and Relationships

(Presented by Mark Miller)

Slides (PDF, will prompt download): http://wiki.ecmascript.org/lib/exe/fetch.php?id=meetings%3Ameeting_mar_12_2013&cache=cache&media=meetings:relationships.pdf

MM: Concerned about the overlap in functionality between WeakMaps and private Symbols.

...WeakMap named with the word "Map" inverts the thinking.

...Allen noted that WeakMaps are about a Relationship, between two objects.

Legend:

base is key field is map

(Slide 2)


"Map" inverts thinking (the use of ">>" signifies the that the item on the LEFT is usually better for most purposes then the RIGHT)

Syntax: [email protected] >> map.get(key) ...Describes the relationship more accurately

GC: impl(base)[field] >> impl(map)[key] ...A better implementation on the LEFT, despite most implementing the RIGHT

Lookup: Inherited props >> own props

Intuition: Relationship >> Symbol >> Map

Unique Symbols ok.


STH: Weak hash tables are found in programming languages and people want them in JS, but they historically fall in the RIGHT. Why can't we declare victory and go home?

MM: I feel like we can declare victory, but more work to do.

WH: Let's avoid a meta discussion.

(Slide 3)


ES6 Encapsulation Mechanisms

Closures hide lexical state (ES5)

Modules hide non-exports

Direct Proxies hide handler and target

WeakMaps hide keys, do rights-amplification

Private Symbols


(Slide 4)


GC: [email protected] = value ...Not discoverable given "base". Have to have both "base" and "field" to get value.

Abstract heap maps(base, field) => value base and field reachable -> value reachable

...Introduces an "and" into the previously only "or" GC map

Obvious representations:

  1. impl(base)[field] => value better when field lives longer ...When base dies early, it will take the association with it, by regular GC and without needing ephemeral

  2. impl(field)[base] => value better when base lives longer ...When field dies earlier, it will take the association with it, by regular GC and without needing ephemeral


(Slide 5)


GC by use case

When base is known to live longer Just use a map (per Yehuda)

oo private field is known to live longer. Just use representation #1

Most remaining WeakMap use cases would do better with representation #1 (untested claim)

(From a GC perspective)


MM: The GC cost is significant. If you chose the wrong implementation, every object that gets trademarked is retained by the WeakMap until you invoke the ephemeron collection algorithm.

ARB: It's worse in v8 because it has an incremental GC that currently can only run that on full collections

MM: w/r to normal access, I believe it's a wash

AWB: I don't think it's a wash, case 1 requires an index, case 2 requires a hash code

(Slide 6)


GC by use case

Only need ephemeron collection when

  • you guessed wrong relative longevity
  • you care about the memory pressure

Felix's O(N) algorithm is affordable with inverted representation

Examples: Membranes


MM: Membranes are an example where you still need the ephemeron collection algorithm

b is base object f is field

L is left side R is right side

T is target P is proxy

(Slide 7)


Transparency vs Privacy ...Membrane:

Test: [email protected] = vL [email protected] === vR

...see slide


[Whiteboard Example, get image from Sam]

MM: Propose changing the name of WeakMap and changing the way we specify and describe them for implementors to think about.

AWB: Last meeting, we discussed cases... eg. when you invoke a method whose this object expects access to the private state, but it receives a proxy, it will break. I believe the solution might solve the problem

YK: |this| binding issues are orthogonal to this issue

BE: (Agree)

MM: (refutes)

WH: I challenge on this, there is a claim that we don't need private symbols and that they're broken, but we need to do things that private symbols are for. So why can't private symbols work the same way?

MM: This accomplishes things that we needed private symbols to accomplish, if you want to propose changing the name of w

WH: I want to see common uses of private symbols and how you would replace them.

MM: I haven't shown the broken solutions...

STH: I think that would've been much more helpful then showing what works today and that you wouldn't change.

MM: I believe this is an acid test to prove the transparency

WH: Implement private symbols in terms of whatever you're proposing.

MM: fT is a private symbol

WH: ...

MM: I'm trying to answer your question

WH: What would I need to do differently and why, using your glorified new approach.

MM: In the expansion of a class that uses a private symbol, for each declared private instance variable, there will be a private symbol per instance variable.

WH: I think you'll need to write it down.

MM: (describes semantics, based on Slide 8)

WH: You're saying private symbols work if they adopt this semantics

WH/STH: What are the changes?

STH:

  1. There is no trapping on writes and reads of proxies, passes through
  2. proxy a private symbol and write sets and gets, trapped to the handler that has that private symbol.

...In Mark's defense, this is a substantial change to how we think about private symbols

AWB: It's a new type of access on an object, with a new type of state. A new, different operation with separate behaviors

YK: Will the vast majority of JavaScript programmers have to understand this? This is the most important question for me

ARB: ...?

TVC: Don't need to change proxies in anyway

YK: Not actually my concern

STH: Need to think of these as something more then properties

MM: Thinking of them as properties is what caused me to gravitate towards addressing

(Slide 9)


Desugaring Private Relationships

1
2
field.get(base) field.set(base, value)

(Slide 10)


What about symbols and strings?

1
2
3
4
5
6
7
8
9
10
11
12
-field.get(base)- -field.set(base, value)-
field[@geti](base) field[@seti](base, value)
String.prototype[@geti] = function(base) {
return base[this];
};
String.prototype[@seti] = function(base, value) {
base[this] = value;
};

MM: Don't want to use string name "get" and "set" for the invocation, I want to use a symbol

WH: What is the implementation of @geti?

MM: The semantics of WeakMap's get, with exception that if the key isn't found, it tries the object the key inherits from (i.e., follows the prototype chain) until it finds a key or fails. In other words, it implements the inheritance semantics we expect of accessing properties. Given the use of representation #1, this can reuse the existing optimizations for inherited property lookup.

...?

MM: Private symbols, not discoverable

AWB: You've transformed it into a alternate MOP level operation, but you could've transformed it into a new MOP level operation... (missed this before Waldemar interrupted)

WH: This was my proposal 3 years ago...

MM: Explanation...

WH: Not allowing these things to have normal descriptor rules is a bug.

STH: Exactly, the existing proposal reuses the mental model of JavaScript programmers that we should continue to use. Same is true for encapsulation at the property level and GC mappings.

AWB: If you want true privacy

WH: ... You need

AWB: You can't proxy anything that has private state. Cant proxy any built-ins, or anything with private symbols.

BE: Asking TVC to address Waldemar's concern

WH: When the issue of membranes vs private symbols first came up, I showed an inversion approach, instead of asking the object's proxy to look up, you'd ask the private symbol's proxy. This had been intended to solve the proxy privacy leak problem (don't want object proxies to see the objects' private state), but it's essentially the same issue and solution.

TVC: Having property access by the private symbol

STH: Mark is proposing something that has similar semantics, without a new meta operation, but pays for that by making it less like true properties

WH: So which is it?

MM: If the definition of WeakMaps is something you "stick things into", then the answer is private symbols.

WH: Please show an example how we'd actually use this and how it would interact with a proxy

(break for lunch)

MM:

private is a pseudo-syntax mechanism

1
2
3
4
5
6
7
8
9
10
class Point {
constructor(private x, private y) {}
toString() {
return `<${this@x}, ${this@y}>`;
}
add(point) {
return Point(this@x + [email protected], this@y + [email protected]);
}
}

Desugars to...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
let Point = (function() {
const x = Rel();
const y = Rel();
function Point(x, y) {
this@x = x;
this@y = y;
}
Point.prototype = {
toString() {
return `<${this@x}, ${this@y}>`;
}
add(point) {
return Point(this@x + [email protected], this@y + [email protected]);
}
};
})();

YK: If you're calling add through a proxy?

MM: If you're calling one Point proxy from another Point proxy, the

YK: Use case, I want the |this| binding to be the proxy

MM: Call add() method on a proxy of a Point If the right operand is a proxy,

BM: a proxy to a point doesn't have an x

AWB: Specifically, a proxy to a point isn't registered in x

...Concern: if you had done toString simply as a get access

YK/STH: If Proxies are going to fit into the language, with any sort of concept of private state, then we need to solve the problem, and this doesn't solve the problem.

MM: Use membranes.

WH: If you come up against this problem many times and each time the answer is membranes, then we need to add membranes, not proxies.

General Agreement.

STH: Until we decide which side of the solution we want: either transparently proxying objects with private state should work, or private state can indicate that something is a genuine not-a-proxy instance of an abstraction (such as Date), then we can't possible have a solution.

YK: Hiding implementation details that manage private state that can't be proxies.

AWB: Virtual object vs Caretaker

BE: Not going to make unstratified traps

YK: only need a small amount of traps: get and set

...Can't go down this road.

(going in circles now)

BM: Notes that the next logical step is interfaces, where you define an interface and proxies implement against this.

BE: Can't apply an interface to already born objects.

BM: if you pre-plan that the object is inline with the interface then security is under control

BE: We should defer private symbols

AWB: If we do that, then there is no private branding on the object

STH: Doesn't solve the problem for "what does proxy for dates do"?

More discussion about the general flaw of proxies wherein... objects that have some form of internally implemented "private" state cannot be observed and therefore not subject to trapping.

MM: Can we agree that transparency through membranes is a requirement?

AWB/STH/YK: Agree its important, but there are a lot of requirements.

MM: A champion group should go and solve these problems. Retaining WeakMaps, deferring private symbols very closely matches the proposal.

STH: ...

MM: Just want to consolidate the issues

STH: Bad idea to postpone WeakMaps, which useful and are already shipping in browsers. Bad idea to postpone anything based on a particular issue with Proxies. A separate issue with regard to the design of private symbols. None of these are solved by adding "@" to represent a WeakMap.

WH: It seems like @ for WeakMap makes sense

BE: Too much for ES6

MM: Regardless of the syntax/API, the slides show that we should encourage implementers to hang the state off the key, not the base.

AWB: The WeakMap abstraction we have is fine as is. If an implementation wants to invert its handling of keys and the map, then that's fine too.

WH: (some comment about private state?)

STH: That's not related

AWB: (re-iterates)

MM: The inverted representation is the better one.

YK: So, what is your proposal?

MM:

  • My proposal is the private symbols get postponed to ES7
  • WeakMap gets renamed to reflect the inverted thinking
  • If we adopt the @ syntax in ES6, I want to be able to use a WeakMap on the right side

...Don't care so much about the renaming, but feel that it could add clarity to the feature

RW: (Disagree based on experience teaching the concept)

WH: no consensus on class without private symbols

MM: Rick, can you find the history of this?

RW: (recounts two meetings where Waldemar was not present, but a general consensus existing with the understanding that Waldemar would still have something to say. At Northeasten, Allen presented @-names, in which Waldemar found to sufficiently meet his privacy requirement for classes)

...Discussion around class private state as a whole.

BE: We need to synthesize what's going into ES6. Waldemar claims this must include some way of adding class private state.

STH: I would like to stop this conversation and allow myself time to think about this.

BE: Done.

link Conclusion/Resolution

  • Sam, Mark and Allen to work on "relationships" and varied representation in ES6.

link 4.3 Proxy

BE: We've had prototype implementations for some time, we made it through the change of API. We use them extensively.

link 4.16 Current Status of ES6

(Presented by Luke Hoban)

Spreadsheet: http://sdrv.ms/Z9pQxs

AWB: Based on this review, we should shoot for December 2014

Discussion of time tables for completed spec reviews

NL: Also need to look at progress on implementations.

NL: Concerned about impact on Internationalization API 2.0 – need to evaluate whether to base on ES5 or slip to December 2014.

link Conclusion/Resolution

  • November 2013, Final review draft
  • June 2014, Editorially complete (STH: we said June in the meeting, but July makes more sense, since we don't have to submit to the GA until September, IIUC)
  • December 2014, ECMA approval

link 4.7 Runtime costs of the override mistake

(Presented by Mark Miller)

Override Mistake http://wiki.ecmascript.org/doku.php?id=strawman:fixing_override_mistake

(Request spreadsheet)

RW: Would like to see the most minimal piece of code required to illustrate the operation, measured by executing the operation in several rounds with MAX number of executions calculated to a mean value. Also, there is use of an in operation which will skew the results between Firefox (a bit faster) and Chrome (slow)

WH: I'd like to see comparisons of non-frozen vs. frozen to see whether the two order of magnitude Chrome slowdown is caused by freezing or inherent slowness of push and pop.

Varying, lengthy discussions around SES techniques and the implications of the override mistake.

Non-issue for code that doesn't freeze.

link Conclusion/Resolution

  • Investigate instrumentation when silently fails non-writable prototype properties.

Ecma/TC39 Meeting – Mar 12 2013

link March 12 2013 Meeting Notes

John Neumann (JN), Norbert Lindenberg (NL), Allen Wirfs-Brock (AWB), Rick Waldron (RW), Waldemar Horwat (WH), Eric Ferraiuolo (EF), Erik Arvidsson (EA), Luke Hoban (LH), Matt Sweeney (MS), Doug Crockford (DC), Yehuda Katz (YK), Brendan Eich (BE), Sam Tobin-Hochstadt (STH), Alex Russell (AR), Dave Herman (DH), Adam Klein (AK), Edward Yang (EY), Dan Stefan (DS), Bernd Mathiske (BM), John Pampuch (JP), Avik Chaudhuri (AC), Edward O'Connor (EOC), Rick Hudson (RH), Andreas Rossberg (ARB), Rafeal Weinstein (RWN), Mark Miller (MM)

link Opening

link Introduction

link Logistics

link Adoption of Agenda

Mixed discussion regarding scheduling over the course of the 3 days.

Approved.

link Approval of January 2013 Meeting Notes

Approved.

link Adobe

JP: Here to help accelerate the ES6 spec, positive motivation. Excited about Modules, concurrency, debugging and profiling specifications.

BM: Background as trained language designers and implementors and here to help.

JP: Also excited about asm.js

BM: Not sure about the spec status/prospects of asm.js.

Edit (2013-03-22) http://blogs.adobe.com/standards/2013/03/21/adobes-ecma-tc-39-involvement

link 4.9 JSON, IETF changes

(Presented by DC Crockford)

Currently, JSON is an RFC, informational, the IETF version will be an internet standard and there is a minor correction that affects ECMAScript.

The use of "should" in 15.12.2

AR: What is the motivation of the change?

DC: The change involves the mistake of using "should" w/r to multiple same-named keys error. Multiple same-name keys are invalid and must throw an error (vs. "should" throw an error)

LH: This is a breaking change

DH: The worst being the use case of multiple, same-named keys as comments

DC: That's stupid

YK: That's based on on your recommendation to use a keyed entry as a comment, so people naturally used the same key, knowing they'd be ignored.

DC: I would certainly never recommend that practice

YK: It was a side-effect

AR: Which key is used now?

AWB: The last one wins.

AR: Is that the root of the security vector?

DC: Not in ES, but in other encodings

AR: Order matters, unescaped content that follows...

DC: The current spec says "[they should not]", but will say "[they must now]"

YK: Let's define an ordering and make it cryptographically secure.

DC: (recapping to Mark Miller, who just arrived)

MM: You can't do that. (laughs)

MM: You can't change "should" to "must"

YK: Agreed, you cannot change JSON, there are too many JSON documents in existence.

MM: Agreed.

AR: It's possible to ignore this change?

DC: Yes

DH: Then why are we creating a dead letter?

MM: ES has a grammatical specification for validating and parsing JSON. Anything that is not conformant JSON, would not parse. This change loses that property.

DC: Or we don't change the spec

MM: The way that you properly reject our favorite fixes, I think you should apply to your favorite fixes

DC: I'll consider that

AR: There is considerable opposition to this change

DC: Two choices...

  1. Make it an error
  2. Continue to take the last one

DC: Decoders have license to do what they want with non-conformant material. Encoders must be conferment to new changes.

MM: Our current encoder conforms...

AWB: I don't think it does... reviver/replacer

MM: No, can only apply objects instead of the original objects.

AR: Did not realize the production/consumption distinction of this change.

WH: Supports this change. ECMAScript is already conformant because it never generates duplicate keys.

MM: With this change ECMAScript would have two unappealing choices: A. No longer be a validating parser (i.e. a parser that doesn't allow any optional syntax or extensions, even though extensions are permitted by the JSON spec). B. Do a breaking change by throwing errors when seeing duplicates when parsing.

link Conclusion/Resolution

  • Revisit this, after DC has made a final decision.
  • FTR: Majority opposition, no consensus.

link 4.12 StopIteration/Generator

(Presented by Dave Herman)

https://github.com/dherman/iteration-protocols

DH: ...Confirms that there is lack of understanding for Generator "instances"

MM: Clarify terminology

DH: Generator objects are instances of Iterators, in that they have a next method. The current design is based on a thrown StopIteration

C#, Java, Python apis for comparison.

My opinion, a single method is win.

Concrete proposal:

  • The benefit of a single method
  • Not based on exceptions
  • Compatible with Generator semantics

Iterator API object has a single method:

1
2
3
4
{
next() -> { done: false , value: any }
| { done: true[, value: any] }
}

b/c generators can return an argument, if you're using a return value

1
2
3
4
function* f() {
yield 1;
return 2;
}

for for-of this doesn't matter, but for libs like q, task.js this is useful for pause and resume with value

If we didn't care, the result value can be omitted

This API was pleasant to write and works nicely with existing idioms

MM: Requires allocation for every iteration?

DH: Yes, will still need the object allocation, but

WH: Does next return a fresh object? or can reuse the same?

DH: Can reuse

AWB: For every iterator in the spec, we need to specify a fresh or reused object?

DH: Yes.

YK: The current API, able to do yield ...returns a promise...

DH: Can still do that, this change is internal and w/r to performance, this should be highly optimizable.

AWB: Anything that uses a method based implementation, will be more optimizable through calls vs exception.

DH: I've never seen an iterator API that didn't have some performance issues

AWB: (refutes) Any method based approach can be better optimized over exception based approaches.

DH: I don't have a solid performance story, but the feedback I'm getting is that there is negative concern about the StopIteration approach, whereas this approach mitigates these concerns. Issues arise when dealing with multiple iterators

WH: If you try throwing StopIteration across iterators, it will be caught

AWB: Or it won't

EA: Surprising: If any function throws a StopIteration, it will jump out of the for-of.

AWB: I noticed this in the examples shown in the github repo

WH: Why I'm in favor... Throwing StopIteration across places where no iterators exist and if code is refactored so that an iterator is present, you'll experience unexpected behavior. (This suffers from the same capture flaws as Lisp's old dynamic scoping.)

LH: When we last talked about this, we whiteboarded the priority order. for-of is the primary case, generator authoring is the secondary case. Cases affected by this: direct API consumption as third and direct API authoring is fourth

If we're really sure the engines will do the work to optimize these things?

A. will this slow down implementation? B. won't be willing to implement due to poor performance?

AR: No implementation wants to ship something that will potentially be slow

LH: Of course, but StopIteration has to go.

MM: One allocation per loop

WH: So is this

MM: Only if you reuse the record

LH/WH: Of course and that's what you want

MM: Then, as Allen said we need to specify this

DH: My inclination would be to use a fresh object each time

AWB: ...you know the first time, because it's the first time that next is called,

MM: My proposal is that you provide stop token as a parameter of next(stop), every time. next(stop) would return either the next value or the stop token.

DH: (clarifying) "iteration" is one time around the loop. "loop" is the entire the operation.

WH: It's possible for next(stop) to cause havoc from one iteration to another by caching one next call's stop parameter and returning it from a different next call.

[Someone had also presented a variant of the proposal where was a field on the iterator instance instead of an argument to next.] WH: This would create funky failures if, for example, you had an iterator that did a deep traversal of an object tree and said tree happened to include the iterator instance.

MM: In order to not allocate on every iteration, you have specify (???)

MM: A new stop token would be generated per loop.

WH: What's a loop? This gets confusing when you have iteration adaptors.

AWB: If the client passes in the token on next(), then it's the client's burden

MM: Anything that's unforgable, unique, or itself side affectable.

DH: Is there support for Mark's API?

RH: If you use Mark's API, overtime...

MM: My API reuses the object for the iterations of the loop, by passing it back in as an argument to next()

RH: To avoid the cost of allocation?

MM: Yes, but only as a token

EA: You can have a return value in a generator so the object passed in needs to be mutated to include the return value in case of end of iteration.

MM: That is a downside of this proposal, where StopIteration would carry the value.

DH: (examples of the two proposals)

Dave's

1
2
3
4
{
next() -> { done: false , value: any }
| { done: true[, value: any] }
}

Marks's

1
2
3
{
next(X) -> any | X
}

AWB: (suggests an alternative: pass an object to next, on which next sets the result)

STH: ...is hostile to implementors and user code.

ARB: That's the C-style of doing it.

WH: Suppose the iterator takes an object and returns all the properties, but calls on itself?

DH: Mark's proposal is broken, because it doesn't work with return values of generators.

MM: Agreed.

DH: Don't think that we're approaching consensus, but don't let your idea of perfect cloud judgement. I'm asking engine implementors if this is appealing. The concern over StopIteration is real.

AWB: This is certainly better then the current plan of record

AR: Agree.

BM, JP, AC: Agree

BM: This is also future proof and works well with concurrency and the semantics are sound. It's also easy to implement and optimize.

AWB: All spec iterators/generators must specify a reused iterator or fresh

MM: (further support for AWB's claim)

DH: Not sure if we're trading short term wins for long term losses. Are there long terms

ARB: There is another secondary effect that it encourages better GC

AWB: This shouldn't be a problem for a good GC

MM: I'm really only concerned about the loop aspect

AR: We have the tools to work with hot loops

WH: Alex's point about the escape valve is key

DH: Not discounting the needs of the developers/user code. The method API is appealing, vs. StopIteration

RW: Agree.

DH: (Shows example of C#)

AWB: The third use case that Luke gave, using an iterator and the fourth use case, creating an iterator. ...This API is more complex for user code ...More ways for client code to go wrong

BM: Disagree, this is a safer.

DH: Don't get out of sync. Argue that the Java and C# API are too error prone.

BM: Agree, this is actually superior to the Java and C# APIs

ARB: This is actually the path you'd want in typed languages, minimizes state space

DH: I want to see a better overall interface for iterators and generators, without jeopardizing the acceptance.

MM: In favor of this API, if the implementors are not objecting. Although I don't like the API itself.

DH: Agree, I prefer the pure, stateless proposal

AWB: If an object is passed an argument, the object is used as the value bucket.

DH: Still mutates the object

AWB: But it mutates an object that you've explicitly provided

BM: The issue is not the allocation, but that you have to go to heap at all.

ARB: If you do this pre-allocation thing, it might be observable

BM: But that's the case either way

DH: Is the mutable version going to harm optimization?

ARB: Yes: the object may be shared, in which case mutation may become observable from the distance, and cannot be optimized away

RH: If the object being mutated escapes to an old mutation, this kills potential optimizations.

DH: Seems like consensus on the pure, stateless version of this:

1
2
3
4
{
next() -> { done: false , value: any }
| { done: true[, value: any] }
}

JP: "more" vs. "done"?

(can discuss further)

link Conclusion/Resolution

  • Rough agreement (between those present) on pure, stateless version of:
1
2
3
4
{
next() -> { done: false , value: any }
| { done: true[, value: any] }
}

...To replace StopIteration

  • Always has an own property called "value":
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var i1 = (function *f() {
return;
})();
"value" in i1.next();
var i2 = (function *g() {
})();
"value" in i2.next();
var i3 = (function* h() {
return (void 0);
})();
"value" in i3.next();
  • Built-in iterators should be specified as returning a fresh value.
  • See: https://gist.github.com/dherman/5145925
  • Without Brendan, a champion of iterators and generators, don't have full consensus

link 4.2 Modules

(Presented by Dave Herman, Sam Tobin-Hochstadt, Yehuda Katz)

See: https://gist.github.com/wycats/51c96e3adcdb3a68cbc3

Slides (PDF, will prompt download): http://wiki.ecmascript.org/lib/exe/fetch.php?id=meetings%3Ameeting_mar_12_2013&cache=cache&media=meetings:modules-march-2013.pdf

DH: We're committed to making this happen for ES6, it's too important to miss and I'm going to do whatever it takes. Please remember that you can always bring specific issues directly to us (DH, STH, YK).

...Not going to spend time on syntax. Focus on Module loading semantics to address any outstanding issues, spent last two months working with Sam and Yehuda and polling community leaders to get use cases to work with.

Recognize that some use cases may not be covered, but that's ok.

link Module Loading Semantics

...Currently a notion of having a string-name registry

...Move towards having a separate space for module registration

Minimalism - IN Nested Modules - OUT

1
2
3
4
5
6
7
8
9
module "libs/string" {
export function capitalize(str) {
return (make the string capitalized)
};
}
module "app" {
import { capitalize } from "libs/string";
}

The registry corresponds to a Loader which creates a Realm

MM: But you can have more then one Realm

DH: Think of Loader as a virtual "iframe", as a concrete way of describing it. When you create an "iframe", you get a whole new global object with it's own DOM. A Loader creates a "sandbox" global that can share system intrinsics.

The System loader.

1
2
var capitalize = System.get('libs/string').capitalize;
var app = System.get('app').app;

Custom loader:

1
2
3
4
5
6
var sandbox = new Loader({ intrinsics: System });
sandbox.set('app', System.get('app'));
sandbox.get('app') === System.get('app'); // true
sandbox.eval("import { capitalize } from 'app'; capitalize('hi')"); // "Hi"

Acts like a map, .get() will get the module

[Module pipeline diagram]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
module name
|
V
normalize
|
V
resolve
|
V
fetch
.
.
V
translate
|
V
link

Produces one of three values:

  • undefined: default linking behavior
  • Module: registers module instance object directly
  • {imports : [ModuleName], execute : (Module ...) -> Module, exports : [String]} : invokes execute to produce module, exports optional

...

link Use Case: Module Paths

1
2
3
4
System.ondemand({
"http://code.jquery.com/jquery-2.4.js": "jquery",
"backbone.js": [ "backbone/events", "backbone/model" ]
});

...is sugar for...

1
2
3
4
5
6
7
8
9
10
11
12
System.resolve = function(path) {
switch (path) {
case "jquery":
return "http://code.jquery.com/jquery-2.4.js";
case "backbone/events":
case "backbone/model":
return {
name: "backbone.js",
type: "script"
};
}
};

MM: This is changing the behavior only at the system Loader?

DH: Yes.

STH: This is the API that several people indicated was important during the last meeting.

link Use Case: ...?

link Use Case: Compile To JS

1
2
3
4
5
6
System.translate = function(src, options) {
if (!options.path.match(/\.coffee$/)) {
return;
}
return CoffeeScript.translate(source);
}

LH: Is this updated on the Wiki?

DH: Will update. Much of the changes are about refining API and making common things easy and most things possible

link Use Case: Custom AMD

Creating custom translations for extensions...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import { data: foo } from "text!foo";
```js
System.normalize = function(path) {
if (/^text!/.test(mod)) {
return {
normalized: mod.substring(5) + ".txt",
metadata: { type: "text" }
};
}
// fall-through for default behavior
}
System.translate = function(src, { metadata }) {
if (metadata.type === "text") {
let escaped = escapeText(src);
return `export let data = "${escaped}"`;
}
// fall-through for default behavior
}

WH: Why would you want to do it this strange way (escape text only to then eval it) instead of just letting the text be? [It feels kind of like the folks doing eval("p." + field) instead of p[field]].

DH: (explains James Burke's summary of static asset loading)

link Use Case: Importing Legacy Libraries

(Specifically, not libraries that use CommonJS or AMD, but libraries that mutate the global object)

1
2
3
4
5
6
7
8
9
10
11
12
13
var legacy = [ "jquery", "backbone", "underscore" ];
System.resolve = function(path, options) {
if (legacy.indexOf(path) >= -1) {
return {
name: path, metadata: { type: "legacy" }
};
} else {
return {
name: path, metadata: { type: "es6" }
};
}
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function extractExports(loader, original) {
var original =
`var exports = {};
(function(window) { ${original}; })(exports);
exports;`
return loader.eval(original);
}
System.link = function(source, options) {
if (options.metadata.type === 'legacy') {
return new Module(extractExports(this, source));
}
// fall-through for default
}

LH: Once we ship this, we want people to start using modules as soon as possible. How?

YK: Realistically, a "plugin" for something like require.js will have to provide an ES6 "shimming" mechanism.

LH: To paraphrase, we're providing the primitives that make the common cases easy to overcome. What about the legacy libraries that won't be brought up to date? Can we provide a simple mechanism?

DH: No, legacy libs that just expose themselves to the global object, without any sort of shimming mechanism are out of reach

LH: Thank you, that's a sufficient answer

link Use Case:

Import AMD style modules and Node style modules. Effectively, ES6 module importing from non-ES6 module.

There is no way to tell

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
System.link = function(source, options) {
if (options.metadata.type !== "amd") { return; }
let loader = new Loader();
let [ imports, factory ] = loader.eval(`
let dependencies, factory;
function define(dependencies, factory) {
imports = dependencies;
factory = factory;
}
${source};
[ imports, factory ];
`);
var exportsPosition = imports.indexOf("exports");
imports.splice(exportsPosition, 1);
function execute(...args) {
let exports = {};
args.splice(exportsPosition, 0, [exports]);
factory(...args);
return new Module(exports);
}
return { imports: imports, execute: execute };
};

BM: Could you postulate that exports and

DH: You could but, unrealistic

BM: Could be optimizing for module provider, but not consumer... ...

MM: What does the Module constructor do? DH: Copies the own properties of the given object.

MM: What is the job of the System.link hook?

STH: To go from a piece of JavaScript source code to module instance object, translate is string->string.

WH: Is it a module or Module instance?

DH: Module instance object

Take the source code, all the deps, finds all the exports, links them together.

The link hook can return

  1. undefined for the default behavior
  2. A Module instance, where everything is done and complete
  3. An object, with list of deps and factory function to execute at some later time (eg. when all deps are downloaded and ready)

YK: Explains that a two phase system is required whether you're using node, AMD or anything. Now you can use ES6 provided hook.

BM: Optionally specify the list of exports?

DH: Yes.

Conversation about specific example.

MM: Clarify... noting that the positional args is similar to AMD positional args

DH: Yes.

ARB: No static checking for non-ES6 modules?

DH: Yes, it's a hole that can't be filled if we want interop from AMD->ES6 and ES6->AMD (or node)

ARB: Concern about having two imports, checked and unchecked. (implementation complexity concern)

BM: The alternative is to not support AMD and provide only one imports

STH/RW: This is an option, but a worse option.

...Discussion re: static checking for non-ES6 modules

ARB: Every single construct, import, loading etc now has two different semantics to support.

BM: Forces users into thinking about which they need... optimizing for module authors, not module users. The wrong case... otherwise enforce static checking for all module code

AR/STH: Not possible for all existing code

STH: (whiteboard) Indirection via dynamic object makes static checking impossible.

For example, if you write the code:

1
2
import { a } from "some.js"
... a ...

where "some.js" is an AMD library, then there's no static checking, but if you refactor "some.js" to be an ES6 module, you automatically get static checking. But if you don't support this use case, then there's indirection:

1
2
import { exports } from "some.js"
... exports.a ...

And changing "some.js" to use ES6 never results in new static semantics.

...Mixed discussion re: dynamic checks vs static checks.

BM: Was under the impression that the dynamic checks might be too late, but it has now become clear that they happen early enough

STH: Cannot create references across Module instances to dynamic module code.

MM: the world of JS uses feature detection, on the AMD side... can AMD code feature test?

STH: (refers to an early slide, which shows example of importing module as single object, properties can then be tested for)

MM: (confirms that STH answers Q)

DH: Pause on the Question of dynamic import/export (Returns to the pipeline diagram) ...The "fetch" hook is the part where you go get the bits

DH: (Slide: 1. Load and Process Dependencies Diagram) (Slide: 2. Link)

AR/DH: Note that browsers can provide their own plugin points for the Fetch step

MM: All of the hooks have been executed and there is no user code? If this fails, there are no side effects?

DH: Correct

ARB/STH: During

DH: Modified the registry, but there is an inflight loading happening, when the inflight is finished, it will pave the changes to registry. (last op wins)

ARB: When you evaluate a script that imports module Foo, which runs hooks that in turn import Foo into the module registry, what happens?

AWB: Why are they operating in the same Realm?

DH: It sounds like an objection to modifying the list of modules in the registry by downloading code that modifies the list of modules in the registry...

STH: Imagine we didn't have loader hooks, all you could do was eval and had two XHRs that fetched and eval'ed. We'd still have the same issues that we'd have with loader hooks, it's a problem with mutation and concurrency.

ARB: Agree that the fundamental problem will always be there, but have a problem with shared global object for all modules.

DH: If the same module is attempted to be defined in two places, that's an error and is a bug.

ARB: Only when within the same compilation stage, silent overwriting otherwise.

WH: What if module A depends on both B and C and the initialization of B fails?

DH: C remains uninitialized but present in the registry

WH: This breaks the model. It's not C's fault that its initializer didn't run.

AWB: Mark C as never having its initializer attempt to run and run it the next time it's imported.

DH: Moving to next slide

(Slide: 3. Execute)

Produces "Result"

Note that each step in the 3 parts has an Error path:

  1. load/syntax error
  2. link error
  3. runtime exception

...Mixed discussion re: execution despite exceptions

...Mixed discussion clarifying fetch semantics (1. Load and Process) re: dynamically building URLs to batch load? re: browser knowledge of sources?

LH: What does the synchronous timeline of Slide 1 look like?

DH: All normalize hooks first (need names and locations), then all resolve hooks

link Use Case: Importing into Node

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
System.resolve = function(path, options) {
if (node.indexOf(path) > -1) {
return { name: path, metadata: { type: 'node' } };
} else {
return { name: path, metadata: { type: 'es6' } };
}
};
function extractNodeExports(loader, source) {
var loader = new Loader();
return loader.eval(`
var exports = {};
${source};
exports;
`);
}
System.link = function(source, options) {
if (options.metadata.type === 'node') {
return new Module(extractNodeExports(this, source));
}
}

link Use Case: Single Export Modules

DH: Brought this up 2 meetings ago, had a proposal that wasn't ready, it was shot down. This is something that I'm being told is very important and I agree with them. We can accommodate single exports via design protocols, but the developer community may not like it.

DH/YK: (walk through the System.link implementation)

DH: Can, should do better. Goal: Simple syntactic sugar. It's important, we will address it and we will do so with syntactic sugar. We will create a means by providing an "anonymous export". We will review the "sugar" at the next face-to-face meeting.

...Recognizes the community frustration regarding lack single/anonymous exports.

...No dissent.

LH: (Questions about how this works with the previously shown use cases)

...

YK: (Shares anecdotal experience from developing the ES6 transpiler that was adopted by Square. Positive experience.)

STH: Updated/removed junk from wiki

LH: Can imports be in scripts?

STH: Yes

DH: There was originally a use case that involved jQuery, we can't satisfy this without breaking everything (there is no way to be ES 3, 5, 6 at the same time)

But...

1
2
3
if (...some detection...) {
System.set("jquery", ...);
}
1
2
3
4
5
6
7
8
9
10
11
<!--
once this is loaded, the jQuery module is
registered and available for all scripts
-->
<script src="jquery.js"></script>
<!--
which means all future scripts may have this:
-->
<script>
import { $ } from "jquery";
</script>

LH: What about concatenation cases?

DH: (whiteboards example of System.ondemand)

1
2
3
System.ondemand({
"all.js": [ "a", "b", "c" ]
});

AWB/STH: (whiteboard)

m.js:

1
2
3
module "m" {
export let a = 1;
}

n.js:

1
2
3
module "n" {
export let b = 2;
}

Needs:

1
2
3
4
System.ondemand({
"m.js": "m",
"n.js": "n"
});

If you concatenate?

m.js + n.js = concat.js...

Needs:

1
2
3
System.ondemand({
"concat.js": [ "m", "n" ]
});

Arrays for files that contain multiple things

...

ARB: We're over-prioritizing for concatenation. The language shouldn't be hostile, but should stop at good enough. We shouldn't optimize the design of the language around a secondary concept

AWB: modules are a concrete concept in the language, we need to focus on these as a building block

LH:

STH: The claim that concatenation is going to become a not-important part of the web is ludicrous

ARB: I think that mid-term concatenation will harm performance

YK: Do you think that concatenation will go away?

ARB: In the long term, it might

YK/STH: This is what is ludicrous

...Mixed discussion re: library vs. language

AWB: There is a standard loader, defined by the language

...From Arv: AR: Joining files to optimize download and compilation

STH: YUI optimized for reality and found that concatting is important

YK: Should Ember ship 100 files?

AR: Any modern library has a lot of files. Apps/libraries are making trade-offs to get good performance.

DC: Caching is not working. Browser will get better.

AR: SPDY will make things better

YK: Even with SPDY, there is a lot of IO

ARB: It is perfectly fine to depend on a tool for concat

EA: We are designing based on concatenation. We should take that out of the picture. We can always write compilers that does the linking.

ARB/LH: With a compiler you can do linking/bundling and existing and future tools can do this.

STH/DH: There will be holes in these.

LH: module "a" { ... } is leading developers down the wrong path

STH: Recommmend doing modules the node style, where each file is a module

YK: AMD developers use a build system that adds the name to the define(). They don't name the modules in their source. The build system names the modules.

MM: AMD experience speaks in favor of a concatenator.

STH: You will get a compile time error if you import a file that contains a module. ...

ARB: How about adding a way to just register a module as a string containing the source of its body as if it was a file.

AR: Then you have to allocate the string ...

AWB: Wants to use module "abc" { ... }. It is a good way to structure code. And you don't want to tie this to your configuration management ...

STH: The strength of the system is that it supports both

ARB: The approach Allen wants is not well supported because it lacks lexical scoping

AR: If we use a string literal we cannot check the code to do prefetching etc

ARB: It is a string so the string only needs to be lexed, then the parsing etc can be paralellized, not so with embedded module declaration ...

ARB: There is no way to not modify the global registry when defining a module.

DH: The file system (in SML) is also a shared registry. The module registry is no different

ARB: Disagree. There is no way to create a local module here

STH: JS has a lot of ways to struccture code: functions, classes etc and modules do not need to fill this role

ARB: More interested in preventing accidents due to name clashes.

...Mixed discussion of module syntax related concerns

DH: Ability to prevent people from using module syntax?

MM: Yes

STH: For Andreas' concern, look for the names of module declaration strings, check the registry and if any already exist, error.

...Defining a loader with right hook, prevent the mutation of the registry by anyone that does not have access to the loader

MM: Satisfied from a security perspective.

ARB: Would prefer for the default behavior to error, need to be explicit if you want module to override in an imperative manner.

DH: Not opposed to moving towards scoped modules in the future. Just worried about complexities.

ARB: Only concerned about import scope semantics

STH: concern is that polyfills have to use eval and then System.set

ARB: good to make it clear that polyfills are doing some special

DH: agree with ARB about polyfills

STH: This is something to be deferred without blocking progress, but ok with changing to error to achieve consensus.

YK: agree with STH about consensus, but potentially concerned.

link Conclusion/Resolution

  • Default: declarative form of a module is an error if a module of the same name already exists in the module registry.
  • Using System.set to overwrite an existing module is not an error.
  • Behavior of errors during module initialization (when some module initializers don't even get started) is still unresolved.

Ecma/TC39 Meeting – Jan 31 2013

link January 31 2013 Meeting Notes

John Neumann (JN), Allen Wirfs-Brock (AWB), Rick Waldron (RW), Waldemar Horwat (WH), Eric Ferraiuolo (EF), Erik Arvidsson (EA), Luke Hoban (LH), Matt Sweeney (MS), Doug Crockford (DC), Yehuda Katz (YK), Andreas Rossberg (ARB), Sam Tobin-Hochstadt (STH), Brendan Eich (BE),

link 4.14 Module Update

(Presented by Sam Tobin-Hochstadt) TODO: Request Slides

STH: (Slide 1)

Recap from November

  • Modules no longer named by Identifiers.
1
2
3
4
module "m" {
import "x/y" as y;
export y;
}

DC: Are they strings?

STH: They are string literals, but may have an internal structure. We should allow characters that don't have to be escaped in URLs.

LH: This is something we will definitely have to specify.

STH: Confirms that they are string literals.

DC: Why strings and not Identifiers?

STH: The string indicates a different scoping behavior

MM: Nesting example?

STH: (Slide 2)

Nested Modules

1
2
3
4
5
6
7
8
module "outer" {
let y = 1; // not exported
module "inner" {
let z = y + 1;
export z;
}
}
import {z} from "outer/inner";

MM: Why isn't "inner" exported?

YK: All modules are visible/available.

MM: Why are all modules visible?

Concern about export visibility.

STH: You're both actually in agreement

LH: There was a change from a more complex system, now when you write something inline, it's loaded into the internal loader registry. This simplifies the proposal, removing the "hybrid" behavior of an Identifier.

STH: Believe this is a better design.

ARB: Disagree.

MM: Q. Where the "inner" string appears, there is no way to change the nesting path.

ARB: ...

MM:

AWB: When you do an import, is that passed through the Loader?

STH: Yes.

AWB: So you could write a Loader that blocked "inner"?

STH: You could enforce any arbitrary rules in the Loader.

ARB: What happens if inside "outer", I have "import from inner"?

STH: Won't work. There is a ...

EA: What happens if you do "import {a} from outer"?

STH: Don't understand.

STH: Important both have a mechanism for top level and relative,

ARB: Appears to be reinventing half of lexical scoping in an ad-hoc way, super-imposed on strings. When somebody thinks to have a better system than lexical scoping, they usually turn out to be wrong.

STH: Trying to avoid this being like lexical scoping. The goal is to be explicitly different, closer to Node... refers to require()

YK: There is a large data set supporting

LH:

YK: Mentions concatenation argument, determined as not strong enough.

STH: ...gave an example of a module that may want nested modules...?

YK: Predict it to be multiple files, not sub modules within a module

STH/YK: If you have a top level...

AWB: clarify? you can't take two top level modules, concatenate them and put them in a script tag?

STH: Yes, but you can't import from them.

LH: Clarifies.

AWB: There isn't a transformation that would take all of the modules and concat into a single file and it would mean the same thing?

STH: You could certainly write a transformation, but you would have to put that result into something that

ARB: What if I import inner, but outer hasn't been imported yet?

STH: Outer is implicitly loaded.

...

YK: I previously understood the module system (STH: I thought it was EA who said this)

LH: I thought... There is a loader that has a table of things. Two ways to get them in there:

  1. Filesystem, where keys are the path
  2. Load a script

Are you saying that the file name is now unnecessary?

STH: Yes

LH: I don't see how you could make this work

YK: I think it's not good. You can't dictate that file A must be here for file B to work.

AWB: You don't want to mix physical identifiers with logical identifiers

ARB: Exactly

STH: One of the other ideas is that the Loader has setters, so that we can replace them... allowing you to change the default Loader. We are going to provide the basic programmatic layer, not design the declarative loader mapping mechanism.

YK: The requirement, based on the example: "jquery-ui" needs "jquery" ...will be problematic when a developer cannot control where the files go.

MM: Will inner be executed?

STH: inner is not executed unless imported.

MM: is the identifier after the module keyword required?

STH: the semantics would likely involve immediate import of that module.

LH: I don't understand why we want nested modules like this. There is no existing system that supports the need.

YK: Agree.

STH: (whiteboard)

1
import {$} from "jquery"

What does "jquery.js" look like?

YK: Top level $ with no "module {}"

STH: What if that file wants to use some other module? I think people will get that very wrong.

AWB: (Concern about the physical file and the import) Not operating logically at the same level as modules

EF: Agrees.

...Discussion regarding "loading" the physical and "importing" the logical.

LH: What Sam is saying... "why can't it just be the import syntax"

MM: Given a fully qualified path and module name, that uniquely identifies a module?

STH: Yes.

MM: What does TypeScript do?

LH: TypeScript has two notions of modules. "declarative object", similar to the earlier module proposal. Also has "file modules" that is a file with "module" that becomes an AMD define.

ARB/LH: Discussion of the semantics of the TypeScript type system.

STH: It assumes that all of the bindings are there for all time.

LH: Yes.

STH: I will avoid "possible futures". To re-answer, module sources are contiguous.

...

STH: Originally, Dave and I punted on nested modules, until we ran into a case that needs nested modules.

ARB: The result is a reinvention of lexical scoping of sorts.

...

AWB: Imagine you had a module named "." and you had a module in the same file named "./util" and so on... Then you take that and put it in a file named "jquery" and try to import from "."...

STH: What that suggests is that naming something "." will give strange behavior.

AWB: It represents an example of the problem you're against.

EA: If you import a file, called "jquery" and that has a nested module named "util", should work the same if "util" is just in the same directory.

Mixed discussion, re: what could be solutions of

STH: Recapping... Yehuda and Erik brought up a concern about defining multiple top level modules and how to indicate that they are belong at the top level.

YK: another example, Ember relies on Handlebars...

STH: (whiteboard)

Solution?

1
2
3
4
module "/jquery" {
}
.
.

LH: One of the things the module system needs, to move forward, there should be 5-10 real world scenarios. Each scenario needs to be met and recorded, each time a change is made, it needs to be applied to each scenario to ensure that we're covering the needs.

AWB/YK/RW: Strongly agree.

STH: Scenarios

  1. Script tag, local file
  2. Script tag, cdn
  3. Inline

AWB: An over simplification

EF: Will always need to provide some kind of configuration, because in reality, files and libs have relevant version numbers.

YK: ...gives example for RSVP, Ember, Metamorph

EF: It should be clear how you link this name to a resource.

STH: Should be able to set up a loader initially and then "import" just works.

YK/STH: But we're not going to define the mechanism, because it's out of scope.

STH: Do you all understand why I don't think this committee should design a complete API for Loader?

EF: But it results in magic and Allen is talking about removing the magic.

STH: But that's configurable

EF: Configuring is not pleasant.

STH: System.fetch(...url)?

EF: Imagine if jQuery home page said: System.fetch(jquery); import {$} from jquery.

YK: We want a programmatic hook, but I want to say "import jquery" and I want to tell you where it is.

STH: This is easy to add, but I'm not sold. I will discuss this with Dave

YK: Is because you don't see the burden?

...The current proposal won't work when you want to use a CDN url and also have jQuery at the top level.

The primary issue:

1
import { jQuery } from "jquery";

Needs to have some mechanism by which we can configure WHERE "jquery" is, via URL.

STH: A possible solution?

1
2
3
Loader.configure([
[ "jquery", "file.js" ]
]);

EF: The original proposal, where the file is inferred by the name doesn't get us close to meeting the need.

BE: This is not design by committee, we really need user testing.

AWB: Are there people that are going to provide the specific scenarios that need to be met?

YK/EF/RW: (agree to work with Same and Dave)

STH: (slide 3)

Dropped Features

  • export =
  • export get/set

LH: Reminder to include the node use case in the scenario write ups.

STH: (slide 4)

Loader Semantics

  • import foo/bar => fetches "foo/bar.js"
  • import ./foo => relative to the file
  • WIP, specifying the details of loading
    • Ordering
    • Error
    • Hooks
  • New "rewrite" hook

EA: Q. re #1, relative to what?

STH/YK: document, document base

ARB: Are you sure about "relative to file" on the second?

YK: This would break concatenation

STH: Important for self-containment

YK: The Loader has to know enough about the system to find the correct thing

Mixed discussion.

LH: We need to drive this through with concrete examples and use those steer the development here. I don't think we're going to get anywhere here today.

STH: (returning to the slide) Specified the "rewrite" hook to see that you want jQuery, it will fetch the source, eval it and then rewrite into jQuery.

DC: ...Recalling the original discussion around modules and the agreement he made with Dave to withhold objection on the grounds that we'd agree with syntax later. That agreement hasn't been met. The discussion we had this morning indicates that it has failed to meet the requirements and should not hold up the rest of the specification. Suggest to remove from ES6

LH: As much as it would be great to deliver this, it's simply not ready and not nearly developed or concrete enough to continue forward with. We'd need a year to user test to get the best results from the feature. Need to understand and meet the needs.

BE: Library code can't dictate and may have to change, but that shouldn't block the feature.

STH: It's unfair to drop the feature when other features have behaved the same way and are still incomplete.

MM: To be fair, changes coming to proxy

STH: There is a great deal of completed work for this and with valuable feedback, we can still deliver. It's not fair to say "We're providing you with feedback, therefore you're not done".

BE: Yes, we need algorithms in the spec and user testing in time.

EA: Modules are the most important feature that we have to ship, but I agree with Doug that it might not be in time.

BE: One option is to move it to ES7

EA: From implementation, modules is the highest priority, but there is nothing to implement.

AWB: And much of the spec will rely on modules.

MM: Comparisons of the lexical scoped modules and the new string name modules

BE: ...Recalls the argument from 3 years ago. Notes that IIFE is NOT what module {} is and cannot be compared.

DC: I've spent years promoting this, but I can't see how it will make it.

AWB: We should aim for a "maximally minimal modules" proposal, that we can then move forward with to be successful.

WH: I like modules but also share Doug's skepticism about them being ready for ES6

ARB: I've been working on implementing modules for a year now and the changes you made in November invalidated most of that work, and they were not changes that I could agree with.

STH: To Clarify, we should not do a design along these lines AND you're concerned about the schedule.

ARB/AWB: Don't want to go back to ground zero.

LH: Start with a more robust design exercise, instead of trying to patch.

YK: To address the notion that the need has eroded, the systems that have been developed have actually put us in a worse position.

EA: Can we get champions of an alternate proposal? Andreas?

AWB: If we're going to defer or decouple modules from ES6, we need to know sooner, by the next meeting.

STH: I believe strongly that the state of the module system is being mis-perceived.

EA: I'm really confused by the current system and I feel like i used to understand the old module proposal well.

ARB: Same here.

LH: I don't think the current system is grounded or addresses the real problems that it needs to address. ...What we need to accomplish is much deeper. ...Prior art and experience dictates how the experience will be received and this doesn't seem to come up.

YK: I see modules as largely "desugaring" to two things that can be done with defining and loading in AMD, YUI etc.

LH: I'm not seeing all of the needs being met. My intuition is to say "this is a sugar for AMD", I think that could be a solid guiding principle.

YK: I agree that it's easier to see a path forward if it's largely the same thing as something that is already in use.

STH: re: possibly maximally minimal? There are too many details and requirements that are closer to surface, syntactically. It's harder to jettison the complicated parts to reduce the work, but also gives me confidence that the fundamental design is not changing as much as those in the room may belief. ...It aligned the programming model with the semantics of the Loader ...Believe it would be a big mistake not to do modules in ES6. ...Problematic that we're having this discussion without Dave present.

RW: We should break and table this until Dave can be present.

LH/DC/STH: Agree.

AWB: Concerned that we're on a path that won't include modules. If we're going to ship within a year of our target, modules won't make it.

STH: If we characterize it that way, then not many features are ready.

AWB: Agree.

RW: We should table this until the next meeting, where we are scheduled to actually discuss which features move forward and which don't. Additionally, Dave will be present.

STH: Of course over the next two months, Dave and I will be working with Allen to move modules into the spec.

EA: That could be the best thing.

RW: Likely to restore confidence if this can be achieved.

LH: Not convinced we have a design that is ready for the spec.

...Seeing this in spec may reify the unknown parts.

YK: If we don't have modules in ES6, certain parts will have to be respec'ed

AWB: I also believe a maximally minimal specification that can be used internally could happen.

LH: Of course, there is a status quo: Creating global names that define built ins

...Discussion re: Map, Set and WeakMap already in browsers.

JN: Steering to break. The point of record...

link Conclusion/Resolution

  • Cannot continue this discussion without Dave Herman
  • Continue work, the understanding the next meeting is decision time.
  • Work with committee members and community to develop concrete scenarios that must be met and addressed.

link New Scope of the Royalty-Free Task Group (TC39TG1)

...Discussion...

WH: Motion

MM: Seconded

DC: Seconded

link Conclusion/Resolution

We approve the new scope for RFTG Unanimously.

There was no specific agenda item here

ATTENTION: Mark, Waldemar, Allen... Please review these notes. I tried to keep up, but I'm not confident in the record.

MM: Want to maintain the option to defer Notification Proxies and Private Symbols—Defer to March?

...Mixed discussion about feature deferment.

WH: I agreed to classes based on private names inclusion, if there are no private names, then I can't agree to classes.

AWB: The objections have all been based on their interaction with Proxies

MM: I disagree, but don't want to deep dive.

WH: This is a bug in Proxy

AWB: Agree.

MM: I'd like to postpone a larger discussion until March.

AWB: (whiteboard)

1
var p = Proxy(target, handler);

Any operation you do on "p" is forwarded onto "target"...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var target = {
foo() {
if (someLookup(this)) {
}
}
};
target.foo();
p.foo();
// "this" in foo() is bound to the object
// SHOULD always be "target"
// EF: Could be multiple bindings for the same "target",
// so "this" should be "target"

AWB: Outlines issues with the MOP...

1
2
3
target.[[Get]]("foo");
P?
self.[[Get]]()

See image.

target has a method named foo, uses the "this" value,

(WH's summary) The point that Allen was demonstrating on the whiteboard was that, given:

1
2
var target = {foo() {if (someLookup(this)) {...}}};
var p = Proxy(target, {});

then: target.foo and p.foo are the same function object. target.foo() and p.foo() get different this values (target and p respectively).

Use cases:

  1. Virtual Object
  2. The target is not really the target, just a book keeping mechanism.
  3. Wouldn't need the target, despite need for invariant checks
  4. Nearly all functionality in the handler

  5. Membranes (also, "nosuch...")

  6. Caretaker

  7. Allows all through until revoked
  8. Nearly all functionality in target

AWB: A virtual object case... the target object is a captive object of each proxy, part of the implementation. Providing most of the functionality. The target never escapes. ...The case that doesn't cover that: the a proxy is being over laid on a pre-existing object.

YK/AWB: The case of defining an array-behaving-length object via a proxy on DefineOwnProperty works well. WH: Is the pseudo-array example a virtual object or caretaker pattern? AWB: Virtual object WH: Why did you classify it that way? It's implemented almost entirely in the target, with but one method in the handler.

MM: target.foo() and p.foo() by themselves mean the same? Yes. Are these still being spec'ed as a Reference Type? (base and a value).

AWB: When you evaluate p.foo(), The [[Get]] operation returns ? The [[Invoke]] operation returns ?

(TODO: Ask Allen to revisit)

MM: [[Get]] value [[Get]] base

AWB: In the spec, it's handled as a single operation... A property access and then an invocation... we can separate

YK: This matches my misunderstanding.

AWB: We can trace this to Notification Proxies

MM: Recounts issues

Bookkeeping with invariant enforcement lead to exposure of the target.

YK: I want create a virtual object and you want to create a caretaker, might not be able to do both.

MM: Have to do both.

Issues with the current list of traps that can be resolved with the addition of a new trap that addresses... ?

AWB: Recommends a "call method" trap to resolve

WH: Still not sure what the motivation is. The behavior of target.foo() and p.foo() getting different this values (target and p respectively) seems correct. Turning function dispatch into a fundamental operation rather than a composite of a property lookup and call won't accomplish much. It would affect p.foo(), but wouldn't affect p.foo.call(p, ...), and I very much don't want to introduce another gratuitous asymmetry between the two.

MM: In the same way that [[Get]] was designed to make a decision, "Call Method"... (Mark, need clarification )

WH: Not specific to Call Method, but any case where you have self-referential object (i.e. any place where you do p.foo(..., p, ...)).

AWB: Anything that involves implicit "this"

AWB: If want to control what's passed through, you'd use a p.foo.call, otherwise you'd use a wrapped function.

MM: The default probably should be the proxy and not the target

1
2
var q = Object.create( p );
q.foo();

MM: When you're inheriting from the Proxy, q is a normal object, does it have the property foo? it does not, recursive get on p and will get the proxy, q is the receiver.

WH: Call Method becomes useless...

MM: [q.foo] does the right [[Get]], q.foo(); the value of "this" is q

...On the target, a getter for "foo", the handler trap is empty, uses the default, the getter function for "foo". What?

AWB: Unsure,

MM: The handler is given the ability to make a decision, same for Call Method. In the absence of a trap, what does the default do? The default case, "this" should be "q".

...The default, the getter should be invoked for "q.foo" case

AWB: ...Recalls discussion with Tom, re: [[Put]] creating properties on wrong objects.

STH: Resteer the discussion...

link Conclusion/Resolution

Continue discussion offline.

MM: What we did with hasInstance, we should audit all of the traps and determine if we can replace with @@methods.

AWB: Applied similar approach in the spec.

link Class extends: Throw on non-constructor?

In July, we discussed what would happen when:

1
2
3
class Foo extends Object.prototype {
}

The decision of record is: Throw on non-constructor.

AWB: You may have class who's instances inherit on the instance side, not the class side.

LH: classes just simplify the Constructor pattern, and we should keep it that way.

RW: Can't you get the same semantics by omitting the super() call?

LH: No, you'll still get class-side.

...Discussion comes back around to throwing on non-constructor. It will also allow for future extension points by relaxing the RHS of extends.

LH/EA/RW/WH: In agreement.

link Conclusion/Resolution

Class extends throws on non-constructor (extends null is still valid)

link Map/Set comparator

(Presented by Allen Wirfs-Brock)

Issue: Allow Map or Set to have a custom comparator for set, get, has, delete

  • Current constructor signature

    • Map(iterator=undefined)
    • Set(iterator=undefined)
  • Proposed Signatures:

    • Map(iterator=undefined, comparator="default")
    • Set(iterator=undefined, comparator="default")

The Comparator Selector

  • comparator must be one of the following values
    • "default" // The default comparator is used
    • "==" // == is used
    • "===" // === is used
    • "is" // Object.is is used
  • The default comparator is the same as "Object.is" except that +0/-0 are considered equivalent and all NaN values are equivalent.
  • Other values produce a range error. In the future we might allow a user provided object or function.
  • Note that all the above comparators do object identity comparisons so map/set hash tables would identity based hashing (for objects) and as long as only the built-in map/set/weakmap hash tables are available ther is no need to expose the interlay maintained per object hash value
  • A future user defined comparator could be used for situations where there is a need to do nonidentity based comparison and ES code-level defined hash functions. Typically such comparisons/hasing would be based upon the values of the object properties. Such a comparator would probably have to expose both a comparison method and a hash method.

LH: Require a string value and throw on invalid

MM: happy with this proposal, any dissent?

WH: The comparators must be equivalence relations. Neither == nor === is an equivalence relation, with == breaking particularly badly. It's neither transitive, symmetric, nor reflexive. AWB: You'd simply have unfindable elements. WH: That might work for a multiset but not for something that claims to be a set. You could iterate through the keys and not be able to look up the corresponding elements. If you stick a NaN into such a map, you then couldn't delete it. AWB: Reduce the set of comparators to "is" and "default". WH: Rename "default" to "===" but keep its semantics (NaN's are equal, ±0 are not). AWB, most: Yes. YK: No. Maps should throw on NaN's. WH: Why? Why not throw on undefineds?

Conclusion/Resolution Consensus w/ comparators: "===" (currently default) and "is"

Signatures:

  • Map(iterator=undefined, comparator="===")
  • Set(iterator=undefined, comparator="===")

(Conversation continued, this resolution was discarded)

ARB: if we have a forth form of equality as "default", we should be honest, name it, and make it available separately

YK: Can we use "===" and disallow NaN as a key?

WH: No.

AWB: Why not?

Comparison of the "===" vs Object.is case, w/r to NaN, +0/-0

MM: Move Object.is to Math.is?

WH: No, it accepts non-numbers

WH: The longer we debate this, the more I want to just go with current implementations [that don't have a comparator parameter and always do the "is" semantics].

RW: +1

AWB: We should use this unnamed function as default, "default" is a fine name for it. If there is a demand, we can add it in the future.

EA: We can skip the name...

ARB: You might have circumstances where you do your comparison outside of the map.

MM: General comparator argument, are we happy with this considering a hypothetical future that allows arbitrary equivalence class?

WH: As long as it's an equivalence class, if you allow anything else, you run into trouble.

link Conclusion/Resolution

  • Map( iterator = undefined, comparator = undefined )
  • Set( iterator = undefined, comparator = undefined )

  • If the second argument is "is", use "Object.is"

  • Otherwise, use "==="
1
2
Map.defaultComparator( a, b )
Set.defaultComparator( a, b )

link Comprehensions/Generator Syntax

(Presented by Sam Tobin-Hochstadt)

Dave Herman's proposal: https://gist.github.com/b250d1fad15dbb5f77a5

Existing:

1
let array = [x for x of itr if x > 0];

switch to

1
let array = [for (x of itr) if (x>0) x]

BE: ...Recalling that the draft proposal is right-to-left, this proposal is left-to-right.

...Mixed discussion with reminders of current specification.

LH: Would like to also have a keyword identifier to start the expression, maybe yield

BE: no, that must mean the outer function, not comprehension in it, is a generator, and would yield a directly enclosing function* or throw a SyntaxError otherwise.

BE: also, comprehensions must be lightweight syntactically or there' s no point.

WH: Expresses surprise at existence of parenthesized comprehension syntax: (for (x of itr) if (x>0) x). This one returns an iterator? Somewhat unhappy that the base case doesn't work: [x] returns a one-element array, but (x) returns x, not a one-element iterator.

STH: This is only a syntactic change. We're not altering previously agreed semantics in any way.

link Conclusion/Resolution

All agree on RTL -> LTR change.

[WH: Noted a moment after meeting adjourned that this is not merely a syntactic change. We had let clauses to create intermediate temporaries in the old syntax but not in the new syntax — you can't do [for (x of y) let (z = ...) for (z of q) ...].]

Ecma/TC39 Meeting – Jan 30 2013

link January 30 2013 Meeting Notes

John Neumann (JN), Norbert Lindenberg (NL), Allen Wirfs-Brock (AWB), Rick Waldron (RW), Waldemar Horwat (WH), Tim Disney (TD), Eric Ferraiuolo (EF), Sam Tobin-Hochstadt (STH), Erik Arvidsson (EA), Brian Terlson (BT), Luke Hoban (LH), Matt Sweeney (MS), Doug Crockford (DC), Yehuda Katz (YK), Nebojša Ćirić (NC), Brendan Eich (BE), Andreas Rossberg (ARB)

link Function In Block Options

(Presented by Luke Hoban)

Option #1: No let and const in non-strict mode Option #2: Taking the breaking change, w/ evangelism Option #3: Hybrid semantics for function-in-block, that still maintained semantic alignment with let and const Option #4: let/const anywhere in scope changes FIB semantics.

LH: a combination of 1 & 3 might be the best path forward.

Option #3

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
function foo() {
bar();/// throw, extended TDZ
for (var i = 0; i < 10; i++ ) {
bar(); // throw, TDZ
let x = 10;
// semantics of function in block are as though...
// 1. let bar = function() {} were inserted
// at start of block
// 2. var bar = function() {} were inserted
// at start of function
// (1) accomplishes ES5 let/const semantics,
// (2) accomplishes compat
// These are combined with an extension of the TDZ rules
// to throw on accesses to let bound variables
// whose activation block has not et been created.
function bar() {
console.log(x);
}
bar(); // succeed
}
bar(); // throw, eTDZ
}

WH/ARB: if there is a let or const anywhere in the program, don't do this in sloppy mode?

LH: There is an option, if you have any let or const, then function block is ES6 semantics... But I don't know how we'd define this.

YK: I want to go on record that I don't support this kind of unrelated opt-in.

RW: This is a language level weak inference...

WH: Far less a concern than burning people for the next twenty years.

BE: It's not an opt-in, it's allowing the syntax to speak for itself.

Discussion re: ES6 static semantics to determine runtime semantics.

LH: Option #4 is a possibility

MM: For both strict and non-strict?

LH: Option #4 in sloppy mode and clean up in strict mode. ...Key thing to note: the extended TDZ.

AWB: Is it compatible semantics with whats observed on the web...

Discussion about compatibility of options

STH: Pick one whether it works with what we want to do later

AWB: What are the compatibility requirements?

Discussion re: the sanity of each implementation's semantics.

BE: Not sure any are worth rescuing in sloppy mode. Leaning towards strict mode to align the let, const and fix FIB semantics.

LH: (Presents: http://web.archive.org/web/20120513130620/http://whereswalden.com/2011/01/24/new-es5-strict-mode-requirement-function-statements-not-at-top-level-of-a-program-or-function-are-prohibited/)

Mixed Discussion centered around the intersection of implementation semantics. Need to avoid creating yet a new set of semantics that are outside of the intersection semantics.

Avoid specifying any of this in sloppy mode? BE, MM, ARB, WH agree.

LH: I still think there is something that we can do to make this work.

MM, BE: Avoid two identities for function declarations.

AWB: Reiterates proposal: Don't hoist the initialization of the function, initialize at the point of declaration.

STH: 1) define the semantics of let, const and FIB in sloppy mode and require special casing, 2) don't define let, const and FIB in sloppy mode. Define how the interact that's "mostly compatible with the intersection. Or we prevent them from interacting by ruling out sloppy mode.

BE: ES6 let in sloppy code makes FIB ES6 semantics

Option #2 will be rejected by implementors

Option #1 No let and const in non-strict mode

LH: Addresses compatibility concern, Forks the language.

Paths of teaching JavaScript will hinge on whether you include "use strict".

eg. Can't copy-paste code from blog post into script tag.

MM, WH: Would like a meta tag that makes all scripts and inline JS strict-mode.

LH: Recognizes the ease of copy/paste JavaScript for teaching purposed.

MM: The future will all be "use strict"

RW: In the last two days there has been two different blog posts focused on removing strictness from JavaScript.

YK: Even if you think strict mode is ok now, but still has low uptake. We're making it an obligation for new features which is too large of change.

Mixed discussion about the semantics and restrictions of strict mode.

Further discussion about how simple examples and teaching JS in the future will require "use strict". Recognizing the real consequences of copy/paste restrictions.

LH: Concerned that Option #1 will absorb ALL new things.

Options

Option #0: No new syntax in non-strict mode 0a. Truly no syntax (ARB) Not Alive 0b. Allow module, but nothing else 0c. Allow module and class, but nothing else 0d. Allow everything with a body, but nothing else (the body is implicitly strict) Not Alive

Option #1: No block scoping in non-strict mode No Support 1a. Preserves everything except let, const and FIB

Option #2: Taking the breaking change No Support

1
- (w/ evangelism)

Option #3: Hybrid semantics for function-in-block 3a. In both strict and non-strict No Support 3b. In only non-strict. Strict keeps ES6 block scope functions 3c. Absolute minimum intersection semantics supported in non-strict, else ES6 semantics

Option #4: let/const anywhere in scope changes FIB semantics

Option #5: No block scoping in ES6 Strong Pushback (after discussion)

(Note: "block scoping" means: let, const, class, FIB)

WH: Are the options listed about what we want to spec or what the implementations ought to do (leaving aside the question of whether or how the standard specs it)? LH: Here we're explicitly discussing what implementations should do. [general agreement that this is what we're discussing at this point.]

LH: We cannot do FIB with meaningful semantics in the face of let/const

AWB: If you didn't have FIB, are there still issues?

LH: No. ...To avoid any issues at all, the solution is Option #5.

RW: Does that also include "class"?

STH/LH: Option #3 is the counter point to Option #5.

LH: Option #5 is only legit if Option #3 is rejected.

BE: Option #5 means that class can only appear where functions can appear.

MM: (reiterates belief that one the experiment of extending ES6 features into sloppy mode has failed) ((Note to Rick: We repeatedly clarified that Dave's 1JS is not the extension of ES6 into sloppy mode. It is the earlier realization that we didn't need an additional mode switch, such as an ES6 pragma.))

AWB: Working towards balancing the future... future advantages of block scoping are so large that we should be willing to find a way to make them work.

BE, WH: The future is bigger then the past.

ARB: Wants #0 as cleanest and easiest path forward. (list updated)

BE: Option #0a is dead on arrival. (list updated)

AWB: Does #0d exclude rest and spread, destructuring? (list updated)

BE: Yes, Andreas and others discovered potential issues, probably not worth pushing.

...Yes, going with Option #0, changes the future

STH: One JS is about not having a switch to get new language features, eg. a language version etc.

RW: "use strict" is still a big red switch.

STH: Yes

BE: Committee opinion on #0d?

link 0d "not alive" (list updated)

Circular discussion about macrocodes caused by Option #1

YK: What about Option #4?

ARB: No.

AWB: Option #4 is an extension of Option #3, because it allows you to safely shift into supporting let and const.

ARB: Strongly dislike because it has a refactoring hazard.

LH: If you're in strict, you already get correct semantics. Option #4 only applies to non-strict mode.

ARB: Want as few component interactions as possible.

WH: This is the closest we can get in the face of web compatibility.

AWB: Proposes Option #3c...? In only the specific cases where a reference does not have a local declaration

WH:

AWB: Willing to throw out function declarations created in eval.

WH: (Whiteboard)

1
2
3
4
5
6
7
8
var f = ...
function a() {
if ( false ) {
function f() {}
}
f();
}

WH: What do we want this to do?

BE: In IE, the inner f hoists. In SpiderMonkey, no hoist. What should we do?

Option #3c: Absolute minimum intersection semantics supported in non-strict, else ES6 semantics.

BE: I think we can do #3c and Allen can make it work, concerned that Waldemar will poke holes and be unhappy.

WH: The above must call the outer f in strict mode. In non-strict mode we shouldn't specify what this does (it becomes a moot point if we continue to outlaw nested functions in non-strict mode). For compatibility we'd want to add an informative note stating that, if the implementation extends non-strict mode with nested functions, the similar program below calls the inner f:

1
2
3
4
5
6
7
8
var f = ...
function a() {
if ( true ) {
function f() {}
}
f();
}

...There is no support for #3a (list updated)

LH: #3b is the bridge between compatibility and progress.

AWB: #3c covers the minimum use cases for compatibility

WH: #3c and 4 are similar

LH: Still supporting #3b

(Break for Lunch)

LH: Summary of current discussion. Why is that people are concerned about any of the #3's?

ARB: A lot of time for the committee to spend on identifying the sloppy mode issues. Why introduce complexity for something "transitional"

LH: So, not really an argument against #3, but for #0

ARB: And not creating a more complicated language

AWB/EA: No.

AWB: [#3] Arguably no more complicated then [#0]

MM: (Uses "duplicate parameters in parameter lists with defaults" as example of adding complexity)

AWB/MM/WH: (Discussion around complexity implications)

AWB: Complexity that occurs in edge cases is not

LH: We can't argue complexity... Let's look at the trade off for long term goals of the language

BE: Can we get rid of Option #1?

Yes. Option #1: no support. (list updated)

LH: For those that support Option #0, If we couldn't get consensus on Option #0, what are the material arguments against Option #3?

BE: (Makes further case for the future friendliness of #0d)

LH: Reiterates the previous question...

BE: Option #3c could work really well

WH: If we go with #3c, there is no spec work, just implementors

AWB: Yes, there is spec work...

Discussion comparing the specifics of #3b & #3c

Support moving to #3c.

AWB: If sloppy mode, here is a compatibility issue.

MM/ARB: (Answering Luke's earlier question) If Option #0 is off the table, then there is no opposition to #3b or #3c.

Consensus

Allen will spec #3c static semantics with informative note for review, tentatively to fallback to #3b

BE: Make an error?

MM: Benefit to future implementors that want to be in conformance by making them errors?

BE: Refutes

MM: Retracts

AWB: Sloppy mode has let, const and class grammatically and semantics

Return to the bigger issue...

Reiterates Kevin Smith's proposal:

  1. No opt-in required for new syntax, except
  2. Except: No breaking changes to sloppy mode
  3. No grammar contortions (e.g. let) to support sloppy mode
  4. All new syntax forms with code bodies are implicit strict

BE: Appears to be stand between #0 and #3

MM: Still opposed to the let issue, by creating a potential hazard.

BE: At last meeting we agreed to break this... (whiteboard)

1
2
var let;
let[x] = y;

AWB: We discussed this last meeting and agreed.

MM: I changed my mind.

WH: This is actually a grammar issue, which means that you must be able to parse it before you know whether or not you're in strict mode.

MM: Reiterates concern about creating potential hazards

LH: If we want to add new syntax, we're going to encounter these issues no matter what "mode" we're in... Hinging new syntax the fact that a small window reserved a few keywords won't scale (let, const, etc).

AWB: There is a certain circularity in arguments that are fine with new features only in strict, but also fine with allowing a single conflicting

MM: Reiterates

WH: So the argument is that we're making "sloppy mode" too attractive?

MM: Yes, avoid linguistic screw-ups.

LH: A lot of us don't view as "screw-ups"

WH: strict mode is just too complicated for user land code with many scripts on one page.

MM: If we're going to continue to support "sloppy mode", we need to make any use of "let" as a variable an error (retro-active reserve?). Cites Safari experiment of "let", Firefox experiments with "let".

LH/BT: Get data on use of "let"

MM: I'm back to where I was previously... I don't care enough to argue anymore.

(Note: Previous discussion can be found here: https://github.com/rwldrn/tc39-notes/blob/master/es6/2012-11/nov-29.md#the-syntax-of-let)

LH: Option #0 is too short sighted and based on "luck"... There won't be another opportunity to retro-reserve words, as there was with Strict Mode

MM: Two scenarios:

  1. A breaking change that leaves the language in a better, more consistent state.
  2. A breaking change that mars the languages and creates something that you constantly need to be aware of...

LH: (anecdotal C# experience)

MM: Counter with sentiments re: language complexity.

AWB/WH: Appear to be converging...

MM: I won't block the let kludge

AWB: But we need to address the larger issue of features in non-strict mode

WH: If there are concrete concerns, I want them on the table, but I don't want to spend more time on abstract arguments.

ARB: Concrete issues have arisen

WH: What are they?

AWB: We expect to have concerns.

ARB: issues with destructuring in sloppy mode

AWB: We have a spec for this.

MM: A spec that special cases for these issues and pays an unnecessary complexity cost.

AWB: Reiterates the concern that user code will not want to "use strict"

EA: I don't want forked languages

ARB/MM: Too many small breaks add up, I want to avoid introducing new breaks.

AWB: Fundamentally two approaches:

  1. A discontinuity, resulting in multiple versions.
  2. A single version, evolves incrementally.

LH: (Insight regarding the effects of "mental forking")

WH/DC: (Discussion about the inline-script problem)

DC: Code has long been moving away from inline code and our goals shouldn't be to preserve that.

LH: But there are still multiple scripts

DC: Strict mode is the path forward, we can maintain ES3 and ES5 "sloppy mode", but ES5 "strict mode" is the way forward.

AWB/YK: Even the term "sloppy mode" is a pejorative.

DC/YK: (Discussion about the current state of strict mode)

WH/YK: We have data that 10% of uses aren't even being used correctly, where "use strict" isn't correctly in the prologue position.

YK: Worried that people will want to use new features, but simply won't understand the requirement "use strict"

DC: This is not hard

...Continued discussion.

LH: ...Interjects to resteer conversation

?: The fundamental disagreement is about whether we want to make a simpler spec for the future by basing new features on strict mode only.

WH: No, that's not the bone of contention. WH would also prefer to have a simpler strict-only spec for new features, but supports 3c/4 from earlier because getting into strict mode is too inconvenient. Today it's too awkward to get into strict mode in practice for web pages, although this may change in the future?. Too many (10%) web pages unknowingly get this wrong by putting a "use strict" somewhere other than the preamble.

MM: What do you see would need to happen to make strict mode convenient enough?

WH: Two requirements:

  1. Need a clear indication that a user's attempt to get into strict mode failed, such as having a use strict directive rather than overloading a string constant. It's obvious from the data that the bug that the strict mode directive doesn't go into strict mode if it's in the wrong place hits too many users.
  2. Need a way to declare that all scripts on a page are strict. That's out of our control, but this is a prerequisite to making strict mode convenient for multi-script pages (and WH is aware of the potential issues of scripts coming from different sources).

YK: Hopefully I've made it clear that the current state of strict mode tooling is at a significant disadvantage.

MM: I understand that we need to work with DOM spec writers to get means of making "global" strict mode a reality.

Revisiting past conversations that led from ES6 being "versioned", to being "strict mode" only, to being "one js".

LH: We did adopt One JS. There have been two concrete issues:

MM: Terminology: "one js"?

LH: As in, new features do not require "use strict" or a "version"... Recommend continuing in the default direction: Continue on the path we're taking.

MM: That is not the meaning of "one js" (Rick: It's really important that we not confuse this issue with 1JS.))

AWB: If we can't agree on a new position.

WH: Wants to hear from others...

RW: (big spiel about strict mode and new features)

EF: Agrees and supports default strict mode in modules. Not enough of a historic sample to say whether what size "switch" and how many "switches" to have will be idea. We only have one real sample so far, ES3 -> ES5. The new ES6 strict mode will only be the second.

RW: Agrees with Eric and supports strict bodies by default.

DC: Including class?

RW: Yes

YK: Not Arrows

MM: Agree, not on that boundary.

LH/MM: Closer to comfort if classes and modules have strict bodies.

MM: Agreed not to hold up consensus

YK/RW: No Arrows

link Conclusion/Resolution

Consensus on... Stay the course on spec development approach Class, Modules implicitly strict. Arrows not strict Sustaining our position on the handling of let ambiguities (Note: this is a local consensus)

MM: Declared as not holding up consensus, though not in agreement. I still think this is a terrible idea, but it looks like the best we can declare consensus on.

BE: (Out of band) I think that's a good consensus, arrows can't have intrinsic names (contrast with NFEs) so arguments.callee may be wanted, so arrows should not be strict-only.

link Static/Class Side Methods

(Presented by Yehuda Katz)

1
2
3
ClassElement:
MethodDefinition
"static" MethodDefinition

Full strawman here: http://wiki.ecmascript.org/doku.php?id=strawman:class_method_syntax

Supported by TypeScript, Continuum, etc.

link Conclusion/Resolution

Consensus in support of this proposal. (File spec update ticket)

link Revising The Array Subclassing "Kind" Issue

(Presented by Allen Wirfs-Brock)

Reiterates the issue at hand, illustrated here:

1
2
3
4
5
6
7
8
9
10
class V extends Array {
constructor(...args) {
super(...args);
}
}
var v, m;
v = new V(1,2,3, );
m = v.map(val => val * 2);
console.log( m instanceof V ); // false :(

If we extend...

Array.from( iterable ) => Array.from( iterable, mapFn )

1
2
3
4
5
6
7
8
// Add a "map" function to the class-side from method:
NodeList.from( nodelist, thing => thing );
// Turn an array into NodeList
NodeList.from( array, thing => thing );
// Turn an array of nodeNames into NodeList of nodes
NodeList.from( ["div"], node => document.createElement(node) );

MM: thisArg?

EF: It's possible to lose the context if you alias the ClassMethod

MM: For consistency purposes, add thisArg

link Conclusion/Resolution

Consensus on this proposal, with the addition of thisArg per Mark's request.

link 4.7 Fail-fast destructuring with ?-syntax for irrefutable opt-in

(Presented by Brendan Eich, Andreas Rossberg)

  1. No ToObject(RHS).
  2. Exception on missing property selected without a ?-suffix.
  3. ?-suffix allowed on any pattern, imputing undefined deeply instead of refuting.
  4. The ? is a separate lexeme from the : in long-hand patterns.

One entry point: https://mail.mozilla.org/pipermail/es-discuss/2013-January/027800.html

Allen argues cogently against (1) but endorses (2-4).

BE: (Whiteboard)

1
var { toLocaleString, split } = "";

The only ones that are affected: string, number, boolean.

ARB: implicit conversion is future-hostile to pattern matching.

STH: (Whiteboard) Example of pattern matching.

switch ("x") { match {}: return 1; match _: return 2; }

You do not want implicit conversions in pattern matching, which would make this take the first branch. Similarly, if we allow matching literal strings.

ARB: For consistency, would imply conversions for other pattern types, too (e.g. literals). No issue technically, but insane from practical perspective

BE: Reiterates... In the case where

There is no history of primitives being used on the RHS, so there is no need to support any kind of implicit ToObject.

"You say po-tah-to and that doesn't change tomato".

...

MM: Question about cover grammar.

AWB: The grammar is spec'ed and in the latest draft.

...

YK: Wants irrefutable destructuring, ie.

1
2
3
4
5
function Foo(options) {
var { foo } = options;
// if foo is not a property of options,
// just give me "foo" that's undefined
}

BE: Use the ?

1
2
3
function Foo(options) {
var { foo }? = options;
}

WH: Is ? deep or shallow? i.e. what should the following do var { p, r }? = q; ? answered:

  • if q is null: p and r are undefined
  • if q is {r: 7}: p is undefined, r is 7. WH: That means that ? is deep.

WH: Given the discussion above [not recorded in these notes?] about doing primitive pattern matching assertions in the future, just curious what the semantics of ? ought to be so that it would interact well with such assertions. Example: What should ? do in these cases? let {p, q}? = {p:17} Here p gets 17 and q gets undefined because ? distributes down. But then what happens when we get value assertions? Without getting into syntax details, assume that x: true is a value assertion that fails unless property x exists and has the value true. let {p: {x: true}}? = null let {p: {x: true}}? = {q: null} let {p: {x: true}}? = {p: null} let {p: {x: true}}? = {p: {}}

Mixed Discussion and debate, re: pattern matching examples.

BE: Return to... Waldemar, are you satisfied with ? for irrefutable destructuring?

WH: The question, is there a purpose of having a shallow "?".

BE: The common case is implied deep "?"

AWB: More comfortable if there was a strawman of what the full language would be like in the future.

BE: Dave has a proposal written, but we need to capture the latest developments.

ARB will work out new pattern matching strawman based on proposed ideas.

BE: (to YK) have we assuaged your concerns about irrefutable destructuring?

YK: yes, as long as "?"

link Conclusion/Resolution

  1. No implicit ToObject(RHS). consensus
  2. Exception on missing property selected without a ?-suffix. consensus
  3. ?-suffix allowed on any pattern, imputing undefined deeply instead of refuting. consensus
  4. The ? is a separate lexeme from the : in long-hand patterns. consensus

"?" in combination with default values, syntax error.

1
{ a? = 42 } // throws.

If you write a "?" on a larger structure, you can have default values anywhere inside.

1
{ a: b = 42 }? = undefined

WH: Where should the ? go syntactically? In particular, should we have {p: q?}, {p:? q}, or {p?: q}

STH:

1
2
3
4
let { p }? = null; // p bound to undefined
let { p? } = null; // throws
let { p: q }? = null; // q bound to undefined
let { p?: q } = null; // throws

WH: This is quite close to conflicting with the ternary operator but can't think of any obvious ambiguities as long as the ? in patterns is always followed by =, }, comma, or :.

Dependent on patterns being fail-fast: ARB: Cute idea: Make undefined into a keyword that is also a pattern that matches only the undefined value. This way existing definitions such as var undefined; and var undefined = ; and (function (undefined){})() will work, but var undefined = 42; will fail.

General Agreement

link 4.11 Name Property of Functions

(Presented by Brendan Eich, with additions by Brandon Benvie) http://wiki.ecmascript.org/doku.php?id=strawman:name_property_of_functions

BE: Early approaches...

1
2
function f() {}
f.name == "f";

BE: (from Brandon Benvie's proposal)

Justification: the usefulness of the name of function is not just for debugging. It is useful in the same ways that property names as strings are such as dispatching by name or assigning by name.

  1. Every function has an own "name" property, and this property is always a string (unless the user specifically decides to violate this norm).
  2. This name property is initialized with the value that makes sense from static semantics.
  3. Allow predefined names to be altered in cases where it makes sense.

Semantics:

The baseline descriptor for every function is the 'name' property defined as { value: "", writable: true, enumerable: false, configurable: false }

For FunctionDeclarations, named FunctionExpressions, MethodDefinitions, or accessor Properties then the function's "name" property is set to the given identifier.

In the case of the constructor method of classes, the class name is used instead.

In the case of accessors, "get" or "set" is included.

The "name" property is set to non-writable.

Function.prototype's name is also non-writable.

Anonymous FunctionExpressions and ArrowFunctionExpressions assigned in a VariableDeclaration or ObjectExpression are given the name of the variable or property they are assigned to and the name remains writable.

Anonymous ClassExpressions follow the same semantics, with the name being used for the constructor method.

Whenever a function's name is defined by a Symbol instead of a regular identifier then the name is the result of ToString(symbol).

The name property should (probably) not have any reflection on the output of Function.prototype.toString.

MM: Having the result of toString be immutable is important, agree with proposal semantics. ...Security leakage from the name property, is the type of information that the toString method leaks. No integrity issue, just a confidentially issue.

BE: We could make Function.prototype.toString be a getter that can be removed.

MM: This is one of the aspects that I gave up attempts to secure, and it's never been an issue.

BE: Make it writable?

WH/MM/AWB/YK: Writable.

WH: There is a slight advantage to making it non-writable. Otherwise when writing it to change the function name, you'd expect it to change the result of "toString".

Discussion re: history of Function.prototype.toString result.

MM: Explain the divergence, toString is a reflection of the source code itself and the name is how you'd like to identify the function within tools.

link Conclusion/Resolution

Consensus on the proposal, with { writable: true }

link 4.12 Typed Arrays Update

(Presented by Allen Wirfs-Brock)

Slides (pdf): http://wiki.ecmascript.org/lib/exe/fetch.php?id=meetings%3Ameeting_jan_29_2013&cache=cache&media=meetings:typedarray_status.pdf

AWB: We're absorbing control of the TypedArray specification, previously authored by Khronos.

W3C has dependencies on the Khronos spec.

This specification will not include any parts of the Khronos spec, but will be compatible.

JN: We need to make sure we're not violating anyone's IPR, Istvan can inquire.

EA: We can have Ken (Kenneth Russell, Google) review the drafts.

LH: Short term, the editors need to understand what's going on and there is no push back. The standards organizations need to know that we're now working on this specification. Agreement

AWB: (Proceeds to technical presentation)

Integrate into ES Spec

  • ES spec conventions and semantics not WebIDL
    • Khronos spec not necessarily tracking WebIDL
    • eg. instanceof
  • Lot's of implementation differences among browsers at MOP level to straighten out
  • TypedArrays are subclassable

LH: TypedArray implementations are incompatible in the same way that all DOM implementations are incompatible, because WebIDL is not implemented compatibly.

Max Length

  • Currently Khronos spec's all lengths as Uint32
  • Not future friendly, especially for byte sussed element arrays
    • eg. a Uint8Array might map to a large real memory-mapped buffer bigger then 4GB.

LH/AWB: Seems that WebIDL is the cause of this constraint.

AWB: I'm going to spec the max length at Int, not Uint32

LH: Should record the deltas

Khronos/W3C TypedArray Objects (Diagram)

AWB: 9 prototype objects, 54 distinct method/get accessor functions per Realm.

MM: How did we get 9?

LH: UintClampedArray, which used to be CanvasPixelArray

Prototype Hierarchy Factoring (Diagram)

AWB: 10 Prototype objects, 6 distinct method/get accessor functions per Realm.

link 10, TypedArray.prototype

  • [ BYTES_PER_ELEMENT: int abstract ]
  • set() void
  • subarray() void
  • byteLength() int get
  • byteOffset() int get
  • buffer() Object get
  • length() long get

Int8Array (BYTES_PER_ELEMENT int=1), Int32Array (BYTES_PER_ELEMENT int=4), Uint8Array (BYTES_PER_ELEMENT int=8), Uint32Array (BYTES_PER_ELEMENT int=4), Float32Array (BYTES_PER_ELEMENT int=4), Float64Array (BYTES_PER_ELEMENT int=8), Int16Array (BYTES_PER_ELEMENT int=1), Uint16Array (BYTES_PER_ELEMENT int=1), Uint8ClampedArray

MM: A Uint1Array or BooleanArray, where each element is one bit.

TypedArrays act like fixed length, numeric element JS Arrays

  • So why not even better Array integration?
  • Class methods?
    • TypedArray.of
    • TypedArray.from
  • TypedArrays should be iterables?
    • @@iterator
    • keys
    • values
    • entries

Even Better Array Integration

  • Other Array.prototype methods that will work just fine on TypedArrays
    • toString, toLocaleString, concat, join, reverse, slice, sort, indexOf, lastIndexof, every, some, forEach, map, filter, reduce, reduceRight
  • Only 5 Array.prototype methods won't work with TypedArrays
    • push, pop, shift, unshift, splice

Add Array methods to TypedArray (Diagram)

WH: Are TypedArrays spread by Array.prototype.concat and ...?

LH: TypedArrays are a targeted tool for byte level programming. ...Doesn't think that the generic, higher-order Array APIs should be exposed on TypedArray

WH: [Repeats question]

?: TypedArrays are not exotic arrays so don't get spread by Array.prototype.concat and ... . On the other hand, TypedArray.prototype.concat will spread TypedArrays only.

WH: OK.

[Debate about whether TypedArrays need the suite of Array methods]

YK: Using TypedArrays would be a pain if they didn't already offer these array operations.

WH: It would be too confusing to have gratuitously different APIs for two array-like things in the language.

RW: Agree.

AWB: My understanding was that we were absorbing these in order to provide the capabilities that the language provides

STH/WH/YK/RW/EA: Strong Agreement.

LH: Agree that there are some use-cases for these, but may not be our place to define these methods

YK: (channelling Alex Russell) The reason we're taking this on, is because it's our responsibility to correct "yet another array like thing that isn't an array"

RW: Agrees.

LH: Implementation and performance issue concerns?

WH: This is not a lot of work for implementations, and implementations (as opposed to users) are clearly in the better place to implement these efficiently.

[STH: After the end of the official meeting, there was some discussion as to why Typed Arrays wouldn't just become genuine Arrays. This would mean that they'd have all the Array methods, some of which would throw on use (those that change length). This needs discussion at a future meeting.]

link Conclusion/Resolution

Move forward with the plan presented.