Skip to content

Commit 025e752

Browse files
committed
Add more phases to the ReactFiberApplyGesture (#32578)
Stacked on #32585 and #32605. This adds more loops for the phases of "Apply Gesture". It doesn't implement the interesting bit yet like adding view-transition-names and measurements. I'll do that in a separate PR to keep reviewing easier. The three phases of this approach is roughly: - Clone and apply names to the "old" state. - Inside startViewTransition: Apply names to the "new" state. Measure both the "old" and "new" state to know whether to cancel some of them. Delete the clones which will include all the "old" names. - After startViewTransition: Restore "new" names back to no view-transition-name. Since we don't have any other Effects in these phases we have a bit more flexibility and we can avoid extra phases that traverse the tree. I've tried to avoid any additional passes. An interesting consequence of this approach is that we could measure both the "old" and "new" state before `startViewTransition`. This would be more efficient because we wouldn't need to take View Transition snapshots of parts of the tree that won't actually animate. However, that would require an extra pass and force layout earlier. It would also have different semantics from the fire-and-forget View Transitions because we could optimize better which can be visible. It would also not account for any late mutations. So I decided to instead let the layout be computed by painting as usual and then measure both "old" and "new" inside the startViewTransition instead. Then canceling anything that doesn't animate to keep it consistent. Unfortunately, though there's not a lot of code sharing possible in these phases because the strategy is so different with the cloning and because the animation is performed in reverse. The "finishedWork" Fiber represents the "old" state and the "current" Fiber represents the "new" state. The most complicated phase is the cloning. I actually ended up having to make a very different pattern from the other phases and CommitWork in general. Because we have to clone as we go and also do other things like apply names and finding pairs, it has more phases. I ended up with an approach that uses three different loops. The outer one for updated trees, one for inserted trees that don't need cloning (doesn't include reappearing offscreen) and one for not updated trees that still need cloning. Inside each loop it can also be in different phases which I track with the `visitPhase` enum - this pattern is kind of new. Additionally, we need to measure the cloned nodes after we've applied mutations to them and we have to wait until the whole tree is inserted. We don't have a reference to these DOM elements in the Fiber tree since that still refers to the original ones. We need to store the cloned elements somewhere. So I added a temporary field on the ViewTransitionState to keep track of any clones owned by that ViewTransition. When we deep clone an unchanged subtree we don't have DOM element instances. It wouldn't be quite safe to try to find them from the tree structure. So we need to avoid the deep clones if we might need DOM elements. Therefore we keep traversing in the case where we need to find nested ViewTransition boundaries that are either potentially affected by layout or a "pair". For the other two phases the pattern there's a lot of code duplication since it's slightly different from the commit ones but they at least follow the same pattern. For the restore phase I was actually able to reuse most of the code. I don't love how much code this is. DiffTrain build for [c4a3b92](c4a3b92)
1 parent 58c68ba commit 025e752

22 files changed

+581
-581
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.1.0-native-fb-3e956805-20250314
1+
19.1.0-native-fb-c4a3b92e-20250314

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<<8a2d9de3633e78af674b727512adf310>>
10+
* @generated SignedSource<<c3d6f2b6c71489013592048f79a0b1b0>>
1111
*/
1212

1313
"use strict";
@@ -404,5 +404,5 @@ __DEV__ &&
404404
exports.useFormStatus = function () {
405405
return resolveDispatcher().useHostTransitionStatus();
406406
};
407-
exports.version = "19.1.0-native-fb-3e956805-20250314";
407+
exports.version = "19.1.0-native-fb-c4a3b92e-20250314";
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<<f3fecc17777af4a1a49bcdad12d01bd0>>
10+
* @generated SignedSource<<a90df4bb663907a4d8bc8da3b3606c1f>>
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.1.0-native-fb-3e956805-20250314";
206+
exports.version = "19.1.0-native-fb-c4a3b92e-20250314";

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<<f3fecc17777af4a1a49bcdad12d01bd0>>
10+
* @generated SignedSource<<a90df4bb663907a4d8bc8da3b3606c1f>>
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.1.0-native-fb-3e956805-20250314";
206+
exports.version = "19.1.0-native-fb-c4a3b92e-20250314";

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

Lines changed: 167 additions & 167 deletions
Large diffs are not rendered by default.

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

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

1313
/*
@@ -12516,20 +12516,20 @@ function debounceScrollEnd(targetInst, nativeEvent, nativeEventTarget) {
1251612516
(nativeEventTarget[internalScrollTimer] = targetInst));
1251712517
}
1251812518
for (
12519-
var i$jscomp$inline_1543 = 0;
12520-
i$jscomp$inline_1543 < simpleEventPluginEvents.length;
12521-
i$jscomp$inline_1543++
12519+
var i$jscomp$inline_1563 = 0;
12520+
i$jscomp$inline_1563 < simpleEventPluginEvents.length;
12521+
i$jscomp$inline_1563++
1252212522
) {
12523-
var eventName$jscomp$inline_1544 =
12524-
simpleEventPluginEvents[i$jscomp$inline_1543],
12525-
domEventName$jscomp$inline_1545 =
12526-
eventName$jscomp$inline_1544.toLowerCase(),
12527-
capitalizedEvent$jscomp$inline_1546 =
12528-
eventName$jscomp$inline_1544[0].toUpperCase() +
12529-
eventName$jscomp$inline_1544.slice(1);
12523+
var eventName$jscomp$inline_1564 =
12524+
simpleEventPluginEvents[i$jscomp$inline_1563],
12525+
domEventName$jscomp$inline_1565 =
12526+
eventName$jscomp$inline_1564.toLowerCase(),
12527+
capitalizedEvent$jscomp$inline_1566 =
12528+
eventName$jscomp$inline_1564[0].toUpperCase() +
12529+
eventName$jscomp$inline_1564.slice(1);
1253012530
registerSimpleEvent(
12531-
domEventName$jscomp$inline_1545,
12532-
"on" + capitalizedEvent$jscomp$inline_1546
12531+
domEventName$jscomp$inline_1565,
12532+
"on" + capitalizedEvent$jscomp$inline_1566
1253312533
);
1253412534
}
1253512535
registerSimpleEvent(ANIMATION_END, "onAnimationEnd");
@@ -16119,16 +16119,16 @@ ReactDOMHydrationRoot.prototype.unstable_scheduleHydration = function (target) {
1611916119
0 === i && attemptExplicitHydrationTarget(target);
1612016120
}
1612116121
};
16122-
var isomorphicReactPackageVersion$jscomp$inline_1792 = React.version;
16122+
var isomorphicReactPackageVersion$jscomp$inline_1812 = React.version;
1612316123
if (
16124-
"19.1.0-native-fb-3e956805-20250314" !==
16125-
isomorphicReactPackageVersion$jscomp$inline_1792
16124+
"19.1.0-native-fb-c4a3b92e-20250314" !==
16125+
isomorphicReactPackageVersion$jscomp$inline_1812
1612616126
)
1612716127
throw Error(
1612816128
formatProdErrorMessage(
1612916129
527,
16130-
isomorphicReactPackageVersion$jscomp$inline_1792,
16131-
"19.1.0-native-fb-3e956805-20250314"
16130+
isomorphicReactPackageVersion$jscomp$inline_1812,
16131+
"19.1.0-native-fb-c4a3b92e-20250314"
1613216132
)
1613316133
);
1613416134
ReactDOMSharedInternals.findDOMNode = function (componentOrElement) {
@@ -16148,24 +16148,24 @@ ReactDOMSharedInternals.findDOMNode = function (componentOrElement) {
1614816148
null === componentOrElement ? null : componentOrElement.stateNode;
1614916149
return componentOrElement;
1615016150
};
16151-
var internals$jscomp$inline_2254 = {
16151+
var internals$jscomp$inline_2274 = {
1615216152
bundleType: 0,
16153-
version: "19.1.0-native-fb-3e956805-20250314",
16153+
version: "19.1.0-native-fb-c4a3b92e-20250314",
1615416154
rendererPackageName: "react-dom",
1615516155
currentDispatcherRef: ReactSharedInternals,
16156-
reconcilerVersion: "19.1.0-native-fb-3e956805-20250314"
16156+
reconcilerVersion: "19.1.0-native-fb-c4a3b92e-20250314"
1615716157
};
1615816158
if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) {
16159-
var hook$jscomp$inline_2255 = __REACT_DEVTOOLS_GLOBAL_HOOK__;
16159+
var hook$jscomp$inline_2275 = __REACT_DEVTOOLS_GLOBAL_HOOK__;
1616016160
if (
16161-
!hook$jscomp$inline_2255.isDisabled &&
16162-
hook$jscomp$inline_2255.supportsFiber
16161+
!hook$jscomp$inline_2275.isDisabled &&
16162+
hook$jscomp$inline_2275.supportsFiber
1616316163
)
1616416164
try {
16165-
(rendererID = hook$jscomp$inline_2255.inject(
16166-
internals$jscomp$inline_2254
16165+
(rendererID = hook$jscomp$inline_2275.inject(
16166+
internals$jscomp$inline_2274
1616716167
)),
16168-
(injectedHook = hook$jscomp$inline_2255);
16168+
(injectedHook = hook$jscomp$inline_2275);
1616916169
} catch (err) {}
1617016170
}
1617116171
exports.createRoot = function (container, options) {
@@ -16257,4 +16257,4 @@ exports.hydrateRoot = function (container, initialChildren, options) {
1625716257
listenToAllSupportedEvents(container);
1625816258
return new ReactDOMHydrationRoot(initialChildren);
1625916259
};
16260-
exports.version = "19.1.0-native-fb-3e956805-20250314";
16260+
exports.version = "19.1.0-native-fb-c4a3b92e-20250314";

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

Lines changed: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* @noflow
88
* @nolint
99
* @preventMunge
10-
* @generated SignedSource<<c6f28990060cd88ea90ba3d4196c76b3>>
10+
* @generated SignedSource<<59c822a97daaed9d1489d3ad4f162577>>
1111
*/
1212

1313
/*
@@ -13158,20 +13158,20 @@ function debounceScrollEnd(targetInst, nativeEvent, nativeEventTarget) {
1315813158
(nativeEventTarget[internalScrollTimer] = targetInst));
1315913159
}
1316013160
for (
13161-
var i$jscomp$inline_1636 = 0;
13162-
i$jscomp$inline_1636 < simpleEventPluginEvents.length;
13163-
i$jscomp$inline_1636++
13161+
var i$jscomp$inline_1656 = 0;
13162+
i$jscomp$inline_1656 < simpleEventPluginEvents.length;
13163+
i$jscomp$inline_1656++
1316413164
) {
13165-
var eventName$jscomp$inline_1637 =
13166-
simpleEventPluginEvents[i$jscomp$inline_1636],
13167-
domEventName$jscomp$inline_1638 =
13168-
eventName$jscomp$inline_1637.toLowerCase(),
13169-
capitalizedEvent$jscomp$inline_1639 =
13170-
eventName$jscomp$inline_1637[0].toUpperCase() +
13171-
eventName$jscomp$inline_1637.slice(1);
13165+
var eventName$jscomp$inline_1657 =
13166+
simpleEventPluginEvents[i$jscomp$inline_1656],
13167+
domEventName$jscomp$inline_1658 =
13168+
eventName$jscomp$inline_1657.toLowerCase(),
13169+
capitalizedEvent$jscomp$inline_1659 =
13170+
eventName$jscomp$inline_1657[0].toUpperCase() +
13171+
eventName$jscomp$inline_1657.slice(1);
1317213172
registerSimpleEvent(
13173-
domEventName$jscomp$inline_1638,
13174-
"on" + capitalizedEvent$jscomp$inline_1639
13173+
domEventName$jscomp$inline_1658,
13174+
"on" + capitalizedEvent$jscomp$inline_1659
1317513175
);
1317613176
}
1317713177
registerSimpleEvent(ANIMATION_END, "onAnimationEnd");
@@ -16769,16 +16769,16 @@ ReactDOMHydrationRoot.prototype.unstable_scheduleHydration = function (target) {
1676916769
0 === i && attemptExplicitHydrationTarget(target);
1677016770
}
1677116771
};
16772-
var isomorphicReactPackageVersion$jscomp$inline_1887 = React.version;
16772+
var isomorphicReactPackageVersion$jscomp$inline_1907 = React.version;
1677316773
if (
16774-
"19.1.0-native-fb-3e956805-20250314" !==
16775-
isomorphicReactPackageVersion$jscomp$inline_1887
16774+
"19.1.0-native-fb-c4a3b92e-20250314" !==
16775+
isomorphicReactPackageVersion$jscomp$inline_1907
1677616776
)
1677716777
throw Error(
1677816778
formatProdErrorMessage(
1677916779
527,
16780-
isomorphicReactPackageVersion$jscomp$inline_1887,
16781-
"19.1.0-native-fb-3e956805-20250314"
16780+
isomorphicReactPackageVersion$jscomp$inline_1907,
16781+
"19.1.0-native-fb-c4a3b92e-20250314"
1678216782
)
1678316783
);
1678416784
ReactDOMSharedInternals.findDOMNode = function (componentOrElement) {
@@ -16798,12 +16798,12 @@ ReactDOMSharedInternals.findDOMNode = function (componentOrElement) {
1679816798
null === componentOrElement ? null : componentOrElement.stateNode;
1679916799
return componentOrElement;
1680016800
};
16801-
var internals$jscomp$inline_1894 = {
16801+
var internals$jscomp$inline_1914 = {
1680216802
bundleType: 0,
16803-
version: "19.1.0-native-fb-3e956805-20250314",
16803+
version: "19.1.0-native-fb-c4a3b92e-20250314",
1680416804
rendererPackageName: "react-dom",
1680516805
currentDispatcherRef: ReactSharedInternals,
16806-
reconcilerVersion: "19.1.0-native-fb-3e956805-20250314",
16806+
reconcilerVersion: "19.1.0-native-fb-c4a3b92e-20250314",
1680716807
getLaneLabelMap: function () {
1680816808
for (
1680916809
var map = new Map(), lane = 1, index$294 = 0;
@@ -16821,16 +16821,16 @@ var internals$jscomp$inline_1894 = {
1682116821
}
1682216822
};
1682316823
if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) {
16824-
var hook$jscomp$inline_2314 = __REACT_DEVTOOLS_GLOBAL_HOOK__;
16824+
var hook$jscomp$inline_2334 = __REACT_DEVTOOLS_GLOBAL_HOOK__;
1682516825
if (
16826-
!hook$jscomp$inline_2314.isDisabled &&
16827-
hook$jscomp$inline_2314.supportsFiber
16826+
!hook$jscomp$inline_2334.isDisabled &&
16827+
hook$jscomp$inline_2334.supportsFiber
1682816828
)
1682916829
try {
16830-
(rendererID = hook$jscomp$inline_2314.inject(
16831-
internals$jscomp$inline_1894
16830+
(rendererID = hook$jscomp$inline_2334.inject(
16831+
internals$jscomp$inline_1914
1683216832
)),
16833-
(injectedHook = hook$jscomp$inline_2314);
16833+
(injectedHook = hook$jscomp$inline_2334);
1683416834
} catch (err) {}
1683516835
}
1683616836
exports.createRoot = function (container, options) {
@@ -16922,4 +16922,4 @@ exports.hydrateRoot = function (container, initialChildren, options) {
1692216922
listenToAllSupportedEvents(container);
1692316923
return new ReactDOMHydrationRoot(initialChildren);
1692416924
};
16925-
exports.version = "19.1.0-native-fb-3e956805-20250314";
16925+
exports.version = "19.1.0-native-fb-c4a3b92e-20250314";

0 commit comments

Comments
 (0)