mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-06-10 18:04:18 -05:00
Allow indirect calls (#51989)
Co-authored-by: Klaus Meinhardt <klaus.meinhardt1@gmail.com>
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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)``;
|
||||
@@ -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([""], [""]));
|
||||
|
||||
@@ -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))
|
||||
|
||||
|
||||
@@ -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
|
||||
>`` : ""
|
||||
|
||||
|
||||
@@ -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)``;
|
||||
Reference in New Issue
Block a user