Skip to content

Commit 863c41c

Browse files
committed
[Fiber] Trigger default transition indicator if needed (#33160)
Stacked on #33159. This implements `onDefaultTransitionIndicator`. The sequence is: 1) In `markRootUpdated` we schedule Transition updates as needing `indicatorLanes` on the root. This tracks the lanes that currently need an indicator to either start or remain going until this lane commits. 2) Track mutations during any commit. We use the same hook that view transitions use here but instead of tracking it just per view transition scope, we also track a global boolean for the whole root. 3) If a sync/default commit had any mutations, then we clear the indicator lane for the `currentEventTransitionLane`. This requires that the lane is still active while we do these commits. See #33159. In other words, a sync update gets associated with the current transition and it is assumed to be rendering the loading state for that corresponding transition so we don't need a default indicator for this lane. 4) At the end of `processRootScheduleInMicrotask`, right before we're about to enter a new "event transition lane" scope, it is no longer possible to render any more loading states for the current transition lane. That's when we invoke `onDefaultTransitionIndicator` for any roots that have new indicator lanes. 5) When we commit, we remove the finished lanes from `indicatorLanes` and once that reaches zero again, then we can clean up the default indicator. This approach means that you can start multiple different transitions while an indicator is still going but it won't stop/restart each time. Instead, it'll wait until all are done before stopping. Follow ups: - [x] Default updates are currently not enough to cancel because those aren't flush in the same microtask. That's unfortunate. #33186 - [x] Handle async actions before the setState. Since these don't necessarily have a root this is tricky. #33190 - [x] Disable for `useDeferredValue`. ~Since it also goes through `markRootUpdated` and schedules a Transition lane it'll get a default indicator even though it probably shouldn't have one.~ EDIT: Turns out this just works because it doesn't go through `markRootUpdated` when work is left behind. - [x] Implement built-in DOM version by default. #33162 DiffTrain build for [62d3f36](62d3f36)
1 parent bb4b9e4 commit 863c41c

24 files changed

+664
-647
lines changed

compiled-rn/VERSION_NATIVE_FB

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
19.2.0-native-fb-676f0879-20250513
1+
19.2.0-native-fb-62d3f36e-20250513

compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react/react-dom/cjs/ReactDOM-dev.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* @noflow
88
* @nolint
99
* @preventMunge
10-
* @generated SignedSource<<c8cd9640bf679d0908e5d46ec54f3189>>
10+
* @generated SignedSource<<0f588882dab9ef4ea9124a97131c2c34>>
1111
*/
1212

1313
"use strict";
@@ -404,5 +404,5 @@ __DEV__ &&
404404
exports.useFormStatus = function () {
405405
return resolveDispatcher().useHostTransitionStatus();
406406
};
407-
exports.version = "19.2.0-native-fb-676f0879-20250513";
407+
exports.version = "19.2.0-native-fb-62d3f36e-20250513";
408408
})();

compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react/react-dom/cjs/ReactDOM-prod.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* @noflow
88
* @nolint
99
* @preventMunge
10-
* @generated SignedSource<<dccf9a8410699996ea709daa7a5df85f>>
10+
* @generated SignedSource<<65b24823e3ee1fda0b4a43de8b27ad03>>
1111
*/
1212

1313
"use strict";
@@ -203,4 +203,4 @@ exports.useFormState = function (action, initialState, permalink) {
203203
exports.useFormStatus = function () {
204204
return ReactSharedInternals.H.useHostTransitionStatus();
205205
};
206-
exports.version = "19.2.0-native-fb-676f0879-20250513";
206+
exports.version = "19.2.0-native-fb-62d3f36e-20250513";

compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react/react-dom/cjs/ReactDOM-profiling.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* @noflow
88
* @nolint
99
* @preventMunge
10-
* @generated SignedSource<<dccf9a8410699996ea709daa7a5df85f>>
10+
* @generated SignedSource<<65b24823e3ee1fda0b4a43de8b27ad03>>
1111
*/
1212

1313
"use strict";
@@ -203,4 +203,4 @@ exports.useFormState = function (action, initialState, permalink) {
203203
exports.useFormStatus = function () {
204204
return ReactSharedInternals.H.useHostTransitionStatus();
205205
};
206-
exports.version = "19.2.0-native-fb-676f0879-20250513";
206+
exports.version = "19.2.0-native-fb-62d3f36e-20250513";

compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react/react-dom/cjs/ReactDOMClient-dev.js

Lines changed: 47 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* @noflow
88
* @nolint
99
* @preventMunge
10-
* @generated SignedSource<<6a9d7c3fdeb5555be8f862a75413cc56>>
10+
* @generated SignedSource<<267c7a1855e539eb2c7e5474aaf1c266>>
1111
*/
1212

1313
/*
@@ -15616,8 +15616,7 @@ __DEV__ &&
1561615616
return null !== transition
1561715617
? (transition._updatedFibers || (transition._updatedFibers = new Set()),
1561815618
transition._updatedFibers.add(fiber),
15619-
(fiber = currentEntangledLane),
15620-
0 !== fiber ? fiber : requestTransitionLane())
15619+
requestTransitionLane())
1562115620
: resolveUpdatePriority();
1562215621
}
1562315622
function requestDeferredLane() {
@@ -16868,9 +16867,9 @@ __DEV__ &&
1686816867
if (0 !== (finishedWork.subtreeFlags & 8772) || rootHasLayoutEffect) {
1686916868
rootHasLayoutEffect = ReactSharedInternals.T;
1687016869
ReactSharedInternals.T = null;
16871-
var previousPriority = ReactDOMSharedInternals.p;
16870+
var _previousPriority = ReactDOMSharedInternals.p;
1687216871
ReactDOMSharedInternals.p = DiscreteEventPriority;
16873-
var prevExecutionContext = executionContext;
16872+
var _prevExecutionContext = executionContext;
1687416873
executionContext |= CommitContext;
1687516874
try {
1687616875
null !== injectedProfilingHooks &&
@@ -16891,8 +16890,8 @@ __DEV__ &&
1689116890
typeof injectedProfilingHooks.markLayoutEffectsStopped &&
1689216891
injectedProfilingHooks.markLayoutEffectsStopped();
1689316892
} finally {
16894-
(executionContext = prevExecutionContext),
16895-
(ReactDOMSharedInternals.p = previousPriority),
16893+
(executionContext = _prevExecutionContext),
16894+
(ReactDOMSharedInternals.p = _previousPriority),
1689616895
(ReactSharedInternals.T = rootHasLayoutEffect);
1689716896
}
1689816897
}
@@ -17530,7 +17529,7 @@ __DEV__ &&
1753017529
(pendingEffectsStatus !== NO_PENDING_EFFECTS &&
1753117530
pendingEffectsStatus !== PENDING_PASSIVE_PHASE) ||
1753217531
flushSyncWorkAcrossRoots_impl(syncTransitionLanes, !1);
17533-
currentEventTransitionLane = 0;
17532+
0 !== currentEventTransitionLane && (currentEventTransitionLane = 0);
1753417533
}
1753517534
function scheduleTaskForRootDuringMicrotask(root, currentTime) {
1753617535
for (
@@ -17668,8 +17667,11 @@ __DEV__ &&
1766817667
});
1766917668
}
1767017669
function requestTransitionLane() {
17671-
0 === currentEventTransitionLane &&
17672-
(currentEventTransitionLane = claimNextTransitionLane());
17670+
if (0 === currentEventTransitionLane) {
17671+
var actionScopeLane = currentEntangledLane;
17672+
currentEventTransitionLane =
17673+
0 !== actionScopeLane ? actionScopeLane : claimNextTransitionLane();
17674+
}
1767317675
return currentEventTransitionLane;
1767417676
}
1767517677
function coerceFormActionProp(actionProp) {
@@ -24410,7 +24412,36 @@ __DEV__ &&
2441024412
return localDate.now();
2441124413
};
2441224414
}
24413-
var OffscreenVisible = 1,
24415+
var reportGlobalError =
24416+
"function" === typeof reportError
24417+
? reportError
24418+
: function (error) {
24419+
if (
24420+
"object" === typeof window &&
24421+
"function" === typeof window.ErrorEvent
24422+
) {
24423+
var event = new window.ErrorEvent("error", {
24424+
bubbles: !0,
24425+
cancelable: !0,
24426+
message:
24427+
"object" === typeof error &&
24428+
null !== error &&
24429+
"string" === typeof error.message
24430+
? String(error.message)
24431+
: String(error),
24432+
error: error
24433+
});
24434+
if (!window.dispatchEvent(event)) return;
24435+
} else if (
24436+
"object" === typeof process &&
24437+
"function" === typeof process.emit
24438+
) {
24439+
process.emit("uncaughtException", error);
24440+
return;
24441+
}
24442+
console.error(error);
24443+
},
24444+
OffscreenVisible = 1,
2441424445
OffscreenPassiveEffectsConnected = 2,
2441524446
concurrentQueues = [],
2441624447
concurrentQueuesIndex = 0,
@@ -26021,35 +26052,6 @@ __DEV__ &&
2602126052
injectedProfilingHooks.markForceUpdateScheduled(inst, lane);
2602226053
}
2602326054
},
26024-
reportGlobalError =
26025-
"function" === typeof reportError
26026-
? reportError
26027-
: function (error) {
26028-
if (
26029-
"object" === typeof window &&
26030-
"function" === typeof window.ErrorEvent
26031-
) {
26032-
var event = new window.ErrorEvent("error", {
26033-
bubbles: !0,
26034-
cancelable: !0,
26035-
message:
26036-
"object" === typeof error &&
26037-
null !== error &&
26038-
"string" === typeof error.message
26039-
? String(error.message)
26040-
: String(error),
26041-
error: error
26042-
});
26043-
if (!window.dispatchEvent(event)) return;
26044-
} else if (
26045-
"object" === typeof process &&
26046-
"function" === typeof process.emit
26047-
) {
26048-
process.emit("uncaughtException", error);
26049-
return;
26050-
}
26051-
console.error(error);
26052-
},
2605326055
componentName = null,
2605426056
errorBoundaryName = null,
2605526057
SelectiveHydrationException = Error(
@@ -26958,11 +26960,11 @@ __DEV__ &&
2695826960
};
2695926961
(function () {
2696026962
var isomorphicReactPackageVersion = React.version;
26961-
if ("19.2.0-native-fb-676f0879-20250513" !== isomorphicReactPackageVersion)
26963+
if ("19.2.0-native-fb-62d3f36e-20250513" !== isomorphicReactPackageVersion)
2696226964
throw Error(
2696326965
'Incompatible React versions: The "react" and "react-dom" packages must have the exact same version. Instead got:\n - react: ' +
2696426966
(isomorphicReactPackageVersion +
26965-
"\n - react-dom: 19.2.0-native-fb-676f0879-20250513\nLearn more: https://react.dev/warnings/version-mismatch")
26967+
"\n - react-dom: 19.2.0-native-fb-62d3f36e-20250513\nLearn more: https://react.dev/warnings/version-mismatch")
2696626968
);
2696726969
})();
2696826970
("function" === typeof Map &&
@@ -26999,10 +27001,10 @@ __DEV__ &&
2699927001
!(function () {
2700027002
var internals = {
2700127003
bundleType: 1,
27002-
version: "19.2.0-native-fb-676f0879-20250513",
27004+
version: "19.2.0-native-fb-62d3f36e-20250513",
2700327005
rendererPackageName: "react-dom",
2700427006
currentDispatcherRef: ReactSharedInternals,
27005-
reconcilerVersion: "19.2.0-native-fb-676f0879-20250513"
27007+
reconcilerVersion: "19.2.0-native-fb-62d3f36e-20250513"
2700627008
};
2700727009
internals.overrideHookState = overrideHookState;
2700827010
internals.overrideHookStateDeletePath = overrideHookStateDeletePath;
@@ -27140,5 +27142,5 @@ __DEV__ &&
2714027142
listenToAllSupportedEvents(container);
2714127143
return new ReactDOMHydrationRoot(initialChildren);
2714227144
};
27143-
exports.version = "19.2.0-native-fb-676f0879-20250513";
27145+
exports.version = "19.2.0-native-fb-62d3f36e-20250513";
2714427146
})();

compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react/react-dom/cjs/ReactDOMClient-prod.js

Lines changed: 43 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* @noflow
88
* @nolint
99
* @preventMunge
10-
* @generated SignedSource<<4efb453f059d3cbb66eb1cbe4cb4da09>>
10+
* @generated SignedSource<<18a0bd07d835883bced56cd97e57332c>>
1111
*/
1212

1313
/*
@@ -2428,7 +2428,36 @@ function registerSimpleEvent(domEventName, reactName) {
24282428
topLevelEventsToReactNames.set(domEventName, reactName);
24292429
registerTwoPhaseEvent(reactName, [domEventName]);
24302430
}
2431-
var concurrentQueues = [],
2431+
var reportGlobalError =
2432+
"function" === typeof reportError
2433+
? reportError
2434+
: function (error) {
2435+
if (
2436+
"object" === typeof window &&
2437+
"function" === typeof window.ErrorEvent
2438+
) {
2439+
var event = new window.ErrorEvent("error", {
2440+
bubbles: !0,
2441+
cancelable: !0,
2442+
message:
2443+
"object" === typeof error &&
2444+
null !== error &&
2445+
"string" === typeof error.message
2446+
? String(error.message)
2447+
: String(error),
2448+
error: error
2449+
});
2450+
if (!window.dispatchEvent(event)) return;
2451+
} else if (
2452+
"object" === typeof process &&
2453+
"function" === typeof process.emit
2454+
) {
2455+
process.emit("uncaughtException", error);
2456+
return;
2457+
}
2458+
console.error(error);
2459+
},
2460+
concurrentQueues = [],
24322461
concurrentQueuesIndex = 0,
24332462
concurrentlyUpdatedLanes = 0;
24342463
function finishQueueingConcurrentUpdates() {
@@ -6101,35 +6130,6 @@ function resolveClassComponentProps(Component, baseProps) {
61016130
}
61026131
return newProps;
61036132
}
6104-
var reportGlobalError =
6105-
"function" === typeof reportError
6106-
? reportError
6107-
: function (error) {
6108-
if (
6109-
"object" === typeof window &&
6110-
"function" === typeof window.ErrorEvent
6111-
) {
6112-
var event = new window.ErrorEvent("error", {
6113-
bubbles: !0,
6114-
cancelable: !0,
6115-
message:
6116-
"object" === typeof error &&
6117-
null !== error &&
6118-
"string" === typeof error.message
6119-
? String(error.message)
6120-
: String(error),
6121-
error: error
6122-
});
6123-
if (!window.dispatchEvent(event)) return;
6124-
} else if (
6125-
"object" === typeof process &&
6126-
"function" === typeof process.emit
6127-
) {
6128-
process.emit("uncaughtException", error);
6129-
return;
6130-
}
6131-
console.error(error);
6132-
};
61336133
function defaultOnUncaughtError(error) {
61346134
reportGlobalError(error);
61356135
}
@@ -11350,8 +11350,7 @@ function requestUpdateLane(fiber) {
1135011350
: 0 !== (executionContext & 2) && 0 !== workInProgressRootRenderLanes
1135111351
? workInProgressRootRenderLanes & -workInProgressRootRenderLanes
1135211352
: null !== ReactSharedInternals.T
11353-
? ((fiber = currentEntangledLane),
11354-
0 !== fiber ? fiber : requestTransitionLane())
11353+
? requestTransitionLane()
1135511354
: resolveUpdatePriority();
1135611355
}
1135711356
function requestDeferredLane() {
@@ -12721,7 +12720,7 @@ function processRootScheduleInMicrotask() {
1272112720
}
1272212721
(0 !== pendingEffectsStatus && 5 !== pendingEffectsStatus) ||
1272312722
flushSyncWorkAcrossRoots_impl(syncTransitionLanes, !1);
12724-
currentEventTransitionLane = 0;
12723+
0 !== currentEventTransitionLane && (currentEventTransitionLane = 0);
1272512724
}
1272612725
function scheduleTaskForRootDuringMicrotask(root, currentTime) {
1272712726
for (
@@ -12829,8 +12828,11 @@ function scheduleImmediateRootScheduleTask() {
1282912828
});
1283012829
}
1283112830
function requestTransitionLane() {
12832-
0 === currentEventTransitionLane &&
12833-
(currentEventTransitionLane = claimNextTransitionLane());
12831+
if (0 === currentEventTransitionLane) {
12832+
var actionScopeLane = currentEntangledLane;
12833+
currentEventTransitionLane =
12834+
0 !== actionScopeLane ? actionScopeLane : claimNextTransitionLane();
12835+
}
1283412836
return currentEventTransitionLane;
1283512837
}
1283612838
function coerceFormActionProp(actionProp) {
@@ -17049,14 +17051,14 @@ ReactDOMHydrationRoot.prototype.unstable_scheduleHydration = function (target) {
1704917051
};
1705017052
var isomorphicReactPackageVersion$jscomp$inline_2015 = React.version;
1705117053
if (
17052-
"19.2.0-native-fb-676f0879-20250513" !==
17054+
"19.2.0-native-fb-62d3f36e-20250513" !==
1705317055
isomorphicReactPackageVersion$jscomp$inline_2015
1705417056
)
1705517057
throw Error(
1705617058
formatProdErrorMessage(
1705717059
527,
1705817060
isomorphicReactPackageVersion$jscomp$inline_2015,
17059-
"19.2.0-native-fb-676f0879-20250513"
17061+
"19.2.0-native-fb-62d3f36e-20250513"
1706017062
)
1706117063
);
1706217064
ReactDOMSharedInternals.findDOMNode = function (componentOrElement) {
@@ -17078,10 +17080,10 @@ ReactDOMSharedInternals.findDOMNode = function (componentOrElement) {
1707817080
};
1707917081
var internals$jscomp$inline_2534 = {
1708017082
bundleType: 0,
17081-
version: "19.2.0-native-fb-676f0879-20250513",
17083+
version: "19.2.0-native-fb-62d3f36e-20250513",
1708217084
rendererPackageName: "react-dom",
1708317085
currentDispatcherRef: ReactSharedInternals,
17084-
reconcilerVersion: "19.2.0-native-fb-676f0879-20250513"
17086+
reconcilerVersion: "19.2.0-native-fb-62d3f36e-20250513"
1708517087
};
1708617088
if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) {
1708717089
var hook$jscomp$inline_2535 = __REACT_DEVTOOLS_GLOBAL_HOOK__;
@@ -17179,4 +17181,4 @@ exports.hydrateRoot = function (container, initialChildren, options) {
1717917181
listenToAllSupportedEvents(container);
1718017182
return new ReactDOMHydrationRoot(initialChildren);
1718117183
};
17182-
exports.version = "19.2.0-native-fb-676f0879-20250513";
17184+
exports.version = "19.2.0-native-fb-62d3f36e-20250513";

0 commit comments

Comments
 (0)