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
Class Private Static Accessors #10217
Conversation
1de0bb8
to
07420b3
Compare
Still a WIP. Spec support has been added. Working on loose now. |
Build successful! You can test your changes in the REPL here: https://babeljs.io/repl/build/11377/ |
Loose support has been added |
a8def51
to
60b2fa9
Compare
@@ -300,8 +303,47 @@ function buildPrivateInstanceFieldInitSpec(ref, prop, privateNamesMap) { | |||
} | |||
|
|||
function buildPrivateStaticFieldInitSpec(prop, privateNamesMap) { | |||
const { id } = privateNamesMap.get(prop.node.key.id.name); | |||
const privateName = privateNamesMap.get(prop.node.key.id.name); | |||
const { id, getId, setId, initAdded } = privateName; | |||
const value = prop.node.value || prop.scope.buildUndefinedNode(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suggest move this line immediately before where value
is used so we can early return for non-accessor class private methods.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated.
60b2fa9
to
14f480d
Compare
packages/babel-helper-create-class-features-plugin/src/fields.js
Outdated
Show resolved
Hide resolved
const value = prop.node.value || prop.scope.buildUndefinedNode(); | ||
if (!prop.isProperty() && (initAdded || !(getId || setId))) return; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When would it not be a property?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It wouldn't be a property if it's a static private accessor.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: could you extract getId || setId
to an isAccessor
boolean variable?
I find it hard to read all these nested boolean expressions.
// enumerable is false by default | ||
// writable is false by default | ||
get: ${getId.name}, | ||
set: ${setId.name} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ditto reuse.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That works in this case, but setting null
as a getter/setter here is a TypeError
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, yah. We should be able to use undefined
in all cases instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point, updated.
@@ -615,14 +697,14 @@ export function buildFieldsInitNodes( | |||
case isStatic && isPrivate && isMethod && !loose: | |||
needsClassRef = true; | |||
staticNodes.push( | |||
buildPrivateStaticFieldInitSpec(prop, privateNamesMap), | |||
); | |||
staticNodes.unshift( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why unshift?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I use unshift
so that the declaration of the getter and/or setter occurs before the usage of the accessor(s) (e.g., when they're defined as the values on an object). Here's what a test failure looks like if that's changed to push
:
babel/packages/babel-plugin-proposal-private-methods/test/fixtures/static-accessors/basic/exec.js: expect(received).toEqual(expected) // deep equality
Expected: "top secret string"
Received: undefined
1 | class Cl {
2 | static getValue() {
3 | return babelHelpers.classStaticPrivateFieldSpecGet(Cl, Cl, _privateStaticFieldValue);
4 | }
5 |
6 | static setValue() {
7 | babelHelpers.classStaticPrivateFieldSpecSet(Cl, Cl, _privateStaticFieldValue, "dank");
8 | }
9 |
10 | }
11 |
12 | var _PRIVATE_STATIC_FIELD = {
13 | writable: true,
14 | value: "top secret string"
15 | };
16 | var _privateStaticFieldValue = {
17 | get: _get_privateStaticFieldValue,
18 | set: _set_privateStaticFieldValue
19 | };
20 |
21 | var _get_privateStaticFieldValue = function () {
22 | return babelHelpers.classStaticPrivateFieldSpecGet(Cl, Cl, _PRIVATE_STATIC_FIELD);
23 | };
24 |
25 | var _set_privateStaticFieldValue = function (newValue) {
26 | babelHelpers.classStaticPrivateFieldSpecSet(Cl, Cl, _PRIVATE_STATIC_FIELD, `Updated: ${newValue}`);
27 | };
28 |
29 | expect(Cl.getValue()).toEqual("top secret string");
30 | Cl.setValue();
31 | expect(Cl.getValue()).toEqual("Updated: dank");
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we change the get/set variables to function declarations instead? If not, this is still fine.
14f480d
to
ee9364e
Compare
packages/babel-helper-create-class-features-plugin/src/fields.js
Outdated
Show resolved
Hide resolved
packages/babel-helper-create-class-features-plugin/src/fields.js
Outdated
Show resolved
Hide resolved
const value = prop.node.value || prop.scope.buildUndefinedNode(); | ||
if (!prop.isProperty() && (initAdded || !(getId || setId))) return; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: could you extract getId || setId
to an isAccessor
boolean variable?
I find it hard to read all these nested boolean expressions.
1bcccbd
to
5ec8290
Compare
5ec8290
to
fc24d84
Compare
cc @robpalme @nicolo-ribaudo @littledan