import type { Fiber } from 'react-reconciler' ; import { Env } from '../env/env' ; import { addChildFiberAt , addChildFiberBefore } from '../fiber/addFiber' ; import { findPreviousFiber } from '../fiber/findFiber' ; import { getFiberFromPath } from '../fiber/getFiber' ; import { updateFiberDebugFields , updateFibersIndex } from '../fiber/updateFiber' ; import { invariant } from '../invariant' ; import { warning } from '../warning' ; param parent param child param position param skipUpdate returns export function addChild ( parent , child , position , skipUpdate ? ) { invariant ( typeof position !== 'number' || position >= - 1 , `The index provided to add the child must be ` + `greater than or equal to -1, found: ${ position }.` ) ; let index ; if ( typeof position === 'number' ) { index = addChildFiberAt ( parent , child , position ) ; } else { index = addChildFiberBefore ( parent , child , position ) ; } if ( __DEV__ ) { if ( typeof position === 'number' ) { if ( position !== - 1 && index !== position ) { warning ( `The index provided is greater than the number of children, ` + `the child is added at the bottom.` ) ; } } else { if ( findPreviousFiber ( parent , position ) === null ) { warning ( `No child with the key: '${ position }' has been found, ` + `the child is added at the bottom.` ) ; } } } updateFibersIndex ( child , index ) ; if ( __DEV__ ) { updateFiberDebugFields ( child , parent ) ; } if ( child . alternate === null || parent . alternate === null ) { if ( child . alternate !== null ) { child . alternate . return = null ; child . alternate . sibling = null ; } } else { if ( typeof position === 'number' ) { addChildFiberAt ( parent . alternate , child . alternate , position ) ; } else { addChildFiberBefore ( parent . alternate , child . alternate , position ) ; } updateFibersIndex ( child . alternate , index ) ; if ( __DEV__ ) { updateFiberDebugFields ( child . alternate , parent ) ; } } if ( skipUpdate ) { return index ; } const containerFiber = getFiberFromPath ( parent , ( fiber ) => fiber . return , ( fiber ) => Env . isElement ( fiber . elementType , fiber . stateNode ) ) ; const elementFiber = getFiberFromPath ( child , ( fiber ) => fiber . child , ( fiber ) => Env . isElement ( fiber . elementType , fiber . stateNode ) ) ; if ( containerFiber === null ) { if ( __DEV__ ) { warning ( 'Cannot find the container element, neither the parent nor any ' + 'component before it seems to generate an element instance. ' + 'You should manually send the element and use the `skipUpdate` option.' ) ; } return index ; } if ( elementFiber === null ) { if ( __DEV__ ) { warning ( 'Cannot find the child element. ' + 'You should manually send the element and use the `skipUpdate` option.' ) ; } return index ; } const container = containerFiber . stateNode ; const element = elementFiber . stateNode ; if ( child . sibling === null ) { Env . appendChildToContainer ( container , element ) ; } else { const beforeFiber = getFiberFromPath ( child . sibling , ( fiber ) => fiber . child , ( fiber ) => Env . isElement ( fiber . elementType , fiber . stateNode ) ) ; if ( beforeFiber !== null ) { const before = beforeFiber . stateNode ; Env . insertInContainerBefore ( container , element , before ) ; } if ( __DEV__ ) { if ( beforeFiber === null ) { warning ( 'Cannot find the previous element. ' + 'You should manually send the element and use the `skipUpdate` option.' ) ; } } } return index ; }