@samitouri / QOS-React-2 / commits / 8e8ae96478

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