mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
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:
+127
@@ -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;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
+14
@@ -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>
|
||||
);
|
||||
}
|
||||
+102
@@ -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;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
function Component(props) {
|
||||
const count = new MaybeMutable();
|
||||
return (
|
||||
<View>
|
||||
<View>
|
||||
{<span>Text</span>}
|
||||
{<span>{maybeMutate(count)}</span>}
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user