Destructuring: Fix handling of impure computed keys with object rest (#9416)
This commit is contained in:
parent
f7bfc774ba
commit
1f5444e96a
@ -19,3 +19,16 @@ key = 2;
|
||||
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"]);
|
||||
|
||||
@ -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
|
||||
@ -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++) {
|
||||
|
||||
@ -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));
|
||||
Loading…
x
Reference in New Issue
Block a user