Skip to content

Commit 9b9537e

Browse files
committed
Update on "[compiler] Validate against locals being reassigned after render"
Adds a pass which validates that local variables are not reassigned by functions which may be called after render. This is a straightforward forward data-flow analysis, where we: 1. Build up a mapping of context variables in the outer component/hook 2. Find ObjectMethod/FunctionExpressions which may reassign those context variables 3. Propagate aliases of those functions via StoreLocal/LoadLocal 4. Disallow passing those functions with a Freeze effect. This includes JSX arguments, hook arguments, hook return types, etc. Conceptually, a function that reassigns a local is inherently mutable. Frozen functions must be side-effect free, so these two categories are incompatible and we can use the freeze effect to find all instances of where such functions are disallowed rather than special-casing eg hook calls and JSX. [ghstack-poisoned]
2 parents 9a5525f + a8fb0d1 commit 9b9537e

File tree

1 file changed

+9
-13
lines changed

1 file changed

+9
-13
lines changed

compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateLocalsNotReassignedAfterRender.ts

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,12 @@
55
* LICENSE file in the root directory of this source tree.
66
*/
77

8-
import prettyFormat from "pretty-format";
98
import { CompilerError, Effect } from "..";
10-
import {
11-
HIRFunction,
12-
IdentifierId,
13-
Place,
14-
getHookKind,
15-
isUseOperator,
16-
} from "../HIR";
9+
import { HIRFunction, IdentifierId, Place } from "../HIR";
1710
import {
1811
eachInstructionValueOperand,
1912
eachTerminalOperand,
2013
} from "../HIR/visitors";
21-
import { isEffectHook } from "./ValidateMemoizedEffectDependencies";
2214

2315
/**
2416
* Validates that local variables cannot be reassigned after render.
@@ -111,8 +103,10 @@ function getContextReassignment(
111103
return value.lvalue.place;
112104
}
113105
} else {
114-
// We only track reassignments of variables defined in the outer
115-
// component or hook.
106+
/*
107+
* We only track reassignments of variables defined in the outer
108+
* component or hook.
109+
*/
116110
contextVariables.add(value.lvalue.place.identifier.id);
117111
}
118112
break;
@@ -130,8 +124,10 @@ function getContextReassignment(
130124
reassignment !== undefined &&
131125
operand.effect === Effect.Freeze
132126
) {
133-
// Functions that reassign local variables are inherently mutable and are unsafe to pass
134-
// to a place that expects a frozen value. Propagate the reassignment upward.
127+
/*
128+
* Functions that reassign local variables are inherently mutable and are unsafe to pass
129+
* to a place that expects a frozen value. Propagate the reassignment upward.
130+
*/
135131
return reassignment;
136132
}
137133
}

0 commit comments

Comments
 (0)