diff --git a/src/compiler/transformers/classFields.ts b/src/compiler/transformers/classFields.ts index 01e3d7c7896a8..02d89a22e604e 100644 --- a/src/compiler/transformers/classFields.ts +++ b/src/compiler/transformers/classFields.ts @@ -339,6 +339,15 @@ namespace ts { if (shouldTransformPrivateFields && isPrivateIdentifierPropertyAccessExpression(node.expression)) { // Transform call expressions of private names to properly bind the `this` parameter. const { thisArg, target } = factory.createCallBinding(node.expression, hoistVariableDeclaration, languageVersion); + if (isCallChain(node)) { + return factory.updateCallChain( + node, + factory.createPropertyAccessChain(visitNode(target, visitor), node.questionDotToken, "call"), + /*questionDotToken*/ undefined, + /*typeArguments*/ undefined, + [visitNode(thisArg, visitor, isExpression), ...visitNodes(node.arguments, visitor, isExpression)] + ); + } return factory.updateCallExpression( node, factory.createPropertyAccessExpression(visitNode(target, visitor), "call"), diff --git a/tests/baselines/reference/privateNameFieldCallExpression.js b/tests/baselines/reference/privateNameFieldCallExpression.js index 37692c12290f3..e4b9a413672fc 100644 --- a/tests/baselines/reference/privateNameFieldCallExpression.js +++ b/tests/baselines/reference/privateNameFieldCallExpression.js @@ -5,6 +5,7 @@ class A { x = 1; test() { this.#fieldFunc(); + this.#fieldFunc?.(); const func = this.#fieldFunc; func(); new this.#fieldFunc(); @@ -35,7 +36,9 @@ class A { } test() { var _a; + var _b; __classPrivateFieldGet(this, _fieldFunc).call(this); + (_a = __classPrivateFieldGet(this, _fieldFunc)) === null || _a === void 0 ? void 0 : _a.call(this); const func = __classPrivateFieldGet(this, _fieldFunc); func(); new (__classPrivateFieldGet(this, _fieldFunc))(); @@ -43,7 +46,7 @@ class A { __classPrivateFieldGet(this, _fieldFunc2).call(this, 0, ...arr, 3); const b = new (__classPrivateFieldGet(this, _fieldFunc2))(0, ...arr, 3); const str = __classPrivateFieldGet(this, _fieldFunc2).bind(this) `head${1}middle${2}tail`; - __classPrivateFieldGet((_a = this.getInstance()), _fieldFunc2).bind(_a) `test${1}and${2}`; + __classPrivateFieldGet((_b = this.getInstance()), _fieldFunc2).bind(_b) `test${1}and${2}`; } getInstance() { return new A(); } } diff --git a/tests/baselines/reference/privateNameFieldCallExpression.symbols b/tests/baselines/reference/privateNameFieldCallExpression.symbols index 3fe98ce7002f7..aea16f011983d 100644 --- a/tests/baselines/reference/privateNameFieldCallExpression.symbols +++ b/tests/baselines/reference/privateNameFieldCallExpression.symbols @@ -18,47 +18,51 @@ class A { this.#fieldFunc(); >this.#fieldFunc : Symbol(A.#fieldFunc, Decl(privateNameFieldCallExpression.ts, 0, 9)) +>this : Symbol(A, Decl(privateNameFieldCallExpression.ts, 0, 0)) + + this.#fieldFunc?.(); +>this.#fieldFunc : Symbol(A.#fieldFunc, Decl(privateNameFieldCallExpression.ts, 0, 9)) >this : Symbol(A, Decl(privateNameFieldCallExpression.ts, 0, 0)) const func = this.#fieldFunc; ->func : Symbol(func, Decl(privateNameFieldCallExpression.ts, 6, 13)) +>func : Symbol(func, Decl(privateNameFieldCallExpression.ts, 7, 13)) >this.#fieldFunc : Symbol(A.#fieldFunc, Decl(privateNameFieldCallExpression.ts, 0, 9)) >this : Symbol(A, Decl(privateNameFieldCallExpression.ts, 0, 0)) func(); ->func : Symbol(func, Decl(privateNameFieldCallExpression.ts, 6, 13)) +>func : Symbol(func, Decl(privateNameFieldCallExpression.ts, 7, 13)) new this.#fieldFunc(); >this.#fieldFunc : Symbol(A.#fieldFunc, Decl(privateNameFieldCallExpression.ts, 0, 9)) >this : Symbol(A, Decl(privateNameFieldCallExpression.ts, 0, 0)) const arr = [ 1, 2 ]; ->arr : Symbol(arr, Decl(privateNameFieldCallExpression.ts, 10, 13)) +>arr : Symbol(arr, Decl(privateNameFieldCallExpression.ts, 11, 13)) this.#fieldFunc2(0, ...arr, 3); >this.#fieldFunc2 : Symbol(A.#fieldFunc2, Decl(privateNameFieldCallExpression.ts, 1, 45)) >this : Symbol(A, Decl(privateNameFieldCallExpression.ts, 0, 0)) ->arr : Symbol(arr, Decl(privateNameFieldCallExpression.ts, 10, 13)) +>arr : Symbol(arr, Decl(privateNameFieldCallExpression.ts, 11, 13)) const b = new this.#fieldFunc2(0, ...arr, 3); ->b : Symbol(b, Decl(privateNameFieldCallExpression.ts, 12, 13)) +>b : Symbol(b, Decl(privateNameFieldCallExpression.ts, 13, 13)) >this.#fieldFunc2 : Symbol(A.#fieldFunc2, Decl(privateNameFieldCallExpression.ts, 1, 45)) >this : Symbol(A, Decl(privateNameFieldCallExpression.ts, 0, 0)) ->arr : Symbol(arr, Decl(privateNameFieldCallExpression.ts, 10, 13)) +>arr : Symbol(arr, Decl(privateNameFieldCallExpression.ts, 11, 13)) const str = this.#fieldFunc2`head${1}middle${2}tail`; ->str : Symbol(str, Decl(privateNameFieldCallExpression.ts, 13, 13)) +>str : Symbol(str, Decl(privateNameFieldCallExpression.ts, 14, 13)) >this.#fieldFunc2 : Symbol(A.#fieldFunc2, Decl(privateNameFieldCallExpression.ts, 1, 45)) >this : Symbol(A, Decl(privateNameFieldCallExpression.ts, 0, 0)) this.getInstance().#fieldFunc2`test${1}and${2}`; >this.getInstance().#fieldFunc2 : Symbol(A.#fieldFunc2, Decl(privateNameFieldCallExpression.ts, 1, 45)) ->this.getInstance : Symbol(A.getInstance, Decl(privateNameFieldCallExpression.ts, 15, 5)) +>this.getInstance : Symbol(A.getInstance, Decl(privateNameFieldCallExpression.ts, 16, 5)) >this : Symbol(A, Decl(privateNameFieldCallExpression.ts, 0, 0)) ->getInstance : Symbol(A.getInstance, Decl(privateNameFieldCallExpression.ts, 15, 5)) +>getInstance : Symbol(A.getInstance, Decl(privateNameFieldCallExpression.ts, 16, 5)) } getInstance() { return new A(); } ->getInstance : Symbol(A.getInstance, Decl(privateNameFieldCallExpression.ts, 15, 5)) +>getInstance : Symbol(A.getInstance, Decl(privateNameFieldCallExpression.ts, 16, 5)) >A : Symbol(A, Decl(privateNameFieldCallExpression.ts, 0, 0)) } diff --git a/tests/baselines/reference/privateNameFieldCallExpression.types b/tests/baselines/reference/privateNameFieldCallExpression.types index a103c2230b4d6..21a72c92c81fa 100644 --- a/tests/baselines/reference/privateNameFieldCallExpression.types +++ b/tests/baselines/reference/privateNameFieldCallExpression.types @@ -27,6 +27,11 @@ class A { this.#fieldFunc(); >this.#fieldFunc() : void >this.#fieldFunc : () => void +>this : this + + this.#fieldFunc?.(); +>this.#fieldFunc?.() : void +>this.#fieldFunc : () => void >this : this const func = this.#fieldFunc; diff --git a/tests/cases/conformance/classes/members/privateNames/privateNameFieldCallExpression.ts b/tests/cases/conformance/classes/members/privateNames/privateNameFieldCallExpression.ts index 996c01c8ef8a7..407a59185403e 100644 --- a/tests/cases/conformance/classes/members/privateNames/privateNameFieldCallExpression.ts +++ b/tests/cases/conformance/classes/members/privateNames/privateNameFieldCallExpression.ts @@ -6,6 +6,7 @@ class A { x = 1; test() { this.#fieldFunc(); + this.#fieldFunc?.(); const func = this.#fieldFunc; func(); new this.#fieldFunc();