Support empty catch clause
Adds support for empty catch clauses in a try/catch. We add a new block kind `catch` which prevents the empty catch block from being merged with other types of blocks, preserving the block structure within the HIR and allowing us to reconstruct the empty catch.
Joe Savona committed
Oct 4, 2023 at 12:24 UTC
8e8ae96478a1116ae7b6d9ede27c3b2da4a64293
6 files changed
+51
-30
compiler/packages/babel-plugin-react-forget/src/HIR/BuildHIR.ts
+1
-1
@@ -1175,7 +1175,7 @@ function lowerStatement(
1175
};
1176
}
1177
1178
- const handler = builder.enter("block", (_blockId) => {
1178
+ const handler = builder.enter("catch", (_blockId) => {
1179
if (handlerBinding !== null) {
1180
lowerAssignment(
1181
builder,
compiler/packages/babel-plugin-react-forget/src/HIR/HIR.ts
+1
-1
@@ -264,7 +264,7 @@ export type HIR = {
264
* an exception occurs, therefore the block model only represents explicit throw
265
* statements and not implicit exceptions which may occur.
266
*/
267
-export type BlockKind = "block" | "value" | "loop" | "sequence";
267
+export type BlockKind = "block" | "value" | "loop" | "sequence" | "catch";
268
export type BasicBlock = {
269
kind: BlockKind;
270
id: BlockId;
compiler/packages/babel-plugin-react-forget/src/SSA/LeaveSSA.ts
+3
-1
@@ -183,7 +183,9 @@ export function leaveSSA(fn: HIRFunction): void {
183
originalLVal.lvalue === value.lvalue // in case this was pre-declared for the `for` initializer
184
) {
185
CompilerError.invariant(
186
- originalLVal !== undefined || block.kind === "block",
186
+ originalLVal !== undefined ||
187
+ block.kind === "block" ||
188
+ block.kind === "catch",
189
{
190
reason: `TODO: Handle reassignment in a value block where the original declaration was removed by dead code elimination (DCE)`,
191
description: null,
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/empty-catch-statement.expect.md
new
+45
@@ -0,0 +1,45 @@
1
+
2
+## Input
3
+
4
+```javascript
5
+import { getNumber } from "shared-runtime";
6
+
7
+function useFoo() {
8
+ try {
9
+ return getNumber();
10
+ } catch {}
11
+}
12
+export const FIXTURE_ENTRYPOINT = {
13
+ fn: useFoo,
14
+ params: [],
15
+};
16
+
17
+```
18
+
19
+## Code
20
+
21
+```javascript
22
+import { unstable_useMemoCache as useMemoCache } from "react";
23
+import { getNumber } from "shared-runtime";
24
+
25
+function useFoo() {
26
+ const $ = useMemoCache(1);
27
+ try {
28
+ let t0;
29
+ if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
30
+ t0 = getNumber();
31
+ $[0] = t0;
32
+ } else {
33
+ t0 = $[0];
34
+ }
35
+ return t0;
36
+ } catch {}
37
+}
38
+
39
+export const FIXTURE_ENTRYPOINT = {
40
+ fn: useFoo,
41
+ params: [],
42
+};
43
+
44
+```
45
+
\ No newline at end of file
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/empty-catch-statement.ts
renamed
+1
-1
@@ -5,7 +5,7 @@ function useFoo() {
5
return getNumber();
6
} catch {}
7
}
8
-export const FIXTURE_ENTRYPONT = {
8
+export const FIXTURE_ENTRYPOINT = {
9
fn: useFoo,
10
params: [],
11
};
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.empty-catch-statement.expect.md
deleted
-26
@@ -1,26 +0,0 @@
1
-
2
-## Input
3
-
4
-```javascript
5
-import { getNumber } from "shared-runtime";
6
-
7
-function useFoo() {
8
- try {
9
- return getNumber();
10
- } catch {}
11
-}
12
-export const FIXTURE_ENTRYPONT = {
13
- fn: useFoo,
14
- params: [],
15
-};
16
-
17
-```
18
-
19
-
20
-## Error
21
-
22
-```
23
-[ReactForget] Invariant: Cannot emit the same block twice: bb2
24
-```
25
-
26
-
\ No newline at end of file