[compiler] Add types for WeakMap, WeakSet, and reanimated shared values
Building on mofeiz's recent work to type constructors. Also, types for reanimated values which are useful in the next PR. ghstack-source-id: 1c81e213a11337ac7e9c85a429ecf3f1d1adef66 Pull Request resolved: https://github.com/facebook/react/pull/33077
Joe Savona committed
May 3, 2025 at 09:15 UTC
4f1d2ddf95906e9a3436552c524410e9d39f48ca
7 files changed
+570
-1
compiler/packages/babel-plugin-react-compiler/src/HIR/Globals.ts
+36
-1
@@ -25,6 +25,9 @@ import {
25
BuiltInUseRefId,
26
BuiltInUseStateId,
27
BuiltInUseTransitionId,
28
+ BuiltInWeakMapId,
29
+ BuiltInWeakSetId,
30
+ ReanimatedSharedValueId,
31
ShapeRegistry,
32
addFunction,
33
addHook,
@@ -491,6 +494,38 @@ const TYPED_GLOBALS: Array<[string, BuiltInType]> = [
494
true,
495
),
496
],
497
+ [
498
+ 'WeakMap',
499
+ addFunction(
500
+ DEFAULT_SHAPES,
501
+ [],
502
+ {
503
+ positionalParams: [Effect.ConditionallyMutateIterator],
504
+ restParam: null,
505
+ returnType: {kind: 'Object', shapeId: BuiltInWeakMapId},
506
+ calleeEffect: Effect.Read,
507
+ returnValueKind: ValueKind.Mutable,
508
+ },
509
+ null,
510
+ true,
511
+ ),
512
+ ],
513
+ [
514
+ 'WeakSet',
515
+ addFunction(
516
+ DEFAULT_SHAPES,
517
+ [],
518
+ {
519
+ positionalParams: [Effect.ConditionallyMutateIterator],
520
+ restParam: null,
521
+ returnType: {kind: 'Object', shapeId: BuiltInWeakSetId},
522
+ calleeEffect: Effect.Read,
523
+ returnValueKind: ValueKind.Mutable,
524
+ },
525
+ null,
526
+ true,
527
+ ),
528
+ ],
529
// TODO: rest of Global objects
530
];
531
@@ -908,7 +943,7 @@ export function getReanimatedModuleType(registry: ShapeRegistry): ObjectType {
943
addHook(registry, {
944
positionalParams: [],
945
restParam: Effect.Freeze,
911
- returnType: {kind: 'Poly'},
946
+ returnType: {kind: 'Object', shapeId: ReanimatedSharedValueId},
947
returnValueKind: ValueKind.Mutable,
948
noAlias: true,
949
calleeEffect: Effect.Read,
compiler/packages/babel-plugin-react-compiler/src/HIR/HIR.ts
+12
@@ -1725,6 +1725,18 @@ export function isRefOrRefValue(id: Identifier): boolean {
1725
return isUseRefType(id) || isRefValueType(id);
1726
}
1727
1728
+/*
1729
+ * Returns true if the type is a Ref or a custom user type that acts like a ref when it
1730
+ * shouldn't. For now the only other case of this is Reanimated's shared values.
1731
+ */
1732
+export function isRefOrRefLikeMutableType(type: Type): boolean {
1733
+ return (
1734
+ type.kind === 'Object' &&
1735
+ (type.shapeId === 'BuiltInUseRefId' ||
1736
+ type.shapeId == 'ReanimatedSharedValueId')
1737
+ );
1738
+}
1739
+
1740
export function isSetStateType(id: Identifier): boolean {
1741
return id.type.kind === 'Function' && id.type.shapeId === 'BuiltInSetState';
1742
}
compiler/packages/babel-plugin-react-compiler/src/HIR/ObjectShape.ts
+100
@@ -203,6 +203,8 @@ export const BuiltInPropsId = 'BuiltInProps';
203
export const BuiltInArrayId = 'BuiltInArray';
204
export const BuiltInSetId = 'BuiltInSet';
205
export const BuiltInMapId = 'BuiltInMap';
206
+export const BuiltInWeakSetId = 'BuiltInWeakSet';
207
+export const BuiltInWeakMapId = 'BuiltInWeakMap';
208
export const BuiltInFunctionId = 'BuiltInFunction';
209
export const BuiltInJsxId = 'BuiltInJsx';
210
export const BuiltInObjectId = 'BuiltInObject';
@@ -225,6 +227,9 @@ export const BuiltInStartTransitionId = 'BuiltInStartTransition';
227
export const BuiltInFireId = 'BuiltInFire';
228
export const BuiltInFireFunctionId = 'BuiltInFireFunction';
229
230
+// See getReanimatedModuleType() in Globals.ts — this is part of supporting Reanimated's ref-like types
231
+export const ReanimatedSharedValueId = 'ReanimatedSharedValueId';
232
+
233
// ShapeRegistry with default definitions for built-ins.
234
export const BUILTIN_SHAPES: ShapeRegistry = new Map();
235
@@ -764,6 +769,101 @@ addObject(BUILTIN_SHAPES, BuiltInMapId, [
769
],
770
]);
771
772
+addObject(BUILTIN_SHAPES, BuiltInWeakSetId, [
773
+ [
774
+ /**
775
+ * add(value)
776
+ * Parameters
777
+ * value: the value of the element to add to the Set object.
778
+ * Returns the Set object with added value.
779
+ */
780
+ 'add',
781
+ addFunction(BUILTIN_SHAPES, [], {
782
+ positionalParams: [Effect.Capture],
783
+ restParam: null,
784
+ returnType: {kind: 'Object', shapeId: BuiltInWeakSetId},
785
+ calleeEffect: Effect.Store,
786
+ // returnValueKind is technically dependent on the ValueKind of the set itself
787
+ returnValueKind: ValueKind.Mutable,
788
+ }),
789
+ ],
790
+ [
791
+ /**
792
+ * setInstance.delete(value)
793
+ * Returns true if value was already in Set; otherwise false.
794
+ */
795
+ 'delete',
796
+ addFunction(BUILTIN_SHAPES, [], {
797
+ positionalParams: [Effect.Read],
798
+ restParam: null,
799
+ returnType: PRIMITIVE_TYPE,
800
+ calleeEffect: Effect.Store,
801
+ returnValueKind: ValueKind.Primitive,
802
+ }),
803
+ ],
804
+ [
805
+ 'has',
806
+ addFunction(BUILTIN_SHAPES, [], {
807
+ positionalParams: [Effect.Read],
808
+ restParam: null,
809
+ returnType: PRIMITIVE_TYPE,
810
+ calleeEffect: Effect.Read,
811
+ returnValueKind: ValueKind.Primitive,
812
+ }),
813
+ ],
814
+]);
815
+
816
+addObject(BUILTIN_SHAPES, BuiltInWeakMapId, [
817
+ [
818
+ 'delete',
819
+ addFunction(BUILTIN_SHAPES, [], {
820
+ positionalParams: [Effect.Read],
821
+ restParam: null,
822
+ returnType: PRIMITIVE_TYPE,
823
+ calleeEffect: Effect.Store,
824
+ returnValueKind: ValueKind.Primitive,
825
+ }),
826
+ ],
827
+ [
828
+ 'get',
829
+ addFunction(BUILTIN_SHAPES, [], {
830
+ positionalParams: [Effect.Read],
831
+ restParam: null,
832
+ returnType: {kind: 'Poly'},
833
+ calleeEffect: Effect.Capture,
834
+ returnValueKind: ValueKind.Mutable,
835
+ }),
836
+ ],
837
+ [
838
+ 'has',
839
+ addFunction(BUILTIN_SHAPES, [], {
840
+ positionalParams: [Effect.Read],
841
+ restParam: null,
842
+ returnType: PRIMITIVE_TYPE,
843
+ calleeEffect: Effect.Read,
844
+ returnValueKind: ValueKind.Primitive,
845
+ }),
846
+ ],
847
+ [
848
+ /**
849
+ * Params
850
+ * key: the key of the element to add to the Map object. The key may be
851
+ * any JavaScript type (any primitive value or any type of JavaScript
852
+ * object).
853
+ * value: the value of the element to add to the Map object.
854
+ * Returns the Map object.
855
+ */
856
+ 'set',
857
+ addFunction(BUILTIN_SHAPES, [], {
858
+ positionalParams: [Effect.Capture, Effect.Capture],
859
+ restParam: null,
860
+ returnType: {kind: 'Object', shapeId: BuiltInWeakMapId},
861
+ calleeEffect: Effect.Store,
862
+ returnValueKind: ValueKind.Mutable,
863
+ }),
864
+ ],
865
+]);
866
+
867
addObject(BUILTIN_SHAPES, BuiltInUseStateId, [
868
['0', {kind: 'Poly'}],
869
[
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/weakmap-constructor.expect.md
new
+176
@@ -0,0 +1,176 @@
1
+
2
+## Input
3
+
4
+```javascript
5
+import {ValidateMemoization} from 'shared-runtime';
6
+
7
+function Component({a, b, c}) {
8
+ const map = new WeakMap();
9
+ const mapAlias = map.set(a, 0);
10
+ mapAlias.set(c, 0);
11
+
12
+ const hasB = map.has(b);
13
+
14
+ return (
15
+ <>
16
+ <ValidateMemoization inputs={[a, c]} output={map} />
17
+ <ValidateMemoization inputs={[a, c]} output={mapAlias} />
18
+ <ValidateMemoization inputs={[b]} output={[hasB]} />
19
+ </>
20
+ );
21
+}
22
+
23
+const v1 = {value: 1};
24
+const v2 = {value: 2};
25
+const v3 = {value: 3};
26
+export const FIXTURE_ENTRYPOINT = {
27
+ fn: Component,
28
+ params: [{a: v1, b: v1, c: v1}],
29
+ sequentialRenders: [
30
+ {a: v1, b: v1, c: v1},
31
+ {a: v2, b: v1, c: v1},
32
+ {a: v1, b: v1, c: v1},
33
+ {a: v1, b: v2, c: v1},
34
+ {a: v1, b: v1, c: v1},
35
+ {a: v3, b: v3, c: v1},
36
+ {a: v3, b: v3, c: v1},
37
+ {a: v1, b: v1, c: v1},
38
+ ],
39
+};
40
+
41
+```
42
+
43
+## Code
44
+
45
+```javascript
46
+import { c as _c } from "react/compiler-runtime";
47
+import { ValidateMemoization } from "shared-runtime";
48
+
49
+function Component(t0) {
50
+ const $ = _c(27);
51
+ const { a, b, c } = t0;
52
+ let map;
53
+ let mapAlias;
54
+ if ($[0] !== a || $[1] !== c) {
55
+ map = new WeakMap();
56
+ mapAlias = map.set(a, 0);
57
+ mapAlias.set(c, 0);
58
+ $[0] = a;
59
+ $[1] = c;
60
+ $[2] = map;
61
+ $[3] = mapAlias;
62
+ } else {
63
+ map = $[2];
64
+ mapAlias = $[3];
65
+ }
66
+
67
+ const hasB = map.has(b);
68
+ let t1;
69
+ if ($[4] !== a || $[5] !== c) {
70
+ t1 = [a, c];
71
+ $[4] = a;
72
+ $[5] = c;
73
+ $[6] = t1;
74
+ } else {
75
+ t1 = $[6];
76
+ }
77
+ let t2;
78
+ if ($[7] !== map || $[8] !== t1) {
79
+ t2 = <ValidateMemoization inputs={t1} output={map} />;
80
+ $[7] = map;
81
+ $[8] = t1;
82
+ $[9] = t2;
83
+ } else {
84
+ t2 = $[9];
85
+ }
86
+ let t3;
87
+ if ($[10] !== a || $[11] !== c) {
88
+ t3 = [a, c];
89
+ $[10] = a;
90
+ $[11] = c;
91
+ $[12] = t3;
92
+ } else {
93
+ t3 = $[12];
94
+ }
95
+ let t4;
96
+ if ($[13] !== mapAlias || $[14] !== t3) {
97
+ t4 = <ValidateMemoization inputs={t3} output={mapAlias} />;
98
+ $[13] = mapAlias;
99
+ $[14] = t3;
100
+ $[15] = t4;
101
+ } else {
102
+ t4 = $[15];
103
+ }
104
+ let t5;
105
+ if ($[16] !== b) {
106
+ t5 = [b];
107
+ $[16] = b;
108
+ $[17] = t5;
109
+ } else {
110
+ t5 = $[17];
111
+ }
112
+ let t6;
113
+ if ($[18] !== hasB) {
114
+ t6 = [hasB];
115
+ $[18] = hasB;
116
+ $[19] = t6;
117
+ } else {
118
+ t6 = $[19];
119
+ }
120
+ let t7;
121
+ if ($[20] !== t5 || $[21] !== t6) {
122
+ t7 = <ValidateMemoization inputs={t5} output={t6} />;
123
+ $[20] = t5;
124
+ $[21] = t6;
125
+ $[22] = t7;
126
+ } else {
127
+ t7 = $[22];
128
+ }
129
+ let t8;
130
+ if ($[23] !== t2 || $[24] !== t4 || $[25] !== t7) {
131
+ t8 = (
132
+ <>
133
+ {t2}
134
+ {t4}
135
+ {t7}
136
+ </>
137
+ );
138
+ $[23] = t2;
139
+ $[24] = t4;
140
+ $[25] = t7;
141
+ $[26] = t8;
142
+ } else {
143
+ t8 = $[26];
144
+ }
145
+ return t8;
146
+}
147
+
148
+const v1 = { value: 1 };
149
+const v2 = { value: 2 };
150
+const v3 = { value: 3 };
151
+export const FIXTURE_ENTRYPOINT = {
152
+ fn: Component,
153
+ params: [{ a: v1, b: v1, c: v1 }],
154
+ sequentialRenders: [
155
+ { a: v1, b: v1, c: v1 },
156
+ { a: v2, b: v1, c: v1 },
157
+ { a: v1, b: v1, c: v1 },
158
+ { a: v1, b: v2, c: v1 },
159
+ { a: v1, b: v1, c: v1 },
160
+ { a: v3, b: v3, c: v1 },
161
+ { a: v3, b: v3, c: v1 },
162
+ { a: v1, b: v1, c: v1 },
163
+ ],
164
+};
165
+
166
+```
167
+
168
+### Eval output
169
+(kind: ok) <div>{"inputs":[{"value":1},"[[ cyclic ref *2 ]]"],"output":{}}</div><div>{"inputs":[{"value":1},"[[ cyclic ref *2 ]]"],"output":{}}</div><div>{"inputs":[{"value":1}],"output":[true]}</div>
170
+<div>{"inputs":[{"value":2},{"value":1}],"output":{}}</div><div>{"inputs":[{"value":2},{"value":1}],"output":{}}</div><div>{"inputs":[{"value":1}],"output":[true]}</div>
171
+<div>{"inputs":[{"value":1},"[[ cyclic ref *2 ]]"],"output":{}}</div><div>{"inputs":[{"value":1},"[[ cyclic ref *2 ]]"],"output":{}}</div><div>{"inputs":[{"value":1}],"output":[true]}</div>
172
+<div>{"inputs":[{"value":1},"[[ cyclic ref *2 ]]"],"output":{}}</div><div>{"inputs":[{"value":1},"[[ cyclic ref *2 ]]"],"output":{}}</div><div>{"inputs":[{"value":2}],"output":[false]}</div>
173
+<div>{"inputs":[{"value":1},"[[ cyclic ref *2 ]]"],"output":{}}</div><div>{"inputs":[{"value":1},"[[ cyclic ref *2 ]]"],"output":{}}</div><div>{"inputs":[{"value":1}],"output":[true]}</div>
174
+<div>{"inputs":[{"value":3},{"value":1}],"output":{}}</div><div>{"inputs":[{"value":3},{"value":1}],"output":{}}</div><div>{"inputs":[{"value":3}],"output":[true]}</div>
175
+<div>{"inputs":[{"value":3},{"value":1}],"output":{}}</div><div>{"inputs":[{"value":3},{"value":1}],"output":{}}</div><div>{"inputs":[{"value":3}],"output":[true]}</div>
176
+<div>{"inputs":[{"value":1},"[[ cyclic ref *2 ]]"],"output":{}}</div><div>{"inputs":[{"value":1},"[[ cyclic ref *2 ]]"],"output":{}}</div><div>{"inputs":[{"value":1}],"output":[true]}</div>
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/weakmap-constructor.js
new
+35
@@ -0,0 +1,35 @@
1
+import {ValidateMemoization} from 'shared-runtime';
2
+
3
+function Component({a, b, c}) {
4
+ const map = new WeakMap();
5
+ const mapAlias = map.set(a, 0);
6
+ mapAlias.set(c, 0);
7
+
8
+ const hasB = map.has(b);
9
+
10
+ return (
11
+ <>
12
+ <ValidateMemoization inputs={[a, c]} output={map} />
13
+ <ValidateMemoization inputs={[a, c]} output={mapAlias} />
14
+ <ValidateMemoization inputs={[b]} output={[hasB]} />
15
+ </>
16
+ );
17
+}
18
+
19
+const v1 = {value: 1};
20
+const v2 = {value: 2};
21
+const v3 = {value: 3};
22
+export const FIXTURE_ENTRYPOINT = {
23
+ fn: Component,
24
+ params: [{a: v1, b: v1, c: v1}],
25
+ sequentialRenders: [
26
+ {a: v1, b: v1, c: v1},
27
+ {a: v2, b: v1, c: v1},
28
+ {a: v1, b: v1, c: v1},
29
+ {a: v1, b: v2, c: v1},
30
+ {a: v1, b: v1, c: v1},
31
+ {a: v3, b: v3, c: v1},
32
+ {a: v3, b: v3, c: v1},
33
+ {a: v1, b: v1, c: v1},
34
+ ],
35
+};
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/weakset-constructor.expect.md
new
+176
@@ -0,0 +1,176 @@
1
+
2
+## Input
3
+
4
+```javascript
5
+import {ValidateMemoization} from 'shared-runtime';
6
+
7
+function Component({a, b, c}) {
8
+ const set = new WeakSet();
9
+ const setAlias = set.add(a);
10
+ setAlias.add(c);
11
+
12
+ const hasB = set.has(b);
13
+
14
+ return (
15
+ <>
16
+ <ValidateMemoization inputs={[a, c]} output={set} />
17
+ <ValidateMemoization inputs={[a, c]} output={setAlias} />
18
+ <ValidateMemoization inputs={[b]} output={[hasB]} />
19
+ </>
20
+ );
21
+}
22
+
23
+const v1 = {value: 1};
24
+const v2 = {value: 2};
25
+const v3 = {value: 3};
26
+export const FIXTURE_ENTRYPOINT = {
27
+ fn: Component,
28
+ params: [{a: v1, b: v1, c: v1}],
29
+ sequentialRenders: [
30
+ {a: v1, b: v1, c: v1},
31
+ {a: v2, b: v1, c: v1},
32
+ {a: v1, b: v1, c: v1},
33
+ {a: v1, b: v2, c: v1},
34
+ {a: v1, b: v1, c: v1},
35
+ {a: v3, b: v3, c: v1},
36
+ {a: v3, b: v3, c: v1},
37
+ {a: v1, b: v1, c: v1},
38
+ ],
39
+};
40
+
41
+```
42
+
43
+## Code
44
+
45
+```javascript
46
+import { c as _c } from "react/compiler-runtime";
47
+import { ValidateMemoization } from "shared-runtime";
48
+
49
+function Component(t0) {
50
+ const $ = _c(27);
51
+ const { a, b, c } = t0;
52
+ let set;
53
+ let setAlias;
54
+ if ($[0] !== a || $[1] !== c) {
55
+ set = new WeakSet();
56
+ setAlias = set.add(a);
57
+ setAlias.add(c);
58
+ $[0] = a;
59
+ $[1] = c;
60
+ $[2] = set;
61
+ $[3] = setAlias;
62
+ } else {
63
+ set = $[2];
64
+ setAlias = $[3];
65
+ }
66
+
67
+ const hasB = set.has(b);
68
+ let t1;
69
+ if ($[4] !== a || $[5] !== c) {
70
+ t1 = [a, c];
71
+ $[4] = a;
72
+ $[5] = c;
73
+ $[6] = t1;
74
+ } else {
75
+ t1 = $[6];
76
+ }
77
+ let t2;
78
+ if ($[7] !== set || $[8] !== t1) {
79
+ t2 = <ValidateMemoization inputs={t1} output={set} />;
80
+ $[7] = set;
81
+ $[8] = t1;
82
+ $[9] = t2;
83
+ } else {
84
+ t2 = $[9];
85
+ }
86
+ let t3;
87
+ if ($[10] !== a || $[11] !== c) {
88
+ t3 = [a, c];
89
+ $[10] = a;
90
+ $[11] = c;
91
+ $[12] = t3;
92
+ } else {
93
+ t3 = $[12];
94
+ }
95
+ let t4;
96
+ if ($[13] !== setAlias || $[14] !== t3) {
97
+ t4 = <ValidateMemoization inputs={t3} output={setAlias} />;
98
+ $[13] = setAlias;
99
+ $[14] = t3;
100
+ $[15] = t4;
101
+ } else {
102
+ t4 = $[15];
103
+ }
104
+ let t5;
105
+ if ($[16] !== b) {
106
+ t5 = [b];
107
+ $[16] = b;
108
+ $[17] = t5;
109
+ } else {
110
+ t5 = $[17];
111
+ }
112
+ let t6;
113
+ if ($[18] !== hasB) {
114
+ t6 = [hasB];
115
+ $[18] = hasB;
116
+ $[19] = t6;
117
+ } else {
118
+ t6 = $[19];
119
+ }
120
+ let t7;
121
+ if ($[20] !== t5 || $[21] !== t6) {
122
+ t7 = <ValidateMemoization inputs={t5} output={t6} />;
123
+ $[20] = t5;
124
+ $[21] = t6;
125
+ $[22] = t7;
126
+ } else {
127
+ t7 = $[22];
128
+ }
129
+ let t8;
130
+ if ($[23] !== t2 || $[24] !== t4 || $[25] !== t7) {
131
+ t8 = (
132
+ <>
133
+ {t2}
134
+ {t4}
135
+ {t7}
136
+ </>
137
+ );
138
+ $[23] = t2;
139
+ $[24] = t4;
140
+ $[25] = t7;
141
+ $[26] = t8;
142
+ } else {
143
+ t8 = $[26];
144
+ }
145
+ return t8;
146
+}
147
+
148
+const v1 = { value: 1 };
149
+const v2 = { value: 2 };
150
+const v3 = { value: 3 };
151
+export const FIXTURE_ENTRYPOINT = {
152
+ fn: Component,
153
+ params: [{ a: v1, b: v1, c: v1 }],
154
+ sequentialRenders: [
155
+ { a: v1, b: v1, c: v1 },
156
+ { a: v2, b: v1, c: v1 },
157
+ { a: v1, b: v1, c: v1 },
158
+ { a: v1, b: v2, c: v1 },
159
+ { a: v1, b: v1, c: v1 },
160
+ { a: v3, b: v3, c: v1 },
161
+ { a: v3, b: v3, c: v1 },
162
+ { a: v1, b: v1, c: v1 },
163
+ ],
164
+};
165
+
166
+```
167
+
168
+### Eval output
169
+(kind: ok) <div>{"inputs":[{"value":1},"[[ cyclic ref *2 ]]"],"output":{}}</div><div>{"inputs":[{"value":1},"[[ cyclic ref *2 ]]"],"output":{}}</div><div>{"inputs":[{"value":1}],"output":[true]}</div>
170
+<div>{"inputs":[{"value":2},{"value":1}],"output":{}}</div><div>{"inputs":[{"value":2},{"value":1}],"output":{}}</div><div>{"inputs":[{"value":1}],"output":[true]}</div>
171
+<div>{"inputs":[{"value":1},"[[ cyclic ref *2 ]]"],"output":{}}</div><div>{"inputs":[{"value":1},"[[ cyclic ref *2 ]]"],"output":{}}</div><div>{"inputs":[{"value":1}],"output":[true]}</div>
172
+<div>{"inputs":[{"value":1},"[[ cyclic ref *2 ]]"],"output":{}}</div><div>{"inputs":[{"value":1},"[[ cyclic ref *2 ]]"],"output":{}}</div><div>{"inputs":[{"value":2}],"output":[false]}</div>
173
+<div>{"inputs":[{"value":1},"[[ cyclic ref *2 ]]"],"output":{}}</div><div>{"inputs":[{"value":1},"[[ cyclic ref *2 ]]"],"output":{}}</div><div>{"inputs":[{"value":1}],"output":[true]}</div>
174
+<div>{"inputs":[{"value":3},{"value":1}],"output":{}}</div><div>{"inputs":[{"value":3},{"value":1}],"output":{}}</div><div>{"inputs":[{"value":3}],"output":[true]}</div>
175
+<div>{"inputs":[{"value":3},{"value":1}],"output":{}}</div><div>{"inputs":[{"value":3},{"value":1}],"output":{}}</div><div>{"inputs":[{"value":3}],"output":[true]}</div>
176
+<div>{"inputs":[{"value":1},"[[ cyclic ref *2 ]]"],"output":{}}</div><div>{"inputs":[{"value":1},"[[ cyclic ref *2 ]]"],"output":{}}</div><div>{"inputs":[{"value":1}],"output":[true]}</div>
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/weakset-constructor.js
new
+35
@@ -0,0 +1,35 @@
1
+import {ValidateMemoization} from 'shared-runtime';
2
+
3
+function Component({a, b, c}) {
4
+ const set = new WeakSet();
5
+ const setAlias = set.add(a);
6
+ setAlias.add(c);
7
+
8
+ const hasB = set.has(b);
9
+
10
+ return (
11
+ <>
12
+ <ValidateMemoization inputs={[a, c]} output={set} />
13
+ <ValidateMemoization inputs={[a, c]} output={setAlias} />
14
+ <ValidateMemoization inputs={[b]} output={[hasB]} />
15
+ </>
16
+ );
17
+}
18
+
19
+const v1 = {value: 1};
20
+const v2 = {value: 2};
21
+const v3 = {value: 3};
22
+export const FIXTURE_ENTRYPOINT = {
23
+ fn: Component,
24
+ params: [{a: v1, b: v1, c: v1}],
25
+ sequentialRenders: [
26
+ {a: v1, b: v1, c: v1},
27
+ {a: v2, b: v1, c: v1},
28
+ {a: v1, b: v1, c: v1},
29
+ {a: v1, b: v2, c: v1},
30
+ {a: v1, b: v1, c: v1},
31
+ {a: v3, b: v3, c: v1},
32
+ {a: v3, b: v3, c: v1},
33
+ {a: v1, b: v1, c: v1},
34
+ ],
35
+};