Always use same code path when transforming function bodies for es2015

This commit is contained in:
Ron Buckton 2019-02-28 16:28:25 -08:00
parent b02dab4e00
commit 86242eed87
9 changed files with 26 additions and 56 deletions

View File

@ -345,13 +345,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);
@ -507,7 +500,6 @@ namespace ts {
const statements: Statement[] = [];
startLexicalEnvironment();
let statementOffset = addStandardPrologue(prologue, node.statements, /*ensureUseStrict*/ false);
insertCaptureThisForNodeIfNeeded(prologue, node);
statementOffset = addCustomPrologue(prologue, node.statements, statementOffset, visitor);
addRange(statements, visitNodes(node.statements, visitor, isStatement, statementOffset));
if (taggedTemplateStringDeclarations) {
@ -515,7 +507,8 @@ namespace ts {
createVariableStatement(/*modifiers*/ undefined,
createVariableDeclarationList(taggedTemplateStringDeclarations)));
}
insertStatementsAfterStandardPrologue(prologue, endLexicalEnvironment());
mergeLexicalEnvironment(prologue, endLexicalEnvironment());
insertCaptureThisForNodeIfNeeded(prologue, node);
exitSubtree(ancestorFacts, HierarchyFacts.None, HierarchyFacts.None);
return updateSourceFileNode(
node,
@ -1194,11 +1187,6 @@ namespace ts {
|| isBindingPattern(node.name);
}
function hasDefaultValueOrBindingPatternOrRest(node: ParameterDeclaration) {
return hasDefaultValueOrBindingPattern(node)
|| node.dotDotDotToken !== undefined;
}
/**
* Adds statements to the body of a function-like node if it contains parameters with
* binding patterns or initializers.
@ -1446,12 +1434,13 @@ namespace ts {
/**
* 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 insertCaptureThisForNodeIfNeeded(statements: Statement[], node: Node): boolean {
if (node.transformFlags & TransformFlags.ContainsCapturedLexicalThis && node.kind !== SyntaxKind.ArrowFunction) {
if (hierarchyFacts & HierarchyFacts.CapturedLexicalThis && node.kind !== SyntaxKind.ArrowFunction) {
insertCaptureThisForNode(statements, node, createThis());
return true;
}
@ -1731,10 +1720,6 @@ namespace ts {
return func;
}
function containsCapturedLexicalThis(node: Node) {
return (node.transformFlags & TransformFlags.ContainsCapturedLexicalThis) !== 0;
}
/**
* Visits a FunctionExpression node.
*
@ -1748,11 +1733,7 @@ namespace ts {
convertedLoopState = undefined;
const parameters = visitParameterList(node.parameters, visitor, context);
const shouldTransform = forEachChild(node, containsCapturedLexicalThis)
|| some(node.parameters, hasDefaultValueOrBindingPatternOrRest);
const body = shouldTransform
? transformFunctionBody(node)
: visitFunctionBodyDownLevel(node);
const body = transformFunctionBody(node);
const name = hierarchyFacts & HierarchyFacts.NewTarget
? getLocalName(node)
: node.name;
@ -1781,11 +1762,7 @@ namespace ts {
convertedLoopState = undefined;
const ancestorFacts = enterSubtree(HierarchyFacts.FunctionExcludes, HierarchyFacts.FunctionIncludes);
const parameters = visitParameterList(node.parameters, visitor, context);
const shouldTransform = forEachChild(node, containsCapturedLexicalThis)
|| some(node.parameters, hasDefaultValueOrBindingPatternOrRest);
const body = shouldTransform
? transformFunctionBody(node)
: visitFunctionBodyDownLevel(node);
const body = transformFunctionBody(node);
const name = hierarchyFacts & HierarchyFacts.NewTarget
? getLocalName(node)
: node.name;
@ -1921,7 +1898,13 @@ namespace ts {
multiLine = true;
}
const block = createBlock(setTextRange(createNodeArray(concatenate(prologue, 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);
@ -1935,19 +1918,6 @@ namespace ts {
return block;
}
function visitFunctionBodyDownLevel(node: FunctionDeclaration | FunctionExpression | AccessorDeclaration) {
const updated = visitFunctionBody(node.body, functionBodyVisitor, context)!;
return updateBlock(
updated,
setTextRange(
createNodeArray(
insertCaptureNewTargetIfNeeded(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.
@ -3501,9 +3471,7 @@ 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);
}

View File

@ -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() {
}

View File

@ -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;

View File

@ -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;
}
};

View File

@ -12,7 +12,6 @@ class P {
}
//// [thisInConstructorParameter2.js]
var _this = this;
var P = /** @class */ (function () {
function P(z, zz, zzz) {
var _this = this;

View File

@ -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() {

View File

@ -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() {

View File

@ -21,7 +21,6 @@ class Foo {
}
//// [thisInOuterClassBody.js]
var _this = this;
var Foo = /** @class */ (function () {
function Foo() {
this.x = this;

View File

@ -8,7 +8,6 @@ class C2<T> {
}
//// [typeOfThisInStaticMembers2.js]
var _this = this;
var C = /** @class */ (function () {
function C() {
}