@@ -35,7 +35,8 @@ namespace ts {
3535 const {
3636 hoistVariableDeclaration,
3737 endLexicalEnvironment,
38- resumeLexicalEnvironment
38+ resumeLexicalEnvironment,
39+ addBlockScopedVariable
3940 } = context ;
4041 const resolver = context . getEmitResolver ( ) ;
4142 const compilerOptions = context . getCompilerOptions ( ) ;
@@ -210,9 +211,12 @@ namespace ts {
210211 // Create a temporary variable to store a computed property name (if necessary).
211212 // If it's not inlineable, then we emit an expression after the class which assigns
212213 // the property name to the temporary variable.
213- const expr = getPropertyNameExpressionIfNeeded ( node . name , ! ! node . initializer || ! ! context . getCompilerOptions ( ) . useDefineForClassFields ) ;
214- if ( expr && ! isSimpleInlineableExpression ( expr ) ) {
215- ( pendingExpressions || ( pendingExpressions = [ ] ) ) . push ( expr ) ;
214+ // No need to transform static computed property names since they are only evaluated once.
215+ if ( ! hasStaticModifier ( node ) ) {
216+ const expr = getPropertyNameExpressionIfNeeded ( node . name , ! ! node . initializer || ! ! context . getCompilerOptions ( ) . useDefineForClassFields ) ;
217+ if ( expr && ! isSimpleInlineableExpression ( expr ) ) {
218+ ( pendingExpressions || ( pendingExpressions = [ ] ) ) . push ( expr ) ;
219+ }
216220 }
217221 return undefined ;
218222 }
@@ -532,8 +536,10 @@ namespace ts {
532536 }
533537 else {
534538 const expressions : Expression [ ] = [ ] ;
535- const isClassWithConstructorReference = resolver . getNodeCheckFlags ( node ) & NodeCheckFlags . ClassWithConstructorReference ;
536- const temp = createTempVariable ( hoistVariableDeclaration , ! ! isClassWithConstructorReference ) ;
539+ const classCheckFlags = resolver . getNodeCheckFlags ( node ) ;
540+ const isClassWithConstructorReference = classCheckFlags & NodeCheckFlags . ClassWithConstructorReference ;
541+ const requiresBlockScopedVar = classCheckFlags & NodeCheckFlags . BlockScopedBindingInLoop ;
542+ const temp = createTempVariable ( requiresBlockScopedVar ? addBlockScopedVariable : hoistVariableDeclaration , ! ! isClassWithConstructorReference ) ;
537543 if ( isClassWithConstructorReference ) {
538544 // record an alias as the class name is not in scope for statics.
539545 enableSubstitutionForClassAliases ( ) ;
@@ -748,7 +754,7 @@ namespace ts {
748754 function transformProperty ( property : PropertyDeclaration , receiver : LeftHandSideExpression ) {
749755 // We generate a name here in order to reuse the value cached by the relocated computed name expression (which uses the same generated name)
750756 const emitAssignment = ! context . getCompilerOptions ( ) . useDefineForClassFields ;
751- const propertyName = isComputedPropertyName ( property . name ) && ! isSimpleInlineableExpression ( property . name . expression )
757+ const propertyName = ! hasStaticModifier ( property ) && isComputedPropertyName ( property . name ) && ! isSimpleInlineableExpression ( property . name . expression )
752758 ? updateComputedPropertyName ( property . name , getGeneratedNameForNode ( property . name ) )
753759 : property . name ;
754760
@@ -858,7 +864,6 @@ namespace ts {
858864 return undefined ;
859865 }
860866
861-
862867 /**
863868 * If the name is a computed property, this function transforms it, then either returns an expression which caches the
864869 * value of the result or the expression itself if the value is either unused or safe to inline into multiple locations
@@ -872,7 +877,12 @@ namespace ts {
872877 const alreadyTransformed = isAssignmentExpression ( innerExpression ) && isGeneratedIdentifier ( innerExpression . left ) ;
873878 if ( ! alreadyTransformed && ! inlinable && shouldHoist ) {
874879 const generatedName = getGeneratedNameForNode ( name ) ;
875- hoistVariableDeclaration ( generatedName ) ;
880+ if ( resolver . getNodeCheckFlags ( name ) & NodeCheckFlags . BlockScopedBindingInLoop ) {
881+ addBlockScopedVariable ( generatedName ) ;
882+ }
883+ else {
884+ hoistVariableDeclaration ( generatedName ) ;
885+ }
876886 return createAssignment ( generatedName , expression ) ;
877887 }
878888 return ( inlinable || isIdentifier ( innerExpression ) ) ? undefined : expression ;
@@ -892,7 +902,12 @@ namespace ts {
892902 const text = getTextOfPropertyName ( name ) as string ;
893903 const weakMapName = createOptimisticUniqueName ( "_" + text . substring ( 1 ) ) ;
894904 weakMapName . autoGenerateFlags |= GeneratedIdentifierFlags . ReservedInNestedScopes ;
895- hoistVariableDeclaration ( weakMapName ) ;
905+ if ( resolver . getNodeCheckFlags ( name ) & NodeCheckFlags . BlockScopedBindingInLoop ) {
906+ addBlockScopedVariable ( weakMapName ) ;
907+ }
908+ else {
909+ hoistVariableDeclaration ( weakMapName ) ;
910+ }
896911 ( currentPrivateIdentifierEnvironment || ( currentPrivateIdentifierEnvironment = createUnderscoreEscapedMap ( ) ) )
897912 . set ( name . escapedText , { placement : PrivateIdentifierPlacement . InstanceField , weakMapName } ) ;
898913 ( pendingExpressions || ( pendingExpressions = [ ] ) ) . push (
0 commit comments