11// @flow
22
33import React , { type Node , type Element } from 'react'
4- import type { Visitor , Frame , AbstractElement } from './types'
4+ import type { Visitor , YieldFrame , Frame , AbstractElement } from './types'
55import { visitChildren , resumeVisitChildren } from './visitor'
66import { getChildrenArray } from './element'
77
@@ -28,49 +28,58 @@ let prevDispatcher = ReactCurrentDispatcher.current
2828 the queue. Hence we recursively look at suspended components in
2929 this queue, wait for their promises to resolve, and continue
3030 calling visitChildren on their children. */
31- const flushFrames = ( queue : Frame [ ] , visitor : Visitor ) : Promise < void > => {
32- if ( queue . length === 0 ) {
33- return Promise . resolve ( )
31+ const updateWithFrame = (
32+ frame : Frame ,
33+ queue : Frame [ ] ,
34+ visitor : Visitor
35+ ) : Promise < void > => {
36+ if ( frame . kind === 'frame.yield' ) {
37+ const yieldFrame : YieldFrame = frame
38+
39+ return new Promise ( resolve => {
40+ setImmediate ( ( ) => {
41+ prevDispatcher = ReactCurrentDispatcher . current
42+ ReactCurrentDispatcher . current = Dispatcher
43+ resumeVisitChildren ( yieldFrame , queue , visitor )
44+ ReactCurrentDispatcher . current = prevDispatcher
45+ resolve ( )
46+ } )
47+ } )
3448 }
3549
36- const frame = queue . shift ( )
37-
3850 return frame . thenable . then ( ( ) => {
3951 prevDispatcher = ReactCurrentDispatcher . current
4052 ReactCurrentDispatcher . current = Dispatcher
4153
4254 let children = [ ]
4355
4456 // Update the component after we've suspended to rerender it,
45- // at which point we'll actually get its children and continue
46- // walking the tree
57+ // at which point we'll actually get its children
4758 if ( frame . kind === 'frame.class' ) {
48- visitChildren (
49- getChildrenArray ( updateClassComponent ( queue , frame ) ) ,
50- queue ,
51- visitor
52- )
59+ children = getChildrenArray ( updateClassComponent ( queue , frame ) )
5360 } else if ( frame . kind === 'frame.hooks' ) {
54- visitChildren (
55- getChildrenArray ( updateFunctionComponent ( queue , frame ) ) ,
56- queue ,
57- visitor
58- )
61+ children = getChildrenArray ( updateFunctionComponent ( queue , frame ) )
5962 } else if ( frame . kind === 'frame.lazy' ) {
60- visitChildren (
61- getChildrenArray ( updateLazyComponent ( queue , frame ) ) ,
62- queue ,
63- visitor
64- )
65- } else if ( frame . kind === 'frame.yield' ) {
66- resumeVisitChildren ( frame , queue , visitor )
63+ children = getChildrenArray ( updateLazyComponent ( queue , frame ) )
6764 }
6865
66+ // Now continue walking the previously suspended component's
67+ // children (which might also suspend)
68+ visitChildren ( children , queue , visitor )
6969 ReactCurrentDispatcher . current = prevDispatcher
70- return flushFrames ( queue , visitor )
7170 } )
7271}
7372
73+ const flushFrames = ( queue : Frame [ ] , visitor : Visitor ) : Promise < void > => {
74+ if ( queue . length === 0 ) {
75+ return Promise . resolve ( )
76+ }
77+
78+ return updateWithFrame ( queue . shift ( ) , queue, visitor) . then ( ( ) =>
79+ flushFrames ( queue , visitor )
80+ )
81+ }
82+
7483const defaultVisitor = ( ) => { }
7584
7685const renderPrepass = ( element : Node , visitor ? : Visitor ) : Promise < void > => {
0 commit comments