Skip to content

Transform private named instance fields #15

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

Conversation

joeywatts
Copy link

@joeywatts joeywatts commented Nov 21, 2018

Downlevel transform for ESNext private named instance fields. Uses WeakMaps to store the value for each private field, and helper functions to access and mutate the field.

Design Notes (and Insights for Implementation of Private Named Methods, Accessors, etc)

  • A "private name environment" stack is maintained in the ESNext transformer which keeps track of all the private names. This is a stack because private names are lexically scoped and you can nest classes.
  • When the ESNext transformer visits a class, it loops over all the class members and populates the private name environment (effectively a map from the private names to an object storing the necessary information for each private name) for that class.
  • At the usage sites of a private name, we look up the private name (using the private name environment stack). Based on the type of the private name, we can transform the usage sites differently.
  • Where possible, the transformation was designed to be agnostic of the type of private name. For example, unary modification operators (++, --) piggy-back off of the instance field access and assignment transformations by first transforming to an intermediate representation and then transforming that. this.#x++ will first transform to this.#x = this.#x + 1 and then will finally transform to _classPrivateFieldSet(this, _x, _classPrivateFieldGet(this, _x) + 1). So for private named get/set accessors, if the access and assignment transformations are implemented, most things should just work! Another example of this is the transformation of call expressions on private names, this.#myFunc() will first transform to this.#myFunc.call(this, /*...args*/) then it will rely on the private name property access transformation to perform the rest of the work. If property accesses are implemented for private named methods, then calling them should just work!

@@ -621,6 +621,9 @@ declare namespace ts {
type?: TypeNode;
initializer?: Expression;
}
interface PrivatePropertyDeclaration extends PropertyDeclaration {
Copy link

Choose a reason for hiding this comment

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

since this is public API:

  • maybe we don't need another interface for this
  • if we keep it, PrivateNamedPropertyDeclaration is probably more accurate, since there are already private properties

Choose a reason for hiding this comment

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

I don't have a strong opinion on the interface, but I'm with Max on the name. "private-named" is our official shortest adjective for this.

@@ -621,6 +621,9 @@ declare namespace ts {
type?: TypeNode;
initializer?: Expression;
}
interface PrivatePropertyDeclaration extends PropertyDeclaration {
Copy link

@mheiber mheiber Dec 7, 2018

Choose a reason for hiding this comment

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

@@ -3637,6 +3637,10 @@ namespace ts {
let excludeFlags = TransformFlags.NodeExcludes;
Copy link

@mheiber mheiber Dec 10, 2018

Choose a reason for hiding this comment

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

@joeywatts I think we can merge this soon. Would help if you could:

  • add a little bit more to the PR description:
    • what were some judgment calls or design decisions made in this PR?
    • are there outstanding issues with private-named fields not covered in this PR?
    • please note that this PR builds on Keep class properties in ESNext target #10
  • rebase this down to a few smaller commits

Copy link

Choose a reason for hiding this comment

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

✔️

/**
* A mapping of private names to information needed for transformation.
*/
type PrivateNameEnvironment = UnderscoreEscapedMap<PrivateNamedInstanceField>;
Copy link

Choose a reason for hiding this comment

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

as discussed, we will fiddle with this structure more in subsequent PRs (so that methods + static methods + getters can share the same WeakSet of instances)

Copy link

@Neuroboy23 Neuroboy23 left a comment

Choose a reason for hiding this comment

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

Looks good.

@@ -621,6 +621,9 @@ declare namespace ts {
type?: TypeNode;
initializer?: Expression;
}
interface PrivatePropertyDeclaration extends PropertyDeclaration {

Choose a reason for hiding this comment

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

I don't have a strong opinion on the interface, but I'm with Max on the name. "private-named" is our official shortest adjective for this.

@joeywatts joeywatts force-pushed the esnext-private-instance-fields branch from b416c58 to 4f59597 Compare December 17, 2018 22:09
Copy link

@mheiber mheiber left a comment

Choose a reason for hiding this comment

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

psyched about this

@joeywatts joeywatts force-pushed the esnext-private-instance-fields branch from 4f59597 to 2641392 Compare December 18, 2018 00:09
@mheiber mheiber closed this Dec 18, 2018
@mheiber mheiber reopened this Dec 18, 2018
Joseph Watts added 4 commits December 18, 2018 15:20
Signed-off-by: Joseph Watts <jwatts43@bloomberg.net>
Signed-off-by: Joseph Watts <jwatts43@bloomberg.net>
Signed-off-by: Joseph Watts <jwatts43@bloomberg.net>
Signed-off-by: Joseph Watts <jwatts43@bloomberg.net>
@joeywatts joeywatts force-pushed the esnext-private-instance-fields branch from 2641392 to fa17cdf Compare December 18, 2018 20:20
@Neuroboy23 Neuroboy23 merged commit 8bfc540 into bloomberg:es-private-fields Dec 18, 2018
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.

3 participants