@samitouri / QOS-React / commits / fbfe37ee40

[compiler] Test fixture: non-reactive phi creates 'dangling ref' scope (#31103)

mofeiZ committed Oct 10, 2024 at 12:23 UTC fbfe37ee4010d36dad795d9144bb88fbeb8e1419
3 files changed +122
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/bug-invalid-phi-as-dependency.expect.md new
+91
@@ -0,0 +1,91 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +import {CONST_TRUE, Stringify, mutate, useIdentity} from 'shared-runtime';
6 +
7 +/**
8 + * Fixture showing an edge case for ReactiveScope variable propagation.
9 + *
10 + * Found differences in evaluator results
11 + * Non-forget (expected):
12 + * <div>{"obj":{"inner":{"value":"hello"},"wat0":"joe"},"inner":["[[ cyclic ref *2 ]]"]}</div>
13 + * <div>{"obj":{"inner":{"value":"hello"},"wat0":"joe"},"inner":["[[ cyclic ref *2 ]]"]}</div>
14 + * Forget:
15 + * <div>{"obj":{"inner":{"value":"hello"},"wat0":"joe"},"inner":["[[ cyclic ref *2 ]]"]}</div>
16 + * [[ (exception in render) Error: invariant broken ]]
17 + *
18 + */
19 +function Component() {
20 + const obj = CONST_TRUE ? {inner: {value: 'hello'}} : null;
21 + const boxedInner = [obj?.inner];
22 + useIdentity(null);
23 + mutate(obj);
24 + if (boxedInner[0] !== obj?.inner) {
25 + throw new Error('invariant broken');
26 + }
27 + return <Stringify obj={obj} inner={boxedInner} />;
28 +}
29 +
30 +export const FIXTURE_ENTRYPOINT = {
31 + fn: Component,
32 + params: [{arg: 0}],
33 + sequentialRenders: [{arg: 0}, {arg: 1}],
34 +};
35 +
36 +```
37 +
38 +## Code
39 +
40 +```javascript
41 +import { c as _c } from "react/compiler-runtime";
42 +import { CONST_TRUE, Stringify, mutate, useIdentity } from "shared-runtime";
43 +
44 +/**
45 + * Fixture showing an edge case for ReactiveScope variable propagation.
46 + *
47 + * Found differences in evaluator results
48 + * Non-forget (expected):
49 + * <div>{"obj":{"inner":{"value":"hello"},"wat0":"joe"},"inner":["[[ cyclic ref *2 ]]"]}</div>
50 + * <div>{"obj":{"inner":{"value":"hello"},"wat0":"joe"},"inner":["[[ cyclic ref *2 ]]"]}</div>
51 + * Forget:
52 + * <div>{"obj":{"inner":{"value":"hello"},"wat0":"joe"},"inner":["[[ cyclic ref *2 ]]"]}</div>
53 + * [[ (exception in render) Error: invariant broken ]]
54 + *
55 + */
56 +function Component() {
57 + const $ = _c(4);
58 + const obj = CONST_TRUE ? { inner: { value: "hello" } } : null;
59 + let t0;
60 + if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
61 + t0 = [obj?.inner];
62 + $[0] = t0;
63 + } else {
64 + t0 = $[0];
65 + }
66 + const boxedInner = t0;
67 + useIdentity(null);
68 + mutate(obj);
69 + if (boxedInner[0] !== obj?.inner) {
70 + throw new Error("invariant broken");
71 + }
72 + let t1;
73 + if ($[1] !== obj || $[2] !== boxedInner) {
74 + t1 = <Stringify obj={obj} inner={boxedInner} />;
75 + $[1] = obj;
76 + $[2] = boxedInner;
77 + $[3] = t1;
78 + } else {
79 + t1 = $[3];
80 + }
81 + return t1;
82 +}
83 +
84 +export const FIXTURE_ENTRYPOINT = {
85 + fn: Component,
86 + params: [{ arg: 0 }],
87 + sequentialRenders: [{ arg: 0 }, { arg: 1 }],
88 +};
89 +
90 +```
91 +
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/bug-invalid-phi-as-dependency.tsx new
+30
@@ -0,0 +1,30 @@
1 +import {CONST_TRUE, Stringify, mutate, useIdentity} from 'shared-runtime';
2 +
3 +/**
4 + * Fixture showing an edge case for ReactiveScope variable propagation.
5 + *
6 + * Found differences in evaluator results
7 + * Non-forget (expected):
8 + * <div>{"obj":{"inner":{"value":"hello"},"wat0":"joe"},"inner":["[[ cyclic ref *2 ]]"]}</div>
9 + * <div>{"obj":{"inner":{"value":"hello"},"wat0":"joe"},"inner":["[[ cyclic ref *2 ]]"]}</div>
10 + * Forget:
11 + * <div>{"obj":{"inner":{"value":"hello"},"wat0":"joe"},"inner":["[[ cyclic ref *2 ]]"]}</div>
12 + * [[ (exception in render) Error: invariant broken ]]
13 + *
14 + */
15 +function Component() {
16 + const obj = CONST_TRUE ? {inner: {value: 'hello'}} : null;
17 + const boxedInner = [obj?.inner];
18 + useIdentity(null);
19 + mutate(obj);
20 + if (boxedInner[0] !== obj?.inner) {
21 + throw new Error('invariant broken');
22 + }
23 + return <Stringify obj={obj} inner={boxedInner} />;
24 +}
25 +
26 +export const FIXTURE_ENTRYPOINT = {
27 + fn: Component,
28 + params: [{arg: 0}],
29 + sequentialRenders: [{arg: 0}, {arg: 1}],
30 +};
compiler/packages/snap/src/SproutTodoFilter.ts
+1
@@ -481,6 +481,7 @@ const skipFilter = new Set([
481 'bug-invalid-hoisting-functionexpr',
482 'bug-try-catch-maybe-null-dependency',
483 'reduce-reactive-deps/bug-infer-function-cond-access-not-hoisted',
484 + 'bug-invalid-phi-as-dependency',
485 'reduce-reactive-deps/bug-merge-uncond-optional-chain-and-cond',
486 'original-reactive-scopes-fork/bug-nonmutating-capture-in-unsplittable-memo-block',
487 'original-reactive-scopes-fork/bug-hoisted-declaration-with-scope',