Skip to content

Commit 27234b3

Browse files
Fix isLeftHandSideExpression to handle AwaitExpression correctly
Co-authored-by: RyanCavanaugh <[email protected]>
1 parent 74504dd commit 27234b3

5 files changed

Lines changed: 141 additions & 8 deletions

File tree

src/compiler/utilitiesPublic.ts

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1990,11 +1990,11 @@ export function isTemplateLiteral(node: Node): node is TemplateLiteral {
19901990
|| kind === SyntaxKind.NoSubstitutionTemplateLiteral;
19911991
}
19921992

1993-
export function isLeftHandSideExpression(node: Node): node is LeftHandSideExpression {
1994-
return isLeftHandSideExpressionKind(skipPartiallyEmittedExpressions(node).kind);
1993+
export function isLeftHandSideExpression(node: Node): node is LeftHandSideExpression {
1994+
return isLeftHandSideExpressionKind(skipPartiallyEmittedExpressions(node).kind);
19951995
}
19961996

1997-
function isLeftHandSideExpressionKind(kind: SyntaxKind): boolean {
1997+
function isLeftHandSideExpressionKind(kind: SyntaxKind): boolean {
19981998
switch (kind) {
19991999
case SyntaxKind.PropertyAccessExpression:
20002000
case SyntaxKind.ElementAccessExpression:
@@ -2022,11 +2022,13 @@ function isLeftHandSideExpressionKind(kind: SyntaxKind): boolean {
20222022
case SyntaxKind.ThisKeyword:
20232023
case SyntaxKind.TrueKeyword:
20242024
case SyntaxKind.SuperKeyword:
2025-
case SyntaxKind.NonNullExpression:
2026-
case SyntaxKind.ExpressionWithTypeArguments:
2027-
case SyntaxKind.MetaProperty:
2028-
case SyntaxKind.ImportKeyword: // technically this is only an Expression if it's in a CallExpression
2029-
case SyntaxKind.MissingDeclaration:
2025+
case SyntaxKind.NonNullExpression:
2026+
case SyntaxKind.ExpressionWithTypeArguments:
2027+
case SyntaxKind.MetaProperty:
2028+
case SyntaxKind.ImportKeyword: // technically this is only an Expression if it's in a CallExpression
2029+
case SyntaxKind.MissingDeclaration:
2030+
case SyntaxKind.PartiallyEmittedExpression:
2031+
case SyntaxKind.AwaitExpression:
20302032
return true;
20312033
default:
20322034
return false;
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
//// [tests/cases/compiler/partiallyEmittedExpressionLeftHandSide.ts] ////
2+
3+
//// [partiallyEmittedExpressionLeftHandSide.ts]
4+
async function testNonNullWithAwait() {
5+
const result = (await null as any)!;
6+
return result;
7+
}
8+
9+
async function testNonNullWithComplexExpression() {
10+
const obj = { prop: Promise.resolve("test") };
11+
const result = (await obj.prop as string)!;
12+
return result;
13+
}
14+
15+
//// [partiallyEmittedExpressionLeftHandSide.js]
16+
async function testNonNullWithAwait() {
17+
const result = await null;
18+
return result;
19+
}
20+
async function testNonNullWithComplexExpression() {
21+
const obj = { prop: Promise.resolve("test") };
22+
const result = await obj.prop;
23+
return result;
24+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
//// [tests/cases/compiler/partiallyEmittedExpressionLeftHandSide.ts] ////
2+
3+
=== partiallyEmittedExpressionLeftHandSide.ts ===
4+
async function testNonNullWithAwait() {
5+
>testNonNullWithAwait : Symbol(testNonNullWithAwait, Decl(partiallyEmittedExpressionLeftHandSide.ts, 0, 0))
6+
7+
const result = (await null as any)!;
8+
>result : Symbol(result, Decl(partiallyEmittedExpressionLeftHandSide.ts, 1, 9))
9+
10+
return result;
11+
>result : Symbol(result, Decl(partiallyEmittedExpressionLeftHandSide.ts, 1, 9))
12+
}
13+
14+
async function testNonNullWithComplexExpression() {
15+
>testNonNullWithComplexExpression : Symbol(testNonNullWithComplexExpression, Decl(partiallyEmittedExpressionLeftHandSide.ts, 3, 1))
16+
17+
const obj = { prop: Promise.resolve("test") };
18+
>obj : Symbol(obj, Decl(partiallyEmittedExpressionLeftHandSide.ts, 6, 9))
19+
>prop : Symbol(prop, Decl(partiallyEmittedExpressionLeftHandSide.ts, 6, 17))
20+
>Promise.resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
21+
>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2018.promise.d.ts, --, --))
22+
>resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
23+
24+
const result = (await obj.prop as string)!;
25+
>result : Symbol(result, Decl(partiallyEmittedExpressionLeftHandSide.ts, 7, 9))
26+
>obj.prop : Symbol(prop, Decl(partiallyEmittedExpressionLeftHandSide.ts, 6, 17))
27+
>obj : Symbol(obj, Decl(partiallyEmittedExpressionLeftHandSide.ts, 6, 9))
28+
>prop : Symbol(prop, Decl(partiallyEmittedExpressionLeftHandSide.ts, 6, 17))
29+
30+
return result;
31+
>result : Symbol(result, Decl(partiallyEmittedExpressionLeftHandSide.ts, 7, 9))
32+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
//// [tests/cases/compiler/partiallyEmittedExpressionLeftHandSide.ts] ////
2+
3+
=== partiallyEmittedExpressionLeftHandSide.ts ===
4+
async function testNonNullWithAwait() {
5+
>testNonNullWithAwait : () => Promise<any>
6+
> : ^^^^^^^^^^^^^^^^^^
7+
8+
const result = (await null as any)!;
9+
>result : any
10+
>(await null as any)! : any
11+
>(await null as any) : any
12+
>await null as any : any
13+
>await null : null
14+
> : ^^^^
15+
16+
return result;
17+
>result : any
18+
}
19+
20+
async function testNonNullWithComplexExpression() {
21+
>testNonNullWithComplexExpression : () => Promise<string>
22+
> : ^^^^^^^^^^^^^^^^^^^^^
23+
24+
const obj = { prop: Promise.resolve("test") };
25+
>obj : { prop: Promise<string>; }
26+
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^
27+
>{ prop: Promise.resolve("test") } : { prop: Promise<string>; }
28+
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^
29+
>prop : Promise<string>
30+
> : ^^^^^^^^^^^^^^^
31+
>Promise.resolve("test") : Promise<string>
32+
> : ^^^^^^^^^^^^^^^
33+
>Promise.resolve : { (): Promise<void>; <T>(value: T): Promise<Awaited<T>>; <T>(value: T | PromiseLike<T>): Promise<Awaited<T>>; }
34+
> : ^^^^^^ ^^^ ^^ ^^ ^^^ ^^^ ^^ ^^ ^^^ ^^^
35+
>Promise : PromiseConstructor
36+
> : ^^^^^^^^^^^^^^^^^^
37+
>resolve : { (): Promise<void>; <T>(value: T): Promise<Awaited<T>>; <T>(value: T | PromiseLike<T>): Promise<Awaited<T>>; }
38+
> : ^^^^^^ ^^^ ^^ ^^ ^^^ ^^^ ^^ ^^ ^^^ ^^^
39+
>"test" : "test"
40+
> : ^^^^^^
41+
42+
const result = (await obj.prop as string)!;
43+
>result : string
44+
> : ^^^^^^
45+
>(await obj.prop as string)! : string
46+
> : ^^^^^^
47+
>(await obj.prop as string) : string
48+
> : ^^^^^^
49+
>await obj.prop as string : string
50+
> : ^^^^^^
51+
>await obj.prop : string
52+
> : ^^^^^^
53+
>obj.prop : Promise<string>
54+
> : ^^^^^^^^^^^^^^^
55+
>obj : { prop: Promise<string>; }
56+
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^
57+
>prop : Promise<string>
58+
> : ^^^^^^^^^^^^^^^
59+
60+
return result;
61+
>result : string
62+
> : ^^^^^^
63+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// @target: es2018
2+
3+
async function testNonNullWithAwait() {
4+
const result = (await null as any)!;
5+
return result;
6+
}
7+
8+
async function testNonNullWithComplexExpression() {
9+
const obj = { prop: Promise.resolve("test") };
10+
const result = (await obj.prop as string)!;
11+
return result;
12+
}

0 commit comments

Comments
 (0)