@@ -1365,8 +1365,10 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri
13651365 let privateNameTempFlags : TempFlags ; // TempFlags for the current name generation scope.
13661366 let tempFlagsStack : TempFlags [ ] ; // Stack of enclosing name generation scopes.
13671367 let tempFlags : TempFlags ; // TempFlags for the current name generation scope.
1368- let reservedNamesStack : Set < string > [ ] ; // Stack of TempFlags reserved in enclosing name generation scopes.
1369- let reservedNames : Set < string > ; // TempFlags to reserve in nested name generation scopes.
1368+ let reservedNamesStack : ( Set < string > | undefined ) [ ] ; // Stack of reserved names in enclosing name generation scopes.
1369+ let reservedNames : Set < string > | undefined ; // Names reserved in nested name generation scopes.
1370+ let reservedPrivateNamesStack : ( Set < string > | undefined ) [ ] ; // Stack of reserved member names in enclosing name generation scopes.
1371+ let reservedPrivateNames : Set < string > | undefined ; // Member names reserved in nested name generation scopes.
13701372 let preserveSourceNewlines = printerOptions . preserveSourceNewlines ; // Can be overridden inside nodes with the `IgnoreSourceNewlines` emit flag.
13711373 let nextListElementPos : number | undefined ; // See comment in `getLeadingLineTerminatorCount`.
13721374
@@ -1658,6 +1660,9 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri
16581660 tempFlagsStack = [ ] ;
16591661 tempFlags = TempFlags . Auto ;
16601662 reservedNamesStack = [ ] ;
1663+ reservedNames = undefined ;
1664+ reservedPrivateNamesStack = [ ] ;
1665+ reservedPrivateNames = undefined ;
16611666 currentSourceFile = undefined ;
16621667 currentLineMap = undefined ;
16631668 detachedCommentsInfo = undefined ;
@@ -2501,9 +2506,13 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri
25012506 }
25022507
25032508 function emitComputedPropertyName ( node : ComputedPropertyName ) {
2509+ const savedPrivateNameTempFlags = privateNameTempFlags ;
2510+ const savedReservedMemberNames = reservedPrivateNames ;
2511+ popPrivateNameGenerationScope ( ) ;
25042512 writePunctuation ( "[" ) ;
25052513 emitExpression ( node . expression , parenthesizer . parenthesizeExpressionOfComputedPropertyName ) ;
25062514 writePunctuation ( "]" ) ;
2515+ pushPrivateNameGenerationScope ( savedPrivateNameTempFlags , savedReservedMemberNames ) ;
25072516 }
25082517
25092518 //
@@ -2723,10 +2732,16 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri
27232732 }
27242733
27252734 function emitTypeLiteral ( node : TypeLiteralNode ) {
2735+ // Type literals don't have private names, but we need to push a new scope so that
2736+ // we can step out of it when emitting a computed property.
2737+ pushPrivateNameGenerationScope ( TempFlags . Auto , /*newReservedMemberNames*/ undefined ) ;
2738+
27262739 writePunctuation ( "{" ) ;
27272740 const flags = getEmitFlags ( node ) & EmitFlags . SingleLine ? ListFormat . SingleLineTypeLiteralMembers : ListFormat . MultiLineTypeLiteralMembers ;
27282741 emitList ( node , node . members , flags | ListFormat . NoSpaceIfEmpty ) ;
27292742 writePunctuation ( "}" ) ;
2743+
2744+ popPrivateNameGenerationScope ( ) ;
27302745 }
27312746
27322747 function emitArrayType ( node : ArrayTypeNode ) {
@@ -2943,6 +2958,9 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri
29432958 }
29442959
29452960 function emitObjectLiteralExpression ( node : ObjectLiteralExpression ) {
2961+ // Object literals don't have private names, but we need to push a new scope so that
2962+ // we can step out of it when emitting a computed property.
2963+ pushPrivateNameGenerationScope ( TempFlags . Auto , /*newReservedMemberNames*/ undefined ) ;
29462964 forEach ( node . properties , generateMemberNames ) ;
29472965
29482966 const indentedFlag = getEmitFlags ( node ) & EmitFlags . Indented ;
@@ -2957,6 +2975,8 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri
29572975 if ( indentedFlag ) {
29582976 decreaseIndent ( ) ;
29592977 }
2978+
2979+ popPrivateNameGenerationScope ( ) ;
29602980 }
29612981
29622982 function emitPropertyAccessExpression ( node : PropertyAccessExpression ) {
@@ -3763,6 +3783,8 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri
37633783 }
37643784
37653785 function emitClassDeclarationOrExpression ( node : ClassDeclaration | ClassExpression ) {
3786+ pushPrivateNameGenerationScope ( TempFlags . Auto , /*newReservedMemberNames*/ undefined ) ;
3787+
37663788 forEach ( node . members , generateMemberNames ) ;
37673789
37683790 emitDecoratorsAndModifiers ( node , node . modifiers ) ;
@@ -3788,9 +3810,15 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri
37883810 if ( indentedFlag ) {
37893811 decreaseIndent ( ) ;
37903812 }
3813+
3814+ popPrivateNameGenerationScope ( ) ;
37913815 }
37923816
37933817 function emitInterfaceDeclaration ( node : InterfaceDeclaration ) {
3818+ // Interfaces don't have private names, but we need to push a new scope so that
3819+ // we can step out of it when emitting a computed property.
3820+ pushPrivateNameGenerationScope ( TempFlags . Auto , /*newReservedMemberNames*/ undefined ) ;
3821+
37943822 emitModifiers ( node , node . modifiers ) ;
37953823 writeKeyword ( "interface" ) ;
37963824 writeSpace ( ) ;
@@ -3801,6 +3829,8 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri
38013829 writePunctuation ( "{" ) ;
38023830 emitList ( node , node . members , ListFormat . InterfaceMembers ) ;
38033831 writePunctuation ( "}" ) ;
3832+
3833+ popPrivateNameGenerationScope ( ) ;
38043834 }
38053835
38063836 function emitTypeAliasDeclaration ( node : TypeAliasDeclaration ) {
@@ -5486,8 +5516,6 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri
54865516 }
54875517 tempFlagsStack . push ( tempFlags ) ;
54885518 tempFlags = TempFlags . Auto ;
5489- privateNameTempFlagsStack . push ( privateNameTempFlags ) ;
5490- privateNameTempFlags = TempFlags . Auto ;
54915519 formattedNameTempFlagsStack . push ( formattedNameTempFlags ) ;
54925520 formattedNameTempFlags = undefined ;
54935521 reservedNamesStack . push ( reservedNames ) ;
@@ -5501,9 +5529,8 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri
55015529 return ;
55025530 }
55035531 tempFlags = tempFlagsStack . pop ( ) ! ;
5504- privateNameTempFlags = privateNameTempFlagsStack . pop ( ) ! ;
55055532 formattedNameTempFlags = formattedNameTempFlagsStack . pop ( ) ;
5506- reservedNames = reservedNamesStack . pop ( ) ! ;
5533+ reservedNames = reservedNamesStack . pop ( ) ;
55075534 }
55085535
55095536 function reserveNameInNestedScopes ( name : string ) {
@@ -5513,6 +5540,31 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri
55135540 reservedNames . add ( name ) ;
55145541 }
55155542
5543+ /**
5544+ * Push a new member name generation scope.
5545+ */
5546+ function pushPrivateNameGenerationScope ( newPrivateNameTempFlags : TempFlags , newReservedMemberNames : Set < string > | undefined ) {
5547+ privateNameTempFlagsStack . push ( privateNameTempFlags ) ;
5548+ privateNameTempFlags = newPrivateNameTempFlags ;
5549+ reservedPrivateNamesStack . push ( reservedNames ) ;
5550+ reservedPrivateNames = newReservedMemberNames ;
5551+ }
5552+
5553+ /**
5554+ * Pop the current member name generation scope.
5555+ */
5556+ function popPrivateNameGenerationScope ( ) {
5557+ privateNameTempFlags = privateNameTempFlagsStack . pop ( ) ! ;
5558+ reservedPrivateNames = reservedPrivateNamesStack . pop ( ) ;
5559+ }
5560+
5561+ function reservePrivateNameInNestedScopes ( name : string ) {
5562+ if ( ! reservedPrivateNames || reservedPrivateNames === lastOrUndefined ( reservedPrivateNamesStack ) ) {
5563+ reservedPrivateNames = new Set ( ) ;
5564+ }
5565+ reservedPrivateNames . add ( name ) ;
5566+ }
5567+
55165568 function generateNames ( node : Node | undefined ) {
55175569 if ( ! node ) return ;
55185570 switch ( node . kind ) {
@@ -5650,16 +5702,23 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri
56505702 * Returns a value indicating whether a name is unique globally, within the current file,
56515703 * or within the NameGenerator.
56525704 */
5653- function isUniqueName ( name : string ) : boolean {
5654- return isFileLevelUniqueName ( name )
5655- && ! generatedNames . has ( name )
5656- && ! ( reservedNames && reservedNames . has ( name ) ) ;
5705+ function isUniqueName ( name : string , privateName : boolean ) : boolean {
5706+ return isFileLevelUniqueName ( name , privateName )
5707+ && ! isReservedName ( name , privateName )
5708+ && ! generatedNames . has ( name ) ;
5709+ }
5710+
5711+ function isReservedName ( name : string , privateName : boolean ) : boolean {
5712+ return privateName ? ! ! reservedPrivateNames ?. has ( name ) : ! ! reservedNames ?. has ( name ) ;
56575713 }
56585714
56595715 /**
56605716 * Returns a value indicating whether a name is unique globally or within the current file.
5717+ *
5718+ * @param _isPrivate (unused) this parameter exists to avoid an unnecessary adaptor frame in v8
5719+ * when `isfileLevelUniqueName` is passed as a callback to `makeUniqueName`.
56615720 */
5662- function isFileLevelUniqueName ( name : string ) {
5721+ function isFileLevelUniqueName ( name : string , _isPrivate : boolean ) {
56635722 return currentSourceFile ? ts . isFileLevelUniqueName ( currentSourceFile , name , hasGlobalName ) : true ;
56645723 }
56655724
@@ -5722,9 +5781,12 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri
57225781 if ( flags && ! ( tempFlags & flags ) ) {
57235782 const name = flags === TempFlags . _i ? "_i" : "_n" ;
57245783 const fullName = formatGeneratedName ( privateName , prefix , name , suffix ) ;
5725- if ( isUniqueName ( fullName ) ) {
5784+ if ( isUniqueName ( fullName , privateName ) ) {
57265785 tempFlags |= flags ;
5727- if ( reservedInNestedScopes ) {
5786+ if ( privateName ) {
5787+ reservePrivateNameInNestedScopes ( fullName ) ;
5788+ }
5789+ else if ( reservedInNestedScopes ) {
57285790 reserveNameInNestedScopes ( fullName ) ;
57295791 }
57305792 setTempFlags ( key , tempFlags ) ;
@@ -5741,8 +5803,11 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri
57415803 ? "_" + String . fromCharCode ( CharacterCodes . a + count )
57425804 : "_" + ( count - 26 ) ;
57435805 const fullName = formatGeneratedName ( privateName , prefix , name , suffix ) ;
5744- if ( isUniqueName ( fullName ) ) {
5745- if ( reservedInNestedScopes ) {
5806+ if ( isUniqueName ( fullName , privateName ) ) {
5807+ if ( privateName ) {
5808+ reservePrivateNameInNestedScopes ( fullName ) ;
5809+ }
5810+ else if ( reservedInNestedScopes ) {
57465811 reserveNameInNestedScopes ( fullName ) ;
57475812 }
57485813 setTempFlags ( key , tempFlags ) ;
@@ -5759,7 +5824,7 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri
57595824 * makeUniqueName are guaranteed to never conflict.
57605825 * If `optimistic` is set, the first instance will use 'baseName' verbatim instead of 'baseName_1'
57615826 */
5762- function makeUniqueName ( baseName : string , checkFn : ( name : string ) => boolean = isUniqueName , optimistic : boolean , scoped : boolean , privateName : boolean , prefix : string , suffix : string ) : string {
5827+ function makeUniqueName ( baseName : string , checkFn : ( name : string , privateName : boolean ) => boolean = isUniqueName , optimistic : boolean , scoped : boolean , privateName : boolean , prefix : string , suffix : string ) : string {
57635828 if ( baseName . length > 0 && baseName . charCodeAt ( 0 ) === CharacterCodes . hash ) {
57645829 baseName = baseName . slice ( 1 ) ;
57655830 }
@@ -5768,8 +5833,11 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri
57685833 }
57695834 if ( optimistic ) {
57705835 const fullName = formatGeneratedName ( privateName , prefix , baseName , suffix ) ;
5771- if ( checkFn ( fullName ) ) {
5772- if ( scoped ) {
5836+ if ( checkFn ( fullName , privateName ) ) {
5837+ if ( privateName ) {
5838+ reservePrivateNameInNestedScopes ( fullName ) ;
5839+ }
5840+ else if ( scoped ) {
57735841 reserveNameInNestedScopes ( fullName ) ;
57745842 }
57755843 else {
@@ -5785,8 +5853,11 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri
57855853 let i = 1 ;
57865854 while ( true ) {
57875855 const fullName = formatGeneratedName ( privateName , prefix , baseName + i , suffix ) ;
5788- if ( checkFn ( fullName ) ) {
5789- if ( scoped ) {
5856+ if ( checkFn ( fullName , privateName ) ) {
5857+ if ( privateName ) {
5858+ reservePrivateNameInNestedScopes ( fullName ) ;
5859+ }
5860+ else if ( scoped ) {
57905861 reserveNameInNestedScopes ( fullName ) ;
57915862 }
57925863 else {
0 commit comments