Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor commitPlacement to recursively insert nodes #17996

Merged
merged 2 commits into from
Feb 10, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion packages/react-dom/src/client/ReactDOM.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,14 @@ setBatchingImplementation(
batchedEventUpdates,
);

export type DOMInstance = Element & {_reactRootContainer: ?RootType, ...};
export type DOMHTMLInstance = HTMLElement & {
_reactRootContainer: ?RootType,
...
};

export type DOMContainer =
| (Element & {_reactRootContainer: ?RootType, ...})
| DOMInstance
| (Document & {_reactRootContainer: ?RootType, ...});

function createPortal(
Expand Down
36 changes: 18 additions & 18 deletions packages/react-dom/src/client/ReactDOMHostConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ import {
} from '../shared/HTMLNodeType';
import dangerousStyleValue from '../shared/dangerousStyleValue';

import type {DOMContainer} from './ReactDOM';
import type {DOMContainer, DOMInstance, DOMHTMLInstance} from './ReactDOM';
import type {
ReactDOMEventResponder,
ReactDOMEventResponderInstance,
Expand Down Expand Up @@ -88,8 +88,8 @@ export type EventTargetChildElement = {
},
...
};
export type Container = Element | Document;
export type Instance = Element;
export type Container = DOMContainer;
export type Instance = DOMInstance;
export type TextInstance = Text;
export type SuspenseInstance = Comment & {_reactRetry?: () => void, ...};
export type HydratableInstance = Instance | TextInstance | SuspenseInstance;
Expand Down Expand Up @@ -252,15 +252,15 @@ export function createInstance(
} else {
parentNamespace = ((hostContext: any): HostContextProd);
}
const domElement: Instance = createElement(
const domElement = createElement(
type,
props,
rootContainerInstance,
parentNamespace,
);
precacheFiberNode(internalInstanceHandle, domElement);
updateFiberProps(domElement, props);
return domElement;
return ((domElement: any): DOMInstance);
}

export function appendInitialChild(
Expand Down Expand Up @@ -398,7 +398,7 @@ export function commitUpdate(
updateProperties(domElement, updatePayload, type, oldProps, newProps);
}

export function resetTextContent(domElement: Instance): void {
export function resetTextContent(domElement: DOMInstance): void {
setTextContent(domElement, '');
}

Expand All @@ -411,15 +411,15 @@ export function commitTextUpdate(
}

export function appendChild(
parentInstance: Instance,
child: Instance | TextInstance,
parentInstance: DOMInstance,
child: DOMInstance | TextInstance,
): void {
parentInstance.appendChild(child);
}

export function appendChildToContainer(
container: DOMContainer,
child: Instance | TextInstance,
container: DOMInstance,
child: DOMInstance | TextInstance,
): void {
let parentNode;
if (container.nodeType === COMMENT_NODE) {
Expand Down Expand Up @@ -448,17 +448,17 @@ export function appendChildToContainer(
}

export function insertBefore(
parentInstance: Instance,
child: Instance | TextInstance,
beforeChild: Instance | TextInstance | SuspenseInstance,
parentInstance: DOMContainer,
child: DOMInstance | TextInstance,
beforeChild: DOMInstance | TextInstance | SuspenseInstance,
): void {
parentInstance.insertBefore(child, beforeChild);
}

export function insertInContainerBefore(
container: Container,
child: Instance | TextInstance,
beforeChild: Instance | TextInstance | SuspenseInstance,
container: DOMContainer,
child: DOMInstance | TextInstance,
beforeChild: DOMInstance | TextInstance | SuspenseInstance,
): void {
if (container.nodeType === COMMENT_NODE) {
(container.parentNode: any).insertBefore(child, beforeChild);
Expand Down Expand Up @@ -587,7 +587,7 @@ export function clearSuspenseBoundaryFromContainer(
export function hideInstance(instance: Instance): void {
// TODO: Does this work for all element types? What about MathML? Should we
// pass host context to this method?
instance = ((instance: any): HTMLElement);
instance = ((instance: any): DOMHTMLInstance);
const style = instance.style;
if (typeof style.setProperty === 'function') {
style.setProperty('display', 'none', 'important');
Expand All @@ -601,7 +601,7 @@ export function hideTextInstance(textInstance: TextInstance): void {
}

export function unhideInstance(instance: Instance, props: Props): void {
instance = ((instance: any): HTMLElement);
instance = ((instance: any): DOMHTMLInstance);
const styleProp = props[STYLE];
const display =
styleProp !== undefined &&
Expand Down
6 changes: 3 additions & 3 deletions packages/react-native-renderer/src/ReactNativeHostConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -289,12 +289,12 @@ export function appendChild(
}

export function appendChildToContainer(
parentInstance: Container,
parentInstance: Instance | Container,
child: Instance | TextInstance,
): void {
const childTag = typeof child === 'number' ? child : child._nativeTag;
UIManager.setChildren(
parentInstance, // containerTag
((parentInstance: any): Container), // containerTag
[childTag], // reactTags
);
}
Expand Down Expand Up @@ -386,7 +386,7 @@ export function insertBefore(
}

export function insertInContainerBefore(
parentInstance: Container,
parentInstance: Instance | Container,
child: Instance | TextInstance,
beforeChild: Instance | TextInstance,
): void {
Expand Down
67 changes: 34 additions & 33 deletions packages/react-reconciler/src/ReactFiberCommitWork.js
Original file line number Diff line number Diff line change
Expand Up @@ -1099,44 +1099,45 @@ function commitPlacement(finishedWork: Fiber): void {
const before = getHostSibling(finishedWork);
// We only have the top Fiber that was inserted but we need to recurse down its
// children to find all the terminal nodes.
let node: Fiber = finishedWork;
while (true) {
const isHost = node.tag === HostComponent || node.tag === HostText;
if (isHost || (enableFundamentalAPI && node.tag === FundamentalComponent)) {
const stateNode = isHost ? node.stateNode : node.stateNode.instance;
if (before) {
if (isContainer) {
insertInContainerBefore(parent, stateNode, before);
} else {
insertBefore(parent, stateNode, before);
}
insertOrAppendPlacementNode(finishedWork, before, parent, isContainer);
}

function insertOrAppendPlacementNode(
node: Fiber,
before: ?Instance,
parent: Instance,
isContainer: boolean,
trueadm marked this conversation as resolved.
Show resolved Hide resolved
): void {
const isHost = node.tag === HostComponent || node.tag === HostText;
if (isHost || (enableFundamentalAPI && node.tag === FundamentalComponent)) {
const stateNode = isHost ? node.stateNode : node.stateNode.instance;
if (before) {
if (isContainer) {
insertInContainerBefore(parent, stateNode, before);
} else {
if (isContainer) {
appendChildToContainer(parent, stateNode);
} else {
appendChild(parent, stateNode);
}
insertBefore(parent, stateNode, before);
}
} else {
if (isContainer) {
appendChildToContainer(parent, stateNode);
} else {
appendChild(parent, stateNode);
}
} else if (node.tag === HostPortal) {
// If the insertion itself is a portal, 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.child !== null) {
node.child.return = node;
node = node.child;
continue;
}
if (node === finishedWork) {
return;
}
while (node.sibling === null) {
if (node.return === null || node.return === finishedWork) {
return;
} else if (node.tag === HostPortal) {
// If the insertion itself is a portal, then we don't want to traverse
// down its children. Instead, we'll get insertions from each child in
// the portal directly.
} else {
const child = node.child;
if (child !== null) {
insertOrAppendPlacementNode(child, before, parent, isContainer);
let sibling = child.sibling;
while (sibling !== null) {
insertOrAppendPlacementNode(sibling, before, parent, isContainer);
sibling = sibling.sibling;
}
node = node.return;
}
node.sibling.return = node.return;
node = node.sibling;
}
}

Expand Down