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 ;
@@ -140,6 +146,10 @@ module.exports = function<T, P, I, TI, C>(
140146 } else {
141147 appendChild ( parent , node . stateNode ) ;
142148 }
149+ } else if ( node . tag === Portal ) {
150+ // If the insertion itself is a portal, then we don't want to traverse
151+ // down its children. Instead, we'll get insertions from each child in
152+ // the portal directly.
143153 } else if ( node . child ) {
144154 // TODO: Coroutines need to visit the stateNode.
145155 node = node . child ;
@@ -197,6 +207,18 @@ module.exports = function<T, P, I, TI, C>(
197207 if ( parent ) {
198208 removeChild ( parent , node . stateNode ) ;
199209 }
210+ } else if ( node . tag === Portal ) {
211+ // If this is a portal, then the parent is actually the portal itself.
212+ // We need to keep track of which parent we're removing from.
213+ // TODO: This uses a recursive call. We can get rid of that by mutating
214+ // the parent binding and restoring it by searching for the host parent
215+ // again when we pop past a portal.
216+ const portalParent = node . stateNode . containerInfo ;
217+ let child = node . child ;
218+ while ( child ) {
219+ unmountHostComponents ( portalParent , child ) ;
220+ child = child . sibling ;
221+ }
200222 } else {
201223 commitUnmount ( node ) ;
202224 if ( node . child ) {
@@ -254,11 +276,6 @@ module.exports = function<T, P, I, TI, C>(
254276 detachRef ( current ) ;
255277 return ;
256278 }
257- case Portal : {
258- const containerInfo : C = current . stateNode . containerInfo ;
259- updateContainer ( containerInfo , null ) ;
260- return ;
261- }
262279 }
263280 }
264281
@@ -268,14 +285,6 @@ module.exports = function<T, P, I, TI, C>(
268285 detachRefIfNeeded ( current , finishedWork ) ;
269286 return ;
270287 }
271- case HostContainer : {
272- // TODO: Attach children to root container.
273- const children = finishedWork . output ;
274- const root : FiberRoot = finishedWork . stateNode ;
275- const containerInfo : C = root . containerInfo ;
276- updateContainer ( containerInfo , children ) ;
277- return ;
278- }
279288 case HostComponent : {
280289 const instance : I = finishedWork . stateNode ;
281290 if ( instance != null && current ) {
@@ -297,10 +306,10 @@ module.exports = function<T, P, I, TI, C>(
297306 commitTextUpdate ( textInstance , oldText , newText ) ;
298307 return ;
299308 }
309+ case HostContainer : {
310+ return ;
311+ }
300312 case Portal : {
301- const children = finishedWork . child ;
302- const containerInfo : C = finishedWork . stateNode . containerInfo ;
303- updateContainer ( containerInfo , children ) ;
304313 return ;
305314 }
306315 default :
0 commit comments