Skip to content

Commit

Permalink
Merge pull request #30259 from Microsoft/transformFlagCleanup
Browse files Browse the repository at this point in the history
Transform flag cleanup
  • Loading branch information
rbuckton authored Mar 8, 2019
2 parents 58e847a + 1c0f9a8 commit 6607e00
Show file tree
Hide file tree
Showing 27 changed files with 478 additions and 638 deletions.
119 changes: 18 additions & 101 deletions src/compiler/binder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3093,32 +3093,24 @@ namespace ts {

function computeCallExpression(node: CallExpression, subtreeFlags: TransformFlags) {
let transformFlags = subtreeFlags;
const callee = skipOuterExpressions(node.expression);
const expression = node.expression;

if (node.typeArguments) {
transformFlags |= TransformFlags.AssertTypeScript;
}

if (subtreeFlags & TransformFlags.ContainsRestOrSpread
|| (expression.transformFlags & (TransformFlags.Super | TransformFlags.ContainsSuper))) {
if (subtreeFlags & TransformFlags.ContainsRestOrSpread || isSuperOrSuperProperty(callee)) {
// If the this node contains a SpreadExpression, or is a super call, then it is an ES6
// node.
transformFlags |= TransformFlags.AssertES2015;
// super property or element accesses could be inside lambdas, etc, and need a captured `this`,
// while super keyword for super calls (indicated by TransformFlags.Super) does not (since it can only be top-level in a constructor)
if (expression.transformFlags & TransformFlags.ContainsSuper) {
if (isSuperProperty(callee)) {
transformFlags |= TransformFlags.ContainsLexicalThis;
}
}

if (expression.kind === SyntaxKind.ImportKeyword) {
transformFlags |= TransformFlags.ContainsDynamicImport;

// A dynamic 'import()' call that contains a lexical 'this' will
// require a captured 'this' when emitting down-level.
if (subtreeFlags & TransformFlags.ContainsLexicalThis) {
transformFlags |= TransformFlags.ContainsCapturedLexicalThis;
}
}

node.transformFlags = transformFlags | TransformFlags.HasComputedFlags;
Expand Down Expand Up @@ -3191,7 +3183,7 @@ namespace ts {
// If a parameter has an initializer, a binding pattern or a dotDotDot token, then
// it is ES6 syntax and its container must emit default value assignments or parameter destructuring downlevel.
if (subtreeFlags & TransformFlags.ContainsBindingPattern || initializer || dotDotDotToken) {
transformFlags |= TransformFlags.AssertES2015 | TransformFlags.ContainsDefaultValueAssignments;
transformFlags |= TransformFlags.AssertES2015;
}

node.transformFlags = transformFlags | TransformFlags.HasComputedFlags;
Expand All @@ -3202,7 +3194,6 @@ namespace ts {
let transformFlags = subtreeFlags;
const expression = node.expression;
const expressionKind = expression.kind;
const expressionTransformFlags = expression.transformFlags;

// If the node is synthesized, it means the emitter put the parentheses there,
// not the user. If we didn't want them, the emitter would not have put them
Expand All @@ -3212,12 +3203,6 @@ namespace ts {
transformFlags |= TransformFlags.AssertTypeScript;
}

// If the expression of a ParenthesizedExpression is a destructuring assignment,
// then the ParenthesizedExpression is a destructuring assignment.
if (expressionTransformFlags & TransformFlags.DestructuringAssignment) {
transformFlags |= TransformFlags.DestructuringAssignment;
}

node.transformFlags = transformFlags | TransformFlags.HasComputedFlags;
return transformFlags & ~TransformFlags.OuterExpressionExcludes;
}
Expand All @@ -3241,12 +3226,6 @@ namespace ts {
|| node.typeParameters) {
transformFlags |= TransformFlags.AssertTypeScript;
}

if (subtreeFlags & TransformFlags.ContainsLexicalThisInComputedPropertyName) {
// A computed property name containing `this` might need to be rewritten,
// so propagate the ContainsLexicalThis flag upward.
transformFlags |= TransformFlags.ContainsLexicalThis;
}
}

node.transformFlags = transformFlags | TransformFlags.HasComputedFlags;
Expand All @@ -3264,12 +3243,6 @@ namespace ts {
transformFlags |= TransformFlags.AssertTypeScript;
}

if (subtreeFlags & TransformFlags.ContainsLexicalThisInComputedPropertyName) {
// A computed property name containing `this` might need to be rewritten,
// so propagate the ContainsLexicalThis flag upward.
transformFlags |= TransformFlags.ContainsLexicalThis;
}

node.transformFlags = transformFlags | TransformFlags.HasComputedFlags;
return transformFlags & ~TransformFlags.ClassExcludes;
}
Expand Down Expand Up @@ -3374,7 +3347,7 @@ namespace ts {
}

node.transformFlags = transformFlags | TransformFlags.HasComputedFlags;
return transformFlags & ~TransformFlags.MethodOrAccessorExcludes;
return propagatePropertyNameFlags(node.name, transformFlags & ~TransformFlags.MethodOrAccessorExcludes);
}

function computeAccessor(node: AccessorDeclaration, subtreeFlags: TransformFlags) {
Expand All @@ -3396,7 +3369,7 @@ namespace ts {
}

node.transformFlags = transformFlags | TransformFlags.HasComputedFlags;
return transformFlags & ~TransformFlags.MethodOrAccessorExcludes;
return propagatePropertyNameFlags(node.name, transformFlags & ~TransformFlags.MethodOrAccessorExcludes);
}

function computePropertyDeclaration(node: PropertyDeclaration, subtreeFlags: TransformFlags) {
Expand All @@ -3410,7 +3383,7 @@ namespace ts {
}

node.transformFlags = transformFlags | TransformFlags.HasComputedFlags;
return transformFlags & ~TransformFlags.NodeExcludes;
return propagatePropertyNameFlags(node.name, transformFlags & ~TransformFlags.PropertyExcludes);
}

function computeFunctionDeclaration(node: FunctionDeclaration, subtreeFlags: TransformFlags) {
Expand Down Expand Up @@ -3444,13 +3417,6 @@ namespace ts {
transformFlags |= TransformFlags.AssertES2018;
}

// If a FunctionDeclaration's subtree has marked the container as needing to capture the
// lexical this, or the function contains parameters with initializers, then this node is
// ES6 syntax.
if (subtreeFlags & TransformFlags.ES2015FunctionSyntaxMask) {
transformFlags |= TransformFlags.AssertES2015;
}

// If a FunctionDeclaration is generator function and is the body of a
// transformed async function, then this node can be transformed to a
// down-level generator.
Expand Down Expand Up @@ -3486,14 +3452,6 @@ namespace ts {
transformFlags |= TransformFlags.AssertES2018;
}


// If a FunctionExpression's subtree has marked the container as needing to capture the
// lexical this, or the function contains parameters with initializers, then this node is
// ES6 syntax.
if (subtreeFlags & TransformFlags.ES2015FunctionSyntaxMask) {
transformFlags |= TransformFlags.AssertES2015;
}

// If a FunctionExpression is generator function and is the body of a
// transformed async function, then this node can be transformed to a
// down-level generator.
Expand Down Expand Up @@ -3527,11 +3485,6 @@ namespace ts {
transformFlags |= TransformFlags.AssertES2018;
}

// If an ArrowFunction contains a lexical this, its container must capture the lexical this.
if (subtreeFlags & TransformFlags.ContainsLexicalThis) {
transformFlags |= TransformFlags.ContainsCapturedLexicalThis;
}

node.transformFlags = transformFlags | TransformFlags.HasComputedFlags;
return transformFlags & ~TransformFlags.ArrowFunctionExcludes;
}
Expand All @@ -3541,11 +3494,10 @@ namespace ts {

// If a PropertyAccessExpression starts with a super keyword, then it is
// ES6 syntax, and requires a lexical `this` binding.
if (transformFlags & TransformFlags.Super) {
transformFlags ^= TransformFlags.Super;
if (node.expression.kind === SyntaxKind.SuperKeyword) {
// super inside of an async function requires hoisting the super access (ES2017).
// same for super inside of an async generator, which is ES2018.
transformFlags |= TransformFlags.ContainsSuper | TransformFlags.ContainsES2017 | TransformFlags.ContainsES2018;
transformFlags |= TransformFlags.ContainsES2017 | TransformFlags.ContainsES2018;
}

node.transformFlags = transformFlags | TransformFlags.HasComputedFlags;
Expand All @@ -3554,16 +3506,13 @@ namespace ts {

function computeElementAccess(node: ElementAccessExpression, subtreeFlags: TransformFlags) {
let transformFlags = subtreeFlags;
const expression = node.expression;
const expressionFlags = expression.transformFlags; // We do not want to aggregate flags from the argument expression for super/this capturing

// If an ElementAccessExpression starts with a super keyword, then it is
// ES6 syntax, and requires a lexical `this` binding.
if (expressionFlags & TransformFlags.Super) {
transformFlags &= ~TransformFlags.Super;
if (node.expression.kind === SyntaxKind.SuperKeyword) {
// super inside of an async function requires hoisting the super access (ES2017).
// same for super inside of an async generator, which is ES2018.
transformFlags |= TransformFlags.ContainsSuper | TransformFlags.ContainsES2017 | TransformFlags.ContainsES2018;
transformFlags |= TransformFlags.ContainsES2017 | TransformFlags.ContainsES2018;
}

node.transformFlags = transformFlags | TransformFlags.HasComputedFlags;
Expand All @@ -3572,7 +3521,7 @@ namespace ts {

function computeVariableDeclaration(node: VariableDeclaration, subtreeFlags: TransformFlags) {
let transformFlags = subtreeFlags;
transformFlags |= TransformFlags.AssertES2015 | TransformFlags.ContainsBindingPattern;
transformFlags |= TransformFlags.AssertES2015 | TransformFlags.ContainsBindingPattern; // TODO(rbuckton): Why are these set unconditionally?

// A VariableDeclaration containing ObjectRest is ES2018 syntax
if (subtreeFlags & TransformFlags.ContainsObjectRestOrSpread) {
Expand Down Expand Up @@ -3634,15 +3583,7 @@ namespace ts {
}

function computeExpressionStatement(node: ExpressionStatement, subtreeFlags: TransformFlags) {
let transformFlags = subtreeFlags;

// If the expression of an expression statement is a destructuring assignment,
// then we treat the statement as ES6 so that we can indicate that we do not
// need to hold on to the right-hand side.
if (node.expression.transformFlags & TransformFlags.DestructuringAssignment) {
transformFlags |= TransformFlags.AssertES2015;
}

const transformFlags = subtreeFlags;
node.transformFlags = transformFlags | TransformFlags.HasComputedFlags;
return transformFlags & ~TransformFlags.NodeExcludes;
}
Expand Down Expand Up @@ -3815,17 +3756,6 @@ namespace ts {
// This is so that they can flow through PropertyName transforms unaffected.
// Instead, we mark the container as ES6, so that it can properly handle the transform.
transformFlags |= TransformFlags.ContainsComputedPropertyName;
if (subtreeFlags & TransformFlags.ContainsLexicalThis) {
// A computed method name like `[this.getName()](x: string) { ... }` needs to
// distinguish itself from the normal case of a method body containing `this`:
// `this` inside a method doesn't need to be rewritten (the method provides `this`),
// whereas `this` inside a computed name *might* need to be rewritten if the class/object
// is inside an arrow function:
// `_this = this; () => class K { [_this.getName()]() { ... } }`
// To make this distinction, use ContainsLexicalThisInComputedPropertyName
// instead of ContainsLexicalThis for computed property names
transformFlags |= TransformFlags.ContainsLexicalThisInComputedPropertyName;
}
break;

case SyntaxKind.SpreadElement:
Expand All @@ -3838,7 +3768,7 @@ namespace ts {

case SyntaxKind.SuperKeyword:
// This node is ES6 syntax.
transformFlags |= TransformFlags.AssertES2015 | TransformFlags.Super;
transformFlags |= TransformFlags.AssertES2015;
excludeFlags = TransformFlags.OuterExpressionExcludes; // must be set to persist `Super`
break;

Expand Down Expand Up @@ -3880,12 +3810,6 @@ namespace ts {
transformFlags |= TransformFlags.AssertES2015;
}

if (subtreeFlags & TransformFlags.ContainsLexicalThisInComputedPropertyName) {
// A computed property name containing `this` might need to be rewritten,
// so propagate the ContainsLexicalThis flag upward.
transformFlags |= TransformFlags.ContainsLexicalThis;
}

if (subtreeFlags & TransformFlags.ContainsObjectRestOrSpread) {
// If an ObjectLiteralExpression contains a spread element, then it
// is an ES2018 node.
Expand All @@ -3895,14 +3819,7 @@ namespace ts {
break;

case SyntaxKind.ArrayLiteralExpression:
case SyntaxKind.NewExpression:
excludeFlags = TransformFlags.ArrayLiteralOrCallOrNewExcludes;
if (subtreeFlags & TransformFlags.ContainsRestOrSpread) {
// If the this node contains a SpreadExpression, then it is an ES6
// node.
transformFlags |= TransformFlags.AssertES2015;
}

break;

case SyntaxKind.DoStatement:
Expand All @@ -3917,10 +3834,6 @@ namespace ts {
break;

case SyntaxKind.SourceFile:
if (subtreeFlags & TransformFlags.ContainsCapturedLexicalThis) {
transformFlags |= TransformFlags.AssertES2015;
}

break;

case SyntaxKind.ReturnStatement:
Expand All @@ -3938,6 +3851,10 @@ namespace ts {
return transformFlags & ~excludeFlags;
}

function propagatePropertyNameFlags(node: PropertyName, transformFlags: TransformFlags) {
return transformFlags | (node.transformFlags & TransformFlags.PropertyNamePropagatingFlags);
}

/**
* Gets the transform flags to exclude when unioning the transform flags of a subtree.
*
Expand Down
Loading

0 comments on commit 6607e00

Please sign in to comment.