mirror of
https://github.com/facebook/react.git
synced 2026-02-22 11:51:55 +00:00
[compiler] Differentiate between inferred setStates and factual setStates
Summary: Rough proposal on how we can differentiate between the a real setState we can track and one we infer. Particularly useful when setting `enableTreatSetIdentifiersAsStateSetters=true` This is mainly so ValidateNoDerivedComputationsInEffects_exp doesn't introduce false positives since we rely on setState type tracking Test Plan: Tests
This commit is contained in:
@@ -1875,6 +1875,14 @@ export function isSetStateType(id: Identifier): boolean {
|
||||
return id.type.kind === 'Function' && id.type.shapeId === 'BuiltInSetState';
|
||||
}
|
||||
|
||||
export function isAnySetStateType(id: Identifier): boolean {
|
||||
return (
|
||||
id.type.kind === 'Function' &&
|
||||
(id.type.shapeId === 'InferredSetState' ||
|
||||
id.type.shapeId === 'BuiltInSetState')
|
||||
);
|
||||
}
|
||||
|
||||
export function isUseActionStateType(id: Identifier): boolean {
|
||||
return (
|
||||
id.type.kind === 'Object' && id.type.shapeId === 'BuiltInUseActionState'
|
||||
|
||||
@@ -386,6 +386,7 @@ export const BuiltInJsxId = 'BuiltInJsx';
|
||||
export const BuiltInObjectId = 'BuiltInObject';
|
||||
export const BuiltInUseStateId = 'BuiltInUseState';
|
||||
export const BuiltInSetStateId = 'BuiltInSetState';
|
||||
export const InferredSetState = 'InferredSetState';
|
||||
export const BuiltInUseActionStateId = 'BuiltInUseActionState';
|
||||
export const BuiltInSetActionStateId = 'BuiltInSetActionState';
|
||||
export const BuiltInUseRefId = 'BuiltInUseRefId';
|
||||
|
||||
@@ -25,7 +25,7 @@ import {
|
||||
ReactiveScopeDependencies,
|
||||
Terminal,
|
||||
isUseRefType,
|
||||
isSetStateType,
|
||||
isAnySetStateType,
|
||||
isFireFunctionType,
|
||||
makeScopeId,
|
||||
HIR,
|
||||
@@ -223,7 +223,7 @@ export function inferEffectDependencies(fn: HIRFunction): void {
|
||||
for (const maybeDep of minimalDeps) {
|
||||
if (
|
||||
((isUseRefType(maybeDep.identifier) ||
|
||||
isSetStateType(maybeDep.identifier)) &&
|
||||
isAnySetStateType(maybeDep.identifier)) &&
|
||||
!reactiveIds.has(maybeDep.identifier.id)) ||
|
||||
isFireFunctionType(maybeDep.identifier) ||
|
||||
isEffectEventFunctionType(maybeDep.identifier)
|
||||
|
||||
@@ -31,8 +31,8 @@ import {
|
||||
BuiltInObjectId,
|
||||
BuiltInPropsId,
|
||||
BuiltInRefValueId,
|
||||
BuiltInSetStateId,
|
||||
BuiltInUseRefId,
|
||||
InferredSetState,
|
||||
} from '../HIR/ObjectShape';
|
||||
import {eachInstructionLValue, eachInstructionOperand} from '../HIR/visitors';
|
||||
import {assertExhaustive} from '../Utils/utils';
|
||||
@@ -281,7 +281,7 @@ function* generateInstructionTypes(
|
||||
if (env.config.enableTreatSetIdentifiersAsStateSetters) {
|
||||
const name = getName(names, value.callee.identifier.id);
|
||||
if (name.startsWith('set')) {
|
||||
shapeId = BuiltInSetStateId;
|
||||
shapeId = InferredSetState;
|
||||
}
|
||||
}
|
||||
yield equation(value.callee.identifier.type, {
|
||||
|
||||
@@ -5,12 +5,13 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import {Environment} from '../HIR/Environment';
|
||||
import {
|
||||
CompilerDiagnostic,
|
||||
CompilerError,
|
||||
ErrorCategory,
|
||||
} from '../CompilerError';
|
||||
import {HIRFunction, IdentifierId, isSetStateType} from '../HIR';
|
||||
import {HIRFunction, IdentifierId, isAnySetStateType} from '../HIR';
|
||||
import {computeUnconditionalBlocks} from '../HIR/ComputeUnconditionalBlocks';
|
||||
import {eachInstructionValueOperand} from '../HIR/visitors';
|
||||
import {Result} from '../Utils/Result';
|
||||
@@ -85,7 +86,7 @@ function validateNoSetStateInRenderImpl(
|
||||
// faster-path to check if the function expression references a setState
|
||||
[...eachInstructionValueOperand(instr.value)].some(
|
||||
operand =>
|
||||
isSetStateType(operand.identifier) ||
|
||||
isAnySetStateType(operand.identifier) ||
|
||||
unconditionalSetStateFunctions.has(operand.identifier.id),
|
||||
) &&
|
||||
// if yes, does it unconditonally call it?
|
||||
@@ -136,7 +137,7 @@ function validateNoSetStateInRenderImpl(
|
||||
case 'CallExpression': {
|
||||
const callee = instr.value.callee;
|
||||
if (
|
||||
isSetStateType(callee.identifier) ||
|
||||
isAnySetStateType(callee.identifier) ||
|
||||
unconditionalSetStateFunctions.has(callee.identifier.id)
|
||||
) {
|
||||
if (activeManualMemoId !== null) {
|
||||
|
||||
Reference in New Issue
Block a user