From 08e92a3a8d3646138002322ab86b5d6fba9c162e Mon Sep 17 00:00:00 2001 From: Joe Savona Date: Fri, 15 Dec 2023 15:19:39 -0800 Subject: [PATCH] More test cases for useCallback Adds test cases per the previous PR for useCallback: * callback that references another callback, which in turn references a possibly-mutated value * callback that references a ref --- ...-value-dont-preserve-memoization.expect.md | 84 +++++++++++++++++++ ...mutable-value-dont-preserve-memoization.js | 31 +++++++ ...table-value-preserve-memoization.expect.md | 84 +++++++++++++++++++ ...aybe-mutable-value-preserve-memoization.js | 31 +++++++ ...-value-dont-preserve-memoization.expect.md | 69 +++++++++++++++ ...set-ref-value-dont-preserve-memoization.js | 19 +++++ ...t-ref-value-preserve-memoization.expect.md | 69 +++++++++++++++ ...back-set-ref-value-preserve-memoization.js | 19 +++++ .../packages/sprout/src/shared-runtime.ts | 4 + 9 files changed, 410 insertions(+) create mode 100644 compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/useCallback-call-second-function-which-captures-maybe-mutable-value-dont-preserve-memoization.expect.md create mode 100644 compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/useCallback-call-second-function-which-captures-maybe-mutable-value-dont-preserve-memoization.js create mode 100644 compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/useCallback-call-second-function-which-captures-maybe-mutable-value-preserve-memoization.expect.md create mode 100644 compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/useCallback-call-second-function-which-captures-maybe-mutable-value-preserve-memoization.js create mode 100644 compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/useCallback-set-ref-value-dont-preserve-memoization.expect.md create mode 100644 compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/useCallback-set-ref-value-dont-preserve-memoization.js create mode 100644 compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/useCallback-set-ref-value-preserve-memoization.expect.md create mode 100644 compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/useCallback-set-ref-value-preserve-memoization.js diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/useCallback-call-second-function-which-captures-maybe-mutable-value-dont-preserve-memoization.expect.md b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/useCallback-call-second-function-which-captures-maybe-mutable-value-dont-preserve-memoization.expect.md new file mode 100644 index 0000000000..f3bbcc346b --- /dev/null +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/useCallback-call-second-function-which-captures-maybe-mutable-value-dont-preserve-memoization.expect.md @@ -0,0 +1,84 @@ + +## Input + +```javascript +// @enablePreserveExistingMemoizationGuarantees:false +import { useCallback } from "react"; +import { + identity, + logValue, + makeObject_Primitives, + useHook, +} from "shared-runtime"; + +function Component(props) { + const object = makeObject_Primitives(); + + useHook(); + + const log = () => { + logValue(object); + }; + + const onClick = useCallback(() => { + log(); + }, [log]); + + identity(object); + + return
; +} + +export const FIXTURE_ENTRYPOINT = { + fn: Component, + params: [{}], +}; + +``` + +## Code + +```javascript +// @enablePreserveExistingMemoizationGuarantees:false +import { useCallback, unstable_useMemoCache as useMemoCache } from "react"; +import { + identity, + logValue, + makeObject_Primitives, + useHook, +} from "shared-runtime"; + +function Component(props) { + const $ = useMemoCache(1); + const object = makeObject_Primitives(); + + useHook(); + + const log = () => { + logValue(object); + }; + + const onClick = () => { + log(); + }; + + identity(object); + let t0; + if ($[0] === Symbol.for("react.memo_cache_sentinel")) { + t0 =
; + $[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/useCallback-call-second-function-which-captures-maybe-mutable-value-dont-preserve-memoization.js b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/useCallback-call-second-function-which-captures-maybe-mutable-value-dont-preserve-memoization.js new file mode 100644 index 0000000000..5f6716fb19 --- /dev/null +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/useCallback-call-second-function-which-captures-maybe-mutable-value-dont-preserve-memoization.js @@ -0,0 +1,31 @@ +// @enablePreserveExistingMemoizationGuarantees:false +import { useCallback } from "react"; +import { + identity, + logValue, + makeObject_Primitives, + useHook, +} from "shared-runtime"; + +function Component(props) { + const object = makeObject_Primitives(); + + useHook(); + + const log = () => { + logValue(object); + }; + + const onClick = useCallback(() => { + log(); + }, [log]); + + identity(object); + + return
; +} + +export const FIXTURE_ENTRYPOINT = { + fn: Component, + params: [{}], +}; diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/useCallback-call-second-function-which-captures-maybe-mutable-value-preserve-memoization.expect.md b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/useCallback-call-second-function-which-captures-maybe-mutable-value-preserve-memoization.expect.md new file mode 100644 index 0000000000..874a4120eb --- /dev/null +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/useCallback-call-second-function-which-captures-maybe-mutable-value-preserve-memoization.expect.md @@ -0,0 +1,84 @@ + +## Input + +```javascript +// @enablePreserveExistingMemoizationGuarantees +import { useCallback } from "react"; +import { + identity, + logValue, + makeObject_Primitives, + useHook, +} from "shared-runtime"; + +function Component(props) { + const object = makeObject_Primitives(); + + useHook(); + + const log = () => { + logValue(object); + }; + + const onClick = useCallback(() => { + log(); + }, [log]); + + identity(object); + + return
; +} + +export const FIXTURE_ENTRYPOINT = { + fn: Component, + params: [{}], +}; + +``` + +## Code + +```javascript +// @enablePreserveExistingMemoizationGuarantees +import { useCallback, unstable_useMemoCache as useMemoCache } from "react"; +import { + identity, + logValue, + makeObject_Primitives, + useHook, +} from "shared-runtime"; + +function Component(props) { + const $ = useMemoCache(1); + const object = makeObject_Primitives(); + + useHook(); + + const log = () => { + logValue(object); + }; + + const onClick = () => { + log(); + }; + + identity(object); + let t0; + if ($[0] === Symbol.for("react.memo_cache_sentinel")) { + t0 =
; + $[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/useCallback-call-second-function-which-captures-maybe-mutable-value-preserve-memoization.js b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/useCallback-call-second-function-which-captures-maybe-mutable-value-preserve-memoization.js new file mode 100644 index 0000000000..19f5858623 --- /dev/null +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/useCallback-call-second-function-which-captures-maybe-mutable-value-preserve-memoization.js @@ -0,0 +1,31 @@ +// @enablePreserveExistingMemoizationGuarantees +import { useCallback } from "react"; +import { + identity, + logValue, + makeObject_Primitives, + useHook, +} from "shared-runtime"; + +function Component(props) { + const object = makeObject_Primitives(); + + useHook(); + + const log = () => { + logValue(object); + }; + + const onClick = useCallback(() => { + log(); + }, [log]); + + identity(object); + + return
; +} + +export const FIXTURE_ENTRYPOINT = { + fn: Component, + params: [{}], +}; diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/useCallback-set-ref-value-dont-preserve-memoization.expect.md b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/useCallback-set-ref-value-dont-preserve-memoization.expect.md new file mode 100644 index 0000000000..d205081829 --- /dev/null +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/useCallback-set-ref-value-dont-preserve-memoization.expect.md @@ -0,0 +1,69 @@ + +## Input + +```javascript +// @enablePreserveExistingMemoizationGuarantees +import { useCallback, useRef } from "react"; + +function Component(props) { + const ref = useRef(null); + + const onChange = useCallback((event) => { + // The ref should still be mutable here even though function deps are frozen in + // @enablePreserveExistingMemoizationGuarantees mode + ref.current = event.target.value; + }); + + return ; +} + +export const FIXTURE_ENTRYPOINT = { + fn: Component, + params: [{}], +}; + +``` + +## Code + +```javascript +// @enablePreserveExistingMemoizationGuarantees +import { + useCallback, + useRef, + unstable_useMemoCache as useMemoCache, +} from "react"; + +function Component(props) { + const $ = useMemoCache(3); + const ref = useRef(null); + let t0; + if ($[0] === Symbol.for("react.memo_cache_sentinel")) { + t0 = (event) => { + ref.current = event.target.value; + }; + $[0] = t0; + } else { + t0 = $[0]; + } + const onChange = t0; + let t1; + if ($[1] !== onChange) { + t1 = ; + $[1] = onChange; + $[2] = t1; + } else { + t1 = $[2]; + } + 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/useCallback-set-ref-value-dont-preserve-memoization.js b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/useCallback-set-ref-value-dont-preserve-memoization.js new file mode 100644 index 0000000000..f9e5c9b171 --- /dev/null +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/useCallback-set-ref-value-dont-preserve-memoization.js @@ -0,0 +1,19 @@ +// @enablePreserveExistingMemoizationGuarantees +import { useCallback, useRef } from "react"; + +function Component(props) { + const ref = useRef(null); + + const onChange = useCallback((event) => { + // The ref should still be mutable here even though function deps are frozen in + // @enablePreserveExistingMemoizationGuarantees mode + ref.current = event.target.value; + }); + + return ; +} + +export const FIXTURE_ENTRYPOINT = { + fn: Component, + params: [{}], +}; diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/useCallback-set-ref-value-preserve-memoization.expect.md b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/useCallback-set-ref-value-preserve-memoization.expect.md new file mode 100644 index 0000000000..d205081829 --- /dev/null +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/useCallback-set-ref-value-preserve-memoization.expect.md @@ -0,0 +1,69 @@ + +## Input + +```javascript +// @enablePreserveExistingMemoizationGuarantees +import { useCallback, useRef } from "react"; + +function Component(props) { + const ref = useRef(null); + + const onChange = useCallback((event) => { + // The ref should still be mutable here even though function deps are frozen in + // @enablePreserveExistingMemoizationGuarantees mode + ref.current = event.target.value; + }); + + return ; +} + +export const FIXTURE_ENTRYPOINT = { + fn: Component, + params: [{}], +}; + +``` + +## Code + +```javascript +// @enablePreserveExistingMemoizationGuarantees +import { + useCallback, + useRef, + unstable_useMemoCache as useMemoCache, +} from "react"; + +function Component(props) { + const $ = useMemoCache(3); + const ref = useRef(null); + let t0; + if ($[0] === Symbol.for("react.memo_cache_sentinel")) { + t0 = (event) => { + ref.current = event.target.value; + }; + $[0] = t0; + } else { + t0 = $[0]; + } + const onChange = t0; + let t1; + if ($[1] !== onChange) { + t1 = ; + $[1] = onChange; + $[2] = t1; + } else { + t1 = $[2]; + } + 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/useCallback-set-ref-value-preserve-memoization.js b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/useCallback-set-ref-value-preserve-memoization.js new file mode 100644 index 0000000000..f9e5c9b171 --- /dev/null +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/useCallback-set-ref-value-preserve-memoization.js @@ -0,0 +1,19 @@ +// @enablePreserveExistingMemoizationGuarantees +import { useCallback, useRef } from "react"; + +function Component(props) { + const ref = useRef(null); + + const onChange = useCallback((event) => { + // The ref should still be mutable here even though function deps are frozen in + // @enablePreserveExistingMemoizationGuarantees mode + ref.current = event.target.value; + }); + + return ; +} + +export const FIXTURE_ENTRYPOINT = { + fn: Component, + params: [{}], +}; diff --git a/compiler/packages/sprout/src/shared-runtime.ts b/compiler/packages/sprout/src/shared-runtime.ts index 8f1133713f..9ccba51bbb 100644 --- a/compiler/packages/sprout/src/shared-runtime.ts +++ b/compiler/packages/sprout/src/shared-runtime.ts @@ -153,6 +153,10 @@ export function throwInput(x: Object): never { throw x; } +export function logValue(value: T): void { + console.log(value); +} + export function useHook(): Object { return makeObject_Primitives(); }