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

Add class fields and private methods #180

Closed

Conversation

adrianheine
Copy link
Member

Closes #154.

type: "FieldDefinition";
key: PrivateName | Expression;
value: Expression | null;
computed: boolean;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this definition language allow you to specify that the type of computed is false?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would expect so, type is also a literal value. Are you thinking about that?

interface PrivateFieldDefinition {
  key: PrivateName;
  computed: false;
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, that’s exactly what I was thinking of.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could introduce a new interface ClassElement with key, value and computed and make MethodDefinition, PublicFieldDefinition and PrivateFieldDefinition extend it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that would make sense to create an interface for ClassElement. But I wonder if it makes more sense to not include computed in this new interface and completely leave it out for PrivateFields?

@adrianheine
Copy link
Member Author

How about this:

interface ClassBody <: Node {
    type: "ClassBody";
    body: [ ClassElement ];
}

abstract interface ClassElement <: Node {
    static: boolean;
    computed: boolean;
    key: Expression | PrivateName;
    value: Expression | null;
}

interface MethodDefinition <: ClassElement {
    type: "MethodDefinition";
    value: FunctionExpression;
    kind: "constructor" | "method" | "get" | "set";
}

interface FieldDefinition <: ClassElement {
    type: "FieldDefinition";
}

Some thoughts:

  • Whether a ClassElement is private can only be determined by the type of the key (there is no redundancy)
  • For private ClassElements, computed is always false (but this fact is not represented)
  • For MethodDefinitions with kind "constructor", computed and static are always false (but this fact is not represented)
  • Adding static blocks will not be straightforward

@piranna
Copy link

piranna commented Mar 27, 2019

Can this be merged? It's blocking support of private methods in babel and babel-eslint...

@adrianheine
Copy link
Member Author

adrianheine commented Mar 27, 2019

@piranna Does the emitted AST follow this proposal?

@nicolo-ribaudo
Copy link
Contributor

Not in Babel, only babel-eslint follows the ESTree spec.

@piranna
Copy link

piranna commented Mar 27, 2019

@piranna Does the emitted AST follow this proposal?

I don't know, I just only use that tools, and found a bug that seems to be directly related to this pull-request to being fixed... :-/

@filmic
Copy link

filmic commented Mar 28, 2019

@piranna Babel transpiles code with private methods without issues if you use @babel/plugin-proposal-private-methods.

This PR will eventually solve issue with ESLint failing to traverse code with private methods when using babel-eslint parser.

@piranna
Copy link

piranna commented Mar 28, 2019

@piranna Babel transpiles code with private methods without issues if you use @babel/plugin-proposal-private-methods.

I'm already using this plugin without problems... Fair enough, the problem only affect babel-eslint.

This PR will eventually solve issue with ESLint failing to traverse code with private methods when using babel-eslint parser.

Ok, thank you for the clarification 👍

@JounQin
Copy link

JounQin commented Aug 17, 2019

Any update?

@anthonator
Copy link

Anything the community can do to help push this along?

@RReverser
Copy link
Member

@adrianheine is this up-to-date with what the tools are doing? If so, feel free to merge, especially since it goes into experimental folder anyway.

@armano2
Copy link

armano2 commented Jan 18, 2020

Do we have a consensus on how AST structure should look for this, namely private Identifier?

@mysticatea
Copy link
Contributor

I think that private:boolean flag (or visibility:string field) is better than PrivateName node.

In semantics, the AST should represent private fields, private methods, and private member accesses. But private names don't exist. I feel that the current proposal is tied to source code text seriously. It doesn't look AST.

@bradzacher
Copy link

This is currently blocking us (typescript-eslint) from adding support for typescript 3.8.

Is there something we can do to help this progress?

}
```

Private methods cannot be static or have computed names.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Per https://github.com/tc39/proposal-static-class-features/, private methods can be static.

Private methods cannot be static or have computed names.

```js
interface PrivateMemberExpression <: Expression, Pattern {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Recently the support of optional chaining has been added to this proposal, and both ?. PrivateIdentifier and OptionalChain . PrivateIdentifier have been accepted. If we are to be consistent with current ChainingExpression approach in #204, does it mean that we should also add PrivateMemberChain?

interface PrivateMemberChain extends Chain {
  type: "PrivateMemberChain";
  property: PrivateName
}

Personally I lean to merge PrivateMemberChain with MemberChain

interface MemberChain extends Chain {
  type: "MemberChain"
  computed: boolean
  property: Expression
}

with an additional note that if property is a PrivateName, computed must be false.

@JLHwung JLHwung mentioned this pull request May 9, 2020
@JLHwung
Copy link
Contributor

JLHwung commented May 9, 2020

In semantics, the AST should represent private fields, private methods, and private member accesses. But private names don't exist.

Note that in #217 a private names is allowed in the left of a BinaryExpression[operator=in].

@mysticatea
Copy link
Contributor

Note that in #217 a private names is allowed in the left of a BinaryExpression[operator=in].

Thank you for teaching. In that case, I'm fine with the PrivateName node.

@nzakas
Copy link
Contributor

nzakas commented May 28, 2020

@JLHwung does this proposal reflect what Babel is currently doing? Or should we close in favor of a spec from you?

@JLHwung JLHwung mentioned this pull request May 28, 2020
@JLHwung
Copy link
Contributor

JLHwung commented May 28, 2020

@nzakas Babel splits both FieldDefinition and MethodDefinition into ClassProperty/ClassMethod and their private versions.

Besides that we don't have PrivateMemberExpression but extend the current MemberExpression with PrivateName support.

I can draft a new PR based on Babel's approach. I don't have strong opinion on closing this one since these two are easily interchangeable.

@JLHwung JLHwung mentioned this pull request May 28, 2020
@nzakas
Copy link
Contributor

nzakas commented Jun 1, 2020

Cool, thanks. Should we close this PR then?

@RReverser
Copy link
Member

@nzakas Given that discussion here sort of depends on decision on optional chaining, I'd say let's leave this open. This PR looks quite reasonable as well, but it's hard to tell which one is better at this point.

@nzakas
Copy link
Contributor

nzakas commented Jun 8, 2020

I guess my point is that since this is in the experimental folder, and we're only giving a cursory look at experimental syntax, what's the expectation when two competing specs are submitted?

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

Successfully merging this pull request may close these issues.

Private Class Field representation