@@ -436,28 +436,76 @@ export const getNearestHostFibers = (fiber: Fiber): Fiber[] => {
436
436
return hostFibers ;
437
437
} ;
438
438
439
- /**
440
- * Traverses up or down a {@link Fiber}, return `true` to stop and select a node.
441
- */
442
- export const traverseFiber = (
439
+ export type FiberSelector = ( node : Fiber ) => boolean | undefined ;
440
+
441
+ export interface TraverseFiberOptions {
442
+ /**
443
+ * The handler to call when entering a fiber, return `true` to stop and select a node.
444
+ */
445
+ enter ?: FiberSelector ;
446
+ /**
447
+ * The handler to call when exiting a fiber, return `true` to stop and select a node.
448
+ */
449
+ leave ?: FiberSelector ;
450
+ /**
451
+ * Whether to traverse the fiber tree in ascending order.
452
+ */
453
+ ascending ?: boolean ;
454
+ }
455
+
456
+ export interface TraverseFiber {
457
+ (
458
+ fiber : Fiber | null ,
459
+ /**
460
+ * The handler to call when entering a fiber.
461
+ */
462
+ selector : FiberSelector ,
463
+ /** @deprecated In favor of `options.ascending`. */
464
+ ascending ?: boolean ,
465
+ ) : Fiber | null ;
466
+ ( fiber : Fiber | null , options : TraverseFiberOptions ) : Fiber | null ;
467
+ }
468
+
469
+ const traverseFiberImpl = (
443
470
fiber : Fiber | null ,
444
- // biome-ignore lint/suspicious/noConfusingVoidType: may or may not exist
445
- selector : ( node : Fiber ) => boolean | void ,
446
- ascending = false ,
471
+ options : TraverseFiberOptions ,
447
472
) : Fiber | null => {
448
473
if ( ! fiber ) return null ;
449
- if ( selector ( fiber ) === true ) return fiber ;
474
+ const { enter, leave, ascending } = options ;
475
+
476
+ if ( enter && enter ( fiber ) === true ) return fiber ;
450
477
451
478
let child = ascending ? fiber . return : fiber . child ;
452
479
while ( child ) {
453
- const match = traverseFiber ( child , selector , ascending ) ;
480
+ const match = traverseFiber ( child , options ) ;
454
481
if ( match ) return match ;
455
482
456
483
child = ascending ? null : child . sibling ;
457
484
}
485
+
486
+ if ( leave && leave ( fiber ) === true ) return fiber ;
487
+
458
488
return null ;
459
489
} ;
460
490
491
+ /**
492
+ * Traverses up or down a {@link Fiber}, return `true` to stop and select a node.
493
+ */
494
+ export const traverseFiber : TraverseFiber = (
495
+ fiber ,
496
+ selectorOrOpts ,
497
+ ascendingOrNever = false ,
498
+ ) => {
499
+ if ( ! fiber ) return null ;
500
+ if ( typeof selectorOrOpts === 'function' ) {
501
+ const opts : TraverseFiberOptions = { enter : selectorOrOpts } ;
502
+ if ( typeof ascendingOrNever === 'boolean' )
503
+ opts . ascending = ascendingOrNever ;
504
+ return traverseFiberImpl ( fiber , opts ) ;
505
+ }
506
+ return traverseFiberImpl ( fiber , selectorOrOpts ) ;
507
+ } ;
508
+
461
509
/**
462
510
* Returns the timings of the {@link Fiber}.
463
511
*
0 commit comments