Skip to content

Commit 6b6cf83

Browse files
authored
Land forked reconciler changes (#24817)
This applies forked changes from the "new" reconciler to the "old" one. Includes: - d410f0a [FORKED] Bugfix: Offscreen instance is null during setState - 58bb117 [FORKED] Check for infinite update loops even if unmounted - 31882b5 [FORKED] Bugfix: Revealing a hidden update - 17691ac [FORKED] Don't update childLanes until after current render
1 parent 4e1fcfa commit 6b6cf83

12 files changed

+307
-191
lines changed

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

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -90,8 +90,10 @@ import type {Lanes, Lane} from './ReactFiberLane.old';
9090
import {
9191
NoLane,
9292
NoLanes,
93+
OffscreenLane,
9394
isSubsetOfLanes,
9495
mergeLanes,
96+
removeLanes,
9597
isTransitionLane,
9698
intersectLanes,
9799
markRootEntangled,
@@ -108,6 +110,7 @@ import {StrictLegacyMode} from './ReactTypeOfMode';
108110
import {
109111
markSkippedUpdateLanes,
110112
isUnsafeClassRenderPhaseUpdate,
113+
getWorkInProgressRootRenderLanes,
111114
} from './ReactFiberWorkLoop.old';
112115
import {
113116
enqueueConcurrentClassUpdate,
@@ -132,7 +135,6 @@ export type Update<State> = {|
132135

133136
export type SharedQueue<State> = {|
134137
pending: Update<State> | null,
135-
interleaved: Update<State> | null,
136138
lanes: Lanes,
137139
|};
138140

@@ -172,7 +174,6 @@ export function initializeUpdateQueue<State>(fiber: Fiber): void {
172174
lastBaseUpdate: null,
173175
shared: {
174176
pending: null,
175-
interleaved: null,
176177
lanes: NoLanes,
177178
},
178179
effects: null,
@@ -525,9 +526,23 @@ export function processUpdateQueue<State>(
525526

526527
let update = firstBaseUpdate;
527528
do {
528-
const updateLane = update.lane;
529+
// TODO: Don't need this field anymore
529530
const updateEventTime = update.eventTime;
530-
if (!isSubsetOfLanes(renderLanes, updateLane)) {
531+
532+
// An extra OffscreenLane bit is added to updates that were made to
533+
// a hidden tree, so that we can distinguish them from updates that were
534+
// already there when the tree was hidden.
535+
const updateLane = removeLanes(update.lane, OffscreenLane);
536+
const isHiddenUpdate = updateLane !== update.lane;
537+
538+
// Check if this update was made while the tree was hidden. If so, then
539+
// it's not a "base" update and we should disregard the extra base lanes
540+
// that were added to renderLanes when we entered the Offscreen tree.
541+
const shouldSkipUpdate = isHiddenUpdate
542+
? !isSubsetOfLanes(getWorkInProgressRootRenderLanes(), updateLane)
543+
: !isSubsetOfLanes(renderLanes, updateLane);
544+
545+
if (shouldSkipUpdate) {
531546
// Priority is insufficient. Skip this update. If this is the first
532547
// skipped update, the previous update/state is the new base
533548
// update/state.
@@ -622,17 +637,7 @@ export function processUpdateQueue<State>(
622637
queue.firstBaseUpdate = newFirstBaseUpdate;
623638
queue.lastBaseUpdate = newLastBaseUpdate;
624639

625-
// Interleaved updates are stored on a separate queue. We aren't going to
626-
// process them during this render, but we do need to track which lanes
627-
// are remaining.
628-
const lastInterleaved = queue.shared.interleaved;
629-
if (lastInterleaved !== null) {
630-
let interleaved = lastInterleaved;
631-
do {
632-
newLanes = mergeLanes(newLanes, interleaved.lane);
633-
interleaved = ((interleaved: any).next: Update<State>);
634-
} while (interleaved !== lastInterleaved);
635-
} else if (firstBaseUpdate === null) {
640+
if (firstBaseUpdate === null) {
636641
// `queue.lanes` is used for entangling transitions. We can set it back to
637642
// zero once the queue is empty.
638643
queue.shared.lanes = NoLanes;

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

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1522,17 +1522,15 @@ function completeWork(
15221522
// at offscreen priority.
15231523
if (includesSomeLane(subtreeRenderLanes, (OffscreenLane: Lane))) {
15241524
bubbleProperties(workInProgress);
1525-
if (supportsMutation) {
1526-
// Check if there was an insertion or update in the hidden subtree.
1527-
// If so, we need to hide those nodes in the commit phase, so
1528-
// schedule a visibility effect.
1529-
if (
1530-
(!enableLegacyHidden ||
1531-
workInProgress.tag !== LegacyHiddenComponent) &&
1532-
workInProgress.subtreeFlags & (Placement | Update)
1533-
) {
1534-
workInProgress.flags |= Visibility;
1535-
}
1525+
// Check if there was an insertion or update in the hidden subtree.
1526+
// If so, we need to hide those nodes in the commit phase, so
1527+
// schedule a visibility effect.
1528+
if (
1529+
(!enableLegacyHidden ||
1530+
workInProgress.tag !== LegacyHiddenComponent) &&
1531+
workInProgress.subtreeFlags & (Placement | Update)
1532+
) {
1533+
workInProgress.flags |= Visibility;
15361534
}
15371535
}
15381536
}

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

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1522,17 +1522,15 @@ function completeWork(
15221522
// at offscreen priority.
15231523
if (includesSomeLane(subtreeRenderLanes, (OffscreenLane: Lane))) {
15241524
bubbleProperties(workInProgress);
1525-
if (supportsMutation) {
1526-
// Check if there was an insertion or update in the hidden subtree.
1527-
// If so, we need to hide those nodes in the commit phase, so
1528-
// schedule a visibility effect.
1529-
if (
1530-
(!enableLegacyHidden ||
1531-
workInProgress.tag !== LegacyHiddenComponent) &&
1532-
workInProgress.subtreeFlags & (Placement | Update)
1533-
) {
1534-
workInProgress.flags |= Visibility;
1535-
}
1525+
// Check if there was an insertion or update in the hidden subtree.
1526+
// If so, we need to hide those nodes in the commit phase, so
1527+
// schedule a visibility effect.
1528+
if (
1529+
(!enableLegacyHidden ||
1530+
workInProgress.tag !== LegacyHiddenComponent) &&
1531+
workInProgress.subtreeFlags & (Placement | Update)
1532+
) {
1533+
workInProgress.flags |= Visibility;
15361534
}
15371535
}
15381536
}

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

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,8 +166,14 @@ export function unsafe_markUpdateLaneFromFiberToRoot(
166166
sourceFiber: Fiber,
167167
lane: Lane,
168168
): FiberRoot | null {
169+
// NOTE: For Hyrum's Law reasons, if an infinite update loop is detected, it
170+
// should throw before `markUpdateLaneFromFiberToRoot` is called. But this is
171+
// undefined behavior and we can change it if we need to; it just so happens
172+
// that, at the time of this writing, there's an internal product test that
173+
// happens to rely on this.
174+
const root = getRootForUpdatedFiber(sourceFiber);
169175
markUpdateLaneFromFiberToRoot(sourceFiber, null, lane);
170-
return getRootForUpdatedFiber(sourceFiber);
176+
return root;
171177
}
172178

173179
function markUpdateLaneFromFiberToRoot(

0 commit comments

Comments
 (0)