@@ -165,10 +165,9 @@ namespace ts {
165
165
let currentNode : Node ;
166
166
let enclosingBlockScopeContainer : Node ;
167
167
let enclosingBlockScopeContainerParent : Node ;
168
- let containingNonArrowFunction : FunctionLikeDeclaration | ClassElement ;
169
-
170
- /** Tracks the container that determines whether `super.x` is a static. */
171
- let superScopeContainer : FunctionLikeDeclaration | ClassElement ;
168
+ let enclosingFunction : FunctionLikeDeclaration ;
169
+ let enclosingNonArrowFunction : FunctionLikeDeclaration ;
170
+ let enclosingNonAsyncFunctionBody : FunctionLikeDeclaration | ClassElement ;
172
171
173
172
/**
174
173
* Used to track if we are emitting body of the converted loop
@@ -182,11 +181,6 @@ namespace ts {
182
181
*/
183
182
let enabledSubstitutions : ES6SubstitutionFlags ;
184
183
185
- /**
186
- * This is used to determine whether we need to emit `_this` instead of `this`.
187
- */
188
- let useCapturedThis : boolean ;
189
-
190
184
return transformSourceFile ;
191
185
192
186
function transformSourceFile ( node : SourceFile ) {
@@ -206,13 +200,13 @@ namespace ts {
206
200
}
207
201
208
202
function saveStateAndInvoke < T > ( node : Node , f : ( node : Node ) => T ) : T {
209
- const savedContainingNonArrowFunction = containingNonArrowFunction ;
210
- const savedSuperScopeContainer = superScopeContainer ;
211
- const savedCurrentParent = currentParent ;
212
- const savedCurrentNode = currentNode ;
203
+ const savedEnclosingFunction = enclosingFunction ;
204
+ const savedEnclosingNonArrowFunction = enclosingNonArrowFunction ;
205
+ const savedEnclosingNonAsyncFunctionBody = enclosingNonAsyncFunctionBody ;
213
206
const savedEnclosingBlockScopeContainer = enclosingBlockScopeContainer ;
214
207
const savedEnclosingBlockScopeContainerParent = enclosingBlockScopeContainerParent ;
215
-
208
+ const savedCurrentParent = currentParent ;
209
+ const savedCurrentNode = currentNode ;
216
210
const savedConvertedLoopState = convertedLoopState ;
217
211
if ( nodeStartsNewLexicalEnvironment ( node ) ) {
218
212
// don't treat content of nodes that start new lexical environment as part of converted loop copy
@@ -223,12 +217,13 @@ namespace ts {
223
217
const visited = f ( node ) ;
224
218
225
219
convertedLoopState = savedConvertedLoopState ;
226
- containingNonArrowFunction = savedContainingNonArrowFunction ;
227
- superScopeContainer = savedSuperScopeContainer ;
228
- currentParent = savedCurrentParent ;
229
- currentNode = savedCurrentNode ;
220
+ enclosingFunction = savedEnclosingFunction ;
221
+ enclosingNonArrowFunction = savedEnclosingNonArrowFunction ;
222
+ enclosingNonAsyncFunctionBody = savedEnclosingNonAsyncFunctionBody ;
230
223
enclosingBlockScopeContainer = savedEnclosingBlockScopeContainer ;
231
224
enclosingBlockScopeContainerParent = savedEnclosingBlockScopeContainerParent ;
225
+ currentParent = savedCurrentParent ;
226
+ currentNode = savedCurrentNode ;
232
227
return visited ;
233
228
}
234
229
@@ -251,22 +246,13 @@ namespace ts {
251
246
}
252
247
253
248
function visitorForConvertedLoopWorker ( node : Node ) : VisitResult < Node > {
254
- const savedUseCapturedThis = useCapturedThis ;
255
-
256
- if ( nodeStartsNewLexicalEnvironment ( node ) ) {
257
- useCapturedThis = false ;
258
- }
259
-
260
249
let result : VisitResult < Node > ;
261
-
262
250
if ( shouldCheckNode ( node ) ) {
263
251
result = visitJavaScript ( node ) ;
264
252
}
265
253
else {
266
254
result = visitNodesInConvertedLoop ( node ) ;
267
255
}
268
-
269
- useCapturedThis = savedUseCapturedThis ;
270
256
return result ;
271
257
}
272
258
@@ -409,30 +395,25 @@ namespace ts {
409
395
}
410
396
411
397
function onBeforeVisitNode ( node : Node ) {
412
- const currentGrandparent = currentParent ;
413
- currentParent = currentNode ;
414
- currentNode = node ;
415
-
416
- if ( currentParent ) {
417
- if ( isBlockScope ( currentParent , currentGrandparent ) ) {
418
- enclosingBlockScopeContainer = currentParent ;
419
- enclosingBlockScopeContainerParent = currentGrandparent ;
398
+ if ( currentNode ) {
399
+ if ( isBlockScope ( currentNode , currentParent ) ) {
400
+ enclosingBlockScopeContainer = currentNode ;
401
+ enclosingBlockScopeContainerParent = currentParent ;
420
402
}
421
403
422
- switch ( currentParent . kind ) {
423
- case SyntaxKind . FunctionExpression :
424
- case SyntaxKind . Constructor :
425
- case SyntaxKind . MethodDeclaration :
426
- case SyntaxKind . GetAccessor :
427
- case SyntaxKind . SetAccessor :
428
- case SyntaxKind . FunctionDeclaration :
429
- containingNonArrowFunction = < FunctionLikeDeclaration > currentParent ;
430
- if ( ! ( containingNonArrowFunction . emitFlags & NodeEmitFlags . AsyncFunctionBody ) ) {
431
- superScopeContainer = containingNonArrowFunction ;
404
+ if ( isFunctionLike ( currentNode ) ) {
405
+ enclosingFunction = currentNode ;
406
+ if ( currentNode . kind !== SyntaxKind . ArrowFunction ) {
407
+ enclosingNonArrowFunction = currentNode ;
408
+ if ( ! ( currentNode . emitFlags & NodeEmitFlags . AsyncFunctionBody ) ) {
409
+ enclosingNonAsyncFunctionBody = currentNode ;
432
410
}
433
- break ;
411
+ }
434
412
}
435
413
}
414
+
415
+ currentParent = currentNode ;
416
+ currentNode = node ;
436
417
}
437
418
438
419
function visitSwitchStatement ( node : SwitchStatement ) : SwitchStatement {
@@ -468,9 +449,8 @@ namespace ts {
468
449
469
450
function visitThisKeyword ( node : Node ) : Node {
470
451
Debug . assert ( convertedLoopState !== undefined ) ;
471
-
472
- if ( useCapturedThis ) {
473
- // if useCapturedThis is true then 'this' keyword is contained inside an arrow function.
452
+ if ( enclosingFunction && enclosingFunction . kind === SyntaxKind . ArrowFunction ) {
453
+ // if the enclosing function is an ArrowFunction is then we use the captured 'this' keyword.
474
454
convertedLoopState . containsLexicalThis = true ;
475
455
return node ;
476
456
}
@@ -1306,12 +1286,7 @@ namespace ts {
1306
1286
enableSubstitutionsForCapturedThis ( ) ;
1307
1287
}
1308
1288
1309
- const savedUseCapturedThis = useCapturedThis ;
1310
- useCapturedThis = true ;
1311
-
1312
1289
const func = transformFunctionLikeToExpression ( node , /*location*/ node , /*name*/ undefined ) ;
1313
-
1314
- useCapturedThis = savedUseCapturedThis ;
1315
1290
setNodeEmitFlags ( func , NodeEmitFlags . CapturesThis ) ;
1316
1291
return func ;
1317
1292
}
@@ -1354,9 +1329,9 @@ namespace ts {
1354
1329
* @param name The name of the new FunctionExpression.
1355
1330
*/
1356
1331
function transformFunctionLikeToExpression ( node : FunctionLikeDeclaration , location : TextRange , name : Identifier ) : FunctionExpression {
1357
- const savedContainingNonArrowFunction = containingNonArrowFunction ;
1332
+ const savedContainingNonArrowFunction = enclosingNonArrowFunction ;
1358
1333
if ( node . kind !== SyntaxKind . ArrowFunction ) {
1359
- containingNonArrowFunction = node ;
1334
+ enclosingNonArrowFunction = node ;
1360
1335
}
1361
1336
1362
1337
const expression = setOriginalNode (
@@ -1372,7 +1347,7 @@ namespace ts {
1372
1347
/*original*/ node
1373
1348
) ;
1374
1349
1375
- containingNonArrowFunction = savedContainingNonArrowFunction ;
1350
+ enclosingNonArrowFunction = savedContainingNonArrowFunction ;
1376
1351
return expression ;
1377
1352
}
1378
1353
@@ -2066,8 +2041,8 @@ namespace ts {
2066
2041
}
2067
2042
2068
2043
const isAsyncBlockContainingAwait =
2069
- containingNonArrowFunction
2070
- && ( containingNonArrowFunction . emitFlags & NodeEmitFlags . AsyncFunctionBody ) !== 0
2044
+ enclosingNonArrowFunction
2045
+ && ( enclosingNonArrowFunction . emitFlags & NodeEmitFlags . AsyncFunctionBody ) !== 0
2071
2046
&& ( node . statement . transformFlags & TransformFlags . ContainsYield ) !== 0 ;
2072
2047
2073
2048
let loopBodyFlags : NodeEmitFlags = 0 ;
@@ -2829,9 +2804,9 @@ namespace ts {
2829
2804
* Visits the `super` keyword
2830
2805
*/
2831
2806
function visitSuperKeyword ( node : PrimaryExpression ) : LeftHandSideExpression {
2832
- return superScopeContainer
2833
- && isClassElement ( superScopeContainer )
2834
- && ! hasModifier ( superScopeContainer , ModifierFlags . Static )
2807
+ return enclosingNonAsyncFunctionBody
2808
+ && isClassElement ( enclosingNonAsyncFunctionBody )
2809
+ && ! hasModifier ( enclosingNonAsyncFunctionBody , ModifierFlags . Static )
2835
2810
&& currentParent . kind !== SyntaxKind . CallExpression
2836
2811
? createPropertyAccess ( createIdentifier ( "_super" ) , "prototype" )
2837
2812
: createIdentifier ( "_super" ) ;
@@ -2856,17 +2831,16 @@ namespace ts {
2856
2831
* @param node The node to be printed.
2857
2832
*/
2858
2833
function onEmitNode ( node : Node , emit : ( node : Node ) => void ) {
2859
- const savedUseCapturedThis = useCapturedThis ;
2834
+ const savedEnclosingFunction = enclosingFunction ;
2860
2835
2861
2836
if ( enabledSubstitutions & ES6SubstitutionFlags . CapturedThis && isFunctionLike ( node ) ) {
2862
- // If we are tracking a captured `this`, push a bit that indicates whether the
2863
- // containing function is an arrow function.
2864
- useCapturedThis = ( getNodeEmitFlags ( node ) & NodeEmitFlags . CapturesThis ) !== 0 ;
2837
+ // If we are tracking a captured `this`, keep track of the enclosing function.
2838
+ enclosingFunction = node ;
2865
2839
}
2866
2840
2867
2841
previousOnEmitNode ( node , emit ) ;
2868
2842
2869
- useCapturedThis = savedUseCapturedThis ;
2843
+ enclosingFunction = savedEnclosingFunction ;
2870
2844
}
2871
2845
2872
2846
/**
@@ -2994,7 +2968,9 @@ namespace ts {
2994
2968
* @param node The ThisKeyword node.
2995
2969
*/
2996
2970
function substituteThisKeyword ( node : PrimaryExpression ) : PrimaryExpression {
2997
- if ( enabledSubstitutions & ES6SubstitutionFlags . CapturedThis && useCapturedThis ) {
2971
+ if ( enabledSubstitutions & ES6SubstitutionFlags . CapturedThis
2972
+ && enclosingFunction
2973
+ && enclosingFunction . emitFlags & NodeEmitFlags . CapturesThis ) {
2998
2974
return createIdentifier ( "_this" , /*location*/ node ) ;
2999
2975
}
3000
2976
0 commit comments