ReactFiberFragmentInstance.js118 lines
mainRaw/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
*/
import type {FragmentInstanceType} from './ReactFiberConfig';
import type {Fiber} from './ReactInternalTypes';
import {
HostRoot,
HostComponent,
HostSingleton,
HostText,
Fragment,
} from './ReactWorkTags';
import {
supportsSingletons,
commitNewChildToFragmentInstance,
deleteChildFromFragmentInstance,
} from './ReactFiberConfig';
import {enableFragmentRefsTextNodes} from 'shared/ReactFeatureFlags';
export function commitNewChildToFragmentInstances(
fiber: Fiber,
parentFragmentInstances: null | Array<FragmentInstanceType>,
): void {
if (
(fiber.tag !== HostComponent &&
fiber.tag !== HostSingleton &&
!(enableFragmentRefsTextNodes && fiber.tag === HostText)) ||
// Only run fragment insertion effects for initial insertions
fiber.alternate !== null ||
parentFragmentInstances === null
) {
return;
}
for (let i = 0; i < parentFragmentInstances.length; i++) {
const fragmentInstance = parentFragmentInstances[i];
commitNewChildToFragmentInstance(fiber.stateNode, fragmentInstance);
}
}
export function commitFragmentInstanceInsertionEffects(fiber: Fiber): void {
let parent = fiber.return;
while (parent !== null) {
if (isFragmentInstanceParent(parent)) {
const fragmentInstance: FragmentInstanceType = parent.stateNode;
commitNewChildToFragmentInstance(fiber.stateNode, fragmentInstance);
}
if (isFragmentInstanceHostBoundary(parent)) {
return;
}
parent = parent.return;
}
}
export function commitFragmentInstanceDeletionEffects(fiber: Fiber): void {
let parent = fiber.return;
while (parent !== null) {
if (isFragmentInstanceParent(parent)) {
const fragmentInstance: FragmentInstanceType = parent.stateNode;
deleteChildFromFragmentInstance(fiber.stateNode, fragmentInstance);
}
if (isFragmentInstanceHostBoundary(parent)) {
return;
}
parent = parent.return;
}
}
export function getParentFragmentInstances(
fiber: Fiber,
): null | Array<FragmentInstanceType> {
let parentFragmentInstances = null;
let parent = fiber.return;
while (parent !== null) {
if (isFragmentInstanceParent(parent)) {
const fragmentInstance: FragmentInstanceType = parent.stateNode;
if (parentFragmentInstances === null) {
parentFragmentInstances = [fragmentInstance];
} else {
parentFragmentInstances.push(fragmentInstance);
}
}
if (isFragmentInstanceHostBoundary(parent)) {
break;
}
parent = parent.return;
}
return parentFragmentInstances;
}
// HostPortal / HostHoistable are host parents for placement, but not for
// fragment instance ancestry — commit bookkeeping walks past them so it
// matches getFragmentParentInstanceOrContainerFiber. HostSingleton is a
// fragment host boundary (and a collected child) even when it is not a
// placement scope.
function isFragmentInstanceHostBoundary(fiber: Fiber): boolean {
return (
fiber.tag === HostComponent ||
fiber.tag === HostRoot ||
// $FlowFixMe[constant-condition]
(supportsSingletons ? fiber.tag === HostSingleton : false)
);
}
function isFragmentInstanceParent(fiber: Fiber): boolean {
return fiber && fiber.tag === Fragment && fiber.stateNode !== null;
}
Loading syntax highlighting…