@@ -161,7 +161,7 @@ namespace ts {
161
161
* Callers should skip the current statement and avoid any returns of '_this'.
162
162
*/
163
163
ReplaceWithReturn ,
164
- }
164
+ }
165
165
166
166
export function transformES6 ( context : TransformationContext ) {
167
167
const {
@@ -902,15 +902,14 @@ namespace ts {
902
902
903
903
/**
904
904
* 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
906
906
* by doing a minimal check on whether some common patterns always explicitly return.
907
907
*/
908
908
function isSufficientlyCoveredByReturnStatements ( statement : Statement ) : boolean {
909
909
// A return statement is considered covered.
910
910
if ( statement . kind === SyntaxKind . ReturnStatement ) {
911
911
return true ;
912
912
}
913
-
914
913
// An if-statement with two covered branches is covered.
915
914
else if ( statement . kind === SyntaxKind . IfStatement ) {
916
915
const ifStatement = statement as IfStatement ;
@@ -973,6 +972,68 @@ namespace ts {
973
972
return SuperCaptureResult . NoReplacement ;
974
973
}
975
974
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
+
976
1037
/**
977
1038
* Visits a parameter declaration.
978
1039
*
@@ -1216,68 +1277,6 @@ namespace ts {
1216
1277
statements . push ( forStatement ) ;
1217
1278
}
1218
1279
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
-
1281
1280
/**
1282
1281
* Adds a statement to capture the `this` of a function declaration if it is needed.
1283
1282
*
0 commit comments