Skip to content

Commit 857f1ae

Browse files
committed
feat: add leave handler to traverseFiber
1 parent f50b577 commit 857f1ae

File tree

1 file changed

+57
-9
lines changed

1 file changed

+57
-9
lines changed

packages/bippy/src/core.ts

Lines changed: 57 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -436,28 +436,76 @@ export const getNearestHostFibers = (fiber: Fiber): Fiber[] => {
436436
return hostFibers;
437437
};
438438

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 = (
443470
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,
447472
): Fiber | null => {
448473
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;
450477

451478
let child = ascending ? fiber.return : fiber.child;
452479
while (child) {
453-
const match = traverseFiber(child, selector, ascending);
480+
const match = traverseFiber(child, options);
454481
if (match) return match;
455482

456483
child = ascending ? null : child.sibling;
457484
}
485+
486+
if (leave && leave(fiber) === true) return fiber;
487+
458488
return null;
459489
};
460490

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+
461509
/**
462510
* Returns the timings of the {@link Fiber}.
463511
*

0 commit comments

Comments
 (0)