Skip to content

Commit

Permalink
Remove enablePersistentOffscreenHostContainer flag (facebook#24460)
Browse files Browse the repository at this point in the history
This was a Fabric-related experiment that we ended up not shipping.
  • Loading branch information
acdlite authored and eps1lon committed Apr 29, 2022
1 parent 0d43b41 commit 1982e7f
Show file tree
Hide file tree
Showing 24 changed files with 25 additions and 688 deletions.
32 changes: 0 additions & 32 deletions packages/react-native-renderer/src/ReactFabricHostConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
* @flow
*/

import type {ReactNodeList, OffscreenMode} from 'shared/ReactTypes';
import type {ElementRef} from 'react';
import type {
HostComponent,
Expand Down Expand Up @@ -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,
Expand Down
179 changes: 3 additions & 176 deletions packages/react-noop-renderer/src/createReactNoop.js
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -721,179 +707,20 @@ 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;
}
}

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) {
Expand Down
25 changes: 1 addition & 24 deletions packages/react-reconciler/src/ReactFiber.new.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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 {
Expand Down Expand Up @@ -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,
Expand Down
25 changes: 1 addition & 24 deletions packages/react-reconciler/src/ReactFiber.old.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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 {
Expand Down Expand Up @@ -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,
Expand Down
Loading

0 comments on commit 1982e7f

Please sign in to comment.