Skip to content

Commit 8e8c1b6

Browse files
Fix bug#56997 - Parenthesized SatisfiesExpressions with comments are not unwrapped consistently in emitted JS (#57281)
Co-authored-by: Jake Bailey <[email protected]>
1 parent c50ec79 commit 8e8c1b6

13 files changed

+507
-1
lines changed

src/compiler/transformers/ts.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ import {
118118
isPrivateIdentifier,
119119
isPropertyAccessExpression,
120120
isPropertyName,
121+
isSatisfiesExpression,
121122
isShorthandPropertyAssignment,
122123
isSimpleInlineableExpression,
123124
isSourceFile,
@@ -1689,7 +1690,7 @@ export function transformTypeScript(context: TransformationContext) {
16891690

16901691
function visitParenthesizedExpression(node: ParenthesizedExpression): Expression {
16911692
const innerExpression = skipOuterExpressions(node.expression, ~OuterExpressionKinds.Assertions);
1692-
if (isAssertionExpression(innerExpression)) {
1693+
if (isAssertionExpression(innerExpression) || isSatisfiesExpression(innerExpression)) {
16931694
// Make sure we consider all nested cast expressions, e.g.:
16941695
// (<any><number><any>-A).x;
16951696
const expression = visitNode(node.expression, visitor, isExpression);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
//// [tests/cases/compiler/commentEmitOnParenthesizedAssertionInReturnStatement2.ts] ////
2+
3+
//// [commentEmitOnParenthesizedAssertionInReturnStatement2.ts]
4+
export class Foo {
5+
client = {
6+
getThing: () => Promise.resolve('')
7+
}
8+
9+
foo() {
10+
return (
11+
/* TODO: please refactor */ this.client
12+
.getThing() satisfies Promise<string>);
13+
}
14+
}
15+
16+
//// [commentEmitOnParenthesizedAssertionInReturnStatement2.js]
17+
export class Foo {
18+
client = {
19+
getThing: () => Promise.resolve('')
20+
};
21+
foo() {
22+
return (
23+
/* TODO: please refactor */ this.client
24+
.getThing());
25+
}
26+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
//// [tests/cases/compiler/commentEmitOnParenthesizedAssertionInReturnStatement2.ts] ////
2+
3+
=== commentEmitOnParenthesizedAssertionInReturnStatement2.ts ===
4+
export class Foo {
5+
>Foo : Symbol(Foo, Decl(commentEmitOnParenthesizedAssertionInReturnStatement2.ts, 0, 0))
6+
7+
client = {
8+
>client : Symbol(Foo.client, Decl(commentEmitOnParenthesizedAssertionInReturnStatement2.ts, 0, 18))
9+
10+
getThing: () => Promise.resolve('')
11+
>getThing : Symbol(getThing, Decl(commentEmitOnParenthesizedAssertionInReturnStatement2.ts, 1, 14))
12+
>Promise.resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
13+
>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, --, --))
14+
>resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
15+
}
16+
17+
foo() {
18+
>foo : Symbol(Foo.foo, Decl(commentEmitOnParenthesizedAssertionInReturnStatement2.ts, 3, 5))
19+
20+
return (
21+
/* TODO: please refactor */ this.client
22+
>this.client .getThing : Symbol(getThing, Decl(commentEmitOnParenthesizedAssertionInReturnStatement2.ts, 1, 14))
23+
>this.client : Symbol(Foo.client, Decl(commentEmitOnParenthesizedAssertionInReturnStatement2.ts, 0, 18))
24+
>this : Symbol(Foo, Decl(commentEmitOnParenthesizedAssertionInReturnStatement2.ts, 0, 0))
25+
>client : Symbol(Foo.client, Decl(commentEmitOnParenthesizedAssertionInReturnStatement2.ts, 0, 18))
26+
27+
.getThing() satisfies Promise<string>);
28+
>getThing : Symbol(getThing, Decl(commentEmitOnParenthesizedAssertionInReturnStatement2.ts, 1, 14))
29+
>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, --, --))
30+
}
31+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
//// [tests/cases/compiler/commentEmitOnParenthesizedAssertionInReturnStatement2.ts] ////
2+
3+
=== commentEmitOnParenthesizedAssertionInReturnStatement2.ts ===
4+
export class Foo {
5+
>Foo : Foo
6+
> : ^^^
7+
8+
client = {
9+
>client : { getThing: () => Promise<string>; }
10+
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
11+
>{ getThing: () => Promise.resolve('') } : { getThing: () => Promise<string>; }
12+
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
13+
14+
getThing: () => Promise.resolve('')
15+
>getThing : () => Promise<string>
16+
> : ^^^^^^^^^^^^^^^^^^^^^
17+
>() => Promise.resolve('') : () => Promise<string>
18+
> : ^^^^^^^^^^^^^^^^^^^^^
19+
>Promise.resolve('') : Promise<string>
20+
> : ^^^^^^^^^^^^^^^
21+
>Promise.resolve : { (): Promise<void>; <T>(value: T): Promise<Awaited<T>>; <T_1>(value: T_1 | PromiseLike<T_1>): Promise<Awaited<T_1>>; }
22+
> : ^^^^^^^^^^^^^^^^^^^^^^ ^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^ ^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^
23+
>Promise : PromiseConstructor
24+
> : ^^^^^^^^^^^^^^^^^^
25+
>resolve : { (): Promise<void>; <T>(value: T): Promise<Awaited<T>>; <T_1>(value: T_1 | PromiseLike<T_1>): Promise<Awaited<T_1>>; }
26+
> : ^^^^^^^^^^^^^^^^^^^^^^ ^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^ ^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^
27+
>'' : ""
28+
> : ^^
29+
}
30+
31+
foo() {
32+
>foo : () => Promise<string>
33+
> : ^^^^^^^^^^^^^^^^^^^^^
34+
35+
return (
36+
>( /* TODO: please refactor */ this.client .getThing() satisfies Promise<string>) : Promise<string>
37+
> : ^^^^^^^^^^^^^^^
38+
39+
/* TODO: please refactor */ this.client
40+
>this.client .getThing() satisfies Promise<string> : Promise<string>
41+
> : ^^^^^^^^^^^^^^^
42+
>this.client .getThing() : Promise<string>
43+
> : ^^^^^^^^^^^^^^^
44+
>this.client .getThing : () => Promise<string>
45+
> : ^^^^^^^^^^^^^^^^^^^^^
46+
>this.client : { getThing: () => Promise<string>; }
47+
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
48+
>this : this
49+
> : ^^^^
50+
>client : { getThing: () => Promise<string>; }
51+
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
52+
53+
.getThing() satisfies Promise<string>);
54+
>getThing : () => Promise<string>
55+
> : ^^^^^^^^^^^^^^^^^^^^^
56+
}
57+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
//// [tests/cases/compiler/parenthesizedSatisfiesExpressionWithComments.ts] ////
2+
3+
//// [parenthesizedSatisfiesExpressionWithComments.ts]
4+
"use strict";
5+
const a = (/*comm*/ 10 satisfies number);
6+
const b = ((/*comm*/ 10 satisfies number));
7+
8+
//// [parenthesizedSatisfiesExpressionWithComments.js]
9+
"use strict";
10+
var a = /*comm*/ 10;
11+
var b = /*comm*/ 10;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
//// [tests/cases/compiler/parenthesizedSatisfiesExpressionWithComments.ts] ////
2+
3+
=== parenthesizedSatisfiesExpressionWithComments.ts ===
4+
"use strict";
5+
const a = (/*comm*/ 10 satisfies number);
6+
>a : Symbol(a, Decl(parenthesizedSatisfiesExpressionWithComments.ts, 1, 5))
7+
8+
const b = ((/*comm*/ 10 satisfies number));
9+
>b : Symbol(b, Decl(parenthesizedSatisfiesExpressionWithComments.ts, 2, 5))
10+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
//// [tests/cases/compiler/parenthesizedSatisfiesExpressionWithComments.ts] ////
2+
3+
=== parenthesizedSatisfiesExpressionWithComments.ts ===
4+
"use strict";
5+
>"use strict" : "use strict"
6+
> : ^^^^^^^^^^^^
7+
8+
const a = (/*comm*/ 10 satisfies number);
9+
>a : 10
10+
> : ^^
11+
>(/*comm*/ 10 satisfies number) : 10
12+
> : ^^
13+
>10 satisfies number : 10
14+
> : ^^
15+
>10 : 10
16+
> : ^^
17+
18+
const b = ((/*comm*/ 10 satisfies number));
19+
>b : 10
20+
> : ^^
21+
>((/*comm*/ 10 satisfies number)) : 10
22+
> : ^^
23+
>(/*comm*/ 10 satisfies number) : 10
24+
> : ^^
25+
>10 satisfies number : 10
26+
> : ^^
27+
>10 : 10
28+
> : ^^
29+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
//// [tests/cases/compiler/referenceSatisfiesExpression.ts] ////
2+
3+
//// [referenceSatisfiesExpression.ts]
4+
let a = 10;
5+
--(a satisfies number);
6+
++(a satisfies number);
7+
8+
(a satisfies number)++;
9+
(a satisfies number)--;
10+
11+
let b: number;
12+
(b satisfies number) = 10;
13+
14+
let c: number;
15+
[(c satisfies number)] = [10];
16+
17+
let d: number, e = 1;
18+
({ d: (e satisfies number) } = { d: 10 });
19+
20+
let g = 1
21+
for ((g satisfies number) of [10]) {
22+
console.log(g)
23+
}
24+
25+
let x: string = "hello"
26+
for ((x satisfies string) in { a: 10 }) {
27+
console.log(x)
28+
}
29+
30+
31+
//// [referenceSatisfiesExpression.js]
32+
var a = 10;
33+
--a;
34+
++a;
35+
a++;
36+
a--;
37+
var b;
38+
b = 10;
39+
var c;
40+
c = [10][0];
41+
var d, e = 1;
42+
(e = { d: 10 }.d);
43+
var g = 1;
44+
for (var _i = 0, _a = [10]; _i < _a.length; _i++) {
45+
g = _a[_i];
46+
console.log(g);
47+
}
48+
var x = "hello";
49+
for (x in { a: 10 }) {
50+
console.log(x);
51+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
//// [tests/cases/compiler/referenceSatisfiesExpression.ts] ////
2+
3+
=== referenceSatisfiesExpression.ts ===
4+
let a = 10;
5+
>a : Symbol(a, Decl(referenceSatisfiesExpression.ts, 0, 3))
6+
7+
--(a satisfies number);
8+
>a : Symbol(a, Decl(referenceSatisfiesExpression.ts, 0, 3))
9+
10+
++(a satisfies number);
11+
>a : Symbol(a, Decl(referenceSatisfiesExpression.ts, 0, 3))
12+
13+
(a satisfies number)++;
14+
>a : Symbol(a, Decl(referenceSatisfiesExpression.ts, 0, 3))
15+
16+
(a satisfies number)--;
17+
>a : Symbol(a, Decl(referenceSatisfiesExpression.ts, 0, 3))
18+
19+
let b: number;
20+
>b : Symbol(b, Decl(referenceSatisfiesExpression.ts, 7, 3))
21+
22+
(b satisfies number) = 10;
23+
>b : Symbol(b, Decl(referenceSatisfiesExpression.ts, 7, 3))
24+
25+
let c: number;
26+
>c : Symbol(c, Decl(referenceSatisfiesExpression.ts, 10, 3))
27+
28+
[(c satisfies number)] = [10];
29+
>c : Symbol(c, Decl(referenceSatisfiesExpression.ts, 10, 3))
30+
31+
let d: number, e = 1;
32+
>d : Symbol(d, Decl(referenceSatisfiesExpression.ts, 13, 3))
33+
>e : Symbol(e, Decl(referenceSatisfiesExpression.ts, 13, 14))
34+
35+
({ d: (e satisfies number) } = { d: 10 });
36+
>d : Symbol(d, Decl(referenceSatisfiesExpression.ts, 14, 2))
37+
>e : Symbol(e, Decl(referenceSatisfiesExpression.ts, 13, 14))
38+
>d : Symbol(d, Decl(referenceSatisfiesExpression.ts, 14, 32))
39+
40+
let g = 1
41+
>g : Symbol(g, Decl(referenceSatisfiesExpression.ts, 16, 3))
42+
43+
for ((g satisfies number) of [10]) {
44+
>g : Symbol(g, Decl(referenceSatisfiesExpression.ts, 16, 3))
45+
46+
console.log(g)
47+
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
48+
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
49+
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
50+
>g : Symbol(g, Decl(referenceSatisfiesExpression.ts, 16, 3))
51+
}
52+
53+
let x: string = "hello"
54+
>x : Symbol(x, Decl(referenceSatisfiesExpression.ts, 21, 3))
55+
56+
for ((x satisfies string) in { a: 10 }) {
57+
>x : Symbol(x, Decl(referenceSatisfiesExpression.ts, 21, 3))
58+
>a : Symbol(a, Decl(referenceSatisfiesExpression.ts, 22, 30))
59+
60+
console.log(x)
61+
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
62+
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
63+
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
64+
>x : Symbol(x, Decl(referenceSatisfiesExpression.ts, 21, 3))
65+
}
66+

0 commit comments

Comments
 (0)