Skip to content

Commit

Permalink
Moved code around, fixed indent, reworded comment.
Browse files Browse the repository at this point in the history
  • Loading branch information
DanielRosenwasser committed Sep 27, 2016
1 parent fb4b503 commit b5a1031
Showing 1 changed file with 64 additions and 65 deletions.
129 changes: 64 additions & 65 deletions src/compiler/transformers/es6.ts
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ namespace ts {
* Callers should skip the current statement and avoid any returns of '_this'.
*/
ReplaceWithReturn,
}
}

export function transformES6(context: TransformationContext) {
const {
Expand Down Expand Up @@ -902,15 +902,14 @@ namespace ts {

/**
* We want to try to avoid emitting a return statement in certain cases if a user already returned something.
* It would be pointless and generate dead code, so we'll try to make things a little bit prettier
* It would generate obviously dead code, so we'll try to make things a little bit prettier
* by doing a minimal check on whether some common patterns always explicitly return.
*/
function isSufficientlyCoveredByReturnStatements(statement: Statement): boolean {
// A return statement is considered covered.
if (statement.kind === SyntaxKind.ReturnStatement) {
return true;
}

// An if-statement with two covered branches is covered.
else if (statement.kind === SyntaxKind.IfStatement) {
const ifStatement = statement as IfStatement;
Expand Down Expand Up @@ -973,6 +972,68 @@ namespace ts {
return SuperCaptureResult.NoReplacement;
}

/**
* Declares a `_this` variable for derived classes and for when arrow functions capture `this`.
*
* @returns The new statement offset into the `statements` array.
*/
function declareOrCaptureOrReturnThisForConstructorIfNeeded(statements: Statement[], ctor: ConstructorDeclaration, hasExtendsClause: boolean, statementOffset: number) {
// If this isn't a derived class, just capture 'this' for arrow functions if necessary.
if (!hasExtendsClause) {
addCaptureThisForNodeIfNeeded(statements, ctor);
return SuperCaptureResult.NoReplacement;
}

// Most of the time, a 'super' call will be the first real statement in a constructor body.
// In these cases, we'd like to transform these into a *single* statement instead of a declaration
// followed by an assignment statement for '_this'. For instance, if we emitted without an initializer,
// we'd get:
//
// var _this;
// _this = _super.call(...) || this;
//
// instead of
//
// var _this = _super.call(...) || this;
//
// Additionally, if the 'super()' call is the last statement, we should just avoid capturing
// entirely and immediately return the result like so:
//
// return _super.call(...) || this;
//
let firstStatement: Statement;
let superCallExpression: Expression;

const ctorStatements = ctor.body.statements;
if (statementOffset < ctorStatements.length) {
firstStatement = ctorStatements[statementOffset];

if (firstStatement.kind === SyntaxKind.ExpressionStatement && isSuperCallExpression((firstStatement as ExpressionStatement).expression)) {
const superCall = (firstStatement as ExpressionStatement).expression as CallExpression;
superCallExpression = setOriginalNode(
saveStateAndInvoke(superCall, visitImmediateSuperCallInBody),
superCall
);
}
}

// Return the result if we have an immediate super() call on the last statement.
if (superCallExpression && statementOffset === ctorStatements.length - 1) {
statements.push(createReturn(superCallExpression));
return SuperCaptureResult.ReplaceWithReturn;
}

// Perform the capture.
captureThisForNode(statements, ctor, superCallExpression, firstStatement);

// If we're actually replacing the original statement, we need to signal this to the caller.
if (superCallExpression) {
return SuperCaptureResult.ReplaceSuperCapture;
}

return SuperCaptureResult.NoReplacement;
}

/**
* Visits a parameter declaration.
*
Expand Down Expand Up @@ -1216,68 +1277,6 @@ namespace ts {
statements.push(forStatement);
}

/**
* Declares a `_this` variable for derived classes and for when arrow functions capture `this`.
*
* @returns The new statement offset into the `statements` array.
*/
function declareOrCaptureOrReturnThisForConstructorIfNeeded(statements: Statement[], ctor: ConstructorDeclaration, hasExtendsClause: boolean, statementOffset: number) {
// If this isn't a derived class, just capture 'this' for arrow functions if necessary.
if (!hasExtendsClause) {
addCaptureThisForNodeIfNeeded(statements, ctor);
return SuperCaptureResult.NoReplacement;
}

// Most of the time, a 'super' call will be the first real statement in a constructor body.
// In these cases, we'd like to transform these into a *single* statement instead of a declaration
// followed by an assignment statement for '_this'. For instance, if we emitted without an initializer,
// we'd get:
//
// var _this;
// _this = _super.call(...) || this;
//
// instead of
//
// var _this = _super.call(...) || this;
//
// Additionally, if the 'super()' call is the last statement, we should just avoid capturing
// entirely and immediately return the result like so:
//
// return _super.call(...) || this;
//
let firstStatement: Statement;
let superCallExpression: Expression;

const ctorStatements = ctor.body.statements;
if (statementOffset < ctorStatements.length) {
firstStatement = ctorStatements[statementOffset];

if (firstStatement.kind === SyntaxKind.ExpressionStatement && isSuperCallExpression((firstStatement as ExpressionStatement).expression)) {
const superCall = (firstStatement as ExpressionStatement).expression as CallExpression;
superCallExpression = setOriginalNode(
saveStateAndInvoke(superCall, visitImmediateSuperCallInBody),
superCall
);
}
}

// Return the result if we have an immediate super() call on the last statement.
if (superCallExpression && statementOffset === ctorStatements.length - 1) {
statements.push(createReturn(superCallExpression));
return SuperCaptureResult.ReplaceWithReturn;
}

// Perform the capture.
captureThisForNode(statements, ctor, superCallExpression, firstStatement);

// If we're actually replacing the original statement, we need to signal this to the caller.
if (superCallExpression) {
return SuperCaptureResult.ReplaceSuperCapture;
}

return SuperCaptureResult.NoReplacement;
}

/**
* Adds a statement to capture the `this` of a function declaration if it is needed.
*
Expand Down

0 comments on commit b5a1031

Please sign in to comment.