diff --git a/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/member-expression-constant/actual.js b/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/member-expression-constant/actual.js new file mode 100644 index 000000000000..a6c1f9b6ec88 --- /dev/null +++ b/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/member-expression-constant/actual.js @@ -0,0 +1,4 @@ +function render() { + this.component = "div"; + return () => ; +} diff --git a/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/member-expression-constant/expected.js b/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/member-expression-constant/expected.js new file mode 100644 index 000000000000..aa7a9994baeb --- /dev/null +++ b/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/member-expression-constant/expected.js @@ -0,0 +1,7 @@ +function render() { + this.component = "div"; + + var _ref = ; + + return () => _ref; +} diff --git a/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/member-expression-this/actual.js b/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/member-expression-this/actual.js new file mode 100644 index 000000000000..bdc61d684a69 --- /dev/null +++ b/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/member-expression-this/actual.js @@ -0,0 +1,5 @@ +class Component extends React.Component { + subComponent = () => Sub Component + + render = () => +} diff --git a/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/member-expression-this/expected.js b/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/member-expression-this/expected.js new file mode 100644 index 000000000000..9ce3a08e7437 --- /dev/null +++ b/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/member-expression-this/expected.js @@ -0,0 +1,12 @@ +var _ref = Sub Component; + +class Component extends React.Component { + constructor(...args) { + var _temp; + + var _ref2 = ; + + return _temp = super(...args), this.subComponent = () => _ref, this.render = () => _ref2, _temp; + } + +} diff --git a/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/member-expression-this/options.json b/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/member-expression-this/options.json new file mode 100644 index 000000000000..d4789bbda3fb --- /dev/null +++ b/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/member-expression-this/options.json @@ -0,0 +1,3 @@ +{ + "plugins": ["syntax-jsx", "transform-react-constant-elements", "transform-class-properties"] +} diff --git a/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/member-expression/actual.js b/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/member-expression/actual.js new file mode 100644 index 000000000000..2ab59df97b89 --- /dev/null +++ b/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/member-expression/actual.js @@ -0,0 +1,6 @@ +const els = { + subComponent: () => Sub Component +}; +class Component extends React.Component { + render = () => +} diff --git a/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/member-expression/expected.js b/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/member-expression/expected.js new file mode 100644 index 000000000000..fe12eb988d5d --- /dev/null +++ b/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/member-expression/expected.js @@ -0,0 +1,16 @@ +var _ref = Sub Component; + +const els = { + subComponent: () => _ref +}; + +var _ref2 = ; + +class Component extends React.Component { + constructor(...args) { + var _temp; + + return _temp = super(...args), this.render = () => _ref2, _temp; + } + +} diff --git a/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/member-expression/options.json b/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/member-expression/options.json new file mode 100644 index 000000000000..d4789bbda3fb --- /dev/null +++ b/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/member-expression/options.json @@ -0,0 +1,3 @@ +{ + "plugins": ["syntax-jsx", "transform-react-constant-elements", "transform-class-properties"] +} diff --git a/packages/babel-traverse/src/path/lib/hoister.js b/packages/babel-traverse/src/path/lib/hoister.js index 93b9323bd35d..c7dbf5cf737e 100644 --- a/packages/babel-traverse/src/path/lib/hoister.js +++ b/packages/babel-traverse/src/path/lib/hoister.js @@ -2,11 +2,23 @@ import { react } from "babel-types"; import * as t from "babel-types"; const referenceVisitor = { + // This visitor looks for bindings to establish a topmost scope for hoisting. ReferencedIdentifier(path, state) { - if (path.isJSXIdentifier() && react.isCompatTag(path.node.name)) { + // Don't hoist regular JSX identifiers ('div', 'span', etc). + // We do have to consider member expressions for hoisting (e.g. `this.component`) + if (path.isJSXIdentifier() && react.isCompatTag(path.node.name) && !path.parentPath.isJSXMemberExpression()) { return; } + // If the identifier refers to `this`, we need to break on the closest non-arrow scope. + if (path.node.name === "this") { + let scope = path.scope; + do { + if (scope.path.isFunction() && !scope.path.isArrowFunctionExpression()) break; + } while (scope = scope.parent); + if (scope) state.breakOnScopePaths.push(scope.path); + } + // direct references that we need to track to hoist this to the highest scope we can const binding = path.scope.getBinding(path.node.name); if (!binding) return;