Skip to content

Commit 45fb607

Browse files
committed
refactor to use updateQueue
1 parent 22f89ed commit 45fb607

File tree

6 files changed

+88
-116
lines changed

6 files changed

+88
-116
lines changed

packages/react-reconciler/src/ReactFiber.new.js

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ import {
3232
allowConcurrentByDefault,
3333
enableTransitionTracing,
3434
enableDebugTracing,
35-
enableUseMemoCacheHook,
3635
} from 'shared/ReactFeatureFlags';
3736
import {NoFlags, Placement, StaticMask} from './ReactFiberFlags';
3837
import {ConcurrentRoot} from './ReactRootTags';
@@ -145,9 +144,6 @@ function FiberNode(
145144
this.updateQueue = null;
146145
this.memoizedState = null;
147146
this.dependencies = null;
148-
if (enableUseMemoCacheHook) {
149-
this.memoCache = null;
150-
}
151147

152148
this.mode = mode;
153149

@@ -314,9 +310,6 @@ export function createWorkInProgress(current: Fiber, pendingProps: any): Fiber {
314310
workInProgress.memoizedProps = current.memoizedProps;
315311
workInProgress.memoizedState = current.memoizedState;
316312
workInProgress.updateQueue = current.updateQueue;
317-
if (enableUseMemoCacheHook) {
318-
workInProgress.memoCache = current.memoCache;
319-
}
320313

321314
// Clone the dependencies object. This is mutated during the render phase, so
322315
// it cannot be shared with the current fiber.
@@ -858,9 +851,6 @@ export function assignFiberPropertiesInDEV(
858851
target.pendingProps = source.pendingProps;
859852
target.memoizedProps = source.memoizedProps;
860853
target.updateQueue = source.updateQueue;
861-
if (enableUseMemoCacheHook) {
862-
target.memoCache = source.memoCache;
863-
}
864854
target.memoizedState = source.memoizedState;
865855
target.dependencies = source.dependencies;
866856
target.mode = source.mode;

packages/react-reconciler/src/ReactFiber.old.js

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ import {
3232
allowConcurrentByDefault,
3333
enableTransitionTracing,
3434
enableDebugTracing,
35-
enableUseMemoCacheHook,
3635
} from 'shared/ReactFeatureFlags';
3736
import {NoFlags, Placement, StaticMask} from './ReactFiberFlags';
3837
import {ConcurrentRoot} from './ReactRootTags';
@@ -145,9 +144,6 @@ function FiberNode(
145144
this.updateQueue = null;
146145
this.memoizedState = null;
147146
this.dependencies = null;
148-
if (enableUseMemoCacheHook) {
149-
this.memoCache = null;
150-
}
151147

152148
this.mode = mode;
153149

@@ -314,9 +310,6 @@ export function createWorkInProgress(current: Fiber, pendingProps: any): Fiber {
314310
workInProgress.memoizedProps = current.memoizedProps;
315311
workInProgress.memoizedState = current.memoizedState;
316312
workInProgress.updateQueue = current.updateQueue;
317-
if (enableUseMemoCacheHook) {
318-
workInProgress.memoCache = current.memoCache;
319-
}
320313

321314
// Clone the dependencies object. This is mutated during the render phase, so
322315
// it cannot be shared with the current fiber.
@@ -858,9 +851,6 @@ export function assignFiberPropertiesInDEV(
858851
target.pendingProps = source.pendingProps;
859852
target.memoizedProps = source.memoizedProps;
860853
target.updateQueue = source.updateQueue;
861-
if (enableUseMemoCacheHook) {
862-
target.memoCache = source.memoCache;
863-
}
864854
target.memoizedState = source.memoizedState;
865855
target.dependencies = source.dependencies;
866856
target.mode = source.mode;

packages/react-reconciler/src/ReactFiberHooks.new.js

Lines changed: 42 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,12 @@ import type {
1616
Usable,
1717
Thenable,
1818
} from 'shared/ReactTypes';
19-
import type {Fiber, Dispatcher, HookType} from './ReactInternalTypes';
19+
import type {
20+
Fiber,
21+
Dispatcher,
22+
HookType,
23+
MemoCache,
24+
} from './ReactInternalTypes';
2025
import type {Lanes, Lane} from './ReactFiberLane.new';
2126
import type {HookFlags} from './ReactHookEffectTags';
2227
import type {FiberRoot} from './ReactInternalTypes';
@@ -173,6 +178,7 @@ type StoreConsistencyCheck<T> = {|
173178
export type FunctionComponentUpdateQueue = {|
174179
lastEffect: Effect | null,
175180
stores: Array<StoreConsistencyCheck<any>> | null,
181+
memoCache: MemoCache | null,
176182
|};
177183

178184
type BasicStateAction<S> = (S => S) | S;
@@ -395,20 +401,6 @@ export function renderWithHooks<Props, SecondArg>(
395401
current !== null && current.type !== workInProgress.type;
396402
}
397403

398-
// Reset the memoCache index and create a backup copy in case of a setState during render
399-
// or error, either of which can leave the cache in an inconsistent state
400-
let previousMemoCache = null;
401-
if (enableUseMemoCacheHook) {
402-
previousMemoCache = workInProgress.memoCache;
403-
if (previousMemoCache !== null) {
404-
const memoCache = {
405-
data: previousMemoCache.data.map(array => array.slice()),
406-
index: 0,
407-
};
408-
workInProgress.memoCache = memoCache;
409-
}
410-
}
411-
412404
workInProgress.memoizedState = null;
413405
workInProgress.updateQueue = null;
414406
workInProgress.lanes = NoLanes;
@@ -480,17 +472,6 @@ export function renderWithHooks<Props, SecondArg>(
480472

481473
workInProgress.updateQueue = null;
482474

483-
if (enableUseMemoCacheHook) {
484-
if (previousMemoCache !== null) {
485-
// Setting state during render could leave the cache in an inconsistent state,
486-
// reset to the previous state before re-rendering.
487-
workInProgress.memoCache = {
488-
data: previousMemoCache.data.map(array => array.slice()),
489-
index: 0,
490-
};
491-
}
492-
}
493-
494475
if (__DEV__) {
495476
// Also validate hook order for cascading updates.
496477
hookTypesUpdateIndexDev = -1;
@@ -604,7 +585,7 @@ export function bailoutHooks(
604585
current.lanes = removeLanes(current.lanes, lanes);
605586
}
606587

607-
export function resetHooksAfterThrow(erroredWork: Fiber | null): void {
588+
export function resetHooksAfterThrow(): void {
608589
// We can assume the previous dispatcher is always this one, since we set it
609590
// at the beginning of the render phase and there's no re-entrance.
610591
ReactCurrentDispatcher.current = ContextOnlyDispatcher;
@@ -629,18 +610,6 @@ export function resetHooksAfterThrow(erroredWork: Fiber | null): void {
629610
didScheduleRenderPhaseUpdate = false;
630611
}
631612

632-
if (enableUseMemoCacheHook) {
633-
if (erroredWork != null) {
634-
const memoCache = erroredWork.memoCache;
635-
if (memoCache !== null) {
636-
// The memo cache may be in an inconsistent state, reset to the version from
637-
// the alternate if available, or clear the cache completely.
638-
const alternate = erroredWork.alternate;
639-
erroredWork.memoCache = alternate != null ? alternate.memoCache : null;
640-
}
641-
}
642-
}
643-
644613
renderLanes = NoLanes;
645614
currentlyRenderingFiber = (null: any);
646615

@@ -747,6 +716,7 @@ function createFunctionComponentUpdateQueue(): FunctionComponentUpdateQueue {
747716
return {
748717
lastEffect: null,
749718
stores: null,
719+
memoCache: null,
750720
};
751721
}
752722

@@ -818,22 +788,48 @@ function use<T>(usable: Usable<T>): T {
818788
}
819789

820790
function useMemoCache(size: number): Array<any> {
821-
let memoCache = currentlyRenderingFiber.memoCache;
791+
let memoCache = null;
792+
// Fast-path, load memo cache from wip fiber if already prepared
793+
let updateQueue: FunctionComponentUpdateQueue | null = (currentlyRenderingFiber.updateQueue: any);
794+
if (updateQueue !== null) {
795+
memoCache = updateQueue.memoCache;
796+
}
797+
// Otherwise clone from the current fiber
798+
// TODO: not sure how to access the current fiber here other than going through
799+
// currentlyRenderingFiber.alternate
800+
if (memoCache === null) {
801+
const current: Fiber | null = currentlyRenderingFiber.alternate;
802+
if (current !== null) {
803+
const currentUpdateQueue: FunctionComponentUpdateQueue | null = (current.updateQueue: any);
804+
if (currentUpdateQueue !== null) {
805+
const currentMemoCache: MemoCache | null = currentUpdateQueue.memoCache;
806+
if (currentMemoCache !== null) {
807+
memoCache = {
808+
data: currentMemoCache.data.map(array => array.slice()),
809+
index: 0,
810+
};
811+
}
812+
}
813+
}
814+
}
815+
// Finally fall back to allocating a fresh instance
822816
if (memoCache === null) {
823-
memoCache = currentlyRenderingFiber.memoCache = {
817+
memoCache = {
824818
data: [],
825819
index: 0,
826820
};
827821
}
822+
if (updateQueue === null) {
823+
updateQueue = createFunctionComponentUpdateQueue();
824+
currentlyRenderingFiber.updateQueue = updateQueue;
825+
}
826+
updateQueue.memoCache = memoCache;
827+
828828
let data = memoCache.data[memoCache.index];
829829
if (data === undefined) {
830830
data = memoCache.data[memoCache.index] = new Array(size);
831831
} else if (data.length !== size) {
832-
if (__DEV__) {
833-
console.warn(
834-
'Expected each useMemoCache to receive a consistent size argument, found different sizes',
835-
);
836-
}
832+
// TODO: consider warning or throwing here
837833
}
838834
memoCache.index++;
839835
return data;

packages/react-reconciler/src/ReactFiberHooks.old.js

Lines changed: 42 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,12 @@ import type {
1616
Usable,
1717
Thenable,
1818
} from 'shared/ReactTypes';
19-
import type {Fiber, Dispatcher, HookType} from './ReactInternalTypes';
19+
import type {
20+
Fiber,
21+
Dispatcher,
22+
HookType,
23+
MemoCache,
24+
} from './ReactInternalTypes';
2025
import type {Lanes, Lane} from './ReactFiberLane.old';
2126
import type {HookFlags} from './ReactHookEffectTags';
2227
import type {FiberRoot} from './ReactInternalTypes';
@@ -173,6 +178,7 @@ type StoreConsistencyCheck<T> = {|
173178
export type FunctionComponentUpdateQueue = {|
174179
lastEffect: Effect | null,
175180
stores: Array<StoreConsistencyCheck<any>> | null,
181+
memoCache: MemoCache | null,
176182
|};
177183

178184
type BasicStateAction<S> = (S => S) | S;
@@ -395,20 +401,6 @@ export function renderWithHooks<Props, SecondArg>(
395401
current !== null && current.type !== workInProgress.type;
396402
}
397403

398-
// Reset the memoCache index and create a backup copy in case of a setState during render
399-
// or error, either of which can leave the cache in an inconsistent state
400-
let previousMemoCache = null;
401-
if (enableUseMemoCacheHook) {
402-
previousMemoCache = workInProgress.memoCache;
403-
if (previousMemoCache !== null) {
404-
const memoCache = {
405-
data: previousMemoCache.data.map(array => array.slice()),
406-
index: 0,
407-
};
408-
workInProgress.memoCache = memoCache;
409-
}
410-
}
411-
412404
workInProgress.memoizedState = null;
413405
workInProgress.updateQueue = null;
414406
workInProgress.lanes = NoLanes;
@@ -480,17 +472,6 @@ export function renderWithHooks<Props, SecondArg>(
480472

481473
workInProgress.updateQueue = null;
482474

483-
if (enableUseMemoCacheHook) {
484-
if (previousMemoCache !== null) {
485-
// Setting state during render could leave the cache in an inconsistent state,
486-
// reset to the previous state before re-rendering.
487-
workInProgress.memoCache = {
488-
data: previousMemoCache.data.map(array => array.slice()),
489-
index: 0,
490-
};
491-
}
492-
}
493-
494475
if (__DEV__) {
495476
// Also validate hook order for cascading updates.
496477
hookTypesUpdateIndexDev = -1;
@@ -604,7 +585,7 @@ export function bailoutHooks(
604585
current.lanes = removeLanes(current.lanes, lanes);
605586
}
606587

607-
export function resetHooksAfterThrow(erroredWork: Fiber | null): void {
588+
export function resetHooksAfterThrow(): void {
608589
// We can assume the previous dispatcher is always this one, since we set it
609590
// at the beginning of the render phase and there's no re-entrance.
610591
ReactCurrentDispatcher.current = ContextOnlyDispatcher;
@@ -629,18 +610,6 @@ export function resetHooksAfterThrow(erroredWork: Fiber | null): void {
629610
didScheduleRenderPhaseUpdate = false;
630611
}
631612

632-
if (enableUseMemoCacheHook) {
633-
if (erroredWork != null) {
634-
const memoCache = erroredWork.memoCache;
635-
if (memoCache !== null) {
636-
// The memo cache may be in an inconsistent state, reset to the version from
637-
// the alternate if available, or clear the cache completely.
638-
const alternate = erroredWork.alternate;
639-
erroredWork.memoCache = alternate != null ? alternate.memoCache : null;
640-
}
641-
}
642-
}
643-
644613
renderLanes = NoLanes;
645614
currentlyRenderingFiber = (null: any);
646615

@@ -747,6 +716,7 @@ function createFunctionComponentUpdateQueue(): FunctionComponentUpdateQueue {
747716
return {
748717
lastEffect: null,
749718
stores: null,
719+
memoCache: null,
750720
};
751721
}
752722

@@ -818,22 +788,48 @@ function use<T>(usable: Usable<T>): T {
818788
}
819789

820790
function useMemoCache(size: number): Array<any> {
821-
let memoCache = currentlyRenderingFiber.memoCache;
791+
let memoCache = null;
792+
// Fast-path, load memo cache from wip fiber if already prepared
793+
let updateQueue: FunctionComponentUpdateQueue | null = (currentlyRenderingFiber.updateQueue: any);
794+
if (updateQueue !== null) {
795+
memoCache = updateQueue.memoCache;
796+
}
797+
// Otherwise clone from the current fiber
798+
// TODO: not sure how to access the current fiber here other than going through
799+
// currentlyRenderingFiber.alternate
800+
if (memoCache === null) {
801+
const current: Fiber | null = currentlyRenderingFiber.alternate;
802+
if (current !== null) {
803+
const currentUpdateQueue: FunctionComponentUpdateQueue | null = (current.updateQueue: any);
804+
if (currentUpdateQueue !== null) {
805+
const currentMemoCache: MemoCache | null = currentUpdateQueue.memoCache;
806+
if (currentMemoCache !== null) {
807+
memoCache = {
808+
data: currentMemoCache.data.map(array => array.slice()),
809+
index: 0,
810+
};
811+
}
812+
}
813+
}
814+
}
815+
// Finally fall back to allocating a fresh instance
822816
if (memoCache === null) {
823-
memoCache = currentlyRenderingFiber.memoCache = {
817+
memoCache = {
824818
data: [],
825819
index: 0,
826820
};
827821
}
822+
if (updateQueue === null) {
823+
updateQueue = createFunctionComponentUpdateQueue();
824+
currentlyRenderingFiber.updateQueue = updateQueue;
825+
}
826+
updateQueue.memoCache = memoCache;
827+
828828
let data = memoCache.data[memoCache.index];
829829
if (data === undefined) {
830830
data = memoCache.data[memoCache.index] = new Array(size);
831831
} else if (data.length !== size) {
832-
if (__DEV__) {
833-
console.warn(
834-
'Expected each useMemoCache to receive a consistent size argument, found different sizes',
835-
);
836-
}
832+
// TODO: consider warning or throwing here
837833
}
838834
memoCache.index++;
839835
return data;

packages/react-reconciler/src/ReactFiberWorkLoop.new.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1691,7 +1691,7 @@ function prepareFreshStack(root: FiberRoot, lanes: Lanes): Fiber {
16911691
function handleThrow(root, thrownValue): void {
16921692
// Reset module-level state that was set during the render phase.
16931693
resetContextDependencies();
1694-
resetHooksAfterThrow(workInProgress);
1694+
resetHooksAfterThrow();
16951695
resetCurrentDebugFiberInDEV();
16961696
// TODO: I found and added this missing line while investigating a
16971697
// separate issue. Write a regression test using string refs.
@@ -3307,7 +3307,7 @@ if (__DEV__ && replayFailedUnitOfWorkWithInvokeGuardedCallback) {
33073307
// Keep this code in sync with handleThrow; any changes here must have
33083308
// corresponding changes there.
33093309
resetContextDependencies();
3310-
resetHooksAfterThrow(unitOfWork);
3310+
resetHooksAfterThrow();
33113311
// Don't reset current debug fiber, since we're about to work on the
33123312
// same fiber again.
33133313

0 commit comments

Comments
 (0)