November 19, 2013 Meeting Notes

# Rick Waldron (10 years ago)

Nov 19 Meeting Notes

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

Welcome

JN: (Introductions)

DC: (Logistics)

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

Unanimous approval

JN: Approval of Sept Minutes?

Unanimous approval

ES6 Status

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

...Function.prototype.toString still needs attention

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

AWB:

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

BE: We agreed on semantics

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

YK: This is the consensus I recall

AWB:

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

YK: (confirms that it's complete)

AWB: Yes, but not yet in the spec.

  • Standard Modules deferred.

(TVC dials in)

4.4 Finalizing the Proxy API for ES6

(Presented by Tom Van Cutsem)

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

  • hasOwn()
  • invoke()

WH:

AWB: Looked for traps for call

BE: Total traps?

AWB: Now 14 traps.

BE: Cool. Not including hasOwn()?

AWB: Not including

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

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

WH: Still not reliable, even with invoke.

YK: So what are the cases?

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

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

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

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

AWB: yes.

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

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

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

AWB: Not really a "class"

AR: You create new ones?

AWB: No prototype

AR: Gives an instance, why not "new"

AWB: Would need an @@create

YK: Then shouldn't be capitalized

BE: We can do "proxy"

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

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

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

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

WH: Proxy is not a class.

YK: ...But has allocation

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

AWB: Must create a special constructor

TVC: @@create doesn't make sense here

BE: Is Proxy a class?

(General: no)

TVC:

DS: What is typeof and instanceof

AWB/BE: object

BE: Capital P

AWB: Ca???

DS: Whatever Proxy creates?

BE: That depends on what is created.

DS: By default?

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

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

BE: (int64 example)

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

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

[ inaudible ]

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

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

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

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

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

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

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

AR: agree. Making it exotic is good.

TVC: what's the summary?

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

EA: Do we REQUIRE "new"?

WH: what does Map do without new?

EA: Throws

BE: Why are we requiring new again?

RW: Needed for subclassing

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

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

AR/RW: agree

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

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

AWB: agree

JM: Removing the throw might change control flows?

BE: non-issue, rare.

Consensus/Resolution

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

ES6 Status (cont)

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

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

AWB: No one has stepped up, deferred to ES7

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

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

AWB: I can live without this section

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

...

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

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

AWB: Yes.

MM: The loader stuff as well?

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

4.1 Review Latest Specification Draft

(Allen Wirfs-Brock)

(request slides)

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

Discussion re: default param aliasing

BE: (tries aliasing on SM)

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

BE: Do we want three types of arguments?

YK: It's not really three types

...

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

YK:

MM: Adopt some semantics where aliasing

BE: Deep aliasing of destructured parameters is bad

AR: Walk back poisoning entirely?

MM: No.

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

AWB: Back to scheduling

BE: If there is destructuring, no deep aliasing.

WH: Easier to explain if the rules are compositional.

Consensus/Resolution

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

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

4.3 Should 'arguments' in an arrow body be from nearest outer defining

scope, or early error? (Brendan Eich)

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

WH: let arguments = ...?

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

questions about conditionally reserved words

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

MM: (whiteboard)

function f() {
var arguments = 1;

[3, 2, 1].forEach(v => v + arguments);
}

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

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

Consensus/Resolution

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

AWB/BE: yield just follows the rules for yield

MM: (whiteboard)

function foo() {
  var yield = 8;
  return function * bar() {
    yield baz();

    function baz() {
      return yield;
    }
  }
}

var f = foo();

console.log(f().next().value);

// 8

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

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

MM: Cannot statically repeat properties in object literals

AWB: This isn't a static object literal

MM: ...

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

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

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

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

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

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

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

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

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

MM: that wasn't the question

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

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

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

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

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

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

Consensus/Resolution

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

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

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

baz = ...
function foo() {
  var yield = 8;
  return function * bar() {
    yield
        baz
    yield
        * baz
    yield (baz) => yield * baz
   }
}

[Almost nobody guessed all of these right.]

Current answer, with all optional semicolons inserted:

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

Consensus/Resolution

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

LineTerminator here] * [Lexical goal InputElementRegexp]`

Class/optional yield arg ambiguity

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

Proposed solutions:

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

BE: (whiteboard)

// Don't want to require these parens:
class C extends (A + B) {

}

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

... lost track here...

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

a = b * (yield c)

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

Consensus/Resolution

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

Cross-Realm Symbol Registration

(need slide)

AWB:

// key is a string
Symbol.for(key) => aSymbol // creates a new Symbol if key is not registered

Symbol.keyFor(aSymbol) => key
  • Where for all strings S: Symbol.keyFor(Symbol.for(S)) === S
  • the use case for Symbol.keyFor is serialization

Revisiting discussion from last meeting, re: Symbol.

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

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

DS: Is there direct correspondance between Symbol and toString?

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

AWB: is this good?

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

undefined

Consensus/Resolution

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

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

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

Introduce a Prototype object that contains sloppy arguments object

@@iterator function?

Discussion re:

  • arguments prototype
  • arguments.prototype.constructor

AWB/MM: instanceof is generally misused

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

MM: Issues are with consistency.

BE: (whiteboard)

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

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

(meta discussion)

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

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

AWB/MM: (discussion re:

Consensus/Resolution

...?

Conventions for ignore over-ride of @@iterator

MM: Why is this a spec issue?

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

BE: Use undefined, not "falsey"

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

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

AWB: Happy with undefined.

Consensus/Resolution

  • Just use undefined

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

See: harmony:function_name_property

AWB: What about anonymous function expressions?

RW: No name is made

AWB: What about bound anonymous function expressions?

RW: Same, no name.

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

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

Consensus/Resolution

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

9 ECMA 404 W3C TAG / TPAC report

(Alex Russell)

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

WH/MM: what does that mean?

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

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

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

AR: (proposal to work together)

STH: 3 levels.

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

Consensus/Resolution

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

4.9 Reconsidering Object.is

(Dave Herman)

DH: Object.is might be a mistake

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

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

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

MM, WH: Multiple NaNs are not visible in JavaScript

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

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

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

[ discussion ]

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

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

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

More discussion re: IEEE NaN

Consensus/Resolution

  • Status Quo
# Rick Waldron (10 years ago)

Nov 20 Meeting Notes

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

Report from the Ecma Secretariat (CC Report)

(Istvan Sebestyen)

Status of the TC39 RFTG

January 2014 Meeting deadline

4.2 Clarification of the interaction of unicode escapes and

identification syntax (Waldemar Horwat)

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

var f\u1234o = 17;

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

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

\u0069f(x===15)

// if(x===15)


There also was a bit confusion about whether escape sequences can occur in
regexp flags, even though the grammar never allowed them there either:

/abc/\u...

// unicode for the flags

AWB: Things that came up in ES5:

  • can you declare a variable that has the same unicode escape sequence as a keyword?
var f\u0

  • introduced in ES5:
// allow
foo.for()

ie. Identifier vs IdentifierName

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

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

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

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

AWB: Agree there is ambiguity

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

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

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

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

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

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

MM: This solves Sam's static code case

BE: No escape processing upstream?

WH: (agreeing)

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

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

Consensus/Resolution

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

Performance impact of Tail Calls

(Brian Terlson)

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

YK/AWB: Any examples?

BT: Stack frame manipulation

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

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

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

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

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

BE: Will have someone work on this for SpiderMonkey

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

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

Consensus/Resolution

  • Share implementation experience

super and object literals

(Allen Wirfs-Brock)

(needs slides)

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

Object.mixin(obj, ???);

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

Object.mixin(obj, {
  toString() {
    return `mixed(super.toString())`;
  }
});

BE: are we asking to allow super anywhere?

MM: We're not adding a restriction?

AWB: No, removing.

MM: Strictly a simplification.

Discussion re: Object.mixin

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

AWB: Allow super in concise methods

EA: All object literals?

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

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

Clarification of Object.mixin capabilities.

MM: (has issue with the naming)

AWB: Let's defer discussion of naming.

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

MM: Refactoring hazard

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

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

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

AWB: Yes.

MM: (whiteboard)


{ foo() {}, ... }

// vs

{ foo: function() {}, ... }

// vs

{ foo: (function() { return function () {}; })(), ... }

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

function f() { super.foo(); }

Object.mixin(o, {
  f: f
});

o.f !== f;

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

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

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

AWB: Alternatives are always clone or never.

DS: All methods should be copied to avoid the distinction

YK: Don't copy exandos?

EA: Happy to go back to Object.defineMethod

YK: Still need to decide if it copies expandos

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

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

AWB: There are many operations like this

EA: No different from Function.prototype.bind

MM: What happens when the method is a Proxy?

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

MM: A Proxy whose target is a function?

AWB: It's not an ordinary ECMAScript function

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

  • Security
  • Transparency

Discussion about Security vs. Transparency

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

MM: fail?

DH: This is shocking.

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

EA: (whiteboard)

Function.prototype.bindSuper

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

YK: Change bind?

DH: Can't change bind, varargs

Mixed discussion re: home binding.

AWB: Expose the home binding via trap?

DH: trap makes sense to me

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

AWB: yes

MM: Don't like that

AWB: Another way

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

AWB: There could be a super call trap

YK: Any objects to bindSuper?

DH: No idea what this means.

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

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

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

changing this and super is a two step change:

function f() { super.foo(this); }

var o = {
  foo(target) {

  }
}
(fill in later

DH: bindSuper is the max/min of define

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

on a bound function?

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

AWB: This is a "clone function"

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

...

AWB: you'll need to bindSuper, then bind

AWB: If you want it to work in either direction

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

?: Want bind and bindSuper to commute

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

?: You can already rebind this in a bound function

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

DH: (whiteboard)

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

bindSuper().bind() -> OK.

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

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

withSuper, bindSuper?

bindSuper(obj[, ...])

BN: what does super.valueOf() return?

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

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

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

Consensus/Resolution

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

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

Dave, please review the details above.

Reconsidering the Map custom comparator API

(Dave Herman)

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

Can we just get rid of this argument?

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

MM: (gives memoization example)

DH: This can be addressed in ES7

Discussion re: -0/+0 difference.

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

Consensus/Resolution

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

Math.hypot() and precision

(Dave Herman)

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

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

BE/DH: He's not here.

Referring to IEEE 754

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

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

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

WH: What does greatly matter is not overflowing for values > sqrt(largest

finite double). What does hypot(1e200, 1e210) do? BE (runs it on bleeding edge Firefox): About 1e210 WH: Good. We do want to avoid the intermediate overflow that would turn this into +?.

[ more discussion ]

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

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

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

Consensus/Resolution

  • Brendan to propose replacement for last two steps.

4.10 Generator arrow function syntax

(Brendan Eich)

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

(whiteboard)

// current
x => x * x;
(...) => { statements }
(...) => ( expr )

// proposed generator arrows...

// Irregular
() =*>

// Hostile to ! (async function)
() => * { ...yield... }

// Not good
() => * (yield a, yield b)

// Ok if 1 token
x *=> x * x;

// Bad (ASI)
*() => ...

// Hostile to !
(x) =* {...}

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

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

prefer those characters anyway.

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

BE/WH: No

DH: Recalls implied generator (yield presense) footgun

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

Consensus/Resolution

  • No addition, revisit for ES7

for-let

(Brian Terlson)

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

MM: Consensus?

RW: recalling the consensus from yahoo 2012

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

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

AWB: no definitive outcome... no satisfactory solutions

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

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

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

(discussion about binding per iteration)

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

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

(yes)

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

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

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

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

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

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

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

BE: FWIW, Dart has the same semantics.

void main() {
  foo(fun) {
    print('pre');
    print(fun());
  }
  for (var i = 0, inc = () => i++, j = foo(inc); i < 5; inc = () => i++) {
    print(i);
    inc();
  }
}

outputs

pre
0
1
2
3
4

Consensus/Resolution

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

5 Post ES6 Spec Process.

(Rafael Weinstein)

Train model.

Consensus/Resolution

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

Ordering of scheduling of microtasks

BE: FIFO

AWB: In the ES6 we need to say something.

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

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

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

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

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

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

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

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

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

Consensus/Resolution

  • ES6 spec needs to spec that Promises are serviced in a FIFO queue
  • Other non ES6 tasks might be interleaved arbitrarily
  • Interleaving of the Promise queue by other non ES6 operations
# Rick Waldron (10 years ago)

Nov 21 Meeting Notes

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

Follow Up on IETF JSON WG Communication document

(review)

Conclusion/Resolution

  • Unanimous consent

4.5 Modules

(Dave Herman, Sam Tobin-Hochstadt)

(request slides)

(fighting Google Hangouts for fun and profit)

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

End-to-End Draft Done:

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

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

EA: is there a license on this?

DH: no, but we'll add one.

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

AR: can you add a license today?

ARB: how are these files related to each other?

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

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

ES6 Draft

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

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

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

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

DH: wanted to talk a bit about the last bits of the semantic cleanups. The distinction between scripts and modules and the browser integration: <script async> was a way to allow you to use the module system at the top

level. This creates 3 global non-terminals. I say you dont' need <script async>.

Clean Ups

  • Scripts and Modules

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

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

  • <script async> was a non-start anyway

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

AR: no, we can fix <script async>

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

DH: <module> instead. A nicer path forward for the web. Automatic async

semantics. More concise than <script async>.

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

AR: this has real security issues.

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

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

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

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

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

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

<module> is a better 1JS

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

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

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

and move to <module> later

(some agreement)

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

these is likely to work

AR: agree.

Alternatives:

  • script module
  • script type="module"

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

<module>

var foo = 1;
</module>

<script>

foo; // undefined.
</script>

DH: Recapping the concatenation story.

(didn't we all do this before?)

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

STH: to address issues with <script async>, we need a separate entry

point. Any of the others listed here address the use cases brought up that <script async> addresses.

WH:now you have 3 things

(emphatic disagreement)

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

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

ARB: you still need the lexical contour, no?

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

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

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

ARB: Multiple module elements?

AR: Document order

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

AR: you need both.

YK: a sync attr seems fine.

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

BE: partial progress if possible

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

Loader API


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

address -> where to find this

source -> the source text

WH: what's fetch for?

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

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

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

Core API

// Loader API
// Promise<void>

l.load(name[, opts]);

// Promise<void>

l.define(name, src[, opts]);

// Promise<Module>

l.module(src[, opts]);

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

DH: Yes

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

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

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

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

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

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

EA: I'm worried about CSP.

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

DH: the registry API

// Registry API, methods on a Loader instance
l.get(name)    // Module?
l.set(name, m) // void
l.has(name)    // boolean
l.keys()       // Iter<string>

l.values()     // Iter<Module>

l.entries()    // Iter<[string, Module]>

MM: delete?

BE/RW: size property?

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

DH: you might astonish a running system

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

YK: I can imagine delete for security purposes

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

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

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

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

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

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

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

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

DH: You can't.

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

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

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

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

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

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

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

STH: (explains pollyfill)

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

DH: We have handling

EF: Do yo have slides for all the exceptions?

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

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

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

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

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

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

(discussion of observability)

BE: Let's take

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

DH: A built in loader called "System"

Decoupling Realms from Loaders

(smells)

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

Realms: Globals, Intrinsics, Eval Hooks

(facts)

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

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

Realm API

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

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

gist.github.com/dherman/7568885

``js let r = new Realm({ ... });

r.global.myGlobal = 17;

r.eval(...);




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

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


Seperable From Loader API

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


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

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

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


Realm API

```js
let realm = new Realm({
eval: ...,
Function: ...
}, function(builtins) {

  // global object starts empty
  // populate with standard builtins

  mixin(this.global, builtins);
});

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

EA: What happens when you omit it.

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

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

DH: Yes

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

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

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

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

RW: agree

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

EA/RW/DH: yes

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

(summarize change)

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

WH: What does the init provide?

DH: Allows you to whitelist what goes into your realm

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

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

Indirect Eval

let caja = new Realm({
indirectEval: function(args) {
    return anything
}
});

caja.eval(`
  (0, eval)("1 + 2")
`);

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

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

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

Direct Eval


let caja = new Realm({
  eval: {
    direct: {
      translate: (s) => { ... }
    }
  }
});

caja.eval(`{ let tmp = f();
             eval("tmp") }`);

Direct Eval


let caja = new Realm({
  eval: {
    direct: {
      fallback: (f, ...rest) => { ... }
    }
  }
});

caja.eval(`{ let tmp = f();
             eval("tmp") }`);

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

Function

let caja = new Realm({
  Function: (args, body) => { ... }
});

caja.eval(`
  Function("x", "return x + 1")
`);

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

STH: Explains the issues the exist with toString.

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

DH:

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

Function*

let caja = new Realm({
  Function: (args, body, prefix) => { ... }
});

caja.eval(`
  (function*().constructor("x", "return  x + 1")
`);

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

DS: concern for changes in semantics of

discussion re: eval of source code

DH: Returning source code is the more conservative

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

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

DH: two place you can reach the function constructor

  • Function global
  • Function.prototype.constructor

If you mutate Function.prototype.constructor

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

MM: This strategy has been field tested in SES

STH: Function.prototype.proto?

BT: Object.prototype

Realm API

let r = new Realm({
  eval: {
    indirect,
    direct: {
      translate, fallback
    }
  },
  Function
});

DH: A compiler for ES7 -> ES6. The compiler has some static source its

carrying around and comes to:

|-
|-
|-
eval(x)

And contains source:

{t1, t2, t3}

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

...
translate: function(s, src) {
  return compile(s, src);
}

fallback: function(f, ...rest) {
  return f(...rest);
}

WH: Fallback needs a this binding to handle cases with 'with' such as this one: a.eval = <something user-defined>

with (a) { eval(b) }

[ agreed ]

Cross-Domain Modules

  • browser loader should allow cross-domain loads
  • ServiceWorker requires cross-domain sources (XHR) and sinks (<img>, <script>, etc)
  • Browser's System.define should be a sink
  • No Problem: type of src parameter unconstrained in ES Semantics—polymorphism to the rescue
  • IOW each loader determines for itself what types are allowed for source

Streaming Modules

  • Might want to support streaming I/O in the future

  • Polymorphism allows admitting stream objects for .define and .module in future

YK: We've built a layer under the new constructs and CSP can work at that level: loader.eval, etc. A small core that we can build on top of.

Conclusion/Resolution

Realm constructor semantics changes:

  • changing "eval" to:
    • directEval
    • indirectEval
  • Remove "Function" hook
  • no callback, default environment with all the builtins
  • w/ callback, object with null [[Prototype]]
  • fold callback into first argument as option, eg. init: function(...) { }
  • "fallback" hook needs an additional first argument: this binding

Dave and Allen, follow up on:

AWB: Not all intrinsics are named?

DH: Yes. Don't need to be hookable, create a new Realm and get the intrinsics.

AWB: Do you only have to define the constructor of the intrinsic? Wire up first?

DH: Don't think those things need ot be customizable. We can extend the optional named parameters of the Realm constructor in a compatible way.

... Can fully customize the relationship between a Loader and Realm.

EA: Does modules have a hard dependency on Realms?

DH: no

AR: Seems like it's adding?

DH: Nothing new, we're just defining what was there.

AWB: Prioritize?

DH: Modules, Module loader first. Realms later.

STH: (explains that Module Loader can't be deferred, needed by browsers)

AWB: Realm seems very essential...

DH: Not necessary, don't put off the Loader API

ARB: What is the confidence level of this spec?

AR/DH: Very confident, but assume there are small bugs to address.

AWB: Very excited, feel like we've finally gotten it.

MM: Really like this, but would like to attempt reimplement SES on top of this and Realms API

ARB: (likes Realms as well)

STH: re: confidence in design... Dave, Yehuda, Jason and I have made revisions for a few cases:

  • making sure everything held together at the lowest level
  • have addressed all of the use cases that were necessary

DH: No more use cases, no more churn. There will be bugs, but we will discover these during implementation and address accordingly.

ARB: Happy with the design now, this is great. I agree that there wont be major changes anymore. Realistically no way to know if the spec is spec'ing what we think it is, until we get to it. What damage would it cause if we defer this?

AR: Alot

DH: Massive

BE: You'll lose momentum and gain a perceived failure hazard.

DH: JS Community will walk away.

ARB: is this all true?

YK/AR/RW: Yes.

Discussion about time line of ES6 implementation

(break)

4.6 The global scope contour

(Dave Herman)

Relevant:

rwaldron/tc39-notes/blob/master/es6/2012-07/july-25.md#scoping-rules-for-global-lexical-declaration

rwaldron/tc39-notes/blob/master/es6/2012-09/sept-19.md#global-scope-revisit

DH: I want to make the case that we don't think we need a second global scope contour.

AWB: We require a different set of rules for how to interact with new binding forms

DH:

  • A clean story for what the development model is for how you share code
  • Starting your script in a module, you're already in local scope
  • no need to be scoping bindings in a global scope
  • if you want to scope things, use a module
  • if you want mutation, use a script

AWB: Can let, const, class be script scoped?

DH: Could disallow let, const, class in Script

EA/RW/WH: no.

ARB: How does that not violate 1JS

Propose: let, const, class scoped to Script, as if it had an implicit scope

EA: This would prevent people from transitioning from function to class.

RW: Developer console hazard.

ARB: class has TDZ ARB: HTML event attributes might need to see the declarations

RW: Use developer tools as an example. The transition has hazards where user code thinks it has created a global binding, but actually hasn't.

<script>

let foo = 1;
</script>

foo appears undefined in the console.

YK/JM: discussing concerns about fragmentation of the mental model of global binding in scripts

BE: Again, we have a consensus on this subject.

MM: In the body of a with() {}, what does let, const, class do?

AWB: It's a block. They're scoped to the block.

BE: What is the new input that we're reopening this for?

DH: The new input is that the module tag or type=module is a better model

RW: Concerns that there will be transitional inconsistency across browsers.

EA: The status quo would allow you to see the binding in a later script

Proposed scoping won't allow this.

EA/RW: let, const, class should be "var like" at the global level in Script.

DH: There is a potential confusion. The local scope contour is less confusing than the extensible contour.

BE: It's bad if people type:

<script>

class C {}
</script>

And C disappears after the </script>

EA/WH/RW: Agree.

DH:

  • let is the same as var globally
  • const is the same as Object.defineProperty(...)
  • class is the same as var globally

EA/RW: ^^^^^ Agreed.

BE: Speculation about module uptake doesn't trump the expectation of cross script global bindings.

Conclusion/Resolution

Status Quo. Yehuda commits to work through existing issues for alternate paths.

Next meeting agenda: tc39/agendas/blob/master/2014/01.md

# David Bruant (10 years ago)

Le 27/11/2013 19:14, Rick Waldron a écrit :

Nov 19 Meeting Notes

4.4 Finalizing the Proxy API for ES6

(Presented by Tom Van Cutsem)

(...)

DS: What is typeof and instanceof

AWB/BE: object

BE: Capital P

AWB: Ca???

DS: Whatever Proxy creates?

BE: That depends on what is created.

DS: By default?

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

Shouldn't it depend on the target's typeof value? depending on apply (not call) trap makes typeof unstable ("delete handler.apply"). In any case, extra caution is required to keep typeof stability for revokable proxies (on revocation, maybe the value need to be saved somewhere)

nit: "instanceof depends on the prototype chain" => Note that it calls the getPrototypeOf trap which doesn't enforce anything for extensible objects 1, so "the prototype chain" has a more volatile meaning for proxies than it has for regular objects.

# Tom Van Cutsem (10 years ago)

2013/11/27 David Bruant <bruant.d at gmail.com>

Shouldn't it depend on the target's typeof value? depending on apply (not call) trap makes typeof unstable ("delete handler.apply"). In any case, extra caution is required to keep typeof stability for revokable proxies (on revocation, maybe the value need to be saved somewhere)

No, the current ES6 draft I believe gets it right:

nit:

"instanceof depends on the prototype chain" => Note that it calls the getPrototypeOf trap which doesn't enforce anything for extensible objects [1], so "the prototype chain" has a more volatile meaning for proxies than it has for regular objects.

Indeed, but only for proxies that claim to be extensible. For non-extensible proxies, the prototype chain is well-defined.

# Brendan Eich (10 years ago)

Thanks, Tom -- your whole bulleted list looks good, but in particular:

Tom Van Cutsem wrote:

(the current draft does lose the ability for a proxy to transparently retain a non-standard typeof value. AFAICT, typeof proxy will always either return "object" or "function")

This seems right. Any typeof extension will come from value objects ('value class' -- still need time to write it up, possibly this coming week).

# Dmitry Soshnikov (10 years ago)

On Wed, Nov 27, 2013 at 10:15 AM, Rick Waldron <waldron.rick at gmail.com>wrote:

Nov 20 Meeting Notes

Consensus/Resolution

  • Remove Object.mixin
  • "toMethod()" wins -- debate about argument order

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

A small observation: the toMethod is cool, and Allen recently showed an example of how it can be applied:

(function(){super()})() //throws because unbound super

(function(){super()}).toMethod(Array.prototype,"toString").call([])///ok

The only thing I'm worried (and that Mark mentioned), is that the super-inheritance is tightly related to the class-based sugar. While the approach above again exposes the prototypes implementation detail via this .prototype stuff.

Probably should be two:

.toMethod(Array, 'toString'); // to (instance/proto) method

.toStaticMethod(Array, 'toString'); // constructor's method

The former, as mentioned, works with the .prototype not exposing this detail to the user-level code.

# Erik Arvidsson (10 years ago)

On Wed, Nov 27, 2013 at 5:49 PM, Dmitry Soshnikov <dmitry.soshnikov at gmail.com> wrote:

.toMethod(Array, 'toString'); // to (instance/proto) method

That does not seem like the lowest level of primitive since now there is no way to no pass an ordinary object as the [[HomeObject]]. Now I have to introduce a temporary object that has a prototype property on it.

This is low level API and I don't think it is worth doing a property get for the prototype here.

.toStaticMethod(Array, 'toString'); // constructor's method

In this case .toMethod(Array, 'toString') is what you want (given that you are making a static method for a sub class of Array)

# Dmitry Soshnikov (10 years ago)

On Wed, Nov 27, 2013 at 4:53 PM, Erik Arvidsson <erik.arvidsson at gmail.com>wrote:

That does not seem like the lowest level of primitive since now there is no way to no pass an ordinary object as the [[HomeObject]]. Now I have to introduce a temporary object that has a prototype property on it.

Yeah, potentially it could check for isConstructor(), otherwise get the home directly.

This is low level API and I don't think it is worth doing a property get for the prototype here.

But if you say this is a really low level API, and won't be often used by user-level / application-level code, then I think it's fine.

In this case .toMethod(Array, 'toString') is what you want (given that you are making a static method for a sub class of Array)

Yeah.

# Rick Waldron (9 years ago)

November 18 2014 Meeting Notes

Brian Terlson (BT), Taylor Woll (TW), Jordan Harband (JHD), Allen Wirfs-Brock (AWB), John Neumann (JN), Rick Waldron (RW), Eric Ferraiuolo (EF), Jeff Morrison (JM), Sebastian Markbage (SM), Erik Arvidsson (EA), Peter Jensen (PJ), Eric Toth (ET), Yehuda Katz (YK), Dave Herman (DH), Brendan Eich (BE), Ben Newman (BN), Forrest Norvell (FN), Waldemar Horwat (WH), Alan Schmitt (AS), Michael Ficarra (MF), Jafar Husain (JH), Lee Byron (LB), Dmitry Lomov (DL), Arnaud Le Hors (ALH), Chip Morningstar (CM), Caridy Patino (CP), Domenic Denicola (DD), Mark Miller (MM)

JN: Introduction

  • Approval of 42nd Meeting Notes?
    • Approved
  • Adoption of Agenda?
    • Approved

4.1 ES6 Draft Status Update

(Allen Wirfs-Brock)

es6-status-update.pdf

AWB: One revision since last meeting, rev 28.

harmony:specification_drafts#october_14_2014_draft_rev_28

  • Modules

  • Removed loader pipeline and Reflect.Loader API (moved to a new document)

  • Stream lined module linking semantics for declarative modules

  • Removed module declaration

  • Updated import decl. to include module imports

  • Updated defautl export syntax and semantics to support export of anonymous default functions

  • Added Module Env Records (See slides)

  • There's a bug in rev r28 wrt module name normalization – should be relative to current module, was omitted (included in r29)

  • Interim Subclass instantiation reform (Copy from slides)

  • Changed ordinary object creation to dispatch object allocation through [[CreateAction]] internal slot instead of @@create

  • Converted all @@create methods into [[CreateAction]] abstract operations

  • Eliminated Symbol.create and @@create

  • super without an immediately following (Copy from slides)

WH: What was the conclusion, not clear from the notes

AWB: (revisits problem statement and agreed upon solution)

rwaldron/tc39-notes/blob/master/es6/2014-09/sept-24.md#object-instantiation-redo

rwaldron/tc39-notes/blob/master/es6/2014-09/sept-24.md#conclusionresolution

EA: What about argument passing?

BT/RW: This was concretely included in conclusion

AWB: (Confirms)

  • Rev28 Draft
  • ES6 eval semantics
  • Eliminated unused abstract operations PromiseAll PromiseCatch, PromiseThen
  • Modified Promise.all to specification internally uses a List instead of an Array
  • Added @@iterator property to %IteratorPrototype%
  • Added requirement that the object returned by ordinary object [[Enumerate]] must inherit from %IteratorPrototype%
  • Removed @@iterator from various standard iterators (inherited now)
  • Updated ToPropertyKey to accept Symbol wrapper objects, similar to how other priitive coercion abstract operations handler wrapper objects
  • ToNumber now recognizes binary and octal integers
  • Significant fix to destructuring assignent where the rest aassingment target is itself a destructuring pattern.
  • Updated Annex A Grammars to match ES6

AWB: (whiteboard) Now allowed:

[a[1], ...[f, ...rest]] = array;

4.2 End Game Planning

(Allen Wirfs-Brock)

  • Needed:
  • One paragraph summary of ES6 goals for introduction
  • Clause 4 - Language Overview. Needs to reflect ES6 features
  • Readers, reviewers
  • Ecma-402 2nd Edition, review
  • How will we resolve last minute issues?

DH: questions about March deadline, JN says deadling is important for patent issues, AWB says that last-minute changes could push publication date

DH: worst-case scenario: possibility of shipping a broken of ES6 to preserve the release momentum, getting the finished spec to the GA

WH: we can't ship a broken ES6

DH: respectfully disagree, need to get a quality ES6 out into the world, that momentum is very important to see

AWB: zero expectation that the ES6 spec is going to be perfect: "too much like software to have any expectations"

AWB: will open a bug tracker on bugs to deal with early errata, hit the next edition – turnaround in a year!

DH: if we do find issues, they won't be hanging out in the world as long

AWB: Revisiting confidence in current state of spec.

DH: If time before we ship, could we do more? Realms? Probably not. Consider revisiting try/finally restriction on generators?

BE: We didn't end up on that path.

AWB: Need to review iterator algorithms for any places that have abnormal exits to call return()

RW: (explanation of why the language overview draft is incomplete)

  • Can we get a concrete due date?

AWB: Before the holidays

RW: (agreement)

AWB: 402 2nd Edition

RW: Currently updated to reflect the necessary changes for ES6. Allen and I have decided to coordinate 402 edition publication with 262 editions (eg Ecma-262 6th -> Ecma-402 2nd, and so forth)

TODO: Review with Allen

AWB: What to do about last minute changes?

BE: es-discuss, but not everyone reads this all the time.

AWB: Can we use the reflector to start conversations?

DH: We need to be prepared to have conference calls

4.3 Assignment to a const: static error?

(Allen Wirfs-Brock)

esdiscuss.org/topic/throwing-errors-on-mutating-immutable-bindings, ecmascript#3253

const x = 42;
x = 32; // early error?
  • es-discuss consensus: eliminate early error, because analysis during parsing is hard and no clear consensus that's work the parser should be taking on
  • current spec. draft (leagcy) ES5 semantics only throws on assignment to an immutable binding in strict mode:
"don't use strict";  // ?

Object.defineProperty(this, "globalReadOnly", { value: "readonly" });

var func = function f() {
  // silently skips assignment
  f = undefined;
  // silently skips assignment
  undefined = 42;
  Infinity = 0;
};
func(); // no exception thrown
  • Should assingment to const also be silent in non-strict mode? Exception will require some new spec mechanisms.

WH: Leery about introducing new kinds of state that then make their way into various reflection APIs. This extra bit of state to distinguish const bindings from merely immutable ones will not be reflected to user code in any way, right?

AWB: Right.

Conclusion/Resolution

  • Runtime assignment to const bindings (ie. bindings introduced by the const keyword) throw in all modes (strict and non-strict).
  • Legacy const bindings (function name bindingin in function expressions) in sloppy mode continue to be no ops

4.4 Array.prototype.contains breaks MooTools

(Allen Wirfs-Brock)

esdiscuss.org/topic/having-a-non-enumerable-array-prototype-contains-may-not-be-web-compatible, esdiscuss.org/topic/array-prototype-contains-solutions

AWB: The issue is not "contains", but specifically in how they create their mixins

(General discussion to clarify: String.prototype.contains, Array.prototype.contains. Both are problematic)

Tabling until Domenic arrives.

BT: Conflict in Outlook web version, Array.prototype.values. This has been patched and the issue should dissappear in the next few months.

  • Where there is one problem, there are many...

BE: Mark may have a proposal for fixing the Array.prototype.contains issue. If we're waiting for Domenic, can we wait for Mark? Is he coming?

AWB: We agreed to not worry about Array.prototype.values, because it can be fixed and the fix is quickly distributed.

BT: IE team has pushed forward on Array.prototype.values in the technical preview (small applause).

EA: We can roll it out again as well.

Discussion of alternative paths for String|Array.prototype.contains. Come back to it.

Conclusion/Resolution

  • Revisit with Domenic present

4.5 Global let shadowing of global object properties

(Allen Wirfs-Brock)

AWB: issues:

  • When are/arent' global lets allowed to shadow an aleady existing property of the global object
  • Are buit-in global equivalent to global vars or are they just properties of global object
  • Make it illegal to shadow a global property would mean future global properties are breaking changes

Proposal: Runtime error when instantiating a script if a lexical declaration shadows a non-configurable property of global object.

WH: Any new non-configurable global properties would be a breaking change

DH:

AWB: Takes care of known issues, eg let Infinity = ...

WH: What does it solve?

DH: w/o this fix: the hazard is that any code can change the meaning (in an irrevocable way) of a global

WH: If it shadows locally, then it's local to scope

DH: This is in top level, script

BE: This is an issue for JITs, when we made non-configurable, JITs took advantage of this

DL: Yes

WH: Can you retroactively introduce a let?

EA: Yes.

DH: Which footgun is least problwem?

AWB: BZ claims there are security implications.

DH: Jason couldn't provide any security issues

AWB/BE: In BZ's email

WH: contained in your scope?

DH: The lexical contour is global

BE: (from BZ's email): window.location ... we should just do it.

AWB: Short of redesigning the entire global lexical scope contour.

BE: window.location, etc. are "own"

DH: Any time you ask for it, it must always be that exact property. If it's on the prototype, the chain can be mutated.

AWB: Properties non-configurable, function declarations didn't override them. Issues in ES5.

DH/BE: Always global:

  • window.location
  • window.top

BE: The minimum solution is to address only own properties of the global.

DH: Based on the current state of the global object.

  • Have to specify when the check is done.

AWB: At var instantiation

DH: Mutated later to become non-configurable, unaffected. Does not retroactively become an error.

JHD: ? About built-ins configurability

DH: Non-issue, we won't specify which names.

  • No retroactive error because (dave can you fill this in)

WH: Why should they be allowed to make something non-configurable later?

BE/AWB: Just an object

BE: Might try to do a two way check? Not worth it.

WH: This will bite us at some point.

DH: Locking down environment against untrusted code, you've always had to be the first to run.

Clarification of who is setting up the invariants. User code vs. Browser.

BE: Browser wants to know later that when it makes access to location or top that it will get the binding that it created.

DH: The browser just has to lock it down before any other code. Just like user code that wants to lock down the environment.

WH: Why do this if security is an issue and not make them let bindings?

BE: Not backwards compatible

WH: Can't create new non-configurable properties

AWB: Anytime there are local scripts with top level var and let bindings, you have possible conflicts with other bindings. It just is. A good a reason to use modules.

Conclusion/Resolution

  • Error when instantiating a script if a lexical declaration shadows an own, non-configurable property of global object.

4.6 Zepto broken by new this.construct usage in some Array.prototype

methods (Allen Wirfs-Brock, Brian Terlson)

BT: The checks that Zepto does internally to know what to construct is broken by changes in Array methods.

var obj = {};
var obj.__proto__

The problem is that ES6 Array methods do not explicitly create new Arrays anymore, but instead call this.constructor. Zepto uses a plain object with proto assigned...

fill in later

AWB: Spec text that breaks Zepto:

4. If O is an exotic Array object, then
   a. Let C be Get(O, "constructor").
   b. ReturnIfAbrupt(C).
   c. If IsConstructor(C) is true, then
i.  Let thisRealm be the running execution context’s Realm.
ii.  If SameValue(thisRealm, GetFunctionRealm(C)) is true, then
iii. Let A be the result of calling the [[Construct]] internal method of C
with argument (0).
5. If A is undefined, then
a. Let A be ArrayCreate(0).

AWB: Forced me to revisit "species".

Discussion clarifying the cause.

AWB: We can fix this by doing one more level of indirection...

Zepto Proposed Fix

4. Let C be Get(O, "constructor")
5. ReturnIfAbrupt(C)
6. If IsConstructor(C) is true, then
a. Let thisRealm be the running execution context's Realm.
b. If SameValue(thisRealm, GetFunctionRealm(C)) is true, then
i.   Let species be Get(C, @@species);
ii.  ReturnIfAbrupt(species)
iii. If IsConstructor(species) is true, then
1. Let A be the resu;t of calling the [[Construct]] internal method of
species with argument O.
7. If A is undefined, then
a. Let A be ArrayCreate(0).

WH: If @@species is intended to create copies of the current object, then why wouldn't Object.constructor have a @@species? Wanting to create copies of Objects is perfectly natural, but then we'd be back to the same Zepto problem. What you'd want is a @@speciesButDoNotDefineMeOnObjectConstructorUnderPentaltyOfBreakingZepto.

What color is the bikeshed?

  • species
  • copyConstructor

BT: Is this 100% back compatible?

AWB: It should be

Who is going to implement and test?

BE: put in spec.

Remaining differences...

AWB: ES5 always gave an array for these methods. For subclassing, we needed to change that.

DD: This works well for creating Promise subclasses.

  • Promise and Array are only built-ins that have methods that make instances of themselves.
  • eg. new this.constructor()

Conclusion/Resolution

  • Allen's proposed fix accepted.
  • It's called "species"

5.1 & 4.4 Array.prototype.contains and String.prototype.contains

(Domenic Denicola, Mark Miller)

DD/RW/BT: Just change them both to includes. It solves it directly.

DH: Consistency constraint? Any other ducktyping that expects "contains"?

Probably

DD: There are also DOM APIs that "look like" arrays, but have no Array.prototype methods, but do have a contains method.

RW: DOMTokenList (and one other?)

BE: This is a naming game

BT: Let's just do includes

BE: (agrees)

MM: (explanation of analogous operations on Array to String.prototype.contains)

There is precedent for papering over the difference between substring and array elements

Conclusion/Resolution

  • String.prototype.contains => String.prototype.includes
  • Array.prototype.contains => Array.prototype.includes

Continues...

DH: We should be allowed to extend built-in prototypes. New syntax can't be the first solution.

Discussion about how, when and where it's appropriate to publish polyfills that adhere to specification bound features.

SM: Not possible to publish polyfills and know that users will be responsible with upgrades

JHD: Each change with the spec has to be a major version bump.

BE: Need to know when to risk

JHD: An es7-shim will likely have finer granularity in feature detection.

DD: Tests will never be complete enough

MM: Experience in SES is proof that the things that need to be tested for will always grow.

DH: We should reprise this conversation when Yehuda is here, he has concrete recommendations to share with authors, with regard to train model.

AWB: Is there something that modules can help with? import ... and get ES7 features?

DD: No, that's effectively "use es7";

AWB: Modules loaded for side effects?

MM: shouldn't encourage the pattern

4.8 Template literal call site object caching.

(Erik Arvidsson, Mark Miller, Allen Wirfs-Brock)

AWB:

let world = "world";
let t = "tag`hello, ${world}`";
eval(t);
eval(t);

new Function(t)();
new Function(t)();

tag`hello, ${world}`

How many unique callsites? 5, 3, 2 or 1?

AWB: Note that the following

tag`hello, ${world}`
tag`hello, ${world}`

has two unique callsites.

BE: Identity can be observed

MM: If you adopt the answer 1, there is no communication channel open. Although mutable state is reachable from the callsite (nee template) object, the only such mutable state is the primordials (Array.prototype, etc). Thus, the memo must be per-realm -- by contrast with the global Symbol registry. The identity sharing is surprising. If we want to avoid that surprise, then 5 is the answer. The performance argument says 1. Whatever the tag function pre-computes, it will typically memoize based on the identity of the callsite (nee template) argument. Note that ES6 provides identity-based maps, but provides no content-equality-based maps for use on array or object keys.

AWB: "Callsite" is probably the wrong term.

WH: What is tag? System or user code?

BE: Tag is not the thing that we're discussing being memoized. It's the constant array that's passed to tag.

MM: (restating issue) The object that captures the literal part of the expession that's captured for the call.

DH: If we go with 5, the argument becomes: regain performance that's been lost? Can the programmer do it for themselves?

  • So if I want the function to execute multiple times, how can implement the single "cached".
  • Impossible to get the performance of 1, because the 5 would always allocate an array.

In favor of 1:

  • No way to get that performance manually
  • If you want 5, you can manually do it with 1.

WH: We've tried to do call site memoization in the past. In ES3 we allowed behaviorally equivalent closures that didn't capture any free variables to share identity. We also made regexp literals share identity. Since then we've backed out of both of those decisions.

BE: ES3 left closure memoization up to implementations. ES5 forbade closure memoization.

MM: (revisiting const functions)

  • const functions strawman:const_functions , by freezing the function, safely enable the joining optimization that ES3 unsafely tried to allow.

MM: 1: the memoization is the raw string contents and the holes, only -- the information that goes into the callsite (nee template) object.

Discussion of performance via caching on "call sites"

MM: The consequences of 1 are easy to enumerate

WH: If we do 1, how would we implement that without leaking memory? An implementation would likely have a memoization map from strings to arrays. At what point can that map forget bindings? There is never a guarantee that a particular key string won't be used again.

("template identity" is better to describe the thing that has been referred to as "call site")

MM: For a given set of template contents, there exists no more than 1 template identity. That invariant is not violated by having 0. Within the implementation, one could have a weak-value map, mapping from the template contents to a weakly held template object. Weak value maps expose non-deterministic GC strawman:weak_references#a_weakvaluemap , but this internal use of a weak value map does not expose any effects of GC to JS code.

BE:

`hi, ${name}`
`hi, ${n}`
`hi, ${_}`

All of those would evaluate to the same template.

WH:

`hi, ${a}, ${b}`
`hi, ${x}, ${x}`

Would those two be the same template or two different templates?

BE: Same.

Conclusion/Resolution

  • The result would be 1

What is the this binding at the top of a module?

DH: Makes sense going forward to access the global via the Reflect library. this should be undefined at the top level of a module.

DD: I previously thought we had consensus on Reflect.global, but it's not in the spec

MM: The idea of something like Reflect.global is a good idea, but nervous about putting it ES6. Libraries like Caja need to be able to virtualize. Things we've made available through committee defined modules have been authority free, but global is authority bearing. Need more experience living with the ES6 module system before deciding how to make authority bearing things available for import.

DD: Won't indirect eval give you a script context global?

MM: Don't need to add something to ES6 for this issue.

DH: Agree

Conclusion/Resolution

  • this is undefined

4.9 Array.isArray(new Proxy([], {}))

(TomVC, Brendan Eich, Rick Waldron, Allen Wirfs-Brock)

AWB: (Explains the expectation of Array.isArray(...))

BE: Tom believes that Array.isArray(new Proxy([], {})) === true

RW: (agrees)

AWB: Breaks the exotic array check

BE: But not the same

AWB: All the checks have been replaced with spec language re: exotic array object

MM: What are the observable differences of a proxied array

DH: (asserts that there are concrete cases for virtualization)

BE/MM: Allowing Array.isArray to behave this way is desirable

AWB: Unless the Proxy is poorly implemented

BE: We already decided that malicious or poorly implemented Proxy's don't restrict our

DH: Agree that Array.isArray(new Proxy([], {})) === true

AWB: Even if they override all the mop operations, and no longer behaves like an Array

DH: Yes.

MM: Array is part of the primordials, don't have to specify how they come into existence, just how they behave once in existence.

BE:

  Array.isArray  | Result
----------------------------
    []       | true
new Proxy([], {})| true
Array Subclass   | true
new Nodelist()   | false
new Uint32Array()| false

WH: (adds row to BE's table, based on the proposed isArray pseudocode on the slide that turns exotic objects that share Array's constructor into being themselves arrays) Any exotic object that inherits from Array | ?!@#

DH: let d = new Date; d.proto = Array.prototype; Array.isArray(d)

DH: can allow typed objects where

BE: Any value object that inherits from Array, isArray => true

AWB: If an exotic object and inherits from Array, isArray => true

EA: @@isConcatSpreadable addresses the failure of Nodelist being unable to inherit from Array

AWB: Proxy with array as target may not behave anything liek an array

DH: But that's not what brands are about, simply about the bit that says "the brand"

AWB: Promise.isPromise wouldn't work if new Proxy(new Promise(), {})

DD: But Array.isArray is a special case.

  • Array.isArray checks to see if its argument is a Proxy and then drills through to the target?

DH: Addressed the lack of typeof ...

DH: Could say that isArray is true IFF argument is an exotic array...

AWB: No, would break many things.

MM: Agreement with Dave, that these things should agree with eachother.

DH: A new term that means "is inductively like an exotic array object".

DH: The meaning of isArray, there is reflectively a bit that's set that differentiates the behaviour to use for all special cases. Any data structure in which Array.isArray is true, JSON.stringify should follow the array path.

eg.

var a = [];
var p = new Proxy(a, {});

Array.isArray(p) === true;

var o = {
  a: p
};

JSON.stringify(o); === '"{"a":[]}"';

DH: Any Proxy whose target is an Array, is treated like an Array.

WH: What about objects that inherit from Array?

DH: Only objects that were created using Array's construction mechanism (from last meeting) would be arrays. Objects that merely monkey-patched the proto chain to inherit from Array would not be arrays. AWB: post meeting note -- "created using Array's construction mechanism" is equivlant to says "is an exotic array object" because that mechanism is the only way to create exotic array objects..

DH: For proxies, remember whether the target object was an array when the proxy was created, and return the same answer. Revoked array proxies would still be arrays.

DH: No other objects would be arrays.

Conclusion/Resolution

  • Array.isArray checks to see if its argument is a Proxy of an Array and returns true when it is
  • b/c of revocable proxy: at creation time, discover it's an Array
  • Any data structure in which Array.isArray is true, JSON.stringify should take the Array path.
  • The following:
  • Array.isArray
  • Array.prototype.concat
  • isConcatSpreadable
  • JSON.stringify should replace the occurrence of "is exotic array object with the isArray interal check.

AWB: In post meeting discussions MM and AWB concluded that Array.isArray should throw when applied to a revoked proxy. This is more consistent with overall revoked proxy behavior and eliminates the need for additiounal mechanism for remembering the array-ness of revoked proxies.

4.10 RegExp subclassing fixes

(Allen Wirfs-Brock)

AWB: When ES6 refactored functions that either take a string or a RegExp there was an issue where the state on the RegExp instance was not set correctly.

AWB: These functions created a clone of the RegExp. But how do we do that when there are subclasses involved.

new RegExp(regExp);
new RegExp(regExp, flags);  // Throws!

AWB: Seems like we should allow passing in flags in this case.

MM: Isn't there a property that gives you the source?

AWB: There is source.

WH: Is this a compatible change?

AWB: The match function does not use lastIndex and other state.

MM: Is the cloning too big of a hammer?

AWB: We are making a clone because we do not want to mutate the internal state.

AWB: What are the obvious reasons to subclass RegExp? Maybe one wants to add new flags? But RegExp has no way of getting the flags as whole.

let re = /abc/mi;
re.??? === 'mi'

AWB: Suggests adding a flags getter, and extending the RegExp constructor so that it can take a RegExp and a flags string, instead of throwing as it does now.

DH: Why do we need this?

AWB: The double dispatch is needed allow subclassing of RegExp.

DH: Why the @@isRegExp symbol

AWB: It is needed due to the double dispatch in functions that take either a RegExp or a string. If we didn't have the symbol then we would blindly just do toString.

WH: We just ran across the same problem earlier today with arrays. Why solve it in two different ways in the standard?

MM: Why don't we use symbols for these double dispatch functions and then we don't need the extra symbol, @@isRegExp

BE: Does anyone want RegExp.prototype.match? Together with String.prototype.match, it's too confusing as to what is matching what.

DH: Can we revert or defer it?

AWB: This has been in the spec for years.

DH: There is a subtle difference between match and exec. If we now add match to RegExp it is going to be even more confusing.

AWB: We can just

AWB/BE: There are only four of these: match, replace, search, split

BE: Lets add symbol names for them.

BE: Symbol.match, Symbol.replace, Symbol.search, Symbol.split

WH: Do we need @@species any more?

AWB: We might still need it for the new this.constructor.

DD: We use @@species for Promises.

MM: If Arrays use @@species, TypedArrays use @@species, Promises use @@species, then RegExp should use it too.

Conclusion/Resolution

  • Add RegExp.prototype.flags getter
  • Per discussion with JHD/AWB/BE: RegExp#flags should return a string of flags, but sorted alphabetically, to match #toString - eg /a/gim.flags === /a/igm.flags === 'gim'
  • Erratum from JHD:
    • All implementations I tested (FF/Chr/Saf/IE/node) alphabetize the flags in RegExp#toString - the spec should make sure that's concrete for both #toString and #flags
    • When there are no flags, the spec should probably specify that RegExp#flags returns an empty string
    • question to be clarified: is flags an own property on a RegExp instance, like "source"? Or, is it a getter defined on RegExp.prototype?
  • Make RegExp constructor not throw for (re: RegExp, flags: string).
    • Essentially, implicit conversion of re -> re.source when "flags" is

provided?

  • Rename the double dispatch methods to use use symbol names instead of string names.
  • Get rid of @@isRegExp
  • Add @@species for consistency.

4.13 Add async as FutureReservedWord

(Rick Waldron)

RW: We've reserved await, but not async. Should async be added as well?

DD: async is contextual. It is only valid as async [nonewlinehere] function.

EA: But async arrow function might need it.

async (...) => {}
       ^ look ahead to here!

async(...)

EA: The existing cover grammar covers this almost completely already.

DH: The cover grammar is creeping me out

  • Not likely to have async the module and async the contextual keyword in the same scope and if you do...

FN: Not insurmountable, if async (the module) is re-written for ES6 modules, nothing saying that it can't be renamed.

DH: Too much of an adoption tax

Conflict with existing Identifier use is not worth creating a reserved word.

Conclusion/Resolution

  • Will not reserve async as FutureReserveWord

4.11 Performance issue: Object.defineProperties, Object.create,

Object.assign. (Brian Terlson, John David Dalton)

BT: The performance issue arises when no error occurs, despite being specified that the first error thrown is to be held onto until the end of the operation.

MM/AWB: Hard to accept that this is specification related.

MM: Implementation effort should be spent, not spec change and user pain.

BT: Don't care at all about the determinism of the shape of the object when an error occurs. No library code does this, so why does the spec?

MM: The original specification focused on atomicity of the operation, which had actual performance costs and we backed out of that. This was the next best semantics.

WH: If more than one error, which do you get? Is that deterministic?

BT/MM/AWB: Always the first.

WH: First property or first temporally?

MM: First temporally. And yes, this leads to the same kind of "nondeterminism" in the choice of errors to throw.

AWB: Hard to believe this is the perf bottleneck. It doesn't seem credible.

BT: It's not the bottleneck.

MM: The burden is not big

JHD: Burden in shims or transpilers?

MM: Need for polyfills?

JHD: Still know of runtimes that need es5-shim

DD: If Object.assign is slow, no one will use it

RW: It will be a complete failure.

BE: The complaint is?

BT: If no one cares about this behaviour, why are we requiring it?

MM: I care.

JHD: Have a ticket in es6-shim for this, haven't implemented it due to the cost of try/catch

BE: If authors aren't testing for this and no one is paying attention to this...

AWB: But we don't want to leave it implementation dependent.

DD: In ES5 it's completely deterministic: you just throw the first

DL: No.

MM: If you consider the object as a bag of properties and not a sequence of properties.

JHD: Not a determinism issue, completely deterministic in all cases. The first error is always thrown

AWB: All the properties that can be computed will be computed.

MM: No disagreement

Discussion about who owns the burden of these performance

RW: Why does Object.assign also behave this way?

BT: b/c we made O.pD and O.c do this, and for consistency

RW: But my original proposal said nothing of doing this. Developer expectation would be: this behaves like jQuery, YUI, Dojo, etc.

MM: Do not object to Object.assign being specified without the try/catch because the operation is just a put and when the target is a non-Proxy it may still have setters invoked on put.

BE: if we made a mistake in not specifying order for Object.defineProperties or Object.assign, that's on us -- not a reason to inflict held-first-exception workaround for our mistake on devs of engines and polyfills

Conclusion/Resolution

Continue tomorrow.

# Rick Waldron (9 years ago)

November 19 2014 Meeting Notes

Brian Terlson (BT), Taylor Woll (TW), Jordan Harband (JHD), Allen Wirfs-Brock (AWB), John Neumann (JN), Rick Waldron (RW), Eric Ferraiuolo (EF), Jeff Morrison (JM), Sebastian Markbage (SM), Erik Arvidsson (EA), Peter Jensen (PJ), Eric Toth (ET), Yehuda Katz (YK), Dave Herman (DH), Brendan Eich (BE), Ben Newman (BN), Forrest Norvell (FN), Waldemar Horwat (WH), Alan Schmitt (AS), Michael Ficarra (MF), Jafar Husain (JH), Lee Byron (LB), Dmitry Lomov (DL), Arnaud Le Hors (ALH), Chip Morningstar (CM), Caridy Patino (CP), Domenic Denicola (DD), Mark Miller (MM), Yehuda Katz (YK), Dmitry Soshnikov (DS), Kevin Smith (KS)

6. Test 262 Status

(Brian Terlson)

BT:

  • Lots of activity happening on Github
  • Harness improvements ongoing, unblocking usage by polyfill authors is a top priority
  • Missing collateral for ES6 features
  • Move all tests to folders based on feature name
  • Improves use and navigation
  • Problem is that 15k tests need to be assigned to folders
  • 10k are categorized so far

AWB: How will we know when we have enough tests that cover a reasonably minimal amount

BT: Existance tests?

DD: When all implementors submit their suites

AWB: Focus on edge cases?

...

4.11 Performance issue: Object.defineProperties, Object.create,

Object.assign. (revisit)

AWB: (Recap)

MM: After consideration of the issue at hand, and in keeping with principle of least surprise: there is no other place where the spec defines similar behaviour. All other speced action before propagating a throw, such as the "return" from for-of loops, is cleanup action rather than continuation of the original operation. Given that the order in which the properties are tried is deterministic and with the balance of the other arguments, I agree that the first error should throw at the point of exception.

Conclusion/Resolution

  • Remove pendingException semantics
  • Error throws at point of exception

4.12 Should WeakMap/WeakSet have a .clear method? (MarkM)

(Mark Miller)

MM: In the absense of clear, we have a security property: the mapping from weakmap/key pair value can only be observed or affected by someone who has both the weakmap and the key. With clear(), someone with only the WeakMap would've been able to affect the WeakMap-and-key-to-value mapping.

Conclusion/Resolution

  • Remove clear from WeakMap and WeakSet

4.7 Clarify the syntax reserved?

(Allen Wirfs-Brock)

AWB: What did we reserve?

WH: Like this but curious about how it's done.

WH, BE: (discussion re: specifics of BindingIdentifier grammar)

WH: Will validate the grammar by January

AWB: The colon-less form of object literal

Various: Discussion of the annoying ambiguities in using colons to add types to destructuring patterns.

Conclusion/Resolution

  • No colon after BindingIdentifier
  • Jeff Morrison and Brian Terlson to chamption refinements

5.8 Map.prototype.map and Map.prototype.filter (spec) + Set

(Dmitry Soshnikov)

Map.prototype-extensions.pdf

DS: Map.prototype extensions

  • map
  • filter
  • more...

These exist on Arrays, hopefully this is straight forward

Proposed spec: gist.github.com/DmitrySoshnikov/a218700746b2d7a7d2c8

MM: Similar to parallel js, lets keep an eye on the higher order operations to ensure that operations remain parallelizable

Design Choices

  • Directly on Map.prototype
  • On generic "map-like"? %CollectionPrototype%
  • Binding :: operator on iter tools?

User-level API

  1. Simple value map:
new Map([["x", 10], ["y", 20]]).map((v, k, m) => {
  return v * 2;
});
=> [["x", 20], ["y", 40]]
  1. Entries map:
new Map([["x", 10], ["y", 20]]).map((v, k, m) => {
  if (k == "x") return ["z", v];
  return [k, v * 2];
});

=> [["z", 10], ["y", 10]]

WH: Common Lisp has a menagerie of map-like functions. One of the most useful ones is one that allows the per-element function to decide to skip an element instead of always producing one.

YK/DD: (discussion re: Ruby style map operations)

MM: If you want to get the default, without being verbose

DD: Put a symbol on the map this[@@collectionConstructor] to find the right constructor

AWB: Smalltalk uses an abstract above that has a species property to determine what to create.

Discussion of lazy mode

YK: Lazy: do not accumulate intermediaries. Non-lazy: accumulate

YK/DD: Not important to determine this right now.

WH: How would you directly turn a map into an array, i.e. provide a mapping function that takes a (key, value, m) and produces array values?

?: Array.from(m.entries.map(...)) instead of new Map(m.entries.map(...))

WH: But that wouldn't work if, as was just being discussed, we got rid of the outer new Map by making it implicit.

  • Prototcol design choices

Re: %CollectionProtocol% esdiscuss.org/topic/map-filter-map-and-more#content-33

AWB: Want to avoid intermediary collection creation

Possibly?

import { map } from "itertools";

var nmap = omap::map((k, v) => [k + 1, v + 1]);

DD: we have the IteratorPrototype

  • Overall
  • To correlate with map.forEach better to be map.map and map.filter, not map::map
  • Direct Map.prototype or %CollectionPrototype% - to be discussed

YK/DD/DS: (discussion of need for additions to Map.prototype) Concern about forEach as stopgap for transition to for-of DH/others: transition still ongoing BE: transition means "stopgap" code on web endures BE: anyway we want high-order "interior" iteration forever BE: JS is a TIMTOWtDI language

RW: These can be made generic enough for both Map and Set if map defaults to the thing that mapEntries is doing. Then works the same for both.

YK: No consensus on a map-specific solution.

DD: Don't think we should put anything else on Map.prototype, it should be on map.entries()?

  • Not consistent in each case

DH: Disagree. Most common case gets the position of being default. Methods on class get to be the domininant, default case.

  • We have keys, values, entries and need iterator

DD: This example seems to have values as the default

DH/YK/RW: Which is wrong.

MM: map vs mapEntries is differentiating in what it does with the callback's return value. These do not differ on the arguments they provide to the callback.

DD: Entries is the default

YK/DH/RW: Agree.

DS: Remove forEach?

WH: Why? I don't see anything wrong with it, and it's analogous to the other mappers.

BE: forEach is not just transitional. We need it.

RW: This isn't a trade.

DH/YK: (discussion re: adding a new CollectionPrototype to the chain?)

BE: Someone needs to do the work to see if this can be done. We want batteries included interators, higher order operations etc.

DH: Might be that we have several inheritance heirarchies? Similar or same methods?

YK: Can have a higher class that gets delegated to.

WH: (itemizes each of the cases: map, filter and forEach)

  • How do you turn on type into another?

YK: This is what we were discussing re: the symbol

[several discussions at once]

AWB: An iterator that wraps another that says "iterate, but of a specific type".

BE: Need slides, DD doing that.

Map.prototype.entries = function () {
  return new MapIterator({ collectAs: this.constructor[Symbol.species] });
};

class MapIterator extends Iterator {
  constructor({ collectAs }) {
    super();
    this[Symbol.collectAs] = collectAs;
  }
}

Iterator.prototype.collect = function () {
  return this[Symbol.collectAs].from(...);
};

myMap.entries()                      // proposal: you can remove .entries()
  .filter(([k, v]) => k % 2 === 0)
  .map(([k, v]) => [k * 2, v])
  .forEach(...);
  // or .reduce(...) also forces
  // or for-of
  // or .collectAs(Array)
  // or .collect(), which uses [Symbol.collectAs] as a default

(mixed discussion)

MM/DH: classic lazyness, "force" means done building up the lazy stuff and want to actually force it to execute and get a result now

WH: Not convinced, what goes in the ... on line 13? (i.e. does the collectAs constructor get passed values or [key, value] pairs? This makes the difference between getting the result ['x', 'y', 'z'] and [[0: 'x'], [1: 'y'], [2: 'z']].)

DH: collectAs is the the way to go from one final thing to another final thing.

Confirmed.

DD: call keys, you get keys, call values, you get values, call entries, get entries.

WH: Very confusing. In for loops "entries" means the format of your input, not what you'll eventually output.

DH: That's just our established terminology for items in Map or Set

WH: Yes, but it's used on the input to specify the kind of the output instead of the kind of the input.

Domenic adds to example: "Proposal: you can remove entries()"

myMap.entries()
  .filter(([k, v]) => k % 2 === 0)
  .map(([k, v]) => [k * 2, v])
  .map(([k, v]) => v)
  .collectAs(Array)

To generate example that collects just the values (not the pairs) into an array.

WH: To clarify, this doesn't collapse the intermediate results into any maps, so there would be no issues with .map(([k, v]) => v) duplicates

getting undesirably coalesced?

DD: Right.

KS: Want to transform one interator into another, but dont want to use the defined function, want to use my own. How does this propagate this through?

DH: Syntax doesn't give you a nice way to do this, generator is just a function that takes an argument

KS: Yes.

DH: No collectAs?

YK: Provide a default

DH: But as Kevin says, this couldn't be implemented with Generators

AWB: Need to explore this, but the subclassability of generators comes into play here. Need to work through it .

DH: Can't instantiate a subclass of generator as a generator

...

MM: Agree that lack of map and filter is a point of confusion.

YK/DH: We all agree with this.

YK: If all in agreement, then we're in consensus to at least do something, but not sure what that is.

  • Also needs to be subclassable

MF: have a reservation about the entire premise. What about the

  • Non-empty list in? Guarantee out?

DH: If input type of filter is

MF: Two functor laws:

  1. If map the id function over a functor, the functor that we get back should be the same as the original functor.
  2. Composing two functions and then mapping the resulting function over a functor should be the same as first mapping one function over the functor and then mapping the other one.

(break)

Conclusion/Resolution

  • Needs work.
  • Sufficient issues
  • Iterator prototype first
  • How does that translate to the collection api proposal itself.

5.9 Revisit Set API (possible exclusion of entries and keys)

(Dmitry Soshnikov)

DS: (proposes removal of second arg to set.forEach)

RW: The matching arguments in map.forEach and set.forEach were designed to match array.forEach for consistency.

JM: Is there any code that would rely on this?

AWB: If set only has value iterator, how do you create a map without keys or entries?

  • If you remove this from ES6, how do we create a map from a set?

JM: Not pleasant.

AWB: Correct.

RW: What is the actual value of removal?

AWB/LB: There is value in consistency

Conclusion/Resolution

  • No removal of argument to set.forEach

Abstract references as a solution to LTR composition and private state

(Kevin Smith)

KS: Abstract referemces, gives a way to provide an abstraction for the records base component, for that record. Antoher way to think about it is virtual properties.

Using the IteratorPrototype Problem to illustrate

  • We want iterator methods!
  • Left to Right composition
  • Userland FTw

Conflicting goals

  • Don't want users to extend built-in prototypes
  • Don't want to wait for TC39

A General Problem?

The user has an object. The user has a function But...

There's no convenient way to all the function as a method of the object. Have to use right-to-left. All chains to the left.

A (More) General Problem?

The user has an object L The user has a function R

A General Solution

L :: R

base = L referenced name = R

AWB: Are you evaluating R?

MM: R is an expression. Only the value it evaluates to is significant. In this regard, it is more similar to square bracket indexing than it is to dot.

Dereferencing behaviour is delegated to the referenced name object.

  • Symbol.referenceGet
  • Symbol.referenceSet
  • Symbol.referenceDelete

Examples

/* gets evaluated approximately like */
L::R
R[Symbol.referenceGet](L)

L::R = expr
  R[Symbol.referenceSet](L)

L::R()
R[Symbol.referenceGet](L).call(L)

WH: Asks clarifying question about what goes into the base, name, and strict slots of the generated Reference object.

[KS flips to the semantics slide]

WH: Does this mean that the call fails whenever L === undefined?

MM/KS: Yes.

WH: Which is the base?

MM/KS: The base is L

WH: In your examples above, it's R

MM: In the desugaring, the references

MM: The value L is the reference's base. The value of R is the reference's "name"

MM: The semantics is normative in the proposal, not the desuraring.

WH: The desugaring is not helpful because it misleads to wrong conclusions about the proposal, such as the base and the behavior when L === undefined.

Built-In Support: Maps

Maps have inherent virtual property semantics: (need to copy from slides)

Private State

// Because the Map has "get", "set", and "delete"
const X = new PrivateMap();
const Y = new PrivateMap();

class Point {
  constructor(x, y) {
    this::X = x;
    this::Y = y;
  }
}

// Private State + Sugar
private X, Y;

class Point {
  constructor(x, y) {
    this::X = x;
    this::Y = y;
  }
}

YK: (question about inheritance, Yehuda can fill that in?)

MM: If you want protected state (visible through inheritance), you can define that.

MM: Think of :: as more like "base["

YK: FWIW, some explicit private state syntax is desirable.

Weaknessess

The user must bring the virtual property object into scope as a variable. Fortunately, we now have better tools to manage scope:

  • Modules
  • Lexical Declarations
  • Destructuring

More Information

Examples:

DD: This doesn't work outside of certain cases, the symbols are added

BE: T

DD: Wouldn't unreified private state, by analogy to spec-internal properties, have the same non-transparency across proxies that spec-internal properties do?

MM: The only non-transparency in both cases is over non-membrane uses of proxies, whose ad hoc nature cause many necessary non-transparencies. For example, applying Data.prototype.getYear to a proxy for a Date. But in a full membrane scenario, you'd apply a proxy for getYear to a proxy for Date, which turns into applying the real getYear to the real Date on the other side of the membrane. Non-reified private state would avoid the membrane tranparency issues in the same way. These issues only arise once you reify the designator into something first class which enables access to that private state.

YK: The only real disagreement is whether the mental model is private state or the model that [Mark just described]

MM: Lead to Relationships: impossible to each "private state designator.get state bearing object" (meta-mm: Rick, I don't understand what you recorded here and it doesn't ring any bells. If no one else remembers, please delete it as uninformative noise. Thanks.)

YK: everybody agrees on the private state semantics, but the argument is whether we need a special-case syntax for private state, or a general-purpose extraction that everyone will need to learn

AWB: Generalization that :: can have use on both sides.

JM: When you see the call example it makes more sense.

DD: But you're not "calling", you're "symbol.referenceGet"ing

  • Ill serving private state
  • Ill serving the bind

MM: Non reifable private state, such as in Java, pure textual. No transparency across membrange problem. The issue cannot arise becase theure is no ability to reify the designator of that slot.

  • Nice conservative starting point because it directly reflects internal slots.

YK: There's a curse of expert knowledge in the room, need to step back and think of it in simpler / easier terms

MM: Given reification of the designator, we're only transparent across membranes if the access invokes the reified state designator with the state bearing object as argument, rather than vice versa.

DD: would work just as well, if this :: only worked with private maps. The generalization that :: can intercept an object with get, set,

MM: (Added after discussion) Only transparent across membranes if :: also works with proxies for these maps. There's no need to make a special rule for proxies to these maps vs other proxies, so we shouldn't. If we don't then it also doesn't make sense to impose a private-map-only restriction in the first place.

WH: Main objection is to choice of the particular syntax used. :: would be more naturally used for either type annotations (due to the existing usage of : in object literals and destructuring) or namespace-like qualifiers (like in C++).

WH: (other than choice of syntax): interesting, but not fully investigated. fear of locking ourselves into using weak-maps-like mechanism for private state. This of course lets you stick "X" onto anything with ::, not just objects of your own class.

AWB: But weakmaps have essentially grown into a thing that provides a separate set of "private slots", keyed on whatever object.

RW: Yes. We're using this pattern significantly in hardware abstractions, where the key is the instance respresnting some device and the "private state" contains the raw readings from the physical device. Keeps this data at hand, but away from user muddling.

CM: In practice, there will be a profusion of extended objects and people won't realize that they're using this :: vs. ?

DD:

class Point {
  private X, Y; // desugars to
  // new PrivateMap(Point) ?

  constructor(x, y) {
    this::X = x;
    this::Y = y;

  X.set(foo, bar);
  }
  method(o) {
    o::X = "foo"; // X.set(o, "foo");
  }
}

WH's objection, as presented by MM: method(o) can be called on any o, not just Points, and can be used to pollute other objects. This leads to issues via various confused deputy integrity bugs.

?: May want to attach private properties to any object.

MM/WH: Sure, fine to allow that case too, but it should require an affirmative step by the programmer. The path of least resistance should be simple private.

DD: What if private means that the map will only accept an instance of Point?

MM: In the

DH: There is a lot we want to achieve with "private" and I don't think we even have consensus on what we want to "private" to be. There is a lot machinery in this proposal. Missing a natural correspondance ot an existing mental model

YK: Or another language

MM: ? re: non-reified private state

DD: (updates)

class Point {
  private X, Y; // causes constructor to do
  // X.set(this, undefined); Y.set(this, undefined);

  constructor(x, y) {
    this::X = x;
    this::Y = y;

  X.set(foo, bar);
  }
  method(o) {
    o::X = "foo";
    // if (!X.has(o)) {
    //   throw new TypeError();
    // }
    // X.set(o, "foo");
  }
}

DH: Hypothetically: if :: was only usable for private. No generalization. Throwing this extra baggage nto class private is doubling down on private being only usable with class. I

Should be a requirement: usable outside of classes.

MM: accessor not be reified AND be usable outside of classes?

DH: Hypothetically, not reified.

MM: Non reified privacy indicator outside of classes?

DH:

MM: Doesn't reify? It should work

AWB: not class specific, you can put private in object literal.

DH: Not confident we have agreement of what private outside of class should do or look like. examples:

(whiteboard image)

DH: If we decide second class, then additional set of concerns

MM: In the absense of reifying, we can faithfully explain what's going on in terms of static semantics.

DH: if first class, allows use as a general mechanism

MM: Proposes that private sugar (for declaring private properties) be defined only within classes. The language already has plenty of mechanisms to define it ad hoc in other contexts. On the other hand, the :: usage sugar would be usable throughout the language.

It's basically impossible to follow (rapid topic-hopping, analogous to frequency-hopping radios :) )

When members review the contents of this discussion, they will have to fill in their own summaries.

BE: for this proposal, take the @ vs :: objection to heart, separate "privacy" from the L-to-R order.

Conclusion/Resolution

  • Resolve the existing issues
  • Separate "privacy" from left to right

Meta MM: Rick -- These conclusions do not reflect anything I remember being concluded from the discussion. As far as I remember, we all came to a much better joint understanding, but there was no attempt to articulate an agreed overall conclusion from the discussion.

5.7 Can security monitors reliably detect monkey-patching of

primordials? (Brendan, Michael Ficarra [invited expert])

MF: The problem space: "How can the developer be more confident in how their code will evaluate in any arbitrary environment"

  • "First Class Realms"

DH: Sorry to interrupt, that work is done. It's part of ES7: Realms.

  • Allows to execute a string of code.
  • Completely isolated
  • Creator can setup it's environment as they like

Can think of it similar to a DOM-less iframe or Worker.

(Questions about the analogy)

Synchronous, unmediated. Owner can reach in, etc.

DH: We should take this offline and compare notes.

MF: Envisioned as a function that has a directive, can cast values from the outside. Cannot reuse. Intended to run as an IIB

DH: What happens if there lexical references?

MF: Any lexical references are resolved.

DD: What if you have [[Global]]Array === [[Realm]]Array, which Array?

MM: Concern, if an adversary's code has run first. No code that runs after can know that it didn't run first.

DH:

MF: you can't rely on the trusted version of a built-in

MM: Code hosted on a server in a different domain, served in response to HTTP GET, not carrying the header ACCESS-CONTROL-ALLOW-ORIGIN (does not allow cross-origin get). Script tag can still read the results of a cross origin get, without access-control header, but xhrs cannot.

MF: Hoping that the security benefits are better for spec analysis. Developer sanity, alleviate working around issues. Performance may be a benefit, but I won't go into that.

MF: The benefit of this proposal over Dave's is that you're not doing string programming and have access to things around you.

DH: Operating under two assumptions: Mine: assume cannot operate under an "pwned" environment Other: assume can operate under an "pwned" environment

Only accident you have worry about is someone trashing Reflect.Realm. At that point, its game over anyway. If malice is the concern, then there is nothing you can do and we can't design that way.

MM: I agree in practice. There is a very narrow threat model in which the advesary can run first, but in which it cannot rewrite the defender's code. If the defender's code is hosted on a server in a different domain, and served -- in response to an HTTP GET -- without the ACCESS-CONTROL-ALLOW-ORIGIN, and if the adversay has no other server of its own on the network that can issue the HTTP GET to the defender's server. However, this is such a narrow and impractical threat model that we should not add any mechanism that support only it.

DH: Can't comment, it's out of my wheelhouse

  • Dislike the proposal in that it creates a false security.

MM: Relies on assumption with no malicious server.

MF: Our motivation is to protect our customer's users.

MM: Assuming adversary code is already running in a browser that your bank software is about to load, the adversary can reach out from an adversary server, which fetches the code from the defender, and sends that code, via xhr say, to the adversary code running in the browser. It doesn't matter whether the adversary rewrites it on the server or the browser. The point is, the adversary will still succeed in the rewriting attack, and the defender will not know it is running in the matrix.

(Discussion re: threat models, tit for tat.)

YK: ServiceWorker: any HTTP request can be intercepted and pwned.

  • Discussion that lead to GreaseMonkey
  • extensions are more dangerous

BE: Should talk about this more.

MM: The APIs in the Realm must be set by the creator of the Realm

DH: Need to determine what things appear in a Realm when you ask for the default

MM: The convenience of "give me the host provided stuff" is to great, the rule should come from us.

DH: Could also maintain a document that specifies what things are in the default

MM: Can say that the default is "at least populated by the built-ins" and anything the host wants to include

DH: Unclear what things should not be included.

DH: Need to provide the list of what should be there and what should not be there.

Conclusion/Resolution

  • Use the Realm API
  • The idea that we can hang something on the Realm API to help protect against possibly-malicious extensions.
  • The Realm initialization API probably should be enhanced to take a whitelist as argument, so it can include only the subset of the initial primordials enumerated by that whitelist.

5.2 Pure Functions

Casual discussion, not sure we've actually started this...

?: Why not define pure functions as passing function source code and then eval'ing it in an empty environment?

MM: It's similar, but defining pure function abstractions allows for better implementation optimization opportunities.

WH: What does structured cloning do with proxies?

Various simultaneously: It's a mess, implementation-defined, not expressible in ECMAScript, and/or breaks proxies.

DH: Separate out design problem of what a frozen environment is.

WH: The implementations discussed so far sound heavy-weight: structured cloning of parameters, possibly eval'ing function body. My impression was that pure function would be used to customize parallel code by mapping a function over a data structure in parallel, etc. These functions are often tiny such as (x, y) -> (x > y) and we'd want a very lightweight pure

function model.

WH: In addition, a lot of the pure functions we'd want to map over data structures in parallel are actually pure closures. The closed-over state would be cloned.

MM: [presents write barrier model of thinking about pure functions. Mark all state allocated before the fork; any attempt by a pure function to modify that state would throw.]

WH: This brings up the library issue of what happens when a pure function calls a library method. C++11 faced the same issue when they added concurrency to the language. Multiple threads are allowed to read the same data unsynchronized, but if at least one thread does a write (and they aren't all synchronized) then the behavior is undefined. For simple accesses such as reading an int, that's clear. But what about calling methods on library functions? What do they do internally? Can readers keep and update caches? The C++ committee decided to stick with the prevailing practice and declare that any library functions that look like they're readers (in C++ indicated by declaring them const) shall not mutate any internals (at least not unless they use special language features to achieve proper synchronization). In ECMAScript we'd want to do something similar.

WH: However, the above makes proxies break pure functions and vice versa. Consider an otherwise transparent proxy of an object O that behaves the same as O but also counts the number of times each method is invoked. That proxy breaks all usage of O in a pure function.

DH: [Skeptical about parallel ECMAScript.]

MM: ES6 specifies that Function.prototype.toString(call) of a normal JS-written function results in an evaluable expression that, if evaled in an adequately similar environment, results in a function object with the same [[Call]] behavior as the original. Thus, given the original (SES-like) assumption that the primordials of the receiving environment are frozen, you can use the same trick as used by the old proposed "there" function strawman:concurrency#there -- stringify the function on the sending side, and then safely eval it on the receiving side. For this eval (or call to Function constructor) to be safe, the receiving environment must be so much like SES that it may as well be SES.

MM: (In response to something by DH) If the primordials are naively frozen, you'll face the same usability issue we faced with SES -- the override mistake strawman:fixing_override_mistake , resulting in innocent code like "Point.prototype.toString = ..." failing. To fix this, you'll need to tamper proof the primorials instead, replacing each data property with an accessor whose setter emulates how assignment would have worked in the absence of the override mistake.

# Rick Waldron (9 years ago)

November 20 2014 Meeting Notes

Brian Terlson (BT), Taylor Woll (TW), Jordan Harband (JHD), Allen Wirfs-Brock (AWB), John Neumann (JN), Rick Waldron (RW), Eric Ferraiuolo (EF), Jeff Morrison (JM), Sebastian Markbage (SM), Erik Arvidsson (EA), Peter Jensen (PJ), Eric Toth (ET), Yehuda Katz (YK), Dave Herman (DH), Brendan Eich (BE), Ben Newman (BN), Forrest Norvell (FN), Waldemar Horwat (WH), Alan Schmitt (AS), Michael Ficarra (MF), Jafar Husain (JH), Lee Byron (LB), Dmitry Lomov (DL), Arnaud Le Hors (ALH), Chip Morningstar (CM), Caridy Patino (CP), Domenic Denicola (DD), Mark Miller (MM), Yehuda Katz (YK), Dmitry Soshnikov (DS), Kevin Smith (KS), Rafael Weinstein (RWS)

5.5 Array.prototype.includes() proposal to move to Stage 2.

(Domenic Denicola)

DD: Has all of the requisite items complete.

  • Not ready for Step 3 because we need more patches landed.
  • Ready for Allen to review specification text.

AWB: Move stuff to TC39 github?

DD: Yes.

AWB: For Ecma record, need PDF

Conclusion/Resolution

  • Proceeds to Stage 2

5.6 Object.observe: proposal to move to Stage 3.

(Rafael Weinstein)

RWS: Move Object.observe to Stage 3?

RW: Can you list out the updates?

RWS: Conferred with Ember team, issues were theoretical

YK: Conceptual

RWS: Appears to be objections from YK and Ember, provided examples that should overcome

YK: Yes, but the actual solution does address the problem with the specification of the feature.

  • There are process issues. I've repeatedly provided feedback and repeatedly dismissed.
  • Technical Issues:
  • As a result of async callback, the decision was "don't ever drop anything"
  • All intermediate values are kept, of all properties in all states, even if these are completely unnecessary.

EA: What if someone needs all the changes?

YK: There should be a mechanism explicitly say what you want

WH: What happens if you change a property repeatedly in a tight loop without switching microtasks?

YK: You will accumulate every change

WH: And eventually run out of memory

DH: Similar concerns from Mozilla engineers

JM: Thoughts on a solution?

YK: Approach that's been discussed is an API mechanism that allows me to specify the properties I want.

EA: I think you're making a bigger problem of this, it's inherently dangerous

RW: Waldemar just illutrated a danger

YK: (gives more examples of problems)

RWS: Restate:

  • Too many allocations, all of the change records.
  • Retaining all of the changes

WH: Does it create a record for every change, say a numeric property: 1, 2, 3, 4... One for each?

YK: Yes.

DH/YK: Overwhelming number of changes when properties you don't care about are also changed.

BT: On the other side, there are a lot of developers waiting for this feature. It's the number one requested.

YK: Not opposed to the feature, just want to get it right.

AWB: We need address issues that we'vIe identified and gain consensus.

DH: Look at it in two parts:

  • "I want an efficient way of being notified of changes that I care about"
  • "I want a full change log"

Both are very useful, but the second is likely to give you more data than you ever need. The default should be minimal, but should allow for opting into the full change log.

BT: I was operating under the assumption that V2 could add the less expensive path on top of the more expensive path.

DH: I would prefer the less expensive path to start with

DD: No, wouldn't you want all the data and then add mechanism to limit?

YK: Want use case

RWS: If you have a generic write barrier on the array, you'd have to hold onto the original array and compute the difference, which is expensive. Providing the intermediary values significantly reduces that expense.

JM: Is there an objection to adding the configurability?

EA/YK: (discussion re: performance of configurability)

JM: But still no objection to configurability, which can be omitted and give you all the change records.

RWS: (provides background of the design)

YK: Changes:

  1. List of properties that I want to observe
  2. Don't hold onto all intermediaries, the change record has only the last value

AWB: Would you want multiple notifications if multiple changes occur before the record is processed?

YK: No, just the last

AWB: How do you know when you need to start making notifications again?

YK: Same as now, when the changes are delivered, start over.

  • Recapping the concern and what's desired.

RWS: Concerned that what you want will start to unravel the design.

(Discussion of authoring responsibilities).

Agreement to work this out offline.

AWB: More concerns:

  • I'd like the specification to be written in terms of ES6 mechanisms.
  • Need to use the Job mechanisms, likely everything you need is there for you.
  • Need to define the interactions with Proxy's (alot of "[[...]]" stuff that doesn't correspond to MOP in ES6)

RWS: My understanding was that Proxy's wouldn't do anything automatic with regard to Object.observe

EA: Right now the spec is defined to tie into DefineOwnProperty. If Plain Object or Exotic Array, then it works. Some other Exotic? No.

AWB: If you wanted to?

EA: No text yet, but could add this

  • Exotic Objects are Exotic. How much do we want to polish that turd?

DD: DOM updated with internal slots. Boris Zbarsky has identified issues with holding all the values as well.

EA: Will add normative text for exotic objects. Will help update the DOM.

(discussion about notification handler changes and special cases that still need to be addressed)

Conclusion/Resolution

  • Draft revisions for filtering
  • Spec terminology updates
  • Normative section about exotic objects

402 Status Update

(Rick Waldron)

RW: Next version will coincide with ES6. Future versions will coincide with future versions of 262.

RW: After ES6 the Yahoo team (Eric Ferraiuolo, Caridy Patino) is taking over.

RW: Intl 1 provides ...

RW: Intl 2 provides Array.prototype.toLocaleString

RW: Intl 2 will align subclassing semantics with ES6. Refactoring [[Construct]] and use [[CreateAction]]. Update to use new spec algorithms/abstract operations.

EA: There was previous talk about big action items for the next version of Intl.

RW: This spec only includes minor fixes and bringing the spec up to date. Will leave the big feature items for future versions of the Intl spec.

AWB: There will be an rf opt out for this at the same time as for the ES6 spec.

Conclusion/Resolution

  • See above.

Break out sesssions

  • Object.observe
  • Async generators/iterators. Get your yield on
  • Value Objects

5.4 I/O Streams as part of the ES standard library

(Domenic Denicola)

DD: Presents: streams.spec.whatwg.org

  • Some suggestion to move into ES
  • Specified as platform agnostic (browser and node)
  • Possibly too narrow

MM: Abstraction is not data specific?

DD: Correct.

  • Walk through back pressure

MM: Explain the "too narrow"

DD: Just that it might be a step too far

RW: agrees

MM: Is the specification bigger than it needs to be?

DD: No, it's as specified as it needs to be, but seems like a step too large

JH: Don't see a conflict with async generators

Discussion on the merit of different io mechanisms

DD: With modules, do we want to extend to cover many different aspects? fetch, etc.

AWB: Programming languages need basic IO? Yes. Need to think about the ES standard built-in library. This could easily be an Ecma spec for a standard module.

RW: Had this same conversation independently and propose this as a TC39 guided spec, not dependent on Ecma-262, but normatively referenced.

WH: Any requirements for asynchrony, execution turns?

DD: No. Specifically designed away from such

AWB: Prefer that TC39 handle these things to avoid too much platform specific design.

Discussion about appropriate groups to foster development. (Compare to Intl)

Discussion re: oversight?

DD: Joint deliverable?

RW: RFTG?

DD:

BT: Honest: The best way you'll get good participation from MS is in TC39, because the legal processes and agreements are in place to protect work here. We can work in w3c for same reason. Whatwg is less clear, and therefore not easy for us to be involved.

AWB: Very complex, legally. To be resolved for whatwg, they'd have to become a recognized standaUrds organization. In the legal/governmental recognition sense.

MM: We've provided plenty of reason why TC39 would take this, can you explain why you'd rather work in whatwg?

DD: Personal preference.

  • Can provide snapshots for ecma if necessary

AWB: Not the issue, the issue is the legality of contributions/contributors.

DH: Hixie is also willing to work with companies on these things.

Heated discussion about specification ownership

MM: If the proposal is to allow the editor unilateral control, vs. committee refinement, consensus, and agreement, then the proposal should be withdrawn.

DD: Then withdrawn.

Conclusion/Resolution

  • Withdrawn

Async Generators

(Jafar Husain)

jhusain/asyncgenerator

JH: Propose to move to Stage 1

Major digression re: process.

...

DH: Want to see a comparative survey of how other languages and systems have approached this problem space. What does it look like, how does it work. Would like to return to providing this sort of detail.

  • Rust has RFC process that nicely tracks feature work history and development.

Slides

interface Iterable {
  Generator @@iterator(Generator);
}

interface Observable {
  Generator observer(Generator);
}

Array.prototype[@@observer] = function(generator) {
  var decoratedGenerator = Object.create(generator),
    done = false;

  ["throw","return"].forEach(method => {
    decoratedGenerator[method] = v => {
      var superMethod = generator[method];
      done = true;
      if (superMethod) {
        return superMethod.call(generator, v);
      }
    }
  });

  for (let x of this) {
    decoratedGenerator.next(x)
    if (done) {
      break;
    }
  }
  if (!done) {
    decoratedGenerator.return();
  }

  return decoratedGenerator;
}

[1,2,3][@@observer]({
  next: function(value) {
    console.log(value);
    if (value === 2) {
      this.return();
    }
  }
});

for (let x of [1,2,3]) {
  console.log(value);
  if (x === 2) {
    break;
  }
}

async function test() {
  for (let x on [1,2,3]) {
    console.log(value);
    if (x === 2) {
      break;
    }
  }
}

document.addEventListener("mousemove", function next(e) {

});

DH: Concerns about symmetry

JH: Any iterable can be an observable.

DH: (Clarifying gist) If I am a data source (collection), I call myself iterable if I want to some consumer to "pull" values. If I am a data source, I call myself "observable" if I want to "push" my values.

Examples of for-on, @@observer

BE: I wouldn't try for Stage 1 quite yet. Let's see more explanation in the form of examples (gists, etc).

DH: need to find more ways to discuss this stuff other than the output of a transpilation.

  • Need it to explain at a user level

DS: Needs a real use case

MMj, WH: These help.

DH: Need to look at this from a "what is the problem space", then try to solve that. There are two competing solutions (async function *) and this

KS: (explains his approach with async iterator)

Interator<Promise> or Observable

asyc function * v() {
  let values = toAsycInterable(new Websocket(...));
  for (let promise of values) {
    let value = await promise;
    yield value + 1;
  }
}

Discussion re: back pressure

WH: Does either approach do buffering by default? [Prefer to transfer/work on one item at a time unless buffering is explicitly requested to avoid blowing up if a turn takes a while.]

JH: (shows an example of for-on to illustrate support for back pressure)

More discussion about backpressure

Conclusion/Resolution

  • Comparison documentation

Thanks to Paypal for the meeting accomodations. Thanks to Ecma.