fix emit for super calls that has preceding prologue directives

This commit is contained in:
Vladimir Matveev
2016-04-12 09:58:57 -07:00
parent a27b4d07ae
commit 83334fac18
+28 -14
View File
@@ -762,19 +762,14 @@ namespace ts {
* @param parameters The transformed parameters for the constructor.
*/
function transformConstructorBody(node: ClassExpression | ClassDeclaration, constructor: ConstructorDeclaration, hasExtendsClause: boolean, parameters: ParameterDeclaration[]) {
let hasSuperCall = false;
const statements: Statement[] = [];
let indexOfFirstStatement = 0;
// The body of a constructor is a new lexical environment
startLexicalEnvironment();
if (constructor) {
const superCall = visitNode(findInitialSuperCall(constructor), visitor, isStatement);
if (superCall) {
// Adds the existing super call as the first line of the constructor.
addNode(statements, superCall);
hasSuperCall = true;
}
indexOfFirstStatement = addPrologueDirectivesAndInitialSuperCall(constructor, statements);
// Add parameters with property assignments. Transforms this:
//
@@ -823,7 +818,7 @@ namespace ts {
if (constructor) {
// The class already had a constructor, so we should add the existing statements, skipping the initial super call.
addNodes(statements, visitNodes(constructor.body.statements, visitor, isStatement, hasSuperCall ? 1 : 0));
addNodes(statements, visitNodes(constructor.body.statements, visitor, isStatement, indexOfFirstStatement));
}
// End the lexical environment.
@@ -841,25 +836,44 @@ namespace ts {
}
/**
* Finds the initial super-call for a constructor.
* Adds super call and preceding prologue directives into the list of statements.
*
* @param ctor The constructor node.
* @returns index of the statement that follows super call
*/
function findInitialSuperCall(ctor: ConstructorDeclaration): ExpressionStatement {
function addPrologueDirectivesAndInitialSuperCall(ctor: ConstructorDeclaration, result: Statement[]): number {
if (ctor.body) {
const statements = ctor.body.statements;
const statement = firstOrUndefined(statements);
if (statement && statement.kind === SyntaxKind.ExpressionStatement) {
// find first statement that is not prologue directive
let indexOfFirstNonPrologueDirective = -1;
for (let i = 0; i < statements.length; i++) {
if (!isPrologueDirective(statements[i])) {
indexOfFirstNonPrologueDirective = i;
break;
}
}
if (indexOfFirstNonPrologueDirective === -1) {
return 0;
}
const statement = statements[indexOfFirstNonPrologueDirective];
if (statement.kind === SyntaxKind.ExpressionStatement) {
const expression = (<ExpressionStatement>statement).expression;
if (expression.kind === SyntaxKind.CallExpression) {
if ((<CallExpression>expression).expression.kind === SyntaxKind.SuperKeyword) {
return <ExpressionStatement>statement;
for (let i = 0; i < indexOfFirstNonPrologueDirective; i++) {
// push all non-prologue directives
result.push(statements[i]);
}
result.push(visitNode(statement, visitor, isStatement));
return indexOfFirstNonPrologueDirective + 1;
}
}
}
}
return undefined;
return 0;
}
/**