@@ -345,13 +345,6 @@ namespace ts {
345345 }
346346 }
347347
348- function functionBodyVisitor ( node : Block ) : Block {
349- if ( shouldVisitNode ( node ) ) {
350- return visitBlock ( node , /*isFunctionBody*/ true ) ;
351- }
352- return node ;
353- }
354-
355348 function callExpressionVisitor ( node : Node ) : VisitResult < Node > {
356349 if ( node . kind === SyntaxKind . SuperKeyword ) {
357350 return visitSuperKeyword ( /*isExpressionOfCall*/ true ) ;
@@ -507,15 +500,15 @@ namespace ts {
507500 const statements : Statement [ ] = [ ] ;
508501 startLexicalEnvironment ( ) ;
509502 let statementOffset = addStandardPrologue ( prologue , node . statements , /*ensureUseStrict*/ false ) ;
510- insertCaptureThisForNodeIfNeeded ( prologue , node ) ;
511503 statementOffset = addCustomPrologue ( prologue , node . statements , statementOffset , visitor ) ;
512504 addRange ( statements , visitNodes ( node . statements , visitor , isStatement , statementOffset ) ) ;
513505 if ( taggedTemplateStringDeclarations ) {
514506 statements . push (
515507 createVariableStatement ( /*modifiers*/ undefined ,
516508 createVariableDeclarationList ( taggedTemplateStringDeclarations ) ) ) ;
517509 }
518- insertStatementsAfterStandardPrologue ( prologue , endLexicalEnvironment ( ) ) ;
510+ mergeLexicalEnvironment ( prologue , endLexicalEnvironment ( ) ) ;
511+ insertCaptureThisForNodeIfNeeded ( prologue , node ) ;
519512 exitSubtree ( ancestorFacts , HierarchyFacts . None , HierarchyFacts . None ) ;
520513 return updateSourceFileNode (
521514 node ,
@@ -1194,11 +1187,6 @@ namespace ts {
11941187 || isBindingPattern ( node . name ) ;
11951188 }
11961189
1197- function hasDefaultValueOrBindingPatternOrRest ( node : ParameterDeclaration ) {
1198- return hasDefaultValueOrBindingPattern ( node )
1199- || node . dotDotDotToken !== undefined ;
1200- }
1201-
12021190 /**
12031191 * Adds statements to the body of a function-like node if it contains parameters with
12041192 * binding patterns or initializers.
@@ -1446,12 +1434,13 @@ namespace ts {
14461434
14471435 /**
14481436 * Adds a statement to capture the `this` of a function declaration if it is needed.
1437+ * NOTE: This must be executed *after* the subtree has been visited.
14491438 *
14501439 * @param statements The statements for the new function body.
14511440 * @param node A node.
14521441 */
14531442 function insertCaptureThisForNodeIfNeeded ( statements : Statement [ ] , node : Node ) : boolean {
1454- if ( node . transformFlags & TransformFlags . ContainsCapturedLexicalThis && node . kind !== SyntaxKind . ArrowFunction ) {
1443+ if ( hierarchyFacts & HierarchyFacts . CapturedLexicalThis && node . kind !== SyntaxKind . ArrowFunction ) {
14551444 insertCaptureThisForNode ( statements , node , createThis ( ) ) ;
14561445 return true ;
14571446 }
@@ -1731,10 +1720,6 @@ namespace ts {
17311720 return func ;
17321721 }
17331722
1734- function containsCapturedLexicalThis ( node : Node ) {
1735- return ( node . transformFlags & TransformFlags . ContainsCapturedLexicalThis ) !== 0 ;
1736- }
1737-
17381723 /**
17391724 * Visits a FunctionExpression node.
17401725 *
@@ -1748,11 +1733,7 @@ namespace ts {
17481733 convertedLoopState = undefined ;
17491734
17501735 const parameters = visitParameterList ( node . parameters , visitor , context ) ;
1751- const shouldTransform = forEachChild ( node , containsCapturedLexicalThis )
1752- || some ( node . parameters , hasDefaultValueOrBindingPatternOrRest ) ;
1753- const body = shouldTransform
1754- ? transformFunctionBody ( node )
1755- : visitFunctionBodyDownLevel ( node ) ;
1736+ const body = transformFunctionBody ( node ) ;
17561737 const name = hierarchyFacts & HierarchyFacts . NewTarget
17571738 ? getLocalName ( node )
17581739 : node . name ;
@@ -1781,11 +1762,7 @@ namespace ts {
17811762 convertedLoopState = undefined ;
17821763 const ancestorFacts = enterSubtree ( HierarchyFacts . FunctionExcludes , HierarchyFacts . FunctionIncludes ) ;
17831764 const parameters = visitParameterList ( node . parameters , visitor , context ) ;
1784- const shouldTransform = forEachChild ( node , containsCapturedLexicalThis )
1785- || some ( node . parameters , hasDefaultValueOrBindingPatternOrRest ) ;
1786- const body = shouldTransform
1787- ? transformFunctionBody ( node )
1788- : visitFunctionBodyDownLevel ( node ) ;
1765+ const body = transformFunctionBody ( node ) ;
17891766 const name = hierarchyFacts & HierarchyFacts . NewTarget
17901767 ? getLocalName ( node )
17911768 : node . name ;
@@ -1921,7 +1898,13 @@ namespace ts {
19211898 multiLine = true ;
19221899 }
19231900
1924- const block = createBlock ( setTextRange ( createNodeArray ( concatenate ( prologue , statements ) ) , statementsLocation ) , multiLine ) ;
1901+ statements . unshift ( ...prologue ) ;
1902+ if ( isBlock ( body ) && arrayIsEqualTo ( statements , body . statements ) ) {
1903+ // no changes were made, preserve the tree
1904+ return body ;
1905+ }
1906+
1907+ const block = createBlock ( setTextRange ( createNodeArray ( statements ) , statementsLocation ) , multiLine ) ;
19251908 setTextRange ( block , node . body ) ;
19261909 if ( ! multiLine && singleLine ) {
19271910 setEmitFlags ( block , EmitFlags . SingleLine ) ;
@@ -1935,19 +1918,6 @@ namespace ts {
19351918 return block ;
19361919 }
19371920
1938- function visitFunctionBodyDownLevel ( node : FunctionDeclaration | FunctionExpression | AccessorDeclaration ) {
1939- const updated = visitFunctionBody ( node . body , functionBodyVisitor , context ) ! ;
1940- return updateBlock (
1941- updated ,
1942- setTextRange (
1943- createNodeArray (
1944- insertCaptureNewTargetIfNeeded ( updated . statements as MutableNodeArray < Statement > , node , /*copyOnWrite*/ true )
1945- ) ,
1946- /*location*/ updated . statements
1947- )
1948- ) ;
1949- }
1950-
19511921 function visitBlock ( node : Block , isFunctionBody : boolean ) : Block {
19521922 if ( isFunctionBody ) {
19531923 // A function body is not a block scope.
@@ -3501,9 +3471,7 @@ namespace ts {
35013471 const ancestorFacts = enterSubtree ( HierarchyFacts . FunctionExcludes , HierarchyFacts . FunctionIncludes ) ;
35023472 let updated : AccessorDeclaration ;
35033473 const parameters = visitParameterList ( node . parameters , visitor , context ) ;
3504- const body = node . transformFlags & ( TransformFlags . ContainsCapturedLexicalThis | TransformFlags . ContainsES2015 )
3505- ? transformFunctionBody ( node )
3506- : visitFunctionBodyDownLevel ( node ) ;
3474+ const body = transformFunctionBody ( node ) ;
35073475 if ( node . kind === SyntaxKind . GetAccessor ) {
35083476 updated = updateGetAccessor ( node , node . decorators , node . modifiers , node . name , parameters , node . type , body ) ;
35093477 }
0 commit comments