Skip to content

Commit 36a5c42

Browse files
Moved code around, fixed indent, reworded comment.
1 parent 47a9368 commit 36a5c42

File tree

1 file changed

+64
-65
lines changed
  • src/compiler/transformers

1 file changed

+64
-65
lines changed

Diff for: src/compiler/transformers/es6.ts

+64-65
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ namespace ts {
161161
* Callers should skip the current statement and avoid any returns of '_this'.
162162
*/
163163
ReplaceWithReturn,
164-
}
164+
}
165165

166166
export function transformES6(context: TransformationContext) {
167167
const {
@@ -902,15 +902,14 @@ namespace ts {
902902

903903
/**
904904
* We want to try to avoid emitting a return statement in certain cases if a user already returned something.
905-
* It would be pointless and generate dead code, so we'll try to make things a little bit prettier
905+
* It would generate obviously dead code, so we'll try to make things a little bit prettier
906906
* by doing a minimal check on whether some common patterns always explicitly return.
907907
*/
908908
function isSufficientlyCoveredByReturnStatements(statement: Statement): boolean {
909909
// A return statement is considered covered.
910910
if (statement.kind === SyntaxKind.ReturnStatement) {
911911
return true;
912912
}
913-
914913
// An if-statement with two covered branches is covered.
915914
else if (statement.kind === SyntaxKind.IfStatement) {
916915
const ifStatement = statement as IfStatement;
@@ -973,6 +972,68 @@ namespace ts {
973972
return SuperCaptureResult.NoReplacement;
974973
}
975974

975+
/**
976+
* Declares a `_this` variable for derived classes and for when arrow functions capture `this`.
977+
*
978+
* @returns The new statement offset into the `statements` array.
979+
*/
980+
function declareOrCaptureOrReturnThisForConstructorIfNeeded(statements: Statement[], ctor: ConstructorDeclaration, hasExtendsClause: boolean, statementOffset: number) {
981+
// If this isn't a derived class, just capture 'this' for arrow functions if necessary.
982+
if (!hasExtendsClause) {
983+
addCaptureThisForNodeIfNeeded(statements, ctor);
984+
return SuperCaptureResult.NoReplacement;
985+
}
986+
987+
// Most of the time, a 'super' call will be the first real statement in a constructor body.
988+
// In these cases, we'd like to transform these into a *single* statement instead of a declaration
989+
// followed by an assignment statement for '_this'. For instance, if we emitted without an initializer,
990+
// we'd get:
991+
//
992+
// var _this;
993+
// _this = _super.call(...) || this;
994+
//
995+
// instead of
996+
//
997+
// var _this = _super.call(...) || this;
998+
//
999+
// Additionally, if the 'super()' call is the last statement, we should just avoid capturing
1000+
// entirely and immediately return the result like so:
1001+
//
1002+
// return _super.call(...) || this;
1003+
//
1004+
let firstStatement: Statement;
1005+
let superCallExpression: Expression;
1006+
1007+
const ctorStatements = ctor.body.statements;
1008+
if (statementOffset < ctorStatements.length) {
1009+
firstStatement = ctorStatements[statementOffset];
1010+
1011+
if (firstStatement.kind === SyntaxKind.ExpressionStatement && isSuperCallExpression((firstStatement as ExpressionStatement).expression)) {
1012+
const superCall = (firstStatement as ExpressionStatement).expression as CallExpression;
1013+
superCallExpression = setOriginalNode(
1014+
saveStateAndInvoke(superCall, visitImmediateSuperCallInBody),
1015+
superCall
1016+
);
1017+
}
1018+
}
1019+
1020+
// Return the result if we have an immediate super() call on the last statement.
1021+
if (superCallExpression && statementOffset === ctorStatements.length - 1) {
1022+
statements.push(createReturn(superCallExpression));
1023+
return SuperCaptureResult.ReplaceWithReturn;
1024+
}
1025+
1026+
// Perform the capture.
1027+
captureThisForNode(statements, ctor, superCallExpression, firstStatement);
1028+
1029+
// If we're actually replacing the original statement, we need to signal this to the caller.
1030+
if (superCallExpression) {
1031+
return SuperCaptureResult.ReplaceSuperCapture;
1032+
}
1033+
1034+
return SuperCaptureResult.NoReplacement;
1035+
}
1036+
9761037
/**
9771038
* Visits a parameter declaration.
9781039
*
@@ -1216,68 +1277,6 @@ namespace ts {
12161277
statements.push(forStatement);
12171278
}
12181279

1219-
/**
1220-
* Declares a `_this` variable for derived classes and for when arrow functions capture `this`.
1221-
*
1222-
* @returns The new statement offset into the `statements` array.
1223-
*/
1224-
function declareOrCaptureOrReturnThisForConstructorIfNeeded(statements: Statement[], ctor: ConstructorDeclaration, hasExtendsClause: boolean, statementOffset: number) {
1225-
// If this isn't a derived class, just capture 'this' for arrow functions if necessary.
1226-
if (!hasExtendsClause) {
1227-
addCaptureThisForNodeIfNeeded(statements, ctor);
1228-
return SuperCaptureResult.NoReplacement;
1229-
}
1230-
1231-
// Most of the time, a 'super' call will be the first real statement in a constructor body.
1232-
// In these cases, we'd like to transform these into a *single* statement instead of a declaration
1233-
// followed by an assignment statement for '_this'. For instance, if we emitted without an initializer,
1234-
// we'd get:
1235-
//
1236-
// var _this;
1237-
// _this = _super.call(...) || this;
1238-
//
1239-
// instead of
1240-
//
1241-
// var _this = _super.call(...) || this;
1242-
//
1243-
// Additionally, if the 'super()' call is the last statement, we should just avoid capturing
1244-
// entirely and immediately return the result like so:
1245-
//
1246-
// return _super.call(...) || this;
1247-
//
1248-
let firstStatement: Statement;
1249-
let superCallExpression: Expression;
1250-
1251-
const ctorStatements = ctor.body.statements;
1252-
if (statementOffset < ctorStatements.length) {
1253-
firstStatement = ctorStatements[statementOffset];
1254-
1255-
if (firstStatement.kind === SyntaxKind.ExpressionStatement && isSuperCallExpression((firstStatement as ExpressionStatement).expression)) {
1256-
const superCall = (firstStatement as ExpressionStatement).expression as CallExpression;
1257-
superCallExpression = setOriginalNode(
1258-
saveStateAndInvoke(superCall, visitImmediateSuperCallInBody),
1259-
superCall
1260-
);
1261-
}
1262-
}
1263-
1264-
// Return the result if we have an immediate super() call on the last statement.
1265-
if (superCallExpression && statementOffset === ctorStatements.length - 1) {
1266-
statements.push(createReturn(superCallExpression));
1267-
return SuperCaptureResult.ReplaceWithReturn;
1268-
}
1269-
1270-
// Perform the capture.
1271-
captureThisForNode(statements, ctor, superCallExpression, firstStatement);
1272-
1273-
// If we're actually replacing the original statement, we need to signal this to the caller.
1274-
if (superCallExpression) {
1275-
return SuperCaptureResult.ReplaceSuperCapture;
1276-
}
1277-
1278-
return SuperCaptureResult.NoReplacement;
1279-
}
1280-
12811280
/**
12821281
* Adds a statement to capture the `this` of a function declaration if it is needed.
12831282
*

0 commit comments

Comments
 (0)