Skip to content

Commit 86242ee

Browse files
committed
Always use same code path when transforming function bodies for es2015
1 parent b02dab4 commit 86242ee

9 files changed

+26
-56
lines changed

src/compiler/transformers/es2015.ts

Lines changed: 14 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -345,13 +345,6 @@ namespace ts {
345345
}
346346
}
347347

348-
function functionBodyVisitor(node: Block): Block {
349-
if (shouldVisitNode(node)) {
350-
return visitBlock(node, /*isFunctionBody*/ true);
351-
}
352-
return node;
353-
}
354-
355348
function callExpressionVisitor(node: Node): VisitResult<Node> {
356349
if (node.kind === SyntaxKind.SuperKeyword) {
357350
return visitSuperKeyword(/*isExpressionOfCall*/ true);
@@ -507,15 +500,15 @@ namespace ts {
507500
const statements: Statement[] = [];
508501
startLexicalEnvironment();
509502
let statementOffset = addStandardPrologue(prologue, node.statements, /*ensureUseStrict*/ false);
510-
insertCaptureThisForNodeIfNeeded(prologue, node);
511503
statementOffset = addCustomPrologue(prologue, node.statements, statementOffset, visitor);
512504
addRange(statements, visitNodes(node.statements, visitor, isStatement, statementOffset));
513505
if (taggedTemplateStringDeclarations) {
514506
statements.push(
515507
createVariableStatement(/*modifiers*/ undefined,
516508
createVariableDeclarationList(taggedTemplateStringDeclarations)));
517509
}
518-
insertStatementsAfterStandardPrologue(prologue, endLexicalEnvironment());
510+
mergeLexicalEnvironment(prologue, endLexicalEnvironment());
511+
insertCaptureThisForNodeIfNeeded(prologue, node);
519512
exitSubtree(ancestorFacts, HierarchyFacts.None, HierarchyFacts.None);
520513
return updateSourceFileNode(
521514
node,
@@ -1194,11 +1187,6 @@ namespace ts {
11941187
|| isBindingPattern(node.name);
11951188
}
11961189

1197-
function hasDefaultValueOrBindingPatternOrRest(node: ParameterDeclaration) {
1198-
return hasDefaultValueOrBindingPattern(node)
1199-
|| node.dotDotDotToken !== undefined;
1200-
}
1201-
12021190
/**
12031191
* Adds statements to the body of a function-like node if it contains parameters with
12041192
* binding patterns or initializers.
@@ -1446,12 +1434,13 @@ namespace ts {
14461434

14471435
/**
14481436
* Adds a statement to capture the `this` of a function declaration if it is needed.
1437+
* NOTE: This must be executed *after* the subtree has been visited.
14491438
*
14501439
* @param statements The statements for the new function body.
14511440
* @param node A node.
14521441
*/
14531442
function insertCaptureThisForNodeIfNeeded(statements: Statement[], node: Node): boolean {
1454-
if (node.transformFlags & TransformFlags.ContainsCapturedLexicalThis && node.kind !== SyntaxKind.ArrowFunction) {
1443+
if (hierarchyFacts & HierarchyFacts.CapturedLexicalThis && node.kind !== SyntaxKind.ArrowFunction) {
14551444
insertCaptureThisForNode(statements, node, createThis());
14561445
return true;
14571446
}
@@ -1731,10 +1720,6 @@ namespace ts {
17311720
return func;
17321721
}
17331722

1734-
function containsCapturedLexicalThis(node: Node) {
1735-
return (node.transformFlags & TransformFlags.ContainsCapturedLexicalThis) !== 0;
1736-
}
1737-
17381723
/**
17391724
* Visits a FunctionExpression node.
17401725
*
@@ -1748,11 +1733,7 @@ namespace ts {
17481733
convertedLoopState = undefined;
17491734

17501735
const parameters = visitParameterList(node.parameters, visitor, context);
1751-
const shouldTransform = forEachChild(node, containsCapturedLexicalThis)
1752-
|| some(node.parameters, hasDefaultValueOrBindingPatternOrRest);
1753-
const body = shouldTransform
1754-
? transformFunctionBody(node)
1755-
: visitFunctionBodyDownLevel(node);
1736+
const body = transformFunctionBody(node);
17561737
const name = hierarchyFacts & HierarchyFacts.NewTarget
17571738
? getLocalName(node)
17581739
: node.name;
@@ -1781,11 +1762,7 @@ namespace ts {
17811762
convertedLoopState = undefined;
17821763
const ancestorFacts = enterSubtree(HierarchyFacts.FunctionExcludes, HierarchyFacts.FunctionIncludes);
17831764
const parameters = visitParameterList(node.parameters, visitor, context);
1784-
const shouldTransform = forEachChild(node, containsCapturedLexicalThis)
1785-
|| some(node.parameters, hasDefaultValueOrBindingPatternOrRest);
1786-
const body = shouldTransform
1787-
? transformFunctionBody(node)
1788-
: visitFunctionBodyDownLevel(node);
1765+
const body = transformFunctionBody(node);
17891766
const name = hierarchyFacts & HierarchyFacts.NewTarget
17901767
? getLocalName(node)
17911768
: node.name;
@@ -1921,7 +1898,13 @@ namespace ts {
19211898
multiLine = true;
19221899
}
19231900

1924-
const block = createBlock(setTextRange(createNodeArray(concatenate(prologue, statements)), statementsLocation), multiLine);
1901+
statements.unshift(...prologue);
1902+
if (isBlock(body) && arrayIsEqualTo(statements, body.statements)) {
1903+
// no changes were made, preserve the tree
1904+
return body;
1905+
}
1906+
1907+
const block = createBlock(setTextRange(createNodeArray(statements), statementsLocation), multiLine);
19251908
setTextRange(block, node.body);
19261909
if (!multiLine && singleLine) {
19271910
setEmitFlags(block, EmitFlags.SingleLine);
@@ -1935,19 +1918,6 @@ namespace ts {
19351918
return block;
19361919
}
19371920

1938-
function visitFunctionBodyDownLevel(node: FunctionDeclaration | FunctionExpression | AccessorDeclaration) {
1939-
const updated = visitFunctionBody(node.body, functionBodyVisitor, context)!;
1940-
return updateBlock(
1941-
updated,
1942-
setTextRange(
1943-
createNodeArray(
1944-
insertCaptureNewTargetIfNeeded(updated.statements as MutableNodeArray<Statement>, node, /*copyOnWrite*/ true)
1945-
),
1946-
/*location*/ updated.statements
1947-
)
1948-
);
1949-
}
1950-
19511921
function visitBlock(node: Block, isFunctionBody: boolean): Block {
19521922
if (isFunctionBody) {
19531923
// A function body is not a block scope.
@@ -3501,9 +3471,7 @@ namespace ts {
35013471
const ancestorFacts = enterSubtree(HierarchyFacts.FunctionExcludes, HierarchyFacts.FunctionIncludes);
35023472
let updated: AccessorDeclaration;
35033473
const parameters = visitParameterList(node.parameters, visitor, context);
3504-
const body = node.transformFlags & (TransformFlags.ContainsCapturedLexicalThis | TransformFlags.ContainsES2015)
3505-
? transformFunctionBody(node)
3506-
: visitFunctionBodyDownLevel(node);
3474+
const body = transformFunctionBody(node);
35073475
if (node.kind === SyntaxKind.GetAccessor) {
35083476
updated = updateGetAccessor(node, node.decorators, node.modifiers, node.name, parameters, node.type, body);
35093477
}

tests/baselines/reference/decoratorOnClassMethod11.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
1717
};
1818
var M;
1919
(function (M) {
20-
var _this = this;
2120
var C = /** @class */ (function () {
2221
function C() {
2322
}

tests/baselines/reference/dynamicImportWithNestedThis_es5.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ c.dynamic();
3030
}
3131
C.prototype.dynamic = function () {
3232
var _a;
33-
var _this = this;
3433
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); });
3534
};
3635
return C;

tests/baselines/reference/newTarget.es5.js

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,17 @@ var __extends = (this && this.__extends) || (function () {
4949
var A = /** @class */ (function () {
5050
function A() {
5151
var _newTarget = this.constructor;
52-
this.d = function _a() { var _newTarget = this && this instanceof _a ? this.constructor : void 0; return _newTarget; };
52+
this.d = function _a() {
53+
var _newTarget = this && this instanceof _a ? this.constructor : void 0;
54+
return _newTarget;
55+
};
5356
var a = _newTarget;
5457
var b = function () { return _newTarget; };
5558
}
56-
A.c = function _a() { var _newTarget = this && this instanceof _a ? this.constructor : void 0; return _newTarget; };
59+
A.c = function _a() {
60+
var _newTarget = this && this instanceof _a ? this.constructor : void 0;
61+
return _newTarget;
62+
};
5763
return A;
5864
}());
5965
var B = /** @class */ (function (_super) {
@@ -78,5 +84,8 @@ var f2 = function _b() {
7884
var j = function () { return _newTarget; };
7985
};
8086
var O = {
81-
k: function k() { var _newTarget = this && this instanceof k ? this.constructor : void 0; return _newTarget; }
87+
k: function k() {
88+
var _newTarget = this && this instanceof k ? this.constructor : void 0;
89+
return _newTarget;
90+
}
8291
};

tests/baselines/reference/thisInConstructorParameter2.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ class P {
1212
}
1313

1414
//// [thisInConstructorParameter2.js]
15-
var _this = this;
1615
var P = /** @class */ (function () {
1716
function P(z, zz, zzz) {
1817
var _this = this;

tests/baselines/reference/thisInInvalidContexts.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,6 @@ var __extends = (this && this.__extends) || (function () {
6262
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
6363
};
6464
})();
65-
var _this = this;
6665
//'this' in static member initializer
6766
var ErrClass1 = /** @class */ (function () {
6867
function ErrClass1() {

tests/baselines/reference/thisInInvalidContextsExternalModule.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,6 @@ var __extends = (this && this.__extends) || (function () {
6363
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
6464
};
6565
})();
66-
var _this = this;
6766
//'this' in static member initializer
6867
var ErrClass1 = /** @class */ (function () {
6968
function ErrClass1() {

tests/baselines/reference/thisInOuterClassBody.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ class Foo {
2121
}
2222

2323
//// [thisInOuterClassBody.js]
24-
var _this = this;
2524
var Foo = /** @class */ (function () {
2625
function Foo() {
2726
this.x = this;

tests/baselines/reference/typeOfThisInStaticMembers2.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ class C2<T> {
88
}
99

1010
//// [typeOfThisInStaticMembers2.js]
11-
var _this = this;
1211
var C = /** @class */ (function () {
1312
function C() {
1413
}

0 commit comments

Comments
 (0)