Test cases for optional call

Tests, focusing on two key behaviors: 

* Dependencies of the args are treated as conditional, since the call may not 
happen 

* Args cannot be memoized independently, even when that would be valid for a 
non-optional call.
This commit is contained in:
Joe Savona
2023-03-24 14:22:15 -07:00
parent 77bb9ff765
commit 326ee664dc
7 changed files with 167 additions and 0 deletions
+7
View File
@@ -960,8 +960,13 @@ function lowerExpression(
const place = buildTemporaryPlace(builder, loc);
const continuationBlock = builder.reserve(builder.currentBlockKind());
// Lower the callee in the current block: the callee is always unconditionally evaluated
// The test block's branch will test on this value to determine whether to evaluate the call (consequent)
// or evaluate to undefined (alternate)
const callee = lowerExpressionToTemporary(builder, calleePath);
// block to evaluate if the callee is non-null/undefined. arguments are lowered in this block to preserve
// the semantic of conditional evaluation depending on the callee
const consequent = builder.enter("value", () => {
const args = lowerArguments(builder, expr.get("arguments"));
const temp = buildTemporaryPlace(builder, loc);
@@ -994,6 +999,8 @@ function lowerExpression(
id: makeInstructionId(0),
};
});
// block to evaluate if the callee is null/undefined, this sets the result of the call to undefined.
const alternate = builder.enter("value", () => {
const temp = buildTemporaryPlace(builder, loc);
builder.push({
@@ -0,0 +1,55 @@
## Input
```javascript
function Component(props) {
const x = makeFunction(props);
const y = x(
<div>
<span>{props.text}</span>
</div>
);
return y;
}
```
## Code
```javascript
function Component(props) {
const $ = React.unstable_useMemoCache(6);
const c_0 = $[0] !== props;
let t2;
if (c_0) {
const x = makeFunction(props);
const c_2 = $[2] !== props.text;
let t0;
if (c_2) {
t0 = <span>{props.text}</span>;
$[2] = props.text;
$[3] = t0;
} else {
t0 = $[3];
}
const c_4 = $[4] !== t0;
let t1;
if (c_4) {
t1 = <div>{t0}</div>;
$[4] = t0;
$[5] = t1;
} else {
t1 = $[5];
}
t2 = x(t1);
$[0] = props;
$[1] = t2;
} else {
t2 = $[1];
}
const y = t2;
return y;
}
```
@@ -0,0 +1,9 @@
function Component(props) {
const x = makeFunction(props);
const y = x(
<div>
<span>{props.text}</span>
</div>
);
return y;
}
@@ -0,0 +1,42 @@
## Input
```javascript
function Component(props) {
const x = makeOptionalFunction(props);
// for a regular call, the JSX element could be independently memoized
// since it is an immutable value. however, because the call is optional,
// we can't extract out independent memoization for the element w/o
// forcing that argument to evaluate unconditionally
const y = x?.(
<div>
<span>{props.text}</span>
</div>
);
return y;
}
```
## Code
```javascript
function Component(props) {
const $ = React.unstable_useMemoCache(2);
const c_0 = $[0] !== props;
let t0;
if (c_0) {
const x = makeOptionalFunction(props);
t0 = x?.(<div>{<span>{props.text}</span>}</div>);
$[0] = props;
$[1] = t0;
} else {
t0 = $[1];
}
const y = t0;
return y;
}
```
@@ -0,0 +1,13 @@
function Component(props) {
const x = makeOptionalFunction(props);
// for a regular call, the JSX element could be independently memoized
// since it is an immutable value. however, because the call is optional,
// we can't extract out independent memoization for the element w/o
// forcing that argument to evaluate unconditionally
const y = x?.(
<div>
<span>{props.text}</span>
</div>
);
return y;
}
@@ -0,0 +1,35 @@
## Input
```javascript
function Component(props) {
const x = makeOptionalFunction(props);
const y = makeObject(props);
const z = x?.(y.a, props.a, foo(y.b), bar(props.b));
return z;
}
```
## Code
```javascript
function Component(props) {
const $ = React.unstable_useMemoCache(2);
const c_0 = $[0] !== props;
let t0;
if (c_0) {
const x = makeOptionalFunction(props);
const y = makeObject(props);
t0 = x?.(y.a, props.a, foo(y.b), bar(props.b));
$[0] = props;
$[1] = t0;
} else {
t0 = $[1];
}
const z = t0;
return z;
}
```
@@ -0,0 +1,6 @@
function Component(props) {
const x = makeOptionalFunction(props);
const y = makeObject(props);
const z = x?.(y.a, props.a, foo(y.b), bar(props.b));
return z;
}