Skip to content

Commit

Permalink
add transition name to startTransition
Browse files Browse the repository at this point in the history
Add a transitionName to start transition, store the transition start time and name in the batch config, and pass it to the root on render
  • Loading branch information
lunaruan committed Jan 12, 2022
1 parent 8bc65be commit 3ba1704
Show file tree
Hide file tree
Showing 16 changed files with 304 additions and 13 deletions.
6 changes: 5 additions & 1 deletion packages/react-debug-tools/src/ReactDebugHooks.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import type {
MutableSourceSubscribeFn,
ReactContext,
ReactProviderType,
StartTransitionOptions,
} from 'shared/ReactTypes';
import type {
Fiber,
Expand Down Expand Up @@ -290,7 +291,10 @@ function useSyncExternalStore<T>(
return value;
}

function useTransition(): [boolean, (() => void) => void] {
function useTransition(): [
boolean,
(callback: () => void, options?: StartTransitionOptions) => void,
] {
// useTransition() composes multiple hooks internally.
// Advance the current hook index the same number of times
// so that subsequent hooks have the right memoized state.
Expand Down
4 changes: 4 additions & 0 deletions packages/react-dom/src/client/ReactDOMHostConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -1270,3 +1270,7 @@ export function scheduleTransitionCallbacks(
});
});
}

export const ReactDOMCurrentHostConfig = {
getCurrentEventStartTime: getCurrentEventStartTime,
};
7 changes: 7 additions & 0 deletions packages/react-dom/src/client/ReactDOMRoot.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ import type {
} from 'react-reconciler/src/ReactInternalTypes';

import {queueExplicitHydrationTarget} from '../events/ReactDOMEventReplaying';
import {ReactDOMCurrentHostConfig} from './ReactDOMHostConfig';

import ReactSharedInternals from 'shared/ReactSharedInternals';

const {ReactCurrentHostConfig} = ReactSharedInternals;

export type RootType = {
render(children: ReactNodeList): void,
Expand Down Expand Up @@ -189,6 +194,8 @@ export function createRoot(
container.nodeType === COMMENT_NODE ? container.parentNode : container;
listenToAllSupportedEvents(rootContainerElement);

ReactCurrentHostConfig.current = ReactDOMCurrentHostConfig;

return new ReactDOMRoot(root);
}

Expand Down
27 changes: 26 additions & 1 deletion packages/react-dom/src/events/ReactDOMEventListener.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@ import type {AnyNativeEvent} from '../events/PluginModuleType';
import type {FiberRoot} from 'react-reconciler/src/ReactInternalTypes';
import type {Container, SuspenseInstance} from '../client/ReactDOMHostConfig';
import type {DOMEventName} from '../events/DOMEventNames';
import {enableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay} from 'shared/ReactFeatureFlags';
import {
enableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay,
enableTransitionTracing,
} from 'shared/ReactFeatureFlags';
import {
isDiscreteEventThatRequiresHydration,
queueDiscreteEvent,
Expand Down Expand Up @@ -118,12 +121,23 @@ function dispatchDiscreteEvent(
const previousPriority = getCurrentUpdatePriority();
const prevTransition = ReactCurrentBatchConfig.transition;
ReactCurrentBatchConfig.transition = 0;

let prevTransitionInfo = null;
if (enableTransitionTracing) {
prevTransitionInfo = ReactCurrentBatchConfig.transitionInfo;
ReactCurrentBatchConfig.transitionInfo = null;
}

try {
setCurrentUpdatePriority(DiscreteEventPriority);
dispatchEvent(domEventName, eventSystemFlags, container, nativeEvent);
} finally {
setCurrentUpdatePriority(previousPriority);
ReactCurrentBatchConfig.transition = prevTransition;

if (enableTransitionTracing) {
ReactCurrentBatchConfig.transitionInfo = prevTransitionInfo;
}
}
}

Expand All @@ -136,12 +150,23 @@ function dispatchContinuousEvent(
const previousPriority = getCurrentUpdatePriority();
const prevTransition = ReactCurrentBatchConfig.transition;
ReactCurrentBatchConfig.transition = 0;

let prevTransitionInfo = null;
if (enableTransitionTracing) {
prevTransitionInfo = ReactCurrentBatchConfig.transitionInfo;
ReactCurrentBatchConfig.transitionInfo = null;
}

try {
setCurrentUpdatePriority(ContinuousEventPriority);
dispatchEvent(domEventName, eventSystemFlags, container, nativeEvent);
} finally {
setCurrentUpdatePriority(previousPriority);
ReactCurrentBatchConfig.transition = prevTransition;

if (enableTransitionTracing) {
ReactCurrentBatchConfig.transitionInfo = prevTransitionInfo;
}
}
}

Expand Down
70 changes: 66 additions & 4 deletions packages/react-reconciler/src/ReactFiberHooks.new.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import type {
MutableSourceGetSnapshotFn,
MutableSourceSubscribeFn,
ReactContext,
StartTransitionOptions,
} from 'shared/ReactTypes';
import type {Fiber, Dispatcher, HookType} from './ReactInternalTypes';
import type {Lanes, Lane} from './ReactFiberLane.new';
Expand All @@ -31,6 +32,7 @@ import {
enableLazyContextPropagation,
enableSuspenseLayoutEffectSemantics,
enableUseMutableSource,
enableTransitionTracing,
} from 'shared/ReactFeatureFlags';

import {
Expand Down Expand Up @@ -111,6 +113,7 @@ import {
import {pushInterleavedQueue} from './ReactFiberInterleavedUpdates.new';
import {warnOnSubscriptionInsideStartTransition} from 'shared/ReactFeatureFlags';
import {getTreeId} from './ReactFiberTreeContext.new';
import {getCurrentEventStartTime} from './ReactFiberHostConfig';

const {ReactCurrentDispatcher, ReactCurrentBatchConfig} = ReactSharedInternals;

Expand Down Expand Up @@ -1929,10 +1932,21 @@ function mountDeferredValue<T>(value: T): T {
mountEffect(() => {
const prevTransition = ReactCurrentBatchConfig.transition;
ReactCurrentBatchConfig.transition = 1;

let prevTransitionInfo = null;
if (enableTransitionTracing) {
prevTransitionInfo = ReactCurrentBatchConfig.transitionInfo;
ReactCurrentBatchConfig.transitionInfo = null;
}

try {
setValue(value);
} finally {
ReactCurrentBatchConfig.transition = prevTransition;

if (enableTransitionTracing) {
ReactCurrentBatchConfig.transitionInfo = prevTransitionInfo;
}
}
}, [value]);
return prevValue;
Expand All @@ -1943,10 +1957,21 @@ function updateDeferredValue<T>(value: T): T {
updateEffect(() => {
const prevTransition = ReactCurrentBatchConfig.transition;
ReactCurrentBatchConfig.transition = 1;

let prevTransitionInfo = null;
if (enableTransitionTracing) {
prevTransitionInfo = ReactCurrentBatchConfig.transitionInfo;
ReactCurrentBatchConfig.transitionInfo = null;
}

try {
setValue(value);
} finally {
ReactCurrentBatchConfig.transition = prevTransition;

if (enableTransitionTracing) {
ReactCurrentBatchConfig.transitionInfo = prevTransitionInfo;
}
}
}, [value]);
return prevValue;
Expand All @@ -1957,16 +1982,27 @@ function rerenderDeferredValue<T>(value: T): T {
updateEffect(() => {
const prevTransition = ReactCurrentBatchConfig.transition;
ReactCurrentBatchConfig.transition = 1;

let prevTransitionInfo = null;
if (enableTransitionTracing) {
prevTransitionInfo = ReactCurrentBatchConfig.transitionInfo;
ReactCurrentBatchConfig.transitionInfo = null;
}

try {
setValue(value);
} finally {
ReactCurrentBatchConfig.transition = prevTransition;

if (enableTransitionTracing) {
ReactCurrentBatchConfig.transitionInfo = prevTransitionInfo;
}
}
}, [value]);
return prevValue;
}

function startTransition(setPending, callback) {
function startTransition(setPending, callback, options) {
const previousPriority = getCurrentUpdatePriority();
setCurrentUpdatePriority(
higherEventPriority(previousPriority, ContinuousEventPriority),
Expand All @@ -1976,12 +2012,29 @@ function startTransition(setPending, callback) {

const prevTransition = ReactCurrentBatchConfig.transition;
ReactCurrentBatchConfig.transition = 1;

let prevTransitionInfo = null;
if (enableTransitionTracing) {
prevTransitionInfo = ReactCurrentBatchConfig.transitionInfo;
if (options !== undefined && options.name !== undefined) {
ReactCurrentBatchConfig.transitionInfo = {
name: options.name,
startTime: getCurrentEventStartTime(),
};
}
}

try {
setPending(false);
callback();
} finally {
setCurrentUpdatePriority(previousPriority);
ReactCurrentBatchConfig.transition = prevTransition;

if (enableTransitionTracing) {
ReactCurrentBatchConfig.transitionInfo = prevTransitionInfo;
}

if (__DEV__) {
if (
prevTransition !== 1 &&
Expand All @@ -2002,7 +2055,10 @@ function startTransition(setPending, callback) {
}
}

function mountTransition(): [boolean, (() => void) => void] {
function mountTransition(): [
boolean,
(callback: () => void, options?: StartTransitionOptions) => void,
] {
const [isPending, setPending] = mountState(false);
// The `start` method never changes.
const start = startTransition.bind(null, setPending);
Expand All @@ -2011,14 +2067,20 @@ function mountTransition(): [boolean, (() => void) => void] {
return [isPending, start];
}

function updateTransition(): [boolean, (() => void) => void] {
function updateTransition(): [
boolean,
(callback: () => void, options?: StartTransitionOptions) => void,
] {
const [isPending] = updateState(false);
const hook = updateWorkInProgressHook();
const start = hook.memoizedState;
return [isPending, start];
}

function rerenderTransition(): [boolean, (() => void) => void] {
function rerenderTransition(): [
boolean,
(callback: () => void, options?: StartTransitionOptions) => void,
] {
const [isPending] = rerenderState(false);
const hook = updateWorkInProgressHook();
const start = hook.memoizedState;
Expand Down
16 changes: 15 additions & 1 deletion packages/react-reconciler/src/ReactFiberLane.new.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* @flow
*/

import type {FiberRoot} from './ReactInternalTypes';
import type {FiberRoot, Transition} from './ReactInternalTypes';

// TODO: Ideally these types would be opaque but that doesn't work well with
// our reconciler fork infra, since these leak into non-reconciler packages.
Expand All @@ -20,6 +20,7 @@ import {
enableSchedulingProfiler,
enableUpdaterTracking,
allowConcurrentByDefault,
enableTransitionTracing,
} from 'shared/ReactFeatureFlags';
import {isDevToolsPresent} from './ReactFiberDevToolsHook.new';
import {ConcurrentUpdatesByDefaultMode, NoMode} from './ReactTypeOfMode';
Expand Down Expand Up @@ -792,3 +793,16 @@ export function movePendingFibersToMemoized(root: FiberRoot, lanes: Lanes) {
lanes &= ~lane;
}
}

export function addTransitionToLanesMap(
root: FiberRoot,
transition: Transition,
lane: Lane,
) {
if (enableTransitionTracing) {
const transitionLanesMap = root.transitionLanes;
const index = laneToIndex(lane);
const transitions = transitionLanesMap[index];
transitions.add(transition);
}
}
4 changes: 4 additions & 0 deletions packages/react-reconciler/src/ReactFiberRoot.new.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,10 @@ function FiberRootNode(containerInfo, tag, hydrate, identifierPrefix) {

if (enableTransitionTracing) {
this.transitionCallbacks = null;
const transitionLanesMap = (this.transitionLanes = []);
for (let i = 0; i < TotalLanes; i++) {
transitionLanesMap.push(new Set());
}
}

if (enableProfilerTimer && enableProfilerCommitHooks) {
Expand Down
Loading

0 comments on commit 3ba1704

Please sign in to comment.