From 871ed897a711a92c9470c481c23fa00bd75f18c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= Date: Mon, 9 May 2022 15:43:12 +0200 Subject: [PATCH] Never hoist JSX elts referencing vars from the current scope (#14536) --- .../src/index.ts | 16 ++++++++++++++-- .../constant-elements/regression-14363/input.js | 12 ++++++++++++ .../constant-elements/regression-14363/output.js | 10 ++++++++++ 3 files changed, 36 insertions(+), 2 deletions(-) create mode 100644 packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/regression-14363/input.js create mode 100644 packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/regression-14363/output.js diff --git a/packages/babel-plugin-transform-react-constant-elements/src/index.ts b/packages/babel-plugin-transform-react-constant-elements/src/index.ts index c025319f26e1..c759d49e6533 100644 --- a/packages/babel-plugin-transform-react-constant-elements/src/index.ts +++ b/packages/babel-plugin-transform-react-constant-elements/src/index.ts @@ -197,7 +197,7 @@ export default declare((api, options: Options) => { current = current.parentPath; jsxScope = HOISTED.get(current.node); } - jsxScope ??= getHoistingScope(path.scope); + jsxScope ??= path.scope; const visitorState: VisitorState = { isImmutable: true, @@ -212,7 +212,19 @@ export default declare((api, options: Options) => { HOISTED.set(path.node, targetScope); // Only hoist if it would give us an advantage. - if (targetScope === jsxScope) return; + for (let currentScope = jsxScope; ; ) { + if (targetScope === currentScope) return; + if (isHoistingScope(currentScope)) break; + + currentScope = currentScope.parent; + if (!currentScope) { + throw new Error( + "Internal @babel/plugin-transform-react-constant-elements error: " + + "targetScope must be an ancestor of jsxScope. " + + "This is a Babel bug, please report it.", + ); + } + } const id = path.scope.generateUidBasedOnNode(name); targetScope.push({ id: t.identifier(id) }); diff --git a/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/regression-14363/input.js b/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/regression-14363/input.js new file mode 100644 index 000000000000..a8f784c7f912 --- /dev/null +++ b/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/regression-14363/input.js @@ -0,0 +1,12 @@ +function RoutesComponent() { + return ( + + {(c) => { + { + const Component = c; + return ; + } + }} + + ); +} \ No newline at end of file diff --git a/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/regression-14363/output.js b/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/regression-14363/output.js new file mode 100644 index 000000000000..1967a7fe7268 --- /dev/null +++ b/packages/babel-plugin-transform-react-constant-elements/test/fixtures/constant-elements/regression-14363/output.js @@ -0,0 +1,10 @@ +function RoutesComponent() { + return + {c => { + { + const Component = c; + return ; + } + }} + ; +}