@@ -53,6 +53,7 @@ exports.FiberVisit = Object.freeze({
5353 Return : 0b000100 ,
5454 Effect : 0b001000 ,
5555 Break : 0b010000 ,
56+ SiblingFirst : 0b100000 ,
5657} ) ;
5758exports . FiberTag = Object . freeze ( {
5859 FunctionComponent : 0 ,
@@ -126,21 +127,30 @@ const isHostFiber = (fiber) => {
126127 }
127128 return false ;
128129} ;
129- const pushVisitStack = ( stack , scope , fiber , flags ) => {
130- if ( scope !== fiber && flags === exports . FiberVisit . Child ) {
130+ const pushVisitStack = ( stack , scope , fiber , flags , callback ) => {
131+ if ( flags === exports . FiberVisit . Return ) {
132+ fiber . return && stack . push ( fiber . return ) ;
133+ return ;
134+ }
135+ if ( flags === exports . FiberVisit . Effect ) {
136+ fiber . nextEffect && stack . push ( fiber . nextEffect ) ;
137+ return ;
138+ }
139+ if ( scope !== fiber && ( flags & ~ exports . FiberVisit . SiblingFirst ) === exports . FiberVisit . Child ) {
131140 flags |= exports . FiberVisit . Sibling ;
132141 }
142+ const siblingFirst = flags & exports . FiberVisit . SiblingFirst ;
133143 if ( flags & exports . FiberVisit . Sibling ) {
134- fiber . sibling && stack . push ( fiber . sibling ) ;
144+ siblingFirst || fiber . sibling && stack . push ( fiber . sibling ) ;
145+ }
146+ if ( isFunction ( callback ) ) {
147+ stack . push ( callback ) ;
135148 }
136149 if ( flags & exports . FiberVisit . Child ) {
137150 fiber . child && stack . push ( fiber . child ) ;
138151 }
139- if ( flags === exports . FiberVisit . Return ) {
140- fiber . return && stack . push ( fiber . return ) ;
141- }
142- if ( flags === exports . FiberVisit . Effect ) {
143- fiber . nextEffect && stack . push ( fiber . nextEffect ) ;
152+ if ( flags & exports . FiberVisit . Sibling ) {
153+ siblingFirst && fiber . sibling && stack . push ( fiber . sibling ) ;
144154 }
145155} ;
146156const findFiber = ( fiber , predicate , flags = exports . FiberVisit . Child ) => {
@@ -156,7 +166,7 @@ const findFiber = (fiber, predicate, flags = exports.FiberVisit.Child) => {
156166 if ( predicate ( current ) ) {
157167 return current ;
158168 }
159- pushVisitStack ( stack , fiber , current , flags ) ;
169+ pushVisitStack ( stack , fiber , current , flags , null ) ;
160170 }
161171 return null ;
162172} ;
@@ -175,7 +185,7 @@ const findFibers = (fiber, predicate, flags = exports.FiberVisit.Child) => {
175185 if ( predicate ( current ) ) {
176186 result . push ( current ) ;
177187 }
178- pushVisitStack ( stack , fiber , current , flags ) ;
188+ pushVisitStack ( stack , fiber , current , flags , null ) ;
179189 }
180190 return result ;
181191} ;
@@ -206,10 +216,7 @@ const traverseFiber = (fiber, visit, flags = exports.FiberVisit.Child) => {
206216 if ( post === exports . FiberVisit . Break ) {
207217 continue ;
208218 }
209- if ( isFunction ( post ) ) {
210- stack . push ( post ) ;
211- }
212- pushVisitStack ( stack , fiber , current , flags ) ;
219+ pushVisitStack ( stack , fiber , current , flags , post ) ;
213220 }
214221} ;
215222exports . traverseFiber = traverseFiber ;
@@ -226,10 +233,10 @@ const findChildHostFibers = (fiber) => {
226233 }
227234 if ( isHostFiber ( current ) ) {
228235 result . push ( current ) ;
229- pushVisitStack ( stack , fiber , current , exports . FiberVisit . Sibling ) ;
236+ pushVisitStack ( stack , fiber , current , exports . FiberVisit . Sibling , null ) ;
230237 }
231238 else {
232- pushVisitStack ( stack , fiber , current , exports . FiberVisit . Child | exports . FiberVisit . Sibling ) ;
239+ pushVisitStack ( stack , fiber , current , exports . FiberVisit . Child | exports . FiberVisit . Sibling , null ) ;
233240 }
234241 }
235242 return result ;
@@ -438,15 +445,13 @@ const appendFiberEffect = (rootFiber, effectFiber, renderFiber, finishFiber) =>
438445 rootFiber [ FiberEffectProp ] |= flags ;
439446 fiber [ FiberEffectProp ] |= flags ;
440447 fiber . nextEffect = null ;
441- return ( ) => {
442- if ( exports . FiberFlag . NoFlags === ( fiber [ FiberEffectProp ] & exports . FiberFlag . LifecycleEffectMask ) ) {
443- return ;
444- }
448+ if ( exports . FiberFlag . NoFlags !== ( fiber [ FiberEffectProp ] & exports . FiberFlag . LifecycleEffectMask ) ) {
445449 const nextEffect = effectFiber . nextEffect ;
446450 effectFiber . nextEffect = fiber ;
447451 fiber . nextEffect = nextEffect ;
448- } ;
449- } ) ;
452+ }
453+ return null ;
454+ } , exports . FiberVisit . Child | exports . FiberVisit . SiblingFirst ) ;
450455 }
451456} ;
452457exports . appendFiberEffect = appendFiberEffect ;
@@ -458,7 +463,7 @@ const defineFiberProp = (fiber, prop, value) => {
458463 value,
459464 } ) ;
460465} ;
461- const protectFiberProp = ( fiber , prop , restore ) => {
466+ const protectFiberProp = ( fiber , prop , restore , needDummy ) => {
462467 if ( null == fiber ) {
463468 return ;
464469 }
@@ -468,12 +473,11 @@ const protectFiberProp = (fiber, prop, restore) => {
468473 }
469474 const backup = fiber [ prop ] ;
470475 let value = backup ;
471- if ( ! restore . current && prop === 'stateNode' && isHostFiber ( fiber ) ) {
476+ if ( needDummy && prop === 'stateNode' && isHostFiber ( fiber ) ) {
472477 value = null ;
473478 if ( backup === null || backup === void 0 ? void 0 : backup . parentNode ) {
474- const dummy = document . createElement ( 'div' ) ;
475- backup . parentNode . appendChild ( dummy ) ;
476- value = dummy ;
479+ value = document . createElement ( 'dummy' ) ;
480+ backup . parentNode . appendChild ( value ) ;
477481 }
478482 }
479483 Object . defineProperty ( fiber , prop , {
@@ -492,13 +496,13 @@ const restoreFiberProp = (fiber, prop) => {
492496 defineFiberProp ( fiber , prop , fiber [ prop ] ) ;
493497 }
494498} ;
495- const protectFiberProps = ( fiber , current , restore ) => {
499+ const protectFiberProps = ( fiber , current , restore , needDummy ) => {
496500 const alternate = fiber . alternate ;
497501 if ( alternate && ! current ) {
498- protectFiberProps ( alternate , fiber , restore ) ;
502+ protectFiberProps ( alternate , fiber , restore , false ) ;
499503 }
500504 for ( const prop of ProtectedFiberProps ) {
501- protectFiberProp ( fiber , prop , restore ) ;
505+ protectFiberProp ( fiber , prop , restore , needDummy ) ;
502506 }
503507} ;
504508const restoreFiberProps = ( fiber , current ) => {
@@ -513,57 +517,62 @@ const restoreFiberProps = (fiber, current) => {
513517 }
514518 }
515519} ;
516- const protectChildHostNodes = ( fiber , restore ) => {
517- const hostFibers = ( 0 , exports . findChildHostFibers ) ( fiber ) ;
518- hostFibers . forEach ( ( hostFiber ) => {
519- protectFiberProp ( hostFiber , 'stateNode' , restore ) ;
520- const hostNode = getHostNode ( hostFiber ) ;
521- const parentNode = hostNode === null || hostNode === void 0 ? void 0 : hostNode . parentNode ;
522- if ( hostNode && parentNode ) {
523- const dummy = document . createElement ( 'div' ) ;
524- parentNode . replaceChild ( dummy , hostNode ) ;
525- hostFiber . stateNode = dummy ;
526- }
527- } ) ;
528- } ;
529520const protectFiber = ( fiber ) => {
530521 const restore = { current : true } ;
531- const portalFibers = ( 0 , exports . findFibers ) ( fiber , ( node ) => node . tag === exports . FiberTag . HostPortal ) ;
532- portalFibers . forEach ( ( portalFiber ) => protectChildHostNodes ( portalFiber . child , restore ) ) ;
533- protectChildHostNodes ( fiber , restore ) ;
522+ const stack = [ true ] ;
523+ ( 0 , exports . traverseFiber ) ( fiber , ( node ) => {
524+ const needDummy = isHostFiber ( node ) && true === stack [ 0 ] ;
525+ if ( needDummy ) {
526+ protectFiberProp ( node , 'stateNode' , restore , false ) ;
527+ const hostNode = getHostNode ( node ) ;
528+ const parentNode = hostNode === null || hostNode === void 0 ? void 0 : hostNode . parentNode ;
529+ if ( hostNode && parentNode ) {
530+ const dummy = document . createElement ( 'dummy' ) ;
531+ parentNode . replaceChild ( dummy , hostNode ) ;
532+ node . stateNode = dummy ;
533+ }
534+ }
535+ if ( UseDeepDetach || node === fiber ) {
536+ protectFiberProps ( node , null , restore , true ) ;
537+ }
538+ if ( node . tag === exports . FiberTag . HostPortal ) {
539+ stack . unshift ( true ) ;
540+ return ( ) => stack . shift ( ) ;
541+ }
542+ if ( needDummy ) {
543+ stack . unshift ( false ) ;
544+ return ( ) => stack . shift ( ) ;
545+ }
546+ return null ;
547+ } ) ;
534548 restore . current = false ;
535- if ( UseDeepDetach ) {
536- ( 0 , exports . traverseFiber ) ( fiber , ( node ) => ( ) => {
537- protectFiberProps ( node , null , restore ) ;
538- } ) ;
539- }
540- else {
541- protectFiberProps ( fiber , null , restore ) ;
542- }
543549 return restore ;
544550} ;
545551exports . protectFiber = protectFiber ;
546552const restoreFiber = ( fiber , restore ) => {
547553 restore . current = true ;
548- if ( UseDeepDetach ) {
549- ( 0 , exports . traverseFiber ) ( fiber , ( node ) => ( ) => {
554+ const stack = [ true ] ;
555+ ( 0 , exports . traverseFiber ) ( fiber , ( node ) => {
556+ const needRestore = isHostFiber ( node ) && true === stack [ 0 ] ;
557+ if ( UseDeepDetach || node === fiber ) {
550558 restoreFiberProps ( node , null ) ;
551- traverseEffectHooks ( node , ( effect ) => {
552- effect . destroy = undefined ;
553- } ) ;
554- } ) ;
555- }
556- else {
557- restoreFiberProps ( fiber , null ) ;
558- ( 0 , exports . findChildHostFibers ) ( fiber ) . forEach ( ( node ) => {
559+ }
560+ else if ( needRestore ) {
559561 restoreFiberProp ( node , 'stateNode' ) ;
562+ }
563+ traverseEffectHooks ( node , ( effect ) => {
564+ effect . destroy = undefined ;
560565 } ) ;
561- ( 0 , exports . traverseFiber ) ( fiber , ( node ) => {
562- traverseEffectHooks ( node , ( effect ) => {
563- effect . destroy = undefined ;
564- } ) ;
565- } ) ;
566- }
566+ if ( node . tag === exports . FiberTag . HostPortal ) {
567+ stack . unshift ( true ) ;
568+ return ( ) => stack . shift ( ) ;
569+ }
570+ if ( needRestore ) {
571+ stack . unshift ( false ) ;
572+ return ( ) => stack . shift ( ) ;
573+ }
574+ return null ;
575+ } ) ;
567576 restore . current = false ;
568577} ;
569578exports . restoreFiber = restoreFiber ;
0 commit comments