diff --git a/compiler/packages/babel-plugin-react-forget/src/HIR/HIRBuilder.ts b/compiler/packages/babel-plugin-react-forget/src/HIR/HIRBuilder.ts index 1246a68c82..d70eda0887 100644 --- a/compiler/packages/babel-plugin-react-forget/src/HIR/HIRBuilder.ts +++ b/compiler/packages/babel-plugin-react-forget/src/HIR/HIRBuilder.ts @@ -517,7 +517,11 @@ export default class HIRBuilder { lookupBreak(label: string | null): BlockId { for (let ii = this.#scopes.length - 1; ii >= 0; ii--) { const scope = this.#scopes[ii]; - if (label === null || label === scope.label) { + if ( + (label === null && + (scope.kind === "loop" || scope.kind === "switch")) || + label === scope.label + ) { return scope.breakBlock; } } diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/bug-unlabeled-break-within-label-loop.expect.md b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/labeled-break-within-label-loop.expect.md similarity index 90% rename from compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/bug-unlabeled-break-within-label-loop.expect.md rename to compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/labeled-break-within-label-loop.expect.md index 8348b32036..52a04577fc 100644 --- a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/bug-unlabeled-break-within-label-loop.expect.md +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/labeled-break-within-label-loop.expect.md @@ -8,7 +8,7 @@ function useHook(end) { log.push(`${i} @A`); bb0: { if (i === end) { - break; + break bb0; } log.push(`${i} @B`); } @@ -59,4 +59,6 @@ export const FIXTURE_ENTRYPOINT = { }; ``` - \ No newline at end of file + +### Eval output +(kind: ok) ["0 @A","0 @B","0 @C","1 @A","1 @C"] \ No newline at end of file diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/labeled-break-within-label-loop.ts b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/labeled-break-within-label-loop.ts new file mode 100644 index 0000000000..481f3e2a5d --- /dev/null +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/labeled-break-within-label-loop.ts @@ -0,0 +1,19 @@ +function useHook(end) { + const log = []; + for (let i = 0; i < end + 1; i++) { + log.push(`${i} @A`); + bb0: { + if (i === end) { + break bb0; + } + log.push(`${i} @B`); + } + log.push(`${i} @C`); + } + return log; +} + +export const FIXTURE_ENTRYPOINT = { + fn: useHook, + params: [1], +}; diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/labeled-break-within-label-switch.expect.md b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/labeled-break-within-label-switch.expect.md new file mode 100644 index 0000000000..a18a31cebd --- /dev/null +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/labeled-break-within-label-switch.expect.md @@ -0,0 +1,71 @@ + +## Input + +```javascript +import { CONST_STRING0 } from "shared-runtime"; + +function useHook(cond) { + const log = []; + switch (CONST_STRING0) { + case CONST_STRING0: + log.push(`@A`); + bb0: { + if (cond) { + break bb0; + } + log.push(`@B`); + } + log.push(`@C`); + } + return log; +} + +export const FIXTURE_ENTRYPOINT = { + fn: useHook, + params: [true], +}; + +``` + +## Code + +```javascript +import { unstable_useMemoCache as useMemoCache } from "react"; +import { CONST_STRING0 } from "shared-runtime"; + +function useHook(cond) { + const $ = useMemoCache(2); + let log; + if ($[0] !== cond) { + log = []; + switch (CONST_STRING0) { + case CONST_STRING0: { + log.push(`@A`); + bb3: { + if (cond) { + break bb3; + } + + log.push(`@B`); + } + + log.push(`@C`); + } + } + $[0] = cond; + $[1] = log; + } else { + log = $[1]; + } + return log; +} + +export const FIXTURE_ENTRYPOINT = { + fn: useHook, + params: [true], +}; + +``` + +### Eval output +(kind: ok) ["@A","@C"] \ No newline at end of file diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/labeled-break-within-label-switch.ts b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/labeled-break-within-label-switch.ts new file mode 100644 index 0000000000..fb3f04dda4 --- /dev/null +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/labeled-break-within-label-switch.ts @@ -0,0 +1,22 @@ +import { CONST_STRING0 } from "shared-runtime"; + +function useHook(cond) { + const log = []; + switch (CONST_STRING0) { + case CONST_STRING0: + log.push(`@A`); + bb0: { + if (cond) { + break bb0; + } + log.push(`@B`); + } + log.push(`@C`); + } + return log; +} + +export const FIXTURE_ENTRYPOINT = { + fn: useHook, + params: [true], +}; diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/unlabeled-break-within-label-loop.expect.md b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/unlabeled-break-within-label-loop.expect.md new file mode 100644 index 0000000000..5f6d9f985b --- /dev/null +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/unlabeled-break-within-label-loop.expect.md @@ -0,0 +1,62 @@ + +## Input + +```javascript +function useHook(end) { + const log = []; + for (let i = 0; i < end + 1; i++) { + log.push(`${i} @A`); + bb0: { + if (i === end) { + break; + } + log.push(`${i} @B`); + } + log.push(`${i} @C`); + } + return log; +} + +export const FIXTURE_ENTRYPOINT = { + fn: useHook, + params: [1], +}; + +``` + +## Code + +```javascript +import { unstable_useMemoCache as useMemoCache } from "react"; +function useHook(end) { + const $ = useMemoCache(2); + let log; + if ($[0] !== end) { + log = []; + for (let i = 0; i < end + 1; i++) { + log.push(`${i} @A`); + if (i === end) { + break; + } + + log.push(`${i} @B`); + + log.push(`${i} @C`); + } + $[0] = end; + $[1] = log; + } else { + log = $[1]; + } + return log; +} + +export const FIXTURE_ENTRYPOINT = { + fn: useHook, + params: [1], +}; + +``` + +### Eval output +(kind: ok) ["0 @A","0 @B","0 @C","1 @A"] \ No newline at end of file diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/bug-unlabeled-break-within-label-loop.ts b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/unlabeled-break-within-label-loop.ts similarity index 100% rename from compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/bug-unlabeled-break-within-label-loop.ts rename to compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/unlabeled-break-within-label-loop.ts diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/unlabeled-break-within-label-switch.expect.md b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/unlabeled-break-within-label-switch.expect.md new file mode 100644 index 0000000000..7ff261158c --- /dev/null +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/unlabeled-break-within-label-switch.expect.md @@ -0,0 +1,69 @@ + +## Input + +```javascript +import { CONST_STRING0 } from "shared-runtime"; + +function useHook(cond) { + const log = []; + switch (CONST_STRING0) { + case CONST_STRING0: + log.push(`@A`); + bb0: { + if (cond) { + break; + } + log.push(`@B`); + } + log.push(`@C`); + } + return log; +} + +export const FIXTURE_ENTRYPOINT = { + fn: useHook, + params: [true], +}; + +``` + +## Code + +```javascript +import { unstable_useMemoCache as useMemoCache } from "react"; +import { CONST_STRING0 } from "shared-runtime"; + +function useHook(cond) { + const $ = useMemoCache(2); + let log; + if ($[0] !== cond) { + log = []; + bb1: switch (CONST_STRING0) { + case CONST_STRING0: { + log.push(`@A`); + if (cond) { + break bb1; + } + + log.push(`@B`); + + log.push(`@C`); + } + } + $[0] = cond; + $[1] = log; + } else { + log = $[1]; + } + return log; +} + +export const FIXTURE_ENTRYPOINT = { + fn: useHook, + params: [true], +}; + +``` + +### Eval output +(kind: ok) ["@A"] \ No newline at end of file diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/unlabeled-break-within-label-switch.ts b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/unlabeled-break-within-label-switch.ts new file mode 100644 index 0000000000..90fd35ce2f --- /dev/null +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/unlabeled-break-within-label-switch.ts @@ -0,0 +1,22 @@ +import { CONST_STRING0 } from "shared-runtime"; + +function useHook(cond) { + const log = []; + switch (CONST_STRING0) { + case CONST_STRING0: + log.push(`@A`); + bb0: { + if (cond) { + break; + } + log.push(`@B`); + } + log.push(`@C`); + } + return log; +} + +export const FIXTURE_ENTRYPOINT = { + fn: useHook, + params: [true], +}; diff --git a/compiler/packages/snap/src/SproutTodoFilter.ts b/compiler/packages/snap/src/SproutTodoFilter.ts index f956fe10bf..fef339c363 100644 --- a/compiler/packages/snap/src/SproutTodoFilter.ts +++ b/compiler/packages/snap/src/SproutTodoFilter.ts @@ -534,7 +534,6 @@ const skipFilter = new Set([ // bugs "bug-reduce-reactive-deps-return-in-scope", "bug-reduce-reactive-deps-break-in-scope", - "bug-unlabeled-break-within-label-loop", // 'react-forget-runtime' not yet supported "flag-enable-emit-hook-guards",