mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Merge pull request #30259 from Microsoft/transformFlagCleanup
Transform flag cleanup
This commit is contained in:
27 files changed
+480
-640
No files matched your search
+18
-101
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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) {
|
||||
@@ -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) {
|
||||
@@ -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) {
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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) {
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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:
|
||||
@@ -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;
|
||||
|
||||
@@ -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.
|
||||
@@ -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:
|
||||
@@ -3917,10 +3834,6 @@ namespace ts {
|
||||
break;
|
||||
|
||||
case SyntaxKind.SourceFile:
|
||||
if (subtreeFlags & TransformFlags.ContainsCapturedLexicalThis) {
|
||||
transformFlags |= TransformFlags.AssertES2015;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SyntaxKind.ReturnStatement:
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
+259
-304
@@ -145,30 +145,6 @@ namespace ts {
|
||||
loopOutParameters: LoopOutParameter[];
|
||||
}
|
||||
|
||||
const enum SuperCaptureResult {
|
||||
/**
|
||||
* A capture may have been added for calls to 'super', but
|
||||
* the caller should emit subsequent statements normally.
|
||||
*/
|
||||
NoReplacement,
|
||||
/**
|
||||
* A call to 'super()' got replaced with a capturing statement like:
|
||||
*
|
||||
* var _this = _super.call(...) || this;
|
||||
*
|
||||
* Callers should skip the current statement.
|
||||
*/
|
||||
ReplaceSuperCapture,
|
||||
/**
|
||||
* A call to 'super()' got replaced with a capturing statement like:
|
||||
*
|
||||
* return _super.call(...) || this;
|
||||
*
|
||||
* Callers should skip the current statement and avoid any returns of '_this'.
|
||||
*/
|
||||
ReplaceWithReturn,
|
||||
}
|
||||
|
||||
type LoopConverter = (node: IterationStatement, outermostLabeledStatement: LabeledStatement | undefined, convertedLoopBodyStatements: Statement[] | undefined) => Statement;
|
||||
|
||||
// Facts we track as we traverse the tree
|
||||
@@ -192,14 +168,14 @@ namespace ts {
|
||||
ForStatement = 1 << 10, // Enclosing block-scoped container is a ForStatement
|
||||
ForInOrForOfStatement = 1 << 11, // Enclosing block-scoped container is a ForInStatement or ForOfStatement
|
||||
ConstructorWithCapturedSuper = 1 << 12, // Enclosed in a constructor that captures 'this' for use with 'super'
|
||||
ComputedPropertyName = 1 << 13, // Enclosed in a computed property name
|
||||
// NOTE: do not add more ancestor flags without also updating AncestorFactsMask below.
|
||||
// NOTE: when adding a new ancestor flag, be sure to update the subtree flags below.
|
||||
|
||||
//
|
||||
// Ancestor masks
|
||||
//
|
||||
|
||||
AncestorFactsMask = (ComputedPropertyName << 1) - 1,
|
||||
AncestorFactsMask = (ConstructorWithCapturedSuper << 1) - 1,
|
||||
|
||||
// We are always in *some* kind of block scope, but only specific block-scope containers are
|
||||
// top-level or Blocks.
|
||||
@@ -212,14 +188,14 @@ namespace ts {
|
||||
|
||||
// Functions, methods, and accessors are both new lexical scopes and new block scopes.
|
||||
FunctionIncludes = Function | TopLevel,
|
||||
FunctionExcludes = BlockScopeExcludes & ~TopLevel | ArrowFunction | AsyncFunctionBody | CapturesThis | NonStaticClassElement | ConstructorWithCapturedSuper | ComputedPropertyName,
|
||||
FunctionExcludes = BlockScopeExcludes & ~TopLevel | ArrowFunction | AsyncFunctionBody | CapturesThis | NonStaticClassElement | ConstructorWithCapturedSuper,
|
||||
|
||||
AsyncFunctionBodyIncludes = FunctionIncludes | AsyncFunctionBody,
|
||||
AsyncFunctionBodyExcludes = FunctionExcludes & ~NonStaticClassElement,
|
||||
|
||||
// Arrow functions are lexically scoped to their container, but are new block scopes.
|
||||
ArrowFunctionIncludes = ArrowFunction | TopLevel,
|
||||
ArrowFunctionExcludes = BlockScopeExcludes & ~TopLevel | ConstructorWithCapturedSuper | ComputedPropertyName,
|
||||
ArrowFunctionExcludes = BlockScopeExcludes & ~TopLevel | ConstructorWithCapturedSuper,
|
||||
|
||||
// Constructors are both new lexical scopes and new block scopes. Constructors are also
|
||||
// always considered non-static members of a class.
|
||||
@@ -248,23 +224,21 @@ namespace ts {
|
||||
IterationStatementBlockIncludes = IterationStatementBlock,
|
||||
IterationStatementBlockExcludes = BlockScopeExcludes,
|
||||
|
||||
// Computed property names track subtree flags differently than their containing members.
|
||||
ComputedPropertyNameIncludes = ComputedPropertyName,
|
||||
ComputedPropertyNameExcludes = None,
|
||||
|
||||
//
|
||||
// Subtree facts
|
||||
//
|
||||
NewTarget = 1 << 14, // Contains a 'new.target' meta-property
|
||||
NewTargetInComputedPropertyName = 1 << 15, // Contains a 'new.target' meta-property in a computed property name.
|
||||
|
||||
NewTarget = 1 << 13, // Contains a 'new.target' meta-property
|
||||
CapturedLexicalThis = 1 << 14, // Contains a lexical `this` reference captured by an arrow function.
|
||||
|
||||
//
|
||||
// Subtree masks
|
||||
//
|
||||
|
||||
SubtreeFactsMask = ~AncestorFactsMask,
|
||||
PropagateNewTargetMask = NewTarget | NewTargetInComputedPropertyName,
|
||||
|
||||
ArrowFunctionSubtreeExcludes = None,
|
||||
FunctionSubtreeExcludes = NewTarget | CapturedLexicalThis,
|
||||
}
|
||||
|
||||
export function transformES2015(context: TransformationContext) {
|
||||
@@ -370,13 +344,6 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function functionBodyVisitor(node: Block): Block {
|
||||
if (shouldVisitNode(node)) {
|
||||
return visitBlock(node, /*isFunctionBody*/ true);
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
function callExpressionVisitor(node: Node): VisitResult<Node> {
|
||||
if (node.kind === SyntaxKind.SuperKeyword) {
|
||||
return visitSuperKeyword(/*isExpressionOfCall*/ true);
|
||||
@@ -528,22 +495,23 @@ namespace ts {
|
||||
|
||||
function visitSourceFile(node: SourceFile): SourceFile {
|
||||
const ancestorFacts = enterSubtree(HierarchyFacts.SourceFileExcludes, HierarchyFacts.SourceFileIncludes);
|
||||
const prologue: Statement[] = [];
|
||||
const statements: Statement[] = [];
|
||||
startLexicalEnvironment();
|
||||
let statementOffset: number | undefined = addStandardPrologue(statements, node.statements, /*ensureUseStrict*/ false);
|
||||
addCaptureThisForNodeIfNeeded(statements, node);
|
||||
statementOffset = addCustomPrologue(statements, node.statements, statementOffset, visitor);
|
||||
let statementOffset = addStandardPrologue(prologue, node.statements, /*ensureUseStrict*/ false);
|
||||
statementOffset = addCustomPrologue(prologue, node.statements, statementOffset, visitor);
|
||||
addRange(statements, visitNodes(node.statements, visitor, isStatement, statementOffset));
|
||||
if (taggedTemplateStringDeclarations) {
|
||||
statements.push(
|
||||
createVariableStatement(/*modifiers*/ undefined,
|
||||
createVariableDeclarationList(taggedTemplateStringDeclarations)));
|
||||
}
|
||||
addStatementsAfterPrologue(statements, endLexicalEnvironment());
|
||||
mergeLexicalEnvironment(prologue, endLexicalEnvironment());
|
||||
insertCaptureThisForNodeIfNeeded(prologue, node);
|
||||
exitSubtree(ancestorFacts, HierarchyFacts.None, HierarchyFacts.None);
|
||||
return updateSourceFileNode(
|
||||
node,
|
||||
setTextRange(createNodeArray(statements), node.statements)
|
||||
setTextRange(createNodeArray(concatenate(prologue, statements)), node.statements)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -596,6 +564,9 @@ namespace ts {
|
||||
}
|
||||
|
||||
function visitThisKeyword(node: Node): Node {
|
||||
if (hierarchyFacts & HierarchyFacts.ArrowFunction) {
|
||||
hierarchyFacts |= HierarchyFacts.CapturedLexicalThis;
|
||||
}
|
||||
if (convertedLoopState) {
|
||||
if (hierarchyFacts & HierarchyFacts.ArrowFunction) {
|
||||
// if the enclosing function is an ArrowFunction then we use the captured 'this' keyword.
|
||||
@@ -847,7 +818,7 @@ namespace ts {
|
||||
setEmitFlags(statement, EmitFlags.NoComments | EmitFlags.NoTokenSourceMaps);
|
||||
statements.push(statement);
|
||||
|
||||
addStatementsAfterPrologue(statements, endLexicalEnvironment());
|
||||
insertStatementsAfterStandardPrologue(statements, endLexicalEnvironment());
|
||||
|
||||
const block = createBlock(setTextRange(createNodeArray(statements), /*location*/ node.members), /*multiLine*/ true);
|
||||
setEmitFlags(block, EmitFlags.NoComments);
|
||||
@@ -904,7 +875,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
statements.push(constructorFunction);
|
||||
exitSubtree(ancestorFacts, HierarchyFacts.PropagateNewTargetMask, HierarchyFacts.None);
|
||||
exitSubtree(ancestorFacts, HierarchyFacts.FunctionSubtreeExcludes, HierarchyFacts.None);
|
||||
convertedLoopState = savedConvertedLoopState;
|
||||
}
|
||||
|
||||
@@ -925,6 +896,28 @@ namespace ts {
|
||||
|| <ParameterDeclaration[]>[];
|
||||
}
|
||||
|
||||
function createDefaultConstructorBody(node: ClassDeclaration | ClassExpression, isDerivedClass: boolean) {
|
||||
// We must be here because the user didn't write a constructor
|
||||
// but we needed to call 'super(...args)' anyway as per 14.5.14 of the ES2016 spec.
|
||||
// If that's the case we can just immediately return the result of a 'super()' call.
|
||||
const statements: Statement[] = [];
|
||||
resumeLexicalEnvironment();
|
||||
mergeLexicalEnvironment(statements, endLexicalEnvironment());
|
||||
|
||||
if (isDerivedClass) {
|
||||
// return _super !== null && _super.apply(this, arguments) || this;
|
||||
statements.push(createReturn(createDefaultSuperCallOrThis()));
|
||||
}
|
||||
|
||||
const statementsArray = createNodeArray(statements);
|
||||
setTextRange(statementsArray, node.members);
|
||||
|
||||
const block = createBlock(statementsArray, /*multiLine*/ true);
|
||||
setTextRange(block, node);
|
||||
setEmitFlags(block, EmitFlags.NoComments);
|
||||
return block;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms the body of a constructor declaration of a class.
|
||||
*
|
||||
@@ -934,82 +927,153 @@ namespace ts {
|
||||
* @param hasSynthesizedSuper A value indicating whether the constructor starts with a
|
||||
* synthesized `super` call.
|
||||
*/
|
||||
function transformConstructorBody(constructor: ConstructorDeclaration | undefined, node: ClassDeclaration | ClassExpression, extendsClauseElement: ExpressionWithTypeArguments | undefined, hasSynthesizedSuper: boolean) {
|
||||
const statements: Statement[] = [];
|
||||
resumeLexicalEnvironment();
|
||||
|
||||
let statementOffset = -1;
|
||||
if (hasSynthesizedSuper) {
|
||||
// If a super call has already been synthesized,
|
||||
// we're going to assume that we should just transform everything after that.
|
||||
// The assumption is that no prior step in the pipeline has added any prologue directives.
|
||||
statementOffset = 0;
|
||||
}
|
||||
else if (constructor) {
|
||||
statementOffset = addStandardPrologue(statements, constructor.body!.statements, /*ensureUseStrict*/ false);
|
||||
}
|
||||
|
||||
if (constructor) {
|
||||
addDefaultValueAssignmentsIfNeeded(statements, constructor);
|
||||
addRestParameterIfNeeded(statements, constructor, hasSynthesizedSuper);
|
||||
if (!hasSynthesizedSuper) {
|
||||
// If no super call has been synthesized, emit custom prologue directives.
|
||||
statementOffset = addCustomPrologue(statements, constructor.body!.statements, statementOffset, visitor);
|
||||
}
|
||||
Debug.assert(statementOffset >= 0, "statementOffset not initialized correctly!");
|
||||
|
||||
}
|
||||
|
||||
function transformConstructorBody(constructor: ConstructorDeclaration & { body: FunctionBody } | undefined, node: ClassDeclaration | ClassExpression, extendsClauseElement: ExpressionWithTypeArguments | undefined, hasSynthesizedSuper: boolean) {
|
||||
// determine whether the class is known syntactically to be a derived class (e.g. a
|
||||
// class that extends a value that is not syntactically known to be `null`).
|
||||
const isDerivedClass = !!extendsClauseElement && skipOuterExpressions(extendsClauseElement.expression).kind !== SyntaxKind.NullKeyword;
|
||||
const superCaptureStatus = declareOrCaptureOrReturnThisForConstructorIfNeeded(statements, constructor, isDerivedClass, hasSynthesizedSuper, statementOffset);
|
||||
|
||||
// The last statement expression was replaced. Skip it.
|
||||
if (superCaptureStatus === SuperCaptureResult.ReplaceSuperCapture || superCaptureStatus === SuperCaptureResult.ReplaceWithReturn) {
|
||||
statementOffset++;
|
||||
// When the subclass does not have a constructor, we synthesize a *default* constructor using the following
|
||||
// representation:
|
||||
//
|
||||
// ```
|
||||
// // es2015 (source)
|
||||
// class C extends Base { }
|
||||
//
|
||||
// // es5 (transformed)
|
||||
// var C = (function (_super) {
|
||||
// function C() {
|
||||
// return _super.apply(this, arguments) || this;
|
||||
// }
|
||||
// return C;
|
||||
// })(Base);
|
||||
// ```
|
||||
if (!constructor) return createDefaultConstructorBody(node, isDerivedClass);
|
||||
|
||||
// The prologue will contain all leading standard and custom prologue statements added by this transform
|
||||
const prologue: Statement[] = [];
|
||||
const statements: Statement[] = [];
|
||||
resumeLexicalEnvironment();
|
||||
|
||||
// If a super call has already been synthesized,
|
||||
// we're going to assume that we should just transform everything after that.
|
||||
// The assumption is that no prior step in the pipeline has added any prologue directives.
|
||||
let statementOffset = 0;
|
||||
if (!hasSynthesizedSuper) statementOffset = addStandardPrologue(prologue, constructor.body.statements, /*ensureUseStrict*/ false);
|
||||
addDefaultValueAssignmentsIfNeeded(statements, constructor);
|
||||
addRestParameterIfNeeded(statements, constructor, hasSynthesizedSuper);
|
||||
if (!hasSynthesizedSuper) statementOffset = addCustomPrologue(statements, constructor.body.statements, statementOffset, visitor);
|
||||
|
||||
// If the first statement is a call to `super()`, visit the statement directly
|
||||
let superCallExpression: Expression | undefined;
|
||||
if (hasSynthesizedSuper) {
|
||||
superCallExpression = createDefaultSuperCallOrThis();
|
||||
}
|
||||
|
||||
if (constructor) {
|
||||
if (superCaptureStatus === SuperCaptureResult.ReplaceSuperCapture) {
|
||||
hierarchyFacts |= HierarchyFacts.ConstructorWithCapturedSuper;
|
||||
else if (isDerivedClass && statementOffset < constructor.body.statements.length) {
|
||||
const firstStatement = constructor.body.statements[statementOffset];
|
||||
if (isExpressionStatement(firstStatement) && isSuperCall(firstStatement.expression)) {
|
||||
superCallExpression = visitImmediateSuperCallInBody(firstStatement.expression);
|
||||
}
|
||||
|
||||
addRange(statements, visitNodes(constructor.body!.statements, visitor, isStatement, /*start*/ statementOffset));
|
||||
}
|
||||
|
||||
// Return `_this` unless we're sure enough that it would be pointless to add a return statement.
|
||||
// If there's a constructor that we can tell returns in enough places, then we *do not* want to add a return.
|
||||
if (isDerivedClass
|
||||
&& superCaptureStatus !== SuperCaptureResult.ReplaceWithReturn
|
||||
&& !(constructor && isSufficientlyCoveredByReturnStatements(constructor.body!))) {
|
||||
statements.push(
|
||||
createReturn(
|
||||
createFileLevelUniqueName("_this")
|
||||
)
|
||||
);
|
||||
if (superCallExpression) {
|
||||
hierarchyFacts |= HierarchyFacts.ConstructorWithCapturedSuper;
|
||||
statementOffset++; // skip this statement, we will add it after visiting the rest of the body.
|
||||
}
|
||||
|
||||
addStatementsAfterPrologue(statements, endLexicalEnvironment());
|
||||
// visit the remaining statements
|
||||
addRange(statements, visitNodes(constructor.body.statements, visitor, isStatement, /*start*/ statementOffset));
|
||||
|
||||
if (constructor) {
|
||||
prependCaptureNewTargetIfNeeded(statements, constructor, /*copyOnWrite*/ false);
|
||||
mergeLexicalEnvironment(prologue, endLexicalEnvironment());
|
||||
insertCaptureNewTargetIfNeeded(prologue, constructor, /*copyOnWrite*/ false);
|
||||
|
||||
if (isDerivedClass) {
|
||||
if (superCallExpression && statementOffset === constructor.body.statements.length && !(constructor.body.transformFlags & TransformFlags.ContainsLexicalThis)) {
|
||||
// If the subclass constructor does *not* contain `this` and *ends* with a `super()` call, we will use the
|
||||
// following representation:
|
||||
//
|
||||
// ```
|
||||
// // es2015 (source)
|
||||
// class C extends Base {
|
||||
// constructor() {
|
||||
// super("foo");
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // es5 (transformed)
|
||||
// var C = (function (_super) {
|
||||
// function C() {
|
||||
// return _super.call(this, "foo") || this;
|
||||
// }
|
||||
// return C;
|
||||
// })(Base);
|
||||
// ```
|
||||
const superCall = cast(cast(superCallExpression, isBinaryExpression).left, isCallExpression);
|
||||
const returnStatement = createReturn(superCallExpression);
|
||||
setCommentRange(returnStatement, getCommentRange(superCall));
|
||||
setEmitFlags(superCall, EmitFlags.NoComments);
|
||||
statements.push(returnStatement);
|
||||
}
|
||||
else {
|
||||
// Otherwise, we will use the following transformed representation for calls to `super()` in a constructor:
|
||||
//
|
||||
// ```
|
||||
// // es2015 (source)
|
||||
// class C extends Base {
|
||||
// constructor() {
|
||||
// super("foo");
|
||||
// this.x = 1;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // es5 (transformed)
|
||||
// var C = (function (_super) {
|
||||
// function C() {
|
||||
// var _this = _super.call(this, "foo") || this;
|
||||
// _this.x = 1;
|
||||
// return _this;
|
||||
// }
|
||||
// return C;
|
||||
// })(Base);
|
||||
// ```
|
||||
|
||||
// Since the `super()` call was the first statement, we insert the `this` capturing call to
|
||||
// `super()` at the top of the list of `statements` (after any pre-existing custom prologues).
|
||||
insertCaptureThisForNode(statements, constructor, superCallExpression || createActualThis());
|
||||
|
||||
if (!isSufficientlyCoveredByReturnStatements(constructor.body)) {
|
||||
statements.push(createReturn(createFileLevelUniqueName("_this")));
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// If a class is not derived from a base class or does not have a call to `super()`, `this` is only
|
||||
// captured when necessitated by an arrow function capturing the lexical `this`:
|
||||
//
|
||||
// ```
|
||||
// // es2015
|
||||
// class C {}
|
||||
//
|
||||
// // es5
|
||||
// var C = (function () {
|
||||
// function C() {
|
||||
// }
|
||||
// return C;
|
||||
// })();
|
||||
// ```
|
||||
insertCaptureThisForNodeIfNeeded(prologue, constructor);
|
||||
}
|
||||
|
||||
const block = createBlock(
|
||||
setTextRange(
|
||||
createNodeArray(
|
||||
statements
|
||||
concatenate(prologue, statements)
|
||||
),
|
||||
/*location*/ constructor ? constructor.body!.statements : node.members
|
||||
/*location*/ constructor.body.statements
|
||||
),
|
||||
/*multiLine*/ true
|
||||
);
|
||||
|
||||
setTextRange(block, constructor ? constructor.body : node);
|
||||
if (!constructor) {
|
||||
setEmitFlags(block, EmitFlags.NoComments);
|
||||
}
|
||||
setTextRange(block, constructor.body);
|
||||
|
||||
return block;
|
||||
}
|
||||
@@ -1043,104 +1107,6 @@ namespace ts {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Declares a `_this` variable for derived classes and for when arrow functions capture `this`.
|
||||
*
|
||||
* @returns The new statement offset into the `statements` array.
|
||||
*/
|
||||
function declareOrCaptureOrReturnThisForConstructorIfNeeded(
|
||||
statements: Statement[],
|
||||
ctor: ConstructorDeclaration | undefined,
|
||||
isDerivedClass: boolean,
|
||||
hasSynthesizedSuper: boolean,
|
||||
statementOffset: number) {
|
||||
// If this isn't a derived class, just capture 'this' for arrow functions if necessary.
|
||||
if (!isDerivedClass) {
|
||||
if (ctor) {
|
||||
addCaptureThisForNodeIfNeeded(statements, ctor);
|
||||
}
|
||||
return SuperCaptureResult.NoReplacement;
|
||||
}
|
||||
|
||||
// We must be here because the user didn't write a constructor
|
||||
// but we needed to call 'super(...args)' anyway as per 14.5.14 of the ES2016 spec.
|
||||
// If that's the case we can just immediately return the result of a 'super()' call.
|
||||
if (!ctor) {
|
||||
statements.push(createReturn(createDefaultSuperCallOrThis()));
|
||||
return SuperCaptureResult.ReplaceWithReturn;
|
||||
}
|
||||
|
||||
// The constructor exists, but it and the 'super()' call it contains were generated
|
||||
// for something like property initializers.
|
||||
// Create a captured '_this' variable and assume it will subsequently be used.
|
||||
if (hasSynthesizedSuper) {
|
||||
captureThisForNode(statements, ctor, createDefaultSuperCallOrThis());
|
||||
enableSubstitutionsForCapturedThis();
|
||||
return SuperCaptureResult.ReplaceSuperCapture;
|
||||
}
|
||||
|
||||
// Most of the time, a 'super' call will be the first real statement in a constructor body.
|
||||
// In these cases, we'd like to transform these into a *single* statement instead of a declaration
|
||||
// followed by an assignment statement for '_this'. For instance, if we emitted without an initializer,
|
||||
// we'd get:
|
||||
//
|
||||
// var _this;
|
||||
// _this = _super.call(...) || this;
|
||||
//
|
||||
// instead of
|
||||
//
|
||||
// var _this = _super.call(...) || this;
|
||||
//
|
||||
// Additionally, if the 'super()' call is the last statement, we should just avoid capturing
|
||||
// entirely and immediately return the result like so:
|
||||
//
|
||||
// return _super.call(...) || this;
|
||||
//
|
||||
let firstStatement: Statement | undefined;
|
||||
let superCallExpression: Expression | undefined;
|
||||
|
||||
const ctorStatements = ctor.body!.statements;
|
||||
if (statementOffset < ctorStatements.length) {
|
||||
firstStatement = ctorStatements[statementOffset];
|
||||
|
||||
if (firstStatement.kind === SyntaxKind.ExpressionStatement && isSuperCall((firstStatement as ExpressionStatement).expression)) {
|
||||
superCallExpression = visitImmediateSuperCallInBody((firstStatement as ExpressionStatement).expression as CallExpression);
|
||||
}
|
||||
}
|
||||
|
||||
// Return the result if we have an immediate super() call on the last statement,
|
||||
// but only if the constructor itself doesn't use 'this' elsewhere.
|
||||
if (superCallExpression
|
||||
&& statementOffset === ctorStatements.length - 1
|
||||
&& !(ctor.transformFlags & (TransformFlags.ContainsLexicalThis | TransformFlags.ContainsCapturedLexicalThis))) {
|
||||
const returnStatement = createReturn(superCallExpression);
|
||||
|
||||
if (superCallExpression.kind !== SyntaxKind.BinaryExpression
|
||||
|| (superCallExpression as BinaryExpression).left.kind !== SyntaxKind.CallExpression) {
|
||||
Debug.fail("Assumed generated super call would have form 'super.call(...) || this'.");
|
||||
}
|
||||
|
||||
// Shift comments from the original super call to the return statement.
|
||||
setCommentRange(returnStatement, getCommentRange(
|
||||
setEmitFlags(
|
||||
(superCallExpression as BinaryExpression).left,
|
||||
EmitFlags.NoComments)));
|
||||
|
||||
statements.push(returnStatement);
|
||||
return SuperCaptureResult.ReplaceWithReturn;
|
||||
}
|
||||
|
||||
// Perform the capture.
|
||||
captureThisForNode(statements, ctor, superCallExpression || createActualThis());
|
||||
|
||||
// If we're actually replacing the original statement, we need to signal this to the caller.
|
||||
if (superCallExpression) {
|
||||
return SuperCaptureResult.ReplaceSuperCapture;
|
||||
}
|
||||
|
||||
return SuperCaptureResult.NoReplacement;
|
||||
}
|
||||
|
||||
function createActualThis() {
|
||||
return setEmitFlags(createThis(), EmitFlags.NoSubstitution);
|
||||
}
|
||||
@@ -1214,14 +1180,9 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a value indicating whether we need to add default value assignments for a
|
||||
* function-like node.
|
||||
*
|
||||
* @param node A function-like node.
|
||||
*/
|
||||
function shouldAddDefaultValueAssignments(node: FunctionLikeDeclaration): boolean {
|
||||
return (node.transformFlags & TransformFlags.ContainsDefaultValueAssignments) !== 0;
|
||||
function hasDefaultValueOrBindingPattern(node: ParameterDeclaration) {
|
||||
return node.initializer !== undefined
|
||||
|| isBindingPattern(node.name);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1231,11 +1192,12 @@ namespace ts {
|
||||
* @param statements The statements for the new function body.
|
||||
* @param node A function-like node.
|
||||
*/
|
||||
function addDefaultValueAssignmentsIfNeeded(statements: Statement[], node: FunctionLikeDeclaration): void {
|
||||
if (!shouldAddDefaultValueAssignments(node)) {
|
||||
return;
|
||||
function addDefaultValueAssignmentsIfNeeded(statements: Statement[], node: FunctionLikeDeclaration): boolean {
|
||||
if (!some(node.parameters, hasDefaultValueOrBindingPattern)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let added = false;
|
||||
for (const parameter of node.parameters) {
|
||||
const { name, initializer, dotDotDotToken } = parameter;
|
||||
|
||||
@@ -1246,12 +1208,14 @@ namespace ts {
|
||||
}
|
||||
|
||||
if (isBindingPattern(name)) {
|
||||
addDefaultValueAssignmentForBindingPattern(statements, parameter, name, initializer);
|
||||
added = insertDefaultValueAssignmentForBindingPattern(statements, parameter, name, initializer) || added;
|
||||
}
|
||||
else if (initializer) {
|
||||
addDefaultValueAssignmentForInitializer(statements, parameter, name, initializer);
|
||||
insertDefaultValueAssignmentForInitializer(statements, parameter, name, initializer);
|
||||
added = true;
|
||||
}
|
||||
}
|
||||
return added;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1262,14 +1226,13 @@ namespace ts {
|
||||
* @param name The name of the parameter.
|
||||
* @param initializer The initializer for the parameter.
|
||||
*/
|
||||
function addDefaultValueAssignmentForBindingPattern(statements: Statement[], parameter: ParameterDeclaration, name: BindingPattern, initializer: Expression | undefined): void {
|
||||
const temp = getGeneratedNameForNode(parameter);
|
||||
|
||||
function insertDefaultValueAssignmentForBindingPattern(statements: Statement[], parameter: ParameterDeclaration, name: BindingPattern, initializer: Expression | undefined): boolean {
|
||||
// In cases where a binding pattern is simply '[]' or '{}',
|
||||
// we usually don't want to emit a var declaration; however, in the presence
|
||||
// of an initializer, we must emit that expression to preserve side effects.
|
||||
if (name.elements.length > 0) {
|
||||
statements.push(
|
||||
insertStatementAfterCustomPrologue(
|
||||
statements,
|
||||
setEmitFlags(
|
||||
createVariableStatement(
|
||||
/*modifiers*/ undefined,
|
||||
@@ -1279,27 +1242,31 @@ namespace ts {
|
||||
visitor,
|
||||
context,
|
||||
FlattenLevel.All,
|
||||
temp
|
||||
getGeneratedNameForNode(parameter)
|
||||
)
|
||||
)
|
||||
),
|
||||
EmitFlags.CustomPrologue
|
||||
)
|
||||
);
|
||||
return true;
|
||||
}
|
||||
else if (initializer) {
|
||||
statements.push(
|
||||
insertStatementAfterCustomPrologue(
|
||||
statements,
|
||||
setEmitFlags(
|
||||
createExpressionStatement(
|
||||
createAssignment(
|
||||
temp,
|
||||
getGeneratedNameForNode(parameter),
|
||||
visitNode(initializer, visitor, isExpression)
|
||||
)
|
||||
),
|
||||
EmitFlags.CustomPrologue
|
||||
)
|
||||
);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1310,7 +1277,7 @@ namespace ts {
|
||||
* @param name The name of the parameter.
|
||||
* @param initializer The initializer for the parameter.
|
||||
*/
|
||||
function addDefaultValueAssignmentForInitializer(statements: Statement[], parameter: ParameterDeclaration, name: Identifier, initializer: Expression): void {
|
||||
function insertDefaultValueAssignmentForInitializer(statements: Statement[], parameter: ParameterDeclaration, name: Identifier, initializer: Expression): void {
|
||||
initializer = visitNode(initializer, visitor, isExpression);
|
||||
const statement = createIf(
|
||||
createTypeCheck(getSynthesizedClone(name), "undefined"),
|
||||
@@ -1339,7 +1306,7 @@ namespace ts {
|
||||
startOnNewLine(statement);
|
||||
setTextRange(statement, parameter);
|
||||
setEmitFlags(statement, EmitFlags.NoTokenSourceMaps | EmitFlags.NoTrailingSourceMap | EmitFlags.CustomPrologue | EmitFlags.NoComments);
|
||||
statements.push(statement);
|
||||
insertStatementAfterCustomPrologue(statements, statement);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1363,10 +1330,11 @@ namespace ts {
|
||||
* part of a constructor declaration with a
|
||||
* synthesized call to `super`
|
||||
*/
|
||||
function addRestParameterIfNeeded(statements: Statement[], node: FunctionLikeDeclaration, inConstructorWithSynthesizedSuper: boolean): void {
|
||||
function addRestParameterIfNeeded(statements: Statement[], node: FunctionLikeDeclaration, inConstructorWithSynthesizedSuper: boolean): boolean {
|
||||
const prologueStatements: Statement[] = [];
|
||||
const parameter = lastOrUndefined(node.parameters);
|
||||
if (!shouldAddRestParameter(parameter, inConstructorWithSynthesizedSuper)) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
// `declarationName` is the name of the local declaration for the parameter.
|
||||
@@ -1379,7 +1347,7 @@ namespace ts {
|
||||
const temp = createLoopVariable();
|
||||
|
||||
// var param = [];
|
||||
statements.push(
|
||||
prologueStatements.push(
|
||||
setEmitFlags(
|
||||
setTextRange(
|
||||
createVariableStatement(
|
||||
@@ -1438,11 +1406,11 @@ namespace ts {
|
||||
|
||||
setEmitFlags(forStatement, EmitFlags.CustomPrologue);
|
||||
startOnNewLine(forStatement);
|
||||
statements.push(forStatement);
|
||||
prologueStatements.push(forStatement);
|
||||
|
||||
if (parameter.name.kind !== SyntaxKind.Identifier) {
|
||||
// do the actual destructuring of the rest parameter if necessary
|
||||
statements.push(
|
||||
prologueStatements.push(
|
||||
setEmitFlags(
|
||||
setTextRange(
|
||||
createVariableStatement(
|
||||
@@ -1457,21 +1425,27 @@ namespace ts {
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
insertStatementsAfterCustomPrologue(statements, prologueStatements);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a statement to capture the `this` of a function declaration if it is needed.
|
||||
* NOTE: This must be executed *after* the subtree has been visited.
|
||||
*
|
||||
* @param statements The statements for the new function body.
|
||||
* @param node A node.
|
||||
*/
|
||||
function addCaptureThisForNodeIfNeeded(statements: Statement[], node: Node): void {
|
||||
if (node.transformFlags & TransformFlags.ContainsCapturedLexicalThis && node.kind !== SyntaxKind.ArrowFunction) {
|
||||
captureThisForNode(statements, node, createThis());
|
||||
function insertCaptureThisForNodeIfNeeded(statements: Statement[], node: Node): boolean {
|
||||
if (hierarchyFacts & HierarchyFacts.CapturedLexicalThis && node.kind !== SyntaxKind.ArrowFunction) {
|
||||
insertCaptureThisForNode(statements, node, createThis());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function captureThisForNode(statements: Statement[], node: Node, initializer: Expression | undefined): void {
|
||||
function insertCaptureThisForNode(statements: Statement[], node: Node, initializer: Expression | undefined): void {
|
||||
enableSubstitutionsForCapturedThis();
|
||||
const captureThisStatement = createVariableStatement(
|
||||
/*modifiers*/ undefined,
|
||||
@@ -1485,10 +1459,10 @@ namespace ts {
|
||||
);
|
||||
setEmitFlags(captureThisStatement, EmitFlags.NoComments | EmitFlags.CustomPrologue);
|
||||
setSourceMapRange(captureThisStatement, node);
|
||||
statements.push(captureThisStatement);
|
||||
insertStatementAfterCustomPrologue(statements, captureThisStatement);
|
||||
}
|
||||
|
||||
function prependCaptureNewTargetIfNeeded(statements: Statement[], node: FunctionLikeDeclaration, copyOnWrite: boolean): Statement[] {
|
||||
function insertCaptureNewTargetIfNeeded(statements: Statement[], node: FunctionLikeDeclaration, copyOnWrite: boolean): Statement[] {
|
||||
if (hierarchyFacts & HierarchyFacts.NewTarget) {
|
||||
let newTarget: Expression;
|
||||
switch (node.kind) {
|
||||
@@ -1548,11 +1522,13 @@ namespace ts {
|
||||
])
|
||||
);
|
||||
|
||||
setEmitFlags(captureNewTargetStatement, EmitFlags.NoComments | EmitFlags.CustomPrologue);
|
||||
|
||||
if (copyOnWrite) {
|
||||
return [captureNewTargetStatement, ...statements];
|
||||
statements = statements.slice();
|
||||
}
|
||||
|
||||
statements.unshift(captureNewTargetStatement);
|
||||
insertStatementAfterCustomPrologue(statements, captureNewTargetStatement);
|
||||
}
|
||||
|
||||
return statements;
|
||||
@@ -1612,7 +1588,6 @@ namespace ts {
|
||||
* @param member The MethodDeclaration node.
|
||||
*/
|
||||
function transformClassMethodDeclarationToStatement(receiver: LeftHandSideExpression, member: MethodDeclaration, container: Node) {
|
||||
const ancestorFacts = enterSubtree(HierarchyFacts.None, HierarchyFacts.None);
|
||||
const commentRange = getCommentRange(member);
|
||||
const sourceMapRange = getSourceMapRange(member);
|
||||
const memberName = createMemberAccessForPropertyName(receiver, visitNode(member.name, visitor, isPropertyName), /*location*/ member.name);
|
||||
@@ -1634,8 +1609,6 @@ namespace ts {
|
||||
// No source map should be emitted for this statement to align with the
|
||||
// old emitter.
|
||||
setEmitFlags(statement, EmitFlags.NoSourceMap);
|
||||
|
||||
exitSubtree(ancestorFacts, HierarchyFacts.PropagateNewTargetMask, hierarchyFacts & HierarchyFacts.PropagateNewTargetMask ? HierarchyFacts.NewTarget : HierarchyFacts.None);
|
||||
return statement;
|
||||
}
|
||||
|
||||
@@ -1662,8 +1635,6 @@ namespace ts {
|
||||
* @param receiver The receiver for the member.
|
||||
*/
|
||||
function transformAccessorsToExpression(receiver: LeftHandSideExpression, { firstAccessor, getAccessor, setAccessor }: AllAccessorDeclarations, container: Node, startsOnNewLine: boolean): Expression {
|
||||
const ancestorFacts = enterSubtree(HierarchyFacts.None, HierarchyFacts.None);
|
||||
|
||||
// To align with source maps in the old emitter, the receiver and property name
|
||||
// arguments are both mapped contiguously to the accessor name.
|
||||
const target = getMutableClone(receiver);
|
||||
@@ -1711,7 +1682,6 @@ namespace ts {
|
||||
startOnNewLine(call);
|
||||
}
|
||||
|
||||
exitSubtree(ancestorFacts, HierarchyFacts.PropagateNewTargetMask, hierarchyFacts & HierarchyFacts.PropagateNewTargetMask ? HierarchyFacts.NewTarget : HierarchyFacts.None);
|
||||
return call;
|
||||
}
|
||||
|
||||
@@ -1722,8 +1692,9 @@ namespace ts {
|
||||
*/
|
||||
function visitArrowFunction(node: ArrowFunction) {
|
||||
if (node.transformFlags & TransformFlags.ContainsLexicalThis) {
|
||||
enableSubstitutionsForCapturedThis();
|
||||
hierarchyFacts |= HierarchyFacts.CapturedLexicalThis;
|
||||
}
|
||||
|
||||
const savedConvertedLoopState = convertedLoopState;
|
||||
convertedLoopState = undefined;
|
||||
const ancestorFacts = enterSubtree(HierarchyFacts.ArrowFunctionExcludes, HierarchyFacts.ArrowFunctionIncludes);
|
||||
@@ -1739,7 +1710,14 @@ namespace ts {
|
||||
setTextRange(func, node);
|
||||
setOriginalNode(func, node);
|
||||
setEmitFlags(func, EmitFlags.CapturesThis);
|
||||
exitSubtree(ancestorFacts, HierarchyFacts.None, HierarchyFacts.None);
|
||||
|
||||
if (hierarchyFacts & HierarchyFacts.CapturedLexicalThis) {
|
||||
enableSubstitutionsForCapturedThis();
|
||||
}
|
||||
|
||||
// If an arrow function contains
|
||||
exitSubtree(ancestorFacts, HierarchyFacts.ArrowFunctionSubtreeExcludes, HierarchyFacts.None);
|
||||
|
||||
convertedLoopState = savedConvertedLoopState;
|
||||
return func;
|
||||
}
|
||||
@@ -1757,14 +1735,12 @@ namespace ts {
|
||||
convertedLoopState = undefined;
|
||||
|
||||
const parameters = visitParameterList(node.parameters, visitor, context);
|
||||
const body = node.transformFlags & TransformFlags.ES2015
|
||||
? transformFunctionBody(node)
|
||||
: visitFunctionBodyDownLevel(node);
|
||||
const body = transformFunctionBody(node);
|
||||
const name = hierarchyFacts & HierarchyFacts.NewTarget
|
||||
? getLocalName(node)
|
||||
: node.name;
|
||||
|
||||
exitSubtree(ancestorFacts, HierarchyFacts.PropagateNewTargetMask, HierarchyFacts.None);
|
||||
exitSubtree(ancestorFacts, HierarchyFacts.FunctionSubtreeExcludes, HierarchyFacts.None);
|
||||
convertedLoopState = savedConvertedLoopState;
|
||||
return updateFunctionExpression(
|
||||
node,
|
||||
@@ -1788,14 +1764,12 @@ namespace ts {
|
||||
convertedLoopState = undefined;
|
||||
const ancestorFacts = enterSubtree(HierarchyFacts.FunctionExcludes, HierarchyFacts.FunctionIncludes);
|
||||
const parameters = visitParameterList(node.parameters, visitor, context);
|
||||
const body = node.transformFlags & TransformFlags.ES2015
|
||||
? transformFunctionBody(node)
|
||||
: visitFunctionBodyDownLevel(node);
|
||||
const body = transformFunctionBody(node);
|
||||
const name = hierarchyFacts & HierarchyFacts.NewTarget
|
||||
? getLocalName(node)
|
||||
: node.name;
|
||||
|
||||
exitSubtree(ancestorFacts, HierarchyFacts.PropagateNewTargetMask, HierarchyFacts.None);
|
||||
exitSubtree(ancestorFacts, HierarchyFacts.FunctionSubtreeExcludes, HierarchyFacts.None);
|
||||
convertedLoopState = savedConvertedLoopState;
|
||||
return updateFunctionDeclaration(
|
||||
node,
|
||||
@@ -1829,7 +1803,7 @@ namespace ts {
|
||||
name = getGeneratedNameForNode(node);
|
||||
}
|
||||
|
||||
exitSubtree(ancestorFacts, HierarchyFacts.PropagateNewTargetMask, HierarchyFacts.None);
|
||||
exitSubtree(ancestorFacts, HierarchyFacts.FunctionSubtreeExcludes, HierarchyFacts.None);
|
||||
convertedLoopState = savedConvertedLoopState;
|
||||
return setOriginalNode(
|
||||
setTextRange(
|
||||
@@ -1859,7 +1833,7 @@ namespace ts {
|
||||
let statementsLocation: TextRange;
|
||||
let closeBraceLocation: TextRange | undefined;
|
||||
|
||||
const leadingStatements: Statement[] = [];
|
||||
const prologue: Statement[] = [];
|
||||
const statements: Statement[] = [];
|
||||
const body = node.body!;
|
||||
let statementOffset: number | undefined;
|
||||
@@ -1868,16 +1842,15 @@ namespace ts {
|
||||
if (isBlock(body)) {
|
||||
// ensureUseStrict is false because no new prologue-directive should be added.
|
||||
// addStandardPrologue will put already-existing directives at the beginning of the target statement-array
|
||||
statementOffset = addStandardPrologue(leadingStatements, body.statements, /*ensureUseStrict*/ false);
|
||||
statementOffset = addStandardPrologue(prologue, body.statements, /*ensureUseStrict*/ false);
|
||||
}
|
||||
|
||||
addCaptureThisForNodeIfNeeded(leadingStatements, node);
|
||||
addDefaultValueAssignmentsIfNeeded(leadingStatements, node);
|
||||
addRestParameterIfNeeded(leadingStatements, node, /*inConstructorWithSynthesizedSuper*/ false);
|
||||
multiLine = addDefaultValueAssignmentsIfNeeded(statements, node) || multiLine;
|
||||
multiLine = addRestParameterIfNeeded(statements, node, /*inConstructorWithSynthesizedSuper*/ false) || multiLine;
|
||||
|
||||
if (isBlock(body)) {
|
||||
// addCustomPrologue puts already-existing directives at the beginning of the target statement-array
|
||||
statementOffset = addCustomPrologue(leadingStatements, body.statements, statementOffset, visitor);
|
||||
statementOffset = addCustomPrologue(statements, body.statements, statementOffset, visitor);
|
||||
|
||||
statementsLocation = body.statements;
|
||||
addRange(statements, visitNodes(body.statements, visitor, isStatement, statementOffset));
|
||||
@@ -1918,16 +1891,22 @@ namespace ts {
|
||||
closeBraceLocation = body;
|
||||
}
|
||||
|
||||
const lexicalEnvironment = context.endLexicalEnvironment();
|
||||
addStatementsAfterPrologue(statements, lexicalEnvironment);
|
||||
prependCaptureNewTargetIfNeeded(statements, node, /*copyOnWrite*/ false);
|
||||
mergeLexicalEnvironment(prologue, endLexicalEnvironment());
|
||||
insertCaptureNewTargetIfNeeded(prologue, node, /*copyOnWrite*/ false);
|
||||
insertCaptureThisForNodeIfNeeded(prologue, node);
|
||||
|
||||
// If we added any final generated statements, this must be a multi-line block
|
||||
if (some(leadingStatements) || some(lexicalEnvironment)) {
|
||||
if (some(prologue)) {
|
||||
multiLine = true;
|
||||
}
|
||||
|
||||
const block = createBlock(setTextRange(createNodeArray([...leadingStatements, ...statements]), statementsLocation), multiLine);
|
||||
statements.unshift(...prologue);
|
||||
if (isBlock(body) && arrayIsEqualTo(statements, body.statements)) {
|
||||
// no changes were made, preserve the tree
|
||||
return body;
|
||||
}
|
||||
|
||||
const block = createBlock(setTextRange(createNodeArray(statements), statementsLocation), multiLine);
|
||||
setTextRange(block, node.body);
|
||||
if (!multiLine && singleLine) {
|
||||
setEmitFlags(block, EmitFlags.SingleLine);
|
||||
@@ -1941,19 +1920,6 @@ namespace ts {
|
||||
return block;
|
||||
}
|
||||
|
||||
function visitFunctionBodyDownLevel(node: FunctionDeclaration | FunctionExpression | AccessorDeclaration) {
|
||||
const updated = visitFunctionBody(node.body, functionBodyVisitor, context)!;
|
||||
return updateBlock(
|
||||
updated,
|
||||
setTextRange(
|
||||
createNodeArray(
|
||||
prependCaptureNewTargetIfNeeded(updated.statements as MutableNodeArray<Statement>, node, /*copyOnWrite*/ true)
|
||||
),
|
||||
/*location*/ updated.statements
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function visitBlock(node: Block, isFunctionBody: boolean): Block {
|
||||
if (isFunctionBody) {
|
||||
// A function body is not a block scope.
|
||||
@@ -2074,7 +2040,7 @@ namespace ts {
|
||||
* @param node A VariableDeclarationList node.
|
||||
*/
|
||||
function visitVariableDeclarationList(node: VariableDeclarationList): VariableDeclarationList {
|
||||
if (node.transformFlags & TransformFlags.ES2015) {
|
||||
if (node.flags & NodeFlags.BlockScoped || node.transformFlags & TransformFlags.ContainsBindingPattern) {
|
||||
if (node.flags & NodeFlags.BlockScoped) {
|
||||
enableSubstitutionsForBlockScopedBindings();
|
||||
}
|
||||
@@ -3104,7 +3070,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
copyOutParameters(currentState.loopOutParameters, LoopOutParameterFlags.Body, CopyDirection.ToOutParameter, statements);
|
||||
addStatementsAfterPrologue(statements, lexicalEnvironment);
|
||||
insertStatementsAfterStandardPrologue(statements, lexicalEnvironment);
|
||||
|
||||
const loopBody = createBlock(statements, /*multiLine*/ true);
|
||||
if (isBlock(statement)) setOriginalNode(loopBody, statement);
|
||||
@@ -3426,7 +3392,6 @@ namespace ts {
|
||||
* @param receiver The receiver for the assignment.
|
||||
*/
|
||||
function transformObjectLiteralMethodDeclarationToExpression(method: MethodDeclaration, receiver: Expression, container: Node, startsOnNewLine: boolean) {
|
||||
const ancestorFacts = enterSubtree(HierarchyFacts.None, HierarchyFacts.None);
|
||||
const expression = createAssignment(
|
||||
createMemberAccessForPropertyName(
|
||||
receiver,
|
||||
@@ -3438,7 +3403,6 @@ namespace ts {
|
||||
if (startsOnNewLine) {
|
||||
startOnNewLine(expression);
|
||||
}
|
||||
exitSubtree(ancestorFacts, HierarchyFacts.PropagateNewTargetMask, hierarchyFacts & HierarchyFacts.PropagateNewTargetMask ? HierarchyFacts.NewTarget : HierarchyFacts.None);
|
||||
return expression;
|
||||
}
|
||||
|
||||
@@ -3509,16 +3473,14 @@ namespace ts {
|
||||
const ancestorFacts = enterSubtree(HierarchyFacts.FunctionExcludes, HierarchyFacts.FunctionIncludes);
|
||||
let updated: AccessorDeclaration;
|
||||
const parameters = visitParameterList(node.parameters, visitor, context);
|
||||
const body = node.transformFlags & (TransformFlags.ContainsCapturedLexicalThis | TransformFlags.ContainsES2015)
|
||||
? transformFunctionBody(node)
|
||||
: visitFunctionBodyDownLevel(node);
|
||||
const body = transformFunctionBody(node);
|
||||
if (node.kind === SyntaxKind.GetAccessor) {
|
||||
updated = updateGetAccessor(node, node.decorators, node.modifiers, node.name, parameters, node.type, body);
|
||||
}
|
||||
else {
|
||||
updated = updateSetAccessor(node, node.decorators, node.modifiers, node.name, parameters, body);
|
||||
}
|
||||
exitSubtree(ancestorFacts, HierarchyFacts.PropagateNewTargetMask, HierarchyFacts.None);
|
||||
exitSubtree(ancestorFacts, HierarchyFacts.FunctionSubtreeExcludes, HierarchyFacts.None);
|
||||
convertedLoopState = savedConvertedLoopState;
|
||||
return updated;
|
||||
}
|
||||
@@ -3539,10 +3501,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function visitComputedPropertyName(node: ComputedPropertyName) {
|
||||
const ancestorFacts = enterSubtree(HierarchyFacts.ComputedPropertyNameExcludes, HierarchyFacts.ComputedPropertyNameIncludes);
|
||||
const updated = visitEachChild(node, visitor, context);
|
||||
exitSubtree(ancestorFacts, HierarchyFacts.PropagateNewTargetMask, hierarchyFacts & HierarchyFacts.PropagateNewTargetMask ? HierarchyFacts.NewTargetInComputedPropertyName : HierarchyFacts.None);
|
||||
return updated;
|
||||
return visitEachChild(node, visitor, context);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3561,7 +3520,7 @@ namespace ts {
|
||||
* @param node An ArrayLiteralExpression node.
|
||||
*/
|
||||
function visitArrayLiteralExpression(node: ArrayLiteralExpression): Expression {
|
||||
if (node.transformFlags & TransformFlags.ES2015) {
|
||||
if (some(node.elements, isSpreadElement)) {
|
||||
// We are here because we contain a SpreadElementExpression.
|
||||
return transformAndSpreadElements(node.elements, /*needsUniqueCopy*/ true, !!node.multiLine, /*hasTrailingComma*/ !!node.elements.hasTrailingComma);
|
||||
}
|
||||
@@ -3578,7 +3537,10 @@ namespace ts {
|
||||
return visitTypeScriptClassWrapper(node);
|
||||
}
|
||||
|
||||
if (node.transformFlags & TransformFlags.ES2015) {
|
||||
const expression = skipOuterExpressions(node.expression);
|
||||
if (expression.kind === SyntaxKind.SuperKeyword ||
|
||||
isSuperProperty(expression) ||
|
||||
some(node.arguments, isSpreadElement)) {
|
||||
return visitCallExpressionWithPotentialCapturedThisAssignment(node, /*assignToCapturedThis*/ true);
|
||||
}
|
||||
|
||||
@@ -3774,7 +3736,7 @@ namespace ts {
|
||||
|
||||
resultingCall = createFunctionApply(
|
||||
visitNode(target, callExpressionVisitor, isExpression),
|
||||
visitNode(thisArg, visitor, isExpression),
|
||||
node.expression.kind === SyntaxKind.SuperKeyword ? thisArg : visitNode(thisArg, visitor, isExpression),
|
||||
transformAndSpreadElements(node.arguments, /*needsUniqueCopy*/ false, /*multiLine*/ false, /*hasTrailingComma*/ false)
|
||||
);
|
||||
}
|
||||
@@ -3790,19 +3752,17 @@ namespace ts {
|
||||
// _super.prototype.m.call(this, a)
|
||||
resultingCall = createFunctionCall(
|
||||
visitNode(target, callExpressionVisitor, isExpression),
|
||||
visitNode(thisArg, visitor, isExpression),
|
||||
node.expression.kind === SyntaxKind.SuperKeyword ? thisArg : visitNode(thisArg, visitor, isExpression),
|
||||
visitNodes(node.arguments, visitor, isExpression),
|
||||
/*location*/ node
|
||||
);
|
||||
}
|
||||
|
||||
if (node.expression.kind === SyntaxKind.SuperKeyword) {
|
||||
const actualThis = createThis();
|
||||
setEmitFlags(actualThis, EmitFlags.NoSubstitution);
|
||||
const initializer =
|
||||
createLogicalOr(
|
||||
resultingCall,
|
||||
actualThis
|
||||
createActualThis()
|
||||
);
|
||||
resultingCall = assignToCapturedThis
|
||||
? createAssignment(createFileLevelUniqueName("_this"), initializer)
|
||||
@@ -3820,7 +3780,7 @@ namespace ts {
|
||||
* @param node A NewExpression node.
|
||||
*/
|
||||
function visitNewExpression(node: NewExpression): LeftHandSideExpression {
|
||||
if (node.transformFlags & TransformFlags.ContainsRestOrSpread) {
|
||||
if (some(node.arguments, isSpreadElement)) {
|
||||
// We are here because we contain a SpreadElementExpression.
|
||||
// [source]
|
||||
// new C(...a)
|
||||
@@ -4132,12 +4092,7 @@ namespace ts {
|
||||
|
||||
function visitMetaProperty(node: MetaProperty) {
|
||||
if (node.keywordToken === SyntaxKind.NewKeyword && node.name.escapedText === "target") {
|
||||
if (hierarchyFacts & HierarchyFacts.ComputedPropertyName) {
|
||||
hierarchyFacts |= HierarchyFacts.NewTargetInComputedPropertyName;
|
||||
}
|
||||
else {
|
||||
hierarchyFacts |= HierarchyFacts.NewTarget;
|
||||
}
|
||||
hierarchyFacts |= HierarchyFacts.NewTarget;
|
||||
return createFileLevelUniqueName("_newTarget");
|
||||
}
|
||||
return node;
|
||||
|
||||
@@ -438,7 +438,7 @@ namespace ts {
|
||||
)
|
||||
);
|
||||
|
||||
addStatementsAfterPrologue(statements, endLexicalEnvironment());
|
||||
insertStatementsAfterStandardPrologue(statements, endLexicalEnvironment());
|
||||
|
||||
// Minor optimization, emit `_super` helper to capture `super` access in an arrow.
|
||||
// This step isn't needed if we eventually transform this to ES5.
|
||||
@@ -448,7 +448,7 @@ namespace ts {
|
||||
enableSubstitutionForAsyncMethodsWithSuper();
|
||||
const variableStatement = createSuperAccessVariableStatement(resolver, node, capturedSuperProperties);
|
||||
substitutedSuperAccessors[getNodeId(variableStatement)] = true;
|
||||
addStatementsAfterPrologue(statements, [variableStatement]);
|
||||
insertStatementsAfterStandardPrologue(statements, [variableStatement]);
|
||||
}
|
||||
|
||||
const block = createBlock(statements, /*multiLine*/ true);
|
||||
|
||||
@@ -689,12 +689,12 @@ namespace ts {
|
||||
enableSubstitutionForAsyncMethodsWithSuper();
|
||||
const variableStatement = createSuperAccessVariableStatement(resolver, node, capturedSuperProperties);
|
||||
substitutedSuperAccessors[getNodeId(variableStatement)] = true;
|
||||
addStatementsAfterPrologue(statements, [variableStatement]);
|
||||
insertStatementsAfterStandardPrologue(statements, [variableStatement]);
|
||||
}
|
||||
|
||||
statements.push(returnStatement);
|
||||
|
||||
addStatementsAfterPrologue(statements, endLexicalEnvironment());
|
||||
insertStatementsAfterStandardPrologue(statements, endLexicalEnvironment());
|
||||
const block = updateBlock(node.body!, statements);
|
||||
|
||||
if (emitSuperHelpers && hasSuperElementAccess) {
|
||||
@@ -726,7 +726,7 @@ namespace ts {
|
||||
const leadingStatements = endLexicalEnvironment();
|
||||
if (statementOffset > 0 || some(statements) || some(leadingStatements)) {
|
||||
const block = convertToFunctionBody(body, /*multiLine*/ true);
|
||||
addStatementsAfterPrologue(statements, leadingStatements);
|
||||
insertStatementsAfterStandardPrologue(statements, leadingStatements);
|
||||
addRange(statements, block.statements.slice(statementOffset));
|
||||
return updateBlock(block, setTextRange(createNodeArray(statements), block.statements));
|
||||
}
|
||||
|
||||
@@ -316,7 +316,7 @@ namespace ts {
|
||||
else if (inGeneratorFunctionBody) {
|
||||
return visitJavaScriptInGeneratorFunctionBody(node);
|
||||
}
|
||||
else if (transformFlags & TransformFlags.Generator) {
|
||||
else if (isFunctionLikeDeclaration(node) && node.asteriskToken) {
|
||||
return visitGenerator(node);
|
||||
}
|
||||
else if (transformFlags & TransformFlags.ContainsGenerator) {
|
||||
@@ -587,7 +587,7 @@ namespace ts {
|
||||
transformAndEmitStatements(body.statements, statementOffset);
|
||||
|
||||
const buildResult = build();
|
||||
addStatementsAfterPrologue(statements, endLexicalEnvironment());
|
||||
insertStatementsAfterStandardPrologue(statements, endLexicalEnvironment());
|
||||
statements.push(createReturn(buildResult));
|
||||
|
||||
// Restore previous generator state
|
||||
|
||||
@@ -100,7 +100,7 @@ namespace ts {
|
||||
append(statements, visitNode(currentModuleInfo.externalHelpersImportDeclaration, sourceElementVisitor, isStatement));
|
||||
addRange(statements, visitNodes(node.statements, sourceElementVisitor, isStatement, statementOffset));
|
||||
addExportEqualsIfNeeded(statements, /*emitAsReturn*/ false);
|
||||
addStatementsAfterPrologue(statements, endLexicalEnvironment());
|
||||
insertStatementsAfterStandardPrologue(statements, endLexicalEnvironment());
|
||||
|
||||
const updated = updateSourceFileNode(node, setTextRange(createNodeArray(statements), node.statements));
|
||||
if (currentModuleInfo.hasExportStarsToExportValues && !compilerOptions.importHelpers) {
|
||||
@@ -432,7 +432,7 @@ namespace ts {
|
||||
|
||||
// End the lexical environment for the module body
|
||||
// and merge any new lexical declarations.
|
||||
addStatementsAfterPrologue(statements, endLexicalEnvironment());
|
||||
insertStatementsAfterStandardPrologue(statements, endLexicalEnvironment());
|
||||
|
||||
const body = createBlock(statements, /*multiLine*/ true);
|
||||
if (currentModuleInfo.hasExportStarsToExportValues && !compilerOptions.importHelpers) {
|
||||
@@ -537,8 +537,8 @@ namespace ts {
|
||||
if (isImportCall(node)) {
|
||||
return visitImportCallExpression(node);
|
||||
}
|
||||
else if (node.transformFlags & TransformFlags.DestructuringAssignment && isBinaryExpression(node)) {
|
||||
return visitDestructuringAssignment(node as DestructuringAssignment);
|
||||
else if (isDestructuringAssignment(node)) {
|
||||
return visitDestructuringAssignment(node);
|
||||
}
|
||||
else {
|
||||
return visitEachChild(node, moduleExpressionElementVisitor, context);
|
||||
|
||||
@@ -257,7 +257,7 @@ namespace ts {
|
||||
// We emit hoisted variables early to align roughly with our previous emit output.
|
||||
// Two key differences in this approach are:
|
||||
// - Temporary variables will appear at the top rather than at the bottom of the file
|
||||
addStatementsAfterPrologue(statements, endLexicalEnvironment());
|
||||
insertStatementsAfterStandardPrologue(statements, endLexicalEnvironment());
|
||||
|
||||
const exportStarFunction = addExportStarIfNeeded(statements)!; // TODO: GH#18217
|
||||
const moduleObject = createObjectLiteral([
|
||||
@@ -1463,9 +1463,8 @@ namespace ts {
|
||||
* @param node The node to visit.
|
||||
*/
|
||||
function destructuringAndImportCallVisitor(node: Node): VisitResult<Node> {
|
||||
if (node.transformFlags & TransformFlags.DestructuringAssignment
|
||||
&& node.kind === SyntaxKind.BinaryExpression) {
|
||||
return visitDestructuringAssignment(<DestructuringAssignment>node);
|
||||
if (isDestructuringAssignment(node)) {
|
||||
return visitDestructuringAssignment(node);
|
||||
}
|
||||
else if (isImportCall(node)) {
|
||||
return visitImportCallExpression(node);
|
||||
|
||||
+47
-140
@@ -208,15 +208,9 @@ namespace ts {
|
||||
* @param node The node to visit.
|
||||
*/
|
||||
function visitorWorker(node: Node): VisitResult<Node> {
|
||||
if (node.transformFlags & TransformFlags.TypeScript) {
|
||||
// This node is explicitly marked as TypeScript, so we should transform the node.
|
||||
if (node.transformFlags & TransformFlags.ContainsTypeScript) {
|
||||
return visitTypeScript(node);
|
||||
}
|
||||
else if (node.transformFlags & TransformFlags.ContainsTypeScript) {
|
||||
// This node contains TypeScript, so we should visit its children.
|
||||
return visitEachChild(node, visitor, context);
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
@@ -296,15 +290,9 @@ namespace ts {
|
||||
(<ImportEqualsDeclaration>node).moduleReference.kind === SyntaxKind.ExternalModuleReference)) {
|
||||
// do not emit ES6 imports and exports since they are illegal inside a namespace
|
||||
return undefined;
|
||||
}
|
||||
else if (node.transformFlags & TransformFlags.TypeScript || hasModifier(node, ModifierFlags.Export)) {
|
||||
// This node is explicitly marked as TypeScript, or is exported at the namespace
|
||||
// level, so we should transform the node.
|
||||
return visitTypeScript(node);
|
||||
}
|
||||
else if (node.transformFlags & TransformFlags.ContainsTypeScript) {
|
||||
// This node contains TypeScript, so we should visit its children.
|
||||
return visitEachChild(node, visitor, context);
|
||||
else if (node.transformFlags & TransformFlags.ContainsTypeScript || hasModifier(node, ModifierFlags.Export)) {
|
||||
return visitTypeScript(node);
|
||||
}
|
||||
|
||||
return node;
|
||||
@@ -365,7 +353,7 @@ namespace ts {
|
||||
* @param node The node to visit.
|
||||
*/
|
||||
function visitTypeScript(node: Node): VisitResult<Node> {
|
||||
if (hasModifier(node, ModifierFlags.Ambient) && isStatement(node)) {
|
||||
if (isStatement(node) && hasModifier(node, ModifierFlags.Ambient)) {
|
||||
// TypeScript ambient declarations are elided, but some comments may be preserved.
|
||||
// See the implementation of `getLeadingComments` in comments.ts for more details.
|
||||
return createNotEmittedStatement(node);
|
||||
@@ -443,7 +431,7 @@ namespace ts {
|
||||
return createNotEmittedStatement(node);
|
||||
|
||||
case SyntaxKind.ClassDeclaration:
|
||||
// This is a class declaration with TypeScript syntax extensions.
|
||||
// This may be a class declaration with TypeScript syntax extensions.
|
||||
//
|
||||
// TypeScript class syntax extensions include:
|
||||
// - decorators
|
||||
@@ -455,7 +443,7 @@ namespace ts {
|
||||
return visitClassDeclaration(<ClassDeclaration>node);
|
||||
|
||||
case SyntaxKind.ClassExpression:
|
||||
// This is a class expression with TypeScript syntax extensions.
|
||||
// This may be a class expression with TypeScript syntax extensions.
|
||||
//
|
||||
// TypeScript class syntax extensions include:
|
||||
// - decorators
|
||||
@@ -467,7 +455,7 @@ namespace ts {
|
||||
return visitClassExpression(<ClassExpression>node);
|
||||
|
||||
case SyntaxKind.HeritageClause:
|
||||
// This is a heritage clause with TypeScript syntax extensions.
|
||||
// This may be a heritage clause with TypeScript syntax extensions.
|
||||
//
|
||||
// TypeScript heritage clause extensions include:
|
||||
// - `implements` clause
|
||||
@@ -503,7 +491,7 @@ namespace ts {
|
||||
return visitArrowFunction(<ArrowFunction>node);
|
||||
|
||||
case SyntaxKind.Parameter:
|
||||
// This is a parameter declaration with TypeScript syntax extensions.
|
||||
// This may be a parameter declaration with TypeScript syntax extensions.
|
||||
//
|
||||
// TypeScript parameter declaration syntax extensions include:
|
||||
// - decorators
|
||||
@@ -556,7 +544,8 @@ namespace ts {
|
||||
return visitImportEqualsDeclaration(<ImportEqualsDeclaration>node);
|
||||
|
||||
default:
|
||||
return Debug.failBadSyntaxKind(node);
|
||||
// node contains some other TypeScript syntax
|
||||
return visitEachChild(node, visitor, context);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -607,18 +596,22 @@ namespace ts {
|
||||
return facts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms a class declaration with TypeScript syntax into compatible ES6.
|
||||
*
|
||||
* This function will only be called when one of the following conditions are met:
|
||||
* - The class has decorators.
|
||||
* - The class has property declarations with initializers.
|
||||
* - The class contains a constructor that contains parameters with accessibility modifiers.
|
||||
* - The class is an export in a TypeScript namespace.
|
||||
*
|
||||
* @param node The node to transform.
|
||||
*/
|
||||
function hasTypeScriptClassSyntax(node: Node) {
|
||||
return !!(node.transformFlags & TransformFlags.ContainsTypeScriptClassSyntax);
|
||||
}
|
||||
|
||||
function isClassLikeDeclarationWithTypeScriptSyntax(node: ClassLikeDeclaration) {
|
||||
return some(node.decorators)
|
||||
|| some(node.typeParameters)
|
||||
|| some(node.heritageClauses, hasTypeScriptClassSyntax)
|
||||
|| some(node.members, hasTypeScriptClassSyntax);
|
||||
}
|
||||
|
||||
function visitClassDeclaration(node: ClassDeclaration): VisitResult<Statement> {
|
||||
if (!isClassLikeDeclarationWithTypeScriptSyntax(node) && !(currentNamespace && hasModifier(node, ModifierFlags.Export))) {
|
||||
return visitEachChild(node, visitor, context);
|
||||
}
|
||||
|
||||
const savedPendingExpressions = pendingExpressions;
|
||||
pendingExpressions = undefined;
|
||||
|
||||
@@ -682,7 +675,7 @@ namespace ts {
|
||||
setEmitFlags(statement, EmitFlags.NoComments | EmitFlags.NoTokenSourceMaps);
|
||||
statements.push(statement);
|
||||
|
||||
addStatementsAfterPrologue(statements, context.endLexicalEnvironment());
|
||||
insertStatementsAfterStandardPrologue(statements, context.endLexicalEnvironment());
|
||||
|
||||
const iife = createImmediatelyInvokedArrowFunction(statements);
|
||||
setEmitFlags(iife, EmitFlags.TypeScriptClassWrapper);
|
||||
@@ -890,16 +883,11 @@ namespace ts {
|
||||
return statement;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms a class expression with TypeScript syntax into compatible ES6.
|
||||
*
|
||||
* This function will only be called when one of the following conditions are met:
|
||||
* - The class has property declarations with initializers.
|
||||
* - The class contains a constructor that contains parameters with accessibility modifiers.
|
||||
*
|
||||
* @param node The node to transform.
|
||||
*/
|
||||
function visitClassExpression(node: ClassExpression): Expression {
|
||||
if (!isClassLikeDeclarationWithTypeScriptSyntax(node)) {
|
||||
return visitEachChild(node, visitor, context);
|
||||
}
|
||||
|
||||
const savedPendingExpressions = pendingExpressions;
|
||||
pendingExpressions = undefined;
|
||||
|
||||
@@ -2237,18 +2225,11 @@ namespace ts {
|
||||
* @param node The HeritageClause to transform.
|
||||
*/
|
||||
function visitHeritageClause(node: HeritageClause): HeritageClause | undefined {
|
||||
if (node.token === SyntaxKind.ExtendsKeyword) {
|
||||
const types = visitNodes(node.types, visitor, isExpressionWithTypeArguments, 0, 1);
|
||||
return setTextRange(
|
||||
createHeritageClause(
|
||||
SyntaxKind.ExtendsKeyword,
|
||||
types
|
||||
),
|
||||
node
|
||||
);
|
||||
if (node.token === SyntaxKind.ImplementsKeyword) {
|
||||
// implements clauses are elided
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return undefined;
|
||||
return visitEachChild(node, visitor, context);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2299,16 +2280,6 @@ namespace ts {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits a method declaration of a class.
|
||||
*
|
||||
* This function will be called when one of the following conditions are met:
|
||||
* - The node is an overload
|
||||
* - The node is marked as abstract, public, private, protected, or readonly
|
||||
* - The node has a computed property name
|
||||
*
|
||||
* @param node The method node.
|
||||
*/
|
||||
function visitMethodDeclaration(node: MethodDeclaration) {
|
||||
if (!shouldEmitFunctionLikeDeclaration(node)) {
|
||||
return undefined;
|
||||
@@ -2344,15 +2315,6 @@ namespace ts {
|
||||
return !(nodeIsMissing(node.body) && hasModifier(node, ModifierFlags.Abstract));
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits a get accessor declaration of a class.
|
||||
*
|
||||
* This function will be called when one of the following conditions are met:
|
||||
* - The node is marked as abstract, public, private, or protected
|
||||
* - The node has a computed property name
|
||||
*
|
||||
* @param node The get accessor node.
|
||||
*/
|
||||
function visitGetAccessor(node: GetAccessorDeclaration) {
|
||||
if (!shouldEmitAccessorDeclaration(node)) {
|
||||
return undefined;
|
||||
@@ -2375,15 +2337,6 @@ namespace ts {
|
||||
return updated;
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits a set accessor declaration of a class.
|
||||
*
|
||||
* This function will be called when one of the following conditions are met:
|
||||
* - The node is marked as abstract, public, private, or protected
|
||||
* - The node has a computed property name
|
||||
*
|
||||
* @param node The set accessor node.
|
||||
*/
|
||||
function visitSetAccessor(node: SetAccessorDeclaration) {
|
||||
if (!shouldEmitAccessorDeclaration(node)) {
|
||||
return undefined;
|
||||
@@ -2405,16 +2358,6 @@ namespace ts {
|
||||
return updated;
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits a function declaration.
|
||||
*
|
||||
* This function will be called when one of the following conditions are met:
|
||||
* - The node is an overload
|
||||
* - The node is exported from a TypeScript namespace
|
||||
* - The node has decorators
|
||||
*
|
||||
* @param node The function node.
|
||||
*/
|
||||
function visitFunctionDeclaration(node: FunctionDeclaration): VisitResult<Statement> {
|
||||
if (!shouldEmitFunctionLikeDeclaration(node)) {
|
||||
return createNotEmittedStatement(node);
|
||||
@@ -2438,14 +2381,6 @@ namespace ts {
|
||||
return updated;
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits a function expression node.
|
||||
*
|
||||
* This function will be called when one of the following conditions are met:
|
||||
* - The node has type annotations
|
||||
*
|
||||
* @param node The function expression node.
|
||||
*/
|
||||
function visitFunctionExpression(node: FunctionExpression): Expression {
|
||||
if (!shouldEmitFunctionLikeDeclaration(node)) {
|
||||
return createOmittedExpression();
|
||||
@@ -2463,11 +2398,6 @@ namespace ts {
|
||||
return updated;
|
||||
}
|
||||
|
||||
/**
|
||||
* @remarks
|
||||
* This function will be called when one of the following conditions are met:
|
||||
* - The node has type annotations
|
||||
*/
|
||||
function visitArrowFunction(node: ArrowFunction) {
|
||||
const updated = updateArrowFunction(
|
||||
node,
|
||||
@@ -2481,22 +2411,12 @@ namespace ts {
|
||||
return updated;
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits a parameter declaration node.
|
||||
*
|
||||
* This function will be called when one of the following conditions are met:
|
||||
* - The node has an accessibility modifier.
|
||||
* - The node has a questionToken.
|
||||
* - The node's kind is ThisKeyword.
|
||||
*
|
||||
* @param node The parameter declaration node.
|
||||
*/
|
||||
function visitParameter(node: ParameterDeclaration) {
|
||||
if (parameterIsThisKeyword(node)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const parameter = createParameter(
|
||||
const updated = updateParameter(
|
||||
node,
|
||||
/*decorators*/ undefined,
|
||||
/*modifiers*/ undefined,
|
||||
node.dotDotDotToken,
|
||||
@@ -2505,24 +2425,17 @@ namespace ts {
|
||||
/*type*/ undefined,
|
||||
visitNode(node.initializer, visitor, isExpression)
|
||||
);
|
||||
|
||||
// While we emit the source map for the node after skipping decorators and modifiers,
|
||||
// we need to emit the comments for the original range.
|
||||
setOriginalNode(parameter, node);
|
||||
setTextRange(parameter, moveRangePastModifiers(node));
|
||||
setCommentRange(parameter, node);
|
||||
setSourceMapRange(parameter, moveRangePastModifiers(node));
|
||||
setEmitFlags(parameter.name, EmitFlags.NoTrailingSourceMap);
|
||||
|
||||
return parameter;
|
||||
if (updated !== node) {
|
||||
// While we emit the source map for the node after skipping decorators and modifiers,
|
||||
// we need to emit the comments for the original range.
|
||||
setCommentRange(updated, node);
|
||||
setTextRange(updated, moveRangePastModifiers(node));
|
||||
setSourceMapRange(updated, moveRangePastModifiers(node));
|
||||
setEmitFlags(updated.name, EmitFlags.NoTrailingSourceMap);
|
||||
}
|
||||
return updated;
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits a variable statement in a namespace.
|
||||
*
|
||||
* This function will be called when one of the following conditions are met:
|
||||
* - The node is exported from a TypeScript namespace.
|
||||
*/
|
||||
function visitVariableStatement(node: VariableStatement): Statement | undefined {
|
||||
if (isExportOfNamespace(node)) {
|
||||
const variables = getInitializedVariables(node.declarationList);
|
||||
@@ -2576,12 +2489,6 @@ namespace ts {
|
||||
visitNode(node.initializer, visitor, isExpression));
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits a parenthesized expression that contains either a type assertion or an `as`
|
||||
* expression.
|
||||
*
|
||||
* @param node The parenthesized expression node.
|
||||
*/
|
||||
function visitParenthesizedExpression(node: ParenthesizedExpression): Expression {
|
||||
const innerExpression = skipOuterExpressions(node.expression, ~OuterExpressionKinds.Assertions);
|
||||
if (isAssertionExpression(innerExpression)) {
|
||||
@@ -2765,7 +2672,7 @@ namespace ts {
|
||||
const statements: Statement[] = [];
|
||||
startLexicalEnvironment();
|
||||
const members = map(node.members, transformEnumMember);
|
||||
addStatementsAfterPrologue(statements, endLexicalEnvironment());
|
||||
insertStatementsAfterStandardPrologue(statements, endLexicalEnvironment());
|
||||
addRange(statements, members);
|
||||
|
||||
currentNamespaceContainerName = savedCurrentNamespaceLocalName;
|
||||
@@ -3086,7 +2993,7 @@ namespace ts {
|
||||
statementsLocation = moveRangePos(moduleBlock.statements, -1);
|
||||
}
|
||||
|
||||
addStatementsAfterPrologue(statements, endLexicalEnvironment());
|
||||
insertStatementsAfterStandardPrologue(statements, endLexicalEnvironment());
|
||||
currentNamespaceContainerName = savedCurrentNamespaceContainerName;
|
||||
currentNamespace = savedCurrentNamespace;
|
||||
currentScopeFirstDeclarationsOfName = savedCurrentScopeFirstDeclarationsOfName;
|
||||
|
||||
+38
-43
@@ -5065,38 +5065,29 @@ namespace ts {
|
||||
|
||||
// Facts
|
||||
// - Flags used to indicate that a node or subtree contains syntax that requires transformation.
|
||||
TypeScript = 1 << 0,
|
||||
ContainsTypeScript = 1 << 1,
|
||||
ContainsJsx = 1 << 2,
|
||||
ContainsESNext = 1 << 3,
|
||||
ContainsES2017 = 1 << 4,
|
||||
ContainsES2016 = 1 << 5,
|
||||
ES2015 = 1 << 6,
|
||||
ContainsTypeScript = 1 << 0,
|
||||
ContainsJsx = 1 << 1,
|
||||
ContainsESNext = 1 << 2,
|
||||
ContainsES2019 = 1 << 3,
|
||||
ContainsES2018 = 1 << 4,
|
||||
ContainsES2017 = 1 << 5,
|
||||
ContainsES2016 = 1 << 6,
|
||||
ContainsES2015 = 1 << 7,
|
||||
Generator = 1 << 8,
|
||||
ContainsGenerator = 1 << 9,
|
||||
DestructuringAssignment = 1 << 10,
|
||||
ContainsDestructuringAssignment = 1 << 11,
|
||||
ContainsGenerator = 1 << 8,
|
||||
ContainsDestructuringAssignment = 1 << 9,
|
||||
|
||||
// Markers
|
||||
// - Flags used to indicate that a subtree contains a specific transformation.
|
||||
ContainsTypeScriptClassSyntax = 1 << 12, // Decorators, Property Initializers, Parameter Property Initializers
|
||||
ContainsLexicalThis = 1 << 13,
|
||||
ContainsCapturedLexicalThis = 1 << 14,
|
||||
ContainsLexicalThisInComputedPropertyName = 1 << 15,
|
||||
ContainsDefaultValueAssignments = 1 << 16,
|
||||
ContainsRestOrSpread = 1 << 17,
|
||||
ContainsObjectRestOrSpread = 1 << 18,
|
||||
ContainsComputedPropertyName = 1 << 19,
|
||||
ContainsBlockScopedBinding = 1 << 20,
|
||||
ContainsBindingPattern = 1 << 21,
|
||||
ContainsYield = 1 << 22,
|
||||
ContainsHoistedDeclarationOrCompletion = 1 << 23,
|
||||
ContainsDynamicImport = 1 << 24,
|
||||
Super = 1 << 25,
|
||||
ContainsSuper = 1 << 26,
|
||||
ContainsES2018 = 1 << 27,
|
||||
ContainsES2019 = 1 << 28,
|
||||
ContainsTypeScriptClassSyntax = 1 << 10, // Decorators, Property Initializers, Parameter Property Initializers
|
||||
ContainsLexicalThis = 1 << 11,
|
||||
ContainsRestOrSpread = 1 << 12,
|
||||
ContainsObjectRestOrSpread = 1 << 13,
|
||||
ContainsComputedPropertyName = 1 << 14,
|
||||
ContainsBlockScopedBinding = 1 << 15,
|
||||
ContainsBindingPattern = 1 << 16,
|
||||
ContainsYield = 1 << 17,
|
||||
ContainsHoistedDeclarationOrCompletion = 1 << 18,
|
||||
ContainsDynamicImport = 1 << 19,
|
||||
|
||||
// Please leave this as 1 << 29.
|
||||
// It is the maximum bit we can set before we outgrow the size of a v8 small integer (SMI) on an x86 system.
|
||||
@@ -5105,40 +5096,44 @@ namespace ts {
|
||||
|
||||
// Assertions
|
||||
// - Bitmasks that are used to assert facts about the syntax of a node and its subtree.
|
||||
AssertTypeScript = TypeScript | ContainsTypeScript,
|
||||
AssertTypeScript = ContainsTypeScript,
|
||||
AssertJsx = ContainsJsx,
|
||||
AssertESNext = ContainsESNext,
|
||||
AssertES2019 = ContainsES2019,
|
||||
AssertES2018 = ContainsES2018,
|
||||
AssertES2017 = ContainsES2017,
|
||||
AssertES2016 = ContainsES2016,
|
||||
AssertES2015 = ES2015 | ContainsES2015,
|
||||
AssertGenerator = Generator | ContainsGenerator,
|
||||
AssertDestructuringAssignment = DestructuringAssignment | ContainsDestructuringAssignment,
|
||||
AssertES2015 = ContainsES2015,
|
||||
AssertGenerator = ContainsGenerator,
|
||||
AssertDestructuringAssignment = ContainsDestructuringAssignment,
|
||||
|
||||
// Scope Exclusions
|
||||
// - Bitmasks that exclude flags from propagating out of a specific context
|
||||
// into the subtree flags of their container.
|
||||
OuterExpressionExcludes = TypeScript | ES2015 | DestructuringAssignment | Generator | HasComputedFlags,
|
||||
PropertyAccessExcludes = OuterExpressionExcludes | Super,
|
||||
NodeExcludes = PropertyAccessExcludes | ContainsSuper,
|
||||
ArrowFunctionExcludes = NodeExcludes | ContainsTypeScriptClassSyntax | ContainsDefaultValueAssignments | ContainsLexicalThis | ContainsBlockScopedBinding | ContainsYield | ContainsHoistedDeclarationOrCompletion | ContainsBindingPattern | ContainsObjectRestOrSpread,
|
||||
FunctionExcludes = NodeExcludes | ContainsTypeScriptClassSyntax | ContainsDefaultValueAssignments | ContainsCapturedLexicalThis | ContainsLexicalThis | ContainsBlockScopedBinding | ContainsYield | ContainsHoistedDeclarationOrCompletion | ContainsBindingPattern | ContainsObjectRestOrSpread,
|
||||
ConstructorExcludes = NodeExcludes | ContainsDefaultValueAssignments | ContainsLexicalThis | ContainsCapturedLexicalThis | ContainsBlockScopedBinding | ContainsYield | ContainsHoistedDeclarationOrCompletion | ContainsBindingPattern | ContainsObjectRestOrSpread,
|
||||
MethodOrAccessorExcludes = NodeExcludes | ContainsDefaultValueAssignments | ContainsLexicalThis | ContainsCapturedLexicalThis | ContainsBlockScopedBinding | ContainsYield | ContainsHoistedDeclarationOrCompletion | ContainsBindingPattern | ContainsObjectRestOrSpread,
|
||||
ClassExcludes = NodeExcludes | ContainsTypeScriptClassSyntax | ContainsLexicalThis | ContainsCapturedLexicalThis | ContainsComputedPropertyName | ContainsLexicalThisInComputedPropertyName,
|
||||
ModuleExcludes = NodeExcludes | ContainsTypeScriptClassSyntax | ContainsLexicalThis | ContainsCapturedLexicalThis | ContainsBlockScopedBinding | ContainsHoistedDeclarationOrCompletion,
|
||||
OuterExpressionExcludes = HasComputedFlags,
|
||||
PropertyAccessExcludes = OuterExpressionExcludes,
|
||||
NodeExcludes = PropertyAccessExcludes,
|
||||
ArrowFunctionExcludes = NodeExcludes | ContainsTypeScriptClassSyntax | ContainsBlockScopedBinding | ContainsYield | ContainsHoistedDeclarationOrCompletion | ContainsBindingPattern | ContainsObjectRestOrSpread,
|
||||
FunctionExcludes = NodeExcludes | ContainsTypeScriptClassSyntax | ContainsLexicalThis | ContainsBlockScopedBinding | ContainsYield | ContainsHoistedDeclarationOrCompletion | ContainsBindingPattern | ContainsObjectRestOrSpread,
|
||||
ConstructorExcludes = NodeExcludes | ContainsLexicalThis | ContainsBlockScopedBinding | ContainsYield | ContainsHoistedDeclarationOrCompletion | ContainsBindingPattern | ContainsObjectRestOrSpread,
|
||||
MethodOrAccessorExcludes = NodeExcludes | ContainsLexicalThis | ContainsBlockScopedBinding | ContainsYield | ContainsHoistedDeclarationOrCompletion | ContainsBindingPattern | ContainsObjectRestOrSpread,
|
||||
PropertyExcludes = NodeExcludes | ContainsLexicalThis,
|
||||
ClassExcludes = NodeExcludes | ContainsTypeScriptClassSyntax | ContainsComputedPropertyName,
|
||||
ModuleExcludes = NodeExcludes | ContainsTypeScriptClassSyntax | ContainsLexicalThis | ContainsBlockScopedBinding | ContainsHoistedDeclarationOrCompletion,
|
||||
TypeExcludes = ~ContainsTypeScript,
|
||||
ObjectLiteralExcludes = NodeExcludes | ContainsTypeScriptClassSyntax | ContainsComputedPropertyName | ContainsLexicalThisInComputedPropertyName | ContainsObjectRestOrSpread,
|
||||
ObjectLiteralExcludes = NodeExcludes | ContainsTypeScriptClassSyntax | ContainsComputedPropertyName | ContainsObjectRestOrSpread,
|
||||
ArrayLiteralOrCallOrNewExcludes = NodeExcludes | ContainsRestOrSpread,
|
||||
VariableDeclarationListExcludes = NodeExcludes | ContainsBindingPattern | ContainsObjectRestOrSpread,
|
||||
ParameterExcludes = NodeExcludes,
|
||||
CatchClauseExcludes = NodeExcludes | ContainsObjectRestOrSpread,
|
||||
BindingPatternExcludes = NodeExcludes | ContainsRestOrSpread,
|
||||
|
||||
// Propagating flags
|
||||
// - Bitmasks for flags that should propagate from a child
|
||||
PropertyNamePropagatingFlags = ContainsLexicalThis,
|
||||
|
||||
// Masks
|
||||
// - Additional bitmasks
|
||||
ES2015FunctionSyntaxMask = ContainsCapturedLexicalThis | ContainsDefaultValueAssignments,
|
||||
}
|
||||
|
||||
export interface SourceMapRange extends TextRange {
|
||||
|
||||
@@ -401,10 +401,7 @@ namespace ts {
|
||||
return !nodeIsMissing(node);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepends statements to an array while taking care of prologue directives.
|
||||
*/
|
||||
export function addStatementsAfterPrologue<T extends Statement>(to: T[], from: ReadonlyArray<T> | undefined): T[] {
|
||||
function insertStatementsAfterPrologue<T extends Statement>(to: T[], from: ReadonlyArray<T> | undefined, isPrologueDirective: (node: Node) => boolean): T[] {
|
||||
if (from === undefined || from.length === 0) return to;
|
||||
let statementIndex = 0;
|
||||
// skip all prologue directives to insert at the correct position
|
||||
@@ -417,6 +414,46 @@ namespace ts {
|
||||
return to;
|
||||
}
|
||||
|
||||
function insertStatementAfterPrologue<T extends Statement>(to: T[], statement: T | undefined, isPrologueDirective: (node: Node) => boolean): T[] {
|
||||
if (statement === undefined) return to;
|
||||
let statementIndex = 0;
|
||||
// skip all prologue directives to insert at the correct position
|
||||
for (; statementIndex < to.length; ++statementIndex) {
|
||||
if (!isPrologueDirective(to[statementIndex])) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
to.splice(statementIndex, 0, statement);
|
||||
return to;
|
||||
}
|
||||
|
||||
|
||||
function isAnyPrologueDirective(node: Node) {
|
||||
return isPrologueDirective(node) || !!(getEmitFlags(node) & EmitFlags.CustomPrologue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepends statements to an array while taking care of prologue directives.
|
||||
*/
|
||||
export function insertStatementsAfterStandardPrologue<T extends Statement>(to: T[], from: ReadonlyArray<T> | undefined): T[] {
|
||||
return insertStatementsAfterPrologue(to, from, isPrologueDirective);
|
||||
}
|
||||
|
||||
export function insertStatementsAfterCustomPrologue<T extends Statement>(to: T[], from: ReadonlyArray<T> | undefined): T[] {
|
||||
return insertStatementsAfterPrologue(to, from, isAnyPrologueDirective);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepends statements to an array while taking care of prologue directives.
|
||||
*/
|
||||
export function insertStatementAfterStandardPrologue<T extends Statement>(to: T[], statement: T | undefined): T[] {
|
||||
return insertStatementAfterPrologue(to, statement, isPrologueDirective);
|
||||
}
|
||||
|
||||
export function insertStatementAfterCustomPrologue<T extends Statement>(to: T[], statement: T | undefined): T[] {
|
||||
return insertStatementAfterPrologue(to, statement, isAnyPrologueDirective);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given comment is a triple-slash
|
||||
*
|
||||
@@ -1436,6 +1473,11 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
export function isSuperOrSuperProperty(node: Node): node is SuperExpression | SuperProperty {
|
||||
return node.kind === SyntaxKind.SuperKeyword
|
||||
|| isSuperProperty(node);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether a node is a property or element access expression for `super`.
|
||||
*/
|
||||
@@ -3418,8 +3460,8 @@ namespace ts {
|
||||
return computeLineAndCharacterOfPosition(lineMap, pos).line;
|
||||
}
|
||||
|
||||
export function getFirstConstructorWithBody(node: ClassLikeDeclaration): ConstructorDeclaration | undefined {
|
||||
return find(node.members, (member): member is ConstructorDeclaration => isConstructorDeclaration(member) && nodeIsPresent(member.body));
|
||||
export function getFirstConstructorWithBody(node: ClassLikeDeclaration): ConstructorDeclaration & { body: FunctionBody } | undefined {
|
||||
return find(node.members, (member): member is ConstructorDeclaration & { body: FunctionBody } => isConstructorDeclaration(member) && nodeIsPresent(member.body));
|
||||
}
|
||||
|
||||
function getSetAccessorValueParameter(accessor: SetAccessorDeclaration): ParameterDeclaration | undefined {
|
||||
|
||||
@@ -1478,8 +1478,8 @@ namespace ts {
|
||||
}
|
||||
|
||||
return isNodeArray(statements)
|
||||
? setTextRange(createNodeArray(addStatementsAfterPrologue(statements.slice(), declarations)), statements)
|
||||
: addStatementsAfterPrologue(statements, declarations);
|
||||
? setTextRange(createNodeArray(insertStatementsAfterStandardPrologue(statements.slice(), declarations)), statements)
|
||||
: insertStatementsAfterStandardPrologue(statements, declarations);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -11,4 +11,4 @@ var d = () => ((<Error>({ name: "foo", message: "bar" })));
|
||||
var a = function () { return ({ name: "foo", message: "bar" }); };
|
||||
var b = function () { return ({ name: "foo", message: "bar" }); };
|
||||
var c = function () { return ({ name: "foo", message: "bar" }); };
|
||||
var d = function () { return (({ name: "foo", message: "bar" })); };
|
||||
var d = function () { return ({ name: "foo", message: "bar" }); };
|
||||
@@ -11,4 +11,4 @@ var d = () => ((<Error>({ name: "foo", message: "bar" })));
|
||||
var a = () => ({ name: "foo", message: "bar" });
|
||||
var b = () => ({ name: "foo", message: "bar" });
|
||||
var c = () => ({ name: "foo", message: "bar" });
|
||||
var d = () => (({ name: "foo", message: "bar" }));
|
||||
var d = () => ({ name: "foo", message: "bar" });
|
||||
@@ -17,7 +17,6 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
||||
};
|
||||
var M;
|
||||
(function (M) {
|
||||
var _this = this;
|
||||
var C = /** @class */ (function () {
|
||||
function C() {
|
||||
}
|
||||
|
||||
@@ -30,7 +30,6 @@ c.dynamic();
|
||||
}
|
||||
C.prototype.dynamic = function () {
|
||||
var _a;
|
||||
var _this = this;
|
||||
return _a = this._path, __syncRequire ? Promise.resolve().then(function () { return require(_a); }) : new Promise(function (resolve_1, reject_1) { require([_a], resolve_1, reject_1); });
|
||||
};
|
||||
return C;
|
||||
|
||||
@@ -34,26 +34,44 @@ var C = /** @class */ (function () {
|
||||
this.f = function () { return _newTarget; };
|
||||
}
|
||||
C.prototype[_newTarget] = function () { };
|
||||
C.prototype.c = function () { var _newTarget = void 0; return _newTarget; };
|
||||
C.prototype.c = function () {
|
||||
var _newTarget = void 0;
|
||||
return _newTarget;
|
||||
};
|
||||
Object.defineProperty(C.prototype, "d", {
|
||||
get: function () { var _newTarget = void 0; return _newTarget; },
|
||||
get: function () {
|
||||
var _newTarget = void 0;
|
||||
return _newTarget;
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
Object.defineProperty(C.prototype, "e", {
|
||||
set: function (_) { var _newTarget = void 0; _ = _newTarget; },
|
||||
set: function (_) {
|
||||
var _newTarget = void 0;
|
||||
_ = _newTarget;
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
C[_newTarget] = function () { };
|
||||
C.g = function () { var _newTarget = void 0; return _newTarget; };
|
||||
C.g = function () {
|
||||
var _newTarget = void 0;
|
||||
return _newTarget;
|
||||
};
|
||||
Object.defineProperty(C, "h", {
|
||||
get: function () { var _newTarget = void 0; return _newTarget; },
|
||||
get: function () {
|
||||
var _newTarget = void 0;
|
||||
return _newTarget;
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
Object.defineProperty(C, "i", {
|
||||
set: function (_) { var _newTarget = void 0; _ = _newTarget; },
|
||||
set: function (_) {
|
||||
var _newTarget = void 0;
|
||||
_ = _newTarget;
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
@@ -62,14 +80,23 @@ var C = /** @class */ (function () {
|
||||
}());
|
||||
var O = (_a = {},
|
||||
_a[_newTarget] = undefined,
|
||||
_a.k = function () { var _newTarget = void 0; return _newTarget; },
|
||||
_a.k = function () {
|
||||
var _newTarget = void 0;
|
||||
return _newTarget;
|
||||
},
|
||||
Object.defineProperty(_a, "l", {
|
||||
get: function () { var _newTarget = void 0; return _newTarget; },
|
||||
get: function () {
|
||||
var _newTarget = void 0;
|
||||
return _newTarget;
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
}),
|
||||
Object.defineProperty(_a, "m", {
|
||||
set: function (_) { var _newTarget = void 0; _ = _newTarget; },
|
||||
set: function (_) {
|
||||
var _newTarget = void 0;
|
||||
_ = _newTarget;
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
}),
|
||||
|
||||
@@ -49,11 +49,17 @@ var __extends = (this && this.__extends) || (function () {
|
||||
var A = /** @class */ (function () {
|
||||
function A() {
|
||||
var _newTarget = this.constructor;
|
||||
this.d = function _a() { var _newTarget = this && this instanceof _a ? this.constructor : void 0; return _newTarget; };
|
||||
this.d = function _a() {
|
||||
var _newTarget = this && this instanceof _a ? this.constructor : void 0;
|
||||
return _newTarget;
|
||||
};
|
||||
var a = _newTarget;
|
||||
var b = function () { return _newTarget; };
|
||||
}
|
||||
A.c = function _a() { var _newTarget = this && this instanceof _a ? this.constructor : void 0; return _newTarget; };
|
||||
A.c = function _a() {
|
||||
var _newTarget = this && this instanceof _a ? this.constructor : void 0;
|
||||
return _newTarget;
|
||||
};
|
||||
return A;
|
||||
}());
|
||||
var B = /** @class */ (function (_super) {
|
||||
@@ -78,5 +84,8 @@ var f2 = function _b() {
|
||||
var j = function () { return _newTarget; };
|
||||
};
|
||||
var O = {
|
||||
k: function k() { var _newTarget = this && this instanceof k ? this.constructor : void 0; return _newTarget; }
|
||||
k: function k() {
|
||||
var _newTarget = this && this instanceof k ? this.constructor : void 0;
|
||||
return _newTarget;
|
||||
}
|
||||
};
|
||||
@@ -25,9 +25,9 @@ function f2(_: ReadonlyArray<number>): void {}
|
||||
//// [noUnusedLocals_writeOnly.js]
|
||||
"use strict";
|
||||
function f(x, b) {
|
||||
var _a, _b;
|
||||
if (x === void 0) { x = 0; }
|
||||
if (b === void 0) { b = false; }
|
||||
var _a, _b;
|
||||
// None of these statements read from 'x', so it will be marked unused.
|
||||
x = 1;
|
||||
x++;
|
||||
|
||||
@@ -17,9 +17,7 @@ let o = {
|
||||
string; // should be => not :
|
||||
// doesn't work in non-type contexts, where the return type is optional
|
||||
var f = function (n) { return function (string) { return n.toString(); }; };
|
||||
var o = {
|
||||
m: function (n) { }
|
||||
};
|
||||
var o = {};
|
||||
string;
|
||||
{
|
||||
return n.toString();
|
||||
|
||||
@@ -2,5 +2,4 @@
|
||||
function f(p: A) => p;
|
||||
|
||||
//// [parserErrantEqualsGreaterThanAfterFunction2.js]
|
||||
function f(p) { }
|
||||
p;
|
||||
@@ -123,8 +123,8 @@ var Bs = /** @class */ (function (_super) {
|
||||
var Cs = /** @class */ (function (_super) {
|
||||
__extends(Cs, _super);
|
||||
function Cs() {
|
||||
var _this = _super.call(this) || this;
|
||||
"use strict";
|
||||
var _this = _super.call(this) || this;
|
||||
return _this;
|
||||
}
|
||||
Cs.s = 9;
|
||||
|
||||
@@ -12,16 +12,15 @@ class P {
|
||||
}
|
||||
|
||||
//// [thisInConstructorParameter2.js]
|
||||
var _this = this;
|
||||
var P = /** @class */ (function () {
|
||||
function P(z, zz, zzz) {
|
||||
var _this = this;
|
||||
if (z === void 0) { z = this; }
|
||||
if (zz === void 0) { zz = this; }
|
||||
if (zzz === void 0) { zzz = function (p) {
|
||||
if (p === void 0) { p = _this; }
|
||||
return _this;
|
||||
}; }
|
||||
var _this = this;
|
||||
this.z = z;
|
||||
this.x = this;
|
||||
zzz = function (p) {
|
||||
|
||||
@@ -62,7 +62,6 @@ var __extends = (this && this.__extends) || (function () {
|
||||
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
||||
};
|
||||
})();
|
||||
var _this = this;
|
||||
//'this' in static member initializer
|
||||
var ErrClass1 = /** @class */ (function () {
|
||||
function ErrClass1() {
|
||||
|
||||
@@ -63,7 +63,6 @@ var __extends = (this && this.__extends) || (function () {
|
||||
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
||||
};
|
||||
})();
|
||||
var _this = this;
|
||||
//'this' in static member initializer
|
||||
var ErrClass1 = /** @class */ (function () {
|
||||
function ErrClass1() {
|
||||
|
||||
@@ -21,7 +21,6 @@ class Foo {
|
||||
}
|
||||
|
||||
//// [thisInOuterClassBody.js]
|
||||
var _this = this;
|
||||
var Foo = /** @class */ (function () {
|
||||
function Foo() {
|
||||
this.x = this;
|
||||
|
||||
@@ -321,7 +321,6 @@ function modifiers() { return this.n; }
|
||||
function restParam(...) { return this.n; }
|
||||
function optional() { return this.n; }
|
||||
function decorated() { return this.n; }
|
||||
function initializer(, C) { }
|
||||
();
|
||||
number;
|
||||
{
|
||||
|
||||
@@ -8,7 +8,6 @@ class C2<T> {
|
||||
}
|
||||
|
||||
//// [typeOfThisInStaticMembers2.js]
|
||||
var _this = this;
|
||||
var C = /** @class */ (function () {
|
||||
function C() {
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user