@@ -22,10 +22,8 @@ namespace ts {
2222 const resolver = context . getEmitResolver ( ) ;
2323 const previousIdentifierSubstitution = context . identifierSubstitution ;
2424 const previousExpressionSubstitution = context . expressionSubstitution ;
25- const previousOnBeforeEmitNode = context . onBeforeEmitNode ;
26- const previousOnAfterEmitNode = context . onAfterEmitNode ;
27- context . onBeforeEmitNode = onBeforeEmitNode ;
28- context . onAfterEmitNode = onAfterEmitNode ;
25+ const previousOnEmitNode = context . onEmitNode ;
26+ context . onEmitNode = onEmitNode ;
2927 context . identifierSubstitution = substituteIdentifier ;
3028 context . expressionSubstitution = substituteExpression ;
3129
@@ -44,23 +42,9 @@ namespace ts {
4442 let enabledSubstitutions : ES6SubstitutionFlags ;
4543
4644 /**
47- * Keeps track of how deeply nested we are within function-likes when printing
48- * nodes. This is used to determine whether we need to emit `_this` instead of
49- * `this`.
45+ * This is used to determine whether we need to emit `_this` instead of `this`.
5046 */
51- let containingFunctionDepth : number ;
52-
53- /**
54- * The first 31 bits are used to determine whether a containing function is an
55- * arrow function.
56- */
57- let containingFunctionState : number ;
58-
59- /**
60- * If the containingFunctionDepth grows beyond 31 nested function-likes, this
61- * array is used as a stack to track deeper levels of nesting.
62- */
63- let containingFunctionStack : number [ ] ;
47+ let useCapturedThis : boolean ;
6448
6549 return transformSourceFile ;
6650
@@ -1715,28 +1699,18 @@ namespace ts {
17151699 *
17161700 * @param node The node to be printed.
17171701 */
1718- function onBeforeEmitNode ( node : Node ) {
1719- previousOnBeforeEmitNode ( node ) ;
1702+ function onEmitNode ( node : Node , emit : ( node : Node ) => void ) {
1703+ const savedUseCapturedThis = useCapturedThis ;
17201704
17211705 if ( enabledSubstitutions & ES6SubstitutionFlags . CapturedThis && isFunctionLike ( node ) ) {
17221706 // If we are tracking a captured `this`, push a bit that indicates whether the
17231707 // containing function is an arrow function.
1724- pushContainingFunction ( node . kind === SyntaxKind . ArrowFunction ) ;
1708+ useCapturedThis = node . kind === SyntaxKind . ArrowFunction ;
17251709 }
1726- }
17271710
1728- /**
1729- * Called by the printer just after a node is printed.
1730- *
1731- * @param node The node that was printed.
1732- */
1733- function onAfterEmitNode ( node : Node ) {
1734- previousOnAfterEmitNode ( node ) ;
1711+ previousOnEmitNode ( node , emit ) ;
17351712
1736- if ( enabledSubstitutions & ES6SubstitutionFlags . CapturedThis && isFunctionLike ( node ) ) {
1737- // If we are tracking a captured `this`, pop the last containing function bit.
1738- popContainingFunction ( ) ;
1739- }
1713+ useCapturedThis = savedUseCapturedThis ;
17401714 }
17411715
17421716 /**
@@ -1757,7 +1731,6 @@ namespace ts {
17571731 function enableSubstitutionsForCapturedThis ( ) {
17581732 if ( ( enabledSubstitutions & ES6SubstitutionFlags . CapturedThis ) === 0 ) {
17591733 enabledSubstitutions |= ES6SubstitutionFlags . CapturedThis ;
1760- containingFunctionDepth = 0 ;
17611734 context . enableExpressionSubstitution ( SyntaxKind . ThisKeyword ) ;
17621735 context . enableEmitNotification ( SyntaxKind . Constructor ) ;
17631736 context . enableEmitNotification ( SyntaxKind . MethodDeclaration ) ;
@@ -1850,68 +1823,13 @@ namespace ts {
18501823 * @param node The ThisKeyword node.
18511824 */
18521825 function substituteThisKeyword ( node : PrimaryExpression ) : PrimaryExpression {
1853- if ( enabledSubstitutions & ES6SubstitutionFlags . CapturedThis && isContainedInArrowFunction ( ) ) {
1826+ if ( enabledSubstitutions & ES6SubstitutionFlags . CapturedThis && useCapturedThis ) {
18541827 return createIdentifier ( "_this" , /*location*/ node ) ;
18551828 }
18561829
18571830 return node ;
18581831 }
18591832
1860- /**
1861- * Pushes a value onto a stack that indicates whether we are currently printing a node
1862- * within an arrow function. This is used to determine whether we need to capture `this`.
1863- *
1864- * @param isArrowFunction A value indicating whether the current function container is
1865- * an arrow function.
1866- */
1867- function pushContainingFunction ( isArrowFunction : boolean ) {
1868- // Encode whether the containing function is an arrow function in the first 31 bits of
1869- // an integer. If the stack grows beyond a depth of 31 functions, use an array.
1870- if ( containingFunctionDepth > 0 && containingFunctionDepth % 31 === 0 ) {
1871- if ( ! containingFunctionStack ) {
1872- containingFunctionStack = [ containingFunctionState ] ;
1873- }
1874- else {
1875- containingFunctionStack . push ( containingFunctionState ) ;
1876- }
1877-
1878- containingFunctionState = 0 ;
1879- }
1880-
1881- if ( isArrowFunction ) {
1882- containingFunctionState |= 1 << ( containingFunctionDepth % 31 ) ;
1883- }
1884-
1885- containingFunctionDepth ++ ;
1886- }
1887-
1888- /**
1889- * Pops a value off of the containing function stack.
1890- */
1891- function popContainingFunction ( ) {
1892- if ( containingFunctionDepth > 0 ) {
1893- containingFunctionDepth -- ;
1894- if ( containingFunctionDepth === 0 ) {
1895- containingFunctionState = 0 ;
1896- }
1897- else if ( containingFunctionDepth % 31 === 0 ) {
1898- containingFunctionState = containingFunctionStack . pop ( ) ;
1899- }
1900- else {
1901- containingFunctionState &= ~ ( 1 << containingFunctionDepth % 31 ) ;
1902- }
1903- }
1904- }
1905-
1906- /**
1907- * Gets a value indicating whether we are currently printing a node inside of an arrow
1908- * function.
1909- */
1910- function isContainedInArrowFunction ( ) {
1911- return containingFunctionDepth > 0
1912- && containingFunctionState & ( 1 << ( containingFunctionDepth - 1 ) % 31 ) ;
1913- }
1914-
19151833 function getDeclarationName ( node : ClassExpression | ClassDeclaration | FunctionDeclaration ) {
19161834 return node . name ? getSynthesizedClone ( node . name ) : getGeneratedNameForNode ( node ) ;
19171835 }
0 commit comments