Skip to content

Commit 08859f9

Browse files
committed
Add useSwipeTransition Hook Behind Experimental Flag (#32373)
This Hook will be used to drive a View Transition based on a gesture. ```js const [value, startGesture] = useSwipeTransition(prev, current, next); ``` The `enableSwipeTransition` flag will depend on `enableViewTransition` flag but we may decide to ship them independently. This PR doesn't do anything interesting yet. There will be a lot more PRs to build out the actual functionality. This is just wiring up the plumbing for the new Hook. This first PR is mainly concerned with how the whole starts (and stops). The core API is the `startGesture` function (although there will be other conveniences added in the future). You can call this to start a gesture with a source provider. You can call this multiple times in one event to batch multiple Hooks listening to the same provider. However, each render can only handle one source provider at a time and so it does one render per scheduled gesture provider. This uses a separate `GestureLane` to drive gesture renders by marking the Hook as having an update on that lane. Then schedule a render. These renders should be blocking and in the same microtask as the `startGesture` to ensure it can block the paint. So it's similar to sync. It may not be possible to finish it synchronously e.g. if something suspends. If so, it just tries again later when it can like any other render. This can also happen because it also may not be possible to drive more than one gesture at a time like if we're limited to one View Transition per document. So right now you can only run one gesture at a time in practice. These renders never commit. This means that we can't clear the `GestureLane` the normal way. Instead, we have to clear only the root's `pendingLanes` if we don't have any new renders scheduled. Then wait until something else updates the Fiber after all gestures on it have stopped before it really clears. DiffTrain build for [a53da6a](a53da6a)
1 parent a622ad3 commit 08859f9

34 files changed

+870
-830
lines changed

compiled/facebook-www/REVISION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
c6a7e18636e610efd3aa7a437bbcaf321bf73abd
1+
a53da6abe1593483098df2baf927fe07d80153a5
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
c6a7e18636e610efd3aa7a437bbcaf321bf73abd
1+
a53da6abe1593483098df2baf927fe07d80153a5

compiled/facebook-www/React-dev.classic.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1986,7 +1986,7 @@ __DEV__ &&
19861986
exports.useTransition = function () {
19871987
return resolveDispatcher().useTransition();
19881988
};
1989-
exports.version = "19.1.0-www-classic-c6a7e186-20250213";
1989+
exports.version = "19.1.0-www-classic-a53da6ab-20250213";
19901990
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
19911991
"function" ===
19921992
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop &&

compiled/facebook-www/React-dev.modern.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1986,7 +1986,7 @@ __DEV__ &&
19861986
exports.useTransition = function () {
19871987
return resolveDispatcher().useTransition();
19881988
};
1989-
exports.version = "19.1.0-www-modern-c6a7e186-20250213";
1989+
exports.version = "19.1.0-www-modern-a53da6ab-20250213";
19901990
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
19911991
"function" ===
19921992
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop &&

compiled/facebook-www/React-prod.classic.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -641,4 +641,4 @@ exports.useSyncExternalStore = function (
641641
exports.useTransition = function () {
642642
return ReactSharedInternals.H.useTransition();
643643
};
644-
exports.version = "19.1.0-www-classic-c6a7e186-20250213";
644+
exports.version = "19.1.0-www-classic-a53da6ab-20250213";

compiled/facebook-www/React-prod.modern.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -641,4 +641,4 @@ exports.useSyncExternalStore = function (
641641
exports.useTransition = function () {
642642
return ReactSharedInternals.H.useTransition();
643643
};
644-
exports.version = "19.1.0-www-modern-c6a7e186-20250213";
644+
exports.version = "19.1.0-www-modern-a53da6ab-20250213";

compiled/facebook-www/React-profiling.classic.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -645,7 +645,7 @@ exports.useSyncExternalStore = function (
645645
exports.useTransition = function () {
646646
return ReactSharedInternals.H.useTransition();
647647
};
648-
exports.version = "19.1.0-www-classic-c6a7e186-20250213";
648+
exports.version = "19.1.0-www-classic-a53da6ab-20250213";
649649
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
650650
"function" ===
651651
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop &&

compiled/facebook-www/React-profiling.modern.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -645,7 +645,7 @@ exports.useSyncExternalStore = function (
645645
exports.useTransition = function () {
646646
return ReactSharedInternals.H.useTransition();
647647
};
648-
exports.version = "19.1.0-www-modern-c6a7e186-20250213";
648+
exports.version = "19.1.0-www-modern-a53da6ab-20250213";
649649
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
650650
"function" ===
651651
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop &&

compiled/facebook-www/ReactART-dev.classic.js

Lines changed: 44 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -443,8 +443,8 @@ __DEV__ &&
443443
if (lane & 8) return "InputContinuous";
444444
if (lane & 16) return "DefaultHydration";
445445
if (lane & 32) return "Default";
446-
if (lane & 64) return "TransitionHydration";
447-
if (lane & 4194176) return "Transition";
446+
if (lane & 128) return "TransitionHydration";
447+
if (lane & 4194048) return "Transition";
448448
if (lane & 62914560) return "Retry";
449449
if (lane & 67108864) return "SelectiveHydration";
450450
if (lane & 134217728) return "IdleHydration";
@@ -472,6 +472,7 @@ __DEV__ &&
472472
case 64:
473473
return 64;
474474
case 128:
475+
return 128;
475476
case 256:
476477
case 512:
477478
case 1024:
@@ -486,7 +487,7 @@ __DEV__ &&
486487
case 524288:
487488
case 1048576:
488489
case 2097152:
489-
return lanes & 4194176;
490+
return lanes & 4194048;
490491
case 4194304:
491492
case 8388608:
492493
case 16777216:
@@ -550,7 +551,7 @@ __DEV__ &&
550551
((suspendedLanes = nextLanes & -nextLanes),
551552
(rootHasPendingCommit = wipLanes & -wipLanes),
552553
suspendedLanes >= rootHasPendingCommit ||
553-
(32 === suspendedLanes && 0 !== (rootHasPendingCommit & 4194176)))
554+
(32 === suspendedLanes && 0 !== (rootHasPendingCommit & 4194048)))
554555
? wipLanes
555556
: nextLanes;
556557
}
@@ -568,10 +569,10 @@ __DEV__ &&
568569
case 2:
569570
case 4:
570571
case 8:
572+
case 64:
571573
return currentTime + syncLaneExpirationMs;
572574
case 16:
573575
case 32:
574-
case 64:
575576
case 128:
576577
case 256:
577578
case 512:
@@ -613,7 +614,7 @@ __DEV__ &&
613614
function claimNextTransitionLane() {
614615
var lane = nextTransitionLane;
615616
nextTransitionLane <<= 1;
616-
0 === (nextTransitionLane & 4194176) && (nextTransitionLane = 128);
617+
0 === (nextTransitionLane & 4194048) && (nextTransitionLane = 256);
617618
return lane;
618619
}
619620
function claimNextRetryLane() {
@@ -683,7 +684,7 @@ __DEV__ &&
683684
root.entanglements[spawnedLaneIndex] =
684685
root.entanglements[spawnedLaneIndex] |
685686
1073741824 |
686-
(entangledLanes & 4194218);
687+
(entangledLanes & 4194090);
687688
}
688689
function markRootEntangled(root, entangledLanes) {
689690
var rootEntangledLanes = (root.entangledLanes |= entangledLanes);
@@ -2284,8 +2285,8 @@ __DEV__ &&
22842285
(1 << (31 - clz32(42 | syncTransitionLanes) + 1)) - 1;
22852286
nextLanes &= pendingLanes & ~(suspendedLanes & ~pingedLanes);
22862287
nextLanes =
2287-
nextLanes & 201326677
2288-
? (nextLanes & 201326677) | 1
2288+
nextLanes & 201326741
2289+
? (nextLanes & 201326741) | 1
22892290
: nextLanes
22902291
? nextLanes | 2
22912292
: 0;
@@ -2775,17 +2776,19 @@ __DEV__ &&
27752776
(isHidden = !0)),
27762777
(sourceFiber = parent),
27772778
(parent = parent.return);
2778-
isHidden &&
2779-
null !== update &&
2780-
3 === sourceFiber.tag &&
2781-
((parent = sourceFiber.stateNode),
2782-
(isHidden = 31 - clz32(lane)),
2783-
(parent = parent.hiddenUpdates),
2784-
(sourceFiber = parent[isHidden]),
2785-
null === sourceFiber
2786-
? (parent[isHidden] = [update])
2787-
: sourceFiber.push(update),
2788-
(update.lane = lane | 536870912));
2779+
return 3 === sourceFiber.tag
2780+
? ((parent = sourceFiber.stateNode),
2781+
isHidden &&
2782+
null !== update &&
2783+
((isHidden = 31 - clz32(lane)),
2784+
(sourceFiber = parent.hiddenUpdates),
2785+
(alternate = sourceFiber[isHidden]),
2786+
null === alternate
2787+
? (sourceFiber[isHidden] = [update])
2788+
: alternate.push(update),
2789+
(update.lane = lane | 536870912)),
2790+
parent)
2791+
: null;
27892792
}
27902793
function getRootForUpdatedFiber(sourceFiber) {
27912794
throwIfInfiniteUpdateLoopDetected();
@@ -2861,7 +2864,7 @@ __DEV__ &&
28612864
}
28622865
function entangleTransitions(root, fiber, lane) {
28632866
fiber = fiber.updateQueue;
2864-
if (null !== fiber && ((fiber = fiber.shared), 0 !== (lane & 4194176))) {
2867+
if (null !== fiber && ((fiber = fiber.shared), 0 !== (lane & 4194048))) {
28652868
var queueLanes = fiber.lanes;
28662869
queueLanes &= root.pendingLanes;
28672870
lane |= queueLanes;
@@ -3702,7 +3705,7 @@ __DEV__ &&
37023705
throw Error(
37033706
"Expected a work-in-progress root. This is a bug in React. Please file an issue."
37043707
);
3705-
0 !== (workInProgressRootRenderLanes & 60) ||
3708+
0 !== (workInProgressRootRenderLanes & 124) ||
37063709
pushStoreConsistencyCheck(fiber, getSnapshot, nextSnapshot);
37073710
hook.memoizedState = nextSnapshot;
37083711
cachedSnapshot = { value: nextSnapshot, getSnapshot: getSnapshot };
@@ -3772,7 +3775,7 @@ __DEV__ &&
37723775
throw Error(
37733776
"Expected a work-in-progress root. This is a bug in React. Please file an issue."
37743777
);
3775-
0 !== (renderLanes & 60) ||
3778+
0 !== (renderLanes & 124) ||
37763779
pushStoreConsistencyCheck(fiber, getSnapshot, nextSnapshot);
37773780
}
37783781
return nextSnapshot;
@@ -4791,7 +4794,7 @@ __DEV__ &&
47914794
queue.pending = update;
47924795
}
47934796
function entangleTransitionUpdate(root, queue, lane) {
4794-
if (0 !== (lane & 4194176)) {
4797+
if (0 !== (lane & 4194048)) {
47954798
var queueLanes = queue.lanes;
47964799
queueLanes &= root.pendingLanes;
47974800
lane |= queueLanes;
@@ -7659,7 +7662,6 @@ __DEV__ &&
76597662
case 32:
76607663
nextProps = 16;
76617664
break;
7662-
case 128:
76637665
case 256:
76647666
case 512:
76657667
case 1024:
@@ -7678,7 +7680,7 @@ __DEV__ &&
76787680
case 8388608:
76797681
case 16777216:
76807682
case 33554432:
7681-
nextProps = 64;
7683+
nextProps = 128;
76827684
break;
76837685
case 268435456:
76847686
nextProps = 134217728;
@@ -10304,7 +10306,7 @@ __DEV__ &&
1030410306
focusedInstanceHandle = null;
1030510307
shouldFireAfterActiveInstanceBlur = !1;
1030610308
root =
10307-
enableViewTransition && (committedLanes & 335544192) === committedLanes;
10309+
enableViewTransition && (committedLanes & 335544064) === committedLanes;
1030810310
nextEffect = firstChild;
1030910311
for (firstChild = root ? 9238 : 9236; null !== nextEffect; ) {
1031010312
committedLanes = nextEffect;
@@ -11618,7 +11620,7 @@ __DEV__ &&
1161811620
recursivelyTraverseMutationEffects(root, finishedWork, lanes);
1161911621
commitReconciliationEffects(finishedWork);
1162011622
enableViewTransition &&
11621-
(lanes & 335544192) === lanes &&
11623+
(lanes & 335544064) === lanes &&
1162211624
null !== current &&
1162311625
viewTransitionMutationContext &&
1162411626
(finishedWork.flags |= 4);
@@ -11940,7 +11942,7 @@ __DEV__ &&
1194011942
committedTransitions
1194111943
) {
1194211944
var isViewTransitionEligible =
11943-
enableViewTransition && (committedLanes & 335544192) === committedLanes;
11945+
enableViewTransition && (committedLanes & 335544064) === committedLanes;
1194411946
if (parentFiber.subtreeFlags & (isViewTransitionEligible ? 10262 : 10256))
1194511947
for (parentFiber = parentFiber.child; null !== parentFiber; )
1194611948
commitPassiveMountOnFiber(
@@ -11960,7 +11962,7 @@ __DEV__ &&
1196011962
committedTransitions
1196111963
) {
1196211964
var isViewTransitionEligible = enableViewTransition
11963-
? (committedLanes & 335544192) === committedLanes
11965+
? (committedLanes & 335544064) === committedLanes
1196411966
: !1;
1196511967
isViewTransitionEligible &&
1196611968
null === finishedWork.alternate &&
@@ -12825,7 +12827,7 @@ __DEV__ &&
1282512827
throw Error("Should not already be working.");
1282612828
var shouldTimeSlice =
1282712829
(!forceSync &&
12828-
0 === (lanes & 60) &&
12830+
0 === (lanes & 124) &&
1282912831
0 === (lanes & root.expiredLanes)) ||
1283012832
(enableSiblingPrerendering && checkIfRootIsPrerendering(root, lanes)),
1283112833
exitStatus = shouldTimeSlice
@@ -12908,7 +12910,7 @@ __DEV__ &&
1290812910
case RootFatalErrored:
1290912911
throw Error("Root did not complete. This is a bug in React.");
1291012912
case RootSuspendedWithDelay:
12911-
if ((lanes & 4194176) !== lanes) break;
12913+
if ((lanes & 4194048) !== lanes) break;
1291212914
case RootSuspendedAtTheShell:
1291312915
markRootSuspended(
1291412916
shouldTimeSlice,
@@ -13014,7 +13016,7 @@ __DEV__ &&
1301413016
root.timeoutHandle = -1;
1301513017
var subtreeFlags = finishedWork.subtreeFlags;
1301613018
if (
13017-
(enableViewTransition && (lanes & 335544192) === lanes) ||
13019+
(enableViewTransition && (lanes & 335544064) === lanes) ||
1301813020
subtreeFlags & 8192 ||
1301913021
16785408 === (subtreeFlags & 16785408)
1302013022
)
@@ -13185,7 +13187,7 @@ __DEV__ &&
1318513187
(JSCompiler_temp =
1318613188
null === JSCompiler_temp
1318713189
? !0
13188-
: (workInProgressRootRenderLanes & 4194176) ===
13190+
: (workInProgressRootRenderLanes & 4194048) ===
1318913191
workInProgressRootRenderLanes
1319013192
? null === shellBoundary
1319113193
? !0
@@ -13269,7 +13271,7 @@ __DEV__ &&
1326913271
function renderDidSuspendDelayIfPossible() {
1327013272
workInProgressRootExitStatus = RootSuspendedWithDelay;
1327113273
workInProgressRootDidSkipSuspendedSiblings ||
13272-
((workInProgressRootRenderLanes & 4194176) !==
13274+
((workInProgressRootRenderLanes & 4194048) !==
1327313275
workInProgressRootRenderLanes &&
1327413276
null !== suspenseHandlerStackCursor.current) ||
1327513277
(workInProgressRootIsPrerendering = !0);
@@ -13818,7 +13820,7 @@ __DEV__ &&
1381813820
pendingDidIncludeRenderPhaseUpdate = didIncludeRenderPhaseUpdate;
1381913821
enableViewTransition
1382013822
? ((pendingViewTransitionEvents = null),
13821-
(lanes & 335544192) === lanes
13823+
(lanes & 335544064) === lanes
1382213824
? ((pendingTransitionTypes = ReactSharedInternals.V),
1382313825
(ReactSharedInternals.V = null),
1382413826
(recoverableErrors = 10262))
@@ -13945,7 +13947,7 @@ __DEV__ &&
1394513947
recoverableErrors = pendingRecoverableErrors,
1394613948
didIncludeRenderPhaseUpdate = pendingDidIncludeRenderPhaseUpdate,
1394713949
passiveSubtreeMask =
13948-
enableViewTransition && (lanes & 335544192) === lanes
13950+
enableViewTransition && (lanes & 335544064) === lanes
1394913951
? 10262
1395013952
: 10256;
1395113953
(passiveSubtreeMask =
@@ -14045,7 +14047,7 @@ __DEV__ &&
1404514047
remainingLanes = root.pendingLanes;
1404614048
(enableInfiniteRenderLoopDetection &&
1404714049
(didIncludeRenderPhaseUpdate || didIncludeCommitPhaseUpdate)) ||
14048-
(0 !== (lanes & 4194218) && 0 !== (remainingLanes & 42))
14050+
(0 !== (lanes & 4194090) && 0 !== (remainingLanes & 42))
1404914051
? ((nestedUpdateScheduled = !0),
1405014052
root === rootWithNestedUpdates
1405114053
? nestedUpdateCount++
@@ -15265,7 +15267,7 @@ __DEV__ &&
1526515267
clz32 = Math.clz32 ? Math.clz32 : clz32Fallback,
1526615268
log = Math.log,
1526715269
LN2 = Math.LN2,
15268-
nextTransitionLane = 128,
15270+
nextTransitionLane = 256,
1526915271
nextRetryLane = 4194304,
1527015272
DiscreteEventPriority = 2,
1527115273
ContinuousEventPriority = 8,
@@ -17392,10 +17394,10 @@ __DEV__ &&
1739217394
(function () {
1739317395
var internals = {
1739417396
bundleType: 1,
17395-
version: "19.1.0-www-classic-c6a7e186-20250213",
17397+
version: "19.1.0-www-classic-a53da6ab-20250213",
1739617398
rendererPackageName: "react-art",
1739717399
currentDispatcherRef: ReactSharedInternals,
17398-
reconcilerVersion: "19.1.0-www-classic-c6a7e186-20250213"
17400+
reconcilerVersion: "19.1.0-www-classic-a53da6ab-20250213"
1739917401
};
1740017402
internals.overrideHookState = overrideHookState;
1740117403
internals.overrideHookStateDeletePath = overrideHookStateDeletePath;
@@ -17429,7 +17431,7 @@ __DEV__ &&
1742917431
exports.Shape = Shape;
1743017432
exports.Surface = Surface;
1743117433
exports.Text = Text;
17432-
exports.version = "19.1.0-www-classic-c6a7e186-20250213";
17434+
exports.version = "19.1.0-www-classic-a53da6ab-20250213";
1743317435
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
1743417436
"function" ===
1743517437
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop &&

0 commit comments

Comments
 (0)