Skip to content

Commit c29ec6f

Browse files
Consolidated 'super()' transformation logic into one function.
1 parent b5a1031 commit c29ec6f

File tree

1 file changed

+38
-50
lines changed
  • src/compiler/transformers

1 file changed

+38
-50
lines changed

src/compiler/transformers/es6.ts

Lines changed: 38 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -837,7 +837,6 @@ namespace ts {
837837
startLexicalEnvironment();
838838

839839
let statementOffset = -1;
840-
let superCaptureStatus = SuperCaptureResult.NoReplacement;
841840
if (hasSynthesizedSuper) {
842841
// If a super call has already been synthesized,
843842
// we're going to assume that we should just transform everything after that.
@@ -854,12 +853,9 @@ namespace ts {
854853
addRestParameterIfNeeded(statements, constructor, hasSynthesizedSuper);
855854
Debug.assert(statementOffset >= 0, "statementOffset not initialized correctly!");
856855

857-
superCaptureStatus = declareOrCaptureOrReturnThisForConstructorIfNeeded(statements, constructor, !!extendsClauseElement, statementOffset);
858856
}
859857

860-
if (superCaptureStatus === SuperCaptureResult.NoReplacement) {
861-
superCaptureStatus = addDefaultSuperCallIfNeeded(statements, constructor, extendsClauseElement, hasSynthesizedSuper);
862-
}
858+
const superCaptureStatus = declareOrCaptureOrReturnThisForConstructorIfNeeded(statements, constructor, !!extendsClauseElement, hasSynthesizedSuper, statementOffset);
863859

864860
// The last statement expression was replaced. Skip it.
865861
if (superCaptureStatus === SuperCaptureResult.ReplaceSuperCapture || superCaptureStatus === SuperCaptureResult.ReplaceWithReturn) {
@@ -929,61 +925,42 @@ namespace ts {
929925
return false;
930926
}
931927

932-
/**
933-
* Adds a synthesized call to `_super` if it is needed.
934-
*
935-
* @param statements The statements for the new constructor body.
936-
* @param constructor The constructor for the class.
937-
* @param extendsClauseElement The expression for the class `extends` clause.
938-
* @param hasSynthesizedSuper A value indicating whether the constructor starts with a
939-
* synthesized `super` call.
940-
*/
941-
function addDefaultSuperCallIfNeeded(statements: Statement[], constructor: ConstructorDeclaration, extendsClauseElement: ExpressionWithTypeArguments, hasSynthesizedSuper: boolean) {
942-
// If the TypeScript transformer needed to synthesize a constructor for property
943-
// initializers, it would have also added a synthetic `...args` parameter and
944-
// `super` call.
945-
// If this is the case, or if the class has an `extends` clause but no
946-
// constructor, we emit a synthesized call to `_super`.
947-
if (constructor ? hasSynthesizedSuper : extendsClauseElement) {
948-
const actualThis = createThis();
949-
setNodeEmitFlags(actualThis, NodeEmitFlags.NoSubstitution);
950-
const superCall = createFunctionApply(
951-
createIdentifier("_super"),
952-
actualThis,
953-
createIdentifier("arguments"),
954-
);
955-
const superReturnValueOrThis = createLogicalOr(superCall, actualThis);
956-
957-
if (!constructor) {
958-
// We must be here because the user didn't write a constructor
959-
// but we needed to call 'super()' anyway - but if that's the case,
960-
// we can just immediately return the result of a 'super()' call.
961-
statements.push(createReturn(superReturnValueOrThis));
962-
return SuperCaptureResult.ReplaceWithReturn;
963-
}
964-
965-
// The constructor was generated for some reason.
966-
// Create a captured '_this' variable.
967-
captureThisForNode(statements, constructor, superReturnValueOrThis);
968-
enableSubstitutionsForCapturedThis();
969-
return SuperCaptureResult.ReplaceSuperCapture;
970-
}
971-
972-
return SuperCaptureResult.NoReplacement;
973-
}
974-
975928
/**
976929
* Declares a `_this` variable for derived classes and for when arrow functions capture `this`.
977930
*
978931
* @returns The new statement offset into the `statements` array.
979932
*/
980-
function declareOrCaptureOrReturnThisForConstructorIfNeeded(statements: Statement[], ctor: ConstructorDeclaration, hasExtendsClause: boolean, statementOffset: number) {
933+
function declareOrCaptureOrReturnThisForConstructorIfNeeded(
934+
statements: Statement[],
935+
ctor: ConstructorDeclaration | undefined,
936+
hasExtendsClause: boolean,
937+
hasSynthesizedSuper: boolean,
938+
statementOffset: number) {
981939
// If this isn't a derived class, just capture 'this' for arrow functions if necessary.
982940
if (!hasExtendsClause) {
983-
addCaptureThisForNodeIfNeeded(statements, ctor);
941+
if (ctor) {
942+
addCaptureThisForNodeIfNeeded(statements, ctor);
943+
}
984944
return SuperCaptureResult.NoReplacement;
985945
}
986946

947+
// We must be here because the user didn't write a constructor
948+
// but we needed to call 'super(...args)' anyway as per 14.5.14 of the ES2016 spec.
949+
// If that's the case we can just immediately return the result of a 'super()' call.
950+
if (!ctor) {
951+
statements.push(createReturn(createDefaultSuperCallOrThis()));
952+
return SuperCaptureResult.ReplaceWithReturn;
953+
}
954+
955+
// The constructor exists, but it and the 'super()' call it contains were generated
956+
// for something like property initializers.
957+
// Create a captured '_this' variable and assume it will subsequently be used.
958+
if (hasSynthesizedSuper) {
959+
captureThisForNode(statements, ctor, createDefaultSuperCallOrThis());
960+
enableSubstitutionsForCapturedThis();
961+
return SuperCaptureResult.ReplaceSuperCapture;
962+
}
963+
987964
// Most of the time, a 'super' call will be the first real statement in a constructor body.
988965
// In these cases, we'd like to transform these into a *single* statement instead of a declaration
989966
// followed by an assignment statement for '_this'. For instance, if we emitted without an initializer,
@@ -1034,6 +1011,17 @@ namespace ts {
10341011
return SuperCaptureResult.NoReplacement;
10351012
}
10361013

1014+
function createDefaultSuperCallOrThis() {
1015+
const actualThis = createThis();
1016+
setNodeEmitFlags(actualThis, NodeEmitFlags.NoSubstitution);
1017+
const superCall = createFunctionApply(
1018+
createIdentifier("_super"),
1019+
actualThis,
1020+
createIdentifier("arguments"),
1021+
);
1022+
return createLogicalOr(superCall, actualThis);
1023+
}
1024+
10371025
/**
10381026
* Visits a parameter declaration.
10391027
*

0 commit comments

Comments
 (0)