mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
Support complex computed properties in OptionalMemberExpression
Our previous lowering for OptionalMemberExpression reordered the evaluation of properties, such that we had to restrict the allowed properties to those that were safe for reordering. With the new representation we preserve order of evaluation, so we can relax the restriction. This unblocks a few cases in an internal product.
This commit is contained in:
@@ -2176,16 +2176,7 @@ function lowerMemberExpression(
|
||||
},
|
||||
};
|
||||
}
|
||||
let property: Place;
|
||||
// See "PropertyLoad" for the difference between optionalMemberExpr()
|
||||
// and node.optional here
|
||||
if (expr.isOptionalMemberExpression()) {
|
||||
// if expr is in an optional chain, evaluation of `property` is
|
||||
// conditional on whether expr is nullish
|
||||
property = lowerReorderableExpression(builder, propertyNode);
|
||||
} else {
|
||||
property = lowerExpressionToTemporary(builder, propertyNode);
|
||||
}
|
||||
const property = lowerExpressionToTemporary(builder, propertyNode);
|
||||
const value: InstructionValue = {
|
||||
kind: "ComputedLoad",
|
||||
object: { ...object },
|
||||
|
||||
-25
@@ -1,25 +0,0 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
function Component(props) {
|
||||
const object = makeObject(props);
|
||||
return object?.[props.key];
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
||||
## Error
|
||||
|
||||
```
|
||||
[ReactForget] TodoError: (BuildHIR::node.lowerReorderableExpression) Expression type 'MemberExpression' cannot be safely reordered
|
||||
1 | function Component(props) {
|
||||
2 | const object = makeObject(props);
|
||||
> 3 | return object?.[props.key];
|
||||
| ^^^^^^^^^
|
||||
4 | }
|
||||
5 |
|
||||
```
|
||||
|
||||
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
function Component(props) {
|
||||
const object = makeObject(props);
|
||||
return object?.[props.key];
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
import { unstable_useMemoCache as useMemoCache } from "react";
|
||||
function Component(props) {
|
||||
const $ = useMemoCache(5);
|
||||
const c_0 = $[0] !== props;
|
||||
let t0;
|
||||
if (c_0) {
|
||||
t0 = makeObject(props);
|
||||
$[0] = props;
|
||||
$[1] = t0;
|
||||
} else {
|
||||
t0 = $[1];
|
||||
}
|
||||
const object = t0;
|
||||
const c_2 = $[2] !== object;
|
||||
const c_3 = $[3] !== props;
|
||||
let t1;
|
||||
if (c_2 || c_3) {
|
||||
t1 = object?.[props.key];
|
||||
$[2] = object;
|
||||
$[3] = props;
|
||||
$[4] = t1;
|
||||
} else {
|
||||
t1 = $[4];
|
||||
}
|
||||
return t1;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
function Component(props) {
|
||||
const x = makeObject();
|
||||
return x?.[foo(props.value)];
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
import { unstable_useMemoCache as useMemoCache } from "react";
|
||||
function Component(props) {
|
||||
const $ = useMemoCache(4);
|
||||
let t0;
|
||||
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t0 = makeObject();
|
||||
$[0] = t0;
|
||||
} else {
|
||||
t0 = $[0];
|
||||
}
|
||||
const x = t0;
|
||||
const c_1 = $[1] !== props;
|
||||
const c_2 = $[2] !== x;
|
||||
let t1;
|
||||
if (c_1 || c_2) {
|
||||
t1 = x?.[foo(props.value)];
|
||||
$[1] = props;
|
||||
$[2] = x;
|
||||
$[3] = t1;
|
||||
} else {
|
||||
t1 = $[3];
|
||||
}
|
||||
return t1;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
function Component(props) {
|
||||
const x = makeObject();
|
||||
return x?.[foo(props.value)];
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
function Component(props) {
|
||||
const x = makeObject();
|
||||
return x.y?.[props.a?.[props.b?.[props.c]]];
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
import { unstable_useMemoCache as useMemoCache } from "react";
|
||||
function Component(props) {
|
||||
const $ = useMemoCache(4);
|
||||
let t0;
|
||||
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t0 = makeObject();
|
||||
$[0] = t0;
|
||||
} else {
|
||||
t0 = $[0];
|
||||
}
|
||||
const x = t0;
|
||||
const c_1 = $[1] !== x.y;
|
||||
const c_2 = $[2] !== props;
|
||||
let t1;
|
||||
if (c_1 || c_2) {
|
||||
t1 = x.y?.[props.a?.[props.b?.[props.c]]];
|
||||
$[1] = x.y;
|
||||
$[2] = props;
|
||||
$[3] = t1;
|
||||
} else {
|
||||
t1 = $[3];
|
||||
}
|
||||
return t1;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
function Component(props) {
|
||||
const x = makeObject();
|
||||
return x.y?.[props.a?.[props.b?.[props.c]]];
|
||||
}
|
||||
Reference in New Issue
Block a user