mirror of
https://github.com/hanzoai/react.git
synced 2026-09-24 17:02:27 +00:00
Re-add old Fabric Offscreen impl behind flag (#22018)
* Re-add old Fabric Offscreen impl behind flag There's a chance that #21960 will affect layout in a way that we don't expect, so I'm adding back the old implementation so we can toggle the feature with a flag. The flag should read from the ReactNativeFeatureFlags shim so that we can change it at runtime. I'll do that separately. * Import dynamic RN flags from external module Internal feature flags that we wish to control with a GK can now be imported from an external module, which I've called "ReactNativeInternalFeatureFlags". We'll need to add this module to the downstream repo. We can't yet use this in our tests, because we don't have a test configuration that runs against the React Native feature flags fork. We should set up that up the same way we did for www.
This commit is contained in:
@@ -460,6 +460,32 @@ export function getOffscreenContainerProps(
|
||||
}
|
||||
}
|
||||
|
||||
export function cloneHiddenInstance(
|
||||
instance: Instance,
|
||||
type: string,
|
||||
props: Props,
|
||||
internalInstanceHandle: Object,
|
||||
): Instance {
|
||||
const viewConfig = instance.canonical.viewConfig;
|
||||
const node = instance.node;
|
||||
const updatePayload = create(
|
||||
{style: {display: 'none'}},
|
||||
viewConfig.validAttributes,
|
||||
);
|
||||
return {
|
||||
node: cloneNodeWithNewProps(node, updatePayload),
|
||||
canonical: instance.canonical,
|
||||
};
|
||||
}
|
||||
|
||||
export function cloneHiddenTextInstance(
|
||||
instance: Instance,
|
||||
text: string,
|
||||
internalInstanceHandle: Object,
|
||||
): TextInstance {
|
||||
throw new Error('Not yet implemented.');
|
||||
}
|
||||
|
||||
export function createContainerChildSet(container: Container): ChildSet {
|
||||
return createChildNodeSet(container);
|
||||
}
|
||||
|
||||
@@ -582,6 +582,54 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
|
||||
children,
|
||||
};
|
||||
},
|
||||
|
||||
cloneHiddenInstance(
|
||||
instance: Instance,
|
||||
type: string,
|
||||
props: Props,
|
||||
internalInstanceHandle: Object,
|
||||
): Instance {
|
||||
const clone = cloneInstance(
|
||||
instance,
|
||||
null,
|
||||
type,
|
||||
props,
|
||||
props,
|
||||
internalInstanceHandle,
|
||||
true,
|
||||
null,
|
||||
);
|
||||
clone.hidden = true;
|
||||
return clone;
|
||||
},
|
||||
|
||||
cloneHiddenTextInstance(
|
||||
instance: TextInstance,
|
||||
text: string,
|
||||
internalInstanceHandle: Object,
|
||||
): TextInstance {
|
||||
const clone = {
|
||||
text: instance.text,
|
||||
id: instance.id,
|
||||
parent: instance.parent,
|
||||
hidden: true,
|
||||
context: instance.context,
|
||||
};
|
||||
// Hide from unit tests
|
||||
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,
|
||||
});
|
||||
return clone;
|
||||
},
|
||||
};
|
||||
|
||||
const NoopRenderer = reconciler(hostConfig);
|
||||
|
||||
@@ -89,6 +89,7 @@ import {
|
||||
enableLazyContextPropagation,
|
||||
enableSuspenseLayoutEffectSemantics,
|
||||
enableSchedulingProfiler,
|
||||
enablePersistentOffscreenHostContainer,
|
||||
} from 'shared/ReactFeatureFlags';
|
||||
import invariant from 'shared/invariant';
|
||||
import isArray from 'shared/isArray';
|
||||
@@ -146,7 +147,6 @@ import {
|
||||
registerSuspenseInstanceRetry,
|
||||
supportsHydration,
|
||||
isPrimaryRenderer,
|
||||
supportsMutation,
|
||||
supportsPersistence,
|
||||
getOffscreenContainerProps,
|
||||
} from './ReactFiberHostConfig';
|
||||
@@ -744,7 +744,7 @@ function updateOffscreenComponent(
|
||||
workInProgress.updateQueue = spawnedCachePool;
|
||||
}
|
||||
|
||||
if (supportsPersistence) {
|
||||
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
|
||||
@@ -760,12 +760,10 @@ function updateOffscreenComponent(
|
||||
renderLanes,
|
||||
);
|
||||
return offscreenContainer;
|
||||
}
|
||||
if (supportsMutation) {
|
||||
} else {
|
||||
reconcileChildren(current, workInProgress, nextChildren, renderLanes);
|
||||
return workInProgress.child;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function reconcileOffscreenHostContainer(
|
||||
@@ -2383,7 +2381,7 @@ function updateSuspenseFallbackChildren(
|
||||
currentPrimaryChildFragment.treeBaseDuration;
|
||||
}
|
||||
|
||||
if (supportsPersistence) {
|
||||
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.
|
||||
@@ -2411,7 +2409,7 @@ function updateSuspenseFallbackChildren(
|
||||
primaryChildProps,
|
||||
);
|
||||
|
||||
if (supportsPersistence) {
|
||||
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.
|
||||
|
||||
@@ -89,6 +89,7 @@ import {
|
||||
enableLazyContextPropagation,
|
||||
enableSuspenseLayoutEffectSemantics,
|
||||
enableSchedulingProfiler,
|
||||
enablePersistentOffscreenHostContainer,
|
||||
} from 'shared/ReactFeatureFlags';
|
||||
import invariant from 'shared/invariant';
|
||||
import isArray from 'shared/isArray';
|
||||
@@ -146,7 +147,6 @@ import {
|
||||
registerSuspenseInstanceRetry,
|
||||
supportsHydration,
|
||||
isPrimaryRenderer,
|
||||
supportsMutation,
|
||||
supportsPersistence,
|
||||
getOffscreenContainerProps,
|
||||
} from './ReactFiberHostConfig';
|
||||
@@ -744,7 +744,7 @@ function updateOffscreenComponent(
|
||||
workInProgress.updateQueue = spawnedCachePool;
|
||||
}
|
||||
|
||||
if (supportsPersistence) {
|
||||
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
|
||||
@@ -760,12 +760,10 @@ function updateOffscreenComponent(
|
||||
renderLanes,
|
||||
);
|
||||
return offscreenContainer;
|
||||
}
|
||||
if (supportsMutation) {
|
||||
} else {
|
||||
reconcileChildren(current, workInProgress, nextChildren, renderLanes);
|
||||
return workInProgress.child;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function reconcileOffscreenHostContainer(
|
||||
@@ -2383,7 +2381,7 @@ function updateSuspenseFallbackChildren(
|
||||
currentPrimaryChildFragment.treeBaseDuration;
|
||||
}
|
||||
|
||||
if (supportsPersistence) {
|
||||
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.
|
||||
@@ -2411,7 +2409,7 @@ function updateSuspenseFallbackChildren(
|
||||
primaryChildProps,
|
||||
);
|
||||
|
||||
if (supportsPersistence) {
|
||||
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.
|
||||
|
||||
@@ -84,6 +84,8 @@ import {
|
||||
supportsMutation,
|
||||
supportsPersistence,
|
||||
cloneInstance,
|
||||
cloneHiddenInstance,
|
||||
cloneHiddenTextInstance,
|
||||
createContainerChildSet,
|
||||
appendChildToContainerChildSet,
|
||||
finalizeContainerChildren,
|
||||
@@ -128,6 +130,7 @@ import {
|
||||
enableProfilerTimer,
|
||||
enableCache,
|
||||
enableSuspenseLayoutEffectSemantics,
|
||||
enablePersistentOffscreenHostContainer,
|
||||
} from 'shared/ReactFeatureFlags';
|
||||
import {
|
||||
renderDidSuspend,
|
||||
@@ -198,7 +201,12 @@ let updateHostText;
|
||||
if (supportsMutation) {
|
||||
// Mutation mode
|
||||
|
||||
appendAllChildren = function(parent: Instance, workInProgress: Fiber) {
|
||||
appendAllChildren = function(
|
||||
parent: Instance,
|
||||
workInProgress: Fiber,
|
||||
needsVisibilityToggle: boolean,
|
||||
isHidden: boolean,
|
||||
) {
|
||||
// We only have the top Fiber that was created but we need recurse down its
|
||||
// children to find all the terminal nodes.
|
||||
let node = workInProgress.child;
|
||||
@@ -286,22 +294,53 @@ if (supportsMutation) {
|
||||
} else if (supportsPersistence) {
|
||||
// Persistent host tree mode
|
||||
|
||||
appendAllChildren = function(parent: Instance, workInProgress: Fiber) {
|
||||
appendAllChildren = function(
|
||||
parent: Instance,
|
||||
workInProgress: Fiber,
|
||||
needsVisibilityToggle: boolean,
|
||||
isHidden: boolean,
|
||||
) {
|
||||
// We only have the top Fiber that was created but we need recurse down its
|
||||
// children to find all the terminal nodes.
|
||||
let node = workInProgress.child;
|
||||
while (node !== null) {
|
||||
// eslint-disable-next-line no-labels
|
||||
branches: if (node.tag === HostComponent) {
|
||||
const instance = node.stateNode;
|
||||
let instance = node.stateNode;
|
||||
if (needsVisibilityToggle && isHidden) {
|
||||
// This child is inside a timed out tree. Hide it.
|
||||
const props = node.memoizedProps;
|
||||
const type = node.type;
|
||||
instance = cloneHiddenInstance(instance, type, props, node);
|
||||
}
|
||||
appendInitialChild(parent, instance);
|
||||
} else if (node.tag === HostText) {
|
||||
const instance = node.stateNode;
|
||||
let instance = node.stateNode;
|
||||
if (needsVisibilityToggle && isHidden) {
|
||||
// This child is inside a timed out tree. Hide it.
|
||||
const text = node.memoizedProps;
|
||||
instance = cloneHiddenTextInstance(instance, text, node);
|
||||
}
|
||||
appendInitialChild(parent, instance);
|
||||
} else if (node.tag === HostPortal) {
|
||||
// If we have a portal child, then we don't want to traverse
|
||||
// down its children. Instead, we'll get insertions from each child in
|
||||
// the portal directly.
|
||||
} else if (
|
||||
node.tag === OffscreenComponent &&
|
||||
node.memoizedState !== null
|
||||
) {
|
||||
// The children in this boundary are hidden. Toggle their visibility
|
||||
// before appending.
|
||||
const child = node.child;
|
||||
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;
|
||||
@@ -327,6 +366,8 @@ if (supportsMutation) {
|
||||
const appendAllChildrenToContainer = function(
|
||||
containerChildSet: ChildSet,
|
||||
workInProgress: Fiber,
|
||||
needsVisibilityToggle: boolean,
|
||||
isHidden: boolean,
|
||||
) {
|
||||
// We only have the top Fiber that was created but we need recurse down its
|
||||
// children to find all the terminal nodes.
|
||||
@@ -334,15 +375,41 @@ if (supportsMutation) {
|
||||
while (node !== null) {
|
||||
// eslint-disable-next-line no-labels
|
||||
branches: if (node.tag === HostComponent) {
|
||||
const instance = node.stateNode;
|
||||
let instance = node.stateNode;
|
||||
if (needsVisibilityToggle && isHidden) {
|
||||
// This child is inside a timed out tree. Hide it.
|
||||
const props = node.memoizedProps;
|
||||
const type = node.type;
|
||||
instance = cloneHiddenInstance(instance, type, props, node);
|
||||
}
|
||||
appendChildToContainerChildSet(containerChildSet, instance);
|
||||
} else if (node.tag === HostText) {
|
||||
const instance = node.stateNode;
|
||||
let instance = node.stateNode;
|
||||
if (needsVisibilityToggle && isHidden) {
|
||||
// This child is inside a timed out tree. Hide it.
|
||||
const text = node.memoizedProps;
|
||||
instance = cloneHiddenTextInstance(instance, text, node);
|
||||
}
|
||||
appendChildToContainerChildSet(containerChildSet, instance);
|
||||
} else if (node.tag === HostPortal) {
|
||||
// If we have a portal child, then we don't want to traverse
|
||||
// down its children. Instead, we'll get insertions from each child in
|
||||
// the portal directly.
|
||||
} else if (
|
||||
node.tag === OffscreenComponent &&
|
||||
node.memoizedState !== null
|
||||
) {
|
||||
// The children in this boundary are hidden. Toggle their visibility
|
||||
// before appending.
|
||||
const child = node.child;
|
||||
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;
|
||||
@@ -376,7 +443,7 @@ if (supportsMutation) {
|
||||
const container = portalOrRoot.containerInfo;
|
||||
const newChildSet = createContainerChildSet(container);
|
||||
// If children might have changed, we have to add them all to the set.
|
||||
appendAllChildrenToContainer(newChildSet, workInProgress);
|
||||
appendAllChildrenToContainer(newChildSet, workInProgress, false, false);
|
||||
portalOrRoot.pendingChildren = newChildSet;
|
||||
// Schedule an update on the container to swap out the container.
|
||||
markUpdate(workInProgress);
|
||||
@@ -449,7 +516,7 @@ if (supportsMutation) {
|
||||
markUpdate(workInProgress);
|
||||
} else {
|
||||
// If children might have changed, we have to add them all to the set.
|
||||
appendAllChildren(newInstance, workInProgress);
|
||||
appendAllChildren(newInstance, workInProgress, false, false);
|
||||
}
|
||||
};
|
||||
updateHostText = function(
|
||||
@@ -722,7 +789,7 @@ export function completeSuspendedOffscreenHostContainer(
|
||||
workInProgress,
|
||||
);
|
||||
|
||||
appendAllChildren(instance, workInProgress);
|
||||
appendAllChildren(instance, workInProgress, false, false);
|
||||
|
||||
workInProgress.stateNode = instance;
|
||||
|
||||
@@ -869,7 +936,7 @@ function completeWork(
|
||||
workInProgress,
|
||||
);
|
||||
|
||||
appendAllChildren(instance, workInProgress);
|
||||
appendAllChildren(instance, workInProgress, false, false);
|
||||
|
||||
workInProgress.stateNode = instance;
|
||||
|
||||
|
||||
@@ -84,6 +84,8 @@ import {
|
||||
supportsMutation,
|
||||
supportsPersistence,
|
||||
cloneInstance,
|
||||
cloneHiddenInstance,
|
||||
cloneHiddenTextInstance,
|
||||
createContainerChildSet,
|
||||
appendChildToContainerChildSet,
|
||||
finalizeContainerChildren,
|
||||
@@ -128,6 +130,7 @@ import {
|
||||
enableProfilerTimer,
|
||||
enableCache,
|
||||
enableSuspenseLayoutEffectSemantics,
|
||||
enablePersistentOffscreenHostContainer,
|
||||
} from 'shared/ReactFeatureFlags';
|
||||
import {
|
||||
renderDidSuspend,
|
||||
@@ -198,7 +201,12 @@ let updateHostText;
|
||||
if (supportsMutation) {
|
||||
// Mutation mode
|
||||
|
||||
appendAllChildren = function(parent: Instance, workInProgress: Fiber) {
|
||||
appendAllChildren = function(
|
||||
parent: Instance,
|
||||
workInProgress: Fiber,
|
||||
needsVisibilityToggle: boolean,
|
||||
isHidden: boolean,
|
||||
) {
|
||||
// We only have the top Fiber that was created but we need recurse down its
|
||||
// children to find all the terminal nodes.
|
||||
let node = workInProgress.child;
|
||||
@@ -286,22 +294,53 @@ if (supportsMutation) {
|
||||
} else if (supportsPersistence) {
|
||||
// Persistent host tree mode
|
||||
|
||||
appendAllChildren = function(parent: Instance, workInProgress: Fiber) {
|
||||
appendAllChildren = function(
|
||||
parent: Instance,
|
||||
workInProgress: Fiber,
|
||||
needsVisibilityToggle: boolean,
|
||||
isHidden: boolean,
|
||||
) {
|
||||
// We only have the top Fiber that was created but we need recurse down its
|
||||
// children to find all the terminal nodes.
|
||||
let node = workInProgress.child;
|
||||
while (node !== null) {
|
||||
// eslint-disable-next-line no-labels
|
||||
branches: if (node.tag === HostComponent) {
|
||||
const instance = node.stateNode;
|
||||
let instance = node.stateNode;
|
||||
if (needsVisibilityToggle && isHidden) {
|
||||
// This child is inside a timed out tree. Hide it.
|
||||
const props = node.memoizedProps;
|
||||
const type = node.type;
|
||||
instance = cloneHiddenInstance(instance, type, props, node);
|
||||
}
|
||||
appendInitialChild(parent, instance);
|
||||
} else if (node.tag === HostText) {
|
||||
const instance = node.stateNode;
|
||||
let instance = node.stateNode;
|
||||
if (needsVisibilityToggle && isHidden) {
|
||||
// This child is inside a timed out tree. Hide it.
|
||||
const text = node.memoizedProps;
|
||||
instance = cloneHiddenTextInstance(instance, text, node);
|
||||
}
|
||||
appendInitialChild(parent, instance);
|
||||
} else if (node.tag === HostPortal) {
|
||||
// If we have a portal child, then we don't want to traverse
|
||||
// down its children. Instead, we'll get insertions from each child in
|
||||
// the portal directly.
|
||||
} else if (
|
||||
node.tag === OffscreenComponent &&
|
||||
node.memoizedState !== null
|
||||
) {
|
||||
// The children in this boundary are hidden. Toggle their visibility
|
||||
// before appending.
|
||||
const child = node.child;
|
||||
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;
|
||||
@@ -327,6 +366,8 @@ if (supportsMutation) {
|
||||
const appendAllChildrenToContainer = function(
|
||||
containerChildSet: ChildSet,
|
||||
workInProgress: Fiber,
|
||||
needsVisibilityToggle: boolean,
|
||||
isHidden: boolean,
|
||||
) {
|
||||
// We only have the top Fiber that was created but we need recurse down its
|
||||
// children to find all the terminal nodes.
|
||||
@@ -334,15 +375,41 @@ if (supportsMutation) {
|
||||
while (node !== null) {
|
||||
// eslint-disable-next-line no-labels
|
||||
branches: if (node.tag === HostComponent) {
|
||||
const instance = node.stateNode;
|
||||
let instance = node.stateNode;
|
||||
if (needsVisibilityToggle && isHidden) {
|
||||
// This child is inside a timed out tree. Hide it.
|
||||
const props = node.memoizedProps;
|
||||
const type = node.type;
|
||||
instance = cloneHiddenInstance(instance, type, props, node);
|
||||
}
|
||||
appendChildToContainerChildSet(containerChildSet, instance);
|
||||
} else if (node.tag === HostText) {
|
||||
const instance = node.stateNode;
|
||||
let instance = node.stateNode;
|
||||
if (needsVisibilityToggle && isHidden) {
|
||||
// This child is inside a timed out tree. Hide it.
|
||||
const text = node.memoizedProps;
|
||||
instance = cloneHiddenTextInstance(instance, text, node);
|
||||
}
|
||||
appendChildToContainerChildSet(containerChildSet, instance);
|
||||
} else if (node.tag === HostPortal) {
|
||||
// If we have a portal child, then we don't want to traverse
|
||||
// down its children. Instead, we'll get insertions from each child in
|
||||
// the portal directly.
|
||||
} else if (
|
||||
node.tag === OffscreenComponent &&
|
||||
node.memoizedState !== null
|
||||
) {
|
||||
// The children in this boundary are hidden. Toggle their visibility
|
||||
// before appending.
|
||||
const child = node.child;
|
||||
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;
|
||||
@@ -376,7 +443,7 @@ if (supportsMutation) {
|
||||
const container = portalOrRoot.containerInfo;
|
||||
const newChildSet = createContainerChildSet(container);
|
||||
// If children might have changed, we have to add them all to the set.
|
||||
appendAllChildrenToContainer(newChildSet, workInProgress);
|
||||
appendAllChildrenToContainer(newChildSet, workInProgress, false, false);
|
||||
portalOrRoot.pendingChildren = newChildSet;
|
||||
// Schedule an update on the container to swap out the container.
|
||||
markUpdate(workInProgress);
|
||||
@@ -449,7 +516,7 @@ if (supportsMutation) {
|
||||
markUpdate(workInProgress);
|
||||
} else {
|
||||
// If children might have changed, we have to add them all to the set.
|
||||
appendAllChildren(newInstance, workInProgress);
|
||||
appendAllChildren(newInstance, workInProgress, false, false);
|
||||
}
|
||||
};
|
||||
updateHostText = function(
|
||||
@@ -722,7 +789,7 @@ export function completeSuspendedOffscreenHostContainer(
|
||||
workInProgress,
|
||||
);
|
||||
|
||||
appendAllChildren(instance, workInProgress);
|
||||
appendAllChildren(instance, workInProgress, false, false);
|
||||
|
||||
workInProgress.stateNode = instance;
|
||||
|
||||
@@ -869,7 +936,7 @@ function completeWork(
|
||||
workInProgress,
|
||||
);
|
||||
|
||||
appendAllChildren(instance, workInProgress);
|
||||
appendAllChildren(instance, workInProgress, false, false);
|
||||
|
||||
workInProgress.stateNode = instance;
|
||||
|
||||
|
||||
@@ -30,3 +30,5 @@ export const finalizeContainerChildren = shim;
|
||||
export const replaceContainerChildren = shim;
|
||||
export const getOffscreenContainerType = shim;
|
||||
export const getOffscreenContainerProps = shim;
|
||||
export const cloneHiddenInstance = shim;
|
||||
export const cloneHiddenTextInstance = shim;
|
||||
|
||||
@@ -44,6 +44,7 @@ import {
|
||||
enableSchedulingProfiler,
|
||||
enableLazyContextPropagation,
|
||||
enableUpdaterTracking,
|
||||
enablePersistentOffscreenHostContainer,
|
||||
} from 'shared/ReactFeatureFlags';
|
||||
import {createCapturedValue} from './ReactCapturedValue';
|
||||
import {
|
||||
@@ -321,7 +322,7 @@ function throwException(
|
||||
// all lifecycle effect tags.
|
||||
sourceFiber.flags &= ~(LifecycleEffectMask | Incomplete);
|
||||
|
||||
if (supportsPersistence) {
|
||||
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.
|
||||
|
||||
@@ -44,6 +44,7 @@ import {
|
||||
enableSchedulingProfiler,
|
||||
enableLazyContextPropagation,
|
||||
enableUpdaterTracking,
|
||||
enablePersistentOffscreenHostContainer,
|
||||
} from 'shared/ReactFeatureFlags';
|
||||
import {createCapturedValue} from './ReactCapturedValue';
|
||||
import {
|
||||
@@ -321,7 +322,7 @@ function throwException(
|
||||
// all lifecycle effect tags.
|
||||
sourceFiber.flags &= ~(LifecycleEffectMask | Incomplete);
|
||||
|
||||
if (supportsPersistence) {
|
||||
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.
|
||||
|
||||
@@ -131,6 +131,8 @@ export const getOffscreenContainerType =
|
||||
$$$hostConfig.getOffscreenContainerType;
|
||||
export const getOffscreenContainerProps =
|
||||
$$$hostConfig.getOffscreenContainerProps;
|
||||
export const cloneHiddenInstance = $$$hostConfig.cloneHiddenInstance;
|
||||
export const cloneHiddenTextInstance = $$$hostConfig.cloneHiddenTextInstance;
|
||||
|
||||
// -------------------
|
||||
// Hydration
|
||||
|
||||
@@ -173,3 +173,5 @@ export const enableLazyContextPropagation = false;
|
||||
export const enableSyncDefaultUpdates = true;
|
||||
|
||||
export const allowConcurrentByDefault = false;
|
||||
|
||||
export const enablePersistentOffscreenHostContainer = false;
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow strict
|
||||
*/
|
||||
|
||||
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,
|
||||
//
|
||||
// Use __VARIANT__ to simulate a GK. The tests will be run twice: once
|
||||
// with the __VARIANT__ set to `true`, and once set to `false`.
|
||||
//
|
||||
// TODO: __VARIANT__ isn't supported for React Native flags yet. You can set the
|
||||
// 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>);
|
||||
@@ -10,6 +10,14 @@
|
||||
import typeof * as FeatureFlagsType from 'shared/ReactFeatureFlags';
|
||||
import typeof * as ExportsType from './ReactFeatureFlags.native-fb';
|
||||
|
||||
// Re-export dynamic flags from the internal module. Intentionally using *
|
||||
// because this import is compiled to a `require` call.
|
||||
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;
|
||||
|
||||
// The rest of the flags are static for better dead code elimination.
|
||||
export const enableDebugTracing = false;
|
||||
export const enableSchedulingProfiler = false;
|
||||
|
||||
@@ -59,6 +59,7 @@ export const disableSchedulerTimeoutInWorkLoop = false;
|
||||
export const enableLazyContextPropagation = false;
|
||||
export const enableSyncDefaultUpdates = true;
|
||||
export const allowConcurrentByDefault = false;
|
||||
export const enablePersistentOffscreenHostContainer = false;
|
||||
|
||||
// Flow magic to verify the exports of this file match the original version.
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
|
||||
@@ -59,6 +59,7 @@ export const disableSchedulerTimeoutInWorkLoop = false;
|
||||
export const enableLazyContextPropagation = false;
|
||||
export const enableSyncDefaultUpdates = true;
|
||||
export const allowConcurrentByDefault = false;
|
||||
export const enablePersistentOffscreenHostContainer = false;
|
||||
|
||||
// Flow magic to verify the exports of this file match the original version.
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
|
||||
@@ -59,6 +59,7 @@ export const disableSchedulerTimeoutInWorkLoop = false;
|
||||
export const enableLazyContextPropagation = false;
|
||||
export const enableSyncDefaultUpdates = true;
|
||||
export const allowConcurrentByDefault = true;
|
||||
export const enablePersistentOffscreenHostContainer = false;
|
||||
|
||||
// Flow magic to verify the exports of this file match the original version.
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
|
||||
@@ -59,6 +59,7 @@ export const disableSchedulerTimeoutInWorkLoop = false;
|
||||
export const enableLazyContextPropagation = false;
|
||||
export const enableSyncDefaultUpdates = true;
|
||||
export const allowConcurrentByDefault = true;
|
||||
export const enablePersistentOffscreenHostContainer = false;
|
||||
|
||||
// Flow magic to verify the exports of this file match the original version.
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
|
||||
@@ -59,6 +59,7 @@ export const disableSchedulerTimeoutInWorkLoop = false;
|
||||
export const enableLazyContextPropagation = false;
|
||||
export const enableSyncDefaultUpdates = true;
|
||||
export const allowConcurrentByDefault = false;
|
||||
export const enablePersistentOffscreenHostContainer = false;
|
||||
|
||||
// Flow magic to verify the exports of this file match the original version.
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
|
||||
@@ -59,6 +59,7 @@ export const disableSchedulerTimeoutInWorkLoop = false;
|
||||
export const enableLazyContextPropagation = false;
|
||||
export const enableSyncDefaultUpdates = true;
|
||||
export const allowConcurrentByDefault = true;
|
||||
export const enablePersistentOffscreenHostContainer = false;
|
||||
|
||||
// Flow magic to verify the exports of this file match the original version.
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
|
||||
@@ -59,3 +59,4 @@ export const disableSchedulerTimeoutInWorkLoop = __VARIANT__;
|
||||
export const enableLazyContextPropagation = __VARIANT__;
|
||||
export const enableSyncDefaultUpdates = __VARIANT__;
|
||||
export const allowConcurrentByDefault = true;
|
||||
export const enablePersistentOffscreenHostContainer = false;
|
||||
|
||||
@@ -94,6 +94,8 @@ export const allowConcurrentByDefault = true;
|
||||
|
||||
export const deletedTreeCleanUpLevel = 3;
|
||||
|
||||
export const enablePersistentOffscreenHostContainer = false;
|
||||
|
||||
// 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;
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
./scripts/flow/react-devtools.js
|
||||
./scripts/flow/react-native-host-hooks.js
|
||||
./scripts/flow/react-relay-hooks.js
|
||||
./scripts/flow/xplat.js
|
||||
|
||||
[lints]
|
||||
untyped-type-import=error
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow
|
||||
*/
|
||||
|
||||
declare module 'ReactNativeInternalFeatureFlags' {
|
||||
declare export var enablePersistentOffscreenHostContainer: boolean;
|
||||
}
|
||||
@@ -79,7 +79,7 @@ const bundles = [
|
||||
moduleType: ISOMORPHIC,
|
||||
entry: 'react',
|
||||
global: 'React',
|
||||
externals: [],
|
||||
externals: ['ReactNativeInternalFeatureFlags'],
|
||||
},
|
||||
|
||||
/******* Isomorphic Shared Subset *******/
|
||||
@@ -105,7 +105,7 @@ const bundles = [
|
||||
moduleType: ISOMORPHIC,
|
||||
entry: 'react/jsx-runtime',
|
||||
global: 'JSXRuntime',
|
||||
externals: ['react'],
|
||||
externals: ['react', 'ReactNativeInternalFeatureFlags'],
|
||||
},
|
||||
|
||||
/******* React JSX DEV Runtime *******/
|
||||
@@ -124,7 +124,7 @@ const bundles = [
|
||||
moduleType: ISOMORPHIC,
|
||||
entry: 'react/jsx-dev-runtime',
|
||||
global: 'JSXDEVRuntime',
|
||||
externals: ['react'],
|
||||
externals: ['react', 'ReactNativeInternalFeatureFlags'],
|
||||
},
|
||||
|
||||
/******* React Fetch Browser (experimental, new) *******/
|
||||
@@ -372,6 +372,7 @@ const bundles = [
|
||||
'react',
|
||||
'ReactFlightNativeRelayServerIntegration',
|
||||
'JSResourceReferenceImpl',
|
||||
'ReactNativeInternalFeatureFlags',
|
||||
],
|
||||
},
|
||||
|
||||
@@ -385,6 +386,7 @@ const bundles = [
|
||||
'react',
|
||||
'ReactFlightNativeRelayClientIntegration',
|
||||
'JSResourceReferenceImpl',
|
||||
'ReactNativeInternalFeatureFlags',
|
||||
],
|
||||
},
|
||||
|
||||
@@ -432,7 +434,7 @@ const bundles = [
|
||||
moduleType: RENDERER,
|
||||
entry: 'react-native-renderer',
|
||||
global: 'ReactNativeRenderer',
|
||||
externals: ['react-native'],
|
||||
externals: ['react-native', 'ReactNativeInternalFeatureFlags'],
|
||||
babel: opts =>
|
||||
Object.assign({}, opts, {
|
||||
plugins: opts.plugins.concat([
|
||||
@@ -462,7 +464,7 @@ const bundles = [
|
||||
moduleType: RENDERER,
|
||||
entry: 'react-native-renderer/fabric',
|
||||
global: 'ReactFabric',
|
||||
externals: ['react-native'],
|
||||
externals: ['react-native', 'ReactNativeInternalFeatureFlags'],
|
||||
babel: opts =>
|
||||
Object.assign({}, opts, {
|
||||
plugins: opts.plugins.concat([
|
||||
@@ -499,7 +501,12 @@ const bundles = [
|
||||
moduleType: RENDERER,
|
||||
entry: 'react-test-renderer',
|
||||
global: 'ReactTestRenderer',
|
||||
externals: ['react', 'scheduler', 'scheduler/unstable_mock'],
|
||||
externals: [
|
||||
'react',
|
||||
'scheduler',
|
||||
'scheduler/unstable_mock',
|
||||
'ReactNativeInternalFeatureFlags',
|
||||
],
|
||||
babel: opts =>
|
||||
Object.assign({}, opts, {
|
||||
plugins: opts.plugins.concat([
|
||||
@@ -692,7 +699,7 @@ const bundles = [
|
||||
moduleType: ISOMORPHIC,
|
||||
entry: 'scheduler',
|
||||
global: 'Scheduler',
|
||||
externals: [],
|
||||
externals: ['ReactNativeInternalFeatureFlags'],
|
||||
},
|
||||
|
||||
/******* React Scheduler Mock (experimental) *******/
|
||||
@@ -710,7 +717,7 @@ const bundles = [
|
||||
moduleType: ISOMORPHIC,
|
||||
entry: 'scheduler/unstable_mock',
|
||||
global: 'SchedulerMock',
|
||||
externals: [],
|
||||
externals: ['ReactNativeInternalFeatureFlags'],
|
||||
},
|
||||
|
||||
/******* React Scheduler Post Task (experimental) *******/
|
||||
|
||||
@@ -21,6 +21,7 @@ const importSideEffects = Object.freeze({
|
||||
'react-fetch/node': HAS_NO_SIDE_EFFECTS_ON_IMPORT,
|
||||
'react-dom': HAS_NO_SIDE_EFFECTS_ON_IMPORT,
|
||||
url: HAS_NO_SIDE_EFFECTS_ON_IMPORT,
|
||||
ReactNativeInternalFeatureFlags: HAS_NO_SIDE_EFFECTS_ON_IMPORT,
|
||||
});
|
||||
|
||||
// Bundles exporting globals that other modules rely on.
|
||||
@@ -31,6 +32,7 @@ const knownGlobals = Object.freeze({
|
||||
'react-interactions/events/tap': 'ReactEventsTap',
|
||||
scheduler: 'Scheduler',
|
||||
'scheduler/unstable_mock': 'SchedulerMock',
|
||||
ReactNativeInternalFeatureFlags: 'ReactNativeInternalFeatureFlags',
|
||||
});
|
||||
|
||||
// Given ['react'] in bundle externals, returns { 'react': 'React' }.
|
||||
|
||||
Reference in New Issue
Block a user