mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
[rhir] Add dependencies produced by active (incomplete) scopes
---
> If this operand is used in a scope, has a dynamic value, and was defined
before this scope, then its a dependency of the scope.
> (from current comments in PropagateScopeDependencies::visitDependency)
A reactive scope can take a dependency from a definition produced by an
incomplete parent scope. Our tests previously did not cover this, since most
object types aliased together and remained mutable throughout a ReactiveScope.
e.g. our tests did not have
```
scope @0 (deps=..., declarations=[x, y]) {
x = {};
// define a reactive, immutable value that is not aliased to become mutable
const immutableVal = ...;
scope @1 (deps=immutableVal, declarations=[y]) {
y = read(immutableVal)
}
mutateX(x, ...);
}
```
We should not add a dependency if it is produced in exactly the same scope as
the one it is used. It is safe (and correct) to depend on values produced by a
parent scope.
---
Note that we still should check for whether a defining scope is active to
determine whether it should be added as a output of that scope
([src](https://github.com/facebook/react-forget/blob/b608ab20d57229b528deeffa19f1ee08a4bad37a/forget/src/ReactiveScopes/PropagateScopeDependencies.ts#L469-L478)).
Access of an identifier produced by a parent scope (i.e. adding a variable
defined by a scope's parent as its own dependency) does not require adding that
identifier to the parent's `declarations`, since that identifier is already
valid to access via identifier binding rules.
This commit is contained in:
@@ -505,7 +505,7 @@ class Context {
|
||||
currentDeclaration !== undefined &&
|
||||
currentDeclaration.id < currentScope.range.start &&
|
||||
(currentDeclaration.scope == null ||
|
||||
!this.#isScopeActive(currentDeclaration.scope))
|
||||
currentDeclaration.scope !== currentScope)
|
||||
) {
|
||||
// Check if there is an existing dependency that describes this operand
|
||||
// We do not try to join/reduce dependencies here due to missing info
|
||||
|
||||
@@ -53,7 +53,7 @@ function AllocatingPrimitiveAsDep(props) {
|
||||
}
|
||||
|
||||
function PrimitiveAsDepNested(props) {
|
||||
const $ = React.unstable_useMemoCache(8);
|
||||
const $ = React.unstable_useMemoCache(10);
|
||||
const c_0 = $[0] !== props.b;
|
||||
const c_1 = $[1] !== props.a;
|
||||
let x;
|
||||
@@ -69,12 +69,15 @@ function PrimitiveAsDepNested(props) {
|
||||
} else {
|
||||
t0 = $[4];
|
||||
}
|
||||
const t1 = t0 + 1;
|
||||
const c_5 = $[5] !== t1;
|
||||
let y;
|
||||
if ($[5] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
y = foo(t0 + 1);
|
||||
$[5] = y;
|
||||
if (c_5) {
|
||||
y = foo(t1);
|
||||
$[5] = t1;
|
||||
$[6] = y;
|
||||
} else {
|
||||
y = $[5];
|
||||
y = $[6];
|
||||
}
|
||||
mutate(x, props.a);
|
||||
$[0] = props.b;
|
||||
@@ -83,16 +86,18 @@ function PrimitiveAsDepNested(props) {
|
||||
} else {
|
||||
x = $[2];
|
||||
}
|
||||
const c_6 = $[6] !== x;
|
||||
let t1;
|
||||
if (c_6) {
|
||||
t1 = [x, y];
|
||||
$[6] = x;
|
||||
$[7] = t1;
|
||||
const c_7 = $[7] !== x;
|
||||
const c_8 = $[8] !== y;
|
||||
let t2;
|
||||
if (c_7 || c_8) {
|
||||
t2 = [x, y];
|
||||
$[7] = x;
|
||||
$[8] = y;
|
||||
$[9] = t2;
|
||||
} else {
|
||||
t1 = $[7];
|
||||
t2 = $[9];
|
||||
}
|
||||
return t1;
|
||||
return t2;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
@@ -46,19 +46,22 @@ function PrimitiveAsDep(props) {
|
||||
}
|
||||
|
||||
function PrimitiveAsDepNested(props) {
|
||||
const $ = React.unstable_useMemoCache(6);
|
||||
const $ = React.unstable_useMemoCache(8);
|
||||
const c_0 = $[0] !== props.b;
|
||||
const c_1 = $[1] !== props.a;
|
||||
let x;
|
||||
if (c_0 || c_1) {
|
||||
x = {};
|
||||
mutate(x);
|
||||
const t0 = props.b + 1;
|
||||
const c_3 = $[3] !== t0;
|
||||
let y;
|
||||
if ($[3] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
y = foo(props.b + 1);
|
||||
$[3] = y;
|
||||
if (c_3) {
|
||||
y = foo(t0);
|
||||
$[3] = t0;
|
||||
$[4] = y;
|
||||
} else {
|
||||
y = $[3];
|
||||
y = $[4];
|
||||
}
|
||||
mutate(x, props.a);
|
||||
$[0] = props.b;
|
||||
@@ -67,16 +70,18 @@ function PrimitiveAsDepNested(props) {
|
||||
} else {
|
||||
x = $[2];
|
||||
}
|
||||
const c_4 = $[4] !== x;
|
||||
let t0;
|
||||
if (c_4) {
|
||||
t0 = [x, y];
|
||||
$[4] = x;
|
||||
$[5] = t0;
|
||||
const c_5 = $[5] !== x;
|
||||
const c_6 = $[6] !== y;
|
||||
let t1;
|
||||
if (c_5 || c_6) {
|
||||
t1 = [x, y];
|
||||
$[5] = x;
|
||||
$[6] = y;
|
||||
$[7] = t1;
|
||||
} else {
|
||||
t0 = $[5];
|
||||
t1 = $[7];
|
||||
}
|
||||
return t0;
|
||||
return t1;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user