Skip to content

Private Class Methods Stage 3: Private Accessors#9101

Merged
nicolo-ribaudo merged 11 commits intobabel:masterfrom
tim-mc:private-class-methods-stage-3_accessors
Jan 21, 2019
Merged

Private Class Methods Stage 3: Private Accessors#9101
nicolo-ribaudo merged 11 commits intobabel:masterfrom
tim-mc:private-class-methods-stage-3_accessors

Conversation

@tim-mc
Copy link
Copy Markdown
Contributor

@tim-mc tim-mc commented Nov 29, 2018

Q A
Fixed Issues? babel/proposals#22
Patch: Bug Fix?
Major: Breaking Change?
Minor: New Feature? Add private accessors support
Tests Added + Pass? Yes
Documentation PR
Any Dependency Changes? No
License MIT
Sponsor @bloomberg

This is a follow-up to #8654. It adds support for private accessors within the current babel-plugin-class-features + babel-plugin-proposal-private-methods plugin combination.

cc: @robpalme @littledan @syg @jridgewell @nicolo-ribaudo

@tim-mc tim-mc force-pushed the private-class-methods-stage-3_accessors branch from 1af57eb to d9593cb Compare November 29, 2018 19:25
@babel-bot
Copy link
Copy Markdown
Collaborator

babel-bot commented Nov 29, 2018

Build successful! You can test your changes in the REPL here: https://babeljs.io/repl/build/9811/

@tim-mc
Copy link
Copy Markdown
Contributor Author

tim-mc commented Nov 29, 2018

I'd like to get some feedback on how this should be handling the usage of update expressions and certain assignment expressions. I'm not sure what exactly the expectation is for how to handle these situations:

// update expressions
this.#privateSetter++;
this.#privateSetter--;
++this.#privateSetter;
// etc.

// assignment expressions
this.#privateSetter += 'foo';
this.#privateSetter -= 'foo';

I made a method that checks for these scenarios which is used in both the spec and loose private name handlers.

My main question is: should these usages be throwing errors? If so,

  • Should they be code frame errors?
  • Is this the proper place to throw an error? I considered putting it over here in features.js, but since this isn't really a check for a "feature," that seemed wrong.

If they should not be throwing, what would be the proper way to handle these?

@nicolo-ribaudo nicolo-ribaudo added the PR: New Feature 🚀 A type of pull request used for our changelog categories label Nov 29, 2018
@nicolo-ribaudo
Copy link
Copy Markdown
Member

nicolo-ribaudo commented Nov 29, 2018

Can't ++this.#privateSetter; be desugared to this.#privateSetter = this.#privateSetter + 1, which should set it to NaN?

++this.#privateGetter; should instead throw at runtime, since it is trying to set a non-writable property.

Btw, I think that these cases are easier if you rely on the existing fields descriptor handling logic.

@nicolo-ribaudo nicolo-ribaudo self-requested a review November 29, 2018 23:18
@tim-mc tim-mc force-pushed the private-class-methods-stage-3_accessors branch from d9593cb to f5fcaf0 Compare December 3, 2018 23:10
@tim-mc tim-mc force-pushed the private-class-methods-stage-3_accessors branch from f5fcaf0 to ee8b26f Compare December 24, 2018 19:28
@tim-mc
Copy link
Copy Markdown
Contributor Author

tim-mc commented Dec 24, 2018

@nicolo-ribaudo I've made the updates to the PR that we discussed.

@tim-mc tim-mc force-pushed the private-class-methods-stage-3_accessors branch 3 times, most recently from c145699 to d074dcc Compare December 24, 2018 21:11
@tim-mc tim-mc force-pushed the private-class-methods-stage-3_accessors branch from d074dcc to b6427cc Compare December 27, 2018 16:05
}

descriptor.value = value;
return value;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

return value; should be outside the if/else, because we always need to return it.

methodId:
isMethod && isInstance && prop.node.kind === "method"
? prop.scope.generateUidIdentifier(name)
: undefined,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Nit: could you move the methodId definition inside an if condition, like you did for getId and setId?

return {
staticNodes,
instanceNodes,
instanceNodes: instanceNodes.filter(instanceNode => instanceNode),
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Nit: we usually use .filter(Boolean)

@nicolo-ribaudo
Copy link
Copy Markdown
Member

This PR looks almost ready!

@tim-mc tim-mc force-pushed the private-class-methods-stage-3_accessors branch from b6427cc to 1cbd79a Compare December 27, 2018 23:16
@tim-mc
Copy link
Copy Markdown
Contributor Author

tim-mc commented Dec 27, 2018

@nicolo-ribaudo requested changes have been made.

@nicolo-ribaudo
Copy link
Copy Markdown
Member

nicolo-ribaudo commented Dec 27, 2018

Can you add a test for the helper change? Something like

let foo;
class Cl {
  set #foo(v) { return 1 }
  test() {
    foo = this.#foo = 2;
  }
}

new Cl().test();

expect(foo).toBe(2);

Also, it would be good to have the following tests:

  • duplicated-names/get-set // does not throw
  • duplicated-names/set-get // does not throw
  • duplicated-names/get-get // throws at compile time
  • duplicated-names/set-set // throws at compile time
  • duplicated-names/get-method // throws at compile time
  • duplicated-names/method-get // throws at compile time
  • duplicated-names/set-method // throws at compile time
  • duplicated-names/method-set // throws at compile time
  • duplicated-names/method-method // throws at compile time. Not really related to this PR, but since we are adding all the other tests it would be good.
  • accessors/set-only-getter // throws at runtime (e.g. get #foo() {} ... this.#foo = 2)
  • accessors/get-only-setter // returns undefined
  • accessors-loose/set-only-getter // throws at runtime
  • accessors-loose/get-only-setter // returns undefined
  • Move the testUpdates functions to accessors/updates and accessors-loose/updates
  • Move the remaining code from private-methods/accessors and private-methods-loose/accessors to accessors/basic and accessors-loose/basic

@tim-mc
Copy link
Copy Markdown
Contributor Author

tim-mc commented Dec 28, 2018

@nicolo-ribaudo Ok, updated with new & modified tests.

@tim-mc tim-mc force-pushed the private-class-methods-stage-3_accessors branch from a2e4a79 to 85d2c6f Compare January 4, 2019 14:19
[
"external-helpers",
{
"helperVersion": "7.1.6"
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Could you use something like 7.1000.0? So that we don't have to change this file if the helpers change in a futue version.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Sure, done.

@tim-mc tim-mc force-pushed the private-class-methods-stage-3_accessors branch from 85d2c6f to 74bbad2 Compare January 7, 2019 16:51
Copy link
Copy Markdown
Member

@nicolo-ribaudo nicolo-ribaudo left a comment

Choose a reason for hiding this comment

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

🎉

@littledan
Copy link
Copy Markdown

🎉 🎉

@tim-mc tim-mc force-pushed the private-class-methods-stage-3_accessors branch from 74bbad2 to e1b2bcb Compare January 11, 2019 21:32
@loganfsmyth loganfsmyth self-requested a review January 14, 2019 17:17
@nicolo-ribaudo nicolo-ribaudo mentioned this pull request Jan 14, 2019
3 tasks
@hzoo hzoo requested a review from jridgewell January 16, 2019 17:37
["proposal-class-properties", { "loose": true }],
"transform-classes",
"transform-block-scoping",
"syntax-class-properties"
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Not specific to this test/PR but was wondering if we actually need to include these plugins?

"transform-block-scoping", "syntax-class-properties"

@tim-mc tim-mc force-pushed the private-class-methods-stage-3_accessors branch from e1b2bcb to 62a0ca4 Compare January 17, 2019 15:05
const isPrivate = prop.isPrivate();
const isMethod = !prop.isProperty();
const isInstance = !prop.node.static;
if (isPrivate) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

isPrivate seems only used here? Could you please inline it?

initNodes.push(template.statement.ast`var ${id} = new WeakMap();`);
} else {
initNodes.push(template.statement.ast`var ${id} = new WeakSet();`);
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The only difference is WeakMap vs WeakSet. Could we switch to an AST here and just parametrize that?

initNodes.push(template.statement.ast`var ${id} = new WeakSet();`);
}
} else if (!isStatic) {
initNodes.push(template.statement.ast`var ${id} = new WeakMap();`);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

See comment above

});
`;
}
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This looks quite verbose to me, could we switch it to building an AST and parametrizing the set/get? Also, I believe we have a few helpers that we could use here.

@nicolo-ribaudo nicolo-ribaudo merged commit e8de6fa into babel:master Jan 21, 2019
@hzoo
Copy link
Copy Markdown
Member

hzoo commented Jan 21, 2019

Released in 7.3! Thanks everyone https://twitter.com/NicoloRibaudo/status/1087473662696017922?s=20

@lock lock bot added the outdated A closed issue/PR that is archived due to age. Recommended to make a new issue label Oct 4, 2019
@lock lock bot locked as resolved and limited conversation to collaborators Oct 4, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

outdated A closed issue/PR that is archived due to age. Recommended to make a new issue PR: New Feature 🚀 A type of pull request used for our changelog categories Spec: Class Fields Spec: Private Methods

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants