[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
}