Skip to content

Commit 2916c9c

Browse files
committed
Fix over-aggressive transformation of super properties
1 parent 1caf7c4 commit 2916c9c

File tree

3 files changed

+65
-60
lines changed

3 files changed

+65
-60
lines changed

src/compiler/transformers/es2015.ts

Lines changed: 61 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -3439,64 +3439,71 @@ namespace ts {
34393439
function visitCallExpressionWithPotentialCapturedThisAssignment(node: CallExpression, assignToCapturedThis: boolean): CallExpression | BinaryExpression {
34403440
// We are here either because SuperKeyword was used somewhere in the expression, or
34413441
// because we contain a SpreadElementExpression.
3442+
if (node.transformFlags & TransformFlags.ContainsSpread ||
3443+
node.expression.kind === SyntaxKind.SuperKeyword ||
3444+
isSuperProperty(skipOuterExpressions(node.expression))) {
34423445

3443-
const { target, thisArg } = createCallBinding(node.expression, hoistVariableDeclaration);
3444-
if (node.expression.kind === SyntaxKind.SuperKeyword) {
3445-
setEmitFlags(thisArg, EmitFlags.NoSubstitution);
3446-
}
3447-
let resultingCall: CallExpression | BinaryExpression;
3448-
if (node.transformFlags & TransformFlags.ContainsSpread) {
3449-
// [source]
3450-
// f(...a, b)
3451-
// x.m(...a, b)
3452-
// super(...a, b)
3453-
// super.m(...a, b) // in static
3454-
// super.m(...a, b) // in instance
3455-
//
3456-
// [output]
3457-
// f.apply(void 0, a.concat([b]))
3458-
// (_a = x).m.apply(_a, a.concat([b]))
3459-
// _super.apply(this, a.concat([b]))
3460-
// _super.m.apply(this, a.concat([b]))
3461-
// _super.prototype.m.apply(this, a.concat([b]))
3462-
3463-
resultingCall = createFunctionApply(
3464-
visitNode(target, callExpressionVisitor, isExpression),
3465-
visitNode(thisArg, visitor, isExpression),
3466-
transformAndSpreadElements(node.arguments, /*needsUniqueCopy*/ false, /*multiLine*/ false, /*hasTrailingComma*/ false)
3467-
);
3468-
}
3469-
else {
3470-
// [source]
3471-
// super(a)
3472-
// super.m(a) // in static
3473-
// super.m(a) // in instance
3474-
//
3475-
// [output]
3476-
// _super.call(this, a)
3477-
// _super.m.call(this, a)
3478-
// _super.prototype.m.call(this, a)
3479-
resultingCall = createFunctionCall(
3480-
visitNode(target, callExpressionVisitor, isExpression),
3481-
visitNode(thisArg, visitor, isExpression),
3482-
visitNodes(node.arguments, visitor, isExpression),
3483-
/*location*/ node
3484-
);
3485-
}
3446+
const { target, thisArg } = createCallBinding(node.expression, hoistVariableDeclaration);
3447+
if (node.expression.kind === SyntaxKind.SuperKeyword) {
3448+
setEmitFlags(thisArg, EmitFlags.NoSubstitution);
3449+
}
34863450

3487-
if (node.expression.kind === SyntaxKind.SuperKeyword) {
3488-
const actualThis = createThis();
3489-
setEmitFlags(actualThis, EmitFlags.NoSubstitution);
3490-
const initializer =
3491-
createLogicalOr(
3492-
resultingCall,
3493-
actualThis
3451+
let resultingCall: CallExpression | BinaryExpression;
3452+
if (node.transformFlags & TransformFlags.ContainsSpread) {
3453+
// [source]
3454+
// f(...a, b)
3455+
// x.m(...a, b)
3456+
// super(...a, b)
3457+
// super.m(...a, b) // in static
3458+
// super.m(...a, b) // in instance
3459+
//
3460+
// [output]
3461+
// f.apply(void 0, a.concat([b]))
3462+
// (_a = x).m.apply(_a, a.concat([b]))
3463+
// _super.apply(this, a.concat([b]))
3464+
// _super.m.apply(this, a.concat([b]))
3465+
// _super.prototype.m.apply(this, a.concat([b]))
3466+
3467+
resultingCall = createFunctionApply(
3468+
visitNode(target, callExpressionVisitor, isExpression),
3469+
visitNode(thisArg, visitor, isExpression),
3470+
transformAndSpreadElements(node.arguments, /*needsUniqueCopy*/ false, /*multiLine*/ false, /*hasTrailingComma*/ false)
3471+
);
3472+
}
3473+
else {
3474+
// [source]
3475+
// super(a)
3476+
// super.m(a) // in static
3477+
// super.m(a) // in instance
3478+
//
3479+
// [output]
3480+
// _super.call(this, a)
3481+
// _super.m.call(this, a)
3482+
// _super.prototype.m.call(this, a)
3483+
resultingCall = createFunctionCall(
3484+
visitNode(target, callExpressionVisitor, isExpression),
3485+
visitNode(thisArg, visitor, isExpression),
3486+
visitNodes(node.arguments, visitor, isExpression),
3487+
/*location*/ node
34943488
);
3495-
resultingCall = assignToCapturedThis
3496-
? createAssignment(createIdentifier("_this"), initializer)
3497-
: initializer;
3489+
}
3490+
3491+
if (node.expression.kind === SyntaxKind.SuperKeyword) {
3492+
const actualThis = createThis();
3493+
setEmitFlags(actualThis, EmitFlags.NoSubstitution);
3494+
const initializer =
3495+
createLogicalOr(
3496+
resultingCall,
3497+
actualThis
3498+
);
3499+
resultingCall = assignToCapturedThis
3500+
? createAssignment(createIdentifier("_this"), initializer)
3501+
: initializer;
3502+
}
3503+
return setOriginalNode(resultingCall, node);
34983504
}
3499-
return setOriginalNode(resultingCall, node);
3505+
3506+
return visitEachChild(node, visitor, context);
35003507
}
35013508

35023509
/**

tests/baselines/reference/superElementAccess.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,16 +69,15 @@ var MyDerived = /** @class */ (function (_super) {
6969
}
7070
MyDerived.prototype.foo = function () {
7171
_super.prototype["m1"].call(this, "hi"); // Should be allowed, method on base prototype
72-
var l2 = (_a = _super.prototype["m1"]).bind.call(_a, this); // Should be allowed, can access properties as well as invoke
72+
var l2 = _super.prototype["m1"].bind(this); // Should be allowed, can access properties as well as invoke
7373
var x = _super.prototype["m1"]; // Should be allowed, can assign to var with compatible signature
74-
(_b = _super.prototype["m2"]).bind.call(_b, this); // Should error, instance property, not a public instance member function
74+
_super.prototype["m2"].bind(this); // Should error, instance property, not a public instance member function
7575
_super.prototype["p1"].call(this); // Should error, private not public instance member function
7676
var l1 = _super.prototype["d1"]; // Should error, instance data property not a public instance member function
7777
var l1 = _super.prototype["d2"]; // Should error, instance data property not a public instance member function
7878
_super.prototype["m1"] = function (a) { return ""; }; // Should be allowed, we will not restrict assignment
7979
_super.prototype["value"] = 0; // Should error, instance data property not a public instance member function
8080
var z = _super.prototype["value"]; // Should error, instance data property not a public instance member function
81-
var _a, _b;
8281
};
8382
return MyDerived;
8483
}(MyBase));

tests/baselines/reference/superPropertyAccess.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,16 +69,15 @@ var MyDerived = /** @class */ (function (_super) {
6969
}
7070
MyDerived.prototype.foo = function () {
7171
_super.prototype.m1.call(this, "hi"); // Should be allowed, method on base prototype
72-
var l2 = (_a = _super.prototype.m1).bind.call(_a, this); // Should be allowed, can access properties as well as invoke
72+
var l2 = _super.prototype.m1.bind(this); // Should be allowed, can access properties as well as invoke
7373
var x = _super.prototype.m1; // Should be allowed, can assign to var with compatible signature
74-
(_b = _super.prototype.m2).bind.call(_b, this); // Should error, instance property, not a public instance member function
74+
_super.prototype.m2.bind(this); // Should error, instance property, not a public instance member function
7575
_super.prototype.p1.call(this); // Should error, private not public instance member function
7676
var l1 = _super.prototype.d1; // Should error, instance data property not a public instance member function
7777
var l1 = _super.prototype.d2; // Should error, instance data property not a public instance member function
7878
_super.prototype.m1 = function (a) { return ""; }; // Should be allowed, we will not restrict assignment
7979
_super.prototype.value = 0; // Should error, instance data property not a public instance member function
8080
var z = _super.prototype.value; // Should error, instance data property not a public instance member function
81-
var _a, _b;
8281
};
8382
return MyDerived;
8483
}(MyBase));

0 commit comments

Comments
 (0)