Skip to content

Commit 8ab882a

Browse files
committed
Reparse top-level 'await' in modules
1 parent 417b0a6 commit 8ab882a

File tree

42 files changed

+2098
-44
lines changed

Some content is hidden

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

42 files changed

+2098
-44
lines changed

src/compiler/checker.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -33533,7 +33533,7 @@ namespace ts {
3353333533
function checkThrowStatement(node: ThrowStatement) {
3353433534
// Grammar checking
3353533535
if (!checkGrammarStatementInAmbientContext(node)) {
33536-
if (node.expression === undefined) {
33536+
if (isIdentifier(node.expression) && !node.expression.escapedText) {
3353733537
grammarErrorAfterFirstToken(node, Diagnostics.Line_break_not_permitted_here);
3353833538
}
3353933539
}

src/compiler/factory/nodeFactory.ts

+22-4
Original file line numberDiff line numberDiff line change
@@ -557,7 +557,13 @@ namespace ts {
557557
modifiers
558558
);
559559
node.name = asName(name);
560-
node.transformFlags |= propagateChildFlags(node.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) ;
561567
return node;
562568
}
563569

@@ -824,6 +830,9 @@ namespace ts {
824830
// NOTE: we do not use `setChildren` here because typeArguments in an identifier do not contribute to transformations
825831
node.typeArguments = createNodeArray(typeArguments);
826832
}
833+
if (node.originalKeywordKind === SyntaxKind.AwaitKeyword) {
834+
node.transformFlags |= TransformFlags.ContainsPossibleTopLevelAwait;
835+
}
827836
return node;
828837
}
829838

@@ -2094,7 +2103,7 @@ namespace ts {
20942103
node.name = asName(name);
20952104
node.transformFlags =
20962105
propagateChildFlags(node.expression) |
2097-
propagateChildFlags(node.name);
2106+
propagatePropertyNameFlags(node.name);
20982107
if (isSuperKeyword(expression)) {
20992108
// super method calls require a lexical 'this'
21002109
// super method calls require 'super' hoisting in ES2017 and ES2018 async functions and async generators
@@ -5777,14 +5786,23 @@ namespace ts {
57775786
return tokenValue;
57785787
}
57795788

5780-
function propagatePropertyNameFlags(node: PropertyName, transformFlags: TransformFlags) {
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;
5796+
}
5797+
5798+
function propagatePropertyNameFlagsOfChild(node: PropertyName, transformFlags: TransformFlags) {
57815799
return transformFlags | (node.transformFlags & TransformFlags.PropertyNamePropagatingFlags);
57825800
}
57835801

57845802
function propagateChildFlags(child: Node | undefined): TransformFlags {
57855803
if (!child) return TransformFlags.None;
57865804
const childFlags = child.transformFlags & ~getTransformFlagsSubtreeExclusions(child.kind);
5787-
return isNamedDeclaration(child) && isPropertyName(child.name) ? propagatePropertyNameFlags(child.name, childFlags) : childFlags;
5805+
return isNamedDeclaration(child) && isPropertyName(child.name) ? propagatePropertyNameFlagsOfChild(child.name, childFlags) : childFlags;
57885806
}
57895807

57905808
function propagateChildrenFlags(children: NodeArray<Node> | undefined): TransformFlags {

src/compiler/parser.ts

+176-20
Large diffs are not rendered by default.

src/compiler/types.ts

+8-7
Original file line numberDiff line numberDiff line change
@@ -2722,7 +2722,7 @@ namespace ts {
27222722

27232723
export interface ThrowStatement extends Statement {
27242724
readonly kind: SyntaxKind.ThrowStatement;
2725-
readonly expression?: Expression;
2725+
readonly expression: Expression;
27262726
}
27272727

27282728
export interface TryStatement extends Statement {
@@ -6242,6 +6242,7 @@ namespace ts {
62426242
ContainsHoistedDeclarationOrCompletion = 1 << 20,
62436243
ContainsDynamicImport = 1 << 21,
62446244
ContainsClassFields = 1 << 22,
6245+
ContainsPossibleTopLevelAwait = 1 << 23,
62456246

62466247
// Please leave this as 1 << 29.
62476248
// It is the maximum bit we can set before we outgrow the size of a v8 small integer (SMI) on an x86 system.
@@ -6268,13 +6269,13 @@ namespace ts {
62686269
OuterExpressionExcludes = HasComputedFlags,
62696270
PropertyAccessExcludes = OuterExpressionExcludes,
62706271
NodeExcludes = PropertyAccessExcludes,
6271-
ArrowFunctionExcludes = NodeExcludes | ContainsTypeScriptClassSyntax | ContainsBlockScopedBinding | ContainsYield | ContainsAwait | ContainsHoistedDeclarationOrCompletion | ContainsBindingPattern | ContainsObjectRestOrSpread,
6272-
FunctionExcludes = NodeExcludes | ContainsTypeScriptClassSyntax | ContainsLexicalThis | ContainsBlockScopedBinding | ContainsYield | ContainsAwait | ContainsHoistedDeclarationOrCompletion | ContainsBindingPattern | ContainsObjectRestOrSpread,
6273-
ConstructorExcludes = NodeExcludes | ContainsLexicalThis | ContainsBlockScopedBinding | ContainsYield | ContainsAwait | ContainsHoistedDeclarationOrCompletion | ContainsBindingPattern | ContainsObjectRestOrSpread,
6274-
MethodOrAccessorExcludes = NodeExcludes | ContainsLexicalThis | ContainsBlockScopedBinding | ContainsYield | ContainsAwait | ContainsHoistedDeclarationOrCompletion | ContainsBindingPattern | ContainsObjectRestOrSpread,
6275-
PropertyExcludes = NodeExcludes | ContainsLexicalThis,
6272+
ArrowFunctionExcludes = NodeExcludes | ContainsTypeScriptClassSyntax | ContainsBlockScopedBinding | ContainsYield | ContainsAwait | ContainsHoistedDeclarationOrCompletion | ContainsBindingPattern | ContainsObjectRestOrSpread | ContainsPossibleTopLevelAwait,
6273+
FunctionExcludes = NodeExcludes | ContainsTypeScriptClassSyntax | ContainsLexicalThis | ContainsBlockScopedBinding | ContainsYield | ContainsAwait | ContainsHoistedDeclarationOrCompletion | ContainsBindingPattern | ContainsObjectRestOrSpread | ContainsPossibleTopLevelAwait,
6274+
ConstructorExcludes = NodeExcludes | ContainsLexicalThis | ContainsBlockScopedBinding | ContainsYield | ContainsAwait | ContainsHoistedDeclarationOrCompletion | ContainsBindingPattern | ContainsObjectRestOrSpread | ContainsPossibleTopLevelAwait,
6275+
MethodOrAccessorExcludes = NodeExcludes | ContainsLexicalThis | ContainsBlockScopedBinding | ContainsYield | ContainsAwait | ContainsHoistedDeclarationOrCompletion | ContainsBindingPattern | ContainsObjectRestOrSpread | ContainsPossibleTopLevelAwait,
6276+
PropertyExcludes = NodeExcludes | ContainsLexicalThis | ContainsPossibleTopLevelAwait,
62766277
ClassExcludes = NodeExcludes | ContainsTypeScriptClassSyntax | ContainsComputedPropertyName,
6277-
ModuleExcludes = NodeExcludes | ContainsTypeScriptClassSyntax | ContainsLexicalThis | ContainsBlockScopedBinding | ContainsHoistedDeclarationOrCompletion,
6278+
ModuleExcludes = NodeExcludes | ContainsTypeScriptClassSyntax | ContainsLexicalThis | ContainsBlockScopedBinding | ContainsHoistedDeclarationOrCompletion | ContainsPossibleTopLevelAwait,
62786279
TypeExcludes = ~ContainsTypeScript,
62796280
ObjectLiteralExcludes = NodeExcludes | ContainsTypeScriptClassSyntax | ContainsComputedPropertyName | ContainsObjectRestOrSpread,
62806281
ArrayLiteralOrCallOrNewExcludes = NodeExcludes | ContainsRestOrSpread,

src/compiler/visitorPublic.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -838,7 +838,7 @@ namespace ts {
838838

839839
case SyntaxKind.ThrowStatement:
840840
return factory.updateThrowStatement(<ThrowStatement>node,
841-
nodeVisitor((<ThrowStatement>node).expression!, visitor, isExpression)); // expression could be `undefined` due to invalid parse.
841+
nodeVisitor((<ThrowStatement>node).expression, visitor, isExpression));
842842

843843
case SyntaxKind.TryStatement:
844844
return factory.updateTryStatement(<TryStatement>node,

tests/baselines/reference/api/tsserverlibrary.d.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1445,7 +1445,7 @@ declare namespace ts {
14451445
}
14461446
export interface ThrowStatement extends Statement {
14471447
readonly kind: SyntaxKind.ThrowStatement;
1448-
readonly expression?: Expression;
1448+
readonly expression: Expression;
14491449
}
14501450
export interface TryStatement extends Statement {
14511451
readonly kind: SyntaxKind.TryStatement;

tests/baselines/reference/api/typescript.d.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1445,7 +1445,7 @@ declare namespace ts {
14451445
}
14461446
export interface ThrowStatement extends Statement {
14471447
readonly kind: SyntaxKind.ThrowStatement;
1448-
readonly expression?: Expression;
1448+
readonly expression: Expression;
14491449
}
14501450
export interface TryStatement extends Statement {
14511451
readonly kind: SyntaxKind.TryStatement;

tests/baselines/reference/throwWithoutNewLine2.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,5 @@ throw
33
a;
44

55
//// [throwWithoutNewLine2.js]
6-
throw;
6+
throw ;
77
a;
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
=== tests/cases/compiler/throwWithoutNewLine2.ts ===
22
throw
33
a;
4+
> : any
45
>a : any
56

tests/baselines/reference/topLevelAwait(module=esnext,target=es2015).errors.txt

+40-1
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,43 @@ tests/cases/conformance/externalModules/topLevelAwait.ts(2,1): error TS1378: Top
66
await x;
77
~~~~~
88
!!! error TS1378: Top-level 'await' expressions are only allowed when the 'module' option is set to 'esnext' or 'system', and the 'target' option is set to 'es2017' or higher.
9-
9+
10+
// reparse element access as await
11+
await [x];
12+
await [x, x];
13+
14+
// reparse call as await
15+
declare function f(): number;
16+
await (x);
17+
await (f(), x);
18+
await <number>(x);
19+
await <number>(f(), x);
20+
21+
// reparse tagged template as await
22+
await ``;
23+
await <string> ``;
24+
25+
// member names should be ok
26+
class C1 {
27+
await() {}
28+
}
29+
class C2 {
30+
get await() { return 1; }
31+
set await(value) { }
32+
}
33+
class C3 {
34+
await = 1;
35+
}
36+
({
37+
await() {}
38+
});
39+
({
40+
get await() { return 1 },
41+
set await(value) { }
42+
});
43+
({
44+
await: 1
45+
});
46+
47+
// property access name should be ok
48+
C1.prototype.await;
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,82 @@
11
//// [topLevelAwait.ts]
22
export const x = 1;
33
await x;
4-
4+
5+
// reparse element access as await
6+
await [x];
7+
await [x, x];
8+
9+
// reparse call as await
10+
declare function f(): number;
11+
await (x);
12+
await (f(), x);
13+
await <number>(x);
14+
await <number>(f(), x);
15+
16+
// reparse tagged template as await
17+
await ``;
18+
await <string> ``;
19+
20+
// member names should be ok
21+
class C1 {
22+
await() {}
23+
}
24+
class C2 {
25+
get await() { return 1; }
26+
set await(value) { }
27+
}
28+
class C3 {
29+
await = 1;
30+
}
31+
({
32+
await() {}
33+
});
34+
({
35+
get await() { return 1 },
36+
set await(value) { }
37+
});
38+
({
39+
await: 1
40+
});
41+
42+
// property access name should be ok
43+
C1.prototype.await;
544

645
//// [topLevelAwait.js]
746
export const x = 1;
847
await x;
48+
// reparse element access as await
49+
await [x];
50+
await [x, x];
51+
await (x);
52+
await (f(), x);
53+
await (x);
54+
await (f(), x);
55+
// reparse tagged template as await
56+
await ``;
57+
await ``;
58+
// member names should be ok
59+
class C1 {
60+
await() { }
61+
}
62+
class C2 {
63+
get await() { return 1; }
64+
set await(value) { }
65+
}
66+
class C3 {
67+
constructor() {
68+
this.await = 1;
69+
}
70+
}
71+
({
72+
await() { }
73+
});
74+
({
75+
get await() { return 1; },
76+
set await(value) { }
77+
});
78+
({
79+
await: 1
80+
});
81+
// property access name should be ok
82+
C1.prototype.await;

tests/baselines/reference/topLevelAwait(module=esnext,target=es2015).symbols

+81
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,84 @@ export const x = 1;
55
await x;
66
>x : Symbol(x, Decl(topLevelAwait.ts, 0, 12))
77

8+
// reparse element access as await
9+
await [x];
10+
>x : Symbol(x, Decl(topLevelAwait.ts, 0, 12))
11+
12+
await [x, x];
13+
>x : Symbol(x, Decl(topLevelAwait.ts, 0, 12))
14+
>x : Symbol(x, Decl(topLevelAwait.ts, 0, 12))
15+
16+
// reparse call as await
17+
declare function f(): number;
18+
>f : Symbol(f, Decl(topLevelAwait.ts, 5, 13))
19+
20+
await (x);
21+
>x : Symbol(x, Decl(topLevelAwait.ts, 0, 12))
22+
23+
await (f(), x);
24+
>f : Symbol(f, Decl(topLevelAwait.ts, 5, 13))
25+
>x : Symbol(x, Decl(topLevelAwait.ts, 0, 12))
26+
27+
await <number>(x);
28+
>x : Symbol(x, Decl(topLevelAwait.ts, 0, 12))
29+
30+
await <number>(f(), x);
31+
>f : Symbol(f, Decl(topLevelAwait.ts, 5, 13))
32+
>x : Symbol(x, Decl(topLevelAwait.ts, 0, 12))
33+
34+
// reparse tagged template as await
35+
await ``;
36+
await <string> ``;
37+
38+
// member names should be ok
39+
class C1 {
40+
>C1 : Symbol(C1, Decl(topLevelAwait.ts, 16, 18))
41+
42+
await() {}
43+
>await : Symbol(C1.await, Decl(topLevelAwait.ts, 19, 10))
44+
}
45+
class C2 {
46+
>C2 : Symbol(C2, Decl(topLevelAwait.ts, 21, 1))
47+
48+
get await() { return 1; }
49+
>await : Symbol(C2.await, Decl(topLevelAwait.ts, 22, 10), Decl(topLevelAwait.ts, 23, 29))
50+
51+
set await(value) { }
52+
>await : Symbol(C2.await, Decl(topLevelAwait.ts, 22, 10), Decl(topLevelAwait.ts, 23, 29))
53+
>value : Symbol(value, Decl(topLevelAwait.ts, 24, 14))
54+
}
55+
class C3 {
56+
>C3 : Symbol(C3, Decl(topLevelAwait.ts, 25, 1))
57+
58+
await = 1;
59+
>await : Symbol(C3.await, Decl(topLevelAwait.ts, 26, 10))
60+
}
61+
({
62+
await() {}
63+
>await : Symbol(await, Decl(topLevelAwait.ts, 29, 2))
64+
65+
});
66+
({
67+
get await() { return 1 },
68+
>await : Symbol(await, Decl(topLevelAwait.ts, 32, 2), Decl(topLevelAwait.ts, 33, 29))
69+
70+
set await(value) { }
71+
>await : Symbol(await, Decl(topLevelAwait.ts, 32, 2), Decl(topLevelAwait.ts, 33, 29))
72+
>value : Symbol(value, Decl(topLevelAwait.ts, 34, 14))
73+
74+
});
75+
({
76+
await: 1
77+
>await : Symbol(await, Decl(topLevelAwait.ts, 36, 2))
78+
79+
});
80+
81+
// property access name should be ok
82+
C1.prototype.await;
83+
>C1.prototype.await : Symbol(C1.await, Decl(topLevelAwait.ts, 19, 10))
84+
>C1.prototype : Symbol(C1.prototype)
85+
>C1 : Symbol(C1, Decl(topLevelAwait.ts, 16, 18))
86+
>prototype : Symbol(C1.prototype)
87+
>await : Symbol(C1.await, Decl(topLevelAwait.ts, 19, 10))
88+

0 commit comments

Comments
 (0)