Fix over-zealous traversal by object-rest-spread (#7388)

Prior to this change, we'd conduct an open-ended traversal on the 'id'
of any VariableDeclarator to find a RestElement. The 'id' of
a VariableDeclarator can contain an AssignmentPattern (to supply
a default value), and if the right-hand side of the AssignmentPattern
contained a RestElement, we'd transform it.

The problem here is that the right-hand side of an AssignmentPattern can
be *any* Expression. If the right-hand side is a function body, we'd
traverse the entire function body, and if a RestElement occurred
anywhere in that function body, we'd transform it and emit the
transformations wherever we began the traversal (at least one scope
outside its usage).

The fix is to stop the inner traversal if we encounter an
AssignmentPattern. The outer traversal will still visit the
AssignmentPattern, so RestElements within the right-hand side of an
AssignmentPattern will be properly transformed at that time.
This commit is contained in:
James Reggio
2018-02-16 21:19:09 -05:00
committed by Justin Ridgewell
parent ee6dfd1580
commit 6cbc585cf4
3 changed files with 33 additions and 0 deletions

View File

@@ -150,6 +150,12 @@ export default function(api, opts) {
path.get("id").traverse(
{
// If there's a default-value AssignmentPattern within the ObjectPattern,
// we should not traverse into it, lest we end up in another function body.
// (The parent traversal will handle it.)
AssignmentPattern(path) {
path.skip();
},
RestElement(path) {
if (!path.parentPath.isObjectPattern()) {
// Return early if the parent is not an ObjectPattern, but

View File

@@ -0,0 +1,12 @@
function fn0(obj0) {
const {
fn1 = (obj1 = {}) => {
const {
fn2 = (obj2 = {}) => {
const {a, ...rest} = obj2;
console.log(rest);
}
} = obj1;
}
} = obj0;
}

View File

@@ -0,0 +1,15 @@
function fn0(obj0) {
const {
fn1 = (obj1 = {}) => {
const {
fn2 = (obj2 = {}) => {
const {
a
} = obj2,
rest = babelHelpers.objectWithoutProperties(obj2, ["a"]);
console.log(rest);
}
} = obj1;
}
} = obj0;
}