mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
Lazily initialize dependencies object (#15944)
Most fibers do not have events or context, so we save memory lazily initializing this container node. Follow-up from #15927
This commit is contained in:
+14
-12
@@ -709,8 +709,7 @@ function getTargetEventResponderInstances(
|
||||
while (node !== null) {
|
||||
// Traverse up the fiber tree till we find event component fibers.
|
||||
const tag = node.tag;
|
||||
const events = node.dependencies.events;
|
||||
|
||||
const dependencies = node.dependencies;
|
||||
if (tag === EventComponent) {
|
||||
const eventComponentInstance = node.stateNode;
|
||||
// Switch to the current fiber tree
|
||||
@@ -721,16 +720,19 @@ function getTargetEventResponderInstances(
|
||||
eventResponderInstances,
|
||||
eventComponentResponders,
|
||||
);
|
||||
} else if (tag === FunctionComponent && events !== null) {
|
||||
for (let i = 0; i < events.length; i++) {
|
||||
const eventComponentInstance = events[i];
|
||||
if (eventComponentResponders.has(eventComponentInstance.responder)) {
|
||||
storeTargetEventResponderInstance(
|
||||
listeningName,
|
||||
eventComponentInstance,
|
||||
eventResponderInstances,
|
||||
null,
|
||||
);
|
||||
} else if (tag === FunctionComponent && dependencies !== null) {
|
||||
const events = dependencies.events;
|
||||
if (events !== null) {
|
||||
for (let i = 0; i < events.length; i++) {
|
||||
const eventComponentInstance = events[i];
|
||||
if (eventComponentResponders.has(eventComponentInstance.responder)) {
|
||||
storeTargetEventResponderInstance(
|
||||
listeningName,
|
||||
eventComponentInstance,
|
||||
eventResponderInstances,
|
||||
null,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+15
-8
@@ -169,8 +169,8 @@ export type Fiber = {|
|
||||
// The state used to create the output
|
||||
memoizedState: any,
|
||||
|
||||
// An object of dependencies for this fiber
|
||||
dependencies: Dependencies,
|
||||
// Dependencies (contexts, events) for this fiber, if it has any
|
||||
dependencies: Dependencies | null,
|
||||
|
||||
// Bitfield that describes properties about the fiber and its subtree. E.g.
|
||||
// the ConcurrentMode flag indicates whether the subtree should be async-by-
|
||||
@@ -270,11 +270,7 @@ function FiberNode(
|
||||
this.memoizedProps = null;
|
||||
this.updateQueue = null;
|
||||
this.memoizedState = null;
|
||||
this.dependencies = {
|
||||
expirationTime: 0,
|
||||
firstContext: null,
|
||||
events: null,
|
||||
};
|
||||
this.dependencies = null;
|
||||
|
||||
this.mode = mode;
|
||||
|
||||
@@ -443,7 +439,18 @@ export function createWorkInProgress(
|
||||
workInProgress.memoizedProps = current.memoizedProps;
|
||||
workInProgress.memoizedState = current.memoizedState;
|
||||
workInProgress.updateQueue = current.updateQueue;
|
||||
workInProgress.dependencies = current.dependencies;
|
||||
|
||||
// Clone the dependencies object. This is mutated during the render phase, so
|
||||
// it cannot be shared with the current fiber.
|
||||
const currentDependencies = current.dependencies;
|
||||
workInProgress.dependencies =
|
||||
currentDependencies === null
|
||||
? null
|
||||
: {
|
||||
expirationTime: currentDependencies.expirationTime,
|
||||
firstContext: currentDependencies.firstContext,
|
||||
events: currentDependencies.events,
|
||||
};
|
||||
|
||||
// These will be overridden during the parent's reconciliation
|
||||
workInProgress.sibling = current.sibling;
|
||||
|
||||
+17
-5
@@ -7,7 +7,7 @@
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import type {Fiber} from './ReactFiber';
|
||||
import type {Fiber, Dependencies} from './ReactFiber';
|
||||
import type {ReactEventComponentInstance} from 'shared/ReactTypes';
|
||||
import type {EventResponder} from 'react-reconciler/src/ReactFiberHostConfig';
|
||||
|
||||
@@ -18,6 +18,7 @@ import {
|
||||
SuspenseComponent,
|
||||
Fragment,
|
||||
} from 'shared/ReactWorkTags';
|
||||
import {NoWork} from './ReactFiberExpirationTime';
|
||||
import invariant from 'shared/invariant';
|
||||
|
||||
let currentlyRenderingFiber: null | Fiber = null;
|
||||
@@ -37,10 +38,21 @@ export function updateEventComponentInstance(
|
||||
'The "%s" event responder cannot be used via the "useEvent" hook.',
|
||||
responder.displayName,
|
||||
);
|
||||
const dependencies = ((currentlyRenderingFiber: any): Fiber).dependencies;
|
||||
let events = dependencies.events;
|
||||
if (events === null) {
|
||||
dependencies.events = events = [];
|
||||
let events;
|
||||
let dependencies: Dependencies | null = ((currentlyRenderingFiber: any): Fiber)
|
||||
.dependencies;
|
||||
if (dependencies === null) {
|
||||
events = [];
|
||||
dependencies = ((currentlyRenderingFiber: any): Fiber).dependencies = {
|
||||
expirationTime: NoWork,
|
||||
firstContext: null,
|
||||
events,
|
||||
};
|
||||
} else {
|
||||
events = dependencies.events;
|
||||
if (events === null) {
|
||||
dependencies.events = events = [];
|
||||
}
|
||||
}
|
||||
if (currentEventComponentInstanceIndex === events.length) {
|
||||
let responderState = null;
|
||||
|
||||
+19
-18
@@ -196,12 +196,11 @@ export function propagateContextChange(
|
||||
let nextFiber;
|
||||
|
||||
// Visit this fiber.
|
||||
const dependencies = fiber.dependencies;
|
||||
const list = dependencies.firstContext;
|
||||
const list = fiber.dependencies;
|
||||
if (list !== null) {
|
||||
nextFiber = fiber.child;
|
||||
|
||||
let dependency = list;
|
||||
let dependency = list.firstContext;
|
||||
while (dependency !== null) {
|
||||
// Check if the context matches.
|
||||
if (
|
||||
@@ -235,8 +234,8 @@ export function propagateContextChange(
|
||||
scheduleWorkOnParentPath(fiber.return, renderExpirationTime);
|
||||
|
||||
// Mark the expiration time on the list, too.
|
||||
if (dependencies.expirationTime < renderExpirationTime) {
|
||||
dependencies.expirationTime = renderExpirationTime;
|
||||
if (list.expirationTime < renderExpirationTime) {
|
||||
list.expirationTime = renderExpirationTime;
|
||||
}
|
||||
|
||||
// Since we already found a match, we can stop traversing the
|
||||
@@ -312,17 +311,17 @@ export function prepareToReadContext(
|
||||
lastContextWithAllBitsObserved = null;
|
||||
|
||||
const dependencies = workInProgress.dependencies;
|
||||
const firstContext = dependencies.firstContext;
|
||||
if (
|
||||
firstContext !== null &&
|
||||
dependencies.expirationTime >= renderExpirationTime
|
||||
) {
|
||||
// Context list has a pending update. Mark that this fiber performed work.
|
||||
markWorkInProgressReceivedUpdate();
|
||||
if (dependencies !== null) {
|
||||
const firstContext = dependencies.firstContext;
|
||||
if (firstContext !== null) {
|
||||
if (dependencies.expirationTime >= renderExpirationTime) {
|
||||
// Context list has a pending update. Mark that this fiber performed work.
|
||||
markWorkInProgressReceivedUpdate();
|
||||
}
|
||||
// Reset the work-in-progress list
|
||||
dependencies.firstContext = null;
|
||||
}
|
||||
}
|
||||
|
||||
// Reset the work-in-progress list
|
||||
dependencies.firstContext = null;
|
||||
}
|
||||
|
||||
export function readContext<T>(
|
||||
@@ -375,9 +374,11 @@ export function readContext<T>(
|
||||
|
||||
// This is the first dependency for this component. Create a new list.
|
||||
lastContextDependency = contextItem;
|
||||
const dependencies = currentlyRenderingFiber.dependencies;
|
||||
dependencies.expirationTime = NoWork;
|
||||
dependencies.firstContext = contextItem;
|
||||
currentlyRenderingFiber.dependencies = {
|
||||
expirationTime: NoWork,
|
||||
firstContext: contextItem,
|
||||
events: null,
|
||||
};
|
||||
} else {
|
||||
// Append a new context item.
|
||||
lastContextDependency = lastContextDependency.next = contextItem;
|
||||
|
||||
Reference in New Issue
Block a user