1313'use strict' ;
1414
1515import type { Fiber } from 'ReactFiber' ;
16- import type { FiberRoot } from 'ReactFiberRoot' ;
1716import type { HostConfig } from 'ReactFiberReconciler' ;
1817
1918var ReactTypeOfWork = require ( 'ReactTypeOfWork' ) ;
@@ -37,7 +36,6 @@ module.exports = function<T, P, I, TI, C>(
3736 trapError : ( failedFiber : Fiber , error : Error , isUnmounting : boolean ) = > void
3837) {
3938
40- const updateContainer = config . updateContainer ;
4139 const commitUpdate = config . commitUpdate ;
4240 const commitTextUpdate = config . commitTextUpdate ;
4341
@@ -68,22 +66,30 @@ module.exports = function<T, P, I, TI, C>(
6866 }
6967 }
7068
71- function getHostParent ( fiber : Fiber ) : ? I {
69+ function getHostParent ( fiber : Fiber ) : null | I | C {
7270 let parent = fiber . return ;
7371 while ( parent ) {
7472 switch ( parent . tag ) {
7573 case HostComponent :
7674 return parent . stateNode ;
7775 case HostContainer :
78- // TODO: Currently we use the updateContainer feature to update these,
79- // but we should be able to handle this case too.
80- return null ;
76+ return parent . stateNode . containerInfo ;
77+ case Portal :
78+ return parent . stateNode . containerInfo ;
8179 }
8280 parent = parent . return ;
8381 }
8482 return null ;
8583 }
8684
85+ function isHostParent ( fiber : Fiber ) : boolean {
86+ return (
87+ fiber . tag === HostComponent ||
88+ fiber . tag === HostContainer ||
89+ fiber . tag === Portal
90+ ) ;
91+ }
92+
8793 function getHostSibling ( fiber : Fiber ) : ?I {
8894 // We're going to search forward into the tree until we find a sibling host
8995 // node. Unfortunately, if multiple insertions are done in a row we have to
@@ -93,7 +99,7 @@ module.exports = function<T, P, I, TI, C>(
9399 siblings: while ( true ) {
94100 // If we didn't find anything, let's try the next sibling.
95101 while ( ! node . sibling ) {
96- if ( ! node . return || node . return . tag === HostComponent ) {
102+ if ( ! node . return || isHostParent ( node . return ) ) {
97103 // If we pop out of the root or hit the parent the fiber we are the
98104 // last sibling.
99105 return null ;
@@ -142,6 +148,10 @@ module.exports = function<T, P, I, TI, C>(
142148 } else {
143149 appendChild ( parent , node . stateNode ) ;
144150 }
151+ } else if ( node . tag === Portal ) {
152+ // If the insertion itself is a portal, then we don't want to traverse
153+ // down its children. Instead, we'll get insertions from each child in
154+ // the portal directly.
145155 } else if ( node . child ) {
146156 // TODO: Coroutines need to visit the stateNode.
147157 node = node . child ;
@@ -201,6 +211,18 @@ module.exports = function<T, P, I, TI, C>(
201211 if ( parent ) {
202212 removeChild ( parent , node . stateNode ) ;
203213 }
214+ } else if ( node . tag === Portal ) {
215+ // If this is a portal, then the parent is actually the portal itself.
216+ // We need to keep track of which parent we're removing from.
217+ // TODO: This uses a recursive call. We can get rid of that by mutating
218+ // the parent binding and restoring it by searching for the host parent
219+ // again when we pop past a portal.
220+ const portalParent = node . stateNode . containerInfo ;
221+ let child = node . child ;
222+ while ( child ) {
223+ unmountHostComponents ( portalParent , child ) ;
224+ child = child . sibling ;
225+ }
204226 } else {
205227 commitUnmount ( node ) ;
206228 if ( node . child ) {
@@ -260,11 +282,6 @@ module.exports = function<T, P, I, TI, C>(
260282 detachRef ( current ) ;
261283 return ;
262284 }
263- case Portal : {
264- const containerInfo : C = current . stateNode . containerInfo ;
265- updateContainer ( containerInfo , null ) ;
266- return ;
267- }
268285 }
269286 }
270287
@@ -274,14 +291,6 @@ module.exports = function<T, P, I, TI, C>(
274291 detachRefIfNeeded ( current , finishedWork ) ;
275292 return ;
276293 }
277- case HostContainer : {
278- // TODO: Attach children to root container.
279- const children = finishedWork . output ;
280- const root : FiberRoot = finishedWork . stateNode ;
281- const containerInfo : C = root . containerInfo ;
282- updateContainer ( containerInfo , children ) ;
283- return ;
284- }
285294 case HostComponent : {
286295 const instance : I = finishedWork . stateNode ;
287296 if ( instance != null && current ) {
@@ -303,10 +312,10 @@ module.exports = function<T, P, I, TI, C>(
303312 commitTextUpdate ( textInstance , oldText , newText ) ;
304313 return ;
305314 }
315+ case HostContainer : {
316+ return ;
317+ }
306318 case Portal : {
307- const children = finishedWork . child ;
308- const containerInfo : C = finishedWork . stateNode . containerInfo ;
309- updateContainer ( containerInfo , children ) ;
310319 return ;
311320 }
312321 default :
0 commit comments