@@ -35,7 +35,8 @@ namespace ts {
35
35
const {
36
36
hoistVariableDeclaration,
37
37
endLexicalEnvironment,
38
- resumeLexicalEnvironment
38
+ resumeLexicalEnvironment,
39
+ addBlockScopedVariable
39
40
} = context ;
40
41
const resolver = context . getEmitResolver ( ) ;
41
42
const compilerOptions = context . getCompilerOptions ( ) ;
@@ -210,9 +211,12 @@ namespace ts {
210
211
// Create a temporary variable to store a computed property name (if necessary).
211
212
// If it's not inlineable, then we emit an expression after the class which assigns
212
213
// 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
+ }
216
220
}
217
221
return undefined ;
218
222
}
@@ -532,8 +536,10 @@ namespace ts {
532
536
}
533
537
else {
534
538
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 ) ;
537
543
if ( isClassWithConstructorReference ) {
538
544
// record an alias as the class name is not in scope for statics.
539
545
enableSubstitutionForClassAliases ( ) ;
@@ -748,7 +754,7 @@ namespace ts {
748
754
function transformProperty ( property : PropertyDeclaration , receiver : LeftHandSideExpression ) {
749
755
// We generate a name here in order to reuse the value cached by the relocated computed name expression (which uses the same generated name)
750
756
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 )
752
758
? updateComputedPropertyName ( property . name , getGeneratedNameForNode ( property . name ) )
753
759
: property . name ;
754
760
@@ -858,7 +864,6 @@ namespace ts {
858
864
return undefined ;
859
865
}
860
866
861
-
862
867
/**
863
868
* If the name is a computed property, this function transforms it, then either returns an expression which caches the
864
869
* 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 {
872
877
const alreadyTransformed = isAssignmentExpression ( innerExpression ) && isGeneratedIdentifier ( innerExpression . left ) ;
873
878
if ( ! alreadyTransformed && ! inlinable && shouldHoist ) {
874
879
const generatedName = getGeneratedNameForNode ( name ) ;
875
- hoistVariableDeclaration ( generatedName ) ;
880
+ if ( resolver . getNodeCheckFlags ( name ) & NodeCheckFlags . BlockScopedBindingInLoop ) {
881
+ addBlockScopedVariable ( generatedName ) ;
882
+ }
883
+ else {
884
+ hoistVariableDeclaration ( generatedName ) ;
885
+ }
876
886
return createAssignment ( generatedName , expression ) ;
877
887
}
878
888
return ( inlinable || isIdentifier ( innerExpression ) ) ? undefined : expression ;
@@ -892,7 +902,12 @@ namespace ts {
892
902
const text = getTextOfPropertyName ( name ) as string ;
893
903
const weakMapName = createOptimisticUniqueName ( "_" + text . substring ( 1 ) ) ;
894
904
weakMapName . autoGenerateFlags |= GeneratedIdentifierFlags . ReservedInNestedScopes ;
895
- hoistVariableDeclaration ( weakMapName ) ;
905
+ if ( resolver . getNodeCheckFlags ( name ) & NodeCheckFlags . BlockScopedBindingInLoop ) {
906
+ addBlockScopedVariable ( weakMapName ) ;
907
+ }
908
+ else {
909
+ hoistVariableDeclaration ( weakMapName ) ;
910
+ }
896
911
( currentPrivateIdentifierEnvironment || ( currentPrivateIdentifierEnvironment = createUnderscoreEscapedMap ( ) ) )
897
912
. set ( name . escapedText , { placement : PrivateIdentifierPlacement . InstanceField , weakMapName } ) ;
898
913
( pendingExpressions || ( pendingExpressions = [ ] ) ) . push (
0 commit comments