[hir] Mark ObjectExpression capturing a context ref as a context ref

A context ref capture is transitive.
This commit is contained in:
Sathya Gunasekaran
2023-02-10 17:59:57 +00:00
parent fa57551dd5
commit 343ebb47bd
5 changed files with 125 additions and 1 deletions
@@ -584,7 +584,10 @@ function inferBlock(env: Environment, block: BasicBlock) {
break;
}
case "ObjectExpression": {
valueKind = ValueKind.Mutable;
valueKind = hasContextRefOperand(env, instrValue)
? ValueKind.Context
: ValueKind.Mutable;
// Object construction captures but does not modify the key/property values
effectKind = Effect.Capture;
lvalueEffect = Effect.Store;
@@ -843,3 +846,10 @@ export function parseHookCall(place: Place): Hook | null {
valueKind: ValueKind.Mutable,
};
}
function hasContextRefOperand(env: Environment, instrValue: InstructionValue) {
for (const place of eachInstructionValueOperand(instrValue)) {
if (env.kind(place) === ValueKind.Context) return true;
}
return false;
}
@@ -0,0 +1,46 @@
## Input
```javascript
function component(foo, bar) {
let x = { foo };
let y = { bar };
(function () {
let a = { y };
let b = x;
a.x = b;
})();
mutate(y);
return x;
}
```
## Code
```javascript
function component(foo, bar) {
const $ = React.unstable_useMemoCache();
const c_0 = $[0] !== foo;
const c_1 = $[1] !== bar;
let x;
if (c_0 || c_1) {
x = { foo: foo };
const y = { bar: bar };
(function () {
let a = { y };
let b = x;
a.x = b;
})();
mutate(y);
$[0] = foo;
$[1] = bar;
$[2] = x;
} else {
x = $[2];
}
return x;
}
```
@@ -0,0 +1,11 @@
function component(foo, bar) {
let x = { foo };
let y = { bar };
(function () {
let a = { y };
let b = x;
a.x = b;
})();
mutate(y);
return x;
}
@@ -0,0 +1,46 @@
## Input
```javascript
function component(foo, bar) {
let x = { foo };
let y = { bar };
(function () {
let a = { y };
let b = x;
a.x = b;
})();
mutate(y);
return y;
}
```
## Code
```javascript
function component(foo, bar) {
const $ = React.unstable_useMemoCache();
const c_0 = $[0] !== foo;
const c_1 = $[1] !== bar;
let y;
if (c_0 || c_1) {
const x = { foo: foo };
y = { bar: bar };
(function () {
let a = { y };
let b = x;
a.x = b;
})();
mutate(y);
$[0] = foo;
$[1] = bar;
$[2] = y;
} else {
y = $[2];
}
return y;
}
```
@@ -0,0 +1,11 @@
function component(foo, bar) {
let x = { foo };
let y = { bar };
(function () {
let a = { y };
let b = x;
a.x = b;
})();
mutate(y);
return y;
}