[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
+}