[compiler] Don't include useEffectEvent values in autodeps (#33450)

Summary: useEffectEvent values are not meant to be added to the dep
array
This commit is contained in:
Jordan Brown
2025-06-09 09:26:45 -04:00
committed by GitHub
parent 95bcf87e6b
commit 4df098c4c2
6 changed files with 109 additions and 1 deletions

View File

@@ -17,6 +17,7 @@ import {
BuiltInSetId,
BuiltInUseActionStateId,
BuiltInUseContextHookId,
BuiltInUseEffectEventId,
BuiltInUseEffectHookId,
BuiltInUseInsertionEffectHookId,
BuiltInUseLayoutEffectHookId,
@@ -27,6 +28,7 @@ import {
BuiltInUseTransitionId,
BuiltInWeakMapId,
BuiltInWeakSetId,
BuiltinEffectEventId,
ReanimatedSharedValueId,
ShapeRegistry,
addFunction,
@@ -722,6 +724,27 @@ const REACT_APIS: Array<[string, BuiltInType]> = [
BuiltInFireId,
),
],
[
'useEffectEvent',
addHook(
DEFAULT_SHAPES,
{
positionalParams: [],
restParam: Effect.Freeze,
returnType: {
kind: 'Function',
return: {kind: 'Poly'},
shapeId: BuiltinEffectEventId,
isConstructor: false,
},
calleeEffect: Effect.Read,
hookKind: 'useEffectEvent',
// Frozen because it should not mutate any locally-bound values
returnValueKind: ValueKind.Frozen,
},
BuiltInUseEffectEventId,
),
],
];
TYPED_GLOBALS.push(

View File

@@ -1785,6 +1785,13 @@ export function isFireFunctionType(id: Identifier): boolean {
);
}
export function isEffectEventFunctionType(id: Identifier): boolean {
return (
id.type.kind === 'Function' &&
id.type.shapeId === 'BuiltInEffectEventFunction'
);
}
export function isStableType(id: Identifier): boolean {
return (
isSetStateType(id) ||

View File

@@ -131,6 +131,7 @@ export type HookKind =
| 'useCallback'
| 'useTransition'
| 'useImperativeHandle'
| 'useEffectEvent'
| 'Custom';
/*
@@ -226,6 +227,8 @@ export const BuiltInUseTransitionId = 'BuiltInUseTransition';
export const BuiltInStartTransitionId = 'BuiltInStartTransition';
export const BuiltInFireId = 'BuiltInFire';
export const BuiltInFireFunctionId = 'BuiltInFireFunction';
export const BuiltInUseEffectEventId = 'BuiltInUseEffectEvent';
export const BuiltinEffectEventId = 'BuiltInEffectEventFunction';
// See getReanimatedModuleType() in Globals.ts — this is part of supporting Reanimated's ref-like types
export const ReanimatedSharedValueId = 'ReanimatedSharedValueId';
@@ -948,6 +951,19 @@ addObject(BUILTIN_SHAPES, BuiltInRefValueId, [
['*', {kind: 'Object', shapeId: BuiltInRefValueId}],
]);
addFunction(
BUILTIN_SHAPES,
[],
{
positionalParams: [],
restParam: Effect.ConditionallyMutate,
returnType: {kind: 'Poly'},
calleeEffect: Effect.ConditionallyMutate,
returnValueKind: ValueKind.Mutable,
},
BuiltinEffectEventId,
);
/**
* MixedReadOnly =
* | primitive

View File

@@ -31,6 +31,7 @@ import {
HIR,
BasicBlock,
BlockId,
isEffectEventFunctionType,
} from '../HIR';
import {collectHoistablePropertyLoadsInInnerFn} from '../HIR/CollectHoistablePropertyLoads';
import {collectOptionalChainSidemap} from '../HIR/CollectOptionalChainDependencies';
@@ -209,7 +210,8 @@ export function inferEffectDependencies(fn: HIRFunction): void {
((isUseRefType(maybeDep.identifier) ||
isSetStateType(maybeDep.identifier)) &&
!reactiveIds.has(maybeDep.identifier.id)) ||
isFireFunctionType(maybeDep.identifier)
isFireFunctionType(maybeDep.identifier) ||
isEffectEventFunctionType(maybeDep.identifier)
) {
// exclude non-reactive hook results, which will never be in a memo block
continue;

View File

@@ -0,0 +1,49 @@
## Input
```javascript
// @inferEffectDependencies
import {useEffect, useEffectEvent} from 'react';
import {print} from 'shared-runtime';
/**
* We do not include effect events in dep arrays.
*/
function NonReactiveEffectEvent() {
const fn = useEffectEvent(() => print('hello world'));
useEffect(() => fn());
}
```
## Code
```javascript
import { c as _c } from "react/compiler-runtime"; // @inferEffectDependencies
import { useEffect, useEffectEvent } from "react";
import { print } from "shared-runtime";
/**
* We do not include effect events in dep arrays.
*/
function NonReactiveEffectEvent() {
const $ = _c(2);
const fn = useEffectEvent(_temp);
let t0;
if ($[0] !== fn) {
t0 = () => fn();
$[0] = fn;
$[1] = t0;
} else {
t0 = $[1];
}
useEffect(t0, []);
}
function _temp() {
return print("hello world");
}
```
### Eval output
(kind: exception) Fixture not implemented

View File

@@ -0,0 +1,11 @@
// @inferEffectDependencies
import {useEffect, useEffectEvent} from 'react';
import {print} from 'shared-runtime';
/**
* We do not include effect events in dep arrays.
*/
function NonReactiveEffectEvent() {
const fn = useEffectEvent(() => print('hello world'));
useEffect(() => fn());
}