From 5a9509205bcc9df673f4954a4ca470083bb9d698 Mon Sep 17 00:00:00 2001 From: Scott Kyle Date: Sat, 3 Dec 2016 12:14:34 -0800 Subject: [PATCH] Fix constant elements hoisted out of block (#4419) When block scoped variables caused the block to be wrapped in a closure, the variable `bindings` remained in parent function scope, which caused the JSX element to be hoisted out of the closure. --- .../src/index.js | 11 ++++++++--- .../dont-hoist-block-scoped-variables/actual.js | 11 +++++++++++ .../expected.js | 17 +++++++++++++++++ .../options.json | 7 +++++++ 4 files changed, 43 insertions(+), 3 deletions(-) create mode 100644 packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/dont-hoist-block-scoped-variables/actual.js create mode 100644 packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/dont-hoist-block-scoped-variables/expected.js create mode 100644 packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/dont-hoist-block-scoped-variables/options.json diff --git a/packages/babel-plugin-transform-es2015-block-scoping/src/index.js b/packages/babel-plugin-transform-es2015-block-scoping/src/index.js index 6f21235196..b6598b6a33 100644 --- a/packages/babel-plugin-transform-es2015-block-scoping/src/index.js +++ b/packages/babel-plugin-transform-es2015-block-scoping/src/index.js @@ -305,14 +305,14 @@ class BlockScoping { this.remap(); } - this.updateScopeInfo(); + this.updateScopeInfo(needsClosure); if (this.loopLabel && !t.isLabeledStatement(this.loopParent)) { return t.labeledStatement(this.loopLabel, this.loop); } } - updateScopeInfo() { + updateScopeInfo(wrappedInClosure) { let scope = this.scope; let parentScope = scope.getFunctionParent(); let letRefs = this.letReferences; @@ -323,7 +323,12 @@ class BlockScoping { if (!binding) continue; if (binding.kind === "let" || binding.kind === "const") { binding.kind = "var"; - scope.moveBindingTo(ref.name, parentScope); + + if (wrappedInClosure) { + scope.removeBinding(ref.name); + } else { + scope.moveBindingTo(ref.name, parentScope); + } } } } diff --git a/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/dont-hoist-block-scoped-variables/actual.js b/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/dont-hoist-block-scoped-variables/actual.js new file mode 100644 index 0000000000..768b6acafa --- /dev/null +++ b/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/dont-hoist-block-scoped-variables/actual.js @@ -0,0 +1,11 @@ +function render(flag) { + if (flag) { + let bar = "bar"; + + [].map(() => bar); + + return ; + } + + return null; +} diff --git a/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/dont-hoist-block-scoped-variables/expected.js b/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/dont-hoist-block-scoped-variables/expected.js new file mode 100644 index 0000000000..9618e6da02 --- /dev/null +++ b/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/dont-hoist-block-scoped-variables/expected.js @@ -0,0 +1,17 @@ +function render(flag) { + if (flag) { + var _ret = function () { + var bar = "bar"; + + [].map(() => bar); + + return { + v: + }; + }(); + + if (typeof _ret === "object") return _ret.v; + } + + return null; +} \ No newline at end of file diff --git a/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/dont-hoist-block-scoped-variables/options.json b/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/dont-hoist-block-scoped-variables/options.json new file mode 100644 index 0000000000..859336d418 --- /dev/null +++ b/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/dont-hoist-block-scoped-variables/options.json @@ -0,0 +1,7 @@ +{ + "plugins": [ + "syntax-jsx", + "transform-es2015-block-scoping", + "transform-react-constant-elements" + ] +}