Skip to content

Commit a9735ba

Browse files
author
Joseph Watts
committed
Add/improve comments, fix double visiting constructor
Signed-off-by: Joseph Watts <[email protected]>
1 parent b9e5a33 commit a9735ba

File tree

1 file changed

+18
-11
lines changed

1 file changed

+18
-11
lines changed

src/compiler/transformers/esnext.ts

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@ namespace ts {
33
const enum ESNextSubstitutionFlags {
44
/** Enables substitutions for async methods with `super` calls. */
55
AsyncMethodsWithSuper = 1 << 0,
6-
/** Enables substitutions for class expressions with static fields which have initializers that reference the class name. */
6+
/**
7+
* Enables substitutions for class expressions with static fields
8+
* which have initializers that reference the class name.
9+
*/
710
ClassAliases = 1 << 1,
811
}
912

@@ -156,9 +159,11 @@ namespace ts {
156159
function classElementVisitor(node: Node): VisitResult<Node> {
157160
switch (node.kind) {
158161
case SyntaxKind.Constructor:
159-
// TypeScript constructors are transformed in `visitClassDeclaration`.
160-
// We elide them here as `visitorWorker` checks transform flags, which could
161-
// erronously include an ES6 constructor without ESNext syntax.
162+
// Constructors for classes using ESNext syntax (like class properties)
163+
// are transformed in `visitClassDeclaration` or `visitClassExpression`.
164+
// We elide them here. The default visitor checks the transformFlags to
165+
// determine whether the node contains ESNext syntax, so it can skip over
166+
// constructors.
162167
return undefined;
163168

164169
case SyntaxKind.PropertyDeclaration:
@@ -180,9 +185,8 @@ namespace ts {
180185
* If the name is a computed property, this function transforms it, then either returns an expression which caches the
181186
* value of the result or the expression itself if the value is either unused or safe to inline into multiple locations
182187
* @param shouldHoist Does the expression need to be reused? (ie, for an initializer or a decorator)
183-
* @param omitSimple Should expressions with no observable side-effects be elided? (ie, the expression is not hoisted for a decorator or initializer and is a literal)
184188
*/
185-
function getPropertyNameExpressionIfNeeded(name: PropertyName, shouldHoist: boolean, omitSimple: boolean): Expression | undefined {
189+
function getPropertyNameExpressionIfNeeded(name: PropertyName, shouldHoist: boolean): Expression | undefined {
186190
if (isComputedPropertyName(name)) {
187191
const expression = visitNode(name.expression, visitor, isExpression);
188192
const innerExpression = skipPartiallyEmittedExpressions(expression);
@@ -193,7 +197,7 @@ namespace ts {
193197
hoistVariableDeclaration(generatedName);
194198
return createAssignment(generatedName, expression);
195199
}
196-
return (omitSimple && (inlinable || isIdentifier(innerExpression))) ? undefined : expression;
200+
return (inlinable || isIdentifier(innerExpression)) ? undefined : expression;
197201
}
198202
}
199203

@@ -213,7 +217,10 @@ namespace ts {
213217

214218
function visitPropertyDeclaration(node: PropertyDeclaration) {
215219
Debug.assert(!some(node.decorators));
216-
const expr = getPropertyNameExpressionIfNeeded(node.name, !!node.initializer, /*omitSimple*/ true);
220+
// Create a temporary variable to store a computed property name (if necessary).
221+
// If it's not inlineable, then we emit an expression after the class which assigns
222+
// the property name to the temporary variable.
223+
const expr = getPropertyNameExpressionIfNeeded(node.name, !!node.initializer);
217224
if (expr && !isSimpleInlineableExpression(expr)) {
218225
(pendingExpressions || (pendingExpressions = [])).push(expr);
219226
}
@@ -340,10 +347,10 @@ namespace ts {
340347
}
341348

342349
function transformConstructor(node: ClassDeclaration | ClassExpression, isDerivedClass: boolean) {
343-
const constructor = getFirstConstructorWithBody(node);
350+
const constructor = visitNode(getFirstConstructorWithBody(node), visitor, isConstructorDeclaration);
344351
const containsPropertyInitializer = forEach(node.members, isInitializedProperty);
345352
if (!containsPropertyInitializer) {
346-
return visitEachChild(constructor, visitor, context);
353+
return constructor;
347354
}
348355
const parameters = visitParameterList(constructor ? constructor.parameters : undefined, visitor, context);
349356
const body = transformConstructorBody(node, constructor, isDerivedClass);
@@ -1119,7 +1126,7 @@ namespace ts {
11191126
// The function only needs to be transformed if there are object rest parameters.
11201127
// It's not enough to rely on the ContainsESNext transform flag check to transform function bodies
11211128
// because any function containing PropertyDeclaration nodes will contain ESNext syntax.
1122-
if (!(node.transformFlags & TransformFlags.ContainsObjectRest)) {
1129+
if (!(node.transformFlags & TransformFlags.ContainsObjectRestOrSpread)) {
11231130
return (node.body && visitFunctionBody(node.body, visitor, context)) || createBlock([]);
11241131
}
11251132
resumeLexicalEnvironment();

0 commit comments

Comments
 (0)