diff --git a/compiler/packages/babel-plugin-react-forget/src/Entrypoint/Program.ts b/compiler/packages/babel-plugin-react-forget/src/Entrypoint/Program.ts index 655dae790e..ba17b58c68 100644 --- a/compiler/packages/babel-plugin-react-forget/src/Entrypoint/Program.ts +++ b/compiler/packages/babel-plugin-react-forget/src/Entrypoint/Program.ts @@ -618,7 +618,18 @@ function checkFunctionReferencedBeforeDeclarationAtTopLevel( program.traverse({ Identifier(id) { const fn = fnNames.get(id.node.name); - if (fnIds.has(id.node) || !fn) { + // We're not tracking this identifier. + if (!fn) { + return; + } + + /* + * We've reached the declaration, hoisting is no longer possible, stop + * checking for this component name. + */ + if (fnIds.has(id.node)) { + fnIds.delete(id.node); + fnNames.delete(id.node.name); return; } @@ -627,12 +638,7 @@ function checkFunctionReferencedBeforeDeclarationAtTopLevel( * A null scope means there's no function scope, which means we're at the * top level scope. */ - if ( - scope === null && - id.node.loc && - fn.loc && - occursBefore(id.node.loc, fn.loc) - ) { + if (scope === null) { errors.pushErrorDetail( new CompilerErrorDetail({ reason: `Encountered ${fn.name} used before declaration which breaks Forget's gating codegen due to hoisting`, @@ -649,15 +655,3 @@ function checkFunctionReferencedBeforeDeclarationAtTopLevel( return errors.details.length > 0 ? errors : null; } - -function occursBefore(a: t.SourceLocation, b: t.SourceLocation): boolean { - if (a.start.line > b.start.line) { - return false; - } - - if (a.start.line < b.start.line) { - return true; - } - - return a.start.column < b.start.column; -} diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/component-syntax-ref-gating.flow.expect.md b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/component-syntax-ref-gating.flow.expect.md deleted file mode 100644 index 7dfcddf3f1..0000000000 --- a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/component-syntax-ref-gating.flow.expect.md +++ /dev/null @@ -1,38 +0,0 @@ - -## Input - -```javascript -// @flow @gating -component Foo(ref: React.RefSetter) { - return ; -} -``` - -## Code - -```javascript -import { isForgetEnabled_Fixtures } from "ReactForgetFeatureFlag"; -import { unstable_useMemoCache as useMemoCache } from "react"; -const Foo = React.forwardRef(Foo_withRef); -const Foo_withRef = isForgetEnabled_Fixtures() - ? function Foo_withRef(_$$empty_props_placeholder$$, ref) { - const $ = useMemoCache(2); - let t0; - if ($[0] !== ref) { - t0 = ; - $[0] = ref; - $[1] = t0; - } else { - t0 = $[1]; - } - return t0; - } - : function Foo_withRef( - _$$empty_props_placeholder$$: $ReadOnly<{ ... }>, - ref: React.RefSetter - ) { - return ; - }; - -``` - \ No newline at end of file diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.component-syntax-ref-gating.flow.expect.md b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.component-syntax-ref-gating.flow.expect.md new file mode 100644 index 0000000000..fdefed1906 --- /dev/null +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.component-syntax-ref-gating.flow.expect.md @@ -0,0 +1,18 @@ + +## Input + +```javascript +// @flow @gating +component Foo(ref: React.RefSetter) { + return ; +} +``` + + +## Error + +``` +[ReactForget] Invariant: Encountered Foo_withRef used before declaration which breaks Forget's gating codegen due to hoisting. Rewrite the reference to not use hoisting to fix this issue (2:2) +``` + + \ No newline at end of file diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/component-syntax-ref-gating.flow.js b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.component-syntax-ref-gating.flow.js similarity index 100% rename from compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/component-syntax-ref-gating.flow.js rename to compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.component-syntax-ref-gating.flow.js