Allow indirect calls (#51989)

Co-authored-by: Klaus Meinhardt <klaus.meinhardt1@gmail.com>
This commit is contained in:
Stephen Hicks
2023-01-09 18:56:33 -05:00
committed by GitHub
parent 394a777fdd
commit 6bedd1c227
6 changed files with 92 additions and 6 deletions

View File

@@ -35810,7 +35810,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
return getRegularTypeOfObjectLiteral(rightType);
}
case SyntaxKind.CommaToken:
if (!compilerOptions.allowUnreachableCode && isSideEffectFree(left) && !isEvalNode(right)) {
if (!compilerOptions.allowUnreachableCode && isSideEffectFree(left) && !isIndirectCall(left.parent as BinaryExpression)) {
const sf = getSourceFileOfNode(left);
const sourceText = sf.text;
const start = skipTrivia(sourceText, left.pos);
@@ -35846,8 +35846,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
}
}
function isEvalNode(node: Expression) {
return node.kind === SyntaxKind.Identifier && (node as Identifier).escapedText === "eval";
// Return true for "indirect calls", (i.e. `(0, x.f)(...)` or `(0, eval)(...)`), which prevents passing `this`.
function isIndirectCall(node: BinaryExpression): boolean {
return node.parent.kind === SyntaxKind.ParenthesizedExpression &&
isNumericLiteral(node.left) &&
node.left.text === "0" &&
(isCallExpression(node.parent.parent) && node.parent.parent.expression === node.parent || node.parent.parent.kind === SyntaxKind.TaggedTemplateExpression) &&
// special-case for "eval" because it's the only non-access case where an indirect call actually affects behavior.
(isAccessExpression(node.right) || isIdentifier(node.right) && node.right.escapedText === "eval");
}
// Return true if there was no error, false if there was an error.

View File

@@ -21,9 +21,10 @@ tests/cases/compiler/commaOperatorLeftSideUnused.ts(38,7): error TS2695: Left si
tests/cases/compiler/commaOperatorLeftSideUnused.ts(39,7): error TS2695: Left side of comma operator is unused and has no side effects.
tests/cases/compiler/commaOperatorLeftSideUnused.ts(40,7): error TS2695: Left side of comma operator is unused and has no side effects.
tests/cases/compiler/commaOperatorLeftSideUnused.ts(41,7): error TS2695: Left side of comma operator is unused and has no side effects.
tests/cases/compiler/commaOperatorLeftSideUnused.ts(42,7): error TS2695: Left side of comma operator is unused and has no side effects.
==== tests/cases/compiler/commaOperatorLeftSideUnused.ts (23 errors) ====
==== tests/cases/compiler/commaOperatorLeftSideUnused.ts (24 errors) ====
var xx: any;
var yy: any;
@@ -111,6 +112,9 @@ tests/cases/compiler/commaOperatorLeftSideUnused.ts(41,7): error TS2695: Left si
xx = (+xx, 10);
~~~
!!! error TS2695: Left side of comma operator is unused and has no side effects.
xx = (0, xx)();
~
!!! error TS2695: Left side of comma operator is unused and has no side effects.
// OK cases
xx = (xx ? x++ : 4, 10);
@@ -122,4 +126,6 @@ tests/cases/compiler/commaOperatorLeftSideUnused.ts(41,7): error TS2695: Left si
xx = (Math.pow(3, 2), 4);
xx = (void xx, 10);
xx = (xx as any, 100);
xx = (0, xx.fn)();
xx = (0, xx['fn'])();
xx = (0, xx.fn)``;

View File

@@ -40,6 +40,7 @@ xx = (!xx, 10);
xx = (~xx, 10);
xx = (-xx, 10);
xx = (+xx, 10);
xx = (0, xx)();
// OK cases
xx = (xx ? x++ : 4, 10);
@@ -51,9 +52,15 @@ xx = ((xx+= 4), xx);
xx = (Math.pow(3, 2), 4);
xx = (void xx, 10);
xx = (xx as any, 100);
xx = (0, xx.fn)();
xx = (0, xx['fn'])();
xx = (0, xx.fn)``;
//// [commaOperatorLeftSideUnused.js]
var __makeTemplateObject = (this && this.__makeTemplateObject) || function (cooked, raw) {
if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; }
return cooked;
};
var xx;
var yy;
function fn() {
@@ -91,6 +98,7 @@ xx = (!xx, 10);
xx = (~xx, 10);
xx = (-xx, 10);
xx = (+xx, 10);
xx = (0, xx)();
// OK cases
xx = (xx ? x++ : 4, 10);
xx = (--xx, 3);
@@ -101,3 +109,6 @@ xx = ((xx += 4), xx);
xx = (Math.pow(3, 2), 4);
xx = (void xx, 10);
xx = (xx, 100);
xx = (0, xx.fn)();
xx = (0, xx['fn'])();
xx = (0, xx.fn)(__makeTemplateObject([""], [""]));

View File

@@ -109,6 +109,10 @@ xx = (+xx, 10);
>xx : Symbol(xx, Decl(commaOperatorLeftSideUnused.ts, 0, 3))
>xx : Symbol(xx, Decl(commaOperatorLeftSideUnused.ts, 0, 3))
xx = (0, xx)();
>xx : Symbol(xx, Decl(commaOperatorLeftSideUnused.ts, 0, 3))
>xx : Symbol(xx, Decl(commaOperatorLeftSideUnused.ts, 0, 3))
// OK cases
xx = (xx ? x++ : 4, 10);
>xx : Symbol(xx, Decl(commaOperatorLeftSideUnused.ts, 0, 3))
@@ -151,3 +155,15 @@ xx = (xx as any, 100);
>xx : Symbol(xx, Decl(commaOperatorLeftSideUnused.ts, 0, 3))
>xx : Symbol(xx, Decl(commaOperatorLeftSideUnused.ts, 0, 3))
xx = (0, xx.fn)();
>xx : Symbol(xx, Decl(commaOperatorLeftSideUnused.ts, 0, 3))
>xx : Symbol(xx, Decl(commaOperatorLeftSideUnused.ts, 0, 3))
xx = (0, xx['fn'])();
>xx : Symbol(xx, Decl(commaOperatorLeftSideUnused.ts, 0, 3))
>xx : Symbol(xx, Decl(commaOperatorLeftSideUnused.ts, 0, 3))
xx = (0, xx.fn)``;
>xx : Symbol(xx, Decl(commaOperatorLeftSideUnused.ts, 0, 3))
>xx : Symbol(xx, Decl(commaOperatorLeftSideUnused.ts, 0, 3))

View File

@@ -240,6 +240,15 @@ xx = (+xx, 10);
>xx : any
>10 : 10
xx = (0, xx)();
>xx = (0, xx)() : any
>xx : any
>(0, xx)() : any
>(0, xx) : any
>0, xx : any
>0 : 0
>xx : any
// OK cases
xx = (xx ? x++ : 4, 10);
>xx = (xx ? x++ : 4, 10) : 10
@@ -335,3 +344,37 @@ xx = (xx as any, 100);
>xx : any
>100 : 100
xx = (0, xx.fn)();
>xx = (0, xx.fn)() : any
>xx : any
>(0, xx.fn)() : any
>(0, xx.fn) : any
>0, xx.fn : any
>0 : 0
>xx.fn : any
>xx : any
>fn : any
xx = (0, xx['fn'])();
>xx = (0, xx['fn'])() : any
>xx : any
>(0, xx['fn'])() : any
>(0, xx['fn']) : any
>0, xx['fn'] : any
>0 : 0
>xx['fn'] : any
>xx : any
>'fn' : "fn"
xx = (0, xx.fn)``;
>xx = (0, xx.fn)`` : any
>xx : any
>(0, xx.fn)`` : any
>(0, xx.fn) : any
>0, xx.fn : any
>0 : 0
>xx.fn : any
>xx : any
>fn : any
>`` : ""

View File

@@ -40,6 +40,7 @@ xx = (!xx, 10);
xx = (~xx, 10);
xx = (-xx, 10);
xx = (+xx, 10);
xx = (0, xx)();
// OK cases
xx = (xx ? x++ : 4, 10);
@@ -51,3 +52,6 @@ xx = ((xx+= 4), xx);
xx = (Math.pow(3, 2), 4);
xx = (void xx, 10);
xx = (xx as any, 100);
xx = (0, xx.fn)();
xx = (0, xx['fn'])();
xx = (0, xx.fn)``;