diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reactive-control-dependency-from-interleaved-reactivity-do-while.expect.md b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reactive-control-dependency-from-interleaved-reactivity-do-while.expect.md new file mode 100644 index 0000000000..4ba809a783 --- /dev/null +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reactive-control-dependency-from-interleaved-reactivity-do-while.expect.md @@ -0,0 +1,73 @@ + +## Input + +```javascript +function Component(props) { + // a and b are independent but their mutations are interleaved, so + // they get grouped in a reactive scope. this means that a becomes + // reactive since it will effectively re-evaluate based on a reactive + // input + const a = []; + const b = []; + b.push(props.cond); + a.push(false); + + // Downstream consumer of a, which initially seems non-reactive except + // that a becomes reactive, per above + const c = [a]; + + let x = 0; + do { + x += 1; + } while (c[0][0]); + // The values assigned to `x` are non-reactive, but the value of `x` + // depends on the "control" value `c[0]` which becomes reactive via + // being interleaved with `b`. + // Therefore x should be treated as reactive too. + return [x]; +} + +export const FIXTURE_ENTRYPOINT = { + fn: Component, + params: [{ cond: true }], +}; + +``` + +## Code + +```javascript +import { unstable_useMemoCache as useMemoCache } from "react"; +function Component(props) { + const $ = useMemoCache(1); + + const a = []; + const b = []; + b.push(props.cond); + a.push(false); + + const c = [a]; + + let x = 0; + do { + x = x + 1; + } while (c[0][0]); + let t0; + if ($[0] === Symbol.for("react.memo_cache_sentinel")) { + t0 = [x]; + $[0] = t0; + } else { + t0 = $[0]; + } + return t0; +} + +export const FIXTURE_ENTRYPOINT = { + fn: Component, + params: [{ cond: true }], +}; + +``` + +### Eval output +(kind: ok) [1] \ No newline at end of file diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reactive-control-dependency-from-interleaved-reactivity-do-while.js b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reactive-control-dependency-from-interleaved-reactivity-do-while.js new file mode 100644 index 0000000000..0ba3dddd26 --- /dev/null +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reactive-control-dependency-from-interleaved-reactivity-do-while.js @@ -0,0 +1,29 @@ +function Component(props) { + // a and b are independent but their mutations are interleaved, so + // they get grouped in a reactive scope. this means that a becomes + // reactive since it will effectively re-evaluate based on a reactive + // input + const a = []; + const b = []; + b.push(props.cond); + a.push(false); + + // Downstream consumer of a, which initially seems non-reactive except + // that a becomes reactive, per above + const c = [a]; + + let x = 0; + do { + x += 1; + } while (c[0][0]); + // The values assigned to `x` are non-reactive, but the value of `x` + // depends on the "control" value `c[0]` which becomes reactive via + // being interleaved with `b`. + // Therefore x should be treated as reactive too. + return [x]; +} + +export const FIXTURE_ENTRYPOINT = { + fn: Component, + params: [{ cond: true }], +}; diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reactive-control-dependency-from-interleaved-reactivity-for-in.expect.md b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reactive-control-dependency-from-interleaved-reactivity-for-in.expect.md new file mode 100644 index 0000000000..7adc4dff16 --- /dev/null +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reactive-control-dependency-from-interleaved-reactivity-for-in.expect.md @@ -0,0 +1,73 @@ + +## Input + +```javascript +function Component(props) { + // a and b are independent but their mutations are interleaved, so + // they get grouped in a reactive scope. this means that a becomes + // reactive since it will effectively re-evaluate based on a reactive + // input + const a = []; + const b = []; + b.push(props.cond); + a.push({ a: false }); + + // Downstream consumer of a, which initially seems non-reactive except + // that a becomes reactive, per above + const c = [a]; + + let x; + for (const i in c[0][0]) { + x = 1; + } + // The values assigned to `x` are non-reactive, but the value of `x` + // depends on the "control" value `c[0]` which becomes reactive via + // being interleaved with `b`. + // Therefore x should be treated as reactive too. + return [x]; +} + +export const FIXTURE_ENTRYPOINT = { + fn: Component, + params: [{ cond: true }], +}; + +``` + +## Code + +```javascript +import { unstable_useMemoCache as useMemoCache } from "react"; +function Component(props) { + const $ = useMemoCache(1); + + const a = []; + const b = []; + b.push(props.cond); + a.push({ a: false }); + + const c = [a]; + + let x; + for (const i in c[0][0]) { + x = 1; + } + let t0; + if ($[0] === Symbol.for("react.memo_cache_sentinel")) { + t0 = [x]; + $[0] = t0; + } else { + t0 = $[0]; + } + return t0; +} + +export const FIXTURE_ENTRYPOINT = { + fn: Component, + params: [{ cond: true }], +}; + +``` + +### Eval output +(kind: ok) [1] \ No newline at end of file diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reactive-control-dependency-from-interleaved-reactivity-for-in.js b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reactive-control-dependency-from-interleaved-reactivity-for-in.js new file mode 100644 index 0000000000..16bfc628c6 --- /dev/null +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reactive-control-dependency-from-interleaved-reactivity-for-in.js @@ -0,0 +1,29 @@ +function Component(props) { + // a and b are independent but their mutations are interleaved, so + // they get grouped in a reactive scope. this means that a becomes + // reactive since it will effectively re-evaluate based on a reactive + // input + const a = []; + const b = []; + b.push(props.cond); + a.push({ a: false }); + + // Downstream consumer of a, which initially seems non-reactive except + // that a becomes reactive, per above + const c = [a]; + + let x; + for (const i in c[0][0]) { + x = 1; + } + // The values assigned to `x` are non-reactive, but the value of `x` + // depends on the "control" value `c[0]` which becomes reactive via + // being interleaved with `b`. + // Therefore x should be treated as reactive too. + return [x]; +} + +export const FIXTURE_ENTRYPOINT = { + fn: Component, + params: [{ cond: true }], +}; diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reactive-control-dependency-from-interleaved-reactivity-for-init.expect.md b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reactive-control-dependency-from-interleaved-reactivity-for-init.expect.md new file mode 100644 index 0000000000..696bb920a2 --- /dev/null +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reactive-control-dependency-from-interleaved-reactivity-for-init.expect.md @@ -0,0 +1,73 @@ + +## Input + +```javascript +function Component(props) { + // a and b are independent but their mutations are interleaved, so + // they get grouped in a reactive scope. this means that a becomes + // reactive since it will effectively re-evaluate based on a reactive + // input + const a = []; + const b = []; + b.push(props.cond); + a.push(0); + + // Downstream consumer of a, which initially seems non-reactive except + // that a becomes reactive, per above + const c = [a]; + + let x; + for (let i = c[0][0]; i < 10; i++) { + x = 1; + } + // The values assigned to `x` are non-reactive, but the value of `x` + // depends on the "control" value `c[0]` which becomes reactive via + // being interleaved with `b`. + // Therefore x should be treated as reactive too. + return [x]; +} + +export const FIXTURE_ENTRYPOINT = { + fn: Component, + params: [{ cond: true }], +}; + +``` + +## Code + +```javascript +import { unstable_useMemoCache as useMemoCache } from "react"; +function Component(props) { + const $ = useMemoCache(1); + + const a = []; + const b = []; + b.push(props.cond); + a.push(0); + + const c = [a]; + + let x; + for (let i = c[0][0]; i < 10; i++) { + x = 1; + } + let t0; + if ($[0] === Symbol.for("react.memo_cache_sentinel")) { + t0 = [x]; + $[0] = t0; + } else { + t0 = $[0]; + } + return t0; +} + +export const FIXTURE_ENTRYPOINT = { + fn: Component, + params: [{ cond: true }], +}; + +``` + +### Eval output +(kind: ok) [1] \ No newline at end of file diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reactive-control-dependency-from-interleaved-reactivity-for-init.js b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reactive-control-dependency-from-interleaved-reactivity-for-init.js new file mode 100644 index 0000000000..0091198ef0 --- /dev/null +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reactive-control-dependency-from-interleaved-reactivity-for-init.js @@ -0,0 +1,29 @@ +function Component(props) { + // a and b are independent but their mutations are interleaved, so + // they get grouped in a reactive scope. this means that a becomes + // reactive since it will effectively re-evaluate based on a reactive + // input + const a = []; + const b = []; + b.push(props.cond); + a.push(0); + + // Downstream consumer of a, which initially seems non-reactive except + // that a becomes reactive, per above + const c = [a]; + + let x; + for (let i = c[0][0]; i < 10; i++) { + x = 1; + } + // The values assigned to `x` are non-reactive, but the value of `x` + // depends on the "control" value `c[0]` which becomes reactive via + // being interleaved with `b`. + // Therefore x should be treated as reactive too. + return [x]; +} + +export const FIXTURE_ENTRYPOINT = { + fn: Component, + params: [{ cond: true }], +}; diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reactive-control-dependency-from-interleaved-reactivity-for-of.expect.md b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reactive-control-dependency-from-interleaved-reactivity-for-of.expect.md new file mode 100644 index 0000000000..b3b231a39a --- /dev/null +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reactive-control-dependency-from-interleaved-reactivity-for-of.expect.md @@ -0,0 +1,73 @@ + +## Input + +```javascript +function Component(props) { + // a and b are independent but their mutations are interleaved, so + // they get grouped in a reactive scope. this means that a becomes + // reactive since it will effectively re-evaluate based on a reactive + // input + const a = []; + const b = []; + b.push(props.cond); + a.push(null); + + // Downstream consumer of a, which initially seems non-reactive except + // that a becomes reactive, per above + const c = [a]; + + let x; + for (const i of c[0]) { + x = 1; + } + // The values assigned to `x` are non-reactive, but the value of `x` + // depends on the "control" value `c[0]` which becomes reactive via + // being interleaved with `b`. + // Therefore x should be treated as reactive too. + return [x]; +} + +export const FIXTURE_ENTRYPOINT = { + fn: Component, + params: [{ cond: true }], +}; + +``` + +## Code + +```javascript +import { unstable_useMemoCache as useMemoCache } from "react"; +function Component(props) { + const $ = useMemoCache(1); + + const a = []; + const b = []; + b.push(props.cond); + a.push(null); + + const c = [a]; + + let x; + for (const i of c[0]) { + x = 1; + } + let t0; + if ($[0] === Symbol.for("react.memo_cache_sentinel")) { + t0 = [x]; + $[0] = t0; + } else { + t0 = $[0]; + } + return t0; +} + +export const FIXTURE_ENTRYPOINT = { + fn: Component, + params: [{ cond: true }], +}; + +``` + +### Eval output +(kind: ok) [1] \ No newline at end of file diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reactive-control-dependency-from-interleaved-reactivity-for-of.js b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reactive-control-dependency-from-interleaved-reactivity-for-of.js new file mode 100644 index 0000000000..d55fef8ff8 --- /dev/null +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reactive-control-dependency-from-interleaved-reactivity-for-of.js @@ -0,0 +1,29 @@ +function Component(props) { + // a and b are independent but their mutations are interleaved, so + // they get grouped in a reactive scope. this means that a becomes + // reactive since it will effectively re-evaluate based on a reactive + // input + const a = []; + const b = []; + b.push(props.cond); + a.push(null); + + // Downstream consumer of a, which initially seems non-reactive except + // that a becomes reactive, per above + const c = [a]; + + let x; + for (const i of c[0]) { + x = 1; + } + // The values assigned to `x` are non-reactive, but the value of `x` + // depends on the "control" value `c[0]` which becomes reactive via + // being interleaved with `b`. + // Therefore x should be treated as reactive too. + return [x]; +} + +export const FIXTURE_ENTRYPOINT = { + fn: Component, + params: [{ cond: true }], +}; diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reactive-control-dependency-from-interleaved-reactivity-for-test.expect.md b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reactive-control-dependency-from-interleaved-reactivity-for-test.expect.md new file mode 100644 index 0000000000..2467d3ef10 --- /dev/null +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reactive-control-dependency-from-interleaved-reactivity-for-test.expect.md @@ -0,0 +1,73 @@ + +## Input + +```javascript +function Component(props) { + // a and b are independent but their mutations are interleaved, so + // they get grouped in a reactive scope. this means that a becomes + // reactive since it will effectively re-evaluate based on a reactive + // input + const a = []; + const b = []; + b.push(props.cond); + a.push(10); + + // Downstream consumer of a, which initially seems non-reactive except + // that a becomes reactive, per above + const c = [a]; + + let x; + for (let i = 0; i < c[0][0]; i++) { + x = 1; + } + // The values assigned to `x` are non-reactive, but the value of `x` + // depends on the "control" value `c[0]` which becomes reactive via + // being interleaved with `b`. + // Therefore x should be treated as reactive too. + return [x]; +} + +export const FIXTURE_ENTRYPOINT = { + fn: Component, + params: [{ cond: true }], +}; + +``` + +## Code + +```javascript +import { unstable_useMemoCache as useMemoCache } from "react"; +function Component(props) { + const $ = useMemoCache(1); + + const a = []; + const b = []; + b.push(props.cond); + a.push(10); + + const c = [a]; + + let x; + for (let i = 0; i < c[0][0]; i++) { + x = 1; + } + let t0; + if ($[0] === Symbol.for("react.memo_cache_sentinel")) { + t0 = [x]; + $[0] = t0; + } else { + t0 = $[0]; + } + return t0; +} + +export const FIXTURE_ENTRYPOINT = { + fn: Component, + params: [{ cond: true }], +}; + +``` + +### Eval output +(kind: ok) [1] \ No newline at end of file diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reactive-control-dependency-from-interleaved-reactivity-for-test.js b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reactive-control-dependency-from-interleaved-reactivity-for-test.js new file mode 100644 index 0000000000..582b8c4d64 --- /dev/null +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reactive-control-dependency-from-interleaved-reactivity-for-test.js @@ -0,0 +1,29 @@ +function Component(props) { + // a and b are independent but their mutations are interleaved, so + // they get grouped in a reactive scope. this means that a becomes + // reactive since it will effectively re-evaluate based on a reactive + // input + const a = []; + const b = []; + b.push(props.cond); + a.push(10); + + // Downstream consumer of a, which initially seems non-reactive except + // that a becomes reactive, per above + const c = [a]; + + let x; + for (let i = 0; i < c[0][0]; i++) { + x = 1; + } + // The values assigned to `x` are non-reactive, but the value of `x` + // depends on the "control" value `c[0]` which becomes reactive via + // being interleaved with `b`. + // Therefore x should be treated as reactive too. + return [x]; +} + +export const FIXTURE_ENTRYPOINT = { + fn: Component, + params: [{ cond: true }], +}; diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reactive-control-dependency-from-interleaved-reactivity-for-update.expect.md b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reactive-control-dependency-from-interleaved-reactivity-for-update.expect.md new file mode 100644 index 0000000000..d529cd3a96 --- /dev/null +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reactive-control-dependency-from-interleaved-reactivity-for-update.expect.md @@ -0,0 +1,73 @@ + +## Input + +```javascript +function Component(props) { + // a and b are independent but their mutations are interleaved, so + // they get grouped in a reactive scope. this means that a becomes + // reactive since it will effectively re-evaluate based on a reactive + // input + const a = []; + const b = []; + b.push(props.cond); + a.push(10); + + // Downstream consumer of a, which initially seems non-reactive except + // that a becomes reactive, per above + const c = [a]; + + let x; + for (let i = 0; i < 10; i += c[0][0]) { + x = 1; + } + // The values assigned to `x` are non-reactive, but the value of `x` + // depends on the "control" value `c[0]` which becomes reactive via + // being interleaved with `b`. + // Therefore x should be treated as reactive too. + return [x]; +} + +export const FIXTURE_ENTRYPOINT = { + fn: Component, + params: [{ cond: true }], +}; + +``` + +## Code + +```javascript +import { unstable_useMemoCache as useMemoCache } from "react"; +function Component(props) { + const $ = useMemoCache(1); + + const a = []; + const b = []; + b.push(props.cond); + a.push(10); + + const c = [a]; + + let x; + for (let i = 0; i < 10; i = i + c[0][0], i) { + x = 1; + } + let t0; + if ($[0] === Symbol.for("react.memo_cache_sentinel")) { + t0 = [x]; + $[0] = t0; + } else { + t0 = $[0]; + } + return t0; +} + +export const FIXTURE_ENTRYPOINT = { + fn: Component, + params: [{ cond: true }], +}; + +``` + +### Eval output +(kind: ok) [1] \ No newline at end of file diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reactive-control-dependency-from-interleaved-reactivity-for-update.js b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reactive-control-dependency-from-interleaved-reactivity-for-update.js new file mode 100644 index 0000000000..b4aafa459e --- /dev/null +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reactive-control-dependency-from-interleaved-reactivity-for-update.js @@ -0,0 +1,29 @@ +function Component(props) { + // a and b are independent but their mutations are interleaved, so + // they get grouped in a reactive scope. this means that a becomes + // reactive since it will effectively re-evaluate based on a reactive + // input + const a = []; + const b = []; + b.push(props.cond); + a.push(10); + + // Downstream consumer of a, which initially seems non-reactive except + // that a becomes reactive, per above + const c = [a]; + + let x; + for (let i = 0; i < 10; i += c[0][0]) { + x = 1; + } + // The values assigned to `x` are non-reactive, but the value of `x` + // depends on the "control" value `c[0]` which becomes reactive via + // being interleaved with `b`. + // Therefore x should be treated as reactive too. + return [x]; +} + +export const FIXTURE_ENTRYPOINT = { + fn: Component, + params: [{ cond: true }], +}; diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reactive-control-dependency-from-interleaved-reactivity-if.expect.md b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reactive-control-dependency-from-interleaved-reactivity-if.expect.md index 098077f59f..1096275ac8 100644 --- a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reactive-control-dependency-from-interleaved-reactivity-if.expect.md +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reactive-control-dependency-from-interleaved-reactivity-if.expect.md @@ -17,7 +17,7 @@ function Component(props) { const c = [a]; let x; - if (c[0]) { + if (c[0][0]) { x = 1; } else { x = 2; @@ -51,7 +51,7 @@ function Component(props) { const c = [a]; let x; - if (c[0]) { + if (c[0][0]) { x = 1; } else { x = 2; @@ -74,4 +74,4 @@ export const FIXTURE_ENTRYPOINT = { ``` ### Eval output -(kind: ok) [1] \ No newline at end of file +(kind: ok) [2] \ No newline at end of file diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reactive-control-dependency-from-interleaved-reactivity-if.js b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reactive-control-dependency-from-interleaved-reactivity-if.js index 9c07d33b12..34122dd290 100644 --- a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reactive-control-dependency-from-interleaved-reactivity-if.js +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reactive-control-dependency-from-interleaved-reactivity-if.js @@ -13,7 +13,7 @@ function Component(props) { const c = [a]; let x; - if (c[0]) { + if (c[0][0]) { x = 1; } else { x = 2; diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reactive-control-dependency-from-interleaved-reactivity-switch.expect.md b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reactive-control-dependency-from-interleaved-reactivity-switch.expect.md new file mode 100644 index 0000000000..672e64924b --- /dev/null +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reactive-control-dependency-from-interleaved-reactivity-switch.expect.md @@ -0,0 +1,85 @@ + +## Input + +```javascript +function Component(props) { + // a and b are independent but their mutations are interleaved, so + // they get grouped in a reactive scope. this means that a becomes + // reactive since it will effectively re-evaluate based on a reactive + // input + const a = []; + const b = []; + b.push(props.cond); + a.push(null); + + // Downstream consumer of a, which initially seems non-reactive except + // that a becomes reactive, per above + const c = [a]; + + let x; + switch (c[0][0]) { + case true: { + x = 1; + break; + } + default: { + x = 2; + } + } + // The values assigned to `x` are non-reactive, but the value of `x` + // depends on the "control" value `c[0]` which becomes reactive via + // being interleaved with `b`. + // Therefore x should be treated as reactive too. + return [x]; +} + +export const FIXTURE_ENTRYPOINT = { + fn: Component, + params: [{ cond: true }], +}; + +``` + +## Code + +```javascript +import { unstable_useMemoCache as useMemoCache } from "react"; +function Component(props) { + const $ = useMemoCache(1); + + const a = []; + const b = []; + b.push(props.cond); + a.push(null); + + const c = [a]; + + let x; + bb1: switch (c[0][0]) { + case true: { + x = 1; + break bb1; + } + default: { + x = 2; + } + } + let t0; + if ($[0] === Symbol.for("react.memo_cache_sentinel")) { + t0 = [x]; + $[0] = t0; + } else { + t0 = $[0]; + } + return t0; +} + +export const FIXTURE_ENTRYPOINT = { + fn: Component, + params: [{ cond: true }], +}; + +``` + +### Eval output +(kind: ok) [2] \ No newline at end of file diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reactive-control-dependency-from-interleaved-reactivity-switch.js b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reactive-control-dependency-from-interleaved-reactivity-switch.js new file mode 100644 index 0000000000..c94c45e4e2 --- /dev/null +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reactive-control-dependency-from-interleaved-reactivity-switch.js @@ -0,0 +1,35 @@ +function Component(props) { + // a and b are independent but their mutations are interleaved, so + // they get grouped in a reactive scope. this means that a becomes + // reactive since it will effectively re-evaluate based on a reactive + // input + const a = []; + const b = []; + b.push(props.cond); + a.push(null); + + // Downstream consumer of a, which initially seems non-reactive except + // that a becomes reactive, per above + const c = [a]; + + let x; + switch (c[0][0]) { + case true: { + x = 1; + break; + } + default: { + x = 2; + } + } + // The values assigned to `x` are non-reactive, but the value of `x` + // depends on the "control" value `c[0]` which becomes reactive via + // being interleaved with `b`. + // Therefore x should be treated as reactive too. + return [x]; +} + +export const FIXTURE_ENTRYPOINT = { + fn: Component, + params: [{ cond: true }], +}; diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reactive-control-dependency-from-interleaved-reactivity-while.expect.md b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reactive-control-dependency-from-interleaved-reactivity-while.expect.md new file mode 100644 index 0000000000..9ede649b06 --- /dev/null +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reactive-control-dependency-from-interleaved-reactivity-while.expect.md @@ -0,0 +1,73 @@ + +## Input + +```javascript +function Component(props) { + // a and b are independent but their mutations are interleaved, so + // they get grouped in a reactive scope. this means that a becomes + // reactive since it will effectively re-evaluate based on a reactive + // input + const a = []; + const b = []; + b.push(props.cond); + a.push(null); + + // Downstream consumer of a, which initially seems non-reactive except + // that a becomes reactive, per above + const c = [a]; + + let x; + while (c[0][0]) { + x = 1; + } + // The values assigned to `x` are non-reactive, but the value of `x` + // depends on the "control" value `c[0]` which becomes reactive via + // being interleaved with `b`. + // Therefore x should be treated as reactive too. + return [x]; +} + +export const FIXTURE_ENTRYPOINT = { + fn: Component, + params: [{ cond: true }], +}; + +``` + +## Code + +```javascript +import { unstable_useMemoCache as useMemoCache } from "react"; +function Component(props) { + const $ = useMemoCache(1); + + const a = []; + const b = []; + b.push(props.cond); + a.push(null); + + const c = [a]; + + let x; + while (c[0][0]) { + x = 1; + } + let t0; + if ($[0] === Symbol.for("react.memo_cache_sentinel")) { + t0 = [x]; + $[0] = t0; + } else { + t0 = $[0]; + } + return t0; +} + +export const FIXTURE_ENTRYPOINT = { + fn: Component, + params: [{ cond: true }], +}; + +``` + +### Eval output +(kind: ok) [null] \ No newline at end of file diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reactive-control-dependency-from-interleaved-reactivity-while.js b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reactive-control-dependency-from-interleaved-reactivity-while.js new file mode 100644 index 0000000000..e53977e70e --- /dev/null +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reactive-control-dependency-from-interleaved-reactivity-while.js @@ -0,0 +1,29 @@ +function Component(props) { + // a and b are independent but their mutations are interleaved, so + // they get grouped in a reactive scope. this means that a becomes + // reactive since it will effectively re-evaluate based on a reactive + // input + const a = []; + const b = []; + b.push(props.cond); + a.push(null); + + // Downstream consumer of a, which initially seems non-reactive except + // that a becomes reactive, per above + const c = [a]; + + let x; + while (c[0][0]) { + x = 1; + } + // The values assigned to `x` are non-reactive, but the value of `x` + // depends on the "control" value `c[0]` which becomes reactive via + // being interleaved with `b`. + // Therefore x should be treated as reactive too. + return [x]; +} + +export const FIXTURE_ENTRYPOINT = { + fn: Component, + params: [{ cond: true }], +};