diff --git a/src/compiler/transformers/es2015.ts b/src/compiler/transformers/es2015.ts index da0fcc73a98..0956c1075ef 100644 --- a/src/compiler/transformers/es2015.ts +++ b/src/compiler/transformers/es2015.ts @@ -3439,64 +3439,71 @@ namespace ts { function visitCallExpressionWithPotentialCapturedThisAssignment(node: CallExpression, assignToCapturedThis: boolean): CallExpression | BinaryExpression { // We are here either because SuperKeyword was used somewhere in the expression, or // because we contain a SpreadElementExpression. + if (node.transformFlags & TransformFlags.ContainsSpread || + node.expression.kind === SyntaxKind.SuperKeyword || + isSuperProperty(skipOuterExpressions(node.expression))) { - const { target, thisArg } = createCallBinding(node.expression, hoistVariableDeclaration); - if (node.expression.kind === SyntaxKind.SuperKeyword) { - setEmitFlags(thisArg, EmitFlags.NoSubstitution); - } - let resultingCall: CallExpression | BinaryExpression; - if (node.transformFlags & TransformFlags.ContainsSpread) { - // [source] - // f(...a, b) - // x.m(...a, b) - // super(...a, b) - // super.m(...a, b) // in static - // super.m(...a, b) // in instance - // - // [output] - // f.apply(void 0, a.concat([b])) - // (_a = x).m.apply(_a, a.concat([b])) - // _super.apply(this, a.concat([b])) - // _super.m.apply(this, a.concat([b])) - // _super.prototype.m.apply(this, a.concat([b])) + const { target, thisArg } = createCallBinding(node.expression, hoistVariableDeclaration); + if (node.expression.kind === SyntaxKind.SuperKeyword) { + setEmitFlags(thisArg, EmitFlags.NoSubstitution); + } - resultingCall = createFunctionApply( - visitNode(target, callExpressionVisitor, isExpression), - visitNode(thisArg, visitor, isExpression), - transformAndSpreadElements(node.arguments, /*needsUniqueCopy*/ false, /*multiLine*/ false, /*hasTrailingComma*/ false) - ); - } - else { - // [source] - // super(a) - // super.m(a) // in static - // super.m(a) // in instance - // - // [output] - // _super.call(this, a) - // _super.m.call(this, a) - // _super.prototype.m.call(this, a) - resultingCall = createFunctionCall( - visitNode(target, callExpressionVisitor, isExpression), - visitNode(thisArg, visitor, isExpression), - visitNodes(node.arguments, visitor, isExpression), - /*location*/ node - ); - } + let resultingCall: CallExpression | BinaryExpression; + if (node.transformFlags & TransformFlags.ContainsSpread) { + // [source] + // f(...a, b) + // x.m(...a, b) + // super(...a, b) + // super.m(...a, b) // in static + // super.m(...a, b) // in instance + // + // [output] + // f.apply(void 0, a.concat([b])) + // (_a = x).m.apply(_a, a.concat([b])) + // _super.apply(this, a.concat([b])) + // _super.m.apply(this, a.concat([b])) + // _super.prototype.m.apply(this, a.concat([b])) - if (node.expression.kind === SyntaxKind.SuperKeyword) { - const actualThis = createThis(); - setEmitFlags(actualThis, EmitFlags.NoSubstitution); - const initializer = - createLogicalOr( - resultingCall, - actualThis + resultingCall = createFunctionApply( + visitNode(target, callExpressionVisitor, isExpression), + visitNode(thisArg, visitor, isExpression), + transformAndSpreadElements(node.arguments, /*needsUniqueCopy*/ false, /*multiLine*/ false, /*hasTrailingComma*/ false) ); - resultingCall = assignToCapturedThis - ? createAssignment(createIdentifier("_this"), initializer) - : initializer; + } + else { + // [source] + // super(a) + // super.m(a) // in static + // super.m(a) // in instance + // + // [output] + // _super.call(this, a) + // _super.m.call(this, a) + // _super.prototype.m.call(this, a) + resultingCall = createFunctionCall( + visitNode(target, callExpressionVisitor, isExpression), + visitNode(thisArg, visitor, isExpression), + visitNodes(node.arguments, visitor, isExpression), + /*location*/ node + ); + } + + if (node.expression.kind === SyntaxKind.SuperKeyword) { + const actualThis = createThis(); + setEmitFlags(actualThis, EmitFlags.NoSubstitution); + const initializer = + createLogicalOr( + resultingCall, + actualThis + ); + resultingCall = assignToCapturedThis + ? createAssignment(createIdentifier("_this"), initializer) + : initializer; + } + return setOriginalNode(resultingCall, node); } - return setOriginalNode(resultingCall, node); + + return visitEachChild(node, visitor, context); } /** diff --git a/tests/baselines/reference/superElementAccess.js b/tests/baselines/reference/superElementAccess.js index 422b80109bb..75789b523c8 100644 --- a/tests/baselines/reference/superElementAccess.js +++ b/tests/baselines/reference/superElementAccess.js @@ -69,16 +69,15 @@ var MyDerived = /** @class */ (function (_super) { } MyDerived.prototype.foo = function () { _super.prototype["m1"].call(this, "hi"); // Should be allowed, method on base prototype - var l2 = (_a = _super.prototype["m1"]).bind.call(_a, this); // Should be allowed, can access properties as well as invoke + var l2 = _super.prototype["m1"].bind(this); // Should be allowed, can access properties as well as invoke var x = _super.prototype["m1"]; // Should be allowed, can assign to var with compatible signature - (_b = _super.prototype["m2"]).bind.call(_b, this); // Should error, instance property, not a public instance member function + _super.prototype["m2"].bind(this); // Should error, instance property, not a public instance member function _super.prototype["p1"].call(this); // Should error, private not public instance member function var l1 = _super.prototype["d1"]; // Should error, instance data property not a public instance member function var l1 = _super.prototype["d2"]; // Should error, instance data property not a public instance member function _super.prototype["m1"] = function (a) { return ""; }; // Should be allowed, we will not restrict assignment _super.prototype["value"] = 0; // Should error, instance data property not a public instance member function var z = _super.prototype["value"]; // Should error, instance data property not a public instance member function - var _a, _b; }; return MyDerived; }(MyBase)); diff --git a/tests/baselines/reference/superPropertyAccess.js b/tests/baselines/reference/superPropertyAccess.js index 8fa0984745c..cc9758a1617 100644 --- a/tests/baselines/reference/superPropertyAccess.js +++ b/tests/baselines/reference/superPropertyAccess.js @@ -69,16 +69,15 @@ var MyDerived = /** @class */ (function (_super) { } MyDerived.prototype.foo = function () { _super.prototype.m1.call(this, "hi"); // Should be allowed, method on base prototype - var l2 = (_a = _super.prototype.m1).bind.call(_a, this); // Should be allowed, can access properties as well as invoke + var l2 = _super.prototype.m1.bind(this); // Should be allowed, can access properties as well as invoke var x = _super.prototype.m1; // Should be allowed, can assign to var with compatible signature - (_b = _super.prototype.m2).bind.call(_b, this); // Should error, instance property, not a public instance member function + _super.prototype.m2.bind(this); // Should error, instance property, not a public instance member function _super.prototype.p1.call(this); // Should error, private not public instance member function var l1 = _super.prototype.d1; // Should error, instance data property not a public instance member function var l1 = _super.prototype.d2; // Should error, instance data property not a public instance member function _super.prototype.m1 = function (a) { return ""; }; // Should be allowed, we will not restrict assignment _super.prototype.value = 0; // Should error, instance data property not a public instance member function var z = _super.prototype.value; // Should error, instance data property not a public instance member function - var _a, _b; }; return MyDerived; }(MyBase));