File tree Expand file tree Collapse file tree 4 files changed +44
-3
lines changed
compiler/packages/babel-plugin-react-compiler/src Expand file tree Collapse file tree 4 files changed +44
-3
lines changed Original file line number Diff line number Diff line change @@ -650,6 +650,14 @@ export const EnvironmentConfigSchema = z.object({
650
650
* useMemo(() => { ... }, [...]);
651
651
*/
652
652
validateNoVoidUseMemo : z . boolean ( ) . default ( false ) ,
653
+
654
+ /**
655
+ * A list of function identifier names that should never be skipped by
656
+ * memoization/flattening optimizations. Calls to any identifier with a name
657
+ * in this list behave like the `use` operator in terms of never being
658
+ * skipped, and may be called conditionally.
659
+ */
660
+ neverSkipFunctionName : z . array ( z . string ( ) ) . default ( [ ] ) ,
653
661
} ) ;
654
662
655
663
export type EnvironmentConfig = z . infer < typeof EnvironmentConfigSchema > ;
Original file line number Diff line number Diff line change @@ -1915,6 +1915,34 @@ export function isUseOperator(id: Identifier): boolean {
1915
1915
) ;
1916
1916
}
1917
1917
1918
+ /**
1919
+ * Treat any call with a neverSkip identifier name similar to the `use` operator:
1920
+ * - It may be called conditionally.
1921
+ * - It should never be skipped by memoization/flattening logic.
1922
+ */
1923
+ export function isNeverSkipIdentifier (
1924
+ env : Environment ,
1925
+ id : Identifier ,
1926
+ ) : boolean {
1927
+ const list = env . config . neverSkipFunctionName ;
1928
+ if ( list == null || list . length === 0 ) {
1929
+ return false ;
1930
+ }
1931
+ if ( id . name != null && list . includes ( id . name . value ) ) {
1932
+ return true ;
1933
+ }
1934
+ const loc = id . loc as any ;
1935
+ if (
1936
+ loc &&
1937
+ typeof loc !== 'symbol' &&
1938
+ typeof loc . identifierName === 'string' &&
1939
+ list . includes ( loc . identifierName )
1940
+ ) {
1941
+ return true ;
1942
+ }
1943
+ return false ;
1944
+ }
1945
+
1918
1946
export function getHookKindForType (
1919
1947
env : Environment ,
1920
1948
type : Type ,
Original file line number Diff line number Diff line change @@ -21,6 +21,7 @@ import {
21
21
isStableType ,
22
22
isStableTypeContainer ,
23
23
isUseOperator ,
24
+ isNeverSkipIdentifier ,
24
25
} from '../HIR' ;
25
26
import { PostDominator } from '../HIR/Dominator' ;
26
27
import {
@@ -302,13 +303,15 @@ export function inferReactivePlaces(fn: HIRFunction): void {
302
303
if (
303
304
value . kind === 'CallExpression' &&
304
305
( getHookKind ( fn . env , value . callee . identifier ) != null ||
305
- isUseOperator ( value . callee . identifier ) )
306
+ isUseOperator ( value . callee . identifier ) ||
307
+ isNeverSkipIdentifier ( fn . env , value . callee . identifier ) )
306
308
) {
307
309
hasReactiveInput = true ;
308
310
} else if (
309
311
value . kind === 'MethodCall' &&
310
312
( getHookKind ( fn . env , value . property . identifier ) != null ||
311
- isUseOperator ( value . property . identifier ) )
313
+ isUseOperator ( value . property . identifier ) ||
314
+ isNeverSkipIdentifier ( fn . env , value . property . identifier ) )
312
315
) {
313
316
hasReactiveInput = true ;
314
317
}
Original file line number Diff line number Diff line change @@ -13,6 +13,7 @@ import {
13
13
PrunedScopeTerminal ,
14
14
getHookKind ,
15
15
isUseOperator ,
16
+ isNeverSkipIdentifier ,
16
17
} from '../HIR' ;
17
18
import { retainWhere } from '../Utils/utils' ;
18
19
@@ -53,7 +54,8 @@ export function flattenScopesWithHooksOrUseHIR(fn: HIRFunction): void {
53
54
value . kind === 'MethodCall' ? value . property : value . callee ;
54
55
if (
55
56
getHookKind ( fn . env , callee . identifier ) != null ||
56
- isUseOperator ( callee . identifier )
57
+ isUseOperator ( callee . identifier ) ||
58
+ isNeverSkipIdentifier ( fn . env , callee . identifier )
57
59
) {
58
60
prune . push ( ...activeScopes . map ( entry => entry . block ) ) ;
59
61
activeScopes . length = 0 ;
You can’t perform that action at this time.
0 commit comments