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(y).toBe("two");
|
||||||
expect(x).toEqual({});
|
expect(x).toEqual({});
|
||||||
expect(z).toBe("zee");
|
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;
|
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 = {};
|
const STOP_TRAVERSAL = {};
|
||||||
|
|
||||||
// NOTE: This visitor is meant to be used via t.traverse
|
// NOTE: This visitor is meant to be used via t.traverse
|
||||||
@ -263,6 +276,31 @@ export default declare((api, options) => {
|
|||||||
objRef = temp;
|
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++) {
|
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