Modify grammar to support Private Fields proposal:#260
Conversation
src/parser/expression.js
Outdated
There was a problem hiding this comment.
Im following the naming convention for publicProps (fields => props), but I think for this one you are right.
As a side note, we agreed that we will reconcile the naming for a mayor version.
There was a problem hiding this comment.
I'm not talking about naming convention, I'm talking about grammar. The grammar for Identifier is more restrictive than IdentifierName/property names, in that it doesn't allow keywords. The grammar for private state specifically allows keywords as the name (just like ordinary properties).
There was a problem hiding this comment.
I believe this is covered by passing liberal as true through to parseIdentifier (although it probably should be hard-coded to true here, rather than an arg to parsePrivateName.
parseIdentifier only restricts using keywords when liberal is falsy
src/parser/statement.js
Outdated
There was a problem hiding this comment.
Will this ignore whitespace? In the current spec, whitespace between the # and the IdentifierName is not allowed (though Waldemar proposed that it be allowed).
There was a problem hiding this comment.
I will test it and probably I should write a test for it.
| # PrivateName | ||
|
|
||
| ```js | ||
| interface PrivateName <: Expression, Pattern { |
There was a problem hiding this comment.
I'm curious to hear other's thoughts, but I'd probably have expected this to be a normal Identifier, rather than having a specific subtype for the private node.
There was a problem hiding this comment.
The grammar of PrivateNames is pretty different from Identifiers, in terms of where they can be used. It's been suggested that the grammar in the specification be refactored to not call it PrivateName but more like PrivateReference, consisting of the two individual tokens. To me, it makes sense that they are treated differently from identifiers.
There was a problem hiding this comment.
Apart from dan's comments about grammar, @loganfsmyth, I though it was cleaner (at least while in stage2) to make additive changes when possible rather than mutating existing nodes, like adding a private attribute for this case. We can recondile in the next mayor version, once public fields, private fields et al, are in +Stage3
There was a problem hiding this comment.
Identifier
It is an identifier with a specific type.
It would be confusing for developers because they will be forced to check the type of the identifier.
Most of them will omnit it and will cause some bugs.
PrivateName
More explicit.
I don't have much context here, but I guess most transformation within a class will be with both PrivateNames and Identifier.
There was a problem hiding this comment.
My main motivation is consistency. You already always need to check what an identifier is. It could be a local variable, it could be a class property, it could be an object property, it could be an import, it could be imported binding. Identifier is essentially a catch-all for non-keyword values in the original source.
My expectation would be that the ClassPrivateProperty would be the clarifying context for it.
|
Someone needs to help me figure out what to do with the one test failure. |
|
The test failure looks like it is catching something valid-ish.
For that particular test-case, it seems like the error we're spitting out now is much less descriptive of the problem. |
|
I have fixed the test issue due to an less descriptive message in the test that runs Although that does work, it prevents for example to use the decorators since it will throw because parseMaybeAssign is used inside decorators as well. The best solution I found was to add in parseMaybeAssign another flag to detect when to raise the error, but I don't like it. I'm not very happy with this change. |
- Adding optional plugin `classPrivateProperties` - Adding PrivateName type identifier - Adding ClassPrivateProperty to ClassBody - Allow PrivateName in MemberExpression - Allow PrivateName as a reference - Adding tests
beef2ef to
5d7b986
Compare
|
Alright this PR has been dead for way too long, and I promised @littledan I will try to land it before the next TC39 meeting :) I fixed the couple outstanding test issues and added a bunch of specific tests for private fields. There are two small details based on the feedback here and the conversation on estree #154: First is about internal naming convention for The second issue is about wether PrivateName contains in the name field a IMHO any of the previous points shouldn't be blocking this PR, otherwise we will continue to be stacked without being able to get feedback from developers and push this hopefully forward. @loganfsmyth @hzoo Can we do another pass at this PR, and unless there are other concerns, merge it? |
|
I'm fine with the current code. My only nitpick would be, maybe there doesn't need to be a 'liberal' parameter, as private names are always liberal. |
Codecov Report
@@ Coverage Diff @@
## master #260 +/- ##
=========================================
- Coverage 98.27% 98.18% -0.1%
=========================================
Files 22 22
Lines 3530 3572 +42
Branches 979 992 +13
=========================================
+ Hits 3469 3507 +38
- Misses 22 24 +2
- Partials 39 41 +2
Continue to review full report at Codecov.
|
|
@littledan suggestion done! |
|
I think not much if we are ok with the naming conventions - I think we should be ok with making the breaking changes if necessary. You can ignore the coverage issue if it's not making sense However (I guess this is my responsibility not yours 😄 ) wanted to be clearer about how we do proposals moving forward (meta issue). I thought that by making a "plugin" like flow/jsx do we could have independent versions of proposals. So if a breaking change is necessary (and it will probably be if we change the AST node names), how can we update the parser without requiring a major version bump? The proposal was to just make another plugin like "classPrivateProperties2" or something etc and then it would be a minor version bump in babylon itself while the transform could do a major version. #275 |
|
@hzoo Ready to be versioned in the future :) |
|
@hzoo Who else I need to bribe to get this in? :) I will keep poking! |
hzoo
left a comment
There was a problem hiding this comment.
LGTM other than we aren't sure about the AST node types. I want to get someone else's feedback like @loganfsmyth @danez but I believe they are both busy atm
ast/spec.md
Outdated
There was a problem hiding this comment.
Still feeling like this should be Identifier, otherwise we're diverging from the semantics that are used throughout the rest of the AST, where literal text blocks without quotes are Identifier nodes.
I agree it's not as pretty nesting-wise, but it seems more consistent.
There was a problem hiding this comment.
I believe semantics are different.
It doesn't make sense to have an Identifier that has its private attribute to true, first because its only available in the scope of a ClassBody, seconds because its meaning of it is different on the spec.
There was a problem hiding this comment.
I could have been clearer, my suggestion is
interface PrivateName <: Expression, Pattern {
type: "PrivateName";
name: Identifier;
}
I'm not suggesting a private: boolean flag on Identifier.
Identifier nodes in our spec are currently every case of non-keyword, non-string literals. The same way it's not name: string on FunctionDeclaration names or MemberExpression properties.
There was a problem hiding this comment.
That I like better. @littledan What do you think?
There was a problem hiding this comment.
Well, thinking of unquoted property names or private field names as Identifiers isn't all that intuitive for me--they are more like strings with a prettier syntax. But if this is just an AST and the rest of the system works this way, it seems fine. I agree that these are somewhat analogous to property names, as long as they are marked specially.
src/tokenizer/index.js
Outdated
There was a problem hiding this comment.
I think this comment should go after the new case for 35 ("#").
src/parser/expression.js
Outdated
There was a problem hiding this comment.
Is this a leftover true from the removal of the "liberal" parameter?
There was a problem hiding this comment.
Yep will update the PR
|
@loganfsmyth with this we should be good to go! :) |
| type: "PrivateName"; | ||
| name: string; | ||
|
|
||
| __clone(): Identifier; |
There was a problem hiding this comment.
This presumably clones to a PrivateName and not an Identifier.
I also don't think it should be a PatternBase unless it's allowed to appear as a parameter.
There was a problem hiding this comment.
I think it's only this.#a, #a and #a = 1 in the class body? At least from the examples.
First step to support Private Fields
Implemented grammar changes according to the spec:
classPrivatePropertiesBonus: Minor renaming and small code tweaks towards a future refactor within ClassBody parsing method.