Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prototype Placement of Private Methods. #2

Open
allenwb opened this issue Jan 30, 2017 · 10 comments
Open

Prototype Placement of Private Methods. #2

allenwb opened this issue Jan 30, 2017 · 10 comments

Comments

@allenwb
Copy link
Contributor

allenwb commented Jan 30, 2017

Private methods on the prototype are pretty useless as there is no convenient way to reference them. Consider:

class X {
   #helper() {};  //private method on prototye
   leader() {
          #this.helper(); //error because instances don't have a #helper field
          #helper() ;   //error because it means same as  this.#helper() 
          this.__proto__.#helper();  //error if invoked on a subclass instance
          X.prototype.#helper();    // works (assuming no rewiring) but ugly
                  //better to use a static private method: 
                  //static #helper() {}; 
                  // X.#helper();
  }
}

Class declaration scoped function declarations are probably more convenient and useful than either prototype private methods or static private methods. Eg:

class X {
  function helper() {);
  leader() {
     helper();
 }
 static supremeLeader() {
    helper()
  }
}

For this reason, I think we should excluded prototype placement of private methods from this proposal and possibly push for the inclusion of class scoped function declarations.

@erights
Copy link
Owner

erights commented Feb 8, 2017

Agreed on the immediate point.

On the other point, I find it attractive in the abstract to have class-scoped declarations. But I am at a loss for a good syntax. Whatever the syntax is, it should treat all declarations the same way. Making a special case for function declarations seems bizarre.

@allenwb
Copy link
Contributor Author

allenwb commented Feb 8, 2017

It seems to me that we already have a perfectly fine syntax for class scoped declarations -- it is exactly function, 'let, const, class (and unfortunately var) declarations. I believe this with even discussed within TC39 as one of the motivations for using a StatementList-like (semi-colon separated) list for class bodies.

class X {
  function helper() {);
  const mask=0x00ff00ff;
  leader() {
     helper();
 }
 let [x,y]=aPoint;
 static supremeLeader() {
    helper()
  }
  class inner {}
}

@erights
Copy link
Owner

erights commented Feb 8, 2017

Awesome! Yes, we should push for this. But separately from this proposal, as you way.

Your example's indentation is weird.

@littledan
Copy link

What if we said that the semantics of a private method which is not 'own' is that it would be in an immutable private slot, and an 'own' private method would be in a mutable private slot? This would make the values of the immutable methods into a sort of 'fake prototype', not reified at all (they would still be instance slots), but similar to prototype methods in that their value is shared by all instances.

@zenparsing
Copy link

zenparsing commented Mar 2, 2017

In my early work on "private" methods, I desperately wanted class-scoped function declarations, but there are some parsing issues.

Consider this token stream:

class X {
  async function [rest of stream]

When you read the async, you need two more tokens of lookahead to distinguish between an async method and an async function declaration.

@allenwb
Copy link
Contributor Author

allenwb commented Mar 2, 2017

Any ambiguities in addition to async function/method?

While it's unfortunate to have such a special case, the easy solution would be to simply not allow async function declarations within a class definition. Assuming that we do allow let declarations within a class, a class scoped async function could still be created via let f = async function() ....

Another approach, that unfortunately we are probably too late for, would be to forbid (via a look ahead restriction) the use of the identifier function as the PropertyName within an AsyncMethod. An AsyncMethod named function could still be defined by saying async "function" () ....

@allenwb
Copy link
Contributor Author

allenwb commented Mar 2, 2017

see tc39/ecma262#832

@littledan
Copy link

@bakkot Is this lookahead worse than what we need for the currently proposed property syntax? IIRC you ran into some pretty hairy cases involving somewhat deep lookahead, but were able to implement it reasonably in the V8 parser. I don't think the syntax has changed since you did that work, either.

@bakkot
Copy link

bakkot commented Mar 2, 2017

@littledan

The current proposal already requires two tokens of lookahead to distinguish between a static getter and a static field named get:

class A {
  static get p() {}
}

vs

class A {
  static get = 0;
}

Assuming we don't have static class-scoped declarations (as below), which I can't imagine why we would, I don't think this makes things any worse.

class A {
  static async function f(){}
}

vs

class A {
  static async function(){}
}

@zenparsing
Copy link

It's been a while since I've done any parser work, but I don't think the static member parsing requires the additional lookahead: you read off the static keyword and then parse the rest of it as a non-static class element. (MethodDefinition in the current ES language.)

Whereas for the async function ... case, you can't read off the async until you know if it's a function declaration or not. I mean, you could, of course, do all manner of crazy stuff with an ad-hoc parser, but I'm not sure if it would align with TC39's previously stated goals for the formal grammar.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants