diff --git a/compiler/packages/babel-plugin-react-forget/src/HIR/MergeConsecutiveBlocks.ts b/compiler/packages/babel-plugin-react-forget/src/HIR/MergeConsecutiveBlocks.ts index b8513f0abb..f965f96d2c 100644 --- a/compiler/packages/babel-plugin-react-forget/src/HIR/MergeConsecutiveBlocks.ts +++ b/compiler/packages/babel-plugin-react-forget/src/HIR/MergeConsecutiveBlocks.ts @@ -14,7 +14,7 @@ import { Instruction, } from "./HIR"; import { markPredecessors, removeUnreachableFallthroughs } from "./HIRBuilder"; -import { mapOptionalFallthroughs } from "./visitors"; +import { mapOptionalFallthroughs, terminalFallthrough } from "./visitors"; /* * Merges sequences of blocks that will always execute consecutively — @@ -30,7 +30,13 @@ import { mapOptionalFallthroughs } from "./visitors"; */ export function mergeConsecutiveBlocks(fn: HIRFunction): void { const merged = new MergedBlocks(); + const fallthroughBlocks = new Set(); for (const [, block] of fn.body.blocks) { + const fallthrough = terminalFallthrough(block.terminal); + if (fallthrough !== null) { + fallthroughBlocks.add(fallthrough); + } + for (const instr of block.instructions) { if ( instr.value.kind === "FunctionExpression" || @@ -40,11 +46,14 @@ export function mergeConsecutiveBlocks(fn: HIRFunction): void { } } - /* - * Can only merge blocks with a single predecessor, can't merge - * value blocks - */ - if (block.kind !== "block" || block.preds.size !== 1) { + if ( + // Can only merge blocks with a single predecessor + block.preds.size !== 1 || + // Value blocks cannot merge + block.kind !== "block" || + // Merging across fallthroughs could move the predecessor out of its block scope + fallthroughBlocks.has(block.id) + ) { continue; } const originalPredecessorId = Array.from(block.preds)[0]!; diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/block-scoping-switch-dead-code.expect.md b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/block-scoping-switch-dead-code.expect.md index cdf6d2d1a3..11ccbe00d8 100644 --- a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/block-scoping-switch-dead-code.expect.md +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/block-scoping-switch-dead-code.expect.md @@ -28,11 +28,14 @@ export const FIXTURE_ENTRYPOINT = { ```javascript function useHook(a, b) { - switch (a) { + bb1: switch (a) { case 1: { if (b == null) { return; } + + console.log(b); + break bb1; } case 2: { return; @@ -41,8 +44,6 @@ function useHook(a, b) { return; } } - - console.log(b); } export const FIXTURE_ENTRYPOINT = { @@ -51,4 +52,7 @@ export const FIXTURE_ENTRYPOINT = { }; ``` - \ No newline at end of file + +### Eval output +(kind: ok) +logs: ['foo'] \ No newline at end of file diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/block-scoping-switch-variable-scoping.expect.md b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/block-scoping-switch-variable-scoping.expect.md index 0a2ccb8457..6b77b6bf00 100644 --- a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/block-scoping-switch-variable-scoping.expect.md +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/block-scoping-switch-variable-scoping.expect.md @@ -35,23 +35,21 @@ import { useMemo, unstable_useMemoCache as useMemoCache } from "react"; function Component(props) { const $ = useMemoCache(2); let t22; - bb2: { - let t0; - if ($[0] !== props.value) { - t0 = { value: props.value }; - $[0] = props.value; - $[1] = t0; - } else { - t0 = $[1]; + let t0; + if ($[0] !== props.value) { + t0 = { value: props.value }; + $[0] = props.value; + $[1] = t0; + } else { + t0 = $[1]; + } + const handlers = t0; + bb2: switch (props.test) { + case true: { + console.log(handlers.value); + break bb2; } - const handlers = t0; - switch (props.test) { - case true: { - console.log(handlers.value); - break bb2; - } - default: { - } + default: { } } @@ -68,10 +66,5 @@ export const FIXTURE_ENTRYPOINT = { ``` ### Eval output -(kind: exception) handlers.foo is not a function -logs: ['The above error occurred in the component:\n' + - '\n' + - ' at WrapperTestComponent (/packages/sprout/dist/runner-evaluator.js:55:26)\n' + - '\n' + - 'Consider adding an error boundary to your tree to customize error handling behavior.\n' + - 'Visit https://reactjs.org/link/error-boundaries to learn more about error boundaries.'] \ No newline at end of file +(kind: ok) {"value":"hello"} +logs: ['hello'] \ No newline at end of file diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/early-return-no-declarations-reassignments-dependencies.expect.md b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/early-return-no-declarations-reassignments-dependencies.expect.md index 605eef8484..2860f89861 100644 --- a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/early-return-no-declarations-reassignments-dependencies.expect.md +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/early-return-no-declarations-reassignments-dependencies.expect.md @@ -79,6 +79,8 @@ function Component(props) { x.push(42); t37 = x; break bb8; + } else { + console.log("fallthrough"); } } $[0] = t37; @@ -88,8 +90,6 @@ function Component(props) { if (t37 !== Symbol.for("react.early_return_sentinel")) { return t37; } - - console.log("fallthrough"); let t0; if ($[1] !== props.a) { t0 = makeArray(props.a); diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/useMemo-inverted-if.expect.md b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/useMemo-inverted-if.expect.md index 072774afc5..38a3a09b08 100644 --- a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/useMemo-inverted-if.expect.md +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/useMemo-inverted-if.expect.md @@ -29,9 +29,9 @@ export const FIXTURE_ENTRYPOINT = { function Component(props) { let t16; bb10: { - bb5: { + bb2: { if (props.cond) { - break bb5; + break bb2; } t16 = props.a; diff --git a/compiler/packages/sprout/src/SproutTodoFilter.ts b/compiler/packages/sprout/src/SproutTodoFilter.ts index 734dd9f435..a2d94fbb12 100644 --- a/compiler/packages/sprout/src/SproutTodoFilter.ts +++ b/compiler/packages/sprout/src/SproutTodoFilter.ts @@ -6,6 +6,11 @@ */ const skipFilter = new Set([ + /** + * Observable different in logging between Forget and non-Forget + */ + "early-return-no-declarations-reassignments-dependencies", + /** * Category A: * Tests with 0 parameters and 0 refs to external values @@ -517,9 +522,6 @@ const skipFilter = new Set([ "bug-invalid-code-when-bailout", "component-syntax-ref-gating.flow", - "block-scoping-switch-dead-code", - "block-scoping-switch-variable-scoping", - // 'react-forget-runtime' not yet supported "flag-enable-emit-hook-guards", ]);