fix object rest in array pattern (#10275)
* fix object rest in array pattern * update test fixtures * early return * use path.stop() at the right path
This commit is contained in:
parent
81831032c3
commit
8027dca501
@ -30,9 +30,20 @@ export default declare((api, opts) => {
|
||||
|
||||
function hasRestElement(path) {
|
||||
let foundRestElement = false;
|
||||
visitRestElements(path, () => {
|
||||
visitRestElements(path, restElement => {
|
||||
foundRestElement = true;
|
||||
path.stop();
|
||||
restElement.stop();
|
||||
});
|
||||
return foundRestElement;
|
||||
}
|
||||
|
||||
function hasObjectPatternRestElement(path) {
|
||||
let foundRestElement = false;
|
||||
visitRestElements(path, restElement => {
|
||||
if (restElement.parentPath.isObjectPattern()) {
|
||||
foundRestElement = true;
|
||||
restElement.stop();
|
||||
}
|
||||
});
|
||||
return foundRestElement;
|
||||
}
|
||||
@ -163,9 +174,9 @@ export default declare((api, opts) => {
|
||||
];
|
||||
}
|
||||
|
||||
function replaceRestElement(parentPath, paramPath, i, numParams) {
|
||||
function replaceRestElement(parentPath, paramPath) {
|
||||
if (paramPath.isAssignmentPattern()) {
|
||||
replaceRestElement(parentPath, paramPath.get("left"), i, numParams);
|
||||
replaceRestElement(parentPath, paramPath.get("left"));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -173,7 +184,7 @@ export default declare((api, opts) => {
|
||||
const elements = paramPath.get("elements");
|
||||
|
||||
for (let i = 0; i < elements.length; i++) {
|
||||
replaceRestElement(parentPath, elements[i], i, elements.length);
|
||||
replaceRestElement(parentPath, elements[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -200,7 +211,7 @@ export default declare((api, opts) => {
|
||||
Function(path) {
|
||||
const params = path.get("params");
|
||||
for (let i = params.length - 1; i >= 0; i--) {
|
||||
replaceRestElement(params[i].parentPath, params[i], i, params.length);
|
||||
replaceRestElement(params[i].parentPath, params[i]);
|
||||
}
|
||||
},
|
||||
// adapted from transform-destructuring/src/index.js#pushObjectRest
|
||||
@ -380,8 +391,12 @@ export default declare((api, opts) => {
|
||||
const leftPath = path.get("left");
|
||||
const left = node.left;
|
||||
|
||||
// for ({a, ...b} of []) {}
|
||||
if (t.isObjectPattern(left) && hasRestElement(leftPath)) {
|
||||
if (!hasObjectPatternRestElement(leftPath)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!t.isVariableDeclaration(left)) {
|
||||
// for ({a, ...b} of []) {}
|
||||
const temp = scope.generateUidIdentifier("ref");
|
||||
|
||||
node.left = t.variableDeclaration("var", [
|
||||
@ -401,27 +416,54 @@ export default declare((api, opts) => {
|
||||
t.assignmentExpression("=", left, t.cloneNode(temp)),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
// for (var {a, ...b} of []) {}
|
||||
const pattern = left.declarations[0].id;
|
||||
|
||||
return;
|
||||
const key = scope.generateUidIdentifier("ref");
|
||||
node.left = t.variableDeclaration(left.kind, [
|
||||
t.variableDeclarator(key, null),
|
||||
]);
|
||||
|
||||
path.ensureBlock();
|
||||
|
||||
node.body.body.unshift(
|
||||
t.variableDeclaration(node.left.kind, [
|
||||
t.variableDeclarator(pattern, t.cloneNode(key)),
|
||||
]),
|
||||
);
|
||||
}
|
||||
},
|
||||
// [{a, ...b}] = c;
|
||||
ArrayPattern(path) {
|
||||
const objectPatterns = [];
|
||||
|
||||
if (!t.isVariableDeclaration(left)) return;
|
||||
visitRestElements(path, path => {
|
||||
if (!path.parentPath.isObjectPattern()) {
|
||||
// Return early if the parent is not an ObjectPattern, but
|
||||
// (for example) an ArrayPattern or Function, because that
|
||||
// means this RestElement is an not an object property.
|
||||
return;
|
||||
}
|
||||
|
||||
const pattern = left.declarations[0].id;
|
||||
if (!t.isObjectPattern(pattern)) return;
|
||||
const objectPattern = path.parentPath;
|
||||
|
||||
const key = scope.generateUidIdentifier("ref");
|
||||
node.left = t.variableDeclaration(left.kind, [
|
||||
t.variableDeclarator(key, null),
|
||||
]);
|
||||
const uid = path.scope.generateUidIdentifier("ref");
|
||||
objectPatterns.push(t.variableDeclarator(objectPattern.node, uid));
|
||||
|
||||
path.ensureBlock();
|
||||
objectPattern.replaceWith(t.cloneNode(uid));
|
||||
path.skip();
|
||||
});
|
||||
|
||||
node.body.body.unshift(
|
||||
t.variableDeclaration(node.left.kind, [
|
||||
t.variableDeclarator(pattern, t.cloneNode(key)),
|
||||
]),
|
||||
);
|
||||
if (objectPatterns.length > 0) {
|
||||
const statementPath = path.getStatementParent();
|
||||
statementPath.insertAfter(
|
||||
t.variableDeclaration(
|
||||
statementPath.node.kind || "var",
|
||||
objectPatterns,
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
// var a = { ...b, ...c }
|
||||
ObjectExpression(path, file) {
|
||||
|
||||
@ -0,0 +1,19 @@
|
||||
// ForXStatement
|
||||
for (const [{a, ...b}] of []) {}
|
||||
for ([{a, ...b}] of []) {}
|
||||
async function a() {
|
||||
for await ([{a, ...b}] of []) {}
|
||||
}
|
||||
|
||||
// skip
|
||||
for ([{a}] in {}) {}
|
||||
for ([{a}] of []) {}
|
||||
async function a() {
|
||||
for await ([{a}] of []) {}
|
||||
}
|
||||
|
||||
for ([a, ...b] in {}) {}
|
||||
for ([a, ...b] of []) {}
|
||||
async function a() {
|
||||
for await ([a, ...b] of []) {}
|
||||
}
|
||||
@ -0,0 +1,49 @@
|
||||
// ForXStatement
|
||||
for (const _ref of []) {
|
||||
const [_ref2] = _ref;
|
||||
const {
|
||||
a
|
||||
} = _ref2,
|
||||
b = babelHelpers.objectWithoutProperties(_ref2, ["a"]);
|
||||
}
|
||||
|
||||
for (var _ref3 of []) {
|
||||
[_ref4] = _ref3;
|
||||
var {
|
||||
a
|
||||
} = _ref4,
|
||||
b = babelHelpers.objectWithoutProperties(_ref4, ["a"]);
|
||||
}
|
||||
|
||||
async function a() {
|
||||
for await (var _ref5 of []) {
|
||||
[_ref6] = _ref5;
|
||||
var {
|
||||
a
|
||||
} = _ref6,
|
||||
b = babelHelpers.objectWithoutProperties(_ref6, ["a"]);
|
||||
}
|
||||
} // skip
|
||||
|
||||
|
||||
for ([{
|
||||
a
|
||||
}] in {}) {}
|
||||
|
||||
for ([{
|
||||
a
|
||||
}] of []) {}
|
||||
|
||||
async function a() {
|
||||
for await ([{
|
||||
a
|
||||
}] of []) {}
|
||||
}
|
||||
|
||||
for ([a, ...b] in {}) {}
|
||||
|
||||
for ([a, ...b] of []) {}
|
||||
|
||||
async function a() {
|
||||
for await ([a, ...b] of []) {}
|
||||
}
|
||||
@ -0,0 +1 @@
|
||||
const [a, [{b, ...c}], {d, ...e}, [{ f, ...g}, {h: [i, {j, ...k}] }]] = x;
|
||||
@ -0,0 +1,19 @@
|
||||
const [a, [_ref], _ref2, [_ref3, {
|
||||
h: [i, _ref4]
|
||||
}]] = x;
|
||||
const {
|
||||
b
|
||||
} = _ref,
|
||||
c = babelHelpers.objectWithoutProperties(_ref, ["b"]),
|
||||
{
|
||||
d
|
||||
} = _ref2,
|
||||
e = babelHelpers.objectWithoutProperties(_ref2, ["d"]),
|
||||
{
|
||||
f
|
||||
} = _ref3,
|
||||
g = babelHelpers.objectWithoutProperties(_ref3, ["f"]),
|
||||
{
|
||||
j
|
||||
} = _ref4,
|
||||
k = babelHelpers.objectWithoutProperties(_ref4, ["j"]);
|
||||
@ -0,0 +1,6 @@
|
||||
const [a, {b, ...c}] = x;
|
||||
|
||||
let [d, {e, ...f}] = x;
|
||||
|
||||
[g, {h, ...i}] = x;
|
||||
|
||||
@ -0,0 +1,15 @@
|
||||
const [a, _ref] = x;
|
||||
const {
|
||||
b
|
||||
} = _ref,
|
||||
c = babelHelpers.objectWithoutProperties(_ref, ["b"]);
|
||||
let [d, _ref2] = x;
|
||||
let {
|
||||
e
|
||||
} = _ref2,
|
||||
f = babelHelpers.objectWithoutProperties(_ref2, ["e"]);
|
||||
[g, _ref3] = x;
|
||||
var {
|
||||
h
|
||||
} = _ref3,
|
||||
i = babelHelpers.objectWithoutProperties(_ref3, ["h"]);
|
||||
@ -1,9 +1,8 @@
|
||||
import "core-js/modules/es7.string.pad-end";
|
||||
import "core-js/modules/es7.string.pad-start";
|
||||
|
||||
for (const _ref of foo) {
|
||||
const {
|
||||
padStart
|
||||
} = _ref;
|
||||
for (const {
|
||||
padStart
|
||||
} of foo) {
|
||||
console.log('b'.padEnd(5));
|
||||
}
|
||||
|
||||
@ -2,9 +2,8 @@ import "core-js/modules/es.array.iterator";
|
||||
import "core-js/modules/es.string.pad-end";
|
||||
import "core-js/modules/es.string.pad-start";
|
||||
|
||||
for (const _ref of foo) {
|
||||
const {
|
||||
padStart
|
||||
} = _ref;
|
||||
for (const {
|
||||
padStart
|
||||
} of foo) {
|
||||
console.log('b'.padEnd(5));
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user