March 13, 2013 TC39 Meeting Notes

Rick Waldron waldron.rick at gmail.com
Mon Mar 18 09:03:02 PDT 2013


# March 13 2013 Meeting Notes

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



## 4.14 Make new Date(dateObj)
(Presented by Allen Wirfs-Brock)

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

AWB: Propose to fix this by spec'ing the Date constructor to special case
date object arguments and produce an accurate copy of the date object.

DC: Produces a clone?

AWB: Yes.

DC: a Issues with toString?

AWB: No

NL: Bug mixes ES5/ES6 spec language: DefaultValue/DateValue?

AWB: Not an issue


**Conclusion/Resolution**

- When date object is passed to the Date constructor, it makes an accurate
copy of the date object.


## 4.4 Spec Update
(Presented by Allen Wirfs-Brock)

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

### RegExp global, ignoreCase, multiline, source, sticky are now prototype
accessor properties rather than instance own data properties.


AWB: WH's question, "why are the flags now accessor properties?" (re:
RegExp global, ignoreCase, multiline, source, sticky) is necessary to
support a web compatible "compile" method. The web reality takes an
existing instance and reinitializes a new instance.

MM: SES doesn't whitelist "compile", but could we specify "compile" to be
SES whitelistable. Freeze, no longer modifiable by compile

Example:

```js
var re = /abc/;

re.compile("changed");
console.log(re);
// > /changed/

Object.freeze(re);

re.compile("again");
console.log(re);
// > /again/

// oops
```

DC: What is the history of "compile"?

AWB: Not sure, but I believe it was JScript


### ArrayBuffer and TypedArray object length no longer restricted to 2^32
limit

DH: We should talk offline about making sure this is future proof

MM: is the new length 2^53? If it goes over, there will be a length that
can't be represented

...Mixed discussion about the length limitations of existing arrays.

AWB: Isn't really an issue, just allows the length of arrays to be
sufficiently large. I believe this is the future proof solution

ARB: Is it inconceivable that you might want to create a TypedArray backed
by a large mapped memory?

DH: Not inconceivable.
...Regardless of whether you want something 2^53 or above

YK: Agree with Allen that this is probably sufficient.

DH/AR: (brief discussion about ownership of TypedArray spec)



AWB: Can't use the same methods as Array, because they use 2^32 length.

MM: And are all generic, so really work on "array likes"

AWB: It's not clear that they _should_ work and it may not make sense to
have these methods. There are possible solutions

WH: An example of non backwards compatible?

MM: Sparse array that's not populated up to the limit and push on it? What
happens?

WH: Calls ToUint32 on it?

AWB: Yes

WH: Doesn't consider those array like?

AWB: Array spec, gets and sets, does its own Uint32
...Need to look at each of these methods and see what can be done to make
these compatible.

BE/AWB: (mixed discussion about historic compatibility issues)

BE: We can try it and the first sign of trouble, back off.

MM/AWB/BE: (agreement)

WH: The main use I see of ToUint32 is to call it on the existing length.
 Indices passed in as arguments are generally processed via ToInteger.  As
such, getting rid of the ToUint32 in generic Array methods applied to
non-Array objects shouldn't present much difficulty (when they're applied
to Array objects the change would be invisible because Array length can't
reach 2^32).

AWB: But it doesn't have to be an array
...We should move on.



## 4.5 Private Symbols, WeakMaps, and Relationships
(Presented by Mark Miller)

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

MM: Concerned about the overlap in functionality between WeakMaps and
private Symbols.

...WeakMap named with the word "Map" inverts the thinking.

...Allen noted that WeakMaps are about a Relationship, between two objects.

Legend:

**base** is **key**
**field** is **map**


(Slide 2)
___
**"Map" inverts thinking**
(the use of ">>" signifies the that the item on the LEFT is usually better
for most purposes then the RIGHT)

Syntax: base at field >> map.get(key)
...Describes the relationship more accurately

GC: impl(base)[field] >> impl(map)[key]
...A better implementation on the LEFT, despite most implementing the RIGHT

Lookup: Inherited props >> own props

Intuition: Relationship >> Symbol >> Map

Unique Symbols ok.
___

STH: Weak hash tables are found in programming languages and people want
them in JS, but they historically fall in the RIGHT. Why can't we declare
victory and go home?

MM: I feel like we can declare victory, but more work to do.

WH: Let's avoid a meta discussion.


(Slide 3)
___
**ES6 Encapsulation Mechanisms**

Closures hide lexical state (ES5)

Modules hide non-exports

Direct Proxies hide handler and target

WeakMaps hide keys, do rights-amplification

Private Symbols
___



(Slide 4)
___
**GC: base at field = value**
...Not discoverable given "base". Have to have both "base" and "field" to
get value.

Abstract heap maps(base, field) => value
base _and_ field reachable -> value reachable

...Introduces an "and" into the previously only "or" GC map

Obvious representations:

1. impl(base)[field] => value
better when field lives longer
...When base dies early, it will take the association with it,
by regular GC and without needing ephemeral

2. impl(field)[base] => value
better when base lives longer
...When field dies earlier, it will take the association with it, by
regular GC and without needing ephemeral
___


(Slide 5)
___
**GC by use case**

When base is known to live longer
_Just use a map_ (per Yehuda)

oo private field **is known** to live longer.
Just use representation #1

Most remaining WeakMap use cases
would do better with representation #1 (untested claim)

(From a GC perspective)
___

MM: The GC cost is significant. If you chose the wrong implementation,
every object that gets trademarked is retained by the WeakMap until you
invoke the ephemeron collection algorithm.

ARB: It's worse in v8 because it has an incremental GC that currently can
only run that on full collections

MM: w/r to normal access, I believe it's a wash

AWB: I don't think it's a wash, case 1 requires an index, case 2 requires a
hash code


(Slide 6)
___
**GC by use case**

Only need ephemeron collection when
 - you guessed wrong relative longevity
 - you care about the memory pressure

Felix's O(N) algorithm is affordable
with inverted representation

Examples: Membranes
___

MM: Membranes are an example where you still need the ephemeron collection
algorithm


**b** is base object
**f** is field

**L** is left side
**R** is right side

**T** is target
**P** is proxy

(Slide 7)
___
**Transparency vs Privacy**
...Membrane:

Test:
bL at fL = vL    bR at fR === vR


...see slide

___

[Whiteboard Example, get image from Sam]

MM: Propose changing the name of WeakMap and changing the way we specify
and describe them for implementors to think about.

AWB: Last meeting, we discussed cases... eg. when you invoke a method whose
this object expects access to the private state, but it receives a proxy,
it will break. I believe the solution might solve the problem

YK: |this| binding issues are orthogonal to this issue

BE: (Agree)

MM: (refutes)

WH: I challenge on this, there is a claim that we don't need private
symbols and that they're broken, but we need to do things that private
symbols are for. So why can't private symbols work the same way?

MM: This accomplishes things that we needed private symbols to accomplish,
if you want to propose changing the name of w

WH: I want to see common uses of private symbols and how you would replace
them.

MM: I haven't shown the broken solutions...

STH: I think that would've been much more helpful then showing what works
today and that you wouldn't change.

MM: I believe this is an acid test to prove the transparency

WH: Implement private symbols in terms of whatever you're proposing.

MM: `fT` is a private symbol

WH: ...

MM: I'm trying to answer your question

WH: What would I need to do differently and why, using your glorified new
approach.

MM: In the expansion of a class that uses a private symbol, for each
declared private instance variable, there will be a private  symbol per
instance variable.

WH: I think you'll need to write it down.

MM: (describes semantics, based on Slide 8)

WH: You're saying private symbols work if they adopt this semantics

WH/STH: What are the changes?

STH:
1. There is no trapping on writes and reads of proxies, passes through
2. proxy a private symbol and write sets and gets, trapped to the handler
that has that private symbol.

...In Mark's defense, this is a substantial change to how we think about
private symbols

AWB: It's a new type of access on an object, with a new type of state. A
new, different operation with separate behaviors

YK: Will the vast majority of JavaScript programmers have to understand
this? This is the most important question for me

ARB: ...?

TVC: Don't need to change proxies in anyway

YK: Not actually my concern

STH: Need to think of these as something more then properties

MM: Thinking of them as properties is what caused me to gravitate towards
addressing


(Slide 9)
___
**Desugaring Private Relationships**

```js

base at field              base at field = value
field.get(base)         field.set(base, value)

```
___

(Slide 10)
___
**What about symbols and strings?**

```js

base at field              base at field = value
-field.get(base)-       -field.set(base, value)-
field[@geti](base)      field[@seti](base, value)


String.prototype[@geti] = function(base) {
  return base[this];
};

String.prototype[@seti] = function(base, value) {
  base[this] = value;
};

```
___

MM: Don't want to use string name "get" and "set" for the invocation, I
want to use a symbol

WH: What is the implementation of @geti?

MM: The semantics of WeakMap's get, with exception that if the key isn't
found, it tries the object the key inherits from (i.e., follows the
prototype chain) until it finds a key or fails. In other words, it
implements the inheritance semantics we expect of accessing properties.
Given the use of representation #1, this can reuse the existing
optimizations for inherited property lookup.

...?

MM: Private symbols, not discoverable

AWB: You've transformed it into a alternate MOP level operation, but you
could've transformed it into a new MOP level operation... (missed this
before Waldemar interrupted)

WH: This was my proposal 3 years ago...

MM: Explanation...

WH: Not allowing these things to have normal descriptor rules is a bug.

STH: Exactly, the existing proposal reuses the mental model of JavaScript
programmers that we should continue to use. Same is true for encapsulation
at the property level and GC mappings.

AWB: If you want true privacy

WH: ... You need

AWB: You can't proxy anything that has private state. Cant proxy any
built-ins, or anything with private symbols.

BE: Asking TVC to address Waldemar's concern

WH: When the issue of membranes vs private symbols first came up, I showed
an inversion approach, instead of asking the object's proxy to look up,
you'd ask the private symbol's proxy. This had been intended to solve the
proxy privacy leak problem (don't want object proxies to see the objects'
private state), but it's essentially the same issue and solution.

TVC: Having property access by the private symbol

STH: Mark is proposing something that has similar semantics, without a new
meta operation, but pays for that by making it less like true properties

WH: So which is it?

MM: If the definition of WeakMaps is something you "stick things into",
then the answer is private symbols.

WH: Please show an example how we'd actually use this and how it would
interact with a proxy

(break for lunch)

MM:

**private** is a pseudo-syntax mechanism

```js
class Point {
  constructor(private x, private y) {}

  toString() {
    return `<${this at x}, ${this at y}>`;
  }
  add(point) {
    return Point(this at x + point at x, this at y + point at y);
  }
}
```

Desugars to...

```js
let Point = (function() {
  const x = Rel();
  const y = Rel();

  function Point(x, y) {
    this at x = x;
    this at y = y;
  }

  Point.prototype = {
    toString() {
      return `<${this at x}, ${this at y}>`;
    }
    add(point) {
      return Point(this at x + point at x, this at y + point at y);
    }
  };
})();
```




YK: If you're calling add through a proxy?

MM: If you're calling one Point proxy from another Point proxy,
the

YK: Use case, I want the |this| binding to be the proxy

MM: Call add() method on a proxy of a Point
If the right operand is a proxy,

BM: a proxy to a point doesn't have an x

AWB: Specifically, a proxy to a point isn't registered in x

...Concern: if you had done toString simply as a get access

YK/STH: If Proxies are going to fit into the language, with any sort of
concept of private state, then we need to solve the problem, and this
doesn't solve the problem.

MM: Use membranes.

WH: If you come up against this problem many times and each time the answer
is membranes, then we need to add membranes, not proxies.

General Agreement.

STH: Until we decide which side of the solution we want: either
transparently proxying objects with private state should work, or private
state can indicate that something is a genuine not-a-proxy instance of an
abstraction (such as Date), then we can't possible have a solution.

YK: Hiding implementation details that manage private state that can't be
proxies.

AWB: Virtual object vs Caretaker

BE: Not going to make unstratified traps

YK: only need a small amount of traps: get and set

...Can't go down this road.

(going in circles now)

BM: Notes that the next logical step is interfaces, where you define an
interface and proxies implement against this.

BE: Can't apply an interface to already born objects.

BM: if you pre-plan that the object is inline with the interface then
security is under control

BE: We should defer private symbols

AWB: If we do that, then there is no private branding _on_ the object

STH: Doesn't solve the problem for "what does proxy for dates do"?

More discussion about the general flaw of proxies wherein... objects that
have some form of internally implemented "private" state cannot be observed
and therefore not subject to trapping.


MM: Can we agree that transparency through membranes is a requirement?

AWB/STH/YK: Agree its important, but there are a lot of requirements.

MM: A champion group should go and solve these problems. Retaining
WeakMaps, deferring private symbols very closely matches the proposal.

STH: ...

MM: Just want to consolidate the issues

STH: Bad idea to postpone WeakMaps, which useful and are already shipping
in browsers. Bad idea to postpone anything based on a particular issue with
Proxies. A separate issue with regard to the design of private symbols.
None of these are solved by adding "@" to represent a WeakMap.

WH: It seems like @ for WeakMap makes sense

BE: Too much for ES6

MM: Regardless of the syntax/API, the slides show that we should encourage
implementers to hang the state off the key, not the base.

AWB: The WeakMap abstraction we have is fine as is. If an implementation
wants to invert its handling of keys and the map, then that's fine too.

WH: (some comment about private state?)

STH: That's not related

AWB: (re-iterates)

MM: The inverted representation is the better one.

YK: So, what is your proposal?

MM:
- **My proposal is the private symbols get postponed to ES7**
- **WeakMap gets renamed to reflect the inverted thinking**
- If we adopt the @ syntax in ES6, I want to be able to use a WeakMap on
the right side

...Don't care so much about the renaming, but feel that it could add
clarity to the feature

RW: (Disagree based on experience teaching the concept)

WH: no consensus on class without private symbols

MM: Rick, can you find the history of this?

RW: (recounts two meetings where Waldemar was not present, but a general
consensus existing with the understanding that Waldemar would still have
something to say. At Northeasten, Allen presented @-names, in which
Waldemar found to sufficiently meet his privacy requirement for classes)


...Discussion around class private state as a whole.

BE: We need to synthesize what's going into ES6. Waldemar claims this must
include some way of adding class private state.

STH: I would like to stop this conversation and allow myself time to think
about this.

BE: Done.

**Conclusion/Resolution**

- Sam, Mark and Allen to work on "relationships" and varied representation
in ES6.


## 4.3 Proxy

BE: We've had prototype implementations for some time, we made it through
the change of API. We use them extensively.


## 4.16 Current Status of ES6
(Presented by Luke Hoban)

(request some form of the spreadsheet?)


AWB: Based on this review, we should shoot for December 2014

Discussion of time tables for completed spec reviews

NL: Also need to look at progress on implementations.

NL: Concerned about impact on Internationalization API 2.0 – need to
evaluate whether to base on ES5 or slip to December 2014.


**Conclusion/Resolution**

- November 2013, Final review draft
- June 2014, Editorially complete
(STH: we said June in the meeting, but July makes more sense, since we
don't have to submit to the GA until September, IIUC)
- December 2014, ECMA approval


## 4.7 Runtime costs of the override mistake
(Presented by Mark Miller)

Override Mistake
http://wiki.ecmascript.org/doku.php?id=strawman:fixing_override_mistake

(Request spreadsheet)

RW: Would like to see the most minimal piece of code required to illustrate
the operation, measured by executing the operation in several rounds with
MAX number of executions calculated to a mean value. Also, there is use of
an `in` operation which will skew the results between Firefox (a bit
faster) and Chrome (slow)

WH: I'd like to see comparisons of non-frozen vs. frozen to see whether the
two order of magnitude Chrome slowdown is caused by freezing or inherent
slowness of push and pop.

Varying, lengthy discussions around SES techniques and the implications of
the override mistake.

Non-issue for code that doesn't freeze.


**Conclusion/Resolution**

- Investigate instrumentation when silently fails non-writable prototype
properties.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20130318/ea10463c/attachment-0001.html>


More information about the es-discuss mailing list