Skip to content

Commit

Permalink
Land forked reconciler changes
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 committed Jun 29, 2022
1 parent 2e1c884 commit 6245ddf
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 6245ddf

Please sign in to comment.