mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
Improve conditional dependency tracking for optional member expr inside optional
call When we traverse an OptionalExpression in PropagateScopeDependencies, we previously considered the entire value to be optional. With the changes in this stack to more accurately model OptionalMemberExpression, the `object` portion of an OptionalMemberExpression is now evaluated within the OptionalExpression. This PR refines the handling of OptionalExpression accordingly, so that we only treat the optional portion as conditional.
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import { CompilerError } from "../CompilerError";
|
||||
import {
|
||||
Identifier,
|
||||
IdentifierId,
|
||||
@@ -451,9 +452,26 @@ class PropagationVisitor extends ReactiveFunctionVisitor<Context> {
|
||||
): void {
|
||||
switch (value.kind) {
|
||||
case "OptionalExpression": {
|
||||
context.enterConditional(() => {
|
||||
this.visitReactiveValue(context, id, value.value);
|
||||
});
|
||||
const inner = value.value;
|
||||
// OptionalExpression value is a SequenceExpression where the instructions
|
||||
// represent the code prior to the `?` and the final value represents the
|
||||
// conditional code that follows.
|
||||
if (inner.kind === "SequenceExpression") {
|
||||
// Instructions are the unconditionally executed portion before the `?`
|
||||
for (const instr of inner.instructions) {
|
||||
this.visitInstruction(instr, context);
|
||||
}
|
||||
// The final value is the conditional portion following the `?`
|
||||
context.enterConditional(() => {
|
||||
this.visitReactiveValue(context, id, inner.value);
|
||||
});
|
||||
} else {
|
||||
CompilerError.invariant(
|
||||
"Expected OptionalExpression value to be a SequenceExpression",
|
||||
value.loc,
|
||||
`Found a '${value.kind}'`
|
||||
);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "LogicalExpression": {
|
||||
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
function Component(props) {
|
||||
return props.post.feedback.comments?.edges?.map(render);
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
import { unstable_useMemoCache as useMemoCache } from "react";
|
||||
function Component(props) {
|
||||
const $ = useMemoCache(2);
|
||||
const c_0 = $[0] !== props.post.feedback.comments;
|
||||
let t0;
|
||||
if (c_0) {
|
||||
t0 = props.post.feedback.comments?.edges?.map(render);
|
||||
$[0] = props.post.feedback.comments;
|
||||
$[1] = t0;
|
||||
} else {
|
||||
t0 = $[1];
|
||||
}
|
||||
return t0;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
function Component(props) {
|
||||
return props.post.feedback.comments?.edges?.map(render);
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
function Component(props) {
|
||||
const x = [];
|
||||
x.push(props.items?.length);
|
||||
x.push(props.items?.edges?.map?.(render)?.filter?.(Boolean) ?? []);
|
||||
return x;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
import { unstable_useMemoCache as useMemoCache } from "react";
|
||||
function Component(props) {
|
||||
const $ = useMemoCache(2);
|
||||
const c_0 = $[0] !== props.items;
|
||||
let x;
|
||||
if (c_0) {
|
||||
x = [];
|
||||
x.push(props.items?.length);
|
||||
x.push(props.items?.edges?.map?.(render)?.filter?.(Boolean) ?? []);
|
||||
$[0] = props.items;
|
||||
$[1] = x;
|
||||
} else {
|
||||
x = $[1];
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
function Component(props) {
|
||||
const x = [];
|
||||
x.push(props.items?.length);
|
||||
x.push(props.items?.edges?.map?.(render)?.filter?.(Boolean) ?? []);
|
||||
return x;
|
||||
}
|
||||
Reference in New Issue
Block a user