Skip to content

Commit

Permalink
Convert passive mount phase to tree traversal
Browse files Browse the repository at this point in the history
  • Loading branch information
acdlite committed Dec 18, 2020
1 parent 19e15a3 commit d37d7a4
Show file tree
Hide file tree
Showing 4 changed files with 248 additions and 136 deletions.
121 changes: 121 additions & 0 deletions packages/react-reconciler/src/ReactFiberCommitWork.new.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,15 @@ import {
Placement,
Snapshot,
Update,
Passive,
PassiveMask,
} from './ReactFiberFlags';
import getComponentName from 'shared/getComponentName';
import invariant from 'shared/invariant';
import {
resetCurrentFiber as resetCurrentDebugFiberInDEV,
setCurrentFiber as setCurrentDebugFiberInDEV,
} from './ReactCurrentFiber';

import {onCommitUnmount} from './ReactFiberDevToolsHook.new';
import {resolveDefaultProps} from './ReactFiberLazyComponent.new';
Expand All @@ -78,6 +84,8 @@ import {
getCommitTime,
recordLayoutEffectDuration,
startLayoutEffectTimer,
recordPassiveEffectDuration,
startPassiveEffectTimer,
} from './ReactProfilerTimer.new';
import {ProfileMode} from './ReactTypeOfMode';
import {commitUpdateQueue} from './ReactUpdateQueue.new';
Expand Down Expand Up @@ -134,6 +142,8 @@ if (__DEV__) {

const PossiblyWeakSet = typeof WeakSet === 'function' ? WeakSet : Set;

let nextEffect: Fiber | null = null;

const callComponentWillUnmountWithTimer = function(current, instance) {
instance.props = current.memoizedProps;
instance.state = current.memoizedState;
Expand Down Expand Up @@ -1798,6 +1808,117 @@ function commitResetTextContent(current: Fiber) {
resetTextContent(current.stateNode);
}

export function commitPassiveMountEffects(
root: FiberRoot,
firstChild: Fiber,
): void {
nextEffect = firstChild;
commitPassiveMountEffects_begin(firstChild, root);
}

function commitPassiveMountEffects_begin(subtreeRoot: Fiber, root: FiberRoot) {
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);
}
}
}

function commitPassiveMountEffects_complete(
subtreeRoot: Fiber,
root: FiberRoot,
) {
while (nextEffect !== null) {
const fiber = nextEffect;
if ((fiber.flags & Passive) !== NoFlags) {
if (__DEV__) {
setCurrentDebugFiberInDEV(fiber);
invokeGuardedCallback(
null,
commitPassiveMountOnFiber,
null,
root,
fiber,
);
if (hasCaughtError()) {
const error = clearCaughtError();
captureCommitPhaseError(fiber, error);
}
resetCurrentDebugFiberInDEV();
} else {
try {
commitPassiveMountOnFiber(root, fiber);
} catch (error) {
captureCommitPhaseError(fiber, error);
}
}
}

if (fiber === subtreeRoot) {
nextEffect = null;
return;
}

const sibling = fiber.sibling;
if (sibling !== null) {
ensureCorrectReturnPointer(sibling, fiber.return);
nextEffect = sibling;
return;
}

nextEffect = fiber.return;
}
}

function commitPassiveMountOnFiber(
finishedRoot: FiberRoot,
finishedWork: Fiber,
): void {
switch (finishedWork.tag) {
case FunctionComponent:
case ForwardRef:
case SimpleMemoComponent: {
if (
enableProfilerTimer &&
enableProfilerCommitHooks &&
finishedWork.mode & ProfileMode
) {
startPassiveEffectTimer();
try {
commitHookEffectListMount(HookPassive | HookHasEffect, finishedWork);
} finally {
recordPassiveEffectDuration(finishedWork);
}
} else {
commitHookEffectListMount(HookPassive | HookHasEffect, finishedWork);
}
break;
}
}
}

let didWarnWrongReturnPointer = false;
function ensureCorrectReturnPointer(fiber, expectedReturnFiber) {
if (__DEV__) {
if (!didWarnWrongReturnPointer && fiber.return !== expectedReturnFiber) {
didWarnWrongReturnPointer = true;
console.error(
'Internal React error: Return pointer is inconsistent ' +
'with parent.',
);
}
}

// TODO: Remove this assignment once we're confident that it won't break
// anything, by checking the warning logs for the above invariant
fiber.return = expectedReturnFiber;
}

export {
commitBeforeMutationLifeCycles,
commitResetTextContent,
Expand Down
121 changes: 121 additions & 0 deletions packages/react-reconciler/src/ReactFiberCommitWork.old.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,15 @@ import {
Placement,
Snapshot,
Update,
Passive,
PassiveMask,
} from './ReactFiberFlags';
import getComponentName from 'shared/getComponentName';
import invariant from 'shared/invariant';
import {
resetCurrentFiber as resetCurrentDebugFiberInDEV,
setCurrentFiber as setCurrentDebugFiberInDEV,
} from './ReactCurrentFiber';

import {onCommitUnmount} from './ReactFiberDevToolsHook.old';
import {resolveDefaultProps} from './ReactFiberLazyComponent.old';
Expand All @@ -78,6 +84,8 @@ import {
getCommitTime,
recordLayoutEffectDuration,
startLayoutEffectTimer,
recordPassiveEffectDuration,
startPassiveEffectTimer,
} from './ReactProfilerTimer.old';
import {ProfileMode} from './ReactTypeOfMode';
import {commitUpdateQueue} from './ReactUpdateQueue.old';
Expand Down Expand Up @@ -134,6 +142,8 @@ if (__DEV__) {

const PossiblyWeakSet = typeof WeakSet === 'function' ? WeakSet : Set;

let nextEffect: Fiber | null = null;

const callComponentWillUnmountWithTimer = function(current, instance) {
instance.props = current.memoizedProps;
instance.state = current.memoizedState;
Expand Down Expand Up @@ -1798,6 +1808,117 @@ function commitResetTextContent(current: Fiber) {
resetTextContent(current.stateNode);
}

export function commitPassiveMountEffects(
root: FiberRoot,
firstChild: Fiber,
): void {
nextEffect = firstChild;
commitPassiveMountEffects_begin(firstChild, root);
}

function commitPassiveMountEffects_begin(subtreeRoot: Fiber, root: FiberRoot) {
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);
}
}
}

function commitPassiveMountEffects_complete(
subtreeRoot: Fiber,
root: FiberRoot,
) {
while (nextEffect !== null) {
const fiber = nextEffect;
if ((fiber.flags & Passive) !== NoFlags) {
if (__DEV__) {
setCurrentDebugFiberInDEV(fiber);
invokeGuardedCallback(
null,
commitPassiveMountOnFiber,
null,
root,
fiber,
);
if (hasCaughtError()) {
const error = clearCaughtError();
captureCommitPhaseError(fiber, error);
}
resetCurrentDebugFiberInDEV();
} else {
try {
commitPassiveMountOnFiber(root, fiber);
} catch (error) {
captureCommitPhaseError(fiber, error);
}
}
}

if (fiber === subtreeRoot) {
nextEffect = null;
return;
}

const sibling = fiber.sibling;
if (sibling !== null) {
ensureCorrectReturnPointer(sibling, fiber.return);
nextEffect = sibling;
return;
}

nextEffect = fiber.return;
}
}

function commitPassiveMountOnFiber(
finishedRoot: FiberRoot,
finishedWork: Fiber,
): void {
switch (finishedWork.tag) {
case FunctionComponent:
case ForwardRef:
case SimpleMemoComponent: {
if (
enableProfilerTimer &&
enableProfilerCommitHooks &&
finishedWork.mode & ProfileMode
) {
startPassiveEffectTimer();
try {
commitHookEffectListMount(HookPassive | HookHasEffect, finishedWork);
} finally {
recordPassiveEffectDuration(finishedWork);
}
} else {
commitHookEffectListMount(HookPassive | HookHasEffect, finishedWork);
}
break;
}
}
}

let didWarnWrongReturnPointer = false;
function ensureCorrectReturnPointer(fiber, expectedReturnFiber) {
if (__DEV__) {
if (!didWarnWrongReturnPointer && fiber.return !== expectedReturnFiber) {
didWarnWrongReturnPointer = true;
console.error(
'Internal React error: Return pointer is inconsistent ' +
'with parent.',
);
}
}

// TODO: Remove this assignment once we're confident that it won't break
// anything, by checking the warning logs for the above invariant
fiber.return = expectedReturnFiber;
}

export {
commitBeforeMutationLifeCycles,
commitResetTextContent,
Expand Down
Loading

0 comments on commit d37d7a4

Please sign in to comment.