@samitouri / QOS-React / commits / d87ba1b9df

[be] Stabilize block ids

ghstack-source-id: 83aedf9f086ccb4819655eab803f25f944b75c7b Pull Request resolved: https://github.com/facebook/react-forget/pull/2851

Mofei Zhang committed Apr 23, 2024 at 10:18 UTC d87ba1b9df3eb1a079fea57f76147441c35274b2
61 files changed +352 -137
compiler/packages/babel-plugin-react-forget/src/Entrypoint/Pipeline.ts
+8
@@ -66,6 +66,7 @@ import {
66 import { alignMethodCallScopes } from "../ReactiveScopes/AlignMethodCallScopes";
67 import { alignReactiveScopesToBlockScopesHIR } from "../ReactiveScopes/AlignReactiveScopesToBlockScopesHIR";
68 import { pruneAlwaysInvalidatingScopes } from "../ReactiveScopes/PruneAlwaysInvalidatingScopes";
69 +import { stabilizeBlockIds } from "../ReactiveScopes/StabilizeBlockIds";
70 import { eliminateRedundantPhi, enterSSA, leaveSSA } from "../SSA";
71 import { inferTypes } from "../TypeInference";
72 import {
@@ -366,6 +367,13 @@ function* runWithEnvironment(
367 value: reactiveFunction,
368 });
369
370 + stabilizeBlockIds(reactiveFunction);
371 + yield log({
372 + kind: "reactive",
373 + name: "StabilizeBlockIds",
374 + value: reactiveFunction,
375 + });
376 +
377 const uniqueIdentifiers = renameVariables(reactiveFunction);
378 yield log({
379 kind: "reactive",
compiler/packages/babel-plugin-react-forget/src/ReactiveScopes/StabilizeBlockIds.ts new
+80
@@ -0,0 +1,80 @@
1 +import {
2 + BlockId,
3 + ReactiveFunction,
4 + ReactiveScopeBlock,
5 + ReactiveTerminalStatement,
6 + makeBlockId,
7 +} from "../HIR";
8 +import { getOrInsertDefault } from "../Utils/utils";
9 +import { ReactiveFunctionVisitor, visitReactiveFunction } from "./visitors";
10 +
11 +export function stabilizeBlockIds(fn: ReactiveFunction): void {
12 + const referenced: Set<BlockId> = new Set();
13 + visitReactiveFunction(fn, new CollectReferencedLabels(), referenced);
14 +
15 + const mappings = new Map<BlockId, BlockId>();
16 + for (const blockId of referenced) {
17 + mappings.set(blockId, makeBlockId(mappings.size));
18 + }
19 +
20 + visitReactiveFunction(fn, new RewriteBlockIds(), mappings);
21 +}
22 +
23 +class CollectReferencedLabels extends ReactiveFunctionVisitor<Set<BlockId>> {
24 + override visitScope(scope: ReactiveScopeBlock, state: Set<BlockId>): void {
25 + const { earlyReturnValue } = scope.scope;
26 + if (earlyReturnValue != null) {
27 + state.add(earlyReturnValue.label);
28 + }
29 + this.traverseScope(scope, state);
30 + }
31 + override visitTerminal(
32 + stmt: ReactiveTerminalStatement,
33 + state: Set<BlockId>
34 + ): void {
35 + if (stmt.label != null) {
36 + if (!stmt.label.implicit) {
37 + state.add(stmt.label.id);
38 + }
39 + }
40 + this.traverseTerminal(stmt, state);
41 + }
42 +}
43 +
44 +class RewriteBlockIds extends ReactiveFunctionVisitor<Map<BlockId, BlockId>> {
45 + override visitScope(
46 + scope: ReactiveScopeBlock,
47 + state: Map<BlockId, BlockId>
48 + ): void {
49 + const { earlyReturnValue } = scope.scope;
50 + if (earlyReturnValue != null) {
51 + const rewrittenId = getOrInsertDefault(
52 + state,
53 + earlyReturnValue.label,
54 + state.size
55 + );
56 + earlyReturnValue.label = makeBlockId(rewrittenId);
57 + }
58 + this.traverseScope(scope, state);
59 + }
60 + override visitTerminal(
61 + stmt: ReactiveTerminalStatement,
62 + state: Map<BlockId, BlockId>
63 + ): void {
64 + if (stmt.label != null) {
65 + const rewrittenId = getOrInsertDefault(state, stmt.label.id, state.size);
66 + stmt.label.id = makeBlockId(rewrittenId);
67 + }
68 +
69 + const terminal = stmt.terminal;
70 + if (terminal.kind === "break" || terminal.kind === "continue") {
71 + const rewrittenId = getOrInsertDefault(
72 + state,
73 + terminal.target,
74 + state.size
75 + );
76 + terminal.target = makeBlockId(rewrittenId);
77 + }
78 + this.traverseTerminal(stmt, state);
79 + }
80 +}
compiler/packages/babel-plugin-react-forget/src/ReactiveScopes/index.ts
+1
@@ -33,6 +33,7 @@ export { pruneTemporaryLValues as pruneUnusedLValues } from "./PruneTemporaryLVa
33 export { pruneUnusedLabels } from "./PruneUnusedLabels";
34 export { pruneUnusedScopes } from "./PruneUnusedScopes";
35 export { renameVariables } from "./RenameVariables";
36 +export { stabilizeBlockIds } from "./StabilizeBlockIds";
37 export {
38 ReactiveFunctionTransform,
39 eachReactiveValueOperand,
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/block-scoping-switch-dead-code.expect.md
+2 -2
@@ -28,14 +28,14 @@ export const FIXTURE_ENTRYPOINT = {
28
29 ```javascript
30 function useHook(a, b) {
31 - bb1: switch (a) {
31 + bb0: switch (a) {
32 case 1: {
33 if (b == null) {
34 return;
35 }
36
37 console.log(b);
38 - break bb1;
38 + break bb0;
39 }
40 case 2: {
41 return;
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/block-scoping-switch-variable-scoping.expect.md
+2 -2
@@ -44,10 +44,10 @@ function Component(props) {
44 t1 = $[1];
45 }
46 const handlers = t1;
47 - bb2: switch (props.test) {
47 + bb0: switch (props.test) {
48 case true: {
49 console.log(handlers.value);
50 - break bb2;
50 + break bb0;
51 }
52 default: {
53 }
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/complex-while.expect.md
+2 -2
@@ -25,10 +25,10 @@ export const FIXTURE_ENTRYPOINT = {
25
26 ```javascript
27 function foo(a, b, c) {
28 - bb1: if (a) {
28 + bb0: if (a) {
29 while (b) {
30 if (c) {
31 - break bb1;
31 + break bb0;
32 }
33 }
34 }
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/conditional-break-labeled.expect.md
+2 -2
@@ -39,9 +39,9 @@ function Component(props) {
39 if ($[0] !== props) {
40 a = [];
41 a.push(props.a);
42 - bb1: {
42 + bb0: {
43 if (props.b) {
44 - break bb1;
44 + break bb0;
45 }
46
47 a.push(props.c);
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/conditional-early-return.expect.md
+6 -6
@@ -76,12 +76,12 @@ function ComponentA(props) {
76 let t0;
77 if ($[0] !== props) {
78 t0 = Symbol.for("react.early_return_sentinel");
79 - bb8: {
79 + bb0: {
80 a_DEBUG = [];
81 a_DEBUG.push(props.a);
82 if (props.b) {
83 t0 = null;
84 - break bb8;
84 + break bb0;
85 }
86
87 a_DEBUG.push(props.d);
@@ -130,13 +130,13 @@ function ComponentC(props) {
130 let t0;
131 if ($[0] !== props) {
132 t0 = Symbol.for("react.early_return_sentinel");
133 - bb8: {
133 + bb0: {
134 a = [];
135 a.push(props.a);
136 if (props.b) {
137 a.push(props.c);
138 t0 = null;
139 - break bb8;
139 + break bb0;
140 }
141
142 a.push(props.d);
@@ -163,13 +163,13 @@ function ComponentD(props) {
163 let t0;
164 if ($[0] !== props) {
165 t0 = Symbol.for("react.early_return_sentinel");
166 - bb8: {
166 + bb0: {
167 a = [];
168 a.push(props.a);
169 if (props.b) {
170 a.push(props.c);
171 t0 = a;
172 - break bb8;
172 + break bb0;
173 }
174
175 a.push(props.d);
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/dominator.expect.md
+5 -5
@@ -49,23 +49,23 @@ export const FIXTURE_ENTRYPOINT = {
49 ```javascript
50 function Component(props) {
51 let x = 0;
52 - bb1: if (props.a) {
52 + bb0: if (props.a) {
53 x = 1;
54 } else {
55 if (props.b) {
56 } else {
57 - break bb1;
57 + break bb0;
58 }
59
60 x = 3;
61 }
62 - bb10: bb12: switch (props.c) {
62 + bb1: bb2: switch (props.c) {
63 case "a": {
64 x = 4;
65 - break bb12;
65 + break bb2;
66 }
67 case "b": {
68 - break bb10;
68 + break bb1;
69 }
70 case "c": {
71 }
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/early-return-nested-early-return-within-reactive-scope.expect.md
+4 -4
@@ -35,7 +35,7 @@ function Component(props) {
35 let t0;
36 if ($[0] !== props) {
37 t0 = Symbol.for("react.early_return_sentinel");
38 - bb12: {
38 + bb0: {
39 const x = [];
40 if (props.cond) {
41 x.push(props.a);
@@ -51,11 +51,11 @@ function Component(props) {
51 const y = t1;
52 x.push(y);
53 t0 = x;
54 - break bb12;
54 + break bb0;
55 }
56
57 t0 = x;
58 - break bb12;
58 + break bb0;
59 } else {
60 let t1;
61 if ($[4] === Symbol.for("react.memo_cache_sentinel")) {
@@ -65,7 +65,7 @@ function Component(props) {
65 t1 = $[4];
66 }
67 t0 = t1;
68 - break bb12;
68 + break bb0;
69 }
70 }
71 $[0] = props;
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/early-return-no-declarations-reassignments-dependencies.expect.md
+2 -2
@@ -73,12 +73,12 @@ function Component(props) {
73 let t0;
74 if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
75 t0 = Symbol.for("react.early_return_sentinel");
76 - bb9: {
76 + bb0: {
77 const x = [];
78 if (ENABLE_FEATURE) {
79 x.push(42);
80 t0 = x;
81 - break bb9;
81 + break bb0;
82 } else {
83 console.log("fallthrough");
84 }
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/early-return-within-reactive-scope.expect.md
+3 -3
@@ -49,12 +49,12 @@ function Component(props) {
49 let t0;
50 if ($[0] !== props) {
51 t0 = Symbol.for("react.early_return_sentinel");
52 - bb9: {
52 + bb0: {
53 const x = [];
54 if (props.cond) {
55 x.push(props.a);
56 t0 = x;
57 - break bb9;
57 + break bb0;
58 } else {
59 let t1;
60 if ($[2] !== props.b) {
@@ -65,7 +65,7 @@ function Component(props) {
65 t1 = $[3];
66 }
67 t0 = t1;
68 - break bb9;
68 + break bb0;
69 }
70 }
71 $[0] = props;
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/inverted-if-else.expect.md
+2 -2
@@ -27,10 +27,10 @@ export const FIXTURE_ENTRYPOINT = {
27 ```javascript
28 function foo(a, b, c) {
29 let x;
30 - bb1: {
30 + bb0: {
31 if (a) {
32 x = b;
33 - break bb1;
33 + break bb0;
34 }
35
36 x = c;
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/inverted-if.expect.md
+2 -2
@@ -31,10 +31,10 @@ function foo(a, b, c, d) {
31 let y;
32 if ($[0] !== a || $[1] !== b || $[2] !== c || $[3] !== d) {
33 y = [];
34 - bb1: if (a) {
34 + bb0: if (a) {
35 if (b) {
36 y.push(c);
37 - break bb1;
37 + break bb0;
38 }
39
40 y.push(d);
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/labeled-break-within-label-loop.expect.md
+2 -2
@@ -35,9 +35,9 @@ function useHook(end) {
35 log = [];
36 for (let i = 0; i < end + 1; i++) {
37 log.push(`${i} @A`);
38 - bb6: {
38 + bb0: {
39 if (i === end) {
40 - break bb6;
40 + break bb0;
41 }
42
43 log.push(`${i} @B`);
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/labeled-break-within-label-switch.expect.md
+2 -2
@@ -41,9 +41,9 @@ function useHook(cond) {
41 switch (CONST_STRING0) {
42 case CONST_STRING0: {
43 log.push(`@A`);
44 - bb3: {
44 + bb0: {
45 if (cond) {
46 - break bb3;
46 + break bb0;
47 }
48
49 log.push(`@B`);
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/object-mutated-in-consequent-alternate-both-return.expect.md
+3 -3
@@ -33,16 +33,16 @@ function Component(props) {
33 let t0;
34 if ($[0] !== props) {
35 t0 = Symbol.for("react.early_return_sentinel");
36 - bb9: {
36 + bb0: {
37 const object = makeObject_Primitives();
38 if (props.cond) {
39 object.value = 1;
40 t0 = object;
41 - break bb9;
41 + break bb0;
42 } else {
43 object.value = props.value;
44 t0 = object;
45 - break bb9;
45 + break bb0;
46 }
47 }
48 $[0] = props;
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/partial-early-return-within-reactive-scope.expect.md
+3 -3
@@ -35,12 +35,12 @@ function Component(props) {
35 let t0;
36 if ($[0] !== props) {
37 t0 = Symbol.for("react.early_return_sentinel");
38 - bb12: {
38 + bb0: {
39 const x = [];
40 if (props.cond) {
41 x.push(props.a);
42 t0 = x;
43 - break bb12;
43 + break bb0;
44 } else {
45 let t1;
46 if ($[3] === Symbol.for("react.memo_cache_sentinel")) {
@@ -52,7 +52,7 @@ function Component(props) {
52 y = t1;
53 if (props.b) {
54 t0 = undefined;
55 - break bb12;
55 + break bb0;
56 }
57 }
58 }
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/preserve-memo-validation/useMemo-conditional-access-own-scope.expect.md
+2 -2
@@ -32,7 +32,7 @@ function Component(t0) {
32 const $ = useMemoCache(2);
33 const { propA, propB } = t0;
34 let t1;
35 - bb6: {
35 + bb0: {
36 if (propA) {
37 let t2;
38 if ($[0] !== propB.x.y) {
@@ -43,7 +43,7 @@ function Component(t0) {
43 t2 = $[1];
44 }
45 t1 = t2;
46 - break bb6;
46 + break bb0;
47 }
48 t1 = undefined;
49 }
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reactive-control-dependency-from-interleaved-reactivity-switch.expect.md
+2 -2
@@ -55,10 +55,10 @@ function Component(props) {
55 const c = [a];
56
57 let x;
58 - bb1: switch (c[0][0]) {
58 + bb0: switch (c[0][0]) {
59 case true: {
60 x = 1;
61 - break bb1;
61 + break bb0;
62 }
63 default: {
64 x = 2;
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reactive-control-dependency-switch-case-test.expect.md
+3 -3
@@ -47,14 +47,14 @@ import { unstable_useMemoCache as useMemoCache } from "react";
47 function Component(props) {
48 const $ = useMemoCache(2);
49 let x;
50 - bb1: switch (props.cond) {
50 + bb0: switch (props.cond) {
51 case true: {
52 x = 1;
53 - break bb1;
53 + break bb0;
54 }
55 case false: {
56 x = 2;
57 - break bb1;
57 + break bb0;
58 }
59 default: {
60 x = 3;
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reactive-control-dependency-switch-condition.expect.md
+2 -2
@@ -48,10 +48,10 @@ function Component(t0) {
48 const $ = useMemoCache(2);
49 const { value } = t0;
50 let x;
51 - bb1: switch (GLOBAL) {
51 + bb0: switch (GLOBAL) {
52 case value: {
53 x = 1;
54 - break bb1;
54 + break bb0;
55 }
56 default: {
57 x = 2;
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reassignment-separate-scopes.expect.md
+2 -2
@@ -62,7 +62,7 @@ function foo(a, b, c) {
62 t0 = $[3];
63 }
64 const y = t0;
65 - bb3: switch (b) {
65 + bb0: switch (b) {
66 case 0: {
67 if ($[4] !== b) {
68 x = [];
@@ -72,7 +72,7 @@ function foo(a, b, c) {
72 } else {
73 x = $[5];
74 }
75 - break bb3;
75 + break bb0;
76 }
77 default: {
78 if ($[6] !== c) {
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reduce-reactive-cond-deps-break-in-scope.expect.md
+2 -2
@@ -36,9 +36,9 @@ function useFoo(t0) {
36 let x;
37 if ($[0] !== objIsNull || $[1] !== obj) {
38 x = [];
39 - bb1: {
39 + bb0: {
40 if (objIsNull) {
41 - break bb1;
41 + break bb0;
42 } else {
43 x.push(obj.a);
44 }
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reduce-reactive-cond-deps-return-in-scope.expect.md
+2 -2
@@ -35,11 +35,11 @@ function useFoo(t0) {
35 let t1;
36 if ($[0] !== objIsNull || $[1] !== obj) {
37 t1 = Symbol.for("react.early_return_sentinel");
38 - bb9: {
38 + bb0: {
39 x = [];
40 if (objIsNull) {
41 t1 = undefined;
42 - break bb9;
42 + break bb0;
43 } else {
44 x.push(obj.a);
45 }
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reduce-reactive-deps/cfg-switch-exhaustive.expect.md
+3 -3
@@ -44,14 +44,14 @@ function useCondDepInSwitch(props, other) {
44 let x;
45 if ($[0] !== other || $[1] !== props.a.b) {
46 x = {};
47 - bb1: switch (identity(other)) {
47 + bb0: switch (identity(other)) {
48 case 1: {
49 x.a = props.a.b;
50 - break bb1;
50 + break bb0;
51 }
52 case 2: {
53 x.b = props.a.b;
54 - break bb1;
54 + break bb0;
55 }
56 default: {
57 x.c = props.a.b;
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reduce-reactive-deps/cfg-switch-missing-case.expect.md
+3 -3
@@ -43,14 +43,14 @@ function useCondDepInSwitchMissingCase(props, other) {
43 let x;
44 if ($[0] !== other || $[1] !== props) {
45 x = {};
46 - bb1: switch (identity(other)) {
46 + bb0: switch (identity(other)) {
47 case 1: {
48 x.a = props.a.b;
49 - break bb1;
49 + break bb0;
50 }
51 case 2: {
52 x.b = 42;
53 - break bb1;
53 + break bb0;
54 }
55 default: {
56 x.c = props.a.b;
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reduce-reactive-deps/cfg-switch-missing-default.expect.md
+2 -2
@@ -40,10 +40,10 @@ function useCondDepInSwitchMissingDefault(props, other) {
40 let x;
41 if ($[0] !== other || $[1] !== props) {
42 x = {};
43 - bb1: switch (identity(other)) {
43 + bb0: switch (identity(other)) {
44 case 1: {
45 x.a = props.a.b;
46 - break bb1;
46 + break bb0;
47 }
48 case 2: {
49 x.b = props.a.b;
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reduce-reactive-deps/jump-poisoned/break-in-scope.expect.md
+2 -2
@@ -38,9 +38,9 @@ function useFoo(t0) {
38 let x;
39 if ($[0] !== objIsNull || $[1] !== obj) {
40 x = [];
41 - bb1: {
41 + bb0: {
42 if (objIsNull) {
43 - break bb1;
43 + break bb0;
44 }
45
46 x.push(obj.a);
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reduce-reactive-deps/jump-poisoned/break-poisons-outer-scope.expect.md
+2 -2
@@ -44,9 +44,9 @@ function useFoo(t0) {
44 let x;
45 if ($[0] !== cond || $[1] !== input) {
46 x = [];
47 - bb1: {
47 + bb0: {
48 if (cond) {
49 - break bb1;
49 + break bb0;
50 }
51 let t1;
52 if ($[3] !== input.a.b) {
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reduce-reactive-deps/jump-poisoned/reduce-if-nonexhaustive-poisoned-deps.expect.md
+2 -2
@@ -46,12 +46,12 @@ function useFoo(t0) {
46 let t1;
47 if ($[0] !== cond || $[1] !== hasAB || $[2] !== input) {
48 t1 = Symbol.for("react.early_return_sentinel");
49 - bb11: {
49 + bb0: {
50 x = [];
51 if (cond) {
52 if (!hasAB) {
53 t1 = null;
54 - break bb11;
54 + break bb0;
55 }
56 let t2;
57 if ($[5] !== input.a.b) {
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reduce-reactive-deps/jump-poisoned/reduce-if-nonexhaustive-poisoned-deps1.expect.md
+2 -2
@@ -47,12 +47,12 @@ function useFoo(t0) {
47 let t1;
48 if ($[0] !== cond || $[1] !== hasAB || $[2] !== input) {
49 t1 = Symbol.for("react.early_return_sentinel");
50 - bb12: {
50 + bb0: {
51 x = [];
52 if (cond) {
53 if (!hasAB) {
54 t1 = null;
55 - break bb12;
55 + break bb0;
56 } else {
57 let t2;
58 if ($[5] !== input.a.b) {
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reduce-reactive-deps/jump-poisoned/return-in-scope.expect.md
+2 -2
@@ -37,11 +37,11 @@ function useFoo(t0) {
37 let t1;
38 if ($[0] !== objIsNull || $[1] !== obj) {
39 t1 = Symbol.for("react.early_return_sentinel");
40 - bb8: {
40 + bb0: {
41 x = [];
42 if (objIsNull) {
43 t1 = undefined;
44 - break bb8;
44 + break bb0;
45 }
46
47 x.push(obj.b);
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reduce-reactive-deps/jump-poisoned/return-poisons-outer-scope.expect.md
+2 -2
@@ -43,11 +43,11 @@ function useFoo(t0) {
43 let t1;
44 if ($[0] !== cond || $[1] !== input) {
45 t1 = Symbol.for("react.early_return_sentinel");
46 - bb8: {
46 + bb0: {
47 x = [];
48 if (cond) {
49 t1 = null;
50 - break bb8;
50 + break bb0;
51 }
52 let t2;
53 if ($[4] !== input.a.b) {
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reduce-reactive-deps/jump-unpoisoned/else-branch-scope-unpoisoned.expect.md
+2 -2
@@ -45,8 +45,8 @@ function useFoo(t0) {
45 let x;
46 if ($[0] !== cond || $[1] !== input) {
47 x = [];
48 - bb1: if (cond) {
49 - break bb1;
48 + bb0: if (cond) {
49 + break bb0;
50 } else {
51 let t1;
52 if ($[3] !== input.a.b) {
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reduce-reactive-deps/jump-unpoisoned/jump-target-within-scope-label.expect.md
+2 -2
@@ -40,8 +40,8 @@ function useFoo(t0) {
40 let x;
41 if ($[0] !== cond || $[1] !== input.a.b) {
42 x = [];
43 - bb1: if (cond) {
44 - break bb1;
43 + bb0: if (cond) {
44 + break bb0;
45 }
46
47 x.push(input.a.b);
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reduce-reactive-deps/jump-unpoisoned/reduce-if-exhaustive-nonpoisoned-deps.expect.md
+2 -2
@@ -37,7 +37,7 @@ function useFoo(t0) {
37 let t1;
38 if ($[0] !== hasAB || $[1] !== input.a || $[2] !== returnNull) {
39 t1 = Symbol.for("react.early_return_sentinel");
40 - bb11: {
40 + bb0: {
41 x = [];
42 if (!hasAB) {
43 let t2;
@@ -51,7 +51,7 @@ function useFoo(t0) {
51 x.push(t2);
52 if (!returnNull) {
53 t1 = null;
54 - break bb11;
54 + break bb0;
55 }
56 } else {
57 let t2;
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reduce-reactive-deps/jump-unpoisoned/reduce-if-exhaustive-nonpoisoned-deps1.expect.md
+2 -2
@@ -47,7 +47,7 @@ function useFoo(t0) {
47 let t1;
48 if ($[0] !== cond1 || $[1] !== cond2 || $[2] !== input.a.b) {
49 t1 = Symbol.for("react.early_return_sentinel");
50 - bb12: {
50 + bb0: {
51 x = [];
52 if (cond1) {
53 if (!cond2) {
@@ -61,7 +61,7 @@ function useFoo(t0) {
61 }
62 x.push(t2);
63 t1 = null;
64 - break bb12;
64 + break bb0;
65 } else {
66 let t2;
67 if ($[7] !== input.a.b) {
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reduce-reactive-deps/reduce-if-exhaustive-poisoned-deps.expect.md
+2 -2
@@ -38,7 +38,7 @@ function useFoo(t0) {
38 let t1;
39 if ($[0] !== inputHasABC || $[1] !== input.a || $[2] !== inputHasAB) {
40 t1 = Symbol.for("react.early_return_sentinel");
41 - bb11: {
41 + bb0: {
42 x = [];
43 if (!inputHasABC) {
44 let t2;
@@ -52,7 +52,7 @@ function useFoo(t0) {
52 x.push(t2);
53 if (!inputHasAB) {
54 t1 = null;
55 - break bb11;
55 + break bb0;
56 }
57 let t3;
58 if ($[7] !== input.a.b) {
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/repro-no-declarations-in-reactive-scope-with-early-return.expect.md
+2 -2
@@ -46,7 +46,7 @@ function Component() {
46 let t2;
47 if ($[0] !== items) {
48 t2 = Symbol.for("react.early_return_sentinel");
49 - bb15: {
49 + bb0: {
50 let t3;
51 if ($[4] === Symbol.for("react.memo_cache_sentinel")) {
52 t3 = (t4) => {
@@ -72,7 +72,7 @@ function Component() {
72 t4 = $[5];
73 }
74 t2 = t4;
75 - break bb15;
75 + break bb0;
76 }
77 let t4;
78 if ($[6] === Symbol.for("react.memo_cache_sentinel")) {
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/repro-no-value-for-temporary-reactive-scope-with-early-return.expect.md
+2 -2
@@ -43,12 +43,12 @@ function Component(props) {
43 let t1;
44 if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
45 t1 = Symbol.for("react.early_return_sentinel");
46 - bb8: {
46 + bb0: {
47 const object = makeObject_Primitives();
48 const cond = makeObject_Primitives();
49 if (!cond) {
50 t1 = null;
51 - break bb8;
51 + break bb0;
52 }
53
54 t0 = (
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/repro-preds-undefined-try-catch-return-primitive.expect.md
+3 -3
@@ -37,15 +37,15 @@ import { useMemo } from "react";
37 const checkforTouchEvents = true;
38 function useSupportsTouchEvent() {
39 let t0;
40 - bb15: {
40 + bb0: {
41 if (checkforTouchEvents) {
42 try {
43 document.createEvent("TouchEvent");
44 t0 = true;
45 - break bb15;
45 + break bb0;
46 } catch {
47 t0 = false;
48 - break bb15;
48 + break bb0;
49 }
50 }
51 t0 = undefined;
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/repro-renaming-conflicting-decls.expect.md
+2 -2
@@ -51,12 +51,12 @@ function Component(props) {
51 let t2;
52 if ($[0] !== props) {
53 t2 = Symbol.for("react.early_return_sentinel");
54 - bb11: {
54 + bb0: {
55 t0 = toJSON(props);
56 const propsString = t0;
57 if (propsString.length <= 2) {
58 t2 = null;
59 - break bb11;
59 + break bb0;
60 }
61
62 t1 = identity(propsString);
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/repro-unreachable-code-early-return-in-useMemo.expect.md
+2 -2
@@ -52,10 +52,10 @@ function Component(t0) {
52 const $ = useMemoCache(7);
53 const { value } = t0;
54 let t1;
55 - bb13: {
55 + bb0: {
56 if (value == null) {
57 t1 = null;
58 - break bb13;
58 + break bb0;
59 }
60 try {
61 let t3;
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reverse-postorder.expect.md
+3 -3
@@ -43,12 +43,12 @@ export const FIXTURE_ENTRYPOINT = {
43 ```javascript
44 function Component(props) {
45 if (props.cond) {
46 - bb3: switch (props.test) {
46 + bb0: switch (props.test) {
47 case 0: {
48 - break bb3;
48 + break bb0;
49 }
50 case 1: {
51 - break bb3;
51 + break bb0;
52 }
53 case 2: {
54 }
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/ssa-switch.expect.md
+3 -3
@@ -34,12 +34,12 @@ export const FIXTURE_ENTRYPOINT = {
34
35 ```javascript
36 function foo() {
37 - bb1: switch (1) {
37 + bb0: switch (1) {
38 case 1: {
39 - break bb1;
39 + break bb0;
40 }
41 case 2: {
42 - break bb1;
42 + break bb0;
43 }
44 default: {
45 }
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/switch-non-final-default.expect.md
+3 -3
@@ -38,9 +38,9 @@ function Component(props) {
38 let y;
39 if ($[0] !== props) {
40 x = [];
41 - bb1: switch (props.p0) {
41 + bb0: switch (props.p0) {
42 case 1: {
43 - break bb1;
43 + break bb0;
44 }
45 case true: {
46 x.push(props.p2);
@@ -54,7 +54,7 @@ function Component(props) {
54 y = t0;
55 }
56 default: {
57 - break bb1;
57 + break bb0;
58 }
59 case false: {
60 y = x;
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/switch-with-fallthrough.expect.md
+3 -3
@@ -42,16 +42,16 @@ export const FIXTURE_ENTRYPOINT = {
42
43 ```javascript
44 function foo(x) {
45 - bb1: switch (x) {
45 + bb0: switch (x) {
46 case 0: {
47 }
48 case 1: {
49 }
50 case 2: {
51 - break bb1;
51 + break bb0;
52 }
53 case 3: {
54 - break bb1;
54 + break bb0;
55 }
56 case 4: {
57 }
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/try-catch-in-nested-scope.expect.md new
+92
@@ -0,0 +1,92 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +import { mutate, setProperty, throwErrorWithMessageIf } from "shared-runtime";
6 +
7 +function useFoo({ value, cond }) {
8 + let y = [value];
9 + let x = { cond };
10 +
11 + try {
12 + mutate(x);
13 + throwErrorWithMessageIf(x.cond, "error");
14 + } catch {
15 + setProperty(x, "henderson");
16 + return x;
17 + }
18 + setProperty(x, "nevada");
19 + y.push(x);
20 +
21 + return y;
22 +}
23 +
24 +export const FIXTURE_ENTRYPOINT = {
25 + fn: useFoo,
26 + params: [{ value: 4, cond: true }],
27 + sequentialRenders: [
28 + { value: 4, cond: true },
29 + { value: 5, cond: true },
30 + { value: 5, cond: false },
31 + ],
32 +};
33 +
34 +```
35 +
36 +## Code
37 +
38 +```javascript
39 +import { unstable_useMemoCache as useMemoCache } from "react";
40 +import { mutate, setProperty, throwErrorWithMessageIf } from "shared-runtime";
41 +
42 +function useFoo(t0) {
43 + const $ = useMemoCache(3);
44 + const { value, cond } = t0;
45 + let t1;
46 + if ($[0] !== value || $[1] !== cond) {
47 + t1 = Symbol.for("react.early_return_sentinel");
48 + bb0: {
49 + const y = [value];
50 + const x = { cond };
51 + try {
52 + mutate(x);
53 + throwErrorWithMessageIf(x.cond, "error");
54 + } catch {
55 + setProperty(x, "henderson");
56 + t1 = x;
57 + break bb0;
58 + }
59 +
60 + setProperty(x, "nevada");
61 + y.push(x);
62 +
63 + t1 = y;
64 + break bb0;
65 + }
66 + $[0] = value;
67 + $[1] = cond;
68 + $[2] = t1;
69 + } else {
70 + t1 = $[2];
71 + }
72 + if (t1 !== Symbol.for("react.early_return_sentinel")) {
73 + return t1;
74 + }
75 +}
76 +
77 +export const FIXTURE_ENTRYPOINT = {
78 + fn: useFoo,
79 + params: [{ value: 4, cond: true }],
80 + sequentialRenders: [
81 + { value: 4, cond: true },
82 + { value: 5, cond: true },
83 + { value: 5, cond: false },
84 + ],
85 +};
86 +
87 +```
88 +
89 +### Eval output
90 +(kind: ok) {"cond":true,"wat0":"joe","wat1":"henderson"}
91 +{"cond":true,"wat0":"joe","wat1":"henderson"}
92 +[5,{"cond":false,"wat0":"joe","wat1":"nevada"}]
\ No newline at end of file
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/try-catch-in-nested-scope.ts new
+28
@@ -0,0 +1,28 @@
1 +import { mutate, setProperty, throwErrorWithMessageIf } from "shared-runtime";
2 +
3 +function useFoo({ value, cond }) {
4 + let y = [value];
5 + let x = { cond };
6 +
7 + try {
8 + mutate(x);
9 + throwErrorWithMessageIf(x.cond, "error");
10 + } catch {
11 + setProperty(x, "henderson");
12 + return x;
13 + }
14 + setProperty(x, "nevada");
15 + y.push(x);
16 +
17 + return y;
18 +}
19 +
20 +export const FIXTURE_ENTRYPOINT = {
21 + fn: useFoo,
22 + params: [{ value: 4, cond: true }],
23 + sequentialRenders: [
24 + { value: 4, cond: true },
25 + { value: 5, cond: true },
26 + { value: 5, cond: false },
27 + ],
28 +};
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/try-catch-try-value-modified-in-catch.expect.md
+3 -3
@@ -34,7 +34,7 @@ function Component(props) {
34 let t0;
35 if ($[0] !== props.y || $[1] !== props.e) {
36 t0 = Symbol.for("react.early_return_sentinel");
37 - bb19: {
37 + bb0: {
38 try {
39 const y = [];
40 y.push(props.y);
@@ -43,11 +43,11 @@ function Component(props) {
43 const e = t1;
44 e.push(props.e);
45 t0 = e;
46 - break bb19;
46 + break bb0;
47 }
48
49 t0 = null;
50 - break bb19;
50 + break bb0;
51 }
52 $[0] = props.y;
53 $[1] = props.e;
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/try-catch-with-catch-param.expect.md
+3 -3
@@ -35,7 +35,7 @@ function Component(props) {
35 let t0;
36 if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
37 t0 = Symbol.for("react.early_return_sentinel");
38 - bb12: {
38 + bb0: {
39 const x = [];
40 try {
41 throwInput(x);
@@ -43,11 +43,11 @@ function Component(props) {
43 const e = t1;
44 e.push(null);
45 t0 = e;
46 - break bb12;
46 + break bb0;
47 }
48
49 t0 = x;
50 - break bb12;
50 + break bb0;
51 }
52 $[0] = t0;
53 } else {
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/try-catch-with-return.expect.md
+3 -3
@@ -37,19 +37,19 @@ function Component(props) {
37 let t0;
38 if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
39 t0 = Symbol.for("react.early_return_sentinel");
40 - bb26: {
40 + bb0: {
41 x = [];
42 try {
43 const y = shallowCopy({});
44 if (y == null) {
45 t0 = undefined;
46 - break bb26;
46 + break bb0;
47 }
48
49 x.push(throwInput(y));
50 } catch {
51 t0 = null;
52 - break bb26;
52 + break bb0;
53 }
54 }
55 $[0] = x;
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/unlabeled-break-within-label-switch.expect.md
+2 -2
@@ -38,11 +38,11 @@ function useHook(cond) {
38 let log;
39 if ($[0] !== cond) {
40 log = [];
41 - bb1: switch (CONST_STRING0) {
41 + bb0: switch (CONST_STRING0) {
42 case CONST_STRING0: {
43 log.push(`@A`);
44 if (cond) {
45 - break bb1;
45 + break bb0;
46 }
47
48 log.push(`@B`);
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/useMemo-if-else-multiple-return.expect.md
+2 -2
@@ -21,7 +21,7 @@ import { unstable_useMemoCache as useMemoCache } from "react";
21 function Component(props) {
22 const $ = useMemoCache(4);
23 let t0;
24 - bb7: {
24 + bb0: {
25 if (props.cond) {
26 let t1;
27 if ($[0] !== props.a) {
@@ -32,7 +32,7 @@ function Component(props) {
32 t1 = $[1];
33 }
34 t0 = t1;
35 - break bb7;
35 + break bb0;
36 }
37 let t1;
38 if ($[2] !== props.b) {
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/useMemo-inlining-block-return.expect.md
+2 -2
@@ -26,7 +26,7 @@ import { unstable_useMemoCache as useMemoCache } from "react";
26 function component(a, b) {
27 const $ = useMemoCache(2);
28 let t0;
29 - bb6: {
29 + bb0: {
30 if (a) {
31 let t1;
32 if ($[0] !== b) {
@@ -37,7 +37,7 @@ function component(a, b) {
37 t1 = $[1];
38 }
39 t0 = t1;
40 - break bb6;
40 + break bb0;
41 }
42 t0 = undefined;
43 }
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/useMemo-inverted-if.expect.md
+4 -4
@@ -28,14 +28,14 @@ export const FIXTURE_ENTRYPOINT = {
28 ```javascript
29 function Component(props) {
30 let t0;
31 - bb10: {
32 - bb2: {
31 + bb0: {
32 + bb1: {
33 if (props.cond) {
34 - break bb2;
34 + break bb1;
35 }
36
37 t0 = props.a;
38 - break bb10;
38 + break bb0;
39 }
40
41 t0 = props.b;
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/useMemo-multiple-if-else.expect.md
+2 -2
@@ -34,7 +34,7 @@ import { useMemo, unstable_useMemoCache as useMemoCache } from "react";
34 function Component(props) {
35 const $ = useMemoCache(3);
36 let t0;
37 - bb9: {
37 + bb0: {
38 let y;
39 if ($[0] !== props) {
40 y = [];
@@ -43,7 +43,7 @@ function Component(props) {
43 }
44 if (props.cond2) {
45 t0 = y;
46 - break bb9;
46 + break bb0;
47 }
48
49 y.push(props.b);
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/useMemo-switch-no-fallthrough.expect.md
+2 -2
@@ -29,10 +29,10 @@ export const FIXTURE_ENTRYPOINT = {
29 ```javascript
30 function Component(props) {
31 let t0;
32 - bb8: switch (props.key) {
32 + bb0: switch (props.key) {
33 case "key": {
34 t0 = props.value;
35 - break bb8;
35 + break bb0;
36 }
37 default: {
38 t0 = props.defaultValue;
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/useMemo-switch-return.expect.md
+4 -4
@@ -35,16 +35,16 @@ export const FIXTURE_ENTRYPOINT = {
35 ```javascript
36 function Component(props) {
37 let t0;
38 - bb10: {
38 + bb0: {
39 let y;
40 - bb2: switch (props.switch) {
40 + bb1: switch (props.switch) {
41 case "foo": {
42 t0 = "foo";
43 - break bb10;
43 + break bb0;
44 }
45 case "bar": {
46 y = "bar";
47 - break bb2;
47 + break bb1;
48 }
49 default: {
50 y = props.y;
compiler/packages/snap/src/sprout/shared-runtime.ts
+6
@@ -157,6 +157,12 @@ export function throwInput(x: Object): never {
157 throw x;
158 }
159
160 +export function throwErrorWithMessageIf(cond: boolean, message: string): void {
161 + if (cond) {
162 + throw new Error(message);
163 + }
164 +}
165 +
166 export function logValue<T>(value: T): void {
167 console.log(value);
168 }