diff --git a/compiler/packages/babel-plugin-react-forget/src/HIR/PrintHIR.ts b/compiler/packages/babel-plugin-react-forget/src/HIR/PrintHIR.ts index e86c62c242..f248e08eb8 100644 --- a/compiler/packages/babel-plugin-react-forget/src/HIR/PrintHIR.ts +++ b/compiler/packages/babel-plugin-react-forget/src/HIR/PrintHIR.ts @@ -266,8 +266,10 @@ export function printTerminal(terminal: Terminal): Array | string { break; } case "try": { - value = `Try block=bb${terminal.block} catch=bb${ - terminal.handler + value = `Try block=bb${terminal.block} handler=bb${terminal.handler}${ + terminal.handlerBinding !== null + ? ` handlerBinding=(${printPlace(terminal.handlerBinding)})` + : "" } fallthrough=${ terminal.fallthrough != null ? `bb${terminal.fallthrough}` : "" }`; diff --git a/compiler/packages/babel-plugin-react-forget/src/HIR/visitors.ts b/compiler/packages/babel-plugin-react-forget/src/HIR/visitors.ts index 55d2536b67..ec814e1ab6 100644 --- a/compiler/packages/babel-plugin-react-forget/src/HIR/visitors.ts +++ b/compiler/packages/babel-plugin-react-forget/src/HIR/visitors.ts @@ -1126,7 +1126,12 @@ export function* eachTerminalOperand(terminal: Terminal): Iterable { yield terminal.value; break; } - case "try": + case "try": { + if (terminal.handlerBinding !== null) { + yield terminal.handlerBinding; + } + break; + } case "maybe-throw": case "sequence": case "label": diff --git a/compiler/packages/babel-plugin-react-forget/src/ReactiveScopes/PrintReactiveFunction.ts b/compiler/packages/babel-plugin-react-forget/src/ReactiveScopes/PrintReactiveFunction.ts index 59a6699811..a336c3e4cc 100644 --- a/compiler/packages/babel-plugin-react-forget/src/ReactiveScopes/PrintReactiveFunction.ts +++ b/compiler/packages/babel-plugin-react-forget/src/ReactiveScopes/PrintReactiveFunction.ts @@ -354,7 +354,12 @@ function writeTerminal(writer: Writer, terminal: ReactiveTerminal): void { case "try": { writer.writeLine(`[${terminal.id}] try {`); writeReactiveInstructions(writer, terminal.block); - writer.writeLine(`} catch {`); + writer.write(`} catch `); + if (terminal.handlerBinding !== null) { + writer.writeLine(`(${printPlace(terminal.handlerBinding)}) {`); + } else { + writer.writeLine(`{`); + } writeReactiveInstructions(writer, terminal.handler); writer.writeLine("}"); break; diff --git a/compiler/packages/babel-plugin-react-forget/src/ReactiveScopes/visitors.ts b/compiler/packages/babel-plugin-react-forget/src/ReactiveScopes/visitors.ts index a27fc17846..9e2fddfbda 100644 --- a/compiler/packages/babel-plugin-react-forget/src/ReactiveScopes/visitors.ts +++ b/compiler/packages/babel-plugin-react-forget/src/ReactiveScopes/visitors.ts @@ -545,6 +545,9 @@ export class ReactiveFunctionTransform< } case "try": { this.visitBlock(terminal.block, state); + if (terminal.handlerBinding !== null) { + this.visitPlace(terminal.id, terminal.handlerBinding, state); + } this.visitBlock(terminal.handler, state); break; } diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.todo-try-catch-within-function-expression.expect.md b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.todo-try-catch-within-function-expression.expect.md deleted file mode 100644 index b9e0184b64..0000000000 --- a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.todo-try-catch-within-function-expression.expect.md +++ /dev/null @@ -1,25 +0,0 @@ - -## Input - -```javascript -function Component(props) { - const callback = () => { - try { - return []; - } catch (e) { - return; - } - }; - return callback(); -} - -``` - - -## Error - -``` -[ReactForget] Invariant: Expected temporaries to be promoted to named identifiers in an earlier pass. identifier 16 is unnamed -``` - - \ No newline at end of file diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/try-catch-within-function-expression-returns-caught-value.expect.md b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/try-catch-within-function-expression-returns-caught-value.expect.md new file mode 100644 index 0000000000..c60d17b796 --- /dev/null +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/try-catch-within-function-expression-returns-caught-value.expect.md @@ -0,0 +1,68 @@ + +## Input + +```javascript +import { throwInput } from "shared-runtime"; + +function Component(props) { + const callback = () => { + try { + throwInput([props.value]); + } catch (e) { + return e; + } + }; + return callback(); +} + +export const FIXTURE_ENTRYPOINT = { + fn: Component, + params: [{ value: 42 }], +}; + +``` + +## Code + +```javascript +import { unstable_useMemoCache as useMemoCache } from "react"; +import { throwInput } from "shared-runtime"; + +function Component(props) { + const $ = useMemoCache(4); + let t0; + if ($[0] !== props.value) { + t0 = () => { + try { + throwInput([props.value]); + } catch (t1) { + const e = t1; + return e; + } + }; + $[0] = props.value; + $[1] = t0; + } else { + t0 = $[1]; + } + const callback = t0; + let t1; + if ($[2] !== callback) { + t1 = callback(); + $[2] = callback; + $[3] = t1; + } else { + t1 = $[3]; + } + return t1; +} + +export const FIXTURE_ENTRYPOINT = { + fn: Component, + params: [{ value: 42 }], +}; + +``` + +### Eval output +(kind: ok) [42] \ No newline at end of file diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/try-catch-within-function-expression-returns-caught-value.js b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/try-catch-within-function-expression-returns-caught-value.js new file mode 100644 index 0000000000..bda4cfbb6d --- /dev/null +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/try-catch-within-function-expression-returns-caught-value.js @@ -0,0 +1,17 @@ +import { throwInput } from "shared-runtime"; + +function Component(props) { + const callback = () => { + try { + throwInput([props.value]); + } catch (e) { + return e; + } + }; + return callback(); +} + +export const FIXTURE_ENTRYPOINT = { + fn: Component, + params: [{ value: 42 }], +}; diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/try-catch-within-function-expression.expect.md b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/try-catch-within-function-expression.expect.md new file mode 100644 index 0000000000..70e2c7f644 --- /dev/null +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/try-catch-within-function-expression.expect.md @@ -0,0 +1,61 @@ + +## Input + +```javascript +function Component(props) { + const callback = () => { + try { + return []; + } catch (e) { + return; + } + }; + return callback(); +} + +export const FIXTURE_ENTRYPOINT = { + fn: Component, + params: [{}], +}; + +``` + +## Code + +```javascript +import { unstable_useMemoCache as useMemoCache } from "react"; +function Component(props) { + const $ = useMemoCache(2); + let t0; + if ($[0] === Symbol.for("react.memo_cache_sentinel")) { + t0 = () => { + try { + return []; + } catch (t1) { + return; + } + }; + $[0] = t0; + } else { + t0 = $[0]; + } + const callback = t0; + let t1; + if ($[1] === Symbol.for("react.memo_cache_sentinel")) { + t1 = callback(); + $[1] = t1; + } else { + t1 = $[1]; + } + return t1; +} + +export const FIXTURE_ENTRYPOINT = { + fn: Component, + params: [{}], +}; + +``` + +### Eval output +(kind: ok) [] \ No newline at end of file diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.todo-try-catch-within-function-expression.js b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/try-catch-within-function-expression.js similarity index 66% rename from compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.todo-try-catch-within-function-expression.js rename to compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/try-catch-within-function-expression.js index 69c394c826..bd1acf10ff 100644 --- a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.todo-try-catch-within-function-expression.js +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/try-catch-within-function-expression.js @@ -8,3 +8,8 @@ function Component(props) { }; return callback(); } + +export const FIXTURE_ENTRYPOINT = { + fn: Component, + params: [{}], +}; diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/try-catch-within-object-method-returns-caught-value.expect.md b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/try-catch-within-object-method-returns-caught-value.expect.md new file mode 100644 index 0000000000..22a73a2b9f --- /dev/null +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/try-catch-within-object-method-returns-caught-value.expect.md @@ -0,0 +1,65 @@ + +## Input + +```javascript +import { throwInput } from "shared-runtime"; + +function Component(props) { + const object = { + foo() { + try { + throwInput([props.value]); + } catch (e) { + return e; + } + }, + }; + return object.foo(); +} + +export const FIXTURE_ENTRYPOINT = { + fn: Component, + params: [{ value: 42 }], +}; + +``` + +## Code + +```javascript +import { unstable_useMemoCache as useMemoCache } from "react"; +import { throwInput } from "shared-runtime"; + +function Component(props) { + const $ = useMemoCache(2); + let t0; + if ($[0] !== props.value) { + const object = { + foo() { + try { + throwInput([props.value]); + } catch (t1) { + const e = t1; + return e; + } + }, + }; + + t0 = object.foo(); + $[0] = props.value; + $[1] = t0; + } else { + t0 = $[1]; + } + return t0; +} + +export const FIXTURE_ENTRYPOINT = { + fn: Component, + params: [{ value: 42 }], +}; + +``` + +### Eval output +(kind: ok) [42] \ No newline at end of file diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/try-catch-within-object-method-returns-caught-value.js b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/try-catch-within-object-method-returns-caught-value.js new file mode 100644 index 0000000000..acc2f376a9 --- /dev/null +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/try-catch-within-object-method-returns-caught-value.js @@ -0,0 +1,19 @@ +import { throwInput } from "shared-runtime"; + +function Component(props) { + const object = { + foo() { + try { + throwInput([props.value]); + } catch (e) { + return e; + } + }, + }; + return object.foo(); +} + +export const FIXTURE_ENTRYPOINT = { + fn: Component, + params: [{ value: 42 }], +}; diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/try-catch-within-object-method.expect.md b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/try-catch-within-object-method.expect.md new file mode 100644 index 0000000000..382399c8a4 --- /dev/null +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/try-catch-within-object-method.expect.md @@ -0,0 +1,59 @@ + +## Input + +```javascript +function Component(props) { + const object = { + foo() { + try { + return []; + } catch (e) { + return; + } + }, + }; + return object.foo(); +} + +export const FIXTURE_ENTRYPOINT = { + fn: Component, + params: [{}], +}; + +``` + +## Code + +```javascript +import { unstable_useMemoCache as useMemoCache } from "react"; +function Component(props) { + const $ = useMemoCache(1); + let t0; + if ($[0] === Symbol.for("react.memo_cache_sentinel")) { + const object = { + foo() { + try { + return []; + } catch (t1) { + return; + } + }, + }; + + t0 = object.foo(); + $[0] = t0; + } else { + t0 = $[0]; + } + return t0; +} + +export const FIXTURE_ENTRYPOINT = { + fn: Component, + params: [{}], +}; + +``` + +### Eval output +(kind: ok) [] \ No newline at end of file diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/try-catch-within-object-method.js b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/try-catch-within-object-method.js new file mode 100644 index 0000000000..d2e95e6080 --- /dev/null +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/try-catch-within-object-method.js @@ -0,0 +1,17 @@ +function Component(props) { + const object = { + foo() { + try { + return []; + } catch (e) { + return; + } + }, + }; + return object.foo(); +} + +export const FIXTURE_ENTRYPOINT = { + fn: Component, + params: [{}], +};