main
js 55 lines 2.2 KB
Raw
1 // @flow @enableTransitivelyFreezeFunctionExpressions:false @enableNewMutationAliasingModel
2 import {arrayPush, setPropertyByKey, Stringify} from 'shared-runtime';
3
4 /**
5 * Repro of a bug fixed in the new aliasing model.
6 *
7 * 1. `InferMutableRanges` derives the mutable range of identifiers and their
8 * aliases from `LoadLocal`, `PropertyLoad`, etc
9 * - After this pass, y's mutable range only extends to `arrayPush(x, y)`
10 * - We avoid assigning mutable ranges to loads after y's mutable range, as
11 * these are working with an immutable value. As a result, `LoadLocal y` and
12 * `PropertyLoad y` do not get mutable ranges
13 * 2. `InferReactiveScopeVariables` extends mutable ranges and creates scopes,
14 * as according to the 'co-mutation' of different values
15 * - Here, we infer that
16 * - `arrayPush(y, x)` might alias `x` and `y` to each other
17 * - `setPropertyKey(x, ...)` may mutate both `x` and `y`
18 * - This pass correctly extends the mutable range of `y`
19 * - Since we didn't run `InferMutableRange` logic again, the LoadLocal /
20 * PropertyLoads still don't have a mutable range
21 *
22 * Note that the this bug is an edge case. Compiler output is only invalid for:
23 * - function expressions with
24 * `enableTransitivelyFreezeFunctionExpressions:false`
25 * - functions that throw and get retried without clearing the memocache
26 *
27 * Found differences in evaluator results
28 * Non-forget (expected):
29 * (kind: ok)
30 * <div>{"cb":{"kind":"Function","result":10},"shouldInvokeFns":true}</div>
31 * <div>{"cb":{"kind":"Function","result":11},"shouldInvokeFns":true}</div>
32 * Forget:
33 * (kind: ok)
34 * <div>{"cb":{"kind":"Function","result":10},"shouldInvokeFns":true}</div>
35 * <div>{"cb":{"kind":"Function","result":10},"shouldInvokeFns":true}</div>
36 */
37 function useFoo({a, b}: {a: number, b: number}) {
38 const x = [];
39 const y = {value: a};
40
41 arrayPush(x, y); // x and y co-mutate
42 const y_alias = y;
43 const cb = () => y_alias.value;
44 setPropertyByKey(x[0], 'value', b); // might overwrite y.value
45 return <Stringify cb={cb} shouldInvokeFns={true} />;
46 }
47
48 export const FIXTURE_ENTRYPOINT = {
49 fn: useFoo,
50 params: [{a: 2, b: 10}],
51 sequentialRenders: [
52 {a: 2, b: 10},
53 {a: 2, b: 11},
54 ],
55 };