fix: add computed property support for object Ref (#10863)

* fix: add computed property support for object Ref

* Apply suggestions from code review

Co-Authored-By: Nicolò Ribaudo <nicolo.ribaudo@gmail.com>

* Update output.js
This commit is contained in:
Huáng Jùnliàng 2019-12-18 19:29:46 -05:00 committed by Nicolò Ribaudo
parent c0d0bf2e5e
commit 9be27bcfea
4 changed files with 120 additions and 10 deletions

View File

@ -102,12 +102,12 @@ export default declare((api, opts) => {
// replaces impure computed keys with new identifiers // replaces impure computed keys with new identifiers
// and returns variable declarators of these new identifiers // and returns variable declarators of these new identifiers
function replaceImpureComputedKeys(path) { function replaceImpureComputedKeys(properties, scope) {
const impureComputedPropertyDeclarators = []; const impureComputedPropertyDeclarators = [];
for (const propPath of path.get("properties")) { for (const propPath of properties) {
const key = propPath.get("key"); const key = propPath.get("key");
if (propPath.node.computed && !key.isPure()) { if (propPath.node.computed && !key.isPure()) {
const name = path.scope.generateUidBasedOnNode(key.node); const name = scope.generateUidBasedOnNode(key.node);
const declarator = t.variableDeclarator(t.identifier(name), key.node); const declarator = t.variableDeclarator(t.identifier(name), key.node);
impureComputedPropertyDeclarators.push(declarator); impureComputedPropertyDeclarators.push(declarator);
key.replaceWith(t.identifier(name)); key.replaceWith(t.identifier(name));
@ -139,7 +139,10 @@ export default declare((api, opts) => {
const restElement = t.cloneNode(last.node); const restElement = t.cloneNode(last.node);
last.remove(); last.remove();
const impureComputedPropertyDeclarators = replaceImpureComputedKeys(path); const impureComputedPropertyDeclarators = replaceImpureComputedKeys(
path.get("properties"),
path.scope,
);
const { keys, allLiteral } = extractNormalizedKeys(path); const { keys, allLiteral } = extractNormalizedKeys(path);
if (keys.length === 0) { if (keys.length === 0) {
@ -265,18 +268,21 @@ export default declare((api, opts) => {
path.findParent(path => { path.findParent(path => {
if (path.isObjectProperty()) { if (path.isObjectProperty()) {
refPropertyPath.unshift(path.node.key.name); refPropertyPath.unshift(path);
} else if (path.isVariableDeclarator()) { } else if (path.isVariableDeclarator()) {
kind = path.parentPath.node.kind; kind = path.parentPath.node.kind;
return true; return true;
} }
}); });
if (refPropertyPath.length) { const impureObjRefComputedDeclarators = replaceImpureComputedKeys(
refPropertyPath.forEach(prop => { refPropertyPath,
ref = t.memberExpression(ref, t.identifier(prop)); path.scope,
}); );
} refPropertyPath.forEach(prop => {
const { node } = prop;
ref = t.memberExpression(ref, t.cloneNode(node.key), node.computed);
});
const objectPatternPath = path.findParent(path => const objectPatternPath = path.findParent(path =>
path.isObjectPattern(), path.isObjectPattern(),
@ -296,6 +302,8 @@ export default declare((api, opts) => {
insertionPath.insertBefore(impureComputedPropertyDeclarators); insertionPath.insertBefore(impureComputedPropertyDeclarators);
insertionPath.insertBefore(impureObjRefComputedDeclarators);
insertionPath.insertAfter( insertionPath.insertAfter(
t.variableDeclarator(argument, callExpression), t.variableDeclarator(argument, callExpression),
); );

View File

@ -0,0 +1,20 @@
var key, x, y, z;
// impure
key = 1;
var { [key++]: { y, ...x } } = { 1: { a: 1, y: 1 } };
expect(x).toEqual({ a: 1 });
expect(key).toBe(2);
expect(y).toBe(1);
// takes care of the order
key = 1;
var {
[++key]: { y, ...rest_y },
[++key]: { z, ...rest_z }
} = {2: { y: 2, z: 3 }, 3: { y: 2, z: 3 } };
expect(y).toBe(2);
expect(rest_y).toEqual({z: 3});
expect(z).toBe(3);
expect(rest_z).toEqual({ y: 2 });
expect(key).toBe(3);

View File

@ -0,0 +1,20 @@
var key, x, y, z;
// impure
key = 1;
var { [key++]: { y, ...x } } = { 1: { a: 1, y: 1 } };
expect(x).toEqual({ a: 1 });
expect(key).toBe(2);
expect(y).toBe(1);
// takes care of the order
key = 1;
var {
[++key]: { y, ...rest_y },
[++key]: { z, ...rest_z }
} = {2: { y: 2, z: 3 }, 3: { y: 2, z: 3 } };
expect(y).toBe(2);
expect(rest_y).toEqual({z: 3});
expect(z).toBe(3);
expect(rest_z).toEqual({ y: 2 });
expect(key).toBe(3);

View File

@ -0,0 +1,62 @@
var key, x, y, z; // impure
key = 1;
var _ref = key++,
{
[_ref]: {
y
}
} = {
1: {
a: 1,
y: 1
}
},
x = babelHelpers.objectWithoutProperties({
1: {
a: 1,
y: 1
}
}[_ref], ["y"]);
expect(x).toEqual({
a: 1
});
expect(key).toBe(2);
expect(y).toBe(1); // takes care of the order
key = 1;
var _$ = {
2: {
y: 2,
z: 3
},
3: {
y: 2,
z: 3
}
},
_ref2 = ++key,
_ref3 = ++key,
{
[_ref3]: {
y
},
[_ref2]: {
z
}
} = _$,
rest_y = babelHelpers.objectWithoutProperties(_$[_ref3], ["y"]),
rest_z = babelHelpers.objectWithoutProperties(_$[_ref2], ["z"]);
expect(y).toBe(2);
expect(rest_y).toEqual({
z: 3
});
expect(z).toBe(3);
expect(rest_z).toEqual({
y: 2
});
expect(key).toBe(3);