mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-09 20:51:43 -06:00
Fix over-aggressive transformation of super properties
This commit is contained in:
parent
421c927150
commit
94b2d40cac
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -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));
|
||||
|
||||
@ -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));
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user