@@ -149,7 +149,7 @@ namespace ts {
149
149
if ( capturedSuperProperties && isPropertyAccessExpression ( node ) && node . expression . kind === SyntaxKind . SuperKeyword ) {
150
150
capturedSuperProperties . set ( node . name . escapedText , true ) ;
151
151
}
152
- return visitEachChild ( node , visitor , context ) ;
152
+ return visitPropertyAccessExpression ( node as PropertyAccessExpression ) ;
153
153
case SyntaxKind . ElementAccessExpression :
154
154
if ( capturedSuperProperties && ( < ElementAccessExpression > node ) . expression . kind === SyntaxKind . SuperKeyword ) {
155
155
hasSuperElementAccess = true ;
@@ -165,6 +165,10 @@ namespace ts {
165
165
return visitVariableStatement ( node as VariableStatement ) ;
166
166
case SyntaxKind . ComputedPropertyName :
167
167
return visitComputedPropertyName ( node as ComputedPropertyName ) ;
168
+ case SyntaxKind . PrefixUnaryExpression :
169
+ return visitPrefixUnaryExpression ( node as PrefixUnaryExpression ) ;
170
+ case SyntaxKind . PostfixUnaryExpression :
171
+ return visitPostfixUnaryExpression ( node as PostfixUnaryExpression ) ;
168
172
default :
169
173
return visitEachChild ( node , visitor , context ) ;
170
174
}
@@ -587,6 +591,98 @@ namespace ts {
587
591
return undefined ;
588
592
}
589
593
594
+ function visitPropertyAccessExpression ( node : PropertyAccessExpression ) {
595
+ if ( isPrivateName ( node . name ) ) {
596
+ const privateNameInfo = accessPrivateName ( node . name ) ;
597
+ if ( privateNameInfo ) {
598
+ switch ( privateNameInfo . type ) {
599
+ case PrivateNameType . InstanceField :
600
+ return setOriginalNode (
601
+ setTextRange (
602
+ createClassPrivateFieldGetHelper (
603
+ context ,
604
+ visitNode ( node . expression , visitor , isExpression ) ,
605
+ privateNameInfo . weakMapName
606
+ ) ,
607
+ node
608
+ ) ,
609
+ node
610
+ ) ;
611
+ }
612
+ }
613
+ }
614
+ return visitEachChild ( node , visitor , context ) ;
615
+ }
616
+
617
+ function visitPrefixUnaryExpression ( node : PrefixUnaryExpression ) {
618
+ if ( isPrivateNamedPropertyAccessExpression ( node . operand ) ) {
619
+ const operator = ( node . operator === SyntaxKind . PlusPlusToken ) ?
620
+ SyntaxKind . PlusEqualsToken : ( node . operator === SyntaxKind . MinusMinusToken ) ?
621
+ SyntaxKind . MinusEqualsToken : undefined ;
622
+ if ( operator ) {
623
+ const transformedExpr = setOriginalNode (
624
+ createBinary (
625
+ node . operand ,
626
+ operator ,
627
+ createNumericLiteral ( "1" )
628
+ ) ,
629
+ node
630
+ ) ;
631
+ const visited = visitNode ( transformedExpr , visitor ) ;
632
+ // If the private name was successfully transformed,
633
+ // return the transformed node. Otherwise, leave existing source untouched.
634
+ if ( visited !== transformedExpr ) {
635
+ return visited ;
636
+ }
637
+ }
638
+ }
639
+ return visitEachChild ( node , visitor , context ) ;
640
+ }
641
+
642
+ function visitPostfixUnaryExpression ( node : PostfixUnaryExpression ) {
643
+ if ( isPrivateNamedPropertyAccessExpression ( node . operand ) ) {
644
+ const operator = ( node . operator === SyntaxKind . PlusPlusToken ) ?
645
+ SyntaxKind . PlusToken : ( node . operator === SyntaxKind . MinusMinusToken ) ?
646
+ SyntaxKind . MinusToken : undefined ;
647
+ if ( operator ) {
648
+ // Create a temporary variable if the receiver is not inlinable, since we
649
+ // will need to access it multiple times.
650
+ const receiver = isSimpleInlineableExpression ( node . operand . expression ) ?
651
+ undefined :
652
+ getGeneratedNameForNode ( node . operand . expression ) ;
653
+ // Create a temporary variable to store the value returned by the expression.
654
+ const returnValue = createTempVariable ( /*recordTempVariable*/ undefined ) ;
655
+
656
+ const transformedExpr = createCommaList ( compact ( [
657
+ receiver && createAssignment ( receiver , node . operand . expression ) ,
658
+ // Store the existing value of the private name in the temporary.
659
+ createAssignment ( returnValue , receiver ? createPropertyAccess ( receiver , node . operand . name ) : node . operand ) ,
660
+ // Assign to private name.
661
+ createAssignment (
662
+ receiver ? createPropertyAccess ( receiver , node . operand . name ) : node . operand ,
663
+ createBinary (
664
+ returnValue , operator , createNumericLiteral ( "1" )
665
+ )
666
+ ) ,
667
+ // Return the cached value.
668
+ returnValue
669
+ ] ) as Expression [ ] ) ;
670
+ const visited = visitNode ( transformedExpr , visitor ) ;
671
+ // If the private name was successfully transformed,
672
+ // hoist the temporary variable and return the transformed node.
673
+ // Otherwise, leave existing source untouched.
674
+ if ( visited !== transformedExpr ) {
675
+ if ( receiver ) {
676
+ hoistVariableDeclaration ( receiver ) ;
677
+ }
678
+ hoistVariableDeclaration ( returnValue ) ;
679
+ return visited ;
680
+ }
681
+ }
682
+ }
683
+ return visitEachChild ( node , visitor , context ) ;
684
+ }
685
+
590
686
function enableSubstitutionForClassAliases ( ) {
591
687
if ( ( enabledSubstitutions & ESNextSubstitutionFlags . ClassAliases ) === 0 ) {
592
688
enabledSubstitutions |= ESNextSubstitutionFlags . ClassAliases ;
@@ -761,6 +857,46 @@ namespace ts {
761
857
visitNode ( node . right , noDestructuringValue ? visitorNoDestructuringValue : visitor , isExpression )
762
858
) ;
763
859
}
860
+ else if ( isAssignmentExpression ( node ) && isPropertyAccessExpression ( node . left ) && isPrivateName ( node . left . name ) ) {
861
+ const privateNameInfo = accessPrivateName ( node . left . name ) ;
862
+ if ( privateNameInfo && privateNameInfo . type === PrivateNameType . InstanceField ) {
863
+ if ( isCompoundAssignment ( node . operatorToken . kind ) ) {
864
+ const isReceiverInlineable = isSimpleInlineableExpression ( node . left . expression ) ;
865
+ const getReceiver = isReceiverInlineable ? node . left . expression : createTempVariable ( hoistVariableDeclaration ) ;
866
+ const setReceiver = isReceiverInlineable
867
+ ? node . left . expression
868
+ : createAssignment ( getReceiver , node . left . expression ) ;
869
+ return setOriginalNode (
870
+ createClassPrivateFieldSetHelper (
871
+ context ,
872
+ setReceiver ,
873
+ privateNameInfo . weakMapName ,
874
+ createBinary (
875
+ createClassPrivateFieldGetHelper (
876
+ context ,
877
+ getReceiver ,
878
+ privateNameInfo . weakMapName
879
+ ) ,
880
+ getOperatorForCompoundAssignment ( node . operatorToken . kind ) ,
881
+ visitNode ( node . right , visitor )
882
+ )
883
+ ) ,
884
+ node
885
+ ) ;
886
+ }
887
+ else {
888
+ return setOriginalNode (
889
+ createClassPrivateFieldSetHelper (
890
+ context ,
891
+ node . left . expression ,
892
+ privateNameInfo . weakMapName ,
893
+ visitNode ( node . right , visitor )
894
+ ) ,
895
+ node
896
+ ) ;
897
+ }
898
+ }
899
+ }
764
900
return visitEachChild ( node , visitor , context ) ;
765
901
}
766
902
@@ -1587,4 +1723,26 @@ namespace ts {
1587
1723
location
1588
1724
) ;
1589
1725
}
1726
+
1727
+ const classPrivateFieldGetHelper : EmitHelper = {
1728
+ name : "typescript:classPrivateFieldGet" ,
1729
+ scoped : false ,
1730
+ text : `var _classPrivateFieldGet = function (receiver, privateMap) { if (!privateMap.has(receiver)) { throw new TypeError("attempted to get private field on non-instance"); } return privateMap.get(receiver); };`
1731
+ } ;
1732
+
1733
+ function createClassPrivateFieldGetHelper ( context : TransformationContext , receiver : Expression , privateField : Identifier ) {
1734
+ context . requestEmitHelper ( classPrivateFieldGetHelper ) ;
1735
+ return createCall ( getHelperName ( "_classPrivateFieldGet" ) , /* typeArguments */ undefined , [ receiver , privateField ] ) ;
1736
+ }
1737
+
1738
+ const classPrivateFieldSetHelper : EmitHelper = {
1739
+ name : "typescript:classPrivateFieldSet" ,
1740
+ scoped : false ,
1741
+ text : `var _classPrivateFieldSet = function (receiver, privateMap, value) { if (!privateMap.has(receiver)) { throw new TypeError("attempted to set private field on non-instance"); } privateMap.set(receiver, value); return value; };`
1742
+ } ;
1743
+
1744
+ function createClassPrivateFieldSetHelper ( context : TransformationContext , receiver : Expression , privateField : Identifier , value : Expression ) {
1745
+ context . requestEmitHelper ( classPrivateFieldSetHelper ) ;
1746
+ return createCall ( getHelperName ( "_classPrivateFieldSet" ) , /* typeArguments */ undefined , [ receiver , privateField , value ] ) ;
1747
+ }
1590
1748
}
0 commit comments