@samitouri / QOS-React-2 / commits / 343ebb47bd

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

A context ref capture is transitive.

Sathya Gunasekaran committed Feb 10, 2023 at 17:59 UTC 343ebb47bd9fdf109c7a092a169c2a296f7f9f3a
5 files changed +125 -1
compiler/forget/src/Inference/InferReferenceEffects.ts
+11 -1
@@ -584,7 +584,10 @@ function inferBlock(env: Environment, block: BasicBlock) {
584 break;
585 }
586 case "ObjectExpression": {
587 - valueKind = ValueKind.Mutable;
587 + valueKind = hasContextRefOperand(env, instrValue)
588 + ? ValueKind.Context
589 + : ValueKind.Mutable;
590 +
591 // Object construction captures but does not modify the key/property values
592 effectKind = Effect.Capture;
593 lvalueEffect = Effect.Store;
@@ -843,3 +846,10 @@ export function parseHookCall(place: Place): Hook | null {
846 valueKind: ValueKind.Mutable,
847 };
848 }
849 +
850 +function hasContextRefOperand(env: Environment, instrValue: InstructionValue) {
851 + for (const place of eachInstructionValueOperand(instrValue)) {
852 + if (env.kind(place) === ValueKind.Context) return true;
853 + }
854 + return false;
855 +}
compiler/forget/src/__tests__/fixtures/hir/capturing-fun-alias-captured-mutate-2.expect.md new
+46
@@ -0,0 +1,46 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +function component(foo, bar) {
6 + let x = { foo };
7 + let y = { bar };
8 + (function () {
9 + let a = { y };
10 + let b = x;
11 + a.x = b;
12 + })();
13 + mutate(y);
14 + return x;
15 +}
16 +
17 +```
18 +
19 +## Code
20 +
21 +```javascript
22 +function component(foo, bar) {
23 + const $ = React.unstable_useMemoCache();
24 + const c_0 = $[0] !== foo;
25 + const c_1 = $[1] !== bar;
26 + let x;
27 + if (c_0 || c_1) {
28 + x = { foo: foo };
29 + const y = { bar: bar };
30 + (function () {
31 + let a = { y };
32 + let b = x;
33 + a.x = b;
34 + })();
35 + mutate(y);
36 + $[0] = foo;
37 + $[1] = bar;
38 + $[2] = x;
39 + } else {
40 + x = $[2];
41 + }
42 + return x;
43 +}
44 +
45 +```
46 +
\ No newline at end of file
compiler/forget/src/__tests__/fixtures/hir/capturing-fun-alias-captured-mutate-2.js new
+11
@@ -0,0 +1,11 @@
1 +function component(foo, bar) {
2 + let x = { foo };
3 + let y = { bar };
4 + (function () {
5 + let a = { y };
6 + let b = x;
7 + a.x = b;
8 + })();
9 + mutate(y);
10 + return x;
11 +}
compiler/forget/src/__tests__/fixtures/hir/capturing-func-alias-captured-mutate.expect.md new
+46
@@ -0,0 +1,46 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +function component(foo, bar) {
6 + let x = { foo };
7 + let y = { bar };
8 + (function () {
9 + let a = { y };
10 + let b = x;
11 + a.x = b;
12 + })();
13 + mutate(y);
14 + return y;
15 +}
16 +
17 +```
18 +
19 +## Code
20 +
21 +```javascript
22 +function component(foo, bar) {
23 + const $ = React.unstable_useMemoCache();
24 + const c_0 = $[0] !== foo;
25 + const c_1 = $[1] !== bar;
26 + let y;
27 + if (c_0 || c_1) {
28 + const x = { foo: foo };
29 + y = { bar: bar };
30 + (function () {
31 + let a = { y };
32 + let b = x;
33 + a.x = b;
34 + })();
35 + mutate(y);
36 + $[0] = foo;
37 + $[1] = bar;
38 + $[2] = y;
39 + } else {
40 + y = $[2];
41 + }
42 + return y;
43 +}
44 +
45 +```
46 +
\ No newline at end of file
compiler/forget/src/__tests__/fixtures/hir/capturing-func-alias-captured-mutate.js new
+11
@@ -0,0 +1,11 @@
1 +function component(foo, bar) {
2 + let x = { foo };
3 + let y = { bar };
4 + (function () {
5 + let a = { y };
6 + let b = x;
7 + a.x = b;
8 + })();
9 + mutate(y);
10 + return y;
11 +}