Repro for bug with memo vars at wrong block scope

Minimal(ish) repro of a bug we saw internally, where an output of a nested 
reactive scope is defined at the wrong block scope, and so later references to 
that value are invalid. 

The simplified structure is: 

``` 

scope0 inputs=[] outputs=[] { 

scope1 inputs=[] outputs=[t0] { 

t0 = ... 

} 

} 

t0 

``` 

Note that `t0` correctly appears as an output of the inner scope1, but not as an 
output of the outer scope0. We need to propagate outputs upward as necessary to 
ensure they are available at the right block scope: in this case, that would add 
`t0` as an output of scope0. 

An earlier version of PropagateScopeDependencies did this but it looks like it 
got lost along the way (not a big deal)
This commit is contained in:
Joe Savona
2023-04-18 16:10:00 -07:00
parent 746c1dbed5
commit fdbfac8f82
4 changed files with 254 additions and 0 deletions
@@ -0,0 +1,127 @@
## Input
```javascript
function Component(props) {
const item = useFragment(FRAGMENT, props.item);
useFreeze(item);
const count = new MaybeMutable(item);
return (
<View>
<View>
{<span>Text</span>}
{<span>{maybeMutate(count)}</span>}
</View>
</View>
);
}
```
## Code
```javascript
import * as React from "react";
function Component(props) {
const $ = React.unstable_useMemoCache(21);
const item = useFragment(FRAGMENT, props.item);
useFreeze(item);
const c_0 = $[0] !== item;
let t1;
let t2;
let t3;
let t4;
let t5;
let t6;
let t7;
if (c_0) {
const count = new MaybeMutable(item);
t6 = View;
t7 = "\n ";
t3 = View;
t4 = "\n ";
let t0;
if ($[8] === Symbol.for("react.memo_cache_sentinel")) {
t0 = <span>Text</span>;
$[8] = t0;
} else {
t0 = $[8];
}
t5 = "\n ";
t1 = "span";
t2 = maybeMutate(count);
$[0] = item;
$[1] = t1;
$[2] = t2;
$[3] = t3;
$[4] = t4;
$[5] = t5;
$[6] = t6;
$[7] = t7;
} else {
t1 = $[1];
t2 = $[2];
t3 = $[3];
t4 = $[4];
t5 = $[5];
t6 = $[6];
t7 = $[7];
}
const c_9 = $[9] !== t1;
const c_10 = $[10] !== t2;
let t8;
if (c_9 || c_10) {
t8 = <t1>{t2}</t1>;
$[9] = t1;
$[10] = t2;
$[11] = t8;
} else {
t8 = $[11];
}
const c_12 = $[12] !== t3;
const c_13 = $[13] !== t4;
const c_14 = $[14] !== t5;
const c_15 = $[15] !== t8;
let t9;
if (c_12 || c_13 || c_14 || c_15) {
t9 = (
<t3>
{t4}
{t0}
{t5}
{t8}
</t3>
);
$[12] = t3;
$[13] = t4;
$[14] = t5;
$[15] = t8;
$[16] = t9;
} else {
t9 = $[16];
}
const c_17 = $[17] !== t6;
const c_18 = $[18] !== t7;
const c_19 = $[19] !== t9;
let t10;
if (c_17 || c_18 || c_19) {
t10 = (
<t6>
{t7}
{t9}
</t6>
);
$[17] = t6;
$[18] = t7;
$[19] = t9;
$[20] = t10;
} else {
t10 = $[20];
}
return t10;
}
```
@@ -0,0 +1,14 @@
function Component(props) {
const item = useFragment(FRAGMENT, props.item);
useFreeze(item);
const count = new MaybeMutable(item);
return (
<View>
<View>
{<span>Text</span>}
{<span>{maybeMutate(count)}</span>}
</View>
</View>
);
}
@@ -0,0 +1,102 @@
## Input
```javascript
function Component(props) {
const count = new MaybeMutable();
return (
<View>
<View>
{<span>Text</span>}
{<span>{maybeMutate(count)}</span>}
</View>
</View>
);
}
```
## Code
```javascript
import * as React from "react";
function Component(props) {
const $ = React.unstable_useMemoCache(11);
let t1;
let t2;
let t3;
let t4;
let t5;
let t6;
let t7;
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
const count = new MaybeMutable();
t6 = View;
t7 = "\n ";
t3 = View;
t4 = "\n ";
let t0;
if ($[7] === Symbol.for("react.memo_cache_sentinel")) {
t0 = <span>Text</span>;
$[7] = t0;
} else {
t0 = $[7];
}
t5 = "\n ";
t1 = "span";
t2 = maybeMutate(count);
$[0] = t1;
$[1] = t2;
$[2] = t3;
$[3] = t4;
$[4] = t5;
$[5] = t6;
$[6] = t7;
} else {
t1 = $[0];
t2 = $[1];
t3 = $[2];
t4 = $[3];
t5 = $[4];
t6 = $[5];
t7 = $[6];
}
let t8;
if ($[8] === Symbol.for("react.memo_cache_sentinel")) {
t8 = <t1>{t2}</t1>;
$[8] = t8;
} else {
t8 = $[8];
}
let t9;
if ($[9] === Symbol.for("react.memo_cache_sentinel")) {
t9 = (
<t3>
{t4}
{t0}
{t5}
{t8}
</t3>
);
$[9] = t9;
} else {
t9 = $[9];
}
let t10;
if ($[10] === Symbol.for("react.memo_cache_sentinel")) {
t10 = (
<t6>
{t7}
{t9}
</t6>
);
$[10] = t10;
} else {
t10 = $[10];
}
return t10;
}
```
@@ -0,0 +1,11 @@
function Component(props) {
const count = new MaybeMutable();
return (
<View>
<View>
{<span>Text</span>}
{<span>{maybeMutate(count)}</span>}
</View>
</View>
);
}