Skip to content

Commit

Permalink
Land forked reconciler changes (#24817)
Browse files Browse the repository at this point in the history
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
  • Loading branch information
acdlite authored Jun 30, 2022
1 parent 4e1fcfa commit 6b6cf83
Show file tree
Hide file tree
Showing 12 changed files with 307 additions and 191 deletions.
35 changes: 20 additions & 15 deletions packages/react-reconciler/src/ReactFiberClassUpdateQueue.old.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,10 @@ import type {Lanes, Lane} from './ReactFiberLane.old';
import {
NoLane,
NoLanes,
OffscreenLane,
isSubsetOfLanes,
mergeLanes,
removeLanes,
isTransitionLane,
intersectLanes,
markRootEntangled,
Expand All @@ -108,6 +110,7 @@ import {StrictLegacyMode} from './ReactTypeOfMode';
import {
markSkippedUpdateLanes,
isUnsafeClassRenderPhaseUpdate,
getWorkInProgressRootRenderLanes,
} from './ReactFiberWorkLoop.old';
import {
enqueueConcurrentClassUpdate,
Expand All @@ -132,7 +135,6 @@ export type Update<State> = {|

export type SharedQueue<State> = {|
pending: Update<State> | null,
interleaved: Update<State> | null,
lanes: Lanes,
|};

Expand Down Expand Up @@ -172,7 +174,6 @@ export function initializeUpdateQueue<State>(fiber: Fiber): void {
lastBaseUpdate: null,
shared: {
pending: null,
interleaved: null,
lanes: NoLanes,
},
effects: null,
Expand Down Expand Up @@ -525,9 +526,23 @@ export function processUpdateQueue<State>(

let update = firstBaseUpdate;
do {
const updateLane = update.lane;
// TODO: Don't need this field anymore
const updateEventTime = update.eventTime;
if (!isSubsetOfLanes(renderLanes, updateLane)) {

// An extra OffscreenLane bit is added to updates that were made to
// a hidden tree, so that we can distinguish them from updates that were
// already there when the tree was hidden.
const updateLane = removeLanes(update.lane, OffscreenLane);
const isHiddenUpdate = updateLane !== update.lane;

// Check if this update was made while the tree was hidden. If so, then
// it's not a "base" update and we should disregard the extra base lanes
// that were added to renderLanes when we entered the Offscreen tree.
const shouldSkipUpdate = isHiddenUpdate
? !isSubsetOfLanes(getWorkInProgressRootRenderLanes(), updateLane)
: !isSubsetOfLanes(renderLanes, updateLane);

if (shouldSkipUpdate) {
// Priority is insufficient. Skip this update. If this is the first
// skipped update, the previous update/state is the new base
// update/state.
Expand Down Expand Up @@ -622,17 +637,7 @@ export function processUpdateQueue<State>(
queue.firstBaseUpdate = newFirstBaseUpdate;
queue.lastBaseUpdate = newLastBaseUpdate;

// Interleaved updates are stored on a separate queue. We aren't going to
// process them during this render, but we do need to track which lanes
// are remaining.
const lastInterleaved = queue.shared.interleaved;
if (lastInterleaved !== null) {
let interleaved = lastInterleaved;
do {
newLanes = mergeLanes(newLanes, interleaved.lane);
interleaved = ((interleaved: any).next: Update<State>);
} while (interleaved !== lastInterleaved);
} else if (firstBaseUpdate === null) {
if (firstBaseUpdate === null) {
// `queue.lanes` is used for entangling transitions. We can set it back to
// zero once the queue is empty.
queue.shared.lanes = NoLanes;
Expand Down
20 changes: 9 additions & 11 deletions packages/react-reconciler/src/ReactFiberCompleteWork.new.js
Original file line number Diff line number Diff line change
Expand Up @@ -1522,17 +1522,15 @@ function completeWork(
// at offscreen priority.
if (includesSomeLane(subtreeRenderLanes, (OffscreenLane: Lane))) {
bubbleProperties(workInProgress);
if (supportsMutation) {
// Check if there was an insertion or update in the hidden subtree.
// If so, we need to hide those nodes in the commit phase, so
// schedule a visibility effect.
if (
(!enableLegacyHidden ||
workInProgress.tag !== LegacyHiddenComponent) &&
workInProgress.subtreeFlags & (Placement | Update)
) {
workInProgress.flags |= Visibility;
}
// Check if there was an insertion or update in the hidden subtree.
// If so, we need to hide those nodes in the commit phase, so
// schedule a visibility effect.
if (
(!enableLegacyHidden ||
workInProgress.tag !== LegacyHiddenComponent) &&
workInProgress.subtreeFlags & (Placement | Update)
) {
workInProgress.flags |= Visibility;
}
}
}
Expand Down
20 changes: 9 additions & 11 deletions packages/react-reconciler/src/ReactFiberCompleteWork.old.js
Original file line number Diff line number Diff line change
Expand Up @@ -1522,17 +1522,15 @@ function completeWork(
// at offscreen priority.
if (includesSomeLane(subtreeRenderLanes, (OffscreenLane: Lane))) {
bubbleProperties(workInProgress);
if (supportsMutation) {
// Check if there was an insertion or update in the hidden subtree.
// If so, we need to hide those nodes in the commit phase, so
// schedule a visibility effect.
if (
(!enableLegacyHidden ||
workInProgress.tag !== LegacyHiddenComponent) &&
workInProgress.subtreeFlags & (Placement | Update)
) {
workInProgress.flags |= Visibility;
}
// Check if there was an insertion or update in the hidden subtree.
// If so, we need to hide those nodes in the commit phase, so
// schedule a visibility effect.
if (
(!enableLegacyHidden ||
workInProgress.tag !== LegacyHiddenComponent) &&
workInProgress.subtreeFlags & (Placement | Update)
) {
workInProgress.flags |= Visibility;
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,8 +166,14 @@ export function unsafe_markUpdateLaneFromFiberToRoot(
sourceFiber: Fiber,
lane: Lane,
): FiberRoot | null {
// NOTE: For Hyrum's Law reasons, if an infinite update loop is detected, it
// should throw before `markUpdateLaneFromFiberToRoot` is called. But this is
// undefined behavior and we can change it if we need to; it just so happens
// that, at the time of this writing, there's an internal product test that
// happens to rely on this.
const root = getRootForUpdatedFiber(sourceFiber);
markUpdateLaneFromFiberToRoot(sourceFiber, null, lane);
return getRootForUpdatedFiber(sourceFiber);
return root;
}

function markUpdateLaneFromFiberToRoot(
Expand Down
Loading

0 comments on commit 6b6cf83

Please sign in to comment.