Skip to content

Commit

Permalink
Destructuring: Fix handling of impure computed keys with object rest (b…
Browse files Browse the repository at this point in the history
  • Loading branch information
motiz88 authored and danez committed Mar 27, 2019
1 parent 31ec26e commit 6b26892
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 0 deletions.
38 changes: 38 additions & 0 deletions src/index.js
Expand Up @@ -44,6 +44,19 @@ export default declare((api, options) => {
return false;
}

/**
* Test if an ObjectPattern's elements contain any RestElements.
*/

function hasObjectRest(pattern) {
for (const elem of (pattern.properties: Array)) {
if (t.isRestElement(elem)) {
return true;
}
}
return false;
}

const STOP_TRAVERSAL = {};

// NOTE: This visitor is meant to be used via t.traverse
Expand Down Expand Up @@ -263,6 +276,31 @@ export default declare((api, options) => {
objRef = temp;
}

// Replace impure computed key expressions if we have a rest parameter
if (hasObjectRest(pattern)) {
let copiedPattern;
for (let i = 0; i < pattern.properties.length; i++) {
const prop = pattern.properties[i];
if (t.isRestElement(prop)) {
break;
}
const key = prop.key;
if (prop.computed && !this.scope.isPure(key)) {
const name = this.scope.generateUidIdentifierBasedOnNode(key);
this.nodes.push(this.buildVariableDeclaration(name, key));
if (!copiedPattern) {
copiedPattern = pattern = {
...pattern,
properties: pattern.properties.slice(),
};
}
copiedPattern.properties[i] = {
...copiedPattern.properties[i],
key: name,
};
}
}
}
//

for (let i = 0; i < pattern.properties.length; i++) {
Expand Down
@@ -0,0 +1,34 @@
var key, x, y, z;
// impure
key = 1;
var { [key++]: y, ...x } = { 1: 1, a: 1 };
expect(x).toEqual({ a: 1 });
expect(key).toBe(2);
expect(1).toBe(y);

// takes care of the order

key = 1;
var { [++key]: y, [++key]: z, ...rest} = {2: 2, 3: 3};
expect(y).toBe(2);
expect(z).toBe(3);

// pure, computed property should remain as-is
key = 2;
({ [key]: y, z, ...x } = {2: "two", z: "zee"});
expect(y).toBe("two");
expect(x).toEqual({});
expect(z).toBe("zee");

// rhs evaluated before lhs
var order = [];
function left() {
order.push("left");
return 0;
}
function right() {
order.push("right");
return {};
}
var { [left()]: y, ...x} = right();
expect(order).toEqual(["right", "left"]);
@@ -0,0 +1 @@
var { [fn()]: x, ...y } = z;
@@ -0,0 +1,4 @@
var _z = z,
_fn = fn(),
x = _z[_fn],
y = babelHelpers.objectWithoutProperties(_z, [_fn].map(babelHelpers.toPropertyKey));

0 comments on commit 6b26892

Please sign in to comment.