mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-05 16:38:05 -06:00
parent
8a81a6722d
commit
15e69acc20
@ -21,11 +21,15 @@ namespace ts {
|
||||
return node;
|
||||
}
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.CallExpression: {
|
||||
const updated = visitNonOptionalCallExpression(node as CallExpression, /*captureThisArg*/ false);
|
||||
Debug.assertNotNode(updated, isSyntheticReference);
|
||||
return updated;
|
||||
}
|
||||
case SyntaxKind.PropertyAccessExpression:
|
||||
case SyntaxKind.ElementAccessExpression:
|
||||
case SyntaxKind.CallExpression:
|
||||
if (node.flags & NodeFlags.OptionalChain) {
|
||||
const updated = visitOptionalExpression(node as OptionalChain, /*captureThisArg*/ false, /*isDelete*/ false);
|
||||
if (isOptionalChain(node)) {
|
||||
const updated = visitOptionalExpression(node, /*captureThisArg*/ false, /*isDelete*/ false);
|
||||
Debug.assertNotNode(updated, isSyntheticReference);
|
||||
return updated;
|
||||
}
|
||||
@ -94,6 +98,15 @@ namespace ts {
|
||||
// If `node` is an optional chain, then it is the outermost chain of an optional expression.
|
||||
return visitOptionalExpression(node, captureThisArg, /*isDelete*/ false);
|
||||
}
|
||||
if (isParenthesizedExpression(node.expression) && isOptionalChain(skipParentheses(node.expression))) {
|
||||
// capture thisArg for calls of parenthesized optional chains like `(foo?.bar)()`
|
||||
const expression = visitNonOptionalParenthesizedExpression(node.expression, /*captureThisArg*/ true, /*isDelete*/ false);
|
||||
const args = visitNodes(node.arguments, visitor, isExpression);
|
||||
if (isSyntheticReference(expression)) {
|
||||
return setTextRange(factory.createFunctionCallCall(expression.expression, expression.thisArg, args), node);
|
||||
}
|
||||
return factory.updateCallExpression(node, expression, /*typeArguments*/ undefined, args);
|
||||
}
|
||||
return visitEachChild(node, visitor, context);
|
||||
}
|
||||
|
||||
|
||||
@ -188,4 +188,11 @@ describe("unittests:: evaluation:: optionalCall", () => {
|
||||
assert.strictEqual(result.output[1], 2);
|
||||
assert.strictEqual(result.output[2], result.o);
|
||||
});
|
||||
it("(o?.f)()", async () => {
|
||||
const result = evaluator.evaluateTypeScript(`
|
||||
export const foo = { bar() { return this } };
|
||||
export const output = (foo?.bar)();
|
||||
`);
|
||||
assert.strictEqual(result.output, result.foo);
|
||||
});
|
||||
});
|
||||
|
||||
18
tests/baselines/reference/parentheses.js
Normal file
18
tests/baselines/reference/parentheses.js
Normal file
@ -0,0 +1,18 @@
|
||||
//// [parentheses.ts]
|
||||
declare const o1: ((...args: any[]) => number);
|
||||
declare const o2: { b: (...args: any[]) => number };
|
||||
declare const o3: { b: ((...args: any[]) => (...args: any[]) => number) };
|
||||
declare const o4: { b: ((...args: any[]) => { c: (...args: any[]) => number } ) };
|
||||
|
||||
(o1)(o1 ?? 1);
|
||||
(o2?.b)(o1 ?? 1);
|
||||
(o3?.b())(o1 ?? 1);
|
||||
(o4?.b().c)(o1 ?? 1);
|
||||
|
||||
|
||||
//// [parentheses.js]
|
||||
var _a;
|
||||
(o1)(o1 !== null && o1 !== void 0 ? o1 : 1);
|
||||
(o2 === null || o2 === void 0 ? void 0 : o2.b).call(o2, o1 !== null && o1 !== void 0 ? o1 : 1);
|
||||
(o3 === null || o3 === void 0 ? void 0 : o3.b())(o1 !== null && o1 !== void 0 ? o1 : 1);
|
||||
(o4 === null || o4 === void 0 ? void 0 : (_a = o4.b()).c).call(_a, o1 !== null && o1 !== void 0 ? o1 : 1);
|
||||
@ -0,0 +1,11 @@
|
||||
// @noTypesAndSymbols: true
|
||||
|
||||
declare const o1: ((...args: any[]) => number);
|
||||
declare const o2: { b: (...args: any[]) => number };
|
||||
declare const o3: { b: ((...args: any[]) => (...args: any[]) => number) };
|
||||
declare const o4: { b: ((...args: any[]) => { c: (...args: any[]) => number } ) };
|
||||
|
||||
(o1)(o1 ?? 1);
|
||||
(o2?.b)(o1 ?? 1);
|
||||
(o3?.b())(o1 ?? 1);
|
||||
(o4?.b().c)(o1 ?? 1);
|
||||
Loading…
x
Reference in New Issue
Block a user