diff --git a/package.json b/package.json index 965a869883..3387444697 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "babel-jest": "^23.0.1", "babel-plugin-check-es2015-constants": "^6.5.0", "babel-plugin-external-helpers": "^6.22.0", + "babel-plugin-syntax-dynamic-import": "^6.18.0", "babel-plugin-syntax-trailing-function-commas": "^6.5.0", "babel-plugin-transform-async-to-generator": "^6.22.0", "babel-plugin-transform-class-properties": "^6.11.5", diff --git a/packages/react-refresh/src/ReactFreshBabelPlugin.js b/packages/react-refresh/src/ReactFreshBabelPlugin.js index a8568b257e..d237ff8f43 100644 --- a/packages/react-refresh/src/ReactFreshBabelPlugin.js +++ b/packages/react-refresh/src/ReactFreshBabelPlugin.js @@ -115,8 +115,40 @@ export default function(babel) { if (!isComponentishName(name)) { return false; } - if (init.type === 'Identifier' || init.type === 'MemberExpression') { - return false; + switch (init.type) { + case 'ArrowFunctionExpression': + case 'FunctionExpression': + // Likely component definitions. + break; + case 'CallExpression': { + // Maybe a HOC. + // Try to determine if this is some form of import. + const callee = init.callee; + const calleeType = callee.type; + if (calleeType === 'Import') { + return false; + } else if (calleeType === 'Identifier') { + if (callee.name.indexOf('require') === 0) { + return false; + } else if (callee.name.indexOf('import') === 0) { + return false; + } + // Neither require nor import. Might be a HOC. + // Pass through. + } else if (calleeType === 'MemberExpression') { + // Could be something like React.forwardRef(...) + // Pass through. + } else { + // More complicated call. + return false; + } + break; + } + case 'TaggedTemplateExpression': + // Maybe something like styled.div`...` + break; + default: + return false; } const initPath = path.get('init'); const foundInside = findInnerComponents( diff --git a/packages/react-refresh/src/__tests__/ReactFreshBabelPlugin-test.js b/packages/react-refresh/src/__tests__/ReactFreshBabelPlugin-test.js index 1e1512b693..2ca46efcb0 100644 --- a/packages/react-refresh/src/__tests__/ReactFreshBabelPlugin-test.js +++ b/packages/react-refresh/src/__tests__/ReactFreshBabelPlugin-test.js @@ -15,7 +15,7 @@ function transform(input, options = {}) { return wrap( babel.transform(input, { babelrc: false, - plugins: ['syntax-jsx', freshPlugin], + plugins: ['syntax-jsx', 'syntax-dynamic-import', freshPlugin], }).code, ); } @@ -407,4 +407,31 @@ describe('ReactFreshBabelPlugin', () => { `), ).toMatchSnapshot(); }); + + it('does not consider require-like methods to be HOCs', () => { + // None of these were declared in this file. + // It's bad to register them because that would trigger + // modules to execute in an environment with inline requires. + // So we expect the transform to skip all of them even though + // they are used in JSX. + expect( + transform(` + const A = require('A'); + const B = foo ? require('X') : require('Y'); + const C = requireCond(gk, 'C'); + const D = import('D'); + + export default function App() { + return ( +
+ + + + +
+ ); + } + `), + ).toMatchSnapshot(); + }); }); diff --git a/packages/react-refresh/src/__tests__/__snapshots__/ReactFreshBabelPlugin-test.js.snap b/packages/react-refresh/src/__tests__/__snapshots__/ReactFreshBabelPlugin-test.js.snap index d18cd4ba61..b3fef460d1 100644 --- a/packages/react-refresh/src/__tests__/__snapshots__/ReactFreshBabelPlugin-test.js.snap +++ b/packages/react-refresh/src/__tests__/__snapshots__/ReactFreshBabelPlugin-test.js.snap @@ -1,5 +1,27 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`ReactFreshBabelPlugin does not consider require-like methods to be HOCs 1`] = ` + +const A = require('A'); +const B = foo ? require('X') : require('Y'); +const C = requireCond(gk, 'C'); +const D = import('D'); + +export default function App() { + return
+ + + + +
; +} +_c = App; + +var _c; + +__register__(_c, 'App'); +`; + exports[`ReactFreshBabelPlugin generates signatures for function declarations calling hooks 1`] = ` var _s = __signature__(); diff --git a/yarn.lock b/yarn.lock index 56a8a7287f..6605e61fa9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -620,6 +620,11 @@ babel-plugin-syntax-class-properties@^6.8.0: version "6.13.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz#d7eb23b79a317f8543962c505b827c7d6cac27de" +babel-plugin-syntax-dynamic-import@^6.18.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz#8d6a26229c83745a9982a441051572caa179b1da" + integrity sha1-jWomIpyDdFqZgqRBBRVyyqF5sdo= + babel-plugin-syntax-flow@^6.18.0, babel-plugin-syntax-flow@^6.8.0: version "6.18.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz#4c3ab20a2af26aa20cd25995c398c4eb70310c8d"