Skip to content

Commit 097972f

Browse files
committed
Add more tests and additional diagnostics
1 parent 73befcc commit 097972f

File tree

113 files changed

+2172
-1193
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

113 files changed

+2172
-1193
lines changed

src/compiler/checker.ts

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28210,7 +28210,7 @@ namespace ts {
2821028210
return undefinedWideningType;
2821128211
}
2821228212

28213-
function isTopLevelAwait(node: AwaitExpression) {
28213+
function isInTopLevelContext(node: Node) {
2821428214
const container = getThisContainer(node, /*includeArrowFunctions*/ true);
2821528215
return isSourceFile(container);
2821628216
}
@@ -28219,7 +28219,7 @@ namespace ts {
2821928219
// Grammar checking
2822028220
if (produceDiagnostics) {
2822128221
if (!(node.flags & NodeFlags.AwaitContext)) {
28222-
if (isTopLevelAwait(node)) {
28222+
if (isInTopLevelContext(node)) {
2822328223
const sourceFile = getSourceFileOfNode(node);
2822428224
if (!hasParseDiagnostics(sourceFile)) {
2822528225
let span: TextSpan | undefined;
@@ -34802,6 +34802,7 @@ namespace ts {
3480234802
}
3480334803

3480434804
function checkImportBinding(node: ImportEqualsDeclaration | ImportClause | NamespaceImport | ImportSpecifier) {
34805+
checkGrammarAwaitIdentifier(node.name);
3480534806
checkCollisionWithRequireExportsInGeneratedCode(node, node.name!);
3480634807
checkCollisionWithGlobalPromiseInGeneratedCode(node, node.name!);
3480734808
checkAliasSymbol(node);
@@ -37545,17 +37546,32 @@ namespace ts {
3754537546
return false;
3754637547
}
3754737548

37549+
function checkGrammarAwaitIdentifier(name: Identifier | undefined): boolean {
37550+
if (name && isIdentifier(name) && name.originalKeywordKind === SyntaxKind.AwaitKeyword && isInTopLevelContext(name.parent)) {
37551+
const file = getSourceFileOfNode(name);
37552+
if (!file.isDeclarationFile && isExternalModule(file)) {
37553+
return grammarErrorOnNode(name, Diagnostics.Identifier_expected_0_is_a_reserved_word_at_the_top_level_of_a_module, idText(name));
37554+
}
37555+
}
37556+
return false;
37557+
}
37558+
3754837559
function checkGrammarFunctionLikeDeclaration(node: FunctionLikeDeclaration | MethodSignature): boolean {
3754937560
// Prevent cascading error by short-circuit
3755037561
const file = getSourceFileOfNode(node);
37551-
return checkGrammarDecoratorsAndModifiers(node) || checkGrammarTypeParameterList(node.typeParameters, file) ||
37552-
checkGrammarParameterList(node.parameters) || checkGrammarArrowFunction(node, file) ||
37562+
return checkGrammarDecoratorsAndModifiers(node) ||
37563+
checkGrammarTypeParameterList(node.typeParameters, file) ||
37564+
(isFunctionDeclaration(node) && checkGrammarAwaitIdentifier(node.name)) ||
37565+
checkGrammarParameterList(node.parameters) ||
37566+
checkGrammarArrowFunction(node, file) ||
3755337567
(isFunctionLikeDeclaration(node) && checkGrammarForUseStrictSimpleParameterList(node));
3755437568
}
3755537569

3755637570
function checkGrammarClassLikeDeclaration(node: ClassLikeDeclaration): boolean {
3755737571
const file = getSourceFileOfNode(node);
37558-
return checkGrammarClassDeclarationHeritageClauses(node) || checkGrammarTypeParameterList(node.typeParameters, file);
37572+
return (isClassDeclaration(node) && checkGrammarAwaitIdentifier(node.name)) ||
37573+
checkGrammarClassDeclarationHeritageClauses(node) ||
37574+
checkGrammarTypeParameterList(node.typeParameters, file);
3755937575
}
3756037576

3756137577
function checkGrammarArrowFunction(node: Node, file: SourceFile): boolean {
@@ -38195,11 +38211,15 @@ namespace ts {
3819538211
if (node.propertyName) {
3819638212
return grammarErrorOnNode(node.name, Diagnostics.A_rest_element_cannot_have_a_property_name);
3819738213
}
38214+
}
3819838215

38199-
if (node.initializer) {
38200-
// Error on equals token which immediately precedes the initializer
38201-
return grammarErrorAtPos(node, node.initializer.pos - 1, 1, Diagnostics.A_rest_element_cannot_have_an_initializer);
38202-
}
38216+
if (isIdentifier(node.name) && checkGrammarAwaitIdentifier(node.name)) {
38217+
return true;
38218+
}
38219+
38220+
if (node.dotDotDotToken && node.initializer) {
38221+
// Error on equals token which immediately precedes the initializer
38222+
return grammarErrorAtPos(node, node.initializer.pos - 1, 1, Diagnostics.A_rest_element_cannot_have_an_initializer);
3820338223
}
3820438224
}
3820538225

@@ -38260,6 +38280,9 @@ namespace ts {
3826038280
}
3826138281
}
3826238282
}
38283+
if (isIdentifier(node.name) && checkGrammarAwaitIdentifier(node.name)) {
38284+
return true;
38285+
}
3826338286

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

src/compiler/diagnosticMessages.json

Lines 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

src/compiler/factory/nodeFactory.ts

Lines changed: 54 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -556,14 +556,29 @@ namespace ts {
556556
decorators,
557557
modifiers
558558
);
559-
node.name = asName(name);
560-
node.transformFlags |=
561-
kind === SyntaxKind.MethodDeclaration ||
562-
kind === SyntaxKind.GetAccessor ||
563-
kind === SyntaxKind.SetAccessor ||
564-
kind === SyntaxKind.PropertyDeclaration ?
565-
propagatePropertyNameFlags(node.name) :
566-
propagateChildFlags(node.name) ;
559+
name = asName(name);
560+
node.name = name;
561+
562+
// The PropertyName of a member is allowed to be `await`.
563+
// We don't need to exclude `await` for type signatures since types
564+
// don't propagate child flags.
565+
if (name) {
566+
switch (node.kind) {
567+
case SyntaxKind.MethodDeclaration:
568+
case SyntaxKind.GetAccessor:
569+
case SyntaxKind.SetAccessor:
570+
case SyntaxKind.PropertyDeclaration:
571+
case SyntaxKind.PropertyAssignment:
572+
if (isIdentifier(name)) {
573+
node.transformFlags |= propagateIdentifierNameFlags(name);
574+
break;
575+
}
576+
// fall through
577+
default:
578+
node.transformFlags |= propagateChildFlags(name);
579+
break;
580+
}
581+
}
567582
return node;
568583
}
569584

@@ -637,7 +652,7 @@ namespace ts {
637652
type
638653
);
639654
node.body = body;
640-
node.transformFlags |= propagateChildFlags(node.body);
655+
node.transformFlags |= propagateChildFlags(node.body) & ~TransformFlags.ContainsPossibleTopLevelAwait;
641656
if (!body) node.transformFlags |= TransformFlags.ContainsTypeScript;
642657
return node;
643658
}
@@ -1022,7 +1037,7 @@ namespace ts {
10221037
node.right = asName(right);
10231038
node.transformFlags |=
10241039
propagateChildFlags(node.left) |
1025-
propagateChildFlags(node.right);
1040+
propagateIdentifierNameFlags(node.right);
10261041
return node;
10271042
}
10281043

@@ -2037,9 +2052,13 @@ namespace ts {
20372052
node.propertyName = asName(propertyName);
20382053
node.dotDotDotToken = dotDotDotToken;
20392054
node.transformFlags |=
2040-
propagateChildFlags(node.propertyName) |
20412055
propagateChildFlags(node.dotDotDotToken) |
20422056
TransformFlags.ContainsES2015;
2057+
if (node.propertyName) {
2058+
node.transformFlags |= isIdentifier(node.propertyName) ?
2059+
propagateIdentifierNameFlags(node.propertyName) :
2060+
propagateChildFlags(node.propertyName);
2061+
}
20432062
if (dotDotDotToken) node.transformFlags |= TransformFlags.ContainsRestOrSpread;
20442063
return node;
20452064
}
@@ -2103,7 +2122,9 @@ namespace ts {
21032122
node.name = asName(name);
21042123
node.transformFlags =
21052124
propagateChildFlags(node.expression) |
2106-
propagatePropertyNameFlags(node.name);
2125+
(isIdentifier(node.name) ?
2126+
propagateIdentifierNameFlags(node.name) :
2127+
propagateChildFlags(node.name));
21072128
if (isSuperKeyword(expression)) {
21082129
// super method calls require a lexical 'this'
21092130
// super method calls require 'super' hoisting in ES2017 and ES2018 async functions and async generators
@@ -2133,10 +2154,12 @@ namespace ts {
21332154
node.questionDotToken = questionDotToken;
21342155
node.name = asName(name);
21352156
node.transformFlags |=
2157+
TransformFlags.ContainsES2020 |
21362158
propagateChildFlags(node.expression) |
21372159
propagateChildFlags(node.questionDotToken) |
2138-
propagateChildFlags(node.name) |
2139-
TransformFlags.ContainsES2020;
2160+
(isIdentifier(node.name) ?
2161+
propagateIdentifierNameFlags(node.name) :
2162+
propagateChildFlags(node.name));
21402163
return node;
21412164
}
21422165

@@ -3565,6 +3588,7 @@ namespace ts {
35653588
node.transformFlags |=
35663589
propagateChildrenFlags(node.members) |
35673590
TransformFlags.ContainsTypeScript;
3591+
node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // Enum declarations cannot contain `await`
35683592
return node;
35693593
}
35703594

@@ -3608,6 +3632,7 @@ namespace ts {
36083632
propagateChildFlags(node.body) |
36093633
TransformFlags.ContainsTypeScript;
36103634
}
3635+
node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // Module declarations cannot contain `await`.
36113636
return node;
36123637
}
36133638

@@ -3692,6 +3717,7 @@ namespace ts {
36923717
node.moduleReference = moduleReference;
36933718
node.transformFlags |= propagateChildFlags(node.moduleReference);
36943719
if (!isExternalModuleReference(node.moduleReference)) node.transformFlags |= TransformFlags.ContainsTypeScript;
3720+
node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // Import= declaration is always parsed in an Await context
36953721
return node;
36963722
}
36973723

@@ -3728,6 +3754,7 @@ namespace ts {
37283754
node.transformFlags |=
37293755
propagateChildFlags(node.importClause) |
37303756
propagateChildFlags(node.moduleSpecifier);
3757+
node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context
37313758
return node;
37323759
}
37333760

@@ -3759,6 +3786,7 @@ namespace ts {
37593786
if (isTypeOnly) {
37603787
node.transformFlags |= TransformFlags.ContainsTypeScript;
37613788
}
3789+
node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context
37623790
return node;
37633791
}
37643792

@@ -3776,6 +3804,7 @@ namespace ts {
37763804
const node = createBaseNode<NamespaceImport>(SyntaxKind.NamespaceImport);
37773805
node.name = name;
37783806
node.transformFlags |= propagateChildFlags(node.name);
3807+
node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context
37793808
return node;
37803809
}
37813810

@@ -3793,6 +3822,7 @@ namespace ts {
37933822
node.transformFlags |=
37943823
propagateChildFlags(node.name) |
37953824
TransformFlags.ContainsESNext;
3825+
node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context
37963826
return node;
37973827
}
37983828

@@ -3808,6 +3838,7 @@ namespace ts {
38083838
const node = createBaseNode<NamedImports>(SyntaxKind.NamedImports);
38093839
node.elements = createNodeArray(elements);
38103840
node.transformFlags |= propagateChildrenFlags(node.elements);
3841+
node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context
38113842
return node;
38123843
}
38133844

@@ -3826,6 +3857,7 @@ namespace ts {
38263857
node.transformFlags |=
38273858
propagateChildFlags(node.propertyName) |
38283859
propagateChildFlags(node.name);
3860+
node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context
38293861
return node;
38303862
}
38313863

@@ -3854,6 +3886,7 @@ namespace ts {
38543886
? parenthesizerRules().parenthesizeRightSideOfBinary(SyntaxKind.EqualsToken, /*leftSide*/ undefined, expression)
38553887
: parenthesizerRules().parenthesizeExpressionOfExportDefault(expression);
38563888
node.transformFlags |= propagateChildFlags(node.expression);
3889+
node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context
38573890
return node;
38583891
}
38593892

@@ -3890,6 +3923,7 @@ namespace ts {
38903923
node.transformFlags |=
38913924
propagateChildFlags(node.exportClause) |
38923925
propagateChildFlags(node.moduleSpecifier);
3926+
node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context
38933927
return node;
38943928
}
38953929

@@ -3916,6 +3950,7 @@ namespace ts {
39163950
const node = createBaseNode<NamedExports>(SyntaxKind.NamedExports);
39173951
node.elements = createNodeArray(elements);
39183952
node.transformFlags |= propagateChildrenFlags(node.elements);
3953+
node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context
39193954
return node;
39203955
}
39213956

@@ -3934,6 +3969,7 @@ namespace ts {
39343969
node.transformFlags |=
39353970
propagateChildFlags(node.propertyName) |
39363971
propagateChildFlags(node.name);
3972+
node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context
39373973
return node;
39383974
}
39393975

@@ -3964,6 +4000,7 @@ namespace ts {
39644000
const node = createBaseNode<ExternalModuleReference>(SyntaxKind.ExternalModuleReference);
39654001
node.expression = expression;
39664002
node.transformFlags |= propagateChildFlags(node.expression);
4003+
node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context
39674004
return node;
39684005
}
39694006

@@ -5786,13 +5823,9 @@ namespace ts {
57865823
return tokenValue;
57875824
}
57885825

5789-
function propagatePropertyNameFlags(node: Node | undefined) {
5790-
if (!node) return TransformFlags.None;
5791-
// `await` in a property name should not be considered a possible top-level await keyword
5792-
const transformFlags = propagateChildFlags(node);
5793-
return isIdentifier(node) ?
5794-
transformFlags & ~TransformFlags.ContainsPossibleTopLevelAwait :
5795-
transformFlags;
5826+
function propagateIdentifierNameFlags(node: Identifier) {
5827+
// An IdentifierName is allowed to be `await`
5828+
return propagateChildFlags(node) & ~TransformFlags.ContainsPossibleTopLevelAwait;
57965829
}
57975830

57985831
function propagatePropertyNameFlagsOfChild(node: PropertyName, transformFlags: TransformFlags) {

src/compiler/factory/utilities.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -811,6 +811,11 @@ namespace ts {
811811
|| kind === SyntaxKind.ExportDeclaration;
812812
}
813813

814+
/* @internal */
815+
export function isExportModifier(node: Modifier): node is ExportKeyword {
816+
return node.kind === SyntaxKind.ExportKeyword;
817+
}
818+
814819
/* @internal */
815820
export function isAsyncModifier(node: Modifier): node is AsyncKeyword {
816821
return node.kind === SyntaxKind.AsyncKeyword;

0 commit comments

Comments
 (0)