Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

ES private class elements#42458

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged

Conversation

@dragomirtitian
Copy link
Contributor

@dragomirtitiandragomirtitian commentedJan 22, 2021
edited
Loading

Private Class Elements

This PR implementsthe TC39 Stage-3 Private Methods and Accessors proposal as well asTC39 Stage 3 Static Class features.

Fixes#39066,#37677,#42985

Remaining Work

  • Resolve open questions (see below)
  • PR the finalized helpers totslib
  • Validate limitations below

Downlevel

WeakSets are used for instance private methods and accessors, in the same way that the existing Private Fields downlevel uses WeakMaps.

Instance Private Methods and Accessors

TypeScript

classSquare{    #size:number;constructor(size:number){this.#size=size;}get #diagonal(){returnMath.hypot(this.#size,this.#size);}area(){returnMath.pow(this.#diagonal,2)/2;}}constsquare=newSquare(7);console.log(square.area());// logs 49

JavaScript - ES2020 emit

var__classPrivateFieldSet=(this&&this.__classPrivateFieldSet)||function(receiver,privateMap,value){if(!privateMap.has(receiver)){thrownewTypeError("attempted to set private field on non-instance");}privateMap.set(receiver,value);returnvalue;};var__classPrivateFieldGet=(this&&this.__classPrivateFieldGet)||function(receiver,privateMap){if(!privateMap.has(receiver)){thrownewTypeError("attempted to get private field on non-instance");}returnprivateMap.get(receiver);};var__classPrivateAccessorGet=(this&&this.__classPrivateAccessorGet)||function(receiver,instances,fn){if(!instances.has(receiver)){thrownewTypeError("attempted to get private accessor on non-instance");}returnfn.call(receiver);};var_Square_size,_Square_diagonal_get,_Square_instances;classSquare{constructor(size){_Square_instances.add(this);_Square_size.set(this,void0);__classPrivateFieldSet(this,_Square_size,size);}area(){returnMath.pow(__classPrivateAccessorGet(this,_Square_instances,_Square_diagonal_get),2)/2;}}_Square_size=newWeakMap(),_Square_instances=newWeakSet(),_Square_diagonal_get=function_Square_diagonal_get(){returnMath.hypot(__classPrivateFieldGet(this,_Square_size),__classPrivateFieldGet(this,_Square_size));};constsquare=newSquare(7);console.log(square.area());// logs 49
Static Private Fields, Methods and Accessors
classA{static #field=10static #method() :void{}// no errorstaticget #roProp(){return0;}staticset #woProp(value:number){}staticget #prop(){return0}staticset #prop(value:number){}statictest(){console.log(A.#field);A.#field=10;A.#method();console.log(A.#roProp);A.#roProp=10console.log(A.#woProp);A.#woProp=10console.log(A.#prop);A.#prop=10}}

JavaScript - ES2020 emit

var__classStaticPrivateFieldGet=(this&&this.__classStaticPrivateFieldGet)||function(receiver,classConstructor,propertyDescriptor){if(receiver!==classConstructor){thrownewTypeError("Private static access of wrong provenance");}if(propertyDescriptor===undefined){thrownewTypeError("Private static field was accessed before its declaration.");}returnpropertyDescriptor.value;};var__classStaticPrivateFieldSet=(this&&this.__classStaticPrivateFieldSet)||function(receiver,classConstructor,propertyDescriptor,value){if(receiver!==classConstructor){thrownewTypeError("Private static access of wrong provenance");}if(propertyDescriptor===undefined){thrownewTypeError("Private static field was accessed before its declaration.");}propertyDescriptor.value=value;returnvalue;};var__classStaticPrivateMethodGet=(this&&this.__classStaticPrivateMethodGet)||function(receiver,classConstructor,fn){if(receiver!==classConstructor){thrownewTypeError("Private static access of wrong provenance");}returnfn;};var__classStaticPrivateAccessorGet=(this&&this.__classStaticPrivateAccessorGet)||function(receiver,classConstructor,fn){if(receiver!==classConstructor){thrownewTypeError("Private static access of wrong provenance");}returnfn.call(receiver);};var__classStaticPrivateReadonly=(this&&this.__classStaticPrivateReadonly)||function(){thrownewTypeError("Private static element is not writable");};var__classStaticPrivateWriteonly=(this&&this.__classStaticPrivateWriteonly)||function(){thrownewTypeError("Private static element is not readable");};var__classStaticPrivateAccessorSet=(this&&this.__classStaticPrivateAccessorSet)||function(receiver,classConstructor,fn,value){if(receiver!==classConstructor){thrownewTypeError("Private static access of wrong provenance");}fn.call(receiver,value);returnvalue;};var_A_field,_A_method,_A_roProp_get,_A_woProp_set,_A_prop_get,_A_prop_set;classA{statictest(){console.log(__classStaticPrivateFieldGet(A,A,_A_field));__classStaticPrivateFieldSet(A,A,_A_field,10);__classStaticPrivateMethodGet(A,A,_A_method).call(A);console.log(__classStaticPrivateAccessorGet(A,A,_A_roProp_get));__classStaticPrivateReadonly(A,10);console.log(__classStaticPrivateWriteonly(A));__classStaticPrivateAccessorSet(A,A,_A_woProp_set,10);console.log(__classStaticPrivateAccessorGet(A,A,_A_prop_get));__classStaticPrivateAccessorSet(A,A,_A_prop_set,10);}}_A_method=function_A_method(){},_A_roProp_get=function_A_roProp_get(){return0;},_A_woProp_set=function_A_woProp_set(value){},_A_prop_get=function_A_prop_get(){return0;},_A_prop_set=function_A_prop_set(value){};_A_field={value:10};

References

Wider Contributions

Development of this PR led to these bug discoveries and fixes in other projects:

Credits

This PR includes contributions from the following Bloomberg engineers:

Design Limitations & Open Questions

  1. The pre-existing class fields transform can produce valid JavaScript from a syntactically invalid input. One example of this isduplicate private names. A similar issue will be visible in#constructor test since we now transform private methods. What is the desired TypeScript behavior in this case?

  2. This implementation does not work with the experimental Decorators in TypeScript. There is no spec for the interaction between these two features and implementing something non-standard that is likely to break in the future does not seem useful. Therefore we issue an error if a Decorators is used on a class containing a static private field/method/accessor.

Example
functiondec(){returnfunction(cls:new(...a:any)=>any){returnclassextendscls{staticsomeField=11;constructor(...a:any){super(...a);}}}}@dec()classFoo{staticsomeField=10;static #somePrivateField=10;staticm(){// displays 11 because decorator redefined it// and all references to Foo were rewritten to point to// whatever the decorator returnedFoo.someField// Right now this would always fail, since Foo will be rewritten// to point to whatever dec returned, so it will not point to the// class that actually defined `#somePrivateField`Foo.#somePrivateField}}
  1. Initializers are not allowed iftarget: esnext ANDuseDefineForClassFields: false. This is due to the fact that initializing private fields outside of a class is a non-trivial transform (a possible solution is describedhere - a modified version of it could be applied if there is desire for this combination to allow it) and keeping the init in the class would change runtime ordering of initializers.

  2. this is not allow in static initialization expressions. The restriction isa pre-existing issue and so is considered out-of-scope of this PR.

  3. Unlike instance #private class elements, static #private class elements do not depend onWeakMap orWeakSet. This means that technically we could transpile static #private class elements fores5 or evenes3. However having different requirements for instance vs static #private class elements would probably cause more confusion than benefit. Therefore we retain the existing minimum target ofes2015 for using static #private class elements and will error otherwise.

ExE-Boss, aidant, tchetwin, robpalme, kaansey, ilkkao, beInDev, fwienber, mohatt, dubzzz, and 20 more reacted with thumbs up emojiorta, ilkkao, acutmore, cherryblossom000, dnalborczyk, ryall, ShlomiAltostra, and yuxino reacted with heart emojidnalborczyk, captain-yossarian, mkubilayk, tchetwin, and luciomartinez reacted with rocket emoji
@typescript-bottypescript-bot added the For Uncommitted BugPR for untriaged, rejected, closed or missing bug labelJan 22, 2021
@mkubilaykmkubilaykforce-pushed thees-private-methods-and-accessors branch fromeff2eda tofb73ccdCompareFebruary 3, 2021 11:00
dragomirtitianand others added28 commitsFebruary 3, 2021 18:44
…ing except classes.Changes objects literal checking to not bail on first private name found in object literal.
Signed-off-by: Kubilay Kahveci <kahvecikubilay@gmail.com>
Signed-off-by: Kubilay Kahveci <kahvecikubilay@gmail.com>
Signed-off-by: Kubilay Kahveci <kahvecikubilay@gmail.com>
Signed-off-by: Kubilay Kahveci <kahvecikubilay@gmail.com>
Signed-off-by: Kubilay Kahveci <kahvecikubilay@gmail.com>
Signed-off-by: Kubilay Kahveci <kahvecikubilay@gmail.com>
Private methods inside class expressions should not error.Signed-off-by: Kubilay Kahveci <kahvecikubilay@gmail.com>
Signed-off-by: Kubilay Kahveci <kahvecikubilay@gmail.com>
Signed-off-by: Kubilay Kahveci <kahvecikubilay@gmail.com>
…y assignmentSigned-off-by: Kubilay Kahveci <kahvecikubilay@gmail.com>
Signed-off-by: Kubilay Kahveci <kahvecikubilay@gmail.com>
Signed-off-by: Kubilay Kahveci <kahvecikubilay@gmail.com>
Signed-off-by: Kubilay Kahveci <kahvecikubilay@gmail.com>
Signed-off-by: Kubilay Kahveci <kahvecikubilay@gmail.com>
Signed-off-by: Kubilay Kahveci <kahvecikubilay@gmail.com>
Signed-off-by: Kubilay Kahveci <kahvecikubilay@gmail.com>
Signed-off-by: Kubilay Kahveci <kahvecikubilay@gmail.com>
Signed-off-by: Kubilay Kahveci <kahvecikubilay@gmail.com>
Signed-off-by: Kubilay Kahveci <kahvecikubilay@gmail.com>
Signed-off-by: Kubilay Kahveci <kahvecikubilay@gmail.com>
Signed-off-by: Kubilay Kahveci <kahvecikubilay@gmail.com>
Signed-off-by: Kubilay Kahveci <kahvecikubilay@gmail.com>
Signed-off-by: Kubilay Kahveci <kahvecikubilay@gmail.com>
@mkubilayk
Copy link
Contributor

Createdmicrosoft/tslib#146 fortslib updates.

@rbuckton thanks for the review again. I think this is ready for another round.

Copy link
Contributor

@rbucktonrbuckton left a comment

Choose a reason for hiding this comment

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

The proposed changes (as well as relevant changes increatePrivateIdentifierAssignment) should address the comment issue.

@mkubilayk
Copy link
Contributor

@rbuckton Thanks a lot for taking the time to debug this. I made the changes you suggested.


// leave invalid code untransformed
constinfo=accessPrivateIdentifier(node.name);
Debug.assert(info,"Undeclared private name for property declaration.");
Copy link
Contributor

@rbucktonrbucktonMar 25, 2021
edited
Loading

Choose a reason for hiding this comment

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

Can a user write source text that would fail this assertion?

Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think so. That would indicate a bug inaddPrivateIdentifierToEnvironment.

@rbucktonrbuckton merged commite638af7 intomicrosoft:masterMar 25, 2021
@rbuckton
Copy link
Contributor

This has been a tremendous effort. I'm happy to see these changes go in and look forward to the community having a chance to test them in nightlies starting tomorrow!

cherryblossom000, ExE-Boss, zajrik, robpalme, vkrol, pabloai, mkubilayk, intrnl, dragomirtitian, almeidx, and danieltroger reacted with hooray emojiExE-Boss, vkrol, tchetwin, and dragomirtitian reacted with rocket emoji

@Kingwl
Copy link
Contributor

Congrats! Great work!

dragomirtitian, robpalme, and mkubilayk reacted with heart emoji

@orta
Copy link
Contributor

Thenightly playground build just shipped for folks interested in playing with it. Also congrats, serious work this.

mkubilayk, ExE-Boss, dragomirtitian, robpalme, Yash-Singh1, dnalborczyk, and danieltroger reacted with hooray emoji

@danieltroger
Copy link

Hello, why is vs code still saying "A method cannot be named with a private identifier."? Shouldn't it stop since this PR has been merged since quite some time now?

@acutmore
Copy link
Contributor

Hello, why is vs code still saying "A method cannot be named with a private identifier."? Shouldn't it stop since this PR has been merged since quite some time now?

Hi@danieltroger, private methods will be part of TypeScript 4.3 which is still in Beta.

danieltroger reacted with confused emoji

@danieltroger
Copy link

@acutmore I see, thank you for the swift reply. Any idea when it will be released? I feel like it will, even after the release, still take a long time until it lands in editors :(

Is it easy to switch to beta? I'm mainly using atom andhttps://github.com/TypeStrong/atom-typescript

@acutmore
Copy link
Contributor

@acutmore I see, thank you for the swift reply. Any idea when it will be released? I feel like it will, even after the release, still take a long time until it lands in editors :(

4.3 is likely to be released at the end of May#42762
https://devblogs.microsoft.com/typescript/announcing-typescript-4-3-beta/#whats-next

Is it easy to switch to beta? I'm mainly using atom andhttps://github.com/TypeStrong/atom-typescript

The atom-typescript docs say you can use a specific version of TypeScript by installing it.
https://github.com/TypeStrong/atom-typescript/blob/master/docs/faq.md#which-version-of-typescript-does-atom-typescript-use

npm install typescript@4.3.0-beta
danieltroger reacted with thumbs up emojidanieltroger and luciomartinez reacted with hooray emojidanieltroger reacted with heart emojidanieltroger reacted with rocket emoji

@danieltroger
Copy link

danieltroger commentedMay 4, 2021
edited
Loading

Yo it worked, finally no red, thanks a lot! I got into npm conflict hell tho

@mahnunchik
Copy link

When is ETA? It is horriblemicrosoft/vscode#106351

najamelan reacted with thumbs up emoji

@acutmoreacutmore mentioned this pull requestJun 18, 2021
1 task
@dragomirtitiandragomirtitian deleted the es-private-methods-and-accessors branchNovember 17, 2023 15:56
@microsoftmicrosoft locked asresolvedand limited conversation to collaboratorsOct 16, 2025
Sign up for freeto subscribe to this conversation on GitHub. Already have an account?Sign in.

Reviewers

2 more reviewers

@mkubilaykmkubilaykmkubilayk left review comments

@rbucktonrbucktonrbuckton approved these changes

Reviewers whose approvals may not affect merge requirements

Assignees

@rbucktonrbuckton

Labels

For Uncommitted BugPR for untriaged, rejected, closed or missing bug

Projects

Archived in project

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Add support for ES.Next private methods and private accessor properties

10 participants

@dragomirtitian@typescript-bot@rbuckton@ExE-Boss@mkubilayk@Kingwl@orta@danieltroger@acutmore@mahnunchik

[8]ページ先頭

©2009-2025 Movatter.jp