mirror of
https://github.com/zebrajr/react.git
synced 2025-12-06 00:20:04 +01:00
Measure Updated ViewTransition Boundaries (#32653)
This does the same thing for `measureUpdateViewTransition` that we did
for `measureNestedViewTransitions` in
e3cbaffef0.
If a boundary hasn't mutated and didn't change in size, we mark it for
cancellation. Otherwise we add names to it. The different from the
CommitViewTransition path is that the "old" names are added to the
clones so this is the first time the "new" names.
Now we also cancel any boundaries that were unchanged. So now the root
no longer animates. We still have to clone them. There are other
optimizations that can avoid cloning but once we've done all the layouts
we can still cancel the running animation and let them just be the
regular content if they didn't change. Just like the regular
fire-and-forget path.
This also fixes the measurement so that we measure clones by adjusting
their position back into the viewport.
This actually surfaces a bug in Safari that was already in #32612. It
turns out that the old names aren't picked up for some reason and so in
Safari they looked more like a cross-fade than what #32612 was supposed
to fix. However, now that bug is even more apparent because they
actually just disappear in Safari. I'm not sure what that bug is but
it's unrelated to this PR so will fix that separately.
This commit is contained in:
parent
90b511ec7a
commit
3c3696d554
|
|
@ -77,9 +77,9 @@ export default function Page({url, navigate}) {
|
|||
<div>
|
||||
<button
|
||||
onClick={() => {
|
||||
navigate(show ? '/?a' : '/?b');
|
||||
navigate(url === '/?b' ? '/?a' : '/?b');
|
||||
}}>
|
||||
{show ? 'A' : 'B'}
|
||||
{url === '/?b' ? 'A' : 'B'}
|
||||
</button>
|
||||
<ViewTransition className="none">
|
||||
<div>
|
||||
|
|
|
|||
|
|
@ -518,6 +518,10 @@ export function measureInstance(instance) {
|
|||
return null;
|
||||
}
|
||||
|
||||
export function measureClonedInstance(instance) {
|
||||
return null;
|
||||
}
|
||||
|
||||
export function wasInstanceInViewport(measurement): boolean {
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1477,10 +1477,12 @@ export type InstanceMeasurement = {
|
|||
view: boolean, // is in viewport bounds
|
||||
};
|
||||
|
||||
export function measureInstance(instance: Instance): InstanceMeasurement {
|
||||
const ownerWindow = instance.ownerDocument.defaultView;
|
||||
const rect = instance.getBoundingClientRect();
|
||||
const computedStyle = getComputedStyle(instance);
|
||||
function createMeasurement(
|
||||
rect: ClientRect | DOMRect,
|
||||
computedStyle: CSSStyleDeclaration,
|
||||
element: Element,
|
||||
): InstanceMeasurement {
|
||||
const ownerWindow = element.ownerDocument.defaultView;
|
||||
return {
|
||||
rect: rect,
|
||||
abs:
|
||||
|
|
@ -1508,6 +1510,26 @@ export function measureInstance(instance: Instance): InstanceMeasurement {
|
|||
};
|
||||
}
|
||||
|
||||
export function measureInstance(instance: Instance): InstanceMeasurement {
|
||||
const rect = instance.getBoundingClientRect();
|
||||
const computedStyle = getComputedStyle(instance);
|
||||
return createMeasurement(rect, computedStyle, instance);
|
||||
}
|
||||
|
||||
export function measureClonedInstance(instance: Instance): InstanceMeasurement {
|
||||
const measuredRect = instance.getBoundingClientRect();
|
||||
// Adjust the DOMRect based on the translate that put it outside the viewport.
|
||||
// TODO: This might not be completely correct if the parent also has a transform.
|
||||
const rect = new DOMRect(
|
||||
measuredRect.x + 20000,
|
||||
measuredRect.y + 20000,
|
||||
measuredRect.width,
|
||||
measuredRect.height,
|
||||
);
|
||||
const computedStyle = getComputedStyle(instance);
|
||||
return createMeasurement(rect, computedStyle, instance);
|
||||
}
|
||||
|
||||
export function wasInstanceInViewport(
|
||||
measurement: InstanceMeasurement,
|
||||
): boolean {
|
||||
|
|
|
|||
|
|
@ -620,6 +620,10 @@ export function measureInstance(instance: Instance): InstanceMeasurement {
|
|||
return null;
|
||||
}
|
||||
|
||||
export function measureClonedInstance(instance: Instance): InstanceMeasurement {
|
||||
return null;
|
||||
}
|
||||
|
||||
export function wasInstanceInViewport(
|
||||
measurement: InstanceMeasurement,
|
||||
): boolean {
|
||||
|
|
|
|||
|
|
@ -796,6 +796,10 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
|
|||
return null;
|
||||
},
|
||||
|
||||
measureClonedInstance(instance: Instance): InstanceMeasurement {
|
||||
return null;
|
||||
},
|
||||
|
||||
wasInstanceInViewport(measurement: InstanceMeasurement): boolean {
|
||||
return true;
|
||||
},
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
import type {Fiber, FiberRoot} from './ReactInternalTypes';
|
||||
|
||||
import type {Instance, TextInstance} from './ReactFiberConfig';
|
||||
import type {Instance, TextInstance, Props} from './ReactFiberConfig';
|
||||
|
||||
import type {OffscreenState} from './ReactFiberActivityComponent';
|
||||
|
||||
|
|
@ -25,6 +25,7 @@ import {
|
|||
removeRootViewTransitionClone,
|
||||
cancelRootViewTransitionName,
|
||||
restoreRootViewTransitionName,
|
||||
cancelViewTransitionName,
|
||||
applyViewTransitionName,
|
||||
appendChild,
|
||||
commitUpdate,
|
||||
|
|
@ -39,6 +40,7 @@ import {
|
|||
popMutationContext,
|
||||
pushMutationContext,
|
||||
viewTransitionMutationContext,
|
||||
trackHostMutation,
|
||||
} from './ReactFiberMutationTracking';
|
||||
import {
|
||||
MutationMask,
|
||||
|
|
@ -48,6 +50,7 @@ import {
|
|||
Visibility,
|
||||
ViewTransitionNamedStatic,
|
||||
ViewTransitionStatic,
|
||||
AffectedParentLayout,
|
||||
} from './ReactFiberFlags';
|
||||
import {
|
||||
HostComponent,
|
||||
|
|
@ -61,9 +64,14 @@ import {
|
|||
import {
|
||||
restoreEnterOrExitViewTransitions,
|
||||
restoreNestedViewTransitions,
|
||||
restoreUpdateViewTransitionForGesture,
|
||||
appearingViewTransitions,
|
||||
commitEnterViewTransitions,
|
||||
measureNestedViewTransitions,
|
||||
measureUpdateViewTransition,
|
||||
viewTransitionCancelableChildren,
|
||||
pushViewTransitionCancelableScope,
|
||||
popViewTransitionCancelableScope,
|
||||
} from './ReactFiberCommitViewTransitions';
|
||||
import {
|
||||
getViewTransitionName,
|
||||
|
|
@ -72,6 +80,10 @@ import {
|
|||
|
||||
let didWarnForRootClone = false;
|
||||
|
||||
// Used during the apply phase to track whether a parent ViewTransition component
|
||||
// might have been affected by any mutations / relayouts below.
|
||||
let viewTransitionContextChanged: boolean = false;
|
||||
|
||||
function detectMutationOrInsertClones(finishedWork: Fiber): boolean {
|
||||
return true;
|
||||
}
|
||||
|
|
@ -421,6 +433,7 @@ function recursivelyInsertNewFiber(
|
|||
// For insertions we don't need to clone. It's already new state node.
|
||||
if (visitPhase !== INSERT_APPEARING_PAIR) {
|
||||
appendChild(hostParentClone, instance);
|
||||
trackHostMutation();
|
||||
recursivelyInsertNew(
|
||||
finishedWork,
|
||||
instance,
|
||||
|
|
@ -450,6 +463,7 @@ function recursivelyInsertNewFiber(
|
|||
// For insertions we don't need to clone. It's already new state node.
|
||||
if (visitPhase !== INSERT_APPEARING_PAIR) {
|
||||
appendChild(hostParentClone, textInstance);
|
||||
trackHostMutation();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -575,6 +589,7 @@ function recursivelyInsertClonesFromExistingTree(
|
|||
}
|
||||
if (visitPhase === CLONE_EXIT || visitPhase === CLONE_UNHIDE) {
|
||||
unhideInstance(clone, child.memoizedProps);
|
||||
trackHostMutation();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -590,6 +605,7 @@ function recursivelyInsertClonesFromExistingTree(
|
|||
appendChild(hostParentClone, clone);
|
||||
if (visitPhase === CLONE_EXIT || visitPhase === CLONE_UNHIDE) {
|
||||
unhideTextInstance(clone, child.memoizedProps);
|
||||
trackHostMutation();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -679,6 +695,10 @@ function recursivelyInsertClones(
|
|||
for (let i = 0; i < deletions.length; i++) {
|
||||
const childToDelete = deletions[i];
|
||||
trackEnterViewTransitions(childToDelete);
|
||||
// Normally we would only mark something as triggering a mutation if there was
|
||||
// actually a HostInstance below here. If this tree didn't contain a HostInstances
|
||||
// we shouldn't trigger a mutation even though a virtual component was deleted.
|
||||
trackHostMutation();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -801,6 +821,7 @@ function insertDestinationClonesOfFiber(
|
|||
clone = cloneMutableInstance(instance, true);
|
||||
if (finishedWork.flags & ContentReset) {
|
||||
resetTextContent(clone);
|
||||
trackHostMutation();
|
||||
}
|
||||
} else {
|
||||
// If we have children we'll clone them as we walk the tree so we just
|
||||
|
|
@ -825,6 +846,7 @@ function insertDestinationClonesOfFiber(
|
|||
);
|
||||
appendChild(hostParentClone, clone);
|
||||
unhideInstance(clone, finishedWork.memoizedProps);
|
||||
trackHostMutation();
|
||||
} else {
|
||||
recursivelyInsertClones(finishedWork, clone, null, visitPhase);
|
||||
appendChild(hostParentClone, clone);
|
||||
|
|
@ -851,10 +873,12 @@ function insertDestinationClonesOfFiber(
|
|||
const newText: string = finishedWork.memoizedProps;
|
||||
const oldText: string = current.memoizedProps;
|
||||
commitTextUpdate(clone, newText, oldText);
|
||||
trackHostMutation();
|
||||
}
|
||||
appendChild(hostParentClone, clone);
|
||||
if (visitPhase === CLONE_EXIT || visitPhase === CLONE_UNHIDE) {
|
||||
unhideTextInstance(clone, finishedWork.memoizedProps);
|
||||
trackHostMutation();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -885,6 +909,10 @@ function insertDestinationClonesOfFiber(
|
|||
} else if (current !== null && current.memoizedState === null) {
|
||||
// Was previously mounted as visible but is now hidden.
|
||||
trackEnterViewTransitions(current);
|
||||
// Normally we would only mark something as triggering a mutation if there was
|
||||
// actually a HostInstance below here. If this tree didn't contain a HostInstances
|
||||
// we shouldn't trigger a mutation even though a virtual component was hidden.
|
||||
trackHostMutation();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -991,13 +1019,6 @@ function measureExitViewTransitions(placement: Fiber): void {
|
|||
}
|
||||
}
|
||||
|
||||
function measureUpdateViewTransition(
|
||||
current: Fiber,
|
||||
finishedWork: Fiber,
|
||||
): void {
|
||||
// TODO
|
||||
}
|
||||
|
||||
function recursivelyApplyViewTransitions(parentFiber: Fiber) {
|
||||
const deletions = parentFiber.deletions;
|
||||
if (deletions !== null) {
|
||||
|
|
@ -1037,15 +1058,6 @@ function applyViewTransitionsOnFiber(finishedWork: Fiber) {
|
|||
// because the fiber tag is more specific. An exception is any flag related
|
||||
// to reconciliation, because those can be set on all fiber types.
|
||||
switch (finishedWork.tag) {
|
||||
case HostComponent: {
|
||||
// const instance: Instance = finishedWork.stateNode;
|
||||
// TODO: Apply name and measure.
|
||||
recursivelyApplyViewTransitions(finishedWork);
|
||||
break;
|
||||
}
|
||||
case HostText: {
|
||||
break;
|
||||
}
|
||||
case HostPortal: {
|
||||
// TODO: Consider what should happen to Portals. For now we exclude them.
|
||||
break;
|
||||
|
|
@ -1063,12 +1075,59 @@ function applyViewTransitionsOnFiber(finishedWork: Fiber) {
|
|||
}
|
||||
break;
|
||||
}
|
||||
case ViewTransitionComponent:
|
||||
measureUpdateViewTransition(current, finishedWork);
|
||||
case ViewTransitionComponent: {
|
||||
const prevContextChanged = viewTransitionContextChanged;
|
||||
const prevCancelableChildren = pushViewTransitionCancelableScope();
|
||||
viewTransitionContextChanged = false;
|
||||
recursivelyApplyViewTransitions(finishedWork);
|
||||
|
||||
if (viewTransitionContextChanged) {
|
||||
finishedWork.flags |= Update;
|
||||
}
|
||||
|
||||
const inViewport = measureUpdateViewTransition(
|
||||
current,
|
||||
finishedWork,
|
||||
true,
|
||||
);
|
||||
|
||||
if ((finishedWork.flags & Update) === NoFlags || !inViewport) {
|
||||
// If this boundary didn't update, then we may be able to cancel its children.
|
||||
// We bubble them up to the parent set to be determined later if we can cancel.
|
||||
// Similarly, if old and new state was outside the viewport, we can skip it
|
||||
// even if it did update.
|
||||
if (prevCancelableChildren === null) {
|
||||
// Bubbling up this whole set to the parent.
|
||||
} else {
|
||||
// Merge with parent set.
|
||||
// $FlowFixMe[method-unbinding]
|
||||
prevCancelableChildren.push.apply(
|
||||
prevCancelableChildren,
|
||||
viewTransitionCancelableChildren,
|
||||
);
|
||||
popViewTransitionCancelableScope(prevCancelableChildren);
|
||||
}
|
||||
// TODO: If this doesn't end up canceled, because a parent animates,
|
||||
// then we should probably issue an event since this instance is part of it.
|
||||
} else {
|
||||
// TODO: Schedule gesture events.
|
||||
// If this boundary did update, we cannot cancel its children so those are dropped.
|
||||
popViewTransitionCancelableScope(prevCancelableChildren);
|
||||
}
|
||||
|
||||
if ((finishedWork.flags & AffectedParentLayout) !== NoFlags) {
|
||||
// This boundary changed size in a way that may have caused its parent to
|
||||
// relayout. We need to bubble this information up to the parent.
|
||||
viewTransitionContextChanged = true;
|
||||
} else {
|
||||
// Otherwise, we restore it to whatever the parent had found so far.
|
||||
viewTransitionContextChanged = prevContextChanged;
|
||||
}
|
||||
|
||||
const viewTransitionState: ViewTransitionState = finishedWork.stateNode;
|
||||
viewTransitionState.clones = null; // Reset
|
||||
recursivelyApplyViewTransitions(finishedWork);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
recursivelyApplyViewTransitions(finishedWork);
|
||||
break;
|
||||
|
|
@ -1082,13 +1141,38 @@ export function applyDepartureTransitions(
|
|||
finishedWork: Fiber,
|
||||
): void {
|
||||
// First measure and apply view-transition-names to the "new" states.
|
||||
viewTransitionContextChanged = false;
|
||||
pushViewTransitionCancelableScope();
|
||||
|
||||
recursivelyApplyViewTransitions(finishedWork);
|
||||
|
||||
// Then remove the clones.
|
||||
const rootClone = root.gestureClone;
|
||||
if (rootClone !== null) {
|
||||
root.gestureClone = null;
|
||||
removeRootViewTransitionClone(root.containerInfo, rootClone);
|
||||
}
|
||||
|
||||
if (!viewTransitionContextChanged) {
|
||||
// If we didn't leak any resizing out to the root, we don't have to transition
|
||||
// the root itself. This means that we can now safely cancel any cancellations
|
||||
// that bubbled all the way up.
|
||||
const cancelableChildren = viewTransitionCancelableChildren;
|
||||
if (cancelableChildren !== null) {
|
||||
for (let i = 0; i < cancelableChildren.length; i += 3) {
|
||||
cancelViewTransitionName(
|
||||
((cancelableChildren[i]: any): Instance),
|
||||
((cancelableChildren[i + 1]: any): string),
|
||||
((cancelableChildren[i + 2]: any): Props),
|
||||
);
|
||||
}
|
||||
}
|
||||
// We also cancel the root itself. First we restore the name to the documentElement
|
||||
// and then we cancel it.
|
||||
restoreRootViewTransitionName(root.containerInfo);
|
||||
cancelRootViewTransitionName(root.containerInfo);
|
||||
}
|
||||
popViewTransitionCancelableScope(null);
|
||||
}
|
||||
|
||||
function recursivelyRestoreViewTransitions(parentFiber: Fiber) {
|
||||
|
|
@ -1130,15 +1214,6 @@ function restoreViewTransitionsOnFiber(finishedWork: Fiber) {
|
|||
// because the fiber tag is more specific. An exception is any flag related
|
||||
// to reconciliation, because those can be set on all fiber types.
|
||||
switch (finishedWork.tag) {
|
||||
case HostComponent: {
|
||||
// const instance: Instance = finishedWork.stateNode;
|
||||
// TODO: Restore the name.
|
||||
recursivelyRestoreViewTransitions(finishedWork);
|
||||
break;
|
||||
}
|
||||
case HostText: {
|
||||
break;
|
||||
}
|
||||
case HostPortal: {
|
||||
// TODO: Consider what should happen to Portals. For now we exclude them.
|
||||
break;
|
||||
|
|
@ -1157,8 +1232,7 @@ function restoreViewTransitionsOnFiber(finishedWork: Fiber) {
|
|||
break;
|
||||
}
|
||||
case ViewTransitionComponent:
|
||||
const viewTransitionState: ViewTransitionState = finishedWork.stateNode;
|
||||
viewTransitionState.clones = null; // Reset
|
||||
restoreUpdateViewTransitionForGesture(current, finishedWork);
|
||||
recursivelyRestoreViewTransitions(finishedWork);
|
||||
break;
|
||||
default: {
|
||||
|
|
|
|||
|
|
@ -199,6 +199,7 @@ export function commitShowHideHostTextInstance(node: Fiber, isHidden: boolean) {
|
|||
unhideTextInstance(instance, node.memoizedProps);
|
||||
}
|
||||
}
|
||||
trackHostMutation();
|
||||
} catch (error) {
|
||||
captureCommitPhaseError(node, node.return, error);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ import {
|
|||
applyViewTransitionName,
|
||||
restoreViewTransitionName,
|
||||
measureInstance,
|
||||
measureClonedInstance,
|
||||
hasInstanceChanged,
|
||||
hasInstanceAffectedParent,
|
||||
wasInstanceInViewport,
|
||||
|
|
@ -564,16 +565,23 @@ export function restoreUpdateViewTransition(
|
|||
current: Fiber,
|
||||
finishedWork: Fiber,
|
||||
): void {
|
||||
finishedWork.memoizedState = null;
|
||||
restoreViewTransitionOnHostInstances(current.child, true);
|
||||
restoreViewTransitionOnHostInstances(finishedWork.child, true);
|
||||
}
|
||||
|
||||
export function restoreUpdateViewTransitionForGesture(
|
||||
current: Fiber,
|
||||
finishedWork: Fiber,
|
||||
): void {
|
||||
// For gestures we don't need to reset "finishedWork" because those would
|
||||
// have all been clones that got deleted.
|
||||
restoreViewTransitionOnHostInstances(current.child, true);
|
||||
}
|
||||
|
||||
export function restoreNestedViewTransitions(changedParent: Fiber): void {
|
||||
let child = changedParent.child;
|
||||
while (child !== null) {
|
||||
if (child.tag === ViewTransitionComponent) {
|
||||
child.memoizedState = null;
|
||||
restoreViewTransitionOnHostInstances(child.child, false);
|
||||
} else if ((child.subtreeFlags & ViewTransitionStatic) !== NoFlags) {
|
||||
restoreNestedViewTransitions(child);
|
||||
|
|
@ -774,13 +782,16 @@ function measureViewTransitionHostInstancesRecursive(
|
|||
export function measureUpdateViewTransition(
|
||||
current: Fiber,
|
||||
finishedWork: Fiber,
|
||||
gesture: boolean,
|
||||
): boolean {
|
||||
const props: ViewTransitionProps = finishedWork.memoizedProps;
|
||||
const newName = getViewTransitionName(props, finishedWork.stateNode);
|
||||
const oldName = getViewTransitionName(
|
||||
current.memoizedProps,
|
||||
current.stateNode,
|
||||
);
|
||||
// If this was a gesture then which Fiber was used for the "old" vs "new" state is reversed.
|
||||
// We still need to treat "finishedWork" as the Fiber that contains the flags for this commmit.
|
||||
const oldFiber = gesture ? finishedWork : current;
|
||||
const newFiber = gesture ? current : finishedWork;
|
||||
const props: ViewTransitionProps = newFiber.memoizedProps;
|
||||
const state: ViewTransitionState = newFiber.stateNode;
|
||||
const newName = getViewTransitionName(props, state);
|
||||
const oldName = getViewTransitionName(oldFiber.memoizedProps, state);
|
||||
const updateClassName: ?string = getViewTransitionClassName(
|
||||
props.className,
|
||||
props.update,
|
||||
|
|
@ -807,7 +818,9 @@ export function measureUpdateViewTransition(
|
|||
if (layoutClassName === 'none') {
|
||||
// If we did not update, then all changes are considered a layout. We'll
|
||||
// attempt to cancel.
|
||||
cancelViewTransitionHostInstances(finishedWork.child, oldName, true);
|
||||
// This should use the Fiber that got names applied in the snapshot phase
|
||||
// since those are the ones we're trying to cancel.
|
||||
cancelViewTransitionHostInstances(oldFiber.child, oldName, true);
|
||||
return false;
|
||||
}
|
||||
// We didn't update but we might still apply layout so we measure each
|
||||
|
|
@ -816,10 +829,21 @@ export function measureUpdateViewTransition(
|
|||
}
|
||||
// If nothing changed due to a mutation, or children changing size
|
||||
// and the measurements end up unchanged, we should restore it to not animate.
|
||||
const previousMeasurements = current.memoizedState;
|
||||
let previousMeasurements: null | Array<InstanceMeasurement>;
|
||||
if (gesture) {
|
||||
const clones = state.clones;
|
||||
if (clones === null) {
|
||||
previousMeasurements = null;
|
||||
} else {
|
||||
previousMeasurements = clones.map(measureClonedInstance);
|
||||
}
|
||||
} else {
|
||||
previousMeasurements = oldFiber.memoizedState;
|
||||
oldFiber.memoizedState = null; // Clear it. We won't need it anymore.
|
||||
}
|
||||
const inViewport = measureViewTransitionHostInstances(
|
||||
finishedWork,
|
||||
finishedWork.child,
|
||||
finishedWork, // This is always finishedWork since it's used to assign flags.
|
||||
newFiber.child, // This either current or finishedWork depending on if was a gesture.
|
||||
newName,
|
||||
oldName,
|
||||
className,
|
||||
|
|
@ -857,10 +881,11 @@ export function measureNestedViewTransitions(
|
|||
if (clones === null) {
|
||||
previousMeasurements = null;
|
||||
} else {
|
||||
previousMeasurements = clones.map(measureInstance);
|
||||
previousMeasurements = clones.map(measureClonedInstance);
|
||||
}
|
||||
} else {
|
||||
previousMeasurements = child.memoizedState;
|
||||
child.memoizedState = null; // Clear it. We won't need it anymore.
|
||||
}
|
||||
const inViewport = measureViewTransitionHostInstances(
|
||||
child,
|
||||
|
|
|
|||
|
|
@ -2474,7 +2474,6 @@ function commitAfterMutationEffectsOnFiber(
|
|||
// the root itself. This means that we can now safely cancel any cancellations
|
||||
// that bubbled all the way up.
|
||||
const cancelableChildren = viewTransitionCancelableChildren;
|
||||
popViewTransitionCancelableScope(null);
|
||||
if (cancelableChildren !== null) {
|
||||
for (let i = 0; i < cancelableChildren.length; i += 3) {
|
||||
cancelViewTransitionName(
|
||||
|
|
@ -2487,6 +2486,7 @@ function commitAfterMutationEffectsOnFiber(
|
|||
// We also cancel the root itself.
|
||||
cancelRootViewTransitionName(root.containerInfo);
|
||||
}
|
||||
popViewTransitionCancelableScope(null);
|
||||
break;
|
||||
}
|
||||
case HostComponent: {
|
||||
|
|
@ -2528,7 +2528,11 @@ function commitAfterMutationEffectsOnFiber(
|
|||
finishedWork.flags |= Update;
|
||||
}
|
||||
|
||||
const inViewport = measureUpdateViewTransition(current, finishedWork);
|
||||
const inViewport = measureUpdateViewTransition(
|
||||
current,
|
||||
finishedWork,
|
||||
false,
|
||||
);
|
||||
|
||||
if ((finishedWork.flags & Update) === NoFlags || !inViewport) {
|
||||
// If this boundary didn't update, then we may be able to cancel its children.
|
||||
|
|
@ -3618,15 +3622,7 @@ function commitPassiveMountOnFiber(
|
|||
if (current === null) {
|
||||
// This is a new mount. We should have handled this as part of the
|
||||
// Placement effect or it is deeper inside a entering transition.
|
||||
} else if (
|
||||
(finishedWork.subtreeFlags &
|
||||
(Placement |
|
||||
Update |
|
||||
ChildDeletion |
|
||||
ContentReset |
|
||||
Visibility)) !==
|
||||
NoFlags
|
||||
) {
|
||||
} else {
|
||||
// Something mutated within this subtree. This might have caused
|
||||
// something to cross-fade if we didn't already cancel it.
|
||||
// If not, restore it.
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ export const cloneRootViewTransitionContainer = shim;
|
|||
export const removeRootViewTransitionClone = shim;
|
||||
export type InstanceMeasurement = null;
|
||||
export const measureInstance = shim;
|
||||
export const measureClonedInstance = shim;
|
||||
export const wasInstanceInViewport = shim;
|
||||
export const hasInstanceChanged = shim;
|
||||
export const hasInstanceAffectedParent = shim;
|
||||
|
|
|
|||
|
|
@ -149,6 +149,7 @@ export const cloneRootViewTransitionContainer =
|
|||
export const removeRootViewTransitionClone =
|
||||
$$$config.removeRootViewTransitionClone;
|
||||
export const measureInstance = $$$config.measureInstance;
|
||||
export const measureClonedInstance = $$$config.measureClonedInstance;
|
||||
export const wasInstanceInViewport = $$$config.wasInstanceInViewport;
|
||||
export const hasInstanceChanged = $$$config.hasInstanceChanged;
|
||||
export const hasInstanceAffectedParent = $$$config.hasInstanceAffectedParent;
|
||||
|
|
|
|||
|
|
@ -389,6 +389,10 @@ export function measureInstance(instance: Instance): InstanceMeasurement {
|
|||
return null;
|
||||
}
|
||||
|
||||
export function measureClonedInstance(instance: Instance): InstanceMeasurement {
|
||||
return null;
|
||||
}
|
||||
|
||||
export function wasInstanceInViewport(
|
||||
measurement: InstanceMeasurement,
|
||||
): boolean {
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user