Skip to content

Commit 2fb0b85

Browse files
committed
Restore ContainsLexicalThsi flag for performance
1 parent 86242ee commit 2fb0b85

File tree

3 files changed

+39
-91
lines changed

3 files changed

+39
-91
lines changed

src/compiler/binder.ts

Lines changed: 8 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -3099,21 +3099,14 @@ namespace ts {
30993099
// If the this node contains a SpreadExpression, or is a super call, then it is an ES6
31003100
// node.
31013101
transformFlags |= TransformFlags.AssertES2015;
3102-
// super property or element accesses could be inside lambdas, etc, and need a captured `this`,
3103-
// while super keyword for super calls (indicated by TransformFlags.Super) does not (since it can only be top-level in a constructor)
3102+
31043103
if (expression.transformFlags & TransformFlags.ContainsSuper) {
31053104
transformFlags |= TransformFlags.ContainsLexicalThis;
31063105
}
31073106
}
31083107

31093108
if (expression.kind === SyntaxKind.ImportKeyword) {
31103109
transformFlags |= TransformFlags.ContainsDynamicImport;
3111-
3112-
// A dynamic 'import()' call that contains a lexical 'this' will
3113-
// require a captured 'this' when emitting down-level.
3114-
if (subtreeFlags & TransformFlags.ContainsLexicalThis) {
3115-
transformFlags |= TransformFlags.ContainsCapturedLexicalThis;
3116-
}
31173110
}
31183111

31193112
node.transformFlags = transformFlags | TransformFlags.HasComputedFlags;
@@ -3236,12 +3229,6 @@ namespace ts {
32363229
|| node.typeParameters) {
32373230
transformFlags |= TransformFlags.AssertTypeScript;
32383231
}
3239-
3240-
if (subtreeFlags & TransformFlags.ContainsLexicalThisInComputedPropertyName) {
3241-
// A computed property name containing `this` might need to be rewritten,
3242-
// so propagate the ContainsLexicalThis flag upward.
3243-
transformFlags |= TransformFlags.ContainsLexicalThis;
3244-
}
32453232
}
32463233

32473234
node.transformFlags = transformFlags | TransformFlags.HasComputedFlags;
@@ -3259,12 +3246,6 @@ namespace ts {
32593246
transformFlags |= TransformFlags.AssertTypeScript;
32603247
}
32613248

3262-
if (subtreeFlags & TransformFlags.ContainsLexicalThisInComputedPropertyName) {
3263-
// A computed property name containing `this` might need to be rewritten,
3264-
// so propagate the ContainsLexicalThis flag upward.
3265-
transformFlags |= TransformFlags.ContainsLexicalThis;
3266-
}
3267-
32683249
node.transformFlags = transformFlags | TransformFlags.HasComputedFlags;
32693250
return transformFlags & ~TransformFlags.ClassExcludes;
32703251
}
@@ -3369,7 +3350,7 @@ namespace ts {
33693350
}
33703351

33713352
node.transformFlags = transformFlags | TransformFlags.HasComputedFlags;
3372-
return transformFlags & ~TransformFlags.MethodOrAccessorExcludes;
3353+
return propagatePropertyNameFlags(node.name, transformFlags & ~TransformFlags.MethodOrAccessorExcludes);
33733354
}
33743355

33753356
function computeAccessor(node: AccessorDeclaration, subtreeFlags: TransformFlags) {
@@ -3391,7 +3372,7 @@ namespace ts {
33913372
}
33923373

33933374
node.transformFlags = transformFlags | TransformFlags.HasComputedFlags;
3394-
return transformFlags & ~TransformFlags.MethodOrAccessorExcludes;
3375+
return propagatePropertyNameFlags(node.name, transformFlags & ~TransformFlags.MethodOrAccessorExcludes);
33953376
}
33963377

33973378
function computePropertyDeclaration(node: PropertyDeclaration, subtreeFlags: TransformFlags) {
@@ -3405,7 +3386,7 @@ namespace ts {
34053386
}
34063387

34073388
node.transformFlags = transformFlags | TransformFlags.HasComputedFlags;
3408-
return transformFlags & ~TransformFlags.NodeExcludes;
3389+
return propagatePropertyNameFlags(node.name, transformFlags & ~TransformFlags.PropertyExcludes);
34093390
}
34103391

34113392
function computeFunctionDeclaration(node: FunctionDeclaration, subtreeFlags: TransformFlags) {
@@ -3439,13 +3420,6 @@ namespace ts {
34393420
transformFlags |= TransformFlags.AssertES2018;
34403421
}
34413422

3442-
// If a FunctionDeclaration's subtree has marked the container as needing to capture the
3443-
// lexical this, or the function contains parameters with initializers, then this node is
3444-
// ES6 syntax.
3445-
if (subtreeFlags & TransformFlags.ContainsCapturedLexicalThis) {
3446-
transformFlags |= TransformFlags.AssertES2015;
3447-
}
3448-
34493423
// If a FunctionDeclaration is generator function and is the body of a
34503424
// transformed async function, then this node can be transformed to a
34513425
// down-level generator.
@@ -3481,14 +3455,6 @@ namespace ts {
34813455
transformFlags |= TransformFlags.AssertES2018;
34823456
}
34833457

3484-
3485-
// If a FunctionExpression's subtree has marked the container as needing to capture the
3486-
// lexical this, or the function contains parameters with initializers, then this node is
3487-
// ES6 syntax.
3488-
if (subtreeFlags & TransformFlags.ContainsCapturedLexicalThis) {
3489-
transformFlags |= TransformFlags.AssertES2015;
3490-
}
3491-
34923458
// If a FunctionExpression is generator function and is the body of a
34933459
// transformed async function, then this node can be transformed to a
34943460
// down-level generator.
@@ -3522,11 +3488,6 @@ namespace ts {
35223488
transformFlags |= TransformFlags.AssertES2018;
35233489
}
35243490

3525-
// If an ArrowFunction contains a lexical this, its container must capture the lexical this.
3526-
if (subtreeFlags & TransformFlags.ContainsLexicalThis) {
3527-
transformFlags |= TransformFlags.ContainsCapturedLexicalThis;
3528-
}
3529-
35303491
node.transformFlags = transformFlags | TransformFlags.HasComputedFlags;
35313492
return transformFlags & ~TransformFlags.ArrowFunctionExcludes;
35323493
}
@@ -3810,17 +3771,6 @@ namespace ts {
38103771
// This is so that they can flow through PropertyName transforms unaffected.
38113772
// Instead, we mark the container as ES6, so that it can properly handle the transform.
38123773
transformFlags |= TransformFlags.ContainsComputedPropertyName;
3813-
if (subtreeFlags & TransformFlags.ContainsLexicalThis) {
3814-
// A computed method name like `[this.getName()](x: string) { ... }` needs to
3815-
// distinguish itself from the normal case of a method body containing `this`:
3816-
// `this` inside a method doesn't need to be rewritten (the method provides `this`),
3817-
// whereas `this` inside a computed name *might* need to be rewritten if the class/object
3818-
// is inside an arrow function:
3819-
// `_this = this; () => class K { [_this.getName()]() { ... } }`
3820-
// To make this distinction, use ContainsLexicalThisInComputedPropertyName
3821-
// instead of ContainsLexicalThis for computed property names
3822-
transformFlags |= TransformFlags.ContainsLexicalThisInComputedPropertyName;
3823-
}
38243774
break;
38253775

38263776
case SyntaxKind.SpreadElement:
@@ -3839,7 +3789,6 @@ namespace ts {
38393789

38403790
case SyntaxKind.ThisKeyword:
38413791
// Mark this node and its ancestors as containing a lexical `this` keyword.
3842-
transformFlags |= TransformFlags.AssertES2015;
38433792
transformFlags |= TransformFlags.ContainsLexicalThis;
38443793
break;
38453794

@@ -3876,12 +3825,6 @@ namespace ts {
38763825
transformFlags |= TransformFlags.AssertES2015;
38773826
}
38783827

3879-
if (subtreeFlags & TransformFlags.ContainsLexicalThisInComputedPropertyName) {
3880-
// A computed property name containing `this` might need to be rewritten,
3881-
// so propagate the ContainsLexicalThis flag upward.
3882-
transformFlags |= TransformFlags.ContainsLexicalThis;
3883-
}
3884-
38853828
if (subtreeFlags & TransformFlags.ContainsObjectRestOrSpread) {
38863829
// If an ObjectLiteralExpression contains a spread element, then it
38873830
// is an ES2018 node.
@@ -3906,10 +3849,6 @@ namespace ts {
39063849
break;
39073850

39083851
case SyntaxKind.SourceFile:
3909-
if (subtreeFlags & TransformFlags.ContainsCapturedLexicalThis) {
3910-
transformFlags |= TransformFlags.AssertES2015;
3911-
}
3912-
39133852
break;
39143853

39153854
case SyntaxKind.ReturnStatement:
@@ -3927,6 +3866,10 @@ namespace ts {
39273866
return transformFlags & ~excludeFlags;
39283867
}
39293868

3869+
function propagatePropertyNameFlags(node: PropertyName, transformFlags: TransformFlags) {
3870+
return transformFlags | (node.transformFlags & TransformFlags.PropertyNamePropagatingFlags);
3871+
}
3872+
39303873
/**
39313874
* Gets the transform flags to exclude when unioning the transform flags of a subtree.
39323875
*

src/compiler/transformers/es2015.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -229,8 +229,7 @@ namespace ts {
229229
//
230230

231231
NewTarget = 1 << 13, // Contains a 'new.target' meta-property
232-
LexicalThis = 1 << 14, // Contains a lexical `this` reference.
233-
CapturedLexicalThis = 1 << 15, // Contains a lexical `this` reference captured by an arrow function.
232+
CapturedLexicalThis = 1 << 14, // Contains a lexical `this` reference captured by an arrow function.
234233

235234
//
236235
// Subtree masks
@@ -239,7 +238,7 @@ namespace ts {
239238
SubtreeFactsMask = ~AncestorFactsMask,
240239

241240
ArrowFunctionSubtreeExcludes = None,
242-
FunctionSubtreeExcludes = NewTarget | LexicalThis | CapturedLexicalThis,
241+
FunctionSubtreeExcludes = NewTarget | CapturedLexicalThis,
243242
}
244243

245244
export function transformES2015(context: TransformationContext) {
@@ -565,7 +564,6 @@ namespace ts {
565564
}
566565

567566
function visitThisKeyword(node: Node): Node {
568-
hierarchyFacts |= HierarchyFacts.LexicalThis;
569567
if (hierarchyFacts & HierarchyFacts.ArrowFunction) {
570568
hierarchyFacts |= HierarchyFacts.CapturedLexicalThis;
571569
}
@@ -989,7 +987,7 @@ namespace ts {
989987
insertCaptureNewTargetIfNeeded(prologue, constructor, /*copyOnWrite*/ false);
990988

991989
if (isDerivedClass) {
992-
if (superCallExpression && statementOffset === constructor.body.statements.length && !(hierarchyFacts & HierarchyFacts.LexicalThis)) {
990+
if (superCallExpression && statementOffset === constructor.body.statements.length && !(constructor.body.transformFlags & TransformFlags.ContainsLexicalThis)) {
993991
// If the subclass constructor does *not* contain `this` and *ends* with a `super()` call, we will use the
994992
// following representation:
995993
//
@@ -1693,6 +1691,10 @@ namespace ts {
16931691
* @param node An ArrowFunction node.
16941692
*/
16951693
function visitArrowFunction(node: ArrowFunction) {
1694+
if (node.transformFlags & TransformFlags.ContainsLexicalThis) {
1695+
hierarchyFacts |= HierarchyFacts.CapturedLexicalThis;
1696+
}
1697+
16961698
const savedConvertedLoopState = convertedLoopState;
16971699
convertedLoopState = undefined;
16981700
const ancestorFacts = enterSubtree(HierarchyFacts.ArrowFunctionExcludes, HierarchyFacts.ArrowFunctionIncludes);

src/compiler/types.ts

Lines changed: 24 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5055,20 +5055,18 @@ namespace ts {
50555055

50565056
// Markers
50575057
// - Flags used to indicate that a subtree contains a specific transformation.
5058-
ContainsTypeScriptClassSyntax = 1 << 11, // Decorators, Property Initializers, Parameter Property Initializers
5059-
ContainsLexicalThis = 1 << 12,
5060-
ContainsCapturedLexicalThis = 1 << 13,
5061-
ContainsLexicalThisInComputedPropertyName = 1 << 14,
5062-
ContainsRestOrSpread = 1 << 15,
5063-
ContainsObjectRestOrSpread = 1 << 16,
5064-
ContainsComputedPropertyName = 1 << 17,
5065-
ContainsBlockScopedBinding = 1 << 18,
5066-
ContainsBindingPattern = 1 << 19,
5067-
ContainsYield = 1 << 20,
5068-
ContainsHoistedDeclarationOrCompletion = 1 << 21,
5069-
ContainsDynamicImport = 1 << 22,
5070-
Super = 1 << 23,
5071-
ContainsSuper = 1 << 24,
5058+
ContainsLexicalThis = 1 << 11,
5059+
ContainsTypeScriptClassSyntax = 1 << 12, // Decorators, Property Initializers, Parameter Property Initializers
5060+
ContainsRestOrSpread = 1 << 13,
5061+
ContainsObjectRestOrSpread = 1 << 14,
5062+
ContainsComputedPropertyName = 1 << 15,
5063+
ContainsBlockScopedBinding = 1 << 16,
5064+
ContainsBindingPattern = 1 << 17,
5065+
ContainsYield = 1 << 18,
5066+
ContainsHoistedDeclarationOrCompletion = 1 << 19,
5067+
ContainsDynamicImport = 1 << 20,
5068+
Super = 1 << 21,
5069+
ContainsSuper = 1 << 22,
50725070

50735071
// Please leave this as 1 << 29.
50745072
// It is the maximum bit we can set before we outgrow the size of a v8 small integer (SMI) on an x86 system.
@@ -5093,20 +5091,25 @@ namespace ts {
50935091
OuterExpressionExcludes = DestructuringAssignment | Generator | HasComputedFlags,
50945092
PropertyAccessExcludes = OuterExpressionExcludes | Super,
50955093
NodeExcludes = PropertyAccessExcludes | ContainsSuper,
5096-
ArrowFunctionExcludes = NodeExcludes | ContainsTypeScriptClassSyntax | ContainsLexicalThis | ContainsBlockScopedBinding | ContainsYield | ContainsHoistedDeclarationOrCompletion | ContainsBindingPattern | ContainsObjectRestOrSpread,
5097-
FunctionExcludes = NodeExcludes | ContainsTypeScriptClassSyntax | ContainsCapturedLexicalThis | ContainsLexicalThis | ContainsBlockScopedBinding | ContainsYield | ContainsHoistedDeclarationOrCompletion | ContainsBindingPattern | ContainsObjectRestOrSpread,
5098-
ConstructorExcludes = NodeExcludes | ContainsLexicalThis | ContainsCapturedLexicalThis | ContainsBlockScopedBinding | ContainsYield | ContainsHoistedDeclarationOrCompletion | ContainsBindingPattern | ContainsObjectRestOrSpread,
5099-
MethodOrAccessorExcludes = NodeExcludes | ContainsLexicalThis | ContainsCapturedLexicalThis | ContainsBlockScopedBinding | ContainsYield | ContainsHoistedDeclarationOrCompletion | ContainsBindingPattern | ContainsObjectRestOrSpread,
5100-
ClassExcludes = NodeExcludes | ContainsTypeScriptClassSyntax | ContainsLexicalThis | ContainsCapturedLexicalThis | ContainsComputedPropertyName | ContainsLexicalThisInComputedPropertyName,
5101-
ModuleExcludes = NodeExcludes | ContainsTypeScriptClassSyntax | ContainsLexicalThis | ContainsCapturedLexicalThis | ContainsBlockScopedBinding | ContainsHoistedDeclarationOrCompletion,
5094+
ArrowFunctionExcludes = NodeExcludes | ContainsTypeScriptClassSyntax | ContainsBlockScopedBinding | ContainsYield | ContainsHoistedDeclarationOrCompletion | ContainsBindingPattern | ContainsObjectRestOrSpread,
5095+
FunctionExcludes = NodeExcludes | ContainsTypeScriptClassSyntax | ContainsLexicalThis | ContainsBlockScopedBinding | ContainsYield | ContainsHoistedDeclarationOrCompletion | ContainsBindingPattern | ContainsObjectRestOrSpread,
5096+
ConstructorExcludes = NodeExcludes | ContainsLexicalThis | ContainsBlockScopedBinding | ContainsYield | ContainsHoistedDeclarationOrCompletion | ContainsBindingPattern | ContainsObjectRestOrSpread,
5097+
MethodOrAccessorExcludes = NodeExcludes | ContainsLexicalThis | ContainsBlockScopedBinding | ContainsYield | ContainsHoistedDeclarationOrCompletion | ContainsBindingPattern | ContainsObjectRestOrSpread,
5098+
PropertyExcludes = NodeExcludes | ContainsLexicalThis,
5099+
ClassExcludes = NodeExcludes | ContainsTypeScriptClassSyntax | ContainsComputedPropertyName,
5100+
ModuleExcludes = NodeExcludes | ContainsTypeScriptClassSyntax | ContainsLexicalThis | ContainsBlockScopedBinding | ContainsHoistedDeclarationOrCompletion,
51025101
TypeExcludes = ~ContainsTypeScript,
5103-
ObjectLiteralExcludes = NodeExcludes | ContainsTypeScriptClassSyntax | ContainsComputedPropertyName | ContainsLexicalThisInComputedPropertyName | ContainsObjectRestOrSpread,
5102+
ObjectLiteralExcludes = NodeExcludes | ContainsTypeScriptClassSyntax | ContainsComputedPropertyName | ContainsObjectRestOrSpread,
51045103
ArrayLiteralOrCallOrNewExcludes = NodeExcludes | ContainsRestOrSpread,
51055104
VariableDeclarationListExcludes = NodeExcludes | ContainsBindingPattern | ContainsObjectRestOrSpread,
51065105
ParameterExcludes = NodeExcludes,
51075106
CatchClauseExcludes = NodeExcludes | ContainsObjectRestOrSpread,
51085107
BindingPatternExcludes = NodeExcludes | ContainsRestOrSpread,
51095108

5109+
// Propagating flags
5110+
// - Bitmasks for flags that should propagate from a child
5111+
PropertyNamePropagatingFlags = ContainsLexicalThis,
5112+
51105113
// Masks
51115114
// - Additional bitmasks
51125115
}

0 commit comments

Comments
 (0)