Fix over-aggressive transformation of super properties

This commit is contained in:
Ron Buckton
2018-02-01 15:22:34 -08:00
parent 421c927150
commit 94b2d40cac
3 changed files with 64 additions and 59 deletions

View File

@@ -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);
}
/**