Skip to content

Commit 2287b46

Browse files
committed
Merge pull request #6495 from Microsoft/moveEmitFlagsToBinder
Move emit helper flags to binder.
2 parents ebfdeaa + 831daea commit 2287b46

13 files changed

+429
-105
lines changed

src/compiler/binder.ts

Lines changed: 80 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -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);

src/compiler/checker.ts

Lines changed: 1 addition & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -174,11 +174,6 @@ namespace ts {
174174
const unionTypes: Map<UnionType> = {};
175175
const intersectionTypes: Map<IntersectionType> = {};
176176
const stringLiteralTypes: Map<StringLiteralType> = {};
177-
let emitExtends = false;
178-
let emitDecorate = false;
179-
let emitParam = false;
180-
let emitAwaiter = false;
181-
const emitGenerator = false;
182177

183178
const resolutionTargets: TypeSystemEntity[] = [];
184179
const resolutionResults: boolean[] = [];
@@ -458,7 +453,7 @@ namespace ts {
458453
* Get symbols that represent parameter-property-declaration as parameter and as property declaration
459454
* @param parameter a parameterDeclaration node
460455
* @param parameterName a name of the parameter to get the symbols for.
461-
* @return a tuple of two symbols
456+
* @return a tuple of two symbols
462457
*/
463458
function getSymbolsOfParameterPropertyDeclaration(parameter: ParameterDeclaration, parameterName: string): [Symbol, Symbol] {
464459
const constructoDeclaration = parameter.parent;
@@ -10249,11 +10244,6 @@ namespace ts {
1024910244
return anyFunctionType;
1025010245
}
1025110246

10252-
const isAsync = isAsyncFunctionLike(node);
10253-
if (isAsync) {
10254-
emitAwaiter = true;
10255-
}
10256-
1025710247
const links = getNodeLinks(node);
1025810248
const type = getTypeOfSymbol(node.symbol);
1025910249
const contextSensitive = isContextSensitive(node);
@@ -10302,10 +10292,6 @@ namespace ts {
1030210292
Debug.assert(node.kind !== SyntaxKind.MethodDeclaration || isObjectLiteralMethod(node));
1030310293

1030410294
const isAsync = isAsyncFunctionLike(node);
10305-
if (isAsync) {
10306-
emitAwaiter = true;
10307-
}
10308-
1030910295
const returnOrPromisedType = node.type && (isAsync ? checkAsyncFunctionReturnType(node) : getTypeFromTypeNode(node.type));
1031010296
if (!node.asteriskToken) {
1031110297
// return is not necessary in the body of generators
@@ -12442,11 +12428,6 @@ namespace ts {
1244212428
}
1244312429
}
1244412430

12445-
emitDecorate = true;
12446-
if (node.kind === SyntaxKind.Parameter) {
12447-
emitParam = true;
12448-
}
12449-
1245012431
forEach(node.decorators, checkDecorator);
1245112432
}
1245212433

@@ -12464,9 +12445,6 @@ namespace ts {
1246412445
checkDecorators(node);
1246512446
checkSignatureDeclaration(node);
1246612447
const isAsync = isAsyncFunctionLike(node);
12467-
if (isAsync) {
12468-
emitAwaiter = true;
12469-
}
1247012448

1247112449
// Do not use hasDynamicName here, because that returns false for well known symbols.
1247212450
// We want to perform checkComputedPropertyName for all computed properties, including
@@ -13597,7 +13575,6 @@ namespace ts {
1359713575

1359813576
const baseTypeNode = getClassExtendsHeritageClauseElement(node);
1359913577
if (baseTypeNode) {
13600-
emitExtends = emitExtends || !isInAmbientContext(node);
1360113578
const baseTypes = getBaseTypes(type);
1360213579
if (baseTypes.length && produceDiagnostics) {
1360313580
const baseType = baseTypes[0];
@@ -14777,10 +14754,6 @@ namespace ts {
1477714754
// Grammar checking
1477814755
checkGrammarSourceFile(node);
1477914756

14780-
emitExtends = false;
14781-
emitDecorate = false;
14782-
emitParam = false;
14783-
emitAwaiter = false;
1478414757
potentialThisCollisions.length = 0;
1478514758

1478614759
deferredNodes = [];
@@ -14797,26 +14770,6 @@ namespace ts {
1479714770
potentialThisCollisions.length = 0;
1479814771
}
1479914772

14800-
if (emitExtends) {
14801-
links.flags |= NodeCheckFlags.EmitExtends;
14802-
}
14803-
14804-
if (emitDecorate) {
14805-
links.flags |= NodeCheckFlags.EmitDecorate;
14806-
}
14807-
14808-
if (emitParam) {
14809-
links.flags |= NodeCheckFlags.EmitParam;
14810-
}
14811-
14812-
if (emitAwaiter) {
14813-
links.flags |= NodeCheckFlags.EmitAwaiter;
14814-
}
14815-
14816-
if (emitGenerator || (emitAwaiter && languageVersion < ScriptTarget.ES6)) {
14817-
links.flags |= NodeCheckFlags.EmitGenerator;
14818-
}
14819-
1482014773
links.flags |= NodeCheckFlags.TypeChecked;
1482114774
}
1482214775
}

src/compiler/emitter.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7349,25 +7349,25 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
73497349
if (!compilerOptions.noEmitHelpers) {
73507350
// Only Emit __extends function when target ES5.
73517351
// For target ES6 and above, we can emit classDeclaration as is.
7352-
if ((languageVersion < ScriptTarget.ES6) && (!extendsEmitted && resolver.getNodeCheckFlags(node) & NodeCheckFlags.EmitExtends)) {
7352+
if ((languageVersion < ScriptTarget.ES6) && (!extendsEmitted && node.flags & NodeFlags.HasClassExtends)) {
73537353
writeLines(extendsHelper);
73547354
extendsEmitted = true;
73557355
}
73567356

7357-
if (!decorateEmitted && resolver.getNodeCheckFlags(node) & NodeCheckFlags.EmitDecorate) {
7357+
if (!decorateEmitted && node.flags & NodeFlags.HasDecorators) {
73587358
writeLines(decorateHelper);
73597359
if (compilerOptions.emitDecoratorMetadata) {
73607360
writeLines(metadataHelper);
73617361
}
73627362
decorateEmitted = true;
73637363
}
73647364

7365-
if (!paramEmitted && resolver.getNodeCheckFlags(node) & NodeCheckFlags.EmitParam) {
7365+
if (!paramEmitted && node.flags & NodeFlags.HasParamDecorators) {
73667366
writeLines(paramHelper);
73677367
paramEmitted = true;
73687368
}
73697369

7370-
if (!awaiterEmitted && resolver.getNodeCheckFlags(node) & NodeCheckFlags.EmitAwaiter) {
7370+
if (!awaiterEmitted && node.flags & NodeFlags.HasAsyncFunctions) {
73717371
writeLines(awaiterHelper);
73727372
awaiterEmitted = true;
73737373
}

src/compiler/types.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -391,11 +391,17 @@ namespace ts {
391391
HasImplicitReturn = 1 << 19, // If function implicitly returns on one of codepaths (initialized by binding)
392392
HasExplicitReturn = 1 << 20, // If function has explicit reachable return on one of codepaths (initialized by binding)
393393
GlobalAugmentation = 1 << 21, // Set if module declaration is an augmentation for the global scope
394+
HasClassExtends = 1 << 22, // If the file has a non-ambient class with an extends clause in ES5 or lower (initialized by binding)
395+
HasDecorators = 1 << 23, // If the file has decorators (initialized by binding)
396+
HasParamDecorators = 1 << 24, // If the file has parameter decorators (initialized by binding)
397+
HasAsyncFunctions = 1 << 25, // If the file has async functions (initialized by binding)
398+
394399
Modifier = Export | Ambient | Public | Private | Protected | Static | Abstract | Default | Async,
395400
AccessibilityModifier = Public | Private | Protected,
396401
BlockScoped = Let | Const,
397402

398-
ReachabilityCheckFlags = HasImplicitReturn | HasExplicitReturn
403+
ReachabilityCheckFlags = HasImplicitReturn | HasExplicitReturn,
404+
EmitHelperFlags = HasClassExtends | HasDecorators | HasParamDecorators | HasAsyncFunctions,
399405
}
400406

401407
/* @internal */
@@ -2047,11 +2053,6 @@ namespace ts {
20472053
TypeChecked = 0x00000001, // Node has been type checked
20482054
LexicalThis = 0x00000002, // Lexical 'this' reference
20492055
CaptureThis = 0x00000004, // Lexical 'this' used in body
2050-
EmitExtends = 0x00000008, // Emit __extends
2051-
EmitDecorate = 0x00000010, // Emit __decorate
2052-
EmitParam = 0x00000020, // Emit __param helper for decorators
2053-
EmitAwaiter = 0x00000040, // Emit __awaiter
2054-
EmitGenerator = 0x00000080, // Emit __generator
20552056
SuperInstance = 0x00000100, // Instance 'super' reference
20562057
SuperStatic = 0x00000200, // Static 'super' reference
20572058
ContextChecked = 0x00000400, // Contextual types have been assigned

0 commit comments

Comments
 (0)