Remove enablePersistentOffscreenHostContainer flag (#24460)

This was a Fabric-related experiment that we ended up not shipping.
This commit is contained in:
Andrew Clark 2022-04-28 15:05:41 -04:00 committed by GitHub
parent 340060cccd
commit ce13860281
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 25 additions and 688 deletions

View File

@ -7,7 +7,6 @@
* @flow
*/
import type {ReactNodeList, OffscreenMode} from 'shared/ReactTypes';
import type {ElementRef} from 'react';
import type {
HostComponent,
@ -545,37 +544,6 @@ export function cloneInstance(
};
}
// TODO: These two methods should be replaced with `createOffscreenInstance` and
// `cloneOffscreenInstance`. I did it this way for now because the offscreen
// instance is stored on an extra HostComponent fiber instead of the
// OffscreenComponent fiber, and I didn't want to add an extra check to the
// generic HostComponent path. Instead we should use the OffscreenComponent
// fiber, but currently Fabric expects a 1:1 correspondence between Fabric
// instances and host fibers, so I'm leaving this optimization for later once
// we can confirm this won't break any downstream expectations.
export function getOffscreenContainerType(): string {
return 'RCTView';
}
export function getOffscreenContainerProps(
mode: OffscreenMode,
children: ReactNodeList,
): Props {
if (mode === 'hidden') {
return {
children,
style: {display: 'none'},
};
} else {
return {
children,
style: {
flex: 1,
},
};
}
}
export function cloneHiddenInstance(
instance: Instance,
type: string,

View File

@ -19,7 +19,7 @@ import type {
TransitionTracingCallbacks,
} from 'react-reconciler/src/ReactInternalTypes';
import type {UpdateQueue} from 'react-reconciler/src/ReactUpdateQueue';
import type {ReactNodeList, OffscreenMode} from 'shared/ReactTypes';
import type {ReactNodeList} from 'shared/ReactTypes';
import type {RootTag} from 'react-reconciler/src/ReactRootTags';
import * as Scheduler from 'scheduler/unstable_mock';
@ -595,20 +595,6 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
container.children = newChildren;
},
getOffscreenContainerType(): string {
return 'offscreen';
},
getOffscreenContainerProps(
mode: OffscreenMode,
children: ReactNodeList,
): Props {
return {
hidden: mode === 'hidden',
children,
};
},
cloneHiddenInstance(
instance: Instance,
type: string,
@ -721,9 +707,7 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
function getChildren(root) {
if (root) {
return useMutation
? root.children
: removeOffscreenContainersFromChildren(root.children, false);
return root.children;
} else {
return null;
}
@ -731,169 +715,12 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
function getPendingChildren(root) {
if (root) {
return useMutation
? root.children
: removeOffscreenContainersFromChildren(root.pendingChildren, false);
return root.children;
} else {
return null;
}
}
function removeOffscreenContainersFromChildren(children, hideNearestNode) {
// Mutation mode and persistent mode have different outputs for Offscreen
// and Suspense trees. Persistent mode adds an additional host node wrapper,
// whereas mutation mode does not.
//
// This function removes the offscreen host wrappers so that the output is
// consistent. If the offscreen node is hidden, it transfers the hiddenness
// to the child nodes, to mimic how it works in mutation mode. That way our
// tests don't have to fork tree assertions.
//
// So, it takes a tree that looks like this:
//
// <offscreen hidden={true}>
// <span>A</span>
// <span>B</span>
// </offscren>
//
// And turns it into this:
//
// <span hidden={true}>A</span>
// <span hidden={true}>B</span>
//
// We don't mutate the original tree, but instead return a copy.
//
// This function is only used by our test assertions, via the `getChildren`
// and `getChildrenAsJSX` methods.
let didClone = false;
const newChildren = [];
for (let i = 0; i < children.length; i++) {
const child = children[i];
const innerChildren = child.children;
if (innerChildren !== undefined) {
// This is a host instance instance
const instance: Instance = (child: any);
if (instance.type === 'offscreen') {
// This is an offscreen wrapper instance. Remove it from the tree
// and recursively return its children, as if it were a fragment.
didClone = true;
if (instance.text !== null) {
// If this offscreen tree contains only text, we replace it with
// a text child. Related to `shouldReplaceTextContent` feature.
const offscreenTextInstance: TextInstance = {
text: instance.text,
id: instanceCounter++,
parent: instance.parent,
hidden: hideNearestNode || instance.hidden,
context: instance.context,
};
// Hide from unit tests
Object.defineProperty(offscreenTextInstance, 'id', {
value: offscreenTextInstance.id,
enumerable: false,
});
Object.defineProperty(offscreenTextInstance, 'parent', {
value: offscreenTextInstance.parent,
enumerable: false,
});
Object.defineProperty(offscreenTextInstance, 'context', {
value: offscreenTextInstance.context,
enumerable: false,
});
newChildren.push(offscreenTextInstance);
} else {
// Skip the offscreen node and replace it with its children
const offscreenChildren = removeOffscreenContainersFromChildren(
innerChildren,
hideNearestNode || instance.hidden,
);
newChildren.push.apply(newChildren, offscreenChildren);
}
} else {
// This is a regular (non-offscreen) instance. If the nearest
// offscreen boundary is hidden, hide this node.
const hidden = hideNearestNode ? true : instance.hidden;
const clonedChildren = removeOffscreenContainersFromChildren(
instance.children,
// We never need to hide the children of this node, since if we're
// inside a hidden tree, then the hidden style will be applied to
// this node.
false,
);
if (
clonedChildren === instance.children &&
hidden === instance.hidden
) {
// No changes. Reuse the original instance without cloning.
newChildren.push(instance);
} else {
didClone = true;
const clone: Instance = {
id: instance.id,
type: instance.type,
parent: instance.parent,
children: clonedChildren,
text: instance.text,
prop: instance.prop,
hidden: hideNearestNode ? true : instance.hidden,
context: instance.context,
};
Object.defineProperty(clone, 'id', {
value: clone.id,
enumerable: false,
});
Object.defineProperty(clone, 'parent', {
value: clone.parent,
enumerable: false,
});
Object.defineProperty(clone, 'text', {
value: clone.text,
enumerable: false,
});
Object.defineProperty(clone, 'context', {
value: clone.context,
enumerable: false,
});
newChildren.push(clone);
}
}
} else {
// This is a text instance
const textInstance: TextInstance = (child: any);
if (hideNearestNode) {
didClone = true;
const clone = {
text: textInstance.text,
id: textInstance.id,
parent: textInstance.parent,
hidden: textInstance.hidden || hideNearestNode,
context: textInstance.context,
};
Object.defineProperty(clone, 'id', {
value: clone.id,
enumerable: false,
});
Object.defineProperty(clone, 'parent', {
value: clone.parent,
enumerable: false,
});
Object.defineProperty(clone, 'context', {
value: clone.context,
enumerable: false,
});
newChildren.push(clone);
} else {
newChildren.push(textInstance);
}
}
}
// There are some tests that assume reference equality, so preserve it
// when possible. Alternatively, we could update the tests to compare the
// ids instead.
return didClone ? newChildren : children;
}
function getChildrenAsJSX(root) {
const children = childToJSX(getChildren(root), null);
if (children === null) {

View File

@ -14,7 +14,7 @@ import type {RootTag} from './ReactRootTags';
import type {WorkTag} from './ReactWorkTags';
import type {TypeOfMode} from './ReactTypeOfMode';
import type {Lanes} from './ReactFiberLane.new';
import type {SuspenseInstance, Props} from './ReactFiberHostConfig';
import type {SuspenseInstance} from './ReactFiberHostConfig';
import type {
OffscreenProps,
OffscreenInstance,
@ -32,10 +32,6 @@ import {
enableTransitionTracing,
enableDebugTracing,
} from 'shared/ReactFeatureFlags';
import {
supportsPersistence,
getOffscreenContainerType,
} from './ReactFiberHostConfig';
import {NoFlags, Placement, StaticMask} from './ReactFiberFlags';
import {ConcurrentRoot} from './ReactRootTags';
import {
@ -605,25 +601,6 @@ export function createFiberFromTypeAndProps(
return fiber;
}
export function createOffscreenHostContainerFiber(
props: Props,
fiberMode: TypeOfMode,
lanes: Lanes,
key: null | string,
): Fiber {
if (supportsPersistence) {
const type = getOffscreenContainerType();
const fiber = createFiber(HostComponent, props, key, fiberMode);
fiber.elementType = type;
fiber.type = type;
fiber.lanes = lanes;
return fiber;
} else {
// Only implemented in persistent mode
throw new Error('Not implemented.');
}
}
export function createFiberFromElement(
element: ReactElement,
mode: TypeOfMode,

View File

@ -14,7 +14,7 @@ import type {RootTag} from './ReactRootTags';
import type {WorkTag} from './ReactWorkTags';
import type {TypeOfMode} from './ReactTypeOfMode';
import type {Lanes} from './ReactFiberLane.old';
import type {SuspenseInstance, Props} from './ReactFiberHostConfig';
import type {SuspenseInstance} from './ReactFiberHostConfig';
import type {
OffscreenProps,
OffscreenInstance,
@ -32,10 +32,6 @@ import {
enableTransitionTracing,
enableDebugTracing,
} from 'shared/ReactFeatureFlags';
import {
supportsPersistence,
getOffscreenContainerType,
} from './ReactFiberHostConfig';
import {NoFlags, Placement, StaticMask} from './ReactFiberFlags';
import {ConcurrentRoot} from './ReactRootTags';
import {
@ -605,25 +601,6 @@ export function createFiberFromTypeAndProps(
return fiber;
}
export function createOffscreenHostContainerFiber(
props: Props,
fiberMode: TypeOfMode,
lanes: Lanes,
key: null | string,
): Fiber {
if (supportsPersistence) {
const type = getOffscreenContainerType();
const fiber = createFiber(HostComponent, props, key, fiberMode);
fiber.elementType = type;
fiber.type = type;
fiber.lanes = lanes;
return fiber;
} else {
// Only implemented in persistent mode
throw new Error('Not implemented.');
}
}
export function createFiberFromElement(
element: ReactElement,
mode: TypeOfMode,

View File

@ -102,7 +102,6 @@ import {
enableLazyContextPropagation,
enableSuspenseLayoutEffectSemantics,
enableSchedulingProfiler,
enablePersistentOffscreenHostContainer,
enableTransitionTracing,
enableLegacyHidden,
} from 'shared/ReactFeatureFlags';
@ -161,8 +160,6 @@ import {
registerSuspenseInstanceRetry,
supportsHydration,
isPrimaryRenderer,
supportsPersistence,
getOffscreenContainerProps,
} from './ReactFiberHostConfig';
import type {SuspenseInstance} from './ReactFiberHostConfig';
import {shouldError, shouldSuspend} from './ReactFiberReconciler';
@ -226,7 +223,6 @@ import {
createFiberFromFragment,
createFiberFromOffscreen,
createWorkInProgress,
createOffscreenHostContainerFiber,
isSimpleFunctionComponent,
} from './ReactFiber.new';
import {
@ -241,7 +237,6 @@ import {setWorkInProgressVersion} from './ReactMutableSource.new';
import {pushCacheProvider, CacheContext} from './ReactFiberCacheComponent.new';
import {createCapturedValue} from './ReactCapturedValue';
import {createClassErrorUpdate} from './ReactFiberThrow.new';
import {completeSuspendedOffscreenHostContainer} from './ReactFiberCompleteWork.new';
import is from 'shared/objectIs';
import {
getForksAtLevel,
@ -800,67 +795,8 @@ function updateOffscreenComponent(
pushRenderLanes(workInProgress, subtreeRenderLanes);
}
if (enablePersistentOffscreenHostContainer && supportsPersistence) {
// In persistent mode, the offscreen children are wrapped in a host node.
// TODO: Optimize this to use the OffscreenComponent fiber instead of
// an extra HostComponent fiber. Need to make sure this doesn't break Fabric
// or some other infra that expects a HostComponent.
const isHidden =
nextProps.mode === 'hidden' &&
(!enableLegacyHidden || workInProgress.tag !== LegacyHiddenComponent);
const offscreenContainer = reconcileOffscreenHostContainer(
current,
workInProgress,
isHidden,
nextChildren,
renderLanes,
);
return offscreenContainer;
} else {
reconcileChildren(current, workInProgress, nextChildren, renderLanes);
return workInProgress.child;
}
}
function reconcileOffscreenHostContainer(
currentOffscreen: Fiber | null,
offscreen: Fiber,
isHidden: boolean,
children: any,
renderLanes: Lanes,
) {
const containerProps = getOffscreenContainerProps(
isHidden ? 'hidden' : 'visible',
children,
);
let hostContainer;
if (currentOffscreen === null) {
hostContainer = createOffscreenHostContainerFiber(
containerProps,
offscreen.mode,
renderLanes,
null,
);
} else {
const currentHostContainer = currentOffscreen.child;
if (currentHostContainer === null) {
hostContainer = createOffscreenHostContainerFiber(
containerProps,
offscreen.mode,
renderLanes,
null,
);
hostContainer.flags |= Placement;
} else {
hostContainer = createWorkInProgress(
currentHostContainer,
containerProps,
);
}
}
hostContainer.return = offscreen;
offscreen.child = hostContainer;
return hostContainer;
reconcileChildren(current, workInProgress, nextChildren, renderLanes);
return workInProgress.child;
}
// Note: These happen to have identical begin phases, for now. We shouldn't hold
@ -2575,24 +2511,6 @@ function updateSuspenseFallbackChildren(
currentPrimaryChildFragment.treeBaseDuration;
}
if (enablePersistentOffscreenHostContainer && supportsPersistence) {
// In persistent mode, the offscreen children are wrapped in a host node.
// We need to complete it now, because we're going to skip over its normal
// complete phase and go straight to rendering the fallback.
const currentOffscreenContainer = currentPrimaryChildFragment.child;
const offscreenContainer: Fiber = (primaryChildFragment.child: any);
const containerProps = getOffscreenContainerProps(
'hidden',
primaryChildren,
);
offscreenContainer.pendingProps = containerProps;
offscreenContainer.memoizedProps = containerProps;
completeSuspendedOffscreenHostContainer(
currentOffscreenContainer,
offscreenContainer,
);
}
// The fallback fiber was added as a deletion during the first pass.
// However, since we're going to remain on the fallback, we no longer want
// to delete it.
@ -2602,29 +2520,6 @@ function updateSuspenseFallbackChildren(
currentPrimaryChildFragment,
primaryChildProps,
);
if (enablePersistentOffscreenHostContainer && supportsPersistence) {
// In persistent mode, the offscreen children are wrapped in a host node.
// We need to complete it now, because we're going to skip over its normal
// complete phase and go straight to rendering the fallback.
const currentOffscreenContainer = currentPrimaryChildFragment.child;
if (currentOffscreenContainer !== null) {
const isHidden = true;
const offscreenContainer = reconcileOffscreenHostContainer(
currentPrimaryChildFragment,
primaryChildFragment,
isHidden,
primaryChildren,
renderLanes,
);
offscreenContainer.memoizedProps = offscreenContainer.pendingProps;
completeSuspendedOffscreenHostContainer(
currentOffscreenContainer,
offscreenContainer,
);
}
}
// Since we're reusing a current tree, we need to reuse the flags, too.
// (We don't do this in legacy mode, because in legacy mode we don't re-use
// the current tree; see previous branch.)

View File

@ -102,7 +102,6 @@ import {
enableLazyContextPropagation,
enableSuspenseLayoutEffectSemantics,
enableSchedulingProfiler,
enablePersistentOffscreenHostContainer,
enableTransitionTracing,
enableLegacyHidden,
} from 'shared/ReactFeatureFlags';
@ -161,8 +160,6 @@ import {
registerSuspenseInstanceRetry,
supportsHydration,
isPrimaryRenderer,
supportsPersistence,
getOffscreenContainerProps,
} from './ReactFiberHostConfig';
import type {SuspenseInstance} from './ReactFiberHostConfig';
import {shouldError, shouldSuspend} from './ReactFiberReconciler';
@ -226,7 +223,6 @@ import {
createFiberFromFragment,
createFiberFromOffscreen,
createWorkInProgress,
createOffscreenHostContainerFiber,
isSimpleFunctionComponent,
} from './ReactFiber.old';
import {
@ -241,7 +237,6 @@ import {setWorkInProgressVersion} from './ReactMutableSource.old';
import {pushCacheProvider, CacheContext} from './ReactFiberCacheComponent.old';
import {createCapturedValue} from './ReactCapturedValue';
import {createClassErrorUpdate} from './ReactFiberThrow.old';
import {completeSuspendedOffscreenHostContainer} from './ReactFiberCompleteWork.old';
import is from 'shared/objectIs';
import {
getForksAtLevel,
@ -800,67 +795,8 @@ function updateOffscreenComponent(
pushRenderLanes(workInProgress, subtreeRenderLanes);
}
if (enablePersistentOffscreenHostContainer && supportsPersistence) {
// In persistent mode, the offscreen children are wrapped in a host node.
// TODO: Optimize this to use the OffscreenComponent fiber instead of
// an extra HostComponent fiber. Need to make sure this doesn't break Fabric
// or some other infra that expects a HostComponent.
const isHidden =
nextProps.mode === 'hidden' &&
(!enableLegacyHidden || workInProgress.tag !== LegacyHiddenComponent);
const offscreenContainer = reconcileOffscreenHostContainer(
current,
workInProgress,
isHidden,
nextChildren,
renderLanes,
);
return offscreenContainer;
} else {
reconcileChildren(current, workInProgress, nextChildren, renderLanes);
return workInProgress.child;
}
}
function reconcileOffscreenHostContainer(
currentOffscreen: Fiber | null,
offscreen: Fiber,
isHidden: boolean,
children: any,
renderLanes: Lanes,
) {
const containerProps = getOffscreenContainerProps(
isHidden ? 'hidden' : 'visible',
children,
);
let hostContainer;
if (currentOffscreen === null) {
hostContainer = createOffscreenHostContainerFiber(
containerProps,
offscreen.mode,
renderLanes,
null,
);
} else {
const currentHostContainer = currentOffscreen.child;
if (currentHostContainer === null) {
hostContainer = createOffscreenHostContainerFiber(
containerProps,
offscreen.mode,
renderLanes,
null,
);
hostContainer.flags |= Placement;
} else {
hostContainer = createWorkInProgress(
currentHostContainer,
containerProps,
);
}
}
hostContainer.return = offscreen;
offscreen.child = hostContainer;
return hostContainer;
reconcileChildren(current, workInProgress, nextChildren, renderLanes);
return workInProgress.child;
}
// Note: These happen to have identical begin phases, for now. We shouldn't hold
@ -2575,24 +2511,6 @@ function updateSuspenseFallbackChildren(
currentPrimaryChildFragment.treeBaseDuration;
}
if (enablePersistentOffscreenHostContainer && supportsPersistence) {
// In persistent mode, the offscreen children are wrapped in a host node.
// We need to complete it now, because we're going to skip over its normal
// complete phase and go straight to rendering the fallback.
const currentOffscreenContainer = currentPrimaryChildFragment.child;
const offscreenContainer: Fiber = (primaryChildFragment.child: any);
const containerProps = getOffscreenContainerProps(
'hidden',
primaryChildren,
);
offscreenContainer.pendingProps = containerProps;
offscreenContainer.memoizedProps = containerProps;
completeSuspendedOffscreenHostContainer(
currentOffscreenContainer,
offscreenContainer,
);
}
// The fallback fiber was added as a deletion during the first pass.
// However, since we're going to remain on the fallback, we no longer want
// to delete it.
@ -2602,29 +2520,6 @@ function updateSuspenseFallbackChildren(
currentPrimaryChildFragment,
primaryChildProps,
);
if (enablePersistentOffscreenHostContainer && supportsPersistence) {
// In persistent mode, the offscreen children are wrapped in a host node.
// We need to complete it now, because we're going to skip over its normal
// complete phase and go straight to rendering the fallback.
const currentOffscreenContainer = currentPrimaryChildFragment.child;
if (currentOffscreenContainer !== null) {
const isHidden = true;
const offscreenContainer = reconcileOffscreenHostContainer(
currentPrimaryChildFragment,
primaryChildFragment,
isHidden,
primaryChildren,
renderLanes,
);
offscreenContainer.memoizedProps = offscreenContainer.pendingProps;
completeSuspendedOffscreenHostContainer(
currentOffscreenContainer,
offscreenContainer,
);
}
}
// Since we're reusing a current tree, we need to reuse the flags, too.
// (We don't do this in legacy mode, because in legacy mode we don't re-use
// the current tree; see previous branch.)

View File

@ -141,7 +141,6 @@ import {
enableProfilerTimer,
enableCache,
enableSuspenseLayoutEffectSemantics,
enablePersistentOffscreenHostContainer,
enableTransitionTracing,
} from 'shared/ReactFeatureFlags';
import {
@ -347,11 +346,7 @@ if (supportsMutation) {
if (child !== null) {
child.return = node;
}
if (enablePersistentOffscreenHostContainer) {
appendAllChildren(parent, node, false, false);
} else {
appendAllChildren(parent, node, true, true);
}
appendAllChildren(parent, node, true, true);
} else if (node.child !== null) {
node.child.return = node;
node = node.child;
@ -416,11 +411,7 @@ if (supportsMutation) {
if (child !== null) {
child.return = node;
}
if (enablePersistentOffscreenHostContainer) {
appendAllChildrenToContainer(containerChildSet, node, false, false);
} else {
appendAllChildrenToContainer(containerChildSet, node, true, true);
}
appendAllChildrenToContainer(containerChildSet, node, true, true);
} else if (node.child !== null) {
node.child.return = node;
node = node.child;
@ -768,65 +759,6 @@ function bubbleProperties(completedWork: Fiber) {
return didBailout;
}
export function completeSuspendedOffscreenHostContainer(
current: Fiber | null,
workInProgress: Fiber,
) {
// This is a fork of the complete phase for HostComponent. We use it when
// a suspense tree is in its fallback state, because in that case the primary
// tree that includes the offscreen boundary is skipped over without a
// regular complete phase.
//
// We can optimize this path further by inlining the update logic for
// offscreen instances specifically, i.e. skipping the `prepareUpdate` call.
const rootContainerInstance = getRootHostContainer();
const type = workInProgress.type;
const newProps = workInProgress.memoizedProps;
if (current !== null) {
updateHostComponent(
current,
workInProgress,
type,
newProps,
rootContainerInstance,
);
} else {
const currentHostContext = getHostContext();
const instance = createInstance(
type,
newProps,
rootContainerInstance,
currentHostContext,
workInProgress,
);
appendAllChildren(instance, workInProgress, false, false);
workInProgress.stateNode = instance;
// Certain renderers require commit-time effects for initial mount.
// (eg DOM renderer supports auto-focus for certain elements).
// Make sure such renderers get scheduled for later work.
if (
finalizeInitialChildren(
instance,
type,
newProps,
rootContainerInstance,
currentHostContext,
)
) {
markUpdate(workInProgress);
}
if (workInProgress.ref !== null) {
// If there is a ref on a host node we need to schedule a callback
markRef(workInProgress);
}
}
bubbleProperties(workInProgress);
}
function completeWork(
current: Fiber | null,
workInProgress: Fiber,

View File

@ -141,7 +141,6 @@ import {
enableProfilerTimer,
enableCache,
enableSuspenseLayoutEffectSemantics,
enablePersistentOffscreenHostContainer,
enableTransitionTracing,
} from 'shared/ReactFeatureFlags';
import {
@ -347,11 +346,7 @@ if (supportsMutation) {
if (child !== null) {
child.return = node;
}
if (enablePersistentOffscreenHostContainer) {
appendAllChildren(parent, node, false, false);
} else {
appendAllChildren(parent, node, true, true);
}
appendAllChildren(parent, node, true, true);
} else if (node.child !== null) {
node.child.return = node;
node = node.child;
@ -416,11 +411,7 @@ if (supportsMutation) {
if (child !== null) {
child.return = node;
}
if (enablePersistentOffscreenHostContainer) {
appendAllChildrenToContainer(containerChildSet, node, false, false);
} else {
appendAllChildrenToContainer(containerChildSet, node, true, true);
}
appendAllChildrenToContainer(containerChildSet, node, true, true);
} else if (node.child !== null) {
node.child.return = node;
node = node.child;
@ -768,65 +759,6 @@ function bubbleProperties(completedWork: Fiber) {
return didBailout;
}
export function completeSuspendedOffscreenHostContainer(
current: Fiber | null,
workInProgress: Fiber,
) {
// This is a fork of the complete phase for HostComponent. We use it when
// a suspense tree is in its fallback state, because in that case the primary
// tree that includes the offscreen boundary is skipped over without a
// regular complete phase.
//
// We can optimize this path further by inlining the update logic for
// offscreen instances specifically, i.e. skipping the `prepareUpdate` call.
const rootContainerInstance = getRootHostContainer();
const type = workInProgress.type;
const newProps = workInProgress.memoizedProps;
if (current !== null) {
updateHostComponent(
current,
workInProgress,
type,
newProps,
rootContainerInstance,
);
} else {
const currentHostContext = getHostContext();
const instance = createInstance(
type,
newProps,
rootContainerInstance,
currentHostContext,
workInProgress,
);
appendAllChildren(instance, workInProgress, false, false);
workInProgress.stateNode = instance;
// Certain renderers require commit-time effects for initial mount.
// (eg DOM renderer supports auto-focus for certain elements).
// Make sure such renderers get scheduled for later work.
if (
finalizeInitialChildren(
instance,
type,
newProps,
rootContainerInstance,
currentHostContext,
)
) {
markUpdate(workInProgress);
}
if (workInProgress.ref !== null) {
// If there is a ref on a host node we need to schedule a callback
markRef(workInProgress);
}
}
bubbleProperties(workInProgress);
}
function completeWork(
current: Fiber | null,
workInProgress: Fiber,

View File

@ -25,7 +25,5 @@ export const createContainerChildSet = shim;
export const appendChildToContainerChildSet = shim;
export const finalizeContainerChildren = shim;
export const replaceContainerChildren = shim;
export const getOffscreenContainerType = shim;
export const getOffscreenContainerProps = shim;
export const cloneHiddenInstance = shim;
export const cloneHiddenTextInstance = shim;

View File

@ -34,17 +34,12 @@ import {
ForceUpdateForLegacySuspense,
ForceClientRender,
} from './ReactFiberFlags';
import {
supportsPersistence,
getOffscreenContainerProps,
} from './ReactFiberHostConfig';
import {shouldCaptureSuspense} from './ReactFiberSuspenseComponent.new';
import {NoMode, ConcurrentMode, DebugTracingMode} from './ReactTypeOfMode';
import {
enableDebugTracing,
enableLazyContextPropagation,
enableUpdaterTracking,
enablePersistentOffscreenHostContainer,
} from 'shared/ReactFeatureFlags';
import {createCapturedValue} from './ReactCapturedValue';
import {
@ -336,26 +331,6 @@ function markSuspenseBoundaryShouldCapture(
// all lifecycle effect tags.
sourceFiber.flags &= ~(LifecycleEffectMask | Incomplete);
if (supportsPersistence && enablePersistentOffscreenHostContainer) {
// Another legacy Suspense quirk. In persistent mode, if this is the
// initial mount, override the props of the host container to hide
// its contents.
const currentSuspenseBoundary = suspenseBoundary.alternate;
if (currentSuspenseBoundary === null) {
const offscreenFiber: Fiber = (suspenseBoundary.child: any);
const offscreenContainer = offscreenFiber.child;
if (offscreenContainer !== null) {
const children = offscreenContainer.memoizedProps.children;
const containerProps = getOffscreenContainerProps(
'hidden',
children,
);
offscreenContainer.pendingProps = containerProps;
offscreenContainer.memoizedProps = containerProps;
}
}
}
if (sourceFiber.tag === ClassComponent) {
const currentSourceFiber = sourceFiber.alternate;
if (currentSourceFiber === null) {

View File

@ -34,17 +34,12 @@ import {
ForceUpdateForLegacySuspense,
ForceClientRender,
} from './ReactFiberFlags';
import {
supportsPersistence,
getOffscreenContainerProps,
} from './ReactFiberHostConfig';
import {shouldCaptureSuspense} from './ReactFiberSuspenseComponent.old';
import {NoMode, ConcurrentMode, DebugTracingMode} from './ReactTypeOfMode';
import {
enableDebugTracing,
enableLazyContextPropagation,
enableUpdaterTracking,
enablePersistentOffscreenHostContainer,
} from 'shared/ReactFeatureFlags';
import {createCapturedValue} from './ReactCapturedValue';
import {
@ -336,26 +331,6 @@ function markSuspenseBoundaryShouldCapture(
// all lifecycle effect tags.
sourceFiber.flags &= ~(LifecycleEffectMask | Incomplete);
if (supportsPersistence && enablePersistentOffscreenHostContainer) {
// Another legacy Suspense quirk. In persistent mode, if this is the
// initial mount, override the props of the host container to hide
// its contents.
const currentSuspenseBoundary = suspenseBoundary.alternate;
if (currentSuspenseBoundary === null) {
const offscreenFiber: Fiber = (suspenseBoundary.child: any);
const offscreenContainer = offscreenFiber.child;
if (offscreenContainer !== null) {
const children = offscreenContainer.memoizedProps.children;
const containerProps = getOffscreenContainerProps(
'hidden',
children,
);
offscreenContainer.pendingProps = containerProps;
offscreenContainer.memoizedProps = containerProps;
}
}
}
if (sourceFiber.tag === ClassComponent) {
const currentSourceFiber = sourceFiber.alternate;
if (currentSourceFiber === null) {

View File

@ -121,10 +121,6 @@ export const appendChildToContainerChildSet =
export const finalizeContainerChildren =
$$$hostConfig.finalizeContainerChildren;
export const replaceContainerChildren = $$$hostConfig.replaceContainerChildren;
export const getOffscreenContainerType =
$$$hostConfig.getOffscreenContainerType;
export const getOffscreenContainerProps =
$$$hostConfig.getOffscreenContainerProps;
export const cloneHiddenInstance = $$$hostConfig.cloneHiddenInstance;
export const cloneHiddenTextInstance = $$$hostConfig.cloneHiddenTextInstance;

View File

@ -16,7 +16,6 @@
export const warnAboutDeprecatedLifecycles = true;
export const enableComponentStackLocations = true;
export const disableSchedulerTimeoutBasedOnReactExpirationTime = false;
export const enablePersistentOffscreenHostContainer = false;
// -----------------------------------------------------------------------------
// Land or remove (moderate effort)

View File

@ -7,8 +7,10 @@
* @flow strict
*/
import typeof * as ExportsType from './ReactFeatureFlags.native-fb-dynamic';
import typeof * as DynamicFlagsType from 'ReactNativeInternalFeatureFlags';
// NOTE: There are no flags, currently. Uncomment the stuff below if we add one.
// import typeof * as ExportsType from './ReactFeatureFlags.native-fb-dynamic';
// import typeof * as DynamicFlagsType from 'ReactNativeInternalFeatureFlags';
// In xplat, these flags are controlled by GKs. Because most GKs have some
// population running in either mode, we should run our tests that way, too,
@ -20,10 +22,8 @@ import typeof * as DynamicFlagsType from 'ReactNativeInternalFeatureFlags';
// flag here but it won't be set to `true` in any of our test runs. Need to
// update the test configuration.
export const enablePersistentOffscreenHostContainer = __VARIANT__;
// Flow magic to verify the exports of this file match the original version.
// eslint-disable-next-line no-unused-vars
type Check<_X, Y: _X, X: Y = _X> = null;
// eslint-disable-next-line no-unused-expressions
(null: Check<ExportsType, DynamicFlagsType>);
// // Flow magic to verify the exports of this file match the original version.
// // eslint-disable-next-line no-unused-vars
// type Check<_X, Y: _X, X: Y = _X> = null;
// // eslint-disable-next-line no-unused-expressions
// (null: Check<ExportsType, DynamicFlagsType>);

View File

@ -10,13 +10,14 @@
import typeof * as FeatureFlagsType from 'shared/ReactFeatureFlags';
import typeof * as ExportsType from './ReactFeatureFlags.native-fb';
// NOTE: There are no flags, currently. Uncomment the stuff below if we add one.
// Re-export dynamic flags from the internal module. Intentionally using *
// because this import is compiled to a `require` call.
import * as dynamicFlags from 'ReactNativeInternalFeatureFlags';
// import * as dynamicFlags from 'ReactNativeInternalFeatureFlags';
// We destructure each value before re-exporting to avoid a dynamic look-up on
// the exports object every time a flag is read.
export const {enablePersistentOffscreenHostContainer} = dynamicFlags;
// export const {} = dynamicFlags;
// The rest of the flags are static for better dead code elimination.
export const enableDebugTracing = false;

View File

@ -62,7 +62,6 @@ export const enableLazyContextPropagation = false;
export const enableLegacyHidden = false;
export const enableSyncDefaultUpdates = true;
export const allowConcurrentByDefault = false;
export const enablePersistentOffscreenHostContainer = false;
export const enableCustomElementPropertySupport = false;
export const consoleManagedByDevToolsDuringStrictMode = false;

View File

@ -62,7 +62,6 @@ export const enableLazyContextPropagation = false;
export const enableLegacyHidden = false;
export const enableSyncDefaultUpdates = true;
export const allowConcurrentByDefault = false;
export const enablePersistentOffscreenHostContainer = false;
export const enableCustomElementPropertySupport = false;
export const consoleManagedByDevToolsDuringStrictMode = false;

View File

@ -61,7 +61,6 @@ export const enableLazyContextPropagation = false;
export const enableLegacyHidden = false;
export const enableSyncDefaultUpdates = true;
export const allowConcurrentByDefault = true;
export const enablePersistentOffscreenHostContainer = false;
export const consoleManagedByDevToolsDuringStrictMode = false;
export const enableServerContext = false;

View File

@ -62,7 +62,6 @@ export const enableLazyContextPropagation = false;
export const enableLegacyHidden = false;
export const enableSyncDefaultUpdates = true;
export const allowConcurrentByDefault = true;
export const enablePersistentOffscreenHostContainer = false;
export const enableCustomElementPropertySupport = false;
export const consoleManagedByDevToolsDuringStrictMode = false;

View File

@ -62,7 +62,6 @@ export const enableLazyContextPropagation = false;
export const enableLegacyHidden = false;
export const enableSyncDefaultUpdates = true;
export const allowConcurrentByDefault = false;
export const enablePersistentOffscreenHostContainer = false;
export const enableCustomElementPropertySupport = false;
export const consoleManagedByDevToolsDuringStrictMode = false;

View File

@ -62,7 +62,6 @@ export const enableLazyContextPropagation = false;
export const enableLegacyHidden = false;
export const enableSyncDefaultUpdates = true;
export const allowConcurrentByDefault = true;
export const enablePersistentOffscreenHostContainer = false;
export const enableCustomElementPropertySupport = false;
export const consoleManagedByDevToolsDuringStrictMode = false;

View File

@ -60,6 +60,5 @@ export const disableNativeComponentFrames = false;
export const createRootStrictEffectsByDefault = false;
export const enableStrictEffects = false;
export const allowConcurrentByDefault = true;
export const enablePersistentOffscreenHostContainer = false;
// You probably *don't* want to add more hardcoded ones.
// Instead, try to add them above with the __VARIANT__ value.

View File

@ -99,8 +99,6 @@ export const allowConcurrentByDefault = true;
export const deletedTreeCleanUpLevel = 3;
export const enablePersistentOffscreenHostContainer = false;
export const consoleManagedByDevToolsDuringStrictMode = true;
export const enableServerContext = true;

View File

@ -8,5 +8,4 @@
*/
declare module 'ReactNativeInternalFeatureFlags' {
declare export var enablePersistentOffscreenHostContainer: boolean;
}