From 5678e61c0ff360a46ea47dcc1906aca1d5e28129 Mon Sep 17 00:00:00 2001 From: Samuel Reed Date: Tue, 8 Nov 2016 12:51:54 -0600 Subject: [PATCH] fix binding kind of destructured variables. (#4813) Fixes #4516 and any other code that hoists into a scope where function params are destructured. --- .../src/index.js | 14 ++++++++++++++ .../parameter-destructure-multi/actual.js | 3 +++ .../parameter-destructure-multi/expected.js | 9 +++++++++ .../parameter-destructure-multi/options.json | 4 ++++ .../parameter-destructure-rest/actual.js | 4 ++++ .../parameter-destructure-rest/expected.js | 13 +++++++++++++ .../parameter-destructure-rest/options.json | 6 ++++++ .../parameter-destructure-spread-deopt/actual.js | 3 +++ .../parameter-destructure-spread-deopt/expected.js | 10 ++++++++++ .../options.json | 6 ++++++ .../parameter-destructure/actual.js | 3 +++ .../parameter-destructure/expected.js | 7 +++++++ .../parameter-destructure/options.json | 4 ++++ 13 files changed, 86 insertions(+) create mode 100644 packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/parameter-destructure-multi/actual.js create mode 100644 packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/parameter-destructure-multi/expected.js create mode 100644 packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/parameter-destructure-multi/options.json create mode 100644 packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/parameter-destructure-rest/actual.js create mode 100644 packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/parameter-destructure-rest/expected.js create mode 100644 packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/parameter-destructure-rest/options.json create mode 100644 packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/parameter-destructure-spread-deopt/actual.js create mode 100644 packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/parameter-destructure-spread-deopt/expected.js create mode 100644 packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/parameter-destructure-spread-deopt/options.json create mode 100644 packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/parameter-destructure/actual.js create mode 100644 packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/parameter-destructure/expected.js create mode 100644 packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/parameter-destructure/options.json diff --git a/packages/babel-plugin-transform-es2015-destructuring/src/index.js b/packages/babel-plugin-transform-es2015-destructuring/src/index.js index cad6e15b93..3fe8c9fd3b 100644 --- a/packages/babel-plugin-transform-es2015-destructuring/src/index.js +++ b/packages/babel-plugin-transform-es2015-destructuring/src/index.js @@ -496,12 +496,26 @@ export default function ({ types: t }) { for (const node of nodes) { const tail = nodesOut[nodesOut.length - 1]; if (tail && t.isVariableDeclaration(tail) && t.isVariableDeclaration(node) && tail.kind === node.kind) { + // Create a single compound let/var rather than many. tail.declarations.push(...node.declarations); } else { nodesOut.push(node); } } + // Need to unmark the current binding to this var as a param, or other hoists + // could be placed above this ref. + // https://github.com/babel/babel/issues/4516 + for (const nodeOut of nodesOut) { + if (!nodeOut.declarations) continue; + for (const declaration of nodeOut.declarations) { + const {name} = declaration.id; + if (scope.bindings[name]) { + scope.bindings[name].kind = nodeOut.kind; + } + } + } + if (nodesOut.length === 1) { path.replaceWith(nodesOut[0]); } else { diff --git a/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/parameter-destructure-multi/actual.js b/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/parameter-destructure-multi/actual.js new file mode 100644 index 0000000000..bbfb5d59e5 --- /dev/null +++ b/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/parameter-destructure-multi/actual.js @@ -0,0 +1,3 @@ +function render({ text, className, id }) { + return () => (); +} diff --git a/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/parameter-destructure-multi/expected.js b/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/parameter-destructure-multi/expected.js new file mode 100644 index 0000000000..c039c14143 --- /dev/null +++ b/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/parameter-destructure-multi/expected.js @@ -0,0 +1,9 @@ +function render(_ref) { + let text = _ref.text, + className = _ref.className, + id = _ref.id; + + var _ref2 = ; + + return () => _ref2; +} diff --git a/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/parameter-destructure-multi/options.json b/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/parameter-destructure-multi/options.json new file mode 100644 index 0000000000..1d38616d70 --- /dev/null +++ b/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/parameter-destructure-multi/options.json @@ -0,0 +1,4 @@ +{ + + "plugins": ["transform-es2015-destructuring", "transform-es2015-parameters", "transform-react-constant-elements", "syntax-jsx"] +} diff --git a/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/parameter-destructure-rest/actual.js b/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/parameter-destructure-rest/actual.js new file mode 100644 index 0000000000..aca4fea6a0 --- /dev/null +++ b/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/parameter-destructure-rest/actual.js @@ -0,0 +1,4 @@ +function render({ text, className, id, ...props }) { + // intentionally ignoring props + return () => (); +} diff --git a/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/parameter-destructure-rest/expected.js b/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/parameter-destructure-rest/expected.js new file mode 100644 index 0000000000..01bec851b2 --- /dev/null +++ b/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/parameter-destructure-rest/expected.js @@ -0,0 +1,13 @@ +function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; } + +function render(_ref) { + let text = _ref.text, + className = _ref.className, + id = _ref.id, + props = _objectWithoutProperties(_ref, ["text", "className", "id"]); + + var _ref2 = ; + + // intentionally ignoring props + return () => _ref2; +} diff --git a/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/parameter-destructure-rest/options.json b/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/parameter-destructure-rest/options.json new file mode 100644 index 0000000000..100ca290b8 --- /dev/null +++ b/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/parameter-destructure-rest/options.json @@ -0,0 +1,6 @@ +{ + + "plugins": ["transform-es2015-destructuring", "transform-es2015-parameters", + "transform-es2015-spread", "syntax-object-rest-spread", + "transform-react-constant-elements", "syntax-jsx"] +} diff --git a/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/parameter-destructure-spread-deopt/actual.js b/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/parameter-destructure-spread-deopt/actual.js new file mode 100644 index 0000000000..fbe2c61cea --- /dev/null +++ b/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/parameter-destructure-spread-deopt/actual.js @@ -0,0 +1,3 @@ +function render({ text, className, id, ...props }) { + return () => (); +} diff --git a/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/parameter-destructure-spread-deopt/expected.js b/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/parameter-destructure-spread-deopt/expected.js new file mode 100644 index 0000000000..eb1d933b93 --- /dev/null +++ b/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/parameter-destructure-spread-deopt/expected.js @@ -0,0 +1,10 @@ +function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; } + +function render(_ref) { + let text = _ref.text, + className = _ref.className, + id = _ref.id, + props = _objectWithoutProperties(_ref, ["text", "className", "id"]); + + return () => ; +} diff --git a/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/parameter-destructure-spread-deopt/options.json b/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/parameter-destructure-spread-deopt/options.json new file mode 100644 index 0000000000..100ca290b8 --- /dev/null +++ b/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/parameter-destructure-spread-deopt/options.json @@ -0,0 +1,6 @@ +{ + + "plugins": ["transform-es2015-destructuring", "transform-es2015-parameters", + "transform-es2015-spread", "syntax-object-rest-spread", + "transform-react-constant-elements", "syntax-jsx"] +} diff --git a/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/parameter-destructure/actual.js b/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/parameter-destructure/actual.js new file mode 100644 index 0000000000..a7fbd1c081 --- /dev/null +++ b/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/parameter-destructure/actual.js @@ -0,0 +1,3 @@ +function render({ text }) { + return () => (); +} diff --git a/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/parameter-destructure/expected.js b/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/parameter-destructure/expected.js new file mode 100644 index 0000000000..272a607c98 --- /dev/null +++ b/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/parameter-destructure/expected.js @@ -0,0 +1,7 @@ +function render(_ref) { + let text = _ref.text; + + var _ref2 = ; + + return () => _ref2; +} diff --git a/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/parameter-destructure/options.json b/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/parameter-destructure/options.json new file mode 100644 index 0000000000..1d38616d70 --- /dev/null +++ b/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/parameter-destructure/options.json @@ -0,0 +1,4 @@ +{ + + "plugins": ["transform-es2015-destructuring", "transform-es2015-parameters", "transform-react-constant-elements", "syntax-jsx"] +}