@@ -720,6 +720,104 @@ func (p *parser) lowerClass(stmt js_ast.Stmt, expr js_ast.Expr, result visitClas
720720 }
721721 }
722722
723+ // If this returns true, the method property should be dropped as it has
724+ // already been accounted for elsewhere (e.g. a lowered private method).
725+ lowerMethod := func (prop js_ast.Property , private * js_ast.EPrivateIdentifier ) bool {
726+ if private != nil && p .privateSymbolNeedsToBeLowered (private ) {
727+ loc := prop .Loc
728+
729+ // Don't generate a symbol for a getter/setter pair twice
730+ if p .symbols [private .Ref .InnerIndex ].Link == js_ast .InvalidRef {
731+ // Generate a new symbol for this private method
732+ ref := p .generateTempRef (tempRefNeedsDeclare , "_" + p .symbols [private .Ref .InnerIndex ].OriginalName [1 :])
733+ p .symbols [private .Ref .InnerIndex ].Link = ref
734+
735+ // Initialize the private method to a new WeakSet
736+ if p .weakSetRef == js_ast .InvalidRef {
737+ p .weakSetRef = p .newSymbol (js_ast .SymbolUnbound , "WeakSet" )
738+ p .moduleScope .Generated = append (p .moduleScope .Generated , p .weakSetRef )
739+ }
740+ privateMembers = append (privateMembers , js_ast .Assign (
741+ js_ast.Expr {Loc : prop .Key .Loc , Data : & js_ast.EIdentifier {Ref : ref }},
742+ js_ast.Expr {Loc : prop .Key .Loc , Data : & js_ast.ENew {Target : js_ast.Expr {Loc : prop .Key .Loc , Data : & js_ast.EIdentifier {Ref : p .weakSetRef }}}},
743+ ))
744+ p .recordUsage (ref )
745+
746+ // Determine where to store the private method
747+ var target js_ast.Expr
748+ if prop .Flags .Has (js_ast .PropertyIsStatic ) {
749+ target = nameFunc ()
750+ } else {
751+ target = js_ast.Expr {Loc : loc , Data : js_ast .EThisShared }
752+ }
753+
754+ // Add every newly-constructed instance into this map
755+ methodExpr := p .callRuntime (loc , "__privateAdd" , []js_ast.Expr {
756+ target ,
757+ {Loc : prop .Key .Loc , Data : & js_ast.EIdentifier {Ref : ref }},
758+ })
759+ p .recordUsage (ref )
760+
761+ // Make sure that adding to the map happens before any field
762+ // initializers to handle cases like this:
763+ //
764+ // class A {
765+ // pub = this.#priv;
766+ // #priv() {}
767+ // }
768+ //
769+ if prop .Flags .Has (js_ast .PropertyIsStatic ) {
770+ // Move this property to an assignment after the class ends
771+ staticPrivateMethods = append (staticPrivateMethods , methodExpr )
772+ } else {
773+ // Move this property to an assignment inside the class constructor
774+ instancePrivateMethods = append (instancePrivateMethods , js_ast.Stmt {Loc : loc , Data : & js_ast.SExpr {Value : methodExpr }})
775+ }
776+ }
777+
778+ // Move the method definition outside the class body
779+ methodRef := p .generateTempRef (tempRefNeedsDeclare , "_" )
780+ if prop .Kind == js_ast .PropertySet {
781+ p .symbols [methodRef .InnerIndex ].Link = p .privateSetters [private .Ref ]
782+ } else {
783+ p .symbols [methodRef .InnerIndex ].Link = p .privateGetters [private .Ref ]
784+ }
785+ p .recordUsage (methodRef )
786+ privateMembers = append (privateMembers , js_ast .Assign (
787+ js_ast.Expr {Loc : prop .Key .Loc , Data : & js_ast.EIdentifier {Ref : methodRef }},
788+ prop .ValueOrNil ,
789+ ))
790+ return true
791+ }
792+
793+ if key , ok := prop .Key .Data .(* js_ast.EString ); ok && helpers .UTF16EqualsString (key .Value , "constructor" ) {
794+ if fn , ok := prop .ValueOrNil .Data .(* js_ast.EFunction ); ok {
795+ // Remember where the constructor is for later
796+ ctor = fn
797+
798+ // Initialize TypeScript constructor parameter fields
799+ if p .options .ts .Parse {
800+ for _ , arg := range ctor .Fn .Args {
801+ if arg .IsTypeScriptCtorField {
802+ if id , ok := arg .Binding .Data .(* js_ast.BIdentifier ); ok {
803+ parameterFields = append (parameterFields , js_ast .AssignStmt (
804+ js_ast.Expr {Loc : arg .Binding .Loc , Data : p .dotOrMangledPropVisit (
805+ js_ast.Expr {Loc : arg .Binding .Loc , Data : js_ast .EThisShared },
806+ p .symbols [id .Ref .InnerIndex ].OriginalName ,
807+ arg .Binding .Loc ,
808+ )},
809+ js_ast.Expr {Loc : arg .Binding .Loc , Data : & js_ast.EIdentifier {Ref : id .Ref }},
810+ ))
811+ }
812+ }
813+ }
814+ }
815+ }
816+ }
817+
818+ return false
819+ }
820+
723821 classLoweringInfo := p .computeClassLoweringInfo (class )
724822
725823 for _ , prop := range class .Properties {
@@ -1050,96 +1148,9 @@ func (p *parser) lowerClass(stmt js_ast.Stmt, expr js_ast.Expr, result visitClas
10501148 prop .InitializerOrNil = js_ast.Expr {}
10511149 }
10521150
1053- if prop .Flags .Has (js_ast .PropertyIsMethod ) {
1054- if mustLowerPrivate {
1055- loc := prop .Loc
1056-
1057- // Don't generate a symbol for a getter/setter pair twice
1058- if p .symbols [private .Ref .InnerIndex ].Link == js_ast .InvalidRef {
1059- // Generate a new symbol for this private method
1060- ref := p .generateTempRef (tempRefNeedsDeclare , "_" + p .symbols [private .Ref .InnerIndex ].OriginalName [1 :])
1061- p .symbols [private .Ref .InnerIndex ].Link = ref
1062-
1063- // Initialize the private method to a new WeakSet
1064- if p .weakSetRef == js_ast .InvalidRef {
1065- p .weakSetRef = p .newSymbol (js_ast .SymbolUnbound , "WeakSet" )
1066- p .moduleScope .Generated = append (p .moduleScope .Generated , p .weakSetRef )
1067- }
1068- privateMembers = append (privateMembers , js_ast .Assign (
1069- js_ast.Expr {Loc : prop .Key .Loc , Data : & js_ast.EIdentifier {Ref : ref }},
1070- js_ast.Expr {Loc : prop .Key .Loc , Data : & js_ast.ENew {Target : js_ast.Expr {Loc : prop .Key .Loc , Data : & js_ast.EIdentifier {Ref : p .weakSetRef }}}},
1071- ))
1072- p .recordUsage (ref )
1073-
1074- // Determine where to store the private method
1075- var target js_ast.Expr
1076- if prop .Flags .Has (js_ast .PropertyIsStatic ) {
1077- target = nameFunc ()
1078- } else {
1079- target = js_ast.Expr {Loc : loc , Data : js_ast .EThisShared }
1080- }
1081-
1082- // Add every newly-constructed instance into this map
1083- methodExpr := p .callRuntime (loc , "__privateAdd" , []js_ast.Expr {
1084- target ,
1085- {Loc : prop .Key .Loc , Data : & js_ast.EIdentifier {Ref : ref }},
1086- })
1087- p .recordUsage (ref )
1088-
1089- // Make sure that adding to the map happens before any field
1090- // initializers to handle cases like this:
1091- //
1092- // class A {
1093- // pub = this.#priv;
1094- // #priv() {}
1095- // }
1096- //
1097- if prop .Flags .Has (js_ast .PropertyIsStatic ) {
1098- // Move this property to an assignment after the class ends
1099- staticPrivateMethods = append (staticPrivateMethods , methodExpr )
1100- } else {
1101- // Move this property to an assignment inside the class constructor
1102- instancePrivateMethods = append (instancePrivateMethods , js_ast.Stmt {Loc : loc , Data : & js_ast.SExpr {Value : methodExpr }})
1103- }
1104- }
1105-
1106- // Move the method definition outside the class body
1107- methodRef := p .generateTempRef (tempRefNeedsDeclare , "_" )
1108- if prop .Kind == js_ast .PropertySet {
1109- p .symbols [methodRef .InnerIndex ].Link = p .privateSetters [private .Ref ]
1110- } else {
1111- p .symbols [methodRef .InnerIndex ].Link = p .privateGetters [private .Ref ]
1112- }
1113- p .recordUsage (methodRef )
1114- privateMembers = append (privateMembers , js_ast .Assign (
1115- js_ast.Expr {Loc : prop .Key .Loc , Data : & js_ast.EIdentifier {Ref : methodRef }},
1116- prop .ValueOrNil ,
1117- ))
1118- continue
1119- } else if key , ok := prop .Key .Data .(* js_ast.EString ); ok && helpers .UTF16EqualsString (key .Value , "constructor" ) {
1120- if fn , ok := prop .ValueOrNil .Data .(* js_ast.EFunction ); ok {
1121- // Remember where the constructor is for later
1122- ctor = fn
1123-
1124- // Initialize TypeScript constructor parameter fields
1125- if p .options .ts .Parse {
1126- for _ , arg := range ctor .Fn .Args {
1127- if arg .IsTypeScriptCtorField {
1128- if id , ok := arg .Binding .Data .(* js_ast.BIdentifier ); ok {
1129- parameterFields = append (parameterFields , js_ast .AssignStmt (
1130- js_ast.Expr {Loc : arg .Binding .Loc , Data : p .dotOrMangledPropVisit (
1131- js_ast.Expr {Loc : arg .Binding .Loc , Data : js_ast .EThisShared },
1132- p .symbols [id .Ref .InnerIndex ].OriginalName ,
1133- arg .Binding .Loc ,
1134- )},
1135- js_ast.Expr {Loc : arg .Binding .Loc , Data : & js_ast.EIdentifier {Ref : id .Ref }},
1136- ))
1137- }
1138- }
1139- }
1140- }
1141- }
1142- }
1151+ // Lower methods
1152+ if prop .Flags .Has (js_ast .PropertyIsMethod ) && lowerMethod (prop , private ) {
1153+ continue
11431154 }
11441155
11451156 // Keep this property
0 commit comments