dillon1000/react

Commit

Feature flag for transitively freezing values

This PR adds a feature flag to model a potential new-in-practice rule in React: 
that freezing a function expression also freezes its closed-over values, 
transitively. For example, in the following code `data` is frozen when the 
lambda that captures it is is passed to useEffect: 

```javascript 

const data = []; 

// useEffect freezes its argument (the function expr), which transitively 
freezes its captured value data 

useEffect(() => { 

foo(data); 

}, [data]); 

data.push(true); // ERROR: mutating a frozen value 

mutate(data); // we conservatively assume this doesn't mutate but could be wrong 

``` 

Note that this rule has never been written down or enforced. It is theoretically 
equivalent to the rule (already implemented in Forget) that values captured by 
JSX are frozen: 

```javascript 

const style = {...}; 

<div style={style}>...</div> 

style.width = 10; // ERROR: mutating a frozen value 

mutate(style); // we conservatively assume this doesn't mutate but could be 
wrong 

``` 

However, JSX is typically constructed toward the very end of a render function. 
Thus in practice there isn't much subsequent code that could even modify such a 
captured value. But for the useEffect case (and other hooks that take closures 
as arguments), they tend to occur much earlier in a render function. There's 
more code that can run later and still modify the captured values, without 
causing issues in practice. The _practical_ rule today is that you can't modify 
values captured by frozen lambdas _after the component returns_: it's fine in 
practice to modify captured values between calling eg useEffect and returning 
from render. 

Thus this feature flag is fairly likely to break some percent of real product 
code. I'm adding this so that we can experiment and see how unsafe it actually 
is.
Browse files
Changed paths8 files
First-parent comparison
M compiler/packages/babel-plugin-react-forget/src/HIR/Environment.ts ModifiedM compiler/packages/babel-plugin-react-forget/src/Inference/InferReferenceEffects.ts ModifiedM compiler/packages/babel-plugin-react-forget/src/ReactiveScopes/AssertScopeInstructionsWithinScope.ts ModifiedA compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/transitive-freeze-array.expect.md AddedA compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/transitive-freeze-array.js AddedA compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/transitive-freeze-function-expressions.expect.md AddedA compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/transitive-freeze-function-expressions.js AddedM compiler/packages/sprout/src/SproutTodoFilter.ts Modified
Patch

Files changed

Rendering syntax-highlighted changes…