Skip to content

Commit e345f47

Browse files
committed
Merge branch 'master' into fix11038
2 parents 619e116 + 9950b98 commit e345f47

14 files changed

+150
-23
lines changed

src/compiler/transformers/destructuring.ts

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -126,14 +126,22 @@ namespace ts {
126126
context: TransformationContext,
127127
node: VariableDeclaration,
128128
value?: Expression,
129-
visitor?: (node: Node) => VisitResult<Node>) {
129+
visitor?: (node: Node) => VisitResult<Node>,
130+
recordTempVariable?: (node: Identifier) => void) {
130131
const declarations: VariableDeclaration[] = [];
131132

133+
let pendingAssignments: Expression[];
132134
flattenDestructuring(context, node, value, node, emitAssignment, emitTempVariableAssignment, visitor);
133135

134136
return declarations;
135137

136138
function emitAssignment(name: Identifier, value: Expression, location: TextRange, original: Node) {
139+
if (pendingAssignments) {
140+
pendingAssignments.push(value);
141+
value = inlineExpressions(pendingAssignments);
142+
pendingAssignments = undefined;
143+
}
144+
137145
const declaration = createVariableDeclaration(name, /*type*/ undefined, value, location);
138146
declaration.original = original;
139147

@@ -146,8 +154,19 @@ namespace ts {
146154
}
147155

148156
function emitTempVariableAssignment(value: Expression, location: TextRange) {
149-
const name = createTempVariable(/*recordTempVariable*/ undefined);
150-
emitAssignment(name, value, location, /*original*/ undefined);
157+
const name = createTempVariable(recordTempVariable);
158+
if (recordTempVariable) {
159+
const assignment = createAssignment(name, value, location);
160+
if (pendingAssignments) {
161+
pendingAssignments.push(assignment);
162+
}
163+
else {
164+
pendingAssignments = [assignment];
165+
}
166+
}
167+
else {
168+
emitAssignment(name, value, location, /*original*/ undefined);
169+
}
151170
return name;
152171
}
153172
}

src/compiler/transformers/es6.ts

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@ namespace ts {
163163
let currentText: string;
164164
let currentParent: Node;
165165
let currentNode: Node;
166+
let enclosingVariableStatement: VariableStatement;
166167
let enclosingBlockScopeContainer: Node;
167168
let enclosingBlockScopeContainerParent: Node;
168169
let enclosingFunction: FunctionLikeDeclaration;
@@ -205,6 +206,7 @@ namespace ts {
205206
const savedEnclosingNonAsyncFunctionBody = enclosingNonAsyncFunctionBody;
206207
const savedEnclosingBlockScopeContainer = enclosingBlockScopeContainer;
207208
const savedEnclosingBlockScopeContainerParent = enclosingBlockScopeContainerParent;
209+
const savedEnclosingVariableStatement = enclosingVariableStatement;
208210
const savedCurrentParent = currentParent;
209211
const savedCurrentNode = currentNode;
210212
const savedConvertedLoopState = convertedLoopState;
@@ -222,6 +224,7 @@ namespace ts {
222224
enclosingNonAsyncFunctionBody = savedEnclosingNonAsyncFunctionBody;
223225
enclosingBlockScopeContainer = savedEnclosingBlockScopeContainer;
224226
enclosingBlockScopeContainerParent = savedEnclosingBlockScopeContainerParent;
227+
enclosingVariableStatement = savedEnclosingVariableStatement;
225228
currentParent = savedCurrentParent;
226229
currentNode = savedCurrentNode;
227230
return visited;
@@ -306,7 +309,7 @@ namespace ts {
306309
return visitFunctionExpression(<FunctionExpression>node);
307310

308311
case SyntaxKind.VariableDeclaration:
309-
return visitVariableDeclaration(<VariableDeclaration>node, /*offset*/ undefined);
312+
return visitVariableDeclaration(<VariableDeclaration>node);
310313

311314
case SyntaxKind.Identifier:
312315
return visitIdentifier(<Identifier>node);
@@ -410,6 +413,25 @@ namespace ts {
410413
}
411414
}
412415
}
416+
417+
// keep track of the enclosing variable statement when in the context of
418+
// variable statements, variable declarations, binding elements, and binding
419+
// patterns.
420+
switch (currentNode.kind) {
421+
case SyntaxKind.VariableStatement:
422+
enclosingVariableStatement = <VariableStatement>currentNode;
423+
break;
424+
425+
case SyntaxKind.VariableDeclarationList:
426+
case SyntaxKind.VariableDeclaration:
427+
case SyntaxKind.BindingElement:
428+
case SyntaxKind.ObjectBindingPattern:
429+
case SyntaxKind.ArrayBindingPattern:
430+
break;
431+
432+
default:
433+
enclosingVariableStatement = undefined;
434+
}
413435
}
414436

415437
currentParent = currentNode;
@@ -1309,7 +1331,7 @@ namespace ts {
13091331
return setOriginalNode(
13101332
createFunctionDeclaration(
13111333
/*decorators*/ undefined,
1312-
/*modifiers*/ undefined,
1334+
node.modifiers,
13131335
node.asteriskToken,
13141336
node.name,
13151337
/*typeParameters*/ undefined,
@@ -1638,13 +1660,13 @@ namespace ts {
16381660
*
16391661
* @param node A VariableDeclaration node.
16401662
*/
1641-
function visitVariableDeclarationInLetDeclarationList(node: VariableDeclaration, offset: number) {
1663+
function visitVariableDeclarationInLetDeclarationList(node: VariableDeclaration) {
16421664
// For binding pattern names that lack initializers there is no point to emit
16431665
// explicit initializer since downlevel codegen for destructuring will fail
16441666
// in the absence of initializer so all binding elements will say uninitialized
16451667
const name = node.name;
16461668
if (isBindingPattern(name)) {
1647-
return visitVariableDeclaration(node, offset);
1669+
return visitVariableDeclaration(node);
16481670
}
16491671

16501672
if (!node.initializer && shouldEmitExplicitInitializerForLetDeclaration(node)) {
@@ -1661,10 +1683,13 @@ namespace ts {
16611683
*
16621684
* @param node A VariableDeclaration node.
16631685
*/
1664-
function visitVariableDeclaration(node: VariableDeclaration, offset: number): VisitResult<VariableDeclaration> {
1686+
function visitVariableDeclaration(node: VariableDeclaration): VisitResult<VariableDeclaration> {
16651687
// If we are here it is because the name contains a binding pattern.
16661688
if (isBindingPattern(node.name)) {
1667-
return flattenVariableDestructuring(context, node, /*value*/ undefined, visitor);
1689+
const recordTempVariablesInLine = !enclosingVariableStatement
1690+
|| !hasModifier(enclosingVariableStatement, ModifierFlags.Export);
1691+
return flattenVariableDestructuring(context, node, /*value*/ undefined, visitor,
1692+
recordTempVariablesInLine ? undefined : hoistVariableDeclaration);
16681693
}
16691694

16701695
return visitEachChild(node, visitor, context);
@@ -1740,7 +1765,7 @@ namespace ts {
17401765
// Note also that because an extra statement is needed to assign to the LHS,
17411766
// for-of bodies are always emitted as blocks.
17421767

1743-
const expression = node.expression;
1768+
const expression = visitNode(node.expression, visitor, isExpression);
17441769
const initializer = node.initializer;
17451770
const statements: Statement[] = [];
17461771

@@ -1989,7 +2014,7 @@ namespace ts {
19892014
case SyntaxKind.ForOfStatement:
19902015
const initializer = (<ForStatement | ForInStatement | ForOfStatement>node).initializer;
19912016
if (initializer && initializer.kind === SyntaxKind.VariableDeclarationList) {
1992-
loopInitializer = <VariableDeclarationList>(<ForStatement | ForInStatement | ForOfStatement>node).initializer;
2017+
loopInitializer = <VariableDeclarationList>initializer;
19932018
}
19942019
break;
19952020
}

src/compiler/transformers/generators.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -573,11 +573,11 @@ namespace ts {
573573
operationLocations = undefined;
574574
state = createTempVariable(/*recordTempVariable*/ undefined);
575575

576-
const statementOffset = addPrologueDirectives(statements, body.statements, /*ensureUseStrict*/ false, visitor);
577-
578576
// Build the generator
579577
startLexicalEnvironment();
580578

579+
const statementOffset = addPrologueDirectives(statements, body.statements, /*ensureUseStrict*/ false, visitor);
580+
581581
transformAndEmitStatements(body.statements, statementOffset);
582582

583583
const buildResult = build();
@@ -615,6 +615,11 @@ namespace ts {
615615
return undefined;
616616
}
617617
else {
618+
// Do not hoist custom prologues.
619+
if (node.emitFlags & NodeEmitFlags.CustomPrologue) {
620+
return node;
621+
}
622+
618623
for (const variable of node.declarationList.declarations) {
619624
hoistVariableDeclaration(<Identifier>variable.name);
620625
}

tests/baselines/reference/asyncArrowFunction7_es5.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ var bar = async (): Promise<void> => {
99
//// [asyncArrowFunction7_es5.js]
1010
var _this = this;
1111
var bar = function () { return __awaiter(_this, void 0, void 0, function () {
12-
_this = this;
12+
var _this = this;
1313
var foo;
1414
return __generator(this, function (_a) {
1515
foo = function (a) {
@@ -22,4 +22,4 @@ var bar = function () { return __awaiter(_this, void 0, void 0, function () {
2222
};
2323
return [2 /*return*/];
2424
});
25-
}); var _this; };
25+
}); };

tests/baselines/reference/es6modulekindWithES5Target6.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,15 @@ export default function f3(d = 0) {
1111

1212

1313
//// [es6modulekindWithES5Target6.js]
14-
function f1(d) {
14+
export function f1(d) {
1515
if (d === void 0) { d = 0; }
1616
}
17-
function f2() {
17+
export function f2() {
1818
var arg = [];
1919
for (var _i = 0; _i < arguments.length; _i++) {
2020
arg[_i - 0] = arguments[_i];
2121
}
2222
}
23-
function f3(d) {
23+
export default function f3(d) {
2424
if (d === void 0) { d = 0; }
2525
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
//// [forOfTransformsExpression.ts]
2+
// https://github.com/Microsoft/TypeScript/issues/11024
3+
let items = [{ name: "A" }, { name: "C" }, { name: "B" }];
4+
for (var item of items.sort((a, b) => a.name.localeCompare(b.name))) {
5+
6+
}
7+
8+
//// [forOfTransformsExpression.js]
9+
// https://github.com/Microsoft/TypeScript/issues/11024
10+
var items = [{ name: "A" }, { name: "C" }, { name: "B" }];
11+
for (var _i = 0, _a = items.sort(function (a, b) { return a.name.localeCompare(b.name); }); _i < _a.length; _i++) {
12+
var item = _a[_i];
13+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
=== tests/cases/compiler/forOfTransformsExpression.ts ===
2+
// https://github.com/Microsoft/TypeScript/issues/11024
3+
let items = [{ name: "A" }, { name: "C" }, { name: "B" }];
4+
>items : Symbol(items, Decl(forOfTransformsExpression.ts, 1, 3))
5+
>name : Symbol(name, Decl(forOfTransformsExpression.ts, 1, 14))
6+
>name : Symbol(name, Decl(forOfTransformsExpression.ts, 1, 29))
7+
>name : Symbol(name, Decl(forOfTransformsExpression.ts, 1, 44))
8+
9+
for (var item of items.sort((a, b) => a.name.localeCompare(b.name))) {
10+
>item : Symbol(item, Decl(forOfTransformsExpression.ts, 2, 8))
11+
>items.sort : Symbol(Array.sort, Decl(lib.d.ts, --, --))
12+
>items : Symbol(items, Decl(forOfTransformsExpression.ts, 1, 3))
13+
>sort : Symbol(Array.sort, Decl(lib.d.ts, --, --))
14+
>a : Symbol(a, Decl(forOfTransformsExpression.ts, 2, 29))
15+
>b : Symbol(b, Decl(forOfTransformsExpression.ts, 2, 31))
16+
>a.name.localeCompare : Symbol(String.localeCompare, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
17+
>a.name : Symbol(name, Decl(forOfTransformsExpression.ts, 1, 14))
18+
>a : Symbol(a, Decl(forOfTransformsExpression.ts, 2, 29))
19+
>name : Symbol(name, Decl(forOfTransformsExpression.ts, 1, 14))
20+
>localeCompare : Symbol(String.localeCompare, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
21+
>b.name : Symbol(name, Decl(forOfTransformsExpression.ts, 1, 14))
22+
>b : Symbol(b, Decl(forOfTransformsExpression.ts, 2, 31))
23+
>name : Symbol(name, Decl(forOfTransformsExpression.ts, 1, 14))
24+
25+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
=== tests/cases/compiler/forOfTransformsExpression.ts ===
2+
// https://github.com/Microsoft/TypeScript/issues/11024
3+
let items = [{ name: "A" }, { name: "C" }, { name: "B" }];
4+
>items : { name: string; }[]
5+
>[{ name: "A" }, { name: "C" }, { name: "B" }] : { name: string; }[]
6+
>{ name: "A" } : { name: string; }
7+
>name : string
8+
>"A" : "A"
9+
>{ name: "C" } : { name: string; }
10+
>name : string
11+
>"C" : "C"
12+
>{ name: "B" } : { name: string; }
13+
>name : string
14+
>"B" : "B"
15+
16+
for (var item of items.sort((a, b) => a.name.localeCompare(b.name))) {
17+
>item : { name: string; }
18+
>items.sort((a, b) => a.name.localeCompare(b.name)) : { name: string; }[]
19+
>items.sort : (compareFn?: (a: { name: string; }, b: { name: string; }) => number) => { name: string; }[]
20+
>items : { name: string; }[]
21+
>sort : (compareFn?: (a: { name: string; }, b: { name: string; }) => number) => { name: string; }[]
22+
>(a, b) => a.name.localeCompare(b.name) : (a: { name: string; }, b: { name: string; }) => number
23+
>a : { name: string; }
24+
>b : { name: string; }
25+
>a.name.localeCompare(b.name) : number
26+
>a.name.localeCompare : { (that: string): number; (that: string, locales?: string | string[], options?: Intl.CollatorOptions): number; }
27+
>a.name : string
28+
>a : { name: string; }
29+
>name : string
30+
>localeCompare : { (that: string): number; (that: string, locales?: string | string[], options?: Intl.CollatorOptions): number; }
31+
>b.name : string
32+
>b : { name: string; }
33+
>name : string
34+
35+
}

tests/baselines/reference/functionsWithModifiersInBlocks1.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,5 @@
77

88
//// [functionsWithModifiersInBlocks1.js]
99
{
10-
function f() { }
10+
export function f() { }
1111
}

tests/baselines/reference/moduleElementsInWrongContext.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
return C;
4646
}());
4747
export default C;
48-
function bee() { }
48+
export function bee() { }
4949
import I2 = require("foo");
5050
import * as Foo from "ambient";
5151
import bar from "ambient";

tests/baselines/reference/moduleElementsInWrongContext2.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ function blah() {
4545
return C;
4646
}());
4747
export default C;
48-
function bee() { }
48+
export function bee() { }
4949
import I2 = require("foo");
5050
import * as Foo from "ambient";
5151
import bar from "ambient";

tests/baselines/reference/parserModifierOnStatementInBlock3.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ export function foo() {
88
//// [parserModifierOnStatementInBlock3.js]
99
"use strict";
1010
function foo() {
11-
function bar() {
11+
export function bar() {
1212
}
1313
}
1414
exports.foo = foo;

tests/baselines/reference/parserModifierOnStatementInBlock4.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,6 @@
77

88
//// [parserModifierOnStatementInBlock4.js]
99
{
10-
function bar() {
10+
export function bar() {
1111
}
1212
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// https://github.com/Microsoft/TypeScript/issues/11024
2+
let items = [{ name: "A" }, { name: "C" }, { name: "B" }];
3+
for (var item of items.sort((a, b) => a.name.localeCompare(b.name))) {
4+
5+
}

0 commit comments

Comments
 (0)