@@ -53,6 +53,7 @@ exports.FiberVisit = Object.freeze({
53
53
Return : 0b000100 ,
54
54
Effect : 0b001000 ,
55
55
Break : 0b010000 ,
56
+ SiblingFirst : 0b100000 ,
56
57
} ) ;
57
58
exports . FiberTag = Object . freeze ( {
58
59
FunctionComponent : 0 ,
@@ -126,21 +127,30 @@ const isHostFiber = (fiber) => {
126
127
}
127
128
return false ;
128
129
} ;
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 ) {
131
140
flags |= exports . FiberVisit . Sibling ;
132
141
}
142
+ const siblingFirst = flags & exports . FiberVisit . SiblingFirst ;
133
143
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 ) ;
135
148
}
136
149
if ( flags & exports . FiberVisit . Child ) {
137
150
fiber . child && stack . push ( fiber . child ) ;
138
151
}
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 ) ;
144
154
}
145
155
} ;
146
156
const findFiber = ( fiber , predicate , flags = exports . FiberVisit . Child ) => {
@@ -156,7 +166,7 @@ const findFiber = (fiber, predicate, flags = exports.FiberVisit.Child) => {
156
166
if ( predicate ( current ) ) {
157
167
return current ;
158
168
}
159
- pushVisitStack ( stack , fiber , current , flags ) ;
169
+ pushVisitStack ( stack , fiber , current , flags , null ) ;
160
170
}
161
171
return null ;
162
172
} ;
@@ -175,7 +185,7 @@ const findFibers = (fiber, predicate, flags = exports.FiberVisit.Child) => {
175
185
if ( predicate ( current ) ) {
176
186
result . push ( current ) ;
177
187
}
178
- pushVisitStack ( stack , fiber , current , flags ) ;
188
+ pushVisitStack ( stack , fiber , current , flags , null ) ;
179
189
}
180
190
return result ;
181
191
} ;
@@ -206,10 +216,7 @@ const traverseFiber = (fiber, visit, flags = exports.FiberVisit.Child) => {
206
216
if ( post === exports . FiberVisit . Break ) {
207
217
continue ;
208
218
}
209
- if ( isFunction ( post ) ) {
210
- stack . push ( post ) ;
211
- }
212
- pushVisitStack ( stack , fiber , current , flags ) ;
219
+ pushVisitStack ( stack , fiber , current , flags , post ) ;
213
220
}
214
221
} ;
215
222
exports . traverseFiber = traverseFiber ;
@@ -226,10 +233,10 @@ const findChildHostFibers = (fiber) => {
226
233
}
227
234
if ( isHostFiber ( current ) ) {
228
235
result . push ( current ) ;
229
- pushVisitStack ( stack , fiber , current , exports . FiberVisit . Sibling ) ;
236
+ pushVisitStack ( stack , fiber , current , exports . FiberVisit . Sibling , null ) ;
230
237
}
231
238
else {
232
- pushVisitStack ( stack , fiber , current , exports . FiberVisit . Child | exports . FiberVisit . Sibling ) ;
239
+ pushVisitStack ( stack , fiber , current , exports . FiberVisit . Child | exports . FiberVisit . Sibling , null ) ;
233
240
}
234
241
}
235
242
return result ;
@@ -438,15 +445,13 @@ const appendFiberEffect = (rootFiber, effectFiber, renderFiber, finishFiber) =>
438
445
rootFiber [ FiberEffectProp ] |= flags ;
439
446
fiber [ FiberEffectProp ] |= flags ;
440
447
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 ) ) {
445
449
const nextEffect = effectFiber . nextEffect ;
446
450
effectFiber . nextEffect = fiber ;
447
451
fiber . nextEffect = nextEffect ;
448
- } ;
449
- } ) ;
452
+ }
453
+ return null ;
454
+ } , exports . FiberVisit . Child | exports . FiberVisit . SiblingFirst ) ;
450
455
}
451
456
} ;
452
457
exports . appendFiberEffect = appendFiberEffect ;
@@ -458,7 +463,7 @@ const defineFiberProp = (fiber, prop, value) => {
458
463
value,
459
464
} ) ;
460
465
} ;
461
- const protectFiberProp = ( fiber , prop , restore ) => {
466
+ const protectFiberProp = ( fiber , prop , restore , needDummy ) => {
462
467
if ( null == fiber ) {
463
468
return ;
464
469
}
@@ -468,12 +473,11 @@ const protectFiberProp = (fiber, prop, restore) => {
468
473
}
469
474
const backup = fiber [ prop ] ;
470
475
let value = backup ;
471
- if ( ! restore . current && prop === 'stateNode' && isHostFiber ( fiber ) ) {
476
+ if ( needDummy && prop === 'stateNode' && isHostFiber ( fiber ) ) {
472
477
value = null ;
473
478
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 ) ;
477
481
}
478
482
}
479
483
Object . defineProperty ( fiber , prop , {
@@ -492,13 +496,13 @@ const restoreFiberProp = (fiber, prop) => {
492
496
defineFiberProp ( fiber , prop , fiber [ prop ] ) ;
493
497
}
494
498
} ;
495
- const protectFiberProps = ( fiber , current , restore ) => {
499
+ const protectFiberProps = ( fiber , current , restore , needDummy ) => {
496
500
const alternate = fiber . alternate ;
497
501
if ( alternate && ! current ) {
498
- protectFiberProps ( alternate , fiber , restore ) ;
502
+ protectFiberProps ( alternate , fiber , restore , false ) ;
499
503
}
500
504
for ( const prop of ProtectedFiberProps ) {
501
- protectFiberProp ( fiber , prop , restore ) ;
505
+ protectFiberProp ( fiber , prop , restore , needDummy ) ;
502
506
}
503
507
} ;
504
508
const restoreFiberProps = ( fiber , current ) => {
@@ -513,57 +517,62 @@ const restoreFiberProps = (fiber, current) => {
513
517
}
514
518
}
515
519
} ;
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
- } ;
529
520
const protectFiber = ( fiber ) => {
530
521
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
+ } ) ;
534
548
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
- }
543
549
return restore ;
544
550
} ;
545
551
exports . protectFiber = protectFiber ;
546
552
const restoreFiber = ( fiber , restore ) => {
547
553
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 ) {
550
558
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 ) {
559
561
restoreFiberProp ( node , 'stateNode' ) ;
562
+ }
563
+ traverseEffectHooks ( node , ( effect ) => {
564
+ effect . destroy = undefined ;
560
565
} ) ;
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
+ } ) ;
567
576
restore . current = false ;
568
577
} ;
569
578
exports . restoreFiber = restoreFiber ;
0 commit comments