Skip to content

Commit 6bedd1c

Browse files
shicksajafff
andauthored
Allow indirect calls (#51989)
Co-authored-by: Klaus Meinhardt <[email protected]>
1 parent 394a777 commit 6bedd1c

6 files changed

+92
-6
lines changed

src/compiler/checker.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35810,7 +35810,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
3581035810
return getRegularTypeOfObjectLiteral(rightType);
3581135811
}
3581235812
case SyntaxKind.CommaToken:
35813-
if (!compilerOptions.allowUnreachableCode && isSideEffectFree(left) && !isEvalNode(right)) {
35813+
if (!compilerOptions.allowUnreachableCode && isSideEffectFree(left) && !isIndirectCall(left.parent as BinaryExpression)) {
3581435814
const sf = getSourceFileOfNode(left);
3581535815
const sourceText = sf.text;
3581635816
const start = skipTrivia(sourceText, left.pos);
@@ -35846,8 +35846,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
3584635846
}
3584735847
}
3584835848

35849-
function isEvalNode(node: Expression) {
35850-
return node.kind === SyntaxKind.Identifier && (node as Identifier).escapedText === "eval";
35849+
// Return true for "indirect calls", (i.e. `(0, x.f)(...)` or `(0, eval)(...)`), which prevents passing `this`.
35850+
function isIndirectCall(node: BinaryExpression): boolean {
35851+
return node.parent.kind === SyntaxKind.ParenthesizedExpression &&
35852+
isNumericLiteral(node.left) &&
35853+
node.left.text === "0" &&
35854+
(isCallExpression(node.parent.parent) && node.parent.parent.expression === node.parent || node.parent.parent.kind === SyntaxKind.TaggedTemplateExpression) &&
35855+
// special-case for "eval" because it's the only non-access case where an indirect call actually affects behavior.
35856+
(isAccessExpression(node.right) || isIdentifier(node.right) && node.right.escapedText === "eval");
3585135857
}
3585235858

3585335859
// Return true if there was no error, false if there was an error.

tests/baselines/reference/commaOperatorLeftSideUnused.errors.txt

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,10 @@ tests/cases/compiler/commaOperatorLeftSideUnused.ts(38,7): error TS2695: Left si
2121
tests/cases/compiler/commaOperatorLeftSideUnused.ts(39,7): error TS2695: Left side of comma operator is unused and has no side effects.
2222
tests/cases/compiler/commaOperatorLeftSideUnused.ts(40,7): error TS2695: Left side of comma operator is unused and has no side effects.
2323
tests/cases/compiler/commaOperatorLeftSideUnused.ts(41,7): error TS2695: Left side of comma operator is unused and has no side effects.
24+
tests/cases/compiler/commaOperatorLeftSideUnused.ts(42,7): error TS2695: Left side of comma operator is unused and has no side effects.
2425

2526

26-
==== tests/cases/compiler/commaOperatorLeftSideUnused.ts (23 errors) ====
27+
==== tests/cases/compiler/commaOperatorLeftSideUnused.ts (24 errors) ====
2728
var xx: any;
2829
var yy: any;
2930

@@ -111,6 +112,9 @@ tests/cases/compiler/commaOperatorLeftSideUnused.ts(41,7): error TS2695: Left si
111112
xx = (+xx, 10);
112113
~~~
113114
!!! error TS2695: Left side of comma operator is unused and has no side effects.
115+
xx = (0, xx)();
116+
~
117+
!!! error TS2695: Left side of comma operator is unused and has no side effects.
114118

115119
// OK cases
116120
xx = (xx ? x++ : 4, 10);
@@ -122,4 +126,6 @@ tests/cases/compiler/commaOperatorLeftSideUnused.ts(41,7): error TS2695: Left si
122126
xx = (Math.pow(3, 2), 4);
123127
xx = (void xx, 10);
124128
xx = (xx as any, 100);
125-
129+
xx = (0, xx.fn)();
130+
xx = (0, xx['fn'])();
131+
xx = (0, xx.fn)``;

tests/baselines/reference/commaOperatorLeftSideUnused.js

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ xx = (!xx, 10);
4040
xx = (~xx, 10);
4141
xx = (-xx, 10);
4242
xx = (+xx, 10);
43+
xx = (0, xx)();
4344

4445
// OK cases
4546
xx = (xx ? x++ : 4, 10);
@@ -51,9 +52,15 @@ xx = ((xx+= 4), xx);
5152
xx = (Math.pow(3, 2), 4);
5253
xx = (void xx, 10);
5354
xx = (xx as any, 100);
54-
55+
xx = (0, xx.fn)();
56+
xx = (0, xx['fn'])();
57+
xx = (0, xx.fn)``;
5558

5659
//// [commaOperatorLeftSideUnused.js]
60+
var __makeTemplateObject = (this && this.__makeTemplateObject) || function (cooked, raw) {
61+
if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; }
62+
return cooked;
63+
};
5764
var xx;
5865
var yy;
5966
function fn() {
@@ -91,6 +98,7 @@ xx = (!xx, 10);
9198
xx = (~xx, 10);
9299
xx = (-xx, 10);
93100
xx = (+xx, 10);
101+
xx = (0, xx)();
94102
// OK cases
95103
xx = (xx ? x++ : 4, 10);
96104
xx = (--xx, 3);
@@ -101,3 +109,6 @@ xx = ((xx += 4), xx);
101109
xx = (Math.pow(3, 2), 4);
102110
xx = (void xx, 10);
103111
xx = (xx, 100);
112+
xx = (0, xx.fn)();
113+
xx = (0, xx['fn'])();
114+
xx = (0, xx.fn)(__makeTemplateObject([""], [""]));

tests/baselines/reference/commaOperatorLeftSideUnused.symbols

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,10 @@ xx = (+xx, 10);
109109
>xx : Symbol(xx, Decl(commaOperatorLeftSideUnused.ts, 0, 3))
110110
>xx : Symbol(xx, Decl(commaOperatorLeftSideUnused.ts, 0, 3))
111111

112+
xx = (0, xx)();
113+
>xx : Symbol(xx, Decl(commaOperatorLeftSideUnused.ts, 0, 3))
114+
>xx : Symbol(xx, Decl(commaOperatorLeftSideUnused.ts, 0, 3))
115+
112116
// OK cases
113117
xx = (xx ? x++ : 4, 10);
114118
>xx : Symbol(xx, Decl(commaOperatorLeftSideUnused.ts, 0, 3))
@@ -151,3 +155,15 @@ xx = (xx as any, 100);
151155
>xx : Symbol(xx, Decl(commaOperatorLeftSideUnused.ts, 0, 3))
152156
>xx : Symbol(xx, Decl(commaOperatorLeftSideUnused.ts, 0, 3))
153157

158+
xx = (0, xx.fn)();
159+
>xx : Symbol(xx, Decl(commaOperatorLeftSideUnused.ts, 0, 3))
160+
>xx : Symbol(xx, Decl(commaOperatorLeftSideUnused.ts, 0, 3))
161+
162+
xx = (0, xx['fn'])();
163+
>xx : Symbol(xx, Decl(commaOperatorLeftSideUnused.ts, 0, 3))
164+
>xx : Symbol(xx, Decl(commaOperatorLeftSideUnused.ts, 0, 3))
165+
166+
xx = (0, xx.fn)``;
167+
>xx : Symbol(xx, Decl(commaOperatorLeftSideUnused.ts, 0, 3))
168+
>xx : Symbol(xx, Decl(commaOperatorLeftSideUnused.ts, 0, 3))
169+

tests/baselines/reference/commaOperatorLeftSideUnused.types

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,15 @@ xx = (+xx, 10);
240240
>xx : any
241241
>10 : 10
242242

243+
xx = (0, xx)();
244+
>xx = (0, xx)() : any
245+
>xx : any
246+
>(0, xx)() : any
247+
>(0, xx) : any
248+
>0, xx : any
249+
>0 : 0
250+
>xx : any
251+
243252
// OK cases
244253
xx = (xx ? x++ : 4, 10);
245254
>xx = (xx ? x++ : 4, 10) : 10
@@ -335,3 +344,37 @@ xx = (xx as any, 100);
335344
>xx : any
336345
>100 : 100
337346

347+
xx = (0, xx.fn)();
348+
>xx = (0, xx.fn)() : any
349+
>xx : any
350+
>(0, xx.fn)() : any
351+
>(0, xx.fn) : any
352+
>0, xx.fn : any
353+
>0 : 0
354+
>xx.fn : any
355+
>xx : any
356+
>fn : any
357+
358+
xx = (0, xx['fn'])();
359+
>xx = (0, xx['fn'])() : any
360+
>xx : any
361+
>(0, xx['fn'])() : any
362+
>(0, xx['fn']) : any
363+
>0, xx['fn'] : any
364+
>0 : 0
365+
>xx['fn'] : any
366+
>xx : any
367+
>'fn' : "fn"
368+
369+
xx = (0, xx.fn)``;
370+
>xx = (0, xx.fn)`` : any
371+
>xx : any
372+
>(0, xx.fn)`` : any
373+
>(0, xx.fn) : any
374+
>0, xx.fn : any
375+
>0 : 0
376+
>xx.fn : any
377+
>xx : any
378+
>fn : any
379+
>`` : ""
380+

tests/cases/compiler/commaOperatorLeftSideUnused.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ xx = (!xx, 10);
4040
xx = (~xx, 10);
4141
xx = (-xx, 10);
4242
xx = (+xx, 10);
43+
xx = (0, xx)();
4344

4445
// OK cases
4546
xx = (xx ? x++ : 4, 10);
@@ -51,3 +52,6 @@ xx = ((xx+= 4), xx);
5152
xx = (Math.pow(3, 2), 4);
5253
xx = (void xx, 10);
5354
xx = (xx as any, 100);
55+
xx = (0, xx.fn)();
56+
xx = (0, xx['fn'])();
57+
xx = (0, xx.fn)``;

0 commit comments

Comments
 (0)