Rough notes from today's meeting.<br><br>    Waldemar<br><br>Classes:<br>What do you get when you access an instance property before the directive defining it has been executed?<br>A. Throw (just as in temporal dead zone for let/const variables)<br>
B. Get undefined<br>C. Property does not exist yet on the object -- prototype shows through<br><br>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).<br>
<br>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".<br>
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.<br>
<br>Explored a different order: doing definitions in reverse hierarchy order and imperative initialization in hierarchy order.<br><br>At what point does a class instance acquire trademarks?  When the constructor returns.<br>
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?<br>
<br>Discussion of __proto__.  All implementations currently disallow using it to mutate the prototype chain of nonextensible objects.<br><br>Should we standardize __proto__ in Annex B?<br>MarkM + a few others:  Yes<br>Waldemar, Doug:  No<br>
<br>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.<br>
<br>Back to throw/undefined/no-property debate.<br><br>Brendan: Fixing the const case (preventing observation of mutation) will also fix the guard case.<br><br>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.<br>
<br>DaveH: Modules and classes are different things.<br><br>MarkM: Only have const classes?<br>Others: Only have non-const classes?<br><br>DaveH: Currently have nothing exactly like a const field on an object.<br>MarkM: Could specify it in terms of proxies.<br>
<br>DaveH: Proposed read barrier on const fields; no read barrier on let fields.<br>Luke: Still worried about performance of dynamic field access.<br>MarkM: Dubious about performance issue because the same case already arises for accessors.<br>
<br>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.<br><br>DaveH: Not dogmatic about classes as sugar.  OK to extend semantics in cases where the current ones are inadequate.<br>
<br>Brendan's summary:<br>class Widget {<br>  constructor(a, b) {<br>    public const k = a*b<br>    const c = a+b<br>    ...<br>  }<br>}<br><br>Similarities between const properties and lexical variables:<br>- Initialize-only<br>
- Temporal dead zone<br>Differences:<br>- property vs. lexical binding (ignoring reflection on modules)<br>- pedagogy<br><br>Went off on a tangent to discuss a class idea:<br><br>class Point(x, y) {<br>  getX() {return x}  // Instance method because it refers to x<br>
  getY() {return y}  // Instance method because it refers to y<br>  getInstanceX() {return this.x}  // prototype method<br>  getInstanceY() {return this.y}  // prototype method<br>  foo() {return getX();}  // Doesn't work -- need to use this.getX()<br>
  public x = x, y = y;  // Instance variables<br>  ... constructor code here ...<br>  alert(this.x);<br>  public m = function() {return x+y}<br>}<br>No way to factor a function into two functions without indirecting via "this" as in the foo line above.<br>
Adding a reference to x to a function changes where it lives.<br><br>Wondering why we're discussing this (which we've previously discussed) instead of discussing const and the dead zone.<br><br>DaveH: Don't go around throwing vetoes. We should not be finding the least objectionable thing.<br>
<br>Trying to understand Oliver's objections to the current class proposal.<br><br><br>Brendan's update on post-es.next paren-free.<br>Luke: concerned about gratuitously having two different ways of doing the same thing.<br>
Brendan: Safe; omitting braces and parentheses will just yield a syntax error.<br>Waldemar: Opportunities for mischief when combined with semicolon insertion:<br>Start with ES5 code:<br><br>if (a + b)<br>  (x.y)()<br>z++<br>
<br>Now (erroneously) convert it to paren-free:<br><br>if a + b<br>  (x.y)()<br>z++<br><br>This doesn't give a syntax error; it silently changes the meaning of the program.<br><br>Block-lambdas:<br>Now the |'s are required (syntax doesn't work if they're not).<br>
<br>