From 6cbc585cf45b18b61bfae0e6935e769f9486b117 Mon Sep 17 00:00:00 2001 From: James Reggio Date: Fri, 16 Feb 2018 21:19:09 -0500 Subject: [PATCH] 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. --- .../src/index.js | 6 ++++++ .../test/fixtures/regression/gh-7388/input.js | 12 ++++++++++++ .../test/fixtures/regression/gh-7388/output.js | 15 +++++++++++++++ 3 files changed, 33 insertions(+) create mode 100644 packages/babel-plugin-proposal-object-rest-spread/test/fixtures/regression/gh-7388/input.js create mode 100644 packages/babel-plugin-proposal-object-rest-spread/test/fixtures/regression/gh-7388/output.js diff --git a/packages/babel-plugin-proposal-object-rest-spread/src/index.js b/packages/babel-plugin-proposal-object-rest-spread/src/index.js index 1ac3b3af3b..2bf068e21e 100644 --- a/packages/babel-plugin-proposal-object-rest-spread/src/index.js +++ b/packages/babel-plugin-proposal-object-rest-spread/src/index.js @@ -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 diff --git a/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/regression/gh-7388/input.js b/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/regression/gh-7388/input.js new file mode 100644 index 0000000000..a311921880 --- /dev/null +++ b/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/regression/gh-7388/input.js @@ -0,0 +1,12 @@ +function fn0(obj0) { + const { + fn1 = (obj1 = {}) => { + const { + fn2 = (obj2 = {}) => { + const {a, ...rest} = obj2; + console.log(rest); + } + } = obj1; + } + } = obj0; +} diff --git a/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/regression/gh-7388/output.js b/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/regression/gh-7388/output.js new file mode 100644 index 0000000000..97254741cb --- /dev/null +++ b/packages/babel-plugin-proposal-object-rest-spread/test/fixtures/regression/gh-7388/output.js @@ -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; +}