Remove enablePersistentOffscreenHostContainer flag (#24460)
This was a Fabric-related experiment that we ended up not shipping.
This commit is contained in:
parent
340060cccd
commit
ce13860281
|
@ -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,
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
// 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.)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
// 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.)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
} 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);
|
||||
}
|
||||
} 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,
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
} 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);
|
||||
}
|
||||
} 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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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>);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -99,8 +99,6 @@ export const allowConcurrentByDefault = true;
|
|||
|
||||
export const deletedTreeCleanUpLevel = 3;
|
||||
|
||||
export const enablePersistentOffscreenHostContainer = false;
|
||||
|
||||
export const consoleManagedByDevToolsDuringStrictMode = true;
|
||||
export const enableServerContext = true;
|
||||
|
||||
|
|
|
@ -8,5 +8,4 @@
|
|||
*/
|
||||
|
||||
declare module 'ReactNativeInternalFeatureFlags' {
|
||||
declare export var enablePersistentOffscreenHostContainer: boolean;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue