@@ -166,10 +166,9 @@ namespace ts {
166166 let enclosingVariableStatement : VariableStatement ;
167167 let enclosingBlockScopeContainer : Node ;
168168 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 ;
173172
174173 /**
175174 * Used to track if we are emitting body of the converted loop
@@ -183,11 +182,6 @@ namespace ts {
183182 */
184183 let enabledSubstitutions : ES6SubstitutionFlags ;
185184
186- /**
187- * This is used to determine whether we need to emit `_this` instead of `this`.
188- */
189- let useCapturedThis : boolean ;
190-
191185 return transformSourceFile ;
192186
193187 function transformSourceFile ( node : SourceFile ) {
@@ -207,14 +201,14 @@ namespace ts {
207201 }
208202
209203 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 ;
215207 const savedEnclosingBlockScopeContainer = enclosingBlockScopeContainer ;
216208 const savedEnclosingBlockScopeContainerParent = enclosingBlockScopeContainerParent ;
217-
209+ const savedEnclosingVariableStatement = enclosingVariableStatement ;
210+ const savedCurrentParent = currentParent ;
211+ const savedCurrentNode = currentNode ;
218212 const savedConvertedLoopState = convertedLoopState ;
219213 if ( nodeStartsNewLexicalEnvironment ( node ) ) {
220214 // don't treat content of nodes that start new lexical environment as part of converted loop copy
@@ -225,13 +219,14 @@ namespace ts {
225219 const visited = f ( node ) ;
226220
227221 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 ;
233225 enclosingBlockScopeContainer = savedEnclosingBlockScopeContainer ;
234226 enclosingBlockScopeContainerParent = savedEnclosingBlockScopeContainerParent ;
227+ enclosingVariableStatement = savedEnclosingVariableStatement ;
228+ currentParent = savedCurrentParent ;
229+ currentNode = savedCurrentNode ;
235230 return visited ;
236231 }
237232
@@ -254,22 +249,13 @@ namespace ts {
254249 }
255250
256251 function visitorForConvertedLoopWorker ( node : Node ) : VisitResult < Node > {
257- const savedUseCapturedThis = useCapturedThis ;
258-
259- if ( nodeStartsNewLexicalEnvironment ( node ) ) {
260- useCapturedThis = false ;
261- }
262-
263252 let result : VisitResult < Node > ;
264-
265253 if ( shouldCheckNode ( node ) ) {
266254 result = visitJavaScript ( node ) ;
267255 }
268256 else {
269257 result = visitNodesInConvertedLoop ( node ) ;
270258 }
271-
272- useCapturedThis = savedUseCapturedThis ;
273259 return result ;
274260 }
275261
@@ -412,36 +398,28 @@ namespace ts {
412398 }
413399
414400 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 ;
423405 }
424406
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 ;
435413 }
436- break ;
414+ }
437415 }
438416
439417 // keep track of the enclosing variable statement when in the context of
440418 // variable statements, variable declarations, binding elements, and binding
441419 // patterns.
442- switch ( currentParent . kind ) {
420+ switch ( currentNode . kind ) {
443421 case SyntaxKind . VariableStatement :
444- enclosingVariableStatement = < VariableStatement > currentParent ;
422+ enclosingVariableStatement = < VariableStatement > currentNode ;
445423 break ;
446424
447425 case SyntaxKind . VariableDeclarationList :
@@ -455,6 +433,9 @@ namespace ts {
455433 enclosingVariableStatement = undefined ;
456434 }
457435 }
436+
437+ currentParent = currentNode ;
438+ currentNode = node ;
458439 }
459440
460441 function visitSwitchStatement ( node : SwitchStatement ) : SwitchStatement {
@@ -490,9 +471,8 @@ namespace ts {
490471
491472 function visitThisKeyword ( node : Node ) : Node {
492473 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.
496476 convertedLoopState . containsLexicalThis = true ;
497477 return node ;
498478 }
@@ -1281,7 +1261,7 @@ namespace ts {
12811261 setNodeEmitFlags ( propertyName , NodeEmitFlags . NoComments | NodeEmitFlags . NoLeadingSourceMap ) ;
12821262 setSourceMapRange ( propertyName , firstAccessor . name ) ;
12831263
1284- const properties : ObjectLiteralElement [ ] = [ ] ;
1264+ const properties : ObjectLiteralElementLike [ ] = [ ] ;
12851265 if ( getAccessor ) {
12861266 const getterFunction = transformFunctionLikeToExpression ( getAccessor , /*location*/ undefined , /*name*/ undefined ) ;
12871267 setSourceMapRange ( getterFunction , getSourceMapRange ( getAccessor ) ) ;
@@ -1328,12 +1308,7 @@ namespace ts {
13281308 enableSubstitutionsForCapturedThis ( ) ;
13291309 }
13301310
1331- const savedUseCapturedThis = useCapturedThis ;
1332- useCapturedThis = true ;
1333-
13341311 const func = transformFunctionLikeToExpression ( node , /*location*/ node , /*name*/ undefined ) ;
1335-
1336- useCapturedThis = savedUseCapturedThis ;
13371312 setNodeEmitFlags ( func , NodeEmitFlags . CapturesThis ) ;
13381313 return func ;
13391314 }
@@ -1376,9 +1351,9 @@ namespace ts {
13761351 * @param name The name of the new FunctionExpression.
13771352 */
13781353 function transformFunctionLikeToExpression ( node : FunctionLikeDeclaration , location : TextRange , name : Identifier ) : FunctionExpression {
1379- const savedContainingNonArrowFunction = containingNonArrowFunction ;
1354+ const savedContainingNonArrowFunction = enclosingNonArrowFunction ;
13801355 if ( node . kind !== SyntaxKind . ArrowFunction ) {
1381- containingNonArrowFunction = node ;
1356+ enclosingNonArrowFunction = node ;
13821357 }
13831358
13841359 const expression = setOriginalNode (
@@ -1394,7 +1369,7 @@ namespace ts {
13941369 /*original*/ node
13951370 ) ;
13961371
1397- containingNonArrowFunction = savedContainingNonArrowFunction ;
1372+ enclosingNonArrowFunction = savedContainingNonArrowFunction ;
13981373 return expression ;
13991374 }
14001375
@@ -1965,7 +1940,7 @@ namespace ts {
19651940 temp ,
19661941 setNodeEmitFlags (
19671942 createObjectLiteral (
1968- visitNodes ( properties , visitor , isObjectLiteralElement , 0 , numInitialProperties ) ,
1943+ visitNodes ( properties , visitor , isObjectLiteralElementLike , 0 , numInitialProperties ) ,
19691944 /*location*/ undefined ,
19701945 node . multiLine
19711946 ) ,
@@ -2091,8 +2066,8 @@ namespace ts {
20912066 }
20922067
20932068 const isAsyncBlockContainingAwait =
2094- containingNonArrowFunction
2095- && ( containingNonArrowFunction . emitFlags & NodeEmitFlags . AsyncFunctionBody ) !== 0
2069+ enclosingNonArrowFunction
2070+ && ( enclosingNonArrowFunction . emitFlags & NodeEmitFlags . AsyncFunctionBody ) !== 0
20962071 && ( node . statement . transformFlags & TransformFlags . ContainsYield ) !== 0 ;
20972072
20982073 let loopBodyFlags : NodeEmitFlags = 0 ;
@@ -2499,7 +2474,7 @@ namespace ts {
24992474 *
25002475 * @param node A MethodDeclaration node.
25012476 */
2502- function visitMethodDeclaration ( node : MethodDeclaration ) : ObjectLiteralElement {
2477+ function visitMethodDeclaration ( node : MethodDeclaration ) : ObjectLiteralElementLike {
25032478 // We should only get here for methods on an object literal with regular identifier names.
25042479 // Methods on classes are handled in visitClassDeclaration/visitClassExpression.
25052480 // Methods with computed property names are handled in visitObjectLiteralExpression.
@@ -2518,7 +2493,7 @@ namespace ts {
25182493 *
25192494 * @param node A ShorthandPropertyAssignment node.
25202495 */
2521- function visitShorthandPropertyAssignment ( node : ShorthandPropertyAssignment ) : ObjectLiteralElement {
2496+ function visitShorthandPropertyAssignment ( node : ShorthandPropertyAssignment ) : ObjectLiteralElementLike {
25222497 return createPropertyAssignment (
25232498 node . name ,
25242499 getSynthesizedClone ( node . name ) ,
@@ -2854,9 +2829,9 @@ namespace ts {
28542829 * Visits the `super` keyword
28552830 */
28562831 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 )
28602835 && currentParent . kind !== SyntaxKind . CallExpression
28612836 ? createPropertyAccess ( createIdentifier ( "_super" ) , "prototype" )
28622837 : createIdentifier ( "_super" ) ;
@@ -2881,17 +2856,16 @@ namespace ts {
28812856 * @param node The node to be printed.
28822857 */
28832858 function onEmitNode ( node : Node , emit : ( node : Node ) => void ) {
2884- const savedUseCapturedThis = useCapturedThis ;
2859+ const savedEnclosingFunction = enclosingFunction ;
28852860
28862861 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 ;
28902864 }
28912865
28922866 previousOnEmitNode ( node , emit ) ;
28932867
2894- useCapturedThis = savedUseCapturedThis ;
2868+ enclosingFunction = savedEnclosingFunction ;
28952869 }
28962870
28972871 /**
@@ -3019,7 +2993,9 @@ namespace ts {
30192993 * @param node The ThisKeyword node.
30202994 */
30212995 function substituteThisKeyword ( node : PrimaryExpression ) : PrimaryExpression {
3022- if ( enabledSubstitutions & ES6SubstitutionFlags . CapturedThis && useCapturedThis ) {
2996+ if ( enabledSubstitutions & ES6SubstitutionFlags . CapturedThis
2997+ && enclosingFunction
2998+ && enclosingFunction . emitFlags & NodeEmitFlags . CapturesThis ) {
30232999 return createIdentifier ( "_this" , /*location*/ node ) ;
30243000 }
30253001
0 commit comments