Skip to content

Commit 347b95f

Browse files
committed
[compiler] Test fixture: non-reactive phi creates 'dangling ref' scope
ghstack-source-id: 2a6f36d Pull Request resolved: #31103
1 parent e957850 commit 347b95f

3 files changed

Lines changed: 104 additions & 0 deletions

File tree

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
2+
## Input
3+
4+
```javascript
5+
import { CONST_TRUE, Stringify, setProperty } from "shared-runtime";
6+
7+
function Component({arg}) {
8+
const obj = CONST_TRUE ? {inner: {value: "hello"}} : null;
9+
const boxedInner = [obj?.inner];
10+
useHook();
11+
setProperty(obj, arg);
12+
if (boxedInner[0] !== obj?.inner) {
13+
throw new Error("invariant broken");
14+
}
15+
return <Stringify obj={obj} inner={boxedInner} />;
16+
}
17+
18+
export const FIXTURE_ENTRYPOINT = {
19+
fn: Component,
20+
params: [{arg: 0}],
21+
sequentialRenders: [{arg: 0}, {arg: 1}]
22+
}
23+
24+
```
25+
26+
## Code
27+
28+
```javascript
29+
import { c as _c } from "react/compiler-runtime";
30+
import { CONST_TRUE, Stringify, setProperty } from "shared-runtime";
31+
32+
function Component(t0) {
33+
const $ = _c(5);
34+
const { arg } = t0;
35+
const obj = CONST_TRUE ? { inner: { value: "hello" } } : null;
36+
const t1 = obj?.inner;
37+
let t2;
38+
if ($[0] !== t1) {
39+
t2 = [t1];
40+
$[0] = t1;
41+
$[1] = t2;
42+
} else {
43+
t2 = $[1];
44+
}
45+
const boxedInner = t2;
46+
useHook();
47+
setProperty(obj, arg);
48+
if (boxedInner[0] !== obj?.inner) {
49+
throw new Error("invariant broken");
50+
}
51+
let t3;
52+
if ($[2] !== obj || $[3] !== boxedInner) {
53+
t3 = <Stringify obj={obj} inner={boxedInner} />;
54+
$[2] = obj;
55+
$[3] = boxedInner;
56+
$[4] = t3;
57+
} else {
58+
t3 = $[4];
59+
}
60+
return t3;
61+
}
62+
63+
export const FIXTURE_ENTRYPOINT = {
64+
fn: Component,
65+
params: [{ arg: 0 }],
66+
sequentialRenders: [{ arg: 0 }, { arg: 1 }],
67+
};
68+
69+
```
70+
71+
### Eval output
72+
(kind: ok) [[ (exception in render) ReferenceError: useHook is not defined ]]
73+
[[ (exception in render) ReferenceError: useHook is not defined ]]
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,7 @@ const skipFilter = new Set([
479479
'fbt/bug-fbt-plural-multiple-mixed-call-tag',
480480
'bug-invalid-hoisting-functionexpr',
481481
'bug-try-catch-maybe-null-dependency',
482+
'bug-invalid-phi-as-dependency',
482483
'reduce-reactive-deps/bug-infer-function-cond-access-not-hoisted',
483484
'reduce-reactive-deps/bug-merge-uncond-optional-chain-and-cond',
484485
'original-reactive-scopes-fork/bug-nonmutating-capture-in-unsplittable-memo-block',

0 commit comments

Comments
 (0)