Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 22 additions & 3 deletions src/compiler/transformers/destructuring.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,14 +126,22 @@ namespace ts {
context: TransformationContext,
node: VariableDeclaration,
value?: Expression,
visitor?: (node: Node) => VisitResult<Node>) {
visitor?: (node: Node) => VisitResult<Node>,
recordTempVariable?: (node: Identifier) => void) {
const declarations: VariableDeclaration[] = [];

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

return declarations;

function emitAssignment(name: Identifier, value: Expression, location: TextRange, original: Node) {
if (pendingAssignments) {
pendingAssignments.push(value);
value = inlineExpressions(pendingAssignments);
pendingAssignments = undefined;
}

const declaration = createVariableDeclaration(name, /*type*/ undefined, value, location);
declaration.original = original;

Expand All @@ -146,8 +154,19 @@ namespace ts {
}

function emitTempVariableAssignment(value: Expression, location: TextRange) {
const name = createTempVariable(/*recordTempVariable*/ undefined);
emitAssignment(name, value, location, /*original*/ undefined);
const name = createTempVariable(recordTempVariable);
if (recordTempVariable) {
const assignment = createAssignment(name, value, location);
if (pendingAssignments) {
pendingAssignments.push(assignment);
}
else {
pendingAssignments = [assignment];
}
}
else {
emitAssignment(name, value, location, /*original*/ undefined);
}
return name;
}
}
Expand Down
37 changes: 31 additions & 6 deletions src/compiler/transformers/es6.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ namespace ts {
let currentText: string;
let currentParent: Node;
let currentNode: Node;
let enclosingVariableStatement: VariableStatement;
let enclosingBlockScopeContainer: Node;
let enclosingBlockScopeContainerParent: Node;
let containingNonArrowFunction: FunctionLikeDeclaration | ClassElement;
Expand Down Expand Up @@ -210,6 +211,7 @@ namespace ts {
const savedSuperScopeContainer = superScopeContainer;
const savedCurrentParent = currentParent;
const savedCurrentNode = currentNode;
const savedEnclosingVariableStatement = enclosingVariableStatement;
const savedEnclosingBlockScopeContainer = enclosingBlockScopeContainer;
const savedEnclosingBlockScopeContainerParent = enclosingBlockScopeContainerParent;

Expand All @@ -227,6 +229,7 @@ namespace ts {
superScopeContainer = savedSuperScopeContainer;
currentParent = savedCurrentParent;
currentNode = savedCurrentNode;
enclosingVariableStatement = savedEnclosingVariableStatement;
enclosingBlockScopeContainer = savedEnclosingBlockScopeContainer;
enclosingBlockScopeContainerParent = savedEnclosingBlockScopeContainerParent;
return visited;
Expand Down Expand Up @@ -320,7 +323,7 @@ namespace ts {
return visitFunctionExpression(<FunctionExpression>node);

case SyntaxKind.VariableDeclaration:
return visitVariableDeclaration(<VariableDeclaration>node, /*offset*/ undefined);
return visitVariableDeclaration(<VariableDeclaration>node);

case SyntaxKind.Identifier:
return visitIdentifier(<Identifier>node);
Expand Down Expand Up @@ -432,6 +435,25 @@ namespace ts {
}
break;
}

// keep track of the enclosing variable statement when in the context of
// variable statements, variable declarations, binding elements, and binding
// patterns.
switch (currentParent.kind) {
case SyntaxKind.VariableStatement:
enclosingVariableStatement = <VariableStatement>currentParent;
break;

case SyntaxKind.VariableDeclarationList:
case SyntaxKind.VariableDeclaration:
case SyntaxKind.BindingElement:
case SyntaxKind.ObjectBindingPattern:
case SyntaxKind.ArrayBindingPattern:
break;

default:
enclosingVariableStatement = undefined;
}
}
}

Expand Down Expand Up @@ -1334,7 +1356,7 @@ namespace ts {
return setOriginalNode(
createFunctionDeclaration(
/*decorators*/ undefined,
/*modifiers*/ undefined,
node.modifiers,
node.asteriskToken,
node.name,
/*typeParameters*/ undefined,
Expand Down Expand Up @@ -1663,13 +1685,13 @@ namespace ts {
*
* @param node A VariableDeclaration node.
*/
function visitVariableDeclarationInLetDeclarationList(node: VariableDeclaration, offset: number) {
function visitVariableDeclarationInLetDeclarationList(node: VariableDeclaration) {
// For binding pattern names that lack initializers there is no point to emit
// explicit initializer since downlevel codegen for destructuring will fail
// in the absence of initializer so all binding elements will say uninitialized
const name = node.name;
if (isBindingPattern(name)) {
return visitVariableDeclaration(node, offset);
return visitVariableDeclaration(node);
}

if (!node.initializer && shouldEmitExplicitInitializerForLetDeclaration(node)) {
Expand All @@ -1686,10 +1708,13 @@ namespace ts {
*
* @param node A VariableDeclaration node.
*/
function visitVariableDeclaration(node: VariableDeclaration, offset: number): VisitResult<VariableDeclaration> {
function visitVariableDeclaration(node: VariableDeclaration): VisitResult<VariableDeclaration> {
// If we are here it is because the name contains a binding pattern.
if (isBindingPattern(node.name)) {
return flattenVariableDestructuring(context, node, /*value*/ undefined, visitor);
const recordTempVariablesInLine = !enclosingVariableStatement
|| !hasModifier(enclosingVariableStatement, ModifierFlags.Export);
return flattenVariableDestructuring(context, node, /*value*/ undefined, visitor,
recordTempVariablesInLine ? undefined : hoistVariableDeclaration);
}

return visitEachChild(node, visitor, context);
Expand Down
6 changes: 3 additions & 3 deletions tests/baselines/reference/es6modulekindWithES5Target6.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@ export default function f3(d = 0) {


//// [es6modulekindWithES5Target6.js]
function f1(d) {
export function f1(d) {
if (d === void 0) { d = 0; }
}
function f2() {
export function f2() {
var arg = [];
for (var _i = 0; _i < arguments.length; _i++) {
arg[_i - 0] = arguments[_i];
}
}
function f3(d) {
export default function f3(d) {
if (d === void 0) { d = 0; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@

//// [functionsWithModifiersInBlocks1.js]
{
function f() { }
export function f() { }
}
2 changes: 1 addition & 1 deletion tests/baselines/reference/moduleElementsInWrongContext.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
return C;
}());
export default C;
function bee() { }
export function bee() { }
import I2 = require("foo");
import * as Foo from "ambient";
import bar from "ambient";
Expand Down
2 changes: 1 addition & 1 deletion tests/baselines/reference/moduleElementsInWrongContext2.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ function blah() {
return C;
}());
export default C;
function bee() { }
export function bee() { }
import I2 = require("foo");
import * as Foo from "ambient";
import bar from "ambient";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export function foo() {
//// [parserModifierOnStatementInBlock3.js]
"use strict";
function foo() {
function bar() {
export function bar() {
}
}
exports.foo = foo;
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@

//// [parserModifierOnStatementInBlock4.js]
{
function bar() {
export function bar() {
}
}