Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion packages/react-reconciler/src/ReactFiber.new.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,6 @@ import {
} from './ReactWorkTags';
import {OffscreenVisible} from './ReactFiberOffscreenComponent';
import getComponentNameFromFiber from 'react-reconciler/src/getComponentNameFromFiber';

import {isDevToolsPresent} from './ReactFiberDevToolsHook.new';
import {
resolveClassForHotReloading,
Expand Down Expand Up @@ -109,6 +108,7 @@ import {
REACT_TRACING_MARKER_TYPE,
} from 'shared/ReactSymbols';
import {TransitionTracingMarker} from './ReactFiberTracingMarkerComponent.new';
import {detachOffscreenInstance} from './ReactFiberCommitWork.new';

export type {Fiber};

Expand Down Expand Up @@ -755,6 +755,8 @@ export function createFiberFromOffscreen(
_pendingMarkers: null,
_retryCache: null,
_transitions: null,
_current: null,
detach: () => detachOffscreenInstance(primaryChildInstance),
};
fiber.stateNode = primaryChildInstance;
return fiber;
Expand All @@ -776,6 +778,8 @@ export function createFiberFromLegacyHidden(
_pendingMarkers: null,
_transitions: null,
_retryCache: null,
_current: null,
detach: () => detachOffscreenInstance(instance),
};
fiber.stateNode = instance;
return fiber;
Expand Down
6 changes: 5 additions & 1 deletion packages/react-reconciler/src/ReactFiber.old.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,6 @@ import {
} from './ReactWorkTags';
import {OffscreenVisible} from './ReactFiberOffscreenComponent';
import getComponentNameFromFiber from 'react-reconciler/src/getComponentNameFromFiber';

import {isDevToolsPresent} from './ReactFiberDevToolsHook.old';
import {
resolveClassForHotReloading,
Expand Down Expand Up @@ -109,6 +108,7 @@ import {
REACT_TRACING_MARKER_TYPE,
} from 'shared/ReactSymbols';
import {TransitionTracingMarker} from './ReactFiberTracingMarkerComponent.old';
import {detachOffscreenInstance} from './ReactFiberCommitWork.old';

export type {Fiber};

Expand Down Expand Up @@ -755,6 +755,8 @@ export function createFiberFromOffscreen(
_pendingMarkers: null,
_retryCache: null,
_transitions: null,
_current: null,
detach: () => detachOffscreenInstance(primaryChildInstance),
};
fiber.stateNode = primaryChildInstance;
return fiber;
Expand All @@ -776,6 +778,8 @@ export function createFiberFromLegacyHidden(
_pendingMarkers: null,
_transitions: null,
_retryCache: null,
_current: null,
detach: () => detachOffscreenInstance(instance),
};
fiber.stateNode = instance;
return fiber;
Expand Down
7 changes: 5 additions & 2 deletions packages/react-reconciler/src/ReactFiberBeginWork.new.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import type {
OffscreenQueue,
OffscreenInstance,
} from './ReactFiberOffscreenComponent';
import {OffscreenDetached} from './ReactFiberOffscreenComponent';
import type {
Cache,
CacheComponentState,
Expand All @@ -37,7 +38,6 @@ import type {
import type {UpdateQueue} from './ReactFiberClassUpdateQueue.new';
import type {RootState} from './ReactFiberRoot.new';
import type {TracingMarkerInstance} from './ReactFiberTracingMarkerComponent.new';

import checkPropTypes from 'shared/checkPropTypes';
import {
markComponentRenderStarted,
Expand Down Expand Up @@ -688,7 +688,10 @@ function updateOffscreenComponent(

if (
nextProps.mode === 'hidden' ||
(enableLegacyHidden && nextProps.mode === 'unstable-defer-without-hiding')
(enableLegacyHidden &&
nextProps.mode === 'unstable-defer-without-hiding') ||
// TODO: remove read from stateNode.
workInProgress.stateNode._visibility & OffscreenDetached
) {
// Rendering a hidden tree.

Expand Down
7 changes: 5 additions & 2 deletions packages/react-reconciler/src/ReactFiberBeginWork.old.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import type {
OffscreenQueue,
OffscreenInstance,
} from './ReactFiberOffscreenComponent';
import {OffscreenDetached} from './ReactFiberOffscreenComponent';
import type {
Cache,
CacheComponentState,
Expand All @@ -37,7 +38,6 @@ import type {
import type {UpdateQueue} from './ReactFiberClassUpdateQueue.old';
import type {RootState} from './ReactFiberRoot.old';
import type {TracingMarkerInstance} from './ReactFiberTracingMarkerComponent.old';

import checkPropTypes from 'shared/checkPropTypes';
import {
markComponentRenderStarted,
Expand Down Expand Up @@ -688,7 +688,10 @@ function updateOffscreenComponent(

if (
nextProps.mode === 'hidden' ||
(enableLegacyHidden && nextProps.mode === 'unstable-defer-without-hiding')
(enableLegacyHidden &&
nextProps.mode === 'unstable-defer-without-hiding') ||
// TODO: remove read from stateNode.
workInProgress.stateNode._visibility & OffscreenDetached
) {
// Rendering a hidden tree.

Expand Down
31 changes: 30 additions & 1 deletion packages/react-reconciler/src/ReactFiberCommitWork.new.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import type {SuspenseState} from './ReactFiberSuspenseComponent.new';
import type {UpdateQueue} from './ReactFiberClassUpdateQueue.new';
import type {FunctionComponentUpdateQueue} from './ReactFiberHooks.new';
import type {Wakeable} from 'shared/ReactTypes';
import {isOffscreenManual} from './ReactFiberOffscreenComponent';
import type {
OffscreenState,
OffscreenInstance,
Expand Down Expand Up @@ -153,6 +154,7 @@ import {
clearSingleton,
acquireSingletonInstance,
releaseSingletonInstance,
scheduleMicrotask,
} from './ReactFiberHostConfig';
import {
captureCommitPhaseError,
Expand All @@ -169,6 +171,7 @@ import {
setIsRunningInsertionEffect,
getExecutionContext,
CommitContext,
RenderContext,
NoContext,
} from './ReactFiberWorkLoop.new';
import {
Expand Down Expand Up @@ -197,6 +200,7 @@ import {releaseCache, retainCache} from './ReactFiberCacheComponent.new';
import {clearTransitionsForLanes} from './ReactFiberLane.new';
import {
OffscreenVisible,
OffscreenDetached,
OffscreenPassiveEffectsConnected,
} from './ReactFiberOffscreenComponent';
import {
Expand Down Expand Up @@ -2426,6 +2430,28 @@ function getRetryCache(finishedWork) {
}
}

export function detachOffscreenInstance(instance: OffscreenInstance): void {
const currentOffscreenFiber = instance._current;
if (currentOffscreenFiber === null) {
throw new Error(
'Calling Offscreen.detach before instance handle has been set.',
);
}

const executionContext = getExecutionContext();
if ((executionContext & (RenderContext | CommitContext)) !== NoContext) {
scheduleMicrotask(() => {
instance._visibility |= OffscreenDetached;
disappearLayoutEffects(currentOffscreenFiber);
disconnectPassiveEffect(currentOffscreenFiber);
});
} else {
instance._visibility |= OffscreenDetached;
disappearLayoutEffects(currentOffscreenFiber);
disconnectPassiveEffect(currentOffscreenFiber);
}
}

function attachSuspenseRetryListeners(
finishedWork: Fiber,
wakeables: Set<Wakeable>,
Expand Down Expand Up @@ -2842,6 +2868,8 @@ function commitMutationEffectsOnFiber(
}

commitReconciliationEffects(finishedWork);
// TODO: Add explicit effect flag to set _current.
finishedWork.stateNode._current = finishedWork;

if (flags & Visibility) {
const offscreenInstance: OffscreenInstance = finishedWork.stateNode;
Expand All @@ -2868,7 +2896,8 @@ function commitMutationEffectsOnFiber(
}
}

if (supportsMutation) {
// Offscreen with manual mode manages visibility manually.
if (supportsMutation && !isOffscreenManual(finishedWork)) {
// TODO: This needs to run whenever there's an insertion or update
// inside a hidden Offscreen tree.
hideOrUnhideAllChildren(offscreenBoundary, isHidden);
Expand Down
31 changes: 30 additions & 1 deletion packages/react-reconciler/src/ReactFiberCommitWork.old.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import type {SuspenseState} from './ReactFiberSuspenseComponent.old';
import type {UpdateQueue} from './ReactFiberClassUpdateQueue.old';
import type {FunctionComponentUpdateQueue} from './ReactFiberHooks.old';
import type {Wakeable} from 'shared/ReactTypes';
import {isOffscreenManual} from './ReactFiberOffscreenComponent';
import type {
OffscreenState,
OffscreenInstance,
Expand Down Expand Up @@ -153,6 +154,7 @@ import {
clearSingleton,
acquireSingletonInstance,
releaseSingletonInstance,
scheduleMicrotask,
} from './ReactFiberHostConfig';
import {
captureCommitPhaseError,
Expand All @@ -169,6 +171,7 @@ import {
setIsRunningInsertionEffect,
getExecutionContext,
CommitContext,
RenderContext,
NoContext,
} from './ReactFiberWorkLoop.old';
import {
Expand Down Expand Up @@ -197,6 +200,7 @@ import {releaseCache, retainCache} from './ReactFiberCacheComponent.old';
import {clearTransitionsForLanes} from './ReactFiberLane.old';
import {
OffscreenVisible,
OffscreenDetached,
OffscreenPassiveEffectsConnected,
} from './ReactFiberOffscreenComponent';
import {
Expand Down Expand Up @@ -2426,6 +2430,28 @@ function getRetryCache(finishedWork) {
}
}

export function detachOffscreenInstance(instance: OffscreenInstance): void {
const currentOffscreenFiber = instance._current;
if (currentOffscreenFiber === null) {
throw new Error(
'Calling Offscreen.detach before instance handle has been set.',
);
}

const executionContext = getExecutionContext();
if ((executionContext & (RenderContext | CommitContext)) !== NoContext) {
scheduleMicrotask(() => {
instance._visibility |= OffscreenDetached;
disappearLayoutEffects(currentOffscreenFiber);
disconnectPassiveEffect(currentOffscreenFiber);
});
} else {
instance._visibility |= OffscreenDetached;
disappearLayoutEffects(currentOffscreenFiber);
disconnectPassiveEffect(currentOffscreenFiber);
}
}

function attachSuspenseRetryListeners(
finishedWork: Fiber,
wakeables: Set<Wakeable>,
Expand Down Expand Up @@ -2842,6 +2868,8 @@ function commitMutationEffectsOnFiber(
}

commitReconciliationEffects(finishedWork);
// TODO: Add explicit effect flag to set _current.
finishedWork.stateNode._current = finishedWork;

if (flags & Visibility) {
const offscreenInstance: OffscreenInstance = finishedWork.stateNode;
Expand All @@ -2868,7 +2896,8 @@ function commitMutationEffectsOnFiber(
}
}

if (supportsMutation) {
// Offscreen with manual mode manages visibility manually.
if (supportsMutation && !isOffscreenManual(finishedWork)) {
// TODO: This needs to run whenever there's an insertion or update
// inside a hidden Offscreen tree.
hideOrUnhideAllChildren(offscreenBoundary, isHidden);
Expand Down
10 changes: 9 additions & 1 deletion packages/react-reconciler/src/ReactFiberCompleteWork.new.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import type {
SuspenseState,
SuspenseListRenderState,
} from './ReactFiberSuspenseComponent.new';
import {isOffscreenManual} from './ReactFiberOffscreenComponent';
import type {OffscreenState} from './ReactFiberOffscreenComponent';
import type {TracingMarkerInstance} from './ReactFiberTracingMarkerComponent.new';
import type {Cache} from './ReactFiberCacheComponent.new';
Expand Down Expand Up @@ -428,7 +429,14 @@ if (supportsMutation) {
if (child !== null) {
child.return = node;
}
appendAllChildrenToContainer(containerChildSet, node, true, true);
// If Offscreen is not in manual mode, detached tree is hidden from user space.
const _needsVisibilityToggle = !isOffscreenManual(node);
appendAllChildrenToContainer(
containerChildSet,
node,
_needsVisibilityToggle,
true,
);
} else if (node.child !== null) {
node.child.return = node;
node = node.child;
Expand Down
10 changes: 9 additions & 1 deletion packages/react-reconciler/src/ReactFiberCompleteWork.old.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import type {
SuspenseState,
SuspenseListRenderState,
} from './ReactFiberSuspenseComponent.old';
import {isOffscreenManual} from './ReactFiberOffscreenComponent';
import type {OffscreenState} from './ReactFiberOffscreenComponent';
import type {TracingMarkerInstance} from './ReactFiberTracingMarkerComponent.old';
import type {Cache} from './ReactFiberCacheComponent.old';
Expand Down Expand Up @@ -428,7 +429,14 @@ if (supportsMutation) {
if (child !== null) {
child.return = node;
}
appendAllChildrenToContainer(containerChildSet, node, true, true);
// If Offscreen is not in manual mode, detached tree is hidden from user space.
const _needsVisibilityToggle = !isOffscreenManual(node);
appendAllChildrenToContainer(
containerChildSet,
node,
_needsVisibilityToggle,
true,
);
} else if (node.child !== null) {
node.child.return = node;
node = node.child;
Expand Down
19 changes: 17 additions & 2 deletions packages/react-reconciler/src/ReactFiberOffscreenComponent.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import type {ReactNodeList, OffscreenMode, Wakeable} from 'shared/ReactTypes';
import type {Lanes} from './ReactFiberLane.old';
import type {SpawnedCachePool} from './ReactFiberCacheComponent.new';
import type {Fiber} from './ReactInternalTypes';
import type {
Transition,
TracingMarkerInstance,
Expand Down Expand Up @@ -44,13 +45,27 @@ export type OffscreenQueue = {

type OffscreenVisibility = number;

export const OffscreenVisible = /* */ 0b01;
export const OffscreenPassiveEffectsConnected = /* */ 0b10;
export const OffscreenVisible = /* */ 0b001;
export const OffscreenDetached = /* */ 0b010;
export const OffscreenPassiveEffectsConnected = /* */ 0b100;

export type OffscreenInstance = {
_visibility: OffscreenVisibility,
_pendingMarkers: Set<TracingMarkerInstance> | null,
_transitions: Set<Transition> | null,
// $FlowFixMe[incompatible-type-arg] found when upgrading Flow
_retryCache: WeakSet<Wakeable> | Set<Wakeable> | null,

// Represents the current Offscreen fiber
_current: Fiber | null,
detach: () => void,

// TODO: attach
};

export function isOffscreenManual(offscreenFiber: Fiber): boolean {
return (
offscreenFiber.memoizedProps !== null &&
offscreenFiber.memoizedProps.mode === 'manual'
);
}
2 changes: 1 addition & 1 deletion packages/react-reconciler/src/ReactFiberWorkLoop.new.js
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ type ExecutionContext = number;

export const NoContext = /* */ 0b000;
const BatchedContext = /* */ 0b001;
const RenderContext = /* */ 0b010;
export const RenderContext = /* */ 0b010;
export const CommitContext = /* */ 0b100;

type RootExitStatus = 0 | 1 | 2 | 3 | 4 | 5 | 6;
Expand Down
2 changes: 1 addition & 1 deletion packages/react-reconciler/src/ReactFiberWorkLoop.old.js
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ type ExecutionContext = number;

export const NoContext = /* */ 0b000;
const BatchedContext = /* */ 0b001;
const RenderContext = /* */ 0b010;
export const RenderContext = /* */ 0b010;
export const CommitContext = /* */ 0b100;

type RootExitStatus = 0 | 1 | 2 | 3 | 4 | 5 | 6;
Expand Down
Loading