Fix bug#56997 - Parenthesized SatisfiesExpressions with comments are not unwrapped consistently in emitted JS (#57281)

Co-authored-by: Jake Bailey <5341706+jakebailey@users.noreply.github.com>
This commit is contained in:
Jean
2024-04-20 01:00:44 +02:00
committed by GitHub
parent c50ec7952c
commit 8e8c1b6a64
13 changed files with 507 additions and 1 deletions

View File

@@ -118,6 +118,7 @@ import {
isPrivateIdentifier,
isPropertyAccessExpression,
isPropertyName,
isSatisfiesExpression,
isShorthandPropertyAssignment,
isSimpleInlineableExpression,
isSourceFile,
@@ -1689,7 +1690,7 @@ export function transformTypeScript(context: TransformationContext) {
function visitParenthesizedExpression(node: ParenthesizedExpression): Expression {
const innerExpression = skipOuterExpressions(node.expression, ~OuterExpressionKinds.Assertions);
if (isAssertionExpression(innerExpression)) {
if (isAssertionExpression(innerExpression) || isSatisfiesExpression(innerExpression)) {
// Make sure we consider all nested cast expressions, e.g.:
// (<any><number><any>-A).x;
const expression = visitNode(node.expression, visitor, isExpression);

View File

@@ -0,0 +1,26 @@
//// [tests/cases/compiler/commentEmitOnParenthesizedAssertionInReturnStatement2.ts] ////
//// [commentEmitOnParenthesizedAssertionInReturnStatement2.ts]
export class Foo {
client = {
getThing: () => Promise.resolve('')
}
foo() {
return (
/* TODO: please refactor */ this.client
.getThing() satisfies Promise<string>);
}
}
//// [commentEmitOnParenthesizedAssertionInReturnStatement2.js]
export class Foo {
client = {
getThing: () => Promise.resolve('')
};
foo() {
return (
/* TODO: please refactor */ this.client
.getThing());
}
}

View File

@@ -0,0 +1,31 @@
//// [tests/cases/compiler/commentEmitOnParenthesizedAssertionInReturnStatement2.ts] ////
=== commentEmitOnParenthesizedAssertionInReturnStatement2.ts ===
export class Foo {
>Foo : Symbol(Foo, Decl(commentEmitOnParenthesizedAssertionInReturnStatement2.ts, 0, 0))
client = {
>client : Symbol(Foo.client, Decl(commentEmitOnParenthesizedAssertionInReturnStatement2.ts, 0, 18))
getThing: () => Promise.resolve('')
>getThing : Symbol(getThing, Decl(commentEmitOnParenthesizedAssertionInReturnStatement2.ts, 1, 14))
>Promise.resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
>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, --, --))
>resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
}
foo() {
>foo : Symbol(Foo.foo, Decl(commentEmitOnParenthesizedAssertionInReturnStatement2.ts, 3, 5))
return (
/* TODO: please refactor */ this.client
>this.client .getThing : Symbol(getThing, Decl(commentEmitOnParenthesizedAssertionInReturnStatement2.ts, 1, 14))
>this.client : Symbol(Foo.client, Decl(commentEmitOnParenthesizedAssertionInReturnStatement2.ts, 0, 18))
>this : Symbol(Foo, Decl(commentEmitOnParenthesizedAssertionInReturnStatement2.ts, 0, 0))
>client : Symbol(Foo.client, Decl(commentEmitOnParenthesizedAssertionInReturnStatement2.ts, 0, 18))
.getThing() satisfies Promise<string>);
>getThing : Symbol(getThing, Decl(commentEmitOnParenthesizedAssertionInReturnStatement2.ts, 1, 14))
>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, --, --))
}
}

View File

@@ -0,0 +1,57 @@
//// [tests/cases/compiler/commentEmitOnParenthesizedAssertionInReturnStatement2.ts] ////
=== commentEmitOnParenthesizedAssertionInReturnStatement2.ts ===
export class Foo {
>Foo : Foo
> : ^^^
client = {
>client : { getThing: () => Promise<string>; }
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>{ getThing: () => Promise.resolve('') } : { getThing: () => Promise<string>; }
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
getThing: () => Promise.resolve('')
>getThing : () => Promise<string>
> : ^^^^^^^^^^^^^^^^^^^^^
>() => Promise.resolve('') : () => Promise<string>
> : ^^^^^^^^^^^^^^^^^^^^^
>Promise.resolve('') : Promise<string>
> : ^^^^^^^^^^^^^^^
>Promise.resolve : { (): Promise<void>; <T>(value: T): Promise<Awaited<T>>; <T_1>(value: T_1 | PromiseLike<T_1>): Promise<Awaited<T_1>>; }
> : ^^^^^^^^^^^^^^^^^^^^^^ ^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^ ^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^
>Promise : PromiseConstructor
> : ^^^^^^^^^^^^^^^^^^
>resolve : { (): Promise<void>; <T>(value: T): Promise<Awaited<T>>; <T_1>(value: T_1 | PromiseLike<T_1>): Promise<Awaited<T_1>>; }
> : ^^^^^^^^^^^^^^^^^^^^^^ ^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^ ^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^
>'' : ""
> : ^^
}
foo() {
>foo : () => Promise<string>
> : ^^^^^^^^^^^^^^^^^^^^^
return (
>( /* TODO: please refactor */ this.client .getThing() satisfies Promise<string>) : Promise<string>
> : ^^^^^^^^^^^^^^^
/* TODO: please refactor */ this.client
>this.client .getThing() satisfies Promise<string> : Promise<string>
> : ^^^^^^^^^^^^^^^
>this.client .getThing() : Promise<string>
> : ^^^^^^^^^^^^^^^
>this.client .getThing : () => Promise<string>
> : ^^^^^^^^^^^^^^^^^^^^^
>this.client : { getThing: () => Promise<string>; }
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>this : this
> : ^^^^
>client : { getThing: () => Promise<string>; }
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.getThing() satisfies Promise<string>);
>getThing : () => Promise<string>
> : ^^^^^^^^^^^^^^^^^^^^^
}
}

View File

@@ -0,0 +1,11 @@
//// [tests/cases/compiler/parenthesizedSatisfiesExpressionWithComments.ts] ////
//// [parenthesizedSatisfiesExpressionWithComments.ts]
"use strict";
const a = (/*comm*/ 10 satisfies number);
const b = ((/*comm*/ 10 satisfies number));
//// [parenthesizedSatisfiesExpressionWithComments.js]
"use strict";
var a = /*comm*/ 10;
var b = /*comm*/ 10;

View File

@@ -0,0 +1,10 @@
//// [tests/cases/compiler/parenthesizedSatisfiesExpressionWithComments.ts] ////
=== parenthesizedSatisfiesExpressionWithComments.ts ===
"use strict";
const a = (/*comm*/ 10 satisfies number);
>a : Symbol(a, Decl(parenthesizedSatisfiesExpressionWithComments.ts, 1, 5))
const b = ((/*comm*/ 10 satisfies number));
>b : Symbol(b, Decl(parenthesizedSatisfiesExpressionWithComments.ts, 2, 5))

View File

@@ -0,0 +1,29 @@
//// [tests/cases/compiler/parenthesizedSatisfiesExpressionWithComments.ts] ////
=== parenthesizedSatisfiesExpressionWithComments.ts ===
"use strict";
>"use strict" : "use strict"
> : ^^^^^^^^^^^^
const a = (/*comm*/ 10 satisfies number);
>a : 10
> : ^^
>(/*comm*/ 10 satisfies number) : 10
> : ^^
>10 satisfies number : 10
> : ^^
>10 : 10
> : ^^
const b = ((/*comm*/ 10 satisfies number));
>b : 10
> : ^^
>((/*comm*/ 10 satisfies number)) : 10
> : ^^
>(/*comm*/ 10 satisfies number) : 10
> : ^^
>10 satisfies number : 10
> : ^^
>10 : 10
> : ^^

View File

@@ -0,0 +1,51 @@
//// [tests/cases/compiler/referenceSatisfiesExpression.ts] ////
//// [referenceSatisfiesExpression.ts]
let a = 10;
--(a satisfies number);
++(a satisfies number);
(a satisfies number)++;
(a satisfies number)--;
let b: number;
(b satisfies number) = 10;
let c: number;
[(c satisfies number)] = [10];
let d: number, e = 1;
({ d: (e satisfies number) } = { d: 10 });
let g = 1
for ((g satisfies number) of [10]) {
console.log(g)
}
let x: string = "hello"
for ((x satisfies string) in { a: 10 }) {
console.log(x)
}
//// [referenceSatisfiesExpression.js]
var a = 10;
--a;
++a;
a++;
a--;
var b;
b = 10;
var c;
c = [10][0];
var d, e = 1;
(e = { d: 10 }.d);
var g = 1;
for (var _i = 0, _a = [10]; _i < _a.length; _i++) {
g = _a[_i];
console.log(g);
}
var x = "hello";
for (x in { a: 10 }) {
console.log(x);
}

View File

@@ -0,0 +1,66 @@
//// [tests/cases/compiler/referenceSatisfiesExpression.ts] ////
=== referenceSatisfiesExpression.ts ===
let a = 10;
>a : Symbol(a, Decl(referenceSatisfiesExpression.ts, 0, 3))
--(a satisfies number);
>a : Symbol(a, Decl(referenceSatisfiesExpression.ts, 0, 3))
++(a satisfies number);
>a : Symbol(a, Decl(referenceSatisfiesExpression.ts, 0, 3))
(a satisfies number)++;
>a : Symbol(a, Decl(referenceSatisfiesExpression.ts, 0, 3))
(a satisfies number)--;
>a : Symbol(a, Decl(referenceSatisfiesExpression.ts, 0, 3))
let b: number;
>b : Symbol(b, Decl(referenceSatisfiesExpression.ts, 7, 3))
(b satisfies number) = 10;
>b : Symbol(b, Decl(referenceSatisfiesExpression.ts, 7, 3))
let c: number;
>c : Symbol(c, Decl(referenceSatisfiesExpression.ts, 10, 3))
[(c satisfies number)] = [10];
>c : Symbol(c, Decl(referenceSatisfiesExpression.ts, 10, 3))
let d: number, e = 1;
>d : Symbol(d, Decl(referenceSatisfiesExpression.ts, 13, 3))
>e : Symbol(e, Decl(referenceSatisfiesExpression.ts, 13, 14))
({ d: (e satisfies number) } = { d: 10 });
>d : Symbol(d, Decl(referenceSatisfiesExpression.ts, 14, 2))
>e : Symbol(e, Decl(referenceSatisfiesExpression.ts, 13, 14))
>d : Symbol(d, Decl(referenceSatisfiesExpression.ts, 14, 32))
let g = 1
>g : Symbol(g, Decl(referenceSatisfiesExpression.ts, 16, 3))
for ((g satisfies number) of [10]) {
>g : Symbol(g, Decl(referenceSatisfiesExpression.ts, 16, 3))
console.log(g)
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>g : Symbol(g, Decl(referenceSatisfiesExpression.ts, 16, 3))
}
let x: string = "hello"
>x : Symbol(x, Decl(referenceSatisfiesExpression.ts, 21, 3))
for ((x satisfies string) in { a: 10 }) {
>x : Symbol(x, Decl(referenceSatisfiesExpression.ts, 21, 3))
>a : Symbol(a, Decl(referenceSatisfiesExpression.ts, 22, 30))
console.log(x)
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>x : Symbol(x, Decl(referenceSatisfiesExpression.ts, 21, 3))
}

View File

@@ -0,0 +1,179 @@
//// [tests/cases/compiler/referenceSatisfiesExpression.ts] ////
=== referenceSatisfiesExpression.ts ===
let a = 10;
>a : number
> : ^^^^^^
>10 : 10
> : ^^
--(a satisfies number);
>--(a satisfies number) : number
> : ^^^^^^
>(a satisfies number) : number
> : ^^^^^^
>a satisfies number : number
> : ^^^^^^
>a : number
> : ^^^^^^
++(a satisfies number);
>++(a satisfies number) : number
> : ^^^^^^
>(a satisfies number) : number
> : ^^^^^^
>a satisfies number : number
> : ^^^^^^
>a : number
> : ^^^^^^
(a satisfies number)++;
>(a satisfies number)++ : number
> : ^^^^^^
>(a satisfies number) : number
> : ^^^^^^
>a satisfies number : number
> : ^^^^^^
>a : number
> : ^^^^^^
(a satisfies number)--;
>(a satisfies number)-- : number
> : ^^^^^^
>(a satisfies number) : number
> : ^^^^^^
>a satisfies number : number
> : ^^^^^^
>a : number
> : ^^^^^^
let b: number;
>b : number
> : ^^^^^^
(b satisfies number) = 10;
>(b satisfies number) = 10 : 10
> : ^^
>(b satisfies number) : number
> : ^^^^^^
>b satisfies number : number
> : ^^^^^^
>b : number
> : ^^^^^^
>10 : 10
> : ^^
let c: number;
>c : number
> : ^^^^^^
[(c satisfies number)] = [10];
>[(c satisfies number)] = [10] : [number]
> : ^^^^^^^^
>[(c satisfies number)] : [number]
> : ^^^^^^^^
>(c satisfies number) : number
> : ^^^^^^
>c satisfies number : number
> : ^^^^^^
>c : number
> : ^^^^^^
>[10] : [number]
> : ^^^^^^^^
>10 : 10
> : ^^
let d: number, e = 1;
>d : number
> : ^^^^^^
>e : number
> : ^^^^^^
>1 : 1
> : ^
({ d: (e satisfies number) } = { d: 10 });
>({ d: (e satisfies number) } = { d: 10 }) : { d: number; }
> : ^^^^^^^^^^^^^^
>{ d: (e satisfies number) } = { d: 10 } : { d: number; }
> : ^^^^^^^^^^^^^^
>{ d: (e satisfies number) } : { d: number; }
> : ^^^^^^^^^^^^^^
>d : number
> : ^^^^^^
>(e satisfies number) : number
> : ^^^^^^
>e satisfies number : number
> : ^^^^^^
>e : number
> : ^^^^^^
>{ d: 10 } : { d: number; }
> : ^^^^^^^^^^^^^^
>d : number
> : ^^^^^^
>10 : 10
> : ^^
let g = 1
>g : number
> : ^^^^^^
>1 : 1
> : ^
for ((g satisfies number) of [10]) {
>(g satisfies number) : number
> : ^^^^^^
>g satisfies number : number
> : ^^^^^^
>g : number
> : ^^^^^^
>[10] : number[]
> : ^^^^^^^^
>10 : 10
> : ^^
console.log(g)
>console.log(g) : void
> : ^^^^
>console.log : (...data: any[]) => void
> : ^^^^ ^^ ^^^^^^^^^
>console : Console
> : ^^^^^^^
>log : (...data: any[]) => void
> : ^^^^ ^^ ^^^^^^^^^
>g : number
> : ^^^^^^
}
let x: string = "hello"
>x : string
> : ^^^^^^
>"hello" : "hello"
> : ^^^^^^^
for ((x satisfies string) in { a: 10 }) {
>(x satisfies string) : string
> : ^^^^^^
>x satisfies string : string
> : ^^^^^^
>x : string
> : ^^^^^^
>{ a: 10 } : { a: number; }
> : ^^^^^^^^^^^^^^
>a : number
> : ^^^^^^
>10 : 10
> : ^^
console.log(x)
>console.log(x) : void
> : ^^^^
>console.log : (...data: any[]) => void
> : ^^^^ ^^ ^^^^^^^^^
>console : Console
> : ^^^^^^^
>log : (...data: any[]) => void
> : ^^^^ ^^ ^^^^^^^^^
>x : string
> : ^^^^^^
}

View File

@@ -0,0 +1,16 @@
// @strict: true
// @lib: esnext
// @target: esnext
// @removeComments: false
export class Foo {
client = {
getThing: () => Promise.resolve('')
}
foo() {
return (
/* TODO: please refactor */ this.client
.getThing() satisfies Promise<string>);
}
}

View File

@@ -0,0 +1,4 @@
"use strict";
// @removeComments: false
const a = (/*comm*/ 10 satisfies number);
const b = ((/*comm*/ 10 satisfies number));

View File

@@ -0,0 +1,25 @@
let a = 10;
--(a satisfies number);
++(a satisfies number);
(a satisfies number)++;
(a satisfies number)--;
let b: number;
(b satisfies number) = 10;
let c: number;
[(c satisfies number)] = [10];
let d: number, e = 1;
({ d: (e satisfies number) } = { d: 10 });
let g = 1
for ((g satisfies number) of [10]) {
console.log(g)
}
let x: string = "hello"
for ((x satisfies string) in { a: 10 }) {
console.log(x)
}