Skip to content

Commit

Permalink
moved mutation code to passive
Browse files Browse the repository at this point in the history
  • Loading branch information
lunaruan committed Apr 7, 2022
1 parent c89a15c commit 09d1fbb
Show file tree
Hide file tree
Showing 6 changed files with 162 additions and 104 deletions.
63 changes: 33 additions & 30 deletions packages/react-reconciler/src/ReactFiberCommitWork.new.js
Original file line number Diff line number Diff line change
Expand Up @@ -2206,32 +2206,6 @@ function commitMutationEffectsOnFiber(
// because of the shared reconciliation logic below.
const flags = finishedWork.flags;

if (enableTransitionTracing) {
switch (finishedWork.tag) {
case HostRoot: {
const state = finishedWork.memoizedState;
const transitions = state.transitions;
if (transitions !== null) {
transitions.forEach(transition => {
// TODO(luna) Do we want to log TransitionStart in the startTransition callback instead?
addTransitionStartCallbackToPendingTransition({
transitionName: transition.name,
startTime: transition.startTime,
});

addTransitionCompleteCallbackToPendingTransition({
transitionName: transition.name,
startTime: transition.startTime,
});
});

clearTransitionsForLanes(root, lanes);
state.transitions = null;
}
}
}
}

if (flags & ContentReset) {
commitResetTextContent(finishedWork);
}
Expand Down Expand Up @@ -2618,34 +2592,41 @@ function reappearLayoutEffects_complete(subtreeRoot: Fiber) {
export function commitPassiveMountEffects(
root: FiberRoot,
finishedWork: Fiber,
committedLanes: Lanes,
): void {
nextEffect = finishedWork;
commitPassiveMountEffects_begin(finishedWork, root);
commitPassiveMountEffects_begin(finishedWork, root, committedLanes);
}

function commitPassiveMountEffects_begin(subtreeRoot: Fiber, root: FiberRoot) {
function commitPassiveMountEffects_begin(
subtreeRoot: Fiber,
root: FiberRoot,
committedLanes: Lanes,
) {
while (nextEffect !== null) {
const fiber = nextEffect;
const firstChild = fiber.child;
if ((fiber.subtreeFlags & PassiveMask) !== NoFlags && firstChild !== null) {
ensureCorrectReturnPointer(firstChild, fiber);
nextEffect = firstChild;
} else {
commitPassiveMountEffects_complete(subtreeRoot, root);
commitPassiveMountEffects_complete(subtreeRoot, root, committedLanes);
}
}
}

function commitPassiveMountEffects_complete(
subtreeRoot: Fiber,
root: FiberRoot,
committedLanes: Lanes,
) {
while (nextEffect !== null) {
const fiber = nextEffect;

if ((fiber.flags & Passive) !== NoFlags) {
setCurrentDebugFiberInDEV(fiber);
try {
commitPassiveMountOnFiber(root, fiber);
commitPassiveMountOnFiber(root, fiber, committedLanes);
} catch (error) {
reportUncaughtErrorInDEV(error);
captureCommitPhaseError(fiber, fiber.return, error);
Expand All @@ -2672,6 +2653,7 @@ function commitPassiveMountEffects_complete(
function commitPassiveMountOnFiber(
finishedRoot: FiberRoot,
finishedWork: Fiber,
committedLanes: Lanes,
): void {
switch (finishedWork.tag) {
case FunctionComponent:
Expand Down Expand Up @@ -2713,6 +2695,27 @@ function commitPassiveMountOnFiber(
}
}
}

if (enableTransitionTracing) {
const transitions = finishedWork.memoizedState.transitions;
if (transitions !== null) {
transitions.forEach(transition => {
// TODO(luna) Do we want to log TransitionStart in the startTransition callback instead?
addTransitionStartCallbackToPendingTransition({
transitionName: transition.name,
startTime: transition.startTime,
});

addTransitionCompleteCallbackToPendingTransition({
transitionName: transition.name,
startTime: transition.startTime,
});
});

clearTransitionsForLanes(finishedRoot, committedLanes);
finishedWork.memoizedState.transitions = null;
}
}
break;
}
case LegacyHiddenComponent:
Expand Down
63 changes: 33 additions & 30 deletions packages/react-reconciler/src/ReactFiberCommitWork.old.js
Original file line number Diff line number Diff line change
Expand Up @@ -2206,32 +2206,6 @@ function commitMutationEffectsOnFiber(
// because of the shared reconciliation logic below.
const flags = finishedWork.flags;

if (enableTransitionTracing) {
switch (finishedWork.tag) {
case HostRoot: {
const state = finishedWork.memoizedState;
const transitions = state.transitions;
if (transitions !== null) {
transitions.forEach(transition => {
// TODO(luna) Do we want to log TransitionStart in the startTransition callback instead?
addTransitionStartCallbackToPendingTransition({
transitionName: transition.name,
startTime: transition.startTime,
});

addTransitionCompleteCallbackToPendingTransition({
transitionName: transition.name,
startTime: transition.startTime,
});
});

clearTransitionsForLanes(root, lanes);
state.transitions = null;
}
}
}
}

if (flags & ContentReset) {
commitResetTextContent(finishedWork);
}
Expand Down Expand Up @@ -2618,34 +2592,41 @@ function reappearLayoutEffects_complete(subtreeRoot: Fiber) {
export function commitPassiveMountEffects(
root: FiberRoot,
finishedWork: Fiber,
committedLanes: Lanes,
): void {
nextEffect = finishedWork;
commitPassiveMountEffects_begin(finishedWork, root);
commitPassiveMountEffects_begin(finishedWork, root, committedLanes);
}

function commitPassiveMountEffects_begin(subtreeRoot: Fiber, root: FiberRoot) {
function commitPassiveMountEffects_begin(
subtreeRoot: Fiber,
root: FiberRoot,
committedLanes: Lanes,
) {
while (nextEffect !== null) {
const fiber = nextEffect;
const firstChild = fiber.child;
if ((fiber.subtreeFlags & PassiveMask) !== NoFlags && firstChild !== null) {
ensureCorrectReturnPointer(firstChild, fiber);
nextEffect = firstChild;
} else {
commitPassiveMountEffects_complete(subtreeRoot, root);
commitPassiveMountEffects_complete(subtreeRoot, root, committedLanes);
}
}
}

function commitPassiveMountEffects_complete(
subtreeRoot: Fiber,
root: FiberRoot,
committedLanes: Lanes,
) {
while (nextEffect !== null) {
const fiber = nextEffect;

if ((fiber.flags & Passive) !== NoFlags) {
setCurrentDebugFiberInDEV(fiber);
try {
commitPassiveMountOnFiber(root, fiber);
commitPassiveMountOnFiber(root, fiber, committedLanes);
} catch (error) {
reportUncaughtErrorInDEV(error);
captureCommitPhaseError(fiber, fiber.return, error);
Expand All @@ -2672,6 +2653,7 @@ function commitPassiveMountEffects_complete(
function commitPassiveMountOnFiber(
finishedRoot: FiberRoot,
finishedWork: Fiber,
committedLanes: Lanes,
): void {
switch (finishedWork.tag) {
case FunctionComponent:
Expand Down Expand Up @@ -2713,6 +2695,27 @@ function commitPassiveMountOnFiber(
}
}
}

if (enableTransitionTracing) {
const transitions = finishedWork.memoizedState.transitions;
if (transitions !== null) {
transitions.forEach(transition => {
// TODO(luna) Do we want to log TransitionStart in the startTransition callback instead?
addTransitionStartCallbackToPendingTransition({
transitionName: transition.name,
startTime: transition.startTime,
});

addTransitionCompleteCallbackToPendingTransition({
transitionName: transition.name,
startTime: transition.startTime,
});
});

clearTransitionsForLanes(finishedRoot, committedLanes);
finishedWork.memoizedState.transitions = null;
}
}
break;
}
case LegacyHiddenComponent:
Expand Down
19 changes: 19 additions & 0 deletions packages/react-reconciler/src/ReactFiberCompleteWork.new.js
Original file line number Diff line number Diff line change
Expand Up @@ -862,6 +862,14 @@ function completeWork(
}
case HostRoot: {
const fiberRoot = (workInProgress.stateNode: FiberRoot);

if (enableTransitionTracing) {
const transitions = workInProgress.memoizedState.transitions;
if (transitions !== null) {
workInProgress.flags |= Passive;
}
}

if (enableCache) {
popRootTransition(fiberRoot, renderLanes);

Expand Down Expand Up @@ -918,6 +926,11 @@ function completeWork(
}
updateHostContainer(current, workInProgress);
bubbleProperties(workInProgress);
if (enableTransitionTracing) {
if ((workInProgress.subtreeFlags & Visibility) !== NoFlags) {
workInProgress.flags |= Passive;
}
}
return null;
}
case HostComponent: {
Expand Down Expand Up @@ -1187,6 +1200,12 @@ function completeWork(
const offscreenFiber: Fiber = (workInProgress.child: any);
offscreenFiber.flags |= Visibility;

// If the suspended state of the boundary changes, we need to schedule
// a passive effect, which is when we process the transitions
if (enableTransitionTracing) {
offscreenFiber.flags |= Passive;
}

// TODO: This will still suspend a synchronous tree if anything
// in the concurrent tree already suspended during this render.
// This is a known bug.
Expand Down
19 changes: 19 additions & 0 deletions packages/react-reconciler/src/ReactFiberCompleteWork.old.js
Original file line number Diff line number Diff line change
Expand Up @@ -862,6 +862,14 @@ function completeWork(
}
case HostRoot: {
const fiberRoot = (workInProgress.stateNode: FiberRoot);

if (enableTransitionTracing) {
const transitions = workInProgress.memoizedState.transitions;
if (transitions !== null) {
workInProgress.flags |= Passive;
}
}

if (enableCache) {
popRootTransition(fiberRoot, renderLanes);

Expand Down Expand Up @@ -918,6 +926,11 @@ function completeWork(
}
updateHostContainer(current, workInProgress);
bubbleProperties(workInProgress);
if (enableTransitionTracing) {
if ((workInProgress.subtreeFlags & Visibility) !== NoFlags) {
workInProgress.flags |= Passive;
}
}
return null;
}
case HostComponent: {
Expand Down Expand Up @@ -1187,6 +1200,12 @@ function completeWork(
const offscreenFiber: Fiber = (workInProgress.child: any);
offscreenFiber.flags |= Visibility;

// If the suspended state of the boundary changes, we need to schedule
// a passive effect, which is when we process the transitions
if (enableTransitionTracing) {
offscreenFiber.flags |= Passive;
}

// TODO: This will still suspend a synchronous tree if anything
// in the concurrent tree already suspended during this render.
// This is a known bug.
Expand Down
51 changes: 29 additions & 22 deletions packages/react-reconciler/src/ReactFiberWorkLoop.new.js
Original file line number Diff line number Diff line change
Expand Up @@ -2301,27 +2301,6 @@ function commitRootImpl(
// If layout work was scheduled, flush it now.
flushSyncCallbacks();

if (enableTransitionTracing) {
const prevPendingTransitionCallbacks = currentPendingTransitionCallbacks;
const prevRootTransitionCallbacks = root.transitionCallbacks;
if (
prevPendingTransitionCallbacks !== null &&
prevRootTransitionCallbacks !== null
) {
// TODO(luna) Refactor this code into the Host Config
const endTime = now();
currentPendingTransitionCallbacks = null;

scheduleCallback(IdleSchedulerPriority, () =>
processTransitionCallbacks(
prevPendingTransitionCallbacks,
endTime,
prevRootTransitionCallbacks,
),
);
}
}

if (__DEV__) {
if (enableDebugTracing) {
logCommitStopped();
Expand Down Expand Up @@ -2433,7 +2412,7 @@ function flushPassiveEffectsImpl() {
executionContext |= CommitContext;

commitPassiveUnmountEffects(root.current);
commitPassiveMountEffects(root, root.current);
commitPassiveMountEffects(root, root.current, lanes);

// TODO: Move to commitPassiveMountEffects
if (enableProfilerTimer && enableProfilerCommitHooks) {
Expand Down Expand Up @@ -2463,6 +2442,34 @@ function flushPassiveEffectsImpl() {

flushSyncCallbacks();

if (enableTransitionTracing) {
const prevPendingTransitionCallbacks = currentPendingTransitionCallbacks;
const prevRootTransitionCallbacks = root.transitionCallbacks;
if (
prevPendingTransitionCallbacks !== null &&
prevRootTransitionCallbacks !== null
) {
// TODO(luna) Refactor this code into the Host Config
// TODO(luna) The end time here is not necessarily accurate
// because passive effects could be called before paint
// (synchronously) or after paint (normally). We need
// to come up with a way to get the correct end time for both cases.
// One solution is in the host config, if the passive effects
// have not yet been run, make a call to flush the passive effects
// right after paint.
const endTime = now();
currentPendingTransitionCallbacks = null;

scheduleCallback(IdleSchedulerPriority, () =>
processTransitionCallbacks(
prevPendingTransitionCallbacks,
endTime,
prevRootTransitionCallbacks,
),
);
}
}

// If additional passive effects were scheduled, increment a counter. If this
// exceeds the limit, we'll fire a warning.
nestedPassiveUpdateCount =
Expand Down
Loading

0 comments on commit 09d1fbb

Please sign in to comment.