[ez] Patch BuildHIR to match unlabeled breaks to switch and loops
Mofei Zhang committed
Mar 22, 2024 at 16:34 UTC
ee93b62f510e28e4696ebea3ef0384d9db046b09
10 files changed
+274
-4
compiler/packages/babel-plugin-react-forget/src/HIR/HIRBuilder.ts
+5
-1
@@ -517,7 +517,11 @@ export default class HIRBuilder {
517
lookupBreak(label: string | null): BlockId {
518
for (let ii = this.#scopes.length - 1; ii >= 0; ii--) {
519
const scope = this.#scopes[ii];
520
- if (label === null || label === scope.label) {
520
+ if (
521
+ (label === null &&
522
+ (scope.kind === "loop" || scope.kind === "switch")) ||
523
+ label === scope.label
524
+ ) {
525
return scope.breakBlock;
526
}
527
}
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/labeled-break-within-label-loop.expect.md
renamed
+4
-2
@@ -8,7 +8,7 @@ function useHook(end) {
8
log.push(`${i} @A`);
9
bb0: {
10
if (i === end) {
11
- break;
11
+ break bb0;
12
}
13
log.push(`${i} @B`);
14
}
@@ -59,4 +59,6 @@ export const FIXTURE_ENTRYPOINT = {
59
};
60
61
```
62
-
\ No newline at end of file
62
+
63
+### Eval output
64
+(kind: ok) ["0 @A","0 @B","0 @C","1 @A","1 @C"]
\ No newline at end of file
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/labeled-break-within-label-loop.ts
new
+19
@@ -0,0 +1,19 @@
1
+function useHook(end) {
2
+ const log = [];
3
+ for (let i = 0; i < end + 1; i++) {
4
+ log.push(`${i} @A`);
5
+ bb0: {
6
+ if (i === end) {
7
+ break bb0;
8
+ }
9
+ log.push(`${i} @B`);
10
+ }
11
+ log.push(`${i} @C`);
12
+ }
13
+ return log;
14
+}
15
+
16
+export const FIXTURE_ENTRYPOINT = {
17
+ fn: useHook,
18
+ params: [1],
19
+};
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/labeled-break-within-label-switch.expect.md
new
+71
@@ -0,0 +1,71 @@
1
+
2
+## Input
3
+
4
+```javascript
5
+import { CONST_STRING0 } from "shared-runtime";
6
+
7
+function useHook(cond) {
8
+ const log = [];
9
+ switch (CONST_STRING0) {
10
+ case CONST_STRING0:
11
+ log.push(`@A`);
12
+ bb0: {
13
+ if (cond) {
14
+ break bb0;
15
+ }
16
+ log.push(`@B`);
17
+ }
18
+ log.push(`@C`);
19
+ }
20
+ return log;
21
+}
22
+
23
+export const FIXTURE_ENTRYPOINT = {
24
+ fn: useHook,
25
+ params: [true],
26
+};
27
+
28
+```
29
+
30
+## Code
31
+
32
+```javascript
33
+import { unstable_useMemoCache as useMemoCache } from "react";
34
+import { CONST_STRING0 } from "shared-runtime";
35
+
36
+function useHook(cond) {
37
+ const $ = useMemoCache(2);
38
+ let log;
39
+ if ($[0] !== cond) {
40
+ log = [];
41
+ switch (CONST_STRING0) {
42
+ case CONST_STRING0: {
43
+ log.push(`@A`);
44
+ bb3: {
45
+ if (cond) {
46
+ break bb3;
47
+ }
48
+
49
+ log.push(`@B`);
50
+ }
51
+
52
+ log.push(`@C`);
53
+ }
54
+ }
55
+ $[0] = cond;
56
+ $[1] = log;
57
+ } else {
58
+ log = $[1];
59
+ }
60
+ return log;
61
+}
62
+
63
+export const FIXTURE_ENTRYPOINT = {
64
+ fn: useHook,
65
+ params: [true],
66
+};
67
+
68
+```
69
+
70
+### Eval output
71
+(kind: ok) ["@A","@C"]
\ No newline at end of file
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/labeled-break-within-label-switch.ts
new
+22
@@ -0,0 +1,22 @@
1
+import { CONST_STRING0 } from "shared-runtime";
2
+
3
+function useHook(cond) {
4
+ const log = [];
5
+ switch (CONST_STRING0) {
6
+ case CONST_STRING0:
7
+ log.push(`@A`);
8
+ bb0: {
9
+ if (cond) {
10
+ break bb0;
11
+ }
12
+ log.push(`@B`);
13
+ }
14
+ log.push(`@C`);
15
+ }
16
+ return log;
17
+}
18
+
19
+export const FIXTURE_ENTRYPOINT = {
20
+ fn: useHook,
21
+ params: [true],
22
+};
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/unlabeled-break-within-label-loop.expect.md
new
+62
@@ -0,0 +1,62 @@
1
+
2
+## Input
3
+
4
+```javascript
5
+function useHook(end) {
6
+ const log = [];
7
+ for (let i = 0; i < end + 1; i++) {
8
+ log.push(`${i} @A`);
9
+ bb0: {
10
+ if (i === end) {
11
+ break;
12
+ }
13
+ log.push(`${i} @B`);
14
+ }
15
+ log.push(`${i} @C`);
16
+ }
17
+ return log;
18
+}
19
+
20
+export const FIXTURE_ENTRYPOINT = {
21
+ fn: useHook,
22
+ params: [1],
23
+};
24
+
25
+```
26
+
27
+## Code
28
+
29
+```javascript
30
+import { unstable_useMemoCache as useMemoCache } from "react";
31
+function useHook(end) {
32
+ const $ = useMemoCache(2);
33
+ let log;
34
+ if ($[0] !== end) {
35
+ log = [];
36
+ for (let i = 0; i < end + 1; i++) {
37
+ log.push(`${i} @A`);
38
+ if (i === end) {
39
+ break;
40
+ }
41
+
42
+ log.push(`${i} @B`);
43
+
44
+ log.push(`${i} @C`);
45
+ }
46
+ $[0] = end;
47
+ $[1] = log;
48
+ } else {
49
+ log = $[1];
50
+ }
51
+ return log;
52
+}
53
+
54
+export const FIXTURE_ENTRYPOINT = {
55
+ fn: useHook,
56
+ params: [1],
57
+};
58
+
59
+```
60
+
61
+### Eval output
62
+(kind: ok) ["0 @A","0 @B","0 @C","1 @A"]
\ No newline at end of file
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/unlabeled-break-within-label-loop.ts
renamed
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/unlabeled-break-within-label-switch.expect.md
new
+69
@@ -0,0 +1,69 @@
1
+
2
+## Input
3
+
4
+```javascript
5
+import { CONST_STRING0 } from "shared-runtime";
6
+
7
+function useHook(cond) {
8
+ const log = [];
9
+ switch (CONST_STRING0) {
10
+ case CONST_STRING0:
11
+ log.push(`@A`);
12
+ bb0: {
13
+ if (cond) {
14
+ break;
15
+ }
16
+ log.push(`@B`);
17
+ }
18
+ log.push(`@C`);
19
+ }
20
+ return log;
21
+}
22
+
23
+export const FIXTURE_ENTRYPOINT = {
24
+ fn: useHook,
25
+ params: [true],
26
+};
27
+
28
+```
29
+
30
+## Code
31
+
32
+```javascript
33
+import { unstable_useMemoCache as useMemoCache } from "react";
34
+import { CONST_STRING0 } from "shared-runtime";
35
+
36
+function useHook(cond) {
37
+ const $ = useMemoCache(2);
38
+ let log;
39
+ if ($[0] !== cond) {
40
+ log = [];
41
+ bb1: switch (CONST_STRING0) {
42
+ case CONST_STRING0: {
43
+ log.push(`@A`);
44
+ if (cond) {
45
+ break bb1;
46
+ }
47
+
48
+ log.push(`@B`);
49
+
50
+ log.push(`@C`);
51
+ }
52
+ }
53
+ $[0] = cond;
54
+ $[1] = log;
55
+ } else {
56
+ log = $[1];
57
+ }
58
+ return log;
59
+}
60
+
61
+export const FIXTURE_ENTRYPOINT = {
62
+ fn: useHook,
63
+ params: [true],
64
+};
65
+
66
+```
67
+
68
+### Eval output
69
+(kind: ok) ["@A"]
\ No newline at end of file
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/unlabeled-break-within-label-switch.ts
new
+22
@@ -0,0 +1,22 @@
1
+import { CONST_STRING0 } from "shared-runtime";
2
+
3
+function useHook(cond) {
4
+ const log = [];
5
+ switch (CONST_STRING0) {
6
+ case CONST_STRING0:
7
+ log.push(`@A`);
8
+ bb0: {
9
+ if (cond) {
10
+ break;
11
+ }
12
+ log.push(`@B`);
13
+ }
14
+ log.push(`@C`);
15
+ }
16
+ return log;
17
+}
18
+
19
+export const FIXTURE_ENTRYPOINT = {
20
+ fn: useHook,
21
+ params: [true],
22
+};
compiler/packages/snap/src/SproutTodoFilter.ts
-1
@@ -534,7 +534,6 @@ const skipFilter = new Set([
534
// bugs
535
"bug-reduce-reactive-deps-return-in-scope",
536
"bug-reduce-reactive-deps-break-in-scope",
537
- "bug-unlabeled-break-within-label-loop",
537
538
// 'react-forget-runtime' not yet supported
539
"flag-enable-emit-hook-guards",