diff --git a/compiler/packages/babel-plugin-react-compiler/src/HIR/Environment.ts b/compiler/packages/babel-plugin-react-compiler/src/HIR/Environment.ts index ba7396e0d7d..f94870fc030 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/HIR/Environment.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/HIR/Environment.ts @@ -608,7 +608,7 @@ export const EnvironmentConfigSchema = z.object({ * * Here the variables `ref` and `myRef` will be typed as Refs. */ - enableTreatRefLikeIdentifiersAsRefs: z.boolean().default(false), + enableTreatRefLikeIdentifiersAsRefs: z.boolean().default(true), /* * If specified a value, the compiler lowers any calls to `useContext` to use diff --git a/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateNoRefAccessInRender.ts b/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateNoRefAccessInRender.ts index 758ee459af1..571fe61c810 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateNoRefAccessInRender.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateNoRefAccessInRender.ts @@ -432,15 +432,11 @@ function validateNoRefAccessInRenderImpl( * By default we check that function call operands are not refs, * ref values, or functions that can access refs. */ - if ( - isRefLValue || - interpolatedAsJsx.has(instr.lvalue.identifier.id) || - hookKind != null - ) { + if (isRefLValue || hookKind != null) { /** * Special cases: * - * 1) the lvalue is a ref + * 1. the lvalue is a ref * In general passing a ref to a function may access that ref * value during render, so we disallow it. * @@ -452,31 +448,22 @@ function validateNoRefAccessInRenderImpl( * * Eg `const mergedRef = mergeRefs(ref1, ref2)` * - * 2) the lvalue is passed as a jsx child - * - * For example `{renderHelper(ref)}`. Here we have more - * context and infer that the ref is being passed to a component-like - * render function which attempts to obey the rules. - * - * 3) hooks + * 2. calling hooks * * Hooks are independently checked to ensure they don't access refs * during render. */ validateNoDirectRefValueAccess(errors, operand, env); - } else if (!isRefLValue) { + } else if (interpolatedAsJsx.has(instr.lvalue.identifier.id)) { /** - * In general passing a ref to a function may access that ref - * value during render, so we disallow it. + * Special case: the lvalue is passed as a jsx child * - * The main exception is the "mergeRefs" pattern, ie a function - * that accepts multiple refs as arguments (or an array of refs) - * and returns a new, aggregated ref. If the lvalue is a ref, - * we assume that the user is doing this pattern and allow passing - * refs. - * - * Eg `const mergedRef = mergeRefs(ref1, ref2)` + * For example `{renderHelper(ref)}`. Here we have more + * context and infer that the ref is being passed to a component-like + * render function which attempts to obey the rules. */ + validateNoRefValueAccess(errors, env, operand); + } else { validateNoRefPassedToFunction( errors, env, diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allow-ref-access-in-effect-indirect.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allow-ref-access-in-effect-indirect.expect.md index 7c1f5ad3727..6cf97f6c351 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allow-ref-access-in-effect-indirect.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allow-ref-access-in-effect-indirect.expect.md @@ -27,6 +27,7 @@ function Component() { } function Child({ref}) { + 'use no memo'; // This violates the rules of React, so we access the ref in a child // component return ref.current; @@ -100,8 +101,10 @@ function Component() { return t6; } -function Child(t0) { - const { ref } = t0; +function Child({ ref }) { + "use no memo"; + // This violates the rules of React, so we access the ref in a child + // component return ref.current; } diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allow-ref-access-in-effect-indirect.js b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allow-ref-access-in-effect-indirect.js index 69429049022..4320b5871da 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allow-ref-access-in-effect-indirect.js +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allow-ref-access-in-effect-indirect.js @@ -23,6 +23,7 @@ function Component() { } function Child({ref}) { + 'use no memo'; // This violates the rules of React, so we access the ref in a child // component return ref.current; diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allow-ref-access-in-effect.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allow-ref-access-in-effect.expect.md index 3bdf358611d..009d504da25 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allow-ref-access-in-effect.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allow-ref-access-in-effect.expect.md @@ -23,6 +23,7 @@ function Component() { } function Child({ref}) { + 'use no memo'; // This violates the rules of React, so we access the ref in a child // component return ref.current; @@ -86,8 +87,10 @@ function Component() { return t5; } -function Child(t0) { - const { ref } = t0; +function Child({ ref }) { + "use no memo"; + // This violates the rules of React, so we access the ref in a child + // component return ref.current; } diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allow-ref-access-in-effect.js b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allow-ref-access-in-effect.js index efba0547ebc..54a1dc22c3a 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allow-ref-access-in-effect.js +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allow-ref-access-in-effect.js @@ -19,6 +19,7 @@ function Component() { } function Child({ref}) { + 'use no memo'; // This violates the rules of React, so we access the ref in a child // component return ref.current; diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allow-ref-access-in-unused-callback-nested.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allow-ref-access-in-unused-callback-nested.expect.md index 3584faf699f..26e996017eb 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allow-ref-access-in-unused-callback-nested.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allow-ref-access-in-unused-callback-nested.expect.md @@ -25,6 +25,7 @@ function Component() { } function Child({ref}) { + 'use no memo'; // This violates the rules of React, so we access the ref in a child // component return ref.current; @@ -83,8 +84,10 @@ function Component() { } function _temp() {} -function Child(t0) { - const { ref } = t0; +function Child({ ref }) { + "use no memo"; + // This violates the rules of React, so we access the ref in a child + // component return ref.current; } diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allow-ref-access-in-unused-callback-nested.js b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allow-ref-access-in-unused-callback-nested.js index 1e402886376..dcd8540e2a4 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allow-ref-access-in-unused-callback-nested.js +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allow-ref-access-in-unused-callback-nested.js @@ -21,6 +21,7 @@ function Component() { } function Child({ref}) { + 'use no memo'; // This violates the rules of React, so we access the ref in a child // component return ref.current; diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-aliased-ref-in-callback-invoked-during-render-.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-aliased-ref-in-callback-invoked-during-render-.expect.md index e9be56ad9b1..3aa52375339 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-aliased-ref-in-callback-invoked-during-render-.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-aliased-ref-in-callback-invoked-during-render-.expect.md @@ -29,7 +29,7 @@ error.invalid-aliased-ref-in-callback-invoked-during-render-.ts:9:33 7 | return ; 8 | }; > 9 | return {props.items.map(item => renderItem(item))}; - | ^^^^^^^^^^^^^^^^^^^^^^^^ Passing a ref to a function may read its value during render + | ^^^^^^^^^^^^^^^^^^^^^^^^ Cannot access ref value during render 10 | } 11 | ``` diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-ref-in-callback-invoked-during-render.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-ref-in-callback-invoked-during-render.expect.md index 6886aa08766..414ee9d536a 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-ref-in-callback-invoked-during-render.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-ref-in-callback-invoked-during-render.expect.md @@ -28,7 +28,7 @@ error.invalid-ref-in-callback-invoked-during-render.ts:8:33 6 | return ; 7 | }; > 8 | return {props.items.map(item => renderItem(item))}; - | ^^^^^^^^^^^^^^^^^^^^^^^^ Passing a ref to a function may read its value during render + | ^^^^^^^^^^^^^^^^^^^^^^^^ Cannot access ref value during render 9 | } 10 | ``` diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.repro-ref-mutable-range.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.repro-ref-mutable-range.expect.md deleted file mode 100644 index 9b3f1d98897..00000000000 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.repro-ref-mutable-range.expect.md +++ /dev/null @@ -1,47 +0,0 @@ - -## Input - -```javascript -import {Stringify, identity, mutate, CONST_TRUE} from 'shared-runtime'; - -function Foo(props, ref) { - const value = {}; - if (CONST_TRUE) { - mutate(value); - return ; - } - mutate(value); - if (CONST_TRUE) { - return ; - } - return value; -} - -export const FIXTURE_ENTRYPOINT = { - fn: Foo, - params: [{}, {current: 'fake-ref-object'}], -}; - -``` - - -## Error - -``` -Found 1 error: - -Error: Cannot access refs during render - -React refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected (https://react.dev/reference/react/useRef) - -error.repro-ref-mutable-range.ts:11:36 - 9 | mutate(value); - 10 | if (CONST_TRUE) { -> 11 | return ; - | ^^^ Passing a ref to a function may read its value during render - 12 | } - 13 | return value; - 14 | } -``` - - \ No newline at end of file diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-effect-dependencies/bailout-retry/mutate-after-useeffect-ref-access.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-effect-dependencies/bailout-retry/mutate-after-useeffect-ref-access.expect.md index 88643995fac..d3b746b1f8a 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-effect-dependencies/bailout-retry/mutate-after-useeffect-ref-access.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-effect-dependencies/bailout-retry/mutate-after-useeffect-ref-access.expect.md @@ -47,7 +47,7 @@ export const FIXTURE_ENTRYPOINT = { ## Logs ``` -{"kind":"CompileError","fnLoc":{"start":{"line":6,"column":0,"index":158},"end":{"line":11,"column":1,"index":331},"filename":"mutate-after-useeffect-ref-access.ts"},"detail":{"options":{"severity":"InvalidReact","category":"This value cannot be modified","description":"Modifying component props or hook arguments is not allowed. Consider using a local variable instead.","details":[{"kind":"error","loc":{"start":{"line":9,"column":2,"index":289},"end":{"line":9,"column":16,"index":303},"filename":"mutate-after-useeffect-ref-access.ts"},"message":"value cannot be modified"}]}}} +{"kind":"CompileError","fnLoc":{"start":{"line":6,"column":0,"index":158},"end":{"line":11,"column":1,"index":331},"filename":"mutate-after-useeffect-ref-access.ts"},"detail":{"options":{"severity":"InvalidReact","category":"Cannot access refs during render","description":"React refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected (https://react.dev/reference/react/useRef)","details":[{"kind":"error","loc":{"start":{"line":9,"column":2,"index":289},"end":{"line":9,"column":16,"index":303},"filename":"mutate-after-useeffect-ref-access.ts"},"message":"Cannot update ref during render"}]}}} {"kind":"AutoDepsDecorations","fnLoc":{"start":{"line":8,"column":2,"index":237},"end":{"line":8,"column":50,"index":285},"filename":"mutate-after-useeffect-ref-access.ts"},"decorations":[{"start":{"line":8,"column":24,"index":259},"end":{"line":8,"column":30,"index":265},"filename":"mutate-after-useeffect-ref-access.ts","identifierName":"arrRef"}]} {"kind":"CompileSuccess","fnLoc":{"start":{"line":6,"column":0,"index":158},"end":{"line":11,"column":1,"index":331},"filename":"mutate-after-useeffect-ref-access.ts"},"fnName":"Component","memoSlots":0,"memoBlocks":0,"memoValues":0,"prunedMemoBlocks":0,"prunedMemoValues":0} ``` diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-effect-dependencies/nonreactive-ref-helper.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-effect-dependencies/nonreactive-ref-helper.expect.md index ec7ac5e0e34..05dcab77968 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-effect-dependencies/nonreactive-ref-helper.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-effect-dependencies/nonreactive-ref-helper.expect.md @@ -51,12 +51,12 @@ function RefsInEffects() { const ref = useRefHelper(); const wrapped = useDeeperRefHelper(); let t0; - if ($[0] !== ref.current || $[1] !== wrapped.foo.current) { + if ($[0] !== ref || $[1] !== wrapped.foo.current) { t0 = () => { print(ref.current); print(wrapped.foo.current); }; - $[0] = ref.current; + $[0] = ref; $[1] = wrapped.foo.current; $[2] = t0; } else { diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/mutate-after-useeffect-ref-access.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/mutate-after-useeffect-ref-access.expect.md index 8df9bd9f852..7bcc917447a 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/mutate-after-useeffect-ref-access.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/mutate-after-useeffect-ref-access.expect.md @@ -47,7 +47,7 @@ export const FIXTURE_ENTRYPOINT = { ## Logs ``` -{"kind":"CompileError","fnLoc":{"start":{"line":6,"column":0,"index":190},"end":{"line":11,"column":1,"index":363},"filename":"mutate-after-useeffect-ref-access.ts"},"detail":{"options":{"severity":"InvalidReact","category":"This value cannot be modified","description":"Modifying component props or hook arguments is not allowed. Consider using a local variable instead.","details":[{"kind":"error","loc":{"start":{"line":9,"column":2,"index":321},"end":{"line":9,"column":16,"index":335},"filename":"mutate-after-useeffect-ref-access.ts"},"message":"value cannot be modified"}]}}} +{"kind":"CompileError","fnLoc":{"start":{"line":6,"column":0,"index":190},"end":{"line":11,"column":1,"index":363},"filename":"mutate-after-useeffect-ref-access.ts"},"detail":{"options":{"severity":"InvalidReact","category":"Cannot access refs during render","description":"React refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected (https://react.dev/reference/react/useRef)","details":[{"kind":"error","loc":{"start":{"line":9,"column":2,"index":321},"end":{"line":9,"column":16,"index":335},"filename":"mutate-after-useeffect-ref-access.ts"},"message":"Cannot update ref during render"}]}}} {"kind":"AutoDepsDecorations","fnLoc":{"start":{"line":8,"column":2,"index":269},"end":{"line":8,"column":50,"index":317},"filename":"mutate-after-useeffect-ref-access.ts"},"decorations":[{"start":{"line":8,"column":24,"index":291},"end":{"line":8,"column":30,"index":297},"filename":"mutate-after-useeffect-ref-access.ts","identifierName":"arrRef"}]} {"kind":"CompileSuccess","fnLoc":{"start":{"line":6,"column":0,"index":190},"end":{"line":11,"column":1,"index":363},"filename":"mutate-after-useeffect-ref-access.ts"},"fnName":"Component","memoSlots":0,"memoBlocks":0,"memoValues":0,"prunedMemoBlocks":0,"prunedMemoValues":0} ``` diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.maybe-invalid-useCallback-read-maybeRef.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.maybe-invalid-useCallback-read-maybeRef.expect.md deleted file mode 100644 index 8cc7c5a49da..00000000000 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.maybe-invalid-useCallback-read-maybeRef.expect.md +++ /dev/null @@ -1,39 +0,0 @@ - -## Input - -```javascript -// @validatePreserveExistingMemoizationGuarantees -import {useCallback} from 'react'; - -function useHook(maybeRef) { - return useCallback(() => { - return [maybeRef.current]; - }, [maybeRef]); -} - -``` - - -## Error - -``` -Found 1 error: - -Memoization: Compilation skipped because existing memoization could not be preserved - -React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `maybeRef.current`, but the source dependencies were [maybeRef]. Differences in ref.current access. - -error.maybe-invalid-useCallback-read-maybeRef.ts:5:21 - 3 | - 4 | function useHook(maybeRef) { -> 5 | return useCallback(() => { - | ^^^^^^^ -> 6 | return [maybeRef.current]; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -> 7 | }, [maybeRef]); - | ^^^^ Could not preserve existing manual memoization - 8 | } - 9 | -``` - - \ No newline at end of file diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.maybe-invalid-useMemo-read-maybeRef.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.maybe-invalid-useMemo-read-maybeRef.expect.md deleted file mode 100644 index 38fd74e66a6..00000000000 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.maybe-invalid-useMemo-read-maybeRef.expect.md +++ /dev/null @@ -1,39 +0,0 @@ - -## Input - -```javascript -// @validatePreserveExistingMemoizationGuarantees -import {useMemo} from 'react'; - -function useHook(maybeRef, shouldRead) { - return useMemo(() => { - return () => [maybeRef.current]; - }, [shouldRead, maybeRef]); -} - -``` - - -## Error - -``` -Found 1 error: - -Memoization: Compilation skipped because existing memoization could not be preserved - -React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `maybeRef.current`, but the source dependencies were [shouldRead, maybeRef]. Differences in ref.current access. - -error.maybe-invalid-useMemo-read-maybeRef.ts:5:17 - 3 | - 4 | function useHook(maybeRef, shouldRead) { -> 5 | return useMemo(() => { - | ^^^^^^^ -> 6 | return () => [maybeRef.current]; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -> 7 | }, [shouldRead, maybeRef]); - | ^^^^ Could not preserve existing manual memoization - 8 | } - 9 | -``` - - \ No newline at end of file diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/repro-maybe-invalid-useCallback-read-maybeRef.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/repro-maybe-invalid-useCallback-read-maybeRef.expect.md new file mode 100644 index 00000000000..0ccfd1e43a6 --- /dev/null +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/repro-maybe-invalid-useCallback-read-maybeRef.expect.md @@ -0,0 +1,38 @@ + +## Input + +```javascript +// @validatePreserveExistingMemoizationGuarantees +import {useCallback} from 'react'; + +function useHook(maybeRef) { + return useCallback(() => { + return [maybeRef.current]; + }, [maybeRef]); +} + +``` + +## Code + +```javascript +import { c as _c } from "react/compiler-runtime"; // @validatePreserveExistingMemoizationGuarantees +import { useCallback } from "react"; + +function useHook(maybeRef) { + const $ = _c(2); + let t0; + if ($[0] !== maybeRef) { + t0 = () => [maybeRef.current]; + $[0] = maybeRef; + $[1] = t0; + } else { + t0 = $[1]; + } + return t0; +} + +``` + +### Eval output +(kind: exception) Fixture not implemented \ No newline at end of file diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.maybe-invalid-useCallback-read-maybeRef.ts b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/repro-maybe-invalid-useCallback-read-maybeRef.ts similarity index 100% rename from compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.maybe-invalid-useCallback-read-maybeRef.ts rename to compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/repro-maybe-invalid-useCallback-read-maybeRef.ts diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/repro-maybe-invalid-useMemo-read-maybeRef.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/repro-maybe-invalid-useMemo-read-maybeRef.expect.md new file mode 100644 index 00000000000..9d02bff8b4c --- /dev/null +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/repro-maybe-invalid-useMemo-read-maybeRef.expect.md @@ -0,0 +1,38 @@ + +## Input + +```javascript +// @validatePreserveExistingMemoizationGuarantees +import {useMemo} from 'react'; + +function useHook(maybeRef, shouldRead) { + return useMemo(() => { + return () => [maybeRef.current]; + }, [shouldRead, maybeRef]); +} + +``` + +## Code + +```javascript +import { c as _c } from "react/compiler-runtime"; // @validatePreserveExistingMemoizationGuarantees +import { useMemo } from "react"; + +function useHook(maybeRef, shouldRead) { + const $ = _c(2); + let t0; + if ($[0] !== maybeRef) { + t0 = () => [maybeRef.current]; + $[0] = maybeRef; + $[1] = t0; + } else { + t0 = $[1]; + } + return t0; +} + +``` + +### Eval output +(kind: exception) Fixture not implemented \ No newline at end of file diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.maybe-invalid-useMemo-read-maybeRef.ts b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/repro-maybe-invalid-useMemo-read-maybeRef.ts similarity index 100% rename from compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.maybe-invalid-useMemo-read-maybeRef.ts rename to compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/repro-maybe-invalid-useMemo-read-maybeRef.ts diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-ref-mutable-range.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-ref-mutable-range.expect.md new file mode 100644 index 00000000000..0ce46d3cc5c --- /dev/null +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-ref-mutable-range.expect.md @@ -0,0 +1,89 @@ + +## Input + +```javascript +import {Stringify, identity, mutate, CONST_TRUE} from 'shared-runtime'; + +function Foo(props, ref) { + const value = {}; + if (CONST_TRUE) { + mutate(value); + return ; + } + mutate(value); + if (CONST_TRUE) { + return ; + } + return value; +} + +export const FIXTURE_ENTRYPOINT = { + fn: Foo, + params: [{}, {current: 'fake-ref-object'}], +}; + +``` + +## Code + +```javascript +import { c as _c } from "react/compiler-runtime"; +import { Stringify, identity, mutate, CONST_TRUE } from "shared-runtime"; + +function Foo(props, ref) { + const $ = _c(7); + let t0; + let value; + if ($[0] !== ref) { + t0 = Symbol.for("react.early_return_sentinel"); + bb0: { + value = {}; + if (CONST_TRUE) { + mutate(value); + t0 = ; + break bb0; + } + + mutate(value); + } + $[0] = ref; + $[1] = t0; + $[2] = value; + } else { + t0 = $[1]; + value = $[2]; + } + if (t0 !== Symbol.for("react.early_return_sentinel")) { + return t0; + } + if (CONST_TRUE) { + let t1; + if ($[3] !== ref) { + t1 = identity(ref); + $[3] = ref; + $[4] = t1; + } else { + t1 = $[4]; + } + let t2; + if ($[5] !== t1) { + t2 = ; + $[5] = t1; + $[6] = t2; + } else { + t2 = $[6]; + } + return t2; + } + return value; +} + +export const FIXTURE_ENTRYPOINT = { + fn: Foo, + params: [{}, { current: "fake-ref-object" }], +}; + +``` + +### Eval output +(kind: ok)
{"ref":{"current":"fake-ref-object"}}
\ No newline at end of file diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.repro-ref-mutable-range.tsx b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-ref-mutable-range.tsx similarity index 100% rename from compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.repro-ref-mutable-range.tsx rename to compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-ref-mutable-range.tsx