Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit fe33e61

Browse filesBrowse files
authored
Reparse top level 'await' in modules (microsoft#39084)
* Reparse top-level 'await' in modules * Add more tests and additional diagnostics * One more incremental parse test
1 parent 59ad375 commit fe33e61
Copy full SHA for fe33e61

111 files changed

+3,234-187Lines changed: 3234 additions & 187 deletions

File tree

Expand file treeCollapse file tree
Open diff view settings
Filter options

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Dismiss banner
Expand file treeCollapse file tree
Open diff view settings
Collapse file

‎src/compiler/checker.ts‎

Copy file name to clipboardExpand all lines: src/compiler/checker.ts
+33-10Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -28255,7 +28255,7 @@ namespace ts {
2825528255
return undefinedWideningType;
2825628256
}
2825728257

28258-
function isTopLevelAwait(node: AwaitExpression) {
28258+
function isInTopLevelContext(node: Node) {
2825928259
const container = getThisContainer(node, /*includeArrowFunctions*/ true);
2826028260
return isSourceFile(container);
2826128261
}
@@ -28264,7 +28264,7 @@ namespace ts {
2826428264
// Grammar checking
2826528265
if (produceDiagnostics) {
2826628266
if (!(node.flags & NodeFlags.AwaitContext)) {
28267-
if (isTopLevelAwait(node)) {
28267+
if (isInTopLevelContext(node)) {
2826828268
const sourceFile = getSourceFileOfNode(node);
2826928269
if (!hasParseDiagnostics(sourceFile)) {
2827028270
let span: TextSpan | undefined;
@@ -33586,7 +33586,7 @@ namespace ts {
3358633586
function checkThrowStatement(node: ThrowStatement) {
3358733587
// Grammar checking
3358833588
if (!checkGrammarStatementInAmbientContext(node)) {
33589-
if (node.expression === undefined) {
33589+
if (isIdentifier(node.expression) && !node.expression.escapedText) {
3359033590
grammarErrorAfterFirstToken(node, Diagnostics.Line_break_not_permitted_here);
3359133591
}
3359233592
}
@@ -34861,6 +34861,7 @@ namespace ts {
3486134861
}
3486234862

3486334863
function checkImportBinding(node: ImportEqualsDeclaration | ImportClause | NamespaceImport | ImportSpecifier) {
34864+
checkGrammarAwaitIdentifier(node.name);
3486434865
checkCollisionWithRequireExportsInGeneratedCode(node, node.name!);
3486534866
checkCollisionWithGlobalPromiseInGeneratedCode(node, node.name!);
3486634867
checkAliasSymbol(node);
@@ -37626,17 +37627,32 @@ namespace ts {
3762637627
return false;
3762737628
}
3762837629

37630+
function checkGrammarAwaitIdentifier(name: Identifier | undefined): boolean {
37631+
if (name && isIdentifier(name) && name.originalKeywordKind === SyntaxKind.AwaitKeyword && isInTopLevelContext(name.parent)) {
37632+
const file = getSourceFileOfNode(name);
37633+
if (!file.isDeclarationFile && isExternalModule(file)) {
37634+
return grammarErrorOnNode(name, Diagnostics.Identifier_expected_0_is_a_reserved_word_at_the_top_level_of_a_module, idText(name));
37635+
}
37636+
}
37637+
return false;
37638+
}
37639+
3762937640
function checkGrammarFunctionLikeDeclaration(node: FunctionLikeDeclaration | MethodSignature): boolean {
3763037641
// Prevent cascading error by short-circuit
3763137642
const file = getSourceFileOfNode(node);
37632-
return checkGrammarDecoratorsAndModifiers(node) || checkGrammarTypeParameterList(node.typeParameters, file) ||
37633-
checkGrammarParameterList(node.parameters) || checkGrammarArrowFunction(node, file) ||
37643+
return checkGrammarDecoratorsAndModifiers(node) ||
37644+
checkGrammarTypeParameterList(node.typeParameters, file) ||
37645+
(isFunctionDeclaration(node) && checkGrammarAwaitIdentifier(node.name)) ||
37646+
checkGrammarParameterList(node.parameters) ||
37647+
checkGrammarArrowFunction(node, file) ||
3763437648
(isFunctionLikeDeclaration(node) && checkGrammarForUseStrictSimpleParameterList(node));
3763537649
}
3763637650

3763737651
function checkGrammarClassLikeDeclaration(node: ClassLikeDeclaration): boolean {
3763837652
const file = getSourceFileOfNode(node);
37639-
return checkGrammarClassDeclarationHeritageClauses(node) || checkGrammarTypeParameterList(node.typeParameters, file);
37653+
return (isClassDeclaration(node) && checkGrammarAwaitIdentifier(node.name)) ||
37654+
checkGrammarClassDeclarationHeritageClauses(node) ||
37655+
checkGrammarTypeParameterList(node.typeParameters, file);
3764037656
}
3764137657

3764237658
function checkGrammarArrowFunction(node: Node, file: SourceFile): boolean {
@@ -38276,11 +38292,15 @@ namespace ts {
3827638292
if (node.propertyName) {
3827738293
return grammarErrorOnNode(node.name, Diagnostics.A_rest_element_cannot_have_a_property_name);
3827838294
}
38295+
}
3827938296

38280-
if (node.initializer) {
38281-
// Error on equals token which immediately precedes the initializer
38282-
return grammarErrorAtPos(node, node.initializer.pos - 1, 1, Diagnostics.A_rest_element_cannot_have_an_initializer);
38283-
}
38297+
if (isIdentifier(node.name) && checkGrammarAwaitIdentifier(node.name)) {
38298+
return true;
38299+
}
38300+
38301+
if (node.dotDotDotToken && node.initializer) {
38302+
// Error on equals token which immediately precedes the initializer
38303+
return grammarErrorAtPos(node, node.initializer.pos - 1, 1, Diagnostics.A_rest_element_cannot_have_an_initializer);
3828438304
}
3828538305
}
3828638306

@@ -38341,6 +38361,9 @@ namespace ts {
3834138361
}
3834238362
}
3834338363
}
38364+
if (isIdentifier(node.name) && checkGrammarAwaitIdentifier(node.name)) {
38365+
return true;
38366+
}
3834438367

3834538368
if (node.exclamationToken && (node.parent.parent.kind !== SyntaxKind.VariableStatement || !node.type || node.initializer || node.flags & NodeFlags.Ambient)) {
3834638369
return grammarErrorOnNode(node.exclamationToken, Diagnostics.Definite_assignment_assertions_can_only_be_used_along_with_a_type_annotation);
Collapse file

‎src/compiler/diagnosticMessages.json‎

Copy file name to clipboardExpand all lines: src/compiler/diagnosticMessages.json
+5Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -867,6 +867,11 @@
867867
"category": "Error",
868868
"code": 1261
869869
},
870+
"Identifier expected. '{0}' is a reserved word at the top-level of a module.": {
871+
"category": "Error",
872+
"code": 1262
873+
},
874+
870875
"'with' statements are not allowed in an async function block.": {
871876
"category": "Error",
872877
"code": 1300
Collapse file

‎src/compiler/factory/nodeFactory.ts‎

Copy file name to clipboardExpand all lines: src/compiler/factory/nodeFactory.ts
+61-10Lines changed: 61 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -558,8 +558,29 @@ namespace ts {
558558
decorators,
559559
modifiers
560560
);
561-
node.name = asName(name);
562-
node.transformFlags |= propagateChildFlags(node.name);
561+
name = asName(name);
562+
node.name = name;
563+
564+
// The PropertyName of a member is allowed to be `await`.
565+
// We don't need to exclude `await` for type signatures since types
566+
// don't propagate child flags.
567+
if (name) {
568+
switch (node.kind) {
569+
case SyntaxKind.MethodDeclaration:
570+
case SyntaxKind.GetAccessor:
571+
case SyntaxKind.SetAccessor:
572+
case SyntaxKind.PropertyDeclaration:
573+
case SyntaxKind.PropertyAssignment:
574+
if (isIdentifier(name)) {
575+
node.transformFlags |= propagateIdentifierNameFlags(name);
576+
break;
577+
}
578+
// fall through
579+
default:
580+
node.transformFlags |= propagateChildFlags(name);
581+
break;
582+
}
583+
}
563584
return node;
564585
}
565586

@@ -633,7 +654,7 @@ namespace ts {
633654
type
634655
);
635656
node.body = body;
636-
node.transformFlags |= propagateChildFlags(node.body);
657+
node.transformFlags |= propagateChildFlags(node.body) & ~TransformFlags.ContainsPossibleTopLevelAwait;
637658
if (!body) node.transformFlags |= TransformFlags.ContainsTypeScript;
638659
return node;
639660
}
@@ -826,6 +847,9 @@ namespace ts {
826847
// NOTE: we do not use `setChildren` here because typeArguments in an identifier do not contribute to transformations
827848
node.typeArguments = createNodeArray(typeArguments);
828849
}
850+
if (node.originalKeywordKind === SyntaxKind.AwaitKeyword) {
851+
node.transformFlags |= TransformFlags.ContainsPossibleTopLevelAwait;
852+
}
829853
return node;
830854
}
831855

@@ -1015,7 +1039,7 @@ namespace ts {
10151039
node.right = asName(right);
10161040
node.transformFlags |=
10171041
propagateChildFlags(node.left) |
1018-
propagateChildFlags(node.right);
1042+
propagateIdentifierNameFlags(node.right);
10191043
return node;
10201044
}
10211045

@@ -2030,9 +2054,13 @@ namespace ts {
20302054
node.propertyName = asName(propertyName);
20312055
node.dotDotDotToken = dotDotDotToken;
20322056
node.transformFlags |=
2033-
propagateChildFlags(node.propertyName) |
20342057
propagateChildFlags(node.dotDotDotToken) |
20352058
TransformFlags.ContainsES2015;
2059+
if (node.propertyName) {
2060+
node.transformFlags |= isIdentifier(node.propertyName) ?
2061+
propagateIdentifierNameFlags(node.propertyName) :
2062+
propagateChildFlags(node.propertyName);
2063+
}
20362064
if (dotDotDotToken) node.transformFlags |= TransformFlags.ContainsRestOrSpread;
20372065
return node;
20382066
}
@@ -2096,7 +2124,9 @@ namespace ts {
20962124
node.name = asName(name);
20972125
node.transformFlags =
20982126
propagateChildFlags(node.expression) |
2099-
propagateChildFlags(node.name);
2127+
(isIdentifier(node.name) ?
2128+
propagateIdentifierNameFlags(node.name) :
2129+
propagateChildFlags(node.name));
21002130
if (isSuperKeyword(expression)) {
21012131
// super method calls require a lexical 'this'
21022132
// super method calls require 'super' hoisting in ES2017 and ES2018 async functions and async generators
@@ -2126,10 +2156,12 @@ namespace ts {
21262156
node.questionDotToken = questionDotToken;
21272157
node.name = asName(name);
21282158
node.transformFlags |=
2159+
TransformFlags.ContainsES2020 |
21292160
propagateChildFlags(node.expression) |
21302161
propagateChildFlags(node.questionDotToken) |
2131-
propagateChildFlags(node.name) |
2132-
TransformFlags.ContainsES2020;
2162+
(isIdentifier(node.name) ?
2163+
propagateIdentifierNameFlags(node.name) :
2164+
propagateChildFlags(node.name));
21332165
return node;
21342166
}
21352167

@@ -3558,6 +3590,7 @@ namespace ts {
35583590
node.transformFlags |=
35593591
propagateChildrenFlags(node.members) |
35603592
TransformFlags.ContainsTypeScript;
3593+
node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // Enum declarations cannot contain `await`
35613594
return node;
35623595
}
35633596

@@ -3601,6 +3634,7 @@ namespace ts {
36013634
propagateChildFlags(node.body) |
36023635
TransformFlags.ContainsTypeScript;
36033636
}
3637+
node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // Module declarations cannot contain `await`.
36043638
return node;
36053639
}
36063640

@@ -3685,6 +3719,7 @@ namespace ts {
36853719
node.moduleReference = moduleReference;
36863720
node.transformFlags |= propagateChildFlags(node.moduleReference);
36873721
if (!isExternalModuleReference(node.moduleReference)) node.transformFlags |= TransformFlags.ContainsTypeScript;
3722+
node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // Import= declaration is always parsed in an Await context
36883723
return node;
36893724
}
36903725

@@ -3721,6 +3756,7 @@ namespace ts {
37213756
node.transformFlags |=
37223757
propagateChildFlags(node.importClause) |
37233758
propagateChildFlags(node.moduleSpecifier);
3759+
node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context
37243760
return node;
37253761
}
37263762

@@ -3752,6 +3788,7 @@ namespace ts {
37523788
if (isTypeOnly) {
37533789
node.transformFlags |= TransformFlags.ContainsTypeScript;
37543790
}
3791+
node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context
37553792
return node;
37563793
}
37573794

@@ -3769,6 +3806,7 @@ namespace ts {
37693806
const node = createBaseNode<NamespaceImport>(SyntaxKind.NamespaceImport);
37703807
node.name = name;
37713808
node.transformFlags |= propagateChildFlags(node.name);
3809+
node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context
37723810
return node;
37733811
}
37743812

@@ -3786,6 +3824,7 @@ namespace ts {
37863824
node.transformFlags |=
37873825
propagateChildFlags(node.name) |
37883826
TransformFlags.ContainsESNext;
3827+
node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context
37893828
return node;
37903829
}
37913830

@@ -3801,6 +3840,7 @@ namespace ts {
38013840
const node = createBaseNode<NamedImports>(SyntaxKind.NamedImports);
38023841
node.elements = createNodeArray(elements);
38033842
node.transformFlags |= propagateChildrenFlags(node.elements);
3843+
node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context
38043844
return node;
38053845
}
38063846

@@ -3819,6 +3859,7 @@ namespace ts {
38193859
node.transformFlags |=
38203860
propagateChildFlags(node.propertyName) |
38213861
propagateChildFlags(node.name);
3862+
node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context
38223863
return node;
38233864
}
38243865

@@ -3847,6 +3888,7 @@ namespace ts {
38473888
? parenthesizerRules().parenthesizeRightSideOfBinary(SyntaxKind.EqualsToken, /*leftSide*/ undefined, expression)
38483889
: parenthesizerRules().parenthesizeExpressionOfExportDefault(expression);
38493890
node.transformFlags |= propagateChildFlags(node.expression);
3891+
node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context
38503892
return node;
38513893
}
38523894

@@ -3883,6 +3925,7 @@ namespace ts {
38833925
node.transformFlags |=
38843926
propagateChildFlags(node.exportClause) |
38853927
propagateChildFlags(node.moduleSpecifier);
3928+
node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context
38863929
return node;
38873930
}
38883931

@@ -3909,6 +3952,7 @@ namespace ts {
39093952
const node = createBaseNode<NamedExports>(SyntaxKind.NamedExports);
39103953
node.elements = createNodeArray(elements);
39113954
node.transformFlags |= propagateChildrenFlags(node.elements);
3955+
node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context
39123956
return node;
39133957
}
39143958

@@ -3927,6 +3971,7 @@ namespace ts {
39273971
node.transformFlags |=
39283972
propagateChildFlags(node.propertyName) |
39293973
propagateChildFlags(node.name);
3974+
node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context
39303975
return node;
39313976
}
39323977

@@ -3957,6 +4002,7 @@ namespace ts {
39574002
const node = createBaseNode<ExternalModuleReference>(SyntaxKind.ExternalModuleReference);
39584003
node.expression = expression;
39594004
node.transformFlags |= propagateChildFlags(node.expression);
4005+
node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context
39604006
return node;
39614007
}
39624008

@@ -5781,14 +5827,19 @@ namespace ts {
57815827
return tokenValue;
57825828
}
57835829

5784-
function propagatePropertyNameFlags(node: PropertyName, transformFlags: TransformFlags) {
5830+
function propagateIdentifierNameFlags(node: Identifier) {
5831+
// An IdentifierName is allowed to be `await`
5832+
return propagateChildFlags(node) & ~TransformFlags.ContainsPossibleTopLevelAwait;
5833+
}
5834+
5835+
function propagatePropertyNameFlagsOfChild(node: PropertyName, transformFlags: TransformFlags) {
57855836
return transformFlags | (node.transformFlags & TransformFlags.PropertyNamePropagatingFlags);
57865837
}
57875838

57885839
function propagateChildFlags(child: Node | undefined): TransformFlags {
57895840
if (!child) return TransformFlags.None;
57905841
const childFlags = child.transformFlags & ~getTransformFlagsSubtreeExclusions(child.kind);
5791-
return isNamedDeclaration(child) && isPropertyName(child.name) ? propagatePropertyNameFlags(child.name, childFlags) : childFlags;
5842+
return isNamedDeclaration(child) && isPropertyName(child.name) ? propagatePropertyNameFlagsOfChild(child.name, childFlags) : childFlags;
57925843
}
57935844

57945845
function propagateChildrenFlags(children: NodeArray<Node> | undefined): TransformFlags {
Collapse file

‎src/compiler/factory/utilities.ts‎

Copy file name to clipboardExpand all lines: src/compiler/factory/utilities.ts
+5Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -815,6 +815,11 @@ namespace ts {
815815
|| kind === SyntaxKind.ExportDeclaration;
816816
}
817817

818+
/* @internal */
819+
export function isExportModifier(node: Modifier): node is ExportKeyword {
820+
return node.kind === SyntaxKind.ExportKeyword;
821+
}
822+
818823
/* @internal */
819824
export function isAsyncModifier(node: Modifier): node is AsyncKeyword {
820825
return node.kind === SyntaxKind.AsyncKeyword;

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.