Skip to content
8 changes: 8 additions & 0 deletions packages/react-art/src/ReactFiberConfigART.js
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,14 @@ export function resolveUpdatePriority(): EventPriority {
return currentUpdatePriority || DefaultEventPriority;
}

export function resolveEventType(): null | string {
return null;
}

export function resolveEventTimeStamp(): number {
return -1.1;
}

export function shouldAttemptEagerTransition() {
return false;
}
Expand Down
10 changes: 10 additions & 0 deletions packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js
Original file line number Diff line number Diff line change
Expand Up @@ -606,6 +606,16 @@ export function shouldAttemptEagerTransition(): boolean {
return false;
}

export function resolveEventType(): null | string {
const event = window.event;
return event ? event.type : null;
}

export function resolveEventTimeStamp(): number {
const event = window.event;
return event ? event.timeStamp : -1.1;
}

export const isPrimaryRenderer = true;
export const warnsIfNotActing = true;
// This initialization code may run even on server environments
Expand Down
8 changes: 8 additions & 0 deletions packages/react-native-renderer/src/ReactFiberConfigFabric.js
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,14 @@ export function resolveUpdatePriority(): EventPriority {
return DefaultEventPriority;
}

export function resolveEventType(): null | string {
return null;
}

export function resolveEventTimeStamp(): number {
return -1.1;
}

export function shouldAttemptEagerTransition(): boolean {
return false;
}
Expand Down
8 changes: 8 additions & 0 deletions packages/react-native-renderer/src/ReactFiberConfigNative.js
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,14 @@ export function resolveUpdatePriority(): EventPriority {
return DefaultEventPriority;
}

export function resolveEventType(): null | string {
return null;
}

export function resolveEventTimeStamp(): number {
return -1.1;
}

export function shouldAttemptEagerTransition(): boolean {
return false;
}
Expand Down
8 changes: 8 additions & 0 deletions packages/react-noop-renderer/src/createReactNoop.js
Original file line number Diff line number Diff line change
Expand Up @@ -533,6 +533,14 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
return currentEventPriority;
},

resolveEventType(): null | string {
return null;
},

resolveEventTimeStamp(): number {
return -1.1;
},

shouldAttemptEagerTransition(): boolean {
return false;
},
Expand Down
52 changes: 35 additions & 17 deletions packages/react-reconciler/src/ReactFiberAsyncAction.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,14 @@ import type {BatchConfigTransition} from './ReactFiberTracingMarkerComponent';

import {requestTransitionLane} from './ReactFiberRootScheduler';
import {NoLane} from './ReactFiberLane';
import {
hasScheduledTransitionWork,
clearAsyncTransitionTimer,
} from './ReactProfilerTimer';
import {
enableComponentPerformanceTrack,
enableProfilerTimer,
} from 'shared/ReactFeatureFlags';

// If there are multiple, concurrent async actions, they are entangled. All
// transition updates that occur while the async action is still in progress
Expand Down Expand Up @@ -64,24 +72,34 @@ export function entangleAsyncAction<S>(
}

function pingEngtangledActionScope() {
if (
currentEntangledListeners !== null &&
--currentEntangledPendingCount === 0
) {
// All the actions have finished. Close the entangled async action scope
// and notify all the listeners.
if (currentEntangledActionThenable !== null) {
const fulfilledThenable: FulfilledThenable<void> =
(currentEntangledActionThenable: any);
fulfilledThenable.status = 'fulfilled';
if (--currentEntangledPendingCount === 0) {
if (enableProfilerTimer && enableComponentPerformanceTrack) {
if (!hasScheduledTransitionWork()) {
// If we have received no updates since we started the entangled Actions
// that means it didn't lead to a Transition being rendered. We need to
// clear the timer so that if we start another entangled sequence we use
// the next start timer instead of appearing like we were blocked the
// whole time. We currently don't log a track for Actions that don't
// render a Transition.
clearAsyncTransitionTimer();
}
}
const listeners = currentEntangledListeners;
currentEntangledListeners = null;
currentEntangledLane = NoLane;
currentEntangledActionThenable = null;
for (let i = 0; i < listeners.length; i++) {
const listener = listeners[i];
listener();
if (currentEntangledListeners !== null) {
// All the actions have finished. Close the entangled async action scope
// and notify all the listeners.
if (currentEntangledActionThenable !== null) {
const fulfilledThenable: FulfilledThenable<void> =
(currentEntangledActionThenable: any);
fulfilledThenable.status = 'fulfilled';
}
const listeners = currentEntangledListeners;
currentEntangledListeners = null;
currentEntangledLane = NoLane;
currentEntangledActionThenable = null;
for (let i = 0; i < listeners.length; i++) {
const listener = listeners[i];
listener();
}
}
}
}
Expand Down
4 changes: 4 additions & 0 deletions packages/react-reconciler/src/ReactFiberClassComponent.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ import {
markStateUpdateScheduled,
setIsStrictModeForDevtools,
} from './ReactFiberDevToolsHook';
import {startUpdateTimerByLane} from './ReactProfilerTimer';

const fakeInternalInstance = {};

Expand Down Expand Up @@ -194,6 +195,7 @@ const classComponentUpdater = {

const root = enqueueUpdate(fiber, update, lane);
if (root !== null) {
startUpdateTimerByLane(lane);
scheduleUpdateOnFiber(root, fiber, lane);
entangleTransitions(root, fiber, lane);
}
Expand Down Expand Up @@ -228,6 +230,7 @@ const classComponentUpdater = {

const root = enqueueUpdate(fiber, update, lane);
if (root !== null) {
startUpdateTimerByLane(lane);
scheduleUpdateOnFiber(root, fiber, lane);
entangleTransitions(root, fiber, lane);
}
Expand Down Expand Up @@ -262,6 +265,7 @@ const classComponentUpdater = {

const root = enqueueUpdate(fiber, update, lane);
if (root !== null) {
startUpdateTimerByLane(lane);
scheduleUpdateOnFiber(root, fiber, lane);
entangleTransitions(root, fiber, lane);
}
Expand Down
69 changes: 60 additions & 9 deletions packages/react-reconciler/src/ReactFiberHooks.js
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ import {
markStateUpdateScheduled,
setIsStrictModeForDevtools,
} from './ReactFiberDevToolsHook';
import {startUpdateTimerByLane} from './ReactProfilerTimer';
import {createCache} from './ReactFiberCacheComponent';
import {
createUpdate as createLegacyQueueUpdate,
Expand Down Expand Up @@ -3019,7 +3020,12 @@ function startTransition<S>(
dispatchOptimisticSetState(fiber, false, queue, pendingState);
} else {
ReactSharedInternals.T = null;
dispatchSetState(fiber, queue, pendingState);
dispatchSetStateInternal(
fiber,
queue,
pendingState,
requestUpdateLane(fiber),
);
ReactSharedInternals.T = currentTransition;
}

Expand Down Expand Up @@ -3062,13 +3068,28 @@ function startTransition<S>(
thenable,
finishedState,
);
dispatchSetState(fiber, queue, (thenableForFinishedState: any));
dispatchSetStateInternal(
fiber,
queue,
(thenableForFinishedState: any),
requestUpdateLane(fiber),
);
} else {
dispatchSetState(fiber, queue, finishedState);
dispatchSetStateInternal(
fiber,
queue,
finishedState,
requestUpdateLane(fiber),
);
}
} else {
// Async actions are not enabled.
dispatchSetState(fiber, queue, finishedState);
dispatchSetStateInternal(
fiber,
queue,
finishedState,
requestUpdateLane(fiber),
);
callback();
}
} catch (error) {
Expand All @@ -3081,7 +3102,12 @@ function startTransition<S>(
status: 'rejected',
reason: error,
};
dispatchSetState(fiber, queue, rejectedThenable);
dispatchSetStateInternal(
fiber,
queue,
rejectedThenable,
requestUpdateLane(fiber),
);
} else {
// The error rethrowing behavior is only enabled when the async actions
// feature is on, even for sync actions.
Expand Down Expand Up @@ -3253,7 +3279,12 @@ export function requestFormReset(formFiber: Fiber) {
const newResetState = {};
const resetStateHook: Hook = (stateHook.next: any);
const resetStateQueue = resetStateHook.queue;
dispatchSetState(formFiber, resetStateQueue, newResetState);
dispatchSetStateInternal(
formFiber,
resetStateQueue,
newResetState,
requestUpdateLane(formFiber),
);
}

function mountTransition(): [
Expand Down Expand Up @@ -3385,6 +3416,7 @@ function refreshCache<T>(fiber: Fiber, seedKey: ?() => T, seedValue: T): void {
const refreshUpdate = createLegacyQueueUpdate(lane);
const root = enqueueLegacyQueueUpdate(provider, refreshUpdate, lane);
if (root !== null) {
startUpdateTimerByLane(lane);
scheduleUpdateOnFiber(root, provider, lane);
entangleLegacyQueueTransitions(root, provider, lane);
}
Expand Down Expand Up @@ -3450,6 +3482,7 @@ function dispatchReducerAction<S, A>(
} else {
const root = enqueueConcurrentHookUpdate(fiber, queue, update, lane);
if (root !== null) {
startUpdateTimerByLane(lane);
scheduleUpdateOnFiber(root, fiber, lane);
entangleTransitionUpdate(root, queue, lane);
}
Expand All @@ -3474,7 +3507,24 @@ function dispatchSetState<S, A>(
}

const lane = requestUpdateLane(fiber);
const didScheduleUpdate = dispatchSetStateInternal(
fiber,
queue,
action,
lane,
);
if (didScheduleUpdate) {
startUpdateTimerByLane(lane);
}
markUpdateInDevTools(fiber, lane, action);
}

function dispatchSetStateInternal<S, A>(
fiber: Fiber,
queue: UpdateQueue<S, A>,
action: A,
lane: Lane,
): boolean {
const update: Update<S, A> = {
lane,
revertLane: NoLane,
Expand Down Expand Up @@ -3518,7 +3568,7 @@ function dispatchSetState<S, A>(
// time the reducer has changed.
// TODO: Do we still need to entangle transitions in this case?
enqueueConcurrentHookUpdateAndEagerlyBailout(fiber, queue, update);
return;
return false;
}
} catch (error) {
// Suppress the error. It will throw again in the render phase.
Expand All @@ -3534,10 +3584,10 @@ function dispatchSetState<S, A>(
if (root !== null) {
scheduleUpdateOnFiber(root, fiber, lane);
entangleTransitionUpdate(root, queue, lane);
return true;
}
}

markUpdateInDevTools(fiber, lane, action);
return false;
}

function dispatchOptimisticSetState<S, A>(
Expand Down Expand Up @@ -3619,6 +3669,7 @@ function dispatchOptimisticSetState<S, A>(
// will never be attempted before the optimistic update. This currently
// holds because the optimistic update is always synchronous. If we ever
// change that, we'll need to account for this.
startUpdateTimerByLane(SyncLane);
scheduleUpdateOnFiber(root, fiber, SyncLane);
// Optimistic updates are always synchronous, so we don't need to call
// entangleTransitionUpdate here.
Expand Down
17 changes: 17 additions & 0 deletions packages/react-reconciler/src/ReactFiberLane.js
Original file line number Diff line number Diff line change
Expand Up @@ -592,6 +592,10 @@ export function includesSyncLane(lanes: Lanes): boolean {
return (lanes & (SyncLane | SyncHydrationLane)) !== NoLanes;
}

export function isSyncLane(lanes: Lanes): boolean {
return (lanes & (SyncLane | SyncHydrationLane)) !== NoLanes;
}

export function includesNonIdleWork(lanes: Lanes): boolean {
return (lanes & NonIdleLanes) !== NoLanes;
}
Expand All @@ -608,6 +612,10 @@ export function includesOnlyTransitions(lanes: Lanes): boolean {
return (lanes & TransitionLanes) === lanes;
}

export function includesTransitionLane(lanes: Lanes): boolean {
return (lanes & TransitionLanes) !== NoLanes;
}

export function includesBlockingLane(lanes: Lanes): boolean {
const SyncDefaultLanes =
InputContinuousHydrationLane |
Expand All @@ -623,6 +631,15 @@ export function includesExpiredLane(root: FiberRoot, lanes: Lanes): boolean {
return (lanes & root.expiredLanes) !== NoLanes;
}

export function isBlockingLane(lane: Lane): boolean {
const SyncDefaultLanes =
InputContinuousHydrationLane |
InputContinuousLane |
DefaultHydrationLane |
DefaultLane;
return (lane & SyncDefaultLanes) !== NoLanes;
}

export function isTransitionLane(lane: Lane): boolean {
return (lane & TransitionLanes) !== NoLanes;
}
Expand Down
Loading
Loading