Skip to content

Commit

Permalink
Properly emit nested destructuring in rest elements (fixes #2587)
Browse files Browse the repository at this point in the history
  • Loading branch information
JsonFreeman committed Apr 14, 2015
1 parent 051aa39 commit 2b83dfb
Show file tree
Hide file tree
Showing 14 changed files with 63 additions and 49 deletions.
22 changes: 14 additions & 8 deletions src/compiler/emitter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2558,14 +2558,24 @@ var __param = this.__param || function(index, decorator) { return function (targ
return node;
}

function createPropertyAccessForDestructuringProperty(object: Expression, propName: Identifier): Expression {
function createPropertyAccessForDestructuringProperty(object: Expression, propName: Identifier | LiteralExpression): Expression {
if (propName.kind !== SyntaxKind.Identifier) {
return createElementAccessExpression(object, propName);
}

return createPropertyAccessExpression(object, propName);
}

function createSliceCall(value: Expression, sliceIndex: number): CallExpression {
let call = <CallExpression>createSynthesizedNode(SyntaxKind.CallExpression);
let sliceIdentifier = <Identifier>createSynthesizedNode(SyntaxKind.Identifier);
sliceIdentifier.text = "slice";
call.expression = createPropertyAccessExpression(value, sliceIdentifier);
call.arguments = <NodeArray<LiteralExpression>>createSynthesizedNodeArray();
call.arguments[0] = createNumericLiteral(sliceIndex);
return call;
}

function emitObjectLiteralAssignment(target: ObjectLiteralExpression, value: Expression) {
let properties = target.properties;
if (properties.length !== 1) {
Expand All @@ -2576,7 +2586,7 @@ var __param = this.__param || function(index, decorator) { return function (targ
for (let p of properties) {
if (p.kind === SyntaxKind.PropertyAssignment || p.kind === SyntaxKind.ShorthandPropertyAssignment) {
// TODO(andersh): Computed property support
let propName = <Identifier>((<PropertyAssignment>p).name);
let propName = <Identifier | LiteralExpression>((<PropertyAssignment>p).name);
emitDestructuringAssignment((<PropertyAssignment>p).initializer || propName, createPropertyAccessForDestructuringProperty(value, propName));
}
}
Expand All @@ -2596,9 +2606,7 @@ var __param = this.__param || function(index, decorator) { return function (targ
emitDestructuringAssignment(e, createElementAccessExpression(value, createNumericLiteral(i)));
}
else if (i === elements.length - 1) {
value = ensureIdentifier(value);
emitAssignment(<Identifier>(<SpreadElementExpression>e).expression, value);
write(".slice(" + i + ")");
emitDestructuringAssignment((<SpreadElementExpression>e).expression, createSliceCall(value, i));
}
}
}
Expand Down Expand Up @@ -2670,9 +2678,7 @@ var __param = this.__param || function(index, decorator) { return function (targ
emitBindingElement(element, createElementAccessExpression(value, createNumericLiteral(i)));
}
else if (i === elements.length - 1) {
value = ensureIdentifier(value);
emitAssignment(<Identifier>element.name, value);
write(".slice(" + i + ")");
emitBindingElement(element, createSliceCall(value, i));
}
}
}
Expand Down
7 changes: 7 additions & 0 deletions src/compiler/utilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1379,6 +1379,13 @@ module ts {
return node;
}

export function createSynthesizedNodeArray(): NodeArray<any> {
var array = <NodeArray<any>>[];
array.pos = -1;
array.end = -1;
return array;
}

/* @internal */
export function createDiagnosticCollection(): DiagnosticCollection {
let nonFileDiagnostics: Diagnostic[] = [];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@ var [x18, y18, ...a12] = [1, "hello", true];
var [x19, y19, z19, ...a13] = [1, "hello", true];

//// [declarationEmitDestructuringArrayPattern4.js]
var _a = [1, 2, 3], a5 = _a.slice(0);
var _b = [1, 2, 3], x14 = _b[0], a6 = _b.slice(1);
var _c = [1, 2, 3], x15 = _c[0], y15 = _c[1], a7 = _c.slice(2);
var _d = [1, 2, 3], x16 = _d[0], y16 = _d[1], z16 = _d[2], a8 = _d.slice(3);
var _e = [1, "hello", true], a9 = _e.slice(0);
var _f = [1, "hello", true], x17 = _f[0], a10 = _f.slice(1);
var _g = [1, "hello", true], x18 = _g[0], y18 = _g[1], a12 = _g.slice(2);
var _h = [1, "hello", true], x19 = _h[0], y19 = _h[1], z19 = _h[2], a13 = _h.slice(3);
var a5 = ([1, 2, 3]).slice(0);
var _a = [1, 2, 3], x14 = _a[0], a6 = _a.slice(1);
var _b = [1, 2, 3], x15 = _b[0], y15 = _b[1], a7 = _b.slice(2);
var _c = [1, 2, 3], x16 = _c[0], y16 = _c[1], z16 = _c[2], a8 = _c.slice(3);
var a9 = ([1, "hello", true]).slice(0);
var _d = [1, "hello", true], x17 = _d[0], a10 = _d.slice(1);
var _e = [1, "hello", true], x18 = _e[0], y18 = _e[1], a12 = _e.slice(2);
var _f = [1, "hello", true], x19 = _f[0], y19 = _f[1], z19 = _f[2], a13 = _f.slice(3);


//// [declarationEmitDestructuringArrayPattern4.d.ts]
Expand Down
36 changes: 18 additions & 18 deletions tests/baselines/reference/declarationsAndAssignments.js
Original file line number Diff line number Diff line change
Expand Up @@ -321,28 +321,28 @@ function f20() {
var x;
var y;
var z;
var _a = [1, 2, 3], a = _a.slice(0);
var _b = [1, 2, 3], x = _b[0], a = _b.slice(1);
var _c = [1, 2, 3], x = _c[0], y = _c[1], a = _c.slice(2);
var _d = [1, 2, 3], x = _d[0], y = _d[1], z = _d[2], a = _d.slice(3);
_e = [1, 2, 3], a = _e.slice(0);
_f = [1, 2, 3], x = _f[0], a = _f.slice(1);
_g = [1, 2, 3], x = _g[0], y = _g[1], a = _g.slice(2);
_h = [1, 2, 3], x = _h[0], y = _h[1], z = _h[2], a = _h.slice(3);
var _e, _f, _g, _h;
var a = ([1, 2, 3]).slice(0);
var _a = [1, 2, 3], x = _a[0], a = _a.slice(1);
var _b = [1, 2, 3], x = _b[0], y = _b[1], a = _b.slice(2);
var _c = [1, 2, 3], x = _c[0], y = _c[1], z = _c[2], a = _c.slice(3);
a = ([1, 2, 3]).slice(0);
_d = [1, 2, 3], x = _d[0], a = _d.slice(1);
_e = [1, 2, 3], x = _e[0], y = _e[1], a = _e.slice(2);
_f = [1, 2, 3], x = _f[0], y = _f[1], z = _f[2], a = _f.slice(3);
var _d, _e, _f;
}
function f21() {
var a;
var x;
var y;
var z;
var _a = [1, "hello", true], a = _a.slice(0);
var _b = [1, "hello", true], x = _b[0], a = _b.slice(1);
var _c = [1, "hello", true], x = _c[0], y = _c[1], a = _c.slice(2);
var _d = [1, "hello", true], x = _d[0], y = _d[1], z = _d[2], a = _d.slice(3);
_e = [1, "hello", true], a = _e.slice(0);
_f = [1, "hello", true], x = _f[0], a = _f.slice(1);
_g = [1, "hello", true], x = _g[0], y = _g[1], a = _g.slice(2);
_h = [1, "hello", true], x = _h[0], y = _h[1], z = _h[2], a = _h.slice(3);
var _e, _f, _g, _h;
var a = ([1, "hello", true]).slice(0);
var _a = [1, "hello", true], x = _a[0], a = _a.slice(1);
var _b = [1, "hello", true], x = _b[0], y = _b[1], a = _b.slice(2);
var _c = [1, "hello", true], x = _c[0], y = _c[1], z = _c[2], a = _c.slice(3);
a = ([1, "hello", true]).slice(0);
_d = [1, "hello", true], x = _d[0], a = _d.slice(1);
_e = [1, "hello", true], x = _e[0], y = _e[1], a = _e.slice(2);
_f = [1, "hello", true], x = _f[0], y = _f[1], z = _f[2], a = _f.slice(3);
var _d, _e, _f;
}
3 changes: 1 addition & 2 deletions tests/baselines/reference/nonIterableRestElement1.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,4 @@ var c = {};

//// [nonIterableRestElement1.js]
var c = {};
_a = ["", 0], c = _a.slice(0);
var _a;
c = (["", 0]).slice(0);
3 changes: 1 addition & 2 deletions tests/baselines/reference/nonIterableRestElement3.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,4 @@ var c = { bogus: 0 };

//// [nonIterableRestElement3.js]
var c = { bogus: 0 };
_a = ["", 0], c = _a.slice(0);
var _a;
c = (["", 0]).slice(0);
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ var tuple: [string, number] = ["", 1];
//// [restElementWithAssignmentPattern3.js]
var a, b;
var tuple = ["", 1];
[a, b = 0] = tuple.slice(0);
_a = tuple.slice(0), a = _a[0], _b = _a[1], b = _b === void 0 ? 0 : _b;
var _a, _b;
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ var tuple: [string, number] = ["", 1];
//// [restElementWithAssignmentPattern4.js]
var a, b;
var tuple = ["", 1];
{ 0: a = "", b: b } = tuple.slice(0);
_a = tuple.slice(0), _b = _a[0], a = _b === void 0 ? "" : _b, b = _a.b;
var _a, _b;
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@ var s: string, s2: string;

//// [restElementWithAssignmentPattern5.js]
var s, s2;
_a = ["", ""], [s, s2] = _a.slice(0);
_a = (["", ""]).slice(0), s = _a[0], s2 = _a[1];
var _a;
2 changes: 1 addition & 1 deletion tests/baselines/reference/restElementWithBindingPattern.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
var [...[a, b]] = [0, 1];

//// [restElementWithBindingPattern.js]
var _a = [0, 1], [a, b] = _a.slice(0);
var _a = ([0, 1]).slice(0), a = _a[0], b = _a[1];
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
var [...{0: a, b }] = [0, 1];

//// [restElementWithBindingPattern2.js]
var _a = [0, 1], { 0: a, b } = _a.slice(0);
var _a = ([0, 1]).slice(0), a = _a[0], b = _a.b;
2 changes: 1 addition & 1 deletion tests/baselines/reference/restElementWithInitializer1.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ var [...x = a] = a; // Error, rest element cannot have initializer

//// [restElementWithInitializer1.js]
var a;
var x = a.slice(0); // Error, rest element cannot have initializer
var _a = a.slice(0), x = _a === void 0 ? a : _a; // Error, rest element cannot have initializer
3 changes: 2 additions & 1 deletion tests/baselines/reference/restElementWithInitializer2.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ var x: number[];
//// [restElementWithInitializer2.js]
var a;
var x;
x = a = a.slice(0); // Error, rest element cannot have initializer
_a = a.slice(0), x = _a === void 0 ? a : _a; // Error, rest element cannot have initializer
var _a;
8 changes: 4 additions & 4 deletions tests/baselines/reference/restElementWithNullInitializer.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@ function foo4([...r] = []) {

//// [restElementWithNullInitializer.js]
function foo1(_a) {
var _b = _a === void 0 ? null : _a, r = _b.slice(0);
var r = (_a === void 0 ? null : _a).slice(0);
}
function foo2(_a) {
var _b = _a === void 0 ? undefined : _a, r = _b.slice(0);
var r = (_a === void 0 ? undefined : _a).slice(0);
}
function foo3(_a) {
var _b = _a === void 0 ? {} : _a, r = _b.slice(0);
var r = (_a === void 0 ? {} : _a).slice(0);
}
function foo4(_a) {
var _b = _a === void 0 ? [] : _a, r = _b.slice(0);
var r = (_a === void 0 ? [] : _a).slice(0);
}

0 comments on commit 2b83dfb

Please sign in to comment.