@@ -166,10 +166,9 @@ namespace ts {
166
166
let enclosingVariableStatement : VariableStatement ;
167
167
let enclosingBlockScopeContainer : Node ;
168
168
let enclosingBlockScopeContainerParent : Node ;
169
- let containingNonArrowFunction : FunctionLikeDeclaration | ClassElement ;
170
-
171
- /** Tracks the container that determines whether `super.x` is a static. */
172
- let superScopeContainer : FunctionLikeDeclaration | ClassElement ;
169
+ let enclosingFunction : FunctionLikeDeclaration ;
170
+ let enclosingNonArrowFunction : FunctionLikeDeclaration ;
171
+ let enclosingNonAsyncFunctionBody : FunctionLikeDeclaration | ClassElement ;
173
172
174
173
/**
175
174
* Used to track if we are emitting body of the converted loop
@@ -183,11 +182,6 @@ namespace ts {
183
182
*/
184
183
let enabledSubstitutions : ES6SubstitutionFlags ;
185
184
186
- /**
187
- * This is used to determine whether we need to emit `_this` instead of `this`.
188
- */
189
- let useCapturedThis : boolean ;
190
-
191
185
return transformSourceFile ;
192
186
193
187
function transformSourceFile ( node : SourceFile ) {
@@ -207,14 +201,14 @@ namespace ts {
207
201
}
208
202
209
203
function saveStateAndInvoke < T > ( node : Node , f : ( node : Node ) => T ) : T {
210
- const savedContainingNonArrowFunction = containingNonArrowFunction ;
211
- const savedSuperScopeContainer = superScopeContainer ;
212
- const savedCurrentParent = currentParent ;
213
- const savedCurrentNode = currentNode ;
214
- const savedEnclosingVariableStatement = enclosingVariableStatement ;
204
+ const savedEnclosingFunction = enclosingFunction ;
205
+ const savedEnclosingNonArrowFunction = enclosingNonArrowFunction ;
206
+ const savedEnclosingNonAsyncFunctionBody = enclosingNonAsyncFunctionBody ;
215
207
const savedEnclosingBlockScopeContainer = enclosingBlockScopeContainer ;
216
208
const savedEnclosingBlockScopeContainerParent = enclosingBlockScopeContainerParent ;
217
-
209
+ const savedEnclosingVariableStatement = enclosingVariableStatement ;
210
+ const savedCurrentParent = currentParent ;
211
+ const savedCurrentNode = currentNode ;
218
212
const savedConvertedLoopState = convertedLoopState ;
219
213
if ( nodeStartsNewLexicalEnvironment ( node ) ) {
220
214
// don't treat content of nodes that start new lexical environment as part of converted loop copy
@@ -225,13 +219,14 @@ namespace ts {
225
219
const visited = f ( node ) ;
226
220
227
221
convertedLoopState = savedConvertedLoopState ;
228
- containingNonArrowFunction = savedContainingNonArrowFunction ;
229
- superScopeContainer = savedSuperScopeContainer ;
230
- currentParent = savedCurrentParent ;
231
- currentNode = savedCurrentNode ;
232
- enclosingVariableStatement = savedEnclosingVariableStatement ;
222
+ enclosingFunction = savedEnclosingFunction ;
223
+ enclosingNonArrowFunction = savedEnclosingNonArrowFunction ;
224
+ enclosingNonAsyncFunctionBody = savedEnclosingNonAsyncFunctionBody ;
233
225
enclosingBlockScopeContainer = savedEnclosingBlockScopeContainer ;
234
226
enclosingBlockScopeContainerParent = savedEnclosingBlockScopeContainerParent ;
227
+ enclosingVariableStatement = savedEnclosingVariableStatement ;
228
+ currentParent = savedCurrentParent ;
229
+ currentNode = savedCurrentNode ;
235
230
return visited ;
236
231
}
237
232
@@ -254,22 +249,13 @@ namespace ts {
254
249
}
255
250
256
251
function visitorForConvertedLoopWorker ( node : Node ) : VisitResult < Node > {
257
- const savedUseCapturedThis = useCapturedThis ;
258
-
259
- if ( nodeStartsNewLexicalEnvironment ( node ) ) {
260
- useCapturedThis = false ;
261
- }
262
-
263
252
let result : VisitResult < Node > ;
264
-
265
253
if ( shouldCheckNode ( node ) ) {
266
254
result = visitJavaScript ( node ) ;
267
255
}
268
256
else {
269
257
result = visitNodesInConvertedLoop ( node ) ;
270
258
}
271
-
272
- useCapturedThis = savedUseCapturedThis ;
273
259
return result ;
274
260
}
275
261
@@ -412,36 +398,28 @@ namespace ts {
412
398
}
413
399
414
400
function onBeforeVisitNode ( node : Node ) {
415
- const currentGrandparent = currentParent ;
416
- currentParent = currentNode ;
417
- currentNode = node ;
418
-
419
- if ( currentParent ) {
420
- if ( isBlockScope ( currentParent , currentGrandparent ) ) {
421
- enclosingBlockScopeContainer = currentParent ;
422
- enclosingBlockScopeContainerParent = currentGrandparent ;
401
+ if ( currentNode ) {
402
+ if ( isBlockScope ( currentNode , currentParent ) ) {
403
+ enclosingBlockScopeContainer = currentNode ;
404
+ enclosingBlockScopeContainerParent = currentParent ;
423
405
}
424
406
425
- switch ( currentParent . kind ) {
426
- case SyntaxKind . FunctionExpression :
427
- case SyntaxKind . Constructor :
428
- case SyntaxKind . MethodDeclaration :
429
- case SyntaxKind . GetAccessor :
430
- case SyntaxKind . SetAccessor :
431
- case SyntaxKind . FunctionDeclaration :
432
- containingNonArrowFunction = < FunctionLikeDeclaration > currentParent ;
433
- if ( ! ( containingNonArrowFunction . emitFlags & NodeEmitFlags . AsyncFunctionBody ) ) {
434
- superScopeContainer = containingNonArrowFunction ;
407
+ if ( isFunctionLike ( currentNode ) ) {
408
+ enclosingFunction = currentNode ;
409
+ if ( currentNode . kind !== SyntaxKind . ArrowFunction ) {
410
+ enclosingNonArrowFunction = currentNode ;
411
+ if ( ! ( currentNode . emitFlags & NodeEmitFlags . AsyncFunctionBody ) ) {
412
+ enclosingNonAsyncFunctionBody = currentNode ;
435
413
}
436
- break ;
414
+ }
437
415
}
438
416
439
417
// keep track of the enclosing variable statement when in the context of
440
418
// variable statements, variable declarations, binding elements, and binding
441
419
// patterns.
442
- switch ( currentParent . kind ) {
420
+ switch ( currentNode . kind ) {
443
421
case SyntaxKind . VariableStatement :
444
- enclosingVariableStatement = < VariableStatement > currentParent ;
422
+ enclosingVariableStatement = < VariableStatement > currentNode ;
445
423
break ;
446
424
447
425
case SyntaxKind . VariableDeclarationList :
@@ -455,6 +433,9 @@ namespace ts {
455
433
enclosingVariableStatement = undefined ;
456
434
}
457
435
}
436
+
437
+ currentParent = currentNode ;
438
+ currentNode = node ;
458
439
}
459
440
460
441
function visitSwitchStatement ( node : SwitchStatement ) : SwitchStatement {
@@ -490,9 +471,8 @@ namespace ts {
490
471
491
472
function visitThisKeyword ( node : Node ) : Node {
492
473
Debug . assert ( convertedLoopState !== undefined ) ;
493
-
494
- if ( useCapturedThis ) {
495
- // if useCapturedThis is true then 'this' keyword is contained inside an arrow function.
474
+ if ( enclosingFunction && enclosingFunction . kind === SyntaxKind . ArrowFunction ) {
475
+ // if the enclosing function is an ArrowFunction is then we use the captured 'this' keyword.
496
476
convertedLoopState . containsLexicalThis = true ;
497
477
return node ;
498
478
}
@@ -1328,12 +1308,7 @@ namespace ts {
1328
1308
enableSubstitutionsForCapturedThis ( ) ;
1329
1309
}
1330
1310
1331
- const savedUseCapturedThis = useCapturedThis ;
1332
- useCapturedThis = true ;
1333
-
1334
1311
const func = transformFunctionLikeToExpression ( node , /*location*/ node , /*name*/ undefined ) ;
1335
-
1336
- useCapturedThis = savedUseCapturedThis ;
1337
1312
setNodeEmitFlags ( func , NodeEmitFlags . CapturesThis ) ;
1338
1313
return func ;
1339
1314
}
@@ -1376,9 +1351,9 @@ namespace ts {
1376
1351
* @param name The name of the new FunctionExpression.
1377
1352
*/
1378
1353
function transformFunctionLikeToExpression ( node : FunctionLikeDeclaration , location : TextRange , name : Identifier ) : FunctionExpression {
1379
- const savedContainingNonArrowFunction = containingNonArrowFunction ;
1354
+ const savedContainingNonArrowFunction = enclosingNonArrowFunction ;
1380
1355
if ( node . kind !== SyntaxKind . ArrowFunction ) {
1381
- containingNonArrowFunction = node ;
1356
+ enclosingNonArrowFunction = node ;
1382
1357
}
1383
1358
1384
1359
const expression = setOriginalNode (
@@ -1394,7 +1369,7 @@ namespace ts {
1394
1369
/*original*/ node
1395
1370
) ;
1396
1371
1397
- containingNonArrowFunction = savedContainingNonArrowFunction ;
1372
+ enclosingNonArrowFunction = savedContainingNonArrowFunction ;
1398
1373
return expression ;
1399
1374
}
1400
1375
@@ -2091,8 +2066,8 @@ namespace ts {
2091
2066
}
2092
2067
2093
2068
const isAsyncBlockContainingAwait =
2094
- containingNonArrowFunction
2095
- && ( containingNonArrowFunction . emitFlags & NodeEmitFlags . AsyncFunctionBody ) !== 0
2069
+ enclosingNonArrowFunction
2070
+ && ( enclosingNonArrowFunction . emitFlags & NodeEmitFlags . AsyncFunctionBody ) !== 0
2096
2071
&& ( node . statement . transformFlags & TransformFlags . ContainsYield ) !== 0 ;
2097
2072
2098
2073
let loopBodyFlags : NodeEmitFlags = 0 ;
@@ -2854,9 +2829,9 @@ namespace ts {
2854
2829
* Visits the `super` keyword
2855
2830
*/
2856
2831
function visitSuperKeyword ( node : PrimaryExpression ) : LeftHandSideExpression {
2857
- return superScopeContainer
2858
- && isClassElement ( superScopeContainer )
2859
- && ! hasModifier ( superScopeContainer , ModifierFlags . Static )
2832
+ return enclosingNonAsyncFunctionBody
2833
+ && isClassElement ( enclosingNonAsyncFunctionBody )
2834
+ && ! hasModifier ( enclosingNonAsyncFunctionBody , ModifierFlags . Static )
2860
2835
&& currentParent . kind !== SyntaxKind . CallExpression
2861
2836
? createPropertyAccess ( createIdentifier ( "_super" ) , "prototype" )
2862
2837
: createIdentifier ( "_super" ) ;
@@ -2881,17 +2856,16 @@ namespace ts {
2881
2856
* @param node The node to be printed.
2882
2857
*/
2883
2858
function onEmitNode ( node : Node , emit : ( node : Node ) => void ) {
2884
- const savedUseCapturedThis = useCapturedThis ;
2859
+ const savedEnclosingFunction = enclosingFunction ;
2885
2860
2886
2861
if ( enabledSubstitutions & ES6SubstitutionFlags . CapturedThis && isFunctionLike ( node ) ) {
2887
- // If we are tracking a captured `this`, push a bit that indicates whether the
2888
- // containing function is an arrow function.
2889
- useCapturedThis = ( getNodeEmitFlags ( node ) & NodeEmitFlags . CapturesThis ) !== 0 ;
2862
+ // If we are tracking a captured `this`, keep track of the enclosing function.
2863
+ enclosingFunction = node ;
2890
2864
}
2891
2865
2892
2866
previousOnEmitNode ( node , emit ) ;
2893
2867
2894
- useCapturedThis = savedUseCapturedThis ;
2868
+ enclosingFunction = savedEnclosingFunction ;
2895
2869
}
2896
2870
2897
2871
/**
@@ -3019,7 +2993,9 @@ namespace ts {
3019
2993
* @param node The ThisKeyword node.
3020
2994
*/
3021
2995
function substituteThisKeyword ( node : PrimaryExpression ) : PrimaryExpression {
3022
- if ( enabledSubstitutions & ES6SubstitutionFlags . CapturedThis && useCapturedThis ) {
2996
+ if ( enabledSubstitutions & ES6SubstitutionFlags . CapturedThis
2997
+ && enclosingFunction
2998
+ && enclosingFunction . emitFlags & NodeEmitFlags . CapturesThis ) {
3023
2999
return createIdentifier ( "_this" , /*location*/ node ) ;
3024
3000
}
3025
3001
0 commit comments