@samitouri / QOS-React / commits / dd8e0ba857

[compiler] Support for useTransition

Summary: UseTransition is a builtin hook that returns a stable value, like useState. This PR represents that in Forget, and marks the startTransition function as stable. ghstack-source-id: 0e76a64f2d0c86a4eb55c620922b4698250bb5c3 Pull Request resolved: https://github.com/facebook/react/pull/30681

Mike Vitousek committed Aug 14, 2024 at 13:54 UTC dd8e0ba857fcd546d677c7283d5f35a663bc8d02
5 files changed +109 -1
compiler/packages/babel-plugin-react-compiler/src/HIR/Globals.ts
+12
@@ -18,6 +18,7 @@ import {
18 BuiltInUseReducerId,
19 BuiltInUseRefId,
20 BuiltInUseStateId,
21 + BuiltInUseTransitionId,
22 ShapeRegistry,
23 addFunction,
24 addHook,
@@ -425,6 +426,17 @@ const REACT_APIS: Array<[string, BuiltInType]> = [
426 BuiltInUseInsertionEffectHookId,
427 ),
428 ],
429 + [
430 + 'useTransition',
431 + addHook(DEFAULT_SHAPES, {
432 + positionalParams: [],
433 + restParam: null,
434 + returnType: {kind: 'Object', shapeId: BuiltInUseTransitionId},
435 + calleeEffect: Effect.Read,
436 + hookKind: 'useTransition',
437 + returnValueKind: ValueKind.Frozen,
438 + }),
439 + ],
440 [
441 'use',
442 addFunction(
compiler/packages/babel-plugin-react-compiler/src/HIR/HIR.ts
+8 -1
@@ -1601,6 +1601,12 @@ export function isUseActionStateType(id: Identifier): boolean {
1601 );
1602 }
1603
1604 +export function isStartTransitionType(id: Identifier): boolean {
1605 + return (
1606 + id.type.kind === 'Function' && id.type.shapeId === 'BuiltInStartTransition'
1607 + );
1608 +}
1609 +
1610 export function isSetActionStateType(id: Identifier): boolean {
1611 return (
1612 id.type.kind === 'Function' && id.type.shapeId === 'BuiltInSetActionState'
@@ -1620,7 +1626,8 @@ export function isStableType(id: Identifier): boolean {
1626 isSetStateType(id) ||
1627 isSetActionStateType(id) ||
1628 isDispatcherType(id) ||
1623 - isUseRefType(id)
1629 + isUseRefType(id) ||
1630 + isStartTransitionType(id)
1631 );
1632 }
1633
compiler/packages/babel-plugin-react-compiler/src/HIR/ObjectShape.ts
+22
@@ -126,6 +126,7 @@ export type HookKind =
126 | 'useInsertionEffect'
127 | 'useMemo'
128 | 'useCallback'
129 + | 'useTransition'
130 | 'Custom';
131
132 /*
@@ -209,6 +210,8 @@ export const BuiltInUseOperatorId = 'BuiltInUseOperator';
210 export const BuiltInUseReducerId = 'BuiltInUseReducer';
211 export const BuiltInDispatchId = 'BuiltInDispatch';
212 export const BuiltInUseContextHookId = 'BuiltInUseContextHook';
213 +export const BuiltInUseTransitionId = 'BuiltInUseTransition';
214 +export const BuiltInStartTransitionId = 'BuiltInStartTransition';
215
216 // ShapeRegistry with default definitions for built-ins.
217 export const BUILTIN_SHAPES: ShapeRegistry = new Map();
@@ -444,6 +447,25 @@ addObject(BUILTIN_SHAPES, BuiltInUseStateId, [
447 ],
448 ]);
449
450 +addObject(BUILTIN_SHAPES, BuiltInUseTransitionId, [
451 + ['0', {kind: 'Primitive'}],
452 + [
453 + '1',
454 + addFunction(
455 + BUILTIN_SHAPES,
456 + [],
457 + {
458 + positionalParams: [],
459 + restParam: null,
460 + returnType: PRIMITIVE_TYPE,
461 + calleeEffect: Effect.Read,
462 + returnValueKind: ValueKind.Primitive,
463 + },
464 + BuiltInStartTransitionId,
465 + ),
466 + ],
467 +]);
468 +
469 addObject(BUILTIN_SHAPES, BuiltInUseActionStateId, [
470 ['0', {kind: 'Poly'}],
471 [
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/preserve-use-memo-transition.expect.md new
+52
@@ -0,0 +1,52 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +// @validatePreserveExistingMemoizationGuarantees
6 +import {useCallback, useTransition} from 'react';
7 +
8 +function useFoo() {
9 + const [t, start] = useTransition();
10 +
11 + return useCallback(() => {
12 + start();
13 + }, []);
14 +}
15 +
16 +export const FIXTURE_ENTRYPOINT = {
17 + fn: useFoo,
18 + params: [],
19 +};
20 +
21 +```
22 +
23 +## Code
24 +
25 +```javascript
26 +import { c as _c } from "react/compiler-runtime"; // @validatePreserveExistingMemoizationGuarantees
27 +import { useCallback, useTransition } from "react";
28 +
29 +function useFoo() {
30 + const $ = _c(1);
31 + const [t, start] = useTransition();
32 + let t0;
33 + if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
34 + t0 = () => {
35 + start();
36 + };
37 + $[0] = t0;
38 + } else {
39 + t0 = $[0];
40 + }
41 + return t0;
42 +}
43 +
44 +export const FIXTURE_ENTRYPOINT = {
45 + fn: useFoo,
46 + params: [],
47 +};
48 +
49 +```
50 +
51 +### Eval output
52 +(kind: ok) "[[ function params=0 ]]"
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/preserve-use-memo-transition.ts new
+15
@@ -0,0 +1,15 @@
1 +// @validatePreserveExistingMemoizationGuarantees
2 +import {useCallback, useTransition} from 'react';
3 +
4 +function useFoo() {
5 + const [t, start] = useTransition();
6 +
7 + return useCallback(() => {
8 + start();
9 + }, []);
10 +}
11 +
12 +export const FIXTURE_ENTRYPOINT = {
13 + fn: useFoo,
14 + params: [],
15 +};