@@ -117,6 +117,12 @@ namespace ts {
117117 let labelIndexMap : Map < number > ;
118118 let implicitLabels : number [ ] ;
119119
120+ // state used for emit helpers
121+ let hasClassExtends : boolean ;
122+ let hasAsyncFunctions : boolean ;
123+ let hasDecorators : boolean ;
124+ let hasParameterDecorators : boolean ;
125+
120126 // If this file is an external module, then it is automatically in strict-mode according to
121127 // ES6. If it is not an external module, then we'll determine if it is in strict mode or
122128 // not depending on if we see "use strict" in certain places (or if we hit a class/namespace).
@@ -151,6 +157,10 @@ namespace ts {
151157 labelStack = undefined ;
152158 labelIndexMap = undefined ;
153159 implicitLabels = undefined ;
160+ hasClassExtends = false ;
161+ hasAsyncFunctions = false ;
162+ hasDecorators = false ;
163+ hasParameterDecorators = false ;
154164 }
155165
156166 return bindSourceFile ;
@@ -351,8 +361,8 @@ namespace ts {
351361 // when the emitter comes back to it, it knows not to qualify the name if it was found in a containing scope.
352362
353363 // NOTE: Nested ambient modules always should go to to 'locals' table to prevent their automatic merge
354- // during global merging in the checker. Why? The only case when ambient module is permitted inside another module is module augmentation
355- // and this case is specially handled. Module augmentations should only be merged with original module definition
364+ // during global merging in the checker. Why? The only case when ambient module is permitted inside another module is module augmentation
365+ // and this case is specially handled. Module augmentations should only be merged with original module definition
356366 // and should never be merged directly with other augmentation, and the latter case would be possible if automatic merge is allowed.
357367 if ( ! isAmbientModule ( node ) && ( hasExportModifier || container . flags & NodeFlags . ExportContext ) ) {
358368 const exportKind =
@@ -429,6 +439,9 @@ namespace ts {
429439 // reset all reachability check related flags on node (for incremental scenarios)
430440 flags &= ~ NodeFlags . ReachabilityCheckFlags ;
431441
442+ // reset all emit helper flags on node (for incremental scenarios)
443+ flags &= ~ NodeFlags . EmitHelperFlags ;
444+
432445 if ( kind === SyntaxKind . InterfaceDeclaration ) {
433446 seenThisKeyword = false ;
434447 }
@@ -459,6 +472,21 @@ namespace ts {
459472 flags = seenThisKeyword ? flags | NodeFlags . ContainsThis : flags & ~ NodeFlags . ContainsThis ;
460473 }
461474
475+ if ( kind === SyntaxKind . SourceFile ) {
476+ if ( hasClassExtends ) {
477+ flags |= NodeFlags . HasClassExtends ;
478+ }
479+ if ( hasDecorators ) {
480+ flags |= NodeFlags . HasDecorators ;
481+ }
482+ if ( hasParameterDecorators ) {
483+ flags |= NodeFlags . HasParamDecorators ;
484+ }
485+ if ( hasAsyncFunctions ) {
486+ flags |= NodeFlags . HasAsyncFunctions ;
487+ }
488+ }
489+
462490 node . flags = flags ;
463491
464492 if ( saveState ) {
@@ -1255,8 +1283,7 @@ namespace ts {
12551283 return bindPropertyOrMethodOrAccessor ( < Declaration > node , SymbolFlags . Method | ( ( < MethodDeclaration > node ) . questionToken ? SymbolFlags . Optional : SymbolFlags . None ) ,
12561284 isObjectLiteralMethod ( node ) ? SymbolFlags . PropertyExcludes : SymbolFlags . MethodExcludes ) ;
12571285 case SyntaxKind . FunctionDeclaration :
1258- checkStrictModeFunctionName ( < FunctionDeclaration > node ) ;
1259- return declareSymbolAndAddToSymbolTable ( < Declaration > node , SymbolFlags . Function , SymbolFlags . FunctionExcludes ) ;
1286+ return bindFunctionDeclaration ( < FunctionDeclaration > node ) ;
12601287 case SyntaxKind . Constructor :
12611288 return declareSymbolAndAddToSymbolTable ( < Declaration > node , SymbolFlags . Constructor , /*symbolExcludes:*/ SymbolFlags . None ) ;
12621289 case SyntaxKind . GetAccessor :
@@ -1272,9 +1299,7 @@ namespace ts {
12721299 return bindObjectLiteralExpression ( < ObjectLiteralExpression > node ) ;
12731300 case SyntaxKind . FunctionExpression :
12741301 case SyntaxKind . ArrowFunction :
1275- checkStrictModeFunctionName ( < FunctionExpression > node ) ;
1276- const bindingName = ( < FunctionExpression > node ) . name ? ( < FunctionExpression > node ) . name . text : "__function" ;
1277- return bindAnonymousDeclaration ( < FunctionExpression > node , SymbolFlags . Function , bindingName ) ;
1302+ return bindFunctionExpression ( < FunctionExpression > node ) ;
12781303
12791304 case SyntaxKind . CallExpression :
12801305 if ( isInJavaScriptFile ( node ) ) {
@@ -1424,6 +1449,15 @@ namespace ts {
14241449 }
14251450
14261451 function bindClassLikeDeclaration ( node : ClassLikeDeclaration ) {
1452+ if ( ! isDeclarationFile ( file ) && ! isInAmbientContext ( node ) ) {
1453+ if ( getClassExtendsHeritageClauseElement ( node ) !== undefined ) {
1454+ hasClassExtends = true ;
1455+ }
1456+ if ( nodeIsDecorated ( node ) ) {
1457+ hasDecorators = true ;
1458+ }
1459+ }
1460+
14271461 if ( node . kind === SyntaxKind . ClassDeclaration ) {
14281462 bindBlockScopedDeclaration ( node , SymbolFlags . Class , SymbolFlags . ClassExcludes ) ;
14291463 }
@@ -1493,6 +1527,13 @@ namespace ts {
14931527 }
14941528
14951529 function bindParameter ( node : ParameterDeclaration ) {
1530+ if ( ! isDeclarationFile ( file ) &&
1531+ ! isInAmbientContext ( node ) &&
1532+ nodeIsDecorated ( node ) ) {
1533+ hasDecorators = true ;
1534+ hasParameterDecorators = true ;
1535+ }
1536+
14961537 if ( inStrictMode ) {
14971538 // It is a SyntaxError if the identifier eval or arguments appears within a FormalParameterList of a
14981539 // strict mode FunctionLikeDeclaration or FunctionExpression(13.1)
@@ -1514,7 +1555,39 @@ namespace ts {
15141555 }
15151556 }
15161557
1558+ function bindFunctionDeclaration ( node : FunctionDeclaration ) {
1559+ if ( ! isDeclarationFile ( file ) && ! isInAmbientContext ( node ) ) {
1560+ if ( isAsyncFunctionLike ( node ) ) {
1561+ hasAsyncFunctions = true ;
1562+ }
1563+ }
1564+
1565+ checkStrictModeFunctionName ( < FunctionDeclaration > node ) ;
1566+ return declareSymbolAndAddToSymbolTable ( < Declaration > node , SymbolFlags . Function , SymbolFlags . FunctionExcludes ) ;
1567+ }
1568+
1569+ function bindFunctionExpression ( node : FunctionExpression ) {
1570+ if ( ! isDeclarationFile ( file ) && ! isInAmbientContext ( node ) ) {
1571+ if ( isAsyncFunctionLike ( node ) ) {
1572+ hasAsyncFunctions = true ;
1573+ }
1574+ }
1575+
1576+ checkStrictModeFunctionName ( < FunctionExpression > node ) ;
1577+ const bindingName = ( < FunctionExpression > node ) . name ? ( < FunctionExpression > node ) . name . text : "__function" ;
1578+ return bindAnonymousDeclaration ( < FunctionExpression > node , SymbolFlags . Function , bindingName ) ;
1579+ }
1580+
15171581 function bindPropertyOrMethodOrAccessor ( node : Declaration , symbolFlags : SymbolFlags , symbolExcludes : SymbolFlags ) {
1582+ if ( ! isDeclarationFile ( file ) && ! isInAmbientContext ( node ) ) {
1583+ if ( isAsyncFunctionLike ( node ) ) {
1584+ hasAsyncFunctions = true ;
1585+ }
1586+ if ( nodeIsDecorated ( node ) ) {
1587+ hasDecorators = true ;
1588+ }
1589+ }
1590+
15181591 return hasDynamicName ( node )
15191592 ? bindAnonymousDeclaration ( node , symbolFlags , "__computed" )
15201593 : declareSymbolAndAddToSymbolTable ( node , symbolFlags , symbolExcludes ) ;
0 commit comments