import { Fiber } from 'bippy'; export const getChildrenFromFiberLL = (fiber: Fiber) => { const children: Array = []; let curr: typeof fiber.child = fiber.child; while (curr) { children.push(curr); curr = curr.sibling; } return children; }; type Node = Map< Fiber, { children: Array; parent: Fiber | null; isRoot: boolean; isSVG: boolean; } >; export const createChildrenAdjacencyList = (root: Fiber, limit: number) => { const tree: Node = new Map([]); const queue: Array<[node: Fiber, parent: Fiber | null]> = []; const visited = new Set(); queue.push([root, root.return]); let traversed = 1; while (queue.length) { if (traversed >= limit) { return tree; } // oxlint-disable-next-line typescript/no-non-null-assertion const [node, parent] = queue.pop()!; const children = getChildrenFromFiberLL(node); tree.set(node, { children: [], parent, isRoot: node === root, isSVG: node.type === 'svg', }); for (const child of children) { traversed += 1; // this isn't needed since the fiber tree is a TREE, not a graph, but it makes me feel safer if (visited.has(child)) { continue; } visited.add(child); tree.get(node)?.children.push(child); queue.push([child, node]); } } return tree; }; const THROW_INVARIANTS = false; export const invariantError = (message: string | undefined) => { if (THROW_INVARIANTS) { throw new Error(message); } }; export const iife = (fn: () => T): T => fn(); export class BoundedArray extends Array { constructor(private capacity: number = 25) { super(); } push(...items: T[]): number { const result = super.push(...items); while (this.length > this.capacity) { this.shift(); } return result; } // do not couple capacity with a default param, it must be explicit static fromArray(array: Array, capacity: number) { const arr = new BoundedArray(capacity); arr.push(...array); return arr; } }