Sep 27 meeting notes

Waldemar Horwat
Tue Sep 27 16:06:51 PDT 2011
https://mail.mozilla.org/pipermail/es-discuss/2011-September/016795.html
Rough notes from today's meeting.

    Waldemar

Classes:
What do you get when you access an instance property before the directive
defining it has been executed?
A. Throw (just as in temporal dead zone for let/const variables)
B. Get undefined
C. Property does not exist yet on the object -- prototype shows through

Waldemar objects to B because it would allow observers to see const
properties get mutated and is future-hostile for guards (a guard expression
would not have even been evaluated at the time of the property access).

Allen's idea: Separate property definitions from any code that refers to
"this" using a barrier statement that deems that the object has been
initialized.  Works for single-level classes but not for inheritance, as the
superclass could have leaked "this".
A suggestion was made to run all property definitions in all classes in the
hierarchy before running imperative initializations in reverse hierarchy
order.  Waldemar doesn't know of any major language that does initializaiton
backwards like this; the problem is that derived classes want to refer to
the already initialized base class state so that they can initialize
themselves.

Explored a different order: doing definitions in reverse hierarchy order and
imperative initialization in hierarchy order.

At what point does a class instance acquire trademarks?  When the
constructor returns.
But then what about constructors that create a trademarked object and then
put them into a registry of all objects with that trademark?  The
constructor can't register the object because it's not trademarked yet
before the constructor returns.  Yet another kind of two-phase
initialization?

Discussion of __proto__.  All implementations currently disallow using it to
mutate the prototype chain of nonextensible objects.

Should we standardize __proto__ in Annex B?
MarkM + a few others:  Yes
Waldemar, Doug:  No

MarkM: Emphasizes that we can't allow one to add new private properties to
nonextensible objects.  Allowing that would create a hidden communication
channel between two frozen entities given access to the same frozen object.

Back to throw/undefined/no-property debate.

Brendan: Fixing the const case (preventing observation of mutation) will
also fix the guard case.

Exported bindings from modules are also reflectible as properties.  If these
are accessed before they execute (i.e. in the dynamic dead zone), they
throw.

DaveH: Modules and classes are different things.

MarkM: Only have const classes?
Others: Only have non-const classes?

DaveH: Currently have nothing exactly like a const field on an object.
MarkM: Could specify it in terms of proxies.

DaveH: Proposed read barrier on const fields; no read barrier on let fields.
Luke: Still worried about performance of dynamic field access.
MarkM: Dubious about performance issue because the same case already arises
for accessors.

Allen: We'd need to define a new instance member state: not yet initialized.
We'd use this for reflecting on module instances as well.

DaveH: Not dogmatic about classes as sugar.  OK to extend semantics in cases
where the current ones are inadequate.

Brendan's summary:
class Widget {
  constructor(a, b) {
    public const k = a*b
    const c = a+b
    ...
  }
}

Similarities between const properties and lexical variables:
- Initialize-only
- Temporal dead zone
Differences:
- property vs. lexical binding (ignoring reflection on modules)
- pedagogy

Went off on a tangent to discuss a class idea:

class Point(x, y) {
  getX() {return x}  // Instance method because it refers to x
  getY() {return y}  // Instance method because it refers to y
  getInstanceX() {return this.x}  // prototype method
  getInstanceY() {return this.y}  // prototype method
  foo() {return getX();}  // Doesn't work -- need to use this.getX()
  public x = x, y = y;  // Instance variables
  ... constructor code here ...
  alert(this.x);
  public m = function() {return x+y}
}
No way to factor a function into two functions without indirecting via
"this" as in the foo line above.
Adding a reference to x to a function changes where it lives.

Wondering why we're discussing this (which we've previously discussed)
instead of discussing const and the dead zone.

DaveH: Don't go around throwing vetoes. We should not be finding the least
objectionable thing.

Trying to understand Oliver's objections to the current class proposal.


Brendan's update on post-es.next paren-free.
Luke: concerned about gratuitously having two different ways of doing the
same thing.
Brendan: Safe; omitting braces and parentheses will just yield a syntax
error.
Waldemar: Opportunities for mischief when combined with semicolon insertion:
Start with ES5 code:

if (a + b)
  (x.y)()
z++

Now (erroneously) convert it to paren-free:

if a + b
  (x.y)()
z++

This doesn't give a syntax error; it silently changes the meaning of the
program.

Block-lambdas:
Now the |'s are required (syntax doesn't work if they're not).

More information about the es-discuss mailing list