diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/try-catch-mutate-outer-value.expect.md b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/try-catch-mutate-outer-value.expect.md index 0feb08976e..cb9823c3a2 100644 --- a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/try-catch-mutate-outer-value.expect.md +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/try-catch-mutate-outer-value.expect.md @@ -2,52 +2,70 @@ ## Input ```javascript +const { shallowCopy, throwErrorWithMessage } = require("shared-runtime"); + function Component(props) { const x = []; try { - x.push(foo()); + x.push(throwErrorWithMessage("oops")); } catch { - x.push(bar()); + x.push(shallowCopy({ a: props.a })); } return x; } +export const FIXTURE_ENTRYPOINT = { + fn: Component, + params: [{ a: 1 }], +}; + ``` ## Code ```javascript import { unstable_useMemoCache as useMemoCache } from "react"; +const { shallowCopy, throwErrorWithMessage } = require("shared-runtime"); + function Component(props) { - const $ = useMemoCache(3); + const $ = useMemoCache(5); + const c_0 = $[0] !== props.a; let x; - if ($[0] === Symbol.for("react.memo_cache_sentinel")) { + if (c_0) { x = []; try { let t0; - if ($[1] === Symbol.for("react.memo_cache_sentinel")) { - t0 = foo(); - $[1] = t0; + if ($[2] === Symbol.for("react.memo_cache_sentinel")) { + t0 = throwErrorWithMessage("oops"); + $[2] = t0; } else { - t0 = $[1]; + t0 = $[2]; } x.push(t0); } catch { + const c_3 = $[3] !== props.a; let t1; - if ($[2] === Symbol.for("react.memo_cache_sentinel")) { - t1 = bar(); - $[2] = t1; + if (c_3) { + t1 = shallowCopy({ a: props.a }); + $[3] = props.a; + $[4] = t1; } else { - t1 = $[2]; + t1 = $[4]; } x.push(t1); } - $[0] = x; + $[0] = props.a; + $[1] = x; } else { - x = $[0]; + x = $[1]; } return x; } +export const FIXTURE_ENTRYPOINT = { + fn: Component, + params: [{ a: 1 }], +}; + ``` \ No newline at end of file diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/try-catch-mutate-outer-value.js b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/try-catch-mutate-outer-value.js index 813dea5736..984042470d 100644 --- a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/try-catch-mutate-outer-value.js +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/try-catch-mutate-outer-value.js @@ -1,9 +1,16 @@ +const { shallowCopy, throwErrorWithMessage } = require("shared-runtime"); + function Component(props) { const x = []; try { - x.push(foo()); + x.push(throwErrorWithMessage("oops")); } catch { - x.push(bar()); + x.push(shallowCopy({ a: props.a })); } return x; } + +export const FIXTURE_ENTRYPOINT = { + fn: Component, + params: [{ a: 1 }], +}; diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/try-catch-with-catch-param.expect.md b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/try-catch-with-catch-param.expect.md index cc881c39b1..033bf885ce 100644 --- a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/try-catch-with-catch-param.expect.md +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/try-catch-with-catch-param.expect.md @@ -2,11 +2,13 @@ ## Input ```javascript +const { throwInput } = require("shared-runtime"); + function Component(props) { let x = []; try { // foo could throw its argument... - foo(x); + throwInput(x); } catch (e) { // ... in which case this could be mutating `x`! e.push(null); @@ -15,19 +17,26 @@ function Component(props) { return x; } +export const FIXTURE_ENTRYPOINT = { + fn: Component, + params: [{}], +}; + ``` ## Code ```javascript import { unstable_useMemoCache as useMemoCache } from "react"; +const { throwInput } = require("shared-runtime"); + function Component(props) { const $ = useMemoCache(1); let x; if ($[0] === Symbol.for("react.memo_cache_sentinel")) { x = []; try { - foo(x); + throwInput(x); } catch (t22) { const e = t22; @@ -41,5 +50,10 @@ function Component(props) { return x; } +export const FIXTURE_ENTRYPOINT = { + fn: Component, + params: [{}], +}; + ``` \ No newline at end of file diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/try-catch-with-catch-param.js b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/try-catch-with-catch-param.js index cdaf1fe0fb..9508694f96 100644 --- a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/try-catch-with-catch-param.js +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/try-catch-with-catch-param.js @@ -1,8 +1,10 @@ +const { throwInput } = require("shared-runtime"); + function Component(props) { let x = []; try { // foo could throw its argument... - foo(x); + throwInput(x); } catch (e) { // ... in which case this could be mutating `x`! e.push(null); @@ -10,3 +12,8 @@ function Component(props) { } return x; } + +export const FIXTURE_ENTRYPOINT = { + fn: Component, + params: [{}], +}; diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/try-catch-with-return.expect.md b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/try-catch-with-return.expect.md index c4efbbd002..b8ec724418 100644 --- a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/try-catch-with-return.expect.md +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/try-catch-with-return.expect.md @@ -2,39 +2,49 @@ ## Input ```javascript +const { shallowCopy, throwInput } = require("shared-runtime"); + // @debug function Component(props) { let x = []; try { - const y = foo(); + const y = shallowCopy({}); if (y == null) { return; } - x.push(bar(y)); + x.push(throwInput(y)); } catch { return null; } return x; } +export const FIXTURE_ENTRYPOINT = { + fn: Component, + params: [{}], +}; + ``` ## Code ```javascript -import { unstable_useMemoCache as useMemoCache } from "react"; // @debug +import { unstable_useMemoCache as useMemoCache } from "react"; +const { shallowCopy, throwInput } = require("shared-runtime"); + +// @debug function Component(props) { const $ = useMemoCache(1); let x; if ($[0] === Symbol.for("react.memo_cache_sentinel")) { x = []; try { - const y = foo(); + const y = shallowCopy({}); if (y == null) { return; } - x.push(bar(y)); + x.push(throwInput(y)); } catch { return null; } @@ -45,5 +55,10 @@ function Component(props) { return x; } +export const FIXTURE_ENTRYPOINT = { + fn: Component, + params: [{}], +}; + ``` \ No newline at end of file diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/try-catch-with-return.js b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/try-catch-with-return.js index 5014f6fefa..056a770e7c 100644 --- a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/try-catch-with-return.js +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/try-catch-with-return.js @@ -1,14 +1,21 @@ +const { shallowCopy, throwInput } = require("shared-runtime"); + // @debug function Component(props) { let x = []; try { - const y = foo(); + const y = shallowCopy({}); if (y == null) { return; } - x.push(bar(y)); + x.push(throwInput(y)); } catch { return null; } return x; } + +export const FIXTURE_ENTRYPOINT = { + fn: Component, + params: [{}], +}; diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/try-catch-within-mutable-range.expect.md b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/try-catch-within-mutable-range.expect.md index d6cf282c57..531b782f72 100644 --- a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/try-catch-within-mutable-range.expect.md +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/try-catch-within-mutable-range.expect.md @@ -2,23 +2,32 @@ ## Input ```javascript +const { throwErrorWithMessage, shallowCopy } = require("shared-runtime"); + function Component(props) { const x = []; try { - x.push(foo()); + x.push(throwErrorWithMessage("oops")); } catch { - x.push(bar()); + x.push(shallowCopy({})); } x.push(props.value); // extend the mutable range to include the try/catch return x; } +export const FIXTURE_ENTRYPOINT = { + fn: Component, + params: [{}], +}; + ``` ## Code ```javascript import { unstable_useMemoCache as useMemoCache } from "react"; +const { throwErrorWithMessage, shallowCopy } = require("shared-runtime"); + function Component(props) { const $ = useMemoCache(4); const c_0 = $[0] !== props.value; @@ -28,7 +37,7 @@ function Component(props) { try { let t0; if ($[2] === Symbol.for("react.memo_cache_sentinel")) { - t0 = foo(); + t0 = throwErrorWithMessage("oops"); $[2] = t0; } else { t0 = $[2]; @@ -37,7 +46,7 @@ function Component(props) { } catch { let t1; if ($[3] === Symbol.for("react.memo_cache_sentinel")) { - t1 = bar(); + t1 = shallowCopy({}); $[3] = t1; } else { t1 = $[3]; @@ -54,5 +63,10 @@ function Component(props) { return x; } +export const FIXTURE_ENTRYPOINT = { + fn: Component, + params: [{}], +}; + ``` \ No newline at end of file diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/try-catch-within-mutable-range.js b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/try-catch-within-mutable-range.js index 665d395a94..f6b971b75d 100644 --- a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/try-catch-within-mutable-range.js +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/try-catch-within-mutable-range.js @@ -1,10 +1,17 @@ +const { throwErrorWithMessage, shallowCopy } = require("shared-runtime"); + function Component(props) { const x = []; try { - x.push(foo()); + x.push(throwErrorWithMessage("oops")); } catch { - x.push(bar()); + x.push(shallowCopy({})); } x.push(props.value); // extend the mutable range to include the try/catch return x; } + +export const FIXTURE_ENTRYPOINT = { + fn: Component, + params: [{}], +}; diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/try-catch.expect.md b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/try-catch.expect.md index c22421c742..8be44e9a7c 100644 --- a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/try-catch.expect.md +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/try-catch.expect.md @@ -2,29 +2,38 @@ ## Input ```javascript +const { throwErrorWithMessage } = require("shared-runtime"); + function Component(props) { let x; try { - x = foo(); + x = throwErrorWithMessage("oops"); } catch { x = null; } return x; } +export const FIXTURE_ENTRYPOINT = { + fn: Component, + params: [{}], +}; + ``` ## Code ```javascript import { unstable_useMemoCache as useMemoCache } from "react"; +const { throwErrorWithMessage } = require("shared-runtime"); + function Component(props) { const $ = useMemoCache(1); let x = undefined; try { let t0; if ($[0] === Symbol.for("react.memo_cache_sentinel")) { - t0 = foo(); + t0 = throwErrorWithMessage("oops"); $[0] = t0; } else { t0 = $[0]; @@ -36,5 +45,10 @@ function Component(props) { return x; } +export const FIXTURE_ENTRYPOINT = { + fn: Component, + params: [{}], +}; + ``` \ No newline at end of file diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/try-catch.js b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/try-catch.js index d729c28bf9..89af9ee95f 100644 --- a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/try-catch.js +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/try-catch.js @@ -1,9 +1,16 @@ +const { throwErrorWithMessage } = require("shared-runtime"); + function Component(props) { let x; try { - x = foo(); + x = throwErrorWithMessage("oops"); } catch { x = null; } return x; } + +export const FIXTURE_ENTRYPOINT = { + fn: Component, + params: [{}], +}; diff --git a/compiler/packages/sprout/src/SproutTodoFilter.ts b/compiler/packages/sprout/src/SproutTodoFilter.ts index 5206dd62cb..1f4d4fb2d4 100644 --- a/compiler/packages/sprout/src/SproutTodoFilter.ts +++ b/compiler/packages/sprout/src/SproutTodoFilter.ts @@ -412,11 +412,6 @@ const skipFilter = new Set([ "fbt-call-complex-param-value", "fbt-template-string-same-scope", "component-declaration-basic.flow", - "try-catch-mutate-outer-value", - "try-catch-within-mutable-range", - "try-catch", - "try-catch-with-return", - "try-catch-with-catch-param", // TODO: 🌲 "forest-basic", diff --git a/compiler/packages/sprout/src/shared-runtime.ts b/compiler/packages/sprout/src/shared-runtime.ts index c62335a454..57a092d16c 100644 --- a/compiler/packages/sprout/src/shared-runtime.ts +++ b/compiler/packages/sprout/src/shared-runtime.ts @@ -73,6 +73,14 @@ export function sum(...args: Array): number { return args.reduce((result, arg) => result + arg, 0); } +export function throwErrorWithMessage(message: string): never { + throw new Error(message); +} + +export function throwInput(x: Object): never { + throw x; +} + /** * React Components */