@@ -165,10 +165,9 @@ namespace ts {
165165 let currentNode : Node ;
166166 let enclosingBlockScopeContainer : Node ;
167167 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 ;
172171
173172 /**
174173 * Used to track if we are emitting body of the converted loop
@@ -182,11 +181,6 @@ namespace ts {
182181 */
183182 let enabledSubstitutions : ES6SubstitutionFlags ;
184183
185- /**
186- * This is used to determine whether we need to emit `_this` instead of `this`.
187- */
188- let useCapturedThis : boolean ;
189-
190184 return transformSourceFile ;
191185
192186 function transformSourceFile ( node : SourceFile ) {
@@ -206,13 +200,13 @@ namespace ts {
206200 }
207201
208202 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 ;
213206 const savedEnclosingBlockScopeContainer = enclosingBlockScopeContainer ;
214207 const savedEnclosingBlockScopeContainerParent = enclosingBlockScopeContainerParent ;
215-
208+ const savedCurrentParent = currentParent ;
209+ const savedCurrentNode = currentNode ;
216210 const savedConvertedLoopState = convertedLoopState ;
217211 if ( nodeStartsNewLexicalEnvironment ( node ) ) {
218212 // don't treat content of nodes that start new lexical environment as part of converted loop copy
@@ -223,12 +217,13 @@ namespace ts {
223217 const visited = f ( node ) ;
224218
225219 convertedLoopState = savedConvertedLoopState ;
226- containingNonArrowFunction = savedContainingNonArrowFunction ;
227- superScopeContainer = savedSuperScopeContainer ;
228- currentParent = savedCurrentParent ;
229- currentNode = savedCurrentNode ;
220+ enclosingFunction = savedEnclosingFunction ;
221+ enclosingNonArrowFunction = savedEnclosingNonArrowFunction ;
222+ enclosingNonAsyncFunctionBody = savedEnclosingNonAsyncFunctionBody ;
230223 enclosingBlockScopeContainer = savedEnclosingBlockScopeContainer ;
231224 enclosingBlockScopeContainerParent = savedEnclosingBlockScopeContainerParent ;
225+ currentParent = savedCurrentParent ;
226+ currentNode = savedCurrentNode ;
232227 return visited ;
233228 }
234229
@@ -251,22 +246,13 @@ namespace ts {
251246 }
252247
253248 function visitorForConvertedLoopWorker ( node : Node ) : VisitResult < Node > {
254- const savedUseCapturedThis = useCapturedThis ;
255-
256- if ( nodeStartsNewLexicalEnvironment ( node ) ) {
257- useCapturedThis = false ;
258- }
259-
260249 let result : VisitResult < Node > ;
261-
262250 if ( shouldCheckNode ( node ) ) {
263251 result = visitJavaScript ( node ) ;
264252 }
265253 else {
266254 result = visitNodesInConvertedLoop ( node ) ;
267255 }
268-
269- useCapturedThis = savedUseCapturedThis ;
270256 return result ;
271257 }
272258
@@ -409,30 +395,25 @@ namespace ts {
409395 }
410396
411397 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 ;
420402 }
421403
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 ;
432410 }
433- break ;
411+ }
434412 }
435413 }
414+
415+ currentParent = currentNode ;
416+ currentNode = node ;
436417 }
437418
438419 function visitSwitchStatement ( node : SwitchStatement ) : SwitchStatement {
@@ -468,9 +449,8 @@ namespace ts {
468449
469450 function visitThisKeyword ( node : Node ) : Node {
470451 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.
474454 convertedLoopState . containsLexicalThis = true ;
475455 return node ;
476456 }
@@ -1306,12 +1286,7 @@ namespace ts {
13061286 enableSubstitutionsForCapturedThis ( ) ;
13071287 }
13081288
1309- const savedUseCapturedThis = useCapturedThis ;
1310- useCapturedThis = true ;
1311-
13121289 const func = transformFunctionLikeToExpression ( node , /*location*/ node , /*name*/ undefined ) ;
1313-
1314- useCapturedThis = savedUseCapturedThis ;
13151290 setNodeEmitFlags ( func , NodeEmitFlags . CapturesThis ) ;
13161291 return func ;
13171292 }
@@ -1354,9 +1329,9 @@ namespace ts {
13541329 * @param name The name of the new FunctionExpression.
13551330 */
13561331 function transformFunctionLikeToExpression ( node : FunctionLikeDeclaration , location : TextRange , name : Identifier ) : FunctionExpression {
1357- const savedContainingNonArrowFunction = containingNonArrowFunction ;
1332+ const savedContainingNonArrowFunction = enclosingNonArrowFunction ;
13581333 if ( node . kind !== SyntaxKind . ArrowFunction ) {
1359- containingNonArrowFunction = node ;
1334+ enclosingNonArrowFunction = node ;
13601335 }
13611336
13621337 const expression = setOriginalNode (
@@ -1372,7 +1347,7 @@ namespace ts {
13721347 /*original*/ node
13731348 ) ;
13741349
1375- containingNonArrowFunction = savedContainingNonArrowFunction ;
1350+ enclosingNonArrowFunction = savedContainingNonArrowFunction ;
13761351 return expression ;
13771352 }
13781353
@@ -2066,8 +2041,8 @@ namespace ts {
20662041 }
20672042
20682043 const isAsyncBlockContainingAwait =
2069- containingNonArrowFunction
2070- && ( containingNonArrowFunction . emitFlags & NodeEmitFlags . AsyncFunctionBody ) !== 0
2044+ enclosingNonArrowFunction
2045+ && ( enclosingNonArrowFunction . emitFlags & NodeEmitFlags . AsyncFunctionBody ) !== 0
20712046 && ( node . statement . transformFlags & TransformFlags . ContainsYield ) !== 0 ;
20722047
20732048 let loopBodyFlags : NodeEmitFlags = 0 ;
@@ -2829,9 +2804,9 @@ namespace ts {
28292804 * Visits the `super` keyword
28302805 */
28312806 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 )
28352810 && currentParent . kind !== SyntaxKind . CallExpression
28362811 ? createPropertyAccess ( createIdentifier ( "_super" ) , "prototype" )
28372812 : createIdentifier ( "_super" ) ;
@@ -2856,17 +2831,16 @@ namespace ts {
28562831 * @param node The node to be printed.
28572832 */
28582833 function onEmitNode ( node : Node , emit : ( node : Node ) => void ) {
2859- const savedUseCapturedThis = useCapturedThis ;
2834+ const savedEnclosingFunction = enclosingFunction ;
28602835
28612836 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 ;
28652839 }
28662840
28672841 previousOnEmitNode ( node , emit ) ;
28682842
2869- useCapturedThis = savedUseCapturedThis ;
2843+ enclosingFunction = savedEnclosingFunction ;
28702844 }
28712845
28722846 /**
@@ -2994,7 +2968,9 @@ namespace ts {
29942968 * @param node The ThisKeyword node.
29952969 */
29962970 function substituteThisKeyword ( node : PrimaryExpression ) : PrimaryExpression {
2997- if ( enabledSubstitutions & ES6SubstitutionFlags . CapturedThis && useCapturedThis ) {
2971+ if ( enabledSubstitutions & ES6SubstitutionFlags . CapturedThis
2972+ && enclosingFunction
2973+ && enclosingFunction . emitFlags & NodeEmitFlags . CapturesThis ) {
29982974 return createIdentifier ( "_this" , /*location*/ node ) ;
29992975 }
30002976
0 commit comments