From c1598444377b4fbe13228641895e1b96a26104dc Mon Sep 17 00:00:00 2001 From: Anton Korzunov Date: Wed, 22 Jan 2020 20:11:29 +1100 Subject: [PATCH] fix: don't record signatures of local hooks, fixes #1412 (#1413) --- src/fresh/babel.js | 1 + test/__babel_fixtures__/local-hooks.js | 36 +++++ test/__snapshots__/babel.test.js.snap | 188 +++++++++++++++++++++++++ 3 files changed, 225 insertions(+) create mode 100644 test/__babel_fixtures__/local-hooks.js diff --git a/src/fresh/babel.js b/src/fresh/babel.js index a86cbc348..9fedefae6 100644 --- a/src/fresh/babel.js +++ b/src/fresh/babel.js @@ -211,6 +211,7 @@ export default function (babel) { key: fnHookCalls.map(call => call.name + '{' + call.key + '}').join('\n'), customHooks: fnHookCalls .filter(call => !isBuiltinHook(call.name)) + .filter(call => scope.parent.hasBinding(call.name)) .map(call => t.cloneDeep(call.callee)), }; } diff --git a/test/__babel_fixtures__/local-hooks.js b/test/__babel_fixtures__/local-hooks.js new file mode 100644 index 000000000..ee333c6f7 --- /dev/null +++ b/test/__babel_fixtures__/local-hooks.js @@ -0,0 +1,36 @@ +import {useState} from "react"; + +function Component1() { + function useRippleHandler() {} + useRippleHandler(); + useRippleHandler(); +} + +function Component2() { + const useRippleHandler = () => {}; + useRippleHandler(); + useRippleHandler(); +} + +function Component3() { + const useRippleHandler = function () {}; + useRippleHandler(); + useRippleHandler(); +} + +const useInnerHook = ({useHookFromProps}) => { + const useHookBase = () => useState(); + const useHook = () => useState(useHookFromProps(useHookBase())); + useHookFromProps(); + { + // sub scope + useHook(); + } +}; + +const OnlyThisOneUsesExternalHook = () => { + useInnerHook(); + useState(); +}; + +// check for "return [" \ No newline at end of file diff --git a/test/__snapshots__/babel.test.js.snap b/test/__snapshots__/babel.test.js.snap index ec039c205..eaa1ab167 100644 --- a/test/__snapshots__/babel.test.js.snap +++ b/test/__snapshots__/babel.test.js.snap @@ -1342,6 +1342,105 @@ function spread() { })();" `; +exports[`babel Targetting "es2015" tags potential React components local hooks.js 1`] = ` +"\\"use strict\\"; + +var _react = require(\\"react\\"); + +(function () { + var enterModule = typeof reactHotLoaderGlobal !== 'undefined' ? reactHotLoaderGlobal.enterModule : undefined; + enterModule && enterModule(module); +})(); + +var __signature__ = typeof reactHotLoaderGlobal !== 'undefined' ? reactHotLoaderGlobal.default.signature : function (a) { + return a; +}; + +function Component1() { + function useRippleHandler() {} + useRippleHandler(); + useRippleHandler(); +} + +__signature__(Component1, \\"useRippleHandler{}\\\\nuseRippleHandler{}\\"); + +function Component2() { + var useRippleHandler = function useRippleHandler() {}; + useRippleHandler(); + useRippleHandler(); +} + +__signature__(Component2, \\"useRippleHandler{}\\\\nuseRippleHandler{}\\"); + +function Component3() { + var useRippleHandler = function useRippleHandler() {}; + useRippleHandler(); + useRippleHandler(); +} + +__signature__(Component3, \\"useRippleHandler{}\\\\nuseRippleHandler{}\\"); + +var useInnerHook = function useInnerHook(_ref) { + var useHookFromProps = _ref.useHookFromProps; + + var useHookBase = function useHookBase() { + return (0, _react.useState)(); + }; + + __signature__(useHookBase, \\"useState{}\\"); + + var useHook = function useHook() { + return (0, _react.useState)(useHookFromProps(useHookBase())); + }; + + __signature__(useHook, \\"useState{(useHookFromProps(useHookBase()))}\\\\nuseHookFromProps{}\\\\nuseHookBase{}\\", function () { + return [useHookFromProps, useHookBase]; + }); + + useHookFromProps(); + { + // sub scope + useHook(); + } +}; + +__signature__(useInnerHook, \\"useHookFromProps{}\\\\nuseHook{}\\"); + +var OnlyThisOneUsesExternalHook = function OnlyThisOneUsesExternalHook() { + useInnerHook(); + (0, _react.useState)(); +}; + +// check for \\"return [\\" + +__signature__(OnlyThisOneUsesExternalHook, \\"useInnerHook{}\\\\nuseState{}\\", function () { + return [useInnerHook]; +}); + +; + +(function () { + var reactHotLoader = typeof reactHotLoaderGlobal !== 'undefined' ? reactHotLoaderGlobal.default : undefined; + + if (!reactHotLoader) { + return; + } + + reactHotLoader.register(Component1, \\"Component1\\", __FILENAME__); + reactHotLoader.register(Component2, \\"Component2\\", __FILENAME__); + reactHotLoader.register(Component3, \\"Component3\\", __FILENAME__); + reactHotLoader.register(useInnerHook, \\"useInnerHook\\", __FILENAME__); + reactHotLoader.register(OnlyThisOneUsesExternalHook, \\"OnlyThisOneUsesExternalHook\\", __FILENAME__); +})(); + +; + +(function () { + var leaveModule = typeof reactHotLoaderGlobal !== 'undefined' ? reactHotLoaderGlobal.leaveModule : undefined; + leaveModule && leaveModule(module); +})();" +`; + exports[`babel Targetting "es2015" tags potential React components name clash.js 1`] = ` "\\"use strict\\"; @@ -2442,6 +2541,95 @@ function spread(...args) { })();" `; +exports[`babel Targetting "modern" tags potential React components local hooks.js 1`] = ` +"\\"use strict\\"; + +var _react = require(\\"react\\"); + +(function () { + var enterModule = typeof reactHotLoaderGlobal !== 'undefined' ? reactHotLoaderGlobal.enterModule : undefined; + enterModule && enterModule(module); +})(); + +var __signature__ = typeof reactHotLoaderGlobal !== 'undefined' ? reactHotLoaderGlobal.default.signature : function (a) { + return a; +}; + +function Component1() { + function useRippleHandler() {} + useRippleHandler(); + useRippleHandler(); +} + +__signature__(Component1, \\"useRippleHandler{}\\\\nuseRippleHandler{}\\"); + +function Component2() { + const useRippleHandler = () => {}; + useRippleHandler(); + useRippleHandler(); +} + +__signature__(Component2, \\"useRippleHandler{}\\\\nuseRippleHandler{}\\"); + +function Component3() { + const useRippleHandler = function () {}; + useRippleHandler(); + useRippleHandler(); +} + +__signature__(Component3, \\"useRippleHandler{}\\\\nuseRippleHandler{}\\"); + +const useInnerHook = ({ useHookFromProps }) => { + const useHookBase = () => (0, _react.useState)(); + + __signature__(useHookBase, \\"useState{}\\"); + + const useHook = () => (0, _react.useState)(useHookFromProps(useHookBase())); + + __signature__(useHook, \\"useState{(useHookFromProps(useHookBase()))}\\\\nuseHookFromProps{}\\\\nuseHookBase{}\\", () => [useHookFromProps, useHookBase]); + + useHookFromProps(); + { + // sub scope + useHook(); + } +}; + +__signature__(useInnerHook, \\"useHookFromProps{}\\\\nuseHook{}\\"); + +const OnlyThisOneUsesExternalHook = () => { + useInnerHook(); + (0, _react.useState)(); +}; + +// check for \\"return [\\" + +__signature__(OnlyThisOneUsesExternalHook, \\"useInnerHook{}\\\\nuseState{}\\", () => [useInnerHook]); + +; + +(function () { + var reactHotLoader = typeof reactHotLoaderGlobal !== 'undefined' ? reactHotLoaderGlobal.default : undefined; + + if (!reactHotLoader) { + return; + } + + reactHotLoader.register(Component1, \\"Component1\\", __FILENAME__); + reactHotLoader.register(Component2, \\"Component2\\", __FILENAME__); + reactHotLoader.register(Component3, \\"Component3\\", __FILENAME__); + reactHotLoader.register(useInnerHook, \\"useInnerHook\\", __FILENAME__); + reactHotLoader.register(OnlyThisOneUsesExternalHook, \\"OnlyThisOneUsesExternalHook\\", __FILENAME__); +})(); + +; + +(function () { + var leaveModule = typeof reactHotLoaderGlobal !== 'undefined' ? reactHotLoaderGlobal.leaveModule : undefined; + leaveModule && leaveModule(module); +})();" +`; + exports[`babel Targetting "modern" tags potential React components name clash.js 1`] = ` "\\"use strict\\";