From d3aa0d0dfbf37dc4150a77389c3ab579a8ae3019 Mon Sep 17 00:00:00 2001 From: Joe Savona Date: Tue, 11 Oct 2022 14:42:08 -0700 Subject: [PATCH 1/4] Flush out useMemoCache API --- packages/react-reconciler/src/ReactFiberHooks.new.js | 6 ++++-- packages/react-reconciler/src/ReactFiberHooks.old.js | 6 ++++-- .../src/__tests__/useMemoCache-test.js | 4 +++- packages/react-server/src/ReactFizzHooks.js | 7 ++++++- packages/react-server/src/ReactFlightHooks.js | 11 +++++++++-- packages/react/src/React.js | 2 ++ packages/shared/ReactSymbols.js | 4 ++++ 7 files changed, 32 insertions(+), 8 deletions(-) diff --git a/packages/react-reconciler/src/ReactFiberHooks.new.js b/packages/react-reconciler/src/ReactFiberHooks.new.js index 2f854410afb11..678c767b829bd 100644 --- a/packages/react-reconciler/src/ReactFiberHooks.new.js +++ b/packages/react-reconciler/src/ReactFiberHooks.new.js @@ -46,6 +46,7 @@ import { import { REACT_CONTEXT_TYPE, REACT_SERVER_CONTEXT_TYPE, + REACT_USE_MEMO_CACHE_SENTINEL, } from 'shared/ReactSymbols'; import { @@ -845,8 +846,6 @@ function useMemoCache(size: number): Array { memoCache = updateQueue.memoCache; } // Otherwise clone from the current fiber - // TODO: not sure how to access the current fiber here other than going through - // currentlyRenderingFiber.alternate if (memoCache == null) { const current: Fiber | null = currentlyRenderingFiber.alternate; if (current !== null) { @@ -878,6 +877,9 @@ function useMemoCache(size: number): Array { let data = memoCache.data[memoCache.index]; if (data === undefined) { data = memoCache.data[memoCache.index] = new Array(size); + for (let i = 0; i < size; i++) { + data[i] = REACT_USE_MEMO_CACHE_SENTINEL; + } } else if (data.length !== size) { // TODO: consider warning or throwing here if (__DEV__) { diff --git a/packages/react-reconciler/src/ReactFiberHooks.old.js b/packages/react-reconciler/src/ReactFiberHooks.old.js index bbdb1e2478f99..10f36ac8c1ef8 100644 --- a/packages/react-reconciler/src/ReactFiberHooks.old.js +++ b/packages/react-reconciler/src/ReactFiberHooks.old.js @@ -46,6 +46,7 @@ import { import { REACT_CONTEXT_TYPE, REACT_SERVER_CONTEXT_TYPE, + REACT_USE_MEMO_CACHE_SENTINEL, } from 'shared/ReactSymbols'; import { @@ -845,8 +846,6 @@ function useMemoCache(size: number): Array { memoCache = updateQueue.memoCache; } // Otherwise clone from the current fiber - // TODO: not sure how to access the current fiber here other than going through - // currentlyRenderingFiber.alternate if (memoCache == null) { const current: Fiber | null = currentlyRenderingFiber.alternate; if (current !== null) { @@ -878,6 +877,9 @@ function useMemoCache(size: number): Array { let data = memoCache.data[memoCache.index]; if (data === undefined) { data = memoCache.data[memoCache.index] = new Array(size); + for (let i = 0; i < size; i++) { + data[i] = REACT_USE_MEMO_CACHE_SENTINEL; + } } else if (data.length !== size) { // TODO: consider warning or throwing here if (__DEV__) { diff --git a/packages/react-reconciler/src/__tests__/useMemoCache-test.js b/packages/react-reconciler/src/__tests__/useMemoCache-test.js index 94684ec8c00b3..7e29cd2817eda 100644 --- a/packages/react-reconciler/src/__tests__/useMemoCache-test.js +++ b/packages/react-reconciler/src/__tests__/useMemoCache-test.js @@ -1,3 +1,5 @@ +const {REACT_USE_MEMO_CACHE_SENTINEL} = require('shared/ReactSymbols'); + let React; let ReactNoop; let act; @@ -46,7 +48,7 @@ describe('useMemoCache()', () => { const cache = useMemoCache(1); expect(Array.isArray(cache)).toBe(true); expect(cache.length).toBe(1); - expect(cache[0]).toBe(undefined); + expect(cache[0]).toBe(REACT_USE_MEMO_CACHE_SENTINEL); return 'Ok'; } const root = ReactNoop.createRoot(); diff --git a/packages/react-server/src/ReactFizzHooks.js b/packages/react-server/src/ReactFizzHooks.js index bd0be42d14563..69af6f41493fd 100644 --- a/packages/react-server/src/ReactFizzHooks.js +++ b/packages/react-server/src/ReactFizzHooks.js @@ -46,6 +46,7 @@ import is from 'shared/objectIs'; import { REACT_SERVER_CONTEXT_TYPE, REACT_CONTEXT_TYPE, + REACT_USE_MEMO_CACHE_SENTINEL, } from 'shared/ReactSymbols'; type BasicStateAction = (S => S) | S; @@ -666,7 +667,11 @@ function useCacheRefresh(): (?() => T, ?T) => void { } function useMemoCache(size: number): Array { - return new Array(size); + const data = new Array(size); + for (let i = 0; i < size; i++) { + data[i] = REACT_USE_MEMO_CACHE_SENTINEL; + } + return data; } function noop(): void {} diff --git a/packages/react-server/src/ReactFlightHooks.js b/packages/react-server/src/ReactFlightHooks.js index a25a5f4b162ae..d99bd1cae8b1e 100644 --- a/packages/react-server/src/ReactFlightHooks.js +++ b/packages/react-server/src/ReactFlightHooks.js @@ -11,7 +11,10 @@ import type {Dispatcher} from 'react-reconciler/src/ReactInternalTypes'; import type {Request} from './ReactFlightServer'; import type {ReactServerContext, Thenable, Usable} from 'shared/ReactTypes'; import type {ThenableState} from './ReactFlightWakeable'; -import {REACT_SERVER_CONTEXT_TYPE} from 'shared/ReactSymbols'; +import { + REACT_SERVER_CONTEXT_TYPE, + REACT_USE_MEMO_CACHE_SENTINEL, +} from 'shared/ReactSymbols'; import {readContext as readContextImpl} from './ReactFlightNewContext'; import {enableUseHook} from 'shared/ReactFeatureFlags'; import { @@ -90,7 +93,11 @@ export const HooksDispatcher: Dispatcher = { return unsupportedRefresh; }, useMemoCache(size: number): Array { - return new Array(size); + const data = new Array(size); + for (let i = 0; i < size; i++) { + data[i] = REACT_USE_MEMO_CACHE_SENTINEL; + } + return data; }, use: enableUseHook ? use : (unsupportedHook: any), }; diff --git a/packages/react/src/React.js b/packages/react/src/React.js index 5edcd9e83049b..b07acbf5a1fd6 100644 --- a/packages/react/src/React.js +++ b/packages/react/src/React.js @@ -20,6 +20,7 @@ import { REACT_SCOPE_TYPE, REACT_CACHE_TYPE, REACT_TRACING_MARKER_TYPE, + REACT_USE_MEMO_CACHE_SENTINEL, } from 'shared/ReactSymbols'; import {Component, PureComponent} from './ReactBaseClasses'; @@ -139,6 +140,7 @@ export { REACT_CACHE_TYPE as unstable_Cache, use as experimental_use, useMemoCache as unstable_useMemoCache, + REACT_USE_MEMO_CACHE_SENTINEL as unstable_MemoCacheSentinel, // enableScopeAPI REACT_SCOPE_TYPE as unstable_Scope, // enableTransitionTracing diff --git a/packages/shared/ReactSymbols.js b/packages/shared/ReactSymbols.js index c68e50d5c693e..e1f0b6625dced 100644 --- a/packages/shared/ReactSymbols.js +++ b/packages/shared/ReactSymbols.js @@ -45,6 +45,10 @@ export const REACT_SERVER_CONTEXT_DEFAULT_VALUE_NOT_LOADED: symbol = Symbol.for( 'react.default_value', ); +export const REACT_USE_MEMO_CACHE_SENTINEL: symbol = Symbol.for( + 'react.use_memo_cache_sentinel', +); + const MAYBE_ITERATOR_SYMBOL = Symbol.iterator; const FAUX_ITERATOR_SYMBOL = '@@iterator'; From c593cde67f1f532148d111bb512adb0ad28c229d Mon Sep 17 00:00:00 2001 From: Joe Savona Date: Fri, 14 Oct 2022 14:14:56 -0700 Subject: [PATCH 2/4] rename symbol --- packages/react-reconciler/src/ReactFiberHooks.new.js | 4 ++-- packages/react-reconciler/src/__tests__/useMemoCache-test.js | 4 ++-- packages/react-server/src/ReactFizzHooks.js | 4 ++-- packages/react-server/src/ReactFlightHooks.js | 4 ++-- packages/react/src/React.js | 4 ++-- packages/shared/ReactSymbols.js | 2 +- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/packages/react-reconciler/src/ReactFiberHooks.new.js b/packages/react-reconciler/src/ReactFiberHooks.new.js index 678c767b829bd..110431001349f 100644 --- a/packages/react-reconciler/src/ReactFiberHooks.new.js +++ b/packages/react-reconciler/src/ReactFiberHooks.new.js @@ -46,7 +46,7 @@ import { import { REACT_CONTEXT_TYPE, REACT_SERVER_CONTEXT_TYPE, - REACT_USE_MEMO_CACHE_SENTINEL, + REACT_MEMO_CACHE_SENTINEL, } from 'shared/ReactSymbols'; import { @@ -878,7 +878,7 @@ function useMemoCache(size: number): Array { if (data === undefined) { data = memoCache.data[memoCache.index] = new Array(size); for (let i = 0; i < size; i++) { - data[i] = REACT_USE_MEMO_CACHE_SENTINEL; + data[i] = REACT_MEMO_CACHE_SENTINEL; } } else if (data.length !== size) { // TODO: consider warning or throwing here diff --git a/packages/react-reconciler/src/__tests__/useMemoCache-test.js b/packages/react-reconciler/src/__tests__/useMemoCache-test.js index 7e29cd2817eda..fd26e34d1ceca 100644 --- a/packages/react-reconciler/src/__tests__/useMemoCache-test.js +++ b/packages/react-reconciler/src/__tests__/useMemoCache-test.js @@ -1,4 +1,4 @@ -const {REACT_USE_MEMO_CACHE_SENTINEL} = require('shared/ReactSymbols'); +const {REACT_MEMO_CACHE_SENTINEL} = require('shared/ReactSymbols'); let React; let ReactNoop; @@ -48,7 +48,7 @@ describe('useMemoCache()', () => { const cache = useMemoCache(1); expect(Array.isArray(cache)).toBe(true); expect(cache.length).toBe(1); - expect(cache[0]).toBe(REACT_USE_MEMO_CACHE_SENTINEL); + expect(cache[0]).toBe(REACT_MEMO_CACHE_SENTINEL); return 'Ok'; } const root = ReactNoop.createRoot(); diff --git a/packages/react-server/src/ReactFizzHooks.js b/packages/react-server/src/ReactFizzHooks.js index 69af6f41493fd..5d5eca52319de 100644 --- a/packages/react-server/src/ReactFizzHooks.js +++ b/packages/react-server/src/ReactFizzHooks.js @@ -46,7 +46,7 @@ import is from 'shared/objectIs'; import { REACT_SERVER_CONTEXT_TYPE, REACT_CONTEXT_TYPE, - REACT_USE_MEMO_CACHE_SENTINEL, + REACT_MEMO_CACHE_SENTINEL, } from 'shared/ReactSymbols'; type BasicStateAction = (S => S) | S; @@ -669,7 +669,7 @@ function useCacheRefresh(): (?() => T, ?T) => void { function useMemoCache(size: number): Array { const data = new Array(size); for (let i = 0; i < size; i++) { - data[i] = REACT_USE_MEMO_CACHE_SENTINEL; + data[i] = REACT_MEMO_CACHE_SENTINEL; } return data; } diff --git a/packages/react-server/src/ReactFlightHooks.js b/packages/react-server/src/ReactFlightHooks.js index d99bd1cae8b1e..f4ee8d384d38b 100644 --- a/packages/react-server/src/ReactFlightHooks.js +++ b/packages/react-server/src/ReactFlightHooks.js @@ -13,7 +13,7 @@ import type {ReactServerContext, Thenable, Usable} from 'shared/ReactTypes'; import type {ThenableState} from './ReactFlightWakeable'; import { REACT_SERVER_CONTEXT_TYPE, - REACT_USE_MEMO_CACHE_SENTINEL, + REACT_MEMO_CACHE_SENTINEL, } from 'shared/ReactSymbols'; import {readContext as readContextImpl} from './ReactFlightNewContext'; import {enableUseHook} from 'shared/ReactFeatureFlags'; @@ -95,7 +95,7 @@ export const HooksDispatcher: Dispatcher = { useMemoCache(size: number): Array { const data = new Array(size); for (let i = 0; i < size; i++) { - data[i] = REACT_USE_MEMO_CACHE_SENTINEL; + data[i] = REACT_MEMO_CACHE_SENTINEL; } return data; }, diff --git a/packages/react/src/React.js b/packages/react/src/React.js index b07acbf5a1fd6..b7eccf3f32e2e 100644 --- a/packages/react/src/React.js +++ b/packages/react/src/React.js @@ -20,7 +20,7 @@ import { REACT_SCOPE_TYPE, REACT_CACHE_TYPE, REACT_TRACING_MARKER_TYPE, - REACT_USE_MEMO_CACHE_SENTINEL, + REACT_MEMO_CACHE_SENTINEL, } from 'shared/ReactSymbols'; import {Component, PureComponent} from './ReactBaseClasses'; @@ -140,7 +140,7 @@ export { REACT_CACHE_TYPE as unstable_Cache, use as experimental_use, useMemoCache as unstable_useMemoCache, - REACT_USE_MEMO_CACHE_SENTINEL as unstable_MemoCacheSentinel, + REACT_MEMO_CACHE_SENTINEL as unstable_MemoCacheSentinel, // enableScopeAPI REACT_SCOPE_TYPE as unstable_Scope, // enableTransitionTracing diff --git a/packages/shared/ReactSymbols.js b/packages/shared/ReactSymbols.js index e1f0b6625dced..189f56b47d599 100644 --- a/packages/shared/ReactSymbols.js +++ b/packages/shared/ReactSymbols.js @@ -45,7 +45,7 @@ export const REACT_SERVER_CONTEXT_DEFAULT_VALUE_NOT_LOADED: symbol = Symbol.for( 'react.default_value', ); -export const REACT_USE_MEMO_CACHE_SENTINEL: symbol = Symbol.for( +export const REACT_MEMO_CACHE_SENTINEL: symbol = Symbol.for( 'react.use_memo_cache_sentinel', ); From 49308b9251f8e9c1dd6d4a40df447952c01c65b9 Mon Sep 17 00:00:00 2001 From: Joe Savona Date: Fri, 14 Oct 2022 14:15:36 -0700 Subject: [PATCH 3/4] rename symbol.for string name --- packages/react-reconciler/src/ReactFiberHooks.old.js | 4 ++-- packages/shared/ReactSymbols.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/react-reconciler/src/ReactFiberHooks.old.js b/packages/react-reconciler/src/ReactFiberHooks.old.js index 10f36ac8c1ef8..527d442f88d22 100644 --- a/packages/react-reconciler/src/ReactFiberHooks.old.js +++ b/packages/react-reconciler/src/ReactFiberHooks.old.js @@ -46,7 +46,7 @@ import { import { REACT_CONTEXT_TYPE, REACT_SERVER_CONTEXT_TYPE, - REACT_USE_MEMO_CACHE_SENTINEL, + REACT_MEMO_CACHE_SENTINEL, } from 'shared/ReactSymbols'; import { @@ -878,7 +878,7 @@ function useMemoCache(size: number): Array { if (data === undefined) { data = memoCache.data[memoCache.index] = new Array(size); for (let i = 0; i < size; i++) { - data[i] = REACT_USE_MEMO_CACHE_SENTINEL; + data[i] = REACT_MEMO_CACHE_SENTINEL; } } else if (data.length !== size) { // TODO: consider warning or throwing here diff --git a/packages/shared/ReactSymbols.js b/packages/shared/ReactSymbols.js index 189f56b47d599..74bb4f0de92d9 100644 --- a/packages/shared/ReactSymbols.js +++ b/packages/shared/ReactSymbols.js @@ -46,7 +46,7 @@ export const REACT_SERVER_CONTEXT_DEFAULT_VALUE_NOT_LOADED: symbol = Symbol.for( ); export const REACT_MEMO_CACHE_SENTINEL: symbol = Symbol.for( - 'react.use_memo_cache_sentinel', + 'react.memo_cache_sentinel', ); const MAYBE_ITERATOR_SYMBOL = Symbol.iterator; From 25f6c1fb68e4461be03d05f76c21bb56e6eb813d Mon Sep 17 00:00:00 2001 From: Joe Savona Date: Fri, 14 Oct 2022 14:38:34 -0700 Subject: [PATCH 4/4] workaround symbol export not working in unit tests --- .../src/__tests__/useMemoCache-test.js | 15 +++++++++++++-- packages/react/src/React.js | 2 -- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/packages/react-reconciler/src/__tests__/useMemoCache-test.js b/packages/react-reconciler/src/__tests__/useMemoCache-test.js index fd26e34d1ceca..bde6671fc5ac5 100644 --- a/packages/react-reconciler/src/__tests__/useMemoCache-test.js +++ b/packages/react-reconciler/src/__tests__/useMemoCache-test.js @@ -1,10 +1,19 @@ -const {REACT_MEMO_CACHE_SENTINEL} = require('shared/ReactSymbols'); +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @emails react-core + * @jest-environment node + */ let React; let ReactNoop; let act; let useState; let useMemoCache; +let MemoCacheSentinel; let ErrorBoundary; describe('useMemoCache()', () => { @@ -16,6 +25,7 @@ describe('useMemoCache()', () => { act = require('jest-react').act; useState = React.useState; useMemoCache = React.unstable_useMemoCache; + MemoCacheSentinel = Symbol.for('react.memo_cache_sentinel'); class _ErrorBoundary extends React.Component { constructor(props) { @@ -48,7 +58,8 @@ describe('useMemoCache()', () => { const cache = useMemoCache(1); expect(Array.isArray(cache)).toBe(true); expect(cache.length).toBe(1); - expect(cache[0]).toBe(REACT_MEMO_CACHE_SENTINEL); + expect(cache[0]).toBe(MemoCacheSentinel); + return 'Ok'; } const root = ReactNoop.createRoot(); diff --git a/packages/react/src/React.js b/packages/react/src/React.js index b7eccf3f32e2e..5edcd9e83049b 100644 --- a/packages/react/src/React.js +++ b/packages/react/src/React.js @@ -20,7 +20,6 @@ import { REACT_SCOPE_TYPE, REACT_CACHE_TYPE, REACT_TRACING_MARKER_TYPE, - REACT_MEMO_CACHE_SENTINEL, } from 'shared/ReactSymbols'; import {Component, PureComponent} from './ReactBaseClasses'; @@ -140,7 +139,6 @@ export { REACT_CACHE_TYPE as unstable_Cache, use as experimental_use, useMemoCache as unstable_useMemoCache, - REACT_MEMO_CACHE_SENTINEL as unstable_MemoCacheSentinel, // enableScopeAPI REACT_SCOPE_TYPE as unstable_Scope, // enableTransitionTracing