mirror of
https://github.com/facebook/react.git
synced 2026-02-23 20:23:02 +00:00
```js
function Component() {
useEffect(() => {
let hasCleanedUp = false;
document.addEventListener(..., () => hasCleanedUp ? foo() : bar());
// effect return values shouldn't be typed as frozen
return () => {
hasCleanedUp = true;
}
};
}
```
### Problem
`PruneHoistedContexts` currently strips hoisted declarations and
rewrites the first `StoreContext` reassignment to a declaration. For
example, in the following example, instruction 0 is removed while a
synthetic `DeclareContext let` is inserted before instruction 1.
```js
// source
const cb = () => x; // reference that causes x to be hoisted
let x = 4;
x = 5;
// React Compiler IR
[0] DeclareContext HoistedLet 'x'
...
[1] StoreContext reassign 'x' = 4
[2] StoreContext reassign 'x' = 5
```
Currently, we don't account for `DeclareContext let`. As a result, we're
rewriting to insert duplicate declarations.
```js
// source
const cb = () => x; // reference that causes x to be hoisted
let x;
x = 5;
// React Compiler IR
[0] DeclareContext HoistedLet 'x'
...
[1] DeclareContext Let 'x'
[2] StoreContext reassign 'x' = 5
```
### Solution
Instead of always lowering context variables to a DeclareContext
followed by a StoreContext reassign, we can keep `kind: 'Const' | 'Let'
| 'Reassign' | etc` on StoreContext.
Pros:
- retain more information in HIR, so we can codegen easily `const` and
`let` context variable declarations back
- pruning hoisted `DeclareContext` instructions is simple.
Cons:
- passes are more verbose as we need to check for both `DeclareContext`
and `StoreContext` declarations
~(note: also see alternative implementation in
https://github.com/facebook/react/pull/32745)~
### Testing
Context variables are tricky. I synced and diffed changes in a large
meta codebase and feel pretty confident about landing this. About 0.01%
of compiled files changed. Among these changes, ~25% were [direct
bugfixes](https://www.internalfb.com/phabricator/paste/view/P1800029094).
The [other
changes](https://www.internalfb.com/phabricator/paste/view/P1800028575)
were primarily due to changed (corrected) mutable ranges from
https://github.com/facebook/react/pull/33047. I tried to represent most
interesting changes in new test fixtures
`