From b21ca44efc75178d797a6bd0427f83c966b2a00a Mon Sep 17 00:00:00 2001 From: Mofei Zhang Date: Tue, 23 Apr 2024 10:18:47 +0100 Subject: [PATCH] [repro] bug repro ghstack-source-id: 64d3266bf39ce5b1b9e9b9470910e029f0e951eb Pull Request resolved: https://github.com/facebook/react-forget/pull/2849 --- ...g-invalid-reactivity-value-block.expect.md | 97 +++++++++++++++++++ .../bug-invalid-reactivity-value-block.ts | 38 ++++++++ .../packages/snap/src/SproutTodoFilter.ts | 3 +- 3 files changed, 136 insertions(+), 2 deletions(-) create mode 100644 compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/bug-invalid-reactivity-value-block.expect.md create mode 100644 compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/bug-invalid-reactivity-value-block.ts diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/bug-invalid-reactivity-value-block.expect.md b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/bug-invalid-reactivity-value-block.expect.md new file mode 100644 index 0000000000..f9420efc7c --- /dev/null +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/bug-invalid-reactivity-value-block.expect.md @@ -0,0 +1,97 @@ + +## Input + +```javascript +import { + CONST_TRUE, + identity, + makeObject_Primitives, + useNoAlias, +} from "shared-runtime"; +/** + * BUG + * Found differences in evaluator results + * Non-forget (expected): + * (kind: ok) [{"a":0,"b":"value1","c":true},"[[ cyclic ref *1 ]]"] + * [{"a":0,"b":"value1","c":true},"[[ cyclic ref *1 ]]"] + * Forget: + * (kind: ok) [{"a":0,"b":"value1","c":true},"[[ cyclic ref *1 ]]"] + * [[ (exception in render) Error: Oh no! ]] + */ + +function Foo() { + const obj = makeObject_Primitives(); + // hook calls keeps the next two lines as its own reactive scope + useNoAlias(); + + const shouldCaptureObj = obj != null && CONST_TRUE; + const result = [shouldCaptureObj ? identity(obj) : null, obj]; + + useNoAlias(result, obj); + + if (shouldCaptureObj && result[0] !== obj) { + throw new Error("Unexpected"); + } + return result; +} + +export const FIXTURE_ENTRYPOINT = { + fn: Foo, + params: [{}], + sequentialRenders: [{}, {}], +}; + +``` + +## Code + +```javascript +import { unstable_useMemoCache as useMemoCache } from "react"; +import { + CONST_TRUE, + identity, + makeObject_Primitives, + useNoAlias, +} from "shared-runtime"; +/** + * BUG + * Found differences in evaluator results + * Non-forget (expected): + * (kind: ok) [{"a":0,"b":"value1","c":true},"[[ cyclic ref *1 ]]"] + * [{"a":0,"b":"value1","c":true},"[[ cyclic ref *1 ]]"] + * Forget: + * (kind: ok) [{"a":0,"b":"value1","c":true},"[[ cyclic ref *1 ]]"] + * [[ (exception in render) Error: Oh no! ]] + */ + +function Foo() { + const $ = useMemoCache(1); + const obj = makeObject_Primitives(); + + useNoAlias(); + + const shouldCaptureObj = obj != null && CONST_TRUE; + let t0; + if ($[0] === Symbol.for("react.memo_cache_sentinel")) { + t0 = [shouldCaptureObj ? identity(obj) : null, obj]; + $[0] = t0; + } else { + t0 = $[0]; + } + const result = t0; + + useNoAlias(result, obj); + if (shouldCaptureObj && result[0] !== obj) { + throw new Error("Unexpected"); + } + return result; +} + +export const FIXTURE_ENTRYPOINT = { + fn: Foo, + params: [{}], + sequentialRenders: [{}, {}], +}; + +``` + \ No newline at end of file diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/bug-invalid-reactivity-value-block.ts b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/bug-invalid-reactivity-value-block.ts new file mode 100644 index 0000000000..0205270757 --- /dev/null +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/bug-invalid-reactivity-value-block.ts @@ -0,0 +1,38 @@ +import { + CONST_TRUE, + identity, + makeObject_Primitives, + useNoAlias, +} from "shared-runtime"; +/** + * BUG + * Found differences in evaluator results + * Non-forget (expected): + * (kind: ok) [{"a":0,"b":"value1","c":true},"[[ cyclic ref *1 ]]"] + * [{"a":0,"b":"value1","c":true},"[[ cyclic ref *1 ]]"] + * Forget: + * (kind: ok) [{"a":0,"b":"value1","c":true},"[[ cyclic ref *1 ]]"] + * [[ (exception in render) Error: Oh no! ]] + */ + +function Foo() { + const obj = makeObject_Primitives(); + // hook calls keeps the next two lines as its own reactive scope + useNoAlias(); + + const shouldCaptureObj = obj != null && CONST_TRUE; + const result = [shouldCaptureObj ? identity(obj) : null, obj]; + + useNoAlias(result, obj); + + if (shouldCaptureObj && result[0] !== obj) { + throw new Error("Unexpected"); + } + return result; +} + +export const FIXTURE_ENTRYPOINT = { + fn: Foo, + params: [{}], + sequentialRenders: [{}, {}], +}; diff --git a/compiler/packages/snap/src/SproutTodoFilter.ts b/compiler/packages/snap/src/SproutTodoFilter.ts index e900610926..7a9d8c7781 100644 --- a/compiler/packages/snap/src/SproutTodoFilter.ts +++ b/compiler/packages/snap/src/SproutTodoFilter.ts @@ -488,8 +488,7 @@ const skipFilter = new Set([ "rules-of-hooks/rules-of-hooks-69521d94fa03", // bugs - "bug-reduce-reactive-deps-return-in-scope", - "bug-reduce-reactive-deps-break-in-scope", + "bug-invalid-reactivity-value-block", // 'react-forget-runtime' not yet supported "flag-enable-emit-hook-guards",