/**
 * 当首次mount时HostRoot会用到，Class Component也会用到该类型的updateQueue
 * Function Component使用的时另外的逻辑
 */ import { Fiber } from './ReactInternalTypes' ; export type SharedQueue = { /**
     * 存储着本次更新的update队列，是实际的updateQueue。
     * shared的意思是current节点与workInProgress节点共享一条更新队列。
     */ pending : Update | null ; } ; export type UpdateQueue < State > = { /**
     * 前一次更新计算得出的状态，它是第一个被跳过的update之前的那些update计算得出的state。会以它为基础计算本次的state
     */ baseState : State ; shared : SharedQueue ; /**
     * 前一次更新时updateQueue中第一个被跳过的update对象
     */ firstBaseUpdate : Update | null ; /**
     *lastBaseUpdate相当于，前一次更新中，updateQueue中以第一个被跳过的update为起点一直到的最后一个update的形成的链表，截取最后一个而获得的update
     */ lastBaseUpdate : Update | null ; } ; export const UpdateState = 0 ; export type Update = { /**
     * 更新所携带的状态。
     * 类组件中：有两种可能，对象（{}），和函数（(prevState, nextProps):newState => {}）
     *根组件中：是React.createElement创建的JSX对象，即ReactDOM.render的第一个参数
     */ payload : any ; /**
     * update之间通过next形成一条链表，后创建的update插在链表前端，
     * 其中最后一个update（最先创建的）的next指向第一个update形成一个环
     * 所以updateQueue.shared.pending为最后创建的update
     */ next : null | Update ; tag : 0 | 1 | 2 | 3 ; } ; param fiber export const initializeUpdateQueue = < State > ( fiber ) : void => { const queue = { baseState : fiber . memoizedState , shared : { pending : null , } , lastBaseUpdate : null , firstBaseUpdate : null , } ; fiber . updateQueue = queue ; } ; returns export const createUpdate = ( ) : Update => { const update = { payload : null , next : null , tag : UpdateState , } ; return update ; } ; param fiber param update export const enqueueUpdate = ( fiber , update ) : void => { const updateQueue = fiber . updateQueue ; if ( ! updateQueue ) return ; const sharedQueue = ( updateQueue as any ) . shared ; const pending = sharedQueue . pending ; if ( pending === null ) { update . next = update ; } else { update . next = pending . next ; pending . next = update ; } sharedQueue . pending = update ; } ; param current param workInProgress export const cloneUpdateQueue = < State > ( current , workInProgress ) : void => { const queue = workInProgress . updateQueue as any ; const currentQueue = current . updateQueue as any ; if ( queue === currentQueue ) { const clone = { shared : currentQueue . shared , firstBaseUpdate : currentQueue . firstBaseUpdate , lastBaseUpdate : currentQueue . lastBaseUpdate , baseState : currentQueue . baseState , } ; workInProgress . updateQueue = clone ; } } ; export const processUpdateQueue = < State > ( workInProgress , props , instance ) => { const queue = workInProgress . updateQueue as any ; let firstBaseUpdate = queue . firstBaseUpdate ; let lastBaseUpdate = queue . lastBaseUpdate ; let pendingQueue = queue . shared . pending ; if ( pendingQueue !== null ) { queue . shared . pending = null ; const lastPendingUpdate = pendingQueue ; const firstPendingUpdate = lastPendingUpdate . next ; lastPendingUpdate . next = null ; if ( lastBaseUpdate === null ) { firstBaseUpdate = firstPendingUpdate ; } else { lastBaseUpdate . next = firstPendingUpdate ; } lastBaseUpdate = lastPendingUpdate ; const current = workInProgress . alternate ; if ( current !== null ) { const currentQueue = current . updateQueue as any ; const currentLastBaseUpdate = currentQueue . lastBaseUpdate ; if ( currentLastBaseUpdate !== lastBaseUpdate ) { if ( currentLastBaseUpdate === null ) { currentQueue . firstBaseUpdate = firstPendingUpdate ; } else { currentLastBaseUpdate . next = firstPendingUpdate ; } currentQueue . lastBaseUpdate = lastPendingUpdate ; } } } if ( firstBaseUpdate !== null ) { let newState = queue . baseState ; let newBaseState = null ; let newFirstBaseUpdate = null ; let newLastBaseUpdate = null ; let update = firstBaseUpdate ; do { newState = getStateFromUpdate ( workInProgress , queue , update ! , newState , props , instance ) ; update = update ! . next ; if ( update === null ) { pendingQueue = queue . shared . pending ; if ( pendingQueue === null ) break ; else { const lastPendingUpdate = pendingQueue ; const firstPendingUpdate = lastPendingUpdate . next ; lastPendingUpdate . next = null ; update = firstPendingUpdate ; queue . lastBaseUpdate = lastPendingUpdate ; queue . shared . pending = null ; } } } while ( true ) ; if ( newLastBaseUpdate === null ) { newBaseState = newState ; } queue . baseState = newBaseState as any ; queue . firstBaseUpdate = newFirstBaseUpdate ; queue . lastBaseUpdate = newLastBaseUpdate ; workInProgress . memoizedState = newState ; } } ; export const getStateFromUpdate = < State > ( _workInProgress , _queue , update , prevState , nextProps , instance ) : any => { switch ( update . tag ) { case UpdateState : { const payload = update . payload ; let partialState ; if ( typeof payload === 'function' ) { partialState = payload . call ( instance , prevState , nextProps ) ; } else { partialState = payload ; } if ( partialState === null || partialState === undefined ) { return prevState ; } return Object . assign ( { } , prevState , partialState ) ; } } } ;