From f9f7e026b44b47e0f78f8912df154f329b8f3415 Mon Sep 17 00:00:00 2001 From: Joe Savona Date: Thu, 1 May 2025 17:43:43 +0900 Subject: [PATCH 1/3] [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-poisoned] --- .../src/HIR/Globals.ts | 37 ++++++- .../src/HIR/HIR.ts | 12 +++ .../src/HIR/ObjectShape.ts | 100 ++++++++++++++++++ 3 files changed, 148 insertions(+), 1 deletion(-) diff --git a/compiler/packages/babel-plugin-react-compiler/src/HIR/Globals.ts b/compiler/packages/babel-plugin-react-compiler/src/HIR/Globals.ts index 7ed42cbce132a..b8504494662d6 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/HIR/Globals.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/HIR/Globals.ts @@ -25,6 +25,9 @@ import { BuiltInUseRefId, BuiltInUseStateId, BuiltInUseTransitionId, + BuiltInWeakMapId, + BuiltInWeakSetId, + ReanimatedSharedValueId, ShapeRegistry, addFunction, addHook, @@ -491,6 +494,38 @@ const TYPED_GLOBALS: Array<[string, BuiltInType]> = [ true, ), ], + [ + 'WeakMap', + addFunction( + DEFAULT_SHAPES, + [], + { + positionalParams: [Effect.ConditionallyMutateIterator], + restParam: null, + returnType: {kind: 'Object', shapeId: BuiltInWeakMapId}, + calleeEffect: Effect.Read, + returnValueKind: ValueKind.Mutable, + }, + null, + true, + ), + ], + [ + 'WeakSet', + addFunction( + DEFAULT_SHAPES, + [], + { + positionalParams: [Effect.ConditionallyMutateIterator], + restParam: null, + returnType: {kind: 'Object', shapeId: BuiltInWeakSetId}, + calleeEffect: Effect.Read, + returnValueKind: ValueKind.Mutable, + }, + null, + true, + ), + ], // TODO: rest of Global objects ]; @@ -908,7 +943,7 @@ export function getReanimatedModuleType(registry: ShapeRegistry): ObjectType { addHook(registry, { positionalParams: [], restParam: Effect.Freeze, - returnType: {kind: 'Poly'}, + returnType: {kind: 'Object', shapeId: ReanimatedSharedValueId}, returnValueKind: ValueKind.Mutable, noAlias: true, calleeEffect: Effect.Read, diff --git a/compiler/packages/babel-plugin-react-compiler/src/HIR/HIR.ts b/compiler/packages/babel-plugin-react-compiler/src/HIR/HIR.ts index 611b5bd210226..99b8c189ee0fd 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/HIR/HIR.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/HIR/HIR.ts @@ -1725,6 +1725,18 @@ export function isRefOrRefValue(id: Identifier): boolean { return isUseRefType(id) || isRefValueType(id); } +/* + * Returns true if the type is a Ref or a custom user type that acts like a ref when it + * shouldn't. For now the only other case of this is Reanimated's shared values. + */ +export function isRefOrRefLikeMutableType(type: Type): boolean { + return ( + type.kind === 'Object' && + (type.shapeId === 'BuiltInUseRefId' || + type.shapeId == 'ReanimatedSharedValueId') + ); +} + export function isSetStateType(id: Identifier): boolean { return id.type.kind === 'Function' && id.type.shapeId === 'BuiltInSetState'; } diff --git a/compiler/packages/babel-plugin-react-compiler/src/HIR/ObjectShape.ts b/compiler/packages/babel-plugin-react-compiler/src/HIR/ObjectShape.ts index a599fc2d74760..4c137738665b6 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/HIR/ObjectShape.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/HIR/ObjectShape.ts @@ -203,6 +203,8 @@ export const BuiltInPropsId = 'BuiltInProps'; export const BuiltInArrayId = 'BuiltInArray'; export const BuiltInSetId = 'BuiltInSet'; export const BuiltInMapId = 'BuiltInMap'; +export const BuiltInWeakSetId = 'BuiltInWeakSet'; +export const BuiltInWeakMapId = 'BuiltInWeakMap'; export const BuiltInFunctionId = 'BuiltInFunction'; export const BuiltInJsxId = 'BuiltInJsx'; export const BuiltInObjectId = 'BuiltInObject'; @@ -225,6 +227,9 @@ export const BuiltInStartTransitionId = 'BuiltInStartTransition'; export const BuiltInFireId = 'BuiltInFire'; export const BuiltInFireFunctionId = 'BuiltInFireFunction'; +// See getReanimatedModuleType() in Globals.ts — this is part of supporting Reanimated's ref-like types +export const ReanimatedSharedValueId = 'ReanimatedSharedValueId'; + // ShapeRegistry with default definitions for built-ins. export const BUILTIN_SHAPES: ShapeRegistry = new Map(); @@ -764,6 +769,101 @@ addObject(BUILTIN_SHAPES, BuiltInMapId, [ ], ]); +addObject(BUILTIN_SHAPES, BuiltInWeakSetId, [ + [ + /** + * add(value) + * Parameters + * value: the value of the element to add to the Set object. + * Returns the Set object with added value. + */ + 'add', + addFunction(BUILTIN_SHAPES, [], { + positionalParams: [Effect.Capture], + restParam: null, + returnType: {kind: 'Object', shapeId: BuiltInSetId}, + calleeEffect: Effect.Store, + // returnValueKind is technically dependent on the ValueKind of the set itself + returnValueKind: ValueKind.Mutable, + }), + ], + [ + /** + * setInstance.delete(value) + * Returns true if value was already in Set; otherwise false. + */ + 'delete', + addFunction(BUILTIN_SHAPES, [], { + positionalParams: [Effect.Read], + restParam: null, + returnType: PRIMITIVE_TYPE, + calleeEffect: Effect.Store, + returnValueKind: ValueKind.Primitive, + }), + ], + [ + 'has', + addFunction(BUILTIN_SHAPES, [], { + positionalParams: [Effect.Read], + restParam: null, + returnType: PRIMITIVE_TYPE, + calleeEffect: Effect.Read, + returnValueKind: ValueKind.Primitive, + }), + ], +]); + +addObject(BUILTIN_SHAPES, BuiltInWeakMapId, [ + [ + 'delete', + addFunction(BUILTIN_SHAPES, [], { + positionalParams: [Effect.Read], + restParam: null, + returnType: PRIMITIVE_TYPE, + calleeEffect: Effect.Store, + returnValueKind: ValueKind.Primitive, + }), + ], + [ + 'get', + addFunction(BUILTIN_SHAPES, [], { + positionalParams: [Effect.Read], + restParam: null, + returnType: {kind: 'Poly'}, + calleeEffect: Effect.Capture, + returnValueKind: ValueKind.Mutable, + }), + ], + [ + 'has', + addFunction(BUILTIN_SHAPES, [], { + positionalParams: [Effect.Read], + restParam: null, + returnType: PRIMITIVE_TYPE, + calleeEffect: Effect.Read, + returnValueKind: ValueKind.Primitive, + }), + ], + [ + /** + * Params + * key: the key of the element to add to the Map object. The key may be + * any JavaScript type (any primitive value or any type of JavaScript + * object). + * value: the value of the element to add to the Map object. + * Returns the Map object. + */ + 'set', + addFunction(BUILTIN_SHAPES, [], { + positionalParams: [Effect.Capture, Effect.Capture], + restParam: null, + returnType: {kind: 'Object', shapeId: BuiltInMapId}, + calleeEffect: Effect.Store, + returnValueKind: ValueKind.Mutable, + }), + ], +]); + addObject(BUILTIN_SHAPES, BuiltInUseStateId, [ ['0', {kind: 'Poly'}], [ From 42c6348d1e6512a4b8a2bb5fc2022e0ae1458562 Mon Sep 17 00:00:00 2001 From: Joe Savona Date: Thu, 1 May 2025 17:46:52 +0900 Subject: [PATCH 2/3] Update on "[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-poisoned] From 6f45e9d27fa44e9758909627f099266e7e99a7a5 Mon Sep 17 00:00:00 2001 From: Joe Savona Date: Fri, 2 May 2025 13:54:19 +0900 Subject: [PATCH 3/3] Update on "[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-poisoned] --- .../src/HIR/ObjectShape.ts | 4 +- .../compiler/weakmap-constructor.expect.md | 176 ++++++++++++++++++ .../fixtures/compiler/weakmap-constructor.js | 35 ++++ .../compiler/weakset-constructor.expect.md | 176 ++++++++++++++++++ .../fixtures/compiler/weakset-constructor.js | 35 ++++ 5 files changed, 424 insertions(+), 2 deletions(-) create mode 100644 compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/weakmap-constructor.expect.md create mode 100644 compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/weakmap-constructor.js create mode 100644 compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/weakset-constructor.expect.md create mode 100644 compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/weakset-constructor.js diff --git a/compiler/packages/babel-plugin-react-compiler/src/HIR/ObjectShape.ts b/compiler/packages/babel-plugin-react-compiler/src/HIR/ObjectShape.ts index 4c137738665b6..03f4120149b0e 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/HIR/ObjectShape.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/HIR/ObjectShape.ts @@ -781,7 +781,7 @@ addObject(BUILTIN_SHAPES, BuiltInWeakSetId, [ addFunction(BUILTIN_SHAPES, [], { positionalParams: [Effect.Capture], restParam: null, - returnType: {kind: 'Object', shapeId: BuiltInSetId}, + returnType: {kind: 'Object', shapeId: BuiltInWeakSetId}, calleeEffect: Effect.Store, // returnValueKind is technically dependent on the ValueKind of the set itself returnValueKind: ValueKind.Mutable, @@ -857,7 +857,7 @@ addObject(BUILTIN_SHAPES, BuiltInWeakMapId, [ addFunction(BUILTIN_SHAPES, [], { positionalParams: [Effect.Capture, Effect.Capture], restParam: null, - returnType: {kind: 'Object', shapeId: BuiltInMapId}, + returnType: {kind: 'Object', shapeId: BuiltInWeakMapId}, calleeEffect: Effect.Store, returnValueKind: ValueKind.Mutable, }), diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/weakmap-constructor.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/weakmap-constructor.expect.md new file mode 100644 index 0000000000000..aebaedf6a8754 --- /dev/null +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/weakmap-constructor.expect.md @@ -0,0 +1,176 @@ + +## Input + +```javascript +import {ValidateMemoization} from 'shared-runtime'; + +function Component({a, b, c}) { + const map = new WeakMap(); + const mapAlias = map.set(a, 0); + mapAlias.set(c, 0); + + const hasB = map.has(b); + + return ( + <> + + + + + ); +} + +const v1 = {value: 1}; +const v2 = {value: 2}; +const v3 = {value: 3}; +export const FIXTURE_ENTRYPOINT = { + fn: Component, + params: [{a: v1, b: v1, c: v1}], + sequentialRenders: [ + {a: v1, b: v1, c: v1}, + {a: v2, b: v1, c: v1}, + {a: v1, b: v1, c: v1}, + {a: v1, b: v2, c: v1}, + {a: v1, b: v1, c: v1}, + {a: v3, b: v3, c: v1}, + {a: v3, b: v3, c: v1}, + {a: v1, b: v1, c: v1}, + ], +}; + +``` + +## Code + +```javascript +import { c as _c } from "react/compiler-runtime"; +import { ValidateMemoization } from "shared-runtime"; + +function Component(t0) { + const $ = _c(27); + const { a, b, c } = t0; + let map; + let mapAlias; + if ($[0] !== a || $[1] !== c) { + map = new WeakMap(); + mapAlias = map.set(a, 0); + mapAlias.set(c, 0); + $[0] = a; + $[1] = c; + $[2] = map; + $[3] = mapAlias; + } else { + map = $[2]; + mapAlias = $[3]; + } + + const hasB = map.has(b); + let t1; + if ($[4] !== a || $[5] !== c) { + t1 = [a, c]; + $[4] = a; + $[5] = c; + $[6] = t1; + } else { + t1 = $[6]; + } + let t2; + if ($[7] !== map || $[8] !== t1) { + t2 = ; + $[7] = map; + $[8] = t1; + $[9] = t2; + } else { + t2 = $[9]; + } + let t3; + if ($[10] !== a || $[11] !== c) { + t3 = [a, c]; + $[10] = a; + $[11] = c; + $[12] = t3; + } else { + t3 = $[12]; + } + let t4; + if ($[13] !== mapAlias || $[14] !== t3) { + t4 = ; + $[13] = mapAlias; + $[14] = t3; + $[15] = t4; + } else { + t4 = $[15]; + } + let t5; + if ($[16] !== b) { + t5 = [b]; + $[16] = b; + $[17] = t5; + } else { + t5 = $[17]; + } + let t6; + if ($[18] !== hasB) { + t6 = [hasB]; + $[18] = hasB; + $[19] = t6; + } else { + t6 = $[19]; + } + let t7; + if ($[20] !== t5 || $[21] !== t6) { + t7 = ; + $[20] = t5; + $[21] = t6; + $[22] = t7; + } else { + t7 = $[22]; + } + let t8; + if ($[23] !== t2 || $[24] !== t4 || $[25] !== t7) { + t8 = ( + <> + {t2} + {t4} + {t7} + + ); + $[23] = t2; + $[24] = t4; + $[25] = t7; + $[26] = t8; + } else { + t8 = $[26]; + } + return t8; +} + +const v1 = { value: 1 }; +const v2 = { value: 2 }; +const v3 = { value: 3 }; +export const FIXTURE_ENTRYPOINT = { + fn: Component, + params: [{ a: v1, b: v1, c: v1 }], + sequentialRenders: [ + { a: v1, b: v1, c: v1 }, + { a: v2, b: v1, c: v1 }, + { a: v1, b: v1, c: v1 }, + { a: v1, b: v2, c: v1 }, + { a: v1, b: v1, c: v1 }, + { a: v3, b: v3, c: v1 }, + { a: v3, b: v3, c: v1 }, + { a: v1, b: v1, c: v1 }, + ], +}; + +``` + +### Eval output +(kind: ok)
{"inputs":[{"value":1},"[[ cyclic ref *2 ]]"],"output":{}}
{"inputs":[{"value":1},"[[ cyclic ref *2 ]]"],"output":{}}
{"inputs":[{"value":1}],"output":[true]}
+
{"inputs":[{"value":2},{"value":1}],"output":{}}
{"inputs":[{"value":2},{"value":1}],"output":{}}
{"inputs":[{"value":1}],"output":[true]}
+
{"inputs":[{"value":1},"[[ cyclic ref *2 ]]"],"output":{}}
{"inputs":[{"value":1},"[[ cyclic ref *2 ]]"],"output":{}}
{"inputs":[{"value":1}],"output":[true]}
+
{"inputs":[{"value":1},"[[ cyclic ref *2 ]]"],"output":{}}
{"inputs":[{"value":1},"[[ cyclic ref *2 ]]"],"output":{}}
{"inputs":[{"value":2}],"output":[false]}
+
{"inputs":[{"value":1},"[[ cyclic ref *2 ]]"],"output":{}}
{"inputs":[{"value":1},"[[ cyclic ref *2 ]]"],"output":{}}
{"inputs":[{"value":1}],"output":[true]}
+
{"inputs":[{"value":3},{"value":1}],"output":{}}
{"inputs":[{"value":3},{"value":1}],"output":{}}
{"inputs":[{"value":3}],"output":[true]}
+
{"inputs":[{"value":3},{"value":1}],"output":{}}
{"inputs":[{"value":3},{"value":1}],"output":{}}
{"inputs":[{"value":3}],"output":[true]}
+
{"inputs":[{"value":1},"[[ cyclic ref *2 ]]"],"output":{}}
{"inputs":[{"value":1},"[[ cyclic ref *2 ]]"],"output":{}}
{"inputs":[{"value":1}],"output":[true]}
\ No newline at end of file diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/weakmap-constructor.js b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/weakmap-constructor.js new file mode 100644 index 0000000000000..ecdec6c9e9621 --- /dev/null +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/weakmap-constructor.js @@ -0,0 +1,35 @@ +import {ValidateMemoization} from 'shared-runtime'; + +function Component({a, b, c}) { + const map = new WeakMap(); + const mapAlias = map.set(a, 0); + mapAlias.set(c, 0); + + const hasB = map.has(b); + + return ( + <> + + + + + ); +} + +const v1 = {value: 1}; +const v2 = {value: 2}; +const v3 = {value: 3}; +export const FIXTURE_ENTRYPOINT = { + fn: Component, + params: [{a: v1, b: v1, c: v1}], + sequentialRenders: [ + {a: v1, b: v1, c: v1}, + {a: v2, b: v1, c: v1}, + {a: v1, b: v1, c: v1}, + {a: v1, b: v2, c: v1}, + {a: v1, b: v1, c: v1}, + {a: v3, b: v3, c: v1}, + {a: v3, b: v3, c: v1}, + {a: v1, b: v1, c: v1}, + ], +}; diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/weakset-constructor.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/weakset-constructor.expect.md new file mode 100644 index 0000000000000..5ebf32d533c91 --- /dev/null +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/weakset-constructor.expect.md @@ -0,0 +1,176 @@ + +## Input + +```javascript +import {ValidateMemoization} from 'shared-runtime'; + +function Component({a, b, c}) { + const set = new WeakSet(); + const setAlias = set.add(a); + setAlias.add(c); + + const hasB = set.has(b); + + return ( + <> + + + + + ); +} + +const v1 = {value: 1}; +const v2 = {value: 2}; +const v3 = {value: 3}; +export const FIXTURE_ENTRYPOINT = { + fn: Component, + params: [{a: v1, b: v1, c: v1}], + sequentialRenders: [ + {a: v1, b: v1, c: v1}, + {a: v2, b: v1, c: v1}, + {a: v1, b: v1, c: v1}, + {a: v1, b: v2, c: v1}, + {a: v1, b: v1, c: v1}, + {a: v3, b: v3, c: v1}, + {a: v3, b: v3, c: v1}, + {a: v1, b: v1, c: v1}, + ], +}; + +``` + +## Code + +```javascript +import { c as _c } from "react/compiler-runtime"; +import { ValidateMemoization } from "shared-runtime"; + +function Component(t0) { + const $ = _c(27); + const { a, b, c } = t0; + let set; + let setAlias; + if ($[0] !== a || $[1] !== c) { + set = new WeakSet(); + setAlias = set.add(a); + setAlias.add(c); + $[0] = a; + $[1] = c; + $[2] = set; + $[3] = setAlias; + } else { + set = $[2]; + setAlias = $[3]; + } + + const hasB = set.has(b); + let t1; + if ($[4] !== a || $[5] !== c) { + t1 = [a, c]; + $[4] = a; + $[5] = c; + $[6] = t1; + } else { + t1 = $[6]; + } + let t2; + if ($[7] !== set || $[8] !== t1) { + t2 = ; + $[7] = set; + $[8] = t1; + $[9] = t2; + } else { + t2 = $[9]; + } + let t3; + if ($[10] !== a || $[11] !== c) { + t3 = [a, c]; + $[10] = a; + $[11] = c; + $[12] = t3; + } else { + t3 = $[12]; + } + let t4; + if ($[13] !== setAlias || $[14] !== t3) { + t4 = ; + $[13] = setAlias; + $[14] = t3; + $[15] = t4; + } else { + t4 = $[15]; + } + let t5; + if ($[16] !== b) { + t5 = [b]; + $[16] = b; + $[17] = t5; + } else { + t5 = $[17]; + } + let t6; + if ($[18] !== hasB) { + t6 = [hasB]; + $[18] = hasB; + $[19] = t6; + } else { + t6 = $[19]; + } + let t7; + if ($[20] !== t5 || $[21] !== t6) { + t7 = ; + $[20] = t5; + $[21] = t6; + $[22] = t7; + } else { + t7 = $[22]; + } + let t8; + if ($[23] !== t2 || $[24] !== t4 || $[25] !== t7) { + t8 = ( + <> + {t2} + {t4} + {t7} + + ); + $[23] = t2; + $[24] = t4; + $[25] = t7; + $[26] = t8; + } else { + t8 = $[26]; + } + return t8; +} + +const v1 = { value: 1 }; +const v2 = { value: 2 }; +const v3 = { value: 3 }; +export const FIXTURE_ENTRYPOINT = { + fn: Component, + params: [{ a: v1, b: v1, c: v1 }], + sequentialRenders: [ + { a: v1, b: v1, c: v1 }, + { a: v2, b: v1, c: v1 }, + { a: v1, b: v1, c: v1 }, + { a: v1, b: v2, c: v1 }, + { a: v1, b: v1, c: v1 }, + { a: v3, b: v3, c: v1 }, + { a: v3, b: v3, c: v1 }, + { a: v1, b: v1, c: v1 }, + ], +}; + +``` + +### Eval output +(kind: ok)
{"inputs":[{"value":1},"[[ cyclic ref *2 ]]"],"output":{}}
{"inputs":[{"value":1},"[[ cyclic ref *2 ]]"],"output":{}}
{"inputs":[{"value":1}],"output":[true]}
+
{"inputs":[{"value":2},{"value":1}],"output":{}}
{"inputs":[{"value":2},{"value":1}],"output":{}}
{"inputs":[{"value":1}],"output":[true]}
+
{"inputs":[{"value":1},"[[ cyclic ref *2 ]]"],"output":{}}
{"inputs":[{"value":1},"[[ cyclic ref *2 ]]"],"output":{}}
{"inputs":[{"value":1}],"output":[true]}
+
{"inputs":[{"value":1},"[[ cyclic ref *2 ]]"],"output":{}}
{"inputs":[{"value":1},"[[ cyclic ref *2 ]]"],"output":{}}
{"inputs":[{"value":2}],"output":[false]}
+
{"inputs":[{"value":1},"[[ cyclic ref *2 ]]"],"output":{}}
{"inputs":[{"value":1},"[[ cyclic ref *2 ]]"],"output":{}}
{"inputs":[{"value":1}],"output":[true]}
+
{"inputs":[{"value":3},{"value":1}],"output":{}}
{"inputs":[{"value":3},{"value":1}],"output":{}}
{"inputs":[{"value":3}],"output":[true]}
+
{"inputs":[{"value":3},{"value":1}],"output":{}}
{"inputs":[{"value":3},{"value":1}],"output":{}}
{"inputs":[{"value":3}],"output":[true]}
+
{"inputs":[{"value":1},"[[ cyclic ref *2 ]]"],"output":{}}
{"inputs":[{"value":1},"[[ cyclic ref *2 ]]"],"output":{}}
{"inputs":[{"value":1}],"output":[true]}
\ No newline at end of file diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/weakset-constructor.js b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/weakset-constructor.js new file mode 100644 index 0000000000000..8c0a7deb186f6 --- /dev/null +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/weakset-constructor.js @@ -0,0 +1,35 @@ +import {ValidateMemoization} from 'shared-runtime'; + +function Component({a, b, c}) { + const set = new WeakSet(); + const setAlias = set.add(a); + setAlias.add(c); + + const hasB = set.has(b); + + return ( + <> + + + + + ); +} + +const v1 = {value: 1}; +const v2 = {value: 2}; +const v3 = {value: 3}; +export const FIXTURE_ENTRYPOINT = { + fn: Component, + params: [{a: v1, b: v1, c: v1}], + sequentialRenders: [ + {a: v1, b: v1, c: v1}, + {a: v2, b: v1, c: v1}, + {a: v1, b: v1, c: v1}, + {a: v1, b: v2, c: v1}, + {a: v1, b: v1, c: v1}, + {a: v3, b: v3, c: v1}, + {a: v3, b: v3, c: v1}, + {a: v1, b: v1, c: v1}, + ], +};